pax_global_header00006660000000000000000000000064141273206640014517gustar00rootroot0000000000000052 comment=b56f671dba79dca00d8cb3ebde83dbd88292e9e1 GDCM-3.0.10/000077500000000000000000000000001412732066400123125ustar00rootroot00000000000000GDCM-3.0.10/.clang-format000066400000000000000000000037211412732066400146700ustar00rootroot00000000000000--- Language: Cpp # BasedOnStyle: Google AccessModifierOffset: -1 AlignAfterOpenBracket: true AlignConsecutiveAssignments: false AlignEscapedNewlinesLeft: true AlignOperands: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: true AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakBeforeMultilineStrings: true AlwaysBreakTemplateDeclarations: true BinPackArguments: true BinPackParameters: true BreakBeforeBinaryOperators: None BreakBeforeBraces: Attach BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false ColumnLimit: 80 CommentPragmas: '^ IWYU pragma:' ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DerivePointerAlignment: true DisableFormat: false ExperimentalAutoDetectBinPacking: false ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] IndentCaseLabels: true IndentWidth: 2 IndentWrappedFunctionNames: false KeepEmptyLinesAtTheStartOfBlocks: false MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None ObjCBlockIndentWidth: 2 ObjCSpaceAfterProperty: false ObjCSpaceBeforeProtocolList: false PenaltyBreakBeforeFirstCallParameter: 1 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 200 PointerAlignment: Left SpaceAfterCStyleCast: false SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 2 SpacesInAngles: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Auto TabWidth: 8 UseTab: Never ... GDCM-3.0.10/.gitattributes000066400000000000000000000002611412732066400152040ustar00rootroot00000000000000appveyor.yml merge=ours * -whitespace /Source/DataDictionary/gdcmDefaultDicts.cxx hooks.MaxObjectKiB=2048 /Source/InformationObjectDefinition/Part3.xml hooks.MaxObjectKiB=4096 GDCM-3.0.10/.gitignore000066400000000000000000000001761412732066400143060ustar00rootroot00000000000000# back-up *~ *.bak # files when there are conflicts *.orig # qtcreator files CMakeLists.txt.user* # kdevelop files *.kdev* GDCM-3.0.10/.gitmodules000066400000000000000000000001351412732066400144660ustar00rootroot00000000000000[submodule "Testing/Data"] path = Testing/Data url = git://git.code.sf.net/p/gdcm/gdcmdata GDCM-3.0.10/.travis.yml000066400000000000000000000152311412732066400144250ustar00rootroot00000000000000# https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables # https://github.com/travis-ci/travis-ci/issues/3505 language: cpp # Use the faster container-based infrastructure. #sudo: false dist: xenial env: global: # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created # via the "travis encrypt" command using the project repo's public key - secure: ClIqhtIIfQPhil8GH9bnJg70rvJfuYs7Z2Aq2SrdwQsIFNvvfFD5pVxQiaYbZI3nxNclggQ50BmGB96e6jLxbbd/xlIOjcU19W2nzyP6LGkXFHDHm8FwhqqDNpfYvirAOfqgjqf7khRe3ajF33jhrLrhb5QOO5640N93pdChu1sAvI0LZv8JFIUcN7A7To3+WYc7H4CK3U8B2V8nzqcBSHDZNBGAdeVdmldwrlBtQeWBg5wJAEzzUHn0x+kltqvuoPYi2ShpaUkEfHeUWYhOT1uoyXNRAqHXiM1jhiw3JCkqaf7sUKLzyx0ozjTnYntNMggtBzavKjuYg6RhdlNdNbdsi2nxrycCOyCZcF+d4limq+yDMqoP7g/DnPag7XFgjkG/ThULPu+pEK/6nV1NqGNWFu1CqgAwPW7hGbIUADPsMEb+Bz2L2KUof2wU1cdvGK4fzsM9Qpdipbagghn4b5eGtvyBzYzoCS02AKrYfimhcm8bVmlfaMVgd6PnJ19Y1+ADCWwStwaQL2S6udh66JVGNszY/kYSmZKn51RQQDkubmGpywzeNdn7gM9u8QR9s2Lsq0GaSdptcLOPmVNSg6mQJThbMRHM/H2UrSyo7/GLr28sNNbYNweGPevsnrRJPUdG2ENWVw5rg1sD1cLm8rLlD4H2f/b97X9NCl4bLxY= # -m32 is not supported # no poppler, openjpeg, uuid, json # no swig # using debian-sid I get: # /usr/bin/ld: BFD (GNU Binutils for Ubuntu) 2.22 internal error, aborting at # ../../bfd/reloc.c line 443 in bfd_get_reloc_size matrix: fast_finish: true include: - compiler: gcc os: linux env: - CFLAGS="-g -O2" - CXXFLAGS="-g -O2" - CMAKE_EXTRA="-DGDCM_WRAP_PYTHON:BOOL=OFF -DGDCM_BUILD_DOCBOOK_MANPAGES:BOOL=OFF" - B_NAME=default - CPACK_NAME=Linux - compiler: gcc os: linux # No docbook-xsl-ns addons: {apt: {packages: [default-jdk, mono-devel, swig, libcharls-dev, libvtk5-dev, libexpat-dev, libz-dev, uuid-dev, python-all-dev, libpoppler-private-dev, xsltproc, docbook-xsl, dcmtk]}} env: - CFLAGS="-Wall -Wextra -m64" - CXXFLAGS="-Wall -Wextra -m64" # Cant use manpage with old docbook - CMAKE_EXTRA="-DGDCM_USE_SYSTEM_OPENSSL:BOOL=ON -DGDCM_WRAP_PYTHON:BOOL=ON -DGDCM_WRAP_CSHARP:BOOL=ON -DGDCM_WRAP_JAVA:BOOL=ON -DGDCM_WRAP_PHP:BOOL=OFF -DGDCM_USE_SYSTEM_EXPAT:BOOL=ON -DGDCM_USE_SYSTEM_JSON:BOOL=OFF -DGDCM_USE_SYSTEM_LIBXML2:BOOL=ON -DGDCM_USE_SYSTEM_OPENJPEG:BOOL=OFF -DGDCM_USE_SYSTEM_POPPLER:BOOL=ON -DGDCM_USE_SYSTEM_UUID:BOOL=ON -DGDCM_USE_SYSTEM_ZLIB:BOOL=ON -DGDCM_WEAK_SWIG_CHECK:BOOL=ON -DGDCM_LEGACY_SILENT:BOOL=ON -DGDCM_BUILD_DOCBOOK_MANPAGES:BOOL=OFF" - B_NAME=system - CPACK_NAME=Linux - compiler: clang os: linux env: - CFLAGS="-g -O0 -Wall -Wextra -m64 -fsanitize=address,undefined,shift" - CXXFLAGS="-g -O0 -Wall -Wextra -m64 -fsanitize=address,undefined,shift" - CMAKE_EXTRA="-DGDCM_BUILD_DOCBOOK_MANPAGES:BOOL=OFF" - B_NAME=fsanitize - CPACK_NAME=Linux - compiler: clang os: osx env: - CFLAGS="-Wall -Wextra" # -m64 -fsanitize=address,undefined - CXXFLAGS="-Wall -Wextra" # -m64 -fsanitize=address,undefined # http://stackoverflow.com/questions/15678153/homebrew-python-on-mac-os-x-10-8-fatal-python-error-pythreadstate-get-no-cu #- CMAKE_EXTRA="-DGDCM_WRAP_PYTHON:BOOL=ON -DGDCM_BUILD_DOCBOOK_MANPAGES:BOOL=OFF -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python2.7" - CMAKE_EXTRA="-DGDCM_WRAP_PYTHON:BOOL=ON -DGDCM_WRAP_CSHARP:BOOL=OFF -DGDCM_WRAP_JAVA:BOOL=OFF -DGDCM_USE_SYSTEM_UUID:BOOL=ON -DGDCM_USE_SYSTEM_ZLIB:BOOL=ON -DGDCM_BUILD_DOCBOOK_MANPAGES:BOOL=OFF" - B_NAME=default - CPACK_NAME=Darwin before_install: #- env - cmake --version - if [ "$B_NAME" == "system" ]; then swig -version; fi # do not run the full test suite for now on fsanitize and osx (takes too long) - if [ "$B_NAME" == "fsanitize" ]; then mv Testing/Data Testing/Data.old; fi # https://docs.travis-ci.com/user/osx-ci-environment/#Environment-variables - if [ "$TRAVIS_OS_NAME" == "osx" ]; then mv Testing/Data Testing/Data.old; fi - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update ; fi - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install swig docbook-xsl ; fi - if [ "$TRAVIS_OS_NAME" == "osx" ]; then swig -version; fi # https://github.com/travis-ci/travis-ci/issues/2312 #- if [ "$TRAVIS_OS_NAME" == "osx" ]; then virtualenv env -p python3 ; fi #- if [ "$TRAVIS_OS_NAME" == "osx" ]; then source env/bin/activate ; fi # kakadu setup for linux/system: - if [ "$B_NAME" == "system" ]; then wget http://kakadusoftware.com/wp-content/uploads/KDU805_Demo_Apps_for_Linux-x86-64_200602.zip; fi - if [ "$B_NAME" == "system" ]; then unzip KDU805_Demo_Apps_for_Linux-x86-64_200602.zip; fi - if [ "$B_NAME" == "system" ]; then export PATH=$PATH:$PWD/KDU805_Demo_Apps_for_Linux-x86-64_200602; fi install: true before_script: - cmake -Wno-dev -G "Unix Makefiles" -DCMAKE_BUILD_TYPE:STRING=None -DGDCM_BUILD_TESTING:BOOL=ON -DGDCM_BUILD_APPLICATIONS:BOOL=ON -DGDCM_BUILD_SHARED_LIBS:BOOL=ON -DBUILDNAME:STRING=${TRAVIS_OS_NAME}-${TRAVIS_BRANCH}-${B_NAME} ${CMAKE_EXTRA} . - ctest -D ExperimentalStart script: - ctest -D ExperimentalBuild -j2 - ctest -D ExperimentalTest -j2 || true after_success: - ctest -D ExperimentalSubmit || true # prefer after_success since before_deploy is not called (conditions unmet) - cpack -G TGZ - cpack -G TBZ2 after_failure: true before_deploy: - VTAG=$(echo $TRAVIS_TAG | cut -f2 -dv) deploy: edge: true provider: releases api_key: secure: R5+dbibdcgPHq6cAPC8uepifDuS3yjZu2dBB2oSeQtBZTAeN1VIfJMrF8TeQDqj2GC28RHxXm4BHwdJ2FUpBXjOS2eUE6Mto1Rbbvfi63MREnFPIAWkNyLtR2Jxq/Gzb8X05PbCWGwCNvX9eeo+qcWTpczuQvJ+/bds7MyRsk45+sUc+j7rglAbxewgijsXebCkObwaXmhqTYJwrvf2lyEnA2Jo1gL2WmK6iPjHvTOVS9JfBMqVRmlk7j8efnqag8fMCzNp1Ess5wBy5Jf58qvVs7RuuBi16s7vOOBtb9xVjcDB1KaAxc/dDQGQhRkrveBtH18ZpFrArOj6DBPbupS3+xuU4ywdYbCuGnvdpRFafBc+iNU4M81crkFUDmSPEQChBnL4wwpaYaQ1LlgdlF0r9/Rlu2/iqKe4t7rdZnkQqQ/3SNNf+x4AKnGmaSGasV/VUXstTGVrtl7hsDMzSdrVCXODao0SRv5tPSI3BgAZi7NzCJ/xv5LgA1EQVkGdTQN0ZpKZCQYfifL5K6oYDI+WlAFU0OcH+9dy4KNqF+QnzMh9iPwP0zR6BN9yE0w6ydnyNt0CkIUaxgaTtr+pHPXsmmtgXzQScESC8B9JHGocOXjT6MtyUmoP/ewlPz2G6x114PnAL7LlZ07jPqAASJwW/ZiXtBcVxv50hPhC7L80= file: - GDCM-$VTAG-$CPACK_NAME-x86_64.tar.gz - GDCM-$VTAG-$CPACK_NAME-x86_64.tar.bz2 skip_cleanup: true on: repo: malaterre/GDCM condition: $B_NAME = default all_branches: true tags: true # final after_script: true addons: coverity_scan: project: name: malaterre/GDCM description: "Grassroots DICOM" notification_email: mathieu.malaterre@gmail.com build_command_prepend: cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo -DGDCM_BUILD_SHARED_LIBS:BOOL=ON .. build_command: cmake --build . branch_pattern: coverity_scan GDCM-3.0.10/AUTHORS000066400000000000000000000036151412732066400133670ustar00rootroot00000000000000GDCM 2.x: -------- Fabrice Bellet : Contributor (RPM) Charl P. Botha : Contributor (Python, VTK) Shane Blackett : Contributor (Win32) Niels Dekker : Contributor (C++ guru) Daniele E. Domenichelli : Contributor (C++) Dean Inglis : Contributor (Win32, VTK) Paulo Henrique Junqueira Amorim : Contributor (Python) Pierre Le Duff : Medecom engineer, Contributor (C++, VTK) Mathieu Malaterre : Project leader, main developer Lars Matthaus : Contributor (Java) Sean McBride : Contributor (C++) Steve M. Robbins : Contributor (debian) Mark Roden : Developer (C++, C#) Jordi Romera : Developer (C++, RTSTRUCT) Jean-Pierre Roux : Developer, maintain gdcmDataExtra Christina Rossmanith : Contributor (Siemens CSA) Christopher W Treml : Contributor (C#) Joel Spaltenstein : Developer (Mac OS X) GDCM 1.x (Developers and contributors, alphabetical order) -------- Aris Basic Fabrice Bellet Hugues Benoit-Cattin Francois Bertel Eric Boix Charl P. Botha Peter Cech Eduardo Enrique Davila Serrano Antonin Descampe David Feng Marco Feuerstein Pierre Fillard Leonardo Flores Valencia Dennis Hu Luis Ibanez Michal Kurgan Gianni Lazzarato George Li Sean McInemey Johan Montagnat Emmanuel Olart Luca Picello Parikshit Prasad Benoit Regrain Jean-Michel Rouet Olivier Stern Satomi Takeo GDCM-3.0.10/Applications/000077500000000000000000000000001412732066400147405ustar00rootroot00000000000000GDCM-3.0.10/Applications/CMakeLists.txt000066400000000000000000000000261412732066400174760ustar00rootroot00000000000000add_subdirectory(Cxx) GDCM-3.0.10/Applications/Cxx/000077500000000000000000000000001412732066400155025ustar00rootroot00000000000000GDCM-3.0.10/Applications/Cxx/CMakeLists.txt000066400000000000000000000241651412732066400202520ustar00rootroot00000000000000# Build the GDCM applications # Namely: # gdcmdump # gdcminfo # gdcmconv # gdcmanon if(WIN32 AND NOT CYGWIN AND NOT MINGW) include_directories( "${GDCM_SOURCE_DIR}/Utilities/getopt" ) endif() # Add the include paths include_directories( "${GDCM_BINARY_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition" "${GDCM_SOURCE_DIR}/Source/MediaStorageAndFileFormat" "${GDCM_SOURCE_DIR}/Source/InformationObjectDefinition" "${GDCM_SOURCE_DIR}/Source/MessageExchangeDefinition" # FIXME: "${GDCM_SOURCE_DIR}/Source/DataDictionary" "${GDCM_SOURCE_DIR}/Utilities" ) if(NOT GDCM_USE_SYSTEM_SOCKETXX) include_directories( "${GDCM_SOURCE_DIR}/Utilities/socketxx" "${GDCM_SOURCE_DIR}/Utilities/socketxx/socket++" # local.h "${GDCM_BINARY_DIR}/Utilities/socketxx/socket++" # config.h ) endif() if(WIN32) if (BUILD_SHARED_LIBS) add_definitions(-DGETOPT_DLL) endif () endif() set(GDCM_EXECUTABLE_NAME gdcmdump gdcmdiff gdcmraw gdcmscanner gdcmanon gdcmgendir #gdcmoverlay gdcmimg #deflate gdcmconv #gdcmstream gdcmtar gdcminfo gdcmscu gdcmxml gdcmpap3 ) # poppler people have the worse API backward compatibility I know of. # there is absolutely no way to check the version of poppler # they change the API during a minor change of the version if(GDCM_USE_SYSTEM_POPPLER) include(CheckCXXSourceCompiles) set(CMAKE_REQUIRED_INCLUDES ${POPPLER_INCLUDE_DIRS}) set(CMAKE_REQUIRED_LIBRARIES ${POPPLER_LIBRARIES}) CHECK_CXX_SOURCE_COMPILES( "\#include \nint main() { globalParams = new GlobalParams(0); return 0;}" LIBPOPPLER_GLOBALPARAMS_CSTOR_HAS_PARAM) set(libpoppler_flags) if(LIBPOPPLER_GLOBALPARAMS_CSTOR_HAS_PARAM) list(APPEND libpoppler_flags -DLIBPOPPLER_GLOBALPARAMS_CSTOR_HAS_PARAM) endif() CHECK_CXX_SOURCE_COMPILES( "\#include \nint main() { globalParams.reset( new GlobalParams()); return 0;}" LIBPOPPLER_GLOBALPARAMS_HAS_RESET) set(libpoppler_flags) if(LIBPOPPLER_GLOBALPARAMS_HAS_RESET) list(APPEND libpoppler_flags -DLIBPOPPLER_GLOBALPARAMS_HAS_RESET) endif() CHECK_CXX_SOURCE_COMPILES( "\#include \nint main() { PDFDoc d((GooString*)NULL,(GooString*)NULL,(GooString*)NULL); d.getPDFVersion(); return 0;}" LIBPOPPLER_PDFDOC_HAS_PDFVERSION) if(LIBPOPPLER_PDFDOC_HAS_PDFVERSION) list(APPEND libpoppler_flags -DLIBPOPPLER_PDFDOC_HAS_PDFVERSION) endif() CHECK_CXX_SOURCE_COMPILES( "\#include \n#include \nint main() { Catalog c(NULL); c.getStructTreeRoot()->getDoc(); return 0;}" LIBPOPPLER_CATALOG_HAS_STRUCTTREEROOT) if(LIBPOPPLER_CATALOG_HAS_STRUCTTREEROOT) list(APPEND libpoppler_flags -DLIBPOPPLER_CATALOG_HAS_STRUCTTREEROOT) endif() CHECK_CXX_SOURCE_COMPILES( "\#include \nint main() { Object o(42); }" LIBPOPPLER_NEW_OBJECT_API) if(LIBPOPPLER_NEW_OBJECT_API) list(APPEND libpoppler_flags -DLIBPOPPLER_NEW_OBJECT_API) endif() CHECK_CXX_SOURCE_COMPILES( "\#include \nint main() { const GooString gs; gs.getChar(0); return 0; }" LIBPOPPLER_GOOSTRING_HAS_CONSTGETCHAR) if(LIBPOPPLER_GOOSTRING_HAS_CONSTGETCHAR) list(APPEND libpoppler_flags -DLIBPOPPLER_GOOSTRING_HAS_CONSTGETCHAR) endif() CHECK_CXX_SOURCE_COMPILES( "\#include \nint main() { GooString gs; gs.getCString(); return 0; }" LIBPOPPLER_GOOSTRING_HAS_GETCSTRING) if(LIBPOPPLER_GOOSTRING_HAS_GETCSTRING) list(APPEND libpoppler_flags -DLIBPOPPLER_GOOSTRING_HAS_GETCSTRING) endif() CHECK_CXX_SOURCE_COMPILES( "\#include \nint main() { Unicode u; char buf[8]; const UnicodeMap *uMap; uMap->mapUnicode(u, buf, sizeof(buf)); return 0; }" LIBPOPPLER_UNICODEMAP_HAS_CONSTMAPUNICODE) if(LIBPOPPLER_UNICODEMAP_HAS_CONSTMAPUNICODE) list(APPEND libpoppler_flags -DLIBPOPPLER_UNICODEMAP_HAS_CONSTMAPUNICODE) endif() if(libpoppler_flags) string(REPLACE ";" " " libpoppler_flags_string "${libpoppler_flags}") set_source_files_properties( ${CMAKE_CURRENT_SOURCE_DIR}/gdcminfo.cxx PROPERTIES COMPILE_FLAGS "${libpoppler_flags_string}") set_source_files_properties( ${CMAKE_CURRENT_SOURCE_DIR}/gdcmpdf.cxx PROPERTIES COMPILE_FLAGS "${libpoppler_flags_string}") endif() include_directories(${POPPLER_INCLUDE_DIRS}) set(GDCM_EXECUTABLE_NAME ${GDCM_EXECUTABLE_NAME} gdcmpdf ) endif() if(GDCM_USE_SYSTEM_LIBXML2) include_directories(${LIBXML2_INCLUDE_DIR}) endif() if(GDCM_USE_SYSTEM_OPENJPEG) include_directories(${OPENJPEG_INCLUDE_DIRS} ) else() include_directories( "${GDCM_BINARY_DIR}/Utilities/gdcmopenjpeg" ) endif() if(NOT BUILD_SHARED_LIBS) set_source_files_properties(gdcmstream.cxx PROPERTIES COMPILE_FLAGS -DOPJ_STATIC ) endif() if(GDCM_USE_SYSTEM_PAPYRUS3) include_directories( ${PAPYRUS3_INCLUDE_DIRS} ) endif() foreach(exename ${GDCM_EXECUTABLE_NAME}) if(${exename} STREQUAL "gdcminfo") add_executable(${exename} ${exename}.cxx puff.c) else() add_executable(${exename} ${exename}.cxx) endif() target_link_libraries(${exename} gdcmMSFF) if(${exename} STREQUAL "gdcmpdf") target_link_libraries(${exename} ${POPPLER_LIBRARIES}) elseif(${exename} STREQUAL "gdcmxml") target_link_libraries(${exename} ${LIBXML2_LIBRARIES}) elseif(${exename} STREQUAL "gdcmscu") if(NOT GDCM_USE_SYSTEM_SOCKETXX) target_link_libraries(${exename} gdcmMEXD socketxx) else() target_link_libraries(${exename} gdcmMEXD socket++) endif() elseif(${exename} STREQUAL "gdcmstream") target_link_libraries(${exename} ${GDCM_OPENJPEG_LIBRARIES}) elseif(${exename} STREQUAL "gdcminfo") if(GDCM_USE_SYSTEM_POPPLER) target_link_libraries(${exename} ${POPPLER_LIBRARIES}) endif() endif() if(GDCM_EXECUTABLE_PROPERTIES) set_target_properties(${exename} PROPERTIES ${GDCM_EXECUTABLE_PROPERTIES}) endif() if(WIN32 AND NOT CYGWIN AND NOT MINGW) target_link_libraries(${exename} gdcmgetopt) endif() if(NOT GDCM_INSTALL_NO_RUNTIME) install(TARGETS ${exename} EXPORT ${GDCM_TARGETS_NAME} RUNTIME DESTINATION ${GDCM_INSTALL_BIN_DIR} COMPONENT Applications ) endif() endforeach() if(GDCM_USE_SYSTEM_PAPYRUS3) target_link_libraries(gdcmpap3 ${PAPYRUS3_LIBRARIES}) endif() #if(BUILD_TESTING) # if(GDCM_DATA_ROOT) # file(MAKE_DIRECTORY ${GDCM_TEMP_DIRECTORY}/gdcmanon-gdcmdata) # add_test(NAME gdcmanon-gdcmdata COMMAND gdcmanon # --continue # skip LIBIDO-16-ACR_NEMA-Volume.dcm # --certificate ${GDCM_SOURCE_DIR}/Testing/Source/Data/certificate.pem # ${GDCM_DATA_ROOT} # ${GDCM_TEMP_DIRECTORY}/gdcmanon-gdcmdata # ) # endif() #endif() if(BUILD_TESTING) # http://www.na-mic.org/Wiki/index.php/CTSC:ARRA:Mockup # http://www.dicomserver.co.uk/ # the NAMIC server is offline, Steve Pieper has volunteered his servers, but they are intermittent # IP Address: common.bwh.harvard.edu (155.52.248.49) # Port: 11112 # AE Title: CTK_AE # and # IP Address: joe.bwh.harvard.edu (155.52.248.50) # Port: 5678 # AE Title: CONQUESTSRV1 #since these servers have no guaranteed uptime, these tests should be changed to some other, known-to-be-up server #add_test(NAME gdcmscu-echo-CONQUEST COMMAND gdcmscu --echo --call CONQUESTSRV1 joe.bwh.harvard.edu 5678) add_test(NAME gdcmscu-echo-dicomserver COMMAND gdcmscu --echo www.dicomserver.co.uk 11112) if(GDCM_DATA_ROOT) # CR-MONO1-10-chest.dcm gets rejected by www.dicomserver.co.uk: # Tag 0x0,0x902 reported as Incorrect VM (1) - Minimum value is 2 : 'Array of N Elements' (error 42752) # CR-MONO1-10-chest.dcm gets rejected by mi2b2.slicer.org # Tag 0x0,0x902 reported as Acceptance of objects without Patient ID is disabled (error 43264) #add_test(NAME gdcmscu-store-CONQUEST COMMAND gdcmscu --store --call CONQUESTSRV1 joe.bwh.harvard.edu 11112 ${GDCM_DATA_ROOT}/SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm) add_test(NAME gdcmscu-store-dicomserver COMMAND gdcmscu --store www.dicomserver.co.uk 11112 ${GDCM_DATA_ROOT}/SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm) endif() #add_test(NAME gdcmscu-find-CONQUEST COMMAND gdcmscu --find --patient --call CONQUESTSRV1 joe.bwh.harvard.edu 11112 --patientroot -k 10,10=X*) add_test(NAME gdcmscu-find-dicomserver COMMAND gdcmscu --find --patient www.dicomserver.co.uk 11112 --patientroot -k 10,20=*) if(GDCM_DICOM_SERVER_AETITLE) if(GDCM_DATA_ROOT) # Let's C-STORE a limited subset of gdcmData for now: set(CSTORE_DATA_FILES CR-MONO1-10-chest.dcm # Implicit VR Little Endian: Default Transfer Syntax for DICOM 012345.002.050.dcm # JPEG Lossless, Non-Hierarchical, First-Order Prediction ) foreach(cstorefile ${CSTORE_DATA_FILES}) add_test(NAME gdcmscu-echo-${cstorefile} COMMAND gdcmscu --echo --aetitle ${GDCM_DICOM_CLIENT_AETITLE} --call ${GDCM_DICOM_SERVER_AETITLE} ${GDCM_DICOM_SERVER_PEER} ${GDCM_DICOM_SERVER_PORT}) add_test(NAME gdcmscu-store-${cstorefile} COMMAND gdcmscu --store --aetitle ${GDCM_DICOM_CLIENT_AETITLE} --call ${GDCM_DICOM_SERVER_AETITLE} ${GDCM_DICOM_SERVER_PEER} ${GDCM_DICOM_SERVER_PORT} ${GDCM_DATA_ROOT}/${cstorefile}) add_test(NAME gdcmscu-find-${cstorefile} COMMAND gdcmscu --find --patient --aetitle ${GDCM_DICOM_CLIENT_AETITLE} --call ${GDCM_DICOM_SERVER_AETITLE} ${GDCM_DICOM_SERVER_PEER} ${GDCM_DICOM_SERVER_PORT} --patientroot -k 10,10=A* -k 10,20) add_test(NAME gdcmscu-move1-${cstorefile} COMMAND gdcmscu --move --patient --aetitle ${GDCM_DICOM_CLIENT_AETITLE} --call ${GDCM_DICOM_SERVER_AETITLE} ${GDCM_DICOM_SERVER_PEER} ${GDCM_DICOM_SERVER_PORT} -o ${CMAKE_CURRENT_BINARY_DIR} --patientroot -k 10,10=Anonymized --port-scp ${GDCM_DICOM_CLIENT_PORT}) add_test(NAME gdcmscu-move2-${cstorefile} COMMAND gdcmscu --move --patient --aetitle ${GDCM_DICOM_CLIENT_AETITLE} --call ${GDCM_DICOM_SERVER_AETITLE} ${GDCM_DICOM_SERVER_PEER} ${GDCM_DICOM_SERVER_PORT} -o ${CMAKE_CURRENT_BINARY_DIR} --patientroot -k 10,10=X* --port-scp ${GDCM_DICOM_CLIENT_PORT}) endforeach() endif() endif() endif() GDCM-3.0.10/Applications/Cxx/deflate.cxx000066400000000000000000000062601412732066400176360ustar00rootroot00000000000000#include #include #include #include #include #include "zlib/zlib.h" #define CHUNK 16384 /* Decompress from file source to file dest until stream ends or EOF. inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be allocated for processing, Z_DATA_ERROR if the deflate data is invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and the version of the library linked do not match, or Z_ERRNO if there is an error reading or writing the files. */ int inf(FILE *source, FILE *dest) { int ret; unsigned have; z_stream strm; unsigned char in[CHUNK]; unsigned char out[CHUNK]; /* allocate inflate state */ strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = 0; strm.next_in = Z_NULL; //ret = inflateInit(&strm); ret = inflateInit2(&strm, -MAX_WBITS); if (ret != Z_OK) { std::cout << "could not inflateInit" << std::endl; return ret; } /* decompress until deflate stream ends or end of file */ do { strm.avail_in = fread(in, 1, CHUNK, source); if (ferror(source)) { (void)inflateEnd(&strm); return Z_ERRNO; } if (strm.avail_in == 0) break; strm.next_in = in; /* run inflate() on input until output buffer not full */ do { strm.avail_out = CHUNK; strm.next_out = out; ret = inflate(&strm, Z_NO_FLUSH); assert(ret != Z_STREAM_ERROR); /* state not clobbered */ switch (ret) { case Z_NEED_DICT: ret = Z_DATA_ERROR; /* and fall through */ case Z_DATA_ERROR: case Z_MEM_ERROR: (void)inflateEnd(&strm); return ret; } have = CHUNK - strm.avail_out; if (fwrite(out, 1, have, dest) != have || ferror(dest)) { (void)inflateEnd(&strm); return Z_ERRNO; } } while (strm.avail_out == 0); /* done when inflate() says it's done */ } while (ret != Z_STREAM_END); /* clean up and return */ (void)inflateEnd(&strm); return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; } void zerr(int ret) { fputs("zpipe: ", stderr); switch (ret) { case Z_ERRNO: if (ferror(stdin)) fputs("error reading stdin\n", stderr); if (ferror(stdout)) fputs("error writing stdout\n", stderr); break; case Z_STREAM_ERROR: fputs("invalid compression level\n", stderr); break; case Z_DATA_ERROR: fputs("invalid or incomplete deflate data\n", stderr); break; case Z_MEM_ERROR: fputs("out of memory\n", stderr); break; case Z_VERSION_ERROR: fputs("zlib version mismatch!\n", stderr); } } int main() { FILE *input; FILE *output; input = fopen("deflat.gz","r"); output = fopen("deflat.dcm","w"); if(!input) std::cout << "no input" << std::endl; if(!output) std::cout << "no output" << std::endl; int r = inf(input, output); //std::cout << strerror( errno) << std::endl; // zerr(r) ; return r; } GDCM-3.0.10/Applications/Cxx/gdcm.cxx000066400000000000000000000025761412732066400171520ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // gdcm will convert almost anything into dicom // - jpg // - j2k // - pdf // - raw.. // - wav // - txt (??) // - 2D stuff -> RT // - new segmentation ! // provide a dicom2 compatible API...maybe ?? // For pdf: /* Provide a mapping for: Title: ITK Software Guide Subject: Medical Image Segmentation and Registration Toolkit Keywords: Registration,Segmentation,Guide Author: Luis Ibanez and Will Schroeder Creator: LaTeX with hyperref package Producer: dvips + GPL Ghostscript 8.15 CreationDate: Mon Nov 21 19:34:28 2005 ModDate: Mon Nov 21 19:34:28 2005 Tagged: no Pages: 836 Encrypted: no Page size: 522 x 675 pts File size: 5580502 bytes Optimized: no PDF version: 1.4 into DICOM elements... */ int main(int argc, char *argv[]) { return 0; } GDCM-3.0.10/Applications/Cxx/gdcmanon.cxx000066400000000000000000000604151412732066400200220ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * PS 3.15 / E.1 / Basic Application Level Confidentiality Profile * Implementation of E.1.1 De-identify & E.1.2 Re-identify */ #include #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmVersion.h" #include "gdcmSystem.h" #include "gdcmCryptoFactory.h" #include "gdcmUIDGenerator.h" #include "gdcmAnonymizer.h" #include "gdcmGlobal.h" #include "gdcmDefs.h" #include "gdcmDirectory.h" #include static void PrintVersion() { std::cout << "gdcmanon: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; } // FIXME int deidentify = 0; int reidentify = 0; static bool AnonymizeOneFileDumb(gdcm::Anonymizer &anon, const char *filename, const char *outfilename, std::vector const &empty_tags, std::vector const &remove_tags, std::vector< std::pair > const & replace_tags, bool continuemode = false) { gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Could not read : " << filename; if( continuemode ) { std::cerr << " -> Skipping from anonymization process (continue mode)." << std::endl; return true; } else { std::cerr << " -> Check [--continue] option for skipping files." << std::endl; return false; } } gdcm::File &file = reader.GetFile(); anon.SetFile( file ); if( empty_tags.empty() && replace_tags.empty() && remove_tags.empty() ) { std::cerr << "No operation to be done." << std::endl; return false; } std::vector::const_iterator it = empty_tags.begin(); bool success = true; for(; it != empty_tags.end(); ++it) { success = success && anon.Empty( *it ); } it = remove_tags.begin(); for(; it != remove_tags.end(); ++it) { success = success && anon.Remove( *it ); } std::vector< std::pair >::const_iterator it2 = replace_tags.begin(); for(; it2 != replace_tags.end(); ++it2) { success = success && anon.Replace( it2->first, it2->second.c_str() ); } gdcm::Writer writer; writer.SetFileName( outfilename ); writer.SetFile( file ); if( !writer.Write() ) { std::cerr << "Could not Write : " << outfilename << std::endl; if( strcmp(filename,outfilename) != 0 ) { gdcm::System::RemoveFile( outfilename ); } else { std::cerr << "gdcmanon just corrupted: " << filename << " for you (data lost)." << std::endl; } return false; } return success; } static bool AnonymizeOneFile(gdcm::Anonymizer &anon, const char *filename, const char *outfilename, bool continuemode = false) { gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Could not read : " << filename << std::endl; if( continuemode ) { std::cerr << "Skipping from anonymization process (continue mode)." << std::endl; return true; } else { std::cerr << "Check [--continue] option for skipping files." << std::endl; return false; } } gdcm::File &file = reader.GetFile(); gdcm::MediaStorage ms; ms.SetFromFile(file); if( !gdcm::Defs::GetIODNameFromMediaStorage(ms) ) { std::cerr << "The Media Storage Type of your file is not supported: " << ms << std::endl; std::cerr << "Please report" << std::endl; return false; } anon.SetFile( file ); if( deidentify ) { //anon.RemovePrivateTags(); //anon.RemoveRetired(); if( !anon.BasicApplicationLevelConfidentialityProfile( true ) ) { std::cerr << "Could not De-indentify : " << filename << std::endl; return false; } } else if ( reidentify ) { if( !anon.BasicApplicationLevelConfidentialityProfile( false ) ) { std::cerr << "Could not Re-indentify : " << filename << std::endl; return false; } } gdcm::FileMetaInformation &fmi = file.GetHeader(); fmi.Clear(); gdcm::Writer writer; writer.SetFileName( outfilename ); writer.SetFile( file ); if( !writer.Write() ) { std::cerr << "Could not Write : " << outfilename << std::endl; if( strcmp(filename,outfilename) != 0 ) { gdcm::System::RemoveFile( outfilename ); } else { std::cerr << "gdcmanon just corrupted: " << filename << " for you (data lost)." << std::endl; } return false; } return true; } static bool GetRSAKeys(gdcm::CryptographicMessageSyntax &cms, const char *privpath = nullptr, const char *certpath = nullptr) { if( privpath && *privpath ) { if( !cms.ParseKeyFile( privpath ) ) { std::cerr << "Could not parse Private Key: " << privpath << std::endl; return false; } } if( certpath && *certpath ) { if( !cms.ParseCertificateFile( certpath ) ) { std::cerr << "Could not parse Certificate Key: " << certpath << std::endl; return false; } } return true; } static void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcmanon [OPTION]... FILE..." << std::endl; std::cout << "PS 3.15 / E.1 / Basic Application Level Confidentiality Profile" << std::endl; std::cout << "Implementation of E.1.1 De-identify & E.1.2 Re-identify" << std::endl; std::cout << "Parameter (required):" << std::endl; std::cout << " -e --de-identify (encrypt) De-identify DICOM (default)" << std::endl; std::cout << " -d --re-identify (decrypt) Re-identify DICOM" << std::endl; std::cout << " --dumb Dumb mode anonymizer" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -i --input DICOM filename / directory" << std::endl; std::cout << " -o --output DICOM filename / directory" << std::endl; std::cout << " -r --recursive recursively process (sub-)directories." << std::endl; std::cout << " --continue Do not stop when file found is not DICOM." << std::endl; std::cout << " --root-uid Root UID." << std::endl; std::cout << " --resources-path Resources path." << std::endl; std::cout << " -k --key Path to RSA Private Key." << std::endl; std::cout << " -c --certificate Path to Certificate." << std::endl; std::cout << " -p --password Encryption passphrase." << std::endl; std::cout << "Crypto Library Options:" << std::endl; std::cout << " --crypto=" << std::endl; std::cout << " openssl OpenSSL (default on non-Windows systems)." << std::endl; std::cout << " capi Microsoft CryptoAPI (default on Windows systems)." << std::endl; std::cout << " openssl-p7 Old OpenSSL implementation." << std::endl; std::cout << "Encryption Algorithm Options:" << std::endl; std::cout << " --des3 Triple DES." << std::endl; std::cout << " --aes128 AES 128." << std::endl; std::cout << " --aes192 AES 192." << std::endl; std::cout << " --aes256 AES 256 (default)." << std::endl; std::cout << "Dumb mode options:" << std::endl; std::cout << " --empty %d,%d DICOM tag(s) to empty" << std::endl; std::cout << " --remove %d,%d DICOM tag(s) to remove" << std::endl; std::cout << " --replace %d,%d=%s DICOM tag(s) to replace" << std::endl; std::cout << "General Options:" << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " -v --version print version." << std::endl; std::cout << "Env var:" << std::endl; std::cout << " GDCM_ROOT_UID Root UID" << std::endl; std::cout << " GDCM_RESOURCES_PATH path pointing to resources files (Part3.xml, ...)" << std::endl; } static gdcm::CryptographicMessageSyntax::CipherTypes GetFromString( const char * str ) { gdcm::CryptographicMessageSyntax::CipherTypes ciphertype; if( strcmp( str, "des3" ) == 0 ) { ciphertype = gdcm::CryptographicMessageSyntax::DES3_CIPHER; } else if( strcmp( str, "aes128" ) == 0 ) { ciphertype = gdcm::CryptographicMessageSyntax::AES128_CIPHER; } else if( strcmp( str, "aes192" ) == 0 ) { ciphertype = gdcm::CryptographicMessageSyntax::AES192_CIPHER; } else if( strcmp( str, "aes256" ) == 0 ) { ciphertype = gdcm::CryptographicMessageSyntax::AES256_CIPHER; } else { // if unrecognized return aes 256... ciphertype = gdcm::CryptographicMessageSyntax::AES256_CIPHER; } return ciphertype; } int main(int argc, char *argv[]) { int c; //int digit_optind = 0; std::string filename; gdcm::Directory::FilenamesType filenames; std::string outfilename; gdcm::Directory::FilenamesType outfilenames; std::string root; std::string xmlpath; std::string rsa_path; std::string cert_path; std::string password; int resourcespath = 0; int dumb_mode = 0; int des3 = 0; int aes128 = 0; int aes192 = 0; int aes256 = 0; int rootuid = 0; int verbose = 0; int warning = 0; int debug = 0; int error = 0; int help = 0; int version = 0; int recursive = 0; int continuemode = 0; int empty_tag = 0; int remove_tag = 0; int replace_tag = 0; int crypto_api = 0; std::vector empty_tags; std::vector remove_tags; std::vector< std::pair > replace_tags_value; gdcm::Tag tag; gdcm::CryptoFactory::CryptoLib crypto_lib; crypto_lib = gdcm::CryptoFactory::DEFAULT; while (true) { //int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"input", required_argument, nullptr, 'i'}, // i {"output", required_argument, nullptr, 'o'}, // o {"root-uid", required_argument, &rootuid, 1}, // specific Root (not GDCM) {"resources-path", required_argument, &resourcespath, 1}, {"de-identify", no_argument, nullptr, 'e'}, {"re-identify", no_argument, nullptr, 'd'}, {"key", required_argument, nullptr, 'k'}, {"certificate", required_argument, nullptr, 'c'}, // 7 {"password", required_argument, nullptr, 'p'}, {"des3", no_argument, &des3, 1}, {"aes128", no_argument, &aes128, 1}, {"aes192", no_argument, &aes192, 1}, {"aes256", no_argument, &aes256, 1}, {"recursive", no_argument, nullptr, 'r'}, {"dumb", no_argument, &dumb_mode, 1}, {"empty", required_argument, &empty_tag, 1}, // 15 {"remove", required_argument, &remove_tag, 1}, {"replace", required_argument, &replace_tag, 1}, {"continue", no_argument, &continuemode, 1}, {"crypto", required_argument, &crypto_api, 1}, //19 {"verbose", no_argument, nullptr, 'V'}, {"warning", no_argument, nullptr, 'W'}, {"debug", no_argument, nullptr, 'D'}, {"error", no_argument, nullptr, 'E'}, {"help", no_argument, nullptr, 'h'}, {"version", no_argument, nullptr, 'v'}, {nullptr, 0, nullptr, 0} }; c = getopt_long (argc, argv, "i:o:rdek:c:p:VWDEhv", long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: { const char *s = long_options[option_index].name; (void)s; //printf ("option %s", s); if (optarg) { //if( option_index == 0 ) /* input */ // { // assert( strcmp(s, "input") == 0 ); // assert( filename.empty() ); // filename = optarg; // } //else if( option_index == 1 ) /* output */ // { // assert( strcmp(s, "output") == 0 ); // assert( outfilename.empty() ); // outfilename = optarg; // } /*else*/ if( option_index == 2 ) /* root-uid */ { assert( strcmp(s, "root-uid") == 0 ); assert( root.empty() ); root = optarg; } else if( option_index == 3 ) /* resources-path */ { assert( strcmp(s, "resources-path") == 0 ); assert( xmlpath.empty() ); xmlpath = optarg; } //else if( option_index == 6 ) /* key */ // { // assert( strcmp(s, "key") == 0 ); // assert( rsa_path.empty() ); // rsa_path = optarg; // } //else if( option_index == 7 ) /* certificate */ // { // assert( strcmp(s, "certificate") == 0 ); // assert( cert_path.empty() ); // cert_path = optarg; // } else if( option_index == 15 ) /* empty */ { assert( strcmp(s, "empty") == 0 ); if( !tag.ReadFromCommaSeparatedString(optarg) ) { std::cerr << "Could not read Tag: " << optarg << std::endl; return 1; } empty_tags.push_back( tag ); } else if( option_index == 16 ) /* remove */ { assert( strcmp(s, "remove") == 0 ); if( !tag.ReadFromCommaSeparatedString(optarg) ) { std::cerr << "Could not read Tag: " << optarg << std::endl; return 1; } remove_tags.push_back( tag ); } else if( option_index == 17 ) /* replace */ { assert( strcmp(s, "replace") == 0 ); if( !tag.ReadFromCommaSeparatedString(optarg) ) { std::cerr << "Could not read Tag: " << optarg << std::endl; return 1; } std::stringstream ss; ss.str( optarg ); uint16_t dummy; char cdummy; // comma ss >> std::hex >> dummy; assert( tag.GetGroup() == dummy ); ss >> cdummy; assert( cdummy == ',' ); ss >> std::hex >> dummy; assert( tag.GetElement() == dummy ); ss >> cdummy; assert( cdummy == ',' || cdummy == '=' ); std::string str; //ss >> str; std::getline(ss, str); // do not skip whitespace replace_tags_value.emplace_back(tag, str ); } else if( option_index == 19 ) /* crypto */ { assert( strcmp(s, "crypto") == 0 ); if (strcmp(optarg, "openssl") == 0) crypto_lib = gdcm::CryptoFactory::OPENSSL; else if (strcmp(optarg, "capi") == 0) crypto_lib = gdcm::CryptoFactory::CAPI; else if (strcmp(optarg, "openssl-p7") == 0) crypto_lib = gdcm::CryptoFactory::OPENSSLP7; else { std::cerr << "Cryptography library id not recognized: " << optarg << std::endl; return 1; } } //printf (" with arg %s", optarg); } //printf ("\n"); } break; case 'i': assert( filename.empty() ); filename = optarg; break; case 'o': assert( outfilename.empty() ); outfilename = optarg; break; case 'r': recursive = 1; break; case 'k': // key assert( rsa_path.empty() ); rsa_path = optarg; break; case 'c': // certificate assert( cert_path.empty() ); cert_path = optarg; break; case 'p': // password assert( password.empty() ); password = optarg; break; case 'e': // encrypt deidentify = 1; break; case 'd': // decrypt reidentify = 1; break; case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { std::vector files; while (optind < argc) { //printf ("%s\n", argv[optind++]); files.emplace_back(argv[optind++] ); } //printf ("\n"); if( files.size() == 2 && filename.empty() && outfilename.empty() ) { filename = files[0]; outfilename = files[1]; } else { PrintHelp(); return 1; } } if( version ) { //std::cout << "version" << std::endl; PrintVersion(); return 0; } if( help ) { //std::cout << "help" << std::endl; PrintHelp(); return 0; } if( filename.empty() ) { //std::cerr << "Need input file (-i)\n"; PrintHelp(); return 1; } // by default de-identify if( !deidentify && !reidentify && !dumb_mode) { deidentify = 1; } // one option only please if( deidentify && reidentify ) { std::cerr << "One option please" << std::endl; return 1; } // dumb mode vs smart mode: if( ( deidentify || reidentify ) && dumb_mode ) { std::cerr << "One option please" << std::endl; return 1; } gdcm::CryptoFactory* crypto_factory = nullptr; if( deidentify || reidentify ) { crypto_factory = gdcm::CryptoFactory::GetFactoryInstance(crypto_lib); if (!crypto_factory) { std::cerr << "Requested cryptographic library not configured." << std::endl; return 1; } } // by default AES 256 gdcm::CryptographicMessageSyntax::CipherTypes ciphertype = gdcm::CryptographicMessageSyntax::AES256_CIPHER; if( !dumb_mode ) { if( !des3 && !aes128 && !aes192 && !aes256 ) { aes256 = 1; } if( des3 ) { ciphertype = GetFromString( "des3" ); } else if( aes128 ) { ciphertype = GetFromString( "aes128" ); } else if( aes192 ) { ciphertype = GetFromString( "aes192" ); } else if( aes256 ) { ciphertype = GetFromString( "aes256" ); } else { return 1; } } if( !gdcm::System::FileExists(filename.c_str()) ) { std::cerr << "Could not find file: " << filename << std::endl; return 1; } // Are we in single file or directory mode: unsigned int nfiles = 1; gdcm::Directory dir; if( gdcm::System::FileIsDirectory(filename.c_str()) ) { if( !gdcm::System::FileIsDirectory(outfilename.c_str()) ) { if( gdcm::System::FileExists( outfilename.c_str() ) ) { std::cerr << "Could not create directory since " << outfilename << " is already a file" << std::endl; return 1; } } // For now avoid user mistake if( filename == outfilename ) { std::cerr << "Input directory should be different from output directory" << std::endl; return 1; } if( outfilename.back() != '/' ) outfilename += '/'; nfiles = dir.Load(filename, (recursive > 0 ? true : false)); filenames = dir.GetFilenames(); gdcm::Directory::FilenamesType::const_iterator it = filenames.begin(); // Prepare outfilenames for( ; it != filenames.end(); ++it ) { std::string dup = *it; // make a copy std::string &out = dup.replace(0, filename.size(), outfilename ); outfilenames.push_back( out ); } // Prepare outdirectory gdcm::Directory::FilenamesType const &dirs = dir.GetDirectories(); gdcm::Directory::FilenamesType::const_iterator itdir = dirs.begin(); for( ; itdir != dirs.end(); ++itdir ) { std::string dirdup = *itdir; // make a copy std::string &dirout = dirdup.replace(0, filename.size(), outfilename ); //std::cout << "Making directory: " << dirout << std::endl; if( !gdcm::System::MakeDirectory( dirout.c_str() ) ) { std::cerr << "Could not create directory: " << dirout << std::endl; return 1; } } } else { filenames.push_back( filename ); outfilenames.push_back( outfilename ); } if( filenames.size() != outfilenames.size() ) { std::cerr << "Something went really wrong" << std::endl; return 1; } // Debug is a little too verbose gdcm::Trace::SetDebug( (debug > 0 ? true : false)); gdcm::Trace::SetWarning( (warning > 0 ? true : false)); gdcm::Trace::SetError( (error > 0 ? true : false)); // when verbose is true, make sure warning+error are turned on: if( verbose ) { gdcm::Trace::SetWarning( (verbose > 0 ? true : false) ); gdcm::Trace::SetError( (verbose > 0 ? true : false) ); } gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( "gdcmanon" ); if( !dumb_mode ) { gdcm::Global& g = gdcm::Global::GetInstance(); if( !resourcespath ) { const char *xmlpathenv = getenv("GDCM_RESOURCES_PATH"); if( xmlpathenv ) { // Make sure to look for XML dict in user explicitly specified dir first: xmlpath = xmlpathenv; resourcespath = 1; } } if( resourcespath ) { // xmlpath is set either by the cmd line option or the env var if( !g.Prepend( xmlpath.c_str() ) ) { std::cerr << "Specified Resources Path is not valid: " << xmlpath << std::endl; return 1; } } // All set, then load the XML files: if( !g.LoadResourcesFiles() ) { std::cerr << "Could not load XML file from specified path" << std::endl; return 1; } const gdcm::Defs &defs = g.GetDefs(); (void)defs; } if( !rootuid ) { // only read the env var if no explicit cmd line option // maybe there is an env var defined... let's check const char *rootuid_env = getenv("GDCM_ROOT_UID"); if( rootuid_env ) { rootuid = 1; root = rootuid_env; } } if( rootuid ) { // root is set either by the cmd line option or the env var if( !gdcm::UIDGenerator::IsValid( root.c_str() ) ) { std::cerr << "specified Root UID is not valid: " << root << std::endl; return 1; } gdcm::UIDGenerator::SetRoot( root.c_str() ); } // Get private key/certificate gdcm::CryptographicMessageSyntax *cms_ptr = nullptr; if( crypto_factory ) { cms_ptr = crypto_factory->CreateCMSProvider(); } if( !dumb_mode ) { if( !GetRSAKeys(*cms_ptr, rsa_path.c_str(), cert_path.c_str() ) ) { delete cms_ptr; return 1; } if (!password.empty() && !cms_ptr->SetPassword(password.c_str(), password.length()) ) { std::cerr << "Could not set the password " << std::endl; delete cms_ptr; return 1; } cms_ptr->SetCipherType( ciphertype ); } // Setup gdcm::Anonymizer gdcm::Anonymizer anon; if( !dumb_mode ) { anon.SetCryptographicMessageSyntax( cms_ptr ); } if( dumb_mode ) { for(unsigned int i = 0; i < nfiles; ++i) { const char *in = filenames[i].c_str(); const char *out = outfilenames[i].c_str(); if( !AnonymizeOneFileDumb(anon, in, out, empty_tags, remove_tags, replace_tags_value, (continuemode > 0 ? true: false)) ) { //std::cerr << "Could not anonymize: " << in << std::endl; delete cms_ptr; return 1; } } } else { for(unsigned int i = 0; i < nfiles; ++i) { const char *in = filenames[i].c_str(); const char *out = outfilenames[i].c_str(); if( !AnonymizeOneFile(anon, in, out, (continuemode > 0 ? true: false)) ) { //std::cerr << "Could not anonymize: " << in << std::endl; delete cms_ptr; return 1; } } } delete cms_ptr; return 0; } GDCM-3.0.10/Applications/Cxx/gdcmcheck.cxx000066400000000000000000000014121412732066400201340ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Need to move gdcminfo --deflated here * gdcmcheck would check for improper Basic Offset Table * JP2 in place of JPEG * more to come ? */ int main(int, char *[]) { return 0; } GDCM-3.0.10/Applications/Cxx/gdcmconv.cxx000066400000000000000000001370031412732066400200320ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * HISTORY: * In GDCM 1.X the preferred term was 'ReWrite', however one author of GDCM dislike * the term ReWrite since it is associated with the highly associated with the Rewrite * notion in software programming where using reinvent the wheel and rewrite from scratch code * the term convert was preferred * * Tools to conv. Goals being to 'purify' a DICOM file. * For now it will do the minimum: * - If Group Length is present, the length is guarantee to be correct * - If Element with Group Tag 0x1, 0x3, 0x5 or 0x7 are present they are * simply discarded (not written). * - Elements are written in alphabetical order * - 32bits VR have the residue bytes sets to 0x0,0x0 * - Same goes from Item Length end delimiter, sets to 0x0,0x0 * - All buggy files (wrong length: GE, 13 and Siemens Leonardo) are fixed * - All size are even (no odd length from gdcm 1.x) * * // \todo: * // --preamble: clean preamble * // --meta: clean meta (meta info version...) * // --dicomV3 (use TS unless not supported) * // --recompute group-length * // --undefined sq * // --explicit sq * * \todo in a close future: * - Set appropriate VR from DICOM dict * - Rewrite PMS SQ into DICOM SQ * - Rewrite Implicit SQ with defined length as undefined length * - PixelData with `overlay` in unused bits should be cleanup * - Any broken JPEG file (wrong bits) should be fixed * - DicomObject bug should be fixed * - Meta and Dataset should have a matching UID (more generally File Meta * should be correct (Explicit!) and consistent with DataSet) * - User should be able to specify he wants Group Length (or remove them) * - Media SOP should be correct (deduct from something else or set to * SOP Secondary if all else fail). * - Padding character should be correct * * \todo distant future: * - Later on, it should run through a Validator * which will make sure all field 1, 1C are present and those only * - In a perfect world I should remove private tags and transform them into * public fields. * - DA should be correct, PN should be correct (no space!) * - Enumerated Value should be correct */ /* check-meta is ideal for image like: gdcmconv -C gdcmData/PICKER-16-MONO2-No_DicomV3_Preamble.dcm bla.dcm */ #include "gdcmReader.h" #include "gdcmFileDerivation.h" #include "gdcmAnonymizer.h" #include "gdcmVersion.h" #include "gdcmPixmapReader.h" #include "gdcmPixmapWriter.h" #include "gdcmWriter.h" #include "gdcmSystem.h" #include "gdcmFileMetaInformation.h" #include "gdcmDataSet.h" #include "gdcmIconImageGenerator.h" #include "gdcmAttribute.h" #include "gdcmSequenceOfItems.h" #include "gdcmUIDGenerator.h" #include "gdcmImage.h" #include "gdcmImageChangeTransferSyntax.h" #include "gdcmImageApplyLookupTable.h" #include "gdcmFileDecompressLookupTable.h" #include "gdcmImageFragmentSplitter.h" #include "gdcmImageChangePlanarConfiguration.h" #include "gdcmImageChangePhotometricInterpretation.h" #include "gdcmFileExplicitFilter.h" #include "gdcmJPEG2000Codec.h" #include "gdcmJPEGCodec.h" #include "gdcmJPEGLSCodec.h" #include "gdcmSequenceOfFragments.h" #include #include #include /* for printf */ #include /* for exit */ #include #include struct SetSQToUndefined { void operator() (gdcm::DataElement &de) { de.SetVLToUndefined(); } }; static void PrintVersion() { std::cout << "gdcmconv: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; } static void PrintLossyWarning() { std::cout << "You have selected a lossy compression transfer syntax." << std::endl; std::cout << "This will degrade the quality of your input image, and can." << std::endl; std::cout << "impact professional interpretation of the image." << std::endl; std::cout << "Do not use if you do not understand the risk." << std::endl; std::cout << "WARNING: this mode is very experimental." << std::endl; } static void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcmconv [OPTION] input.dcm output.dcm" << std::endl; std::cout << "Convert a DICOM file into another DICOM file.\n"; std::cout << "Parameter (required):" << std::endl; std::cout << " -i --input DICOM filename" << std::endl; std::cout << " -o --output DICOM filename" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -X --explicit Change Transfer Syntax to explicit." << std::endl; std::cout << " -M --implicit Change Transfer Syntax to implicit." << std::endl; std::cout << " -U --use-dict Use dict for VR (only public by default)." << std::endl; std::cout << " --with-private-dict Use private dict for VR (advanced user only)." << std::endl; std::cout << " -C --check-meta Check File Meta Information (advanced user only)." << std::endl; std::cout << " --root-uid Root UID." << std::endl; std::cout << " --remove-gl Remove group length (deprecated in DICOM 2008)." << std::endl; std::cout << " --remove-private-tags Remove private tags." << std::endl; std::cout << " --remove-retired Remove retired tags." << std::endl; std::cout << "Image only Options:" << std::endl; std::cout << " -l --apply-lut Apply LUT (non-standard, advanced user only)." << std::endl; std::cout << " -8 --apply-lut8 Apply LUT/RGB8 (non-standard, advanced user only)." << std::endl; std::cout << " --decompress-lut Decompress LUT (linearize segmented LUT)." << std::endl; std::cout << " -P --photometric-interpretation %s Change Photometric Interpretation (when possible)." << std::endl; std::cout << " -w --raw Decompress image." << std::endl; std::cout << " -d --deflated Compress using deflated (gzip)." << std::endl; std::cout << " -J --jpeg Compress image in jpeg." << std::endl; std::cout << " -K --j2k Compress image in j2k." << std::endl; std::cout << " -L --jpegls Compress image in jpeg-ls." << std::endl; std::cout << " -R --rle Compress image in rle (lossless only)." << std::endl; std::cout << " -F --force Force decompression/merging before recompression/splitting." << std::endl; std::cout << " --generate-icon Generate icon." << std::endl; std::cout << " --icon-minmax %d,%d Min/Max value for icon." << std::endl; std::cout << " --icon-auto-minmax Automatically compute best Min/Max values for icon." << std::endl; std::cout << " --compress-icon Decide whether icon follows main TransferSyntax or remains uncompressed." << std::endl; std::cout << " --planar-configuration [01] Change planar configuration." << std::endl; std::cout << " -Y --lossy Use the lossy (if possible) compressor." << std::endl; std::cout << " -S --split %d Write 2D image with multiple fragments (using max size)" << std::endl; std::cout << "General Options:" << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " -v --version print version." << std::endl; std::cout << " --quiet do not print to stdout." << std::endl; std::cout << "JPEG Options:" << std::endl; std::cout << " -q --quality %*f set quality." << std::endl; std::cout << "JPEG-LS Options:" << std::endl; std::cout << " -e --allowed-error %*i set allowed error." << std::endl; std::cout << "J2K Options:" << std::endl; std::cout << " -r --rate %*f set rate." << std::endl; std::cout << " -q --quality %*f set quality." << std::endl; std::cout << " -t --tile %d,%d set tile size." << std::endl; std::cout << " -n --number-resolution %d set number of resolution." << std::endl; std::cout << " --irreversible set irreversible." << std::endl; std::cout << "Special Options:" << std::endl; std::cout << " -I --ignore-errors convert even if file is corrupted (advanced users only, see disclaimers)." << std::endl; std::cout << "Env var:" << std::endl; std::cout << " GDCM_ROOT_UID Root UID" << std::endl; /* * Default behavior for root UID is: * By default the GDCM one is used * If GDCM_ROOT_UID is set, then use this one instead * If --root-uid is explicitly set on the command line, it will override any other defined behavior */ } template static size_t readvector(std::vector &v, const char *str) { if( !str ) return 0; std::istringstream os( str ); T f; while( os >> f ) { v.push_back( f ); os.get(); // == "," } return v.size(); } namespace gdcm { static bool derives( File & file, const Pixmap& compressed_image ) { #if 1 DataSet &ds = file.GetDataSet(); if( !ds.FindDataElement( Tag(0x0008,0x0016) ) || ds.GetDataElement( Tag(0x0008,0x0016) ).IsEmpty() ) { return false; } if( !ds.FindDataElement( Tag(0x0008,0x0018) ) || ds.GetDataElement( Tag(0x0008,0x0018) ).IsEmpty() ) { return false; } const DataElement &sopclassuid = ds.GetDataElement( Tag(0x0008,0x0016) ); const DataElement &sopinstanceuid = ds.GetDataElement( Tag(0x0008,0x0018) ); // Make sure that const char* pointer will be properly padded with \0 char: std::string sopclassuid_str( sopclassuid.GetByteValue()->GetPointer(), sopclassuid.GetByteValue()->GetLength() ); std::string sopinstanceuid_str( sopinstanceuid.GetByteValue()->GetPointer(), sopinstanceuid.GetByteValue()->GetLength() ); ds.Remove( Tag(0x8,0x18) ); FileDerivation fd; fd.SetFile( file ); fd.AddReference( sopclassuid_str.c_str(), sopinstanceuid_str.c_str() ); // CID 7202 Source Image Purposes of Reference // {"DCM",121320,"Uncompressed predecessor"}, fd.SetPurposeOfReferenceCodeSequenceCodeValue( 121320 ); // CID 7203 Image Derivation // { "DCM",113040,"Lossy Compression" }, fd.SetDerivationCodeSequenceCodeValue( 113040 ); fd.SetDerivationDescription( "lossy conversion" ); if( !fd.Derive() ) { std::cerr << "Sorry could not derive using input info" << std::endl; return false; } #else /* (0008,2111) ST [Lossy compression with JPEG extended sequential 8 bit, IJG quality... # 102, 1 DerivationDescription (0008,2112) SQ (Sequence with explicit length #=1) # 188, 1 SourceImageSequence (fffe,e000) na (Item with explicit length #=3) # 180, 1 Item (0008,1150) UI =UltrasoundImageStorage # 28, 1 ReferencedSOPClassUID (0008,1155) UI [1.2.840.1136190195280574824680000700.3.0.1.19970424140438] # 58, 1 ReferencedSOPInstanceUID (0040,a170) SQ (Sequence with explicit length #=1) # 66, 1 PurposeOfReferenceCodeSequence (fffe,e000) na (Item with explicit length #=3) # 58, 1 Item (0008,0100) SH [121320] # 6, 1 CodeValue (0008,0102) SH [DCM] # 4, 1 CodingSchemeDesignator (0008,0104) LO [Uncompressed predecessor] # 24, 1 CodeMeaning (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem */ const Tag sisq(0x8,0x2112); SequenceOfItems * sqi; sqi = new SequenceOfItems; DataElement de( sisq); de.SetVR( VR::SQ ); de.SetValue( *sqi ); de.SetVLToUndefined(); DataSet &ds = file.GetDataSet(); ds.Insert( de ); { // (0008,0008) CS [ORIGINAL\SECONDARY] # 18, 2 ImageType gdcm::Attribute<0x0008,0x0008> at3; static const gdcm::CSComp values[] = {"DERIVED","SECONDARY"}; at3.SetValues( values, 2, true ); // true => copy data ! if( ds.FindDataElement( at3.GetTag() ) ) { const gdcm::DataElement &de = ds.GetDataElement( at3.GetTag() ); at3.SetFromDataElement( de ); // Make sure that value #1 is at least 'DERIVED', so override in all cases: at3.SetValue( 0, values[0] ); } ds.Replace( at3.GetAsDataElement() ); } { Attribute<0x0008,0x2111> at1; at1.SetValue( "lossy conversion" ); ds.Replace( at1.GetAsDataElement() ); } sqi = (SequenceOfItems*)ds.GetDataElement( sisq ).GetSequenceOfItems(); sqi->SetLengthToUndefined(); if( !sqi->GetNumberOfItems() ) { Item item; //( Tag(0xfffe,0xe000) ); item.SetVLToUndefined(); sqi->AddItem( item ); } Item &item1 = sqi->GetItem(1); DataSet &subds = item1.GetNestedDataSet(); /* (0008,1150) UI =UltrasoundImageStorage # 28, 1 ReferencedSOPClassUID (0008,1155) UI [1.2.840.1136190195280574824680000700.3.0.1.19970424140438] # 58, 1 ReferencedSOPInstanceUID */ { DataElement sopinstanceuid = ds.GetDataElement( Tag(0x0008,0x0016) ); sopinstanceuid.SetTag( Tag(0x8,0x1150 ) ); subds.Replace( sopinstanceuid ); DataElement sopclassuid = ds.GetDataElement( Tag(0x0008,0x0018) ); sopclassuid.SetTag( Tag(0x8,0x1155 ) ); subds.Replace( sopclassuid ); ds.Remove( Tag(0x8,0x18) ); } const Tag prcs(0x0040,0xa170); if( !subds.FindDataElement( prcs) ) { SequenceOfItems *sqi2 = new SequenceOfItems; DataElement de( prcs ); de.SetVR( VR::SQ ); de.SetValue( *sqi2 ); de.SetVLToUndefined(); subds.Insert( de ); } sqi = (SequenceOfItems*)subds.GetDataElement( prcs ).GetSequenceOfItems(); sqi->SetLengthToUndefined(); if( !sqi->GetNumberOfItems() ) { Item item; //( Tag(0xfffe,0xe000) ); item.SetVLToUndefined(); sqi->AddItem( item ); } Item &item2 = sqi->GetItem(1); DataSet &subds2 = item2.GetNestedDataSet(); /* (0008,0100) SH [121320] # 6, 1 CodeValue (0008,0102) SH [DCM] # 4, 1 CodingSchemeDesignator (0008,0104) LO [Uncompressed predecessor] # 24, 1 CodeMeaning */ Attribute<0x0008,0x0100> at1; at1.SetValue( "121320" ); subds2.Replace( at1.GetAsDataElement() ); Attribute<0x0008,0x0102> at2; at2.SetValue( "DCM" ); subds2.Replace( at2.GetAsDataElement() ); Attribute<0x0008,0x0104> at3; at3.SetValue( "Uncompressed predecessor" ); subds2.Replace( at3.GetAsDataElement() ); /* (0008,9215) SQ (Sequence with explicit length #=1) # 98, 1 DerivationCodeSequence (fffe,e000) na (Item with explicit length #=3) # 90, 1 Item (0008,0100) SH [121327] # 6, 1 CodeValue (0008,0102) SH [DCM] # 4, 1 CodingSchemeDesignator (0008,0104) LO [Full fidelity image, uncompressed or lossless compressed] # 56, 1 CodeMeaning (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem */ { const Tag sisq(0x8,0x9215); SequenceOfItems * sqi; sqi = new SequenceOfItems; DataElement de( sisq ); de.SetVR( VR::SQ ); de.SetValue( *sqi ); de.SetVLToUndefined(); ds.Insert( de ); sqi = (SequenceOfItems*)ds.GetDataElement( sisq ).GetSequenceOfItems(); sqi->SetLengthToUndefined(); if( !sqi->GetNumberOfItems() ) { Item item; //( Tag(0xfffe,0xe000) ); item.SetVLToUndefined(); sqi->AddItem( item ); } Item &item1 = sqi->GetItem(1); DataSet &subds3 = item1.GetNestedDataSet(); Attribute<0x0008,0x0100> at1; at1.SetValue( "121327" ); subds3.Replace( at1.GetAsDataElement() ); Attribute<0x0008,0x0102> at2; at2.SetValue( "DCM" ); subds3.Replace( at2.GetAsDataElement() ); Attribute<0x0008,0x0104> at3; at3.SetValue( "Full fidelity image, uncompressed or lossless compressed" ); subds3.Replace( at3.GetAsDataElement() ); } #endif { /* (0028,2110) CS [01] # 2, 1 LossyImageCompression (0028,2112) DS [15.95] # 6, 1 LossyImageCompressionRatio (0028,2114) CS [ISO_10918_1] # 12, 1 LossyImageCompressionMethod */ const DataElement & pixeldata = compressed_image.GetDataElement(); size_t len = pixeldata.GetSequenceOfFragments()->ComputeByteLength(); size_t reflen = compressed_image.GetBufferLength(); double ratio = (double)reflen / (double)len; Attribute<0x0028,0x2110> at1; at1.SetValue( "01" ); ds.Replace( at1.GetAsDataElement() ); Attribute<0x0028,0x2112> at2; at2.SetValues( &ratio, 1); ds.Replace( at2.GetAsDataElement() ); Attribute<0x0028,0x2114> at3; // ImageWriter will properly set attribute 0028,2114 (Lossy Image Compression Method) } return true; } } // end namespace gdcm int main (int argc, char *argv[]) { int c; //int digit_optind = 0; std::string filename; std::string outfilename; std::string root; int explicitts = 0; // explicit is a reserved keyword int implicit = 0; int quiet = 0; int lut = 0; int lut8 = 0; int decompress_lut = 0; int raw = 0; int deflated = 0; int rootuid = 0; int checkmeta = 0; int jpeg = 0; int jpegls = 0; int j2k = 0; int lossy = 0; int split = 0; int fragmentsize = 0; int rle = 0; int force = 0; int planarconf = 0; int planarconfval = 0; double iconmin = 0; double iconmax = 0; int usedict = 0; int compressicon = 0; int generateicon = 0; int iconminmax = 0; int iconautominmax = 0; int removegrouplength = 0; int removeprivate = 0; int removeretired = 0; int photometricinterpretation = 0; std::string photometricinterpretation_str; int quality = 0; int rate = 0; int tile = 0; int nres = 0; int nresvalue = 6; // ?? std::vector qualities; std::vector rates; std::vector tilesize; int irreversible = 0; int changeprivatetags = 0; int verbose = 0; int warning = 0; int debug = 0; int error = 0; int help = 0; int version = 0; int ignoreerrors = 0; int jpeglserror = 0; int jpeglserror_value = 0; while (true) { //int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"input", 1, nullptr, 0}, {"output", 1, nullptr, 0}, {"group-length", 1, nullptr, 0}, // valid / create / remove {"preamble", 1, nullptr, 0}, // valid / create / remove {"padding", 1, nullptr, 0}, // valid (\0 -> space) / optimize (at most 1 byte of padding) {"vr", 1, nullptr, 0}, // valid {"sop", 1, nullptr, 0}, // default to SC... {"iod", 1, nullptr, 0}, // valid {"meta", 1, nullptr, 0}, // valid / create / remove {"dataset", 1, nullptr, 0}, // valid / create / remove? {"sequence", 1, nullptr, 0}, // defined / undefined {"deflate", 1, nullptr, 0}, // 1 - 9 / best = 9 / fast = 1 {"tag", 1, nullptr, 0}, // need to specify a tag xxxx,yyyy = value to override default {"name", 1, nullptr, 0}, // same as tag but explicit use of name {"root-uid", 1, &rootuid, 1}, // specific Root (not GDCM) {"check-meta", 0, &checkmeta, 1}, // specific Root (not GDCM) // Image specific options: {"pixeldata", 1, nullptr, 0}, // valid {"apply-lut", 0, &lut, 1}, // default (implicit VR, LE) / Explicit LE / Explicit BE {"raw", 0, &raw, 1}, // default (implicit VR, LE) / Explicit LE / Explicit BE {"deflated", 0, &deflated, 1}, // DeflatedExplicitVRLittleEndian {"lossy", 0, &lossy, 1}, // Specify lossy comp {"force", 0, &force, 1}, // force decompression even if target compression is identical {"jpeg", 0, &jpeg, 1}, // JPEG lossy / lossless {"jpegls", 0, &jpegls, 1}, // JPEG-LS: lossy / lossless {"j2k", 0, &j2k, 1}, // J2K: lossy / lossless {"rle", 0, &rle, 1}, // lossless ! {"mpeg2", 0, nullptr, 0}, // lossy ! {"jpip", 0, nullptr, 0}, // ?? {"split", 1, &split, 1}, // split fragments {"planar-configuration", 1, &planarconf, 1}, // Planar Configuration {"explicit", 0, &explicitts, 1}, // {"implicit", 0, &implicit, 1}, // {"use-dict", 0, &usedict, 1}, // {"generate-icon", 0, &generateicon, 1}, // {"icon-minmax", 1, &iconminmax, 1}, // {"icon-auto-minmax", 0, &iconautominmax, 1}, // {"compress-icon", 0, &compressicon, 1}, // {"remove-gl", 0, &removegrouplength, 1}, // {"remove-private-tags", 0, &removeprivate, 1}, // {"remove-retired", 0, &removeretired, 1}, // {"photometric-interpretation", 1, &photometricinterpretation, 1}, // {"with-private-dict", 0, &changeprivatetags, 1}, // {"decompress-lut", 0, &decompress_lut, 1}, // linearized segmented LUT {"apply-lut8", 0, &lut8, 1}, // j2k : {"rate", 1, &rate, 1}, // {"quality", 1, &quality, 1}, // will also work for regular jpeg compressor {"tile", 1, &tile, 1}, // {"number-resolution", 1, &nres, 1}, // {"irreversible", 0, &irreversible, 1}, // {"allowed-error", 1, &jpeglserror, 1}, // // General options ! {"verbose", 0, &verbose, 1}, {"warning", 0, &warning, 1}, {"debug", 0, &debug, 1}, {"error", 0, &error, 1}, {"help", 0, &help, 1}, {"version", 0, &version, 1}, {"ignore-errors", 0, &ignoreerrors, 1}, {"quiet", 0, &quiet, 1}, {nullptr, 0, nullptr, 0} }; c = getopt_long (argc, argv, "i:o:XMUCl8wdJKLRFYS:P:VWDEhvIr:q:t:n:e:", long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: { const char *s = long_options[option_index].name; (void)s; //printf ("option %s", s); if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); assert( filename.empty() ); filename = optarg; } else if( option_index == 14 ) /* root-uid */ { assert( strcmp(s, "root-uid") == 0 ); assert( root.empty() ); root = optarg; } else if( option_index == 28 ) /* split */ { assert( strcmp(s, "split") == 0 ); fragmentsize = atoi(optarg); } else if( option_index == 29 ) /* planar conf*/ { assert( strcmp(s, "planar-configuration") == 0 ); planarconfval = atoi(optarg); } else if( option_index == 34 ) /* icon minmax*/ { assert( strcmp(s, "icon-minmax") == 0 ); std::stringstream ss; ss.str( optarg ); ss >> iconmin; char comma; ss >> comma; ss >> iconmax; } else if( option_index == 40 ) /* photometricinterpretation */ { assert( strcmp(s, "photometric-interpretation") == 0 ); photometricinterpretation_str = optarg; } else if( option_index == 42 ) /* rate */ { assert( strcmp(s, "rate") == 0 ); readvector(rates, optarg); } else if( option_index == 43 ) /* quality */ { assert( strcmp(s, "quality") == 0 ); readvector(qualities, optarg); } else if( option_index == 44 ) /* tile */ { assert( strcmp(s, "tile") == 0 ); size_t n = readvector(tilesize, optarg); assert( n == 2 ); (void)n; } else if( option_index == 45 ) /* number of resolution */ { assert( strcmp(s, "number-resolution") == 0 ); nresvalue = atoi(optarg); } else if( option_index == 47 ) /* JPEG-LS error */ { assert( strcmp(s, "allowed-error") == 0 ); jpeglserror_value = atoi(optarg); } //printf (" with arg %s, index = %d", optarg, option_index); } //printf ("\n"); } break; case 'i': //printf ("option i with value '%s'\n", optarg); assert( filename.empty() ); filename = optarg; break; case 'o': //printf ("option o with value '%s'\n", optarg); assert( outfilename.empty() ); outfilename = optarg; break; case 'X': explicitts = 1; break; case 'M': implicit = 1; break; case 'U': usedict = 1; break; case 'C': checkmeta = 1; break; // root-uid case 'l': lut = 1; break; case '8': lut8 = 1; break; case 'w': raw = 1; break; case 'e': jpeglserror = 1; jpeglserror_value = atoi(optarg); break; case 'd': deflated = 1; break; case 'J': jpeg = 1; break; case 'K': j2k = 1; break; case 'L': jpegls = 1; break; case 'R': rle = 1; break; case 'F': force = 1; break; case 'Y': lossy = 1; break; case 'S': split = 1; fragmentsize = atoi(optarg); break; case 'P': photometricinterpretation = 1; photometricinterpretation_str = optarg; break; case 'r': rate = 1; readvector(rates, optarg); break; case 'q': quality = 1; readvector(qualities, optarg); break; case 't': tile = 1; readvector(tilesize, optarg); break; case 'n': nres = 1; nresvalue = atoi(optarg); break; // General option case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case 'I': ignoreerrors = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } // For now only support one input / one output if (optind < argc) { //printf ("non-option ARGV-elements: "); std::vector files; while (optind < argc) { //printf ("%s\n", argv[optind++]); files.emplace_back(argv[optind++] ); } //printf ("\n"); if( files.size() == 2 && filename.empty() && outfilename.empty() ) { filename = files[0]; outfilename = files[1]; } else { PrintHelp(); return 1; } } if( version ) { //std::cout << "version" << std::endl; PrintVersion(); return 0; } if( help ) { //std::cout << "help" << std::endl; PrintHelp(); return 0; } if( filename.empty() ) { //std::cerr << "Need input file (-i)\n"; PrintHelp(); return 1; } if( outfilename.empty() ) { //std::cerr << "Need output file (-o)\n"; PrintHelp(); return 1; } // Debug is a little too verbose gdcm::Trace::SetDebug( (debug > 0 ? true : false)); gdcm::Trace::SetWarning( (warning > 0 ? true : false)); gdcm::Trace::SetError( (error > 0 ? true : false)); // when verbose is true, make sure warning+error are turned on: if( verbose ) { gdcm::Trace::SetWarning( (verbose > 0 ? true : false) ); gdcm::Trace::SetError( (verbose > 0 ? true : false) ); } gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( "gdcmconv" ); if( !rootuid ) { // only read the env var is no explicit cmd line option // maybe there is an env var defined... let's check const char *rootuid_env = getenv("GDCM_ROOT_UID"); if( rootuid_env ) { rootuid = 1; root = rootuid_env; } } if( rootuid ) { // root is set either by the cmd line option or the env var if( !gdcm::UIDGenerator::IsValid( root.c_str() ) ) { std::cerr << "specified Root UID is not valid: " << root << std::endl; return 1; } gdcm::UIDGenerator::SetRoot( root.c_str() ); } if( removegrouplength || removeprivate || removeretired ) { gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } gdcm::MediaStorage ms; ms.SetFromFile( reader.GetFile() ); if( ms == gdcm::MediaStorage::MediaStorageDirectoryStorage ) { std::cerr << "Sorry DICOMDIR is not supported" << std::endl; return 1; } gdcm::Anonymizer ano; ano.SetFile( reader.GetFile() ); if( removegrouplength ) { if( !ano.RemoveGroupLength() ) { std::cerr << "Could not remove group length" << std::endl; } } if( removeretired ) { if( !ano.RemoveRetired() ) { std::cerr << "Could not remove retired tags" << std::endl; } } if( removeprivate ) { if( !ano.RemovePrivateTags() ) { std::cerr << "Could not remove private tags" << std::endl; } } gdcm::Writer writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( ano.GetFile() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } return 0; } // Handle here the general file (not required to be image) if ( !raw && (explicitts || implicit || deflated) ) { if( explicitts && implicit ) return 1; // guard if( explicitts && deflated ) return 1; // guard if( implicit && deflated ) return 1; // guard gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } gdcm::MediaStorage ms; ms.SetFromFile( reader.GetFile() ); if( ms == gdcm::MediaStorage::MediaStorageDirectoryStorage ) { std::cerr << "Sorry DICOMDIR is not supported" << std::endl; return 1; } gdcm::Writer writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); gdcm::File & file = writer.GetFile(); gdcm::FileMetaInformation &fmi = file.GetHeader(); const gdcm::TransferSyntax &orits = fmi.GetDataSetTransferSyntax(); if( orits != gdcm::TransferSyntax::ExplicitVRLittleEndian && orits != gdcm::TransferSyntax::ImplicitVRLittleEndian && orits != gdcm::TransferSyntax::DeflatedExplicitVRLittleEndian ) { std::cerr << "Sorry input Transfer Syntax not supported for this conversion: " << orits << std::endl; return 1; } gdcm::TransferSyntax ts = gdcm::TransferSyntax::ImplicitVRLittleEndian; if( explicitts ) { ts = gdcm::TransferSyntax::ExplicitVRLittleEndian; } else if( deflated ) { ts = gdcm::TransferSyntax::DeflatedExplicitVRLittleEndian; } std::string tsuid = gdcm::TransferSyntax::GetTSString( ts ); if( tsuid.size() % 2 == 1 ) { tsuid.push_back( 0 ); // 0 padding } gdcm::DataElement de( gdcm::Tag(0x0002,0x0010) ); de.SetByteValue( &tsuid[0], (uint32_t)tsuid.size() ); de.SetVR( gdcm::Attribute<0x0002, 0x0010>::GetVR() ); fmi.Clear(); fmi.Replace( de ); fmi.SetDataSetTransferSyntax(ts); if( explicitts || deflated ) { gdcm::FileExplicitFilter fef; fef.SetChangePrivateTags( (changeprivatetags > 0 ? true: false)); fef.SetFile( reader.GetFile() ); if( !fef.Change() ) { std::cerr << "Failed to change: " << filename << std::endl; return 1; } } if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } return 0; } // split fragments if( split ) { gdcm::PixmapReader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Could not read (pixmap): " << filename << std::endl; return 1; } const gdcm::Pixmap &image = reader.GetPixmap(); gdcm::ImageFragmentSplitter splitter; splitter.SetInput( image ); splitter.SetFragmentSizeMax( fragmentsize ); splitter.SetForce( (force > 0 ? true: false)); bool b = splitter.Split(); if( !b ) { std::cerr << "Could not split: " << filename << std::endl; return 1; } gdcm::PixmapWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); writer.SetPixmap( splitter.PixmapToPixmapFilter::GetOutput() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } } else if( photometricinterpretation ) { gdcm::PixmapReader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Could not read (pixmap): " << filename << std::endl; return 1; } const gdcm::Pixmap &image = reader.GetPixmap(); // Just in case: if( gdcm::PhotometricInterpretation::GetPIType(photometricinterpretation_str.c_str()) == gdcm::PhotometricInterpretation::PI_END ) { std::cerr << "Do not handle PhotometricInterpretation: " << photometricinterpretation_str << std::endl; return 1; } gdcm::PhotometricInterpretation pi ( gdcm::PhotometricInterpretation::GetPIType(photometricinterpretation_str.c_str()) ); gdcm::ImageChangePhotometricInterpretation pifilt; pifilt.SetInput( image ); pifilt.SetPhotometricInterpretation( pi ); bool b = pifilt.Change(); if( !b ) { std::cerr << "Could not apply PhotometricInterpretation: " << filename << std::endl; return 1; } gdcm::PixmapWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); writer.SetPixmap( pifilt.PixmapToPixmapFilter::GetOutput() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } } else if( decompress_lut ) { gdcm::PixmapReader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Could not read (pixmap): " << filename << std::endl; return 1; } const gdcm::Pixmap &image = reader.GetPixmap(); gdcm::FileDecompressLookupTable lutfilt; lutfilt.SetFile( reader.GetFile() ); lutfilt.SetPixmap( image ); bool b = lutfilt.Change(); if( !b ) { std::cerr << "Could not decompress LUT: " << filename << std::endl; return 1; } gdcm::PixmapWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); writer.SetPixmap( lutfilt.GetPixmap() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } } else if( lut || lut8 ) { gdcm::PixmapReader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Could not read (pixmap): " << filename << std::endl; return 1; } const gdcm::Pixmap &image = reader.GetPixmap(); gdcm::ImageApplyLookupTable lutfilt; lutfilt.SetInput( image ); lutfilt.SetRGB8( lut8 != 0 ); bool b = lutfilt.Apply(); if( !b ) { std::cerr << "Could not apply LUT: " << filename << std::endl; return 1; } gdcm::PixmapWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); writer.SetPixmap( lutfilt.PixmapToPixmapFilter::GetOutput() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } } else if( jpeg || j2k || jpegls || rle || raw || force /*|| deflated*/ /*|| planarconf*/ ) { gdcm::PixmapReader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Could not read (pixmap): " << filename << std::endl; return 1; } gdcm::Pixmap &image = reader.GetPixmap(); //const gdcm::IconImage &icon = image.GetIconImage(); //if( !icon.IsEmpty() ) // { // std::cerr << "Icons are not supported" << std::endl; // return 1; // } if( generateicon ) { gdcm::IconImageGenerator iig; iig.SetPixmap( image ); const unsigned int idims[2] = { 64, 64 }; iig.SetOutputDimensions( idims ); if( iconminmax ) { iig.SetPixelMinMax( iconmin, iconmax ); } iig.AutoPixelMinMax( iconautominmax ? true : false ); bool b = iig.Generate(); if( !b ) return 1; const gdcm::IconImage &icon = iig.GetIconImage(); image.SetIconImage( icon ); } gdcm::JPEG2000Codec j2kcodec; gdcm::JPEGCodec jpegcodec; gdcm::JPEGLSCodec jpeglscodec; gdcm::ImageChangeTransferSyntax change; change.SetForce( (force > 0 ? true: false)); change.SetCompressIconImage( (compressicon > 0 ? true: false)); if( jpeg ) { if( lossy ) { const gdcm::PixelFormat &pf = image.GetPixelFormat(); if( pf.GetBitsAllocated() > 8 ) change.SetTransferSyntax(gdcm::TransferSyntax::JPEGExtendedProcess2_4); else change.SetTransferSyntax( gdcm::TransferSyntax::JPEGBaselineProcess1 ); jpegcodec.SetLossless( false ); if( quality ) { assert( qualities.size() == 1 ); jpegcodec.SetQuality( static_cast(qualities[0]) ); } change.SetUserCodec( &jpegcodec ); } else { change.SetTransferSyntax( gdcm::TransferSyntax::JPEGLosslessProcess14_1 ); } } else if( jpegls ) { if( lossy ) { change.SetTransferSyntax( gdcm::TransferSyntax::JPEGLSNearLossless ); jpeglscodec.SetLossless( false ); if( jpeglserror ) { jpeglscodec.SetLossyError( jpeglserror_value ); } change.SetUserCodec( &jpeglscodec ); } else { change.SetTransferSyntax( gdcm::TransferSyntax::JPEGLSLossless ); } } else if( j2k ) { if( lossy ) { change.SetTransferSyntax( gdcm::TransferSyntax::JPEG2000 ); if( rate ) { int i = 0; for(std::vector::const_iterator it = rates.begin(); it != rates.end(); ++it ) { j2kcodec.SetRate(i++, static_cast(*it) ); } } if( quality ) { int i = 0; for(std::vector::const_iterator it = qualities.begin(); it != qualities.end(); ++it ) { j2kcodec.SetQuality( i++, static_cast(*it) ); } } if( tile ) { j2kcodec.SetTileSize( tilesize[0], tilesize[1] ); } if( nres ) { j2kcodec.SetNumberOfResolutions( nresvalue ); } j2kcodec.SetReversible( !irreversible ); change.SetUserCodec( &j2kcodec ); } else { change.SetTransferSyntax( gdcm::TransferSyntax::JPEG2000Lossless ); } } else if( raw ) { if( lossy ) { std::cerr << "no such thing as raw & lossy" << std::endl; return 1; } const gdcm::TransferSyntax &ts = image.GetTransferSyntax(); #ifdef GDCM_WORDS_BIGENDIAN (void)ts; change.SetTransferSyntax( gdcm::TransferSyntax::ExplicitVRBigEndian ); #else if( ts.IsExplicit() ) { change.SetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); if( implicit ) change.SetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian ); } else { assert( ts.IsImplicit() ); change.SetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian ); if( explicitts ) change.SetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); } #endif } else if( rle ) { if( lossy ) { std::cerr << "no such thing as rle & lossy" << std::endl; return 1; } change.SetTransferSyntax( gdcm::TransferSyntax::RLELossless ); } else if( deflated ) { if( lossy ) { std::cerr << "no such thing as deflated & lossy" << std::endl; return 1; } change.SetTransferSyntax( gdcm::TransferSyntax::DeflatedExplicitVRLittleEndian ); } else if( force ) { // If image is encapsulated it will check some attribute (col/row/pi/pf) and // some attributes... } else { std::cerr << "unhandled action" << std::endl; return 1; } if( raw && planarconf ) { gdcm::ImageChangePlanarConfiguration icpc; icpc.SetPlanarConfiguration( planarconfval ); icpc.SetInput( image ); bool b = icpc.Change(); if( !b ) { std::cerr << "Could not change the Planar Configuration: " << filename << std::endl; return 1; } change.SetInput( icpc.PixmapToPixmapFilter::GetOutput() ); } else { change.SetInput( image ); } bool b = change.Change(); if( !b ) { std::cerr << "Could not change the Transfer Syntax: " << filename << std::endl; return 1; } if( lossy ) { if(!quiet) PrintLossyWarning(); if( !gdcm::derives( reader.GetFile(), change.PixmapToPixmapFilter::GetOutput() ) ) { std::cerr << "Failed to derives: " << filename << std::endl; return 1; } } if( usedict /*ts.IsImplicit()*/ ) { gdcm::FileExplicitFilter fef; fef.SetChangePrivateTags( (changeprivatetags > 0 ? true : false)); fef.SetFile( reader.GetFile() ); if(!fef.Change()) { std::cerr << "Failed to change: " << filename << std::endl; return 1; } } gdcm::PixmapWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); //writer.SetFile( fef.GetFile() ); gdcm::File & file = writer.GetFile(); gdcm::FileMetaInformation &fmi = file.GetHeader(); fmi.Remove( gdcm::Tag(0x0002,0x0100) ); // ' ' ' // PrivateInformationCreatorUID fmi.Remove( gdcm::Tag(0x0002,0x0102) ); // ' ' ' // PrivateInformation const gdcm::Pixmap &pixout = change.PixmapToPixmapFilter::GetOutput(); writer.SetPixmap( pixout ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } } else if( raw && false ) { gdcm::PixmapReader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Could not read (pixmap): " << filename << std::endl; return 1; } const gdcm::Pixmap &ir = reader.GetPixmap(); gdcm::Pixmap image( ir ); const gdcm::TransferSyntax &ts = ir.GetTransferSyntax(); if( ts.IsExplicit() ) { image.SetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); } else { assert( ts.IsImplicit() ); image.SetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian ); } /* image.SetNumberOfDimensions( ir.GetNumberOfDimensions() ); const unsigned int *dims = ir.GetDimensions(); image.SetDimension(0, dims[0] ); image.SetDimension(1, dims[1] ); const gdcm::PixelFormat &pixeltype = ir.GetPixelFormat(); image.SetPixelFormat( pixeltype ); const gdcm::PhotometricInterpretation &pi = ir.GetPhotometricInterpretation(); image.SetPhotometricInterpretation( pi ); */ unsigned long len = ir.GetBufferLength(); //assert( len = ir.GetBufferLength() ); std::vector buffer; buffer.resize(len); // black image ir.GetBuffer( &buffer[0] ); gdcm::ByteValue *bv = new gdcm::ByteValue(buffer); gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0,0x0010) ); pixeldata.SetValue( *bv ); image.SetDataElement( pixeldata ); gdcm::PixmapWriter writer; writer.SetFile( reader.GetFile() ); writer.SetPixmap( image ); writer.SetFileName( outfilename.c_str() ); if( !writer.Write() ) { std::cerr << "could not write: " << outfilename << std::endl; return 1; } } else { gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { if( ignoreerrors ) { std::cerr << "WARNING: an error was found during the reading of your DICOM file." << std::endl; std::cerr << "gdcmconv will still try to continue and rewrite your DICOM file." << std::endl; std::cerr << "There is absolutely no guarantee that your output file will be valid." << std::endl; } else { std::cerr << "Failed to read: " << filename << std::endl; return 1; } } gdcm::MediaStorage ms; ms.SetFromFile( reader.GetFile() ); if( ms == gdcm::MediaStorage::MediaStorageDirectoryStorage ) { std::cerr << "Sorry DICOMDIR is not supported" << std::endl; return 1; } #if 0 // if preamble create: gdcm::File f(reader.GetFile()); gdcm::Preamble p; p.Create(); f.SetPreamble(p); gdcm::DataSet ds = reader.GetFile().GetDataSet(); SetSQToUndefined undef; ds.ExecuteOperation(undef); gdcm::File f(reader.GetFile()); f.SetDataSet(ds); #endif #if 0 gdcm::DataSet& ds = reader.GetFile().GetDataSet(); gdcm::DataElement de = ds.GetDataElement( gdcm::Tag(0x0010,0x0010) ); const char patname[] = "John^Doe"; de.SetByteValue(patname, strlen(patname)); std::cout << de << std::endl; ds.Replace( de ); std::cout << ds.GetDataElement( gdcm::Tag(0x0010,0x0010) ) << std::endl; #endif /* //(0020,0032) DS [-158.135803\-179.035797\-75.699997] # 34, 3 ImagePositionPatient //(0020,0037) DS [1.000000\0.000000\0.000000\0.000000\1.000000\0.000000] # 54, 6 ImageOrientationPatient gdcm::Attribute<0x0020,0x0032> at = { -158.135803, -179.035797, -75.699997 }; gdcm::DataElement ipp = at.GetAsDataElement(); ds.Remove( at.GetTag() ); ds.Remove( ipp.GetTag() ); ds.Replace( ipp ); */ gdcm::Writer writer; writer.SetFileName( outfilename.c_str() ); writer.SetCheckFileMetaInformation( (checkmeta > 0 ? true : false)); //writer.SetFile( f ); writer.SetFile( reader.GetFile() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; // remove file to avoid any temptation if( filename != outfilename ) { gdcm::System::RemoveFile( outfilename.c_str() ); } else { std::cerr << "gdcmconv just corrupted: " << filename << " for you (data lost)." << std::endl; } return 1; } } return 0; } GDCM-3.0.10/Applications/Cxx/gdcmdictdump.cxx000066400000000000000000000001451412732066400206720ustar00rootroot00000000000000/* * TODO: Is this really useful ? * Dump the dict from a DICOM file. Useful for the private dict */ GDCM-3.0.10/Applications/Cxx/gdcmdiff.cxx000066400000000000000000000203711412732066400177740ustar00rootroot00000000000000/*========================================================================= Program: gdcmdiff for GDCM (Grassroots DICOM) Copyright (c) 2011 Andy Buckle 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 "gdcmReader.h" #include "gdcmAttribute.h" #include "gdcmDataSet.h" #include "gdcmDicts.h" #include "gdcmDict.h" #include "gdcmGlobal.h" #include "gdcmCSAHeader.h" #include "gdcmPrivateTag.h" #include static void usage(); static void difference_of_datasets(const gdcm::DataSet& ds1, const gdcm::DataSet& ds2, int depthSQ); static void display_element(std::ostream& os, const gdcm::DataElement& de, const gdcm::DictEntry& dictentry, const char *note, int depthSQ); static void underline(int depthSQ); static void difference_of_sequences(const gdcm::DataElement& sqde1, const gdcm::DataElement& sqde2, const gdcm::DictEntry& dictentry, int depthSQ); // previous declaration of 'int truncate(const char*, __off_t)' static uint32_t Truncate=30; // trim dumped string values to this number of chars. zero means no trimming. static std::stringstream sq_disp; // store SQ output while recursing through: only displayed if a difference is found within SQ int main( int argc, const char* argv[] ) { // Check number of args if (3 > argc) { std::cerr << "Must supply the filenames of 2 DICOM files\n" << std::endl; usage(); return 1; } // Check last 2 args are readable DICOM files gdcm::Reader reader1, reader2; reader1.SetFileName( argv[argc-2] ); reader2.SetFileName( argv[argc-1] ); if( !reader1.Read() || !reader2.Read() ) { std::cerr << "At least one of the DICOM files could not be read: " << '\"' << argv[argc-2] << "\", \"" << argv[argc-1] << '\"' << std::endl; return 1; } // Parse other args bool include_meta = false; for(int i=1; i<(argc-2) ;i++) { std::string arg = std::string(argv[i]); if ("-h" == arg || "--help" == arg) { usage(); return 0; } else if ("-m" == arg || "--meta" == arg) { include_meta = true; } else if ("-t" == arg || "--truncate" == arg) { Truncate = atoi(argv[++i]); } else { std::cerr << "Warning: command argument not understood: " << arg << std::endl; usage(); return 1; } } // Start comparison const gdcm::File &file1 = reader1.GetFile(); const gdcm::File &file2 = reader2.GetFile(); const gdcm::FileMetaInformation &hds1 = file1.GetHeader(); const gdcm::FileMetaInformation &hds2 = file2.GetHeader(); const gdcm::DataSet &ds1 = file1.GetDataSet(); const gdcm::DataSet &ds2 = file2.GetDataSet(); if(include_meta) { difference_of_datasets(hds1, hds2, 0); } difference_of_datasets(ds1, ds2, 0); return 0; } static void usage() { std::cout << "Usage: gdcmdiff [OPTIONS] DICOM_FILE1 DICOM_FILE2\n\n" " -h --help (This) help and exit.\n" " -m --meta Compare metainformation. Default is off.\n" " -t --truncate String values trimmed to n characters.\n" " 0 means no trimmming. Default 30." << std::endl; } static void difference_of_datasets(const gdcm::DataSet& ds1, const gdcm::DataSet& ds2, int depthSQ) { gdcm::DataSet::ConstIterator it1 = ds1.Begin(); gdcm::DataSet::ConstIterator it2 = ds2.Begin(); do { // find lowest value tag, being careful not to pick one for an iterator that has finished const gdcm::Tag tag1 = (it1!=ds1.End()) ? it1->GetTag() : gdcm::Tag(0xffff,0xffff); const gdcm::Tag tag2 = (it2!=ds2.End()) ? it2->GetTag() : gdcm::Tag(0xffff,0xffff); gdcm::Tag tag= (tag1GetLength(); // error: operands to ?: have different types 'gdcm::VL' and 'uint32_t' uint32_t val_vl = vl; uint32_t trimto = (Truncate > val_vl ) ? val_vl : Truncate; if (0 == Truncate) { trimto = de.GetByteValue()->GetLength(); } os << " [" << std::string(de.GetByteValue()->GetPointer(),trimto) << ']'; } else { os << " null"; } } else { os << " VR unknown"; } os << " # " << dictentry.GetName() << std::endl ; } static void underline(int depthSQ) { std::cout << std::string(depthSQ, ' '); //indent for SQ std::cout << " -------------" << std::endl; } static void difference_of_sequences(const gdcm::DataElement& sqde1, const gdcm::DataElement& sqde2, const gdcm::DictEntry& dictentry, int depthSQ) { gdcm::SmartPointer sqi1 = sqde1.GetValueAsSQ(); gdcm::SmartPointer sqi2 = sqde2.GetValueAsSQ(); size_t n1 = sqi1 ? sqi1->GetNumberOfItems() : 0; size_t n2 = sqi2 ? sqi2->GetNumberOfItems() : 0; size_t n = (n1 < n2) ? n1 : n2 ; std::stringstream sq_note; if (n1 != n2) { sq_note << "[sequence, file 1 has " << n1 << " datasets, file 2 has " << n2 << " datasets]"; } else { sq_note << "[sequence]"; } display_element(sq_disp, sqde1, dictentry, sq_note.str().c_str(),depthSQ); for(size_t i=1; i <= n; i++) { difference_of_datasets( sqi1->GetItem(i).GetNestedDataSet(), sqi2->GetItem(i).GetNestedDataSet(), depthSQ+1); } sq_disp.str(std::string()); // clear stringstream } GDCM-3.0.10/Applications/Cxx/gdcmdump.cxx000066400000000000000000001450761412732066400200430ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Simple command line tool to dump the layout/values of a DICOM file * This is largely inspired by other tools available from other toolkit, namely: * - dcdump (dicom3tools) * - dcmdump (dcmtk) * - dcmInfo (SIEMENS) * - PrintFile (GDCM 1.x) * * For now all layout are hardcoded (see --color/--xml-dict for instance) * * gdcmdump has some feature not described in the DICOM standard: * --csa : to print CSA information (dcmInfo.exe compatible) * --pdb : to print PDB information (GEMS private info) * --elscint : to print ELSCINT information (ELSCINT private info) * * * TODO: it would be nice to have custom printing, namely printing as HTML/XML * it would be nice to have runtime dict (instead of compile time) */ #include "gdcmReader.h" #include "gdcmVersion.h" #include "gdcmFileMetaInformation.h" #include "gdcmDataSet.h" #include "gdcmPrivateTag.h" #include "gdcmPrinter.h" #include "gdcmDumper.h" #include "gdcmDictPrinter.h" #include "gdcmValidate.h" #include "gdcmWriter.h" #include "gdcmSystem.h" #include "gdcmDirectory.h" #include "gdcmCSAHeader.h" #include "gdcmPDBHeader.h" #include "gdcmSequenceOfItems.h" #include "gdcmASN1.h" #include "gdcmAttribute.h" #include "gdcmBase64.h" #include "gdcmTagKeywords.h" #include #include #include /* for printf */ #include /* for exit */ #include #include static int color = 0; static int ignoreerrors = 0; namespace cleanup { // {"1.3.46.670589.11.0.0.12.2" ,"Philips Private MR Series Data Storage"}, enum { TYPE_FLOAT = 0, // float TYPE_INT32 = 1, // int32 TYPE_STRING = 2, // 80 bytes string (+1) TYPE_UINT32 = 4 // uint32 }; template static void printvaluet(std::istream & is, uint32_t numels) { T buffer; for( uint32_t i = 0; i < numels; ++i ) { if( i ) std::cout << "\\"; is.read( (char*)&buffer, sizeof(T) ); std::cout << buffer; } } static void printvalue(std::istream &is, uint32_t type, uint32_t numels, uint32_t pos) { assert( numels > 0 ); std::streampos start = is.tellg(); is.seekg( pos ); std::cout << "["; typedef char (string81)[81]; // 80'th byte == 0 assert( sizeof( string81 ) == 81 ); switch( type ) { case TYPE_FLOAT: printvaluet(is, numels); break; case TYPE_INT32: printvaluet(is, numels); break; case TYPE_STRING: printvaluet(is, numels); break; case TYPE_UINT32: printvaluet(is, numels); break; default: assert( 0 ); } std::cout << "]"; std::cout << " # " << numels; is.seekg( start ); } struct PDFElement { const char *getname() const { return name; } uint32_t gettype() const { return getvalue(0); } uint32_t getnumelems() const { return getvalue(1); } uint32_t getdummy() const { return getvalue(2); } uint32_t getoffset() const { return getvalue(3); } private: char name[50]; // type , numel and offset needs to be read starting from the end // the data in between name and those value can contains garbage stuff uint32_t getvalue(int n) const { uint32_t val = 0; memcpy( (char*)&val, name + 50 - 16 + n * 4, sizeof( val ) ); return val; } }; static void printbinary(std::istream &is, PDFElement const & pdfel ) { const char *bufferref = pdfel.getname(); std::cout << " " << bufferref << " "; uint32_t type = pdfel.gettype(); uint32_t numels = pdfel.getnumelems(); //uint32_t dummy = pdfel.getdummy(); //assert( dummy == 0 ); (void)dummy; uint32_t offset = pdfel.getoffset(); uint32_t pos = (uint32_t)(offset + is.tellg() - 4); printvalue(is, type, numels, pos); } static void ProcessSDSDataInt( std::istream & is ) { (void)is; std::cerr << "TODO" << std::endl; } // see read_direct_string / read_direct_int static void ProcessSDSDataString( std::istream & is ) { (void)is; #if 0 int32_t v1; is.read( (char*)&v1,sizeof(v1)); assert( v1 == 0x1 ); uint32_t bla; is.read( (char*)&bla, sizeof(bla) ); char name0[32]; memset(name0,0,sizeof(name0)); assert( bla < sizeof(name0) ); is.read( name0, bla); size_t l = strlen(name0); assert( l == bla ); std::cerr << "name0:" << name0 << std::endl; is.read( (char*)&bla, sizeof(bla) ); assert( bla == 0x1 ); is.read( (char*)&bla, sizeof(bla) ); char value[32]; memset(value,0,sizeof(value)); assert( bla < sizeof(value) ); is.read( value, bla); is.read( (char*)&bla, sizeof(bla) ); assert( bla == 0 ); // trailing stuff ? is.read( (char*)&bla, sizeof(bla) ); assert( bla == 0 ); // trailing stuff ? const uint32_t cur = (uint32_t)is.tellg(); std::cerr << "offset:" << cur << std::endl; #else std::cerr << "TODO" << std::endl; #endif } static void ProcessSDSData( std::istream & is ) { // haven't been able to figure out what was the begin meant for is.seekg( 0x20 - 8 ); uint32_t version = 0; assert( sizeof(uint32_t) == 4 ); is.read( (char*)&version, sizeof(version) ); assert( version == 8 ); uint32_t numel = 0; is.read( (char*)&numel, sizeof(numel) ); for( uint32_t el = 0; el < numel; ++el ) { PDFElement pdfel; assert( sizeof(pdfel) == 50 ); is.read( (char*)&pdfel, 50 ); if( *pdfel.getname() ) { printbinary( is, pdfel ); std::cout << std::endl; } } } // PMS MR Series Data Storage static int DumpPMS_MRSDS(const gdcm::DataSet & ds) { const gdcm::PrivateTag tdata(0x2005,0x32,"Philips MR Imaging DD 002"); if( !ds.FindDataElement( tdata ) ) return 1; const gdcm::DataElement &data = ds.GetDataElement( tdata ); gdcm::SmartPointer sqi = data.GetValueAsSQ(); if( !sqi ) return 1; std::cout << "PMS Dumping info from tag " << tdata << std::endl; gdcm::SequenceOfItems::ConstIterator it = sqi->Begin(); for( ; it != sqi->End(); ++it ) { const gdcm::Item & item = *it; const gdcm::DataSet & nestedds = item.GetNestedDataSet(); const gdcm::PrivateTag tprotocoldataname(0x2005,0x37,"Philips MR Imaging DD 002"); const gdcm::DataElement & protocoldataname = nestedds.GetDataElement( tprotocoldataname ); const gdcm::ByteValue *bv1 = protocoldataname.GetByteValue(); const gdcm::PrivateTag tprotocoldatatype(0x2005,0x39,"Philips MR Imaging DD 002"); const gdcm::DataElement & protocoldatatype = nestedds.GetDataElement( tprotocoldatatype ); const gdcm::ByteValue *bv2 = protocoldatatype.GetByteValue(); const gdcm::PrivateTag tprotocoldatablock(0x2005,0x44,"Philips MR Imaging DD 002"); const gdcm::DataElement & protocoldatablock = nestedds.GetDataElement( tprotocoldatablock ); const gdcm::ByteValue *bv3 = protocoldatablock.GetByteValue(); const gdcm::PrivateTag tprotocoldatabool(0x2005,0x47,"Philips MR Imaging DD 002"); const gdcm::DataElement & protocoldatabool = nestedds.GetDataElement( tprotocoldatabool ); const gdcm::ByteValue *bv4 = protocoldatabool.GetByteValue(); std::string s1; if( bv1 ) { s1 = std::string( bv1->GetPointer(), bv1->GetLength() ); } std::string s2; if( bv2 ) { s2 = std::string( bv2->GetPointer(), bv2->GetLength() ); } std::string s3; if( bv3 ) { s3 = std::string( bv3->GetPointer(), bv3->GetLength() ); } std::string s4; if( bv4 ) { s4 = std::string( bv4->GetPointer(), bv4->GetLength() ); } std::cout << "PMS/Item name: [" << s1 << "/" << s2 << "/" << s4 << "]" << std::endl; if( bv3 ) { std::istringstream is( s3 ); char v1 = is.peek(); if( v1 == 0x1 ) { if( s1 == "HARDWARE_CONFIG " ) ProcessSDSDataInt( is ); else if( s1 == "COILSTATE " ) ProcessSDSDataString( is ); else assert(0); } else { ProcessSDSData( is ); } } else { std::cout << " EMPTY !" << std::endl; } } return 0; } static int DumpTOSHIBA_MEC_CT3(const gdcm::DataSet & ds) { const gdcm::PrivateTag tdata(0x7005,0x10,"TOSHIBA_MEC_CT3"); if( !ds.FindDataElement( tdata ) ) return 1; const gdcm::DataElement &data = ds.GetDataElement( tdata ); const gdcm::ByteValue *bv = data.GetByteValue(); if( !bv ) return 1; const unsigned int offset = 24; if( bv->GetLength() < offset ) { std::cerr << "Not enough header" << std::endl; return 1; } std::istringstream is0; const std::string str0 = std::string( bv->GetPointer(), offset ); is0.str( str0 ); gdcm::ImplicitDataElement ide0; ide0.Read(is0); gdcm::ImplicitDataElement ide1; ide1.Read(is0); gdcm::Attribute<0x0,0x0> at0; at0.SetFromDataElement( ide0 ); if( at0.GetValue() != 12 ) { std::cerr << "Bogus header value #0" << std::endl; return 1; } gdcm::Attribute<0x0,0x1> at1; at1.SetFromDataElement( ide1 ); const unsigned int dlen = bv->GetLength() - offset; if( at1.GetValue() != dlen ) { std::cerr << "Bogus header value #1" << std::endl; return 1; } std::istringstream is1; const std::string str1 = std::string( bv->GetPointer() + offset, bv->GetLength() - offset); is1.str( str1 ); gdcm::Reader r; r.SetStream( is1 ); if( !r.Read() ) { std::cerr << "Could not read CT Private Data 2" << std::endl; return 1; } gdcm::Printer printer; printer.SetFile ( r.GetFile() ); printer.SetColor( color != 0 ); printer.Print( std::cout ); return 0; } static bool DumpToshibaDTI( const char * input, size_t len ) { if( len % 2 ) return false; std::vector copy( input, input + len ); std::reverse( copy.begin(), copy.end() ); std::istringstream is; std::string dup( ©[0], copy.size() ); is.str( dup ); gdcm::File file; gdcm::FileMetaInformation & fmi = file.GetHeader(); fmi.SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); gdcm::DataSet & ds = file.GetDataSet(); ds.Read( is ); gdcm::Printer p; p.SetFile( file ); p.SetColor( color != 0 ); p.Print( std::cout ); return true; } static int DumpTOSHIBA_Reverse(const gdcm::DataSet & ds, const gdcm::PrivateTag &tpmtf, const gdcm::PrivateTag &tseq) { // (0029,0010) ?? (LO) [PMTF INFORMATION DATA ] # 22,1 Private Creator // (0029,1001) ?? (SQ) (Sequence with undefined length) # u/l,1 ? if( !ds.FindDataElement( tpmtf) ) return 1; const gdcm::DataElement& pmtf = ds.GetDataElement( tpmtf ); if ( pmtf.IsEmpty() ) return 1; gdcm::SmartPointer seq = pmtf.GetValueAsSQ(); if ( !seq || !seq->GetNumberOfItems() ) return 1; size_t n = seq->GetNumberOfItems(); for( size_t i = 1; i <= n; ++i ) { std::cout << "Item #" << i << std::endl; gdcm::Item &item = seq->GetItem(i); gdcm::DataSet &subds = item.GetNestedDataSet(); // (0029,0010) ?? (LO) [PMTF INFORMATION DATA ] # 22,1 Private Creator // (0029,1090) ?? (OB) 00\05\00\13\00\12\00\22\ # 202,1 ? if( subds.FindDataElement( tseq ) ) { const gdcm::DataElement & de = subds.GetDataElement( tseq ); const gdcm::ByteValue * bv = de.GetByteValue(); if( !bv ) return 1; bool b = DumpToshibaDTI( bv->GetPointer(), bv->GetLength() ); if( !b ) return 1; } } return 0; } // VEPRO /* [VIMDATA2] PrivateCreator = VEPRO VIM 5.0 DATA Group = 0x0055 Element = 0x0020 Data.ID = C|0|3 Data.Version = C|3|3 Data.UserName = C|6|32 Data.UserAdress1 = C|38|32 Data.UserAdress2 = C|70|32 Data.UserAdress3 = C|102|32 Data.UserAdress4 = C|134|32 Data.UserAdress5 = C|166|32 Data.RecDate = C|198|8 Data.RecTime = C|206|6 Data.RecPlace = C|212|64 Data.RecSource = C|276|64 Data.DF1 = C|340|64 Data.DF2 = C|404|64 Data.DF3 = C|468|64 Data.DF4 = C|532|64 Data.DF5 = C|596|64 Data.DF6 = C|660|64 Data.DF7 = C|724|64 Data.DF8 = C|788|64 Data.DF9 = C|852|64 Data.DF10 = C|916|64 Data.DF11 = C|980|64 Data.DF12 = C|1044|64 Data.DF13 = C|1108|64 Data.DF14 = C|1172|64 Data.DF15 = C|1236|64 Data.DF16 = C|1300|64 Data.DF17 = C|1364|64 Data.DF18 = C|1428|64 Data.DF19 = C|1492|64 Data.DF20 = C|1556|64 Data.StudyUID = C|1642|64 Data.SeriesUID = C|1706|64 Data.Modality = C|1770|16 */ // TYPE[C/I] / OFFSET / LENGTH (in bytes) struct Data2 { char ID[3]; // Data.ID = C|0|3 char Version[3]; // Data.Version = C|3|3 char UserName[32]; // Data.UserName = C|6|32 char UserAdress1[32]; // Data.UserAdress1 = C|38|32 char UserAdress2[32]; // Data.UserAdress2 = C|70|32 char UserAdress3[32]; // Data.UserAdress3 = C|102|32 char UserAdress4[32]; // Data.UserAdress4 = C|134|32 char UserAdress5[32]; // Data.UserAdress5 = C|166|32 char RecDate[8]; // Data.RecDate = C|198|8 char RecTime[6]; // Data.RecTime = C|206|6 char RecPlace[64]; // Data.RecPlace = C|212|64 char RecSource[64];// Data.RecSource = C|276|64 char DF1[64]; // Data.DF1 = C|340|64 char DF2[64]; // Data.DF2 = C|404|64 char DF3[64]; // Data.DF3 = C|468|64 char DF4[64]; // Data.DF4 = C|532|64 char DF5[64]; // Data.DF5 = C|596|64 char DF6[64]; // Data.DF6 = C|660|64 char DF7[64]; // Data.DF7 = C|724|64 char DF8[64]; // Data.DF8 = C|788|64 char DF9[64]; // Data.DF9 = C|852|64 char DF10[64]; // Data.DF10 = C|916|64 char DF11[64]; // Data.DF11 = C|980|64 char DF12[64]; // Data.DF12 = C|1044|64 char DF13[64]; // Data.DF13 = C|1108|64 char DF14[64]; // Data.DF14 = C|1172|64 char DF15[64]; // Data.DF15 = C|1236|64 char DF16[64]; // Data.DF16 = C|1300|64 char DF17[64]; // Data.DF17 = C|1364|64 char DF18[64]; // Data.DF18 = C|1428|64 char DF19[64]; // Data.DF19 = C|1492|64 char DF20[64]; // Data.DF20 = C|1556|64 char Padding[22]; // ????? char StudyUID[64]; // Data.StudyUID = C|1642|64 char SeriesUID[64]; // Data.SeriesUID = C|1706|64 char Modality[16]; // Data.Modality = C|1770|16 void Print( std::ostream &os ) { os << " ID: " << std::string(ID,3) << "\n"; os << " Version: " << std::string(Version,3) << "\n"; os << " UserName: " << std::string(UserName,32) << "\n"; os << " UserAdress1: " << std::string(UserAdress1,32) << "\n"; os << " UserAdress2: " << std::string(UserAdress2,32) << "\n"; os << " UserAdress3: " << std::string(UserAdress3,32) << "\n"; os << " UserAdress4: " << std::string(UserAdress4,32) << "\n"; os << " UserAdress5: " << std::string(UserAdress5,32) << "\n"; os << " RecDate: " << std::string(RecDate,8) << "\n"; os << " RecTime: " << std::string(RecTime,64) << "\n"; os << " RecPlace: " << std::string(RecPlace,64) << "\n"; os << " RecSource: " << std::string(RecSource,64) << "\n"; os << " DF1: " << std::string(DF1,64) << "\n"; os << " DF2: " << std::string(DF2,64) << "\n"; os << " DF3: " << std::string(DF3,64) << "\n"; os << " DF4: " << std::string(DF4,64) << "\n"; os << " DF5: " << std::string(DF5,64) << "\n"; os << " DF6: " << std::string(DF6,64) << "\n"; os << " DF7: " << std::string(DF7,64) << "\n"; os << " DF8: " << std::string(DF8,64) << "\n"; os << " DF9: " << std::string(DF9,64) << "\n"; os << " DF10: " << std::string(DF10,64) << "\n"; os << " DF11: " << std::string(DF11,64) << "\n"; os << " DF12: " << std::string(DF12,64) << "\n"; os << " DF13: " << std::string(DF13,64) << "\n"; os << " DF14: " << std::string(DF14,64) << "\n"; os << " DF15: " << std::string(DF15,64) << "\n"; os << " DF16: " << std::string(DF16,64) << "\n"; os << " DF17: " << std::string(DF17,64) << "\n"; os << " DF18: " << std::string(DF18,64) << "\n"; os << " DF19: " << std::string(DF19,64) << "\n"; os << " DF20: " << std::string(DF20,64) << "\n"; //os << " Padding: " << std::string(Padding,22) << "\n"; os << " StudyUID: " << std::string(StudyUID,64) << "\n"; os << " SeriesUID: " << std::string(SeriesUID,64) << "\n"; os << " Modality: " << std::string(Modality,16) << "\n"; } }; static bool ProcessData( const char *buf, size_t len ) { Data2 data2; const size_t s = sizeof(data2); assert( len >= s); (void)len; // VIMDATA2 is generally 2048 bytes, while s = 1786 // the end is filled with \0 bytes memcpy(&data2, buf, s); data2.Print( std::cout ); return true; } static int DumpVEPRO(const gdcm::DataSet & ds) { // 01f7,1026 const gdcm::ByteValue *bv2 = nullptr; const gdcm::PrivateTag tdata1(0x55,0x0020,"VEPRO VIF 3.0 DATA"); const gdcm::PrivateTag tdata2(0x55,0x0020,"VEPRO VIM 5.0 DATA"); // Prefer VIF over VIM ? if( ds.FindDataElement( tdata1 ) ) { std::cout << "VIF DATA: " << tdata1 << "\n"; const gdcm::DataElement &data = ds.GetDataElement( tdata1 ); bv2 = data.GetByteValue(); } else if( ds.FindDataElement( tdata2 ) ) { std::cout << "VIMDATA2: " << tdata2 << "\n"; const gdcm::DataElement &data = ds.GetDataElement( tdata2 ); bv2 = data.GetByteValue(); } if( bv2 ) { ProcessData( bv2->GetPointer(), bv2->GetLength() ); return 0; } return 1; } // ELSCINT1 static bool readastring(std::string &out, const char *input ) { out.clear(); while( *input ) { out.push_back( *input++ ); } return true; } struct el { std::string name; uint32_t pad; std::vector values; size_t Size() const { size_t s = 0; s += name.size() + 1; s += sizeof(pad); for( std::vector::const_iterator it = values.begin(); it != values.end(); ++it ) s += it->size() + 1; return s; } void ReadFromString( const char * input ) { readastring( name, input ); const char *p = input + 1+ name.size(); memcpy( &pad, p, sizeof( pad ) ); //assert( pad == 1 || pad == 2 || pad == 3 || pad == 6 ); values.resize( pad ); const char *pp = p + sizeof(uint32_t); for( uint32_t pidx = 0; pidx < pad; ++pidx ) { readastring( values[pidx], pp ); pp = pp + values[pidx].size() + 1; } } void Print() const { //std::cout << " " << name << " : " << pad << " : ("; std::cout << " " << name << " ["; { std::vector::const_iterator it = values.begin(); std::cout << *it++; for(; it != values.end(); ++it ) { std::cout << "\\"; std::cout << *it; } } std::cout << "]" << std::endl; } }; struct info { size_t Read(const char *in ) { const char *m = in; uint32_t h; memcpy( &h, in, sizeof(h) ); in += sizeof(h); std::string dummy; readastring( dummy, in ); in += dummy.size(); in += 1; if( h == 432154 ) // 0x6981a { // Single item uint32_t nels; memcpy( &nels, in, sizeof(nels) ); in += sizeof(nels); //std::cout << " ELSCINT1/Item name: " << dummy << " : " << nels << std::endl; std::cout << "ELSCINT1/Item name: [" << dummy << "]" << std::endl; for( uint32_t i = 0; i < nels; ++i ) { el e; e.ReadFromString( in ); e.Print(); in += e.Size(); } } else if( h == 2341 ) // 0x925 { // Multiple Item(s) uint32_t d; memcpy( &d, in, sizeof(d) ); in += sizeof(d); //std::cout << " Info Name: " << dummy << " : " << d << std::endl; std::cout << "ELSCINT1/Item name: " << dummy << std::endl; for( uint32_t dix = 0; dix < d; ++dix ) { uint32_t fixme; memcpy( &fixme, in, sizeof(fixme) ); in += 4; // //std::cout << " number of Subitems " << fixme << std::endl; uint32_t nels = fixme; if( nels ) std::cout << " SubItems #" << dix << std::endl; else std::cout << " No SubItems (Empty)" << std::endl; for( uint32_t i = 0; i < nels; ++i ) { el e; e.ReadFromString( in ); e.Print(); in += e.Size(); } } // postcondition uint32_t fixme; memcpy( &fixme, in, sizeof(fixme) ); assert( fixme == 0x0006981A ); } else { assert( 0 ); } return in - m; } }; static int DumpEl2_new(const gdcm::DataSet & ds) { // 01f7,1026 const gdcm::PrivateTag t01f7_26(0x01f7,0x1026,"ELSCINT1"); if( !ds.FindDataElement( t01f7_26 ) ) return 1; const gdcm::DataElement& de01f7_26 = ds.GetDataElement( t01f7_26 ); if ( de01f7_26.IsEmpty() ) return 1; const gdcm::ByteValue * bv = de01f7_26.GetByteValue(); const char *begin = bv->GetPointer(); uint32_t val0[3]; memcpy( &val0, begin, sizeof( val0 ) ); assert( val0[0] == 0xF22D ); begin += sizeof( val0 ); // 1A 98 06 00 -> start element // Next is a string (can be NULL) // then number of (nested) elements std::cout << "ELSCINT1 Dumping info from tag " << t01f7_26 << std::endl; info i; size_t o; assert( val0[1] == 0x1 ); for( uint32_t idx = 0; idx < val0[2]; ++idx ) { o = i.Read( begin ); std::cout << std::endl; begin += o; } return 0; } } // end namespace cleanup template static int DoOperation(const std::string & filename) { gdcm::Reader reader; reader.SetFileName( filename.c_str() ); bool success = reader.Read(); if( !success && !ignoreerrors ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } TPrinter printer; printer.SetFile ( reader.GetFile() ); printer.SetColor( color != 0); printer.Print( std::cout ); // Only return success when file read succeeded not depending whether or not we printed it return success ? 0 : 1; } static int PrintASN1(const std::string & filename, bool verbose) { (void)verbose; gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); gdcm::Tag tencryptedattributessequence(0x0400,0x0500); if( !ds.FindDataElement( tencryptedattributessequence ) ) { return 1; } const gdcm::DataElement &encryptedattributessequence = ds.GetDataElement( tencryptedattributessequence ); //const gdcm::SequenceOfItems * sqi = encryptedattributessequence.GetSequenceOfItems(); gdcm::SmartPointer sqi = encryptedattributessequence.GetValueAsSQ(); if( !sqi->GetNumberOfItems() ) { return 1; } const gdcm::Item &item1 = sqi->GetItem(1); const gdcm::DataSet &subds = item1.GetNestedDataSet(); gdcm::Tag tencryptedcontent(0x0400,0x0520); if( !subds.FindDataElement( tencryptedcontent) ) { return 1; } const gdcm::DataElement &encryptedcontent = subds.GetDataElement( tencryptedcontent ); const gdcm::ByteValue *bv = encryptedcontent.GetByteValue(); bool b = gdcm::ASN1::ParseDump( bv->GetPointer(), bv->GetLength() ); if( !b ) return 1; return 0; } static int PrintELSCINT(const std::string & filename, bool verbose) { (void)verbose; gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); int ret = cleanup::DumpEl2_new( ds ); return ret; } static int PrintVEPRO(const std::string & filename, bool verbose) { (void)verbose; gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); int ret = cleanup::DumpVEPRO( ds ); return ret; } static int PrintSDS(const std::string & filename, bool verbose) { (void)verbose; gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); int ret = cleanup::DumpPMS_MRSDS( ds ); return ret; } static int PrintCT3(const std::string & filename, bool verbose) { (void)verbose; gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); int ret = cleanup::DumpTOSHIBA_MEC_CT3( ds ); return ret; } static int PrintPMTF(const std::string & filename, bool verbose) { (void)verbose; gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); const gdcm::PrivateTag tpmtf(0x0029,0x1,"PMTF INFORMATION DATA"); const gdcm::PrivateTag tseq(0x0029,0x90,"PMTF INFORMATION DATA"); int ret = cleanup::DumpTOSHIBA_Reverse( ds, tpmtf, tseq ); return ret; } static int PrintMECMR3(const std::string & filename, bool verbose) { (void)verbose; gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); const gdcm::PrivateTag tpmtf(0x0029,0x1,"TOSHIBA_MEC_MR3"); const gdcm::PrivateTag tseq(0x0029,0x90,"TOSHIBA_MEC_MR3"); int ret = cleanup::DumpTOSHIBA_Reverse( ds, tpmtf, tseq ); const gdcm::PrivateTag tpmtf2(0x0029,0x2,"TOSHIBA_MEC_MR3"); int ret2 = cleanup::DumpTOSHIBA_Reverse( ds, tpmtf2, tseq ); return ret +ret2; } static int PrintPDB(const std::string & filename, bool verbose) { (void)verbose; gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } gdcm::PDBHeader pdb; const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); const gdcm::PrivateTag &t1 = pdb.GetPDBInfoTag(); bool found = false; int ret = 0; if( ds.FindDataElement( t1 ) ) { pdb.LoadFromDataElement( ds.GetDataElement( t1 ) ); pdb.Print( std::cout ); found = true; } if( !found ) { std::cerr << "no pdb tag found" << std::endl; ret = 1; } return ret; } static int PrintCSABase64(const std::string & filename, const char * name) { gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); gdcm::CSAHeader csa; const gdcm::PrivateTag &t1 = csa.GetCSAImageHeaderInfoTag(); if( !ds.FindDataElement( t1 ) ) return 1; csa.LoadFromDataElement( ds.GetDataElement( t1 ) ); if( csa.FindCSAElementByName(name) ) { const gdcm::CSAElement & el = csa.GetCSAElementByName(name); if( el.IsEmpty() ) return 1; const gdcm::ByteValue* bv = el.GetByteValue(); std::string str( bv->GetPointer(), bv->GetLength() ); str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); size_t dl = gdcm::Base64::GetDecodeLength( str.c_str(), str.size() ); std::vector buf; buf.resize( dl ); size_t dl2 = gdcm::Base64::Decode( &buf[0], buf.size(), str.c_str(), str.size() ); if( dl != dl2 ) return 1; std::stringstream ss; ss.str( std::string(&buf[0], buf.size()) ); gdcm::File file; gdcm::DataSet &ds2 = file.GetDataSet(); gdcm::DataElement xde; try { while( xde.Read( ss ) ) { ds2.Insert( xde ); } assert( ss.eof() ); } catch(std::exception &) { return 1; } gdcm::Printer p; p.SetFile( file ); p.Print(std::cout); } return 0; } static int PrintCSA(const std::string & filename) { gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } gdcm::CSAHeader csa; const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); const gdcm::PrivateTag &t1 = csa.GetCSAImageHeaderInfoTag(); const gdcm::PrivateTag &t2 = csa.GetCSASeriesHeaderInfoTag(); const gdcm::PrivateTag &t3 = csa.GetCSADataInfo(); bool found = false; int ret = 0; if( ds.FindDataElement( t1 ) ) { csa.LoadFromDataElement( ds.GetDataElement( t1 ) ); csa.Print( std::cout ); found = true; if( csa.GetFormat() == gdcm::CSAHeader::ZEROED_OUT ) { std::cerr << "CSA Header has been zero-out (contains only 0)" << std::endl; ret = 1; } else if( csa.GetFormat() == gdcm::CSAHeader::DATASET_FORMAT ) { gdcm::Printer p; gdcm::File f; f.SetDataSet( csa.GetDataSet() ); p.SetFile( f ); p.Print( std::cout ); } } if( ds.FindDataElement( t2 ) ) { csa.LoadFromDataElement( ds.GetDataElement( t2 ) ); csa.Print( std::cout ); found = true; if( csa.GetFormat() == gdcm::CSAHeader::ZEROED_OUT ) { std::cerr << "CSA Header has been zero-out (contains only 0)" << std::endl; ret = 1; } else if( csa.GetFormat() == gdcm::CSAHeader::DATASET_FORMAT ) { gdcm::Printer p; gdcm::File f; f.SetDataSet( csa.GetDataSet() ); p.SetFile( f ); p.Print( std::cout ); } } if( ds.FindDataElement( t3 ) ) { csa.LoadFromDataElement( ds.GetDataElement( t3 ) ); csa.Print( std::cout ); found = true; if( csa.GetFormat() == gdcm::CSAHeader::ZEROED_OUT ) { std::cerr << "CSA Header has been zero-out (contains only 0)" << std::endl; ret = 1; } else if( csa.GetFormat() == gdcm::CSAHeader::INTERFILE ) { const char *interfile = csa.GetInterfile(); if( interfile ) std::cout << interfile << std::endl; } else if( csa.GetFormat() == gdcm::CSAHeader::DATASET_FORMAT ) { gdcm::Printer p; gdcm::File f; f.SetDataSet( csa.GetDataSet() ); p.SetFile( f ); p.Print( std::cout ); } } if( !found ) { std::cerr << "no csa tag found" << std::endl; ret = 1; } return ret; } static int PrintMrProtocol(const std::string & filename) { gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } gdcm::CSAHeader csa; const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); gdcm::MrProtocol mrprot; const gdcm::PrivateTag att1(0x21,0x19,"SIEMENS MR SDS 01"); const gdcm::PrivateTag att2(0x21,0xfe,"SIEMENS MR SDS 01"); bool found = false; namespace kwd = gdcm::Keywords; kwd::SharedFunctionalGroupsSequence sfgs; (void)sfgs; if( csa.GetMrProtocol(ds, mrprot)) { found = true; } else if( ds.FindDataElement( att1) ) { const gdcm::DataElement &data = ds.GetDataElement( att1 ); const gdcm::ByteValue *bv = data.GetByteValue(); static const char csastr[] = "PhoenixMetaProtocol"; // FIXME if( mrprot.Load( bv, csastr, -1)) found = true; } // SIEMENS now supports Enhanced MR else if( ds.FindDataElement( sfgs.GetTag() ) ) { const gdcm::DataElement &shared = ds.GetDataElement( sfgs.GetTag() ); gdcm::SmartPointer sqi = shared.GetValueAsSQ(); if( sqi != nullptr && sqi->GetNumberOfItems() == 1 ) { gdcm::Item &item = sqi->GetItem(1); gdcm::DataSet & subds = item.GetNestedDataSet(); if( subds.FindDataElement( att2) ) { const gdcm::DataElement &privsq = subds.GetDataElement( att2 ); gdcm::SmartPointer sqi2 = privsq.GetValueAsSQ(); if( sqi2 != nullptr && sqi2->GetNumberOfItems() == 1 ) { gdcm::Item &item2 = sqi2->GetItem(1); gdcm::DataSet & subds2 = item2.GetNestedDataSet(); if( subds2.FindDataElement( att1) ) { const gdcm::DataElement &data = subds2.GetDataElement( att1 ); const gdcm::ByteValue *bv = data.GetByteValue(); static const char csastr[] = "PhoenixMetaProtocol"; // FIXME if( mrprot.Load( bv, csastr, -1)) found = true; } } } } } if( found ) std::cout << mrprot; else std::cerr << "Could not find MrProtocol/MrPhoenixProtocol ASCII section" << std::endl; return found ? 0 : 1; } static void PrintVersion() { std::cout << "gdcmdump: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; } static void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcmdump [OPTION]... FILE..." << std::endl; std::cout << "dumps a DICOM file, it will display the structure and values contained in the specified DICOM file\n"; std::cout << "Parameter (required):" << std::endl; std::cout << " -i --input DICOM filename or directory" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -x --xml-dict generate the XML dict (only private elements for now)." << std::endl; std::cout << " -r --recursive recursive." << std::endl; std::cout << " -d --dump dump value (limited use)." << std::endl; std::cout << " -p --print print value instead of simply dumping (default)." << std::endl; std::cout << " -c --color print in color." << std::endl; std::cout << " -C --csa print SIEMENS CSA Header (0029,[12]0,SIEMENS CSA HEADER)." << std::endl; std::cout << " --csa-asl print decoded SIEMENS CSA MR_ASL (base64)." << std::endl; std::cout << " --csa-diffusion print decoded SIEMENS CSA MRDiffusion (base64)." << std::endl; std::cout << " --mrprotocol print SIEMENS CSA MrProtocol only (within ASCCONV BEGIN/END)." << std::endl; std::cout << " -P --pdb print GEMS Protocol Data Block (0025,1b,GEMS_SERS_01)." << std::endl; std::cout << " --elscint print ELSCINT Protocol Information (01f7,26,ELSCINT1)." << std::endl; std::cout << " --vepro print VEPRO Protocol Information (0055,20,VEPRO VIF 3.0 DATA)." << std::endl; std::cout << " or VEPRO Protocol Information (0055,20,VEPRO VIM 5.0 DATA)." << std::endl; std::cout << " --sds print Philips MR Series Data Storage (1.3.46.670589.11.0.0.12.2) Information (2005,32,Philips MR Imaging DD 002)." << std::endl; std::cout << " --ct3 print CT Private Data 2 (7005,10,TOSHIBA_MEC_CT3)." << std::endl; std::cout << " --pmtf print PMTF INFORMATION DATA sub-sequences (0029,01,PMTF INFORMATION DATA)." << std::endl; std::cout << " --mecmr3 print TOSHIBA_MEC_MR3 sub-sequences (0029,01,TOSHIBA_MEC_MR3)." << std::endl; std::cout << " -A --asn1 print encapsulated ASN1 structure >(0400,0520)." << std::endl; std::cout << " --map-uid-names map UID to names." << std::endl; std::cout << "General Options:" << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " -v --version print version." << std::endl; std::cout << "Special Options:" << std::endl; std::cout << " -I --ignore-errors print even if file is corrupted." << std::endl; } int main (int argc, char *argv[]) { int c; //int digit_optind = 0; std::string filename; int printdict = 0; int dump = 0; int print = 0; int printcsa = 0; int printmrprotocol = 0; int printcsabase64 = 0; int printcsaasl = 0; int printcsadiffusion = 0; int printpdb = 0; int printelscint = 0; int printvepro = 0; int printsds = 0; // MR Series Data Storage int printct3 = 0; // TOSHIBA_MEC_CT3 int printpmtf = 0; // TOSHIBA / PMTF INFORMATION DATA int printmecmr3 = 0; // TOSHIBA / TOSHIBA_MEC_MR3 int verbose = 0; int warning = 0; int debug = 0; int error = 0; int help = 0; int version = 0; int recursive = 0; int printasn1 = 0; int mapuidnames = 0; while (true) { //int this_option_optind = optind ? optind : 1; int option_index = 0; /* struct option { const char *name; int has_arg; int *flag; int val; }; */ static struct option long_options[] = { {"input", 1, nullptr, 0}, {"xml-dict", 0, &printdict, 1}, {"recursive", 0, &recursive, 1}, {"print", 0, &print, 1}, {"dump", 0, &dump, 1}, {"color", 0, &color, 1}, {"csa", 0, &printcsa, 1}, {"pdb", 0, &printpdb, 1}, {"verbose", 0, &verbose, 1}, {"warning", 0, &warning, 1}, {"debug", 0, &debug, 1}, {"error", 0, &error, 1}, {"help", 0, &help, 1}, {"version", 0, &version, 1}, {"ignore-errors", 0, &ignoreerrors, 1}, {"asn1", 0, &printasn1, 1}, {"map-uid-names", 0, &mapuidnames, 1}, {"elscint", 0, &printelscint, 1}, {"vepro", 0, &printvepro, 1}, {"sds", 0, &printsds, 1}, {"ct3", 0, &printct3, 1}, {"csa-asl", 0, &printcsaasl, 1}, {"csa-diffusion", 0, &printcsadiffusion, 1}, {"mrprotocol", 0, &printmrprotocol, 1}, {"pmtf", 0, &printpmtf, 1}, {"mecmr3", 0, &printmecmr3, 1}, {nullptr, 0, nullptr, 0} // required }; static const char short_options[] = "i:xrpdcCPAVWDEhvI"; c = getopt_long (argc, argv, short_options, long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: case '-': { const char *s = long_options[option_index].name; (void)s; //printf ("option %s", s); if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); assert( filename.empty() ); filename = optarg; } //printf (" with arg %s", optarg); } //printf ("\n"); } break; case 'i': //printf ("option i with value '%s'\n", optarg); assert( filename.empty() ); filename = optarg; break; case 'x': //printf ("option d with value '%s'\n", optarg); printdict = 1; break; case 'r': recursive = 1; break; case 'p': //printf ("option p with value '%s'\n", optarg); print = 1; break; case 'd': dump = 1; break; case 'c': color = 1; break; case 'C': printcsa = 1; break; case 'A': printasn1 = 1; break; case 'P': printpdb = 1; break; case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case 'I': ignoreerrors = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { //printf ("non-option ARGV-elements: %d", optind ); //while (optind < argc) // { // printf ("%s\n", argv[optind++]); // } //printf ("\n"); // Ok there is only one arg, easy, it's the filename: int v = argc - optind; if( v == 1 ) { filename = argv[optind]; } } // //gdcm::System::SetArgv0( argv[0] ); if( version ) { //std::cout << "version" << std::endl; PrintVersion(); return 0; } if( help ) { //std::cout << "help" << std::endl; PrintHelp(); return 0; } // check if d or p are passed, only one at a time if( print || printdict ) { if ( print && printdict ) { std::cerr << "d or p" << std::endl; return 1; } } if( filename.empty() ) { //std::cerr << "Need input file (-i)\n"; PrintHelp(); return 1; } // Debug is a little too verbose gdcm::Trace::SetDebug( debug != 0); gdcm::Trace::SetWarning( warning != 0); gdcm::Trace::SetError( error != 0); // when verbose is true, make sure warning+error are turned on: if( verbose ) { gdcm::Trace::SetWarning( verbose != 0); gdcm::Trace::SetError( verbose!= 0); } if( mapuidnames ) { std::cerr << "Not handled for now" << std::endl; } const char * csaname = nullptr; if( printcsaasl ) { printcsabase64 = 1; csaname = "MR_ASL"; } else if( printcsadiffusion ) { printcsabase64 = 1; csaname = "MRDiffusion"; } // else int res = 0; if( !gdcm::System::FileExists(filename.c_str()) ) { std::cerr << "no such file: " << filename << std::endl; return 1; } else if( gdcm::System::FileIsDirectory( filename.c_str() ) ) { gdcm::Directory d; d.Load(filename, recursive!= 0); gdcm::Directory::FilenamesType const &filenames = d.GetFilenames(); for( gdcm::Directory::FilenamesType::const_iterator it = filenames.begin(); it != filenames.end(); ++it ) { if( printdict ) { res += DoOperation(*it); } else if( printasn1 ) { res += PrintASN1(*it, verbose!= 0); } else if( printvepro ) { res += PrintVEPRO(*it, verbose!= 0); } else if( printsds ) { res += PrintSDS(*it, verbose!= 0); } else if( printct3 ) { res += PrintCT3(*it, verbose!= 0); } else if( printpmtf ) { res += PrintPMTF(*it, verbose!= 0); } else if( printmecmr3 ) { res += PrintMECMR3(*it, verbose!= 0); } else if( printelscint ) { res += PrintELSCINT(*it, verbose!= 0); } else if( printpdb ) { res += PrintPDB(*it, verbose!= 0); } else if( printcsa ) { res += PrintCSA(*it); } else if( printmrprotocol ) { res += PrintMrProtocol(*it); } else if( printcsabase64 ) { res += PrintCSABase64(*it, csaname); } else if( dump ) { res += DoOperation(*it); } else { res += DoOperation(*it); } if( verbose ) std::cerr << *it << std::endl; } if( verbose ) std::cerr << "Total: " << filenames.size() << " files were processed" << std::endl; } else { assert( gdcm::System::FileExists(filename.c_str()) ); if( printdict ) { res += DoOperation(filename); } else if( printasn1 ) { res += PrintASN1(filename, verbose!= 0); } else if( printvepro ) { res += PrintVEPRO(filename, verbose!= 0); } else if( printsds ) { res += PrintSDS(filename, verbose!= 0); } else if( printct3 ) { res += PrintCT3(filename, verbose!= 0); } else if( printpmtf ) { res += PrintPMTF(filename, verbose!= 0); } else if( printmecmr3 ) { res += PrintMECMR3(filename, verbose!= 0); } else if( printelscint ) { res += PrintELSCINT(filename, verbose!= 0); } else if( printpdb ) { res += PrintPDB(filename, verbose!= 0); } else if( printcsa ) { res += PrintCSA(filename); } else if( printmrprotocol ) { res += PrintMrProtocol(filename); } else if( printcsabase64 ) { res += PrintCSABase64(filename, csaname); } else if( dump ) { res += DoOperation(filename); } else { res += DoOperation(filename); } // ... if ( verbose ) std::cerr << "Filename: " << filename << std::endl; } return res; } /* * Harvested data: * A lot of them are still non-obvious Most obvious ones: ETL -> Echo Train Length FLIPANG -> Flip Angle MATRIXX / MATRIXY -> Acquisition Matrix SLTHICK -> Slice Thickness ENTRY "Feet First" + POSITION "Supine" -------------------- = Patient Position Full list: ANREF "IC" ANREF "NA" ANREF "SN" AUTOCF "Water" AUTOSCIC "0" AUTOSCIC "2" AUTOSHIM "Auto" AUTOSHIM "Off" AUTOSHIM "Yes" AUTOSUBOPTIONS "0" AUTOTRGTYPE "0" AUTOTRIGWIN "0" AUTOVOICE "0" B4PAUSE "0" BPMMODE "0" BWRT "0" BWRT "-1" CLOC1 "0.0" CLOC1 "L4.7" CLOC1 "L5.9" CLOC2 "0.0" CLOC2 "P20.0" CLOC2 "P42.2" CLOC2 "P44.5" CLOC3 "0.0" CLOC3 "S7.0" CLOC3 "S8.2" COIL "5GP" COIL "8HRBRAIN" COIL "HEAD" COIL "LOOP2CM" CONTAG "GAD" CONTAM "10 GAD" CONTAM "No " CONTAM "Yes " CONTRAST "No" CONTRAST "Yes" DELACQ "Minimum" DUMACQ "0" ELOC1 "L12.4" ELOC1 "L142.9" ELOC1 "L1.6" ELOC1 "L2.2" ELOC1 "L4.9" ELOC1 "L5.9" ELOC1 "L80.1" ELOC1 "L84.1" ELOC1 "L99.3" ELOC1 "S65.4" ELOC1 "S66.5" ELOC1 "S89.0" ELOC2 "0.0" ELOC2 "A18.3" ELOC2 "A43.5" ELOC2 "A79.2" ELOC2 "A87.6" ELOC2 "L6.9" ELOC2 "P27.4" ELOC2 "P38.8" ELOC2 "P48.8" ELOC2 "P49.4" ELOC3 "A12.8" ELOC3 "I111.9" ELOC3 "I27.7" ELOC3 "I7.1" ELOC3 "P21.2" ELOC3 "P31.1" ELOC3 "S12.3" ELOC3 "S1.7" ELOC3 "S31.8" ELOC3 "S5.4" ELOC3 "S7.0" ELOC3 "S9.8" ENTRY "Head First" ETL "17" ETL "2" ETL "24" ETL "3" ETL "6" ETL "8" ETL "9" FILTCHOICE "None" FLDIR "Slice" FLIPANG "12" FLIPANG "17" FLIPANG "20" FLIPANG "36" FLIPANG "8" FLIPANG "90" FOV "12" FOV "14" FOV "24" FOV "24.0" FOV "3" FOV "30" FOV "4" FOV "6" FOV "8" FOVCNT1 "0.0" FOVCNT2 "0.0" FOVCNT2 "P21.2" FOVCNT2 "P31.1" GRADMODE "WHOLE" GRADMODE "ZOOM" GRIP_NUMPSCVOL "0" GRIP_NUMSLGROUPS "0" GRIP_NUMSLGROUPS "1" GRIP_PSCVOL1 "0" GRIP_PSCVOL2 "0" GRIP_PSCVOLFOV "0" GRIP_PSCVOLFOV "0.000000" GRIP_PSCVOLTHICK "0" GRIP_PSCVOLTHICK "0.000000" GRIP_SATGROUP1 "0" GRIP_SATGROUP2 "0" GRIP_SATGROUP3 "0" GRIP_SATGROUP4 "0" GRIP_SATGROUP5 "0" GRIP_SATGROUP6 "0" GRIP_SLGROUP1 "0.000000 -21.170785 -13.463666 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 1 0.000000 1 0" GRIP_SLGROUP1 "0.000000 -31.122005 2.926577 0.000000 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 0.000000 0.000000 26 0.000000 1 0" GRIP_SLGROUP1 "-13.163267 0.000000 25.592358 0.005670 0.000000 -0.999984 0.999984 0.000000 0.005670 0.000000 -1.000000 0.000000 56 0.000000 1 0 1" GRIP_SLGROUP1 "3.135807 14.667716 -32.340976 -0.997518 0.043626 0.055276 -0.056814 -0.962372 -0.265728 0.041603 -0.268209 0.962462 1 0.000000 1 0 1" GRIP_SPECTRO "0" GRIP_TRACKER "0" GRXOPT "0" GRXOPT "2" IEC_ACCEPT "ON" IMODE "2D" IMODE "3D" INITSTATE "0" IOPT "EDR, Fast, IrP" IOPT "EPI, FMRI" IOPT "Fast, IrP" IOPT "Fast, ZIP512, FR" IOPT "FC, EDR, TRF, Fast, ZIP512" IOPT "FC, VBw, EDR" IOPT "None" IOPT "NPW, Seq, VBw, TRF, Fast" IOPT "NPW, TRF, Fast, ZIP512, FR" IOPT "NPW, VBw, EDR, Fast, ZIP2" IOPT "NPW, VBw, Fast" IOPT "NPW, ZIP512" IOPT "TRF, Fast" IOPT "VBw, EDR, Fast" IOPT "VBw, Fast" MASKPAUSE "0" MASKPHASE "0" MATRIXX "192" MATRIXX "256" MATRIXX "288" MATRIXX "320" MATRIXX "416" MATRIXX "512" MATRIXX "64" MATRIXY "128" MATRIXY "160" MATRIXY "192" MATRIXY "224" MATRIXY "256" MATRIXY "320" MATRIXY "64" MONSAR "y" NECHO "1" NEX "1.00" NEX "1.50" NEX "2.00" NEX "3.00" NEX "4.00" NOSLC "1" NOSLC "12" NOSLC "15" NOSLC "19" NOSLC "20" NOSLC "21" NOSLC "24" NOSLC "26" NOSLC "56" NOTES ".pn/_2" NOTES ".pn/_3" NOTES ".pn/_4" NUMACCELFACTOR "1.00" NUMACCELFACTOR "Recommended" NUMACQS "0" NUMACQS "2" NUMSHOTS "1" OVLPLOC "0" PAUSEDELMASKACQ "1" PDGMSTR "None" PHASEASSET "1.00" PHASECORR "No" PHASECORR "Yes" PHASEFOV "0.75" PHASEFOV "1.00" PLANE "3-PLANE" PLANE "AXIAL" PLANE "OBLIQUE" PLUG "0" PLUG "11" PLUG "14" PLUG "22" PLUG "23" PLUG "45" PLUG "5" PLUG "6" PLUG "9" POSITION "Prone" POSITION "Supine" PRESETDELAY "0.0" PSDNAME "fse-xl" PSDTRIG "0" PSEQ "FRFSE-XL" PSEQ "FSE-XL" PSEQ "Gradient Echo" PSEQ "IR" PSEQ "Localizer" PSEQ "SPGR" PSEQ "Spin Echo" RBW "12.50" RBW "14.71" RBW "15.63" RBW "17.86" RBW "20.83" RBW "22.73" RBW "25.00" RBW "31.25" SATLOCZ1 "9990" SATLOCZ2 "9990" SATTHICKZ1 "40.0" SATTHICKZ2 "40.0" SEDESC "3D FSPGR IR" SEDESC "3DIR PREP" SEDESC "3 plane loc" SEDESC "AX FSE T1" SEDESC "AX FSE T2" SEDESC "AX T2*" SEDESC "FATSAT T2 FSE Scout" SEDESCFLAG "1" SEDESC "LOCALIZER-RATCOIL" SEDESC "O-Ax FATSAT T2 FSE high Res" SEDESC "Oblique PD AX" SEDESC "Oblique STIR" SEDESC "Oblique T1 AX +C" SEDESC "Oblique T1-SAG" SEDESC "Oblique T1-SAG+C" SEDESC "Oblique T2 AX." SEDESC "O-Cor T1 " SEDESC "RUN 1" SEDESC "SPGR3D-HRES-Brasch" SEDESC "SPGR3D-LRES-Brasch" SEPSERIES "0" SL3PLANE "0" SL3PLANE "1" SL3PLANE1 "0" SL3PLANE1 "5" SL3PLANE2 "0" SL3PLANE2 "5" SL3PLANE3 "0" SL3PLANE3 "5" SLABLOC "128" SLABLOC "144" SLABLOC "64" SLABLOC "80" SLICEASSET "1.00" SLICEORDER "1" SLOC1 "I35.2" SLOC1 "I59.6" SLOC1 "I93.4" SLOC1 "L13.9" SLOC1 "L1.6" SLOC1 "L2.1" SLOC1 "L5.0" SLOC1 "L5.9" SLOC1 "L84.1" SLOC1 "L85.9" SLOC1 "L99.2" SLOC1 "R86.3" SLOC2 "0.0" SLOC2 "A11.0" SLOC2 "A115.0" SLOC2 "A79.2" SLOC2 "A80.8" SLOC2 "P34.4" SLOC2 "P37.0" SLOC2 "P46.5" SLOC2 "P50.2" SLOC3 "I27.8" SLOC3 "I37.0" SLOC3 "I7.1" SLOC3 "S12.3" SLOC3 "S163.1" SLOC3 "S1.7" SLOC3 "S5.4" SLOC3 "S7.0" SLPERLOC "274" SLTHICK "0.2" SLTHICK "0.7" SLTHICK "1.2" SLTHICK "1.3" SLTHICK "3.0" SLTHICK "4.0" SLTHICK "5.0" SLTHICK "5.5" SPC "0.0" SPC "1.5" SPCPERPLANE1 "0.0" SPCPERPLANE1 "1.5" SPCPERPLANE2 "0.0" SPCPERPLANE2 "1.5" SPCPERPLANE3 "0.0" SPCPERPLANE3 "1.5" STATION "0" SUPPTQ "1" SWAPPF "A/P" SWAPPF "R/L" SWAPPF "S/I" SWAPPF "Unswap" TAG_SPACE "7" TAG_TYPE "None" TBLDELTA "0.00" TE "100.0" TE "102.0" TE "15.0" TE "30.0" TE "50.0" TE "Min Full" TE "Minimum" TI "150" TI "450" TI "500" TOTALNOSTATION "0" TR "2000.0" TR "3000.0" TR "4000.0" TR "4125.0" TR "4575.0" TR "475.0" TR "500.0" TR "5200.0" TR "525.0" TR "5325.0" TR "6600.0" TRACKLEN "200.0" TRACKTHICK "20.0" TRACTIVE "0" TRACTIVE "4" TRICKSIMG "1" TRREST "0" TRREST "4" USERCV0 "0.00" USERCV0 "1.00" USERCV21 "0.00" USERCV23 "100.00" USERCV4 "0.00" USERCV6 "0.00" USERCV7 "0.00" USERCV_MASK "0" USERCV_MASK "1" USERCV_MASK "128" USERCV_MASK "192" USERCV_MASK "2097344" USERCV_MASK "6144" USERCV_MASK "64" USERCV_MASK "8388688" VIEWORDER "1" */ GDCM-3.0.10/Applications/Cxx/gdcmfile.cxx000066400000000000000000000037421412732066400200060ustar00rootroot00000000000000/*========================================================================= 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 // fstat #include #include #include // open #include #include #include // mmap #include #include "gdcmFile.h" #include "gdcmObject.h" #include "gdcmDataSet.h" #include "gdcmFileMetaInformation.h" #include "gdcmSmartPointer.h" #include "gdcmDeflateStream.h" #include "gdcmDumper.h" #include "gdcmDirectory.h" #include "gdcmSystem.h" int DoOperation(std::string const & path) { //std::cout << path << "\n"; std::ifstream is( path.c_str(), std::ios::binary ); is.seekg(0, std::ios::end ); std::streampos size = is.tellg(); is.seekg(0,std::ios::beg); std::vector buffer; buffer.resize(size); is.read(&buffer[0], size ); char k = buffer[(size_t)size-1]; // at least read one char to avoid compiler optimization is.close(); return 0; } int main(int argc, char *argv[]) { if( argc < 2 ) { return 1; } std::string filename = argv[1]; int res = 0; if( gdcm::System::FileIsDirectory( filename.c_str() ) ) { gdcm::Directory d; d.Load(filename); gdcm::Directory::FilenamesType const &filenames = d.GetFilenames(); for( gdcm::Directory::FilenamesType::const_iterator it = filenames.begin(); it != filenames.end(); ++it ) { res += DoOperation(*it); } } else { res += DoOperation(filename); } return res; } GDCM-3.0.10/Applications/Cxx/gdcmgendir.cxx000066400000000000000000000213501412732066400203320ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Implementation of General Purpose CD-R Interchange / STD-GEN-CD DICOMDIR in GDCM */ #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmVersion.h" #include "gdcmSystem.h" #include "gdcmUIDGenerator.h" #include "gdcmGlobal.h" #include "gdcmDefs.h" #include "gdcmDirectory.h" #include "gdcmDICOMDIRGenerator.h" #include static void PrintVersion() { std::cout << "gdcmgendir: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; } static void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcmgendir [OPTION]... FILE..." << std::endl; std::cout << "create DICOMDIR" << std::endl; std::cout << "Parameter:" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -i --input DICOM filename or directory" << std::endl; std::cout << " -o --output DICOM filename or directory" << std::endl; std::cout << " -r --recursive recursive." << std::endl; std::cout << " --descriptor descriptor." << std::endl; std::cout << " --root-uid Root UID." << std::endl; std::cout << "General Options:" << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " -v --version print version." << std::endl; std::cout << "Env var:" << std::endl; std::cout << " GDCM_ROOT_UID Root UID" << std::endl; } int main(int argc, char *argv[]) { int c; std::string filename; std::string outfilename; gdcm::Directory::FilenamesType filenames; std::string xmlpath; int verbose = 0; int warning = 0; int help = 0; int recursive = 0; int version = 0; int debug = 0; int error = 0; int resourcespath = 0; int rootuid = 0; int descriptor = 0; std::string descriptor_str; std::string root; while (true) { int option_index = 0; static struct option long_options[] = { {"input", 1, nullptr, 0}, {"output", 1, nullptr, 0}, // o {"recursive", 0, &recursive, 1}, {"root-uid", 1, &rootuid, 1}, // specific Root (not GDCM) {"resources-path", 1, &resourcespath, 1}, {"descriptor", 1, &descriptor, 1}, {"verbose", 0, &verbose, 1}, {"warning", 0, &warning, 1}, {"debug", 0, &debug, 1}, {"error", 0, &error, 1}, {"help", 0, &help, 1}, {"version", 0, &version, 1}, {nullptr, 0, nullptr, 0} // required }; static const char short_options[] = "i:o:rVWDEhv"; c = getopt_long (argc, argv, short_options, long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: case '-': { const char *s = long_options[option_index].name; (void)s; //printf ("option %s", s); if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); assert( filename.empty() ); filename = optarg; } else if( option_index == 1 ) /* output */ { assert( strcmp(s, "output") == 0 ); assert( outfilename.empty() ); outfilename = optarg; } else if( option_index == 3 ) /* root-uid */ { assert( strcmp(s, "root-uid") == 0 ); root = optarg; } else if( option_index == 4 ) /* resources-path */ { assert( strcmp(s, "resources-path") == 0 ); assert( xmlpath.empty() ); xmlpath = optarg; } else if( option_index == 5 ) /* descriptor */ { assert( strcmp(s, "descriptor") == 0 ); assert( descriptor_str.empty() ); descriptor_str = optarg; } //printf (" with arg %s", optarg); } //printf ("\n"); } break; case 'i': //printf ("option i with value '%s'\n", optarg); assert( filename.empty() ); filename = optarg; break; case 'o': assert( outfilename.empty() ); outfilename = optarg; break; case 'r': recursive = 1; break; case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { //printf ("non-option ARGV-elements: %d", optind ); std::vector files; while (optind < argc) { //printf ("%s\n", argv[optind++]); files.emplace_back(argv[optind++] ); } //printf ("\n"); if( files.size() >= 2 && filename.empty() && outfilename.empty() ) { filename = files[0].c_str(); filenames = files; outfilename = files[ files.size() - 1 ].c_str(); filenames.pop_back(); } else { PrintHelp(); return 1; } } if( version ) { //std::cout << "version" << std::endl; PrintVersion(); return 0; } if( help ) { //std::cout << "help" << std::endl; PrintHelp(); return 0; } if( filename.empty() || outfilename.empty() ) { //std::cerr << "Need input file (-i)\n"; PrintHelp(); return 1; } // Debug is a little too verbose gdcm::Trace::SetDebug( debug != 0 ); gdcm::Trace::SetWarning( warning != 0 ); gdcm::Trace::SetError( error != 0 ); // when verbose is true, make sure warning+error are turned on: if( verbose ) { gdcm::Trace::SetWarning( verbose != 0 ); gdcm::Trace::SetError( verbose != 0); } if( !gdcm::System::FileExists(filename.c_str()) ) { return 1; } /* gdcm::Global& g = gdcm::Global::GetInstance(); // First thing we need to locate the XML dict // did the user requested to look XML file in a particular directory ? if( !resourcespath ) { const char *xmlpathenv = getenv("GDCM_RESOURCES_PATH"); if( xmlpathenv ) { // Make sure to look for XML dict in user explicitly specified dir first: xmlpath = xmlpathenv; resourcespath = 1; } } if( resourcespath ) { // xmlpath is set either by the cmd line option or the env var if( !g.Prepend( xmlpath.c_str() ) ) { std::cerr << "specified Resources Path is not valid: " << xmlpath << std::endl; return 1; } } // All set, then load the XML files: if( !g.LoadResourcesFiles() ) { return 1; } const gdcm::Defs &defs = g.GetDefs(); */ gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( "gdcmgendir" ); if( !rootuid ) { // only read the env var is no explicit cmd line option // maybe there is an env var defined... let's check const char *rootuid_env = getenv("GDCM_ROOT_UID"); if( rootuid_env ) { rootuid = 1; root = rootuid_env; } } if( rootuid ) { if( !gdcm::UIDGenerator::IsValid( root.c_str() ) ) { std::cerr << "specified Root UID is not valid: " << root << std::endl; return 1; } gdcm::UIDGenerator::SetRoot( root.c_str() ); } int res = 0; unsigned int nfiles = 1; gdcm::DICOMDIRGenerator gen; if( gdcm::System::FileIsDirectory(filename.c_str()) ) { gdcm::Directory dir; nfiles = dir.Load(filename, recursive!= 0); (void)nfiles; filenames = dir.GetFilenames(); gen.SetRootDirectory( filename ); } else { // should be all set ! } (void)nfiles; gen.SetFilenames( filenames ); gen.SetDescriptor( descriptor_str.c_str() ); if( !gen.Generate() ) { std::cerr << "Problem during generation" << std::endl; return 1; } gdcm::Writer writer; writer.SetFile( gen.GetFile() ); writer.SetFileName( outfilename.c_str() ); if( !writer.Write() ) { return 1; } return res; } GDCM-3.0.10/Applications/Cxx/gdcmimg.cxx000066400000000000000000001174651412732066400176530ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * TODO: Merging (burnin) of overlay would be nice (merge 0x60xx overlay into PixelData) * TODO: --add-thumbnail / --remove-thumbnail * convert: -thumbnail geometry create a thumbnail of the image * convert: -crop geometry cut out a rectangular region of the image * -floodfill geometry color * floodfill the image with color * 1. Create a DICOM file from a 'raw' input: * 2. Create a blob (jpeg,pgm/pnm,j2k,rle) from input * - binary blob(s) (grayscale / RGB) input * - jpeg(s) * - j2k(s) * * Mapping is: * * DICOM RAW <-> pnm/pgm * DICOM jpg <-> jpg * DICOM ljpg <-> ljpg * DICOM jls <-> jls * DICOM j2k <-> j2k * DICOM rle <-> Utah RLE ?? * * ??: * DICOM avi <-> avi * DICOM wav <-> wav * DICOM pdf <-> pdf * Todo: check compat API with jhead */ #include "gdcmFilename.h" #include "gdcmImageHelper.h" #include "gdcmDirectory.h" #include "gdcmMediaStorage.h" #include "gdcmSmartPointer.h" #include "gdcmUIDGenerator.h" #include "gdcmSequenceOfFragments.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmPixmapWriter.h" #include "gdcmPixmapReader.h" #include "gdcmFileMetaInformation.h" #include "gdcmDataSet.h" #include "gdcmAttribute.h" #include "gdcmPNMCodec.h" #include "gdcmPGXCodec.h" #include "gdcmJPEGCodec.h" #include "gdcmJPEGLSCodec.h" #include "gdcmJPEG2000Codec.h" #include "gdcmRLECodec.h" #include "gdcmRAWCodec.h" #include "gdcmVersion.h" #include #include #include /* for printf */ #include /* for exit */ #include #include static unsigned int readsize(const char *str, unsigned int * size) { int n = sscanf( str, "%i,%i,%i", size, size+1, size+2); return n == EOF ? 0 : (unsigned int)n; } static bool readgeometry(const char *geometry, unsigned int * region) { int n = sscanf( geometry, "%i,%i,%i,%i,%i,%i", region, region+1, region+2, region+3, region+4, region+5); if( n != 6 ) return false; return true; } template static void FillRegionWithColor(T *p, const unsigned int *dims, const unsigned int * region, unsigned int color, unsigned int nsamples) { unsigned int xmin = region[0]; unsigned int xmax = region[1]; unsigned int ymin = region[2]; unsigned int ymax = region[3]; unsigned int zmin = region[4]; unsigned int zmax = region[5]; for( unsigned int x = xmin; x <= xmax; ++x) { for( unsigned int y = ymin; y <= ymax; ++y) { for( unsigned int z = zmin; z <= zmax; ++z) { for( unsigned int sample = 0; sample < nsamples; ++sample) { p[x*nsamples+y*dims[0]*nsamples+z*dims[0]*dims[1]*nsamples+sample] = (T)color; } } } } } static void PrintVersion() { std::cout << "gdcmimg: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; } static void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcmimg [OPTION]... FILE..." << std::endl; std::cout << "Manipulate DICOM image file:" << std::endl; std::cout << " 1. Convert to and from other file format (jpg, jp2, pnm...)" << std::endl; std::cout << " 2. Anonymize burn-in annotation (rect region fill with pixel value)" << std::endl; std::cout << "Parameter (required):" << std::endl; std::cout << " -i --input Input filename" << std::endl; std::cout << " -o --output Output filename" << std::endl; std::cout << "Options:" << std::endl; std::cout << " --endian %s Endianness (LSB/MSB)." << std::endl; std::cout << " -d --depth %d Depth (Either 8/16/32 or BitsAllocated eg. 12 when known)." << std::endl; std::cout << " --sign %s Pixel sign (0/1)." << std::endl; std::cout << " --spp %d Sample Per Pixel (1/3/4)." << std::endl; std::cout << " --pc [01] Change planar configuration." << std::endl; std::cout << " --pi [str] Change photometric interpretation." << std::endl; std::cout << " --pf %d,%d,%d Change pixel format: (BA,BS,HB)." << std::endl; std::cout << " -s --size %d,%d,%d Size." << std::endl; std::cout << " --offset %ull Start Offset." << std::endl; std::cout << " -C --sop-class-uid SOP Class UID (name or value)." << std::endl; std::cout << " -T --study-uid Study UID." << std::endl; std::cout << " -S --series-uid Series UID." << std::endl; std::cout << " --template DICOM template." << std::endl; std::cout << " --keep-meta Keep meta info from template file (advanced users only)." << std::endl; std::cout << " --root-uid Root UID." << std::endl; std::cout << "Fill Options:" << std::endl; std::cout << " -R --region %d,%d Region." << std::endl; std::cout << " -F --fill %d Fill with pixel value specified." << std::endl; std::cout << "General Options:" << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " -v --version print version." << std::endl; std::cout << "Env var:" << std::endl; std::cout << " GDCM_ROOT_UID Root UID" << std::endl; /* * Default behavior for root UID is: * By default the GDCM one is used * If GDCM_ROOT_UID is set, then use this one instead * If --root-uid is explicitly set on the command line, it will override any other defined behavior */ } static bool AddContentDateTime(gdcm::DataSet &ds, const char *filename ) { time_t studydatetime = gdcm::System::FileTime( filename ); char date[22]; gdcm::System::FormatDateTime(date, studydatetime); const size_t datelen = 8; { gdcm::DataElement de( gdcm::Tag(0x0008,0x0023) ); // Content Date // Do not copy the whole cstring: de.SetByteValue( date, datelen ); de.SetVR( gdcm::Attribute<0x0008,0x0023>::GetVR() ); ds.Insert( de ); } // StudyTime const size_t timelen = 6; // get rid of milliseconds { gdcm::DataElement de( gdcm::Tag(0x0008,0x0033) ); // Content Time // Do not copy the whole cstring: de.SetByteValue( date+datelen, timelen ); de.SetVR( gdcm::Attribute<0x0008,0x0033>::GetVR() ); ds.Insert( de ); } return true; } // Set Study Date/Time to the file time: static bool AddStudyDateTime(gdcm::DataSet &ds, const char *filename ) { // StudyDate char date[22]; const size_t datelen = 8; int res = gdcm::System::GetCurrentDateTime(date); if( !res ) return false; { gdcm::DataElement de( gdcm::Tag(0x0008,0x0020) ); // Do not copy the whole cstring: de.SetByteValue( date, datelen ); de.SetVR( gdcm::Attribute<0x0008,0x0020>::GetVR() ); ds.Insert( de ); } // StudyTime const size_t timelen = 6; // get rid of milliseconds { gdcm::DataElement de( gdcm::Tag(0x0008,0x0030) ); // Do not copy the whole cstring: de.SetByteValue( date+datelen, timelen ); de.SetVR( gdcm::Attribute<0x0008,0x0030>::GetVR() ); ds.Insert( de ); } return AddContentDateTime(ds, filename); } static bool AddUIDs(int sopclassuid, std::string const & sopclass, std::string const & study_uid, std::string const & series_uid, gdcm::PixmapWriter& writer) { gdcm::DataSet & ds = writer.GetFile().GetDataSet(); gdcm::MediaStorage ms = gdcm::MediaStorage::MS_END; gdcm::Pixmap &image = writer.GetPixmap(); if( sopclassuid ) { // Is it by value or by name ? if( gdcm::UIDGenerator::IsValid( sopclass.c_str() ) ) { ms = gdcm::MediaStorage::GetMSType( sopclass.c_str() ); } else { std::cerr << "not implemented" << std::endl; } } else { // guess a default ms = gdcm::ImageHelper::ComputeMediaStorageFromModality( "OT", image.GetNumberOfDimensions(), image.GetPixelFormat(), image.GetPhotometricInterpretation() ); } if( !gdcm::MediaStorage::IsImage(ms) ) { std::cerr << "invalid media storage (no pixel data): " << sopclass << std::endl; return false; } if( ms.GetModalityDimension() < image.GetNumberOfDimensions() ) { std::cerr << "Could not find Modality" << std::endl; return false; } const char* msstr = gdcm::MediaStorage::GetMSString(ms); if( !msstr ) { std::cerr << "problem with media storage: " << sopclass << std::endl; return false; } { gdcm::DataElement de( gdcm::Tag(0x0008, 0x0016 ) ); de.SetByteValue( msstr, (uint32_t)strlen(msstr) ); de.SetVR( gdcm::Attribute<0x0008, 0x0016>::GetVR() ); ds.Insert( de ); } { gdcm::DataElement de( gdcm::Tag(0x0020,0x000d) ); // Study de.SetByteValue( study_uid.c_str(), (uint32_t)study_uid.size() ); de.SetVR( gdcm::Attribute<0x0020, 0x000d>::GetVR() ); ds.Insert( de ); } { gdcm::DataElement de( gdcm::Tag(0x0020,0x000e) ); // Series de.SetByteValue( series_uid.c_str(), (uint32_t)series_uid.size() ); de.SetVR( gdcm::Attribute<0x0020, 0x000e>::GetVR() ); ds.Insert( de ); } return true; } // Append data to either sq or bv depending whether encapsulated or not static bool PopulateSingeFile( gdcm::PixmapWriter & writer, gdcm::SequenceOfFragments *sq , gdcm::ByteValue * bv, gdcm::ImageCodec & jpeg, const char *filename, std::streampos const pos = 0 ) { /* * FIXME: when JPEG contains JFIF marker, we should only read them * during header parsing but discard them when copying the JPG byte stream into * the encapsulated Pixel Data Element... */ std::ifstream is(filename, std::ios::binary); gdcm::TransferSyntax ts; bool b = jpeg.GetHeaderInfo( is, ts ); if( !b ) { std::cerr << "Could not read: " << filename << std::endl; return false; } gdcm::Pixmap &image = writer.GetPixmap(); image.SetDimensions( jpeg.GetDimensions() ); image.SetPixelFormat( jpeg.GetPixelFormat() ); image.SetPhotometricInterpretation( jpeg.GetPhotometricInterpretation() ); image.SetPlanarConfiguration( jpeg.GetPlanarConfiguration() ); image.SetTransferSyntax( ts ); AddStudyDateTime( writer.GetFile().GetDataSet(), filename ); size_t len = gdcm::System::FileSize(filename); if( ts.IsEncapsulated() ) { is.seekg(0, std::ios::beg );// rewind ! } else { len = image.GetBufferLength(); // do not rewind file should be just at right offset } char *buf = new char[len]; if( pos ) { is.seekg( pos, std::ios::beg ); } is.read(buf, len); gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0,0x0010) ); if( ts.IsEncapsulated() ) { gdcm::Fragment frag; frag.SetByteValue( buf, (uint32_t)len ); sq->AddFragment( frag ); pixeldata.SetValue( *sq ); } else { gdcm::ByteValue frame( buf, (uint32_t)len ); bv->Append( frame ); pixeldata.SetValue( *bv ); } delete[] buf; image.SetDataElement( pixeldata ); return true; } static bool Populate( gdcm::PixmapWriter & writer, gdcm::ImageCodec & jpeg, gdcm::Directory::FilenamesType const & filenames, unsigned int ndim = 2, std::streampos const & pos = 0 ) { assert( !filenames.empty() ); std::vector::const_iterator it = filenames.begin(); bool b = true; gdcm::Pixmap &image = writer.GetPixmap(); image.SetNumberOfDimensions( ndim ); gdcm::SmartPointer sq = new gdcm::SequenceOfFragments; gdcm::SmartPointer bv = new gdcm::ByteValue; for(; it != filenames.end(); ++it) { b = b && PopulateSingeFile( writer, sq, bv, jpeg, it->c_str(), pos ); } if( filenames.size() > 1 ) { image.SetNumberOfDimensions( 3 ); image.SetDimension(2, (unsigned int)filenames.size() ); } return b; } static bool GetPixelFormat( gdcm::PixelFormat & pf, int depth, int bpp, int sign, int pixelsign, int spp = 0, int pixelspp = 1 ) { if( depth ) { if( bpp <= 8 ) { pf = gdcm::PixelFormat::UINT8; } else if( bpp > 8 && bpp <= 16 ) { pf = gdcm::PixelFormat::UINT16; } else if( bpp > 16 && bpp <= 32 ) { pf = gdcm::PixelFormat::UINT32; } else { std::cerr << "Invalid depth: << " << bpp << std::endl; return false; } pf.SetBitsStored( (short)bpp ); } if( sign ) { pf.SetPixelRepresentation( (unsigned short)pixelsign ); } if( spp ) { pf.SetSamplesPerPixel( (unsigned short)pixelspp ); } return true; } int main (int argc, char *argv[]) { int c; //int digit_optind = 0; std::string root; int rootuid = 0; gdcm::Filename filename; gdcm::Directory::FilenamesType filenames; gdcm::Filename outfilename; gdcm::Filename templatefilename; unsigned int region[6] = {}; // Rows & Columns are VR=US anyway... unsigned int color = 0; int bregion = 0; int fill = 0; int sign = 0; int spp = 0; int pconf = 0; // planar configuration int studyuid = 0; int seriesuid = 0; int templated = 0; int keepmeta = 0; unsigned int size[3] = {0,0,0}; unsigned int ndimension = 2; int depth = 0; int endian = 0; int bpp = 0; int pixelsign = 0; int pixelspp = 0; std::string sopclass; std::string lsb_msb; int sopclassuid = 0; int pinter = 0; std::string pinterstr; int pformat = 0; std::string pformatstr; int poffset = 0; size_t start_pos = 0; int verbose = 0; int warning = 0; int debug = 0; int error = 0; int help = 0; int version = 0; gdcm::UIDGenerator uid; // Too early for UID Generation std::string series_uid; // = uid.Generate(); std::string study_uid; // = uid.Generate(); while (true) { //int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"input", 1, nullptr, 0}, {"output", 1, nullptr, 0}, // provide convert-like command line args: {"depth", 1, &depth, 1}, {"size", 1, nullptr, 0}, {"region", 1, &bregion, 1}, {"fill", 1, &fill, 1}, {"study-uid", 1, &studyuid, 1}, {"series-uid", 1, &seriesuid, 1}, {"root-uid", 1, &rootuid, 1}, // specific Root (not GDCM) {"sop-class-uid", 1, &sopclassuid, 1}, // specific SOP Class UID {"endian", 1, &endian, 1}, // {"sign", 1, &sign, 1}, // {"spp", 1, &spp, 1}, // {"pc", 1, &pconf, 1}, // {"pi", 1, &pinter, 1}, // {"pf", 1, &pformat, 1}, // {"offset", 1, &poffset, 1}, // {"template", 1, &templated, 1}, {"keep-meta", 0, &keepmeta, 1}, // by default we do not want to keep // General options ! {"verbose", 0, &verbose, 1}, {"warning", 0, &warning, 1}, {"debug", 0, &debug, 1}, {"error", 0, &error, 1}, {"help", 0, &help, 1}, {"version", 0, &version, 1}, {nullptr, 0, nullptr, 0} }; // i -> input file // I -> input directory // o -> output file // O -> output directory c = getopt_long (argc, argv, "i:o:I:O:d:s:R:C:F:T:S:VWDEhv", long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: { const char *s = long_options[option_index].name; (void)s; //printf ("option %s", s); if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); assert( filename.IsEmpty() ); filename = optarg; filenames.emplace_back(filename); } else if( option_index == 2 ) /* depth */ { assert( strcmp(s, "depth") == 0 ); bpp = atoi(optarg); } else if( option_index == 3 ) /* size */ { assert( strcmp(s, "size") == 0 ); ndimension = readsize(optarg, size); } else if( option_index == 4 ) /* region */ { assert( strcmp(s, "region") == 0 ); readgeometry(optarg, region); } else if( option_index == 5 ) /* fill */ { assert( strcmp(s, "fill") == 0 ); color = atoi(optarg); } else if( option_index == 6 ) /* study-uid */ { assert( strcmp(s, "study-uid") == 0 ); study_uid = optarg; } else if( option_index == 7 ) /* series-uid */ { assert( strcmp(s, "series-uid") == 0 ); series_uid = optarg; } else if( option_index == 8 ) /* root-uid */ { assert( strcmp(s, "root-uid") == 0 ); root = optarg; } else if( option_index == 9 ) /* sop-class-uid */ { assert( strcmp(s, "sop-class-uid") == 0 ); sopclass = optarg; } else if( option_index == 10 ) /* endian */ { assert( strcmp(s, "endian") == 0 ); lsb_msb = optarg; } else if( option_index == 11 ) /* sign */ { assert( strcmp(s, "sign") == 0 ); pixelsign = atoi(optarg); } else if( option_index == 12 ) /* spp */ { assert( strcmp(s, "spp") == 0 ); pixelspp = atoi(optarg); } else if( option_index == 13 ) /* pconf */ { assert( strcmp(s, "pc") == 0 ); pconf = atoi(optarg); } else if( option_index == 14 ) /* pinter */ { assert( strcmp(s, "pi") == 0 ); pinter = 1; pinterstr = optarg; } else if( option_index == 15 ) /* pformat */ { assert( strcmp(s, "pf") == 0 ); pformat = 1; pformatstr = optarg; } else if( option_index == 16 ) /* start_pos */ { assert( strcmp(s, "offset") == 0 ); poffset = 1; start_pos = (size_t)std::atoll(optarg); } else if( option_index == 17 ) /* template */ { assert( strcmp(s, "template") == 0 ); templated = 1; templatefilename = optarg; } //printf (" with arg %s", optarg); } //printf ("\n"); } break; case 'i': //printf ("option i with value '%s'\n", optarg); assert( filename.IsEmpty() ); filename = optarg; filenames.emplace_back(filename); break; case 'o': //printf ("option o with value '%s'\n", optarg); assert( outfilename.IsEmpty() ); outfilename = optarg; break; case 'd': // depth bpp = atoi(optarg); depth = 1; break; case 's': // size ndimension = readsize(optarg, size); break; case 'T': studyuid = 1; study_uid = optarg; break; case 'S': seriesuid = 1; series_uid = optarg; break; case 'C': sopclassuid = 1; sopclass = optarg; break; case 'R': // region //outfilename = optarg; readgeometry(optarg, region); break; case 'F': // fill color = atoi( optarg ); fill = 1; break; case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } // For now only support one input / one output if (optind < argc) { //printf ("non-option ARGV-elements: "); std::vector files; while (optind < argc) { //printf ("%s\n", argv[optind++]); files.emplace_back(argv[optind++] ); } //printf ("\n"); if( files.size() >= 2 && filename.IsEmpty() && outfilename.IsEmpty() ) { filename = files[0].c_str(); filenames = files; outfilename = files[ files.size() - 1 ].c_str(); filenames.pop_back(); } else { PrintHelp(); return 1; } } if( version ) { //std::cout << "version" << std::endl; PrintVersion(); return 0; } if( help ) { //std::cout << "help" << std::endl; PrintHelp(); return 0; } if( filenames.empty() && filename.IsEmpty() ) { //std::cerr << "Need input file (-i)\n"; PrintHelp(); return 1; } if( outfilename.IsEmpty() ) { //std::cerr << "Need output file (-o)\n"; PrintHelp(); return 1; } // Ok so we are about to write a DICOM file, do not forget to stamp it GDCM ! gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( "gdcmimg" ); if( !rootuid ) { // only read the env var is no explicit cmd line option // maybe there is an env var defined... let's check const char *rootuid_env = getenv("GDCM_ROOT_UID"); if( rootuid_env ) { rootuid = 1; root = rootuid_env; } } if( rootuid ) { if( !gdcm::UIDGenerator::IsValid( root.c_str() ) ) { std::cerr << "specified Root UID is not valid: " << root << std::endl; return 1; } gdcm::UIDGenerator::SetRoot( root.c_str() ); } if( study_uid.empty() ) { study_uid = uid.Generate(); } if( !gdcm::UIDGenerator::IsValid( study_uid.c_str() ) ) { std::cerr << "Invalid UID for Study UID: " << study_uid << std::endl; return 1; } if( series_uid.empty() ) { series_uid = uid.Generate(); } if( !gdcm::UIDGenerator::IsValid( series_uid.c_str() ) ) { std::cerr << "Invalid UID for Series UID: " << series_uid << std::endl; return 1; } // Debug is a little too verbose gdcm::Trace::SetDebug( (debug > 0 ? true : false)); gdcm::Trace::SetWarning( (warning > 0 ? true : false)); gdcm::Trace::SetError( (error > 0 ? true : false)); // when verbose is true, make sure warning+error are turned on: if( verbose ) { gdcm::Trace::SetWarning( (verbose > 0 ? true : false) ); gdcm::Trace::SetError( (verbose > 0 ? true : false) ); } if( depth ) { if( bpp < 1 || bpp > 32 ) { std::cerr << "Invalid depth for pixel: " << bpp << std::endl; return 1; } } if( sign ) { if( pixelsign != 0 && pixelsign != 1 ) return 1; } if( spp ) { if( pixelspp != 1 && pixelspp != 3 && pixelspp != 4 ) return 1; } if( pconf != 0 && pconf != 1 ) return 1; if( pconf ) { if( pixelspp != 3 ) return 1; } gdcm::PixelFormat pfref = gdcm::PixelFormat::UINT8; if( pformat ) { int ba, bs, hb; int n = sscanf( pformatstr.c_str(), "%d,%d,%d", &ba, &bs, &hb ); if( n != 3 ) return 1; pfref.SetBitsAllocated( (unsigned short)ba ); pfref.SetBitsStored( (unsigned short)bs ); pfref.SetHighBit( (unsigned short)hb ); if( spp ) pfref.SetSamplesPerPixel( (unsigned short)pixelspp ); if( sign ) pfref.SetPixelRepresentation( (unsigned short)pixelsign ); } gdcm::PhotometricInterpretation::PIType refpi = gdcm::PhotometricInterpretation::MONOCHROME2; if( pinter ) { refpi = gdcm::PhotometricInterpretation::GetPIType( pinterstr.c_str() ); if( refpi == gdcm::PhotometricInterpretation::UNKNOWN || refpi == gdcm::PhotometricInterpretation::PI_END ) { std::cerr << "Invalid PI: " << pinterstr << std::endl; return 1; } } const char *inputextension = filename.GetExtension(); const char *outputextension = outfilename.GetExtension(); //if( !inputextension || !outputextension ) return 1; if( inputextension ) { gdcm::Reader reader; if( templated ) { reader.SetFileName( templatefilename ); if( !reader.Read() ) { std::cerr << "Failed to read: " << templatefilename << std::endl; return 1; } } if( gdcm::System::StrCaseCmp(inputextension,".raw") == 0 // watch out that .raw for kakadu means big-endian || gdcm::System::StrCaseCmp(inputextension,".rawl") == 0 // kakadu convention for raw little endian || gdcm::System::StrCaseCmp(inputextension,".gray") == 0 // imagemagick convention || gdcm::System::StrCaseCmp(inputextension,".bin") == 0 // openjp3d convention for raw little endian || gdcm::System::StrCaseCmp(inputextension,".rgb") == 0 // imagemagick convention || gdcm::System::StrCaseCmp(inputextension,".yuv") == 0 ) // ffmpeg convention { if( !size[0] || !size[1] ) { std::cerr << "need to specify size of image stored in RAW file" << std::endl; return 1; } gdcm::RAWCodec raw; gdcm::PixmapWriter writer; writer.SetCheckFileMetaInformation( (keepmeta > 0 ? false : true) ); writer.SetFile( reader.GetFile() ); // Because the RAW stream is not self sufficient, we need to pass in some extra // user info: unsigned int dims[3] = {}; dims[0] = size[0]; dims[1] = size[1]; if( ndimension == 3 ) { dims[2] = size[2]; } raw.SetDimensions( dims ); gdcm::PixelFormat pf = gdcm::PixelFormat::UINT8; gdcm::PhotometricInterpretation pi = refpi; if( gdcm::System::StrCaseCmp(inputextension,".rgb") == 0 ) { pi = gdcm::PhotometricInterpretation::RGB; spp = 1; pixelspp = 3; } if( !GetPixelFormat( pf, depth, bpp, sign, pixelsign, spp, pixelspp ) ) return 1; raw.SetPixelFormat( pf ); if( spp ) { if( pixelspp == 3 && !pinter ) pi = gdcm::PhotometricInterpretation::RGB; } raw.SetPhotometricInterpretation( pi ); raw.SetNeedByteSwap( false ); raw.SetPlanarConfiguration( pconf ); if( endian ) { if( lsb_msb == "LSB" || lsb_msb == "MSB" ) { if( lsb_msb == "MSB" ) { raw.SetNeedByteSwap( true ); } } else { std::cerr << "Unrecognized endian: " << lsb_msb << std::endl; return 1; } } if( !Populate( writer, raw, filenames, ndimension, start_pos ) ) return 1; // populate will guess pixel format and photometric inter from file, need // to override after calling Populate: if( pformat ) { writer.GetPixmap().SetPixelFormat( pfref ); } if( pinter ) { writer.GetPixmap().SetPhotometricInterpretation( refpi ); } if( !AddUIDs(sopclassuid, sopclass, study_uid, series_uid, writer ) ) return 1; writer.SetFileName( outfilename ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } return 0; } if( gdcm::System::StrCaseCmp(inputextension,".rle") == 0 ) { if( !size[0] || !size[1] ) { std::cerr << "need to specify size of image stored in RLE file" << std::endl; return 1; } gdcm::RLECodec rle; gdcm::PixmapWriter writer; writer.SetCheckFileMetaInformation( (keepmeta > 0 ? false : true) ); writer.SetFile( reader.GetFile() ); // Because the RLE stream is not self sufficient, we need to pass in some extra // user info: unsigned int dims[3] = {}; dims[0] = size[0]; dims[1] = size[1]; rle.SetDimensions( dims ); gdcm::PixelFormat pf = gdcm::PixelFormat::UINT8; if( !GetPixelFormat( pf, depth, bpp, sign, pixelsign, spp, pixelspp ) ) return 1; rle.SetPixelFormat( pf ); gdcm::PhotometricInterpretation pi = refpi; if( spp ) { if( pixelspp == 3 && !pinter ) pi = gdcm::PhotometricInterpretation::RGB; } rle.SetPhotometricInterpretation( pi ); if( !Populate( writer, rle, filenames ) ) return 1; if( !AddUIDs(sopclassuid, sopclass, study_uid, series_uid, writer ) ) return 1; writer.SetFileName( outfilename ); if( !writer.Write() ) { return 1; } return 0; } if( gdcm::System::StrCaseCmp(inputextension,".pgm") == 0 || gdcm::System::StrCaseCmp(inputextension,".pnm") == 0 || gdcm::System::StrCaseCmp(inputextension,".pbm") == 0 || gdcm::System::StrCaseCmp(inputextension,".ppm") == 0 ) { gdcm::PNMCodec pnm; // Let's handle the case where user really wants to specify the data: gdcm::PixelFormat pf = gdcm::PixelFormat::UINT8; if( !GetPixelFormat( pf, depth, bpp, sign, pixelsign ) ) return 1; pnm.SetPixelFormat( pf ); gdcm::PixmapWriter writer; writer.SetCheckFileMetaInformation( (keepmeta > 0 ? false : true) ); writer.SetFile( reader.GetFile() ); if( !Populate( writer, pnm, filenames ) ) return 1; // populate will guess pixel format and photometric inter from file, need // to override after calling Populate: if( pformat ) { writer.GetPixmap().SetPixelFormat( pfref ); } if( pinter ) { writer.GetPixmap().SetPhotometricInterpretation( refpi ); } // HACK if( endian && lsb_msb == "LSB" ) writer.GetPixmap().SetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian ); if( !AddUIDs(sopclassuid, sopclass, study_uid, series_uid, writer ) ) return 1; writer.SetFileName( outfilename ); if( !writer.Write() ) { return 1; } return 0; } if( gdcm::System::StrCaseCmp(inputextension,".pgx") == 0 ) { gdcm::PGXCodec pnm; gdcm::PixmapWriter writer; writer.SetCheckFileMetaInformation( (keepmeta > 0 ? false : true) ); writer.SetFile( reader.GetFile() ); if( !Populate( writer, pnm, filenames ) ) return 1; if( !AddUIDs(sopclassuid, sopclass, study_uid, series_uid, writer ) ) return 1; writer.SetFileName( outfilename ); if( !writer.Write() ) { return 1; } return 0; } if( gdcm::System::StrCaseCmp(inputextension,".jls") == 0 ) { gdcm::JPEGLSCodec jpeg; gdcm::PixmapWriter writer; writer.SetCheckFileMetaInformation( (keepmeta > 0 ? false : true) ); writer.SetFile( reader.GetFile() ); if( !Populate( writer, jpeg, filenames ) ) return 1; if( !AddUIDs(sopclassuid, sopclass, study_uid, series_uid, writer ) ) return 1; writer.SetFileName( outfilename ); if( !writer.Write() ) { return 1; } return 0; } if( gdcm::System::StrCaseCmp(inputextension,".jp2") == 0 || gdcm::System::StrCaseCmp(inputextension,".j2k") == 0 || gdcm::System::StrCaseCmp(inputextension,".j2c") == 0 || gdcm::System::StrCaseCmp(inputextension,".jpx") == 0 || gdcm::System::StrCaseCmp(inputextension,".jpf") == 0 || gdcm::System::StrCaseCmp(inputextension,".jpc") == 0 ) { /* * FIXME: Same problem as in classic JPEG: JP2 is NOT a J2K byte stream * need to chop off all extra header information... */ gdcm::JPEG2000Codec jpeg; gdcm::PixmapWriter writer; writer.SetCheckFileMetaInformation( (keepmeta > 0 ? false : true) ); writer.SetFile( reader.GetFile() ); if( !Populate( writer, jpeg, filenames ) ) return 1; if( pinter ) { writer.GetPixmap().SetPhotometricInterpretation( refpi ); } if( !AddUIDs(sopclassuid, sopclass, study_uid, series_uid, writer ) ) return 1; writer.SetFileName( outfilename ); if( !writer.Write() ) { return 1; } return 0; } if( gdcm::System::StrCaseCmp(inputextension,".jpg") == 0 || gdcm::System::StrCaseCmp(inputextension,".jpeg") == 0 || gdcm::System::StrCaseCmp(inputextension,".ljpg") == 0 || gdcm::System::StrCaseCmp(inputextension,".ljpeg") == 0 ) { gdcm::JPEGCodec jpeg; // Let's handle the case where user really wants to specify signess of data: gdcm::PixelFormat pf = gdcm::PixelFormat::UINT8; if( !GetPixelFormat( pf, depth, bpp, sign, pixelsign ) ) return 1; jpeg.SetPixelFormat( pf ); gdcm::PixmapWriter writer; writer.SetCheckFileMetaInformation( (keepmeta > 0 ? false : true) ); writer.SetFile( reader.GetFile() ); if( !Populate( writer, jpeg, filenames ) ) return 1; if( !AddUIDs(sopclassuid, sopclass, study_uid, series_uid, writer ) ) return 1; writer.SetFileName( outfilename ); if( !writer.Write() ) { std::cerr << "Problem during DICOM steps" << std::endl; return 1; } return 0; } } // else safely assume that if no inputextension matched then it is a DICOM file gdcm::PixmapReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::Pixmap &imageori = reader.GetPixmap(); const gdcm::File &file = reader.GetFile(); if ( outputextension ) { if( gdcm::System::StrCaseCmp(outputextension,".pgm") == 0 || gdcm::System::StrCaseCmp(outputextension,".pnm") == 0 || gdcm::System::StrCaseCmp(outputextension,".pbm") == 0 || gdcm::System::StrCaseCmp(outputextension,".ppm") == 0 ) { gdcm::PNMCodec pnm; pnm.SetDimensions( imageori.GetDimensions() ); pnm.SetPixelFormat( imageori.GetPixelFormat() ); pnm.SetPhotometricInterpretation( imageori.GetPhotometricInterpretation() ); pnm.SetPlanarConfiguration( imageori.GetPlanarConfiguration() ); pnm.SetLUT( imageori.GetLUT() ); const gdcm::DataElement& in = imageori.GetDataElement(); bool b = pnm.Write( outfilename, in ); if( !b ) { std::cerr << "Problem writing PNM file" << std::endl; return 1; } return 0; } if( gdcm::System::StrCaseCmp(outputextension,".pgx") == 0 ) { gdcm::PGXCodec pnm; pnm.SetDimensions( imageori.GetDimensions() ); pnm.SetPixelFormat( imageori.GetPixelFormat() ); pnm.SetPhotometricInterpretation( imageori.GetPhotometricInterpretation() ); pnm.SetPlanarConfiguration( imageori.GetPlanarConfiguration() ); pnm.SetLUT( imageori.GetLUT() ); const gdcm::DataElement& in = imageori.GetDataElement(); bool b = pnm.Write( outfilename, in ); if( !b ) { std::cerr << "Problem writing PNM file" << std::endl; return 1; } return 0; } } // else safely assume that if no outputextension matched then it is a DICOM file gdcm::PixmapWriter writer; writer.SetFile( file ); writer.SetImage( imageori ); writer.SetFileName( outfilename ); gdcm::DataSet &ds = writer.GetFile().GetDataSet(); if( fill ) { const gdcm::PixelFormat &pixeltype = imageori.GetPixelFormat(); assert( imageori.GetNumberOfDimensions() == 2 || imageori.GetNumberOfDimensions() == 3 ); unsigned long len = imageori.GetBufferLength(); gdcm::SmartPointer image = new gdcm::Pixmap; image->SetNumberOfDimensions( 2 ); // good default const unsigned int *dims = imageori.GetDimensions(); if ( region[0] > region[1] || region[2] > region[3] || region[4] > region[5] || region[1] > dims[0] || region[3] > dims[1] || (imageori.GetNumberOfDimensions() > 2 && region[5] > dims[2]) ) { if( imageori.GetNumberOfDimensions() == 2 ) { std::cerr << "bogus region. Should be at most: (" << dims[0] << "," << dims[1] << "," /*<< dims[2]*/ << ")" << std::endl; } else { std::cerr << "bogus region. Should be at most: (" << dims[0] << "," << dims[1] << "," << dims[2] << ")" << std::endl; } return 1; } image->SetDimension(0, dims[0] ); image->SetDimension(1, dims[1] ); if( imageori.GetNumberOfDimensions() == 3 ) { image->SetNumberOfDimensions( 3 ); image->SetDimension(2, dims[2] ); } image->SetPhotometricInterpretation( imageori.GetPhotometricInterpretation() ); image->SetPixelFormat( imageori.GetPixelFormat() ); image->SetPlanarConfiguration( imageori.GetPlanarConfiguration() ); image->SetLUT( imageori.GetLUT() ); image->SetLossyFlag( imageori.IsLossy() ); // FIXME what is overlay is in pixel data ? gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0,0x0010) ); gdcm::ByteValue *bv = new gdcm::ByteValue(); bv->SetLength( (uint32_t)len ); //memcpy( bv->GetPointer(), imageori imageori.GetBuffer( (char*)bv->GetVoidPointer() ); // Rub out pixels: char *p = (char*)bv->GetVoidPointer(); switch(pixeltype) { case gdcm::PixelFormat::UINT8: FillRegionWithColor ((uint8_t*)p, dims, region, color, pixeltype.GetSamplesPerPixel()); break; case gdcm::PixelFormat::INT8: FillRegionWithColor ((int8_t*)p, dims, region, color, pixeltype.GetSamplesPerPixel()); break; case gdcm::PixelFormat::UINT16: FillRegionWithColor((uint16_t*)p, dims, region, color, pixeltype.GetSamplesPerPixel()); break; case gdcm::PixelFormat::INT16: FillRegionWithColor ((int16_t*)p, dims, region, color, pixeltype.GetSamplesPerPixel()); break; default: std::cerr << "not implemented" << std::endl; return 1; } pixeldata.SetValue( *bv ); image->SetDataElement( pixeldata ); const gdcm::TransferSyntax &ts = imageori.GetTransferSyntax(); // FIXME: for now we do not know how to recompress the image... if( ts.IsExplicit() ) { image->SetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); } else { assert( ts.IsImplicit() ); image->SetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian ); } //imageori.Print( std::cout ); //image.Print( std::cout ); // Set our filled image instead: writer.SetImage( *image ); #if 0 // gdcm::Attribute<0x0028,0x0301> at; at.SetValue( "NO" ); // 'YES' ds.Replace( at.GetAsDataElement() ); // (0008,2111) ST [MedCom Resample v] # 18, 1 DerivationDescriptio gdcm::Attribute<0x0008,0x2111> at2; std::ostringstream os; os << "Fill Region [" << region[0] << "," << region[1] << "," << region[2] << "," << region[3] << "," << region[4] << "," << region[5] << "] with color value=" << std::hex << (int)color; at2.SetValue( os.str() ); ds.Replace( at2.GetAsDataElement() ); #else #endif /* > 1. Replace Value #1 of Image Type by 'DERIVED' Don't do that ... leave Image Type alone (unless you are changing the UID ... vide infra). */ #if 0 // (0008,0008) CS [ORIGINAL\SECONDARY] # 18, 2 ImageType gdcm::Attribute<0x0008,0x0008> at3; static const gdcm::CSComp values[] = {"DERIVED","SECONDARY"}; at3.SetValues( values, 2, true ); // true => copy data ! if( ds.FindDataElement( at3.GetTag() ) ) { const gdcm::DataElement &de = ds.GetDataElement( at3.GetTag() ); at3.SetFromDataElement( de ); // Make sure that value #1 is at least 'DERIVED', so override in all cases: at3.SetValue( 0, values[0] ); } ds.Replace( at3.GetAsDataElement() ); #endif // Make sure to recompute Planar Configuration: ds.Remove( gdcm::Tag(0x0028, 0x0004) ); } // ds.Remove( gdcm::Tag(0x0,0x0) ); // FIXME if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } return 0; } GDCM-3.0.10/Applications/Cxx/gdcminfo.cxx000066400000000000000000000553261412732066400200270ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * TODO: * Should implement the gdcmiodvfy here * I need to implement gdcmoverlay here (print info on overlay / img / LUT ...) */ #include "gdcmReader.h" #include "gdcmImageReader.h" #include "gdcmMediaStorage.h" #include "gdcmFile.h" #include "gdcmDataSet.h" #include "gdcmUIDs.h" #include "gdcmGlobal.h" #include "gdcmModules.h" #include "gdcmDefs.h" #include "gdcmOrientation.h" #include "gdcmVersion.h" #include "gdcmMD5.h" #include "gdcmSystem.h" #include "gdcmDirectory.h" #include "gdcmImageHelper.h" #include "gdcmSplitMosaicFilter.h" #include "gdcmImageChangePlanarConfiguration.h" #ifdef GDCM_USE_SYSTEM_POPPLER #include #include #include #include #include #endif // GDCM_USE_SYSTEM_POPPLER #include "puff.h" #include #include /* for printf */ #include #include /* for exit */ #include #include #include #include static int checkmagick(unsigned char *input) { if( input[128+0] == 'D' && input[128+1] == 'I' && input[128+2] == 'C' && input[128+3] == 'M' ) { return 1; } return 0; } static int checkdeflated(const char *name) { int ret; unsigned char *source; unsigned long len, sourcelen, destlen; unsigned long size; unsigned long size1; unsigned char *buf; FILE *in; struct stat s; //const char *name = 0; union { uint32_t tag; uint16_t tags[2]; char bytes[4]; } tag; char vr[3]; uint16_t vl; uint32_t value; //if (argc < 2) return 2; //name = argv[1]; len = 0; if (stat(name, &s)) { fprintf( stderr, "Cannot stat: %s\n", name ); return 1; } if ((s.st_mode & S_IFMT) != S_IFREG) { fprintf( stderr, "not a regular file\n" ); return 1; } size = (unsigned long)(s.st_size); if (size == 0 || (off_t)size != s.st_size) { fprintf( stderr, "size mismatch\n" ); return 1; } in = fopen(name, "r"); if (in == nullptr) { fprintf( stderr, "in is NULL\n" ); return 1; } buf = (unsigned char*)malloc(size); if (buf != nullptr && (size1 = (unsigned long)fread(buf, 1, size, in)) != size) { free(buf); buf = nullptr; fprintf( stderr, "could not fread: %lu bytes != %lu\n", size, size1 ); fprintf( stderr, "feof: %i ferror %i\n", feof(in), ferror(in) ); } fclose(in); len = size; source = buf; if( source == nullptr ) { fprintf( stderr, "source is NULL\n" ); return 1; } sourcelen = len; if( !checkmagick(source) ) { fprintf( stderr, "checkmagick failed\n" ); return 1; } // magick succeed so skip header: source += 128 + 4; sourcelen -= 128 + 4; memcpy(&tag, source, sizeof(tag) ); fprintf( stdout,"tag: %d, %d\n", tag.tags[0], tag.tags[1] ); source += sizeof(tag); sourcelen -= sizeof(tag); vr[2] = 0; memcpy(vr, source, 2); printf( "vr: %s\n", vr); source += 2; sourcelen -= 2; memcpy(&vl, source, sizeof(vl)); printf( "vl: %d\n", vl); source += sizeof(vl); sourcelen -= sizeof(vl); memcpy(&value, source, sizeof(value)); printf( "value: %d\n", value); source += sizeof(value); sourcelen -= sizeof(value); source += value; sourcelen -= value; len = sourcelen; if( len % 2 ) { printf( "len of bit stream is odd: %lu. Continuing anyway\n", len ); } else { printf( "deflate stream has proper length: %lu\n", len ); } ret = puff(nullptr, &destlen, source, &sourcelen); if (ret) fprintf(stdout,"puff() failed with return code %d\n", ret); else { fprintf(stdout,"puff() succeeded uncompressing %lu bytes\n", destlen); if (sourcelen < len) printf("%lu compressed bytes unused\n", len - sourcelen); } free(buf); return ret; } #ifdef GDCM_USE_SYSTEM_POPPLER static std::string getInfoDate(Dict *infoDict, const char *key) { Object obj; const char *s; int year, mon, day, hour, min, sec, n; struct tm tmStruct; //char buf[256]; std::string out; #ifdef LIBPOPPLER_NEW_OBJECT_API if ((obj = infoDict->lookup(const_cast(key))).isString()) #else if (infoDict->lookup((char*)key, &obj)->isString()) #endif { const GooString* gs = obj.getString(); #ifdef LIBPOPPLER_GOOSTRING_HAS_GETCSTRING s = gs->getCString(); #else s = gs->c_str(); #endif if (s[0] == 'D' && s[1] == ':') { s += 2; } if ((n = sscanf(s, "%4d%2d%2d%2d%2d%2d", &year, &mon, &day, &hour, &min, &sec)) >= 1) { switch (n) { case 1: mon = 1; /* fall through */ case 2: day = 1; /* fall through */ case 3: hour = 0; /* fall through */ case 4: min = 0; /* fall through */ case 5: sec = 0; /* fall through */ } tmStruct.tm_year = year - 1900; tmStruct.tm_mon = mon - 1; tmStruct.tm_mday = day; tmStruct.tm_hour = hour; tmStruct.tm_min = min; tmStruct.tm_sec = sec; tmStruct.tm_wday = -1; tmStruct.tm_yday = -1; tmStruct.tm_isdst = -1; /* // compute the tm_wday and tm_yday fields if (mktime(&tmStruct) != (time_t)-1 && strftime(buf, sizeof(buf), "%c", &tmStruct)) { fputs(buf, stdout); } else { fputs(s, stdout); } } else { fputs(s, stdout); */ } //fputc('\n', stdout); char date[22]; time_t t = mktime(&tmStruct); if( t != -1 ) { if( gdcm::System::FormatDateTime(date, t) ) out = date; } } #ifndef LIBPOPPLER_NEW_OBJECT_API obj.free(); #endif return out; } #ifdef LIBPOPPLER_UNICODEMAP_HAS_CONSTMAPUNICODE static std::string getInfoString(Dict *infoDict, const char *key, const UnicodeMap *uMap) #else static std::string getInfoString(Dict *infoDict, const char *key, UnicodeMap *uMap) #endif { Object obj; #ifdef LIBPOPPLER_GOOSTRING_HAS_CONSTGETCHAR const GooString *s1; #else GooString *s1; #endif bool isUnicode; Unicode u; char buf[8]; int i, n; std::string out; #ifdef LIBPOPPLER_NEW_OBJECT_API if ((obj = infoDict->lookup(const_cast(key))).isString()) #else if (infoDict->lookup((char*)key, &obj)->isString()) #endif { s1 = obj.getString(); if ((s1->getChar(0) & 0xff) == 0xfe && (s1->getChar(1) & 0xff) == 0xff) { isUnicode = true; i = 2; } else { isUnicode = false; i = 0; } while (i < obj.getString()->getLength()) { if (isUnicode) { u = ((s1->getChar(i) & 0xff) << 8) | (s1->getChar(i+1) & 0xff); i += 2; } else { u = pdfDocEncoding[s1->getChar(i) & 0xff]; ++i; } n = uMap->mapUnicode(u, buf, sizeof(buf)); //fwrite(buf,1,n,stdout); out.append( std::string(buf, n) ); } } #ifndef LIBPOPPLER_NEW_OBJECT_API obj.free(); #endif return out; } #endif static void PrintVersion() { std::cout << "gdcminfo: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; } static void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcminfo [OPTION]... FILE..." << std::endl; std::cout << "display meta info about the input DICOM file" << std::endl; std::cout << "Parameter:" << std::endl; std::cout << " -i --input DICOM filename or directory" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -r --recursive recursive." << std::endl; std::cout << " -d --check-deflated check if file is proper deflated syntax." << std::endl; std::cout << " --resources-path Resources path." << std::endl; std::cout << " --md5sum Compute md5sum of Pixel Data attribute value." << std::endl; std::cout << " --check-compression check the encapsulated stream compression (lossless/lossy)." << std::endl; // the following options would require an advanced MediaStorage::SetFromFile ... sigh //std::cout << " --media-storage-uid return media storage uid only." << std::endl; //std::cout << " --media-storage-name return media storage name only (when possible)." << std::endl; // std::cout << " -b --check-big-endian check if file is ." << std::endl; std::cout << " --force-rescale force rescale." << std::endl; std::cout << " --force-spacing force spacing." << std::endl; std::cout << " --mosaic dump image information of MOSAIC." << std::endl; std::cout << "General Options:" << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " -v --version print version." << std::endl; std::cout << "Env var:" << std::endl; std::cout << " GDCM_RESOURCES_PATH path pointing to resources files (Part3.xml, ...)" << std::endl; } int deflated = 0; // check deflated int checkcompression = 0; int md5sum = 0; int mosaic = 0; static int ProcessOneFile( std::string const & filename, gdcm::Defs const & defs ) { (void)defs; if( deflated ) { return checkdeflated(filename.c_str()); } //const char *filename = argv[1]; //std::cout << "filename: " << filename << std::endl; gdcm::Reader reader0; reader0.SetFileName( filename.c_str() ); if( !reader0.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::File &file = reader0.GetFile(); gdcm::MediaStorage ms; ms.SetFromFile(file); /* * Until gdcm::MediaStorage is fixed only *compile* time constant will be handled * see -> http://chuckhahm.com/Ischem/Zurich/XX_0134 * which make gdcm::UIDs useless :( */ if( ms.IsUndefined() ) { std::cerr << "Unknown MediaStorage" << std::endl; return 1; } gdcm::UIDs uid; uid.SetFromUID( ms.GetString() ); std::cout << "MediaStorage is " << ms << " [" << uid.GetName() << "]" << std::endl; const gdcm::TransferSyntax &ts = file.GetHeader().GetDataSetTransferSyntax(); uid.SetFromUID( ts.GetString() ); std::cout << "TransferSyntax is " << ts << " [" << uid.GetName() << "]" << std::endl; if( gdcm::MediaStorage::IsImage( ms ) ) { gdcm::ImageReader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Could not read image from: " << filename << std::endl; return 1; } gdcm::SplitMosaicFilter filter; const gdcm::Image *pimage = nullptr; const gdcm::Image &image = reader.GetImage(); if( mosaic ) { filter.SetImage( image ); filter.SetFile( reader.GetFile() ); if( !filter.Split() ) { std::cerr << "Could not split mosaic : " << filename << std::endl; return 1; } pimage = &filter.GetImage(); } else { pimage = ℑ } const double *dircos = pimage->GetDirectionCosines(); gdcm::Orientation::OrientationType type = gdcm::Orientation::GetType(dircos); const char *label = gdcm::Orientation::GetLabel( type ); pimage->Print( std::cout ); std::cout << "Orientation Label: " << label << std::endl; if( checkcompression ) { bool lossy = pimage->IsLossy(); std::cout << "Encapsulated Stream was found to be: " << (lossy ? "lossy" : "lossless") << std::endl; } if( md5sum ) { int ret = 0; char *buffer = new char[ pimage->GetBufferLength() ]; gdcm::ImageChangePlanarConfiguration icpc; icpc.SetPlanarConfiguration( 0 ); icpc.SetInput( *pimage ); bool b = icpc.Change(); if( !b ) { std::cerr << "Could not change the Planar Configuration: " << filename << std::endl; return 1; } pimage = &icpc.GetOutput(); if( pimage->GetBuffer( buffer ) ) { char digest[33] = {}; gdcm::MD5::Compute( buffer, pimage->GetBufferLength(), digest ); std::cout << "md5sum: " << digest << std::endl; } else { std::cerr << "Problem decompressing file: " << filename << std::endl; ret = 1; } delete[] buffer; return ret; } } else if ( ms == gdcm::MediaStorage::EncapsulatedPDFStorage ) { #ifdef GDCM_USE_SYSTEM_POPPLER const gdcm::DataSet &ds = file.GetDataSet(); const gdcm::DataElement& de = ds.GetDataElement( gdcm::Tag(0x42,0x11) ); const gdcm::ByteValue* bv = de.GetByteValue(); const char *p = bv->GetPointer(); (void)p; Object appearDict; //appearDict.initDict(xref); //appearDict.dictAdd(copyString("Length"), // obj1.initInt(appearBuf->getLength())); //appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form")); //obj1.initArray(xref); //obj1.arrayAdd(obj2.initReal(0)); //obj1.arrayAdd(obj2.initReal(0)); //obj1.arrayAdd(obj2.initReal(xMax - xMin)); //obj1.arrayAdd(obj2.initReal(yMax - yMin)); //appearDict.dictAdd(copyString("BBox"), &obj1); MemStream *appearStream; appearStream = new MemStream(const_cast(bv->GetPointer()), 0, #ifdef LIBPOPPLER_NEW_OBJECT_API bv->GetLength(), std::move(appearDict)); #else bv->GetLength(), &appearDict); #endif GooString *ownerPW, *userPW; ownerPW = NULL; userPW = NULL; PDFDoc *doc; doc = new PDFDoc(appearStream, ownerPW, userPW); std::string title; std::string subject; std::string keywords; std::string author; std::string creator; std::string producer; std::string creationdate; std::string moddate; #ifdef LIBPOPPLER_UNICODEMAP_HAS_CONSTMAPUNICODE const UnicodeMap *uMap; #else UnicodeMap *uMap; #endif #ifdef LIBPOPPLER_GLOBALPARAMS_CSTOR_HAS_PARAM globalParams = new GlobalParams(0); #else #ifdef LIBPOPPLER_GLOBALPARAMS_HAS_RESET globalParams.reset(new GlobalParams()); #else globalParams = new GlobalParams(); #endif #endif uMap = globalParams->getTextEncoding(); Object info; if (doc->isOk()) { #ifdef LIBPOPPLER_NEW_OBJECT_API info = doc->getDocInfo(); #else doc->getDocInfo(&info); #endif if (info.isDict()) { title = getInfoString(info.getDict(), "Title", uMap); subject = getInfoString(info.getDict(), "Subject", uMap); keywords = getInfoString(info.getDict(), "Keywords", uMap); author = getInfoString(info.getDict(), "Author", uMap); creator = getInfoString(info.getDict(), "Creator", uMap); producer = getInfoString(info.getDict(), "Producer", uMap); creationdate = getInfoDate( info.getDict(), "CreationDate" ); moddate = getInfoDate( info.getDict(), "ModDate" ); #ifndef LIBPOPPLER_NEW_OBJECT_API info.free(); #endif } #ifdef LIBPOPPLER_CATALOG_HAS_STRUCTTREEROOT const char *tagged = doc->getStructTreeRoot() ? "yes" : "no"; #else const char *tagged = doc->getStructTreeRoot()->isDict() ? "yes" : "no"; #endif int pages = doc->getNumPages(); const char *encrypted = doc->isEncrypted() ? "yes" : "no"; // printf("yes (print:%s copy:%s change:%s addNotes:%s)\n", // doc->okToPrint(true) ? "yes" : "no", // doc->okToCopy(true) ? "yes" : "no", // doc->okToChange(true) ? "yes" : "no", // doc->okToAddNotes(true) ? "yes" : "no"); // print linearization info const char *optimized = doc->isLinearized() ? "yes" : "no"; // print PDF version #ifdef LIBPOPPLER_PDFDOC_HAS_PDFVERSION float pdfversion = doc->getPDFVersion(); #else const double pdfversion = doc->getPDFMajorVersion() + 0.1 * doc->getPDFMinorVersion(); #endif // print page count printf("Pages: %d\n", doc->getNumPages()); std::cout << "PDF Info:" << std::endl; std::cout << " Title: " << title << std::endl; std::cout << " Subject: " << subject << std::endl; std::cout << " Keywords: " << keywords << std::endl; std::cout << " Author: " << author << std::endl; std::cout << " Creator: " << creator << std::endl; std::cout << " Producer: " << producer << std::endl; std::cout << " CreationDate: " << creationdate << std::endl; std::cout << " ModDate: " << moddate << std::endl; std::cout << " Tagged: " << tagged << std::endl; std::cout << " Pages: " << pages << std::endl; std::cout << " Encrypted: " << encrypted << std::endl; //std::cout << "Page size: " << subject << std::endl; std::cout << " File size: " << bv->GetLength() << std::endl; std::cout << " Optimized: " << optimized << std::endl; std::cout << " PDF version: " << pdfversion << std::endl; } else { std::cout << "Problem reading Encapsulated PDF " << std::endl; } #else // GDCM_USE_SYSTEM_POPPLER std::cout << " Encapsulated PDF File" << std::endl; #endif // GDCM_USE_SYSTEM_POPPLER } // Do the IOD verification ! //bool v = defs.Verify( file ); //std::cerr << "IOD Verification: " << (v ? "succeed" : "failed") << std::endl; return 0; } int main(int argc, char *argv[]) { int c; std::string filename; std::string xmlpath; int forcerescale = 0; int forcespacing = 0; int resourcespath = 0; int verbose = 0; int warning = 0; int help = 0; int recursive = 0; int version = 0; int debug = 0; int error = 0; while (true) { int option_index = 0; static struct option long_options[] = { {"input", 1, nullptr, 0}, {"recursive", 0, &recursive, 1}, {"check-deflated", 0, &deflated, 1}, {"resources-path", 0, &resourcespath, 1}, {"md5sum", 0, &md5sum, 1}, {"check-compression", 0, &checkcompression, 1}, {"force-rescale", 0, &forcerescale, 1}, {"force-spacing", 0, &forcespacing, 1}, {"mosaic", 0, &mosaic, 1}, {"verbose", 0, &verbose, 1}, {"warning", 0, &warning, 1}, {"debug", 0, &debug, 1}, {"error", 0, &error, 1}, {"help", 0, &help, 1}, {"version", 0, &version, 1}, {nullptr, 0, nullptr, 0} // required }; static const char short_options[] = "i:rdVWDEhv"; c = getopt_long (argc, argv, short_options, long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: case '-': { const char *s = long_options[option_index].name; (void)s; //printf ("option %s", s); if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); assert( filename.empty() ); filename = optarg; } else if( option_index == 3 ) /* resources-path */ { assert( strcmp(s, "resources-path") == 0 ); assert( xmlpath.empty() ); xmlpath = optarg; } //printf (" with arg %s", optarg); } //printf ("\n"); } break; case 'i': //printf ("option i with value '%s'\n", optarg); assert( filename.empty() ); filename = optarg; break; case 'r': recursive = 1; break; case 'd': deflated = 1; break; case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { //printf ("non-option ARGV-elements: %d", optind ); //while (optind < argc) // { // printf ("%s\n", argv[optind++]); // } //printf ("\n"); // Ok there is only one arg, easy, it's the filename: int v = argc - optind; if( v == 1 ) { filename = argv[optind]; } } if( version ) { //std::cout << "version" << std::endl; PrintVersion(); return 0; } if( help ) { //std::cout << "help" << std::endl; PrintHelp(); return 0; } gdcm::ImageHelper::SetForceRescaleInterceptSlope(forcerescale ? true : false); gdcm::ImageHelper::SetForcePixelSpacing(forcespacing ? true : false); if( filename.empty() ) { //std::cerr << "Need input file (-i)\n"; PrintHelp(); return 1; } // Debug is a little too verbose gdcm::Trace::SetDebug( debug != 0); gdcm::Trace::SetWarning( warning != 0); gdcm::Trace::SetError( error != 0); // when verbose is true, make sure warning+error are turned on: if( verbose ) { gdcm::Trace::SetWarning( verbose != 0); gdcm::Trace::SetError( verbose != 0); } if( !gdcm::System::FileExists(filename.c_str()) ) { return 1; } gdcm::Global& g = gdcm::Global::GetInstance(); // First thing we need to locate the XML dict // did the user requested to look XML file in a particular directory ? if( !resourcespath ) { const char *xmlpathenv = getenv("GDCM_RESOURCES_PATH"); if( xmlpathenv ) { // Make sure to look for XML dict in user explicitly specified dir first: xmlpath = xmlpathenv; resourcespath = 1; } } if( resourcespath ) { // xmlpath is set either by the cmd line option or the env var if( !g.Prepend( xmlpath.c_str() ) ) { std::cerr << "specified Resources Path is not valid: " << xmlpath << std::endl; return 1; } } // All set, then load the XML files: if( !g.LoadResourcesFiles() ) { std::cerr << "Could not load XML file from specified path" << std::endl; return 1; } const gdcm::Defs &defs = g.GetDefs(); int res = 0; if( gdcm::System::FileIsDirectory(filename.c_str()) ) { gdcm::Directory d; d.Load(filename, recursive!= 0); gdcm::Directory::FilenamesType const &filenames = d.GetFilenames(); for( gdcm::Directory::FilenamesType::const_iterator it = filenames.begin(); it != filenames.end(); ++it ) { std::cout << "filename: " << *it << std::endl; res += ProcessOneFile(*it, defs); } } else { res += ProcessOneFile( filename, defs ); } return res; } GDCM-3.0.10/Applications/Cxx/gdcmkey.cxx000066400000000000000000000021751412732066400176560ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // DCKEY(1) DICOM PS3 - Extract attribute values DCKEY(1) // // NAME // dckey - ACR/NEMA DICOM PS3 ... Extract attribute values // // SYNOPSIS // dckey [ -v|verbose ] [ -describe ] [ -key|k attributename // ] // // DESCRIPTION // dckey reads the named dicom input file and displays the // values of the selected attributes. // // Binary attributes are written in hexadecimal with a pre- // ceding "0x". Numeric string attributes are written in dec- // imal. // int main(int argc, char *argv[]) { return 0; } GDCM-3.0.10/Applications/Cxx/gdcmoverlay.cxx000066400000000000000000000106601412732066400205450ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmImageReader.h" #include "gdcmFileMetaInformation.h" #include "gdcmDataSet.h" #include "gdcmPrinter.h" #include "gdcmDictPrinter.h" #include "gdcmValidate.h" #include "gdcmWriter.h" #include "gdcmDumper.h" #include "gdcmSystem.h" #include "gdcmDirectory.h" #include "gdcmOverlay.h" #include #include #include /* for printf */ #include /* for exit */ #include #include template int DoOperation(const std::string & filename) { gdcm::ImageReader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } // Image part: const gdcm::Image& img = reader.GetImage(); img.Print( std::cout ); // Overlay part: unsigned int n = reader.GetImage().GetNumberOfOverlays(); std::cout << "Num of Overlays: " << n << std::endl; for(unsigned int i = 0; i < n; ++i ) { const gdcm::Overlay& o = reader.GetImage().GetOverlay(i); o.Print( std::cout ); } return 0; } int main (int argc, char *argv[]) { int c; //int digit_optind = 0; std::string filename; bool printdict = false; bool verbose = false; while (1) { //int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"input", 1, 0, 0}, {"output", 1, 0, 0}, {"dict", 1, 0, 0}, {"verbose", 1, 0, 0}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "i:o:dv", long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: { const char *s = long_options[option_index].name; printf ("option %s", s); if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); assert( filename.empty() ); filename = optarg; } printf (" with arg %s", optarg); } printf ("\n"); } break; case 'i': //printf ("option i with value '%s'\n", optarg); assert( filename.empty() ); filename = optarg; break; case 'o': printf ("option o with value '%s'\n", optarg); break; case 'd': //printf ("option d with value '%s'\n", optarg); printdict = true; break; case 'v': //printf ("option d with value '%s'\n", optarg); verbose = true; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) { printf ("%s ", argv[optind++]); } printf ("\n"); } if( filename.empty() ) { std::cerr << "Need input file (-i)\n"; return 1; } // else int res = 0; if( gdcm::System::FileIsDirectory( filename.c_str() ) ) { gdcm::Directory d; d.Load(filename); gdcm::Directory::FilenamesType const &filenames = d.GetFilenames(); for( gdcm::Directory::FilenamesType::const_iterator it = filenames.begin(); it != filenames.end(); ++it ) { if( printdict ) { res += DoOperation(*it); } else { res += DoOperation(*it); } if( verbose ) std::cerr << *it << std::endl; } if( verbose ) std::cerr << "Total: " << filenames.size() << " files were processed" << std::endl; } else { assert( gdcm::System::FileExists(filename.c_str()) ); if( printdict ) { res += DoOperation(filename); } else { res += DoOperation(filename); } // ... if ( verbose ) std::cerr << "Filename: " << filename << std::endl; } return res; } GDCM-3.0.10/Applications/Cxx/gdcmpap3.cxx000066400000000000000000000431671412732066400177370ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Command line tool to deal with legacy PAPYRUS 3.0 file * The command line tool can be compiled in two flavour: * * 1. without papyrus 3.0 (more portable) * 2. with papyrus 3.0 * * The (2) is only required when dealing with invalid JPEG Lossless compressed * PAPYRUS 3.0 files */ #include "gdcmReader.h" #include "gdcmDirectionCosines.h" #include "gdcmUIDGenerator.h" #include "gdcmVersion.h" #include "gdcmWriter.h" #include "gdcmAttribute.h" #include "gdcmTrace.h" #include "gdcmImageHelper.h" #include "gdcmSequenceOfItems.h" #include #ifdef GDCM_USE_SYSTEM_PAPYRUS3 extern "C" { #include } #endif static void PrintVersion() { std::cout << "gdcmpap3: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; } static void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcmpap3 [OPTION] input.pa3 output.dcm" << std::endl; std::cout << "Convert a PAPYRUS 3.0 file into another DICOM file.\n"; std::cout << "Parameter (required):" << std::endl; std::cout << " -i --input PAPYRUS 3.0 filename" << std::endl; std::cout << " -o --output DICOM filename" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -S --split Split single PAPYRUS 3.0 file into multiples DICOM files." << std::endl; std::cout << " --decomp-pap3 Use PAPYRUS 3.0 for decompressing (can be combined with --split)." << std::endl; std::cout << " --check-iop Check that the Image Orientation (Patient) Attribute is ok (see --split)." << std::endl; std::cout << " --root-uid Specify Root UID." << std::endl; std::cout << "General Options:" << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " -v --version print version." << std::endl; std::cout << "Env var:" << std::endl; std::cout << " GDCM_ROOT_UID Root UID" << std::endl; } static bool InitPapyrus3( const char *filename, int & outfileNb) { outfileNb = -1; #ifdef GDCM_USE_SYSTEM_PAPYRUS3 /* initialisation of the Papyrus toolkit v3.6 */ Papy3Init(); /* open the pap3 file */ PapyShort fileNb = Papy3FileOpen ((char*)filename, (PAPY_FILE) 0, TRUE, 0); if( fileNb < 0 ) { PAPY3PRINTERRMSG(); return false; } outfileNb = fileNb; return true; #else (void)filename; (void)outfileNb; std::cerr << "No PAPYRUS 3.0 library found" << std::endl; return false; #endif } static bool DecompressPapyrus3( int pap3handle, int itemnum, gdcm::TransferSyntax const & ts, gdcm::File & file ) { #ifdef GDCM_USE_SYSTEM_PAPYRUS3 PapyShort fileNb = (PapyShort)pap3handle; PapyShort imageNb = (PapyShort)(itemnum + 1); if( ts == gdcm::TransferSyntax::JPEGLosslessProcess14_1 ) { SElement *group; PapyUShort *theImage; std::vector dims = gdcm::ImageHelper::GetDimensionsValue(file); gdcm::PixelFormat pf = gdcm::ImageHelper::GetPixelFormatValue(file); gdcm::DataSet & nested = file.GetDataSet(); /* position the file pointer to the beginning of the data set */ PapyShort err = Papy3GotoNumber (fileNb, (PapyShort)imageNb, DataSetID); gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0,0x0010) ); /* then goto group 0x7FE0 */ if ((err = Papy3GotoGroupNb (fileNb, 0x7FE0)) == 0) { /* read group 0x7FE0 from the file */ if ((err = Papy3GroupRead (fileNb, &group)) > 0) { /* PIXEL DATA */ theImage = (PapyUShort *)Papy3GetPixelData (fileNb, imageNb, group, ImagePixel); //assert( dims[0] == 512 ); //assert( dims[1] == 512 ); //assert( pf.GetPixelSize() == 2 ); const size_t imglen = dims[0] * dims[1] * pf.GetPixelSize(); pixeldata.SetByteValue( (char*)theImage, (uint32_t)imglen ); /* free group 7FE0 */ err = Papy3GroupFree (&group, TRUE); } /* endif ...group 7FE0 read */ else { PAPY3PRINTERRMSG (); } } /* endif ...group 7FE0 found */ else { PAPY3PRINTERRMSG (); } nested.Replace( pixeldata ); } else { std::cerr << "TransferSyntax: " << ts << " is not handled at this point" << std::endl; return false; } return true; #else (void)pap3handle; (void)itemnum; (void)ts; (void)file; std::cerr << "No PAPYRUS 3.0 library found" << std::endl; return false; #endif } static bool CleanupPapyrus3( int pap3handle ) { #ifdef GDCM_USE_SYSTEM_PAPYRUS3 PapyShort fileNb = (PapyShort)pap3handle; /* close and free the file and the associated allocated memory */ Papy3FileClose (fileNb, TRUE); /* free the allocated global value in the toolkit */ Papy3FreeDataSetModules (); return true; #else (void)pap3handle; return false; #endif } int main(int argc, char *argv[]) { int c; std::string filename; std::string outfilename; std::string root; int rootuid = 0; int split = 0; int decomp_pap3 = 0; int check_iop = 0; int verbose = 0; int warning = 0; int debug = 0; int error = 0; int help = 0; int version = 0; while (true) { int option_index = 0; static struct option long_options[] = { {"input", 1, nullptr, 0}, {"output", 1, nullptr, 0}, {"root-uid", 1, &rootuid, 1}, // specific Root (not GDCM) {"split", 0, &split, 1}, {"decomp-pap3", 0, &decomp_pap3, 1}, {"check-iop", 0, &check_iop, 1}, // General options ! {"verbose", 0, &verbose, 1}, {"warning", 0, &warning, 1}, {"debug", 0, &debug, 1}, {"error", 0, &error, 1}, {"help", 0, &help, 1}, {"version", 0, &version, 1}, {nullptr, 0, nullptr, 0} }; c = getopt_long (argc, argv, "i:o:S:VWDEhv", long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: { const char *s = long_options[option_index].name; (void)s; //printf ("option %s", s); if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); assert( filename.empty() ); filename = optarg; } else if( option_index == 1 ) /* output */ { assert( strcmp(s, "output") == 0 ); assert( outfilename.empty() ); outfilename = optarg; } else if( option_index == 2 ) /* root-uid */ { assert( strcmp(s, "root-uid") == 0 ); root = optarg; } //printf (" with arg %s, index = %d", optarg, option_index); } //printf ("\n"); } break; case 'i': //printf ("option i with value '%s'\n", optarg); assert( filename.empty() ); filename = optarg; break; case 'o': //printf ("option o with value '%s'\n", optarg); assert( outfilename.empty() ); outfilename = optarg; break; // case 'S': split = 1; break; // General option case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } // For now only support one input / one output if (optind < argc) { //printf ("non-option ARGV-elements: "); std::vector files; while (optind < argc) { //printf ("%s\n", argv[optind++]); files.emplace_back(argv[optind++] ); } //printf ("\n"); if( files.size() == 2 && filename.empty() && outfilename.empty() ) { filename = files[0]; outfilename = files[1]; } else { PrintHelp(); return 1; } } if( version ) { //std::cout << "version" << std::endl; PrintVersion(); return 0; } if( help ) { //std::cout << "help" << std::endl; PrintHelp(); return 0; } if( filename.empty() ) { //std::cerr << "Need input file (-i)\n"; PrintHelp(); return 1; } if( outfilename.empty() ) { //std::cerr << "Need output file (-o)\n"; PrintHelp(); return 1; } // Debug is a little too verbose gdcm::Trace::SetDebug( (debug > 0 ? true : false)); gdcm::Trace::SetWarning( (warning > 0 ? true : false)); gdcm::Trace::SetError( (error > 0 ? true : false)); // when verbose is true, make sure warning+error are turned on: if( verbose ) { gdcm::Trace::SetWarning( (verbose > 0 ? true : false) ); gdcm::Trace::SetError( (verbose > 0 ? true : false) ); } gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( "gdcmpap3" ); if( !rootuid ) { // only read the env var is no explicit cmd line option // maybe there is an env var defined... let's check const char *rootuid_env = getenv("GDCM_ROOT_UID"); if( rootuid_env ) { rootuid = 1; root = rootuid_env; } } if( rootuid ) { // root is set either by the cmd line option or the env var if( !gdcm::UIDGenerator::IsValid( root.c_str() ) ) { std::cerr << "specified Root UID is not valid: " << root << std::endl; return 1; } gdcm::UIDGenerator::SetRoot( root.c_str() ); } gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } gdcm::File & file = reader.GetFile(); gdcm::FileMetaInformation & header = file.GetHeader(); gdcm::DataSet & ds = file.GetDataSet(); gdcm::MediaStorage ms = header.GetMediaStorage(); (void)ms; const gdcm::TransferSyntax & ts = header.GetDataSetTransferSyntax(); //std::cout << ts << std::endl; std::string msstr = header.GetMediaStorageAsString(); //std::cout << msstr << std::endl; int pap3handle; if( decomp_pap3 ) { if( !InitPapyrus3( filename.c_str(), pap3handle ) ) { std::cerr << "Problem during init of PAPYRUS 3.0. File was: " << filename << std::endl; return 1; } } gdcm::PrivateTag pt(0x0041,0x50,"PAPYRUS 3.0"); const gdcm::DataElement &depap = ds.GetDataElement( pt ); gdcm::SmartPointer sq = depap.GetValueAsSQ(); if( !split ) { gdcm::Writer w; w.CheckFileMetaInformationOff(); w.SetFileName( outfilename.c_str() ); w.SetFile( reader.GetFile() ); if( decomp_pap3 ) { gdcm::TransferSyntax outts = ts; for( gdcm::SequenceOfItems::SizeType i = 0; i < sq->GetNumberOfItems(); ++i ) { gdcm::Item & it = sq->GetItem( i + 1 ); gdcm::DataSet & nested = it.GetNestedDataSet(); gdcm::File f; f.SetDataSet( nested ); if( !DecompressPapyrus3( pap3handle, (int)i, ts, f ) ) { std::cerr << "Could not decompress frame #" << i << " from file: " << filename << std::endl; return 1; } const gdcm::DataElement & pixeldata = f.GetDataSet().GetDataElement( gdcm::Tag(0x7fe0,0x0010) ); nested.Replace( pixeldata ); } // make sq as undefined length (avoid length computation): gdcm::DataElement de_dup = depap; de_dup.SetValue( *sq ); de_dup.SetVLToUndefined(); ds.Replace( de_dup ); gdcm::FileMetaInformation & h = w.GetFile().GetHeader(); // pap3 returns image as decompressed: outts = gdcm::TransferSyntax::ExplicitVRLittleEndian; gdcm::Attribute<0x0002, 0x0010> TransferSyntaxUID; const char *tsstr = gdcm::TransferSyntax::GetTSString( outts ); TransferSyntaxUID.SetValue( tsstr ); h.Replace( TransferSyntaxUID.GetAsDataElement() ); gdcm::Attribute<0x0002, 0x0000> filemetagrouplength; h.Remove( filemetagrouplength.GetTag() ); // important unsigned int glen = h.GetLength(); filemetagrouplength.SetValue( glen ); h.Insert( filemetagrouplength.GetAsDataElement() ); } if( !w.Write() ) { std::cerr << "Could not write output file: " << outfilename << std::endl; return 1; } } else { if( !gdcm::System::FileIsDirectory(outfilename.c_str()) ) { std::cerr << "Output is not a directory: " << outfilename << std::endl; return 1; } #if 1 gdcm::UIDGenerator uid; const std::string seriesstr = uid.Generate(); for( gdcm::SequenceOfItems::SizeType i = 0; i < sq->GetNumberOfItems(); ++i ) { gdcm::Item & it = sq->GetItem( i + 1 ); gdcm::DataSet & nested = it.GetNestedDataSet(); std::stringstream ss; ss << outfilename; ss << "/IMG"; ss << std::setw(4) << std::setfill( '0') << i; ss << ".dcm"; gdcm::Writer w; // 1.2.840.10008.1.2.4.70 w.CheckFileMetaInformationOn(); const std::string & outfn = ss.str(); w.SetFileName( outfn.c_str() ); gdcm::TransferSyntax outts; #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( ts == gdcm::TransferSyntax::WeirdPapryus ) { outts = gdcm::TransferSyntax::ImplicitVRLittleEndian; } else #endif { outts = ts; } w.GetFile().SetDataSet( nested ); if( decomp_pap3 ) { if( !DecompressPapyrus3( pap3handle, (int)i, ts, w.GetFile() ) ) { std::cerr << "Could not decompress frame #" << i << " from file: " << filename << std::endl; return 1; } // pap3 returns image as decompressed: outts = gdcm::TransferSyntax::ExplicitVRLittleEndian; } w.GetFile().GetHeader().SetDataSetTransferSyntax( outts ); if( check_iop ) { bool erroriop = false; std::vector iop_orig; iop_orig.resize( 6 ); // gdcm::ImageHelper::GetDirectionCosinesValue( w.GetFile() ); if( !gdcm::ImageHelper::GetDirectionCosinesFromDataSet(w.GetFile().GetDataSet(), iop_orig) ) { erroriop = true; gdcm::DirectionCosines dc( &iop_orig[0] ); assert( !dc.IsValid() ); { gdcm::Attribute<0x0008,0x0008> imagetype; imagetype.Set( w.GetFile().GetDataSet() ); if( imagetype.GetNumberOfValues() > 2 ) { const std::string &str = imagetype.GetValue( 2 ); gdcm::Attribute<0x0020,0x0037> at_axial = {{1,0,0,0,1,0}}; // default value for AXIAL if( str == "AXIAL" ) { w.GetFile().GetDataSet().Replace( at_axial.GetAsDataElement() ); erroriop = false; // error has been corrected } else if( str == "LOCALIZER" ) { static const double fake_axial[] = { 1, 0, 0, 0, 0, 0 }; assert( memcmp( &iop_orig[0], fake_axial, 6 * sizeof( double ) ) == 0 ); (void)fake_axial; w.GetFile().GetDataSet().Replace( at_axial.GetAsDataElement() ); erroriop = false; // error has been corrected } } assert( !erroriop ); // did our heuristic failed ? } } if( erroriop ) { std::cerr << "Error IOP (could not correct) for frame #" << i << " value : (" << iop_orig[0] << "," << iop_orig[1] << "," << iop_orig[2] << "," << iop_orig[3] << "," << iop_orig[4] << "," << iop_orig[5] << ")" << std::endl; return 1; } } #if 0 gdcm::Attribute<0x0008,0x0016> outms; outms.SetValue( "1.2.840.10008.5.1.4.1.1.2" ); nested.Replace( outms.GetAsDataElement() ); gdcm::Attribute<0x028,0x0102> highbits = { 15 }; nested.Replace( highbits.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0030> pixelspacing = { 0.57, 0.57 }; nested.Replace( pixelspacing.GetAsDataElement() ); gdcm::Attribute<0x0020,0x000e> seriesuid; seriesuid.SetValue( seriesstr ); nested.Insert( seriesuid.GetAsDataElement() ); // do not replace if exists gdcm::Attribute<0x0008,0x0018> instanceuid; instanceuid.SetValue( uid.Generate() ); nested.Replace( instanceuid.GetAsDataElement() ); // ??? gdcm::Attribute<0x0020,0x0032> ipp = {{0,0, i * 0.57}}; // default value nested.Replace( ipp.GetAsDataElement() ); gdcm::Attribute<0x0020,0x0037> iop = {{1,0,0,0,1,0}}; // default value nested.Replace( iop.GetAsDataElement() ); #endif //std::cout << w.GetFile().GetDataSet( ) << std::endl; if( !w.Write() ) { std::cerr << "Problem writing output file: " << outfn << std::endl; return 1; } } #endif } if( decomp_pap3 ) { if( !CleanupPapyrus3( pap3handle ) ) { std::cerr << "Problem during PAPYRUS 3.0 cleanup" << std::endl; return 1; } } return 0; } GDCM-3.0.10/Applications/Cxx/gdcmpdf.cxx000066400000000000000000000452241412732066400176410ustar00rootroot00000000000000/*========================================================================= 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 "gdcmVersion.h" #include "gdcmUIDGenerator.h" #include "gdcmWriter.h" #include "gdcmAttribute.h" #include "gdcmSystem.h" #ifdef GDCM_USE_SYSTEM_POPPLER #include #include #include #include #include #endif #include #include /* for printf */ #include /* for exit */ #include #include static std::string getInfoDate(Dict *infoDict, const char *key) { Object obj; const char *s; int year, mon, day, hour, min, sec, n; struct tm tmStruct; //char buf[256]; std::string out; #ifdef LIBPOPPLER_NEW_OBJECT_API if ((obj = infoDict->lookup(const_cast(key))).isString()) #else if (infoDict->lookup((char*)key, &obj)->isString()) #endif { const GooString* gs = obj.getString(); #ifdef LIBPOPPLER_GOOSTRING_HAS_GETCSTRING s = gs->getCString(); #else s = gs->c_str(); #endif if (s[0] == 'D' && s[1] == ':') { s += 2; } if ((n = sscanf(s, "%4d%2d%2d%2d%2d%2d", &year, &mon, &day, &hour, &min, &sec)) >= 1) { switch (n) { case 1: mon = 1; /* fall through */ case 2: day = 1; /* fall through */ case 3: hour = 0; /* fall through */ case 4: min = 0; /* fall through */ case 5: sec = 0; /* fall through */ } tmStruct.tm_year = year - 1900; tmStruct.tm_mon = mon - 1; tmStruct.tm_mday = day; tmStruct.tm_hour = hour; tmStruct.tm_min = min; tmStruct.tm_sec = sec; tmStruct.tm_wday = -1; tmStruct.tm_yday = -1; tmStruct.tm_isdst = -1; /* // compute the tm_wday and tm_yday fields if (mktime(&tmStruct) != (time_t)-1 && strftime(buf, sizeof(buf), "%c", &tmStruct)) { fputs(buf, stdout); } else { fputs(s, stdout); } } else { fputs(s, stdout); */ } //fputc('\n', stdout); char date[22]; time_t t = mktime(&tmStruct); if( t != -1 ) { if( gdcm::System::FormatDateTime(date, t) ) out = date; } } #ifndef LIBPOPPLER_NEW_OBJECT_API obj.free(); #endif return out; } #ifdef LIBPOPPLER_UNICODEMAP_HAS_CONSTMAPUNICODE static std::string getInfoString(Dict *infoDict, const char *key, const UnicodeMap *uMap, bool & unicode) #else static std::string getInfoString(Dict *infoDict, const char *key, UnicodeMap *uMap, bool & unicode) #endif { Object obj; #ifdef LIBPOPPLER_GOOSTRING_HAS_CONSTGETCHAR const GooString *s1; #else GooString *s1; #endif bool isUnicode = false; Unicode u; char buf[8]; int i, n; std::string out; #ifdef LIBPOPPLER_NEW_OBJECT_API if ((obj = infoDict->lookup(const_cast(key))).isString()) #else if (infoDict->lookup((char*)key, &obj)->isString()) #endif { s1 = obj.getString(); if ((s1->getChar(0) & 0xff) == 0xfe && (s1->getChar(1) & 0xff) == 0xff) { isUnicode = true; i = 2; } else { isUnicode = false; i = 0; } while (i < obj.getString()->getLength()) { if (isUnicode) { u = ((s1->getChar(i) & 0xff) << 8) | (s1->getChar(i+1) & 0xff); i += 2; } else { u = pdfDocEncoding[s1->getChar(i) & 0xff]; ++i; } n = uMap->mapUnicode(u, buf, sizeof(buf)); //fwrite(buf,1,n,stdout); out.append( std::string(buf, n) ); } } #ifndef LIBPOPPLER_NEW_OBJECT_API obj.free(); #endif unicode = unicode || isUnicode; return out; } static void PrintVersion() { std::cout << "gdcmpdf: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; } static void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcmpdf [OPTION]... FILE..." << std::endl; std::cout << "Convert a PDF file to DICOM/PDF\n"; std::cout << "Parameter (required):" << std::endl; std::cout << " -i --input PDF filename" << std::endl; std::cout << " -o --output DICOM filename" << std::endl; std::cout << "General Options:" << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " -v --version print version." << std::endl; } int main (int argc, char *argv[]) { int c; //int digit_optind = 0; std::string filename; std::string outfilename; int verbose = 0; int warning = 0; int debug = 0; int error = 0; int help = 0; int version = 0; while (1) { //int this_option_optind = optind ? optind : 1; int option_index = 0; /* struct option { const char *name; int has_arg; int *flag; int val; }; */ static struct option long_options[] = { {"input", 1, 0, 0}, {"output", 1, 0, 0}, {"verbose", 0, &verbose, 1}, {"warning", 0, &warning, 1}, {"debug", 0, &debug, 1}, {"error", 0, &error, 1}, {"help", 0, &help, 1}, {"version", 0, &version, 1}, {0, 0, 0, 0} // required }; static const char short_options[] = "i:o:VWDEhv"; c = getopt_long (argc, argv, short_options, long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: case '-': { const char *s = long_options[option_index].name; (void)s; //printf ("option %s", s); if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); assert( filename.empty() ); filename = optarg; } //printf (" with arg %s", optarg); } //printf ("\n"); } break; case 'i': //printf ("option i with value '%s'\n", optarg); assert( filename.empty() ); filename = optarg; break; case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { //printf ("non-option ARGV-elements: %d", optind ); //while (optind < argc) // { // printf ("%s\n", argv[optind++]); // } //printf ("\n"); int v = argc - optind; if( v == 2 ) { filename = argv[optind]; outfilename = argv[optind+1]; } else { PrintHelp(); return 1; } } if( filename.empty() || outfilename.empty() ) { PrintHelp(); return 1; } if( version ) { //std::cout << "version" << std::endl; PrintVersion(); return 0; } if( help ) { //std::cout << "help" << std::endl; PrintHelp(); return 0; } GooString *ownerPW, *userPW; GooString *fileName; PDFDoc *doc; Object info; #ifdef LIBPOPPLER_UNICODEMAP_HAS_CONSTMAPUNICODE const UnicodeMap *uMap; #else UnicodeMap *uMap; #endif ownerPW = NULL; userPW = NULL; #ifdef LIBPOPPLER_GLOBALPARAMS_CSTOR_HAS_PARAM globalParams = new GlobalParams(0); #else #ifdef LIBPOPPLER_GLOBALPARAMS_HAS_RESET globalParams.reset(new GlobalParams()); #else globalParams = new GlobalParams(); #endif #endif uMap = globalParams->getTextEncoding(); //const char *filename = argv[1]; if( !gdcm::System::FileExists(filename.c_str()) ) { return 1; } // get length of file: size_t length = gdcm::System::FileSize(filename.c_str()); // PDF doc is stored in an OB element, check that 32bits length is fine: if( length > gdcm::VL::GetVL32Max() ) { return 1; } //const char *outfilename = argv[2]; fileName = new GooString( filename.c_str() ); //ownerPW = new GooString( "toto" ); Object obj; #ifndef LIBPOPPLER_NEW_OBJECT_API obj.initNull(); #endif doc = new PDFDoc(fileName, ownerPW, userPW); if (doc->isEncrypted()) { std::string password; std::cout << "Enter password:" << std::endl; // http://www.daniweb.com/code/snippet1174.html std::cin >> password; //std::cout << "Enter password:" << password << std::endl; /* #include #include int mygetch(void) { struct termios oldt, newt; int ch; tcgetattr( STDIN_FILENO, &oldt ); newt = oldt; newt.c_lflag &= ~( ICANON | ECHO ); tcsetattr( STDIN_FILENO, TCSANOW, &newt ); ch = getchar(); tcsetattr( STDIN_FILENO, TCSANOW, &oldt ); return ch; http://msdn.microsoft.com/en-us/library/078sfkak(VS.80).aspx } */ ownerPW = new GooString( password.c_str() ); doc = new PDFDoc(fileName, ownerPW, userPW); } std::string title; std::string subject; std::string keywords; std::string author; std::string creator; std::string producer; std::string creationdate; std::string moddate; bool isUnicode = false; if (doc->isOk()) { #ifdef LIBPOPPLER_NEW_OBJECT_API info = doc->getDocInfo(); #else doc->getDocInfo(&info); #endif if (info.isDict()) { title = getInfoString(info.getDict(), "Title", uMap, isUnicode); subject = getInfoString(info.getDict(), "Subject", uMap, isUnicode); keywords = getInfoString(info.getDict(), "Keywords", uMap, isUnicode); author = getInfoString(info.getDict(), "Author", uMap, isUnicode); creator = getInfoString(info.getDict(), "Creator", uMap, isUnicode); producer = getInfoString(info.getDict(), "Producer", uMap, isUnicode); creationdate = getInfoDate( info.getDict(), "CreationDate" ); moddate = getInfoDate( info.getDict(), "ModDate" ); #ifndef LIBPOPPLER_NEW_OBJECT_API info.free(); #endif } } gdcm::Writer writer; gdcm::DataSet &ds = writer.GetFile().GetDataSet(); { gdcm::DataElement de( gdcm::Tag(0x42,0x11) ); de.SetVR( gdcm::VR::OB ); std::ifstream is; is.open (filename.c_str(), std::ios::binary ); char *buffer = new char [length]; // read data as a block: is.read (buffer,length); is.close(); de.SetByteValue( buffer, (uint32_t)length ); delete[] buffer; gdcm::FileMetaInformation &fmi = writer.GetFile().GetHeader(); gdcm::TransferSyntax ts = gdcm::TransferSyntax::ExplicitVRLittleEndian; fmi.SetDataSetTransferSyntax( ts ); ds.Insert( de ); } { char date[22]; const size_t datelen = 8; int res = gdcm::System::GetCurrentDateTime(date); if( !res ) return 1; { gdcm::DataElement de( gdcm::Tag(0x0008,0x0020) ); // Do not copy the whole cstring: de.SetByteValue( date, datelen ); de.SetVR( gdcm::Attribute<0x0008,0x0020>::GetVR() ); ds.Insert( de ); } // StudyTime const size_t timelen = 6 + 1 + 6; // time + milliseconds (void)timelen; { gdcm::Attribute<0x8,0x30> at; at.SetValue( date+datelen ); ds.Insert( at.GetAsDataElement() ); //gdcm::DataElement de( gdcm::Tag(0x0008,0x0030) ); // Do not copy the whole cstring: //de.SetByteValue( date+datelen, timelen ); //de.SetVR( gdcm::Attribute<0x0008,0x0030>::GetVR() ); //ds.Insert( de ); } } gdcm::UIDGenerator uid; { const char *sop = uid.Generate(); gdcm::DataElement de( gdcm::Tag(0x0008,0x0018) ); de.SetByteValue( sop, (uint32_t)strlen(sop) ); de.SetVR( gdcm::Attribute<0x0008, 0x0018>::GetVR() ); ds.Insert( de ); } gdcm::MediaStorage ms = gdcm::MediaStorage::EncapsulatedPDFStorage; { gdcm::DataElement de( gdcm::Tag(0x0008, 0x0016) ); const char* msstr = gdcm::MediaStorage::GetMSString(ms); de.SetByteValue( msstr, (uint32_t)strlen(msstr) ); de.SetVR( gdcm::Attribute<0x0008, 0x0016>::GetVR() ); ds.Insert( de ); } gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( "gdcmpdf" ); char date[22]; const size_t datelen = 8; bool b = gdcm::System::GetCurrentDateTime(date); (void)b; //std::cout << date << std::endl; { gdcm::Attribute<0x0008, 0x0005> at; const char s[] = "ISO_IR 100"; const char s_unicode[] = "ISO_IR 192"; at.SetNumberOfValues( 1 ); if( isUnicode ) at.SetValue( s_unicode ); else at.SetValue( s ); ds.Insert( at.GetAsDataElement() ); } { gdcm::Attribute<0x0008, 0x0012> at; std::string tmp( date, datelen ); at.SetValue( tmp.c_str() ); ds.Insert( at.GetAsDataElement() ); } const size_t timelen = 6 + 1 + 6; // TM + milliseconds { gdcm::Attribute<0x0008, 0x0013> at; std::string tmp( date+datelen, timelen); at.SetValue( tmp.c_str() ); ds.Insert( at.GetAsDataElement() ); } //(0008,0020) DA (no value available) # 0, 0 StudyDate { gdcm::Attribute<0x0008, 0x0020> at; ds.Insert( at.GetAsDataElement() ); } //(0008,0023) DA (no value available) # 0, 0 ContentDate { gdcm::Attribute<0x0008, 0x0023> at; std::string tmp( creationdate.c_str(), datelen ); at.SetValue( tmp.c_str() ); ds.Insert( at.GetAsDataElement() ); } //(0008,002a) DT (no value available) # 0, 0 AcquisitionDatetime { gdcm::Attribute<0x0008, 0x002a> at; time_t studydatetime = gdcm::System::FileTime( filename.c_str() ); char date2[22]; gdcm::System::FormatDateTime(date2, studydatetime); at.SetValue( date2 ); ds.Insert( at.GetAsDataElement() ); } //(0008,0030) TM (no value available) # 0, 0 StudyTime { gdcm::Attribute<0x0008, 0x0030> at; ds.Insert( at.GetAsDataElement() ); } //(0008,0033) TM (no value available) # 0, 0 ContentTime { gdcm::Attribute<0x0008, 0x0033> at; std::string tmp( creationdate.c_str() + datelen, timelen); at.SetValue( tmp.c_str() ); ds.Insert( at.GetAsDataElement() ); } //(0008,0050) SH (no value available) # 0, 0 AccessionNumber { gdcm::Attribute<0x0008, 0x0050> at; ds.Insert( at.GetAsDataElement() ); } //(0008,0060) CS [DOC] # 2, 1 Modality { gdcm::Attribute<0x0008, 0x0060> at; at.SetValue( "DOC " ); ds.Insert( at.GetAsDataElement() ); } //(0008,0064) CS [WSD] # 4, 1 ConversionType { gdcm::Attribute<0x0008, 0x0064> at; at.SetValue( "WSD" ); ds.Insert( at.GetAsDataElement() ); } //(0008,0070) LO (no value available) # 0, 0 Manufacturer { gdcm::Attribute<0x0008, 0x0070> at; at.SetValue( creator.c_str() ); ds.Insert( at.GetAsDataElement() ); } //(0008,0090) PN (no value available) # 0, 0 ReferringPhysiciansName { gdcm::Attribute<0x0008, 0x0090> at; ds.Insert( at.GetAsDataElement() ); } // In past DICOM implementation there used to be those neat tags: // (0088,0904) Topic Title TopicTitle LO 1 RET // (0088,0906) Topic Subject TopicSubject ST 1 RET // (0088,0910) Topic Author TopicAuthor LO 1 RET // (0088,0912) Topic Keywords TopicKeywords LO 1-32 RET // However they are now deprecated... //(0010,0010) PN (no value available) # 0, 0 PatientsName { gdcm::Attribute<0x0010, 0x0010> at; at.SetValue( author.c_str() ); ds.Insert( at.GetAsDataElement() ); } //(0010,0020) LO (no value available) # 0, 0 PatientID { gdcm::Attribute<0x0010, 0x0020> at; ds.Insert( at.GetAsDataElement() ); } //(0010,0030) DA (no value available) # 0, 0 PatientsBirthDate { gdcm::Attribute<0x0010, 0x0030> at; ds.Insert( at.GetAsDataElement() ); } //(0010,0040) CS (no value available) # 0, 0 PatientsSex { gdcm::Attribute<0x0010, 0x0040> at; ds.Insert( at.GetAsDataElement() ); } { gdcm::Attribute<0x0018, 0x1020> at; at.SetNumberOfValues( 1 ); at.SetValue( producer.c_str() ); ds.Insert( at.GetAsDataElement() ); } //(0020,000d) UI [1.2.276.0.7230010.3.1.4.8323329.511.1228064157.1] # 48, 1 StudyInstanceUID { gdcm::Attribute<0x0020, 0x000d> at; at.SetValue( uid.Generate() ); ds.Insert( at.GetAsDataElement() ); } //(0020,000e) UI [1.2.276.0.7230010.3.1.4.8323329.511.1228064157.2] # 48, 1 SeriesInstanceUID { gdcm::Attribute<0x0020, 0x000e> at; at.SetValue( uid.Generate() ); ds.Insert( at.GetAsDataElement() ); } //(0020,0010) SH (no value available) # 0, 0 StudyID { gdcm::Attribute<0x0020, 0x0010> at; ds.Insert( at.GetAsDataElement() ); } //(0020,0011) IS [1] # 2, 1 SeriesNumber { gdcm::Attribute<0x0020, 0x0011> at = { 1 }; ds.Insert( at.GetAsDataElement() ); } //(0020,0013) IS [1] # 2, 1 InstanceNumber { gdcm::Attribute<0x0020, 0x0013> at = { 1 }; ds.Insert( at.GetAsDataElement() ); } //(0028,0301) CS [YES] # 4, 1 BurnedInAnnotation { gdcm::Attribute<0x0028, 0x0301> at; at.SetValue( "YES" ); ds.Insert( at.GetAsDataElement() ); } //(0040,a043) SQ (Sequence with explicit length #=0) # 0, 1 ConceptNameCodeSequence //(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem { gdcm::Attribute<0x0040, 0xa043> at; gdcm::DataElement de( at.GetTag() ); de.SetVR( at.GetVR() ); //ds.Insert( at.GetAsDataElement() ); ds.Insert( de ); } //(0042,0010) ST (no value available) # 0, 0 DocumentTitle { gdcm::Attribute<0x0042, 0x0010> at; at.SetValue( title.c_str() ); ds.Insert( at.GetAsDataElement() ); } //(0042,0011) OB 25\50\44\46\2d\31\2e\34\0a\25\e7\f3\cf\d3\0a\32\34\35\38\38\20\30... # 6861900, 1 EncapsulatedDocument //(0042,0012) LO [application/pdf] # 16, 1 MIMETypeOfEncapsulatedDocument { gdcm::Attribute<0x0042, 0x0012> at; at.SetValue( "application/pdf" ); ds.Insert( at.GetAsDataElement() ); } { // gdcm::Attribute<0x0042, 0x0015> at; // at.SetValue( length ); // ds.Insert( at.GetAsDataElement() ); gdcm::Element el; el.SetValue( length ); gdcm::DataElement de = el.GetAsDataElement(); de.SetTag( gdcm::Tag(0x0042, 0x0015) ); ds.Insert( de ); } writer.SetFileName( outfilename.c_str() ); if( !writer.Write() ) { return 1; } return 0; } GDCM-3.0.10/Applications/Cxx/gdcmraw.cxx000066400000000000000000000260561412732066400176630ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * gdcmraw - ACR/NEMA DICOM PS3 ... DICOM PS3 - DICOM image to raw file * Synopsis: * gdcmraw [ -t | --tag Tag# (default: 07fe,0010) ] -i inputfile * Description: * gdcmraw * reads the named dicom or acr-nema input file and copies the raw image * pixel data to a raw binary file without a header of any kind. * The byte order, packing or encapsulation of the raw result is dependent * only on the encoding of the input file and cannot be changed. */ #include "gdcmReader.h" #include "gdcmImageReader.h" #include "gdcmImage.h" #include "gdcmFileMetaInformation.h" #include "gdcmDataSet.h" #include "gdcmTag.h" #include "gdcmByteValue.h" #include "gdcmSequenceOfFragments.h" #include "gdcmFragment.h" #include "gdcmFilename.h" #include "gdcmFilenameGenerator.h" #include "gdcmVersion.h" #include #include #include /* for printf */ #include /* for exit */ #include #include static void PrintVersion() { std::cout << "gdcmraw: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; } static void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcmraw [OPTION]... FILE..." << std::endl; std::cout << "Extract Data Element Value Field" << std::endl; std::cout << "Parameter (required):" << std::endl; std::cout << " -i --input DICOM filename" << std::endl; std::cout << " -o --output DICOM filename" << std::endl; std::cout << " -t --tag Specify tag to extract value from." << std::endl; std::cout << "Options:" << std::endl; std::cout << " -S --split-frags Split fragments into multiple files." << std::endl; std::cout << " -p --pattern Specify trailing file pattern (see split-frags)." << std::endl; std::cout << " -P --pixel-data Pixel Data trailing 0." << std::endl; std::cout << "General Options:" << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " -v --version print version." << std::endl; } int main(int argc, char *argv[]) { int c; //int digit_optind = 0; gdcm::Tag rawTag(0x7fe0, 0x0010); // Default to Pixel Data std::string filename; std::string outfilename; std::string pattern; int splitfrags = 0; int pixeldata = 0; int verbose = 0; int warning = 0; int debug = 0; int error = 0; int help = 0; int version = 0; while (true) { //int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"input", 1, nullptr, 0}, // i {"output", 1, nullptr, 0}, // o {"tag", 1, nullptr, 0}, // t {"split-frags", 0, &splitfrags, 1}, // f /* * pixel-data flag is important for image like DermaColorLossLess.dcm since the bytevalue is * 63532, because of the DICOM \0 padding, but we would rather have the image buffer instead * which is simply one byte shorter, so add a special flag that simply mimic what TestImageReader * would expect */ {"pixel-data", 0, &pixeldata, 1}, // P {"pattern", 1, nullptr, 0}, // p {"verbose", 0, &verbose, 1}, {"warning", 0, &warning, 1}, {"debug", 0, &debug, 1}, {"error", 0, &error, 1}, {"help", 0, &help, 1}, {"version", 0, &version, 1}, {nullptr, 0, nullptr, 0} }; c = getopt_long (argc, argv, "i:o:t:Sp:PVWDEhv", long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: { const char *s = long_options[option_index].name; (void)s; //printf ("option %s", s); if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); assert( filename.empty() ); filename = optarg; } else if( option_index == 2 ) /* tag */ { assert( strcmp(s, "tag") == 0 ); rawTag.ReadFromCommaSeparatedString(optarg); } else if( option_index == 5 ) /* pattern */ { assert( strcmp(s, "pattern") == 0 ); assert( pattern.empty() ); pattern = optarg; } //printf (" with arg %s", optarg); } //printf ("\n"); } break; case 'i': //printf ("option i with value '%s'\n", optarg); assert( filename.empty() ); filename = optarg; break; case 'o': //printf ("option o with value '%s'\n", optarg); assert( outfilename.empty() ); outfilename = optarg; break; case 'P': pixeldata = 1; break; case 'S': splitfrags = 1; break; case 'p': assert( pattern.empty() ); pattern = optarg; break; case 't': //printf ("option t with value '%s'\n", optarg); rawTag.ReadFromCommaSeparatedString(optarg); //std::cerr << rawTag << std::endl; break; case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { std::vector files; while (optind < argc) { //printf ("%s\n", argv[optind++]); files.emplace_back(argv[optind++] ); } //printf ("\n"); if( files.size() == 2 && filename.empty() && outfilename.empty() ) { filename = files[0]; outfilename = files[1]; } else { PrintHelp(); return 1; } } if( version ) { //std::cout << "version" << std::endl; PrintVersion(); return 0; } if( help ) { //std::cout << "help" << std::endl; PrintHelp(); return 0; } if( filename.empty() ) { //std::cerr << "Need input file (-i)\n"; PrintHelp(); return 1; } // Debug is a little too verbose gdcm::Trace::SetDebug( debug != 0); gdcm::Trace::SetWarning( warning != 0); gdcm::Trace::SetError( error != 0); // when verbose is true, make sure warning+error are turned on: if( verbose ) { gdcm::Trace::SetWarning( verbose != 0); gdcm::Trace::SetError( verbose!= 0); } // else //std::cout << "Filename: " << filename << std::endl; // very special option, handle it first: if( pixeldata ) { if( rawTag != gdcm::Tag(0x7fe0,0x0010) ) { return 1; } gdcm::ImageReader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::Image& image = reader.GetImage(); unsigned long len = image.GetBufferLength(); char * buf = new char[len]; image.GetBuffer( buf ); std::ofstream output(outfilename.c_str(), std::ios::binary); output.write( buf, len ); delete[] buf; return 0; } gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } //const gdcm::FileMetaInformation &h = reader.GetFile().GetHeader(); //std::cout << h << std::endl; const gdcm::DataSet &ds = reader.GetFile().GetDataSet(); //std::cout << ds << std::endl; if( !ds.FindDataElement( rawTag ) ) { std::cerr << "Cannot find Tag: " << rawTag << std::endl; return 1; } if( outfilename.empty() ) { std::cerr << "Need output file (-o)\n"; return 1; } gdcm::Filename fn1(filename.c_str()), fn2(outfilename.c_str()); if( fn1.IsIdentical(fn2) ) { std::cerr << "Output is Input\n"; return 1; } const gdcm::DataElement& pdde = ds.GetDataElement( rawTag ); const gdcm::ByteValue *bv = pdde.GetByteValue(); const gdcm::SequenceOfFragments *sf = pdde.GetSequenceOfFragments(); if( bv ) { std::ofstream output(outfilename.c_str(), std::ios::binary); bv->WriteBuffer(output); } else if( sf ) { if( splitfrags ) { size_t nfrags = sf->GetNumberOfFragments(); gdcm::FilenameGenerator fg; fg.SetNumberOfFilenames( nfrags ); fg.SetPrefix( outfilename.c_str() ); fg.SetPattern( pattern.c_str() ); if(!fg.Generate()) { std::cerr << "Could not generate" << std::endl; return 1; } for(unsigned int i = 0; i < nfrags; ++i) { const gdcm::Fragment& frag = sf->GetFragment(i); const gdcm::ByteValue *fragbv = frag.GetByteValue(); const char *outfilenamei = fg.GetFilename(i); std::ofstream outputi(outfilenamei, std::ios::binary); fragbv->WriteBuffer(outputi); } } else { std::ofstream output(outfilename.c_str(), std::ios::binary); sf->WriteBuffer(output); } } else { const gdcm::Value &value = pdde.GetValue(); const gdcm::Value * v = &value; const gdcm::SequenceOfItems *sqi = dynamic_cast( v ); if( sqi ) { //std::ofstream output(outfilename.c_str(), std::ios::binary); //sqi->Write(output); size_t nfrags = sqi->GetNumberOfItems(); gdcm::FilenameGenerator fg; fg.SetNumberOfFilenames( nfrags ); fg.SetPrefix( outfilename.c_str() ); fg.SetPattern( pattern.c_str() ); if(!fg.Generate()) { std::cerr << "Could not generate" << std::endl; return 1; } for(unsigned int i = 0; i < nfrags; ++i) { const gdcm::Item& frag = sqi->GetItem(i+1); const gdcm::DataSet &subds = frag.GetNestedDataSet(); const char *outfilenamei = fg.GetFilename(i); std::ofstream outputi(outfilenamei, std::ios::binary); // Let's imagine we found an undefined length Pixel Data attribute in // this sequence. Let's pick ExplicitDataElement for writing out then subds.Write(outputi); } } else { std::cerr << "Unhandled" << std::endl; return 1; } } return 0; } GDCM-3.0.10/Applications/Cxx/gdcmscanner.cxx000066400000000000000000000206701412732066400205170ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * a Scanner application * Usage: * * $ gdcmscanner -d /images/ -t 0020,000d -t 0020,000e * * Options: * -d : directory * -t : tag (can be specified multiple times) * -p : print * -r : recursive (enter subdir of main directory) * * TODO: * --bench... */ #include "gdcmScanner.h" #include "gdcmStrictScanner.h" #include "gdcmTrace.h" #include "gdcmVersion.h" #include "gdcmSimpleSubjectWatcher.h" #include "gdcmGlobal.h" #include "gdcmDicts.h" #include "gdcmDict.h" #include "gdcmDictEntry.h" #include #include #include #include /* for printf */ #include /* for exit */ #include #include static void PrintVersion() { std::cout << "gdcmscanner: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; } static void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcmscanner [OPTION] -d directory -t tag(s)" << std::endl; std::cout << "Scan a directory containing DICOM files.\n"; std::cout << "Parameter (required):" << std::endl; std::cout << " -d --dir DICOM directory" << std::endl; std::cout << " -t --tag %d,%d DICOM tag(s) to look for" << std::endl; std::cout << " -k --keyword %s DICOM keyword(s) to look for" << std::endl; std::cout << " -P --private-tag %d,%d,%s DICOM private tag(s) to look for" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -p --print Print output." << std::endl; std::cout << " -r --recursive Recursively descend directory." << std::endl; std::cout << " --strict Use strict parser (faster but less tolerant with bogus DICOM files)." << std::endl; std::cout << " --table Use Table output." << std::endl; std::cout << "General Options:" << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " -v --version print version." << std::endl; } typedef std::vector VectorTags; typedef std::vector VectorPrivateTags; template < typename TScanner > static int DoIt( gdcm::Directory const & d, bool const & print , int table, VectorTags const & tags, VectorPrivateTags const & privatetags) { gdcm::SmartPointer ps = new TScanner; TScanner &s = *ps; //gdcm::SimpleSubjectWatcher watcher(ps, "Scanner"); for( VectorTags::const_iterator it = tags.begin(); it != tags.end(); ++it) { s.AddTag( *it ); } for( VectorPrivateTags::const_iterator it = privatetags.begin(); it != privatetags.end(); ++it) { s.AddPrivateTag( *it ); } bool b = s.Scan( d.GetFilenames() ); if( !b ) { std::cerr << "Scanner failed" << std::endl; return 1; } if (print) { if(table) s.PrintTable( std::cout ); else s.Print( std::cout ); } return 0; } int main(int argc, char *argv[]) { int c; //int digit_optind = 0; bool print = false; bool recursive = false; std::string dirname; VectorTags tags; VectorPrivateTags privatetags; gdcm::Tag tag; gdcm::PrivateTag privatetag; static const gdcm::Global &g = gdcm::Global::GetInstance(); static const gdcm::Dicts &dicts = g.GetDicts(); static const gdcm::Dict &pubdict = dicts.GetPublicDict(); int strict = 0; int table = 0; int verbose = 0; int warning = 0; int debug = 0; int error = 0; int help = 0; int version = 0; while (true) { //int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"dir", required_argument, nullptr, 'd'}, {"tag", required_argument, nullptr, 't'}, {"recursive", no_argument, nullptr, 'r'}, {"print", no_argument, nullptr, 'p'}, {"private-tag", required_argument, nullptr, 'P'}, {"keyword", required_argument, nullptr, 'k'}, {"strict", no_argument, &strict, 1}, {"table", no_argument, &table, 1}, // General options ! {"verbose", no_argument, nullptr, 'V'}, {"warning", no_argument, nullptr, 'W'}, {"debug", no_argument, nullptr, 'D'}, {"error", no_argument, nullptr, 'E'}, {"help", no_argument, nullptr, 'H'}, {"version", no_argument, nullptr, 'v'}, {nullptr, 0, nullptr, 0} }; c = getopt_long (argc, argv, "d:t:rpP:k:VWDEhv", long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: if (optarg) { const char *s = long_options[option_index].name; (void)s; assert(0); } break; case 'd': dirname = optarg; break; case 't': tag.ReadFromCommaSeparatedString(optarg); tags.push_back( tag ); //std::cerr << optarg << std::endl; break; case 'k': { const char * keyword = optarg; /*const gdcm::DictEntry &dictentry =*/ pubdict.GetDictEntryByKeyword(keyword, tag); if( tag != gdcm::Tag(0xffff,0xffff) ) tags.push_back( tag ); else { std::cerr << "Invalid keyword: " << keyword << std::endl; return 1; } } break; case 'P': privatetag.ReadFromCommaSeparatedString(optarg); privatetags.push_back( privatetag ); //std::cerr << optarg << std::endl; break; case 'r': recursive = true; break; case 'p': print = true; break; case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { /* printf ("non-option ARGV-elements: "); while (optind < argc) { printf ("%s ", argv[optind++]); } printf ("\n"); */ PrintHelp(); return 1; } if( version ) { //std::cout << "version" << std::endl; PrintVersion(); return 0; } if( help ) { //std::cout << "help" << std::endl; PrintHelp(); return 0; } if( dirname.empty() ) { //std::cerr << "Need dir (-d)\n"; PrintHelp(); return 1; } if( tags.empty() && privatetags.empty() ) { //std::cerr << "Need tags (-t)\n"; PrintHelp(); return 1; } // Debug is a little too verbose gdcm::Trace::SetDebug( (debug > 0 ? true : false)); gdcm::Trace::SetWarning( (warning > 0 ? true : false)); gdcm::Trace::SetError( (error > 0 ? true : false)); // when verbose is true, make sure warning+error are turned on: if( verbose ) { gdcm::Trace::SetWarning( (verbose > 0 ? true : false) ); gdcm::Trace::SetError( (verbose > 0 ? true : false) ); } if( verbose ) { std::cout << "Will parse: " << dirname << std::endl; std::cout << "Looking for tags: \n"; std::copy(tags.begin(), tags.end(), std::ostream_iterator( std::cout, "\n")); std::copy(privatetags.begin(), privatetags.end(), std::ostream_iterator( std::cout, "\n")); //std::cout << std::endl; } gdcm::Directory d; unsigned int nfiles = d.Load( dirname.c_str(), recursive ); if( !nfiles ) { std::cerr << "No files found in: " << dirname << std::endl; return 1; } if( verbose ) d.Print( std::cout ); if( !table ) std::cout << "done retrieving file list " << nfiles << " files found." << std::endl; if( strict ) return DoIt(d,print,table,tags,privatetags); return DoIt(d,print,table,tags,privatetags); } GDCM-3.0.10/Applications/Cxx/gdcmscu.cxx000066400000000000000000000573661412732066400176740ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Simple command line tool to echo/store/find/move DICOM using * DICOM Query/Retrieve * This is largely inspired by other tool available from other toolkit, namely: * echoscu (DCMTK) * findscu (DCMTK) * movescu (DCMTK) * storescu (DCMTK) */ #include "gdcmCompositeNetworkFunctions.h" #include #include #include #include #include "gdcmVersion.h" #include "gdcmGlobal.h" #include "gdcmSystem.h" #include "gdcmDirectory.h" #include "gdcmDataSet.h" #include "gdcmFileMetaInformation.h" #include "gdcmUIDGenerator.h" #include "gdcmBaseRootQuery.h" #include "gdcmQueryFactory.h" #include "gdcmPrinter.h" static void PrintVersion() { std::cout << "gdcmscu: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; } static void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcmscu [OPTION]...[OPERATION]...HOSTNAME...[PORT]..." << std::endl; std::cout << "Execute a DICOM Q/R operation to HOSTNAME, using port PORT (104 when not specified)\n"; std::cout << "Options:" << std::endl; std::cout << " -H --hostname Hostname." << std::endl; std::cout << " -p --port Port number." << std::endl; std::cout << " --aetitle Set Calling AE Title." << std::endl; std::cout << " --call Set Called AE Title." << std::endl; std::cout << "Mode Options:" << std::endl; std::cout << " --echo C-ECHO (default when none)." << std::endl; std::cout << " --store C-STORE." << std::endl; std::cout << " --find C-FIND." << std::endl; std::cout << " --move C-MOVE." << std::endl; std::cout << " --get C-GET." << std::endl; std::cout << "C-STORE Options:" << std::endl; std::cout << " -i --input DICOM filename" << std::endl; std::cout << " -r --recursive recursively process (sub-)directories." << std::endl; std::cout << " --store-query Store constructed query in file." << std::endl; std::cout << "C-FIND Options:" << std::endl; std::cout << " --worklist C-FIND Worklist Model." << std::endl; std::cout << " --patientroot C-FIND Patient Root Model." << std::endl; std::cout << " --studyroot C-FIND Study Root Model." << std::endl; std::cout << " --patient C-FIND Query on Patient Info (cannot be used with --studyroot)" << std::endl; std::cout << " --study C-FIND Query on Study Info." << std::endl; std::cout << " --series C-FIND Query on Series Info." << std::endl; std::cout << " --image C-FIND Query on Image Info." << std::endl; //std::cout << " --psonly C-FIND Patient/Study Only Model." << std::endl; std::cout << " --key 0123,4567=VALUE for specifying search criteria (wildcard allowed)." << std::endl; std::cout << " With --key, leave blank (ie, --key 10,10="") to retrieve values" << std::endl; std::cout << "C-MOVE Options:" << std::endl; std::cout << " -o --output DICOM output directory." << std::endl; std::cout << " --port-scp Port used for incoming association." << std::endl; std::cout << " --key 0123,4567=VALUE for specifying search criteria (wildcard not allowed)." << std::endl; std::cout << " Note that C-MOVE supports the same queries as C-FIND, but no wildcards are allowed." << std::endl; std::cout << "C-GET Options:" << std::endl; std::cout << "General Options:" << std::endl; std::cout << " --root-uid Root UID." << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " --queryhelp print query help." << std::endl; std::cout << " -v --version print version." << std::endl; std::cout << " -L --log-file set log file (instead of cout)." << std::endl; try { std::locale l(""); std::string loc = l.name(); std::cout << std::endl; std::cout << "Local Name: " << loc << std::endl; } catch( const std::exception& e) { std::cerr << e.what() << std::endl; } std::cout << "Local Character Set: " << gdcm::System::GetLocaleCharset() << std::endl; std::vector charsettype; charsettype.push_back( gdcm::QueryFactory::GetCharacterFromCurrentLocale() ); gdcm::DataElement de = gdcm::QueryFactory::ProduceCharacterSetDataElement(charsettype); const gdcm::ByteValue *bv = de.GetByteValue(); std::string s( bv->GetPointer(), bv->GetLength() ); std::cout << "DICOM Character Set: [" << s << "]" << std::endl; } static void PrintQueryHelp(int inFindPatientRoot) { gdcm::BaseRootQuery* theBase; if (inFindPatientRoot) { std::cout << "To find the help for a study-level query, type" <WriteHelpFile(std::cout); delete theBase; } else { std::cout << "To find the help for a patient-level query, type" <WriteHelpFile(std::cout); delete theBase; } } int main(int argc, char *argv[]) { int c; //int digit_optind = 0; std::string shostname; std::string callingaetitle = "GDCMSCU"; std::string callaetitle = "ANY-SCP"; int port = 104; // default int portscp = 0; int outputopt = 0; int portscpnum = 0; gdcm::Directory::FilenamesType filenames; std::string outputdir; int storequery = 0; int verbose = 0; int warning = 0; int debug = 0; int error = 0; int help = 0; int queryhelp = 0; int version = 0; int echomode = 0; int storemode = 0; int findmode = 0; int movemode = 0; int getmode = 0; int findworklist = 0; int findpatientroot = 0; int findstudyroot = 0; int patientquery = 0; int studyquery = 0; int seriesquery = 0; int imagequery = 0; int findpsonly = 0; std::string queryfile; std::string root; int rootuid = 0; int recursive = 0; int logfile = 0; std::string logfilename; gdcm::Tag tag; std::vector< std::pair > keys; while (true) { //int this_option_optind = optind ? optind : 1; int option_index = 0; /* struct option { const char *name; int has_arg; int *flag; int val; }; */ static struct option long_options[] = { {"verbose", 0, &verbose, 1}, {"warning", 0, &warning, 1}, {"debug", 0, &debug, 1}, {"error", 0, &error, 1}, {"help", 0, &help, 1}, {"version", 0, &version, 1}, {"hostname", 1, nullptr, 0}, // -h {"aetitle", 1, nullptr, 0}, // {"call", 1, nullptr, 0}, // {"port", 0, &port, 1}, // -p {"input", 1, nullptr, 0}, // dcmfile-in {"echo", 0, &echomode, 1}, // --echo {"store", 0, &storemode, 1}, // --store {"find", 0, &findmode, 1}, // --find {"move", 0, &movemode, 1}, // --move {"key", 1, nullptr, 0}, // (15) --key {"worklist", 0, &findworklist, 1}, // --worklist {"patientroot", 0, &findpatientroot, 1}, // --patientroot {"studyroot", 0, &findstudyroot, 1}, // --studyroot {"psonly", 0, &findpsonly, 1}, // --psonly {"port-scp", 1, &portscp, 1}, // (20) --port-scp {"output", 1, &outputopt, 1}, // --output {"recursive", 0, &recursive, 1}, {"store-query", 1, &storequery, 1}, {"queryhelp", 0, &queryhelp, 1}, {"patient", 0, &patientquery, 1}, // --patient {"study", 0, &studyquery, 1}, // --study {"series", 0, &seriesquery, 1}, // --series {"image", 0, &imagequery, 1}, // --image {"log-file", 1, &logfile, 1}, // --log-file {"get", 0, &getmode, 1}, // --get {nullptr, 0, nullptr, 0} // required }; static const char short_options[] = "i:H:p:L:VWDEhvk:o:r"; c = getopt_long (argc, argv, short_options, long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: case '-': { const char *s = long_options[option_index].name; (void)s; //printf ("option %s", s); if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); filenames.push_back( optarg ); } else if( option_index == 7 ) /* calling aetitle */ { assert( strcmp(s, "aetitle") == 0 ); //assert( callingaetitle.empty() ); callingaetitle = optarg; } else if( option_index == 8 ) /* called aetitle */ { assert( strcmp(s, "call") == 0 ); //assert( callaetitle.empty() ); callaetitle = optarg; } else if( option_index == 15 ) /* key */ { assert( strcmp(s, "key") == 0 ); if( !tag.ReadFromCommaSeparatedString(optarg) ) { std::cerr << "Could not read Tag: " << optarg << std::endl; return 1; } std::stringstream ss; ss.str( optarg ); uint16_t dummy; char cdummy; // comma ss >> std::hex >> dummy; assert( tag.GetGroup() == dummy ); ss >> cdummy; assert( cdummy == ',' ); ss >> std::hex >> dummy; assert( tag.GetElement() == dummy ); ss >> cdummy; assert( cdummy == ',' || cdummy == '=' ); std::string str; //ss >> str; std::getline(ss, str); // do not skip whitespace if( str.size() % 2 == 1 ) str += " "; keys.emplace_back(tag, str ); } else if( option_index == 20 ) /* port-scp */ { assert( strcmp(s, "port-scp") == 0 ); portscpnum = atoi(optarg); } else if( option_index == 21 ) /* output */ { assert( strcmp(s, "output") == 0 ); outputdir = optarg; } else if( option_index == 23 ) /* store-query */ { assert( strcmp(s, "store-query") == 0 ); queryfile = optarg; } else if( option_index == 29 ) /* log-file */ { assert( strcmp(s, "log-file") == 0 ); logfilename = optarg; } else { // If you reach here someone mess-up the index and the argument in // the getopt table assert( 0 ); } //printf (" with arg %s", optarg); } //printf ("\n"); } break; case 'k': { if( !tag.ReadFromCommaSeparatedString(optarg) ) { std::cerr << "Could not read Tag: " << optarg << std::endl; return 1; } std::stringstream ss; ss.str( optarg ); uint16_t dummy; char cdummy; // comma ss >> std::hex >> dummy; assert( tag.GetGroup() == dummy ); ss >> cdummy; assert( cdummy == ',' ); ss >> std::hex >> dummy; assert( tag.GetElement() == dummy ); ss >> cdummy; assert( cdummy == ',' || cdummy == '=' ); std::string str; std::getline(ss, str); // do not skip whitespace keys.emplace_back(tag, str ); } break; case 'i': //printf ("option i with value '%s'\n", optarg); filenames.push_back( optarg ); break; case 'r': recursive = 1; break; case 'o': assert( outputdir.empty() ); outputdir = optarg; break; case 'H': shostname = optarg; break; case 'p': port = atoi( optarg ); break; case 'L': logfile = 1; logfilename = optarg; break; case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'q': queryhelp = 1; break; case 'v': version = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { int v = argc - optind; // hostname port filename if( v == 1 ) { shostname = argv[optind++]; } else if( v == 2 ) { shostname = argv[optind++]; port = atoi( argv[optind++] ); } else if( v >= 3 ) { shostname = argv[optind++]; port = atoi( argv[optind++] ); std::vector files; while (optind < argc) { files.emplace_back(argv[optind++] ); } filenames = files; } else { return 1; } assert( optind == argc ); } if( version ) { PrintVersion(); return 0; } if( help ) { PrintHelp(); return 0; } if(queryhelp) { PrintQueryHelp(findpatientroot); return 0; } const bool theDebug = debug != 0; const bool theWarning = warning != 0; const bool theError = error != 0; const bool theVerbose = verbose != 0; const bool theRecursive = recursive != 0; // Debug is a little too verbose gdcm::Trace::SetDebug( theDebug ); gdcm::Trace::SetWarning( theWarning ); gdcm::Trace::SetError( theError ); // when verbose is true, make sure warning+error are turned on: if( verbose ) { gdcm::Trace::SetWarning( theVerbose ); gdcm::Trace::SetError( theVerbose); } if( logfile ) { gdcm::Trace::SetStreamToFile( logfilename.c_str() ); } gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( callaetitle.c_str() ); if( !rootuid ) { // only read the env var if no explicit cmd line option // maybe there is an env var defined... let's check const char *rootuid_env = getenv("GDCM_ROOT_UID"); if( rootuid_env ) { rootuid = 1; root = rootuid_env; } } if( rootuid ) { // root is set either by the cmd line option or the env var if( !gdcm::UIDGenerator::IsValid( root.c_str() ) ) { std::cerr << "specified Root UID is not valid: " << root << std::endl; return 1; } gdcm::UIDGenerator::SetRoot( root.c_str() ); } if( shostname.empty() ) { //std::cerr << "Hostname missing" << std::endl; PrintHelp(); // needed to display help message when no arg return 1; } if( port == 0 ) { std::cerr << "Problem with port number" << std::endl; return 1; } // checkout outputdir opt: if( outputopt ) { if( !gdcm::System::FileIsDirectory( outputdir.c_str()) ) { if( !gdcm::System::MakeDirectory( outputdir.c_str() ) ) { std::cerr << "Sorry: " << outputdir << " is not a valid directory."; std::cerr << std::endl; std::cerr << "and I could not create it."; std::cerr << std::endl; return 1; } } } const char *hostname = shostname.c_str(); std::string mode = "echo"; if ( echomode ) { mode = "echo"; } else if ( storemode ) { mode = "store"; } else if ( findmode ) { mode = "find"; } else if ( movemode ) { mode = "move"; } else if ( getmode ) { mode = "get"; } else if ( findworklist ) { mode = "worklist"; } //this class contains the networking calls if ( mode == "server" ) // C-STORE SCP { // MM: Do not expose that to user for now (2010/10/11). //CStoreServer( port ); return 1; } else if ( mode == "echo" ) // C-ECHO SCU { // ./bin/gdcmscu mi2b2.slicer.org 11112 --aetitle ACME1 --call MI2B2 // ./bin/gdcmscu --echo mi2b2.slicer.org 11112 --aetitle ACME1 --call MI2B2 bool didItWork = gdcm::CompositeNetworkFunctions::CEcho( hostname, (uint16_t)port, callingaetitle.c_str(), callaetitle.c_str() ); gdcmDebugMacro( (didItWork ? "Echo succeeded." : "Echo failed.") ); return didItWork ? 0 : 1; } else if ( mode == "move" ) // C-FIND SCU { // ./bin/gdcmscu --move --patient dhcp-67-183 5678 move // ./bin/gdcmscu --move --patient mi2b2.slicer.org 11112 move gdcm::ERootType theRoot = gdcm::eStudyRootType; if (findpatientroot) theRoot = gdcm::ePatientRootType; gdcm::EQueryLevel theLevel = gdcm::eStudy; if (patientquery) theLevel = gdcm::ePatient; if (seriesquery) theLevel = gdcm::eSeries; if (imagequery) theLevel = gdcm::eImage; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys, gdcm::eMove ); if (findstudyroot == 0 && findpatientroot == 0) { if (gdcm::Trace::GetErrorFlag()) { std::cerr << "Need to explicitly choose query retrieve level, --patientroot or --studyroot" << std::endl; } std::cerr << "Move failed." << std::endl; return 1; } if( !portscp ) { std::cerr << "Need to set explicitly port number for SCP association" " --port-scp" << std::endl; //std::cerr << "Move failed." << std::endl; return 1; } if( storequery ) { if (!theQuery->WriteQuery(queryfile)) { std::cerr << "Could not write out query to: " << queryfile << std::endl; std::cerr << "Move failed." << std::endl; return 1; } } if (!theQuery->ValidateQuery(false)) { std::cerr << "You have not constructed a valid find query." " Please try again." << std::endl; return 1; } //!!! added the boolean to 'interleave writing', which basically writes //each file out as it comes across, rather than all at once at the end. //Turn off the boolean to have it written all at once at the end. bool didItWork = gdcm::CompositeNetworkFunctions::CMove( hostname, (uint16_t)port, theQuery, (uint16_t)portscpnum, callingaetitle.c_str(), callaetitle.c_str(), outputdir.c_str() ); gdcmDebugMacro( (didItWork ? "Move succeeded." : "Move failed.") ); return didItWork ? 0 : 1; } else if ( mode == "worklist" ) { gdcm::ERootType theRoot = gdcm::ePatientRootType; gdcm::EQueryLevel theLevel = gdcm::eSeries; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery( theRoot, theLevel ,keys, gdcm::eWLMFind ); if (!theQuery->ValidateQuery(false)) { //issue } std::vector theDataSet; if( !gdcm::CompositeNetworkFunctions::CFind(hostname, (uint16_t)port, theQuery, theDataSet, callingaetitle.c_str(), callaetitle.c_str()) ) { } gdcm::Printer p; std::ostream &os = gdcm::Trace::GetStream(); for( std::vector::iterator itor = theDataSet.begin(); itor != theDataSet.end(); itor++) { os << "WL Find Response: " << (itor - theDataSet.begin() + 1) << std::endl; p.PrintDataSet( *itor, os ); os << std::endl; } if( gdcm::Trace::GetWarningFlag() ) // == verbose flag { os << "WL Find was successful." << std::endl; } } else if ( mode == "find" ) // C-FIND SCU { // Construct C-FIND DataSet: // ./bin/gdcmscu --find --patient dhcp-67-183 5678 // ./bin/gdcmscu --find --patient mi2b2.slicer.org 11112 --aetitle ACME1 --call MI2B2 // findscu -aec MI2B2 -P -k 0010,0010=F* mi2b2.slicer.org 11112 patqry.dcm // PATIENT query: // ./bin/gdcmscu --find --patient mi2b2.slicer.org 11112 --aetitle ACME1 --call MI2B2 --key 10,10="F*" -V gdcm::ERootType theRoot = gdcm::eStudyRootType; if (findpatientroot) theRoot = gdcm::ePatientRootType; gdcm::EQueryLevel theLevel = gdcm::eStudy; if (patientquery) theLevel = gdcm::ePatient; if (seriesquery) theLevel = gdcm::eSeries; if (imagequery) theLevel = gdcm::eImage; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if (findstudyroot == 0 && findpatientroot == 0) { if (gdcm::Trace::GetErrorFlag()) { std::cerr << "Need to explicitly choose query retrieve level, --patientroot or --studyroot" << std::endl; } std::cerr << "Find failed." << std::endl; return 1; } if (!theQuery) { std::cerr << "Query construction failed." <WriteQuery(queryfile)) { std::cerr << "Could not write out query to: " << queryfile << std::endl; return 1; } } //doing a non-strict query, the second parameter there. //look at the base query comments if (!theQuery->ValidateQuery(false)) { std::cerr << "You have not constructed a valid find query." " Please try again." << std::endl; return 1; } //the value in that tag corresponds to the query type std::vector theDataSet; if( !gdcm::CompositeNetworkFunctions::CFind(hostname, (uint16_t)port, theQuery, theDataSet, callingaetitle.c_str(), callaetitle.c_str()) ) { gdcmDebugMacro( "Problem in CFind." ); return 1; } gdcm::Printer p; std::ostream &os = gdcm::Trace::GetStream(); for( std::vector::iterator itor = theDataSet.begin(); itor != theDataSet.end(); itor++) { os << "Find Response: " << (itor - theDataSet.begin() + 1) << std::endl; p.PrintDataSet( *itor, os ); os << std::endl; } if( gdcm::Trace::GetWarningFlag() ) // == verbose flag { os << "Find was successful." << std::endl; } return 0; } else if ( mode == "store" ) // C-STORE SCU { // mode == directory gdcm::Directory::FilenamesType thefiles; for( gdcm::Directory::FilenamesType::const_iterator file = filenames.begin(); file != filenames.end(); ++file ) { if( gdcm::System::FileIsDirectory(file->c_str()) ) { gdcm::Directory::FilenamesType files; gdcm::Directory dir; dir.Load(*file, theRecursive); files = dir.GetFilenames(); thefiles.insert(thefiles.end(), files.begin(), files.end()); } else { // This is a file simply add it thefiles.push_back(*file); } } bool didItWork = gdcm::CompositeNetworkFunctions::CStore(hostname, (uint16_t)port, thefiles, callingaetitle.c_str(), callaetitle.c_str()); gdcmDebugMacro( (didItWork ? "Store was successful." : "Store failed.") ); return didItWork ? 0 : 1; } else if ( mode == "get" ) // C-GET SCU { return 1; } else { assert( 0 ); return 1; } return 0; } GDCM-3.0.10/Applications/Cxx/gdcmstream.cxx000066400000000000000000000765001412732066400203640ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAttribute.h" #include "gdcmFile.h" #include "gdcmFilename.h" #include "gdcmImageHelper.h" #include "gdcmItem.h" #include "gdcmMediaStorage.h" #include "gdcmSequenceOfItems.h" #include "gdcmStreamImageReader.h" #include "gdcmStreamImageWriter.h" #include "gdcmSystem.h" #include "gdcmTag.h" #include "gdcmTrace.h" #include "gdcmTransferSyntax.h" #include "gdcmUIDGenerator.h" #include "gdcmVersion.h" #ifdef OPENJPEG_VERSION_MAJOR #if OPENJPEG_VERSION_MAJOR == 1 #include "gdcm_openjpeg.h" #elif OPENJPEG_VERSION_MAJOR == 2 #define USE_OPJ_DEPRECATED // opj_setup_decoder #include "gdcm_openjpeg2.h" #else #error should not happen #endif #else #error should not happen #endif #include static void error_callback(const char *msg, void *) { (void)msg; } static void warning_callback(const char *msg, void *) { (void)msg; } static void info_callback(const char *msg, void *) { (void)msg; } template static unsigned int readvector(std::vector &v, const char *str) { if( !str ) return 0; std::istringstream os( str ); T f; while( os >> f ) { v.push_back( f ); os.get(); // == "," } return (unsigned int)v.size(); } static int No_Of_Resolutions(const char *filename) { std::ifstream is; is.open( filename, std::ios::binary ); opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_dinfo_t* dinfo; /* handle to a decompressor */ opj_cio_t *cio; // FIXME: Do some stupid work: is.seekg( 0, std::ios::end); size_t buf_size = (size_t)is.tellg(); char *dummy_buffer = new char[(unsigned int)buf_size]; is.seekg(0, std::ios::beg); is.read( dummy_buffer, buf_size); unsigned char *src = (unsigned char*)dummy_buffer; uint32_t file_length = (uint32_t)buf_size; // 32bits truncation should be ok since DICOM cannot have larger than 2Gb image /* configure the event callbacks (not required) */ memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); event_mgr.error_handler = error_callback; event_mgr.warning_handler = warning_callback; event_mgr.info_handler = info_callback; /* set decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); // default blindly copied parameters.cp_layer=0; parameters.cp_reduce= 0; // parameters.decod_format=-1; // parameters.cod_format=-1; const char jp2magic[] = "\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A"; if( memcmp( src, jp2magic, sizeof(jp2magic) ) == 0 ) { /* JPEG-2000 compressed image data ... sigh */ // gdcmData/ELSCINT1_JP2vsJ2K.dcm // gdcmData/MAROTECH_CT_JP2Lossy.dcm //gdcmWarningMacro( "J2K start like JPEG-2000 compressed image data instead of codestream" ); parameters.decod_format = 1; //JP2_CFMT; //assert(parameters.decod_format == JP2_CFMT); } else { /* JPEG-2000 codestream */ //parameters.decod_format = J2K_CFMT; //assert(parameters.decod_format == J2K_CFMT); assert( 0 ); } parameters.cod_format = 11; // PGX_DFMT; //assert(parameters.cod_format == PGX_DFMT); /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JP2); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ if(! opj_decode(dinfo, cio)) { opj_destroy_decompress(dinfo); opj_cio_close(cio); //gdcmErrorMacro( "opj_decode failed" ); return 1; } opj_cp_t * cp = ((opj_jp2_t*)dinfo->jp2_handle)->j2k->cp; opj_tcp_t *tcp = &cp->tcps[0]; opj_tccp_t *tccp = &tcp->tccps[0]; return tccp->numresolutions; /* std::cout << "\n No of Cols In Image" << image->x1; std::cout << "\n No of Rows In Image" << image->y1; std::cout << "\n No of Components in Image" << image->numcomps; std::cout << "\n No of Resolutions"<< tccp->numresolutions << "\n"; */ } static bool Write_Resolution(gdcm::StreamImageWriter & theStreamWriter, const char *filename, int res, std::ostream& of, int flag, gdcm::SequenceOfItems *sq) { (void)of; std::ifstream is; is.open( filename, std::ios::binary ); opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_dinfo_t* dinfo; /* handle to a decompressor */ opj_cio_t *cio; opj_image_t *image = NULL; // FIXME: Do some stupid work: is.seekg( 0, std::ios::end); size_t buf_size = (size_t)is.tellg(); char *dummy_buffer = new char[buf_size]; is.seekg(0, std::ios::beg); is.read( dummy_buffer, buf_size); unsigned char *src = (unsigned char*)dummy_buffer; uint32_t file_length = (uint32_t)buf_size; // 32bits truncation should be ok since DICOM cannot have larger than 2Gb image /* configure the event callbacks (not required) */ memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); event_mgr.error_handler = error_callback; event_mgr.warning_handler = warning_callback; event_mgr.info_handler = info_callback; /* set decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); // default blindly copied parameters.cp_layer=0; parameters.cp_reduce= res; // parameters.decod_format=-1; // parameters.cod_format=-1; const char jp2magic[] = "\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A"; if( memcmp( src, jp2magic, sizeof(jp2magic) ) == 0 ) { /* JPEG-2000 compressed image data ... sigh */ // gdcmData/ELSCINT1_JP2vsJ2K.dcm // gdcmData/MAROTECH_CT_JP2Lossy.dcm //gdcmWarningMacro( "J2K start like JPEG-2000 compressed image data instead of codestream" ); parameters.decod_format = 1; //JP2_CFMT; //assert(parameters.decod_format == JP2_CFMT); } else { /* JPEG-2000 codestream */ //parameters.decod_format = J2K_CFMT; //assert(parameters.decod_format == J2K_CFMT); assert( 0 ); } parameters.cod_format = 11; // PGX_DFMT; //assert(parameters.cod_format == PGX_DFMT); /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JP2); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); if(!image) { opj_destroy_decompress(dinfo); opj_cio_close(cio); //gdcmErrorMacro( "opj_decode failed" ); return 1; } //opj_cp_t * cp = ((opj_jp2_t*)dinfo->jp2_handle)->j2k->cp; //opj_tcp_t *tcp = &cp->tcps[0]; //opj_tccp_t *tccp = &tcp->tccps[0]; /* std::cout << "\n No of Cols In Image" << image->x1; std::cout << "\n No of Rows In Image" << image->y1; std::cout << "\n No of Components in Image" << image->numcomps; std::cout << "\n No of Resolutions"<< tccp->numresolutions << "\n"; */ //opj_j2k_t* j2k = NULL; //opj_jp2_t* jp2 = NULL; //jp2 = (opj_jp2_t*)dinfo->jp2_handle; //int reversible = jp2->j2k->cp->tcps->tccps->qmfbid; //std:: cout << reversible; int Dimensions[2]; { int compno = 0; opj_image_comp_t *comp = &image->comps[compno]; Dimensions[0]= comp->w; Dimensions[1] = comp->h; opj_cio_close(cio); } unsigned long rawlen = Dimensions[0]*Dimensions[1] * image->numcomps; //std::cout << "\nTest" <comps[0].factor; char *raw = new char[rawlen]; for (unsigned int compno = 0; compno < (unsigned int)image->numcomps; compno++) { const opj_image_comp_t *comp = &image->comps[compno]; int w = comp->w; int h = comp->h; uint8_t *data8 = (uint8_t*)raw + compno; for (int i = 0; i < w * h ; i++) { int v = image->comps[compno].data[i]; *data8 = (uint8_t)v; data8 += image->numcomps; } } gdcm::Writer w; gdcm::File &file = w.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); file.GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); gdcm::UIDGenerator uid; gdcm::DataElement de( gdcm::Tag(0x8,0x18) ); // SOP Instance UID de.SetVR( gdcm::VR::UI ); const char *u = uid.Generate(); de.SetByteValue( u, (uint32_t)strlen(u) ); ds.Insert( de ); gdcm::DataElement de1( gdcm::Tag(0x8,0x16) ); de1.SetVR( gdcm::VR::UI ); gdcm::MediaStorage ms( gdcm::MediaStorage::VLWholeSlideMicroscopyImageStorage ); de1.SetByteValue( ms.GetString(), (uint32_t)strlen(ms.GetString())); ds.Insert( de1 ); gdcm::DataElement de2( gdcm::Tag(0x28,0x04) ); //de.SetTag(gdcm::Tag(0x28,0x04)); de2.SetVR( gdcm::VR::CS ); if(image->numcomps == 1) { const char mystr[] = "MONOCHROME2"; de2.SetByteValue(mystr, (uint32_t)strlen(mystr)); } else { const char mystr1[] = "RGB"; de2.SetByteValue(mystr1, (uint32_t)strlen(mystr1)); } ds.Insert( de2 ); gdcm::Attribute<0x0028,0x0100> at = {8}; ds.Insert( at.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0002> at1 = { (uint16_t)image->numcomps}; ds.Insert( at1.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0101> at2 = {8}; ds.Insert( at2.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0102> at3 = {7}; ds.Insert( at3.GetAsDataElement() ); if (flag == 1) //This flag is to write Image Information { for (int i=0; i <= res; i++) // Loop to set different dimensions of all resolution { int a = 1; int b =1; while(a!=((res+1)-i)) { b = b*2; a = a+1; } uint16_t row = (uint16_t)((image->y1)/b); uint16_t col = (uint16_t)((image->x1)/b); gdcm::Element el2; el2.SetValue(i+1); gdcm::DataElement rfn = el2.GetAsDataElement(); //rfn ---> reference frame number rfn.SetTag( gdcm::Tag(0x0008,0x1160) ); gdcm::Element el; el.SetValue(1,0); el.SetValue(1,1); gdcm::DataElement ulr = el.GetAsDataElement(); //ulr --> upper left col/row ulr.SetTag( gdcm::Tag(0x0048,0x0201) ); gdcm::Element el1; el1.SetValue(col,0); el1.SetValue(row,1); gdcm::DataElement brr = el1.GetAsDataElement(); brr.SetTag( gdcm::Tag(0x0048,0x0202) ); //brr --> bottom right col/row gdcm::Item it; gdcm::DataSet &nds = it.GetNestedDataSet(); nds.Insert( rfn ); nds.Insert(ulr); nds.Insert(brr); sq->AddItem(it); }//For loop gdcm::File &file2 = w.GetFile(); gdcm::DataSet &ds1 = file2.GetDataSet(); gdcm::Attribute<0x0048,0x0006> row1 = {(unsigned short)image->y1}; ds1.Insert( row1.GetAsDataElement() ); gdcm::Attribute<0x0048,0x0007> col1 = {(unsigned short)image->x1}; ds1.Insert( col1.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0008> Number_Of_Frames = {res+1}; ds1.Insert( Number_Of_Frames.GetAsDataElement() ); gdcm::DataElement des( gdcm::Tag(0x0048,0x0200) ); des.SetVR(gdcm::VR::SQ); des.SetValue(*sq); des.SetVLToUndefined(); ds1.Insert(des); theStreamWriter.SetFile(file2); if (!theStreamWriter.WriteImageInformation()) { std::cerr << "unable to write image information" << std::endl; return 1; //the CanWrite function should prevent getting here, else, //that's a test failure } ds1.Remove( gdcm::Tag(0x0048,0x0006) ); ds1.Remove( gdcm::Tag(0x0048,0x0007) ); ds1.Remove( gdcm::Tag(0x0028,0x0008) ); }//if (flag == 1) //This flag is to write Image Information gdcm::Attribute<0x0048,0x0006> row = {(unsigned short)image->comps[0].w}; ds.Insert( row.GetAsDataElement() ); gdcm::Attribute<0x0048,0x0007> col = {(unsigned short)image->comps[0].h}; ds.Insert( col.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0008> Number_Of_Frames = {1}; ds.Insert( Number_Of_Frames.GetAsDataElement() ); theStreamWriter.SetFile(file); if (!theStreamWriter.CanWriteFile()) { delete [] raw; std::cerr << "Not able to write" << std::endl; return 0;//this means that the file was unwritable, period. //very similar to a ReadImageInformation failure } // Important to write here std::vector extent = gdcm::ImageHelper::GetDimensionsValue(file); unsigned short xmax = (uint16_t)extent[0]; unsigned short ymax = (uint16_t)extent[1]; unsigned short theChunkSize = 4; unsigned short ychunk = (unsigned short)(extent[1]/theChunkSize); //go in chunk sizes of theChunkSize unsigned short zmax = (uint16_t)extent[2]; //std::cout << "\n"<numcomps<<"\n"; if (xmax == 0 || ymax == 0) { std::cerr << "Image has no size, unable to write zero-sized image." << std::endl; return 0; } int z, y, nexty; unsigned long prevLen = 0; //when going through the char buffer, make sure to grab //the bytes sequentially. So, store how far you got in the buffer with each iteration. for (z = 0; z < zmax; ++z) { for (y = 0; y < ymax; y += ychunk) { nexty = y + ychunk; if (nexty > ymax) nexty = ymax; theStreamWriter.DefinePixelExtent(0, xmax, (uint16_t)y, (uint16_t)nexty, (uint16_t)z, (uint16_t)(z+1)); unsigned long len = theStreamWriter.DefineProperBufferLength(); //std::cout << "\n" < ymax) nexty = ymax; reader.DefinePixelExtent(xmin, xmax, (uint16_t)y, (uint16_t)nexty, (uint16_t)z, (uint16_t)(z+1)); unsigned long len = reader.DefineProperBufferLength(); char* finalBuffer = new char[len]; if (reader.CanReadImage()) { bool result = reader.Read(finalBuffer, len); if( !result ) { std::cerr << "res2 failure:" << std::endl; delete [] finalBuffer; return 1; } else { // std::cout<< "Able to read"; //delete [] finalBuffer; // return 0; //essentially, we're going to skip this file since it can't be read by the streamer } } else { std::cerr<< "Not able to put in read data buffer"<< std::endl; } theStreamWriter.DefinePixelExtent(xmin, xmax, (uint16_t)y, (uint16_t)nexty, (uint16_t)z, (uint16_t)(z+1)); // unsigned long len = theStreamWriter.DefineProperBufferLength(); //std::cout << "\n" < start, std::vector end) { //std::vector::const_iterator it = filenames.begin(); gdcm::StreamImageReader reader; reader.SetFileName( filename ); if (!reader.ReadImageInformation()) { std::cerr << "unable to read image information" << std::endl; return 1; //unable to read tags as expected. } gdcm::File file1 = reader.GetFile(); gdcm::DataSet ds1 = file1.GetDataSet(); gdcm::Writer w; gdcm::File &file = w.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); file.GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); gdcm::DataElement uid = ds1.GetDataElement( gdcm::Tag(0x0008,0x0018) ); ds.Insert( uid ); gdcm::DataElement ms = ds1.GetDataElement( gdcm::Tag(0x0008,0x0016) ); ds.Insert( ms ); gdcm::DataElement mystr = ds1.GetDataElement( gdcm::Tag(0x0028,0x0004) ); ds.Insert( mystr ); if(res == 0) { gdcm::DataElement seq = ds1.GetDataElement( gdcm::Tag(0x0048,0x0200) ); ds.Insert(seq); } else { std::vector extent = reader.GetDimensionsValueForResolution(res); gdcm::SmartPointer sq = new gdcm::SequenceOfItems(); sq->SetLengthToUndefined(); gdcm::Element el1; el1.SetValue(res); gdcm::DataElement rfn = el1.GetAsDataElement(); //rfn ---> reference frame number rfn.SetTag( gdcm::Tag(0x0008,0x1160) ); gdcm::Element el2; if(tile == 1) { el2.SetValue((unsigned short)start[0],0); el2.SetValue((unsigned short)start[1],1); } else { el2.SetValue(1,0); el2.SetValue(1,1); } gdcm::DataElement ulr = el2.GetAsDataElement(); //ulr --> upper left col/row ulr.SetTag( gdcm::Tag(0x0048,0x0201) ); gdcm::Element el3; if(tile == 1) { el3.SetValue((unsigned short)end[0],0); el3.SetValue((unsigned short)end[1],1); } else { el3.SetValue((unsigned short)extent[0],0); el3.SetValue((unsigned short)extent[1],1); } gdcm::DataElement brr = el3.GetAsDataElement(); brr.SetTag( gdcm::Tag(0x0048,0x0202) ); //brr --> bottom right col/row gdcm::Item it; gdcm::DataSet &nds = it.GetNestedDataSet(); nds.Insert( rfn ); nds.Insert(ulr); nds.Insert(brr); sq->AddItem(it); gdcm::DataElement des( gdcm::Tag(0x0048,0x0200) ); des.SetVR(gdcm::VR::SQ); des.SetValue(*sq); des.SetVLToUndefined(); ds.Insert(des); } gdcm::DataElement row = ds1.GetDataElement( gdcm::Tag(0x0048,0x0006) ); assert( row.GetVR() == gdcm::VR::UL ); ds.Insert(row); gdcm::DataElement col = ds1.GetDataElement( gdcm::Tag(0x0048,0x0007) ); ds.Insert(col); gdcm::DataElement Number_Of_Frames = ds1.GetDataElement( gdcm::Tag(0x0028,0x0008) ); ds.Insert(Number_Of_Frames); gdcm::Element el; el.SetFromDataElement( Number_Of_Frames ); uint16_t No_Of_Resolutions = (uint16_t)el.GetValue(0); //std::cout << "HERE NO. "<< No_Of_Resolutions; gdcm::DataElement BA = ds1.GetDataElement( gdcm::Tag(0x0028,0x0100) ); ds.Insert( BA ); gdcm::DataElement SPP = ds1.GetDataElement( gdcm::Tag(0x0028,0x0002) ); ds.Insert( SPP ); gdcm::DataElement BS = ds1.GetDataElement( gdcm::Tag(0x0028,0x0101) ); ds.Insert( BS ); gdcm::DataElement HB = ds1.GetDataElement( gdcm::Tag(0x0028,0x0102) ); ds.Insert( HB ); theStreamWriter.SetFile(file); if (!theStreamWriter.WriteImageInformation()) { std::cerr << "unable to write image information" << std::endl; return 1; //the CanWrite function should prevent getting here, else, //that's a test failure } bool b = true; if(res == 0) { for(int i = 1 ; i <= No_Of_Resolutions; ++i) { b = b && StreamImageRead_Write( theStreamWriter, reader, i, of, tile , start , end ); } } else b = b && StreamImageRead_Write( theStreamWriter, reader, res, of ,tile, start, end ); return b; } static bool Different_Resolution_From_jp2( gdcm::StreamImageWriter & theStreamWriter, const char *filename, std::ostream& of, int nres) { //std::vector::const_iterator it = filenames.begin(); bool b = true; int flag = 1; gdcm::SmartPointer sq = new gdcm::SequenceOfItems(); sq->SetLengthToUndefined(); int resolutions; if(nres==0) resolutions = No_Of_Resolutions(filename); else resolutions = nres; for(int i = resolutions-1 ; i>=0; --i) { b = b && Write_Resolution( theStreamWriter, filename, i, of ,flag,sq); flag = 0; } return b; } static void PrintVersion() { std::cout << "gdcmstream: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; } static void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcmstream [OPTION] input.dcm output.dcm" << std::endl; } static void end_of_WSIFile(std::ostream& of) { uint16_t firstTag1 = 0xfffe; uint16_t secondTag1 = 0xe0dd; uint32_t thirdTag1 = 0x00000000; //uint16_t fourthTag1 = 0xffff; const int theBufferSize1 = 2*sizeof(uint16_t)+sizeof(uint32_t); char* tmpBuffer2 = new char[theBufferSize1]; memcpy(&(tmpBuffer2[0]), &firstTag1, sizeof(uint16_t)); memcpy(&(tmpBuffer2[sizeof(uint16_t)]), &secondTag1, sizeof(uint16_t)); memcpy(&(tmpBuffer2[2*sizeof(uint16_t)]), &thirdTag1, sizeof(uint32_t)); //memcpy(&(tmpBuffer2[3*sizeof(uint16_t)]), &fourthTag1, sizeof(uint16_t)); assert( of && !of.eof() && of.good() ); of.write(tmpBuffer2, theBufferSize1); of.flush(); assert( of ); } int main (int argc, char *argv[]) { int c; //int digit_optind = 0; //std::string filename; //std::string outfilename; gdcm::Filename filename; gdcm::Filename outfilename; std::string root; int rootuid = 0; int verbose = 0; int warning = 0; int debug = 0; int error = 0; int help = 0; int version = 0; int nres = 0; int res = 0; int tile = 0; std::vector start; std::vector end; while (1) { //int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"input", 1, 0, 0}, {"output", 1, 0, 0}, // General options ! {"verbose", 0, &verbose, 1}, {"warning", 0, &warning, 1}, {"debug", 0, &debug, 1}, {"error", 0, &error, 1}, {"help", 0, &help, 1}, {"version", 0, &version, 1}, {"resolution", 1, &nres, 1}, {"resolution-only", 1, &res, 1}, {"roi-start", 1, &tile, 1}, {"roi-end", 1, &tile, 1}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "i:o:VWDEhv:r:n:",long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: { const char *s = long_options[option_index].name; (void)s; //printf ("option %s", s); if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); assert( filename.IsEmpty() ); filename = optarg; } //printf (" with arg %s, index = %d", optarg, option_index) else if( option_index == 1 ) /* input */ { assert( strcmp(s, "output") == 0 ); assert( outfilename.IsEmpty() ); outfilename = optarg; } //printf (" with arg %s, index = %d", optarg, option_index); else if( option_index == 8 ) /* number of resolution */ { assert( strcmp(s, "resolution") == 0 ); nres = atoi(optarg); } else if( option_index == 9 ) /* number of resolution */ { assert( strcmp(s, "resolution-only") == 0 ); res = atoi(optarg); } else if( option_index == 10 ) /* tile */ { assert( strcmp(s, "roi-start") == 0 ); tile = 1; unsigned int n = readvector(start, optarg); assert( n == 2 ); (void)n; } else if( option_index == 11 ) /* tile */ { assert( strcmp(s, "roi-end") == 0 ); tile = 1; unsigned int n = readvector(end, optarg); assert( n == 2 ); (void)n; } //printf ("\n"); } } break; case 'i': assert( filename.IsEmpty() ); filename = optarg; break; case 'o': assert( outfilename.IsEmpty() ); outfilename = optarg; break; // General option case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case 'r': nres = atoi(optarg); break; case 'n': res = atoi(optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } // For now only support one input / one output if (optind < argc) { //printf ("non-option ARGV-elements: "); //std::cout << "HERE"; std::vector files; while (optind < argc) { //printf ("%s\n", argv[optind]); files.push_back( argv[optind] ); } //printf ("\n"); if( files.size() == 2 && filename.IsEmpty() && outfilename.IsEmpty() ) { filename = files[0].c_str(); outfilename = files[ files.size() - 1 ].c_str(); } else { PrintHelp(); return 1; } }//if (optind < argc) if( version ) { std::cout << "version" << std::endl; PrintVersion(); return 0; } if( help ) { std::cout << "help here" << std::endl; PrintHelp(); return 0; } if( filename.IsEmpty()) { std::cerr << "Need input file (-i)\n"; PrintHelp(); return 1; } if( outfilename.IsEmpty() ) { std::cerr << "Need output file (-o)\n"; PrintHelp(); return 1; } // Debug is a little too verbose gdcm::Trace::SetDebug( (debug > 0 ? true : false)); gdcm::Trace::SetWarning( (warning > 0 ? true : false)); gdcm::Trace::SetError( (error > 0 ? true : false)); // when verbose is true, make sure warningerror are turned on: if( verbose ) { gdcm::Trace::SetWarning( (verbose > 0 ? true : false) ); gdcm::Trace::SetError( (verbose > 0 ? true : false) ); } gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( "gdcmstream" ); if( !rootuid ) { // only read the env var is no explicit cmd line option // maybe there is an env var defined... let's check const char *rootuid_env = getenv("GDCM_ROOT_UID"); if( rootuid_env ) { rootuid = 1; root = rootuid_env; } } if( rootuid ) { // root is set either by the cmd line option or the env var if( !gdcm::UIDGenerator::IsValid( root.c_str() ) ) { std::cerr << "specified Root UID is not valid: " << root << std::endl; return 1; } gdcm::UIDGenerator::SetRoot( root.c_str() ); } const char *inputextension = filename.GetExtension(); //const char *outputextension = outfilename.GetExtension(); gdcm::StreamImageWriter theStreamWriter; std::ofstream of; of.open( outfilename, std::ios::out | std::ios::binary ); theStreamWriter.SetStream(of); if( inputextension ) { if( gdcm::System::StrCaseCmp(inputextension,".jp2") == 0 ) { if( !Different_Resolution_From_jp2( theStreamWriter, filename,of,nres ) ) return 1; end_of_WSIFile(of); } if( gdcm::System::StrCaseCmp(inputextension,".dcm") == 0 ) { Different_Resolution_From_DICOM( theStreamWriter, filename, of, res , tile , start , end); //if(!StreamImageRead_Write( theStreamWriter, filename, 0)) return 1; end_of_WSIFile(of); } } // gdcm::StreamImageReader ... return 0; } GDCM-3.0.10/Applications/Cxx/gdcmtar.cxx000066400000000000000000001500401412732066400176470ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * tar is a UNIX program for archiving. * Two types of operations are possible: concatenate / extract * Thus the name of 'gdcmtar' to concatenate a list of 2D slices into a multi frames * and the other way around: extract 2D slices from a multi frames image * It also support the fake multi frame image (CSA MOSAIC) */ #include "gdcmReader.h" #include "gdcmCSAHeader.h" #include "gdcmVersion.h" #include "gdcmImageReader.h" #include "gdcmDataElement.h" #include "gdcmImageWriter.h" #include "gdcmSplitMosaicFilter.h" #include "gdcmFilename.h" #include "gdcmFilenameGenerator.h" #include "gdcmDirectionCosines.h" #include "gdcmImageHelper.h" #include "gdcmUIDGenerator.h" #include "gdcmUIDs.h" #include "gdcmGlobal.h" #include "gdcmDirectory.h" #include "gdcmScanner.h" #include "gdcmIPPSorter.h" #include "gdcmAttribute.h" #include "gdcmAnonymizer.h" #include "gdcmTagKeywords.h" #include "gdcmMrProtocol.h" #include #include #include /* for printf */ #include /* for exit */ #include #include static void PrintVersion() { std::cout << "gdcmtar: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; } static void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcmtar [OPTION] [FILE]" << std::endl; std::cout << "Concatenate/Extract DICOM files.\n"; std::cout << "Parameter (required):" << std::endl; std::cout << " -i --input DICOM filename" << std::endl; std::cout << " -o --output DICOM filename" << std::endl; std::cout << "Options:" << std::endl; std::cout << " --enhance Enhance (default)" << std::endl; std::cout << " -U --unenhance Unenhance" << std::endl; std::cout << " -M --mosaic Split SIEMENS Mosaic image into multiple frames." << std::endl; std::cout << " --mosaic-private When splitting SIEMENS Mosaic image into multiple frames, preserve private attributes (advanced user only)." << std::endl; std::cout << " -p --pattern Specify trailing file pattern." << std::endl; std::cout << " --root-uid Root UID." << std::endl; //std::cout << " --resources-path Resources path." << std::endl; std::cout << "General Options:" << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " -v --version print version." << std::endl; std::cout << "Env var:" << std::endl; std::cout << " GDCM_ROOT_UID Root UID" << std::endl; //std::cout << " GDCM_RESOURCES_PATH path pointing to resources files (Part3.xml, ...)" << std::endl; } /* * The following example is a basic sorted which should work in generic cases. * It sort files based on: * Study Instance UID * Series Instance UID * Frame of Reference UID * Image Orientation (Patient) * Image Position (Patient) (Sorting based on IPP + IOP) */ namespace gdcm { const Tag T0(0x0008,0x0016); // SOP Class UID const Tag T1(0x0020,0x000d); // Study Instance UID const Tag T2(0x0020,0x000e); // Series Instance UID const Tag T3(0x0020,0x0052); // Frame of Reference UID const Tag T4(0x0020,0x0037); // Image Orientation (Patient) const Tag T5(0x0008,0x0008); // Image Type class DiscriminateVolume { private: static const bool debuggdcmtar = false; std::vector< Directory::FilenamesType > SortedFiles; std::vector< Directory::FilenamesType > UnsortedFiles; Directory::FilenamesType GetAllFilenamesFromTagToValue( Scanner const & s, Directory::FilenamesType const &filesubset, Tag const &t, const char *valueref) { Directory::FilenamesType theReturn; if( valueref ) { size_t len = strlen( valueref ); Directory::FilenamesType::const_iterator file = filesubset.begin(); for(; file != filesubset.end(); ++file) { const char *filename = file->c_str(); const char * value = s.GetValue(filename, t); if( value && strncmp(value, valueref, len ) == 0 ) { theReturn.push_back( filename ); } } } return theReturn; } class frame_diff /* */ { public: bool operator<(const frame_diff &rhs) const { (void)rhs; return true; } }; static frame_diff get_frame_diff( const char* filename ) { frame_diff ret; gdcm::Reader reader; reader.SetFileName( filename ); gdcm::Tag dummy(0x7fe0,0x0000); std::set skiptags; skiptags.insert( dummy ); if ( !reader.ReadUpToTag( dummy, skiptags) ) { assert(0); } gdcm::CSAHeader csa; const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); const gdcm::PrivateTag &t1 = csa.GetCSAImageHeaderInfoTag(); //const gdcm::PrivateTag &t2 = csa.GetCSASeriesHeaderInfoTag(); //const gdcm::PrivateTag &t3 = csa.GetCSADataInfo(); //bool found = false; if( ds.FindDataElement( t1 ) ) { csa.LoadFromDataElement( ds.GetDataElement( t1 ) ); assert( csa.GetFormat() == gdcm::CSAHeader::SV10 || csa.GetFormat() == gdcm::CSAHeader::NOMAGIC ); // SIEMENS / Diffusion const CSAElement &bvalue = csa.GetCSAElementByName( "B_value" ); (void)bvalue; const CSAElement &bmatrix = csa.GetCSAElementByName( "B_matrix" ); (void)bmatrix; const CSAElement &dgd = csa.GetCSAElementByName( "DiffusionGradientDirection" ); (void)dgd; //assert(0); } else { assert(0); } return ret; } void ProcessAIOP(Scanner const & s, Directory::FilenamesType const & subset, const char *iopval) { if( debuggdcmtar ) std::cout << "IOP: " << iopval << std::endl; bool is_diffusion = false; gdcm::Scanner::ValuesType imagetypes = s.GetValues(gdcm::T5); if( imagetypes.size() == 1 ) { const std::string & imagetype = *imagetypes.begin(); //gdcm::Attribute<0x0008, 0x0008> at; //at.SetValue( imagetype ); std::string::size_type pos = imagetype.find( "DIFFUSION" ); is_diffusion = (pos != std::string::npos); } if( is_diffusion ) { std::multimap mm; for( Directory::FilenamesType::const_iterator file = subset.begin(); file != subset.end(); ++file) { //std::cerr << *file << std::endl; mm.insert( std::make_pair(get_frame_diff( file->c_str() ), file->c_str()) ); } //assert(0); for( std::multimap::const_iterator it = mm.begin(); it != mm.end(); ++it ) { std::cerr << it->second << std::endl; } SortedFiles.push_back( subset ); } else { IPPSorter ipp; ipp.SetComputeZSpacing( true ); ipp.SetZSpacingTolerance( 1e-3 ); // ?? bool b = ipp.Sort( subset ); if( !b ) { // If you reach here this means you need one more parameter to discriminate this // series. Eg. T1 / T2 intertwined. Multiple Echo (0018,0081) if( debuggdcmtar ) { std::cerr << "Failed to sort: " << subset.begin()->c_str() << std::endl; for( Directory::FilenamesType::const_iterator file = subset.begin(); file != subset.end(); ++file) { std::cerr << *file << std::endl; } } UnsortedFiles.push_back( subset ); return ; } if( debuggdcmtar ) ipp.Print( std::cout ); SortedFiles.push_back( ipp.GetFilenames() ); } } void ProcessAFrameOfRef(Scanner const & s, Directory::FilenamesType const & subset, const char * frameuid) { // In this subset of files (belonging to same series), let's find those // belonging to the same Frame ref UID: Directory::FilenamesType files = GetAllFilenamesFromTagToValue( s, subset, T3, frameuid); std::set< std::string > iopset; for( Directory::FilenamesType::const_iterator file = files.begin(); file != files.end(); ++file) { //std::cout << *file << std::endl; const char * value = s.GetValue(file->c_str(), gdcm::T4 ); assert( value ); iopset.insert( value ); } size_t n = iopset.size(); if ( n == 0 ) { assert( files.empty() ); return; } if( debuggdcmtar ) std::cout << "Frame of Ref: " << frameuid << std::endl; if ( n == 1 ) { ProcessAIOP(s, files, iopset.begin()->c_str() ); } else { const char *f = files.begin()->c_str(); if( debuggdcmtar ) std::cerr << "More than one IOP: " << f << std::endl; // Make sure that there is actually 'n' different IOP gdcm::DirectionCosines ref; gdcm::DirectionCosines dc; for( std::set< std::string >::const_iterator it = iopset.begin(); it != iopset.end(); ++it ) { ref.SetFromString( it->c_str() ); for( Directory::FilenamesType::const_iterator file = files.begin(); file != files.end(); ++file) { std::string value = s.GetValue(file->c_str(), gdcm::T4 ); if( value != it->c_str() ) { dc.SetFromString( value.c_str() ); const double crossdot = ref.CrossDot(dc); const double eps = std::fabs( 1. - crossdot ); if( eps < 1e-6 ) { std::cerr << "Problem with IOP discrimination: " << file->c_str() << " " << it->c_str() << std::endl; return; } } } } // If we reach here this means there is actually 'n' different IOP for( std::set< std::string >::const_iterator it = iopset.begin(); it != iopset.end(); ++it ) { const char *iopvalue = it->c_str(); Directory::FilenamesType iopfiles = GetAllFilenamesFromTagToValue( s, files, T4, iopvalue ); ProcessAIOP(s, iopfiles, iopvalue ); } } } void ProcessASeries(Scanner const & s, const char * seriesuid) { if( debuggdcmtar ) std::cout << "Series: " << seriesuid << std::endl; // let's find all files belonging to this series: Directory::FilenamesType seriesfiles = GetAllFilenamesFromTagToValue( s, s.GetFilenames(), T2, seriesuid); gdcm::Scanner::ValuesType vt3 = s.GetValues(T3); for( gdcm::Scanner::ValuesType::const_iterator it = vt3.begin() ; it != vt3.end(); ++it ) { ProcessAFrameOfRef(s, seriesfiles, it->c_str()); } } void ProcessAStudy(Scanner const & s, const char * studyuid) { if( debuggdcmtar ) std::cout << "Study: " << studyuid << std::endl; gdcm::Scanner::ValuesType vt2 = s.GetValues(T2); if( vt2.empty() ) std::cerr << "No Series Found" << std::endl; for( gdcm::Scanner::ValuesType::const_iterator it = vt2.begin() ; it != vt2.end(); ++it ) { ProcessASeries(s, it->c_str()); } } public: void Print( std::ostream & os ) { os << "Sorted Files: " << std::endl; for( std::vector< Directory::FilenamesType >::const_iterator it = SortedFiles.begin(); it != SortedFiles.end(); ++it ) { os << "Group: " << std::endl; for( Directory::FilenamesType::const_iterator file = it->begin(); file != it->end(); ++file) { os << *file << std::endl; } } os << "Unsorted Files: " << std::endl; for( std::vector< Directory::FilenamesType >::const_iterator it = UnsortedFiles.begin(); it != UnsortedFiles.end(); ++it ) { os << "Group: " << std::endl; for( Directory::FilenamesType::const_iterator file = it->begin(); file != it->end(); ++file) { os << *file << std::endl; } } } std::vector< Directory::FilenamesType > const & GetSortedFiles() const { return SortedFiles; } std::vector< Directory::FilenamesType > const & GetUnsortedFiles() const { return UnsortedFiles; } void ProcessIntoVolume( Scanner const & s ) { gdcm::Scanner::ValuesType vt1 = s.GetValues( gdcm::T1 ); for( gdcm::Scanner::ValuesType::const_iterator it = vt1.begin() ; it != vt1.end(); ++it ) { ProcessAStudy( s, it->c_str() ); } } }; static bool ConcatenateImages(Image &im1, Image const &im2) { DataElement& de1 = im1.GetDataElement(); if( de1.GetByteValue() ) { const ByteValue *bv1 = de1.GetByteValue(); std::vector v1 = *bv1; const DataElement& de2 = im2.GetDataElement(); const ByteValue *bv2 = de2.GetByteValue(); const std::vector & v2 = *bv2; v1.insert( v1.end(), v2.begin(), v2.end() ); de1.SetByteValue(&v1[0], (uint32_t)v1.size()); } else if( de1.GetSequenceOfFragments() ) { SequenceOfFragments *sqf1 = de1.GetSequenceOfFragments(); assert( sqf1 ); const DataElement& de2 = im2.GetDataElement(); const SequenceOfFragments *sqf2 = de2.GetSequenceOfFragments(); assert( sqf2 ); assert( sqf2->GetNumberOfFragments() == 1 ); const Fragment& frag = sqf2->GetFragment(0); sqf1->AddFragment(frag); } else { return false; } // update meta info unsigned int z = im1.GetDimension(2); im1.SetDimension(2, z + 1 ); return true; } static void InsertIfExist( DataSet &enhds, const DataSet &ds, const Tag & t ) { if( ds.FindDataElement( t ) ) { assert( !enhds.FindDataElement( t ) ); enhds.Insert( ds.GetDataElement( t ) ); } } } // namespace gdcm static int MakeImageEnhanced( std::string const & filename, std::string const &outfilename ) { if( !gdcm::System::FileIsDirectory(filename.c_str()) ) { std::cerr << "Input needs to be directory" << std::endl; return 1; } gdcm::Directory d; d.Load( filename.c_str(), true ); // recursive ! gdcm::Scanner s; s.AddTag( gdcm::T0 ); s.AddTag( gdcm::T1 ); s.AddTag( gdcm::T2 ); s.AddTag( gdcm::T3 ); s.AddTag( gdcm::T4 ); s.AddTag( gdcm::T5 ); bool b = s.Scan( d.GetFilenames() ); if( !b ) { std::cerr << "Scanner failed" << std::endl; return 1; } // For now only accept MR Image Storage gdcm::Scanner::ValuesType vt = s.GetValues(gdcm::T0); if( vt.size() != 1 ) return 1; const char *sop = vt.begin()->c_str(); gdcm::MediaStorage msorig = gdcm::MediaStorage::GetMSType( sop ); if( msorig != gdcm::MediaStorage::MRImageStorage && msorig != gdcm::MediaStorage::CTImageStorage ) { std::cerr << "Sorry MediaStorage not supported: [" << sop << "]" << std::endl; return 1; } gdcm::DiscriminateVolume dv; dv.ProcessIntoVolume( s ); // dv.Print( std::cout ); // gdcm::DataElement &de = im.GetImage().GetDataElement(); std::vector< gdcm::Directory::FilenamesType > const &sorted = dv.GetSortedFiles(); if( !gdcm::System::MakeDirectory( outfilename.c_str() ) ) { std::cerr << "Could not create dir: " << outfilename << std::endl; return 1; } for( std::vector< gdcm::Directory::FilenamesType >::const_iterator it = sorted.begin(); it != sorted.end(); ++it ) { gdcm::ImageWriter im0; gdcm::Directory::FilenamesType const & files = *it; gdcm::Directory::FilenamesType::const_iterator file = files.begin(); const char *reffile = file->c_str(); // construct the target dir: const char* studyuid = s.GetValue(reffile, gdcm::T1); const char* seriesuid = s.GetValue(reffile, gdcm::T2); const char* frameuid = s.GetValue(reffile, gdcm::T3); std::string targetdir = outfilename; targetdir += '/'; targetdir += studyuid; targetdir += '/'; targetdir += seriesuid; targetdir += '/'; targetdir += frameuid; // construct the target name: std::string targetname = targetdir; targetdir += "/old"; // make sure the dir exist first: if( !gdcm::System::MakeDirectory( targetdir.c_str() ) ) { std::cerr << "Could not create dir: " << targetdir << std::endl; return 1; } gdcm::FilenameGenerator fg; fg.SetNumberOfFilenames( files.size() ); fg.SetPrefix( targetdir.c_str() ); fg.SetPattern( "%04d.dcm" ); if( !fg.Generate() ) { assert( 0 ); } gdcm::ImageReader reader0; reader0.SetFileName( reffile ); if( !reader0.Read() ) { assert( 0 ); } gdcm::Image ¤tim = reader0.GetImage(); assert( currentim.GetNumberOfDimensions( ) == 2 ); currentim.SetNumberOfDimensions( 3 ); size_t count = 0; //gdcm::ImageWriter writer; gdcm::Writer writer0; writer0.SetFileName( fg.GetFilename( count ) ); writer0.SetFile( reader0.GetFile() ); writer0.GetFile().GetHeader().Clear(); if( !writer0.Write() ) { assert( 0 ); } ++file; ++count; // insert Enhanced MR Image Storage if( false ) { gdcm::DataSet & enhds = im0.GetFile().GetDataSet(); gdcm::DataSet & ds = reader0.GetFile().GetDataSet(); gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0005) ); // SpecificCharacterSet gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0008) ); // ImageType gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0012) ); // InstanceCreationDate gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0013) ); // InstanceCreationTime gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0020) ); // StudyDate gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0021) ); // StudyTime //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0022) ); // AcquisitionDate gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0023) ); // ContentDate gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0030) ); // StudyTime gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0031) ); // SeriesTime //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0032) ); // AcquisitionTime gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0033) ); // ContentTime gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0050) ); // AccessionNumber gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0070) ); // Manufacturer gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0080) ); // InstitutionName gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0081) ); // InstitutionAddress gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x0090) ); // ReferringPhysicianName gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x1010) ); // StationName gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x1030) ); // StudyDescription gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x103e) ); // SeriesDescription gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x1040) ); // InstitutionalDepartme gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x1050) ); // PerformingPhysicianNa gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x8,0x1090) ); // ManufacturerModelName gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0010,0x0010)); // PatientName gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0010,0x0020)); // gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0010,0x0030)); // gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0010,0x0040)); // gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0010,0x1010)); // gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0010,0x1030)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0020)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0021)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0022)); // gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0023)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0024)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0025)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0050)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0080)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0081)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0083)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0084)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0085)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0086)); // gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0087)); // gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0088)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0089)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0091)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0093)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0094)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x0095)); // gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x1000)); // gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x1020)); // gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x1030)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x1251)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x1310)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x1312)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x1314)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x1315)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x1316)); // //gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x1318)); // gdcm::InsertIfExist( enhds, ds, gdcm::Tag(0x0018,0x5100)); // { gdcm::SmartPointer sqi1 = new gdcm::SequenceOfItems; /* (5200,9229) SQ (Sequence with undefined length) # u/l,1 Shared Functional Groups Sequence (fffe,e000) na (Item with undefined length) (0018,9006) SQ (Sequence with undefined length) # u/l,1 MR Imaging Modifier Sequence (fffe,e000) na (Item with undefined length) (0018,0095) DS [109 ] # 4,1 Pixel Bandwidth (0018,9020) CS [NONE] # 4,1 Magnetization Transfer (0018,9022) CS [NO] # 2,1 Blood Signal Nulling (0018,9028) CS [NONE] # 4,1 Tagging (0018,9098) FD 63.8799 # 8,1-2 Transmitter Frequency */ gdcm::Item item0; gdcm::DataSet &subds0 = item0.GetNestedDataSet(); { gdcm::SmartPointer sqi0 = new gdcm::SequenceOfItems; const gdcm::Tag sisq0(0x0018,0x9006); gdcm::DataElement de0( sisq0 ); de0.SetVR( gdcm::VR::SQ ); de0.SetValue( *sqi0 ); subds0.Insert( de0 ); gdcm::Item item1; gdcm::DataSet &subds1 = item1.GetNestedDataSet(); gdcm::InsertIfExist( subds1, ds, gdcm::Tag(0x0018,0x0095)); // gdcm::InsertIfExist( subds1, ds, gdcm::Tag(0x0018,0x9020)); // gdcm::InsertIfExist( subds1, ds, gdcm::Tag(0x0018,0x9022)); // gdcm::InsertIfExist( subds1, ds, gdcm::Tag(0x0018,0x9028)); // gdcm::InsertIfExist( subds1, ds, gdcm::Tag(0x0018,0x9098)); // sqi0->AddItem( item1 ); } /* (0018,9042) SQ (Sequence with undefined length) # u/l,1 MR Receive Coil Sequence (fffe,e000) na (Item with undefined length) (0018,1250) SH [MULTI COIL] # 10,1 Receive Coil Name (0018,9041) LO (no value) # 0,1 Receive Coil Manufacturer Name (0018,9043) CS [MULTICOIL ] # 10,1 Receive Coil Type (0018,9044) CS [NO] # 2,1 Quadrature Receive Coil (0018,9045) SQ (Sequence with undefined length) # u/l,1 Multi-Coil Definition Sequence (fffe,e000) na (Item with undefined length) (0018,9047) SH [MULTI ELEMENT ] # 14,1 Multi-Coil Element Name (0018,9048) CS [YES ] # 4,1 Multi-Coil Element Used (fffe,e00d) (fffe,e0dd) (fffe,e00d) */ { gdcm::SmartPointer sqi0 = new gdcm::SequenceOfItems; const gdcm::Tag sisq0(0x0018,0x9042); gdcm::DataElement de0( sisq0 ); de0.SetVR( gdcm::VR::SQ ); de0.SetValue( *sqi0 ); subds0.Insert( de0 ); gdcm::Item item1; gdcm::DataSet &subds1 = item1.GetNestedDataSet(); gdcm::InsertIfExist( subds1, ds, gdcm::Tag(0x0018,0x1250)); // gdcm::InsertIfExist( subds1, ds, gdcm::Tag(0x0018,0x9041)); // gdcm::InsertIfExist( subds1, ds, gdcm::Tag(0x0018,0x9043)); // gdcm::InsertIfExist( subds1, ds, gdcm::Tag(0x0018,0x9044)); // //gdcm::InsertIfExist( subds1, ds, gdcm::Tag(0x0018,0x9045)); // sqi0->AddItem( item1 ); } sqi1->AddItem( item0 ); const gdcm::Tag sisq1(0x5200,0x9229); gdcm::DataElement de1( sisq1 ); de1.SetVR( gdcm::VR::SQ ); de1.SetValue( *sqi1 ); enhds.Insert( de1 ); } } for( ; file != files.end(); ++file, ++count ) { gdcm::ImageReader reader; reader.SetFileName( file->c_str() ); if( !reader.Read() ) { assert( 0 ); } const gdcm::Image &im = reader.GetImage(); //gdcm::ImageWriter writer; gdcm::Writer writer; writer.SetFileName( fg.GetFilename( count ) ); writer.SetFile( reader.GetFile() ); writer.GetFile().GetHeader().Clear(); if( !writer.Write() ) { assert( 0 ); } if( !ConcatenateImages(currentim, im) ) { assert( 0 ); } // check consistency if( false ) { //gdcm::DataSet & enhds = im0.GetFile().GetDataSet(); //gdcm::DataSet & ds = reader.GetFile().GetDataSet(); // TODO } } im0.SetFileName( (targetname + "/new.dcm").c_str() ); // im.SetFile( reader.GetFile() ); gdcm::DataSet &ds = im0.GetFile().GetDataSet(); gdcm::MediaStorage ms; switch( msorig ) { case gdcm::MediaStorage::CTImageStorage: ms = gdcm::MediaStorage::EnhancedCTImageStorage; break; case gdcm::MediaStorage::MRImageStorage: ms = gdcm::MediaStorage::EnhancedMRImageStorage; break; default: return 1; } gdcm::DataElement de( gdcm::Tag(0x0008, 0x0016) ); const char* msstr = gdcm::MediaStorage::GetMSString(ms); de.SetByteValue( msstr, (uint32_t)strlen(msstr) ); de.SetVR( gdcm::Attribute<0x0008, 0x0016>::GetVR() ); ds.Insert( de ); im0.SetImage( currentim ); if( !im0.Write() ) { std::cerr << "Could not write: " << std::endl; return 1; } } std::vector< gdcm::Directory::FilenamesType > const &unsorted = dv.GetUnsortedFiles(); if( !unsorted.empty() ) { std::string targetdir3 = outfilename; targetdir3 += "/unhandled"; if( !gdcm::System::MakeDirectory( targetdir3.c_str() ) ) { std::cerr << "Could not create dir: " << targetdir3 << std::endl; return 1; } std::cerr << "Could not process the following files (please report): " << std::endl; std::vector< gdcm::Directory::FilenamesType >::const_iterator it = unsorted.begin(); for( ; it != unsorted.end(); ++it ) { gdcm::Directory::FilenamesType const & files = *it; gdcm::Directory::FilenamesType::const_iterator file = files.begin(); for( ; file != files.end(); ++file ) { const char *f = file->c_str(); std::string targetdir2 = outfilename; targetdir2 += "/unhandled/"; gdcm::Filename fn2( f ); const char *outfn2 = fn2.GetName(); targetdir2 += outfn2; //std::cerr << f << " -> " << targetdir2 << std::endl; std::ifstream in( f, std::ios::binary ); std::ofstream out( targetdir2.c_str() , std::ios::binary ); out << in.rdbuf(); } } } return 0; } namespace gdcm { static inline void ReplaceIf(DataSet &rootds, const DataSet &ds, const Tag & t1, const Tag & t2 ) { if( !ds.FindDataElement( t1 ) ) return ; SmartPointer sqi1 = ds.GetDataElement( t1 ).GetValueAsSQ(); if( !sqi1 || sqi1->IsEmpty() ) return ; const Item &item1 = sqi1->GetItem(1); const DataSet & ds1 = item1.GetNestedDataSet(); if( !ds1.FindDataElement( t2 ) ) return ; rootds.Replace(ds1.GetDataElement( t2 )); } static bool RemapSharedIntoOld( gdcm::DataSet & ds, SequenceOfItems *sfgs, SequenceOfItems *pffgs, unsigned int index ) { assert( sfgs ); assert( pffgs ); assert( sfgs->GetNumberOfItems() == 1 ); Item const &item1 = sfgs->GetItem( 1 ); const DataSet & sfgs_ds = item1.GetNestedDataSet(); #if 1 // Repetition Time ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9112), Tag(0x0018,0x0080) ); // Echo Train Length ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9112), Tag(0x0018,0x0091) ); // Flip Angle ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9112), Tag(0x0018,0x1314) ); // Number of Averages ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9119), Tag(0x0018,0x0083) ); // Percent Sampling ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9125), Tag(0x0018,0x0093) ); // Percent Phase Field of View ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9125), Tag(0x0018,0x0094) ); // Receive Coil Name ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9042), Tag(0x0018,0x1250) ); // Transmit Coil Name ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9049), Tag(0x0018,0x1251) ); // InPlanePhaseEncodingDirection ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9125), Tag(0x0018,0x1312) ); // TransmitterFrequency ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9006), Tag(0x0018,0x9098) ); // InversionRecovery ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9115), Tag(0x0018,0x9009) ); // FlowCompensation ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9115), Tag(0x0018,0x9010) ); // ReceiveCoilType ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9042), Tag(0x0018,0x9043) ); // QuadratureReceiveCoil ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9042), Tag(0x0018,0x9044) ); // SlabThickness ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9107), Tag(0x0018,0x9104) ); // MultiCoilDefinitionSequence ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9042), Tag(0x0018,0x9045) ); // SlabOrientation ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9107), Tag(0x0018,0x9105) ); // MidSlabPosition ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9107), Tag(0x0018,0x9106) ); // OperatingModeSequence ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9112), Tag(0x0018,0x9176) ); // MRAcquisitionPhaseEncodingStepsOutOf ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9125), Tag(0x0018,0x9232) ); // SpecificAbsorptionRateSequence ReplaceIf(ds, sfgs_ds, Tag(0x0018,0x9112), Tag(0x0018,0x9239) ); // AnatomicRegionSequence ReplaceIf(ds, sfgs_ds, Tag(0x0020,0x9071), Tag(0x0008,0x2218) ); // Purpose of Reference Code Sequence // FIXME what if there is multiple purpose of rcs ? ReplaceIf(ds, sfgs_ds, Tag(0x0008,0x1140), Tag(0x0040,0xa170) ); #else for( DataSet::ConstIterator it = sfgs_ds.Begin(); it != sfgs_ds.End(); ++it ) { ds.Replace( *it ); } #endif Item const &item2 = pffgs->GetItem( index + 1 ); const DataSet & pffgs_ds = item2.GetNestedDataSet(); #if 1 // Effective Echo Time ReplaceIf(ds, pffgs_ds, Tag(0x0018,0x9114), Tag(0x0018,0x9082) ); // -> should also be Echo Time // Nominal Cardiac Trigger Delay Time ReplaceIf(ds, pffgs_ds, Tag(0x0018,0x9118), Tag(0x0020,0x9153) ); // Metabolite Map Description ReplaceIf(ds, pffgs_ds, Tag(0x0018,0x9152), Tag(0x0018,0x9080) ); // IPP ReplaceIf(ds, pffgs_ds, Tag(0x0020,0x9113), Tag(0x0020,0x0032) ); // IOP ReplaceIf(ds, pffgs_ds, Tag(0x0020,0x9116), Tag(0x0020,0x0037) ); // Slice Thickness ReplaceIf(ds, pffgs_ds, Tag(0x0028,0x9110), Tag(0x0018,0x0050) ); // Pixel Spacing ReplaceIf(ds, pffgs_ds, Tag(0x0028,0x9110), Tag(0x0028,0x0030) ); // window level ReplaceIf(ds, pffgs_ds, Tag(0x0028,0x9132), Tag(0x0028,0x1050) ); ReplaceIf(ds, pffgs_ds, Tag(0x0028,0x9132), Tag(0x0028,0x1051) ); // rescale slope/intercept ReplaceIf(ds, pffgs_ds, Tag(0x0028,0x9145), Tag(0x0028,0x1052) ); ReplaceIf(ds, pffgs_ds, Tag(0x0028,0x9145), Tag(0x0028,0x1053) ); ReplaceIf(ds, pffgs_ds, Tag(0x0028,0x9145), Tag(0x0028,0x1054) ); // FrameReferenceDateTime ReplaceIf(ds, pffgs_ds, Tag(0x0020,0x9111), Tag(0x0018,0x9151) ); // FrameAcquisitionDuration ReplaceIf(ds, pffgs_ds, Tag(0x0020,0x9111), Tag(0x0018,0x9220) ); // TemporalPositionIndex ReplaceIf(ds, pffgs_ds, Tag(0x0020,0x9111), Tag(0x0020,0x9128) ); // InStackPositionNumber ReplaceIf(ds, pffgs_ds, Tag(0x0020,0x9111), Tag(0x0020,0x9057) ); // FrameType ReplaceIf(ds, pffgs_ds, Tag(0x0018,0x9226), Tag(0x0008,0x9007) ); // DimensionIndexValues ReplaceIf(ds, pffgs_ds, Tag(0x0020,0x9111), Tag(0x0020,0x9157) ); // FrameAcquisitionDateTime ReplaceIf(ds, pffgs_ds, Tag(0x0020,0x9111), Tag(0x0018,0x9074) ); // Nominal Cardiac Trigger Delay Time -> Trigger Time //const DataElement &NominalCardiacTriggerDelayTime = // GetNestedDataElement(pffgs_ds, Tag(0x0018,0x9226), Tag(0x0008,0x9007) ); #endif // (0020,9228) UL 158 # 4, 1 ConcatenationFrameOffsetNumber gdcm::Attribute<0x0020,0x9228> at = { index }; ds.Replace( at.GetAsDataElement() ); return true; } } // namespace gdcm int main (int argc, char *argv[]) { int c; //int digit_optind = 0; int rootuid = 0; std::string filename; std::string outfilename; std::string root; int resourcespath = 0; int mosaic = 0; int mosaic_private = 0; int enhance = 1; int unenhance = 0; std::string xmlpath; int verbose = 0; int warning = 0; int debug = 0; int error = 0; int help = 0; int version = 0; std::string pattern; while (true) { //int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"input", 1, nullptr, 0}, {"output", 1, nullptr, 0}, {"mosaic", 0, &mosaic, 1}, // split siemens mosaic into multiple frames {"pattern", 1, nullptr, 0}, // p {"enhance", 0, &enhance, 1}, // unenhance {"unenhance", 0, &unenhance, 1}, // unenhance {"root-uid", 1, &rootuid, 1}, // specific Root (not GDCM) //{"resources-path", 0, &resourcespath, 1}, {"mosaic-private", 0, &mosaic_private, 1}, // keep private attributes // General options ! {"verbose", 0, &verbose, 1}, {"warning", 0, &warning, 1}, {"debug", 0, &debug, 1}, {"error", 0, &error, 1}, {"help", 0, &help, 1}, {"version", 0, &version, 1}, {nullptr, 0, nullptr, 0} }; c = getopt_long (argc, argv, "i:o:MUp:VWDEhv", long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: { const char *s = long_options[option_index].name; (void)s; //printf ("option %s", s); if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); assert( filename.empty() ); filename = optarg; } else if( option_index == 3 ) /* pattern */ { assert( strcmp(s, "pattern") == 0 ); assert( pattern.empty() ); pattern = optarg; } else if( option_index == 6 ) /* root uid */ { assert( strcmp(s, "root-uid") == 0 ); root = optarg; } else if( option_index == 7 ) /* resourcespath */ { assert( strcmp(s, "resources-path") == 0 ); assert( xmlpath.empty() ); xmlpath = optarg; } else { printf (" with arg %s, index = %d", optarg, option_index); assert(0); } //printf (" with arg %s, index = %d", optarg, option_index); } //printf ("\n"); } break; case 'i': assert( filename.empty() ); filename = optarg; break; case 'o': assert( outfilename.empty() ); outfilename = optarg; break; case 'U': //assert( outfilename.empty() ); //outfilename = optarg; //printf ("option unenhance \n"); unenhance = 1; break; case 'M': //assert( outfilename.empty() ); //outfilename = optarg; mosaic = 1; break; case 'p': assert( pattern.empty() ); pattern = optarg; break; case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } // For now only support one input / one output if (optind < argc) { std::vector files; while (optind < argc) { //printf ("%s\n", argv[optind++]); files.emplace_back(argv[optind++] ); } //printf ("\n"); if( files.size() == 2 && filename.empty() && outfilename.empty() ) { filename = files[0]; outfilename = files[1]; } else { PrintHelp(); return 1; } } if( version ) { //std::cout << "version" << std::endl; PrintVersion(); return 0; } if( help ) { //std::cout << "help" << std::endl; PrintHelp(); return 0; } if( filename.empty() ) { //std::cerr << "Need input file (-i)\n"; PrintHelp(); return 1; } if( outfilename.empty() ) { //std::cerr << "Need output file (-o)\n"; PrintHelp(); return 1; } // Debug is a little too verbose gdcm::Trace::SetDebug( (debug > 0 ? true : false)); gdcm::Trace::SetWarning( (warning > 0 ? true : false)); gdcm::Trace::SetError( (error > 0 ? true : false)); // when verbose is true, make sure warning+error are turned on: if( verbose ) { gdcm::Trace::SetWarning( (verbose > 0 ? true : false) ); gdcm::Trace::SetError( (verbose > 0 ? true : false) ); } gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( "gdcmtar" ); if( !rootuid ) { // only read the env var is no explicit cmd line option // maybe there is an env var defined... let's check const char *rootuid_env = getenv("GDCM_ROOT_UID"); if( rootuid_env ) { rootuid = 1; root = rootuid_env; } } if( rootuid ) { if( !gdcm::UIDGenerator::IsValid( root.c_str() ) ) { std::cerr << "specified Root UID is not valid: " << root << std::endl; return 1; } gdcm::UIDGenerator::SetRoot( root.c_str() ); } if( unenhance && false ) { gdcm::Global& g = gdcm::Global::GetInstance(); // First thing we need to locate the XML dict // did the user requested to look XML file in a particular directory ? if( !resourcespath ) { const char *xmlpathenv = getenv("GDCM_RESOURCES_PATH"); if( xmlpathenv ) { // Make sure to look for XML dict in user explicitly specified dir first: xmlpath = xmlpathenv; resourcespath = 1; } } if( resourcespath ) { // xmlpath is set either by the cmd line option or the env var if( !g.Prepend( xmlpath.c_str() ) ) { std::cerr << "specified Resources Path is not valid: " << xmlpath << std::endl; return 1; } } // All set, then load the XML files: if( !g.LoadResourcesFiles() ) { return 1; } //const gdcm::Defs &defs = g.GetDefs(); } if( mosaic ) { gdcm::ImageReader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "could not read: " << filename << std::endl; return 1; } gdcm::SplitMosaicFilter filter; filter.SetImage( reader.GetImage() ); filter.SetFile( reader.GetFile() ); bool b = filter.Split(); if( !b ) { std::cerr << "Could not split : " << filename << std::endl; return 1; } const gdcm::Image &image = filter.GetImage(); const unsigned int *dims = image.GetDimensions(); const gdcm::DataElement &pixeldata = image.GetDataElement(); const gdcm::ByteValue *bv = pixeldata.GetByteValue(); size_t slice_len = image.GetBufferLength() / dims[2]; gdcm::FilenameGenerator fg; fg.SetNumberOfFilenames( dims[2] ); fg.SetPrefix( outfilename.c_str() ); fg.SetPattern( pattern.c_str() ); if( !fg.Generate() ) { std::cerr << "could not generate filenames" << std::endl; return 1; } const double *cosines = image.GetDirectionCosines(); gdcm::DirectionCosines dc( cosines ); double normal[3]; dc.Cross( normal ); const double *origin = image.GetOrigin(); double zspacing = image.GetSpacing(2); gdcm::CSAHeader csa; gdcm::DataSet & ds = reader.GetFile().GetDataSet(); gdcm::MrProtocol mrprot; if( !csa.GetMrProtocol(ds, mrprot) ) return 1; gdcm::MrProtocol::SliceArray sa; b = mrprot.GetSliceArray(sa); if( !b ) return 1; size_t size = sa.Slices.size(); if( !size ) return 1; if( !mosaic_private ) { gdcm::Anonymizer ano; ano.SetFile( reader.GetFile() ); // Remove CSA header ano.RemovePrivateTags(); } double slicePos[3]; double sliceNor[3]; namespace kwd = gdcm::Keywords; gdcm::UIDGenerator ug; kwd::InstanceNumber instart; instart.Set(ds); int istart = instart.GetValue(); for(unsigned int i = 0; i < dims[2]; ++i) { gdcm::MrProtocol::Slice & protSlice = sa.Slices[i]; gdcm::MrProtocol::Vector3 & protV = protSlice.Position; gdcm::MrProtocol::Vector3 & protN = protSlice.Normal; slicePos[0] = protV.dSag; slicePos[1] = protV.dCor; slicePos[2] = protV.dTra; sliceNor[0] = protN.dSag; sliceNor[1] = protN.dCor; sliceNor[2] = protN.dTra; double new_origin[3]; for (int j = 0; j < 3; j++) { // the n'th slice is n * z-spacing aloung the IOP-derived // z-axis new_origin[j] = origin[j] + normal[j] * i * zspacing; if( std::fabs(slicePos[j] - new_origin[j]) > 1e-3 ) { gdcmErrorMacro("Invalid position found"); return 1; } const double snv_dot = gdcm::DirectionCosines::Dot( normal, sliceNor ); if( std::fabs(1. - snv_dot) > 1e-6 ) { gdcmErrorMacro("Invalid direction found"); return 1; } } kwd::SOPInstanceUID sid; sid.SetValue( ug.Generate() ); ds.Replace( sid.GetAsDataElement() ); const char *outfilenamei = fg.GetFilename(i); kwd::SliceLocation sl; sl.SetValue( new_origin[2] ); ds.Replace( sl.GetAsDataElement() ); kwd::InstanceNumber in; in.SetValue( istart + i ); // Start at mosaic instance number ds.Replace( in.GetAsDataElement() ); gdcm::ImageWriter writer; writer.SetFileName( outfilenamei ); //writer.SetFile( filter.GetFile() ); writer.SetFile( reader.GetFile() ); // //writer.SetImage( filter.GetImage() ); gdcm::Image &slice = writer.GetImage(); slice = filter.GetImage(); slice.SetOrigin( new_origin ); slice.SetNumberOfDimensions( 2 ); assert( slice.GetPixelFormat() == filter.GetImage().GetPixelFormat() ); slice.SetSpacing(2, filter.GetImage().GetSpacing(2) ); //slice.Print( std::cout ); gdcm::DataElement &pd = slice.GetDataElement(); const char *sliceptr = bv->GetPointer() + i * slice_len; pd.SetByteValue( sliceptr, (uint32_t)slice_len); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } } return 0; } else if ( unenhance ) { gdcm::ImageReader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "could not read: " << filename << std::endl; return 1; } gdcm::File &file = reader.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); gdcm::MediaStorage ms; ms.SetFromFile(file); if( ms.IsUndefined() ) { std::cerr << "Unknown MediaStorage" << std::endl; return 1; } gdcm::UIDs uid; uid.SetFromUID( ms.GetString() ); if( uid != gdcm::UIDs::uid_1_2_840_10008_5_1_4_1_1_4_1 ) //NOTE: uid_1_2_840_10008_5_1_4_1_1_4_1 = 121, // Enhanced MR Image Storage { std::cerr << "MediaStorage is not handled " << ms << " [" << uid.GetName() << "]" << std::endl; return 1; } // Preserve info: gdcm::DataElement oldsopclassuid = ds.GetDataElement( gdcm::Tag(0x8,0x16) ); gdcm::DataElement oldinstanceuid = ds.GetDataElement( gdcm::Tag(0x8,0x18) ); // Ok then change it old Old MR Image Storage gdcm::DataElement de( gdcm::Tag(0x0008, 0x0016) ); ms = gdcm::MediaStorage::MRImageStorage; const char* msstr = gdcm::MediaStorage::GetMSString(ms); de.SetByteValue( msstr, (uint32_t)strlen(msstr) ); de.SetVR( gdcm::Attribute<0x0008, 0x0016>::GetVR() ); ds.Replace( de ); const gdcm::Image &image = reader.GetImage(); const unsigned int *dims = image.GetDimensions(); //std::cout << image << std::endl; const gdcm::DataElement &pixeldata = image.GetDataElement(); //const gdcm::ByteValue *bv = pixeldata.GetByteValue(); gdcm::SmartPointer bv = const_cast(pixeldata.GetByteValue()); if( !bv ) { std::cerr << "decompress first" << std::endl; return 1; } unsigned long slice_len = image.GetBufferLength() / dims[2]; assert( slice_len * dims[2] == image.GetBufferLength() ); //assert( image.GetBufferLength() == bv->GetLength() ); gdcm::FilenameGenerator fg; fg.SetNumberOfFilenames( dims[2] ); fg.SetPrefix( outfilename.c_str() ); fg.SetPattern( pattern.c_str() ); if( !fg.Generate() ) { std::cerr << "could not generate" << std::endl; return 1; } const double *cosines = image.GetDirectionCosines(); gdcm::DirectionCosines dc( cosines ); double normal[3]; dc.Cross( normal ); //const double *origin = image.GetOrigin(); //double zspacing = image.GetSpacing(2); // Remove SharedFunctionalGroupsSequence gdcm::SmartPointer sfgs = ds.GetDataElement( gdcm::Tag( 0x5200,0x9229 ) ).GetValueAsSQ(); ds.Remove( gdcm::Tag( 0x5200,0x9229 ) ); assert( ds.FindDataElement( gdcm::Tag( 0x5200,0x9229 ) ) == false ); // Remove PerFrameFunctionalGroupsSequence gdcm::SmartPointer pffgs = ds.GetDataElement( gdcm::Tag( 0x5200,0x9230 ) ).GetValueAsSQ(); ds.Remove( gdcm::Tag( 0x5200,0x9230 ) ); assert( ds.FindDataElement( gdcm::Tag( 0x5200,0x9230 ) ) == false ); ds.Remove( gdcm::Tag( 0x28,0x8) ); ds.Remove( gdcm::Tag( 0x7fe0,0x0010) ); assert( ds.FindDataElement( gdcm::Tag( 0x7fe0,0x0010) ) == false ); //ds.Remove( gdcm::Tag( 0x0008,0x0012) ); //ds.Remove( gdcm::Tag( 0x0008,0x0013) ); // reference the old instance: // PS 3.3-2009 C.7.6.16.1.3 #if 0 assert( ds.FindDataElement( gdcm::Tag(0x0008,0x1150) ) == false ); assert( ds.FindDataElement( gdcm::Tag(0x0008,0x1155) ) == false ); assert( ds.FindDataElement( gdcm::Tag(0x0008,0x1160) ) == false ); oldsopclassuid.SetTag( gdcm::Tag(0x8,0x1150) ); oldinstanceuid.SetTag( gdcm::Tag(0x8,0x1155) ); ds.Insert( oldsopclassuid ); ds.Insert( oldinstanceuid ); #endif char date[22]; const size_t datelen = 8; gdcm::System::GetCurrentDateTime(date); gdcm::Attribute<0x8,0x12> instcreationdate; instcreationdate.SetValue( gdcm::DTComp( date, datelen ) ); ds.Replace( instcreationdate.GetAsDataElement() ); gdcm::Attribute<0x8,0x13> instcreationtime; instcreationtime.SetValue( gdcm::DTComp( date + datelen, 13 ) ); ds.Replace( instcreationtime.GetAsDataElement() ); const char *offset = gdcm::System::GetTimezoneOffsetFromUTC(); gdcm::Attribute<0x8,0x201> timezoneoffsetfromutc; timezoneoffsetfromutc.SetValue( offset ); ds.Replace( timezoneoffsetfromutc.GetAsDataElement() ); for(unsigned int i = 0; i < dims[2]; ++i) { #if 0 double new_origin[3]; for (int j = 0; j < 3; j++) { // the n'th slice is n * z-spacing aloung the IOP-derived // z-axis new_origin[j] = origin[j] + normal[j] * i * zspacing; } #endif const char *outfilenamei = fg.GetFilename(i); //gdcm::ImageWriter writer; gdcm::Writer writer; writer.SetFileName( outfilenamei ); //writer.SetFile( filter.GetFile() ); writer.SetFile( reader.GetFile() ); if ( !gdcm::RemapSharedIntoOld( ds, sfgs, pffgs, i ) ) { return 1; } // //writer.SetImage( filter.GetImage() ); //gdcm::Image & //slice = writer.GetImage(); //slice = reader.GetImage(); // slice.SetOrigin( new_origin ); // slice.SetNumberOfDimensions( 2 ); // assert( slice.GetPixelFormat() == reader.GetImage().GetPixelFormat() ); // slice.SetSpacing(2, reader.GetImage().GetSpacing(2) ); //slice.Print( std::cout ); // gdcm::DataElement &pd = slice.GetDataElement(); const char *sliceptr = bv->GetPointer() + i * slice_len; gdcm::DataElement newpixeldata( gdcm::Tag(0x7fe0,0x0010) ); newpixeldata.SetVR( pixeldata.GetVR() ); newpixeldata.SetByteValue( sliceptr, (uint32_t)slice_len); // slow ! ds.Replace( newpixeldata ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilenamei << std::endl; return 1; } //else // { // std::cout << "Success to write: " << outfilenamei << std::endl; // } } return 0; } else { assert( enhance ); return MakeImageEnhanced( filename, outfilename ); #if 0 std::cerr << "Not implemented" << std::endl; return 1; gdcm::ImageReader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "could not read: " << filename << std::endl; return 1; } const gdcm::Image &image = reader.GetImage(); const unsigned int *dims = image.GetDimensions(); std::cout << image << std::endl; const gdcm::DataElement &pixeldata = image.GetDataElement(); const gdcm::ByteValue *bv = pixeldata.GetByteValue(); unsigned long slice_len = image.GetBufferLength() / dims[2]; //assert( image.GetBufferLength() == bv->GetLength() ); gdcm::FilenameGenerator fg; fg.SetNumberOfFilenames( dims[2] ); fg.SetPrefix( outfilename.c_str() ); fg.SetPattern( pattern.c_str() ); if( !fg.Generate() ) { std::cerr << "could not generate" << std::endl; return 1; } const double *cosines = image.GetDirectionCosines(); gdcm::DirectionCosines dc( cosines ); double normal[3]; dc.Cross( normal ); const double *origin = image.GetOrigin(); double zspacing = image.GetSpacing(2); for(unsigned int i = 0; i < dims[2]; ++i) { double new_origin[3]; for (int j = 0; j < 3; j++) { // the n'th slice is n * z-spacing aloung the IOP-derived // z-axis new_origin[j] = origin[j] + normal[j] * i * zspacing; } const char *outfilenamei = fg.GetFilename(i); gdcm::ImageWriter writer; writer.SetFileName( outfilenamei ); //writer.SetFile( filter.GetFile() ); writer.SetFile( reader.GetFile() ); // //writer.SetImage( filter.GetImage() ); gdcm::Image &slice = writer.GetImage(); slice = reader.GetImage(); slice.SetOrigin( new_origin ); slice.SetNumberOfDimensions( 2 ); assert( slice.GetPixelFormat() == reader.GetImage().GetPixelFormat() ); slice.SetSpacing(2, reader.GetImage().GetSpacing(2) ); //slice.Print( std::cout ); gdcm::DataElement &pd = slice.GetDataElement(); const char *sliceptr = bv->GetPointer() + i * slice_len; pd.SetByteValue( sliceptr, slice_len); // slow ! if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilenamei << std::endl; return 1; } else { std::cout << "Success to write: " << outfilenamei << std::endl; } } return 0; #endif } } GDCM-3.0.10/Applications/Cxx/gdcmxml.cxx000066400000000000000000000606471412732066400176760ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This is an implementation of Application Hosting: DICOM Native Model */ #include "gdcmFilename.h" #include "gdcmReader.h" #include "gdcmVersion.h" #include "gdcmFileMetaInformation.h" #include "gdcmDataSet.h" #include "gdcmDataElement.h" #include "gdcmAttribute.h" #include "gdcmPrivateTag.h" #include "gdcmValidate.h" #include "gdcmWriter.h" #include "gdcmSystem.h" #include "gdcmDirectory.h" #include "gdcmCSAHeader.h" #include "gdcmPDBHeader.h" #include "gdcmSequenceOfItems.h" #include "gdcmASN1.h" #include "gdcmFile.h" #include "gdcmXMLPrinter.h" #include "gdcmPrinter.h" #ifdef GDCM_USE_SYSTEM_LIBXML2 #include #endif #include #include #include #include /* for printf */ #include /* for exit */ #include #include using namespace gdcm; // This is a very dumb implementation for getData handling // by default GDCM simply drop the BulkData so we need to store // the actual BulkData somewhere for proper implementation of getData class SimpleFileXMLPrinter : public XMLPrinter { public: void HandleBulkData(const char *uuid, const TransferSyntax & ts, const char *bulkdata, size_t bulklen) override { // Store Bulk Data std::ofstream out( uuid, std::ios::binary ); out.write( bulkdata, bulklen ); out.close(); std::string tsfn = uuid; tsfn += ".ts"; // Need to store Transfer Syntax for later getData() implementation // See Sup118 for details const char *tsstring = ts.GetString(); assert( tsstring ); std::ofstream out2( tsfn.c_str(), std::ios::binary ); out2.write( tsstring, strlen(tsstring) ); out2.close(); } }; //Global Variables int loadBulkData = 0; int loadTransferSyntax = 0; TransferSyntax ts; static void PrintVersion() { std::cout << "gdcmxml: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; } static void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcmxml [OPTION]... FILE..." << std::endl; std::cout << "Convert a DICOM file into an XML file or vice-versa \n"; std::cout << "Parameter (required):" << std::endl; std::cout << " -i --input Filename1" << std::endl; std::cout << " -o --output Filename2" << std::endl; std::cout << "General Options:" << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " -v --version print version." << std::endl; std::cout << "Options for Dicom to XML:" << std::endl; std::cout << " -B --loadBulkData Loads bulk data into a binary file named \"UUID\"(by default UUID are written)." << std::endl; std::cout << "Options for XML to Dicom:" << std::endl; std::cout << " -B --loadBulkData Loads bulk data from a binary file named as the \"UUID\" in XML file(by default UUID are written)."<< std::endl; std::cout << " -T --TransferSyntax Loads transfer syntax from file (default is LittleEndianImplicit)" << std::endl; } #ifdef GDCM_USE_SYSTEM_LIBXML2 #define CHECK_READER \ if(ret == -1) \ assert(0 && "unable to read"); #define READ_NEXT\ ret = xmlTextReaderRead(reader);\ CHECK_READER\ if(xmlTextReaderNodeType(reader) == 14 || xmlTextReaderNodeType(reader) == 13)\ ret = xmlTextReaderRead(reader);\ CHECK_READER #define CHECK_NAME(value)\ strcmp((const char*)xmlTextReaderConstName(reader),value) static void HandleBulkData(const char *uuid, DataElement &de) { // Load Bulk Data if(loadBulkData) { std::ifstream file( uuid, std::ios::in|std::ios::binary|std::ios::ate );//open file with pointer at file end if (file.is_open()) { std::ifstream::pos_type size = file.tellg(); char *bulkData = new char [size]; file.seekg (0, std::ios::beg); file.read (bulkData, size); file.close(); ByteValue *bv = new ByteValue(bulkData,(int)size); de.SetValue(*bv); } } if(loadTransferSyntax) { std::string tsfn = uuid; tsfn += ".ts"; std::ifstream file( tsfn.c_str(), std::ios::in|std::ios::binary|std::ios::ate );//open file with pointer at file end if (file.is_open()) { std::ifstream::pos_type size = file.tellg(); char *tsstring = new char [size]; file.seekg (0, std::ios::beg); file.read (tsstring, size); file.close(); TransferSyntax::TSType tsType = TransferSyntax::GetTSType(tsstring); const TransferSyntax ts_temp(tsType); if(ts_temp.IsValid()) { ts = tsType; } } } } static void HandlePN(xmlTextReaderPtr reader,DataElement &de) { if(CHECK_NAME("DicomAttribute") == 0 && xmlTextReaderNodeType(reader) == 15) return;//empty element else if(!(CHECK_NAME("PersonName") == 0)) assert(0 && "Invalid XML"); int depth_curr = xmlTextReaderDepth(reader); (void)depth_curr; int ret; std::string name; READ_NEXT; READ_NEXT; while(!(CHECK_NAME("DicomAttribute") == 0 && xmlTextReaderNodeType(reader) == 15)) { READ_NEXT if(xmlTextReaderNodeType(reader) == 3) { name += (char*)xmlTextReaderConstValue(reader); name += "^"; } if((CHECK_NAME("Ideographic") == 0 || CHECK_NAME("Phonetic") == 0) && xmlTextReaderNodeType(reader) == 1) { name += "="; } } de.SetByteValue( name.c_str(), (uint32_t)name.size() ); return; /* READ_NEXT//at ByteValue //char *temp_name=new char[500]; std::string name; int count =0; //while(!(CHECK_NAME("PersonName") == 0 && xmlTextReaderDepth(reader) == depth_curr && xmlTextReaderNodeType(reader) == 15)) //{ if(CHECK_NAME("SingleByte") == 0) { READ_NEXT if(CHECK_NAME("FamilyName") == 0) { READ_NEXT if(xmlTextReaderNodeType(reader) == 3) { //append here count +=strlen((char*)xmlTextReaderConstValue(reader)); name += (char*)xmlTextReaderConstValue(reader); name += "^"; } READ_NEXT//at READ_NEXT//at //READ_NEXT//may be new name or at //if(CHECK_NAME("ByteValue") == 0) //READ_NEXT } if(CHECK_NAME("GivenName") == 0) { READ_NEXT if(xmlTextReaderNodeType(reader) == 3) { //append here name += (char*)xmlTextReaderConstValue(reader); name += "^"; } READ_NEXT READ_NEXT } if(CHECK_NAME("MiddleName") == 0) { READ_NEXT if(xmlTextReaderNodeType(reader) == 3) { //append here name += (char*)xmlTextReaderConstValue(reader); name += "^"; } READ_NEXT READ_NEXT } if(CHECK_NAME("NamePrefix") == 0) { READ_NEXT if(xmlTextReaderNodeType(reader) == 3) { //append here name += (char*)xmlTextReaderConstValue(reader); name += "^"; } READ_NEXT READ_NEXT } if(CHECK_NAME("NameSuffix") == 0) { READ_NEXT if(xmlTextReaderNodeType(reader) == 3) { //append here name += (char*)xmlTextReaderConstValue(reader); name += "^"; } READ_NEXT READ_NEXT } READ_NEXT//starts new or end tag PersonName //name += "="; } if(CHECK_NAME("Ideographic") == 0) { } if(CHECK_NAME("Phonetic") == 0) { } //Set Value in de Element el; el.SetValue(name.c_str(),0); de = el.GetAsDataElement(); READ_NEXT//at correct place for Populate DataSet return; */ } static void HandleSequence(SequenceOfItems *sqi,xmlTextReaderPtr reader,int depth); static void PopulateDataSet(xmlTextReaderPtr reader,DataSet &DS, int depth, bool SetSQ ) { (void)depth; int ret; const char *name = (const char*)xmlTextReaderConstName(reader); //printf("%s\n",name); #define LoadValueASCII(type) \ case type: \ { \ int count =0; \ name = (const char*)xmlTextReaderConstName(reader); \ if(strcmp(name,"DicomAttribute") == 0 && xmlTextReaderNodeType(reader) == 15)\ break;\ char values[10][100] = {"","","","","","","","","",""}; \ Element el; \ while(strcmp(name,"Value") == 0) \ { \ READ_NEXT \ if(CHECK_NAME("Value") == 0)\ {READ_NEXT;}\ else{\ char *value = (char*)xmlTextReaderConstValue(reader); \ strcpy((char *)values[count++],value); \ READ_NEXT /*Value ending tag*/ \ name = (const char*)xmlTextReaderConstName(reader); \ READ_NEXT \ name = (const char*)xmlTextReaderConstName(reader); }\ } \ assert(CHECK_NAME("DicomAttribute") == 0);\ el.SetLength( (count) * vr.GetSizeof() ); \ int total = 0; \ while(total < count) \ { \ el.SetValue(values[total],total); \ total++; \ } \ de = el.GetAsDataElement(); \ }break #define LoadValueInteger(type) \ case type: \ { \ int count =0; \ name = (const char*)xmlTextReaderConstName(reader); \ if(strcmp(name,"DicomAttribute") == 0 && xmlTextReaderNodeType(reader) == 15)\ break;\ int values[10]; \ Element el; \ while(strcmp(name,"Value") == 0) \ { \ READ_NEXT \ char *value_char = (char*)xmlTextReaderConstValue(reader); \ int nvalue = sscanf(value_char,"%d",&(values[count++])); \ assert( nvalue == 1 ); (void)nvalue; \ READ_NEXT /*Value ending tag*/ \ name = (const char*)xmlTextReaderConstName(reader); \ READ_NEXT \ name = (const char*)xmlTextReaderConstName(reader); \ } \ el.SetLength( (count) * vr.GetSizeof() ); \ int total = 0; \ while(total < count) \ { \ el.SetValue( (VRToType::Type)(values[total]),total); \ total++; \ } \ de = el.GetAsDataElement(); \ }break #define LoadValueFloat(type) \ case type: \ { \ int count =0; \ name = (const char*)xmlTextReaderConstName(reader); \ if(strcmp(name,"DicomAttribute") == 0 && xmlTextReaderNodeType(reader) == 15)\ break;\ float values[10]; \ Element el; \ while(strcmp(name,"Value") == 0) \ { \ READ_NEXT \ char *value_char = (char*)xmlTextReaderConstValue(reader); \ sscanf(value_char,"%f",&(values[count++])); \ READ_NEXT /*Value ending tag*/ \ name = (const char*)xmlTextReaderConstName(reader); \ READ_NEXT \ name = (const char*)xmlTextReaderConstName(reader); \ } \ el.SetLength( (count) * vr.GetSizeof() ); \ int total = 0; \ while(total < count) \ { \ el.SetValue(values[total],total); \ total++; \ } \ de = el.GetAsDataElement(); \ }break #define LoadValueDouble(type) \ case type: \ { \ int count =0; \ name = (const char*)xmlTextReaderConstName(reader); \ if(strcmp(name,"DicomAttribute") == 0 && xmlTextReaderNodeType(reader) == 15)\ break;\ double values[10]; \ Element el; \ while(strcmp(name,"Value") == 0) \ { \ READ_NEXT \ char *value_char = (char*)xmlTextReaderConstValue(reader); \ sscanf(value_char,"%lf",&(values[count++])); \ READ_NEXT/*Value ending tag*/ \ name = (const char*)xmlTextReaderConstName(reader); \ READ_NEXT \ name = (const char*)xmlTextReaderConstName(reader); \ } \ el.SetLength( (count) * vr.GetSizeof() ); \ int total = 0; \ while(total < count) \ { \ el.SetValue(values[total],total); \ total++; \ } \ de = el.GetAsDataElement(); \ }break #define LoadValueAT(type)\ case type: \ { \ int count =0; \ name = (const char*)xmlTextReaderConstName(reader);\ if(strcmp(name,"DicomAttribute") == 0 && xmlTextReaderNodeType(reader) == 15)\ break;\ Tag tags[10];\ unsigned int group = 0, element = 0;\ Element el;\ while(strcmp(name,"Value") == 0)\ {\ READ_NEXT\ char *value = (char*)xmlTextReaderConstValue(reader); \ if( sscanf(value, "(%04x,%04x)", &group , &element) != 2 )\ {\ gdcmDebugMacro( "Problem reading AT: ");\ } \ tags[count].SetGroup( (uint16_t)group );\ tags[count].SetElement( (uint16_t)element );count++;\ READ_NEXT/*Value ending tag*/ \ name = (const char*)xmlTextReaderConstName(reader); \ READ_NEXT \ name = (const char*)xmlTextReaderConstName(reader); \ }\ el.SetLength( (count) * vr.GetSizeof() ); \ int total = 0; \ while(total < count) \ { \ el.SetValue(tags[total],total); \ total++; \ } \ de = el.GetAsDataElement();\ }break while( xmlTextReaderDepth(reader)!=0 ) { if(SetSQ && (xmlTextReaderNodeType(reader) == 15) && CHECK_NAME("Item") == 0 ) return; if(CHECK_NAME("DicomAttribute") == 0) { DataElement de; /* Reading Tag */ char *tag_read =(char *)xmlTextReaderGetAttribute(reader,(const unsigned char*)"tag"); Tag t; if(!t.ReadFromContinuousString((const char *)tag_read)) assert(0 && "Invalid Tag!"); /* Reading VR */ char vr_read[3] = ""; strcpy(vr_read, (const char *)xmlTextReaderGetAttribute(reader,(const unsigned char*)"vr")); vr_read[2]='\0'; const gdcm::VR vr = gdcm::VR::GetVRType(vr_read); READ_NEXT /* should be at Value tag or BulkData tag or Item Tag */ /* Load Value */ switch(vr) { LoadValueAT(VR::AT); LoadValueASCII(VR::AE); LoadValueASCII(VR::AS); LoadValueASCII(VR::CS); LoadValueASCII(VR::DA); LoadValueDouble(VR::DS); LoadValueASCII(VR::DT); LoadValueInteger(VR::IS); LoadValueASCII(VR::LO); LoadValueASCII(VR::LT); LoadValueASCII(VR::SH); LoadValueASCII(VR::ST); LoadValueASCII(VR::TM); LoadValueASCII(VR::UI); LoadValueASCII(VR::UT); LoadValueInteger(VR::SS); LoadValueInteger(VR::UL); LoadValueInteger(VR::SL); LoadValueInteger(VR::US); LoadValueFloat(VR::FL); LoadValueDouble(VR::FD); case VR::SQ: { SequenceOfItems *sqi = new SequenceOfItems(); HandleSequence(sqi,reader,xmlTextReaderDepth(reader)); de.SetValue(*sqi); }break; case VR::PN: { //Current node must be Person Name HandlePN(reader,de); }break; case VR::OF: case VR::OB: case VR::OW: { //Presently should be at BulkData assert(((CHECK_NAME("BulkData")) == 0)); char * uuid = (char *)xmlTextReaderGetAttribute(reader,(const unsigned char*)"uuid"); HandleBulkData(uuid,de); READ_NEXT }break; case VR::UN: { int depth_UN=xmlTextReaderDepth(reader); while(!(CHECK_NAME("DicomAttribute") == 0 && xmlTextReaderNodeType(reader) == 15 && (depth_UN-1) == xmlTextReaderDepth(reader))) {READ_NEXT} //assert(0 && "UN not Handled yet"); }break; default: assert(0 && "Unknown VR"); }; /*Modify de before insert*/ de.SetTag(t); DS.Insert(de); READ_NEXT // To next Element } } } static void HandleSequence(SequenceOfItems *sqi, xmlTextReaderPtr reader,int depth) { int ret; while(!( CHECK_NAME("DicomAttribute") == 0 && xmlTextReaderDepth(reader) == (depth - 1) && xmlTextReaderNodeType(reader) == 15 ) ) { gdcmDebugMacro( "HandleSequence (while loop)" ); if( CHECK_NAME("Item") == 0 && xmlTextReaderDepth(reader) == depth && xmlTextReaderNodeType(reader) == 1) { //at Item READ_NEXT //assert(0 && "Hi1"); //at DicomAtt if( CHECK_NAME("DicomAttribute") == 0 && xmlTextReaderDepth(reader) == (depth + 1) && xmlTextReaderNodeType(reader) == 1) { //start of an item //Create Nested DataSet //assert(0 && "Hi2"); Item *item = new Item(); DataSet *NestedDS = new DataSet() ; PopulateDataSet(reader,*NestedDS,xmlTextReaderDepth(reader),true); item->SetNestedDataSet(*NestedDS); sqi->AddItem(*item); //assert(0 && "Hi3"); } else assert("Empty Item or Invalid XML"); READ_NEXT } else assert("Expected Item"); } } static void WriteDICOM(xmlTextReaderPtr reader, gdcm::Filename file2) { int ret; READ_NEXT READ_NEXT // at first element "DicomAttribute" //populate DS DataSet DS; if(xmlTextReaderDepth(reader) == 1 && strcmp((const char*)xmlTextReaderConstName(reader),"DicomAttribute") == 0) PopulateDataSet(reader,DS,1,false); //DataElement de; //Tag t(0xFFFe,0xE0DD); //de.SetTag(t); //DS.Insert(de); //add to File //store in heap File *F = new File(); F->SetDataSet(DS); //Validate - possibly from gdcmValidate Class FileMetaInformation meta = F->GetHeader(); meta.SetDataSetTransferSyntax(ts); F->SetHeader(meta); //Validate - possibly from gdcmValidate Class //Validate V; //V.SetFile(F); //V.Validation(); //F = V.GetValidatedFile(); //add to Writer if(!file2.IsEmpty()) { Writer W; W.SetFileName(file2.GetFileName()); W.SetFile(*F); //finally write to file W.Write(); } else { Printer printer; printer.SetFile ( *F ); printer.SetColor(1); printer.Print( std::cout ); } } static void XMLtoDICOM(gdcm::Filename file1, gdcm::Filename file2) { xmlTextReaderPtr reader; FILE *in; char *buffer; size_t numBytes; in = fopen(file1.GetFileName(), "r"); if(in == NULL) return ; fseek(in, 0L, SEEK_END); numBytes = ftell(in); fseek(in, 0L, SEEK_SET); buffer = (char*)calloc(numBytes, sizeof(char)); if(buffer == NULL) return ; size_t ret = fread(buffer, sizeof(char), numBytes, in); if( numBytes != ret ) { // FIXME how to return error code ? return; } fclose(in); reader = xmlReaderForMemory (buffer, (int)numBytes, NULL, NULL, 0); //reader = xmlReaderForFile(filename, "UTF-8", 0); Not Working!! if (reader != NULL) { WriteDICOM(reader, file2); } else { fprintf(stderr, "Unable to open %s\n", file1.GetFileName()); } } #endif // GDCM_USE_SYSTEM_LIBXML2 int main (int argc, char *argv[]) { int c; //int digit_optind = 0; gdcm::Filename file1; gdcm::Filename file2; // int loadTransferSyntax = 0; int verbose = 0; int warning = 0; int debug = 0; int error = 0; int help = 0; int version = 0; while (true) { int option_index = 0; static struct option long_options[] = { {"input", 1, nullptr, 0}, {"output", 1, nullptr, 0}, {"loadBulkData", 0, &loadBulkData, 1}, {"TransferSyntax", 0, &loadTransferSyntax, 1}, {"verbose", 0, &verbose, 1}, {"warning", 0, &warning, 1}, {"debug", 0, &debug, 1}, {"error", 0, &error, 1}, {"help", 0, &help, 1}, {"version", 0, &version, 1}, {nullptr, 0, nullptr, 0} // required }; static const char short_options[] = "i:o:BTVWDEhv"; c = getopt_long (argc, argv, short_options, long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: case '-': { const char *s = long_options[option_index].name; (void)s; if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); assert( file1.IsEmpty() ); file1 = optarg; } } } break; case 'i': //printf ("option i with value '%s'\n", optarg); assert( file1.IsEmpty() ); file1 = optarg; break; case 'o': assert( file2.IsEmpty() ); file2 = optarg; break; case 'B': loadBulkData = 1; break; case 'T': loadTransferSyntax = 1; break; case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { int v = argc - optind; if( v == 2 ) { file1 = argv[optind]; file2 = argv[optind+1]; } else if( v == 1 ) { file1 = argv[optind]; } else { PrintHelp(); return 1; } } if( file1.IsEmpty() ) { PrintHelp(); return 1; } if( version ) { PrintVersion(); return 0; } if( help ) { PrintHelp(); return 0; } gdcm::Trace::SetDebug( debug != 0); gdcm::Trace::SetWarning( warning != 0); gdcm::Trace::SetError( error != 0); // when verbose is true, make sure warning+error are turned on: if( verbose ) { gdcm::Trace::SetWarning( verbose != 0); gdcm::Trace::SetError( verbose!= 0); } const char *file1extension = file1.GetExtension(); //const char *file2extension = file2.GetExtension(); if(gdcm::System::StrCaseCmp(file1extension,".xml") != 0)// by default we assume it is a DICOM file-- as no extension is required for it { gdcm::Reader reader; reader.SetFileName( file1.GetFileName() ); bool success = reader.Read(); if( !success )//!ignoreerrors ) { std::cerr << "Failed to read: " << file1 << std::endl; return 1; } if(loadBulkData) { SimpleFileXMLPrinter printer; printer.SetFile ( reader.GetFile() ); if( file2.IsEmpty() ) { printer.Print( std::cout ); } else { std::ofstream outfile; outfile.open (file2.GetFileName()); printer.Print( outfile ); outfile.close(); } } else { XMLPrinter printer; printer.SetFile ( reader.GetFile() ); if( file2.IsEmpty() ) { printer.Print( std::cout ); } else { std::ofstream outfile; outfile.open (file2.GetFileName()); printer.Print( outfile ); outfile.close(); } } return 0; } else { #ifdef GDCM_USE_SYSTEM_LIBXML2 /* * This initializes the library and checks potential ABI mismatches * between the version it was compiled for and the actual shared * library used. */ LIBXML_TEST_VERSION XMLtoDICOM(file1,file2); /* * Cleanup function for the XML library. */ xmlCleanupParser(); /* * This is to debug memory for regression tests. */ xmlMemoryDump(); #else printf("\nPlease configure Cmake options with GDCM_USE_SYSTEM_LIBXML2 as ON and compile!\n"); #endif } } GDCM-3.0.10/Applications/Cxx/pdf2dcm.cxx000066400000000000000000000011041412732066400175410ustar00rootroot00000000000000/* Provide a mapping for: Title: ITK Software Guide Subject: Medical Image Segmentation and Registration Toolkit Keywords: Registration,Segmentation,Guide Author: Luis Ibanez and Will Schroeder Creator: LaTeX with hyperref package Producer: dvips + GPL Ghostscript 8.15 CreationDate: Mon Nov 21 19:34:28 2005 ModDate: Mon Nov 21 19:34:28 2005 Tagged: no Pages: 836 Encrypted: no Page size: 522 x 675 pts File size: 5580502 bytes Optimized: no PDF version: 1.4 into DICOM elements... */ GDCM-3.0.10/Applications/Cxx/puff.c000066400000000000000000001115361412732066400166150ustar00rootroot00000000000000/* * puff.c * Copyright (C) 2002-2010 Mark Adler * For conditions of distribution and use, see copyright notice in puff.h * version 2.2, 25 Apr 2010 * * puff.c is a simple inflate written to be an unambiguous way to specify the * deflate format. It is not written for speed but rather simplicity. As a * side benefit, this code might actually be useful when small code is more * important than speed, such as bootstrap applications. For typical deflate * data, zlib's inflate() is about four times as fast as puff(). zlib's * inflate compiles to around 20K on my machine, whereas puff.c compiles to * around 4K on my machine (a PowerPC using GNU cc). If the faster decode() * function here is used, then puff() is only twice as slow as zlib's * inflate(). * * All dynamically allocated memory comes from the stack. The stack required * is less than 2K bytes. This code is compatible with 16-bit int's and * assumes that long's are at least 32 bits. puff.c uses the short data type, * assumed to be 16 bits, for arrays in order to to conserve memory. The code * works whether integers are stored big endian or little endian. * * In the comments below are "Format notes" that describe the inflate process * and document some of the less obvious aspects of the format. This source * code is meant to supplement RFC 1951, which formally describes the deflate * format: * * http://www.zlib.org/rfc-deflate.html */ /* * Change history: * * 1.0 10 Feb 2002 - First version * 1.1 17 Feb 2002 - Clarifications of some comments and notes * - Update puff() dest and source pointers on negative * errors to facilitate debugging deflators * - Remove longest from struct huffman -- not needed * - Simplify offs[] index in construct() * - Add input size and checking, using longjmp() to * maintain easy readability * - Use short data type for large arrays * - Use pointers instead of long to specify source and * destination sizes to avoid arbitrary 4 GB limits * 1.2 17 Mar 2002 - Add faster version of decode(), doubles speed (!), * but leave simple version for readability * - Make sure invalid distances detected if pointers * are 16 bits * - Fix fixed codes table error * - Provide a scanning mode for determining size of * uncompressed data * 1.3 20 Mar 2002 - Go back to lengths for puff() parameters [Gailly] * - Add a puff.h file for the interface * - Add braces in puff() for else do [Gailly] * - Use indexes instead of pointers for readability * 1.4 31 Mar 2002 - Simplify construct() code set check * - Fix some comments * - Add FIXLCODES #define * 1.5 6 Apr 2002 - Minor comment fixes * 1.6 7 Aug 2002 - Minor format changes * 1.7 3 Mar 2003 - Added test code for distribution * - Added zlib-like license * 1.8 9 Jan 2004 - Added some comments on no distance codes case * 1.9 21 Feb 2008 - Fix bug on 16-bit integer architectures [Pohland] * - Catch missing end-of-block symbol error * 2.0 25 Jul 2008 - Add #define to permit distance too far back * - Add option in TEST code for puff to write the data * - Add option in TEST code to skip input bytes * - Allow TEST code to read from piped stdin * 2.1 4 Apr 2010 - Avoid variable initialization for happier compilers * - Avoid unsigned comparisons for even happier compilers * 2.2 25 Apr 2010 - Fix bug in variable initializations [Oberhumer] * - Add const where appropriate [Oberhumer] * - Split if's and ?'s for coverage testing * - Break out test code to separate file * - Move NIL to puff.h * - Allow incomplete code only if single code length is 1 * - Add full code coverage test to Makefile */ #include /* for setjmp(), longjmp(), and jmp_buf */ #include "puff.h" /* prototype for puff() */ #define local static /* for local function definitions */ /* * Maximums for allocations and loops. It is not useful to change these -- * they are fixed by the deflate format. */ #define MAXBITS 15 /* maximum bits in a code */ #define MAXLCODES 286 /* maximum number of literal/length codes */ #define MAXDCODES 30 /* maximum number of distance codes */ #define MAXCODES (MAXLCODES+MAXDCODES) /* maximum codes lengths to read */ #define FIXLCODES 288 /* number of fixed literal/length codes */ /* input and output state */ struct state { /* output state */ unsigned char *out; /* output buffer */ unsigned long outlen; /* available space at out */ unsigned long outcnt; /* bytes written to out so far */ /* input state */ const unsigned char *in; /* input buffer */ unsigned long inlen; /* available input at in */ unsigned long incnt; /* bytes read so far */ int bitbuf; /* bit buffer */ int bitcnt; /* number of bits in bit buffer */ /* input limit error return state for bits() and decode() */ jmp_buf env; }; /* * Return need bits from the input stream. This always leaves less than * eight bits in the buffer. bits() works properly for need == 0. * * Format notes: * * - Bits are stored in bytes from the least significant bit to the most * significant bit. Therefore bits are dropped from the bottom of the bit * buffer, using shift right, and new bytes are appended to the top of the * bit buffer, using shift left. */ local int bits(struct state *s, int need) { long val; /* bit accumulator (can use up to 20 bits) */ /* load at least need bits into val */ val = s->bitbuf; while (s->bitcnt < need) { if (s->incnt == s->inlen) longjmp(s->env, 1); /* out of input */ val |= (long)(s->in[s->incnt++]) << s->bitcnt; /* load eight bits */ s->bitcnt += 8; } /* drop need bits and update buffer, always zero to seven bits left */ s->bitbuf = (int)(val >> need); s->bitcnt -= need; /* return need bits, zeroing the bits above that */ return (int)(val & ((1L << need) - 1)); } /* * Process a stored block. * * Format notes: * * - After the two-bit stored block type (00), the stored block length and * stored bytes are byte-aligned for fast copying. Therefore any leftover * bits in the byte that has the last bit of the type, as many as seven, are * discarded. The value of the discarded bits are not defined and should not * be checked against any expectation. * * - The second inverted copy of the stored block length does not have to be * checked, but it's probably a good idea to do so anyway. * * - A stored block can have zero length. This is sometimes used to byte-align * subsets of the compressed data for random access or partial recovery. */ local int stored(struct state *s) { unsigned len; /* length of stored block */ /* discard leftover bits from current byte (assumes s->bitcnt < 8) */ s->bitbuf = 0; s->bitcnt = 0; /* get length and check against its one's complement */ if (s->incnt + 4 > s->inlen) return 2; /* not enough input */ len = s->in[s->incnt++]; len |= s->in[s->incnt++] << 8; if (s->in[s->incnt++] != (~len & 0xff) || s->in[s->incnt++] != ((~len >> 8) & 0xff)) return -2; /* didn't match complement! */ /* copy len bytes from in to out */ if (s->incnt + len > s->inlen) return 2; /* not enough input */ if (s->out != NIL) { if (s->outcnt + len > s->outlen) return 1; /* not enough output space */ while (len--) s->out[s->outcnt++] = s->in[s->incnt++]; } else { /* just scanning */ s->outcnt += len; s->incnt += len; } /* done with a valid stored block */ return 0; } /* * Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of * each length, which for a canonical code are stepped through in order. * symbol[] are the symbol values in canonical order, where the number of * entries is the sum of the counts in count[]. The decoding process can be * seen in the function decode() below. */ struct huffman { short *count; /* number of symbols of each length */ short *symbol; /* canonically ordered symbols */ }; /* * Decode a code from the stream s using huffman table h. Return the symbol or * a negative value if there is an error. If all of the lengths are zero, i.e. * an empty code, or if the code is incomplete and an invalid code is received, * then -10 is returned after reading MAXBITS bits. * * Format notes: * * - The codes as stored in the compressed data are bit-reversed relative to * a simple integer ordering of codes of the same lengths. Hence below the * bits are pulled from the compressed data one at a time and used to * build the code value reversed from what is in the stream in order to * permit simple integer comparisons for decoding. A table-based decoding * scheme (as used in zlib) does not need to do this reversal. * * - The first code for the shortest length is all zeros. Subsequent codes of * the same length are simply integer increments of the previous code. When * moving up a length, a zero bit is appended to the code. For a complete * code, the last code of the longest length will be all ones. * * - Incomplete codes are handled by this decoder, since they are permitted * in the deflate format. See the format notes for fixed() and dynamic(). */ #ifdef SLOW local int decode(struct state *s, const struct huffman *h) { int len; /* current number of bits in code */ int code; /* len bits being decoded */ int first; /* first code of length len */ int count; /* number of codes of length len */ int index; /* index of first code of length len in symbol table */ code = first = index = 0; for (len = 1; len <= MAXBITS; len++) { code |= bits(s, 1); /* get next bit */ count = h->count[len]; if (code - count < first) /* if length len, return symbol */ return h->symbol[index + (code - first)]; index += count; /* else update for next length */ first += count; first <<= 1; code <<= 1; } return -10; /* ran out of codes */ } /* * A faster version of decode() for real applications of this code. It's not * as readable, but it makes puff() twice as fast. And it only makes the code * a few percent larger. */ #else /* !SLOW */ local int decode(struct state *s, const struct huffman *h) { int len; /* current number of bits in code */ int code; /* len bits being decoded */ int first; /* first code of length len */ int count; /* number of codes of length len */ int index; /* index of first code of length len in symbol table */ int bitbuf; /* bits from stream */ int left; /* bits left in next or left to process */ short *next; /* next number of codes */ bitbuf = s->bitbuf; left = s->bitcnt; code = first = index = 0; len = 1; next = h->count + 1; while (1) { while (left--) { code |= bitbuf & 1; bitbuf >>= 1; count = *next++; if (code - count < first) { /* if length len, return symbol */ s->bitbuf = bitbuf; s->bitcnt = (s->bitcnt - len) & 7; return h->symbol[index + (code - first)]; } index += count; /* else update for next length */ first += count; first <<= 1; code <<= 1; len++; } left = (MAXBITS+1) - len; if (left == 0) break; if (s->incnt == s->inlen) longjmp(s->env, 1); /* out of input */ bitbuf = s->in[s->incnt++]; if (left > 8) left = 8; } return -10; /* ran out of codes */ } #endif /* SLOW */ /* * Given the list of code lengths length[0..n-1] representing a canonical * Huffman code for n symbols, construct the tables required to decode those * codes. Those tables are the number of codes of each length, and the symbols * sorted by length, retaining their original order within each length. The * return value is zero for a complete code set, negative for an over- * subscribed code set, and positive for an incomplete code set. The tables * can be used if the return value is zero or positive, but they cannot be used * if the return value is negative. If the return value is zero, it is not * possible for decode() using that table to return an error--any stream of * enough bits will resolve to a symbol. If the return value is positive, then * it is possible for decode() using that table to return an error for received * codes past the end of the incomplete lengths. * * Not used by decode(), but used for error checking, h->count[0] is the number * of the n symbols not in the code. So n - h->count[0] is the number of * codes. This is useful for checking for incomplete codes that have more than * one symbol, which is an error in a dynamic block. * * Assumption: for all i in 0..n-1, 0 <= length[i] <= MAXBITS * This is assured by the construction of the length arrays in dynamic() and * fixed() and is not verified by construct(). * * Format notes: * * - Permitted and expected examples of incomplete codes are one of the fixed * codes and any code with a single symbol which in deflate is coded as one * bit instead of zero bits. See the format notes for fixed() and dynamic(). * * - Within a given code length, the symbols are kept in ascending order for * the code bits definition. */ local int construct(struct huffman *h, const short *length, int n) { int symbol; /* current symbol when stepping through length[] */ int len; /* current length when stepping through h->count[] */ int left; /* number of possible codes left of current length */ short offs[MAXBITS+1]; /* offsets in symbol table for each length */ /* count number of codes of each length */ for (len = 0; len <= MAXBITS; len++) h->count[len] = 0; for (symbol = 0; symbol < n; symbol++) (h->count[length[symbol]])++; /* assumes lengths are within bounds */ if (h->count[0] == n) /* no codes! */ return 0; /* complete, but decode() will fail */ /* check for an over-subscribed or incomplete set of lengths */ left = 1; /* one possible code of zero length */ for (len = 1; len <= MAXBITS; len++) { left <<= 1; /* one more bit, double codes left */ left -= h->count[len]; /* deduct count from possible codes */ if (left < 0) return left; /* over-subscribed--return negative */ } /* left > 0 means incomplete */ /* generate offsets into symbol table for each length for sorting */ offs[1] = 0; for (len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + h->count[len]; /* * put symbols in table sorted by length, by symbol order within each * length */ for (symbol = 0; symbol < n; symbol++) if (length[symbol] != 0) h->symbol[offs[length[symbol]]++] = symbol; /* return zero for complete set, positive for incomplete set */ return left; } /* * Decode literal/length and distance codes until an end-of-block code. * * Format notes: * * - Compressed data that is after the block type if fixed or after the code * description if dynamic is a combination of literals and length/distance * pairs terminated by and end-of-block code. Literals are simply Huffman * coded bytes. A length/distance pair is a coded length followed by a * coded distance to represent a string that occurs earlier in the * uncompressed data that occurs again at the current location. * * - Literals, lengths, and the end-of-block code are combined into a single * code of up to 286 symbols. They are 256 literals (0..255), 29 length * symbols (257..285), and the end-of-block symbol (256). * * - There are 256 possible lengths (3..258), and so 29 symbols are not enough * to represent all of those. Lengths 3..10 and 258 are in fact represented * by just a length symbol. Lengths 11..257 are represented as a symbol and * some number of extra bits that are added as an integer to the base length * of the length symbol. The number of extra bits is determined by the base * length symbol. These are in the static arrays below, lens[] for the base * lengths and lext[] for the corresponding number of extra bits. * * - The reason that 258 gets its own symbol is that the longest length is used * often in highly redundant files. Note that 258 can also be coded as the * base value 227 plus the maximum extra value of 31. While a good deflate * should never do this, it is not an error, and should be decoded properly. * * - If a length is decoded, including its extra bits if any, then it is * followed a distance code. There are up to 30 distance symbols. Again * there are many more possible distances (1..32768), so extra bits are added * to a base value represented by the symbol. The distances 1..4 get their * own symbol, but the rest require extra bits. The base distances and * corresponding number of extra bits are below in the static arrays dist[] * and dext[]. * * - Literal bytes are simply written to the output. A length/distance pair is * an instruction to copy previously uncompressed bytes to the output. The * copy is from distance bytes back in the output stream, copying for length * bytes. * * - Distances pointing before the beginning of the output data are not * permitted. * * - Overlapped copies, where the length is greater than the distance, are * allowed and common. For example, a distance of one and a length of 258 * simply copies the last byte 258 times. A distance of four and a length of * twelve copies the last four bytes three times. A simple forward copy * ignoring whether the length is greater than the distance or not implements * this correctly. You should not use memcpy() since its behavior is not * defined for overlapped arrays. You should not use memmove() or bcopy() * since though their behavior -is- defined for overlapping arrays, it is * defined to do the wrong thing in this case. */ local int codes(struct state *s, const struct huffman *lencode, const struct huffman *distcode) { int symbol; /* decoded symbol */ int len; /* length for copy */ unsigned dist; /* distance for copy */ static const short lens[29] = { /* Size base for length codes 257..285 */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258}; static const short lext[29] = { /* Extra bits for length codes 257..285 */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; static const short dists[30] = { /* Offset base for distance codes 0..29 */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577}; static const short dext[30] = { /* Extra bits for distance codes 0..29 */ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; /* decode literals and length/distance pairs */ do { symbol = decode(s, lencode); if (symbol < 0) return symbol; /* invalid symbol */ if (symbol < 256) { /* literal: symbol is the byte */ /* write out the literal */ if (s->out != NIL) { if (s->outcnt == s->outlen) return 1; s->out[s->outcnt] = symbol; } s->outcnt++; } else if (symbol > 256) { /* length */ /* get and compute length */ symbol -= 257; if (symbol >= 29) return -10; /* invalid fixed code */ len = lens[symbol] + bits(s, lext[symbol]); /* get and check distance */ symbol = decode(s, distcode); if (symbol < 0) return symbol; /* invalid symbol */ dist = dists[symbol] + bits(s, dext[symbol]); #ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (dist > s->outcnt) return -11; /* distance too far back */ #endif /* copy length bytes from distance bytes back */ if (s->out != NIL) { if (s->outcnt + len > s->outlen) return 1; while (len--) { s->out[s->outcnt] = #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR dist > s->outcnt ? 0 : #endif s->out[s->outcnt - dist]; s->outcnt++; } } else s->outcnt += len; } } while (symbol != 256); /* end of block symbol */ /* done with a valid fixed or dynamic block */ return 0; } /* * Process a fixed codes block. * * Format notes: * * - This block type can be useful for compressing small amounts of data for * which the size of the code descriptions in a dynamic block exceeds the * benefit of custom codes for that block. For fixed codes, no bits are * spent on code descriptions. Instead the code lengths for literal/length * codes and distance codes are fixed. The specific lengths for each symbol * can be seen in the "for" loops below. * * - The literal/length code is complete, but has two symbols that are invalid * and should result in an error if received. This cannot be implemented * simply as an incomplete code since those two symbols are in the "middle" * of the code. They are eight bits long and the longest literal/length\ * code is nine bits. Therefore the code must be constructed with those * symbols, and the invalid symbols must be detected after decoding. * * - The fixed distance codes also have two invalid symbols that should result * in an error if received. Since all of the distance codes are the same * length, this can be implemented as an incomplete code. Then the invalid * codes are detected while decoding. */ local int fixed(struct state *s) { static int virgin = 1; static short lencnt[MAXBITS+1], lensym[FIXLCODES]; static short distcnt[MAXBITS+1], distsym[MAXDCODES]; static struct huffman lencode, distcode; /* build fixed huffman tables if first call (may not be thread safe) */ if (virgin) { int symbol; short lengths[FIXLCODES]; /* construct lencode and distcode */ lencode.count = lencnt; lencode.symbol = lensym; distcode.count = distcnt; distcode.symbol = distsym; /* literal/length table */ for (symbol = 0; symbol < 144; symbol++) lengths[symbol] = 8; for (; symbol < 256; symbol++) lengths[symbol] = 9; for (; symbol < 280; symbol++) lengths[symbol] = 7; for (; symbol < FIXLCODES; symbol++) lengths[symbol] = 8; construct(&lencode, lengths, FIXLCODES); /* distance table */ for (symbol = 0; symbol < MAXDCODES; symbol++) lengths[symbol] = 5; construct(&distcode, lengths, MAXDCODES); /* do this just once */ virgin = 0; } /* decode data until end-of-block code */ return codes(s, &lencode, &distcode); } /* * Process a dynamic codes block. * * Format notes: * * - A dynamic block starts with a description of the literal/length and * distance codes for that block. New dynamic blocks allow the compressor to * rapidly adapt to changing data with new codes optimized for that data. * * - The codes used by the deflate format are "canonical", which means that * the actual bits of the codes are generated in an unambiguous way simply * from the number of bits in each code. Therefore the code descriptions * are simply a list of code lengths for each symbol. * * - The code lengths are stored in order for the symbols, so lengths are * provided for each of the literal/length symbols, and for each of the * distance symbols. * * - If a symbol is not used in the block, this is represented by a zero as * as the code length. This does not mean a zero-length code, but rather * that no code should be created for this symbol. There is no way in the * deflate format to represent a zero-length code. * * - The maximum number of bits in a code is 15, so the possible lengths for * any code are 1..15. * * - The fact that a length of zero is not permitted for a code has an * interesting consequence. Normally if only one symbol is used for a given * code, then in fact that code could be represented with zero bits. However * in deflate, that code has to be at least one bit. So for example, if * only a single distance base symbol appears in a block, then it will be * represented by a single code of length one, in particular one 0 bit. This * is an incomplete code, since if a 1 bit is received, it has no meaning, * and should result in an error. So incomplete distance codes of one symbol * should be permitted, and the receipt of invalid codes should be handled. * * - It is also possible to have a single literal/length code, but that code * must be the end-of-block code, since every dynamic block has one. This * is not the most efficient way to create an empty block (an empty fixed * block is fewer bits), but it is allowed by the format. So incomplete * literal/length codes of one symbol should also be permitted. * * - If there are only literal codes and no lengths, then there are no distance * codes. This is represented by one distance code with zero bits. * * - The list of up to 286 length/literal lengths and up to 30 distance lengths * are themselves compressed using Huffman codes and run-length encoding. In * the list of code lengths, a 0 symbol means no code, a 1..15 symbol means * that length, and the symbols 16, 17, and 18 are run-length instructions. * Each of 16, 17, and 18 are follwed by extra bits to define the length of * the run. 16 copies the last length 3 to 6 times. 17 represents 3 to 10 * zero lengths, and 18 represents 11 to 138 zero lengths. Unused symbols * are common, hence the special coding for zero lengths. * * - The symbols for 0..18 are Huffman coded, and so that code must be * described first. This is simply a sequence of up to 19 three-bit values * representing no code (0) or the code length for that symbol (1..7). * * - A dynamic block starts with three fixed-size counts from which is computed * the number of literal/length code lengths, the number of distance code * lengths, and the number of code length code lengths (ok, you come up with * a better name!) in the code descriptions. For the literal/length and * distance codes, lengths after those provided are considered zero, i.e. no * code. The code length code lengths are received in a permuted order (see * the order[] array below) to make a short code length code length list more * likely. As it turns out, very short and very long codes are less likely * to be seen in a dynamic code description, hence what may appear initially * to be a peculiar ordering. * * - Given the number of literal/length code lengths (nlen) and distance code * lengths (ndist), then they are treated as one long list of nlen + ndist * code lengths. Therefore run-length coding can and often does cross the * boundary between the two sets of lengths. * * - So to summarize, the code description at the start of a dynamic block is * three counts for the number of code lengths for the literal/length codes, * the distance codes, and the code length codes. This is followed by the * code length code lengths, three bits each. This is used to construct the * code length code which is used to read the remainder of the lengths. Then * the literal/length code lengths and distance lengths are read as a single * set of lengths using the code length codes. Codes are constructed from * the resulting two sets of lengths, and then finally you can start * decoding actual compressed data in the block. * * - For reference, a "typical" size for the code description in a dynamic * block is around 80 bytes. */ local int dynamic(struct state *s) { int nlen, ndist, ncode; /* number of lengths in descriptor */ int index; /* index of lengths[] */ int err; /* construct() return value */ short lengths[MAXCODES]; /* descriptor code lengths */ short lencnt[MAXBITS+1], lensym[MAXLCODES]; /* lencode memory */ short distcnt[MAXBITS+1], distsym[MAXDCODES]; /* distcode memory */ struct huffman lencode, distcode; /* length and distance codes */ static const short order[19] = /* permutation of code length codes */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; /* construct lencode and distcode */ lencode.count = lencnt; lencode.symbol = lensym; distcode.count = distcnt; distcode.symbol = distsym; /* get number of lengths in each table, check lengths */ nlen = bits(s, 5) + 257; ndist = bits(s, 5) + 1; ncode = bits(s, 4) + 4; if (nlen > MAXLCODES || ndist > MAXDCODES) return -3; /* bad counts */ /* read code length code lengths (really), missing lengths are zero */ for (index = 0; index < ncode; index++) lengths[order[index]] = bits(s, 3); for (; index < 19; index++) lengths[order[index]] = 0; /* build huffman table for code lengths codes (use lencode temporarily) */ err = construct(&lencode, lengths, 19); if (err != 0) /* require complete code set here */ return -4; /* read length/literal and distance code length tables */ index = 0; while (index < nlen + ndist) { int symbol; /* decoded value */ int len; /* last length to repeat */ symbol = decode(s, &lencode); if (symbol < 16) /* length in 0..15 */ lengths[index++] = symbol; else { /* repeat instruction */ len = 0; /* assume repeating zeros */ if (symbol == 16) { /* repeat last length 3..6 times */ if (index == 0) return -5; /* no last length! */ len = lengths[index - 1]; /* last length */ symbol = 3 + bits(s, 2); } else if (symbol == 17) /* repeat zero 3..10 times */ symbol = 3 + bits(s, 3); else /* == 18, repeat zero 11..138 times */ symbol = 11 + bits(s, 7); if (index + symbol > nlen + ndist) return -6; /* too many lengths! */ while (symbol--) /* repeat last or zero symbol times */ lengths[index++] = len; } } /* check for end-of-block code -- there better be one! */ if (lengths[256] == 0) return -9; /* build huffman table for literal/length codes */ err = construct(&lencode, lengths, nlen); if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1])) return -7; /* incomplete code ok only for single length 1 code */ /* build huffman table for distance codes */ err = construct(&distcode, lengths + nlen, ndist); if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1])) return -8; /* incomplete code ok only for single length 1 code */ /* decode data until end-of-block code */ return codes(s, &lencode, &distcode); } /* * Inflate source to dest. On return, destlen and sourcelen are updated to the * size of the uncompressed data and the size of the deflate data respectively. * On success, the return value of puff() is zero. If there is an error in the * source data, i.e. it is not in the deflate format, then a negative value is * returned. If there is not enough input available or there is not enough * output space, then a positive error is returned. In that case, destlen and * sourcelen are not updated to facilitate retrying from the beginning with the * provision of more input data or more output space. In the case of invalid * inflate data (a negative error), the dest and source pointers are updated to * facilitate the debugging of deflators. * * puff() also has a mode to determine the size of the uncompressed output with * no output written. For this dest must be (unsigned char *)0. In this case, * the input value of *destlen is ignored, and on return *destlen is set to the * size of the uncompressed output. * * The return codes are: * * 2: available inflate data did not terminate * 1: output space exhausted before completing inflate * 0: successful inflate * -1: invalid block type (type == 3) * -2: stored block length did not match one's complement * -3: dynamic block code description: too many length or distance codes * -4: dynamic block code description: code lengths codes incomplete * -5: dynamic block code description: repeat lengths with no first length * -6: dynamic block code description: repeat more than specified lengths * -7: dynamic block code description: invalid literal/length code lengths * -8: dynamic block code description: invalid distance code lengths * -9: dynamic block code description: missing end-of-block code * -10: invalid literal/length or distance code in fixed or dynamic block * -11: distance is too far back in fixed or dynamic block * * Format notes: * * - Three bits are read for each block to determine the kind of block and * whether or not it is the last block. Then the block is decoded and the * process repeated if it was not the last block. * * - The leftover bits in the last byte of the deflate data after the last * block (if it was a fixed or dynamic block) are undefined and have no * expected values to check. */ int puff(unsigned char *dest, /* pointer to destination pointer */ unsigned long *destlen, /* amount of output space */ const unsigned char *source, /* pointer to source data pointer */ unsigned long *sourcelen) /* amount of input available */ { struct state s; /* input/output state */ int last, type; /* block information */ int err; /* return value */ /* initialize output state */ s.out = dest; s.outlen = *destlen; /* ignored if dest is NIL */ s.outcnt = 0; /* initialize input state */ s.in = source; s.inlen = *sourcelen; s.incnt = 0; s.bitbuf = 0; s.bitcnt = 0; /* return if bits() or decode() tries to read past available input */ if (setjmp(s.env) != 0) /* if came back here via longjmp() */ err = 2; /* then skip do-loop, return error */ else { /* process blocks until last block or error */ do { last = bits(&s, 1); /* one if last block */ type = bits(&s, 2); /* block type 0..3 */ err = type == 0 ? stored(&s) : (type == 1 ? fixed(&s) : (type == 2 ? dynamic(&s) : -1)); /* type == 3, invalid */ if (err != 0) break; /* return with error */ } while (!last); } /* update the lengths and return */ if (err <= 0) { *destlen = s.outcnt; *sourcelen = s.incnt; } return err; } GDCM-3.0.10/Applications/Cxx/puff.h000066400000000000000000000027421412732066400166200ustar00rootroot00000000000000/* puff.h Copyright (C) 2002-2010 Mark Adler, all rights reserved version 2.2, 25 Apr 2010 This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Mark Adler madler@alumni.caltech.edu */ #ifdef __cplusplus extern "C" { #endif /* * See puff.c for purpose and usage. */ #ifndef NIL # define NIL ((unsigned char *)0) /* for no output option */ #endif int puff(unsigned char *dest, /* pointer to destination pointer */ unsigned long *destlen, /* amount of output space */ const unsigned char *source, /* pointer to source data pointer */ unsigned long *sourcelen); /* amount of input available */ #ifdef __cplusplus } /* end extern "C" */ #endif GDCM-3.0.10/Applications/Python/000077500000000000000000000000001412732066400162215ustar00rootroot00000000000000GDCM-3.0.10/Applications/Python/README000066400000000000000000000044171412732066400171070ustar00rootroot00000000000000= !CherryWado = == About == !CherryWado is a WADO server written in python, using the !CherryPy web framework. DICOM images are handled with the GDCM DICOM toolkit command line utilities. For information about DICOM and Web Access to persistent Dicom Objects see http://en.wikipedia.org/wiki/DICOM. == Dependencies == * !CherryPy * flup * Python Imaging Library (PIL) * DICOM Toolkit - gdcm (+VTK: gdcm2pnm) == Installation and configuration == Our WADO server doesn't make any assumption about how / where you store DICOM files. Therefore, in order to use it, you need to tweak accessdata.py to specify a way to retrieve the requested DICOM object. You can test the server as follows: $ python wado.py test # preparation: mkdir -p /tmp/dicom/1.2.840.113619.2.5.1762386977.1328.985934491.590/1.2.840.113619.2.5.1762386977.1328.985934491.643/1.2.840.113619.2.5.1762386977.1328.985934491.693 rmdir /tmp/dicom/1.2.840.113619.2.5.1762386977.1328.985934491.590/1.2.840.113619.2.5.1762386977.1328.985934491.643/1.2.840.113619.2.5.1762386977.1328.985934491.693 cp gdcmData/012345.002.050.dcm /tmp/dicom/1.2.840.113619.2.5.1762386977.1328.985934491.590/1.2.840.113619.2.5.1762386977.1328.985934491.643/1.2.840.113619.2.5.1762386977.1328.985934491.693 # Open in your favorite browser http://127.0.0.1:8080/?requestType=WADO&studyUID=1.2.840.113619.2.5.1762386977.1328.985934491.590&seriesUID=1.2.840.113619.2.5.1762386977.1328.985934491.643&objectUID=1.2.840.113619.2.5.1762386977.1328.985934491.693&contentType=image/png !CherryWado uses FLUP to ease deployment with lighttpd or Apache. Here is a lighttpd.conf snippet for your convenience: {{{ $HTTP["url"] =~ "" { fastcgi.server = ( "/wado/" => ( "wado" => ( "bin-path" => "/path/to/wado.py", "socket" => "/tmp/wado.sock", "check-local" => "disable", "disable-time" => 1, "min-procs" => 1, "max-procs" => 10, ), ), ) }}} Make sure you have "mod_fastcgi" in server.modules! == License == !CherryWado is licensed under the Apache License, Version 2.0. See http://www.apache.org/licenses/LICENSE-2.0 for the full text. == Authors == Emanuele Rocca, Marco De Benedetto, Mathieu Malaterre GDCM-3.0.10/Applications/Python/accessdata.py000066400000000000000000000056471412732066400207020ustar00rootroot00000000000000# Copyright 2008 Emanuele Rocca # Copyright 2008 Marco De Benedetto # Copyright (c) 2006-2011 Mathieu Malaterre # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ DICOM data access layer. Write your own __getfile function to suit your needs. """ from lib import * import images def __getfile(studyUID, seriesUID, objectUID): """Given a studyUID, a seriesUID and an objectUID, this function must retrieve (somehow) the corresponding DICOM file and return the filename. Take this implementation as a rough example.""" #tmpdir = "/var/spool/dicom" tmpdir = "/tmp/dicom" import os import errno import tempfile studydir = "%s/%s" % (tmpdir, studyUID) seriesdir = "%s/%s" % (studydir, seriesUID) objectfile = "%s/%s" % (seriesdir, objectUID) if not os.path.isdir(seriesdir): dump_file = tempfile.NamedTemporaryFile() dump_file.write("(0008,0052) CS [STUDY]\n(0020,000d) UI [%s]" % studyUID) dump_file.flush() dicom_filename = dump_file.name + ".dcm" trycmd("dump2dcm %s %s" % (dump_file.name, dicom_filename)) # Si chiede all'aetitle DW_AM (PACS) di muovere su webapps # Per come e' definito il nodo webapps sul PACS (DW_AM) lo studio # viene inviato sulla porta 3000 # Deve essere attivo il servizio (!!! avviato da www-data !!!) simple_storage: # simple_storage -s -x /var/spool/dicom -n /etc/dicom/naming-convention -c webapps -f 3000 # Le immagini DICOM vengono archiviate in /var/spool/dicom/studyUID/seriersUID/objectUID # come descritto in /etc/dicom/naming-convention # Il servizio simple_storage forka ed e' quindi possibile ricevere piu' # studi contemporaneamente movecmd = "movescu --study --aetitle webapps --move webapps --call DW_AM pacs.ceed 3102" trycmd("%s %s" % (movecmd, dicom_filename)) dump_file.close() os.unlink(dicom_filename) return objectfile def get(studyUID, seriesUID, objectUID, format='jpeg'): """Function called by the main program to get an image.""" objectfile = __getfile(studyUID, seriesUID, objectUID) return images.Dicom(objectfile, format) if __name__ == "__main__": print get(studyUID="1.3.76.13.10010.0.5.74.3996.1224256625.4053", seriesUID="1.3.12.2.1107.5.4.4.1053.30000008100608242373400002493", objectUID="1.3.12.2.1107.5.4.4.1053.30000008100608324685900001822") GDCM-3.0.10/Applications/Python/images.py000066400000000000000000000071331412732066400200440ustar00rootroot00000000000000# Copyright 2008 Emanuele Rocca # Copyright 2008 Marco De Benedetto # Copyright (c) 2006-2011 Mathieu Malaterre # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ DICOM images conversion and manipulation. This module uses the OFFIS DICOM toolkit command line utilities. """ import os import Image, ImageEnhance import StringIO from lib import * def calc_size(orig_size, max_size): tofloat = lambda x: (float(x[0]), float(x[1])) toint = lambda x: (int(x[0]), int(x[1])) orig_size = tofloat(orig_size) max_size = tofloat(max_size) h_ratio = orig_size[1] / max_size[1] new_w = orig_size[0] / h_ratio if new_w > max_size[0]: w_ratio = orig_size[0] / max_size[0] new_h = orig_size[1] / w_ratio new_size = max_size[0], new_h else: new_size = new_w, max_size[1] return toint(new_size) class Dicom: def __init__(self, filename, format): """DICOM filename with full path, format can be either jpeg or png""" assert format in ('jpeg', 'png', 'dicom') self.format = format self.filename = filename if format != 'dicom': converted = "%s.%s" % (filename, format) if not os.path.isfile(converted): quality = "" if format == 'jpeg': quality = '--compr-quality 100' try: #trycmd("gdcm2pnm --write-%s %s --use-window 1 %s %s" % (format, quality, filename, converted)) print "gdcm2pnm %s %s" % (filename, converted) trycmd("gdcm2pnm %s %s" % (filename, converted)) except CmdException: #trycmd("gdcm2pnm --write-%s %s %s %s" % (format, quality, filename, converted)) print "gdcm2pnm %s %s" % (filename, converted) trycmd("gdcm2pnm %s %s" % (filename, converted)) os.unlink(filename) self.img = Image.open(converted) def dump(self): """To be called after PIL modifications""" destfile = StringIO.StringIO() self.img.save(destfile, self.format.upper()) destfile.seek(0) return destfile.read() def contrast(self, windowWidth): enhancer = ImageEnhance.Brightness(self.img) self.img = enhancer.enhance(float(windowWidth)) def brightness(self, windowCenter): enhancer = ImageEnhance.Contrast(self.img) self.img = enhancer.enhance(float(windowCenter)) def resize(self, rows, columns): size = (int(rows), int(columns)) newsize = calc_size(self.img.size, size) algorithm = Image.BICUBIC if newsize[0] < self.img.size[0]: algorithm = Image.ANTIALIAS self.img = self.img.resize(newsize, algorithm) def crop(self, left, upper, right, lower): self.img = self.img.crop((left, upper, right, lower)) def raw(self): return open(self.filename).read() if __name__ == "__main__": img = Dicom('/var/tmp/1.3.76.13.10010.0.5.74.3996.1224513675.10543/CT.1.2.840.113619.2.81.290.3160.35958.3.9.20081020.270228', 'png') GDCM-3.0.10/Applications/Python/lib.py000066400000000000000000000020311412732066400173350ustar00rootroot00000000000000# Copyright 2008 Emanuele Rocca # Copyright 2008 Marco De Benedetto # Copyright (c) 2006-2011 Mathieu Malaterre # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import commands class CmdException(Exception): """Exception representing a command line error""" pass def trycmd(cmd): """Try to execute the given command, raising an Exception on errors""" (exitstatus, outtext) = commands.getstatusoutput(cmd) if exitstatus != 0: raise CmdException, "cmd: %s\noutput: %s" % (cmd, outtext) GDCM-3.0.10/Applications/Python/wado.py000077500000000000000000000131541412732066400175340ustar00rootroot00000000000000#!/usr/bin/python # Copyright 2008 Emanuele Rocca # Copyright 2008 Marco De Benedetto # Copyright (c) 2006-2011 Mathieu Malaterre # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ A WADO server, compliant with section 3.18 of the DICOM standard. See http://www.dclunie.com/dicom-status/status.html for more information about DICOM. Basic usage example: requestType=WADO&studyUID=1.3.76.13.10010.0.5.74.6120.1224052386.1578&seriesUID=1.3.76.2.1.1.3.1.3.3115.274695982&objectUID=1.3.76.2.1.1.3.1.3.3115.274695982.26&contentType=image/png """ import cherrypy from flup.server.fcgi import WSGIServer import sys import os CURDIR = os.path.dirname(os.path.abspath(__file__)) import accessdata try: testing = sys.argv[1] == "test" BASEURL = "/" except IndexError: BASEURL = "/wado/" testing = False REQUIRED = ( 'requestType', 'studyUID', 'seriesUID', 'objectUID' ) OPTIONAL = ( 'contentType', 'charset', 'anonymize', 'annotation', 'rows', 'columns', 'region', 'windowWidth', 'windowCenter', 'frameNumber', 'imageQuality', 'presentationUID', 'presentationSeriesUID', 'transferSyntax' ) INVALID_DICOM = ( 'annotation', 'rows', 'columns', 'region', 'windowWidth', 'windowCenter' ) INVALID_NONDICOM = ( 'anonymize', ) def err(msg): """Function to handle errors""" raise Exception, msg def check_params(kwargs): """Validate and sanitize requests""" # TODO: implement every check valid = REQUIRED + OPTIONAL curparams = kwargs.keys() # WADO is the only requestType currently accepted by the standard assert kwargs['requestType'] == "WADO" # checking unknown parameters for par in curparams: if par not in valid: err("Unknown parameter: " + par) # checking missing parameters for par in REQUIRED: if par not in curparams: err("Missing parameter: " + par) # default content type is image/jpeg kwargs['contentType'] = kwargs.get('contentType', 'image/jpeg') # checking values for contentType = application/dicom if kwargs['contentType'] == 'application/dicom': for par in INVALID_DICOM: if par in curparams: err(par + " is not valid if contentType is application/dicom") # Validation finished return # checking values for contentType != application/dicom for par in INVALID_NONDICOM: if par in curparams: err(par + " is valid only if contentType is application/dicom") if 'annotation' in curparams: assert kwargs['annotation'] in ('patient', 'technique') if 'windowWidth' in curparams: assert 'windowCenter' in curparams if 'windowCenter' in curparams: assert 'windowWidth' in curparams if 'region' in curparams: region = kwargs['region'].split(',') assert len(region) == 4 for val in region: assert 0.0 <= float(val) <= 1.0 class Wado: """Wado controller""" @cherrypy.expose def index(self, **kwargs): cherrypy.log(str(kwargs)) check_params(kwargs) cherrypy.response.headers['Content-Type'] = kwargs['contentType'] cherrypy.response.headers['Pragma'] = 'cache' if kwargs['contentType'] == "application/dicom": format = "dicom" else: # image/png -> png, image/jpeg -> jpeg format = kwargs['contentType'].replace('image/', '') # getting DICOM image from accessdata image = accessdata.get(studyUID=kwargs['studyUID'], seriesUID=kwargs['seriesUID'], objectUID=kwargs['objectUID'], format=format) if kwargs['contentType'] == "application/dicom": return image.raw() if 'windowWidth' in kwargs: image.brightness(kwargs['windowWidth']) if 'windowCenter' in kwargs: image.contrast(kwargs['windowCenter']) if 'region' in kwargs: left, upper, right, lower = [ float(val) for val in kwargs['region'].split(",") ] # coordinates normalization width, height = image.img.size # 1 : width = left : x image.crop(width * left, height * upper, width * right, height * lower) if 'rows' in kwargs or 'columns' in kwargs: image.resize(kwargs['rows'], kwargs['columns']) return image.dump() if __name__ == "__main__": cherrypy.config.update({ #'server.socket_port': 7777, #'server.thread_pool': 1, #'environment': testing and 'testing' or 'production', #'log.access_file': 'access.log', #'log.error_file': 'errors.log', #'tools.sessions.on': True, 'tools.gzip.on': True, 'tools.caching.on': True }) conf = {} app = cherrypy.tree.mount(Wado(), BASEURL, config=conf) if testing: cherrypy.quickstart(app) else: cherrypy.engine.start(blocking=False) try: WSGIServer(app).run() finally: cherrypy.engine.stop() GDCM-3.0.10/Applications/README.txt000066400000000000000000000007161412732066400164420ustar00rootroot00000000000000I know I will regret that later, but for now Application are part of GDCM Naming convention, pretty much the same used for tiff (tiffinfo and tiffdump), we have gdcmdump, gdcminfo (should I rename them dcmdump. dcminfo ? but it will collide with dcmtk...) TODO: I have this file: acc-max.dcm it's pretty much a ACR-NEMA file, but it contains Modality. It would be great if gdcmconv would handle this file and generate a file that would make dciodvfy happy GDCM-3.0.10/CMake/000077500000000000000000000000001412732066400132725ustar00rootroot00000000000000GDCM-3.0.10/CMake/CMakeCSharpCompiler.cmake.in000066400000000000000000000037501412732066400204620ustar00rootroot00000000000000set(CMAKE_CSharp_COMPILER "@CMAKE_CSharp_COMPILER@") set(CMAKE_CSharp_COMPILER_ARG1 "@CMAKE_CSharp_COMPILER_ARG1@") #set(CMAKE_Fortran_COMPILER_ID "@CMAKE_Fortran_COMPILER_ID@") #set(CMAKE_Fortran_PLATFORM_ID "@CMAKE_Fortran_PLATFORM_ID@") #set(CMAKE_AR "@CMAKE_AR@") #set(CMAKE_RANLIB "@CMAKE_RANLIB@") # Should none on Win32, and 'mono' on unix set(CMAKE_CSharp_RUNTIME "@CMAKE_CSharp_RUNTIME@") set(CMAKE_CSharp_ARCHIVE "@CMAKE_CSharp_ARCHIVE@") # gacutil ?? set(CMAKE_CSharp_COMPILER_LOADED 1) set(CMAKE_CSharp_COMPILER_ENV_VAR "CSC") set(CMAKE_CSharp_SOURCE_FILE_EXTENSIONS cs;CS) set(CMAKE_CSharp_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) set(CMAKE_CSharp_LINKER_PREFERENCE 20) set(CMAKE_STATIC_LIBRARY_PREFIX_CSharp "") set(CMAKE_STATIC_LIBRARY_SUFFIX_CSharp ".dll") set(CMAKE_SHARED_LIBRARY_PREFIX_CSharp "") set(CMAKE_SHARED_LIBRARY_SUFFIX_CSharp ".dll") # FIXME ... where should it go #set(CMAKE_EXECUTABLE_SUFFIX ".exe") set(CMAKE_STATIC_LIBRARY_CREATE_CSharp_FLAGS "/target:library") set(CMAKE_STATIC_LIBRARY_CSharp_FLAGS "/target:library") #CMAKE_STATIC_LIBRARY_CSharp_FLAGS # partial library set(CMAKE_MODULE_LIBRARY_CREATE_CSharp_FLAGS "/target:module") set(CMAKE_MODULE_LIBRARY_CSharp_FLAGS "/target:module") # static set(CMAKE_SHARED_LIBRARY_CREATE_CSharp_FLAGS "/target:library") set(CMAKE_SHARED_LIBRARY_CSharp_FLAGS "/target:library") #set(CMAKE_SHARED_LIBRARY_LINK_CSharp_FLAGS "-r") #set(CMAKE_SHARED_LIBRARY_RUNTIME_CSharp_FLAG "-r") #set(CMAKE_SHARED_LIBRARY_LINK_CSharp_FLAGS "-r") # FIXME: CMAKE_LINK_LIBRARY_FILE_FLAG always add a space, so I cannot simply use "/r" because # I would need to remove the space, but instead use the -r that tolerate a space #set(CMAKE_LINK_LIBRARY_FILE_FLAG "") #set(CMAKE_LINK_LIBRARY_FLAG "-r") #set(CMAKE_CREATE_WIN32_EXE /target:winexe) #set(CMAKE_CREATE_CONSOLE_EXE /target:exe) #set(CMAKE_LINK_LIBRARY_FLAG "-l") #set(CMAKE_EXECUTABLE_RUNTIME_CSharp_FLAG "-foo") if(WIN32) else() set(CMAKE_CSHARP_INTERPRETER ${MONO_EXECUTABLE}) endif() GDCM-3.0.10/CMake/CMakeCSharpInformation.cmake000066400000000000000000000065441412732066400205740ustar00rootroot00000000000000 # This file sets the basic flags for the CSharp language in CMake. # It also loads the available platform file for the system-compiler # if it exists. #set(CMAKE_BASE_NAME) #get_filename_component(CMAKE_BASE_NAME ${CMAKE_CSharp_COMPILER} NAME_WE) #set(CMAKE_SYSTEM_AND_CSharp_COMPILER_INFO_FILE # #${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake) # ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake) #message(${CMAKE_SYSTEM_AND_CSharp_COMPILER_INFO_FILE}) #include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL) # This should be included before the _INIT variables are # used to initialize the cache. Since the rule variables # have if blocks on them, users can still define them here. # But, it should still be after the platform file so changes can # be made to those values. if(CMAKE_USER_MAKE_RULES_OVERRIDE) include(${CMAKE_USER_MAKE_RULES_OVERRIDE}) endif() # Copy from CSharp, ref CXX ??? if(CMAKE_USER_MAKE_RULES_OVERRIDE_CSHARP) include(${CMAKE_USER_MAKE_RULES_OVERRIDE_CSHARP}) endif() # # the target without the suffix # # # # # # this is a place holder if java needed flags for javac they would go here. if(NOT CMAKE_CSharp_CREATE_STATIC_LIBRARY) # if(WIN32) # set(class_files_mask "*.class") # else() set(class_files_mask ".") # endif() set(CMAKE_CSharp_CREATE_STATIC_LIBRARY #" -cf -C ") " -out:") endif() # compile a CSharp file into an object file if(NOT CMAKE_CSharp_COMPILE_OBJECT) # there is no such thing as intermediate representation (object file) in C#. # Instead to avoid multiple recompilation of the same src file, I could use the .dll form, since # one can add src / .dll that same way # copy src version set(CMAKE_CSharp_COMPILE_OBJECT " -E copy ") endif() if(NOT CMAKE_CSharp_LINK_EXECUTABLE) set(CMAKE_CSharp_LINK_EXECUTABLE # I could not references 'SOURCES' so I simply copy all source to fake OBJECTS # .exe is required otherwise I get: # Unhandled Exception: System.ArgumentException: Module file name # 'cmTryCompileExec' must have file extension. #" -out:.exe ") " -out:.exe ") endif() if(NOT CMAKE_CSharp_CREATE_SHARED_LIBRARY) set(CMAKE_CSharp_CREATE_SHARED_LIBRARY #" /target:library -out:") " -out:") endif() # set java include flag option and the separator for multiple include paths #set(CMAKE_INCLUDE_FLAG_CSharp "-classpath ") #if(WIN32 AND NOT CYGWIN) # set(CMAKE_INCLUDE_FLAG_SEP_CSharp ";") #else() # set(CMAKE_INCLUDE_FLAG_SEP_CSharp ":") #endif() set(CMAKE_CSharp_FLAGS_INIT "$ENV{CSFLAGS} ${CMAKE_CSharp_FLAGS_INIT}") # avoid just having a space as the initial value for the cache if(CMAKE_CSharp_FLAGS_INIT STREQUAL " ") set(CMAKE_CSharp_FLAGS_INIT) endif() set (CMAKE_CSharp_FLAGS "${CMAKE_CSharp_FLAGS_INIT}" CACHE STRING "Flags used by the compiler during all build types.") GDCM-3.0.10/CMake/CMakeDetermineCSharpCompiler.cmake000066400000000000000000000045341412732066400217130ustar00rootroot00000000000000 # determine the compiler to use for CSharp programs # NOTE, a generator may set CMAKE_CSharp_COMPILER before # loading this file to force a compiler. # use environment variable CSHARP first if defined by user, next use # the cmake variable CMAKE_GENERATOR_CSHARP which can be defined by a generator # as a default compiler # # Sets the following variables: # CMAKE_CSharp_COMPILER # CMAKE_AR # CMAKE_RANLIB # CMAKE_COMPILER_IS_GNUGNAT if(NOT CMAKE_CSharp_COMPILER) # prefer the environment variable CSHARP if($ENV{CSHARP} MATCHES ".+") get_filename_component(CMAKE_CSharp_COMPILER_INIT $ENV{CSHARP} PROGRAM PROGRAM_ARGS CMAKE_CSharp_FLAGS_ENV_INIT) if(CMAKE_CSharp_FLAGS_ENV_INIT) set(CMAKE_CSharp_COMPILER_ARG1 "${CMAKE_CSharp_FLAGS_ENV_INIT}" CACHE STRING "First argument to CSharp compiler") endif() if(NOT EXISTS ${CMAKE_CSharp_COMPILER_INIT}) message(FATAL_ERROR "Could not find compiler set in environment variable CSHARP:\n$ENV{CSHARP}.") endif() endif() # next prefer the generator-specified compiler if(CMAKE_GENERATOR_CSHARP) if(NOT CMAKE_CSharp_COMPILER_INIT) set(CMAKE_CSharp_COMPILER_INIT ${CMAKE_GENERATOR_CSHARP}) endif() endif() # finally list compilers to try if(CMAKE_CSharp_COMPILER_INIT) set(CMAKE_CSharp_COMPILER_LIST ${CMAKE_CSharp_COMPILER_INIT}) else() # Known compilers: # mcs/gmcs/smcs/dmcs # mono # see: https://www.mono-project.com/docs/about-mono/languages/csharp/ # csc: DotNet set(CMAKE_CSharp_COMPILER_LIST csc mcs gmcs smcs dmcs) endif() # Find the compiler. find_program(CMAKE_CSharp_COMPILER NAMES ${CMAKE_CSharp_COMPILER_LIST} DOC "CSharp compiler") if(CMAKE_CSharp_COMPILER_INIT AND NOT CMAKE_CSharp_COMPILER) set(CMAKE_CSharp_COMPILER "${CMAKE_CSharp_COMPILER_INIT}" CACHE FILEPATH "CSharp compiler" FORCE) endif() endif() mark_as_advanced(CMAKE_CSharp_COMPILER) get_filename_component(COMPILER_LOCATION "${CMAKE_CSharp_COMPILER}" PATH) #include(CMakeFindBinUtils) # configure variables set in this file for fast reload later on configure_file( #${CMAKE_ROOT}/Modules/CMakeCSharpCompiler.cmake.in ${CMAKE_MODULE_PATH}/CMakeCSharpCompiler.cmake.in # "${CMAKE_PLATFORM_ROOT_BIN}/CMakeCSharpCompiler.cmake" ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeCSharpCompiler.cmake @ONLY ) set(CMAKE_CSharp_COMPILER_ENV_VAR "CSC") GDCM-3.0.10/CMake/CMakeTestCSharpCompiler.cmake000066400000000000000000000044251412732066400207150ustar00rootroot00000000000000 # This file is used by EnableLanguage in cmGlobalGenerator to # determine that that selected CShapr compiler can actually compile # and link the most basic of programs. If not, a fatal error # is set and cmake stops processing commands and will not generate # any makefiles or projects. if(NOT CMAKE_CSharp_COMPILER_WORKS) message(STATUS "Check for working CSharp compiler: ${CMAKE_CSharp_COMPILER}") file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCSharpCompiler.cs "class Dummy {\n" "static void Main() {\n" "}\n}\n") try_compile(CMAKE_CSharp_COMPILER_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCSharpCompiler.cs OUTPUT_VARIABLE OUTPUT) set(C_TEST_WAS_RUN 1) endif() if(NOT CMAKE_CSharp_COMPILER_WORKS) message(STATUS "Check for working CSharp compiler: ${CMAKE_CSharp_COMPILER} -- broken") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the CSharp compiler works failed with " "the following output:\n${OUTPUT}\n\n") message(FATAL_ERROR "The CSharp compiler \"${CMAKE_CSharp_COMPILER}\" " "is not able to compile a simple test program.\nIt fails " "with the following output:\n ${OUTPUT}\n\n" "CMake will not be able to correctly generate this project.") else() if(C_TEST_WAS_RUN) message(STATUS "Check for working CSharp compiler: ${CMAKE_CSharp_COMPILER} -- works") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the CSharp compiler works passed with " "the following output:\n${OUTPUT}\n\n") endif() set(CMAKE_CSharp_COMPILER_WORKS 1 CACHE INTERNAL "") if(CMAKE_CSharp_COMPILER_FORCED) # The compiler configuration was forced by the user. # Assume the user has configured all compiler information. else() # Try to identify the ABI and configure it into CMakeCSharpCompiler.cmake include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake) CMAKE_DETERMINE_COMPILER_ABI(C ${CMAKE_ROOT}/Modules/CMakeCSharpCompilerABI.c) configure_file( #${CMAKE_ROOT}/Modules/CMakeCSharpCompiler.cmake.in ${CMAKE_MODULE_PATH}/CMakeCSharpCompiler.cmake.in ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeCSharpCompiler.cmake @ONLY ) endif() endif() GDCM-3.0.10/CMake/COPYING-CMAKE-SCRIPTS000066400000000000000000000024561412732066400162770ustar00rootroot00000000000000Redistribution 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 copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 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 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. GDCM-3.0.10/CMake/CTestCustom.ctest.in000066400000000000000000000052531412732066400171650ustar00rootroot00000000000000# same as boost settings: #SET(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS 1000) #SET(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS 1000) ##SET(CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE 1000000) #SET(CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE 49152) #SET(CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE 49152) SET(CTEST_CUSTOM_WARNING_EXCEPTION ${CTEST_CUSTOM_WARNING_EXCEPTION} "Utilities" "Utilities.gdcmopenjpeg.*warning C4101: '.*' : unreferenced local variable" "gdcm.*.cxx.obj : warning LNK4221: no public symbols found; archive member will be inaccessible" "/usr/bin/ranlib: for architecture: .* file: .* has no symbols" "gdcmcharls" "gdcmexpat" "warning CS0114:" "warning CS0108:" "warning CS0109:" "warning CS1591:" "gdcmJAVA_wrap.cxx" # swig generated "gdcmswigPYTHON_wrap.cxx" # swig generated "gdcmCSHARP_wrap.cxx" # swig generated "gdcmPythonFilter.cxx" # need some love "puff.c" # zlib code "/usr/bin/ld: warning: libjpeg.so.62" # needed by .*libvtkIO.so, may conflict with libjpeg.so.8 "/usr/bin/ld: warning: libavcodec.so.52" # needed by .*libvtkIO.so, may conflict with libavcodec.so.53 "/usr/bin/ld: warning: libavformat.so.52" #needed by libvtkIO.so, may conflict with libavformat.so.53 "/usr/bin/ld: warning: libavutil.so.49" # needed by .*libvtkIO.so, may conflict with libavutil.so.51 "/usr/bin/ld: warning: libswscale.so.0" # needed by .*libvtkIO.so, may conflict with libswscale.so.2 "CUSTOMBUILD : warning CS1668: Invalid search path" # appveyor ? "Returning a pointer or reference in a director method is not recommended." "Covariant return types not supported in Java." "Covariant return types not supported in C#." "Nested struct not currently supported" "bootstrap class path not set in conjunction with" "warning CS1699" "has been explicitly marked deprecated here" # clang-6.0: warning: the object size sanitizer has no effect at -O0, but is explicitly enabled: -fsanitize=float-cast-overflow,integer-divide-by-zero,null,object-size,return,shift,signed-integer-overflow,unreachable,vla-bound [-Winvalid-command-line-argument] "the object size sanitizer has no effect at" ) # Disable dynamic analysis on some tests: SET(CTEST_CUSTOM_MEMCHECK_IGNORE ${CTEST_CUSTOM_MEMCHECK_IGNORE} "Python" "DCMDUMP" "DCDUMP" "DCMDJPEG" "DCMDRLE" "vtk" ) # ==3201== 8 bytes in 1 blocks are still reachable in loss record 2 of 8 # ==3201== at 0x4C20809: operator new(unsigned long) (vg_replace_malloc.c:230) # ==3201== by 0x405E28F: DJDecoderRegistration::registerCodecs(E_DecompressionColorSpaceConversion, E_UIDCreation, E_PlanarConfiguration, bool) (in /usr/lib/libdcmjpeg.so.1.0.0) # ==3201== by 0x402AB1: (within /usr/bin/dcmdjpeg) GDCM-3.0.10/CMake/ExportConfiguration/000077500000000000000000000000001412732066400173035ustar00rootroot00000000000000GDCM-3.0.10/CMake/ExportConfiguration/CMakeLists.txt000066400000000000000000000077101412732066400220500ustar00rootroot00000000000000### Build the configuration file for external projects using GDCM and cmake: configure_file( GDCMConfig.cmake.in ${GDCM_BINARY_DIR}/GDCMConfig.cmake @ONLY ) install( FILES ${GDCM_BINARY_DIR}/GDCMConfig.cmake DESTINATION ${GDCM_INSTALL_PACKAGE_DIR} COMPONENT Headers ) configure_file( GDCMConfigVersion.cmake.in ${GDCM_BINARY_DIR}/GDCMConfigVersion.cmake @ONLY ) install( FILES ${GDCM_BINARY_DIR}/GDCMConfigVersion.cmake DESTINATION ${GDCM_INSTALL_PACKAGE_DIR} COMPONENT Headers ) configure_file( UseGDCM.cmake.in ${GDCM_BINARY_DIR}/UseGDCM.cmake @ONLY ) install( FILES ${GDCM_BINARY_DIR}/UseGDCM.cmake DESTINATION ${GDCM_INSTALL_PACKAGE_DIR} COMPONENT Headers ) # install all targets referenced as ${GDCM_TARGETS_NAME} if(GDCM_STANDALONE) install(EXPORT ${GDCM_TARGETS_NAME} DESTINATION ${GDCM_INSTALL_PACKAGE_DIR} COMPONENT Headers) endif() # [Prevent viral CMake dep] # See the following ref, which explain this mess. # http://cmake.org/Bug/view.php?id=9822 # 0009822: Please expose: cmGlobalGenerator::GetExportSet at cmake level # I cannot retrieve the lists of exported targets, so read them from the file instead #set(gdcmtarget_cmake # "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Export/${GDCM_INSTALL_PACKAGE_DIR}/${GDCM_TARGETS_NAME}.cmake") #configure_file( # ${GDCM_BINARY_DIR}/CMakeCache.txt # ${CMAKE_CURRENT_BINARY_DIR}/gdcmtarget_cmake.dep #COPYONLY #) # CMake Error at CMake/ExportConfiguration/CMakeLists.txt:59 (export): # export given target "gdcmopenjpeg" which is not built by this project. #add_custom_command( # OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/gdcmtarget_cmake.dep # COMMAND ${CMAKE_COMMAND} -E copy_if_different ${GDCM_BINARY_DIR}/CMakeCache.txt ${CMAKE_CURRENT_BINARY_DIR}/gdcmtarget_cmake.dep # COMMAND ${CMAKE_COMMAND} -E remove ${gdcmtarget_cmake} # COMMAND ${CMAKE_COMMAND} -E remove ${GDCM_BINARY_DIR}/GDCMExports.cmake # #DEPENDS ${GDCM_BINARY_DIR}/CMakeCache.txt # #DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/gdcmtarget_cmake.dep # DEPENDS ${gdcmtarget_cmake} #) #add_custom_target(clean_t ALL # COMMAND echo "Execute" # #COMMAND ${CMAKE_COMMAND} -E remove ${gdcmtarget_cmake} # COMMAND ${CMAKE_COMMAND} -E remove ${GDCM_BINARY_DIR}/GDCMExports.cmake # DEPENDS ${gdcmtarget_cmake} ${GDCM_BINARY_DIR}/GDCMExports.cmake # COMMENT "Crazy" #) #set( targets ) ##file(REMOVE ${gdcmtarget_cmake}) #if(EXISTS ${gdcmtarget_cmake}) # #message( "reading: ${gdcmtarget_cmake}" ) # file(READ ${gdcmtarget_cmake} ENT) # string(REGEX REPLACE "\r?\n" ";" ENT "${ENT}") # foreach(line ${ENT}) # string(REGEX MATCH "ADD_LIBRARY\\(.*SHARED IMPORTED\\)" m ${line}) # if( m ) # string(REGEX REPLACE "ADD_LIBRARY\\((.*) SHARED IMPORTED\\)" "\\1" out ${m}) # list(APPEND targets ${out}) # endif() # endforeach() #endif() # #set( exports ) #set(gdcmexport_cmake ${GDCM_BINARY_DIR}/GDCMExports.cmake) #if(EXISTS ${gdcmexport_cmake}) # file(READ ${gdcmexport_cmake} ENT) # string(REGEX REPLACE "\r?\n" ";" ENT "${ENT}") # foreach(line ${ENT}) # string(REGEX MATCH "ADD_LIBRARY\\(.*SHARED IMPORTED\\)" m ${line}) # if( m ) # string(REGEX REPLACE "ADD_LIBRARY\\((.*) SHARED IMPORTED\\)" "\\1" out ${m}) # list(APPEND exports ${out}) # endif() # endforeach() #endif() #list(LENGTH targets targets_len) #list(LENGTH exports exports_len) #if( ${targets_len} EQUAL ${exports_len} ) # message("equal") #else() # message("diff") # message( "${targets}" ) # message( "${exports}" ) ##set(targets ${exports}) ## execute_process( ## COMMAND ${CMAKE_COMMAND} -E remove ${gdcmtarget_cmake} ## ) #endif() set(targets gdcmCommon gdcmDICT gdcmDSED gdcmIOD gdcmMSFF gdcmMEXD gdcmjpeg8 gdcmjpeg12 gdcmjpeg16 gdcmexpat gdcmopenjp2 gdcmcharls gdcmmd5 gdcmzlib gdcmuuid socketxx vtkgdcm php_vtkgdcm vtkgdcmsharpglue ) file(WRITE ${GDCM_BINARY_DIR}/GDCMExports.cmake "") foreach(target ${targets}) if(TARGET ${target}) export(TARGETS ${target} FILE ${GDCM_BINARY_DIR}/GDCMExports.cmake APPEND) endif() endforeach() GDCM-3.0.10/CMake/ExportConfiguration/GDCMConfig.cmake.in000066400000000000000000000033631412732066400225570ustar00rootroot00000000000000#----------------------------------------------------------------------------- # # GDCMConfig.cmake - CMake configuration file for external projects. # # This file is configured by GDCM and used by the UseGDCM.cmake # module to load GDCM's settings for an external project. @GDCM_CONFIG_INSTALL_ONLY@ # The GDCM version number. set(GDCM_MAJOR_VERSION "@GDCM_MAJOR_VERSION@") set(GDCM_MINOR_VERSION "@GDCM_MINOR_VERSION@") set(GDCM_BUILD_VERSION "@GDCM_BUILD_VERSION@") # The libraries. set(GDCM_LIBRARIES "@GDCM_LIBRARIES@") # The CMake macros dir. set(GDCM_CMAKE_DIR "@GDCM_CMAKE_DIR_CONFIG@") # The configuration options. set(GDCM_BUILD_SHARED_LIBS "@GDCM_BUILD_SHARED_LIBS@") if(NOT GDCM_SKIP_USE_VTK) set(GDCM_USE_VTK "@GDCM_USE_VTK@") else() set(GDCM_USE_VTK "OFF") endif() # The "use" file. set(GDCM_USE_FILE "@GDCM_USE_FILE_CONFIG@") # The VTK options. if(GDCM_USE_VTK) set(GDCM_VTK_DIR "@GDCM_VTK_DIR_CONFIG@") endif() get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) if(EXISTS ${SELF_DIR}/GDCMTargets.cmake) # This is an install tree include(${SELF_DIR}/GDCMTargets.cmake) get_filename_component(GDCM_INCLUDE_ROOT "${SELF_DIR}/../../@GDCM_INSTALL_INCLUDE_DIR@" ABSOLUTE) set(GDCM_INCLUDE_DIRS ${GDCM_INCLUDE_ROOT}) get_filename_component(GDCM_LIB_ROOT "${SELF_DIR}/../../@GDCM_INSTALL_LIB_DIR@" ABSOLUTE) set(GDCM_LIBRARY_DIRS ${GDCM_LIB_ROOT}) else() if(EXISTS ${SELF_DIR}/GDCMExports.cmake) # This is a build tree set( GDCM_INCLUDE_DIRS "@GDCM_INCLUDE_PATH@") set(GDCM_LIBRARY_DIRS "@GDCM_LIBRARY_DIR@") include(${SELF_DIR}/GDCMExports.cmake) else() message(FATAL_ERROR "ooops") endif() endif() set(GDCM_USE_FILE ${SELF_DIR}/UseGDCM.cmake) # Backward compatible part: set(GDCM_FOUND TRUE) GDCM-3.0.10/CMake/ExportConfiguration/GDCMConfigVersion.cmake.in000066400000000000000000000014431412732066400241220ustar00rootroot00000000000000# Test config file. # Version number set( GDCM_MAJOR_VERSION "@GDCM_MAJOR_VERSION@") set( GDCM_MINOR_VERSION "@GDCM_MINOR_VERSION@") set( GDCM_BUILD_VERSION "@GDCM_BUILD_VERSION@") set( GDCM_VERSION "@GDCM_VERSION@") set(PACKAGE_VERSION "${GDCM_VERSION}") if("${PACKAGE_FIND_VERSION}" STREQUAL "") # User did not request any particular version set(PACKAGE_VERSION_COMPATIBLE 1) elseif("${PACKAGE_FIND_VERSION}" VERSION_EQUAL "${PACKAGE_VERSION}") # User did request exactly this version set(PACKAGE_VERSION_COMPATIBLE 1) set(PACKAGE_VERSION_EXACT 1) elseif("${PACKAGE_FIND_VERSION}" VERSION_LESS "${PACKAGE_VERSION}") # User requested an older version set(PACKAGE_VERSION_COMPATIBLE 1) else() message("REQUESTING: [${PACKAGE_FIND_VERSION}] but found: ${PACKAGE_VERSION}") endif() GDCM-3.0.10/CMake/ExportConfiguration/UseGDCM.cmake.in000066400000000000000000000015421412732066400221030ustar00rootroot00000000000000# # This module is provided as GDCM_USE_FILE by GDCMConfig.cmake. # It can be INCLUDEd in a project to load the needed compiler and linker # settings to use GDCM: # find_package(GDCM REQUIRED) # include(${GDCM_USE_FILE}) if(NOT GDCM_USE_FILE_INCLUDED) set(GDCM_USE_FILE_INCLUDED 1) # Add include directories needed to use GDCM. include_directories(${GDCM_INCLUDE_DIRS}) # Add link directories needed to use GDCM. link_directories(${GDCM_LIBRARY_DIRS}) # Add cmake module path. set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${GDCM_CMAKE_DIR}") # Use VTK. if(GDCM_USE_VTK) if(NOT GDCM_SKIP_USE_VTK) set(VTK_DIR ${GDCM_VTK_DIR}) find_package(VTK) if(VTK_FOUND) include(${VTK_USE_FILE}) else() message("VTK not found in GDCM_VTK_DIR=\"${GDCM_VTK_DIR}\".") endif() endif() endif() endif() GDCM-3.0.10/CMake/FindACTIVIZ.cmake000066400000000000000000000027621412732066400162150ustar00rootroot00000000000000# # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # Testing on Linux with: # ActiViz.NET-5.4.0.455-Linux-x86_64-Personal # Note: # IMHO I cannot use FIND_LIBRARY on Linux because of the .dll extension... # instead switch to FIND_FILE find_file(ACTIVIZ_KITWARE_VTK_LIBRARY NAMES Kitware.VTK.dll PATHS /usr/lib /usr/local/lib /usr/lib/cli/activiz-cil /usr/lib/cli/ActiViz.NET "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Kitware\\ActiVizDotNet 5.2.1]/bin" $ENV{ACTIVIZ_ROOT}/bin ) find_file(ACTIVIZ_KITWARE_MUMMY_RUNTIME_LIBRARY NAMES Kitware.mummy.Runtime.dll PATHS /usr/lib /usr/local/lib /usr/lib/cli/activiz-cil /usr/lib/cli/Kitware.mummy.Runtime-1.0 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Kitware\\ActiVizDotNet 5.2.1]/bin" $ENV{ACTIVIZ_ROOT}/bin ) if (ACTIVIZ_KITWARE_VTK_LIBRARY AND ACTIVIZ_KITWARE_MUMMY_RUNTIME_LIBRARY) set(ACTIVIZ_LIBRARIES ${ACTIVIZ_KITWARE_MUMMY_RUNTIME_LIBRARY} ${ACTIVIZ_KITWARE_VTK_LIBRARY}) set(ACTIVIZ_FOUND "YES") else() set(ACTIVIZ_FOUND "NO") endif () if (ACTIVIZ_FOUND) if (NOT ACTIVIZ_FIND_QUIETLY) message(STATUS "Found ACTIVIZ: ${ACTIVIZ_LIBRARIES}") endif () else () if (ACTIVIZ_FIND_REQUIRED) message(FATAL_ERROR "Could not find ACTIVIZ library") endif () endif () mark_as_advanced( ACTIVIZ_KITWARE_VTK_LIBRARY ACTIVIZ_KITWARE_MUMMY_RUNTIME_LIBRARY ) GDCM-3.0.10/CMake/FindCSharp.cmake000066400000000000000000000012071412732066400162550ustar00rootroot00000000000000# A C# Module for cmake # # TODO: # Should I inspect the ENV{CSC} var first ? # # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # if(WIN32) find_package(DotNETFrameworkSDK) else() #TODO handle CSharp_FIND_QUIETLY #TODO handle CSharp_FIND_REQUIRED find_package(MONO) endif() # http://public.kitware.com/Bug/view.php?id=7757 get_filename_component(current_list_path ${CMAKE_CURRENT_LIST_FILE} PATH) set(CSharp_USE_FILE ${current_list_path}/UseCSharp.cmake) GDCM-3.0.10/CMake/FindCharLS.cmake000066400000000000000000000016071412732066400162150ustar00rootroot00000000000000# # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # find_path(CHARLS_INCLUDE_DIR CharLS/charls.h /usr/local/include /usr/include ) find_library(CHARLS_LIBRARY NAMES CharLS PATHS /usr/lib /usr/local/lib ) if (CHARLS_LIBRARY AND CHARLS_INCLUDE_DIR) set(CHARLS_LIBRARIES ${CHARLS_LIBRARY}) set(CHARLS_INCLUDE_DIRS ${CHARLS_INCLUDE_DIR}) set(CHARLS_FOUND "YES") else () set(CHARLS_FOUND "NO") endif () if (CHARLS_FOUND) if (NOT CHARLS_FIND_QUIETLY) message(STATUS "Found CHARLS: ${CHARLS_LIBRARIES}") endif () else () if (CHARLS_FIND_REQUIRED) message(FATAL_ERROR "Could not find CHARLS library") endif () endif () mark_as_advanced( CHARLS_LIBRARY CHARLS_INCLUDE_DIR ) GDCM-3.0.10/CMake/FindDCMTK.cmake000066400000000000000000000100331412732066400157340ustar00rootroot00000000000000# - find DCMTK libraries and applications # # DCMTK_INCLUDE_DIRS - Directories to include to use DCMTK # DCMTK_LIBRARIES - Files to link against to use DCMTK # DCMTK_FOUND - If false, don't try to use DCMTK # DCMTK_DIR - (optional) Source directory for DCMTK # # DCMTK_DIR can be used to make it simpler to find the various include # directories and compiled libraries if you've just compiled it in the # source tree. Just set it to the root of the tree where you extracted # the source (default to /usr/include/dcmtk/) #============================================================================= # Copyright 2004-2009 Kitware, Inc. # Copyright 2009-2011 Mathieu Malaterre # Copyright 2010 Thomas Sondergaard # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distributed this file outside of CMake, substitute the full # License text for the above reference.) # # Written for VXL by Amitha Perera. # Upgraded for GDCM by Mathieu Malaterre. # Modified for EasyViz by Thomas Sondergaard. # if(NOT DCMTK_FOUND AND NOT DCMTK_DIR) set(DCMTK_DIR "/usr/include/dcmtk/" CACHE PATH "Root of DCMTK source tree (optional).") mark_as_advanced(DCMTK_DIR) endif() foreach(lib dcmdata dcmimage dcmimgle dcmjpeg dcmnet dcmpstat dcmqrdb dcmsign dcmsr dcmtls ijg12 ijg16 ijg8 ofstd) find_library(DCMTK_${lib}_LIBRARY ${lib} PATHS ${DCMTK_DIR}/${lib}/libsrc ${DCMTK_DIR}/${lib}/libsrc/Release ${DCMTK_DIR}/${lib}/libsrc/Debug ${DCMTK_DIR}/${lib}/Release ${DCMTK_DIR}/${lib}/Debug ${DCMTK_DIR}/lib) mark_as_advanced(DCMTK_${lib}_LIBRARY) if(DCMTK_${lib}_LIBRARY) list(APPEND DCMTK_LIBRARIES ${DCMTK_${lib}_LIBRARY}) endif() endforeach() set(DCMTK_config_TEST_HEADER osconfig.h) set(DCMTK_dcmdata_TEST_HEADER dctypes.h) set(DCMTK_dcmimage_TEST_HEADER dicoimg.h) set(DCMTK_dcmimgle_TEST_HEADER dcmimage.h) set(DCMTK_dcmjpeg_TEST_HEADER djdecode.h) set(DCMTK_dcmnet_TEST_HEADER assoc.h) set(DCMTK_dcmpstat_TEST_HEADER dcmpstat.h) set(DCMTK_dcmqrdb_TEST_HEADER dcmqrdba.h) set(DCMTK_dcmsign_TEST_HEADER sicert.h) set(DCMTK_dcmsr_TEST_HEADER dsrtree.h) set(DCMTK_dcmtls_TEST_HEADER tlslayer.h) set(DCMTK_ofstd_TEST_HEADER ofstdinc.h) foreach(dir config dcmdata dcmimage dcmimgle dcmjpeg dcmnet dcmpstat dcmqrdb dcmsign dcmsr dcmtls ofstd) find_path(DCMTK_${dir}_INCLUDE_DIR ${DCMTK_${dir}_TEST_HEADER} PATHS ${DCMTK_DIR}/${dir}/include ${DCMTK_DIR}/${dir} ${DCMTK_DIR}/include/${dir}) mark_as_advanced(DCMTK_${dir}_INCLUDE_DIR) if(DCMTK_${dir}_INCLUDE_DIR) list(APPEND DCMTK_INCLUDE_DIRS ${DCMTK_${dir}_INCLUDE_DIR}) endif() endforeach() if(WIN32) list(APPEND DCMTK_LIBRARIES netapi32 wsock32) endif() if(DCMTK_ofstd_INCLUDE_DIR) get_filename_component(DCMTK_dcmtk_INCLUDE_DIR ${DCMTK_ofstd_INCLUDE_DIR} PATH CACHE) list(APPEND DCMTK_INCLUDE_DIRS ${DCMTK_dcmtk_INCLUDE_DIR}) mark_as_advanced(DCMTK_dcmtk_INCLUDE_DIR) endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(DCMTK DEFAULT_MSG DCMTK_config_INCLUDE_DIR DCMTK_ofstd_INCLUDE_DIR DCMTK_ofstd_LIBRARY DCMTK_dcmdata_INCLUDE_DIR DCMTK_dcmdata_LIBRARY DCMTK_dcmimgle_INCLUDE_DIR DCMTK_dcmimgle_LIBRARY) # Compatibility: This variable is deprecated set(DCMTK_INCLUDE_DIR ${DCMTK_INCLUDE_DIRS}) foreach(executable dcmdump dcmdjpeg dcmdrle dcmdjpls storescu echoscu movescu findscu dcmqrscp) string(TOUPPER ${executable} EXECUTABLE) find_program(DCMTK_${EXECUTABLE}_EXECUTABLE ${executable} ${DCMTK_DIR}/bin) mark_as_advanced(DCMTK_${EXECUTABLE}_EXECUTABLE) endforeach() GDCM-3.0.10/CMake/FindDICOM3TOOLS.cmake000066400000000000000000000025601412732066400166370ustar00rootroot00000000000000# # this module looks for Dicom3Tools, well right now only dciodvfy, dcuncat, # dcmulti # # DCIODVFY_EXECUTABLE - the full path to the dciodvfy # DCIODVFY_FOUND - If false, don't attempt to use dciodvfy # dicom3tools are funny to build you'll need imake # Anyway in order not to pollute your system, you can do an in-source build and # install which should be clean enough: # # ./Configure # imake -I./config -DInstallInTopDir # make World # make install (will copy in ./bin) # # then all you need to do is export an env var DICOM3TOOLS pointing to that dir # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # find_program(DCIODVFY_EXECUTABLE dciodvfy "/tmp/" "$ENV{DICOM3TOOLS}/bin" "$ENV{DICOM3TOOLS}/bin/1.2.6.8." ) find_program(DCDUMP_EXECUTABLE dcdump "/tmp/" "$ENV{DICOM3TOOLS}/bin" "$ENV{DICOM3TOOLS}/bin/1.2.6.8." ) find_program(DCUNCAT_EXECUTABLE dcuncat "$ENV{DICOM3TOOLS}/bin" ) find_program(DCMULTI_EXECUTABLE dcmulti "$ENV{DICOM3TOOLS}/bin" ) mark_as_advanced( DCIODVFY_EXECUTABLE DCDUMP_EXECUTABLE DCUNCAT_EXECUTABLE DCMULTI_EXECUTABLE ) #if (NOT DCIODVFY_EXECUTABLE) # set(DCIODVFY_FOUND "NO") #else () # set(DCIODVFY_FOUND "YES") #endif () GDCM-3.0.10/CMake/FindDotNETFrameworkSDK.cmake000066400000000000000000000034371412732066400204210ustar00rootroot00000000000000# - Find .NET Software Development Kit # This module finds an installed .NET Software Development Kit. It sets the following variables: # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # Note: # .NET Framework SDK Version 1.1 # http://www.microsoft.com/downloads/details.aspx?FamilyID=9b3a2ca6-3647-4070-9f41-a333c6b9181d&displaylang=en # .NET Framework 2.0 Software Development Kit (SDK) (x86) # http://www.microsoft.com/downloads/details.aspx?FamilyID=fe6f2099-b7b4-4f47-a244-c96d69c35dec&displaylang=en # Microsoft .NET Framework 3.5 # http://www.microsoft.com/downloads/details.aspx?familyid=333325FD-AE52-4E35-B531-508D977D32A6&displaylang=en # Comparison Between C++ and C# # http://msdn.microsoft.com/en-us/library/yyaad03b(VS.71).aspx # http://www.akadia.com/services/dotnet_assemblies.html # Visual C# Language Concepts # Building from the Command Line # http://msdn.microsoft.com/en-us/library/1700bbwd(VS.71).aspx # FIXME, path are hardcoded. # http://www.walkernews.net/2007/07/30/how-to-verify-dot-net-framework-version/ find_program(CSC_v1_EXECUTABLE csc $ENV{windir}/Microsoft.NET/Framework/v1.1.4322/ ) find_program(CSC_v2_EXECUTABLE csc $ENV{windir}/Microsoft.NET/Framework/v2.0.50727/ ) find_program(CSC_v3_EXECUTABLE csc $ENV{windir}/Microsoft.NET/Framework/v3.5/ ) find_program(CSC_v4_EXECUTABLE csc $ENV{windir}/Microsoft.NET/Framework/v4.0.30319/ ) get_filename_component(current_list_path ${CMAKE_CURRENT_LIST_FILE} PATH) set(DotNETFrameworkSDK_USE_FILE ${current_list_path}/UseDotNETFrameworkSDK.cmake) mark_as_advanced( CSC_v1_EXECUTABLE CSC_v2_EXECUTABLE CSC_v3_EXECUTABLE CSC_v4_EXECUTABLE ) GDCM-3.0.10/CMake/FindJSON.cmake000066400000000000000000000020611412732066400156450ustar00rootroot00000000000000# - Find json # Find the native JSON headers and libraries. # This module defines # JSON_INCLUDE_DIRS - the json include directory # JSON_LIBRARIES - the libraries needed to use json # JSON_FOUND - system has the json library # # Copyright (c) 2013 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # See: # https://github.com/json-c/json-c/wiki # $ sudo apt-get install libjson0-dev # in sid: # $ sudo apt-get install libjson-c-dev find_path(JSON_INCLUDE_DIR NAMES json-c/json.h json/json.h) find_library(JSON_LIBRARY NAMES json-c json) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(JSON DEFAULT_MSG JSON_LIBRARY JSON_INCLUDE_DIR ) if(JSON_FOUND) set(JSON_LIBRARIES ${JSON_LIBRARY}) # hack to get old and new layout working: set(JSON_INCLUDE_DIRS ${JSON_INCLUDE_DIR}/json-c ${JSON_INCLUDE_DIR}/json) endif() mark_as_advanced( JSON_LIBRARY JSON_INCLUDE_DIR ) GDCM-3.0.10/CMake/FindJavaProperties.cmake000066400000000000000000000055131412732066400200370ustar00rootroot00000000000000# Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # This module will populate the following cmake variables: # JavaProp_JAVA_LIBRARY_PATH # JavaProp_OS_ARCH # JavaProp_OS_NAME # JavaProp_JAVA_HOME # JavaProp_SUN_BOOT_LIBRARY_PATH # JavaProp_PATH_SEPARATOR # JavaProp_SUN_ARCH_DATA_MODEL # I can't get FindJNI.cmake to work, so instead re-write one more robust # which only requires javac and java being in the PATH get_filename_component(current_list_path ${CMAKE_CURRENT_LIST_FILE} PATH) find_package(Java 1.5 REQUIRED) # need to re-run every time the setting for Java has changed: # There is technically one caveat still, when one only modify # Java_JAVA_EXECUTABLE from cmake-gui, everything is re-run properly except the # FIND_PATH for jar and javac if(JavaProp_JAVA_HOME) get_filename_component(javarealpath ${Java_JAVA_EXECUTABLE} REALPATH ) get_filename_component(javahomesubdir ${JavaProp_JAVA_HOME} PATH ) string(REGEX MATCH "${javahomesubdir}" outputvar "${javarealpath}" ) if(NOT outputvar) message(STATUS "Need to re-execute JavaProp: ${outputvar}") file(REMOVE ${CMAKE_BINARY_DIR}/GetSystemProperty.class ) endif() endif() # For some reason I have to use two execute_process instead of a chained one... if(${current_list_path}/GetSystemProperty.java IS_NEWER_THAN ${CMAKE_BINARY_DIR}/GetSystemProperty.class) #message("${current_list_path}/GetSystemProperty.java") #message("${CMAKE_CURRENT_BINARY_DIR}/GetSystemProperty.class") execute_process( COMMAND ${Java_JAVAC_EXECUTABLE} -source ${GDCM_JAVA_SOURCE_VERSION} -target ${GDCM_JAVA_TARGET_VERSION} ${current_list_path}/GetSystemProperty.java -d ${CMAKE_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) # populate the following list of java properties into CMake properties: set(JAVA_PROPERTY_LIST java.library.path os.arch os.name java.home sun.boot.library.path path.separator # : / ; sun.arch.data.model # 32 / 64 ) foreach(property ${JAVA_PROPERTY_LIST}) string(TOUPPER ${property} property_upper) string(REPLACE "." "_" property_cmake_name ${property_upper}) execute_process( COMMAND ${Java_JAVA_EXECUTABLE} GetSystemProperty ${property} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE ${property_cmake_name} OUTPUT_STRIP_TRAILING_WHITESPACE ) #message(STATUS "${property} : ${property_cmake_name} : ${${property_cmake_name}}") set(JavaProp_${property_cmake_name} ${${property_cmake_name}} CACHE STRING "Java Prop Value for: ${property}" FORCE ) mark_as_advanced( JavaProp_${property_cmake_name} ) endforeach() endif() GDCM-3.0.10/CMake/FindKAKADU.cmake000066400000000000000000000006201412732066400160330ustar00rootroot00000000000000# # this module looks for KAKADu # http://www.kakadusoftware.com/ # # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # find_program(KDU_EXPAND_EXECUTABLE kdu_expand ) mark_as_advanced( KDU_EXPAND_EXECUTABLE ) GDCM-3.0.10/CMake/FindKWStyle.cmake000066400000000000000000000017211412732066400164400ustar00rootroot00000000000000# # this module looks for KWStyle # https://kitware.github.io/KWStyle/ # # # Copyright (c) 2009-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # find_program(KWSTYLE_EXECUTABLE NAMES KWStyle PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Kitware Inc.\\KWStyle 1.0.0]/bin" ) # option(KWSTYLE_USE_VIM_FORMAT "Set KWStyle to generate errors with a VIM-compatible format." OFF) # option(KWSTYLE_USE_MSVC_FORMAT "Set KWStyle to generate errors with a VisualStudio-compatible format." OFF) # mark_as_advanced(KWSTYLE_USE_VIM_FORMAT) # mark_as_advanced(KWSTYLE_USE_MSVC_FORMAT) # # if(KWSTYLE_USE_VIM_FORMAT) # set(KWSTYLE_ARGUMENTS -vim ${KWSTYLE_ARGUMENTS}) # endif() # # if(KWSTYLE_USE_MSVC_FORMAT) # set(KWSTYLE_ARGUMENTS -msvc ${KWSTYLE_ARGUMENTS}) # endif() mark_as_advanced( KWSTYLE_EXECUTABLE ) GDCM-3.0.10/CMake/FindLJPEG.cmake000066400000000000000000000021001412732066400157270ustar00rootroot00000000000000# # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # find_path(LJPEG_INCLUDE_DIR ljpeg-62/jpeglib.h /usr/local/include /usr/include ) find_library(LJPEG8_LIBRARY NAMES jpeg8 PATHS /usr/lib /usr/local/lib ) find_library(LJPEG12_LIBRARY NAMES jpeg12 PATHS /usr/lib /usr/local/lib ) find_library(LJPEG16_LIBRARY NAMES jpeg16 PATHS /usr/lib /usr/local/lib ) if (LJPEG8_LIBRARY AND LJPEG_INCLUDE_DIR) set(LJPEG_LIBRARIES ${LJPEG8_LIBRARY} ${LJPEG12_LIBRARY} ${LJPEG16_LIBRARY}) set(LJPEG_INCLUDE_DIRS ${LJPEG_INCLUDE_DIR}) set(LJPEG_FOUND "YES") else () set(LJPEG_FOUND "NO") endif () if (LJPEG_FOUND) if (NOT LJPEG_FIND_QUIETLY) message(STATUS "Found LJPEG: ${LJPEG_LIBRARIES}") endif () else () if (LJPEG_FIND_REQUIRED) message(FATAL_ERROR "Could not find LJPEG library") endif () endif () mark_as_advanced( LJPEG_LIBRARIES LJPEG_INCLUDE_DIR ) GDCM-3.0.10/CMake/FindMAGIC.cmake000066400000000000000000000017641412732066400157250ustar00rootroot00000000000000# # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # $ sudo apt-get install libmagic-dev # $ dpkg -L libmagic-dev # ... # /usr/include/magic.h # /usr/lib/libmagic.so find_path(MAGIC_INCLUDE_DIR magic.h /usr/local/include /usr/include ) find_library(MAGIC_LIBRARY NAMES magic PATHS /usr/lib /usr/local/lib ) if (MAGIC_LIBRARY AND MAGIC_INCLUDE_DIR) set(MAGIC_LIBRARIES ${MAGIC_LIBRARY}) set(MAGIC_INCLUDE_DIRS ${MAGIC_INCLUDE_DIR}) set(MAGIC_FOUND "YES") else () set(MAGIC_FOUND "NO") endif () if (MAGIC_FOUND) if (NOT MAGIC_FIND_QUIETLY) message(STATUS "Found MAGIC: ${MAGIC_LIBRARIES} ${MAGIC_INCLUDE_DIR}") endif () else () if (MAGIC_FIND_REQUIRED) message(FATAL_ERROR "Could not find MAGIC library") endif () endif () mark_as_advanced( MAGIC_LIBRARY MAGIC_INCLUDE_DIR ) GDCM-3.0.10/CMake/FindMONO.cmake000066400000000000000000000050261412732066400156500ustar00rootroot00000000000000# - Find MONO # This module finds an installed MONO. It sets the following variables: # MONO_FOUND - set to true if MONO is found # MONO_DIR - the directory where swig is installed # MONO_EXECUTABLE - the path to the swig executable # MONO_VERSION - the version number of the swig executable # # All information are collected from the MONO_EXECUTABLE so the # version to be found can be changed from the command line by # means of setting MONO_EXECUTABLE # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # set(MONO_FOUND FALSE) # apt-get install mono-jit mono-mcs mono-gac mono-gmcs # eg. # $ gmcs HelloWorld.cs # $ mono HelloWorld.exe # TODO: what are 'cscc' and 'ilrun' ? find_program(MONO_EXECUTABLE mono) find_program(MCS_EXECUTABLE mcs) # 1.0 (mono >= 2.11 => target all version) find_program(GMCS_EXECUTABLE mono-csc gmcs) # 2.0 find_program(SMCS_EXECUTABLE smcs) # 3.0 find_program(DMCS_EXECUTABLE dmcs) # 4.0 # mono-gac: /usr/bin/gacutil find_program(GACUTIL_EXECUTABLE gacutil) # gacutil - Global Assembly Cache management utility. # mono-1.0-devel: /usr/bin/ilasm find_program(ILASM_EXECUTABLE ilasm) # ilasm, ilasm2 - Mono IL assembler # mono-1.0-devel: /usr/bin/sn find_program(SN_EXECUTABLE sn) # sn - Digitally sign/verify/compare strongnames on CLR assemblies. # We decide to declare mono found when both interpreter and compiler 1.0 are found. if(MONO_EXECUTABLE AND MCS_EXECUTABLE) set(MONO_FOUND TRUE) # TODO get version # TODO: there are multiple 'mcs' command on unix, need to check this is Mono: # mcs --version should return "Mono C# compiler version 1.9.1.0" elseif(MONO_EXECUTABLE AND GMCS_EXECUTABLE) set(MONO_FOUND TRUE) elseif(MONO_EXECUTABLE AND SMCS_EXECUTABLE) set(MONO_FOUND TRUE) elseif(MONO_EXECUTABLE AND DMCS_EXECUTABLE) set(MONO_FOUND TRUE) endif() if(NOT MONO_FOUND) if(NOT MONO_FIND_QUIETLY) if(MONO_FIND_REQUIRED) message(FATAL_ERROR "MONO was not found. Please specify mono/mcs executable location") else() message(STATUS "MONO was not found. Please specify mono/mcs executable location") endif() endif() endif() get_filename_component(current_list_path ${CMAKE_CURRENT_LIST_FILE} PATH) set(MONO_USE_FILE ${current_list_path}/UseMONO.cmake) mark_as_advanced( MONO_EXECUTABLE MCS_EXECUTABLE GMCS_EXECUTABLE SMCS_EXECUTABLE DMCS_EXECUTABLE GACUTIL_EXECUTABLE ILASM_EXECUTABLE SN_EXECUTABLE ) GDCM-3.0.10/CMake/FindMd5sum.cmake000066400000000000000000000034021412732066400162460ustar00rootroot00000000000000# # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # find md5sum set(Md5sum_FOUND FALSE) find_program(Md5sum_EXECUTABLE md5sum) mark_as_advanced(Md5sum_EXECUTABLE) if (Md5sum_EXECUTABLE) set(Md5sum_FOUND TRUE) endif () # Compute the md5sums file by doing a recursion of directory: `DIRECTORY` macro(COMPUTE_MD5SUMS DIRECTORY OUTPUT_FILE) # Super ugly and barely readable but you need that in order to # work around a deficiency in EXECUTE_PROCESS which does not have dependencies scanning file(WRITE ${CMAKE_BINARY_DIR}/md5sum.cmake " file(GLOB_RECURSE MD5SUM_INPUT_FILES ${DIRECTORY}/* ) execute_process( COMMAND md5sum \${MD5SUM_INPUT_FILES} WORKING_DIRECTORY ${DIRECTORY} OUTPUT_VARIABLE md5sum_VAR # OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE md5sum_RES ) # apparently md5sums start with: usr/... string(REPLACE ${DIRECTORY}/ \"\" md5sum_VAR_clean \${md5sum_VAR}) file(WRITE ${CMAKE_BINARY_DIR}/md5sums \${md5sum_VAR_clean}) " ) add_custom_command( OUTPUT ${OUTPUT_FILE} COMMAND cmake ARGS -P ${CMAKE_BINARY_DIR}/md5sum.cmake WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS ${DIRECTORY} ${CMAKE_BINARY_DIR}/md5sum.cmake COMMENT "Generating md5sums" ) endmacro() # Report the results. if(NOT Md5sum_FOUND) set(Md5sum_DIR_MESSAGE "Md5sum was not found. Make sure the entries Md5sum_* are set.") if(NOT Md5sum_FIND_QUIETLY) message(STATUS "${Md5sum_DIR_MESSAGE}") else() if(Md5sum_FIND_REQUIRED) message(FATAL_ERROR "${Md5sum_DIR_MESSAGE}") endif() endif() endif() GDCM-3.0.10/CMake/FindOpenJPEG.cmake000066400000000000000000000023051412732066400164440ustar00rootroot00000000000000# - Try to find the OpenJPEG (JPEG 2000) library # # Read-Only variables: # OPENJPEG_FOUND - system has the OpenJPEG library # OPENJPEG_INCLUDE_DIR - the OpenJPEG include directory # OPENJPEG_LIBRARIES - The libraries needed to use OpenJPEG #============================================================================= # Copyright 2006-2011 Mathieu Malaterre # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) # Try with pkg-config first find_package(PkgConfig) pkg_check_modules(OPENJPEG libopenjp2) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(OpenJPEG REQUIRED_VARS OPENJPEG_LIBRARIES OPENJPEG_INCLUDE_DIRS VERSION_VAR OPENJPEG_VERSION ) mark_as_advanced( OPENJPEG_LIBRARIES OPENJPEG_INCLUDE_DIRS ) GDCM-3.0.10/CMake/FindOpenSSL.cmake000066400000000000000000000106541412732066400163660ustar00rootroot00000000000000# - Try to find the OpenSSL encryption library # Once done this will define # # OPENSSL_ROOT_DIR - Set this variable to the root installation of OpenSSL # # Read-Only variables: # OPENSSL_FOUND - system has the OpenSSL library # OPENSSL_INCLUDE_DIR - the OpenSSL include directory # OPENSSL_LIBRARIES - The libraries needed to use OpenSSL #============================================================================= # Copyright 2006-2009 Kitware, Inc. # Copyright 2006 Alexander Neundorf # Copyright 2009-2011 Mathieu Malaterre # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distributed this file outside of CMake, substitute the full # License text for the above reference.) # http://www.slproweb.com/products/Win32OpenSSL.html set(_OPENSSL_ROOT_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]" ) set(_OPENSSL_ROOT_PATHS "C:/OpenSSL/" "C:/OpenSSL-Win32/" ) find_path(OPENSSL_ROOT_DIR NAMES include/openssl/ssl.h HINTS ${_OPENSSL_ROOT_HINTS} PATHS ${_OPENSSL_ROOT_PATHS} ) mark_as_advanced(OPENSSL_ROOT_DIR) # Re-use the previous path: find_path(OPENSSL_INCLUDE_DIR openssl/ssl.h PATHS ${OPENSSL_ROOT_DIR}/include ) if(WIN32 AND NOT CYGWIN) # MINGW should go here too if(MSVC) # /MD and /MDd are the standard values - if someone wants to use # others, the libnames have to change here too # use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b # TODO: handle /MT and static lib # In Visual C++ naming convention each of these four kinds of Windows libraries has it's standard suffix: # * MD for dynamic-release # * MDd for dynamic-debug # * MT for static-release # * MTd for static-debug # Implementation details: # We are using the libraries located in the VC subdir instead of the parent directory even though : # libeay32MD.lib is identical to ../libeay32.lib, and # ssleay32MD.lib is identical to ../ssleay32.lib find_library(LIB_EAY_DEBUG NAMES libeay32MDd libeay32 PATHS ${OPENSSL_ROOT_DIR}/lib/VC ) find_library(LIB_EAY_RELEASE NAMES libeay32MD libeay32 PATHS ${OPENSSL_ROOT_DIR}/lib/VC ) find_library(SSL_EAY_DEBUG NAMES ssleay32MDd ssleay32 ssl PATHS ${OPENSSL_ROOT_DIR}/lib/VC ) find_library(SSL_EAY_RELEASE NAMES ssleay32MD ssleay32 ssl PATHS ${OPENSSL_ROOT_DIR}/lib/VC ) if( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) set( OPENSSL_LIBRARIES optimized ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} debug ${SSL_EAY_DEBUG} ${LIB_EAY_DEBUG} ) else() set( OPENSSL_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} ) endif() mark_as_advanced(SSL_EAY_DEBUG SSL_EAY_RELEASE) mark_as_advanced(LIB_EAY_DEBUG LIB_EAY_RELEASE) elseif(MINGW) # same player, for MingW find_library(LIB_EAY NAMES libeay32 PATHS ${OPENSSL_ROOT_DIR}/lib/MinGW ) find_library(SSL_EAY NAMES ssleay32 PATHS ${OPENSSL_ROOT_DIR}/lib/MinGW ) mark_as_advanced(SSL_EAY LIB_EAY) set( OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY} ) else() # Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues: find_library(LIB_EAY NAMES libeay32 PATHS ${OPENSSL_ROOT_DIR}/lib ) find_library(SSL_EAY NAMES ssleay32 PATHS ${OPENSSL_ROOT_DIR}/lib ) mark_as_advanced(SSL_EAY LIB_EAY) set( OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY} ) endif() else() find_library(OPENSSL_SSL_LIBRARIES NAMES ssl ssleay32 ssleay32MD) find_library(OPENSSL_CRYPTO_LIBRARIES NAMES crypto) mark_as_advanced(OPENSSL_CRYPTO_LIBRARIES OPENSSL_SSL_LIBRARIES) set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES}) endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(OpenSSL DEFAULT_MSG OPENSSL_LIBRARIES OPENSSL_INCLUDE_DIR ) mark_as_advanced(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES) GDCM-3.0.10/CMake/FindPAPYRUS3.cmake000066400000000000000000000017671412732066400163360ustar00rootroot00000000000000# - Find papyrus3 # Find the native PAPYRUS3 headers and libraries. # This module defines # PAPYRUS3_INCLUDE_DIRS - the json include directory # PAPYRUS3_LIBRARIES - the libraries needed to use json # PAPYRUS3_FOUND - system has the json library # # Copyright (c) 2013 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. set(PAPYRUS3_INCLUDE_DIRECTORIES /usr/include/ /usr/include/Papyrus3 ) find_path(PAPYRUS3_INCLUDE_DIR Papyrus3.h ${PAPYRUS3_INCLUDE_DIRECTORIES} ) find_library(PAPYRUS3_LIBRARY NAMES Papyrus3) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PAPYRUS3 DEFAULT_MSG PAPYRUS3_LIBRARY PAPYRUS3_INCLUDE_DIR ) if(PAPYRUS3_FOUND) set(PAPYRUS3_LIBRARIES ${PAPYRUS3_LIBRARY}) set(PAPYRUS3_INCLUDE_DIRS ${PAPYRUS3_INCLUDE_DIR}) endif() mark_as_advanced( PAPYRUS3_LIBRARY PAPYRUS3_INCLUDE_DIR ) GDCM-3.0.10/CMake/FindPHP5.cmake000066400000000000000000000025321412732066400156130ustar00rootroot00000000000000# - Find PHP5 # This module finds if PHP5 is installed and determines where the include files # and libraries are. It also determines what the name of the library is. This # code sets the following variables: # # PHP5_INCLUDE_PATH = path to where php.h can be found # PHP5_EXECUTABLE = full path to the php5 binary # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # set(PHP5_POSSIBLE_INCLUDE_PATHS /usr/include/php5 /usr/local/include/php5 /usr/include/php /usr/local/include/php /usr/local/apache/php ) set(PHP5_POSSIBLE_LIB_PATHS /usr/lib ) find_path(PHP5_FOUND_INCLUDE_PATH main/php.h ${PHP5_POSSIBLE_INCLUDE_PATHS}) if(PHP5_FOUND_INCLUDE_PATH) set(php5_paths "${PHP5_POSSIBLE_INCLUDE_PATHS}") foreach(php5_path Zend main TSRM) set(php5_paths ${php5_paths} "${PHP5_FOUND_INCLUDE_PATH}/${php5_path}") endforeach() set(PHP5_INCLUDE_PATH "${php5_paths}" CACHE INTERNAL "PHP5 include paths") endif() find_program(PHP5_EXECUTABLE NAMES php5 php ) mark_as_advanced( PHP5_EXECUTABLE PHP5_FOUND_INCLUDE_PATH ) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PHP5 DEFAULT_MSG PHP5_EXECUTABLE PHP5_INCLUDE_PATH) GDCM-3.0.10/CMake/FindPVRGJPEG.cmake000066400000000000000000000015001412732066400163150ustar00rootroot00000000000000# # this module looks for PVRG-JPEG # # PVRG_JPEG_EXECUTABLE - the full path to pvrg-jpeg # PVRG_JPEG_FOUND - If false, don't attempt to use pvrg-jpeg # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # find_program(PVRGJPEG_EXECUTABLE pvrg-jpeg ) mark_as_advanced( PVRGJPEG_EXECUTABLE ) if (PVRGJPEG_EXECUTABLE) set(PVRGJPEG_FOUND "YES") else () set(PVRGJPEG_FOUND "NO") endif () if (PVRGJPEG_FOUND) if (NOT PVRGJPEG_FIND_QUIETLY) message(STATUS "Found PVRGJPEG: ${PVRGJPEG_EXECUTABLE}") endif () else () if (PVRGJPEG_FIND_REQUIRED) message(FATAL_ERROR "Could not find PVRGJPEG exe") endif () endif () GDCM-3.0.10/CMake/FindPoppler.cmake000066400000000000000000000016771412732066400165310ustar00rootroot00000000000000# # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # find_path(POPPLER_INCLUDE_DIR poppler/poppler-config.h /usr/local/include /usr/include ) find_library(POPPLER_LIBRARY NAMES poppler PATHS /usr/lib /usr/local/lib ) if (POPPLER_LIBRARY AND POPPLER_INCLUDE_DIR) set(POPPLER_LIBRARIES ${POPPLER_LIBRARY}) set(POPPLER_INCLUDE_DIRS ${POPPLER_INCLUDE_DIR} ${POPPLER_INCLUDE_DIR}/poppler) set(POPPLER_FOUND "YES") else () set(POPPLER_FOUND "NO") endif () if (POPPLER_FOUND) if (NOT Poppler_FIND_QUIETLY) message(STATUS "Found POPPLER: ${POPPLER_LIBRARIES}") endif () else () if (Poppler_FIND_REQUIRED) message(FATAL_ERROR "Could not find POPPLER library") endif () endif () mark_as_advanced( POPPLER_LIBRARY POPPLER_INCLUDE_DIR ) GDCM-3.0.10/CMake/FindRsync.cmake000066400000000000000000000011271412732066400161740ustar00rootroot00000000000000# # This module finds if rsync is installed # # RSYNC_EXECUTABLE = full path to the pike binary # # Typical usage for gdcm is: # rsync -avH --delete [options] rsync.creatis.insa-lyon.fr::module localdir # Compression option is: -z # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # find_program(RSYNC_EXECUTABLE NAMES rsync PATHS /usr/bin /usr/local/bin ) mark_as_advanced( RSYNC_EXECUTABLE ) GDCM-3.0.10/CMake/FindSOCKET++.cmake000066400000000000000000000016421412732066400162160ustar00rootroot00000000000000# - Find socket++ # Find the native socket++ headers and libraries. # This module defines # SOCKETXX_INCLUDE_DIRS - the json include directory # SOCKETXX_LIBRARIES - the libraries needed to use json # SOCKETXX_FOUND - system has the json library # # Copyright (c) 2013 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. find_path(SOCKETXX_INCLUDE_DIR socket++.h /usr/include/socket++ ) find_library(SOCKETXX_LIBRARY NAMES Papyrus3) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(SOCKETXX DEFAULT_MSG SOCKETXX_LIBRARY SOCKETXX_INCLUDE_DIR ) if(SOCKETXX_FOUND) set(SOCKETXX_LIBRARIES ${SOCKETXX_LIBRARY}) set(SOCKETXX_INCLUDE_DIRS ${SOCKETXX_INCLUDE_DIR}) endif() mark_as_advanced( SOCKETXX_LIBRARY SOCKETXX_INCLUDE_DIR ) GDCM-3.0.10/CMake/FindSQLITE3.cmake000066400000000000000000000011261412732066400161610ustar00rootroot00000000000000# # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # find_path(SQLITE3_INCLUDE_DIR sqlite3.h) find_library(SQLITE3_LIBRARY NAMES sqlite3) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(SQLITE3 DEFAULT_MSG SQLITE3_LIBRARY SQLITE3_INCLUDE_DIR) set(SQLITE3_LIBRARIES ${SQLITE3_LIBRARY}) set(SQLITE3_INCLUDE_DIRS ${SQLITE3_INCLUDE_DIR}) mark_as_advanced(SQLITE3_LIBRARY SQLITE3_INCLUDE_DIR ) GDCM-3.0.10/CMake/FindUUID.cmake000066400000000000000000000033051412732066400156440ustar00rootroot00000000000000# - Find UUID # Find the native UUID includes and library # This module defines # UUID_INCLUDE_DIR, where to find jpeglib.h, etc. # UUID_LIBRARIES, the libraries needed to use UUID. # UUID_FOUND, If false, do not try to use UUID. # also defined, but not for general use are # UUID_LIBRARY, where to find the UUID library. # # Copyright (c) 2006-2016 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # On Mac OS X the uuid functions are in the System library. if(APPLE) set(UUID_LIBRARY_VAR System) else() # Linux type: set(UUID_LIBRARY_VAR uuid) endif() find_library(UUID_LIBRARY NAMES ${UUID_LIBRARY_VAR} PATHS /lib /usr/lib /usr/local/lib ) # Must be *after* the lib itself set(CMAKE_FIND_FRAMEWORK_SAVE ${CMAKE_FIND_FRAMEWORK}) set(CMAKE_FIND_FRAMEWORK NEVER) find_path(UUID_INCLUDE_DIR uuid/uuid.h /usr/local/include /usr/include ) if (UUID_LIBRARY AND UUID_INCLUDE_DIR) set(UUID_LIBRARIES ${UUID_LIBRARY}) set(UUID_FOUND "YES") else () set(UUID_FOUND "NO") endif () if (UUID_FOUND) if (NOT UUID_FIND_QUIETLY) message(STATUS "Found UUID: ${UUID_LIBRARIES}") endif () else () if (UUID_FIND_REQUIRED) message( "library: ${UUID_LIBRARY}" ) message( "include: ${UUID_INCLUDE_DIR}" ) message(FATAL_ERROR "Could not find UUID library") endif () endif () # Deprecated declarations. #set (NATIVE_UUID_INCLUDE_PATH ${UUID_INCLUDE_DIR} ) #get_filename_component (NATIVE_UUID_LIB_PATH ${UUID_LIBRARY} PATH) mark_as_advanced( UUID_LIBRARY UUID_INCLUDE_DIR ) set(CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK_SAVE}) GDCM-3.0.10/CMake/GetSystemProperty.java000066400000000000000000000024041412732066400176260ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ import java.util.Properties; import java.util.Enumeration; /* * Java only allows setting properties from the command line not reading them * Let's create a small app for this specific task then: * * namely: */ public class GetSystemProperty { public static void main(String args[]) { if( args.length == 0 ) { Properties p = System.getProperties(); Enumeration keys = p.keys(); while (keys.hasMoreElements()) { String key = (String)keys.nextElement(); String value = (String)p.get(key); System.out.println(key + " : " + value); } } else { for (String key: args) { System.out.println(System.getProperty( key )); } } } } GDCM-3.0.10/CMake/InstallMacros.cmake000066400000000000000000000050421412732066400170500ustar00rootroot00000000000000# # This module install PDB files. # # Based on users posts: # http://www.cmake.org/pipermail/cmake/2007-October/016924.html # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # macro(install_swig_module module_name module_type) # The following trick permits installation of module to the right destination: # binary path for dll (on windows) # library for non-dll platform if(WIN32) set(MODDST ${GDCM_INSTALL_BIN_DIR}) else() set(MODDST ${GDCM_INSTALL_LIB_DIR}) endif() string(TOUPPER ${module_type}Module MODTYPE) set(MODDIR GDCM_INSTALL_${MODTYPE}_DIR) # if user sets a GDCM_INSTALL_PYTHONMODULE_DIR if(${MODDIR}) set(MODDST "${${MODDIR}}") endif() if(NOT GDCM_INSTALL_NO_LIBRARIES) install(TARGETS ${SWIG_MODULE_${module_name}_REAL_NAME} RUNTIME DESTINATION ${MODDST} COMPONENT ${module_type}Module LIBRARY DESTINATION ${MODDST} COMPONENT ${module_type}Module ) endif() endmacro() macro(install_library library) if(NOT GDCM_INSTALL_NO_LIBRARIES) # Runtime install(TARGETS ${library} EXPORT ${GDCM_TARGETS_NAME} RUNTIME DESTINATION ${GDCM_INSTALL_BIN_DIR} COMPONENT Applications LIBRARY DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT Libraries ${NAMELINK_SKIP} INCLUDES DESTINATION ${GDCM_INSTALL_INCLUDE_DIR} ARCHIVE DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT DebugDevel ) # need recent cmake: http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cbe7e8fa #export(EXPORT ${GDCM_TARGETS_NAME} APPEND FILE "${CMAKE_CURRENT_BINARY_DIR}/foo.cmake") #Development if(NAMELINK_ONLY) install(TARGETS ${library} EXPORT ${GDCM_TARGETS_NAME} LIBRARY DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT DebugDevel ${NAMELINK_ONLY} ) endif() endif() endmacro() macro (install_pdb library) if(BUILD_SHARED_LIBS) if (MSVC) install ( FILES "$" DESTINATION "${GDCM_INSTALL_BIN_DIR}" COMPONENT DebugDevel CONFIGURATIONS Debug RelWithDebInfo ) endif () endif () endmacro () # At least one argument is required macro (install_includes glob_expression) if(NOT GDCM_INSTALL_NO_DEVELOPMENT) file(GLOB header_files ${glob_expression} ${ARGN}) install(FILES ${header_files} DESTINATION ${GDCM_INSTALL_INCLUDE_DIR} COMPONENT Headers ) endif() endmacro () GDCM-3.0.10/CMake/InstallRequiredVTKLibraries.cmake000066400000000000000000000046251412732066400216340ustar00rootroot00000000000000# - Install VTK required libs for GDCM # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # if("${VTK_MAJOR_VERSION}" LESS 6) set(vtklist vtkCommon vtkFiltering vtkGraphics vtkHybrid vtkIO vtkImaging vtkRendering vtkWidgets # utilities vtkDICOMParser vtkNetCDF vtkNetCDF_cxx vtkexoIIc vtkexpat vtkfreetype vtkftgl vtkjpeg vtkmetaio vtkpng vtksys vtktiff vtkverdict vtkzlib ) foreach(el ${vtklist}) list(APPEND CMAKE_INSTALL_VTK_RUNTIME_LIBS ${VTK_DIR}/bin/${el}.dll) endforeach() if(CMAKE_INSTALL_VTK_RUNTIME_LIBS) if(NOT CMAKE_INSTALL_VTK_RUNTIME_LIBS_SKIP) if(NOT CMAKE_INSTALL_VTK_RUNTIME_DESTINATION) if(WIN32) set(CMAKE_INSTALL_VTK_RUNTIME_DESTINATION bin) else() set(CMAKE_INSTALL_VTK_RUNTIME_DESTINATION lib) endif() endif() install(PROGRAMS ${CMAKE_INSTALL_VTK_RUNTIME_LIBS} DESTINATION ${CMAKE_INSTALL_VTK_RUNTIME_DESTINATION} COMPONENT VTKLibraries ) endif() endif() else() set(vtkgdcm_LIBS vtkCommonCore vtkImagingCore vtkImagingSources vtkIOImage vtkIOLegacy vtksys ) set(vtkgdcm_COND_LIBS vtkIOMPIImage vtkInteractionStyle vtkRenderingCore vtkRenderingFreeType vtkRenderingFreeTypeOpenGL vtkRenderingOpenGL ) foreach(TMP_LIB ${VTK_LIBRARIES}) foreach(TRY_LIB ${vtkgdcm_COND_LIBS}) if("${TMP_LIB}" STREQUAL "${TRY_LIB}") set(vtkgdcm_LIBS ${vtkgdcm_LIBS} "${TRY_LIB}") endif() endforeach() endforeach() foreach(el ${vtkgdcm_LIBS}) list(APPEND CMAKE_INSTALL_VTK_RUNTIME_LIBS ${VTK_DIR}/../../../bin/${el}-${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}.dll) endforeach() if(CMAKE_INSTALL_VTK_RUNTIME_LIBS) if(NOT CMAKE_INSTALL_VTK_RUNTIME_LIBS_SKIP) if(NOT CMAKE_INSTALL_VTK_RUNTIME_DESTINATION) if(WIN32) set(CMAKE_INSTALL_VTK_RUNTIME_DESTINATION bin) else() set(CMAKE_INSTALL_VTK_RUNTIME_DESTINATION lib) endif() endif() install(PROGRAMS ${CMAKE_INSTALL_VTK_RUNTIME_LIBS} DESTINATION ${CMAKE_INSTALL_VTK_RUNTIME_DESTINATION} COMPONENT VTKLibraries ) endif() endif() endif() GDCM-3.0.10/CMake/Release/000077500000000000000000000000001412732066400146525ustar00rootroot00000000000000GDCM-3.0.10/CMake/Release/README.cygwin.in000066400000000000000000000000001412732066400174240ustar00rootroot00000000000000GDCM-3.0.10/CMake/Release/cygwin-package.sh.in000066400000000000000000000000001412732066400204720ustar00rootroot00000000000000GDCM-3.0.10/CMake/Release/cygwin-patch.diff.in000066400000000000000000000000001412732066400204740ustar00rootroot00000000000000GDCM-3.0.10/CMake/Release/cygwin-setup.hint.in000066400000000000000000000000001412732066400205670ustar00rootroot00000000000000GDCM-3.0.10/CMake/Toolchain-gcc-arm-linux-gnueabi.cmake000066400000000000000000000025651412732066400223000ustar00rootroot00000000000000# http://wiki.debian.org/BuildingCrossCompilers # Usage: # # $ cmake ../gdcm -DCMAKE_TOOLCHAIN_FILE=../gdcm/CMake/Toolchain-gcc-arm-linux-gnueabi.cmake # # For gdcm you need at least the following three packages (squeeze suite) # # fix /etc/apt/source.lists # + deb http://www.emdebian.org/debian squeeze main # # // prebuilt Emdebian project # sudo apt-get install g++-4.4-arm-linux-gnueabi # # sudo xapt -S squeeze -M http://ftp.fr.debian.org/debian/ -a armel -m zlib1g-dev uuid-dev libexpat1-dev # # qemu-arm -L /usr/arm-linux-gnueabi/ ./bin/gdcminfo test.acr # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # the name of the target operating system set(CMAKE_SYSTEM_NAME Linux) # which compilers to use for C and C++ set(CMAKE_C_COMPILER arm-linux-gnueabi-gcc-4.4) set(CMAKE_CXX_COMPILER arm-linux-gnueabi-g++-4.4) # here is the target environment located set(CMAKE_FIND_ROOT_PATH /usr/arm-linux-gnueabi) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) GDCM-3.0.10/CMake/Toolchain-gcc-m32.cmake000066400000000000000000000023711412732066400173500ustar00rootroot00000000000000# http://www.cmake.org/Wiki/CmakeMingw # Usage: # # $ cmake ../trunk -DCMAKE_TOOLCHAIN_FILE=../trunk/CMake/Toolchain-mingw32.cmake # # For gdcm you need at least the following three package (2008/08/19): # # apt-cross --arch i386 -i zlib1g-dev # apt-cross --arch i386 -i uuid-dev # apt-cross --arch i386 -i libexpat1-dev # # Do not forget to set to on the following: # GDCM_USE_SYSTEM_EXPAT / GDCM_USE_SYSTEM_ZLIB / GDCM_USE_SYSTEM_UUID # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # the name of the target operating system set(CMAKE_SYSTEM_NAME Linux) # which compilers to use for C and C++ set(CMAKE_C_COMPILER gcc) set(CMAKE_C_FLAGS -m32) set(CMAKE_CXX_COMPILER g++) set(CMAKE_CXX_FLAGS -m32) # here is the target environment located set(CMAKE_FIND_ROOT_PATH /usr/i486-linux-gnu ) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) GDCM-3.0.10/CMake/Toolchain-gcc-powerpc.cmake000066400000000000000000000032731412732066400204300ustar00rootroot00000000000000# http://www.cmake.org/Wiki/CmakeMingw # http://doc.cliss21.com/index.php?title=QEMU # Usage: # # $ cmake ../trunk -DCMAKE_TOOLCHAIN_FILE=../trunk/CMake/Toolchain-mingw32.cmake # # For gdcm you need at least the following three package (2008/08/19): # # fix /etc/apt/source.lists # + deb http://www.emdebian.org/debian/ unstable main # # // prebuilt Emdebian project # sudo apt-get install g++-4.1-powerpc-linux-gnu # # apt-cross --arch powerpc -i zlib1g-dev # apt-cross --arch powerpc -i uuid-dev # apt-cross --arch powerpc -i libexpat1-dev # #I was getting: #$ qemu-ppc ./a.out #/lib/ld.so.1: No such file or directory # #Two approach for solving it: #1. #CMAKE_EXE_LINKER_FLAGS:STRING=-static #2. #$ qemu-ppc -L /usr/powerpc-linux-gnu/ ./a.out #Hello cross-compiling world! # # # Do not forget to set to on the following: # GDCM_USE_SYSTEM_EXPAT / GDCM_USE_SYSTEM_ZLIB / GDCM_USE_SYSTEM_UUID # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # the name of the target operating system set(CMAKE_SYSTEM_NAME Linux) # which compilers to use for C and C++ set(CMAKE_C_COMPILER powerpc-linux-gnu-gcc) set(CMAKE_CXX_COMPILER powerpc-linux-gnu-g++) # here is the target environment located set(CMAKE_FIND_ROOT_PATH /usr/powerpc-linux-gnu ) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) GDCM-3.0.10/CMake/Toolchain-mingw32.cmake000066400000000000000000000021621412732066400175010ustar00rootroot00000000000000# http://www.cmake.org/Wiki/CmakeMingw # Usage: # # mingw32 does not seems to be updated in Debian, switch to mingw-w64 target # i686 instead: # # $ sudo apt-get install g++-mingw-w64-i686 # $ cmake -DCMAKE_TOOLCHAIN_FILE=../gdcm/CMake/Toolchain-mingw32.cmake ../gdcm # # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # the name of the target operating system set(CMAKE_SYSTEM_NAME Windows) # which compilers to use for C and C++ set(CMAKE_C_COMPILER i686-w64-mingw32-gcc) set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) set(CMAKE_RC_COMPILER i686-w64-mingw32-windres) # here is the target environment located set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) GDCM-3.0.10/CMake/Toolchain-mingw64.cmake000066400000000000000000000020221412732066400175010ustar00rootroot00000000000000# http://www.cmake.org/Wiki/CmakeMingw # Usage: # # $ sudo apt-get install mingw-w64 # $ cmake -DCMAKE_TOOLCHAIN_FILE=../gdcm/CMake/Toolchain-mingw64.cmake ../gdcm # # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # the name of the target operating system set(CMAKE_SYSTEM_NAME Windows) # which compilers to use for C and C++ set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) # here is the target environment located set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) GDCM-3.0.10/CMake/UseCSharp.cmake000066400000000000000000000153151412732066400161360ustar00rootroot00000000000000# - C# module for CMake # Defines the following macros: # CSHARP_ADD_EXECUTABLE(name [ files ]) # - Define C# executable with given name # CSHARP_ADD_LIBRARY(name [ files ]) # - Define C# library with given name # CSHARP_LINK_LIBRARIES(name [ libraries ]) # - Link libraries to csharp library # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # TODO: # http://www.cs.nuim.ie/~jpower/Research/csharp/Index.html if(WIN32) include(${DotNETFrameworkSDK_USE_FILE}) # remap set(CMAKE_CSHARP1_COMPILER ${CSC_v1_EXECUTABLE}) set(CMAKE_CSHARP2_COMPILER ${CSC_v2_EXECUTABLE}) set(CMAKE_CSHARP3_COMPILER ${CSC_v3_EXECUTABLE}) set(CMAKE_CSHARP4_COMPILER ${CSC_v4_EXECUTABLE}) #set(CMAKE_CSHARP3_INTERPRETER ${MONO_EXECUTABLE}) else() include(${MONO_USE_FILE}) set(CMAKE_CSHARP1_COMPILER ${MCS_EXECUTABLE}) if(GMCS_EXECUTABLE) set(CMAKE_CSHARP2_COMPILER ${GMCS_EXECUTABLE}) elseif(MCS_EXECUTABLE) set(CMAKE_CSHARP2_COMPILER ${MCS_EXECUTABLE}) endif() if(SMCS_EXECUTABLE) set(CMAKE_CSHARP3_COMPILER ${SMCS_EXECUTABLE}) elseif(MCS_EXECUTABLE) set(CMAKE_CSHARP3_COMPILER ${MCS_EXECUTABLE}) endif() if(DMCS_EXECUTABLE) set(CMAKE_CSHARP4_COMPILER ${DMCS_EXECUTABLE}) elseif(MCS_EXECUTABLE) set(CMAKE_CSHARP4_COMPILER ${MCS_EXECUTABLE}) endif() set(CMAKE_CSHARP_INTERPRETER ${MONO_EXECUTABLE}) endif() set(DESIRED_CSHARP_COMPILER_VERSION 4 CACHE STRING "Pick a version for C# compiler to use: 1, 2, 3 or 4") mark_as_advanced(DESIRED_CSHARP_COMPILER_VERSION) # default to v1: if(DESIRED_CSHARP_COMPILER_VERSION MATCHES 1) set(CMAKE_CSHARP_COMPILER ${CMAKE_CSHARP1_COMPILER}) elseif(DESIRED_CSHARP_COMPILER_VERSION MATCHES 2) set(CMAKE_CSHARP_COMPILER ${CMAKE_CSHARP2_COMPILER}) elseif(DESIRED_CSHARP_COMPILER_VERSION MATCHES 3) set(CMAKE_CSHARP_COMPILER ${CMAKE_CSHARP3_COMPILER}) elseif(DESIRED_CSHARP_COMPILER_VERSION MATCHES 4) set(CMAKE_CSHARP_COMPILER ${CMAKE_CSHARP4_COMPILER}) else() message(FATAL_ERROR "Do not know this version") endif() # CMAKE_CSHARP_COMPILER /platform and anycpu if(WIN32) # There is a subttle issue when compiling on 64bits platform using a 32bits compiler # See bug ID: 3510023 (BadImageFormatException: An attempt was made to load a progr) set(CSC_ACCEPTS_PLATFORM_FLAG 0) if(CMAKE_CSHARP_COMPILER) execute_process(COMMAND "${CMAKE_CSHARP_COMPILER}" "/?" OUTPUT_VARIABLE CSC_HELP) # get version (no /version, so use /help output): if("${CSC_HELP}" MATCHES "Compiler version") string(REGEX REPLACE ".*Compiler version ([0-9\\.]+).*" "\\1" VERSION_STRING "${CSC_HELP}") message(STATUS "Comp version: ${VERSION_STRING}") endif() # when cmd locale is in French it displays: "/platform:" in english: "/platform:" # so only regex match in /platform: if("${CSC_HELP}" MATCHES "/platform:") set(CSC_ACCEPTS_PLATFORM_FLAG 1) endif() endif() if(NOT DEFINED CSC_PLATFORM_FLAG) set(CSC_PLATFORM_FLAG "") if(CSC_ACCEPTS_PLATFORM_FLAG) set(CSC_PLATFORM_FLAG "/platform:x86") if("${CMAKE_SIZEOF_VOID_P}" GREATER 4) set(CSC_PLATFORM_FLAG "/platform:x64") endif() endif() endif() endif() # Check something is found: if(NOT CMAKE_CSHARP_COMPILER) # status message only for now: message("Sorry C# v${DESIRED_CSHARP_COMPILER_VERSION} was not found on your system") else() #if (NOT CSHARP_FIND_QUIETLY) message(STATUS "Will be using C# v${DESIRED_CSHARP_COMPILER_VERSION}: ${CMAKE_CSHARP_COMPILER}") #endif () endif() macro(CSHARP_ADD_LIBRARY name) set(csharp_cs_sources) set(csharp_cs_sources_dep) foreach(it ${ARGN}) if(EXISTS ${it}) set(csharp_cs_sources "${csharp_cs_sources} ${it}") set(csharp_cs_sources_dep ${csharp_cs_sources_dep} ${it}) else() if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${it}) set(csharp_cs_sources "${csharp_cs_sources} ${CMAKE_CURRENT_SOURCE_DIR}/${it}") set(csharp_cs_sources_dep ${csharp_cs_sources_dep} ${CMAKE_CURRENT_SOURCE_DIR}/${it}) else() #message("Could not find: ${it}") set(csharp_cs_sources "${csharp_cs_sources} ${it}") endif() endif() endforeach() #set(SHARP #) separate_arguments(csharp_cs_sources) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}.dll COMMAND ${CMAKE_CSHARP_COMPILER} ARGS "/t:library" "/out:${name}.dll" ${csharp_cs_sources} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS "${csharp_cs_sources_dep}" COMMENT "Creating Csharp library ${name}.cs" ) add_custom_target(CSharp_${name} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${name}.dll ) endmacro() macro(CSHARP_ADD_EXECUTABLE name) set(csharp_cs_sources) foreach(it ${ARGN}) if(EXISTS ${it}) set(csharp_cs_sources "${csharp_cs_sources} ${it}") else() if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${it}) set(csharp_cs_sources "${csharp_cs_sources} ${CMAKE_CURRENT_SOURCE_DIR}/${it}") else() #message("Could not find: ${it}") set(csharp_cs_sources "${csharp_cs_sources} ${it}") endif() endif() endforeach() set(CSHARP_EXECUTABLE_${name}_ARGS #"/out:${name}.dll" ${csharp_cs_sources} #"/r:gdcm_csharp.dll" "/out:${name}.exe ${csharp_cs_sources}" ) endmacro() macro(CSHARP_LINK_LIBRARIES name) set(csharp_libraries) set(csharp_libraries_depends) foreach(it ${ARGN}) #if(EXISTS ${it}.dll) set(csharp_libraries "${csharp_libraries} /r:${it}.dll") # set(csharp_libraries_depends ${it}.dll) #else() # if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${it}.dll) # set(csharp_libraries "${csharp_libraries} /r:${it}.dll") # set(csharp_libraries_depends ${CMAKE_CURRENT_BINARY_DIR}/${it}.dll) # else() # message("Could not find: ${it}") # endif() #endif() endforeach() set(CSHARP_EXECUTABLE_${name}_ARGS " ${csharp_libraries} ${CSHARP_EXECUTABLE_${name}_ARGS}") #message( "DEBUG: ${CSHARP_EXECUTABLE_${name}_ARGS}" ) # BAD DESIGN ! # This should be in the _ADD_EXECUTABLE... separate_arguments(CSHARP_EXECUTABLE_${name}_ARGS) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}.exe COMMAND ${CMAKE_CSHARP_COMPILER} #ARGS "/r:gdcm_csharp.dll" "/out:${name}.exe" ${csharp_cs_sources} ARGS ${CSHARP_EXECUTABLE_${name}_ARGS} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} #DEPENDS ${csharp_cs_sources} COMMENT "Create ${name}.exe" ) #message("DEBUG2:${csharp_libraries_depends}") add_custom_target(CSHARP_EXECUTABLE_${name} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${name}.exe ${csharp_libraries_depends} ) endmacro() GDCM-3.0.10/CMake/UseCSharpTest.cmake000066400000000000000000000044241412732066400167750ustar00rootroot00000000000000# Add a python test from a python file # One cannot simply do: # set(ENV{PYTHONPATH} ${LIBRARY_OUTPUT_PATH}) # set(my_test "from test_mymodule import *\;test_mymodule()") # add_test(PYTHON-TEST-MYMODULE python -c ${my_test}) # Since cmake is only transmitting the ADD_TEST line to ctest thus you are losing # the env var. The only way to store the env var is to physically write in the cmake script # whatever PYTHONPATH you want and then add the test as 'cmake -P python_test.cmake' # # Usage: # set_source_files_properties(test.py PROPERTIES PYTHONPATH # "${LIBRARY_OUTPUT_PATH}:${VTK_DIR}") # ADD_PYTHON_TEST(PYTHON-TEST test.py) # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # UseCSharp.cmake macro(ADD_CSHARP_TEST TESTNAME FILENAME) get_source_file_property(loc ${FILENAME} LOCATION) get_source_file_property(pyenv ${FILENAME} RUNTIMEPATH) if(CMAKE_CONFIGURATION_TYPES) # I cannot use CMAKE_CFG_INTDIR since it expand to "$(OutDir)" if(pyenv) set(pyenv "${pyenv};${LIBRARY_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}") else() set(pyenv ${LIBRARY_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}) #set(pyenv ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}) #set(pyenv ${LIBRARY_OUTPUT_PATH}/${CMAKE_CONFIG_TYPE}) #set(pyenv ${LIBRARY_OUTPUT_PATH}/\${CMAKE_CONFIG_TYPE}) endif() else() if(pyenv) set(pyenv ${pyenv}:${LIBRARY_OUTPUT_PATH}) else() set(pyenv ${LIBRARY_OUTPUT_PATH}) endif() endif() string(REGEX REPLACE ";" " " wo_semicolumn "${ARGN}") file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake " set(ENV{LD_LIBRARY_PATH} ${pyenv}) set(ENV{MONO_PATH} ${pyenv}) message(\"${pyenv}\") execute_process( COMMAND ${CMAKE_CSHARP_INTERPRETER} ${loc} ${wo_semicolumn} RESULT_VARIABLE import_res OUTPUT_VARIABLE import_output ERROR_VARIABLE import_output ) # Pass the output back to ctest if(import_output) message(\"\${import_output}\") endif() if(import_res) message(SEND_ERROR \"\${import_res}\") endif() " ) add_test(NAME ${TESTNAME} COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake) endmacro() GDCM-3.0.10/CMake/UseCopyright.cmake000066400000000000000000000014051412732066400167210ustar00rootroot00000000000000# Handy macro to gather all copyright in a single file (to pass to cpack) # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # macro(CREATE_COPYRIGHT_FILE name) # Always cleanup the file: file(WRITE ${name} "") set(COPYRIGHT_MODULE_FILENAME ${name}) endmacro() # Append copyright file macro(APPEND_COPYRIGHT) # need to raise an error if COPYRIGHT_MODULE_FILENAME is not set... if(EXISTS ${COPYRIGHT_MODULE_FILENAME} ) foreach(filename ${ARGN}) file(READ ${filename} content) file(APPEND ${COPYRIGHT_MODULE_FILENAME} ${content}) endforeach() endif() endmacro() GDCM-3.0.10/CMake/UseDebian.cmake000066400000000000000000000145361412732066400161440ustar00rootroot00000000000000# create .deb file # You need to setup CPack first ! # UGLY: I reuse CPACK_NSIS_CONTACT to get the contact name for the debian package... # TODO: How do I transmit the 'Depends' line ? # DOCUMENTATION; You need to fill these values to set the control file: # "Package: ${DEBIAN_PACKAGE_NAME} # Version: ${DEBIAN_PACKAGE_VERSION} # Architecture: ${DEBIAN_ARCHITECTURE} # Depends: ${DEBIAN_PACKAGE_DEPENDS} # Maintainer: ${CPACK_NSIS_CONTACT} # Description: ${CPACK_PACKAGE_DESCRIPTION_SUMMARY} # Thanks: # Eric Noulard for initial UseRpmTools used as template # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # if(UNIX) if (NOT CMAKE_AR) message(STATUS "No ar, cannot proceed") set(DEBIAN_FOUND FALSE) else () set(DEBIAN_FOUND TRUE) # Detect if CPack was included or not if (NOT DEFINED "CPACK_PACKAGE_NAME") message(FATAL_ERROR "CPack was not included, you should include CPack before Using UseDebian") endif () macro(ADD_DEBIAN_TARGETS DEBNAME) # $ ar tv cmake_2.4.5-1_i386.deb # rw-r--r-- 0/0 4 Dec 4 22:58 2006 debian-binary # rw-r--r-- 0/0 8981 Dec 4 22:58 2006 control.tar.gz # rw-r--r-- 0/0 4893146 Dec 4 22:58 2006 data.tar.gz # Need a newline: # dpkg-deb: archive has no newlines in header add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/debian-binary COMMAND ${CMAKE_COMMAND} ARGS -E echo "2.0" > ${CMAKE_BINARY_DIR}/debian-binary COMMENT "Generating debian-binary" VERBATIM) # seems better to ADD_CUSTOM_COMMAND this way debian-binary may # be regenerated when make is called. # file(WRITE ${CMAKE_BINARY_DIR}/debian-binary "2.0 #" ) # debian policy enforce lower case for package name if(NOT DEBIAN_PACKAGE_NAME) string(TOLOWER ${CPACK_PACKAGE_NAME} DEBIAN_PACKAGE_NAME ) endif() if(NOT DEBIAN_PACKAGE_DEPENDS) set(DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.3.1-6), libgcc1 (>= 1:3.4.2-12)" ) endif() if(NOT DEBIAN_ARCHITECTURE) # There is no such thing as i686 architecture on debian, you should use i386 instead # $ dpkg --print-architecture set(DEBIAN_ARCHITECTURE i386) endif() if(NOT DEBIAN_PACKAGE_VERSION) set(DEBIAN_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION}) endif() #message(${CMAKE_SYSTEM_PROCESSOR}) file(WRITE ${CMAKE_BINARY_DIR}/control "Package: ${DEBIAN_PACKAGE_NAME} Version: ${CPACK_PACKAGE_VERSION} Section: devel Priority: optional Architecture: ${DEBIAN_ARCHITECTURE} Depends: ${DEBIAN_PACKAGE_DEPENDS} Maintainer: ${CPACK_NSIS_CONTACT} Description: ${CPACK_PACKAGE_DESCRIPTION_SUMMARY} . ${DEBIAN_PACKAGE_NAME} was packaged by UseDebian and CMake. . ") # FIXME: # I have no friggin clue how cpack works, let's reinvent the wheel instead #include(${CMAKE_BINARY_DIR}/CPackConfig.cmake) #add_custom_target(data_tgz # COMMAND cpack -G TGZ --config CPackConfig.cmake ## TODO: How to get the cpack package name ? # COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/${CPACK_PACKAGE_FILE_NAME}.tar.gz ${CMAKE_BINARY_DIR}/data.tar.gz #) # let's create a temp directory to call 'DESTDIR=... make install' into: # cleanup file(REMOVE ${CMAKE_BINARY_DIR}/debian_package) # make dir: file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/debian_package) # calling cmake -P cmake_install.cmake is the same as calling make install: add_custom_target(deb_destdir_install COMMAND ${CMAKE_MAKE_PROGRAM} DESTDIR=${CMAKE_BINARY_DIR}/debian_package install DEPENDS ${CMAKE_BINARY_DIR}/cmake_install.cmake COMMENT "Building debian_package directory with DESTDIR" ) add_dependencies(deb_destdir_install all preinstall) # create data.tar.gz from the make install stuff # all files starts with: ./usr add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/data.tar.gz COMMAND cmake -E tar ARGS cfz ${CMAKE_BINARY_DIR}/data.tar.gz . WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/debian_package DEPENDS ${CMAKE_BINARY_DIR}/debian_package COMMENT "Generating data.tar.gz" ) # get all the files to be installed: find_package(Md5sum REQUIRED) COMPUTE_MD5SUMS( ${CMAKE_BINARY_DIR}/debian_package ${CMAKE_BINARY_DIR}/md5sums ) # create a tarball (control.tar.gz) of control and md5sums # files need to be in relative path: ./md5sums ./control ... add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/control.tar.gz WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND cmake -E tar ARGS cfz ${CMAKE_BINARY_DIR}/control.tar.gz ./control ./md5sums DEPENDS ${CMAKE_BINARY_DIR}/control ${CMAKE_BINARY_DIR}/md5sums COMMENT "Generating control.tar.gz" ) # Warning order is important: # ar -r your-package-name.deb debian-binary control.tar.gz data.tar.gz # eg: cmake_2.4.5-1_i386.deb add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/${DEBIAN_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}-1_${DEBIAN_ARCHITECTURE}.deb COMMAND ${CMAKE_AR} ARGS -r ${CMAKE_BINARY_DIR}/${DEBIAN_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}-1_${DEBIAN_ARCHITECTURE}.deb ${CMAKE_BINARY_DIR}/debian-binary ${CMAKE_BINARY_DIR}/control.tar.gz ${CMAKE_BINARY_DIR}/data.tar.gz DEPENDS ${CMAKE_BINARY_DIR}/debian-binary ${CMAKE_BINARY_DIR}/control.tar.gz ${CMAKE_BINARY_DIR}/data.tar.gz COMMENT "Generating deb package" ) # the final target: add_custom_target(${DEBNAME}_deb DEPENDS ${CMAKE_BINARY_DIR}/${DEBIAN_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}-1_${DEBIAN_ARCHITECTURE}.deb ) add_dependencies(${DEBNAME}_deb deb_destdir_install) # BUG: debian_package is not removed during a 'make clean': set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "debian-binary;control;md5sums;debian_package;") endmacro() endif () endif() GDCM-3.0.10/CMake/UseDotNETFrameworkSDK.cmake000066400000000000000000000003461412732066400202710ustar00rootroot00000000000000# Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # GDCM-3.0.10/CMake/UseJavaTest.cmake000066400000000000000000000062541412732066400165010ustar00rootroot00000000000000# Add a java test from a java file # # Usage: # set_source_files_properties(test.py PROPERTIES PYTHONPATH # "${LIBRARY_OUTPUT_PATH}:${VTK_DIR}") # ADD_PYTHON_TEST(PYTHON-TEST test.py) # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # Need python interpreter: #find_package(PythonInterp REQUIRED) #mark_as_advanced(PYTHON_EXECUTABLE) # UseCSharp.cmake macro(ADD_JAVA_TEST TESTNAME FILENAME) set(_sep ":") if(WIN32) set(_sep "\\;") endif() get_source_file_property(loc ${FILENAME}.class LOCATION) get_source_file_property(pyenv ${FILENAME}.class RUNTIMEPATH) get_source_file_property(theclasspath ${FILENAME}.class CLASSPATH) get_filename_component(loc2 ${loc} NAME_WE) if(CMAKE_CONFIGURATION_TYPES) # I cannot use CMAKE_CFG_INTDIR since it expand to "$(OutDir)" if(pyenv) set(pyenv "${pyenv};${LIBRARY_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}") else() set(pyenv ${LIBRARY_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}) #set(pyenv ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}) #set(pyenv ${LIBRARY_OUTPUT_PATH}/${CMAKE_CONFIG_TYPE}) #set(pyenv ${LIBRARY_OUTPUT_PATH}/\${CMAKE_CONFIG_TYPE}) endif() else() if(pyenv) set(pyenv ${pyenv}${_sep}${LIBRARY_OUTPUT_PATH}) else() set(pyenv ${LIBRARY_OUTPUT_PATH}) endif() endif() string(REGEX REPLACE ";" " " wo_semicolumn "${ARGN}") set(classpath) if(theclasspath) set(classpath "${theclasspath}${_sep}.") else() set(classpath ".") endif() set(theld_library_path $ENV{LD_LIBRARY_PATH}) set(ld_library_path) if(theld_library_path) set(ld_library_path ${theld_library_path}) endif() if(pyenv) set(ld_library_path ${ld_library_path}${_sep}${pyenv}) endif() file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake " if(UNIX) set(ENV{LD_LIBRARY_PATH} ${ld_library_path}) set(ENV{DYLD_LIBRARY_PATH} ${ld_library_path}) #set(ENV{CLASSPATH} ${pyenv}/gdcm.jar${_sep}.) #message(\"pyenv: ${pyenv}\") else() #set(the_path $ENV{PATH}) set(ENV{PATH} ${ld_library_path}) endif() message(\"ld_library_path: ${ld_library_path}\") message(\"loc: ${loc}\") message(\"loc2: ${loc2}\") message(\"JavaProp_PATH_SEPARATOR: \"${JavaProp_PATH_SEPARATOR}\"\") message(\"classpath: \"${classpath}\"\") message(\"java runtime: ${Java_JAVA_EXECUTABLE}\") #message( \"wo_semicolumn: ${wo_semicolumn}\" ) execute_process( #COMMAND ${Java_JAVA_EXECUTABLE} -Djava.library.path=\"${GDCM_LIBRARY_DIR}\" -classpath \"${classpath}\" ${loc2} ${wo_semicolumn} COMMAND ${Java_JAVA_EXECUTABLE} -classpath \"${classpath}\" ${loc2} ${wo_semicolumn} WORKING_DIRECTORY \"${EXECUTABLE_OUTPUT_PATH}\" RESULT_VARIABLE import_res OUTPUT_VARIABLE import_output ERROR_VARIABLE import_output ) # Pass the output back to ctest if(import_output) message(STATUS \"\${import_output}\") endif() if(import_res) message(SEND_ERROR \"\${import_res}\") endif() " ) add_test(NAME ${TESTNAME} COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake) endmacro() GDCM-3.0.10/CMake/UseMONO.cmake000066400000000000000000000030061412732066400155200ustar00rootroot00000000000000# - MONO module for CMake # Defines the following macros: # MONO_ADD_MODULE(name language [ files ]) # - Define swig module with given name and specified language # MONO_LINK_LIBRARIES(name [ libraries ]) # - Link libraries to swig module # All other macros are for internal use only. # To get the actual name of the swig module, # use: ${MONO_MODULE_name_REAL_NAME}. # Set Source files properties such as CPLUSPLUS and MONO_FLAGS to specify # special behavior of MONO. Also global CMAKE_MONO_FLAGS can be used to add # special flags to all swig calls. # Another special variable is CMAKE_MONO_OUTDIR, it allows one to specify # where to write all the swig generated module (swig -outdir option) # The name-specific variable MONO_MODULE__EXTRA_DEPS may be used # to specify extra dependencies for the generated modules. # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # # Create Swig module # macro(MONO_ADD_MODULE name) set(swig_dot_i_sources) foreach(it ${ARGN}) set(swig_dot_i_sources ${swig_dot_i_sources} "${it}") endforeach() endmacro() # # Like TARGET_LINK_LIBRARIES but for swig modules # macro(MONO_LINK_LIBRARIES name) if(MONO_MODULE_${name}_REAL_NAME) target_link_libraries(${MONO_MODULE_${name}_REAL_NAME} ${ARGN}) else() message(SEND_ERROR "Cannot find Swig library \"${name}\".") endif() endmacro() GDCM-3.0.10/CMake/UsePythonTest.cmake000066400000000000000000000067221412732066400171010ustar00rootroot00000000000000# Add a python test from a python file # One cannot simply do: # set(ENV{PYTHONPATH} ${LIBRARY_OUTPUT_PATH}) # set(my_test "from test_mymodule import *\;test_mymodule()") # add_test(PYTHON-TEST-MYMODULE python -c ${my_test}) # Since cmake is only transmitting the ADD_TEST line to ctest thus you are losing # the env var. The only way to store the env var is to physically write in the cmake script # whatever PYTHONPATH you want and then add the test as 'cmake -P python_test.cmake' # # Usage: # set_source_files_properties(test.py PROPERTIES PYTHONPATH # "${LIBRARY_OUTPUT_PATH}:${VTK_DIR}") # ADD_PYTHON_TEST(PYTHON-TEST test.py) # # Copyright (c) 2006-2011 Mathieu Malaterre # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # Need python interpreter: find_package(PythonInterp ${GDCM_DEFAULT_PYTHON_VERSION} REQUIRED) mark_as_advanced(PYTHON_EXECUTABLE) macro(ADD_PYTHON_TEST TESTNAME FILENAME) set(_sep ":") if(WIN32) set(_sep "\\;") endif() get_source_file_property(loc ${FILENAME} LOCATION) get_source_file_property(pyenv ${FILENAME} PYTHONPATH) if(CMAKE_CONFIGURATION_TYPES) # I cannot use CMAKE_CFG_INTDIR since it expand to "$(OutDir)" if(pyenv) set(pyenv "${pyenv};${LIBRARY_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}") else() set(pyenv ${LIBRARY_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}) #set(pyenv ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}) #set(pyenv ${LIBRARY_OUTPUT_PATH}/${CMAKE_CONFIG_TYPE}) #set(pyenv ${LIBRARY_OUTPUT_PATH}/\${CMAKE_CONFIG_TYPE}) endif() else() if(pyenv) set(pyenv ${pyenv}${_sep}${LIBRARY_OUTPUT_PATH}) else() set(pyenv ${LIBRARY_OUTPUT_PATH}) endif() endif() string(REGEX REPLACE ";" " " wo_semicolumn "${ARGN}") file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake " set(ENV{PYTHONPATH} ${pyenv}${_sep}\$ENV{PYTHONPATH}) set(ENV{LD_LIBRARY_PATH} ${pyenv}${_sep}\$ENV{LD_LIBRARY_PATH}) message(\"pyenv is: ${pyenv}\") message(\"py_exec is: ${PYTHON_EXECUTABLE}\") message(\"py_found is: ${PYTHONINTERP_FOUND}\") execute_process( COMMAND ${PYTHON_EXECUTABLE} ${loc} ${wo_semicolumn} RESULT_VARIABLE import_res OUTPUT_VARIABLE import_output ERROR_VARIABLE import_output ) # Pass the output back to ctest if(import_output) message(\"import_output is: \${import_output}\") endif() if(import_res) message(\"Import res: \${import_res}\") message(\"py_exec is: \${PYTHON_EXECUTABLE}\") message(\"loc is: \${loc}\") message(\"wo is: \${wo_semicolumn}\") execute_process( COMMAND ${PYTHON_EXECUTABLE} ${loc} ${wo_semicolumn} RESULT_VARIABLE import2_res OUTPUT_VARIABLE import2_output ERROR_VARIABLE import2_output ) message(\"\${import2_output}\") message(SEND_ERROR \"\${import_res}\") endif() " ) add_test(NAME ${TESTNAME} COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/${TESTNAME}.cmake) endmacro() # Byte compile recursively a directory (DIRNAME) macro(ADD_PYTHON_COMPILEALL_TEST DIRNAME) # First get the path: get_filename_component(temp_path "${PYTHON_LIBRARIES}" PATH) # Find the python script: get_filename_component(PYTHON_COMPILE_ALL_PY "${temp_path}/../compileall.py" ABSOLUTE) # add test, use DIRNAME to create uniq name for the test: add_test(COMPILE_ALL-${DIRNAME} ${PYTHON_EXECUTABLE} "${PYTHON_COMPILE_ALL_PY}" -q ${DIRNAME}) endmacro() GDCM-3.0.10/CMake/dcmqrscp.cfg.in000066400000000000000000000007721412732066400162020ustar00rootroot00000000000000# http://support.dcmtk.org/docs/dcmqrscp.html # http://support.dcmtk.org/docs/file_dcmqrset.html NetworkType = "tcp" NetworkTCPPort = 5679 MaxPDUSize = 16384 MaxAssociations = 16 Display = "no" HostTable BEGIN gdcmdash = (GDCMDASH, @DCMQRSCP_HOSTNAME@, @DCMQRSCP_PORT@) gdcmcompany = gdcmdash HostTable END VendorTable BEGIN "GDCM Company" = gdcmcompany VendorTable END AETable BEGIN GDCM_STORE @DCMQRSCP_DIRECTORY@/GDCM_STORE RW (9, 1024mb) gdcmcompany AETable END GDCM-3.0.10/CMake/gdcmValgrind.supp000066400000000000000000000051611412732066400166070ustar00rootroot00000000000000{ Memcheck:Param write(buf) fun:__write_nocancel obj:/usr/X11R6/lib/libX11.so.6.2 fun:_X11TransWrite obj:/usr/X11R6/lib/libX11.so.6.2 } { Memcheck:Free fun:free fun:__GI__dl_deallocate_tls fun:vgArch_thread_exit fun:thread_exit_wrapper } { Memcheck:Leak fun:malloc fun:__cxa_get_globals fun:_ZSt18uncaught_exceptionv fun:_ZNSo6sentryD1Ev } { Memcheck:Leak fun:malloc fun:XextCreateExtension fun:__glXInitialize fun:glXGetConfig } { Memcheck:Leak fun:calloc fun:_dlerror_run fun:dlsym fun:__errno_location } { Memcheck:Leak fun:malloc fun:OpenDriver fun:__glXRegisterExtensions fun:__glXNewIndirectAPI } { Memcheck:Leak fun:malloc fun:_dl_map_object_internal fun:openaux fun:_dl_catch_error_internal } { Memcheck:Leak fun:malloc fun:_dl_map_object_deps_internal fun:dl_open_worker fun:_dl_catch_error_internal } { Memcheck:Leak fun:malloc fun:__glXstrdup fun:OpenDriver fun:__glXRegisterExtensions } { Memcheck:Leak fun:malloc fun:_dl_map_object_internal fun:dl_open_worker fun:_dl_catch_error_internal } { Memcheck:Leak fun:malloc fun:_dl_new_object fun:_dl_map_object_from_fd fun:_dl_map_object_internal } { Memcheck:Leak fun:malloc fun:dl_open_worker fun:_dl_catch_error_internal fun:__GI__dl_open } { Memcheck:Leak fun:calloc fun:_dl_check_map_versions_internal fun:dl_open_worker fun:_dl_catch_error_internal } { Memcheck:Leak fun:calloc fun:_dl_new_object fun:_dl_map_object_from_fd fun:_dl_map_object_internal } { Memcheck:Leak fun:malloc fun:__glXNewIndirectAPI fun:glXMakeCurrent fun:_ZN22vtkXOpenGLRenderWindow11MakeCurrentEv } { Memcheck:Leak fun:malloc fun:__fgl_glapi_add_entrypoint fun:__driRegisterExtensions fun:__glXRegisterExtensions } { Memcheck:Cond obj:/lib/ld-2.3.6.so obj:/lib/ld-2.3.6.so obj:/lib/ld-2.3.6.so obj:/lib/ld-2.3.6.so obj:/lib/ld-2.3.6.so obj:/lib/ld-2.3.6.so } GDCM-3.0.10/CMakeLists.txt000066400000000000000000001162771412732066400150700ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.9.2 FATAL_ERROR) set(GDCM_MAX_VALIDATED_CMAKE_VERSION "3.13.1") if("${CMAKE_VERSION}" VERSION_LESS_EQUAL "${GDCM_MAX_VALIDATED_CMAKE_VERSION}") # As of 2018-12-04 GDCM has been validated to build with cmake version 3.13.1 new policies. # Set and use the newest cmake policies that are validated to work set(GDCM_CMAKE_POLICY_VERSION "${CMAKE_VERSION}") else() set(GDCM_CMAKE_POLICY_VERSION "${GDCM_MAX_VALIDATED_CMAKE_VERSION}") endif() cmake_policy(VERSION ${GDCM_CMAKE_POLICY_VERSION}) # GDCM version 3.0.0 will only support C++11 and greater if(CMAKE_CXX_STANDARD EQUAL "98" ) message(FATAL_ERROR "CMAKE_CXX_STANDARD:STRING=98 is not supported in GDCM version 3.0.0 and greater.") endif() #---------------------------------------------------------------------------- project(GDCM VERSION 3.0.10 LANGUAGES CXX C ) ## NOTE: the "DESCRIPTION" feature of project() was introduced in cmake 3.10.0 set(PROJECT_DESCRIPTION "GDCM - Grassroots DICOM. GDCM is yet another DICOM library.") ## Set aliases for backwards compatibility. GDCM_VERSION_XXX are configured by the project() command 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} mark_as_advanced(CMAKE_BACKWARDS_COMPATIBILITY CMAKE_BUILD_TYPE CMAKE_INSTALL_PREFIX) set(GDCM_CMAKE_DIR "${GDCM_SOURCE_DIR}/CMake" CACHE INTERNAL "") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${GDCM_CMAKE_DIR}") set(GDCM_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_DESCRIPTION}) set(GDCM_PACKAGE_CONTACT "GDCM Developers ") # TODO # http://www.vtk.org/pipermail/vtkusers/2007-May/090968.html # # False memory leak reports are caused by VTK dlls loading *before* MFC dlls. # You have to use the linker's /delayload flag to avoid this issue. # # The /delayload flag should be correct by default in the MFC examples if you # are using CVS VTK... If you are using a previous version of VTK (5.0 or # earlier) then you will have to figure out a way to link with that flag. # # See the CVS version of files in VTK/GUISupport/MFC for details. Or grep the # VTK source tree for "DELAYLOAD" # let advanced user the option to define GDCM_API_VERSION: if(NOT DEFINED GDCM_API_VERSION) set(GDCM_API_VERSION "${GDCM_VERSION_MAJOR}.${GDCM_VERSION_MINOR}") endif() set(GDCM_LIBRARY_PROPERTIES ${GDCM_LIBRARY_PROPERTIES} VERSION "${GDCM_VERSION}" SOVERSION "${GDCM_API_VERSION}" ) set(GDCM_EXECUTABLE_PROPERTIES) if(GDCM_NO_EXECUTABLE_PROPERTIES) set(GDCM_EXECUTABLE_PROPERTIES) set(python_site_package "python/dist-packages") else() set(python_site_package "") endif() set(GDCM_STANDALONE 0) # Top level project (eg. ITK) should set GDCM_TARGETS_NAME # to define a particular behavior where GDCM does not call # install(EXPORT...) # This sets the default value for GDCM_STANDALONE if(NOT GDCM_TARGETS_NAME) set(GDCM_TARGETS_NAME GDCMTargets) set(GDCM_STANDALONE 1) endif() #----------------------------------------------------------------------------- # PDB handling + Module handling include(${GDCM_SOURCE_DIR}/CMake/InstallMacros.cmake) #----------------------------------------------------------------------------- include(${GDCM_SOURCE_DIR}/CMake/UseCopyright.cmake) CREATE_COPYRIGHT_FILE(${CMAKE_CURRENT_BINARY_DIR}/Copyright.txt) APPEND_COPYRIGHT(${CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt) APPEND_COPYRIGHT(${CMAKE_CURRENT_SOURCE_DIR}/CMake/COPYING-CMAKE-SCRIPTS) #----------------------------------------------------------------------------- if(GDCM_VERSION_MINOR MATCHES "[02468]$") # Are we building a release branch / tag (read: even number)? # By default dashboard are expected to run with Design by Contract on # to trigger any of the assert, but on the other hand no user really # can figure out they need to change this value # So unless the user *specifically* requested a particular cmake_build_type # do the work internally and append the NDEBUG def flag (hopefully portable) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNDEBUG") endif() # Since we are on a release branch, chance is that people don't care about testing # let's disable it for them set(GDCM_BUILD_TESTING_DEFAULT OFF) else() set(GDCM_BUILD_TESTING_DEFAULT ON) endif() #----------------------------------------------------------------------------- # Disable deprecation warnings for standard C and STL functions in VS2005 # and later if(MSVC_VERSION EQUAL 1400 OR MSVC_VERSION GREATER 1400) add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS) add_definitions(-D_SCL_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS) endif() #----------------------------------------------------------------------------- # Build shared lib by default if(GDCM_STANDALONE) option(GDCM_BUILD_SHARED_LIBS "Build GDCM with shared libraries." OFF) set(BUILD_SHARED_LIBS ${GDCM_BUILD_SHARED_LIBS}) else() set(GDCM_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) endif() if(BUILD_SHARED_LIBS) set(NAMELINK_ONLY NAMELINK_ONLY) set(NAMELINK_SKIP NAMELINK_SKIP) endif() #----------------------------------------------------------------------------- if(NOT EXECUTABLE_OUTPUT_PATH) set(EXECUTABLE_OUTPUT_PATH ${GDCM_BINARY_DIR}/bin CACHE PATH "Single output directory for building all executables.") mark_as_advanced(EXECUTABLE_OUTPUT_PATH) endif() if(NOT LIBRARY_OUTPUT_PATH) set(LIBRARY_OUTPUT_PATH ${GDCM_BINARY_DIR}/bin CACHE PATH "Single output directory for building all libraries.") mark_as_advanced(LIBRARY_OUTPUT_PATH) endif() #----------------------------------------------------------------------------- # Adding GDCM_DATA_ROOT if(GDCM_STANDALONE) find_path(GDCM_DATA_ROOT test.acr ${GDCM_SOURCE_DIR}/Testing/Data $ENV{GDCM_DATA_ROOT} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) mark_as_advanced(GDCM_DATA_ROOT) # You can define a path where you extra the famous D. Clunie spacing dataset # http://www.dclunie.com/images/pixelspacingtestimages.zip # for example: # find $HOME/pixelspacingtestimages # $HOME/pixelspacingtestimages # $HOME/pixelspacingtestimages/DISCIMG # $HOME/pixelspacingtestimages/DISCIMG/DICOMDIR # $HOME/pixelspacingtestimages/DISCIMG/IMAGES # $HOME/pixelspacingtestimages/DISCIMG/IMAGES/DXIMAGE # $HOME/pixelspacingtestimages/DISCIMG/IMAGES/MGIMAGE # $HOME/pixelspacingtestimages/DISCIMG/IMAGES/CRIMAGE mark_as_advanced(GDCM_PIXEL_SPACING_DATA_ROOT) #----------------------------------------------------------------------------- find_path(GDCM_DATA_EXTRA_ROOT gdcmData.tar.gz ${GDCM_SOURCE_DIR}/../gdcmDataExtra $ENV{GDCM_DATA_EXTRA_ROOT} $ENV{PUB_DICT_PATH}/../../gdcmDataExtra NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH ) mark_as_advanced(GDCM_DATA_EXTRA_ROOT) endif() # Define a temp directory in which we can output stuff set(GDCM_TEMP_DIRECTORY "${GDCM_BINARY_DIR}/Testing/Temporary" CACHE PATH "Path to a valid temp directory") mark_as_advanced(GDCM_TEMP_DIRECTORY) #----------------------------------------------------------------------------- include(${CMAKE_ROOT}/Modules/CheckIncludeFile.cmake) include(${CMAKE_ROOT}/Modules/CheckIncludeFiles.cmake) # Check if header file exists and add it to the list. macro(CHECK_INCLUDE_FILE_CONCAT FILE VARIABLE) CHECK_INCLUDE_FILES("${UUID_INCLUDES};${FILE}" ${VARIABLE}) if(${VARIABLE}) set(UUID_INCLUDES ${UUID_INCLUDES} ${FILE}) endif() endmacro() CHECK_INCLUDE_FILE("stdint.h" GDCM_HAVE_STDINT_H) if(UNIX) #Avoid polluting Win32 cmakecache CHECK_INCLUDE_FILE("inttypes.h" GDCM_HAVE_INTTYPES_H) endif() #include(${GDCM_SOURCE_DIR}/CMake/gdcmPlatformCxxTests.cmake) # #GDCM_PLATFORM_CXX_TEST(GDCM_CXX_HAS_FUNCTION # "Checking whether compiler has __FUNCTION__" DIRECT) #----------------------------------------------------------------------------- # Build the main lib... if(NOT GDCM_HAVE_STDINT_H) message(FATAL_ERROR "You system does not have stdint.h") endif() # -------------------------------------------------------------------------- # Configure the export configuration # You will also need to define a value for the following variables: # GDCM_INSTALL_BIN_DIR - binary dir (executables) # GDCM_INSTALL_LIB_DIR - library dir (libs) # GDCM_INSTALL_DATA_DIR - share dir (say, examples, data, etc) # GDCM_INSTALL_INCLUDE_DIR - include dir (headers) # GDCM_INSTALL_PACKAGE_DIR - package/export configuration files # GDCM_VTK_INSTALL_PACKAGE_DIR - VTK package/export configuration files # GDCM_INSTALL_NO_DEVELOPMENT - do not install development files # GDCM_INSTALL_NO_RUNTIME - do not install runtime files # GDCM_INSTALL_NO_DOCUMENTATION - do not install documentation files # GDCM_INSTALL_PYTHONMODULE_DIR - Python Module install dir # GDCM_VTK_INSTALL_PYTHONMODULE_DIR - VTK/Python Module install dir # GDCM_INSTALL_CSHARPMODULE_DIR - C# Module install dir # GDCM_VTK_INSTALL_CSHARPMODULE_DIR - VTK/C# Module install dir # GDCM_INSTALL_JAVAMODULE_DIR - Java Module install dir (JNI glue) # GDCM_INSTALL_JARMODULE_DIR - Java Module install dir (JAR) # GDCM_VTK_INSTALL_JAVAMODULE_DIR - VTK/Java Module install dir (JNI glue) # GDCM_VTK_INSTALL_JARMODULE_DIR - VTK/Java Module install dir (JAR) # -------------------------------------------------------------------------- # Install directories string(TOLOWER ${PROJECT_NAME} projectname) set(subdir "${projectname}-${GDCM_VERSION_MAJOR}.${GDCM_VERSION_MINOR}") if(NOT GDCM_INSTALL_BIN_DIR) set(GDCM_INSTALL_BIN_DIR "bin") endif() if(NOT GDCM_INSTALL_LIB_DIR) #set(GDCM_INSTALL_LIB_DIR "lib/${PROJECT_NAME}") set(GDCM_INSTALL_LIB_DIR "lib") endif() if(NOT GDCM_INSTALL_DATA_DIR) set(GDCM_INSTALL_DATA_DIR "share/${subdir}") endif() if(NOT GDCM_INSTALL_INCLUDE_DIR) set(GDCM_INSTALL_INCLUDE_DIR "include/${subdir}") endif() if(NOT GDCM_INSTALL_DOC_DIR) set(GDCM_INSTALL_DOC_DIR "share/doc/${subdir}") endif() if(NOT GDCM_INSTALL_MAN_DIR) set(GDCM_INSTALL_MAN_DIR "share/man") endif() if(NOT GDCM_INSTALL_PACKAGE_DIR) set(GDCM_INSTALL_PACKAGE_DIR ${GDCM_INSTALL_LIB_DIR}/${subdir} CACHE INTERNAL "") endif() if(NOT GDCM_VTK_INSTALL_PACKAGE_DIR) set(GDCM_VTK_INSTALL_PACKAGE_DIR ${VTK_INSTALL_PACKAGE_DIR}) endif() if(NOT GDCM_INSTALL_NO_DEVELOPMENT) set(GDCM_INSTALL_NO_DEVELOPMENT 0) endif() if(NOT GDCM_INSTALL_NO_RUNTIME) set(GDCM_INSTALL_NO_RUNTIME 0) endif() if(NOT GDCM_INSTALL_NO_DOCUMENTATION) set(GDCM_INSTALL_NO_DOCUMENTATION 0) endif() set(GDCM_INSTALL_NO_LIBRARIES) if(GDCM_BUILD_SHARED_LIBS) if(GDCM_INSTALL_NO_RUNTIME AND GDCM_INSTALL_NO_DEVELOPMENT) set(GDCM_INSTALL_NO_LIBRARIES 1) endif() else() if(GDCM_INSTALL_NO_DEVELOPMENT) set(GDCM_INSTALL_NO_LIBRARIES 1) endif() endif() if(NOT GDCM_INSTALL_PYTHONMODULE_DIR) set(GDCM_INSTALL_PYTHONMODULE_DIR ${GDCM_INSTALL_LIB_DIR}/${python_site_package}) endif() if(NOT GDCM_VTK_INSTALL_PYTHONMODULE_DIR) set(GDCM_VTK_INSTALL_PYTHONMODULE_DIR ${GDCM_INSTALL_PYTHONMODULE_DIR}) endif() if(NOT GDCM_INSTALL_CSHARPMODULE_DIR) set(GDCM_INSTALL_CSHARPMODULE_DIR ${GDCM_INSTALL_LIB_DIR}) endif() if(NOT GDCM_VTK_INSTALL_CSHARPMODULE_DIR) set(GDCM_VTK_INSTALL_CSHARPMODULE_DIR ${GDCM_INSTALL_CSHARPMODULE_DIR}) endif() if(NOT GDCM_INSTALL_JAVAMODULE_DIR) set(GDCM_INSTALL_JAVAMODULE_DIR ${GDCM_INSTALL_LIB_DIR}) endif() if(NOT GDCM_VTK_INSTALL_JAVAMODULE_DIR) set(GDCM_VTK_INSTALL_JAVAMODULE_DIR ${GDCM_INSTALL_JAVAMODULE_DIR}) endif() if(NOT GDCM_INSTALL_JARMODULE_DIR) set(GDCM_INSTALL_JARMODULE_DIR ${GDCM_INSTALL_LIB_DIR}) endif() if(NOT GDCM_VTK_INSTALL_JARMODULE_DIR) set(GDCM_VTK_INSTALL_JARMODULE_DIR ${GDCM_INSTALL_JARMODULE_DIR}) endif() #----------------------------------------------------------------------------- #System stuff, mainly for packager or paranoid people with up-to-date lib moto option(GDCM_USE_SYSTEM_ZLIB "Use system zlib" OFF) option(GDCM_USE_SYSTEM_OPENSSL "Use system OpenSSL" OFF) if(UNIX) # Will search for the uuid_generate symbols. # Can be in libSystem.dylib or libuuid.so option(GDCM_USE_SYSTEM_UUID "Use system uuid" OFF) endif() option(GDCM_USE_SYSTEM_EXPAT "Use system expat" OFF) option(GDCM_USE_SYSTEM_JSON "Use system json" OFF) option(GDCM_USE_SYSTEM_PAPYRUS3 "Use system papyrus3" OFF) option(GDCM_USE_SYSTEM_SOCKETXX "Use system socket++" OFF) option(GDCM_USE_SYSTEM_LJPEG "Use system ljpeg (ijg lib)" OFF) option(GDCM_USE_SYSTEM_OPENJPEG "Use system openjpeg" OFF) option(GDCM_USE_SYSTEM_CHARLS "Use system CharLS" OFF) mark_as_advanced( GDCM_USE_SYSTEM_ZLIB GDCM_USE_SYSTEM_OPENSSL GDCM_USE_SYSTEM_UUID GDCM_USE_SYSTEM_EXPAT GDCM_USE_SYSTEM_JSON GDCM_USE_SYSTEM_PAPYRUS3 GDCM_USE_SYSTEM_SOCKETXX GDCM_USE_SYSTEM_LJPEG GDCM_USE_SYSTEM_OPENJPEG GDCM_USE_SYSTEM_CHARLS ) option(GDCM_USE_SYSTEM_POPPLER "Use system poppler (pdf)" OFF) if(GDCM_USE_SYSTEM_POPPLER) find_package(Poppler REQUIRED) endif() mark_as_advanced(GDCM_USE_SYSTEM_POPPLER) option(GDCM_USE_SYSTEM_LIBXML2 "Use LibXml2" OFF) if(GDCM_USE_SYSTEM_LIBXML2) find_package(LibXml2) endif() mark_as_advanced(GDCM_USE_SYSTEM_LIBXML2) if(GDCM_USE_SYSTEM_LJPEG) find_package(LJPEG REQUIRED) set(GDCM_LJPEG_LIBRARIES ${LJPEG_LIBRARIES}) else() set(GDCM_LJPEG_LIBRARIES gdcmjpeg8 gdcmjpeg12 gdcmjpeg16) endif() if(GDCM_USE_SYSTEM_CHARLS) find_package(CharLS 2.0.0 REQUIRED) set(GDCM_CHARLS_LIBRARIES ${CHARLS_LIBRARIES}) else() set(GDCM_CHARLS_LIBRARIES gdcmcharls) endif() if(GDCM_USE_SYSTEM_OPENJPEG) find_package(OpenJPEG 2.0.0 REQUIRED) set(GDCM_OPENJPEG_LIBRARIES ${OPENJPEG_LIBRARIES}) else() set(GDCM_OPENJPEG_LIBRARIES gdcmopenjp2) endif() # Very advanced user option: # This will cause building of the broken JPEG library released by the Standford PVRG group: option(GDCM_USE_PVRG "Use pvrg lib, only turn it on if you know what you are doing." OFF) mark_as_advanced(GDCM_USE_PVRG) option(GDCM_USE_KAKADU "Use kakadu lib, only turn it on if you know what you are doing." OFF) mark_as_advanced(GDCM_USE_KAKADU) if(GDCM_USE_PVRG) option(GDCM_USE_SYSTEM_PVRG "Use system PVRG" OFF) mark_as_advanced(GDCM_USE_SYSTEM_PVRG) if(GDCM_USE_SYSTEM_PVRG) find_package(PVRGJPEG REQUIRED) endif() endif() # Very advanced behavior only use if you want to keep backward compatible # behavior but possibly incorrect behavior. option(GDCMV2_0_COMPATIBILITY "Preserve compatibility with GDCM 2.0 release" ON) mark_as_advanced(GDCMV2_0_COMPATIBILITY) if(GDCM_USE_KAKADU) option(GDCM_USE_SYSTEM_KAKADU "Use system KAKADU " ON) mark_as_advanced(GDCM_USE_SYSTEM_KAKADU) if(GDCM_USE_SYSTEM_KAKADU) find_package(KAKADU REQUIRED) else() message(FATAL_ERROR "Not Implemented") endif() endif() if(GDCM_USE_SYSTEM_ZLIB) # If user say so, then this is a requirement ! find_package(ZLIB REQUIRED) include_directories(${ZLIB_INCLUDE_DIR}) set(GDCM_ZLIB_LIBRARIES ${ZLIB_LIBRARIES}) else() set(GDCM_ZLIB_LIBRARIES "gdcmzlib") endif() if(GDCM_USE_SYSTEM_OPENSSL) find_package(OpenSSL REQUIRED) endif() if(GDCM_USE_SYSTEM_UUID) # If user say so, then this is a requirement ! find_package(UUID REQUIRED) set(GDCM_UUID_LIBRARIES ${UUID_LIBRARIES}) else() set(GDCM_UUID_LIBRARIES "gdcmuuid") endif() if(GDCM_USE_SYSTEM_EXPAT) # If user say so, then this is a requirement ! find_package(EXPAT REQUIRED) set(GDCM_EXPAT_LIBRARIES ${EXPAT_LIBRARIES}) else() set(GDCM_EXPAT_LIBRARIES "gdcmexpat") endif() if(GDCM_USE_SYSTEM_JSON) find_package(JSON REQUIRED) endif() if(GDCM_USE_SYSTEM_PAPYRUS3) find_package(PAPYRUS3 REQUIRED) endif() #----------------------------------------------------------------------------- if(GDCM_STANDALONE) option(GDCM_BUILD_EXAMPLES "Build GDCM examples." OFF) set(BUILD_EXAMPLES ${GDCM_BUILD_EXAMPLES}) else() set(GDCM_BUILD_EXAMPLES OFF) set(BUILD_EXAMPLES OFF) endif() #----------------------------------------------------------------------------- # Add the testing directories if(GDCM_STANDALONE) option(GDCM_BUILD_TESTING "Build testing." ${GDCM_BUILD_TESTING_DEFAULT}) set(BUILD_TESTING ${GDCM_BUILD_TESTING}) # CACHE BOOL "" FORCE) else() set(GDCM_BUILD_TESTING OFF) set(BUILD_TESTING OFF) endif() # Hide BUILD_TESTING as user tend to always turn all options on and then complains when something # does not work 'by default' mark_as_advanced(BUILD_TESTING) # GDCM_BUILD_TESTING) #----------------------------------------------------------------------------- if(GDCM_TESTING_USE_LC_NUMERIC) set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN "setlocale(LC_ALL,\"fr_FR.UTF-8\");std::locale::global(std::locale(\"fr_FR.UTF-8\"));" ) endif() #----------------------------------------------------------------------------- # Python install #find_package(PythonInterp REQUIRED) #macro(GET_PYTHON_SITE_PACKAGE dir) # execute_process( # COMMAND ${PYTHON_EXECUTABLE} "-c" "from distutils import sysconfig; print sysconfig.get_python_lib()" # #WORKING_DIRECTORY @LIBRARY_OUTPUT_PATH@ # RESULT_VARIABLE import_res # OUTPUT_VARIABLE import_output # ERROR_VARIABLE import_error # OUTPUT_STRIP_TRAILING_WHITESPACE # ) # #set(dir ${import_output}) #endmacro() # # #GET_PYTHON_SITE_PACKAGE(python_site_package) #if(import_output) #string(LENGTH ${import_output} len) ## let's remove the "/usr/lib" part... #math(EXPR fileend "${len} - 9") #string(SUBSTRING ${import_output} 9 ${fileend} dummy1) #if(UNIX) # set(python_site_package ${dummy1}) # message(${python_site_package}) #endif() #endif() # On unix one have: "python2.4/site-packages" # while on Win32: "c:/Python24/Lib/site-packages/" # give up for now and place python modules stuff in a general 'python' subdir # Typical runtime env should be then # (assuming CMAKE_INSTALL_PREFIX:PATH=/tmp/local) # One would do: # export PYTHONPATH=/tmp/local/lib/python/site-packages/gdcm-2.1 # export LD_LIBRARY_PATH=/tmp/local/lib/ # python # > import gdcm #----------------------------------------------------------------------------- # Wrapping if(GDCM_STANDALONE) option(GDCM_WRAP_PYTHON "build 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) mark_as_advanced(GDCM_WRAP_PHP) mark_as_advanced(GDCM_WRAP_PERL) mark_as_advanced(GDCM_USE_ACTIVIZ) option(GDCM_USE_JPEGLS "Build GDCM with JPEG-LS support" ON) mark_as_advanced(GDCM_USE_JPEGLS) if(NOT DEFINED GDCM_DEFAULT_PYTHON_VERSION) # override with cmake -DGDCM_DEFAULT_PYTHON_VERSION:STRING=2.7 if you dare set(GDCM_DEFAULT_PYTHON_VERSION 3.2) endif() if(NOT DEFINED GDCM_DEFAULT_JAVA_VERSION) # override with cmake -DGDCM_DEFAULT_JAVA_VERSION:STRING=1.5 if you dare set(GDCM_DEFAULT_JAVA_VERSION 1.7) endif() if(GDCM_WRAP_JAVA) set(GDCM_JAVA_SOURCE_VERSION "${GDCM_DEFAULT_JAVA_VERSION}" CACHE STRING "javac source version") set(GDCM_JAVA_TARGET_VERSION "${GDCM_DEFAULT_JAVA_VERSION}" CACHE STRING "javac target version") mark_as_advanced(GDCM_JAVA_SOURCE_VERSION GDCM_JAVA_TARGET_VERSION) endif() if(GDCM_WRAP_CSHARP) find_package(CSharp REQUIRED) include(${CSharp_USE_FILE}) endif() # Expose a way to pass -fPIC to static libs of gdcm core, while still build wrapped language as shared lib: if(NOT DEFINED GDCM_USE_PIC_FOR_STATIC_LIBS) if(GDCM_WRAP_JAVA) if(NOT BUILD_SHARED_LIBS) if(CMAKE_COMPILER_IS_GNUCXX) set(GDCM_USE_PIC_FOR_STATIC_LIBS ON) endif() endif() endif() endif() if(GDCM_USE_PIC_FOR_STATIC_LIBS) if(BUILD_SHARED_LIBS) message(FATAL_ERROR "Invalid configuration for static/shared lib") else() set(CMAKE_POSITION_INDEPENDENT_CODE ON) endif() endif() endif() set(GDCM_LIBRARY_DIR ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}) set(GDCM_EXECUTABLE_DIR ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}) #----------------------------------------------------------------------------- # we need to link against CoreFoundation so that we can use CFBundle to get the executable path. if(APPLE) option(GDCM_USE_COREFOUNDATION_LIBRARY "Use COREFOUNDATION_LIBRARY?" ON) if(GDCM_USE_COREFOUNDATION_LIBRARY) find_library(COREFOUNDATION_LIBRARY CoreFoundation ) endif() endif() #----------------------------------------------------------------------------- # Allow user to set a postfix symbol to a target library name (eg. 'd') if(WIN32) set(GDCM_DEBUG_POSTFIX "" CACHE STRING "Globally append a debug postfix symbols on all libraries") if(GDCM_DEBUG_POSTFIX) set(CMAKE_DEBUG_POSTFIX "${GDCM_DEBUG_POSTFIX}") endif() mark_as_advanced(GDCM_DEBUG_POSTFIX) endif() #----------------------------------------------------------------------------- # Add a target so that the documentation can be build from the # root dir if(GDCM_DOCUMENTATION) if(NOT DEFINED GDCM_SKIP_DOXYGENDOC_ALL_RULE) add_custom_target(DoxygenDoc ALL) else() add_custom_target(DoxygenDoc) endif() endif() # Need to add_subdirectory in Source/Common before Wrapping # to have gdcmConfigure.h around if(GDCM_STANDALONE) set(BUILD_APPLICATIONS ${GDCM_BUILD_APPLICATIONS}) else() set(BUILD_APPLICATIONS OFF) endif() #----------------------------------------------------------------------------- # Need pthread for the following class: CHECK_INCLUDE_FILE("pthread.h" GDCM_HAVE_PTHREAD_H) # Big endian thing: if(GDCM_STANDALONE) include(TestBigEndian) TEST_BIG_ENDIAN(GDCM_WORDS_BIGENDIAN) endif() if(GDCM_STANDALONE) if(GDCM_BUILD_TESTING) configure_file(${GDCM_SOURCE_DIR}/CMake/CTestCustom.ctest.in ${GDCM_BINARY_DIR}/CMake/CTestCustom.ctest @ONLY) file(WRITE ${GDCM_BINARY_DIR}/CTestCustom.cmake "include(\"${GDCM_BINARY_DIR}/CMake/CTestCustom.ctest\")\n") mark_as_advanced(DART_TESTING_TIMEOUT) enable_testing() include(CTest) add_subdirectory(Testing) if(NOT GDCM_DATA_ROOT) message("If you want to build the test suite, you must set GDCM_DATA_ROOT (advanced option) " "to the full path name of the gdcmData directory; if you don't want, disable GDCM_BUILD_TESTING.\n" "What is gdcmData? Please read: http://gdcm.sourceforge.net/wiki/index.php/General_questions#What_is_gdcmData_.3F") endif() endif() endif() # After enable_testing() add_subdirectory(Utilities) add_subdirectory(Source) if(GDCM_STANDALONE) add_subdirectory(Wrapping) endif() if(GDCM_STANDALONE) # After Wrapping please if(BUILD_EXAMPLES) add_subdirectory(Examples) endif() endif() #----------------------------------------------------------------------------- if(GDCM_STANDALONE) option(GDCM_DOCUMENTATION "Build source documentation using doxygen." OFF) if(GDCM_DOCUMENTATION) option(GDCM_PDF_DOCUMENTATION "Build source doxygen using doxygen as pdf" ON) mark_as_advanced(GDCM_PDF_DOCUMENTATION) endif() endif() #----------------------------------------------------------------------------- if(GDCM_STANDALONE) option(GDCM_USE_VTK "vtk bridge ?" OFF) if(GDCM_USE_VTK AND GDCM_WRAP_CSHARP) option(GDCM_USE_ACTIVIZ "vtk/Activiz bridge ?" OFF) endif() if(GDCM_USE_VTK) option(GDCM_USE_PARAVIEW "paraview plugin ?" OFF) # needed here so that we have VTK_WRAP_PYTHON and al. available find_package(VTK REQUIRED) mark_as_advanced(VTK_DIR) set(GDCM_VTK_DIR ${VTK_DIR}) mark_as_advanced(GDCM_USE_PARAVIEW) add_subdirectory(Utilities/VTK) endif() endif() #----------------------------------------------------------------------------- if(GDCM_STANDALONE) option(GDCM_BUILD_APPLICATIONS "apps ?" OFF) set(BUILD_APPLICATIONS ${GDCM_BUILD_APPLICATIONS}) if(BUILD_APPLICATIONS) add_subdirectory(Applications) endif() else() set(BUILD_APPLICATIONS OFF) set(GDCM_BUILD_APPLICATIONS OFF) endif() #----------------------------------------------------------------------------- if(GDCM_USE_VTK) if(WIN32) include(CMake/InstallRequiredVTKLibraries.cmake) endif() endif() # Make sure to run doxygen after everything else (in particular vtkgdcm): if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/doxygen) add_subdirectory(Utilities/doxygen) endif() #----------------------------------------------------------------------------- # CPack stuff if(GDCM_STANDALONE) # disabled for ITK distribution of gdcm if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") if(EXISTS "${CMAKE_ROOT}/Modules/InstallRequiredSystemLibraries.cmake") set(CMAKE_INSTALL_MFC_LIBRARIES 0) set(CMAKE_INSTALL_DEBUG_LIBRARIES 0) if(NOT DEFINED CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON) endif() include(${CMAKE_ROOT}/Modules/InstallRequiredSystemLibraries.cmake) endif() set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${GDCM_PACKAGE_DESCRIPTION_SUMMARY}) set(CPACK_PACKAGE_VENDOR "GDCM") set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_BINARY_DIR}/Copyright.txt") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_BINARY_DIR}/Copyright.txt") set(CPACK_PACKAGE_VERSION_MAJOR "${GDCM_VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MINOR "${GDCM_VERSION_MINOR}") set(CPACK_PACKAGE_VERSION_PATCH "${GDCM_VERSION_PATCH}") set(CPACK_PACKAGE_INSTALL_DIRECTORY "GDCM ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}") set(CPACK_SOURCE_PACKAGE_FILE_NAME "gdcm-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") if(WIN32 AND NOT UNIX) # There is a bug in NSIS that does not handle full UNIX paths properly. Make # sure there is at least one set of four (4) backlashes. set(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\gdcmviewer.exe") set(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY}") set(CPACK_NSIS_HELP_LINK "http://gdcm.sourceforge.net") set(CPACK_NSIS_URL_INFO_ABOUT "http://gdcm.sourceforge.net") set(CPACK_NSIS_MODIFY_PATH ON) # if(${CMAKE_INSTALL_PREFIX} MATCHES ${CPACK_PACKAGE_INSTALL_DIRECTORY}) # else() # string(REPLACE ${PROJECT_NAME} ${CPACK_PACKAGE_INSTALL_DIRECTORY} dummy ${CMAKE_INSTALL_PREFIX} ) # set(CMAKE_INSTALL_PREFIX ${dummy} CACHE PATH "" FORCE) # endif() else() set(CPACK_STRIP_FILES TRUE) set(CPACK_SOURCE_STRIP_FILES "") set(CPACK_PACKAGE_EXECUTABLES "gdcmviewer" "VIEWER") endif() # cygwin stff also copied from cmake #if(NOT DEFINED CPACK_PACKAGE_FILE_NAME) # # if the CPACK_PACKAGE_FILE_NAME is not defined by the cache # # default to source package - system, on cygwin system is not # # needed # if(CYGWIN) # set(CPACK_PACKAGE_FILE_NAME "${CPACK_SOURCE_PACKAGE_FILE_NAME}") # else() # set(CPACK_PACKAGE_FILE_NAME # "${CPACK_SOURCE_PACKAGE_FILE_NAME}-${CPACK_SYSTEM_NAME}") # endif() #endif() #Cygwin stuff copied from cmake if(NOT DEFINED CPACK_SYSTEM_NAME) # make sure package is not Cygwin-unknown, for Cygwin just # cygwin is good for the system name if("${CMAKE_SYSTEM_NAME}" STREQUAL "CYGWIN") set(CPACK_SYSTEM_NAME Cygwin) else() #set(CMAKE_SYSTEM_PROCESSOR "x86_64") #set(CPACK_GENERATOR "TGZ;TBZ2") #set(CPACK_SOURCE_GENERATOR "TGZ;TBZ2") set(CPACK_SYSTEM_NAME ${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}) endif() endif() # Need to set the architecture for debian package set(CPACK_PACKAGE_CONTACT ${GDCM_PACKAGE_CONTACT}) set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6, libstdc++6 (>= 4.0.2-4), libuuid1, zlib1g (>= 1:1.2.1), libgcc1 (>= 1:4.0.2), libexpat1, swig") # bug: missing dep to python... set(CPACK_DEBIAN_PACKAGE_SUGGESTS "dcmtk") set(CPACK_SOURCE_IGNORE_FILES "/\\\\.gitmodules" "/\\\\.git/" "/\\\\.gitignore" "TODO" "/Testing/Data/") set(CPACK_IGNORE_FILES ${CPACK_SOURCE_IGNORE_FILES}) # List executables #set(CPACK_PACKAGE_EXECUTABLES "gdcmviewer" "VIEWER") if(CYGWIN) set(CPACK_CYGWIN_PATCH_NUMBER 1) set(CPACK_CYGWIN_BUILD_SCRIPT "${GDCM_BINARY_DIR}/@CPACK_PACKAGE_FILE_NAME@-@CPACK_CYGWIN_PATCH_NUMBER@.sh") set(CPACK_CYGWIN_PATCH_FILE "${GDCM_BINARY_DIR}/@CPACK_PACKAGE_FILE_NAME@-@CPACK_CYGWIN_PATCH_NUMBER@.patch") configure_file(${GDCM_SOURCE_DIR}/CMake/Release/cygwin-patch.diff.in ${CPACK_CYGWIN_PATCH_FILE}) configure_file(${GDCM_SOURCE_DIR}/CMake/Release/cygwin-package.sh.in ${CPACK_CYGWIN_BUILD_SCRIPT}) endif() # Tell CPack all of the components to install. The "ALL" # refers to the fact that this is the set of components that # will be included when CPack is instructed to put everything # into the binary installer (the default behavior). set(components) if(GDCM_BUILD_APPLICATIONS) list(APPEND components Applications) endif() list(APPEND components Libraries) list(APPEND components Headers) list(APPEND components DebugDevel) if(GDCM_WRAP_PYTHON) list(APPEND components PythonModule) endif() if(GDCM_WRAP_CSHARP) list(APPEND components CSharpModule) # https://cmake.org/cmake/help/latest/cpack_gen/nuget.html#cpack_gen:CPack%20NuGet%20Generator if (${CMAKE_VERSION} VERSION_GREATER "3.12.0") set(CPACK_BINARY_NUGET "ON") # ${CMAKE_CURRENT_BINARY_DIR}/Copyright.txt is too long (>4000 characters) set(CPACK_NUGET_PACKAGE_DESCRIPTION "Grassroots DiCoM is a C++ library for DICOM medical files. It is accessible from Python, C#, Java and PHP. It supports RAW, JPEG, JPEG 2000, JPEG-LS, RLE and deflated transfer syntax. It comes with a super fast scanner implementation to quickly scan hundreds of DICOM files. It supports SCU network operations (C-ECHO, C-FIND, C-STORE, C-MOVE). PS 3.3 & 3.6 are distributed as XML files. It also provides PS 3.15 certificates and password based mechanism to anonymize and de-identify DICOM datasets.") set(CPACK_NUGET_PACKAGE_LICENSEURL "http://gdcm.sourceforge.net/Copyright.html") set(CPACK_NUGET_PACKAGE_HOMEPAGE_URL "http://gdcm.sourceforge.net") set(CPACK_NUGET_PACKAGE_TAGS "dicom" "medical") set(CPACK_NUGET_PACKAGE_ICONURL "http://gdcm.sourceforge.net/images/logo_gdcm64x64.png") endif() endif() if(GDCM_WRAP_JAVA) list(APPEND components JavaModule) endif() if(GDCM_WRAP_PHP) list(APPEND components PHPModule) endif() if(GDCM_USE_VTK) foreach(comp ${components}) if( "${comp}" STREQUAL "PythonModule" ) if(VTK_WRAP_PYTHON) list(APPEND components VTK${comp}) endif() elseif( "${comp}" STREQUAL "JavaModule" ) if(VTK_WRAP_JAVA) list(APPEND components VTK${comp}) endif() else() list(APPEND components VTK${comp}) endif() endforeach() endif() if(GDCM_USE_PARAVIEW) list(APPEND components ParaViewModule) endif() # Ok this is the complete list of all components: set(CPACK_COMPONENTS_ALL ${components}) # Set the displayed names for each of the components to install. # These will be displayed in the list of components inside the installer. set(CPACK_COMPONENT_APPLICATIONS_DISPLAY_NAME "GDCM Applications") set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "GDCM Libraries") set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "GDCM C/C++ Headers") set(CPACK_COMPONENT_DEBUGDEVEL_DISPLAY_NAME "GDCM Debug Symbols (PDB)") set(CPACK_COMPONENT_PYTHONMODULE_DISPLAY_NAME "GDCM Python Module") set(CPACK_COMPONENT_CSHARPMODULE_DISPLAY_NAME "GDCM C# Module") set(CPACK_COMPONENT_JAVAMODULE_DISPLAY_NAME "GDCM Java Module") set(CPACK_COMPONENT_PHPMODULE_DISPLAY_NAME "GDCM PHP Module") set(CPACK_COMPONENT_VTKAPPLICATIONS_DISPLAY_NAME "VTK/GDCM Applications") set(CPACK_COMPONENT_VTKLIBRARIES_DISPLAY_NAME "VTK/GDCM Libraries") set(CPACK_COMPONENT_VTKHEADERS_DISPLAY_NAME "VTK/GDCM C/C++ Headers") set(CPACK_COMPONENT_VTKPYTHONMODULE_DISPLAY_NAME "VTK/GDCM Python Module") set(CPACK_COMPONENT_VTKCSHARPMODULE_DISPLAY_NAME "VTK/GDCM C# Module") set(CPACK_COMPONENT_VTKJAVAMODULE_DISPLAY_NAME "VTK/GDCM Java Module") set(CPACK_COMPONENT_VTKPHPMODULE_DISPLAY_NAME "VTK/GDCM PHP Module") set(CPACK_COMPONENT_PARAVIEWMODULE_DISPLAY_NAME "ParaView Module") # Provide descriptions for each of the components to install. # When the user hovers the mouse over the name of a component, # the description will be shown in the "Description" box in the # installer. If no descriptions are provided, the "Description" # box will be removed. set(CPACK_COMPONENT_APPLICATIONS_DESCRIPTION "Command line applications that uses GDCM: gdcmconv, gdcmscu, gdcmdump, gdcminfo, gdcmscanner, gdcmimg, gdcmanon") set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION "Libraries used to build programs with GDCM") set(CPACK_COMPONENT_HEADERS_DESCRIPTION "C/C++ header files for use with GDCM") set(CPACK_COMPONENT_DEBUGDEVEL_DESCRIPTION "Program Database files for use with GDCM") set(CPACK_COMPONENT_PYTHONMODULE_DESCRIPTION "Python Module for GDCM") set(CPACK_COMPONENT_CSHARPMODULE_DESCRIPTION "C# Module for GDCM") set(CPACK_COMPONENT_JAVAMODULE_DESCRIPTION "Java Module for GDCM") set(CPACK_COMPONENT_PHPMODULE_DESCRIPTION "PHP Module for GDCM") set(CPACK_COMPONENT_VTKAPPLICATIONS_DESCRIPTION "Command line applications that uses GDCM: gdcmviewer & gdcm2vtk") set(CPACK_COMPONENT_VTKLIBRARIES_DESCRIPTION "Libraries used to build programs with VTK/GDCM") set(CPACK_COMPONENT_VTKHEADERS_DESCRIPTION "C/C++ header files for use with VTK/GDCM") set(CPACK_COMPONENT_VTKPYTHONMODULE_DESCRIPTION "Python Module for VTK/GDCM") set(CPACK_COMPONENT_VTKCSHARPMODULE_DESCRIPTION "C# Module for VTK/GDCM") set(CPACK_COMPONENT_VTKJAVAMODULE_DESCRIPTION "Java Module for VTK/GDCM") set(CPACK_COMPONENT_VTKPHPMODULE_DESCRIPTION "PHP Module for VTK/GDCM") set(CPACK_COMPONENT_PARAVIEWMODULE_DESCRIPTION "ParaView Module for VTK/GDCM") # Put the components into two different groups: "Runtime" and "Development" set(CPACK_COMPONENT_APPLICATIONS_GROUP "Runtime") set(CPACK_COMPONENT_LIBRARIES_GROUP "Development") set(CPACK_COMPONENT_HEADERS_GROUP "Development") set(CPACK_COMPONENT_DEBUGDEVEL_GROUP "Development") set(CPACK_COMPONENT_PYTHONMODULE_GROUP "Runtime") set(CPACK_COMPONENT_CSHARPMODULE_GROUP "Runtime") set(CPACK_COMPONENT_JAVAMODULE_GROUP "Runtime") set(CPACK_COMPONENT_PHPMODULE_GROUP "Runtime") set(CPACK_COMPONENT_VTKAPPLICATIONS_GROUP "Runtime") set(CPACK_COMPONENT_VTKPYTHONMODULE_GROUP "Runtime") set(CPACK_COMPONENT_VTKCSHARPMODULE_GROUP "Runtime") set(CPACK_COMPONENT_VTKJAVAMODULE_GROUP "Runtime") set(CPACK_COMPONENT_VTKPHPMODULE_GROUP "Runtime") set(CPACK_COMPONENT_VTKLIBRARIES_GROUP "Development") set(CPACK_COMPONENT_VTKHEADERS_GROUP "Development") set(CPACK_COMPONENT_PARAVIEWMODULE_GROUP "Runtime") # Expand the "Development" group by default, since we have so few components. # Also, provide this group with a description. if(CMAKE_VERSION VERSION_EQUAL 2.8.3) # The following is needed for CMake 2.8.3 and above to preserve backward compat set(CPACK_MONOLITHIC_INSTALL 1) endif() set(CPACK_COMPONENT_GROUP_DEVELOPMENT_EXPANDED ON) set(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION "All of the tools you'll ever need to develop software using GDCM") # It doesn't make sense to install the headers without the libraries # (because you could never use the headers!), so make the headers component # depend on the libraries component. set(CPACK_COMPONENT_HEADERS_DEPENDS Libraries) set(CPACK_COMPONENT_DEBUGDEVEL_DEPENDS Libraries) set(CPACK_COMPONENT_APPLICATIONS_DEPENDS Libraries) set(CPACK_COMPONENT_PYTHONMODULE_DEPENDS Libraries) set(CPACK_COMPONENT_CSHARPMODULE_DEPENDS Libraries) set(CPACK_COMPONENT_JAVAMODULE_DEPENDS Libraries) set(CPACK_COMPONENT_PHPMODULE_DEPENDS Libraries) set(CPACK_COMPONENT_VTKHEADERS_DEPENDS VTKLibraries) set(CPACK_COMPONENT_VTKLIBRARIES_DEPENDS Libraries) set(CPACK_COMPONENT_VTKAPPLICATIONS_DEPENDS VTKLibraries) set(CPACK_COMPONENT_VTKPYTHONMODULE_DEPENDS VTKLibraries) set(CPACK_COMPONENT_VTKCSHARPMODULE_DEPENDS VTKLibraries) set(CPACK_COMPONENT_VTKJAVAMODULE_DEPENDS VTKLibraries) set(CPACK_COMPONENT_VTKPHPMODULE_DEPENDS VTKLibraries) set(CPACK_COMPONENT_PARAVIEWMODULE_DEPENDS VTKLibraries) # Create two installation types with pre-selected components. # The "Developer" installation has just the library and headers, # while the "Full" installation has everything. set(CPACK_ALL_INSTALL_TYPES Full Developer) set(CPACK_INSTALL_TYPE_FULL_DISPLAY_NAME "Everything") set(CPACK_COMPONENT_APPLICATIONS_INSTALL_TYPES Full) set(CPACK_COMPONENT_LIBRARIES_INSTALL_TYPES Developer Full) set(CPACK_COMPONENT_HEADERS_INSTALL_TYPES Developer Full) set(CPACK_COMPONENT_DEBUGDEVEL_INSTALL_TYPES Developer Full) set(CPACK_COMPONENT_PYTHONMODULE_INSTALL_TYPES Developer Full) set(CPACK_COMPONENT_CSHARPMODULE_INSTALL_TYPES Developer Full) set(CPACK_COMPONENT_JAVAMODULE_INSTALL_TYPES Developer Full) set(CPACK_COMPONENT_PHPMODULE_INSTALL_TYPES Developer Full) set(CPACK_COMPONENT_VTKLIBRARIES_INSTALL_TYPES Developer Full) set(CPACK_COMPONENT_VTKHEADERS_INSTALL_TYPES Developer Full) set(CPACK_COMPONENT_VTKAPPLICATIONS_INSTALL_TYPES Full) set(CPACK_COMPONENT_VTKPYTHONMODULE_INSTALL_TYPES Developer Full) set(CPACK_COMPONENT_VTKCSHARPMODULE_INSTALL_TYPES Developer Full) set(CPACK_COMPONENT_VTKJAVAMODULE_INSTALL_TYPES Developer Full) set(CPACK_COMPONENT_VTKPHPMODULE_INSTALL_TYPES Developer Full) set(CPACK_COMPONENT_PARAVIEWMODULE_INSTALL_TYPES Developer Full) include(CPack) endif() endif() macro(PROCESSONEDIR DIRNAME myoutput) file(GLOB files ${DIRNAME}/* ) foreach(file ${files}) if(IS_DIRECTORY ${file}) if("${file}" MATCHES ".git") #message("${file} is git dir") else() #message("${file} is dir") PROCESSONEDIR(${file} mytests2) list(APPEND ${myoutput} ${mytests2}) endif() else() #message("${file} is file") get_filename_component(filename ${file} NAME) if("${filename}" MATCHES "Test" AND ${filename} MATCHES ".cxx") string(LENGTH ${filename} filename_length) #message("${filename} is test, ${filename_length}") math(EXPR fileend "${filename_length} - 4 - 4") # Need to remove 'Test' and '.cxx' string(SUBSTRING ${filename} 4 ${fileend} classname) #message("${classname} is tested") list(APPEND ${myoutput} ${classname}) endif() endif() endforeach() endmacro() #PROCESSONEDIR( # ${CMAKE_CURRENT_SOURCE_DIR}/Testing/Source/Common # theoutput #) #message("${theoutput}") # For DICOM Q/R testing if(GDCM_BUILD_TESTING) set(GDCM_DICOM_CLIENT_AETITLE "" CACHE STRING "DICOM CLIENT AETITLE") set(GDCM_DICOM_SERVER_AETITLE "" CACHE STRING "DICOM SERVER AETITLE") set(GDCM_DICOM_SERVER_PEER "" CACHE STRING "DICOM SERVER PEER") set(GDCM_DICOM_SERVER_PORT "" CACHE STRING "DICOM SERVER PORT") set(GDCM_DICOM_CLIENT_PORT "" CACHE STRING "DICOM CLIENT PORT") mark_as_advanced( GDCM_DICOM_CLIENT_AETITLE GDCM_DICOM_SERVER_AETITLE GDCM_DICOM_SERVER_PEER GDCM_DICOM_SERVER_PORT GDCM_DICOM_CLIENT_PORT ) endif() #----------------------------------------------------------------------------- # Need to be the last operation: set(GDCM_INCLUDE_PATH "${GDCM_SOURCE_DIR}/Source/Common" "${GDCM_BINARY_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition" "${GDCM_SOURCE_DIR}/Source/MediaStorageAndFileFormat" "${GDCM_SOURCE_DIR}/Source/MessageExchangeDefinition" "${GDCM_SOURCE_DIR}/Source/DataDictionary" "${GDCM_SOURCE_DIR}/Source/InformationObjectDefinition" ) if(GDCM_USE_VTK) set(GDCM_INCLUDE_PATH ${GDCM_INCLUDE_PATH} "${GDCM_SOURCE_DIR}/Utilities/VTK" ) endif() set(GDCM_LIBRARY_DIRS ${LIBRARY_OUTPUT_PATH}) if(GDCM_STANDALONE) add_subdirectory(CMake/ExportConfiguration) endif() GDCM-3.0.10/CTestConfig.cmake000066400000000000000000000003451412732066400154660ustar00rootroot00000000000000set(CTEST_PROJECT_NAME "GDCM") set(CTEST_NIGHTLY_START_TIME "21:00:00 EDT") set(CTEST_DROP_METHOD "http") set(CTEST_DROP_SITE "open.cdash.org") set(CTEST_DROP_LOCATION "/submit.php?project=GDCM") set(CTEST_DROP_SITE_CDASH TRUE) GDCM-3.0.10/Copyright.txt000066400000000000000000000035071412732066400150300ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2016 Mathieu Malaterre Copyright (c) 1993-2005 CREATIS (CREATIS = Centre de Recherche et d'Applications en Traitement de l'Image) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither name of Mathieu Malaterre, or CREATIS, nor the names of any contributors (CNRS, INSERM, UCB, Universite Lyon I), may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =========================================================================*/ GDCM-3.0.10/Examples/000077500000000000000000000000001412732066400140705ustar00rootroot00000000000000GDCM-3.0.10/Examples/CMakeLists.txt000066400000000000000000000010611412732066400166260ustar00rootroot00000000000000cmake_minimum_required(VERSION 2.8.7) # Choose behavior based on whether we are building inside the GDCM tree. if(GDCM_BINARY_DIR) add_subdirectory(Cxx) if(GDCM_WRAP_PYTHON) add_subdirectory(Python) endif() if(GDCM_WRAP_CSHARP) add_subdirectory(Csharp) endif() if(GDCM_WRAP_JAVA) add_subdirectory(Java) endif() else() # We are building outside the GDCM tree. Build the examples directly. project(GDCMExamples) # Find and load the VTK configuration. find_package(GDCM REQUIRED) include(${GDCM_USE_FILE}) add_subdirectory(Cxx) endif() GDCM-3.0.10/Examples/Csharp/000077500000000000000000000000001412732066400153105ustar00rootroot00000000000000GDCM-3.0.10/Examples/Csharp/BasicAnonymizer.cs000066400000000000000000000101111412732066400207260ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /** * This is a minimal Anonymizer. All it does is anonymize a single file. * When anonymizing more than a single file, one should be really careful * to only create one single instance of a gdcm.Anonymizer and reuse it * for the entire Series. * See ClinicalTrialIdentificationWorkflow.cs for a more complex example */ /* * Usage: * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono bin/BasicAnonymizer.exe gdcmData/012345.002.050.dcm out.dcm */ using System; using gdcm; public class MyWatcher : SimpleSubjectWatcher { public MyWatcher(Subject s):base(s,"Override String"){} protected override void StartFilter() { System.Console.WriteLine( "This is my start" ); } protected override void EndFilter(){ System.Console.WriteLine( "This is my end" ); } protected override void ShowProgress(Subject caller, Event evt){ ProgressEvent pe = ProgressEvent.Cast(evt); System.Console.WriteLine( "This is my progress: " + pe.GetProgress() ); } protected override void ShowIteration(){ System.Console.WriteLine( "This is my iteration" ); } protected override void ShowAnonymization(Subject caller, Event evt){ /* * A couple of explanation are necessary here to understand how SWIG work * http://www.swig.org/Doc1.3/Java.html#adding_downcasts * * System.Console.WriteLine( "This is my Anonymization. Type: " + evt.GetEventName() ); * System.Type type = evt.GetType(); * System.Console.WriteLine( "This is my Anonymization. System.Type: " + type.ToString() ); * System.Console.WriteLine( "This is my Anonymization. CheckEvent: " + ae.CheckEvent( evt ) ); * System.Console.WriteLine( "This is my Anonymization. Processing Tag #" + ae.GetTag().toString() ); */ AnonymizeEvent ae = AnonymizeEvent.Cast(evt); if( ae != null ) { Tag t = ae.GetTag(); System.Console.WriteLine( "This is my Anonymization. Processing Tag #" + t.toString() ); } else { System.Console.WriteLine( "This is my Anonymization. Unhandled Event type: " + evt.GetEventName() ); } } protected override void ShowAbort(){ System.Console.WriteLine( "This is my abort" ); } } public class BasicAnonymizer { public static int Main(string[] args) { gdcm.Global global = gdcm.Global.GetInstance(); if( !global.LoadResourcesFiles() ) { System.Console.WriteLine( "Could not LoadResourcesFiles" ); return 1; } string file1 = args[0]; string file2 = args[1]; Reader reader = new Reader(); reader.SetFileName( file1 ); bool ret = reader.Read(); if( !ret ) { return 1; } string certpath = gdcm.Filename.Join(gdcm.Testing.GetSourceDirectory(), "/Testing/Source/Data/certificate.pem" ); gdcm.CryptoFactory fact = gdcm.CryptoFactory.GetFactoryInstance(); gdcm.CryptographicMessageSyntax cms = fact.CreateCMSProvider(); if( !cms.ParseCertificateFile( certpath ) ) { return 1; } //Anonymizer ano = new Anonymizer(); SmartPtrAno sano = Anonymizer.New(); Anonymizer ano = sano.__ref__(); //SimpleSubjectWatcher watcher = new SimpleSubjectWatcher(ano, "Anonymizer"); MyWatcher watcher = new MyWatcher(ano); ano.SetFile( reader.GetFile() ); ano.SetCryptographicMessageSyntax( cms ); if( !ano.BasicApplicationLevelConfidentialityProfile() ) { return 1; } Writer writer = new Writer(); writer.SetFileName( file2 ); writer.SetFile( ano.GetFile() ); ret = writer.Write(); if( !ret ) { return 1; } return 0; } } GDCM-3.0.10/Examples/Csharp/BasicImageAnonymizer.cs000066400000000000000000000047461412732066400217120ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* */ using System; using gdcm; public class BasicImageAnonymizer { public static int Main(string[] args) { string filename = args[0]; // instanciate the reader: gdcm.ImageReader reader = new gdcm.ImageReader(); reader.SetFileName( filename ); if (!reader.Read()) return 1; Image ir = reader.GetImage(); uint[] dims = {0, 0, 0}; dims[0] = ir.GetDimension(0); dims[1] = ir.GetDimension(1); dims[2] = ir.GetDimension(2); System.Console.WriteLine( "Dim:" + dims[0] ); System.Console.WriteLine( "Dim:" + dims[1] ); System.Console.WriteLine( "Dim:" + dims[2] ); // buffer to get the pixels byte[] buffer = new byte[ ir.GetBufferLength()]; System.Console.WriteLine( "Dim:" + ir.GetBufferLength() ); ir.GetBuffer( buffer ); for (uint z = 0; z < dims[2]; z++) { for (uint y = 0; y < dims[1] / 2; y++) // only half Y { for (uint x = 0; x < dims[0] / 2; x++) // only half X { buffer[ (z * dims[1] + y) * dims[0] + x ] = 0; // works when pixel type == UINT8 } } } DataElement pixeldata = new DataElement( new Tag(0x7fe0,0x0010) ); pixeldata.SetByteValue( buffer, new VL( (uint)buffer.Length ) ); ir.SetDataElement( pixeldata ); ir.SetTransferSyntax( new TransferSyntax( TransferSyntax.TSType.ExplicitVRLittleEndian ) ); ImageChangeTransferSyntax change = new ImageChangeTransferSyntax(); change.SetTransferSyntax( new TransferSyntax( TransferSyntax.TSType.JPEGLSLossless ) ); change.SetInput( ir ); if( !change.Change() ) { System.Console.WriteLine( "Could not change: " + filename ); return 1; } ImageWriter writer = new ImageWriter(); writer.SetFileName( "out.dcm" ); writer.SetFile( reader.GetFile() ); writer.SetImage( change.GetOutput() ); bool ret = writer.Write(); if( !ret ) { return 1; } return 0; } } GDCM-3.0.10/Examples/Csharp/CMakeLists.txt000066400000000000000000000041671412732066400200600ustar00rootroot00000000000000# C# examples set(CSHARP_EXAMPLES SimplePrintPatientName ExtractOneFrame ExtractImageRegion ExtractImageRegionWithLUT ManipulateFile RescaleImage ExtractEncapsulatedFile DecompressImage DecompressImageMultiframe DecompressJPEGFile SimplePrint ScanDirectory #SortImage2 GetArray NewSequence GenerateDICOMDIR StandardizeFiles ReformatFile CompressLossyJPEG SendFileSCU MpegVideoInfo BasicImageAnonymizer FileAnonymize FileStreaming FileChangeTS FileChangeTSLossy DumpCSA ) if(BUILD_TESTING) list(APPEND CSHARP_EXAMPLES BasicAnonymizer ClinicalTrialIdentificationWorkflow ) endif() set(DEP) # http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_add_a_dependency_to_a_source_file_which_is_generated_in_a_subdirectory.3F # Tell CMake the source won't be available until build time. set_source_files_properties(${GDCM_LIBRARY_DIR}/gdcm-sharp.dll PROPERTIES GENERATED 1) # Make sure the source is generated before the executable builds. foreach(example ${CSHARP_EXAMPLES}) file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${example}.cs result) add_custom_command( OUTPUT ${GDCM_EXECUTABLE_DIR}/${example}.exe COMMAND ${CMAKE_CSHARP_COMPILER} "${CSC_PLATFORM_FLAG}" "/r:${GDCM_LIBRARY_DIR}/gdcm-sharp.dll" "/out:${GDCM_EXECUTABLE_DIR}/${example}.exe" ${result} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${example}.cs COMMENT "Create ${example}.exe" ) add_custom_target(gdcm_sharp_${example} DEPENDS ${GDCM_EXECUTABLE_DIR}/${example}.exe) # Make sure the gdcm-sharp.dll is generated before the exampls builds. add_dependencies(gdcm_sharp_${example} GDCMCSharp) list(APPEND DEP ${GDCM_EXECUTABLE_DIR}/${example}.exe) endforeach() add_custom_target(GDCMExampleCSharp ALL DEPENDS ${DEP} COMMENT "building examples" ) add_dependencies(GDCMExampleCSharp GDCMCSharp) if(BUILD_TESTING) if(GDCM_DATA_ROOT) ADD_CSHARP_TEST(TestSimplePrintCSharp ${GDCM_EXECUTABLE_DIR}/SimplePrint.exe ${GDCM_DATA_ROOT}/012345.002.050.dcm) # TODO: #if(BUILD_EXAMPLES) # ADD_CSHARP_TEST(HelloWorldCSharp ${GDCM_EXECUTABLE_DIR}/HelloWorld.exe ${GDCM_DATA_ROOT}/012345.002.050.dcm) #endif() endif() endif() GDCM-3.0.10/Examples/Csharp/ClinicalTrialIdentificationWorkflow.cs000066400000000000000000000232661412732066400247670ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /** * This is a simple example that show typical pipeline to setup when * preprocessing incoming DICOM file from around the round, and making * sur eto remove any Patient Information. * This is actually identical to running the C++ command line tool: gdcmanon, * except this is easily integrated into another C# environment. * * PS 3.17 - 2008 Annex H. * Clinical Trial Identification Workflow Examples (Informative) * * This Annex was formerly located in Annex O of PS 3.3 in the 2003 and earlier * revisions of the standard. The Clinical Trial Identification modules are * optional. As such, there are several points in the workflow of clinical trial * data at which the Clinical Trial Identification attributes may be added to the * data. At the Clinical Trial Site, the attributes may be added at the scanner, a * PACS system, a site workstation, or a workstation provided to the site by a * Clinical Trial Coordinating Center. If not added at the site, the Clinical * Trial Identification attributes may be added to the data after receipt by the * Clinical Trial Coordinating Center. The addition of clinical trial attributes * does not itself require changes to the SOP Instance UID. However, the clinical * trial protocol or the process of de-identification may require such a change. */ /* * Typical usage on UNIX: * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono bin/ClinicalTrialIdentificationWorkflow.exe input_dir output_dir */ using System; using gdcm; public class MyWatcher : SimpleSubjectWatcher { public MyWatcher(Subject s):base(s,"Override String"){} protected override void StartFilter() { System.Console.WriteLine( "This is my start" ); } protected override void EndFilter(){ System.Console.WriteLine( "This is my end" ); } protected override void ShowProgress(Subject caller, Event evt){ ProgressEvent pe = ProgressEvent.Cast(evt); System.Console.WriteLine( "This is my progress: " + pe.GetProgress() ); } protected override void ShowIteration(){ System.Console.WriteLine( "This is my iteration" ); } protected override void ShowAnonymization(Subject caller, Event evt){ /* * A couple of explanation are necessary here to understand how SWIG work * http://www.swig.org/Doc1.3/Java.html#adding_downcasts * * System.Console.WriteLine( "This is my Anonymization. Type: " + evt.GetEventName() ); * System.Type type = evt.GetType(); * System.Console.WriteLine( "This is my Anonymization. System.Type: " + type.ToString() ); * System.Console.WriteLine( "This is my Anonymization. CheckEvent: " + ae.CheckEvent( evt ) ); * System.Console.WriteLine( "This is my Anonymization. Processing Tag #" + ae.GetTag().toString() ); */ AnonymizeEvent ae = AnonymizeEvent.Cast(evt); if( ae != null ) { Tag t = ae.GetTag(); System.Console.WriteLine( "This is my Anonymization. Processing Tag #" + t.toString() ); } else { System.Console.WriteLine( "This is my Anonymization. Unhandled Event type: " + evt.GetEventName() ); } } protected override void ShowAbort(){ System.Console.WriteLine( "This is my abort" ); } } public class ClinicalTrialIdentificationWorkflow { public static bool ProcessOneFile( gdcm.Anonymizer ano , string filename, string outfilename ) { Reader reader = new Reader(); reader.SetFileName( filename ); bool ret = reader.Read(); if( !ret ) { return false; } // Pass in the file: ano.SetFile( reader.GetFile() ); // First step, let's protect all Patient information as per // PS 3.15 / E.1 / Basic Application Level Confidentiality Profile if( !ano.BasicApplicationLevelConfidentialityProfile() ) { return false; } // Now let's pass in all Clinical Trial fields // PS 3.3 - 2008 / C.7.1.3 Clinical Trial Subject Module /* Clinical Trial Sponsor Name (0012,0010) 1 The name of the clinical trial sponsor. See C.7.1.3.1.1. Clinical Trial Protocol ID (0012,0020) 1 Identifier for the noted protocol. See C.7.1.3.1.2. Clinical Trial Protocol Name (0012,0021) 2 The name of the clinical trial protocol. See C.7.1.3.1.3. Clinical Trial Site ID (0012,0030) 2 The identifier of the site responsible for submitting clinical trial data. See C.7.1.3.1.4. Clinical Trial Site Name (0012,0031) 2 Name of the site responsible for submitting clinical trial data. See C.7.1.3.1.5 Clinical Trial Subject ID (0012,0040) 1C The assigned identifier for the clinical trial subject. See C.7.1.3.1.6. Shall be present if Clinical Trial Subject Reading ID (0012,0042) is absent. May be present otherwise. Clinical Trial Subject Reading ID (0012,0042) 1C Identifies the subject for blinded evaluations. Shall be present if Clinical Trial Subject ID (0012,0040) is absent. May be present otherwise. See C.7.1.3.1.7. */ ano.Replace( new gdcm.Tag(0x0012,0x0010), "MySponsorName"); ano.Replace( new gdcm.Tag(0x0012,0x0020), "MyProtocolID"); ano.Replace( new gdcm.Tag(0x0012,0x0021), "MyProtocolName"); ano.Replace( new gdcm.Tag(0x0012,0x0030), "MySiteId"); ano.Replace( new gdcm.Tag(0x0012,0x0031), "MySiteName"); ano.Replace( new gdcm.Tag(0x0012,0x0040), "MySponsorId"); ano.Replace( new gdcm.Tag(0x0012,0x0050), "MyTPId"); ano.Replace( new gdcm.Tag(0x0012,0x0051), "MyTPDescription"); // The following two are not required as they are guaranteed to be filled in by the // Basic Application Level Confidentiality Profile. Only override if you understand what // you are doing //ano.Replace( new gdcm.Tag(0x0012,0x0062), "YES"); //ano.Replace( new gdcm.Tag(0x0012,0x0063), "My Super Duper Anonymization Overload"); // We might be generating a subdirectory. Let's make sure the subdir exist: gdcm.Filename fn = new gdcm.Filename( outfilename ); string subdir = fn.GetPath(); if( !gdcm.PosixEmulation.MakeDirectory( subdir ) ) { return false; } gdcm.FileMetaInformation fmi = ano.GetFile().GetHeader(); // The following three lines make sure to regenerate any value: fmi.Remove( new gdcm.Tag(0x0002,0x0012) ); fmi.Remove( new gdcm.Tag(0x0002,0x0013) ); fmi.Remove( new gdcm.Tag(0x0002,0x0016) ); Writer writer = new Writer(); writer.SetFileName( outfilename ); writer.SetFile( ano.GetFile() ); ret = writer.Write(); if( !ret ) { return false; } return true; } public static int Main(string[] args) { gdcm.FileMetaInformation.SetSourceApplicationEntityTitle( "My ClinicalTrial App" ); // http://www.oid-info.com/get/1.3.6.1.4.17434 string THERALYS_ORG_ROOT = "1.3.6.1.4.17434"; gdcm.UIDGenerator.SetRoot( THERALYS_ORG_ROOT ); System.Console.WriteLine( "Root dir is now: " + gdcm.UIDGenerator.GetRoot() ); gdcm.Global global = gdcm.Global.GetInstance(); if( !global.LoadResourcesFiles() ) { System.Console.WriteLine( "Could not LoadResourcesFiles" ); return 1; } if( args.Length != 2 ) { System.Console.WriteLine( "Usage:" ); System.Console.WriteLine( "ClinicalTrialIdentificationWorkflow input_dir output_dir" ); return 1; } string dir1 = args[0]; string dir2 = args[1]; // Check input is valid: if( !gdcm.PosixEmulation.FileIsDirectory(dir1) ) { System.Console.WriteLine( "Input directory: " + dir1 + " does not exist. Sorry" ); return 1; } if( !gdcm.PosixEmulation.FileIsDirectory(dir2) ) { System.Console.WriteLine( "Output directory: " + dir2 + " does not exist. Sorry" ); return 1; } // Recursively search all file within this toplevel directory: Directory d = new Directory(); uint nfiles = d.Load( dir1, true ); if(nfiles == 0) return 1; // Let's use the pre-shipped certificate of GDCM. string certpath = gdcm.Filename.Join(gdcm.Testing.GetSourceDirectory(), "/Testing/Source/Data/certificate.pem" ); gdcm.CryptoFactory fact = gdcm.CryptoFactory.GetFactoryInstance(); gdcm.CryptographicMessageSyntax cms = fact.CreateCMSProvider(); if( !cms.ParseCertificateFile( certpath ) ) { System.Console.WriteLine( "PEM Certificate : " + certpath + " could not be read. Sorry" ); return 1; } //Anonymizer ano = new Anonymizer(); // A reference to an actual C++ instance is required here: SmartPtrAno sano = Anonymizer.New(); Anonymizer ano = sano.__ref__(); //SimpleSubjectWatcher watcher = new SimpleSubjectWatcher(ano, "Anonymizer"); MyWatcher watcher = new MyWatcher(ano); // Explicitly specify the Cryptographic Message Syntax to use: ano.SetCryptographicMessageSyntax( cms ); // Process all filenames: FilenamesType filenames = d.GetFilenames(); for( uint i = 0; i < nfiles; ++i ) { string filename = filenames[ (int)i ]; string outfilename = filename.Replace( dir1, dir2 ); System.Console.WriteLine( "Filename: " + filename ); System.Console.WriteLine( "Out Filename: " + outfilename ); if( !ProcessOneFile( ano , filename, outfilename ) ) { System.Console.WriteLine( "Could not process filename: " + filename ); return 1; } } return 0; } } GDCM-3.0.10/Examples/Csharp/CompressLossyJPEG.cs000066400000000000000000000051501412732066400211330ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Usage: * $ export LD_LIBRARY_PATH=$HOME/Perso/gdcm/debug-gcc/bin * $ mono bin/CompressLossyJPEG.exe input.dcm output.dcm */ using System; using gdcm; public class CompressLossyJPEG { public static int Main(string[] args) { if( args.Length < 2 ) { System.Console.WriteLine( " input.dcm output.dcm" ); return 1; } string filename = args[0]; string outfilename = args[1]; ImageReader reader = new ImageReader(); reader.SetFileName( filename ); if( !reader.Read() ) { System.Console.WriteLine( "Could not read: " + filename ); return 1; } // The output of gdcm::Reader is a gdcm::File File file = reader.GetFile(); // the dataset is the the set of element we are interested in: DataSet ds = file.GetDataSet(); Image image = reader.GetImage(); //image.Print( cout ); ImageChangeTransferSyntax change = new ImageChangeTransferSyntax(); TransferSyntax targetts = new TransferSyntax( TransferSyntax.TSType.JPEGBaselineProcess1 ); change.SetTransferSyntax( targetts ); // Setup our JPEGCodec, warning it should be compatible with JPEGBaselineProcess1 JPEGCodec jpegcodec = new JPEGCodec(); if( !jpegcodec.CanCode( targetts ) ) { System.Console.WriteLine( "Something went really wrong, JPEGCodec cannot handle JPEGBaselineProcess1" ); return 1; } jpegcodec.SetLossless( false ); jpegcodec.SetQuality( 50 ); // poor quality ! change.SetUserCodec( jpegcodec ); // specify the codec to use to the ImageChangeTransferSyntax change.SetInput( image ); bool b = change.Change(); if( !b ) { System.Console.WriteLine( "Could not change the Transfer Syntax" ); return 1; } ImageWriter writer = new ImageWriter(); writer.SetImage( (gdcm.Image)change.GetOutput() ); writer.SetFile( reader.GetFile() ); writer.SetFileName( outfilename ); if( !writer.Write() ) { System.Console.WriteLine( "Could not write: " + outfilename ); return 1; } return 0; } } GDCM-3.0.10/Examples/Csharp/DecompressImage.cs000066400000000000000000000052631412732066400207140ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Usage: * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono bin/DecompressImage.exe gdcmData/012345.002.050.dcm decompress.dcm */ using System; using gdcm; public class DecompressImage { public static int Main(string[] args) { string file1 = args[0]; string file2 = args[1]; ImageReader reader = new ImageReader(); reader.SetFileName( file1 ); bool ret = reader.Read(); if( !ret ) { return 1; } // check that one can access a Fragment from C#: var de = reader.GetFile().GetDataSet().GetDataElement(new Tag(0x7fe0, 0x0010)); var sq = de.GetSequenceOfFragments(); sq.GetFragment(0); Image image = new Image(); Image ir = reader.GetImage(); image.SetNumberOfDimensions( ir.GetNumberOfDimensions() ); //Just for fun: //int dircos = ir.GetDirectionCosines(); //t = gdcm.Orientation.GetType(dircos); //int l = gdcm.Orientation.GetLabel(t); //System.Console.WriteLine( "Orientation label:" + l ); // Set the dimensions, // 1. either one at a time //image.SetDimension(0, ir.GetDimension(0) ); //image.SetDimension(1, ir.GetDimension(1) ); // 2. the array at once uint[] dims = {0, 0}; // Just for fun let's invert the dimensions: dims[0] = ir.GetDimension(1); dims[1] = ir.GetDimension(0); ir.SetDimensions( dims ); PixelFormat pixeltype = ir.GetPixelFormat(); image.SetPixelFormat( pixeltype ); PhotometricInterpretation pi = ir.GetPhotometricInterpretation(); image.SetPhotometricInterpretation( pi ); DataElement pixeldata = new DataElement( new Tag(0x7fe0,0x0010) ); byte[] str1 = new byte[ ir.GetBufferLength()]; ir.GetBuffer( str1 ); //System.Console.WriteLine( ir.GetBufferLength() ); pixeldata.SetByteValue( str1, new VL( (uint)str1.Length ) ); //image.SetDataElement( pixeldata ); ir.SetDataElement( pixeldata ); ImageWriter writer = new ImageWriter(); writer.SetFileName( file2 ); writer.SetFile( reader.GetFile() ); writer.SetImage( ir ); ret = writer.Write(); if( !ret ) { return 1; } return 0; } } GDCM-3.0.10/Examples/Csharp/DecompressImageMultiframe.cs000066400000000000000000000105111412732066400227320ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* $ gdcminfo ~/Desktop/angiogram-06.dcm MediaStorage is 1.2.840.10008.5.1.4.1.1.12.1 [X-Ray Angiographic Image Storage] TransferSyntax is 1.2.840.10008.1.2.4.50 [JPEG Baseline (Process 1): Default Transfer Syntax for Lossy JPEG 8 Bit Image Compression] NumberOfDimensions: 3 Dimensions: (512,512,355) Origin: (0,0,0) Spacing: (1,1,40) DirectionCosines: (1,0,0,0,1,0) Rescale Intercept/Slope: (0,1) SamplesPerPixel :1 BitsAllocated :8 BitsStored :8 HighBit :7 PixelRepresentation:0 ScalarType found :UINT8 PhotometricInterpretation: MONOCHROME2 PlanarConfiguration: 0 TransferSyntax: 1.2.840.10008.1.2.4.50 Orientation Label: AXIAL */ /* * Description: * * Assume we have a file angiogram-06.dcm as described above. * the following program will decompress directly from the extracted jpeg stream. * * First step extract the jpeg stream (but not the Basic Offset Table): * * $ gdcmraw -i angiogram-06.dcm -o /tmp/output/chris --split-frags --pattern %d.jpg * * Check that indeed there are 355 files, while there are 356 fragments in the original DICOM file, since * gdcmraw always skip the first fragment (Basic Offset Table). * * Now from those individual jpeg stream, recreate a fake gdcm.DataElement... * * Usage: * * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono ./bin/DecompressImageMultiframe.exe /tmp/output */ using System; using gdcm; public class DecompressImageMultiframe { public static int Main(string[] args) { string directory = args[0]; gdcm.Directory dir = new gdcm.Directory(); uint nfiles = dir.Load(directory); //System.Console.WriteLine(dir.toString()); gdcm.FilenamesType filenames = dir.GetFilenames(); Image image = new Image(); image.SetNumberOfDimensions( 3 ); // important for now DataElement pixeldata = new DataElement( new gdcm.Tag(0x7fe0,0x0010) ); // Create a new SequenceOfFragments C++ object, store it as a SmartPointer : SmartPtrFrag sq = SequenceOfFragments.New(); // Yeah, the file are not garantee to be in order, please adapt... for(uint i = 0; i < nfiles; ++i) { System.Console.WriteLine( filenames[(int)i] ); string file = filenames[(int)i]; System.IO.FileStream infile = new System.IO.FileStream(file, System.IO.FileMode.Open, System.IO.FileAccess.Read); uint fsize = gdcm.PosixEmulation.FileSize(file); byte[] jstream = new byte[fsize]; infile.Read(jstream, 0 , jstream.Length); Fragment frag = new Fragment(); frag.SetByteValue( jstream, new gdcm.VL( (uint)jstream.Length) ); sq.AddFragment( frag ); } // Pass by reference: pixeldata.SetValue( sq.__ref__() ); // insert: image.SetDataElement( pixeldata ); // JPEG use YBR to achieve better compression ratio by default (not RGB) // FIXME hardcoded: PhotometricInterpretation pi = new PhotometricInterpretation( PhotometricInterpretation.PIType.MONOCHROME2 ); image.SetPhotometricInterpretation( pi ); // FIXME hardcoded: PixelFormat pixeltype = new PixelFormat(1,8,8,7); image.SetPixelFormat( pixeltype ); // FIXME hardcoded: image.SetTransferSyntax( new TransferSyntax( TransferSyntax.TSType.JPEGLosslessProcess14_1 ) ); image.SetDimension(0, 512); image.SetDimension(1, 512); image.SetDimension(2, 355); // Decompress ! byte[] decompressedData = new byte[(int)image.GetBufferLength()]; image.GetBuffer(decompressedData); // Write out the decompressed bytes System.Console.WriteLine(image.toString()); using (System.IO.Stream stream = System.IO.File.Open(@"/tmp/dd.raw", System.IO.FileMode.Create)) { System.IO.BinaryWriter writer = new System.IO.BinaryWriter(stream); writer.Write(decompressedData); } return 0; } } GDCM-3.0.10/Examples/Csharp/DecompressJPEGFile.cs000066400000000000000000000057361412732066400212240ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Usage: * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono bin/DecompressJPEGFile.exe somejpegfile.jpg */ using System; using gdcm; public class DecompressJPEGFile { public static int Main(string[] args) { string file1 = args[0]; System.IO.FileStream infile = new System.IO.FileStream(file1, System.IO.FileMode.Open, System.IO.FileAccess.Read); uint fsize = gdcm.PosixEmulation.FileSize(file1); byte[] jstream = new byte[fsize]; infile.Read(jstream, 0 , jstream.Length); Trace.DebugOn(); Image image = new Image(); image.SetNumberOfDimensions( 2 ); // important for now DataElement pixeldata = new DataElement( new gdcm.Tag(0x7fe0,0x0010) ); // DO NOT set a ByteValue here, JPEG is a particular kind of encapsulated syntax // in which can one cannot use a simple byte array for storage. Instead, see // gdcm.SequenceOfFragments //pixeldata.SetByteValue( jstream, new gdcm.VL( (uint)jstream.Length ) ); // Create a new SequenceOfFragments C++ object, store it as a SmartPointer : SmartPtrFrag sq = SequenceOfFragments.New(); Fragment frag = new Fragment(); frag.SetByteValue( jstream, new gdcm.VL( (uint)jstream.Length) ); // Single file => single fragment sq.AddFragment( frag ); // Pass by reference: pixeldata.SetValue( sq.__ref__() ); // insert: image.SetDataElement( pixeldata ); // JPEG use YBR to achieve better compression ratio by default (not RGB) // FIXME hardcoded: PhotometricInterpretation pi = new PhotometricInterpretation( PhotometricInterpretation.PIType.YBR_FULL ); image.SetPhotometricInterpretation( pi ); // FIXME hardcoded: PixelFormat pixeltype = new PixelFormat(3,8,8,7); image.SetPixelFormat( pixeltype ); // FIXME hardcoded: image.SetTransferSyntax( new TransferSyntax( TransferSyntax.TSType.JPEGLosslessProcess14_1 ) ); image.SetDimension(0, 692); image.SetDimension(1, 721); // Decompress ! byte[] decompressedData = new byte[(int)image.GetBufferLength()]; image.GetBuffer(decompressedData); // Write out the decompressed bytes System.Console.WriteLine(image.toString()); using (System.IO.Stream stream = System.IO.File.Open(@"/tmp/dd.raw", System.IO.FileMode.Create)) { System.IO.BinaryWriter writer = new System.IO.BinaryWriter(stream); writer.Write(decompressedData); } return 0; } } GDCM-3.0.10/Examples/Csharp/DumpCSA.cs000066400000000000000000000042711412732066400170770ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Usage: * $ bin/DumpCSA.exe input.dcm */ using System; using gdcm; public class DumpCSA { public static int Main(string[] args) { string filename = args[0]; gdcm.Reader reader = new gdcm.Reader(); reader.SetFileName( filename ); if (!reader.Read()) return 1; gdcm.File f = reader.GetFile(); gdcm.DataSet ds = f.GetDataSet(); string[] expectedSiemensTags = new string[] { "B_value" , "AcquisitionMatrixText" }; using (PrivateTag gtag = CSAHeader.GetCSAImageHeaderInfoTag()) { if (ds.FindDataElement(gtag)) { using (DataElement de = ds.GetDataElement(gtag)) { if (de != null && !de.IsEmpty()) { using (CSAHeader csa = new CSAHeader()) { if (csa.LoadFromDataElement(de)) { foreach (string str in expectedSiemensTags) { if (csa.FindCSAElementByName(str)) { using (CSAElement elem = csa.GetCSAElementByName(str)) { if (elem != null) { System.Console.WriteLine( elem.toString() ); } } } } } } } } } } return 0; } } GDCM-3.0.10/Examples/Csharp/ExtractEncapsulatedFile.cs000066400000000000000000000045021412732066400224030ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This example shows how one from C# context can extract a binary blob * and write out as a file. * This example is meant for pdf encapsulated file, but can be adapted for other type * of binary blob. * * DICOM file is: * ... * (0042,0010) ST (no value available) # 0, 0 DocumentTitle * (0042,0011) OB 25\50\44\46\2d\31\2e\32\20\0d\25\e2\e3\cf\d3\20\0d\31\30\20\30\20... # 40718, 1 EncapsulatedDocument * (0042,0012) LO [application/pdf] # 16, 1 MIMETypeOfEncapsulatedDocument * ... * * Usage: * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono bin/ExtractEncapsulatedFile.exe some_pdf_encapsulated.dcm */ using System; using gdcm; public class ExtractEncapsulatedFile { public static int Main(string[] args) { string file = args[0]; Reader reader = new Reader(); reader.SetFileName( file ); bool ret = reader.Read(); if( !ret ) { return 1; } File f = reader.GetFile(); DataSet ds = f.GetDataSet(); Tag tencapsulated_stream = new Tag(0x0042,0x0011); // Encapsulated Document if( !ds.FindDataElement( tencapsulated_stream ) ) { return 1; } // else DataElement de = ds.GetDataElement( tencapsulated_stream ); ByteValue bv = de.GetByteValue(); uint len = bv.GetLength(); byte[] encapsulated_stream = new byte[len]; bv.GetBuffer( encapsulated_stream, len ); // Write out the decompressed bytes //System.Console.WriteLine(image.toString()); using (System.IO.Stream stream = System.IO.File.Open(@"/tmp/dd.pdf", System.IO.FileMode.Create)) { System.IO.BinaryWriter writer = new System.IO.BinaryWriter(stream); writer.Write( encapsulated_stream ); } return 0; } } GDCM-3.0.10/Examples/Csharp/ExtractImageRegion.cs000066400000000000000000000063201412732066400213610ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This small code shows how to use the gdcm.ImageRegionReader API * In this example we are taking each frame by frame and dump them to * /tmp/frame.raw. * * Usage: * $ bin/ExtractImageRegion.exe input.dcm * * Example: * $ bin/ExtractImageRegion.exe gdcmData/012345.002.050.dcm * $ md5sum /tmp/frame.raw * d594a5e2fde12f32b6633ca859b4d4a6 /tmp/frame.raw * $ gdcminfo --md5sum gdcmData/012345.002.050.dcm * [...] * md5sum: d594a5e2fde12f32b6633ca859b4d4a6 */ using System; using gdcm; public class ExtractImageRegion { public static int Main(string[] args) { string filename = args[0]; uint file_size = gdcm.PosixEmulation.FileSize(filename); // instantiate the reader: gdcm.ImageRegionReader reader = new gdcm.ImageRegionReader(); reader.SetFileName( filename ); // pull DICOM info: if (!reader.ReadInformation()) return 1; // store current offset: uint cur_pos = reader.GetStreamCurrentPosition(); uint remaining = file_size - cur_pos; Console.WriteLine("Remaining bytes to read (Pixel Data): " + remaining.ToString() ); // Get file infos gdcm.File f = reader.GetFile(); // get some info about image UIntArrayType dims = ImageHelper.GetDimensionsValue(f); PixelFormat pf = ImageHelper.GetPixelFormatValue (f); int pixelsize = pf.GetPixelSize(); PhotometricInterpretation pi = ImageHelper.GetPhotometricInterpretationValue(f); Console.WriteLine( pi.toString() ); // buffer to get the pixels byte[] buffer = new byte[ dims[0] * dims[1] * pixelsize ]; // define a simple box region. BoxRegion box = new BoxRegion(); for (uint z = 0; z < dims[2]; z++) { // Define that I want the image 0, full size (dimx x dimy pixels) // and do that for each z: box.SetDomain(0, dims[0] - 1, 0, dims[1] - 1, z, z); //System.Console.WriteLine( box.toString() ); reader.SetRegion( box ); // reader will try to load the uncompressed image region into buffer. // the call returns an error when buffer.Length is too small. For instance // one can call: // uint buf_len = reader.ComputeBufferLength(); // take into account pixel size // to get the exact size of minimum buffer if (reader.ReadIntoBuffer(buffer, (uint)buffer.Length)) { using (System.IO.Stream stream = System.IO.File.Open(@"/tmp/frame.raw", System.IO.FileMode.Create)) { System.IO.BinaryWriter writer = new System.IO.BinaryWriter(stream); writer.Write(buffer); } } else { throw new Exception("can't read pixels error"); } } return 0; } } GDCM-3.0.10/Examples/Csharp/ExtractImageRegionWithLUT.cs000066400000000000000000000064251412732066400226100ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This small code shows how to use the gdcm.ImageRegionReader API * In this example we are taking each frame by frame and dump them to * /tmp/frame.raw. * Furthermore we are applying the LUT on this image. * Special care should be taken in case the image is not PALETTE COLOR * * Usage: * $ bin/ExtractImageRegionWithLUT.exe input.dcm * * Example: * $ bin/ExtractImageRegionWithLUT.exe gdcmData/rle16loo.dcm * $ md5sum /tmp/frame_rgb.raw * 73bf61325fdb6e2830244a2b7b0c4ae2 /tmp/frame_rgb.raw * $ gdcmimg --depth 16 --spp 3 --size 600,430 /tmp/frame_rgb.raw rgb.dcm * $ gdcmviewer rgb.dcm */ using System; using gdcm; public class ExtractImageRegion { public static int Main(string[] args) { string filename = args[0]; // instantiate the reader: gdcm.ImageRegionReader reader = new gdcm.ImageRegionReader(); reader.SetFileName( filename ); // pull DICOM info: if (!reader.ReadInformation()) return 1; // Get file infos gdcm.File f = reader.GetFile(); gdcm.LookupTable lut = reader.GetImage().GetLUT(); // get some info about image UIntArrayType dims = ImageHelper.GetDimensionsValue(f); PixelFormat pf = ImageHelper.GetPixelFormatValue (f); int pixelsize = pf.GetPixelSize(); // buffer to get the pixels byte[] buffer = new byte[ dims[0] * dims[1] * pixelsize ]; // output buffer for the RGB decoded image: byte[] buffer2 = new byte[ dims[0] * dims[1] * pixelsize * 3 ]; // define a simple box region. BoxRegion box = new BoxRegion(); for (uint z = 0; z < dims[2]; z++) { // Define that I want the image 0, full size (dimx x dimy pixels) // and do that for each z: box.SetDomain(0, dims[0] - 1, 0, dims[1] - 1, z, z); //System.Console.WriteLine( box.toString() ); reader.SetRegion( box ); // reader will try to load the uncompressed image region into buffer. // the call returns an error when buffer.Length is too small. For instance // one can call: // uint buf_len = reader.ComputeBufferLength(); // take into account pixel size // to get the exact size of minimum buffer if (reader.ReadIntoBuffer(buffer, (uint)buffer.Length)) { if( !lut.Decode( buffer2, (uint)buffer2.Length, buffer, (uint)buffer.Length ) ) { throw new Exception("can't decode"); } using (System.IO.Stream stream = System.IO.File.Open(@"/tmp/frame_rgb.raw", System.IO.FileMode.Create)) { System.IO.BinaryWriter writer = new System.IO.BinaryWriter(stream); writer.Write(buffer2); } } else { throw new Exception("can't read pixels error"); } } return 0; } } GDCM-3.0.10/Examples/Csharp/ExtractOneFrame.cs000066400000000000000000000051561412732066400206750ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This small code shows how to use the gdcm.StreamImageReader API * to read a single (whole) frame at a time * The API allow extracting a smaller extent of the frame of course. * It will write out the extracted frame in /tmp/frame.raw * * Usage: * $ bin/ExtractOneFrame.exe input.dcm */ using System; using gdcm; public class ExtractOneFrame { public static int Main(string[] args) { string filename = args[0]; gdcm.StreamImageReader reader = new gdcm.StreamImageReader(); reader.SetFileName( filename ); if (!reader.ReadImageInformation()) return 1; // Get file infos gdcm.File f = reader.GetFile(); // get some info about image UIntArrayType extent = ImageHelper.GetDimensionsValue(f); //System.Console.WriteLine( extent[0] ); uint dimx = extent[0]; //System.Console.WriteLine( extent[1] ); uint dimy = extent[1]; //System.Console.WriteLine( extent[2] ); uint dimz = extent[2]; PixelFormat pf = ImageHelper.GetPixelFormatValue (f); int pixelsize = pf.GetPixelSize(); //System.Console.WriteLine( pixelsize ); // buffer to get the pixels byte[] buffer = new byte[ dimx * dimy * pixelsize ]; for (int i = 0; i < dimz; i++) { // Define that I want the image 0, full size (dimx x dimy pixels) reader.DefinePixelExtent(0, (ushort)dimx, 0, (ushort)dimy, (ushort)i, (ushort)(i+1)); uint buf_len = reader.DefineProperBufferLength(); // take into account pixel size //System.Console.WriteLine( buf_len ); if( buf_len > buffer.Length ) { throw new Exception("buffer is too small for target"); } if (reader.Read(buffer, (uint)buffer.Length)) { using (System.IO.Stream stream = System.IO.File.Open(@"/tmp/frame.raw", System.IO.FileMode.Create)) { System.IO.BinaryWriter writer = new System.IO.BinaryWriter(stream); writer.Write(buffer); } } else { throw new Exception("can't read pixels error"); } } return 0; } } GDCM-3.0.10/Examples/Csharp/FileAnonymize.cs000066400000000000000000000032031412732066400204060ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Simple C# example * * Usage: * $ mono bin/FileAnonymize.exe input.dcm output.dcm */ using System; using gdcm; public class FileAnonymize { public static int Main(string[] args) { string filename = args[0]; string outfilename = args[1]; gdcm.FileAnonymizer fa = new gdcm.FileAnonymizer(); fa.SetInputFileName( filename ); fa.SetOutputFileName( outfilename ); // Empty Operations // It will create elements, since those tags are non-registered public elements (2011): fa.Empty( new Tag(0x0008,0x1313) ); fa.Empty( new Tag(0x0008,0x1317) ); // Remove Operations // The following Tag are actually carefully chosen, since they refer to SQ: fa.Remove( new Tag(0x0008,0x2112) ); fa.Remove( new Tag(0x0008,0x9215) ); // Replace Operations // do not call replace operation on SQ attribute ! fa.Replace( new Tag(0x0018,0x5100), "MYVALUE " ); fa.Replace( new Tag(0x0008,0x1160), "MYOTHERVAL" ); if( !fa.Write() ) { System.Console.WriteLine( "Could not write" ); return 1; } return 0; } } GDCM-3.0.10/Examples/Csharp/FileChangeTS.cs000066400000000000000000000153371412732066400201040ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Simple C# example * * Shows multiple steps: * Steps 1. * Create a fake (dummy) DICOM file, with size 512 x 512 x 2 We use a small * image to be able to create the volume in memory Of course you can use any * existing DICOM instead * * Step 2. * Hack the DICOM file to pretend the number of frames is 1000 (instead of 2) * At this point in time this makes the DICOM file invalid (truncated). But the * next step will fix this. * * Step 3. * Use C# to create a binary data which will represent our source object for * image. * * Step 4. * We use gdcm.FileStreamer to merge the template DICOM file from Step 2, with * the binary data from Step 3. We decide to read a scanline at a time, but * this can be read with any number of bytes. AppendToDataElement() will always * do the proper computation. * * Step 5. * We compress this gigantic file, into [JPEG Lossless, Non-Hierarchical, * First-Order Prediction (Process 14 [Selection Value 1])] * * Usage: * $ mono bin/FileChangeTS.exe small.dcm big.dcm raw.data merge.dcm jpeg.dcm */ using System; using System.IO; using gdcm; public class FileChangeTS { public static byte[] StrToByteArray(string str) { System.Text.ASCIIEncoding encoding=new System.Text.ASCIIEncoding(); return encoding.GetBytes(str); } // Create a 256 x 256 Secondary Capture Image Storage static private void CreateSmallDICOM(string fileName) { using( var writer = new gdcm.PixmapWriter() ) { gdcm.Pixmap img = writer.GetImage(); img.SetNumberOfDimensions( 3 ); img.SetDimension(0, 512 ); img.SetDimension(1, 512 ); img.SetDimension(2, 2 ); // fake a 3d volume PhotometricInterpretation pi = new PhotometricInterpretation( PhotometricInterpretation.PIType.MONOCHROME2 ); img.SetPhotometricInterpretation( pi ); gdcm.DataElement pixeldata = new gdcm.DataElement( new gdcm.Tag(0x7fe0,0x0010) ); byte[] buffer = new byte[ 512 * 512 * 2 ]; pixeldata.SetByteValue( buffer, new gdcm.VL((uint)buffer.Length) ); img.SetDataElement( pixeldata ); gdcm.File file = writer.GetFile(); gdcm.DataSet ds = file.GetDataSet(); gdcm.DataElement ms = new gdcm.DataElement(new gdcm.Tag(0x0008,0x0016)); string mediastorage = "1.2.840.10008.5.1.4.1.1.7.2"; // Multi-frame Grayscale Byte Secondary Capture Image Storage byte[] val = StrToByteArray(mediastorage); ms.SetByteValue( val, new gdcm.VL( (uint)val.Length) ); ds.Insert( ms ); writer.SetFileName( fileName ); writer.Write(); } } static private void CreateBigDICOM(string fileName, string outfilename) { using( var ano = new gdcm.FileAnonymizer() ) { // The following is somewhat dangerous, do not try at home: string nframes = "1000"; ano.Replace( new gdcm.Tag(0x0028,0x0008), nframes ); ano.SetInputFileName(fileName); ano.SetOutputFileName(outfilename); ano.Write(); // at this point the DICOM is invalid ! } } static private void CreateDummyFile(string fileName, long length) { using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) { // Looks like C# always init to 0 (fallocate ?) // For the purpose of the test we could add some random noise fileStream.SetLength(length); } } static private void ReadBytesIntoArray( byte[] array, FileStream source ) { int numBytesToRead = array.Length; int numBytesRead = 0; while (numBytesToRead > 0) { // According to spec: Read() may return anything from 0 to numBytesToRead. int n = source.Read(array, numBytesRead, numBytesToRead); // Break when the end of the file is reached. if (n == 0) break; numBytesRead += n; numBytesToRead -= n; } } static private void AssembleDICOMAndRaw(string dicomfn, string rawdata, string outfn) { using ( var fs = new gdcm.FileStreamer() ) { fs.SetTemplateFileName(dicomfn); fs.SetOutputFileName(outfn); gdcm.Tag pixeldata = new gdcm.Tag(0x7fe0, 0x0010); // FileStreamer support automatic checking of pixel data length // based on DICOM attributes, only if we say so: fs.CheckDataElement( pixeldata ); // Declare we are working on Pixel Data attribute: fs.StartDataElement( pixeldata ); using (FileStream rawSource = new FileStream(rawdata, FileMode.Open, FileAccess.Read)) { byte[] bytes = new byte[512]; // Only read one scanline at a time // We could have been reading more at once, if this is more efficient, // AppendToDataElement will do the logic in all cases. for( int i = 0; i < 512 * 1000; ++i ) { // Read the source file into a byte array. ReadBytesIntoArray( bytes, rawSource ); fs.AppendToDataElement( pixeldata, bytes, (uint)bytes.Length ); } } if( !fs.StopDataElement( pixeldata ) ) { // Most likely an issue with Pixel Data Length computation: throw new Exception("StopDataElement failed"); } } } static private void CompressIntoJPEG(string rawdicom, string jpegdicom) { using( var sfcts = FileChangeTransferSyntax.New() ) { // Need to retrieve the actual C++ reference, to pass to // SimpleSubjectWatcher: FileChangeTransferSyntax fcts = sfcts.__ref__(); SimpleSubjectWatcher watcher = new SimpleSubjectWatcher(fcts, "FileChangeTransferSyntax"); gdcm.TransferSyntax ts = new TransferSyntax( TransferSyntax.TSType.JPEGLosslessProcess14_1 ); fcts.SetTransferSyntax( ts ); fcts.SetInputFileName( rawdicom ); fcts.SetOutputFileName( jpegdicom ); fcts.Change(); } } public static int Main(string[] args) { string filename = args[0]; string outfilename = args[1]; string rawfilename = args[2]; string mergefn = args[3]; string jpegfn = args[4]; CreateSmallDICOM(filename); CreateBigDICOM(filename, outfilename); CreateDummyFile(rawfilename, 512 * 512 * 1000 ); AssembleDICOMAndRaw(outfilename, rawfilename, mergefn); CompressIntoJPEG(mergefn, jpegfn); return 0; } } GDCM-3.0.10/Examples/Csharp/FileChangeTSLossy.cs000066400000000000000000000155771412732066400211440ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Simple C# example * * Shows multiple steps: * Steps 1. * Create a fake (dummy) DICOM file, with size 512 x 512 x 2 We use a small * image to be able to create the volume in memory Of course you can use any * existing DICOM instead * * Step 2. * Hack the DICOM file to pretend the number of frames is 1000 (instead of 2) * At this point in time this makes the DICOM file invalid (truncated). But the * next step will fix this. * * Step 3. * Use C# to create a binary data which will represent our source object for * image. * * Step 4. * We use gdcm.FileStreamer to merge the template DICOM file from Step 2, with * the binary data from Step 3. We decide to read a scanline at a time, but * this can be read with any number of bytes. AppendToDataElement() will always * do the proper computation. * * Step 5. * We compress this gigantic file, into [JPEG Baseline (Process 1): Default Transfer Syntax for Lossy JPEG 8 Bit Image Compression] * * Usage: * $ bin/FileChangeTSLossy.exe small.dcm big.dcm raw.data merge.dcm jpeg.dcm */ using System; using System.IO; using gdcm; public class FileChangeTS { public static byte[] StrToByteArray(string str) { System.Text.ASCIIEncoding encoding=new System.Text.ASCIIEncoding(); return encoding.GetBytes(str); } // Create a 256 x 256 Secondary Capture Image Storage static private void CreateSmallDICOM(string fileName) { using( var writer = new gdcm.PixmapWriter() ) { gdcm.Pixmap img = writer.GetImage(); img.SetNumberOfDimensions( 3 ); img.SetDimension(0, 512 ); img.SetDimension(1, 512 ); img.SetDimension(2, 2 ); // fake a 3d volume PhotometricInterpretation pi = new PhotometricInterpretation( PhotometricInterpretation.PIType.MONOCHROME2 ); img.SetPhotometricInterpretation( pi ); gdcm.DataElement pixeldata = new gdcm.DataElement( new gdcm.Tag(0x7fe0,0x0010) ); byte[] buffer = new byte[ 512 * 512 * 2 ]; pixeldata.SetByteValue( buffer, new gdcm.VL((uint)buffer.Length) ); img.SetDataElement( pixeldata ); gdcm.File file = writer.GetFile(); gdcm.DataSet ds = file.GetDataSet(); gdcm.DataElement ms = new gdcm.DataElement(new gdcm.Tag(0x0008,0x0016)); string mediastorage = "1.2.840.10008.5.1.4.1.1.7.2"; // Multi-frame Grayscale Byte Secondary Capture Image Storage byte[] val = StrToByteArray(mediastorage); ms.SetByteValue( val, new gdcm.VL( (uint)val.Length) ); ds.Insert( ms ); writer.SetFileName( fileName ); writer.Write(); } } static private void CreateBigDICOM(string fileName, string outfilename) { using( var ano = new gdcm.FileAnonymizer() ) { // The following is somewhat dangerous, do not try at home: string nframes = "1000"; ano.Replace( new gdcm.Tag(0x0028,0x0008), nframes ); ano.SetInputFileName(fileName); ano.SetOutputFileName(outfilename); ano.Write(); // at this point the DICOM is invalid ! } } static private void CreateDummyFile(string fileName, long length) { using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) { // Looks like C# always init to 0 (fallocate ?) // For the purpose of the test we could add some random noise fileStream.SetLength(length); } } static private void ReadBytesIntoArray( byte[] array, FileStream source ) { int numBytesToRead = array.Length; int numBytesRead = 0; while (numBytesToRead > 0) { // According to spec: Read() may return anything from 0 to numBytesToRead. int n = source.Read(array, numBytesRead, numBytesToRead); // Break when the end of the file is reached. if (n == 0) break; numBytesRead += n; numBytesToRead -= n; } } static private void AssembleDICOMAndRaw(string dicomfn, string rawdata, string outfn) { using ( var fs = new gdcm.FileStreamer() ) { fs.SetTemplateFileName(dicomfn); fs.SetOutputFileName(outfn); gdcm.Tag pixeldata = new gdcm.Tag(0x7fe0, 0x0010); // FileStreamer support automatic checking of pixel data length // based on DICOM attributes, only if we say so: fs.CheckDataElement( pixeldata ); // Declare we are working on Pixel Data attribute: fs.StartDataElement( pixeldata ); using (FileStream rawSource = new FileStream(rawdata, FileMode.Open, FileAccess.Read)) { byte[] bytes = new byte[512]; // Only read one scanline at a time // We could have been reading more at once, if this is more efficient, // AppendToDataElement will do the logic in all cases. for( int i = 0; i < 512 * 1000; ++i ) { // Read the source file into a byte array. ReadBytesIntoArray( bytes, rawSource ); fs.AppendToDataElement( pixeldata, bytes, (uint)bytes.Length ); } } if( !fs.StopDataElement( pixeldata ) ) { // Most likely an issue with Pixel Data Length computation: throw new Exception("StopDataElement failed"); } } } static private void CompressIntoJPEG(string rawdicom, string jpegdicom) { using( var sfcts = FileChangeTransferSyntax.New() ) { // Need to retrieve the actual C++ reference, to pass to // SimpleSubjectWatcher: FileChangeTransferSyntax fcts = sfcts.__ref__(); SimpleSubjectWatcher watcher = new SimpleSubjectWatcher(fcts, "FileChangeTransferSyntax"); gdcm.TransferSyntax ts = new TransferSyntax( TransferSyntax.TSType.JPEGBaselineProcess1 ); fcts.SetTransferSyntax( ts ); ImageCodec ic = fcts.GetCodec(); JPEGCodec jpeg = JPEGCodec.Cast( ic ); jpeg.SetLossless( false ); jpeg.SetQuality( 50 ); // poor quality ! fcts.SetInputFileName( rawdicom ); fcts.SetOutputFileName( jpegdicom ); fcts.Change(); } } public static int Main(string[] args) { string filename = args[0]; string outfilename = args[1]; string rawfilename = args[2]; string mergefn = args[3]; string jpegfn = args[4]; CreateSmallDICOM(filename); CreateBigDICOM(filename, outfilename); CreateDummyFile(rawfilename, 512 * 512 * 1000 ); AssembleDICOMAndRaw(outfilename, rawfilename, mergefn); CompressIntoJPEG(mergefn, jpegfn); return 0; } } GDCM-3.0.10/Examples/Csharp/FileStreaming.cs000066400000000000000000000036551412732066400204010ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Simple C# example * * Usage: * $ mono bin/FileStreaming.exe gdcmData/CT_16b_signed-UsedBits13.dcm output.dcm * * The class will take care of group handling and will use the first available group: * (0009,0012) ?? (LO) [MYTEST] # 6,1 Private Creator */ using System; using gdcm; public class FileStreaming { public static int Main(string[] args) { string filename = args[0]; string outfilename = args[1]; gdcm.PrivateTag pt = new gdcm.PrivateTag( new gdcm.Tag(0x9,0x10), "MYTEST" ); gdcm.FileStreamer fs = new gdcm.FileStreamer(); fs.SetTemplateFileName( filename ); fs.SetOutputFileName( outfilename ); byte[] buffer = new byte[ 8192 ]; uint len = (uint)buffer.Length; // In this example, we want that each newly created Private Attribute // contains at most 1000 bytes of incoming dataset. // We are also calling the function twice to check that appending mode is // working from one call to the other. The last element will have a length // of (2 * 8192) % 1000 = 384 if( !fs.StartGroupDataElement( pt, 1000, 1 ) || !fs.AppendToGroupDataElement( pt, buffer, len ) || !fs.AppendToGroupDataElement( pt, buffer, len ) || !fs.StopGroupDataElement( pt ) ) { System.Console.WriteLine( "Could not change private group" ); return 1; } return 0; } } GDCM-3.0.10/Examples/Csharp/GenerateDICOMDIR.cs000066400000000000000000000033001412732066400205000ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Simple C# example to show how to use DICOMDIRGenerator * * Usage: * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono bin/GenerateDICOMDIR.exe path output_filename */ using System; using gdcm; public class GenerateDICOMDIR { public static int Main(string[] args) { string directory = args[0]; string outfilename = args[1]; Directory d = new Directory(); uint nfiles = d.Load( directory, true ); if(nfiles == 0) return 1; //System.Console.WriteLine( "Files:\n" + d.toString() ); // Implement fast path ? // Scanner s = new Scanner(); string descriptor = "My_Descriptor"; FilenamesType filenames = d.GetFilenames(); gdcm.DICOMDIRGenerator gen = new DICOMDIRGenerator(); gen.SetFilenames( filenames ); gen.SetDescriptor( descriptor ); if( !gen.Generate() ) { return 1; } gdcm.FileMetaInformation.SetSourceApplicationEntityTitle( "GenerateDICOMDIR" ); gdcm.Writer writer = new Writer(); writer.SetFile( gen.GetFile() ); writer.SetFileName( outfilename ); if( !writer.Write() ) { return 1; } return 0; } } GDCM-3.0.10/Examples/Csharp/GetArray.cs000066400000000000000000000051611412732066400173600ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Usage: * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono bin/GetArray.exe gdcmData/012345.002.050.dcm */ using System; using gdcm; public class GetArray { public static int Main(string[] args) { string file1 = args[0]; ImageReader reader = new ImageReader(); reader.SetFileName( file1 ); bool ret = reader.Read(); if( !ret ) { return 1; } Image image = reader.GetImage(); PixelFormat pixeltype = image.GetPixelFormat(); if( image.GetNumberOfDimensions() != 2 ) { // For the purpose of the test, exit early on return 1; } uint dimx = image.GetDimension(0); uint dimy = image.GetDimension(1); uint npixels = dimx * dimy; //LookupTable lut = image.GetLUT(); //uint rl = lut.GetLUTLength( LookupTable.LookupTableType.RED ); //byte[] rbuf = new byte[ rl ]; //uint rl2 = lut.GetLUT( LookupTable.LookupTableType.RED, rbuf ); //assert rl == rl2; //byte[] str1 = new byte[ image.GetBufferLength()]; //image.GetBuffer( str1 ); if( pixeltype.GetScalarType() == PixelFormat.ScalarType.UINT8 ) { System.Console.WriteLine( "Processing UINT8 image type" ); byte[] str1 = new byte[ npixels ]; image.GetArray( str1 ); } else if( pixeltype.GetScalarType() == PixelFormat.ScalarType.INT16 ) { System.Console.WriteLine( "Processing INT16 image type" ); short[] str1 = new short[ npixels ]; image.GetArray( str1 ); } else if( pixeltype.GetScalarType() == PixelFormat.ScalarType.UINT16 ) { System.Console.WriteLine( "Processing UINT16 image type" ); ushort[] str1 = new ushort[ npixels ]; image.GetArray( str1 ); } else { //System.Console.WriteLine( "Default (unhandled pixel format): " + pixeltype.toString() ); System.Console.WriteLine( "Default (unhandled pixel format): " + pixeltype.GetScalarTypeAsString() ); // Get bytes byte[] str1 = new byte[ image.GetBufferLength()]; image.GetBuffer( str1 ); } return 0; } } GDCM-3.0.10/Examples/Csharp/ManipulateFile.cs000066400000000000000000000032541412732066400205420ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Usage: * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono bin/ManipulateFile.exe gdcmData/012345.002.050.dcm out.dcm */ using System; using gdcm; public class ManipulateFile { public static int Main(string[] args) { string file1 = args[0]; string file2 = args[1]; Reader reader = new Reader(); reader.SetFileName( file1 ); bool ret = reader.Read(); if( !ret ) { return 1; } Anonymizer ano = new Anonymizer(); ano.SetFile( reader.GetFile() ); ano.RemovePrivateTags(); ano.RemoveGroupLength(); Tag t = new Tag(0x10,0x10); ano.Replace( t, "GDCM^Csharp^Test^Hello^World" ); UIDGenerator g = new UIDGenerator(); ano.Replace( new Tag(0x0008,0x0018), g.Generate() ); ano.Replace( new Tag(0x0020,0x000d), g.Generate() ); ano.Replace( new Tag(0x0020,0x000e), g.Generate() ); ano.Replace( new Tag(0x0020,0x0052), g.Generate() ); Writer writer = new Writer(); writer.SetFileName( file2 ); writer.SetFile( ano.GetFile() ); ret = writer.Write(); if( !ret ) { return 1; } return 0; } } GDCM-3.0.10/Examples/Csharp/MpegVideoInfo.cs000066400000000000000000000326201412732066400203350ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This examples takes in a MPEG2 and write out a Video Endoscopic Imagae Storage * encoded using MPEG2 @ Main Profile * ref: http://chrisa.wordpress.com/2007/11/21/decoding-mpeg2-information/ * See also: * http://dvd.sourceforge.net/dvdinfo/mpeghdrs.html#gop * http://cvs.linux.hr/cgi-bin/viewcvs.cgi/mpeg_mod/README.infompeg?view=markup * http://www.guru-group.fi/~too/sw/m2vmp2cut/mpeg2info.c */ /* * Provides information about an MPEG2 file, including the duration, frame rate, aspect * ratio, and resolution. Good information about the MPEG2 file structure that helps * explain parts of the code can be found here: * http://dvd.sourceforge.net/dvdinfo/mpeghdrs.html#gop * * Copyright (c) 2007 Chris Anderson (chrisa@wordpress.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ using System; using System.IO; using gdcm; public class Mpeg2VideoInfo { #region Member Variables private TimeSpan m_startTime = TimeSpan.Zero; private TimeSpan m_endTime = TimeSpan.Zero; private TimeSpan m_duration = TimeSpan.Zero; private eAspectRatios m_aspectRatio = eAspectRatios.Invalid; private eFrameRates m_frameRate = 0; private int m_pictureWidth = 0; private int m_pictureHeight = 0; #endregion #region Constants private const byte PADDING_PACKET = 0xBE; private const byte VIDEO_PACKET = 0xE0; private const byte AUDIO_PACKET = 0xC0; private const byte SYSTEM_PACKET = 0xBB; private const byte TIMESTAMP_PACKET = 0xB8; private const byte HEADER_PACKET = 0xB3; private const int BUFFER_SIZE = 8162; // 8K buffer private readonly static TimeSpan EMPTY_TIMESPAN = new TimeSpan(0, 0, -1); #endregion #region Enumerations public enum eFrameRates { Invalid, PulldownNTSC, // 24000d/1001d = 23.976 Hz Film, // 24 Hz PAL, // 25 Hz NTSC, // 30000d/1001d = 29.97 Hz DropFrameNTSC, // 30 Hz DoubleRatePAL, // 50 Hz DoubleRateNTSC, // 59.97 Hz DoubleRateDropFrameNTSC // 60 Hz } public enum eAspectRatios { Invalid, VGA, // 1/1 StandardTV, // 4/3 LargeTV, // 16/9 Cinema // 2.21/1 } #endregion #region Constructor public Mpeg2VideoInfo(string file) { ParseMpeg(file); } #endregion #region Public Properties public TimeSpan StartTime { get { return m_startTime; } } public TimeSpan EndTime { get { return m_endTime; } } public TimeSpan Duration { get { return m_duration; } } public eAspectRatios AspectRatio { get { return m_aspectRatio; } } public eFrameRates FrameRate { get { return m_frameRate; } } public int PictureWidth { get { return m_pictureWidth; } } public int PictureHeight { get { return m_pictureHeight; } } #endregion #region Private Functions /// /// Handles the parsing of the MPEG file and retrieving MPEG data /// /// The path to the MPEG file to parse private void ParseMpeg(string file) { FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); BinaryReader br = new BinaryReader(fs); m_startTime = GetStartTimeStampInfo(br); m_endTime = GetEndTimeStampInfo(br); m_duration = m_endTime.Subtract(m_startTime); GetHeaderInfo(br); br.Close(); fs.Close(); } /// /// Looks for the first timestamp in the file and returns the value /// (generally 0:00:00, but get it anyway) /// /// The binary reader providing random access to the MPEG file data /// The timestamp value private TimeSpan GetStartTimeStampInfo(BinaryReader br) { TimeSpan startTime = EMPTY_TIMESPAN; byte[] buffer = new byte[BUFFER_SIZE]; br.BaseStream.Seek(0, SeekOrigin.Begin); while (startTime == EMPTY_TIMESPAN && br.BaseStream.Position < br.BaseStream.Length) { int readBytes = br.Read(buffer, 0, BUFFER_SIZE); for (int offset = 0; offset < readBytes - 8; offset++) { if (IsStreamMarker(ref buffer, offset, TIMESTAMP_PACKET)) { offset += 4; // Move to the data position which follows the stream header uint timeStampEncoded = GetData(ref buffer, offset); startTime = DecodeTimeStamp(timeStampEncoded); if (startTime != EMPTY_TIMESPAN) break; } } } return startTime; } /// /// Looks for the first timestamp in the file and returns the value /// (generally 0:00:00, but get it anyway) /// /// The binary reader providing random access to the MPEG file data /// The timestamp value private TimeSpan GetEndTimeStampInfo(BinaryReader br) { TimeSpan endTime = EMPTY_TIMESPAN; byte[] buffer = new byte[BUFFER_SIZE]; br.BaseStream.Seek(-BUFFER_SIZE, SeekOrigin.End); while (endTime == EMPTY_TIMESPAN && br.BaseStream.Position > BUFFER_SIZE) { int readBytes = br.Read(buffer, 0, BUFFER_SIZE); for (int offset = readBytes - 8; offset >= 0; offset--) { if (IsStreamMarker(ref buffer, offset, TIMESTAMP_PACKET)) { offset += 4; // Move to the data position which follows the stream header uint timeStampEncoded = GetData(ref buffer, offset); endTime = DecodeTimeStamp(timeStampEncoded); if (endTime != EMPTY_TIMESPAN) break; } } br.BaseStream.Seek(-BUFFER_SIZE * 2, SeekOrigin.Current); } return endTime; } /// /// Decodes the timestamp data as encoded in the MPEG file and returns the value /// /// The encoded timestamp data /// The decoded timestamp data private TimeSpan DecodeTimeStamp(uint timeStampEncoded) { TimeSpan timeStamp = EMPTY_TIMESPAN; // Mask out the bits containing the property we are after, then // shift the data to the right to get its value int hour = (int)(timeStampEncoded & 0x7C000000) >> 26; // Bits 31 -> 27 int minute = (int)(timeStampEncoded & 0x03F00000) >> 20; // Bits 26 -> 21 int second = (int)(timeStampEncoded & 0x0007E000) >> 13; // Bits 19 -> 14 int frame = (int)(timeStampEncoded & 0x00001F80) >> 7; // Bits 13 -> 8 - not used, but included for completeness timeStamp = new TimeSpan(hour, minute, second); return timeStamp; } /// /// Obtains the header data located in the MPEG file and decodes it /// /// The binary reader providing random access to the MPEG file data private void GetHeaderInfo(BinaryReader br) { byte[] buffer = new byte[BUFFER_SIZE]; br.BaseStream.Seek(0, SeekOrigin.Begin); br.Read(buffer, 0, BUFFER_SIZE); for (int offset = 0; offset < buffer.Length - 4; offset++) { if (IsStreamMarker(ref buffer, offset, HEADER_PACKET)) { offset += 4; // Move to the data position which follows the stream header uint headerData = GetData(ref buffer, offset); // Mask out the bits containing the property we are after, then // shift the data to the right to get its value m_pictureWidth = (int)(headerData & 0xFFF00000) >> 20; m_pictureHeight = (int)(headerData & 0x000FFF00) >> 8; uint aspectRatioIndex = (headerData & 0x000000F0) >> 4; uint fpsIndex = headerData & 0x0000000F; m_aspectRatio = (eAspectRatios)fpsIndex; m_frameRate = (eFrameRates)fpsIndex; break; } } } /// /// Combine 4 bytes of data into an integer /// /// The buffer containing the data /// The position within the buffer to get the required 4 bytes of data /// An integer containing the combined 4 bytes of data private uint GetData(ref byte[] buffer, int offset) { return (uint) ((buffer[offset] << 24) | (buffer[offset + 1] << 16) | (buffer[offset + 2] << 8) | (buffer[offset + 3])); } /// /// The MPEG file contains numerous stream markers representing the type of /// data to follow. This function looks at data at a position in the buffer to /// determine whether it represents a marker of a specified type /// /// The buffer containing the data to identify the marker within /// The position within the buffer to test for the marker /// The type of marker to match against /// Whether the specified position contains the specified marker private bool IsStreamMarker(ref byte[] buffer, int offset, byte markerType) { return (buffer[offset] == 0x00 && buffer[offset + 1] == 0x00 && buffer[offset + 2] == 0x01 && buffer[offset + 3] == markerType); } #endregion public static int Main(string[] args) { string file1 = args[0]; Mpeg2VideoInfo info = new Mpeg2VideoInfo(file1); System.Console.WriteLine( info.StartTime ); System.Console.WriteLine( info.EndTime ); System.Console.WriteLine( info.Duration ); System.Console.WriteLine( info.AspectRatio ); System.Console.WriteLine( info.FrameRate ); System.Console.WriteLine( info.PictureWidth ); System.Console.WriteLine( info.PictureHeight ); ImageReader r = new ImageReader(); //Image image = new Image(); Image image = r.GetImage(); image.SetNumberOfDimensions( 3 ); DataElement pixeldata = new DataElement( new gdcm.Tag(0x7fe0,0x0010) ); System.IO.FileStream infile = new System.IO.FileStream(file1, System.IO.FileMode.Open, System.IO.FileAccess.Read); uint fsize = gdcm.PosixEmulation.FileSize(file1); byte[] jstream = new byte[fsize]; infile.Read(jstream, 0 , jstream.Length); SmartPtrFrag sq = SequenceOfFragments.New(); Fragment frag = new Fragment(); frag.SetByteValue( jstream, new gdcm.VL( (uint)jstream.Length) ); sq.AddFragment( frag ); pixeldata.SetValue( sq.__ref__() ); // insert: image.SetDataElement( pixeldata ); PhotometricInterpretation pi = new PhotometricInterpretation( PhotometricInterpretation.PIType.YBR_PARTIAL_420 ); image.SetPhotometricInterpretation( pi ); // FIXME hardcoded: PixelFormat pixeltype = new PixelFormat(3,8,8,7); image.SetPixelFormat( pixeltype ); // FIXME hardcoded: TransferSyntax ts = new TransferSyntax( TransferSyntax.TSType.MPEG2MainProfile); image.SetTransferSyntax( ts ); image.SetDimension(0, (uint)info.PictureWidth); image.SetDimension(1, (uint)info.PictureHeight); image.SetDimension(2, 721); ImageWriter writer = new ImageWriter(); gdcm.File file = writer.GetFile(); file.GetHeader().SetDataSetTransferSyntax( ts ); Anonymizer anon = new Anonymizer(); anon.SetFile( file ); MediaStorage ms = new MediaStorage( MediaStorage.MSType.VideoEndoscopicImageStorage); UIDGenerator gen = new UIDGenerator(); anon.Replace( new Tag(0x0008,0x16), ms.GetString() ); anon.Replace( new Tag(0x0018,0x40), "25" ); anon.Replace( new Tag(0x0018,0x1063), "40.000000" ); anon.Replace( new Tag(0x0028,0x34), "4\\3" ); anon.Replace( new Tag(0x0028,0x2110), "01" ); writer.SetImage( image ); writer.SetFileName( "dummy.dcm" ); if( !writer.Write() ) { System.Console.WriteLine( "Could not write" ); return 1; } return 0; } } GDCM-3.0.10/Examples/Csharp/NewSequence.cs000066400000000000000000000043711412732066400200660ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Usage: * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono bin/NewSequence.exe gdcmData/012345.002.050.dcm out.dcm */ using System; //using gdcm; public class NewSequence { public static byte[] StrToByteArray(string str) { System.Text.ASCIIEncoding encoding=new System.Text.ASCIIEncoding(); return encoding.GetBytes(str); } public static int Main(string[] argv) { string file1 = argv[0]; string file2 = argv[1]; gdcm.Reader r = new gdcm.Reader(); r.SetFileName( file1 ); if ( ! r.Read() ) { return 1; } gdcm.File f = r.GetFile(); gdcm.DataSet ds = f.GetDataSet(); // tsis = gdcm.Tag(0x0008,0x2112) # SourceImageSequence // Create a dataelement gdcm.DataElement de = new gdcm.DataElement(new gdcm.Tag(0x0010, 0x2180)); string occ = "Occupation"; de.SetByteValue( StrToByteArray(occ), new gdcm.VL((uint)occ.Length)); de.SetVR(new gdcm.VR(gdcm.VR.VRType.SH)); // Create an item gdcm.Item it = new gdcm.Item(); it.SetVLToUndefined(); // Needed to not popup error message //it.InsertDataElement(de) gdcm.DataSet nds = it.GetNestedDataSet(); nds.Insert(de); // Create a Sequence gdcm.SmartPtrSQ sq = gdcm.SequenceOfItems.New(); sq.SetLengthToUndefined(); sq.AddItem(it); // Insert sequence into data set gdcm.DataElement des = new gdcm.DataElement(new gdcm.Tag(0x0400,0x0550)); des.SetVR(new gdcm.VR(gdcm.VR.VRType.SQ)); des.SetValue(sq.__ref__()); des.SetVLToUndefined(); ds.Insert(des); gdcm.Writer w = new gdcm.Writer(); w.SetFile( f ); w.SetFileName( file2 ); if ( !w.Write() ) return 1; return 0; } } GDCM-3.0.10/Examples/Csharp/ReformatFile.cs000066400000000000000000000056761412732066400202340ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Simple C# example * * Usage: * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono bin/ReformatFile.exe input.dcm output.dcm */ using System; using gdcm; public class ReformatFile { public static int Main(string[] args) { gdcm.FileMetaInformation.SetSourceApplicationEntityTitle( "My Reformat App" ); // http://www.oid-info.com/get/1.3.6.1.4.17434 string THERALYS_ORG_ROOT = "1.3.6.1.4.17434"; gdcm.UIDGenerator.SetRoot( THERALYS_ORG_ROOT ); System.Console.WriteLine( "Root dir is now: " + gdcm.UIDGenerator.GetRoot() ); string filename = args[0]; string outfilename = args[1]; Reader reader = new Reader(); reader.SetFileName( filename ); if( !reader.Read() ) { System.Console.WriteLine( "Could not read: " + filename ); return 1; } UIDGenerator uid = new UIDGenerator(); // helper for uid generation FileDerivation fd = new FileDerivation(); // For the pupose of this execise we will pretend that this image is referencing // two source image (we need to generate fake UID for that). string ReferencedSOPClassUID = "1.2.840.10008.5.1.4.1.1.7"; // Secondary Capture fd.AddReference( ReferencedSOPClassUID, uid.Generate() ); fd.AddReference( ReferencedSOPClassUID, uid.Generate() ); // Again for the purpose of the exercise we will pretend that the image is a // multiplanar reformat (MPR): // CID 7202 Source Image Purposes of Reference // {"DCM",121322,"Source image for image processing operation"}, fd.SetPurposeOfReferenceCodeSequenceCodeValue( 121322 ); // CID 7203 Image Derivation // { "DCM",113072,"Multiplanar reformatting" }, fd.SetDerivationCodeSequenceCodeValue( 113072 ); fd.SetFile( reader.GetFile() ); // If all Code Value are ok the filter will execute properly if( !fd.Derive() ) { return 1; } gdcm.FileMetaInformation fmi = reader.GetFile().GetHeader(); // The following three lines make sure to regenerate any value: fmi.Remove( new gdcm.Tag(0x0002,0x0012) ); fmi.Remove( new gdcm.Tag(0x0002,0x0013) ); fmi.Remove( new gdcm.Tag(0x0002,0x0016) ); Writer writer = new Writer(); writer.SetFileName( outfilename ); writer.SetFile( fd.GetFile() ); if( !writer.Write() ) { System.Console.WriteLine( "Could not write: " + outfilename ); return 1; } return 0; } } GDCM-3.0.10/Examples/Csharp/RescaleImage.cs000066400000000000000000000036061412732066400201650ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Usage: * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono bin/DecompressImage.exe gdcmData/012345.002.050.dcm rescaled.dcm */ using System; using gdcm; public class DecompressImage { public static int Main(string[] args) { string file1 = args[0]; ImageReader reader = new ImageReader(); reader.SetFileName( file1 ); bool ret = reader.Read(); if( !ret ) { return 1; } Image image = reader.GetImage(); PixelFormat pixeltype = image.GetPixelFormat(); Rescaler r = new Rescaler(); r.SetIntercept( 0 ); r.SetSlope( 1.2 ); r.SetPixelFormat( pixeltype ); PixelFormat outputpt = new PixelFormat( r.ComputeInterceptSlopePixelType() ); System.Console.WriteLine( "pixeltype" ); System.Console.WriteLine( pixeltype.toString() ); System.Console.WriteLine( "outputpt" ); System.Console.WriteLine( outputpt.toString() ); uint len = image.GetBufferLength(); short[] input = new short[ len / 2 ]; // sizeof(short) == 2 image.GetArray( input ); double[] output = new double[ len / 2 ]; r.Rescale( output, input, len ); // First Pixel is: System.Console.WriteLine( "Input:" ); System.Console.WriteLine( input[0] ); System.Console.WriteLine( "Output:" ); System.Console.WriteLine( output[0] ); return 0; } } GDCM-3.0.10/Examples/Csharp/ScanDirectory.cs000066400000000000000000000042321412732066400204110ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Usage: * $ bin/ScanDirectory.exe /path/to/gdcmData/ */ using System; using gdcm; // We will print each filename being processed public class MyWatcher : SimpleSubjectWatcher { public MyWatcher(Subject s):base(s,"Override String"){} protected override void ShowFileName(Subject caller, Event evt){ FileNameEvent fne = FileNameEvent.Cast(evt); if( fne != null ) { string fn = fne.GetFileName(); System.Console.WriteLine( "This is my Scanner. Processing FileName: " + fn ); } else { System.Console.WriteLine( "This is my Anonymization. Unhandled Event type: " + evt.GetEventName() ); } } } public class ScanDirectory { public static int Main(string[] args) { string directory = args[0]; Tag t = new Tag(0x8,0x80); Directory d = new Directory(); uint nfiles = d.Load( directory ); if(nfiles == 0) return 1; //System.Console.WriteLine( "Files:\n" + d.toString() ); // Use a StrictScanner, need to use a reference to pass the C++ pointer to // MyWatcher implementation SmartPtrStrictScan sscan = StrictScanner.New(); StrictScanner s = sscan.__ref__(); MyWatcher watcher = new MyWatcher(s); s.AddTag( t ); bool b = s.Scan( d.GetFilenames() ); if(!b) return 1; for(int i = 0; i < (int)nfiles; ++i) { if( !s.IsKey( d.GetFilenames()[i] ) ) { System.Console.WriteLine( "File is not DICOM or could not be read: " + d.GetFilenames()[i] ); } } System.Console.WriteLine( "Scan:\n" + s.toString() ); System.Console.WriteLine( "success" ); return 0; } } GDCM-3.0.10/Examples/Csharp/SendFileSCU.cs000066400000000000000000000022111412732066400176770ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Usage: * $ export LD_LIBRARY_PATH=$HOME/Perso/gdcm-gcc/bin * $ mono bin/SendFileSCU.exe server port input.dcm */ using System; using gdcm; public class SendFileSCU { public static int Main(string[] args) { string server = args[0]; ushort port = ushort.Parse(args[1]); string filename = args[2]; bool b = CompositeNetworkFunctions.CEcho( server, port ); if( !b ) return 1; FilenamesType files = new FilenamesType(); files.Add( filename ); b = CompositeNetworkFunctions.CStore( server, port, files ); if( !b ) return 1; return 0; } } GDCM-3.0.10/Examples/Csharp/SimplePrint.cs000066400000000000000000000045171412732066400201140ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* Convertor convertor = new Convertor(); int a = convertor.Convert( some_int_blob ); double b = convertor.Convert( some_double_blob ); */ /* * Usage: * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono bin/SimplePrint.exe gdcmData/012345.002.050.dcm */ using System; using gdcm; public class SimplePrint { public static void RecurseDataSet(File f, DataSet ds, string indent) { CSharpDataSet cds = new CSharpDataSet(ds); while(!cds.IsAtEnd()) { DataElement de = cds.GetCurrent(); // Compute VR from the toplevel file, and the currently processed dataset: VR vr = DataSetHelper.ComputeVR(f, ds, de.GetTag() ); if( vr.Compatible( new VR(VR.VRType.SQ) ) ) { uint uvl = (uint)de.GetVL(); // Test cast is ok System.Console.WriteLine( indent + de.GetTag().toString() + ":" + uvl ); // why not ? //SequenceOfItems sq = de.GetSequenceOfItems(); // GetValueAsSQ handle more cases than GetSequenceOfItems SmartPtrSQ sq = de.GetValueAsSQ(); uint n = sq.GetNumberOfItems(); for( uint i = 1; i <= n; i++) // item starts at 1, not 0 { Item item = sq.GetItem( i ); DataSet nested = item.GetNestedDataSet(); RecurseDataSet( f, nested, indent + " " ); } } else { System.Console.WriteLine( indent + de.toString() ); } cds.Next(); } } public static int Main(string[] args) { string filename = args[0]; Reader reader = new Reader(); reader.SetFileName( filename ); bool ret = reader.Read(); if( !ret ) { return 1; } File f = reader.GetFile(); DataSet ds = f.GetDataSet(); RecurseDataSet( f, ds, "" ); return 0; } } GDCM-3.0.10/Examples/Csharp/SimplePrintPatientName.cs000066400000000000000000000033431412732066400222360ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Usage: * $ export LD_LIBRARY_PATH=$HOME/Perso/gdcm/debug-gcc/bin * $ mono bin/SimplePrintPatientName.exe gdcmData/012345.002.050.dcm */ /* This example was provided by Jonathan Morra /jonmorra gmail com/ on the gdcm mailing list (Fri, 28 May 2010) */ using System; using gdcm; namespace GDCMTest { class SimplePrintPatientName { static int Main(string[] args) { if (args.Length != 1) { Console.WriteLine("This program prints the patient name of a dicom file with gdcm"); Console.WriteLine("Usage: [input.dcm]"); return 1; } gdcm.Reader reader = new gdcm.Reader(); reader.SetFileName(args[0]); bool ret = reader.Read(); //TagSetType tst = new TagSetType(); //tst.Add( new Tag(0x7fe0,0x10) ); //bool ret = reader.ReadUpToTag( new Tag(0x88,0x200), tst ); if( !ret ) { return 1; } gdcm.File file = reader.GetFile(); gdcm.StringFilter filter = new gdcm.StringFilter(); filter.SetFile(file); string value = filter.ToString(new gdcm.Tag(0x0010, 0x0010)); Console.WriteLine("Patient Name: " + value); return 0; } } } GDCM-3.0.10/Examples/Csharp/SortImage2.cs000066400000000000000000000017151412732066400176170ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Usage: * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono bin/SortImage.exe gdcmData/012345.002.050.dcm out.dcm */ using System; using gdcm; public class SortImage2 { bool mysort(DataSet ds1, DataSet ds2) { return false; } public static int Main(string[] args) { Sorter sorter = new Sorter(); sorter.SetSortFunction( mysort ); return 0; } } GDCM-3.0.10/Examples/Csharp/StandardizeFiles.cs000066400000000000000000000072651412732066400211040ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Simple C# example to show how one would 'Standardize' a DICOM File-Set * * Usage: * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono bin/StandardizeFiles.exe input_path output_path */ using System; using gdcm; public class StandardizeFiles { public static bool ProcessOneFile( string filename, string outfilename ) { PixmapReader reader = new PixmapReader(); reader.SetFileName( filename ); if( !reader.Read() ) { System.Console.WriteLine( "Could not read: " + filename ); return false; } ImageChangeTransferSyntax change = new ImageChangeTransferSyntax(); change.SetForce( false ); // do we really want to recompress when input is alread compressed in same alg ? change.SetCompressIconImage( false ); // Keep it simple change.SetTransferSyntax( new TransferSyntax( TransferSyntax.TSType.JPEG2000Lossless ) ); change.SetInput( reader.GetPixmap() ); if( !change.Change() ) { System.Console.WriteLine( "Could not change: " + filename ); return false; } gdcm.FileMetaInformation fmi = reader.GetFile().GetHeader(); // The following three lines make sure to regenerate any value: fmi.Remove( new gdcm.Tag(0x0002,0x0012) ); fmi.Remove( new gdcm.Tag(0x0002,0x0013) ); fmi.Remove( new gdcm.Tag(0x0002,0x0016) ); PixmapWriter writer = new PixmapWriter(); writer.SetFileName( outfilename ); writer.SetFile( reader.GetFile() ); gdcm.Pixmap pixout = ((PixmapToPixmapFilter)change).GetOutput(); writer.SetPixmap( pixout ); if( !writer.Write() ) { System.Console.WriteLine( "Could not write: " + outfilename ); return false; } return true; } public static int Main(string[] args) { gdcm.FileMetaInformation.SetSourceApplicationEntityTitle( "My Standardize App" ); // http://www.oid-info.com/get/1.3.6.1.4.17434 string THERALYS_ORG_ROOT = "1.3.6.1.4.17434"; gdcm.UIDGenerator.SetRoot( THERALYS_ORG_ROOT ); System.Console.WriteLine( "Root dir is now: " + gdcm.UIDGenerator.GetRoot() ); string dir1 = args[0]; string dir2 = args[1]; // Check input is valid: if( !gdcm.PosixEmulation.FileIsDirectory(dir1) ) { System.Console.WriteLine( "Input directory: " + dir1 + " does not exist. Sorry" ); return 1; } if( !gdcm.PosixEmulation.FileIsDirectory(dir2) ) { System.Console.WriteLine( "Output directory: " + dir2 + " does not exist. Sorry" ); return 1; } Directory d = new Directory(); uint nfiles = d.Load( dir1, true ); if(nfiles == 0) return 1; // Process all filenames: FilenamesType filenames = d.GetFilenames(); for( uint i = 0; i < nfiles; ++i ) { string filename = filenames[ (int)i ]; string outfilename = filename.Replace( dir1, dir2 ); System.Console.WriteLine( "Filename: " + filename ); System.Console.WriteLine( "Out Filename: " + outfilename ); if( !ProcessOneFile( filename, outfilename ) ) { System.Console.WriteLine( "Could not process filename: " + filename ); //return 1; } } return 0; } } GDCM-3.0.10/Examples/Cxx/000077500000000000000000000000001412732066400146325ustar00rootroot00000000000000GDCM-3.0.10/Examples/Cxx/CMakeLists.txt000066400000000000000000000130221412732066400173700ustar00rootroot00000000000000# Build the GDCM examples # Add the include paths include_directories( "${GDCM_BINARY_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition" "${GDCM_SOURCE_DIR}/Source/MediaStorageAndFileFormat" "${GDCM_SOURCE_DIR}/Source/InformationObjectDefinition" "${GDCM_SOURCE_DIR}/Source/MessageExchangeDefinition" # FIXME: "${GDCM_SOURCE_DIR}/Source/DataDictionary" "${GDCM_SOURCE_DIR}/Utilities" ) # error C1083: Cannot open include file: 'zconf.h' if(NOT GDCM_USE_SYSTEM_ZLIB) include_directories( "${GDCM_BINARY_DIR}/Utilities/gdcmzlib" ) endif() if(GDCM_BINARY_DIR) find_package(SQLITE3) find_package(MAGIC) find_package(Qt4 4.4.3 COMPONENTS QtCore QtGui) # cmake 2.6.4 does not set it to advanced mark_as_advanced(QT_QMAKE_EXECUTABLE) endif() set(EXAMPLES_SRCS PrintLUT EmptyMask DumpSiemensBase64 DumpVisusChange TemplateEmptyImage MakeTemplate DeriveSeries FixOrientation DumpGEMSMovieGroup QIDO-RS DumpExamCard DumpPhilipsECHO ExtractIconFromFile CreateJPIPDataSet DumpADAC DumpToshibaDTI DumpToshibaDTI2 DumpImageHeaderInfo ReadMultiTimesException pmsct_rgb1 GenAllVR ELSCINT1WaveToText DiscriminateVolume GetSubSequenceData GenLongSeqs ReadGEMSSDO DiffFile SimpleScanner TraverseModules GetSequenceUltrasound ReadAndPrintAttributes ChangeSequenceUltrasound ChangePrivateTags LargeVRDSExplicit ExtractEncryptedContent ReadAndDumpDICOMDIR #ReadAndDumpDICOMDIR2 # commented out since requires C++11 GenerateStandardSOPClasses ClinicalTrialAnnotate CheckBigEndianBug DuplicatePCDE CreateARGBImage CreateCMYKImage CompressImage FixBrokenJ2K GenFakeImage GenFakeIdentifyFile HelloVizWorld HelloWorld MergeTwoFiles MrProtocol PatchFile ReadExplicitLengthSQIVR SortImage csa2img iU22tomultisc rle2img uid_unique PublicDict GenSeqs GetJPEGSamplePrecision ) #set(EXAMPLES_SRCS # ${EXAMPLES_SRCS} # StreamImageReaderTest # Extracting_All_Resolution # Fake_Image_Using_Stream_Image_Writer # ) if(GDCM_USE_JPEGLS) set(EXAMPLES_SRCS ${EXAMPLES_SRCS} FixJAIBugJPEGLS ) endif() if(QT4_FOUND) include(${QT_USE_FILE}) add_executable(ConvertToQImage ConvertToQImage.cxx) # qtGUI will resolved QImage symbol # qtcore will resolve qstring symbols target_link_libraries(ConvertToQImage gdcmMSFF ${QT_LIBRARIES}) add_executable(ReadUTF8QtDir ReadUTF8QtDir.cxx) target_link_libraries(ReadUTF8QtDir gdcmMSFF ${QT_LIBRARIES}) add_executable(CStoreQtProgress CStoreQtProgress.cxx) target_link_libraries(CStoreQtProgress gdcmMEXD gdcmMSFF ${QT_LIBRARIES}) endif() if(MAGIC_FOUND) include_directories(${MAGIC_INCLUDE_DIRS}) add_executable(EncapsulateFileInRawData EncapsulateFileInRawData.cxx) target_link_libraries(EncapsulateFileInRawData gdcmMSFF ${MAGIC_LIBRARIES}) endif() if(SQLITE3_FOUND) include_directories(${SQLITE3_INCLUDE_DIRS}) add_executable(DumpToSQLITE3 DumpToSQLITE3.cxx) target_link_libraries(DumpToSQLITE3 gdcmMSFF ${SQLITE3_LIBRARIES}) endif() if(GDCM_BUILD_TESTING) set(EXAMPLES_SRCS ${EXAMPLES_SRCS} VolumeSorter ) endif() if(BUILD_SHARED_LIBS) set_source_files_properties(FixJAIBugJPEGLS.cxx PROPERTIES COMPILE_FLAGS -DCHARLS_DLL ) endif() foreach(example ${EXAMPLES_SRCS}) add_executable(${example} ${example}.cxx) if(${example} STREQUAL "FixJAIBugJPEGLS") target_link_libraries(${example} gdcmMSFF ${GDCM_CHARLS_LIBRARIES}) elseif(${example} STREQUAL "DumpPhilipsECHO") target_link_libraries(${example} gdcmMSFF ${GDCM_ZLIB_LIBRARIES}) else() target_link_libraries(${example} gdcmMSFF) endif() endforeach() if(CMAKE_COMPILER_IS_GNUCXX AND MINGW) #../../bin/libgdcmDSED.dll.a(d000469.o)(.text+0x0): multiple definition of `gdcm::VL gdcm::Item::GetLength() const' #CMakeFiles/ReadExplicitLengthSQIVR.dir/ReadExplicitLengthSQIVR.obj(.text$_ZNK4gdcm4Item9GetLengthINS_19ImplicitDataElementEEENS_2VLEv[gdcm::VL gdcm::Item::GetLength() const]+0x0):ReadExplicitLengthSQIVR.cxx: first defined here #../../bin/libgdcmDSED.dll.a(d000252.o)(.text+0x0): multiple definition of `std::istream& gdcm::DataSet::ReadNested(std::istream&)' #CMakeFiles/ReadExplicitLengthSQIVR.dir/ReadExplicitLengthSQIVR.obj(.text$_ZN4gdcm7DataSet10ReadNestedINS_19ImplicitDataElementENS_11SwapperDoOpEEERSiS4_[std::basic_istream >& gdcm::DataSet::ReadNested(std::basic_istream >&)]+0x0):ReadExplicitLengthSQIVR.cxx: first defined here #../../bin/libgdcmDSED.dll.a(d000253.o)(.text+0x0): multiple definition of `std::istream& gdcm::DataSet::ReadNested(std::istream&)' #CMakeFiles/ReadExplicitLengthSQIVR.dir/ReadExplicitLengthSQIVR.obj(.text$_ZN4gdcm7DataSet10ReadNestedINS_19ImplicitDataElementENS_11SwapperNoOpEEERSiS4_[std::basic_istream >& gdcm::DataSet::ReadNested(std::basic_istream >&)]+0x0):ReadExplicitLengthSQIVR.cxx: first defined here #../../bin/libgdcmDSED.dll.a(d000271.o)(.text+0x0): multiple definition of `std::istream& gdcm::DataSet::ReadWithLength(std::istream&, gdcm::VL&)' set_target_properties( ReadExplicitLengthSQIVR PROPERTIES LINK_FLAGS "-Wl,--allow-multiple-definition") endif() GDCM-3.0.10/Examples/Cxx/CStoreQtProgress.cxx000066400000000000000000000117501412732066400206130ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This small example show how one can use the virtual function * mechanism of the SimpleSubjectWatcher class to redirect progress * report to a custom Qt classes * * http://doc.qt.nokia.com/latest/qprogressdialog.html * * Usage: * CStoreQtProgress dicom.example.com 11112 gdcmData/MR_Spectroscopy_SIEMENS_OF.dcm * */ #include "gdcmServiceClassUser.h" #include "gdcmSimpleSubjectWatcher.h" #include "gdcmProgressEvent.h" #include "gdcmDirectory.h" #include "gdcmPresentationContextGenerator.h" #include #include #include namespace gdcm { /* * This class is a little more complicated than what this example demonstrate * This watcher is capable of handling nested progress. Since the Progress * grows from [0 to 1] on a per file basis and we only have one instance of a * watcher per association, we need some calculation to compute the global * (total) progress * In fact we simply divide the per-file progress by the number of files. * * This QtWatcher class will then update the progress bar according to the * progress. */ class MyQtWatcher : public SimpleSubjectWatcher { size_t nfiles; double progress; size_t index; double refprogress; QWidget* win; QProgressDialog* qtprogress; public: MyQtWatcher(Subject * s, const char *comment = "", QWidget *w = NULL, QProgressDialog* p = NULL, size_t n = 1): SimpleSubjectWatcher(s,comment),nfiles(n),progress(0),index(0),refprogress(0),win(w),qtprogress(p){} void ShowIteration() { index++; assert( index <= nfiles ); // update refprogess (we are moving to the next file) refprogress = progress; } void ShowProgress(Subject *, const Event &evt) { // Retrieve the ProgressEvent: const ProgressEvent &pe = dynamic_cast(evt); // compute global progress: progress = refprogress + (1. / (double)nfiles ) * pe.GetProgress(); // Print Global and local progress to stdout: std::cout << "Global Progress: " << progress << " per file progress " << pe.GetProgress() << std::endl; //set progress value in the QtProgress bar int i = (int)(progress * 100 + 0.5); // round to next int qtprogress->setValue(i); win->show(); } virtual void ShowDataSet(Subject *caller, const Event &evt) { (void)caller; (void)evt; } }; } // end namespace gdcm int main(int argc, char *argv[]) { if( argc < 4 ) { std::cerr << argv[0] << " remote_server port filename" << std::endl; return 1; } QApplication a(argc, argv); std::ostringstream error_log; gdcm::Trace::SetErrorStream( error_log ); const char *remote = argv[1]; int portno = atoi(argv[2]); const char *filename = argv[3]; QVBoxLayout* layout = new QVBoxLayout; QWidget* win = new QWidget; QProgressDialog* progress = new QProgressDialog("Sending data...", "Cancel", 0, 100); progress->setWindowModality(Qt::WindowModal); layout->addWidget(progress,Qt::AlignCenter); win->setLayout(layout); gdcm::SmartPointer scup = new gdcm::ServiceClassUser; gdcm::ServiceClassUser &scu = *scup; //gdcm::SimpleSubjectWatcher w( &scu, "TestServiceClassUser" ); // let's use a more complicated progress reported in this example gdcm::MyQtWatcher w( &scu, "QtWatcher", win, progress ); scu.SetHostname( remote ); scu.SetPort( (uint16_t)portno ); scu.SetTimeout( 1000 ); scu.SetCalledAETitle( "GDCM_STORE" ); if( !scu.InitializeConnection() ) { std::cerr << "Could not InitializeConnection" << std::endl; return 1; } gdcm::Directory::FilenamesType filenames; filenames.push_back( filename ); // setup the PC(s) based on the filenames: gdcm::PresentationContextGenerator generator; if( !generator.GenerateFromFilenames(filenames) ) { std::cerr << "Could not GenerateFromFilenames" << std::endl; return 1; } // Setup PresentationContext(s) scu.SetPresentationContexts( generator.GetPresentationContexts() ); // Start ASSOCIATION if( !scu.StartAssociation() ) { std::cerr << "Could not Start" << std::endl; return 1; } // Send C-STORE if( !scu.SendStore( filename ) ) { std::cerr << "Could not Store" << std::endl; std::cerr << "Error log is:" << std::endl; std::cerr << error_log.str() << std::endl; return 1; } // Stop ASSOCIATION if( !scu.StopAssociation() ) { std::cerr << "Could not Stop" << std::endl; return 1; } win->show(); return a.exec(); } GDCM-3.0.10/Examples/Cxx/ChangePrivateTags.cxx000066400000000000000000000054261412732066400207240ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmPrivateTag.h" int main(int argc, char* argv[] ) { if( argc < 3 ) { std::cerr << argv[0] << " path/to/05148044-mr-siemens-avanto-syngo.dcm output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; gdcm::Reader reader; reader.SetFileName( filename ); if (! reader.Read() ) { return 1; } // (0029,0010) LO [SIEMENS CSA HEADER] # 18,1 Private Creator // (0029,0011) LO [SIEMENS MEDCOM HEADER ] # 22,1 Private Creator // (0029,0012) LO [SIEMENS MEDCOM HEADER2] # 22,1 Private Creator // [...] // (0029,1018) CS [MR] # 2,1 CSA Series Header Type // (0029,1134) CS [DB TO DICOM ] # 12,1 PMTF Information 4 // (0029,1260) LO [com ] # 4,1 Series Workflow Status gdcm::File &file = reader.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); // Declare private tag we need to find: gdcm::PrivateTag pt1( 0x29,0x18, "SIEMENS CSA HEADER" ); gdcm::PrivateTag pt2( 0x29,0x34, "SIEMENS MEDCOM HEADER" ); gdcm::PrivateTag pt3( 0x29,0x60, "SIEMENS MEDCOM HEADER2" ); const char str1[] = "GDCM was here 3!"; if( !ds.FindDataElement( pt1 ) ) return 1; gdcm::DataElement de1 = ds.GetDataElement( pt1 ); // Convert Private tag, into actual DataElement std::cout << de1 << std::endl; de1.SetByteValue( str1, (uint32_t)strlen(str1) ); ds.Replace( de1 ); const char str2[] = "GDCM was here 2!"; if( !ds.FindDataElement( pt2 ) ) return 1; gdcm::DataElement de2 = ds.GetDataElement( pt2 ); std::cout << de2 << std::endl; de2.SetByteValue( str2, (uint32_t)strlen(str2) ); ds.Replace( de2 ); const char str3[] = "GDCM was here 3!"; if( !ds.FindDataElement( pt3 ) ) return 1; gdcm::DataElement de3 = ds.GetDataElement( pt3 ); std::cout << de3 << std::endl; de3.SetByteValue( str3, (uint32_t)strlen(str3) ); ds.Replace( de3 ); gdcm::Writer writer; writer.SetFile( file ); writer.SetFileName( outfilename ); if ( !writer.Write() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/ChangeSequenceUltrasound.cxx000066400000000000000000000052371412732066400223240ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmSmartPointer.h" #include "gdcmDataSetHelper.h" /* ./ChangeSequenceUltrasound gdcmData/D_CLUNIE_CT1_J2KI.dcm myoutput.dcm This is the exact C++ translation of the original python example: ManipulateSequence.py */ int main(int argc, char* argv[] ) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; gdcm::Reader reader; reader.SetFileName( filename ); if (! reader.Read() ) { return 1; } gdcm::File &file = reader.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); gdcm::Tag tsis(0x0008,0x2112); // SourceImageSequence if ( ds.FindDataElement( tsis ) ) { const gdcm::DataElement &sis = ds.GetDataElement( tsis ); gdcm::SmartPointer sqsis = sis.GetValueAsSQ(); if ( sqsis && sqsis->GetNumberOfItems() ) { gdcm::Item &item1 = sqsis->GetItem(1); gdcm::DataSet &nestedds = item1.GetNestedDataSet(); gdcm::Tag tprcs(0x0040,0xa170); // PurposeOfReferenceCodeSequence if( nestedds.FindDataElement( tprcs ) ) { const gdcm::DataElement &prcs = nestedds.GetDataElement( tprcs ); gdcm::SmartPointer sqprcs = prcs.GetValueAsSQ(); if ( sqprcs && sqprcs->GetNumberOfItems() ) { gdcm::Item &item2 = sqprcs->GetItem(1); gdcm::DataSet &nestedds2 = item2.GetNestedDataSet(); // (0008,0104) LO [Uncompressed predecessor] # 24, 1 CodeMeaning gdcm::Tag tcm(0x0008,0x0104); if( nestedds2.FindDataElement( tcm ) ) { gdcm::DataElement cm = nestedds2.GetDataElement( tcm ); std::string mystr = "GDCM was here"; cm.SetByteValue( mystr.c_str(), (uint32_t)mystr.size() ); nestedds2.Replace( cm ); } } } } } gdcm::Writer writer; writer.SetFile( file ); writer.SetFileName( outfilename ); if ( !writer.Write() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/CheckBigEndianBug.cxx000066400000000000000000000061101412732066400205700ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * WARNING: This is a dev tool, do not use ! * * Usage: after a gdcmconv, you would like to know if the conversion process is acceptable * sometime a vbindiff is acceptable, sometime it is not. In the case of the famous Philips * Little/Big Endian Explicit Transfer Syntax it is not easy to compare two files. However * this only impact byte ordering, thus we can compute byte-indenpendant information to still * compare the files. */ #include "gdcmImageReader.h" #include "gdcmImage.h" #include "gdcmWriter.h" #include "gdcmAttribute.h" #include "gdcmSystem.h" #include #include int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input1.dcm input2.dcm" << std::endl; return 1; } const char *filename1 = argv[1]; const char *filename2 = argv[2]; gdcm::ImageReader reader1; reader1.SetFileName( filename1 ); if( !reader1.Read() ) { std::cerr << "Could not read: " << filename1 << std::endl; return 1; } gdcm::ImageReader reader2; reader2.SetFileName( filename2 ); if( !reader2.Read() ) { std::cerr << "Could not read: " << filename2 << std::endl; return 1; } // TODO: need a DataSet== operator implementation std::cout << "Both files can be read and looks like DICOM" << std::endl; size_t s1 = gdcm::System::FileSize(filename1); size_t s2 = gdcm::System::FileSize(filename2); if( s1 != s2 ) { std::cout << "Size mismatch: " << s1 << " != " << s2 << std::endl; return 1; } else { std::cout << "Size match: " << s1 << " = " << s2 << std::endl; } std::ifstream is1( filename1, std::ios::binary ); char *buffer1 = new char[s1]; is1.read(buffer1, s1); std::ifstream is2( filename2, std::ios::binary ); char *buffer2 = new char[s2]; is2.read(buffer2, s2); assert( s1 == s2 ); if( memcmp(buffer1, buffer2, s1 ) == 0 ) { std::cout << "memcmp succeed ! File are bit identical" << std::endl; } else { std::cout << "memcmp failed!" << std::endl; } // Hum...memcmp failed, for big endian/ little endian inversion the histogram of bytes // should still be the same. So let's compute it // buffer2[0] = 1; // let's make the test fail std::multiset set1( buffer1, buffer1 + s1 ); std::multiset set2( buffer2, buffer2 + s2 ); if( set1 == set2 ) { std::cout << "set1 == set2. Byte histogram seems valid" << std::endl; } else { std::cout << "set1 != set2" << std::endl; } delete[] buffer1; delete[] buffer2; return 0; } GDCM-3.0.10/Examples/Cxx/ClinicalTrialAnnotate.cxx000066400000000000000000000054361412732066400215720ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Dummy implementation of C.7.1.3 Clinical Trial Subject Module * * Usage: * ClinicalTrialAnnotate gdcmData/012345.002.050.dcm out.dcm */ #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmAnonymizer.h" int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } // The output of gdcm::Reader is a gdcm::File //gdcm::File &file = reader.GetFile(); // the dataset is the the set of element we are interested in: //gdcm::DataSet &ds = file.GetDataSet(); gdcm::Anonymizer ano; ano.SetFile( reader.GetFile() ); ano.RemoveGroupLength(); ano.RemovePrivateTags(); // PS 3.3 - 2008 // C.7.1.3 Clinical Trial Subject Module // ano.Replace( gdcm::Tag(0x12,0x10), "BigCompany name" ); // ano.Replace( gdcm::Tag(0x12,0x20), "My Clinical Trial Protocol ID" ); // ano.Replace( gdcm::Tag(0x12,0x21), "My Clinical Trial Protocol Name" ); // ano.Replace( gdcm::Tag(0x12,0x30), "My Clinical Trial Site ID" ); // ano.Replace( gdcm::Tag(0x12,0x31), "My Clinical Trial Site Name" ); // ano.Replace( gdcm::Tag(0x12,0x40), "My Clinical Trial Subject ID" ); // ano.Replace( gdcm::Tag(0x12,0x42), "My Clinical Trial Subject Reading ID" ); gdcm::Writer writer; writer.SetFile( reader.GetFile() ); writer.SetFileName( outfilename ); if( !writer.Write() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/CompressImage.cxx000066400000000000000000000044061412732066400201200ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageReader.h" #include "gdcmImage.h" #include "gdcmWriter.h" #include "gdcmAttribute.h" #include "gdcmImageWriter.h" #include "gdcmImageChangeTransferSyntax.h" #include #include int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } // The output of gdcm::Reader is a gdcm::File //gdcm::File &file = reader.GetFile(); // the dataset is the the set of element we are interested in: //gdcm::DataSet &ds = file.GetDataSet(); gdcm::Image &image = reader.GetImage(); // image.SetSpacing(0, 0.1); // image.SetSpacing(1, 0.2); image.Print( std::cout ); gdcm::ImageChangeTransferSyntax change; change.SetTransferSyntax( gdcm::TransferSyntax::JPEG2000Lossless ); change.SetTransferSyntax( gdcm::TransferSyntax::JPEGLosslessProcess14_1 ); //change.SetTransferSyntax( gdcm::TransferSyntax::JPEGBaselineProcess1 ); //change.SetTransferSyntax( image.GetTransferSyntax() ); change.SetInput( image ); bool b = change.Change(); if( !b ) { std::cerr << "Could not change the Transfer Syntax" << std::endl; return 1; } //std::ofstream out( outfilename, std::ios::binary ); //image.GetBuffer2(out); //out.close(); gdcm::ImageWriter writer; writer.SetImage( change.GetOutput() ); writer.SetFile( reader.GetFile() ); writer.SetFileName( outfilename ); if( !writer.Write() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/ConvertToQImage.cxx000066400000000000000000000103021412732066400203610ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This example shows how to setup the pipeline from a gdcm::ImageReader into a * Qt QImage data structure. * It only handles 2D image. * * Ref: * http://doc.trolltech.com/4.5/qimage.html * * Usage: * ConvertToQImage gdcmData/012345.002.050.dcm output.png * Thanks: * Sylvain ADAM (sylvain51 hotmail com) for contributing this example */ #include "gdcmImageReader.h" #include #include bool ConvertToFormat_RGB888(gdcm::Image const & gimage, char *buffer, QImage* &imageQt) { const unsigned int* dimension = gimage.GetDimensions(); unsigned int dimX = dimension[0]; unsigned int dimY = dimension[1]; gimage.GetBuffer(buffer); // Let's start with the easy case: if( gimage.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::RGB ) { if( gimage.GetPixelFormat() != gdcm::PixelFormat::UINT8 ) { return false; } unsigned char *ubuffer = (unsigned char*)buffer; // QImage::Format_RGB888 13 The image is stored using a 24-bit RGB format (8-8-8). imageQt = new QImage((unsigned char *)ubuffer, dimX, dimY, 3*dimX, QImage::Format_RGB888); } else if( gimage.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ) { if( gimage.GetPixelFormat() == gdcm::PixelFormat::UINT8 ) { // We need to copy each individual 8bits into R / G and B: unsigned char *ubuffer = new unsigned char[dimX*dimY*3]; unsigned char *pubuffer = ubuffer; for(unsigned int i = 0; i < dimX*dimY; i++) { *pubuffer++ = *buffer; *pubuffer++ = *buffer; *pubuffer++ = *buffer++; } imageQt = new QImage(ubuffer, dimX, dimY, QImage::Format_RGB888); } else if( gimage.GetPixelFormat() == gdcm::PixelFormat::INT16 ) { // We need to copy each individual 16bits into R / G and B (truncate value) short *buffer16 = (short*)buffer; unsigned char *ubuffer = new unsigned char[dimX*dimY*3]; unsigned char *pubuffer = ubuffer; for(unsigned int i = 0; i < dimX*dimY; i++) { // Scalar Range of gdcmData/012345.002.050.dcm is [0,192], we could simply do: // *pubuffer++ = *buffer16; // *pubuffer++ = *buffer16; // *pubuffer++ = *buffer16; // instead do it right: *pubuffer++ = (unsigned char)std::min(255, (32768 + *buffer16) / 255); *pubuffer++ = (unsigned char)std::min(255, (32768 + *buffer16) / 255); *pubuffer++ = (unsigned char)std::min(255, (32768 + *buffer16) / 255); buffer16++; } imageQt = new QImage(ubuffer, dimX, dimY, QImage::Format_RGB888); } else { std::cerr << "Pixel Format is: " << gimage.GetPixelFormat() << std::endl; return false; } } else { std::cerr << "Unhandled PhotometricInterpretation: " << gimage.GetPhotometricInterpretation() << std::endl; return false; } return true; } int main(int argc, char *argv[]) { if( argc < 2 ) { return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; gdcm::ImageReader ir; ir.SetFileName( filename ); if(!ir.Read()) { //Read failed return 1; } std::cout<<"Getting image from ImageReader..."< vbuffer; vbuffer.resize( gimage.GetBufferLength() ); char *buffer = &vbuffer[0]; QImage *imageQt = NULL; if( !ConvertToFormat_RGB888( gimage, buffer, imageQt ) ) { return 1; } QImageWriter writer; writer.setFormat("png"); writer.setFileName( outfilename ); if( !writer.write( *imageQt ) ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/CreateARGBImage.cxx000066400000000000000000000037771412732066400201760ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * http://www.w3.org/Graphics/PNG/inline-alpha.html * alphatest.png: PNG image data, 380 x 287, 8-bit/color RGBA, non-interlaced * * $ convert alphatest.png alphatest.rgba */ #include "gdcmImageReader.h" #include "gdcmSequenceOfFragments.h" #include "gdcmSystem.h" #include "gdcmImageWriter.h" #include #include int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.rgba output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; size_t len = gdcm::System::FileSize(filename); std::ifstream is(filename, std::ios::binary); char * buf = new char[len]; is.read(buf, len); gdcm::ImageWriter writer; gdcm::Image &image = writer.GetImage(); image.SetNumberOfDimensions( 2 ); unsigned int dims[3] = {}; dims[0] = 380; dims[1] = 287; image.SetDimensions( dims ); gdcm::PixelFormat pf = gdcm::PixelFormat::UINT8; pf.SetSamplesPerPixel( 4 ); image.SetPixelFormat( pf ); gdcm::PhotometricInterpretation pi = gdcm::PhotometricInterpretation::ARGB; image.SetPhotometricInterpretation( pi ); image.SetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0,0x0010) ); pixeldata.SetByteValue( buf, (uint32_t)len ); image.SetDataElement( pixeldata ); writer.SetFileName( outfilename ); if( !writer.Write() ) { return 1; } delete[] buf; return 0; } GDCM-3.0.10/Examples/Cxx/CreateCMYKImage.cxx000066400000000000000000000037761412732066400202250ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * http://www.w3.org/Graphics/PNG/inline-alpha.html * alphatest.png: PNG image data, 380 x 287, 8-bit/color RGBA, non-interlaced * * $ convert alphatest.png alphatest.cmyk */ #include "gdcmImageReader.h" #include "gdcmSequenceOfFragments.h" #include "gdcmSystem.h" #include "gdcmImageWriter.h" #include #include int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.cmyk output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; size_t len = gdcm::System::FileSize(filename); std::ifstream is(filename, std::ios::binary); char * buf = new char[len]; is.read(buf, len); gdcm::ImageWriter writer; gdcm::Image &image = writer.GetImage(); image.SetNumberOfDimensions( 2 ); unsigned int dims[3] = {}; dims[0] = 380; dims[1] = 287; image.SetDimensions( dims ); gdcm::PixelFormat pf = gdcm::PixelFormat::UINT8; pf.SetSamplesPerPixel( 4 ); image.SetPixelFormat( pf ); gdcm::PhotometricInterpretation pi = gdcm::PhotometricInterpretation::CMYK; image.SetPhotometricInterpretation( pi ); image.SetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0,0x0010) ); pixeldata.SetByteValue( buf, (uint32_t)len ); image.SetDataElement( pixeldata ); writer.SetFileName( outfilename ); if( !writer.Write() ) { return 1; } delete[] buf; return 0; } GDCM-3.0.10/Examples/Cxx/CreateJPIPDataSet.cxx000066400000000000000000000050431412732066400205140ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This example was created during the GSOC 2011 project for * JPIP */ #include "gdcmAnonymizer.h" #include "gdcmWriter.h" #include "gdcmUIDGenerator.h" #include "gdcmFile.h" #include "gdcmTag.h" #include "gdcmSystem.h" #include "gdcmAttribute.h" int main(int argc, char *argv[]) { if( argc < 2 ) { std::cerr << argv[0] << " output.dcm" << std::endl; return 1; } const char *outfilename = argv[1]; gdcm::Writer w; gdcm::File &file = w.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); //w.SetCheckFileMetaInformation( true ); w.SetFileName( outfilename ); file.GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::JPIPReferenced ); gdcm::Anonymizer anon; anon.SetFile( file ); gdcm::MediaStorage ms = gdcm::MediaStorage::SecondaryCaptureImageStorage; gdcm::UIDGenerator gen; anon.Replace( gdcm::Tag(0x0008,0x16), ms.GetString() ); std::cout << ms.GetString() << std::endl; anon.Replace( gdcm::Tag(0x0008,0x18), gen.Generate() ); // anon.Replace( gdcm::Tag(0x0010,0x10), "JPIP^EXAMPLE" ); anon.Replace( gdcm::Tag(0x0010,0x20), "012345" ); anon.Empty( gdcm::Tag(0x0010,0x30) ); anon.Empty( gdcm::Tag(0x0010,0x40) ); anon.Empty( gdcm::Tag(0x0008,0x20) ); anon.Empty( gdcm::Tag(0x0008,0x30) ); anon.Empty( gdcm::Tag(0x0008,0x90) ); anon.Empty( gdcm::Tag(0x0020,0x10) ); anon.Empty( gdcm::Tag(0x0020,0x11) ); anon.Empty( gdcm::Tag(0x0008,0x50) ); anon.Empty( gdcm::Tag(0x0020,0x0013) ); anon.Replace( gdcm::Tag(0x0020,0xd), gen.Generate() ); anon.Replace( gdcm::Tag(0x0020,0xe), gen.Generate() ); anon.Replace( gdcm::Tag(0x0008,0x64), "WSD " ); anon.Replace( gdcm::Tag(0x0008,0x60), "OT" ); gdcm::Attribute<0x0028,0x7FE0> at; at.SetValue( "http://dicom.example.com/jpipserver.cgi?target=img.jp2" ); ds.Insert( at.GetAsDataElement() ); // Need to retrieve the PixelFormat information from the given file if (!w.Write() ) { std::cerr << "Could not write: " << outfilename << std::endl; return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/DeriveSeries.cxx000066400000000000000000000056751412732066400177640ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmAttribute.h" #include "gdcmFileDerivation.h" #include "gdcmUIDGenerator.h" int main(int argc, char *argv[]) { if( argc < 3 ) { return 1; } const char * ref = argv[1]; const char * in = argv[2]; gdcm::Reader r1; r1.SetFileName( ref ); if( !r1.Read() ) return 1; gdcm::Reader r2; r2.SetFileName( in ); if( !r2.Read() ) return 1; // Fix Spatial info: gdcm::DataSet & ds1 = r1.GetFile().GetDataSet(); gdcm::File & file2 = r2.GetFile(); gdcm::DataSet & ds2 = file2.GetDataSet(); //gdcm::Attribute<0x8,0x8> img_type = { "ORIGINAL", "PRIMARY" }; ds2.Replace( ds1.GetDataElement( gdcm::Tag(0x0008,0x0008) )); ds2.Replace( ds1.GetDataElement( gdcm::Tag(0x0020,0x0032) )); ds2.Replace( ds1.GetDataElement( gdcm::Tag(0x0020,0x0037) )); ds2.Replace( ds1.GetDataElement( gdcm::Tag(0x0018,0x0088) )); // Spacing between slices ds2.Replace( ds1.GetDataElement( gdcm::Tag(0x0020,0x0013) )); // Instance Number ds2.Replace( ds1.GetDataElement( gdcm::Tag(0x0018,0x5100) )); // Patient Position ds2.Replace( ds1.GetDataElement( gdcm::Tag(0x0018,0x0050) )); // Slice Thickness ds2.Replace( ds1.GetDataElement( gdcm::Tag(0x0008,0x0070) )); // Manufacturer ds2.Replace( ds1.GetDataElement( gdcm::Tag(0x0018,0x0081) )); // Echo Time ds2.Replace( ds1.GetDataElement( gdcm::Tag(0x0020,0x1041) )); // Slice Location gdcm::Attribute<0x8,0x16> sopclassuid; sopclassuid.SetFromDataSet( ds1 ); gdcm::Attribute<0x8,0x18> sopinstanceuid; sopinstanceuid.SetFromDataSet( ds1 ); // Step 2: DERIVED object gdcm::FileDerivation fd; fd.AddReference( sopclassuid.GetValue(), sopinstanceuid.GetValue() ); // http://dicom.nema.org/MEDICAL/dicom/current/output/chtml/part16/chapter_D.html#DCM_121321 // CID 7202 "Source Image Purposes of Reference" // DCM 121321 "Mask image for image processing operation" fd.SetPurposeOfReferenceCodeSequenceCodeValue( 121321 ); // CID 7203 "Image Derivation" // DCM 113047 "Pixel by pixel mask" fd.SetDerivationCodeSequenceCodeValue( 113047 ); fd.SetFile( file2 ); // If all Code Value are ok the filter will execute properly if( !fd.Derive() ) { std::cerr << "Sorry could not derive using input info" << std::endl; return 1; } gdcm::Writer w; w.SetFile( r2.GetFile() ); w.SetFileName( "derived.dcm" ); if( !w.Write() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/DiffFile.cxx000066400000000000000000000034671412732066400170400ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input1.dcm input2.dcm" << std::endl; return 1; } const char *filename1 = argv[1]; const char *filename2 = argv[2]; gdcm::Reader reader1; reader1.SetFileName( filename1 ); if( !reader1.Read() ) { return 1; } gdcm::Reader reader2; reader2.SetFileName( filename2 ); if( !reader2.Read() ) { return 1; } const gdcm::File &file1 = reader1.GetFile(); const gdcm::File &file2 = reader2.GetFile(); const gdcm::DataSet &ds1 = file1.GetDataSet(); const gdcm::DataSet &ds2 = file2.GetDataSet(); gdcm::DataSet::ConstIterator it1 = ds1.Begin(); gdcm::DataSet::ConstIterator it2 = ds2.Begin(); const gdcm::DataElement &de1 = *it1; const gdcm::DataElement &de2 = *it2; if( de1 == de2 ) { } while( it1 != ds1.End() && it2 != ds2.End() && *it1 == *it2 ) { ++it1; ++it2; } if( it1 != ds1.End() || it2 != ds2.End() ) { std::cerr << "Problem with:" << std::endl; if( it1 != ds1.End() ) { std::cerr << "ds1: " << *it1 << std::endl; } if( it2 != ds2.End() ) { std::cerr << "ds2: " << *it2 << std::endl; } return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/DiscriminateVolume.cxx000066400000000000000000000175351412732066400211740ustar00rootroot00000000000000/*========================================================================= 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 "gdcmScanner.h" #include "gdcmTesting.h" #include "gdcmIPPSorter.h" #include "gdcmDirectionCosines.h" #include /* * The following example is a basic sorted which should work in generic cases. * It sort files based on: * Study Instance UID * Series Instance UID * Frame of Reference UID * Image Orientation (Patient) * Image Position (Patient) (Sorting based on IPP + IOP) */ namespace gdcm { const Tag t1(0x0020,0x000d); // Study Instance UID const Tag t2(0x0020,0x000e); // Series Instance UID const Tag t3(0x0020,0x0052); // Frame of Reference UID const Tag t4(0x0020,0x0037); // Image Orientation (Patient) class DiscriminateVolume { private: std::vector< Directory::FilenamesType > SortedFiles; std::vector< Directory::FilenamesType > UnsortedFiles; Directory::FilenamesType GetAllFilenamesFromTagToValue( Scanner const & s, Directory::FilenamesType const &filesubset, Tag const &t, const char *valueref) { Directory::FilenamesType theReturn; if( valueref ) { size_t len = strlen( valueref ); Directory::FilenamesType::const_iterator file = filesubset.begin(); for(; file != filesubset.end(); ++file) { const char *filename = file->c_str(); const char * value = s.GetValue(filename, t); if( value && strncmp(value, valueref, len ) == 0 ) { theReturn.push_back( filename ); } } } return theReturn; } void ProcessAIOP(Scanner const & , Directory::FilenamesType const & subset, const char *iopval) { std::cout << "IOP: " << iopval << std::endl; IPPSorter ipp; ipp.SetComputeZSpacing( true ); ipp.SetZSpacingTolerance( 1e-3 ); // ?? bool b = ipp.Sort( subset ); if( !b ) { // If you reach here this means you need one more parameter to discriminiat this // series. Eg. T1 / T2 intertwinted. Multiple Echo (0018,0081) std::cerr << "Failed to sort: " << subset.begin()->c_str() << std::endl; for( Directory::FilenamesType::const_iterator file = subset.begin(); file != subset.end(); ++file) { std::cerr << *file << std::endl; } UnsortedFiles.push_back( subset ); return ; } ipp.Print( std::cout ); SortedFiles.push_back( ipp.GetFilenames() ); } void ProcessAFrameOfRef(Scanner const & s, Directory::FilenamesType const & subset, const char * frameuid) { // In this subset of files (belonging to same series), let's find those // belonging to the same Frame ref UID: Directory::FilenamesType files = GetAllFilenamesFromTagToValue( s, subset, t3, frameuid); std::set< std::string > iopset; for( Directory::FilenamesType::const_iterator file = files.begin(); file != files.end(); ++file) { //std::cout << *file << std::endl; const char * value = s.GetValue(file->c_str(), gdcm::t4 ); assert( value ); iopset.insert( value ); } size_t n = iopset.size(); if ( n == 0 ) { assert( files.empty() ); return; } std::cout << "Frame of Ref: " << frameuid << std::endl; if ( n == 1 ) { ProcessAIOP(s, files, iopset.begin()->c_str() ); } else { const char *f = files.begin()->c_str(); std::cerr << "More than one IOP: " << f << std::endl; // Make sure that there is actually 'n' different IOP gdcm::DirectionCosines ref; gdcm::DirectionCosines dc; for( std::set< std::string >::const_iterator it = iopset.begin(); it != iopset.end(); ++it ) { ref.SetFromString( it->c_str() ); for( Directory::FilenamesType::const_iterator file = files.begin(); file != files.end(); ++file) { std::string value = s.GetValue(file->c_str(), gdcm::t4 ); if( value != it->c_str() ) { dc.SetFromString( value.c_str() ); const double crossdot = ref.CrossDot(dc); const double eps = std::fabs( 1. - crossdot ); if( eps < 1e-6 ) { std::cerr << "Problem with IOP discrimination: " << file->c_str() << " " << it->c_str() << std::endl; return; } } } } // If we reach here this means there is actually 'n' different IOP for( std::set< std::string >::const_iterator it = iopset.begin(); it != iopset.end(); ++it ) { const char *iopvalue = it->c_str(); Directory::FilenamesType iopfiles = GetAllFilenamesFromTagToValue( s, files, t4, iopvalue ); ProcessAIOP(s, iopfiles, iopvalue ); } } } void ProcessASeries(Scanner const & s, const char * seriesuid) { std::cout << "Series: " << seriesuid << std::endl; // let's find all files belonging to this series: Directory::FilenamesType seriesfiles = GetAllFilenamesFromTagToValue( s, s.GetFilenames(), t2, seriesuid); gdcm::Scanner::ValuesType vt3 = s.GetValues(t3); for( gdcm::Scanner::ValuesType::const_iterator it = vt3.begin() ; it != vt3.end(); ++it ) { ProcessAFrameOfRef(s, seriesfiles, it->c_str()); } } void ProcessAStudy(Scanner const & s, const char * studyuid) { std::cout << "Study: " << studyuid << std::endl; gdcm::Scanner::ValuesType vt2 = s.GetValues(t2); for( gdcm::Scanner::ValuesType::const_iterator it = vt2.begin() ; it != vt2.end(); ++it ) { ProcessASeries(s, it->c_str()); } } public: void Print( std::ostream & os ) { os << "Sorted Files: " << std::endl; for( std::vector< Directory::FilenamesType >::const_iterator it = SortedFiles.begin(); it != SortedFiles.end(); ++it ) { os << "Group: " << std::endl; for( Directory::FilenamesType::const_iterator file = it->begin(); file != it->end(); ++file) { os << *file << std::endl; } } os << "Unsorted Files: " << std::endl; for( std::vector< Directory::FilenamesType >::const_iterator it = UnsortedFiles.begin(); it != UnsortedFiles.end(); ++it ) { os << "Group: " << std::endl; for( Directory::FilenamesType::const_iterator file = it->begin(); file != it->end(); ++file) { os << *file << std::endl; } } } std::vector< Directory::FilenamesType > const & GetSortedFiles() const { return SortedFiles; } std::vector< Directory::FilenamesType > const & GetUnsortedFiles() const { return UnsortedFiles; } void ProcessIntoVolume( Scanner const & s ) { gdcm::Scanner::ValuesType vt1 = s.GetValues( gdcm::t1 ); for( gdcm::Scanner::ValuesType::const_iterator it = vt1.begin() ; it != vt1.end(); ++it ) { ProcessAStudy( s, it->c_str() ); } } }; } // namespace gdcm int main(int argc, char *argv[]) { std::string dir1; if( argc < 2 ) { const char *extradataroot = nullptr; #ifdef GDCM_BUILD_TESTING extradataroot = gdcm::Testing::GetDataExtraRoot(); #endif if( !extradataroot ) { return 1; } dir1 = extradataroot; dir1 += "/gdcmSampleData/ForSeriesTesting/VariousIncidences/ST1"; } else { dir1 = argv[1]; } gdcm::Directory d; d.Load( dir1.c_str(), true ); // recursive ! gdcm::Scanner s; s.AddTag( gdcm::t1 ); s.AddTag( gdcm::t2 ); s.AddTag( gdcm::t3 ); s.AddTag( gdcm::t4 ); bool b = s.Scan( d.GetFilenames() ); if( !b ) { std::cerr << "Scanner failed" << std::endl; return 1; } gdcm::DiscriminateVolume dv; dv.ProcessIntoVolume( s ); dv.Print( std::cout ); return 0; } GDCM-3.0.10/Examples/Cxx/DumpADAC.cxx000066400000000000000000000232641412732066400167030ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * the goal of this example is to mimic the behavior of disp_img_header * see http://www.gmecorp-usa.com/IM/NM/GC/ADAC/SV/adactechtips/Released_01Q3.pdf */ #include "gdcmReader.h" #include "gdcmPrivateTag.h" #include "gdcmAttribute.h" #include "gdcmImageWriter.h" #include #include #include #include #include #include struct dict { uint16_t key; const char *name; }; dict Array[] = { { 0x01, "Patient name" }, { 0x02, "Patient ID" }, { 0x03, "Patient sex" }, { 0x04, "Patient age" }, { 0x05, "Patient height" }, { 0x06, "Patient weight" }, { 0x07, "Exam date" }, { 0x08, "Dose admin. time" }, { 0x09, "Unique exam key" }, { 0x0a, "Exam procedure" }, { 0x0b, "Referring physician" }, { 0x0c, "Attending physician" }, { 0x0d, "Imaging modality" }, { 0x0e, "Hospital ID" }, { 0x0f, "Histogram crv file" }, { 0x10, "Acq. start time" }, { 0x11, "Object data type" }, { 0x12, "Image viewid" }, { 0x13, "Imaging device name" }, { 0x14, "Device serial number" }, { 0x15, "Collimator" }, { 0x16, "Software version" }, { 0x17, "Radiopharmaceutical #1" }, { 0x18, "Energy window #1 center" }, { 0x19, "Radiopharmaceutical #2" }, { 0x1a, "Energy window #1 width" }, { 0x1b, "Isotope imaging mode" }, { 0x1c, "Energy window #2 center" }, { 0x1d, "Energy window #2 width" }, { 0x1e, "Energy window #3 center" }, { 0x1f, "Energy window #3 width" }, { 0x20, "Energy window #4 center" }, { 0x21, "Energy window #4 width" }, { 0x22, "??Energy window #5 center" }, { 0x23, "??Energy window #5 width" }, { 0x24, "Patient orientation" }, { 0x25, "Spatial resolution" }, { 0x26, "Slice thickness" }, { 0x27, "Image X dimension" }, { 0x28, "Image Y dimension" }, { 0x29, "Image Z dimension" }, { 0x2a, "Image pixel width" }, { 0x2b, "Uniformity corr. file" }, { 0x2c, "Acquisition zoom factor" }, { 0x2d, "Total counts in set" }, { 0x2e, "Time / frame" }, { 0x2f, "Total acq. time" }, { 0x30, "Maximum pixel value" }, { 0x31, "Minimum pixel value" }, { 0x32, "R-R interval time" }, { 0x33, "Percent of cycle imaged" }, { 0x34, "# of cycles accepted" }, { 0x35, "# of cycles rejected" }, { 0x36, "Approximate ED frame" }, { 0x37, "Approximate ES frame" }, { 0x38, "Approximate EF" }, { 0x39, "Starting angle" }, { 0x3a, "Degrees of rotation" }, { 0x3b, "Direction of rotation" }, { 0x3c, "Cont. or step/shoot" }, { 0x3d, "Lim recon start frame" }, { 0x3e, "Upper window grey shade" }, { 0x3f, "Lower lvl grey shade" }, { 0x40, "Associated color map" }, { 0x41, "Custom color map file" }, { 0x42, "Manipulated image" }, { 0x43, "Axis of rotation corr." }, { 0x44, "Reorientation azimuth" }, { 0x45, "Reorientation elevation" }, { 0x46, "Filter type" }, { 0x47, "Filter order" }, { 0x48, "Filter cutoff frequency" }, { 0x49, "Reconstruction type" }, { 0x4a, "Attenuation coefficient" }, { 0x4b, "Associated parent file" }, { 0x4c, "Unique patient key" }, { 0x52, "Normalization crv file" }, { 0x53, "Unique object key" }, { 0x54, "This phase of VFR is" }, { 0x55, "True color value" }, { 0x56, "# of sets of x,y,z grps" }, { 0x57, "Scale factor of set" }, { 0x6d, "Date of birth" }, { 0x6e, "Directional orientation" }, { 0x6f, "Number of VFR studies" }, { 0x70, "R-R low tolerance" }, { 0x71, "R-R high tolerance" }, { 0x72, "Prog specific results:" }, { 0x99, nullptr } }; void printname( int , int , uint16_t v ) { if( v == 0x1 ) { std::cout << "DATABASE PARAMETERS" << std::endl; std::cout << "___________________" << std::endl; } else if( v == 0x27 ) { std::cout << "IMAGE PARAMETERS" << std::endl; std::cout << "________________" << std::endl; } else if( v == 0x13 ) { std::cout << "EXTRA PARAMETERS" << std::endl; std::cout << "________________" << std::endl; } else if( v == 0x2e ) { std::cout << "*** NOT CURRENTLY USED :" << std::endl; } static const unsigned int n = sizeof( Array ) / sizeof( *Array ) - 1; for( unsigned int i = 0; i < n; ++i ) { if( v == Array[i].key ) { std::cout << /*"" << std::dec << len << "," << mult << " " << */ Array[i].name; std::cout << " : "; return; } } std::cout << /*"\t# " << std::dec << len << "," << mult << */ std::hex << v << "\t: "; } uint16_t readint16(std::istream &is ) { uint16_t val; is.read( (char*)&val, sizeof( val )); return (uint16_t)((val>>8) | (val<<8)); } uint32_t readint32(std::istream &is ) { uint32_t val; is.read( (char*)&val, sizeof( val )); val= ((val<<8)&0xFF00FF00) | ((val>>8)&0x00FF00FF); return (val>>16) | (val<<16); } float readfloat32(std::istream &is ) { union { uint32_t val; float f;} dual; dual.val = readint32(is); return dual.f; } struct el { uint16_t v1; uint16_t v2; uint16_t v3; void read( std::istream & is ) { v1 = readint16(is); v2 = readint16(is); v3 = readint16(is); } void print( std::ostream & os ) { os << std::hex << v1 << "\t" << v2 << "\t" << v3 << std::endl; } }; std::vector Vel; void readelement( std::istream & is ) { el e; e.read( is ); Vel.push_back( e ); } void printascii( uint16_t tag, const char *buffer, size_t len ) { std::ostream & os = std::cout; if( tag == 0x72 ) { os << "\n "; for(size_t i = 0; i < len; ++i) { const char &c = buffer[i]; if( c == 0x0 ) os << "!"; else if( c == 0x0f ) os << " "; else if( c == 0x17 ) os << ":"; else if( c == 0x14 ) os << ":"; else if( c == 0x10 ) os << ":"; else if( c == 0x16 ) os << ":"; else if( c == 0x08 ) os << ":"; else if( c == 0x0b ) os << ":"; else if( c == 0x0e ) os << ":"; else if( c == 0x07 ) os << ":"; else os << c; } os << ""; } else { (void)len; os << "" << buffer << ""; } } bool DumpADAC( std::istream & is ) { std::ostream &os = std::cout; char magic[6 + 1]; magic[6] = 0; is.read( magic, 6); // std::cout << magic << " "; assert( strcmp( magic, "adac01" ) == 0 ); int c = is.get(); assert( c == 0 ); (void)c; c = is.get(); assert( c == 'X' ); uint16_t v; v = readint16(is); // std::cout << v << std::endl; assert( v == 512 ); (void)v; // ?? int nel = 87; for (int i = 0; i <= nel; ++i ) { readelement( is ); } char buffer[512]; for( int i = 0; i <= nel; ++i ) { const el &e = Vel[i]; int diff; if( i == nel ) { diff = 2048 - e.v3; if( diff > 512 ) diff = 512; } else { const el &enext = Vel[i+1]; diff = enext.v3 - e.v3; } is.seekg( e.v3, std::ios::beg ); //std::cout << "(" << std::hex << std::setw( 2 ) << std::setfill( '0' ) << e.v1 << ") " << std::hex << std::setw( 3 ) << std::setfill( '0' ) << e.v2 << " "; printname( diff, 0, e.v1 ); int mult = 1; if( e.v2 == 0 ) { is.read( buffer, diff); buffer[ diff ] = 0; printascii( e.v1, buffer, diff); } else if( e.v2 == 0x100 ) { mult = diff / 2; assert( diff == 2 * mult ); for ( int ii = 0; ii < mult; ++ii ) { if ( ii ) os << "\\"; uint16_t val = readint16(is); os << "" << std::dec << val << ""; } } else if( e.v2 == 0x200 ) { assert( diff == 4 ); uint32_t val = readint32(is); os << "" << std::dec << val << ""; } else if( e.v2 == 0x300 ) { assert( diff == 4 ); float val = readfloat32(is); os << "" << std::dec << val << ""; } else { assert( 0 ); } os << std::endl; } return true; } int main(int argc, char *argv[]) { if( argc < 2 ) return 1; const char *filename = argv[1]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); // (0019,1061) UN (OB) 61\64\61\63\30 # 2048,1 Ver200 ADAC Pegasys Headers const gdcm::PrivateTag tver200adacpegasysheaders(0x0019,0x61,"ADAC_IMG"); if( !ds.FindDataElement( tver200adacpegasysheaders ) ) return 1; const gdcm::DataElement& ver200adacpegasysheaders = ds.GetDataElement( tver200adacpegasysheaders ); if ( ver200adacpegasysheaders.IsEmpty() ) return 1; const gdcm::ByteValue * bv = ver200adacpegasysheaders.GetByteValue(); // (0019,1021) US 1 # 2,1 Ver200 Number of ADAC Headers // TODO // (0019,1041) IS [2048\221184 ] # 12,1-n Ver200 ADAC Header/Image Size if( bv->GetLength() != 2048 ) return 1; gdcm::Element el; const gdcm::PrivateTag tver200adacheaderimagesize(0x0019,0x41,"ADAC_IMG"); if( !ds.FindDataElement( tver200adacheaderimagesize ) ) return 1; const gdcm::DataElement& ver200adacheaderimagesize = ds.GetDataElement( tver200adacheaderimagesize ); el.SetFromDataElement( ver200adacheaderimagesize ); if( el.GetValue(0) != 2048 ) return 1; std::istringstream is; std::string dup( bv->GetPointer(), bv->GetLength() ); is.str( dup ); bool b = DumpADAC( is ); if( !b ) return 1; return 0; } GDCM-3.0.10/Examples/Cxx/DumpExamCard.cxx000066400000000000000000000505601412732066400176760ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* Try to extract contents of Philips RAW storage class: (0002,0002) UI [1.2.840.10008.5.1.4.1.1.66] # 26,1 Media Storage SOP Class UID (0002,0003) UI [1.3.46.670589.11.17240.5.23.4.1.3012.2010032409482568018] # 56,1 Media Storage SOP Instance UID (0002,0010) UI [1.2.840.10008.1.2.1] # 20,1 Transfer Syntax UID (0002,0012) UI [1.3.46.670589.11.0.0.51.4.4.1] # 30,1 Implementation Class UID (0002,0013) SH [MR DICOM 4.1] # 12,1 Implementation Version Name * Everything done in this code is for the sole purpose of writing interoperable * software under Sect. 1201 (f) Reverse Engineering exception of the DMCA. * If you believe anything in this code violates any law or any of your rights, * please contact us (gdcm-developers@lists.sourceforge.net) so that we can * find a solution. * * Everything you do with this code is at your own risk, since decompression * algorithm was not written from specification documents. * * Special thanks to: * Triplett,William T for bringing to your attention on this ExamCard stuff */ #include "gdcmReader.h" #include "gdcmDataSet.h" #include "gdcmPrivateTag.h" #include "gdcmBase64.h" #include static bool compfn(const char *s1, const char *s2) { return strcmp(s1,s2) < 0 ? true : false; } static const char *PDFStrings[] = { // Keep me ordered please "COILSTATE", // series of string ? "HARDWARE_CONFIG", // series of number ? "PDF_CONTROL_GEN_PARS", "PDF_CONTROL_PREP_PARS", "PDF_CONTROL_RECON_PARS", "PDF_CONTROL_SCAN_PARS", "PDF_EXAM_PARS", "PDF_HARDWARE_PARS", "PDF_PREP_PARS", "PDF_PRESCAN_COIL_PARS", "PDF_SPT_PARS", }; static bool isvalidpdfstring( const char *pdfstring ) { assert( pdfstring ); static const size_t n = sizeof( PDFStrings ) / sizeof( *PDFStrings ); static const char **begin = PDFStrings; static const char **end = begin + n; return std::binary_search(begin, end, pdfstring, compfn); } typedef enum { param_float = 0, param_integer = 1, // 1 << 0 param_string = 2, // 1 << 1 param_3, // ?? param_enum = 4 // 1 << 2 } param_type; static const char *gettypenamefromtype( int i) { const char *ret = nullptr; param_type e = (param_type)i; switch( e ) { case param_float: ret = "float"; break; case param_integer: ret = "int"; break; case param_string: ret = "string"; break; case param_3: ret = "??"; break; case param_enum: ret = "enum"; break; } assert( ret ); return ret; } struct header { /* * TODO: * Looks as if we could read all int*, float* and string* at once... */ int32_t v1; // offset to int pointer array ? uint16_t nints; // number of ints (max number?) uint16_t v3; // always 0 ? int32_t v4; // offset to float pointer array ? uint32_t nfloats; int32_t v6; // offset to string pointer array ? uint32_t nstrings; int32_t v8; // always 8 ?? uint32_t numparams; uint32_t getnints() const { return nints; } uint32_t getnfloats() const { return nfloats; } uint32_t getnstrings() const { return nstrings; } uint32_t getnparams() const { return numparams; } void read( std::istream & is ) { is.read( (char*)&v1,sizeof(v1)); if( v1 == 0x01 ) { // direct (FIXME how should we detect this, much like TIFF ???) nints = 0; v3 = 0; v4 = 0; nfloats = 0; v6 = 0; nstrings = 0; v8 = 0; numparams = 0; uint32_t bla; is.read( (char*)&bla, sizeof(bla) ); assert( bla == 0x2 || bla == 0x3 ); nstrings = 1; numparams = 1; } else { // indirect is.read( (char*)&nints,sizeof(nints)); is.read( (char*)&v3,sizeof(v3)); assert( v3 == 0 ); // looks like this is always 0 is.read( (char*)&v4,sizeof(v4)); is.read( (char*)&nfloats,sizeof(nfloats)); is.read( (char*)&v6,sizeof(v6)); is.read( (char*)&nstrings,sizeof(nstrings)); is.read( (char*)&v8,sizeof(v8)); assert( v8 == 8 ); is.read( (char*)&numparams,sizeof(numparams)); } } void print( std::ostream & os ) { os << v1 << ","; os << nints << ","; os << v3 << ","; os << v4 << ","; os << nfloats << ","; os << v6 << ","; os << nstrings << ","; os << v8 << ","; os << numparams << std::endl; } }; struct param { char name[32+1]; uint8_t boolean; int32_t type; uint32_t dim; union { uint32_t val; char * ptr; } v4; int32_t /*std::streamoff*/ offset; param_type gettype() const { return (param_type)type; } uint32_t getdim() const { return dim; } void read_direct_int( std::istream & is ) { uint32_t bla; int max = 9; std::vector v; for( int i = 0; i < max; ++i ) { is.read( (char*)&bla, sizeof(bla) ); v.push_back( bla ); } is.read( (char*)&bla, sizeof(bla) ); char name0[32]; memset(name0,0,sizeof(name0)); assert( bla < sizeof(name0) ); is.read( name0, bla); size_t l = strlen(name0); assert( l == bla ); (void)l; char * ptr = strdup( name0 ); v4.ptr = ptr; type = param_string; dim = 1; offset = 0; // important ! } void read_direct_string( std::istream & is ) { uint32_t bla; is.read( (char*)&bla, sizeof(bla) ); char name0[32]; memset(name0,0,sizeof(name0)); assert( bla < sizeof(name0) ); is.read( name0, bla); size_t l = strlen(name0); assert( l == bla ); (void)l; memcpy( this->name, name0, bla ); is.read( (char*)&bla, sizeof(bla) ); assert( bla == 0x1 ); is.read( (char*)&bla, sizeof(bla) ); char value[32]; memset(value,0,sizeof(value)); assert( bla < sizeof(value) ); is.read( value, bla); is.read( (char*)&bla, sizeof(bla) ); assert( bla == 0 ); // trailing stuff ? is.read( (char*)&bla, sizeof(bla) ); assert( bla == 0 ); // trailing stuff ? const uint32_t cur = (uint32_t)is.tellg(); std::cerr << "offset:" << cur << std::endl; if( cur == 65 ) is.read( (char*)&bla, 1 ); else if( cur == 66 ) is.read( (char*)&bla, 1 ); else if( cur == 122 ) is.read( (char*)&bla, 2 ); else assert(0); type = param_string; dim = 1; // FIXME: store the value in v4 for now: char * ptr = strdup( value ); v4.ptr = ptr; offset = 0; // important ! } void read( std::istream & is ) { is.read( name, 32 + 1); // This is always the same issue the string can contains garbarge from previous run, // we need to print only until the first \0 character: assert( strlen( name ) <= 32 ); is.read( (char*)&boolean,1); assert( boolean == 0 || boolean == 1 || boolean == 0x69 ); // some kind of bool, or digital trash ? is.read( (char*)&type, sizeof( type ) ); assert( gettypenamefromtype( type ) ); is.read( (char*)&dim, sizeof( dim ) ); // number of elements is.read( (char*)&v4.val, sizeof( v4.val ) ); //assert( v4.val == 0 ); // always 0 ? sometimes not... const uint32_t cur = (uint32_t)is.tellg(); is.read( (char*)&offset, sizeof( offset ) ); assert( offset != 0 ); offset += cur; } void print( std::ostream & os ) const { os << name << ","; os << (int)boolean << ","; os << type << ","; os << dim << ","; os << v4.val << ","; os << offset << std::endl; } void printvalue( std::ostream & os, std::istream & is ) const { if( offset ) { is.seekg( offset ); switch( type ) { case param_float: { os.precision(2); os << std::fixed; for( uint32_t idx = 0; idx < dim; ++idx ) { if( idx ) os << ","; float v; is.read( (char*)&v, sizeof(v) ); os << v; // what if the string contains \0 ? } } break; case param_integer: { int32_t v; for( uint32_t idx = 0; idx < dim; ++idx ) { if( idx ) os << ","; is.read( (char*)&v, sizeof(v) ); os << v; } } break; case param_string: { int size = 81; std::string v; v.resize( size ); for( uint32_t idx = 0; idx < dim; ++idx ) { if( idx ) os << ";"; is.read( &v[0], size ); os << v.c_str(); } } break; case param_enum: { int32_t v; for( uint32_t idx = 0; idx < dim; ++idx ) { if( idx ) os << ","; is.read( (char*)&v, sizeof(v) ); os << v; } } break; } } else { #if 1 // direct assert ( type == param_string ); char * ptr = v4.ptr; //std::string v; //v.resize( dim ); //is.read( &v[0], dim ); os << ptr; #endif } } void printxml( std::ostream & os, std::istream & is ) const { // 0 os << " "; printvalue( os, is ); os << "\n"; } void printcsv( std::ostream & os, std::istream & is ) const { os << std::setw(32) << std::left << name << ","; os << std::setw(7) << std::right << gettypenamefromtype(type) << ","; os << std::setw(4) << dim << ","; os << " "; printvalue( os, is ); os << ",\n"; } }; static bool ProcessNested( gdcm::DataSet & ds ) { /* TODO: Looks like the real length of the blob is stored here: (2005,1132) SQ # u/l,1 ? (fffe,e000) na (Item with undefined length) (2005,0011) LO [Philips MR Imaging DD 002 ] # 26,1 Private Creator (2005,1143) SL 3103 # 4,1 ? Wotsit ? (2005,1132) SQ # u/l,1 ? (fffe,e000) na (Item with undefined length) (2005,0011) LO [Philips MR Imaging DD 002 ] # 26,1 Private Creator (2005,1147) CS [Y ] # 2,1 ? */ bool ret = false; // (2005,1137) PN (LO) [PDF_CONTROL_GEN_PARS] # 20,1 Protocol Data Name const gdcm::PrivateTag pt0(0x2005,0x37,"Philips MR Imaging DD 002"); if( !ds.FindDataElement( pt0 ) ) return false; const gdcm::DataElement &de0 = ds.GetDataElement( pt0 ); if( de0.IsEmpty() ) return false; const gdcm::ByteValue * bv0 = de0.GetByteValue(); std::string s0( bv0->GetPointer() , bv0->GetLength() ); // (2005,1139) LO [IEEE_PDF] # 8,1 Protocol Data Type const gdcm::PrivateTag pt1(0x2005,0x39,"Philips MR Imaging DD 002"); if( !ds.FindDataElement( pt1 ) ) return false; const gdcm::DataElement &de1 = ds.GetDataElement( pt1 ); // (2005,1143) SL 53 # 4,1 Protocol Data Block Length (non-padded) const gdcm::PrivateTag pt2(0x2005,0x43,"Philips MR Imaging DD 002"); if( !ds.FindDataElement( pt2 ) ) return false; const gdcm::DataElement &de2 = ds.GetDataElement( pt2 ); // (2005,1147) CS [Y ] # 2,1 Protocol Data Boolean const gdcm::PrivateTag pt3(0x2005,0x47,"Philips MR Imaging DD 002"); if( !ds.FindDataElement( pt3 ) ) return false; const gdcm::DataElement &de3 = ds.GetDataElement( pt3 ); (void)de3; // (2005,1144) OW 00\00\00\00\05\00\00\00\35\2e\31\2e\37\00 # 54,1 Protocol Data Block const gdcm::PrivateTag pt(0x2005,0x44,"Philips MR Imaging DD 002"); if( !ds.FindDataElement( pt ) ) return false; const gdcm::DataElement &de = ds.GetDataElement( pt ); if( de.IsEmpty() ) return false; const gdcm::ByteValue * bv = de.GetByteValue(); if( s0 == "ExamCardBlob" ) { assert( de1.IsEmpty() ); std::string fn = gdcm::LOComp::Trim( s0.c_str() ); // remove trailing space fn += ".xml"; std::ofstream out( fn.c_str() ); // remove trailing \0 size_t len = strlen( bv->GetPointer() ); out.write( bv->GetPointer() , len ); out.close(); // Extract binary64 thingy (this is a ugly hack, better use an XML parser) std::string dup( bv->GetPointer(), len ); std::string::size_type pos1 = dup.find( "" ); std::string::size_type pos2 = dup.find( "" ); std::string b64( bv->GetPointer() + pos1 + 14, pos2 - (pos1 + 14) ); // ulgy hack to remove \r\n from input base64: std::string::iterator r_pos = std::remove(b64.begin(), b64.end(), '\r'); b64.erase(r_pos, b64.end()); std::string::iterator n_pos = std::remove(b64.begin(), b64.end(), '\n'); b64.erase(n_pos, b64.end()); #if 0 std::ofstream out2( "debug" ); out2.write( b64.c_str(), b64.size() ); out2.close(); #endif const size_t dlen = gdcm::Base64::GetDecodeLength(b64.c_str(), b64.size() ); std::string decoded; decoded.resize( dlen ); gdcm::Base64::Decode( &decoded[0], decoded.size(), b64.c_str(), b64.size() ); std::ofstream f64( "soap.xml" ); f64.write( decoded.c_str(), decoded.size() ); f64.close(); ret = true; } else { if( de1.IsEmpty() ) return false; const gdcm::ByteValue * bv1 = de1.GetByteValue(); gdcm::Element dlen = {{0l}}; dlen.SetFromDataElement( de2 ); std::string s1( bv1->GetPointer() , bv1->GetLength() ); if( s1 == "IEEE_PDF" ) { std::istringstream is; assert( bv->GetLength() == (size_t)dlen.GetValue() || bv->GetLength() == (size_t)(dlen.GetValue() + 1) ); std::string dup( bv->GetPointer(), dlen.GetValue() /*bv->GetLength()*/ ); is.str( dup ); header h; h.read( is ); //assert( is.peek() && is.eof() ); #if 1 static int c = 0; std::string fn0 = gdcm::LOComp::Trim( s1.c_str() ); // remove trailing space std::stringstream ss; ss << fn0 << "_" << c++; if( h.v1 == 0x01 ) ss << ".direct"; else ss << ".indirect"; std::cout << "fn0=" << ss.str() << " Len= " << bv->GetLength() << std::endl; std::ofstream out( ss.str().c_str() ); out.write( bv->GetPointer(), bv->GetLength() ); out.close(); #endif #if 1 std::cout << dup.c_str() << std::endl; h.print( std::cout ); #endif std::vector< param > params; if( h.v1 == 0x01 ) { for( uint32_t i = 0; i < 1 /* h.getnparams()*/; ++i ) { param p; if( s0 == "HARDWARE_CONFIG " ) { p.read_direct_int( is ); } else if( s0 == "COILSTATE " ) { p.read_direct_string( is ); } else { assert(0); } params.push_back( p ); } } else { assert( is.tellg() == std::streampos(0x20) ); is.seekg( 0x20 ); param p; for( uint32_t i = 0; i < h.getnparams(); ++i ) { p.read( is ); //p.print( std::cout ); params.push_back( p ); } } std::string fn = gdcm::LOComp::Trim( s0.c_str() ); // remove trailing space bool b1 = isvalidpdfstring( fn.c_str() ); assert( b1 ); (void)b1; fn += ".csv"; //fn += ".xml"; std::ofstream csv( fn.c_str() ); // let's do some bookeeping: uint32_t nfloats = 0; uint32_t nints = 0; uint32_t nstrings = 0; for( std::vector::const_iterator it = params.begin(); it != params.end(); ++it ) { param_type type = it->gettype(); switch( type ) { case param_float: nfloats += it->getdim(); break; case param_integer: nints += it->getdim(); break; case param_string: nstrings += it->getdim(); break; default: ; } } #if 0 std::cout << "Stats:" << std::endl; std::cout << "nfloats:" << nfloats << std::endl; std::cout << "nints:" << nints << std::endl; std::cout << "nstrings:" << nstrings << std::endl; #endif assert( h.getnints() >= nints ); assert( h.getnfloats() >= nfloats ); assert( h.getnstrings() >= nstrings); for( uint32_t i = 0; i < h.getnparams(); ++i ) { params[i].printcsv( csv, is ); //params[i].printxml( csv, is ); } csv.close(); ret = true; } else if( s1 == "ASCII " ) { #if 0 std::cerr << "ASCII is not handled" << std::endl; std::string fn = gdcm::LOComp::Trim( s0.c_str() ); // remove trailing space fn += ".asc"; std::ofstream out( fn.c_str() ); out.write( bv->GetPointer() , bv->GetLength() ); out.close(); #endif std::string fn = gdcm::LOComp::Trim( s0.c_str() ); // remove trailing space fn += ".sin"; std::ofstream sin( fn.c_str() ); const char *beg = bv->GetPointer(); const char *end = beg + bv->GetLength(); assert( *beg == 0 ); const char *p = beg + 1; // skip first \0 size_t prev = 0; for( ; p != end; ++p ) { if( *p == 0 ) { const char *s = beg + prev + 1; if( *s ) { sin << s << std::endl; } else { sin << std::endl; } prev = p - beg; } } sin.close(); ret = true; } else if( s1 == "BINARY" ) { std::cerr << "BINARY is not handled" << std::endl; std::string fn = gdcm::LOComp::Trim( s0.c_str() ); // remove trailing space fn += ".bin"; std::ofstream out( fn.c_str() ); //out.write( bv->GetPointer() + 512, bv->GetLength() - 512); out.write( bv->GetPointer() , bv->GetLength() ); out.close(); #if 0 int array[ 128 ]; memcpy( array, bv->GetPointer(), 512 ); for( int i = 0; i < 14; ++i ) { std::cout << array[i] << std::endl; } #endif ret = true; } } // else -> ret == false assert( ret ); return ret; } int main(int argc, char *argv[]) { if( argc < 2 ) return 1; const char *filename = argv[1]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); /* (2005,1132) SQ # u/l,1 ? (fffe,e000) na (Item with undefined length) (2005,0011) LO [Philips MR Imaging DD 002 ] # 26,1 Private Creator (2005,1137) PN (LO) [PDF_CONTROL_GEN_PARS] # 20,1 ? (2005,1138) PN (LO) (no value) # 0,1 ? (2005,1139) PN (LO) [IEEE_PDF] # 8,1 ? (2005,1140) PN (LO) (no value) # 0,1 ? (2005,1141) PN (LO) (no value) # 0,1 ? (2005,1143) SL 3103 # 4,1 ? (2005,1144) OW 66\05\00\00\3b\01\00\00\4a\0a\00\00\0e\00\00\00\7a\0a\00\00\95\01\00\00\08\00\00\00\1b\00\00\00\43\47\45\4e\5f\75\73\65\72\5f\64\65\66\5f\6b\65\79\5f\6e\61\6d\65\73\00\00\00\00\00\00\00\00\00 # 3104,1 ? (2005,1147) CS [Y ] # 2,1 ? (fffe,e00d) */ const gdcm::PrivateTag pt(0x2005,0x32,"Philips MR Imaging DD 002"); if( !ds.FindDataElement( pt ) ) return 1; const gdcm::DataElement &de = ds.GetDataElement( pt ); if( de.IsEmpty() ) return 1; gdcm::SequenceOfItems *sqi = de.GetValueAsSQ(); if ( !sqi ) return 1; gdcm::SequenceOfItems::SizeType s = sqi->GetNumberOfItems(); for( gdcm::SequenceOfItems::SizeType i = 1; i <= s; ++i ) { gdcm::Item &item = sqi->GetItem(i); gdcm::DataSet &nestedds = item.GetNestedDataSet(); if( !ProcessNested( nestedds ) ) { std::cerr << "Error processing Item #" << i << std::endl; } } return 0; } GDCM-3.0.10/Examples/Cxx/DumpGEMSMovieGroup.cxx000066400000000000000000000420541412732066400207610ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmImage.h" #include "gdcmImageWriter.h" #include "gdcmDataElement.h" #include "gdcmPrivateTag.h" #include "gdcmUIDGenerator.h" #include #include #include bool PrintNameValueMapping( gdcm::SequenceOfItems *sqi_values, gdcm::SequenceOfItems *sqi_names, std::string const & indent ) { using namespace gdcm; // prepare names mapping: typedef VRToType::Type UL; std::map< UL, std::string > names; assert( sqi_names ); assert( sqi_values ); SequenceOfItems::SizeType s = sqi_names->GetNumberOfItems(); PrivateTag tindex(0x7fe1,0x71,"GEMS_Ultrasound_MovieGroup_001"); PrivateTag tname (0x7fe1,0x72,"GEMS_Ultrasound_MovieGroup_001"); // First sequence contains all possible names (this is a dict) for( SequenceOfItems::SizeType i = 1; i <= s; ++i ) { const Item & item = sqi_names->GetItem( i ); const DataSet & ds = item.GetNestedDataSet(); if( !ds.FindDataElement( tindex ) || !ds.FindDataElement( tname ) ) { assert( 0 ); return false; } const DataElement & index = ds.GetDataElement( tindex ); const DataElement & name = ds.GetDataElement( tname ); if( index.IsEmpty() || name.IsEmpty() ) { assert( 0 ); return false; } gdcm::Element el1; el1.SetFromDataElement( index ); gdcm::Element el2; el2.SetFromDataElement( name ); // std::cout << el1.GetValue() << " " << el2.GetValue() << std::endl; names.insert( std::make_pair( el1.GetValue(), el2.GetValue() ) ); } SequenceOfItems::SizeType s2 = sqi_values->GetNumberOfItems(); assert( s2 <= s ); PrivateTag tindex2(0x7fe1,0x48,"GEMS_Ultrasound_MovieGroup_001"); for( SequenceOfItems::SizeType i = 1; i <= s2; ++i ) { const Item & item = sqi_values->GetItem( i ); const DataSet & ds = item.GetNestedDataSet(); if( !ds.FindDataElement( tindex2 ) ) { assert( 0 ); return false; } const DataElement & index2 = ds.GetDataElement( tindex2 ); if( index2.IsEmpty() ) { assert( 0 ); return false; } gdcm::Element el1; el1.SetFromDataElement( index2 ); UL copy = (UL)el1.GetValue(); #if 1 std::cout << indent; std::cout << "( " << names[ copy ]; #endif // (7fe1,1052) FD 1560 # 8,1 ? // (7fe1,1057) LT [MscSkelSup] # 10,1 ? //PrivateTag tvalue(0x7fe1,0x52,"GEMS_Ultrasound_MovieGroup_001"); PrivateTag tvalueint(0x7fe1,0x49,"GEMS_Ultrasound_MovieGroup_001"); // UL PrivateTag tvaluefloat1(0x7fe1,0x51,"GEMS_Ultrasound_MovieGroup_001"); // FL PrivateTag tvaluefloat(0x7fe1,0x52,"GEMS_Ultrasound_MovieGroup_001"); // FD PrivateTag tvalueul(0x7fe1,0x53,"GEMS_Ultrasound_MovieGroup_001"); // UL PrivateTag tvaluesl(0x7fe1,0x54,"GEMS_Ultrasound_MovieGroup_001"); // SL PrivateTag tvalueob(0x7fe1,0x55,"GEMS_Ultrasound_MovieGroup_001"); // OB PrivateTag tvaluetext(0x7fe1,0x57,"GEMS_Ultrasound_MovieGroup_001"); // LT PrivateTag tvaluefd(0x7fe1,0x77,"GEMS_Ultrasound_MovieGroup_001"); // FD / 1-N PrivateTag tvaluesl3(0x7fe1,0x79,"GEMS_Ultrasound_MovieGroup_001"); // SL / 1-N PrivateTag tvaluesl2(0x7fe1,0x86,"GEMS_Ultrasound_MovieGroup_001"); // SL ?? PrivateTag tvaluefd1(0x7fe1,0x87,"GEMS_Ultrasound_MovieGroup_001"); // FD / 1-N PrivateTag tvaluefloat2(0x7fe1,0x88,"GEMS_Ultrasound_MovieGroup_001"); // FD ?? #if 1 std::cout << " ) = "; #endif if( ds.FindDataElement( tvalueint ) ) { const DataElement & value = ds.GetDataElement( tvalueint ); gdcm::Element el2; el2.SetFromDataElement( value ); std::cout << el2.GetValue() << std::endl; } else if( ds.FindDataElement( tvaluefloat1 ) ) { const DataElement & value = ds.GetDataElement( tvaluefloat1 ); gdcm::Element el2; el2.SetFromDataElement( value ); std::cout << el2.GetValue() << std::endl; } else if( ds.FindDataElement( tvaluefloat ) ) { const DataElement & value = ds.GetDataElement( tvaluefloat ); gdcm::Element el2; el2.SetFromDataElement( value ); std::cout << el2.GetValue() << std::endl; } else if( ds.FindDataElement( tvaluesl ) ) { const DataElement & value = ds.GetDataElement( tvaluesl ); gdcm::Element el2; el2.SetFromDataElement( value ); std::cout << el2.GetValue() << std::endl; } else if( ds.FindDataElement( tvalueul ) ) { const DataElement & value = ds.GetDataElement( tvalueul ); gdcm::Element el2; el2.SetFromDataElement( value ); assert( el2.GetLength() == 1 ); std::cout << el2.GetValue() << std::endl; } else if( ds.FindDataElement( tvalueob ) ) { const DataElement & value = ds.GetDataElement( tvalueob ); // gdcm::Element el2; // el2.SetFromDataElement( value ); // std::cout << el2.GetValue() << std::endl; std::cout << value << std::endl; } else if( ds.FindDataElement( tvaluetext ) ) { const DataElement & value = ds.GetDataElement( tvaluetext ); gdcm::Element el2; el2.SetFromDataElement( value ); std::cout << el2.GetValue() << std::endl; } else if( ds.FindDataElement( tvaluesl2 ) ) { const DataElement & value = ds.GetDataElement( tvaluesl2 ); gdcm::Element el2; el2.SetFromDataElement( value ); el2.Print( std::cout ); assert( el2.GetLength() == 4 ); std::cout << std::endl; } else if( ds.FindDataElement( tvaluesl3 ) ) { const DataElement & value = ds.GetDataElement( tvaluesl3 ); gdcm::Element el2; el2.SetFromDataElement( value ); el2.Print( std::cout ); // assert( el2.GetLength() == 4 ); std::cout << std::endl; } else if( ds.FindDataElement( tvaluefd ) ) { const DataElement & value = ds.GetDataElement( tvaluefd ); gdcm::Element el2; el2.SetFromDataElement( value ); el2.Print( std::cout ); // assert( el2.GetLength() == 4 || el2.GetLength() == 3 || el2.GetLength() == 8 ); std::cout << std::endl; } else if( ds.FindDataElement( tvaluefloat2 ) ) { const DataElement & value = ds.GetDataElement( tvaluefloat2 ); gdcm::Element el2; el2.SetFromDataElement( value ); el2.Print( std::cout ); assert( el2.GetLength() == 2 ); std::cout << std::endl; } else if( ds.FindDataElement( tvaluefd1 ) ) { const DataElement & value = ds.GetDataElement( tvaluefd1 ); gdcm::Element el2; el2.SetFromDataElement( value ); el2.Print( std::cout ); assert( el2.GetLength() == 4 ); std::cout << std::endl; } else { std::cout << "(no value)" << std::endl; // std::cout << ds << std::endl; assert( ds.Size() == 2 ); } } return true; } bool PrintNameValueMapping2( gdcm::PrivateTag const & privtag, const gdcm::DataSet & ds , gdcm::SequenceOfItems *sqi_names, std::string const & indent ) { if( !ds.FindDataElement( privtag ) ) return false; const gdcm::DataElement& seq_values = ds.GetDataElement( privtag ); gdcm::SmartPointer sqi = seq_values.GetValueAsSQ(); return PrintNameValueMapping( sqi, sqi_names, indent); } bool PrintNameValueMapping3( gdcm::PrivateTag const & privtag1, gdcm::PrivateTag const & privtag2, const gdcm::DataSet & ds , gdcm::SequenceOfItems *sqi_names, std::string const & indent ) { if( !ds.FindDataElement( privtag1 ) ) { assert( 0 ); return false; } const gdcm::DataElement& values10name = ds.GetDataElement( privtag1 ); gdcm::Element el; el.SetFromDataElement( values10name ); std::cout << std::endl; std::cout << " <" << el.GetValue().c_str() << ">" << std::endl; return PrintNameValueMapping2( privtag2, ds, sqi_names, indent); } bool print73( gdcm::DataSet const & ds10, gdcm::SequenceOfItems *sqi_dict, std::string const & indent ) { const gdcm::PrivateTag tseq_values73(0x7fe1,0x73,"GEMS_Ultrasound_MovieGroup_001"); if( !ds10.FindDataElement( tseq_values73 ) ) { std::cout << indent << "No group 73" << std::endl; return false; } const gdcm::DataElement& seq_values73 = ds10.GetDataElement( tseq_values73 ); gdcm::SmartPointer sqi_values73 = seq_values73.GetValueAsSQ(); size_t ni3 = sqi_values73->GetNumberOfItems(); for( size_t i3 = 1; i3 <= ni3; ++i3 ) { gdcm::Item &item_73 = sqi_values73->GetItem(i3); gdcm::DataSet &ds73 = item_73.GetNestedDataSet(); assert( ds73.Size() == 3 ); const gdcm::PrivateTag tseq_values74name(0x7fe1,0x74,"GEMS_Ultrasound_MovieGroup_001"); const gdcm::PrivateTag tseq_values75(0x7fe1,0x75,"GEMS_Ultrasound_MovieGroup_001"); PrintNameValueMapping3( tseq_values74name, tseq_values75, ds73, sqi_dict, indent); std::cout << std::endl; } return true; } bool print36( gdcm::DataSet const & ds10, gdcm::SequenceOfItems *sqi_dict, std::string const & indent ) { (void)sqi_dict; const gdcm::PrivateTag tseq_values36(0x7fe1,0x36,"GEMS_Ultrasound_MovieGroup_001"); if( !ds10.FindDataElement( tseq_values36 ) ) { std::cout << indent << "No group 36" << std::endl; return false; } const gdcm::DataElement& seq_values36 = ds10.GetDataElement( tseq_values36 ); gdcm::SmartPointer sqi_values36 = seq_values36.GetValueAsSQ(); size_t ni3 = sqi_values36->GetNumberOfItems(); assert( ni3 >= 1 ); for( size_t i3 = 1; i3 <= ni3; ++i3 ) { gdcm::Item &item_36 = sqi_values36->GetItem(i3); gdcm::DataSet &ds36 = item_36.GetNestedDataSet(); assert( ds36.Size() == 4 ); // (7fe1,1037) UL 47 # 4,1 US MovieGroup Number of Frames // (7fe1,1043) OB 40\00\1c\c4\67\2f\0b\11\40 # 376,1 ? // (7fe1,1060) OB 4e\4e\49\4f\4e\47\46\43\2a # 4562714,1 US MovieGroup Image Data // const gdcm::PrivateTag timagedata(0x7fe1,0x60,"GEMS_Ultrasound_MovieGroup_001"); assert( ds36.FindDataElement( timagedata ) ); gdcm::DataElement const & imagedata = ds36.GetDataElement( timagedata ); const gdcm::ByteValue * bv = imagedata.GetByteValue(); assert( bv ); static int c = 0; std::stringstream ss; ss << "/tmp/debug"; ss << c++; std::ofstream os( ss.str().c_str(), std::ios::binary ); os.write( bv->GetPointer(), bv->GetLength() ); os.close(); //const gdcm::PrivateTag tseq_values85(0x7fe1,0x85,"GEMS_Ultrasound_MovieGroup_001"); //PrintNameValueMapping3( tseq_values84name, tseq_values85, ds83, sqi_dict, indent); //std::cout << std::endl; } return true; } bool print83( gdcm::DataSet const & ds10, gdcm::SequenceOfItems *sqi_dict, std::string const & indent ) { const gdcm::PrivateTag tseq_values83(0x7fe1,0x83,"GEMS_Ultrasound_MovieGroup_001"); if( !ds10.FindDataElement( tseq_values83 ) ) { std::cout << indent << "No group 83" << std::endl; return false; } const gdcm::DataElement& seq_values83 = ds10.GetDataElement( tseq_values83 ); gdcm::SmartPointer sqi_values83 = seq_values83.GetValueAsSQ(); size_t ni3 = sqi_values83->GetNumberOfItems(); for( size_t i3 = 1; i3 <= ni3; ++i3 ) { gdcm::Item &item_83 = sqi_values83->GetItem(i3); gdcm::DataSet &ds83 = item_83.GetNestedDataSet(); assert( ds83.Size() == 3 ); const gdcm::PrivateTag tseq_values84name(0x7fe1,0x84,"GEMS_Ultrasound_MovieGroup_001"); const gdcm::PrivateTag tseq_values85(0x7fe1,0x85,"GEMS_Ultrasound_MovieGroup_001"); PrintNameValueMapping3( tseq_values84name, tseq_values85, ds83, sqi_dict, indent); std::cout << std::endl; } return true; } bool PrintNameValueMapping4( gdcm::PrivateTag const & privtag0, const gdcm::DataSet & subds, gdcm::PrivateTag const & privtag1, gdcm::PrivateTag const & privtag2, gdcm::SequenceOfItems *sqi_dict, std::string const & indent ) { (void)indent; if( !subds.FindDataElement( privtag0 ) ) { assert( 0 ); return false; } const gdcm::DataElement& seq_values10 = subds.GetDataElement( privtag0 ); gdcm::SmartPointer sqi_values10 = seq_values10.GetValueAsSQ(); size_t ni1 = sqi_values10->GetNumberOfItems(); // assert( ni1 == 1 ); for( size_t i1 = 1; i1 <= ni1; ++i1 ) { gdcm::Item &item_10 = sqi_values10->GetItem(i1); gdcm::DataSet &ds10 = item_10.GetNestedDataSet(); assert( ds10.Size() == 2 + 3 ); // (7fe1,0010) // (7fe1,1012) // (7fe1,1018) // (7fe1,1020) // (7fe1,1083) PrintNameValueMapping3( privtag1, privtag2, ds10, sqi_dict, " " ); std::cout << std::endl; const gdcm::PrivateTag tseq_values20(0x7fe1,0x20,"GEMS_Ultrasound_MovieGroup_001"); if( !ds10.FindDataElement( tseq_values20 ) ) { assert( 0 ); return false; } const gdcm::DataElement& seq_values20 = ds10.GetDataElement( tseq_values20 ); gdcm::SmartPointer sqi_values20 = seq_values20.GetValueAsSQ(); size_t ni2 = sqi_values20->GetNumberOfItems(); //assert( ni == 1 ); for( size_t i2 = 1; i2 <= ni2; ++i2 ) { gdcm::Item &item_20 = sqi_values20->GetItem(i2); gdcm::DataSet &ds20 = item_20.GetNestedDataSet(); size_t count = ds20.Size(); (void)count; assert( ds20.Size() == 2 + 3 || ds20.Size() == 2 + 2 ); // (7fe1,0010) // (7fe1,1024) // (7fe1,1026) // (7fe1,1036) // (7fe1,103a) // (7fe1,1083) (*) const gdcm::PrivateTag tseq_values20name(0x7fe1,0x24,"GEMS_Ultrasound_MovieGroup_001"); const gdcm::PrivateTag tseq_values26(0x7fe1,0x26,"GEMS_Ultrasound_MovieGroup_001"); PrintNameValueMapping3( tseq_values20name, tseq_values26, ds20, sqi_dict, " "); std::cout << std::endl; print36(ds20, sqi_dict, " "); print83(ds20, sqi_dict, " "); } print83(ds10, sqi_dict, " "); } return true; } int main(int argc, char *argv[]) { if( argc < 2 ) return 1; using namespace gdcm; const char *filename = argv[1]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) return 1; gdcm::File &file = reader.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); const PrivateTag tseq(0x7fe1,0x1,"GEMS_Ultrasound_MovieGroup_001"); if( !ds.FindDataElement( tseq ) ) return 1; const DataElement& seq = ds.GetDataElement( tseq ); SmartPointer sqi = seq.GetValueAsSQ(); assert( sqi->GetNumberOfItems() == 1 ); Item &item = sqi->GetItem(1); DataSet &subds = item.GetNestedDataSet(); const PrivateTag tseq_dict(0x7fe1,0x70,"GEMS_Ultrasound_MovieGroup_001"); if( !subds.FindDataElement( tseq_dict ) ) return 1; const DataElement& seq_dict = subds.GetDataElement( tseq_dict ); SmartPointer sqi_dict = seq_dict.GetValueAsSQ(); const PrivateTag tseq_values8(0x7fe1,0x8,"GEMS_Ultrasound_MovieGroup_001"); if( !subds.FindDataElement( tseq_values8 ) ) return 1; const DataElement& seq_values8 = subds.GetDataElement( tseq_values8 ); SmartPointer sqi_values8 = seq_values8.GetValueAsSQ(); const PrivateTag tseq_values8name(0x7fe1,0x2,"GEMS_Ultrasound_MovieGroup_001"); if( !subds.FindDataElement( tseq_values8name ) ) return 1; const DataElement& values8name = subds.GetDataElement( tseq_values8name ); { Element el; el.SetFromDataElement( values8name ); std::cout << el.GetValue() << std::endl; } size_t count = subds.Size(); (void)count; assert( subds.Size() == 3 + 2 + 1 || subds.Size() == 3 + 2 + 2); // (7fe1,0010) # 30,1 Private Creator // (7fe1,1002) # 8,1 US MovieGroup Value 0008 Name // (7fe1,1003) # 4,1 ? // (7fe1,1008) # 8140,1 US MovieGroup Value 0008 Sequence // (7fe1,1010) # 1372196,1 ? // (7fe1,1070) # 33684,1 US MovieGroup Dict // (7fe1,1073) (*) PrintNameValueMapping( sqi_values8, sqi_dict, " "); const PrivateTag tseq_values10(0x7fe1,0x10,"GEMS_Ultrasound_MovieGroup_001"); const PrivateTag tseq_values10name(0x7fe1,0x12,"GEMS_Ultrasound_MovieGroup_001"); const PrivateTag tseq_values18(0x7fe1,0x18,"GEMS_Ultrasound_MovieGroup_001"); PrintNameValueMapping4( tseq_values10, subds, tseq_values10name, tseq_values18, sqi_dict," "); print73( subds, sqi_dict, " " ); #if 0 gdcm::DataSet::ConstIterator it = subds.Begin(); for( ; it != subds.End(); ++it ) { const gdcm::DataElement &de = *it; std::cout << de.GetTag() << std::endl; } #endif return 0; } GDCM-3.0.10/Examples/Cxx/DumpImageHeaderInfo.cxx000066400000000000000000000112761412732066400211620ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Dump TOSHIBA MDW HEADER / Image Header Info */ #include "gdcmReader.h" #include "gdcmPrivateTag.h" #include "gdcmAttribute.h" #include "gdcmImageWriter.h" #include #include #include #include #include #include struct element { std::istream & read( std::istream & is ); }; std::istream & element::read( std::istream & is ) { static const uint32_t ref = 0xe000fffe; std::ostream &os = std::cout; if( is.eof() ) { return is; } uint32_t magic; if( !is.read( (char*)&magic, sizeof(magic) ) ) { return is; } //os << magic << std::endl; assert( magic == ref ); (void)ref; uint32_t l; is.read( (char*)&l, sizeof(l) ); //os << l << std::endl; char str[17]; str[16] = 0; is.read( str, 16 ); os << str << " (" << l << ")" << std::endl; std::vector bytes; bytes.resize( l - 16 ); if( !bytes.empty() ) { is.read( &bytes[0], l - 16 ); } //os << "pos:" << is.tellg() << std::endl; if( strcmp(str, "TUSREMEASUREMENT" ) == 0 ) { const char *p = &bytes[0]; uint32_t val; memcpy( (char*)&val, p, sizeof(val) ); os << " " << val << std::endl; p += sizeof(val); memcpy( (char*)&val, p, sizeof(val) ); os << " " << val << std::endl; p += sizeof(val); memcpy( (char*)&val, p, sizeof(val) ); os << " " << val << std::endl; p += sizeof(val); memcpy( (char*)&val, p, sizeof(val) ); os << " " << val << std::endl; p += sizeof(val); memcpy( (char*)&val, p, sizeof(val) ); os << " " << val << std::endl; p += sizeof(val); memcpy( (char*)&val, p, sizeof(val) ); os << " " << val << std::endl; p += sizeof(val); #if 0 float f; memcpy( (char*)&f, p, sizeof(f) ); os << " " << f << std::endl; p += sizeof(f); #else memcpy( (char*)&val, p, sizeof(val) ); os << " " << val << std::endl; p += sizeof(val); #endif memcpy( (char*)&val, p, sizeof(val) ); os << " " << val << std::endl; p += sizeof(val); char str2[17]; memcpy( str2, p, 16 ); str2[16] = 0; os << " " << str2 << std::endl; } #if 0 std::ofstream out( str, std::ios::binary ); out.write( (char*)&magic, sizeof( magic ) ); out.write( (char*)&l, sizeof( l ) ); out.write( str, 16 ); out.write( &bytes[0], bytes.size() ); #endif return is; } static bool DumpImageHeaderInfo( std::istream & is, size_t reflen ) { // TUSNONIMAGESTAM (5176) // TUSREMEASUREMEN (1352) // TUSBSINGLELAYOU (16) // TUSCLIPPARAMETE (104) element el; while( el.read( is ) ) { } //size_t pos = is.tellg(); //assert( pos == reflen ); (void)reflen; return true; } int main(int argc, char *argv[]) { if( argc < 2 ) return 1; const char *filename = argv[1]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); const gdcm::PrivateTag timageheaderinfo(0x0029,0x10,"TOSHIBA MDW HEADER"); if( !ds.FindDataElement( timageheaderinfo) ) return 1; const gdcm::DataElement& imageheaderinfo = ds.GetDataElement( timageheaderinfo ); if ( imageheaderinfo.IsEmpty() ) return 1; const gdcm::ByteValue * bv = imageheaderinfo.GetByteValue(); std::istringstream is; std::string dup( bv->GetPointer(), bv->GetLength() ); is.str( dup ); bool b = DumpImageHeaderInfo( is, bv->GetLength() ); if( !b ) return 1; #if 0 const float d1 = 0.0041666668839752674; // 89 88 88 3B // 0x44c //const float d1 = 0.053231674455417881; const float d2 = 0.10828025639057159; // 0A C2 DD 3D // 0x1ac //const float d1 = 0.17869562069272813; //const unsigned int d2 = 4294967280; const float d3 = 0.10828025639057159; // 0A C2 DD 3D // 0x15c const int32_t d4 = 134; const uint32_t d5 = 1153476; std::ofstream t("/tmp/debug", std::ios::binary ); //t.write( (char*)&d0, sizeof( d0 ) ); t.write( (char*)&d1, sizeof( d1 ) ); t.write( (char*)&d2, sizeof( d2 ) ); t.write( (char*)&d3, sizeof( d3 ) ); t.write( (char*)&d4, sizeof( d4 ) ); t.write( (char*)&d5, sizeof( d5 ) ); t.close(); #endif return 0; } GDCM-3.0.10/Examples/Cxx/DumpPhilipsECHO.cxx000066400000000000000000000316501412732066400202600ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmDeflateStream.h" #include "gdcm_zlib.h" /* * This example extract the ZLIB compressed US image from a Philips private tag * * Everything done in this code is for the sole purpose of writing interoperable * software under Sect. 1201 (f) Reverse Engineering exception of the DMCA. * If you believe anything in this code violates any law or any of your rights, * please contact us (gdcm-developers@lists.sourceforge.net) so that we can * find a solution. * * Everything you do with this code is at your own risk, since decompression * algorithm was not written from specification documents. * * Usage: * * $ DumpPhilipsECHO private_us.dcm raw_us_img.raw * $ gdcmimg --sop-class-uid 1.2.840.10008.5.1.4.1.1.3.1 --size 608,427,88 raw_us_img.raw raw_us_img.dcm */ // header: struct hframe { uint32_t val0; // 800 increment ? uint16_t val1[2]; uint16_t val2[2]; uint32_t imgsize; bool operator==(const hframe &h) const { return val0 == h.val0 && val1[0] == h.val1[0] && val1[1] == h.val1[1] && val2[0] == h.val2[0] && val2[1] == h.val2[1] && imgsize == h.imgsize; } }; static bool ProcessDeflate( const char *outfilename, const int nslices, const int buf_size, const char *buf, const std::streampos len, const char *crcbuf, const size_t crclen ) { std::vector< hframe > crcheaders; crcheaders.reserve( nslices ); { std::istringstream is; is.str( std::string( crcbuf, crclen ) ); hframe header; for( int r = 0; r < nslices; ++r ) { is.read( (char*)&header, sizeof( header )); #if 0 std::cout << header.val0 << " " << header.val1[0] << " " << header.val1[1] << " " << header.val2[0] << " " << header.val2[1] << " " << header.imgsize << std::endl; #endif crcheaders.push_back( header ); } } std::istringstream is; is.str( std::string( buf, (size_t)len ) ); std::streamoff totalsize; is.read( (char*)&totalsize, sizeof( totalsize )); assert( totalsize == len ); uint32_t nframes; is.read( (char*)&nframes, sizeof( nframes )); assert( nframes == (uint32_t)nslices ); std::vector< std::streamoff > offsets; offsets.reserve( nframes ); for( uint32_t frame = 0; frame < nframes ; ++frame ) { uint32_t offset; is.read( (char*)&offset, sizeof( offset )); offsets.push_back( offset ); } std::vector outbuf; const int size[2] = { 608, 427 }; // FIXME: where does it comes from ? std::stringstream ss; ss << outfilename; ss << '_'; //ss << crcheaders[0].imgsize; // FIXME: Assume all header are identical ! ss << size[0]; ss << '_'; ss << size[1]; ss << '_'; ss << nframes; ss << ".raw"; std::ofstream os( ss.str().c_str(), std::ios::binary ); assert( buf_size >= size[0] * size[1] ); outbuf.resize( buf_size ); hframe header; //uint32_t prev = 0; for( unsigned int r = 0; r < nframes; ++r ) { is.read( (char*)&header, sizeof( header )); assert( header == crcheaders[r] ); assert( header.val1[0] == 2000 ); assert( header.val1[1] == 3 ); assert( header.val2[0] == 1 ); assert( header.val2[1] == 1280 ); uLongf destLen = buf_size; // >= 608,427 Bytef *dest = (Bytef*)&outbuf[0]; assert( is.tellg() == offsets[r] + 16 ); const Bytef *source = (const Bytef*)buf + offsets[r] + 16; uLong sourceLen; if( r + 1 == nframes ) sourceLen = (uLong)totalsize - (uLong)offsets[r] - 16; else sourceLen = (uLong)offsets[r+1] - (uLong)offsets[r] - 16; // FIXME: in-memory decompression: int ret = uncompress (dest, &destLen, source, sourceLen); assert( ret == Z_OK ); (void)ret; assert( destLen >= (uLongf)size[0] * size[1] ); // 16bytes padding ? assert( header.imgsize == (uint32_t)size[0] * size[1] ); //os.write( &outbuf[0], outbuf.size() ); os.write( &outbuf[0], size[0] * size[1] ); // skip data: is.seekg( sourceLen, std::ios::cur ); } os.close(); assert( is.tellg() == totalsize ); return true; } static bool ProcessNone( const char *outfilename, const int nslices, const int buf_size, const char *buf, const std::streampos len, const char *crcbuf, const size_t crclen ) { std::vector< hframe > crcheaders; crcheaders.reserve( nslices ); { std::istringstream is; is.str( std::string( crcbuf, crclen ) ); hframe header; for( int r = 0; r < nslices; ++r ) { is.read( (char*)&header, sizeof( header )); #if 0 std::cout << header.val0 << " " << header.val1[0] << " " << header.val1[1] << " " << header.val2[0] << " " << header.val2[1] << " " << header.imgsize << std::endl; #endif crcheaders.push_back( header ); } } std::istringstream is; is.str( std::string( buf, (size_t)len ) ); std::streampos totalsize; is.read( (char*)&totalsize, sizeof( totalsize )); assert( totalsize == len ); uint32_t nframes; is.read( (char*)&nframes, sizeof( nframes )); assert( nframes == (uint32_t)nslices ); std::vector< uint32_t > offsets; offsets.reserve( nframes ); for( uint32_t frame = 0; frame < nframes ; ++frame ) { uint32_t offset; is.read( (char*)&offset, sizeof( offset )); offsets.push_back( offset ); //std::cout << offset << std::endl; } std::vector outbuf; // No idea how to present the data, I'll just append everything, and present it as 2D std::stringstream ss; ss << outfilename; ss << '_'; ss << crcheaders[0].imgsize; // FIXME: Assume all header are identical ! ss << '_'; ss << nframes; ss << ".raw"; std::ofstream os( ss.str().c_str(), std::ios::binary ); outbuf.resize( buf_size ); // overallocated + 16 char *buffer = &outbuf[0]; hframe header; for( unsigned int r = 0; r < nframes; ++r ) { is.read( (char*)&header, sizeof( header )); #if 0 std::cout << header.val0 << " " << header.val1[0] << " " << header.val1[1] << " " << header.val2[0] << " " << header.val2[1] << " " << header.imgsize << std::endl; #endif assert( header == crcheaders[r] ); is.read( buffer, buf_size - 16 ); os.write( buffer, header.imgsize ); } assert( is.tellg() == totalsize ); os.close(); return true; } #ifndef NDEBUG static const char * const UDM_USD_DATATYPE_STRINGS[] = { "UDM_USD_DATATYPE_DIN_2D_ECHO", "UDM_USD_DATATYPE_DIN_2D_ECHO_CONTRAST", "UDM_USD_DATATYPE_DIN_DOPPLER_CW", "UDM_USD_DATATYPE_DIN_DOPPLER_PW", "UDM_USD_DATATYPE_DIN_DOPPLER_PW_TDI", "UDM_USD_DATATYPE_DIN_2D_COLOR_FLOW", "UDM_USD_DATATYPE_DIN_2D_COLOR_PMI", "UDM_USD_DATATYPE_DIN_2D_COLOR_CPA", "UDM_USD_DATATYPE_DIN_2D_COLOR_TDI", "UDM_USD_DATATYPE_DIN_MMODE_ECHO", "UDM_USD_DATATYPE_DIN_MMODE_COLOR", "UDM_USD_DATATYPE_DIN_MMODE_COLOR_TDI", "UDM_USD_DATATYPE_DIN_PARAM_BLOCK", "UDM_USD_DATATYPE_DIN_2D_COLOR_VELOCITY", "UDM_USD_DATATYPE_DIN_2D_COLOR_POWER", "UDM_USD_DATATYPE_DIN_2D_COLOR_VARIANCE", "UDM_USD_DATATYPE_DIN_DOPPLER_AUDIO", "UDM_USD_DATATYPE_DIN_DOPPLER_HIGHQ", "UDM_USD_DATATYPE_DIN_PHYSIO", "UDM_USD_DATATYPE_DIN_2D_COLOR_STRAIN", "UDM_USD_DATATYPE_DIN_COMPOSITE_RGB", "UDM_USD_DATATYPE_DIN_XFOV_REALTIME_GRAPHICS", "UDM_USD_DATATYPE_DIN_XFOV_MOSAIC", "UDM_USD_DATATYPE_DIN_COMPOSITE_R", "UDM_USD_DATATYPE_DIN_COMPOSITE_G", "UDM_USD_DATATYPE_DIN_COMPOSITE_B", "UDM_USD_DATATYPE_DIN_MMODE_COLOR_VELOCITY", "UDM_USD_DATATYPE_DIN_MMODE_COLOR_POWER", "UDM_USD_DATATYPE_DIN_MMODE_COLOR_VARIANCE", "UDM_USD_DATATYPE_DIN_2D_ELASTO", }; static inline bool is_valid( const char * datatype_str ) { static const int n = sizeof( UDM_USD_DATATYPE_STRINGS ) / sizeof( *UDM_USD_DATATYPE_STRINGS ); bool found = false; if( datatype_str ) { for( int i = 0; !found && i < n; ++i ) { found = strcmp( datatype_str, UDM_USD_DATATYPE_STRINGS[i] ) == 0; } } return found; } #endif int main(int argc, char *argv[]) { if( argc < 2 ) return 1; using namespace gdcm; const char *filename = argv[1]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) return 1; gdcm::File &file = reader.GetFile(); gdcm::DataSet &ds1 = file.GetDataSet(); const PrivateTag tseq1(0x200d,0x3cf8,"Philips US Imaging DD 045"); if( !ds1.FindDataElement( tseq1 ) ) return 1; const DataElement& seq1 = ds1.GetDataElement( tseq1 ); SmartPointer sqi1 = seq1.GetValueAsSQ(); assert( sqi1->GetNumberOfItems() >= 1 ); const size_t nitems = sqi1->GetNumberOfItems(); for( size_t item = 1; item < nitems; ++item ) { Item &item1 = sqi1->GetItem(item); DataSet &ds2 = item1.GetNestedDataSet(); // (200d,300d) LO 28 UDM_USD_DATATYPE_DIN_2D_ECHO const PrivateTag tdatatype(0x200d,0x300d,"Philips US Imaging DD 033"); if( !ds2.FindDataElement( tdatatype ) ) return 1; const DataElement& datatype = ds2.GetDataElement( tdatatype ); const ByteValue *bvdatatype = datatype.GetByteValue(); if( !bvdatatype ) return 1; const PrivateTag tseq2(0x200d,0x3cf1,"Philips US Imaging DD 045"); if( !ds2.FindDataElement( tseq2 ) ) return 1; const DataElement& seq2 = ds2.GetDataElement( tseq2 ); SmartPointer sqi2 = seq2.GetValueAsSQ(); assert( sqi2->GetNumberOfItems() >= 1 ); // FIXME: what if not in first Item ? assert( sqi2->GetNumberOfItems() == 1 ); Item &item2 = sqi2->GetItem(1); DataSet &ds3 = item2.GetNestedDataSet(); const PrivateTag tzlib(0x200d,0x3cfa,"Philips US Imaging DD 045"); if( !ds3.FindDataElement( tzlib ) ) return 1; const DataElement& zlib = ds3.GetDataElement( tzlib ); const ByteValue *bv = zlib.GetByteValue(); if( !bv ) return 1; if( bv->GetLength() != 4 ) return 1; // (200d,3010) IS 2 88 const PrivateTag tnslices(0x200d,0x3010,"Philips US Imaging DD 033"); if( !ds3.FindDataElement( tnslices ) ) return 1; const DataElement& nslices = ds3.GetDataElement( tnslices ); Element elnslices; elnslices.SetFromDataElement( nslices ); const int nslicesref = elnslices.GetValue(); assert( nslicesref >= 0 ); // (200d,3011) IS 6 259648 const PrivateTag tzalloc(0x200d,0x3011,"Philips US Imaging DD 033"); if( !ds3.FindDataElement( tzalloc ) ) return 1; const DataElement& zalloc = ds3.GetDataElement( tzalloc ); Element elzalloc; elzalloc.SetFromDataElement( zalloc ); const int zallocref = elzalloc.GetValue(); assert( zallocref >= 0 ); // (200d,3021) IS 2 0 const PrivateTag tzero(0x200d,0x3021,"Philips US Imaging DD 033"); if( !ds3.FindDataElement( tzero ) ) return 1; const DataElement& zero = ds3.GetDataElement( tzero ); Element elzero; elzero.SetFromDataElement( zero ); const int zerocref = elzero.GetValue(); assert( zerocref == 0 ); (void)zerocref; // (200d,3cf3) OB const PrivateTag tdeflate(0x200d,0x3cf3,"Philips US Imaging DD 045"); if( !ds3.FindDataElement( tdeflate) ) return 1; const DataElement& deflate = ds3.GetDataElement( tdeflate ); const ByteValue *bv2 = deflate.GetByteValue(); // (200d,3cfb) OB const PrivateTag tcrc(0x200d,0x3cfb,"Philips US Imaging DD 045"); if( !ds3.FindDataElement( tcrc ) ) return 1; const DataElement& crc = ds3.GetDataElement( tcrc ); const ByteValue *bv3 = crc.GetByteValue(); std::string outfile = std::string( bvdatatype->GetPointer(), bvdatatype->GetLength() ); outfile = LOComp::Trim( outfile.c_str() ); const char *outfilename = outfile.c_str(); assert( is_valid(outfilename) ); if( bv2 ) { assert( bv3 ); assert( zallocref > 0 ); assert( nslicesref > 0 ); std::cout << ds2 << std::endl; if( strncmp(bv->GetPointer(), "ZLib", 4) == 0 ) { if( !ProcessDeflate( outfilename, nslicesref, zallocref, bv2->GetPointer(), std::streampos(bv2->GetLength()), bv3->GetPointer(), bv3->GetLength() ) ) { return 1; } } else if( strncmp(bv->GetPointer(), "None", 4) == 0 ) { if( !ProcessNone( outfilename, nslicesref, zallocref, bv2->GetPointer(), std::streampos(bv2->GetLength()), bv3->GetPointer(), bv3->GetLength() ) ) { return 1; } } else { std::string str( bv->GetPointer(), bv->GetLength() ); std::cerr << "Unhandled: " << str << std::endl; return 1; } } } return 0; } GDCM-3.0.10/Examples/Cxx/DumpSiemensBase64.cxx000066400000000000000000000047571412732066400205710ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * https://groups.google.com/forum/#!msg/comp.protocols.dicom/2kZ2lLP8EcM/WzjFrtjnAgAJ */ #include "gdcmReader.h" #include "gdcmPrivateTag.h" #include "gdcmPrinter.h" #include "gdcmDictPrinter.h" #include "gdcmCSAHeader.h" #include "gdcmBase64.h" #include "gdcmExplicitDataElement.h" #include "gdcmSwapper.h" #include "gdcmPrinter.h" #include #include #include #include int main(int argc, char *argv[]) { if( argc < 2 ) return 1; const char *filename = argv[1]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); gdcm::CSAHeader csa; const gdcm::PrivateTag &t1 = csa.GetCSAImageHeaderInfoTag(); if( !ds.FindDataElement( t1 ) ) return 1; csa.LoadFromDataElement( ds.GetDataElement( t1 ) ); //const char name[] = "MRDiffusion"; const char name[] = "MR_ASL"; if( csa.FindCSAElementByName(name) ) { const gdcm::CSAElement & el = csa.GetCSAElementByName(name); const gdcm::ByteValue* bv = el.GetByteValue(); std::string str( bv->GetPointer(), bv->GetLength() ); str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); size_t dl = gdcm::Base64::GetDecodeLength( str.c_str(), str.size() ); std::vector buf; buf.resize( dl ); size_t dl2 = gdcm::Base64::Decode( &buf[0], buf.size(), str.c_str(), str.size() ); (void)dl2; std::stringstream ss; ss.str( std::string(&buf[0], buf.size()) ); gdcm::File file; gdcm::DataSet &ds2 = file.GetDataSet(); gdcm::DataElement xde; try { while( xde.Read( ss ) ) { ds2.Insert( xde ); } assert( ss.eof() ); } catch(std::exception &) { return 1; } gdcm::Printer p; p.SetFile( file ); p.Print(std::cout); } return 0; } GDCM-3.0.10/Examples/Cxx/DumpToSQLITE3.cxx000066400000000000000000000074621412732066400176040ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Ref: * http://massmail.spl.harvard.edu/public-archives/slicer-devel/2010/004408.html * * Implementation details: * http://www.sqlite.org/c3ref/bind_blob.html * http://www.adp-gmbh.ch/sqlite/bind_insert.html */ #include "gdcmScanner.h" #include "gdcmDirectory.h" #include "gdcmTag.h" #include "gdcmTrace.h" #include "sqlite3.h" #include #include int main(int argc, char *argv[]) { if( argc < 2 ) { return 1; } time_t time_start = time(nullptr); gdcm::Trace::SetDebug( false ); gdcm::Trace::SetWarning( false ); const char *inputdirectory = argv[1]; gdcm::Directory d; unsigned int nfiles = d.Load( inputdirectory, true); gdcm::Scanner s; using gdcm::Tag; s.AddTag( Tag(0x20,0xd) ); // Study Instance UID s.AddTag( Tag(0x20,0xe) ); // Series Instance UID bool b0 = s.Scan( d.GetFilenames() ); if( !b0 ) return 1; time_t time_scanner = time(nullptr); std::cout << "Finished loading data from : " << nfiles << " files" << std::endl; // MappingType const &mappings = s.GetMappings(); sqlite3* db; sqlite3_open("./dicom.db", &db); if(db == nullptr) { std::cerr << "Could not open database." << std::endl; return 1; } const char sql_stmt[] = "create table browser (seriesuid, studyuid)"; int ret; char *errmsg; ret = sqlite3_exec(db, sql_stmt, nullptr, nullptr, &errmsg); if(ret != SQLITE_OK) { printf("Error in statement: %s [%s].\n", sql_stmt, errmsg); return 1; } using gdcm::Directory; using gdcm::Scanner; const Directory::FilenamesType& files = d.GetFilenames(); Directory::FilenamesType::const_iterator file = files.begin(); sqlite3_stmt *stmt; if ( sqlite3_prepare( db, "insert into browser values (?,?)", // stmt -1, // If than zero, then stmt is read up to the first nul terminator &stmt, nullptr // Pointer to unused portion of stmt ) != SQLITE_OK) { printf("\nCould not prepare statement."); return 1; } //printf("\nThe statement has %d wildcards\n", sqlite3_bind_parameter_count(stmt)); for(; file != files.end(); ++file) { const char *filename = file->c_str(); bool b = s.IsKey(filename); if( b ) { const Scanner::TagToValue &mapping = s.GetMapping(filename); Scanner::TagToValue::const_iterator it = mapping.begin(); sqlite3_reset(stmt); for( int index = 1; it != mapping.end(); ++it, ++index) { //const Tag & tag = it->first; const char *value = it->second; if (sqlite3_bind_text ( stmt, index, // Index of wildcard value, (int)strlen(value), // length of text SQLITE_STATIC // SQLite assumes that the information is in static ) != SQLITE_OK) { printf("\nCould not bind int.\n"); return 1; } } if (sqlite3_step(stmt) != SQLITE_DONE) { printf("\nCould not step (execute) stmt.\n"); return 1; } } } sqlite3_close(db); time_t time_sqlite = time(nullptr); std::cout << "Time to scan DICOM files: " << (time_scanner - time_start) << std::endl; std::cout << "Time to build SQLITE3: " << (time_sqlite - time_scanner) << std::endl; return 0; } GDCM-3.0.10/Examples/Cxx/DumpToshibaDTI.cxx000066400000000000000000000063021412732066400201370ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * https://groups.google.com/d/msg/comp.protocols.dicom/7IaIkT0ZG5U/k7LPu81VvAMJ */ #include "gdcmReader.h" #include "gdcmPrivateTag.h" #include "gdcmPrinter.h" #include "gdcmDictPrinter.h" #include #include #include #include static bool DumpToshibaDTI( const char * input, size_t len ) { static int i = 0; ++i; if( len % 2 ) return false; std::vector copy( input, input + len ); std::reverse( copy.begin(), copy.end() ); #if 0 std::ostringstream f; f << "debug" << i; std::ofstream of( f.str().c_str(), std::ios::binary ); of.write( ©[0], copy.size() ); of.close(); #else std::istringstream is; std::string dup( ©[0], copy.size() ); is.str( dup ); gdcm::File file; gdcm::FileMetaInformation & fmi = file.GetHeader(); fmi.SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); gdcm::DataSet & ds = file.GetDataSet(); ds.Read( is ); //gdcm::DictPrinter p; gdcm::Printer p; p.SetFile( file ); p.SetColor( true ); p.Print( std::cout ); #endif return true; } int main(int argc, char *argv[]) { if( argc < 2 ) return 1; const char *filename = argv[1]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); // (0029,0010) ?? (LO) [PMTF INFORMATION DATA ] # 22,1 Private Creator // (0029,1001) ?? (SQ) (Sequence with undefined length) # u/l,1 ? const gdcm::PrivateTag tpmtf(0x0029,0x1,"PMTF INFORMATION DATA"); if( !ds.FindDataElement( tpmtf) ) return 1; const gdcm::DataElement& pmtf = ds.GetDataElement( tpmtf ); if ( pmtf.IsEmpty() ) return 1; gdcm::SmartPointer seq = pmtf.GetValueAsSQ(); if ( !seq || !seq->GetNumberOfItems() ) return 1; size_t n = seq->GetNumberOfItems(); for( size_t i = 1; i <= n; ++i ) { gdcm::Item &item = seq->GetItem(i); gdcm::DataSet &subds = item.GetNestedDataSet(); // (0029,0010) ?? (LO) [PMTF INFORMATION DATA ] # 22,1 Private Creator // (0029,1090) ?? (OB) 00\05\00\13\00\12\00\22\ # 202,1 ? const gdcm::PrivateTag tseq(0x0029,0x90,"PMTF INFORMATION DATA"); if( subds.FindDataElement( tseq ) ) { const gdcm::DataElement & de = subds.GetDataElement( tseq ); const gdcm::ByteValue * bv = de.GetByteValue(); if( !bv ) return 1; bool b = DumpToshibaDTI( bv->GetPointer(), bv->GetLength() ); if( !b ) return 1; } } return 0; } GDCM-3.0.10/Examples/Cxx/DumpToshibaDTI2.cxx000066400000000000000000000101231412732066400202150ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * https://gazelle.ihe.net/EVSClient/dicomResult.seam;jsessionid=x+Rf9Zs+ip49P+jC3L8SLZb8?&oid=1.3.6.1.4.1.12559.11.1.2.1.4.1622284 */ #include "gdcmReader.h" #include "gdcmPrivateTag.h" #include "gdcmPrinter.h" #include "gdcmDictPrinter.h" #include #include #include #include static bool DumpToshibaDTI2( const char * input, size_t len ) { static int i = 0; ++i; if( len % 2 ) return false; std::vector copy( input, input + len ); std::reverse( copy.begin(), copy.end() ); #if 0 std::ostringstream f; f << "debug" << i; std::ofstream of( f.str().c_str(), std::ios::binary ); of.write( ©[0], copy.size() ); of.close(); #else std::istringstream is; std::string dup( ©[0], copy.size() ); is.str( dup ); gdcm::File file; gdcm::FileMetaInformation & fmi = file.GetHeader(); fmi.SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); gdcm::DataSet & ds = file.GetDataSet(); ds.Read( is ); //gdcm::DictPrinter p; gdcm::Printer p; p.SetFile( file ); p.SetColor( true ); p.Print( std::cout ); #endif return true; } int main(int argc, char *argv[]) { if( argc < 2 ) return 1; const char *filename = argv[1]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); /* (0029,1001) SQ (Sequence with explicit length #=6) # 18746, 1 Unknown Tag & Data (fffe,e000) na (Item with explicit length #=2) # 206, 1 Item (0029,0010) LO [TOSHIBA_MEC_MR3] # 16, 1 PrivateCreator (0029,1090) OB 00\07\00\06\00\05\00\04\00\03\00\02\00\0c\00\01\00\00\00\00\00\12... # 170, 1 Unknown Tag & Data (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem (fffe,e000) na (Item with explicit length #=2) # 866, 1 Item (0029,0010) LO [TOSHIBA_MEC_MR3] # 16, 1 PrivateCreator (0029,1090) OB 45\4e\49\50\53\4c\20\52\41\5c\45\4e\49\50\53\4c\54\5c\52\45\53\55... # 830, 1 Unknown Tag & Data [...] (0029,1002) SQ (Sequence with explicit length #=1) # 120, 1 Unknown Tag & Data (fffe,e000) na (Item with explicit length #=2) # 112, 1 Item (0029,0010) LO [TOSHIBA_MEC_MR3] # 16, 1 PrivateCreator (0029,1090) OB 00\10\00\02\53\55\10\80\70\0d\30\31\5e\33\52\4d\5f\43\45\4d\5f\41... # 76, 1 Unknown Tag & Data (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem */ const gdcm::PrivateTag tmecmr3(0x0029,0x1,"TOSHIBA_MEC_MR3"); if( !ds.FindDataElement( tmecmr3) ) return 1; const gdcm::DataElement& mecmr3 = ds.GetDataElement( tmecmr3 ); if ( mecmr3.IsEmpty() ) return 1; gdcm::SmartPointer seq = mecmr3.GetValueAsSQ(); if ( !seq || !seq->GetNumberOfItems() ) return 1; size_t n = seq->GetNumberOfItems(); for( size_t i = 1; i <= n; ++i ) { gdcm::Item &item = seq->GetItem(i); gdcm::DataSet &subds = item.GetNestedDataSet(); const gdcm::PrivateTag tseq(0x0029,0x90,"TOSHIBA_MEC_MR3"); if( subds.FindDataElement( tseq ) ) { const gdcm::DataElement & de = subds.GetDataElement( tseq ); const gdcm::ByteValue * bv = de.GetByteValue(); if( !bv ) return 1; bool b = DumpToshibaDTI2( bv->GetPointer(), bv->GetLength() ); if( !b ) return 1; } } return 0; } GDCM-3.0.10/Examples/Cxx/DumpVisusChange.cxx000066400000000000000000000077501412732066400204340ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmDirectory.h" #include "gdcmStringFilter.h" #include #include /* */ static bool process( std::vector & ms, const char * filename) { using namespace gdcm; Tag pd(0x7fe0,0x0000); std::set skiptags; skiptags.insert( pd ); gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.ReadUpToTag( pd, skiptags ) ) { std::cerr << "Failure to read: " << filename << std::endl; return false; } gdcm::File &file = reader.GetFile(); gdcm::DataSet &ds1 = file.GetDataSet(); const gdcm::PrivateTag tseq1(0x5533,0x33,"Visus Change"); if( !ds1.FindDataElement( tseq1 ) ) return true; const gdcm::DataElement& seq1 = ds1.GetDataElement( tseq1 ); SmartPointer sqi1 = seq1.GetValueAsSQ(); const size_t nitems = sqi1->GetNumberOfItems(); for( size_t item = 1; item < nitems; ++item ) { Item &item1 = sqi1->GetItem(item); DataSet &ds2 = item1.GetNestedDataSet(); for(DataSet::ConstIterator it = ds2.Begin(); it != ds2.End(); ++it ) { DataElement const & de = *it; // cannot simply use std::set here, see there is a discrepancy in between // operator== and operator<. // So only use operator== here: std::vector::iterator vit = std::find(ms.begin(), ms.end(), de); if( vit == ms.end() ) ms.push_back(de); } } return true; } int main(int argc, char *argv[]) { bool usefastpath = true; if( argc < 2 ) return 1; using namespace gdcm; const char *filename = argv[1]; gdcm::Directory::FilenamesType filenames; if( !gdcm::System::FileExists(filename) ) { std::cerr << "Could not find file: " << filename << std::endl; return 1; } gdcm::Directory dir; if( gdcm::System::FileIsDirectory(filename) ) { unsigned int nfiles = dir.Load(filename, false); if( nfiles == 0 ) { std::cerr << "Could not find files: " << filename << std::endl; return 1; } filenames = dir.GetFilenames(); } else { filenames.push_back( filename ); } gdcm::StringFilter sf; Tag pd(0x7fe0,0x0000); std::set skiptags; skiptags.insert( pd ); gdcm::Reader reader; reader.SetFileName( filenames[0].c_str() ); if( !reader.ReadUpToTag( pd, skiptags ) ) { std::cerr << "Could not read file: " << filename << std::endl; return 1; } gdcm::File &file = reader.GetFile(); sf.SetFile(file); if( usefastpath ) { // Heuristic, assume if private tag cannot be found in first file, skip the directory gdcm::DataSet &ds1 = file.GetDataSet(); const gdcm::PrivateTag tseq1(0x5533,0x33,"Visus Change"); if( !ds1.FindDataElement( tseq1 ) ){ std::cerr << "Could not find private tag in first file skipping whole directory: " << filename << std::endl; return 0; } } std::vector ms; for(gdcm::Directory::FilenamesType::const_iterator cit = filenames.begin(); cit != filenames.end(); ++cit ) { if( !process(ms, cit->c_str()) ) { return 1; } } if( !ms.empty() ) { std::sort(ms.begin(), ms.end()); std::cout << filename << ",\""; for(std::vector::const_iterator it = ms.begin(); it != ms.end(); ++it ) { DataElement const & de = *it; std::string const & s = sf.ToString( de ); std::cout << de.GetTag() << " " << s << std::endl; } std::cout << "\"" << std::endl; } return 0; } GDCM-3.0.10/Examples/Cxx/DuplicatePCDE.cxx000066400000000000000000000155751412732066400177410ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmItem.h" #include "gdcmImageReader.h" #include "gdcmSequenceOfItems.h" #include "gdcmFile.h" #include "gdcmTag.h" /* Usage: DuplicatePCDE gdcmData/D_CLUNIE_CT1_J2KI.dcm out.dcm aka: medical.nema.org/medical/dicom/DataSets/WG04/IMAGES/J2KI/CT1_J2KI See: gdcmConformanceTests/CT1_J2KI_DuplicatePCDE.dcm Original thread can be found at: http://groups.google.com/group/comp.protocols.dicom/browse_thread/thread/82f28c4db28963af Question: 1. There is no restriction for a specific Private Creator Data Element (PCDE) to be unique within the same group, right ? Decoders of Private Data would have to handle the case where a PCDE would be repeated and should NOT stop on the first instance of a particular PCDE, right ? Eg. when searching for the tag associated with (0x0029,0x0010,"SIEMENS CSA HEADER") in the following (pseudo) dataset: (0029,0010) LO [SIEMENS CSA HEADER] # 18, 1 PrivateCreator (0029,0011) LO [SIEMENS MEDCOM HEADER] # 22, 1 PrivateCreator (0029,0012) LO [SIEMENS MEDCOM HEADER2] # 22, 1 PrivateCreator (0029,0013) LO [SIEMENS CSA HEADER] # 18, 1 PrivateCreator (0029,1008) CS [IMAGE NUM 4] # 12, 1 CSAImageHeaderType (0029,1009) LO [20050723] # 8, 1 CSAImageHeaderVersion (0029,1010) OB 53\56\31\30\04\03\02\01\38\00\00\00\4d \00\00\00\45\63\68\6f\4c\69... # 6788, 1 CSAImageHeaderInfo (0029,1018) CS [MR] # 2, 1 CSASeriesHeaderType (0029,1019) LO [20050723] # 8, 1 CSASeriesHeaderVersion (0029,1020) OB 53\56\31\30\04\03\02\01\2c\00\00\00\4d \00\00\00\55\73\65\64\50\61... # 51520, 1 CSASeriesHeaderInfo (0029,1131) LO [4.0.163088300] # 14, 1 PMTFInformation1 (0029,1132) UL 32768 # 4, 1 PMTFInformation2 (0029,1133) UL 0 # 4, 1 PMTFInformation3 (0029,1134) CS [DB TO DICOM] # 12, 1 PMTFInformation4 (0029,1260) ?? 63\6f\6d\20 # 4, 1 Unknown Tag & Data (0029,1310) OB 53\56\31\30\04\03\02\01\38\00\00\00\4d \00\00\00\45\63\68\6f\4c\69... # 6788, 1 CSAImageHeaderInfo one should return two instances, correct ? Answer: I would say that this is covered in principle by the PS 3.5 7.1 "The Data Elements ... shall occur at most once in a Data Set" rule, since the data element is defined by the tuple (private creator,gggg,ee) where xxee is the element number and xx is arbitrary and has no inherent meaning and does not serve to disambiguate the data element. E.g.: (0019,0030) Private Creator ID = "Smith" ... (0019,0032) Private Creator ID = "Smith" ... (0019,3015) Fractal Index = "32" ... (0019,3215) Fractal Index = "32" would be illegal because even though they are assigned different (completely arbitrary) blocks, with the same group, element number and private creator, (0019,3015) and (0019,3215) are the "same" data element. */ int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { return 1; } gdcm::File &file = reader.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); // Let's get all private element from group 0x9: /* (0009,0010) LO [GEMS_IDEN_01] # 12,1 Private Creator (0009,1001) LO [GE_GENESIS_FF ] # 14,1 Full fidelity (0009,1002) SH [CT01] # 4,1 Suite id (0009,1004) SH [HiSpeed CT/i] # 12,1 Product id (0009,1027) SL 862399669 # 4,1 Image actual date (0009,1030) SH (no value) # 0,1 Service id (0009,1031) SH (no value) # 0,1 Mobile location number (0009,10e6) SH [05] # 2,1 Genesis Version - now (0009,10e7) UL 973283917 # 4,1 Exam Record checksum (0009,10e9) SL 862399669 # 4,1 Actual series data time stamp */ gdcm::Tag start(0x0009,0x0); // Create a temporary duplicate dataset, since we cannot insert data element as we go over them (std::set // would reorganize itself as we go over it ...) gdcm::DataSet dup; gdcm::Tag new_private(0x0009,0x0); while (start.GetGroup() == 0x9 ) { const gdcm::DataElement& de = ds.FindNextDataElement(start); const gdcm::Tag &t = de.GetTag(); if( t.IsPrivateCreator() ) { std::cout << t << std::endl; // Ok let's duplicate into the next available attribute: gdcm::DataElement duplicate = de; duplicate.GetTag().SetElement( (uint16_t)(t.GetElement() + 1) ); dup.Insert( duplicate ); new_private = duplicate.GetTag(); } else if( t.IsPrivate() && !t.IsPrivateCreator() ) { //std::cout << de << std::endl; std::string owner = ds.GetPrivateCreator( de.GetTag() ); //std::cout << owner << std::endl; gdcm::DataElement duplicate = de; duplicate.GetTag().SetPrivateCreator( new_private ); if( const gdcm::ByteValue *bv = duplicate.GetByteValue() ) { // Warning: when doing : duplicate = de, only the pointer to the ByteValue is passed // (to avoid large memory duplicate). We need to explicitly duplicate the bytevalue ourselves: gdcm::ByteValue *dupbv = new gdcm::ByteValue( bv->GetPointer(), bv->GetLength() ); // Let's recognize the duplicated ASCII-type elements: if( duplicate.GetVR() & gdcm::VR::VRASCII ) dupbv->Fill( 'X' ); duplicate.SetValue( *dupbv ); } dup.Insert( duplicate ); } start = t; // move to next possible 'public' element start.SetElement( (uint16_t)(start.GetElement() + 1) ); } gdcm::DataSet::ConstIterator it = dup.Begin(); for( ; it != dup.End(); ++it ) { ds.Insert( *it ); } gdcm::Writer w; w.SetFile( file ); w.SetFileName( outfilename ); if (!w.Write() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/ELSCINT1WaveToText.cxx000066400000000000000000000140141412732066400205330ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmPrivateTag.h" /* * This example shows how to read a Wave Information tag from ELSCINT1 * The wave information is stored in Tag (01e1,18,ELSCINT1) hidden in a * Secondary Capture Image Storage (usually a 'N' Symbol is shown) * * Everything done in this code is for the sole purpose of writing interoperable * software under Sect. 1201 (f) Reverse Engineering exception of the DMCA. * If you believe anything in this code violates any law or any of your rights, * please contact us (gdcm-developers@lists.sourceforge.net) so that we can * find a solution. * * Everything you do with this code is at your own risk, since decompression * algorithm was not written from specification documents. * * Special thanks to: * Gauthier Bouilhol */ template bool dumpargs(std::ostream & os, T c1, T c2, T c3, T c4, T c5, T c6, T c7, T c8) { static const char sep = '\t'; os << c1 << sep << c2 << sep << c3 << sep << c4 << sep << c5 << sep << c6 << sep << c7 << sep << c8; os << std::endl; return true; } bool wave2stream( std::ostream &text_file, const char *in, size_t len ) { const short * buffer = (const short*)in; size_t length = len / sizeof( short ); text_file << "COMPLETE_WAVE" << '\t' << "MASK" << '\t' << "AQUISITION_PROFIL" << '\t' << "END-INHALE" << '\t' << "END-EXHALE" << '\t' << "AQUISITION_WAVE" << '\t' << "WAVE_STATISTICS" << '\t' << "MASK" << std::endl; for (size_t i=0;iGetPointer(), bv->GetLength() ); os.close(); return 0; } GDCM-3.0.10/Examples/Cxx/EmptyMask.cxx000066400000000000000000000033271412732066400172750ustar00rootroot00000000000000/*========================================================================= 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 "gdcmEmptyMaskGenerator.h" #include #include int main( int argc, char *argv[] ) { std::string inputdir; std::string outputdir; bool input_sopclassuid = true; bool grayscale_secondary_sopclassuid = false; if( argc < 3 ) return 1; inputdir = argv[1]; outputdir = argv[2]; // input_sopclassuid -> Use original SOP Class UID from input DICOM (Default). // grayscale_secondary_sopclassuid -> Use Grayscale Secondary Image Storage SOP Class UID. if( argc >= 3 ) { input_sopclassuid = false; if( strcmp("input_sopclassuid", argv[3]) == 0 ) input_sopclassuid = true; else if (strcmp("grayscale_secondary_sopclassuid", argv[3]) == 0 ) { grayscale_secondary_sopclassuid = true; } } // gdcm::EmptyMaskGenerator emg; if( input_sopclassuid ) emg.SetSOPClassUIDMode( gdcm::EmptyMaskGenerator::UseOriginalSOPClassUID ); else if( grayscale_secondary_sopclassuid ) emg.SetSOPClassUIDMode( gdcm::EmptyMaskGenerator::UseGrayscaleSecondaryImageStorage ); emg.SetInputDirectory( inputdir.c_str() ); emg.SetOutputDirectory( outputdir.c_str() ); if( !emg.Execute() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/EncapsulateFileInRawData.cxx000066400000000000000000000045241412732066400221620ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAnonymizer.h" #include "gdcmWriter.h" #include "gdcmUIDGenerator.h" #include "gdcmFile.h" #include "gdcmTag.h" #include "gdcmSystem.h" #include "magic.h" // libmagic, API to file command line tool /* * Let say you want to encapsulate a file type that is not defined in DICOM (exe, zip, png) * PNG is a bad example, unless it contains transparency (which has been deprecated). * It will take care of dispatching each chunk to an appropriate data item (pretty much like * WaveformData) * * Usage: * ./EncapsulateFileInRawData large_input_file.exe large_input_file.dcm */ // TODO: // $ file -bi /tmp/gdcm-2.1.0.pdf int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " inputfile output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; if( !gdcm::System::FileExists( filename ) ) return 1; size_t s = gdcm::System::FileSize(filename); if( !s ) return 1; magic_t cookie = magic_open(MAGIC_NONE); const char * file_type = magic_file(cookie, filename); if( !file_type ) return 1; magic_close(cookie); gdcm::Writer w; gdcm::File &file = w.GetFile(); //gdcm::DataSet &ds = file.GetDataSet(); //w.SetCheckFileMetaInformation( true ); w.SetFileName( outfilename ); file.GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian ); gdcm::Anonymizer anon; anon.SetFile( file ); gdcm::MediaStorage ms = gdcm::MediaStorage::RawDataStorage; gdcm::UIDGenerator gen; anon.Replace( gdcm::Tag(0x0008,0x16), ms.GetString() ); std::cout << ms.GetString() << std::endl; anon.Replace( gdcm::Tag(0x0008,0x18), gen.Generate() ); if (!w.Write() ) { std::cerr << "Could not write: " << outfilename << std::endl; return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/ExtractEncryptedContent.cxx000066400000000000000000000040141412732066400222000ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include /* openssl smime -encrypt -binary -aes256 -in outputfile.dcm -inform DER -out outputfile.der -outform DER ../trunk/Testing/Source/Data/certificate.pem openssl smime -decrypt -binary -in out.der -inform DER -out outputfile.dcm -outform DER -inkey ../trunk/Testing/Source/Data/privatekey.pem ../trunk/Testing/Source/Data/certificate.pem */ int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.der" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { return 1; } gdcm::File &file = reader.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); const gdcm::DataElement &EncryptedAttributesSequence = ds.GetDataElement( gdcm::Tag( 0x0400,0x0500 ) ); gdcm::SequenceOfItems *sqi = EncryptedAttributesSequence.GetValueAsSQ(); if ( !sqi || sqi->GetNumberOfItems() != 1 ) return 1; gdcm::Item &item = sqi->GetItem(1); gdcm::DataSet &nestedds = item.GetNestedDataSet(); if( ! nestedds.FindDataElement( gdcm::Tag( 0x0400,0x0520) ) ) return 1; const gdcm::DataElement &EncryptedContent = nestedds.GetDataElement( gdcm::Tag( 0x0400,0x0520) ); const gdcm::ByteValue *bv = EncryptedContent.GetByteValue(); std::ofstream of( outfilename, std::ios::binary ); of.write( bv->GetPointer(), bv->GetLength() ); of.close(); return 0; } GDCM-3.0.10/Examples/Cxx/ExtractIconFromFile.cxx000066400000000000000000000054401412732066400212300ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This example shows how to either retrieve an Icon if present somewhere * in the file, or else generate one. */ #include "gdcmImageReader.h" #include "gdcmPNMCodec.h" #include "gdcmIconImageFilter.h" #include "gdcmIconImageGenerator.h" bool WriteIconAsPNM(const char* filename, const gdcm::IconImage& icon) { gdcm::PNMCodec pnm; pnm.SetDimensions( icon.GetDimensions() ); pnm.SetPixelFormat( icon.GetPixelFormat() ); pnm.SetPhotometricInterpretation( icon.GetPhotometricInterpretation() ); pnm.SetLUT( icon.GetLUT() ); const gdcm::DataElement& in = icon.GetDataElement(); bool b = pnm.Write( filename, in ); assert( b ); return b; } int main(int argc, char *argv []) { if( argc < 2 ) return 1; const char *filename = argv[1]; gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Failed to read (or not image): " << filename << std::endl; return 1; } gdcm::IconImageFilter iif; iif.SetFile( reader.GetFile() ); bool b = iif.Extract(); if( b ) { const gdcm::IconImage &icon = iif.GetIconImage(0); icon.Print( std::cout ); if( !icon.GetTransferSyntax().IsEncapsulated() ) { // Let's write out this icon as PNM file WriteIconAsPNM("icon.ppm", icon); } else if( icon.GetTransferSyntax() == gdcm::TransferSyntax::JPEGBaselineProcess1 || icon.GetTransferSyntax() == gdcm::TransferSyntax::JPEGExtendedProcess2_4 ) { const gdcm::DataElement& in = icon.GetDataElement(); const gdcm::ByteValue *bv = in.GetByteValue(); assert( bv ); std::ofstream out( "icon.jpg", std::ios::binary ); out.write( bv->GetPointer(), bv->GetLength() ); out.close(); } } else { assert( iif.GetNumberOfIconImages() == 0 ); std::cerr << "No Icon Found anywhere in file" << std::endl; const gdcm::Image &img = reader.GetImage(); gdcm::IconImageGenerator iig; iig.AutoPixelMinMax(true); iig.SetPixmap( img ); const unsigned int idims[2] = { 64, 64 }; iig.SetOutputDimensions( idims ); //iig.SetPixelMinMax(60, 868); if( !iig.Generate() ) return 1; const gdcm::IconImage & icon = iig.GetIconImage(); WriteIconAsPNM("icon.ppm", icon); } return 0; } GDCM-3.0.10/Examples/Cxx/Extracting_All_Resolution.cxx000066400000000000000000000340711412732066400225060ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // This work was realised during the GSOC 2011 by Manoj Alwani #include #include #include #include #include #include #include #include #include #include #include #include #include "gdcmImageReader.h" #include "gdcmSequenceOfItems.h" #include "gdcmSystem.h" #include #include "gdcm_openjpeg.h" #include "gdcmMediaStorage.h" #include "gdcmWriter.h" #include "gdcmItem.h" #include "gdcmImageReader.h" #include "gdcmAttribute.h" #include "gdcmFile.h" #include "gdcmTag.h" #include "gdcmTransferSyntax.h" #include "gdcmUIDGenerator.h" #include "gdcmAnonymizer.h" #include "gdcmStreamImageWriter.h" #include "gdcmImageHelper.h" #include "gdcmTrace.h" void error_callback(const char *msg, void *) { (void)msg; } void warning_callback(const char *msg, void *) { (void)msg; } void info_callback(const char *msg, void *) { (void)msg; } bool Write_Resolution(gdcm::StreamImageWriter & theStreamWriter, const char *filename, int res, std::ostream& of, int flag, gdcm::SequenceOfItems *sq, int No_Of_Resolutions) { std::ifstream is; is.open( filename, std::ios::binary ); opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_dinfo_t* dinfo; /* handle to a decompressor */ opj_cio_t *cio; opj_image_t *image = NULL; // FIXME: Do some stupid work: is.seekg( 0, std::ios::end); std::streampos buf_size = is.tellg(); char *dummy_buffer = new char[(unsigned int)buf_size]; is.seekg(0, std::ios::beg); is.read( dummy_buffer, buf_size); unsigned char *src = (unsigned char*)dummy_buffer; uint32_t file_length = (uint32_t)buf_size; // 32bits truncation should be ok since DICOM cannot have larger than 2Gb image /* configure the event callbacks (not required) */ memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); event_mgr.error_handler = error_callback; event_mgr.warning_handler = warning_callback; event_mgr.info_handler = info_callback; /* set decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); // default blindly copied parameters.cp_layer=0; parameters.cp_reduce= res; // parameters.decod_format=-1; // parameters.cod_format=-1; const char jp2magic[] = "\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A"; if( memcmp( src, jp2magic, sizeof(jp2magic) ) == 0 ) { /* JPEG-2000 compressed image data ... sigh */ // gdcmData/ELSCINT1_JP2vsJ2K.dcm // gdcmData/MAROTECH_CT_JP2Lossy.dcm //gdcmWarningMacro( "J2K start like JPEG-2000 compressed image data instead of codestream" ); parameters.decod_format = 1; //JP2_CFMT; //assert(parameters.decod_format == JP2_CFMT); } else { /* JPEG-2000 codestream */ //parameters.decod_format = J2K_CFMT; //assert(parameters.decod_format == J2K_CFMT); assert( 0 ); } parameters.cod_format = 11; // PGX_DFMT; //assert(parameters.cod_format == PGX_DFMT); /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JP2); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); if(!image) { opj_destroy_decompress(dinfo); opj_cio_close(cio); //gdcmErrorMacro( "opj_decode failed" ); return 1; } opj_cp_t * cp = ((opj_jp2_t*)dinfo->jp2_handle)->j2k->cp; opj_tcp_t *tcp = &cp->tcps[0]; opj_tccp_t *tccp = &tcp->tccps[0]; /* std::cout << "\n No of Cols In Image" << image->x1; std::cout << "\n No of Rows In Image" << image->y1; std::cout << "\n No of Components in Image" << image->numcomps; std::cout << "\n No of Resolutions"<< tccp->numresolutions << "\n"; */ opj_j2k_t* j2k = NULL; opj_jp2_t* jp2 = NULL; jp2 = (opj_jp2_t*)dinfo->jp2_handle; int reversible = jp2->j2k->cp->tcps->tccps->qmfbid; //std:: cout << reversible; int compno = 0; opj_image_comp_t *comp = &image->comps[compno]; int Dimensions[2]; Dimensions[0]= comp->w; Dimensions[1] = comp->h; opj_cio_close(cio); unsigned long len = Dimensions[0]*Dimensions[1] * image->numcomps; //std::cout << "\nTest" <comps[0].factor; char *raw = new char[len]; for (unsigned int compno = 0; compno < (unsigned int)image->numcomps; compno++) { opj_image_comp_t *comp = &image->comps[compno]; int w = image->comps[compno].w; int h = image->comps[compno].h; uint8_t *data8 = (uint8_t*)raw + compno; for (int i = 0; i < w * h ; i++) { int v = image->comps[compno].data[i]; *data8 = (uint8_t)v; data8 += image->numcomps; } } gdcm::Writer w; gdcm::File &file = w.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); file.GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); gdcm::UIDGenerator uid; gdcm::DataElement de( gdcm::Tag(0x8,0x18) ); // SOP Instance UID de.SetVR( gdcm::VR::UI ); const char *u = uid.Generate(); de.SetByteValue( u, strlen(u) ); ds.Insert( de ); gdcm::DataElement de1( gdcm::Tag(0x8,0x16) ); de1.SetVR( gdcm::VR::UI ); gdcm::MediaStorage ms( gdcm::MediaStorage::CTImageStorage ); de1.SetByteValue( ms.GetString(), strlen(ms.GetString())); ds.Insert( de1 ); const char mystr[] = "MONOCHROME2 "; gdcm::DataElement de2( gdcm::Tag(0x28,0x04) ); //de.SetTag(gdcm::Tag(0x28,0x04)); de2.SetVR( gdcm::VR::CS ); de2.SetByteValue(mystr, strlen(mystr)); ds.Insert( de2 ); gdcm::Attribute<0x0028,0x0010> row = {image->comps[0].w}; //row.SetValue(512); ds.Insert( row.GetAsDataElement() ); // w.SetCheckFileMetaInformation( true ); gdcm::Attribute<0x0028,0x0011> col = {image->comps[0].h}; ds.Insert( col.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0008> Number_Of_Frames = {1}; ds.Insert( Number_Of_Frames.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0100> at = {8}; ds.Insert( at.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0002> at1 = {image->numcomps}; ds.Insert( at1.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0101> at2 = {8}; ds.Insert( at2.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0102> at3 = {7}; ds.Insert( at3.GetAsDataElement() ); if (flag == 1) { for (int i=0; i < No_Of_Resolutions; i++) { int a = 1; int b =1; while(a!=((No_Of_Resolutions)-i)) { b = b*2; a = a+1; } uint16_t row = (image->y1)/b; uint16_t col = (image->x1)/b; //std::cout << row; gdcm::Element el2; el2.SetValue(i+1); gdcm::DataElement rfn = el2.GetAsDataElement(); //ulr --> upper left row rfn.SetTag( gdcm::Tag(0x0008,0x1160) ); gdcm::Element el; el.SetValue(1,0); el.SetValue(1,1); gdcm::DataElement ulr = el.GetAsDataElement(); //ulr --> upper left col/row ulr.SetTag( gdcm::Tag(0x0048,0x0201) ); gdcm::Element el1; el1.SetValue(col,0); el1.SetValue(row,1); gdcm::DataElement brr = el1.GetAsDataElement(); brr.SetTag( gdcm::Tag(0x0048,0x0202) ); //brr --> bottom right col/row gdcm::Item it; gdcm::DataSet &nds = it.GetNestedDataSet(); nds.Insert( rfn ); nds.Insert(ulr); nds.Insert(brr); sq->AddItem(it); } gdcm::Writer w1; gdcm::File &file1 = w1.GetFile(); gdcm::DataSet &ds1 = file1.GetDataSet(); file1.GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); gdcm::UIDGenerator uid1; gdcm::DataElement dea( gdcm::Tag(0x8,0x18) ); // SOP Instance UID dea.SetVR( gdcm::VR::UI ); const char *u1 = uid1.Generate(); dea.SetByteValue( u1, strlen(u1) ); ds1.Insert( dea ); gdcm::DataElement deb( gdcm::Tag(0x8,0x16) ); deb.SetVR( gdcm::VR::UI ); gdcm::MediaStorage ms1( gdcm::MediaStorage::VLWholeSlideMicroscopyImageStorage ); deb.SetByteValue( ms1.GetString(), strlen(ms1.GetString())); ds1.Insert( deb ); const char mystr1[] = "MONOCHROME2 "; gdcm::DataElement dec( gdcm::Tag(0x28,0x04) ); //de.SetTag(gdcm::Tag(0x28,0x04)); dec.SetVR( gdcm::VR::CS ); dec.SetByteValue(mystr, strlen(mystr1)); ds1.Insert( dec ); gdcm::Attribute<0x0028,0x0010> row1 = {image->y1}; //row.SetValue(512); ds1.Insert( row1.GetAsDataElement() ); // w.SetCheckFileMetaInformation( true ); gdcm::Attribute<0x0028,0x0011> col1 = {image->x1}; ds1.Insert( col1.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0008> Number_Of_Frames1 = {tccp->numresolutions}; ds1.Insert( Number_Of_Frames1.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0100> ata = {8}; ds1.Insert( ata.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0002> atb = {image->numcomps}; ds1.Insert( atb.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0101> atc = {8}; ds1.Insert( atc.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0102> atd = {7}; ds1.Insert( atd.GetAsDataElement() ); theStreamWriter.SetFile(file1); gdcm::DataElement des( gdcm::Tag(0x0048,0x0200) ); des.SetVR(gdcm::VR::SQ); //des.SetVR(gdcm::VM::VM1); des.SetValue(*sq); des.SetVLToUndefined(); ds1.Insert(des); if (!theStreamWriter.WriteImageInformation()){ std::cerr << "unable to write image information" << std::endl; return 1; //the CanWrite function should prevent getting here, else, //that's a test failure } } theStreamWriter.SetFile(file); if (!theStreamWriter.CanWriteFile()){ delete [] raw; std::cout << "Not able to write"; return 0;//this means that the file was unwritable, period. //very similar to a ReadImageInformation failure } else std::cout<<"\nabletoread"; // Important to write here std::vector extent = gdcm::ImageHelper::GetDimensionsValue(file); unsigned short xmax = extent[0]; unsigned short ymax = extent[1]; unsigned short theChunkSize = 4; unsigned short ychunk = extent[1]/theChunkSize; //go in chunk sizes of theChunkSize unsigned short zmax = extent[2]; std::cout << "\n"<numcomps<<"\n"; if (xmax == 0 || ymax == 0) { std::cerr << "Image has no size, unable to write zero-sized image." << std::endl; return 0; } int z, y, nexty; unsigned long prevLen = 0; //when going through the char buffer, make sure to grab //the bytes sequentially. So, store how far you got in the buffer with each iteration. for (z = 0; z < zmax; ++z){ for (y = 0; y < ymax; y += ychunk){ nexty = y + ychunk; if (nexty > ymax) nexty = ymax; theStreamWriter.DefinePixelExtent(0, xmax, y, nexty, z, z+1); unsigned long len = theStreamWriter.DefineProperBufferLength(); std::cout << "\n" < row = {256}; //row.SetValue(512); ds.Insert( row.GetAsDataElement() ); // w.SetCheckFileMetaInformation( true ); gdcm::Attribute<0x0028,0x0011> col = {256}; ds.Insert( col.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0008> Number_Of_Frames = {1}; ds.Insert( Number_Of_Frames.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0100> at = {8}; ds.Insert( at.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0002> at1 = {3}; //bits per pixel ds.Insert( at1.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0101> at2 = {8}; ds.Insert( at2.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0102> at3 = {7}; ds.Insert( at3.GetAsDataElement() ); gdcm::Attribute<0x0028,0x006> at4 = {0}; ds.Insert( at4.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0103> at5 = {0}; ds.Insert( at5.GetAsDataElement() ); //de.SetTag(gdcm::Tag(0x7fe0,0x0010)); //ds.Insert(de); gdcm::StreamImageWriter theStreamWriter; gdcm::SmartPointer sq = new gdcm::SequenceOfItems(); sq->SetLengthToUndefined(); uint16_t row1 = 256; uint16_t col1 = 256; //std::cout << row; gdcm::Element el2; el2.SetValue(1); gdcm::DataElement rfn = el2.GetAsDataElement(); //rfn ---> reference frame number rfn.SetTag( gdcm::Tag(0x0008,0x1160) ); gdcm::Element el; el.SetValue(1,0); el.SetValue(1,1); gdcm::DataElement ulr = el.GetAsDataElement(); //ulr --> upper left col/row ulr.SetTag( gdcm::Tag(0x0048,0x0201) ); gdcm::Element el1; el1.SetValue(col1,0); el1.SetValue(row1,1); gdcm::DataElement brr = el1.GetAsDataElement(); brr.SetTag( gdcm::Tag(0x0048,0x0202) ); //brr --> bottom right col/row gdcm::Item it; gdcm::DataSet &nds = it.GetNestedDataSet(); nds.Insert( rfn ); nds.Insert(ulr); nds.Insert(brr); sq->AddItem(it); gdcm::DataElement des( gdcm::Tag(0x0048,0x0200) ); des.SetVR(gdcm::VR::SQ); des.SetValue(*sq); des.SetVLToUndefined(); ds.Insert(des); theStreamWriter.SetFile(file); std::ofstream of; of.open( "output.dcm", std::ios::out | std::ios::binary ); theStreamWriter.SetStream(of); if (!theStreamWriter.CanWriteFile()){ delete [] buffer; std::cout << "Not able to write"; return 0;//this means that the file was unwritable, period. //very similar to a ReadImageInformation failure } else std::cout<<"\nabletoread"; if (!theStreamWriter.WriteImageInformation()){ std::cerr << "unable to write image information" << std::endl; delete [] buffer; return 1; //the CanWrite function should prevent getting here, else, //that's a test failure } std::vector extent = gdcm::ImageHelper::GetDimensionsValue(file); unsigned short xmax = extent[0]; unsigned short ymax = extent[1]; unsigned short theChunkSize = 1; unsigned short ychunk = extent[1]/theChunkSize; //go in chunk sizes of theChunkSize unsigned short zmax = extent[2]; std::cout << xmax << ymax << zmax; if (xmax == 0 || ymax == 0) { std::cerr << "Image has no size, unable to write zero-sized image." << std::endl; return 0; } int z, y, nexty; unsigned long prevLen = 0; //when going through the char buffer, make sure to grab //the bytes sequentially. So, store how far you got in the buffer with each iteration. for (z = 0; z < zmax; ++z){ for (y = 0; y < ymax; y += ychunk){ nexty = y + ychunk; if (nexty > ymax) nexty = ymax; theStreamWriter.DefinePixelExtent(0, xmax, y, nexty, z, z+1); unsigned long len = theStreamWriter.DefineProperBufferLength(); std::cout << "\n" < BuggyJ2Kvvvua-fixed2-j2k.dcm /* * This program attemps to fix a broken J2K/DICOM: * It contains 2 bugs: * 1. The first 8 bytes seems to be random bytes: remove them * 2. YCC is set to 1, while image is grayscale need to set it back to 0 * * Ref: * It's a software from http://rentgenprom.ru/ , shipped with universal digital radiographic units * "ProScan-2000". The Ukrainian manufacturer developed own digital radiographic unit and it is * compatible with software from "ProScan-2000". * Information found in DICOM file is: * * (0008,0070) LO [ZAO "Renthenprom" (JSC Rentgenprom) ] # 36,1 Manufacturer * (0018,1020) LO [2.13.1.7] # 8,1-n Software Version(s) * */ int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { return 1; } gdcm::File &file = reader.GetFile(); const gdcm::DataElement &pixeldata0 = file.GetDataSet().GetDataElement( gdcm::Tag(0x7fe0,0x0010) ); const gdcm::SequenceOfFragments *sqf = pixeldata0.GetSequenceOfFragments(); if( !sqf ) { return 1; } const gdcm::Fragment &frag0 = sqf->GetFragment(0); gdcm::ByteValue *bv = const_cast(frag0.GetByteValue()); char *ptr = (char*)bv->GetVoidPointer(); size_t len = bv->GetLength(); static const unsigned char sig[] = {0,0,0,0,0x6A,0x70,0x32,0x63}; if( memcmp(ptr, sig, sizeof(sig)) != 0 ) { std::cerr << "magic random signature not found" << std::endl; return 1; } // Apparently the flag to enable a color transform on 3 color components is set in // the COD marker. (YCC is byte[6] in the COD marker) // we need to disable this flag; char *cod_marker = ptr + 0x35; /* 0x2d + 0x8 */ // FIXME if( cod_marker[0] == (char)0xff && cod_marker[1] == 0x52 ) { // found start of COD if( cod_marker[6+2] == 1 ) { // Change in place: *((char*)cod_marker + 6+2) = 0; // Prepare a new DataElement: gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0,0x0010) ); pixeldata.SetVR( gdcm::VR::OB ); gdcm::SmartPointer sq = new gdcm::SequenceOfFragments; gdcm::Fragment frag; // remove 8 first bytes: frag.SetByteValue( ptr + 8, (uint32_t)(len - 8) ); sq->AddFragment( frag ); pixeldata.SetValue( *sq ); file.GetDataSet().Replace( pixeldata ); } else { return 1; } } else { std::cerr << "COD not found" << (int)cod_marker[0] << std::endl; return 1; } gdcm::Writer writer; writer.SetFile( reader.GetFile() ); writer.SetFileName( outfilename ); writer.CheckFileMetaInformationOff(); if( !writer.Write() ) { std::cerr << "Could not write" << std::endl; } // paranoid check: gdcm::ImageReader ireader; ireader.SetFileName( outfilename ); if( !ireader.Read() ) { std::cerr << "file written is still not valid, please report" << std::endl; return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/FixJAIBugJPEGLS.cxx000066400000000000000000000147551412732066400200070ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmImageReader.h" #include #include "gdcm_charls.h" /* * This small example should show how one can handle the famous JAI-JPEGLS bug * It will take in as invalid DICOM/JAI-JPEG-LS and write out as Explicit Little * Endian. One can use `gdcmconv --jpegls` to recompress properly * * References: * http://charls.codeplex.com/discussions/230307?ProjectName=charls * http://charls.codeplex.com/workitem/7297 * http://www.dcm4che.org/jira/browse/DCM-442 * http://www.dcm4che.org/jira/browse/DCMEE-1144 * http://java.net/jira/browse/JAI_IMAGEIO_CORE-183 * * Explanation of the issue: * * Seems, the error is in the calculation of the default values for thresholds T1, * T2, T3, in particular min(MAXVAL, 4095) is not applied in * * FACTOR = (min(MAXVAL, 4095) + 128)/256 * * as specified in http://www.itu.int/rec/T-REC-T.87-199806-I/en . * */ int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( "FixJAIBugJPEGLS" ); gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { return 1; } gdcm::Image &image = reader.GetImage(); //unsigned long len = image.GetBufferLength(); const gdcm::DataElement & in = reader.GetFile().GetDataSet().GetDataElement( gdcm::Tag(0x7fe0,0x0010) ); const gdcm::SequenceOfFragments *sf = in.GetSequenceOfFragments(); if( !sf ) { std::cerr << "No pixel data (or not encapsulated)" << std::endl; return 1; } const unsigned int *dims = image.GetDimensions(); if ( sf->GetNumberOfFragments() != dims[2] ) { std::cerr << "Unsupported" << std::endl; return 1; } // unsigned long totalLen = sf->ComputeByteLength(); std::vector rgbyteOutall; for(unsigned int i = 0; i < sf->GetNumberOfFragments(); ++i) { const gdcm::Fragment &frag = sf->GetFragment(i); if( frag.IsEmpty() ) return 1; const gdcm::ByteValue *bv = frag.GetByteValue(); if( !bv ) return 1; unsigned long totalLen = bv->GetLength(); std::vector vbuffer; vbuffer.resize( totalLen ); char *buffer = &vbuffer[0]; bv->GetBuffer(buffer, totalLen); const unsigned char* pbyteCompressed0 = (const unsigned char*)buffer; while( totalLen > 0 && pbyteCompressed0[totalLen-1] != 0xd9 ) { totalLen--; } JlsParameters metadata; char errorMsg[256+1]={'\0'}; if (JpegLsReadHeader(buffer, totalLen, &metadata, errorMsg) != charls::ApiResult::OK) { std::cerr << "Cant parse jpegls: " << errorMsg << std::endl; return 1; } std::cout << metadata.width << std::endl; std::cout << metadata.height << std::endl; std::cout << metadata.bitsPerSample << std::endl; gdcm::PixelFormat const & pf = image.GetPixelFormat(); std::cout << pf << std::endl; // http://charls.codeplex.com/discussions/230307?ProjectName=charls unsigned char marker_lse_13[] = { 0xFF, 0xF8, 0x00, 0x0D, 0x01, 0x1F, 0xFF, 0x00, 0x22, // T1 = 34 0x00, 0x83, // T2 = 131 0x02, 0x24, // T3 = 548 0x00, 0x40 }; unsigned char marker_lse_14[] = { 0xFF, 0xF8, 0x00, 0x0D, 0x01, 0x3F, 0xFF, 0x00, 0x42, // T1 = 66 0x01, 0x03, // T2 = 259 0x04, 0x44, // T3 = 1092 0x00, 0x40 }; unsigned char marker_lse_15[] = { 0xFF, 0xF8, 0x00, 0x0D, 0x01, 0x7F, 0xFF, 0x00, 0x82, // T1 = 130 0x02, 0x03, // T2 = 515 0x08, 0x84, // T3 = 2180 0x00, 0x40 }; unsigned char marker_lse_16[] = { 0xFF, 0xF8, 0x00, 0x0D, 0x01, 0xFF, 0xFF, 0x01, 0x02, // T1 = 258 0x04, 0x03, // T2 = 1027 0x11, 0x04, // T3 = 4356 0x00, 0x40 }; const unsigned char *marker_lse = nullptr; switch( metadata.bitsPerSample ) { case 13: marker_lse = marker_lse_13; break; case 14: marker_lse = marker_lse_14; break; case 15: marker_lse = marker_lse_15; break; case 16: marker_lse = marker_lse_16; break; } if( !marker_lse ) { std::cerr << "Cant handle: " << metadata.bitsPerSample << std::endl; return 1; } // FIXME: One should recompute the value for 0x0F vbuffer.insert (vbuffer.begin() + 0x0F, marker_lse, marker_lse+15); #if 0 std::ofstream of( "/tmp/d.jls", std::ios::binary ); of.write( &vbuffer[0], vbuffer.size() ); of.close(); #endif const char *pbyteCompressed = &vbuffer[0]; size_t cbyteCompressed = vbuffer.size(); // updated legnth JlsParameters params; JpegLsReadHeader(pbyteCompressed, cbyteCompressed, ¶ms, nullptr); std::vector rgbyteOut; //rgbyteOut.resize( image.GetBufferLength() ); rgbyteOut.resize(params.height *params.width * ((params.bitsPerSample + 7) / 8) * params.components); CharlsApiResultType result = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), pbyteCompressed, cbyteCompressed, ¶ms, errorMsg ); if (result != charls::ApiResult::OK) { std::cerr << "Could not patch JAI-JPEGLS: " << errorMsg << std::endl; return 1; } rgbyteOutall.insert( rgbyteOutall.end(), rgbyteOut.begin(), rgbyteOut.end() ); } gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0,0x0010) ); pixeldata.SetVR( gdcm::VR::OW ); pixeldata.SetByteValue( (char*)&rgbyteOutall[0], (uint32_t)rgbyteOutall.size() ); // Add the pixel data element reader.GetFile().GetDataSet().Replace( pixeldata ); reader.GetFile().GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian); gdcm::Writer writer; writer.SetFileName( outfilename ); writer.SetFile( reader.GetFile() ); writer.Write(); std::cout << "Success !" << std::endl; return 0; } GDCM-3.0.10/Examples/Cxx/FixOrientation.cxx000066400000000000000000000043721412732066400203260ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmFile.h" #include "gdcmOrientation.h" #include "gdcmAttribute.h" // Very simple orientation changer, fix invalid dataset int main(int argc, char* argv[] ) { // assume AXIAL input for now if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; gdcm::Reader reader; reader.SetFileName( filename ); if (! reader.Read() ) { return 1; } const double axial[] = { 1,0,0, 0,1,0 }; (void)axial; const double coronal[] = { 0,0,1, 1,0,0 }; (void)coronal; const double sagittal[] = { 0,1,0, 0,0,1 }; (void)sagittal; gdcm::Attribute<0x0020,0x0032> at1; // IPP (void)at1; gdcm::Attribute<0x0020,0x0037> at2; // IOP (void)at2; gdcm::File & f = reader.GetFile(); gdcm::DataSet & ds = f.GetDataSet(); at1.SetFromDataSet( ds ); #if 0 at2.SetFromDataSet( ds ); const double * iop = at2.GetValues(); if( !std::equal(iop, iop + 6, axial ) ) { gdcm::Orientation::OrientationType type = gdcm::Orientation::GetType ( iop ); std::cerr << "Wrong orientation: " << gdcm::Orientation::GetLabel( type ) << std::endl; return 1; } at2.SetValues( sagittal ); ds.Replace( at2.GetAsDataElement() ); #endif // for sagittal: swap element 0 & 2 const double tmp0 = at1.GetValue(0); const double tmp2 = at1.GetValue(2); (void)tmp2; //at1.SetValue(tmp2, 0); //at1.SetValue(tmp0, 2); at1.SetValue( - tmp0 ); ds.Replace( at1.GetAsDataElement() ); gdcm::Writer writer; writer.SetFile( f ); writer.SetFileName( outfilename ); if ( !writer.Write() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/GenAllVR.cxx000066400000000000000000000107241412732066400167740ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmGlobal.h" #include "gdcmDummyValueGenerator.h" #include "gdcmMediaStorage.h" #include "gdcmWriter.h" #include "gdcmItem.h" #include "gdcmImageReader.h" #include "gdcmSequenceOfItems.h" #include "gdcmFile.h" #include "gdcmTag.h" #include "gdcmDict.h" #include "gdcmDictEntry.h" #include "gdcmDicts.h" #include "gdcmTransferSyntax.h" #include "gdcmUIDGenerator.h" #include "gdcmFileExplicitFilter.h" #include #include gdcm::Tag FindTagFromVR(gdcm::Dict const &dict, gdcm::VR const &vr) { using gdcm::Dict; Dict::ConstIterator beg = dict.Begin(); Dict::ConstIterator end = dict.End(); Dict::ConstIterator it; for( it = beg; it != end; ++it) { const gdcm::Tag &t = it->first; const gdcm::DictEntry &de = it->second; const gdcm::VR &vr_de = de.GetVR(); if( vr == vr_de && !de.GetRetired() && t.GetGroup() >= 0x8 ) { return t; } } return gdcm::Tag(0xffff,0xffff); } struct rnd_gen { rnd_gen(char const* r = "abcdefghijklmnopqrstuvwxyz0123456789") : range(r), len(std::strlen(r)) { } char operator ()() const { return range[static_cast(std::rand() * (1.0 / ((double)RAND_MAX + 1.0 )) * (double)len)]; } private: char const* range; std::size_t len; }; /* */ int main(int argc, char *argv[]) { if( argc < 2 ) { std::cerr << argv[0] << " output.dcm" << std::endl; return 1; } const char *outfilename = argv[1]; static const gdcm::Global &g = gdcm::Global::GetInstance(); static const gdcm::Dicts &dicts = g.GetDicts(); static const gdcm::Dict &pubdict = dicts.GetPublicDict(); using gdcm::VR; using gdcm::Tag; gdcm::Writer w; gdcm::File &f = w.GetFile(); gdcm::DataSet &ds = f.GetDataSet(); gdcm::FileExplicitFilter fef; //fef.SetChangePrivateTags( true ); fef.SetFile( w.GetFile() ); if( !fef.Change() ) { std::cerr << "Failed to change" << std::endl; return 1; } gdcm::SmartPointer sq = new gdcm::SequenceOfItems(); sq->SetLengthToUndefined(); // gdcm::DummyValueGenerator dvg; const std::size_t len = 10; char ss[len+1]; ss[len] = '\0'; const char owner_str[] = "GDCM CONFORMANCE TESTS"; gdcm::DataElement owner( gdcm::Tag(0x4d4d, 0x10) ); owner.SetByteValue(owner_str, (uint32_t)strlen(owner_str)); owner.SetVR( gdcm::VR::LO ); // Create an item gdcm::Item it; it.SetVLToUndefined(); gdcm::DataSet &nds = it.GetNestedDataSet(); // nds.Insert(owner); // nds.Insert(de); // Insert sequence into data set gdcm::DataElement des( gdcm::Tag(0x4d4d,0x1001) ); des.SetVR(gdcm::VR::SQ); des.SetValue(*sq); des.SetVLToUndefined(); ds.Insert(owner); ds.Insert(des); // avoid INVALID = 0 for(int i = 1; i < 27; ++i) { VR vr = (VR::VRType)(1LL << i); Tag t = FindTagFromVR( pubdict, vr ); if( vr != VR::UN && vr != VR::SQ ) { assert( t != Tag(0xffff,0xffff) ); gdcm::DataElement de( t ); std::generate_n(ss, len, rnd_gen()); de.SetVR( vr ); de.SetByteValue( ss, (uint32_t)std::strlen( ss ) ); nds.Insert( de ); } } sq->AddItem(it); // Make sure to override any UID stuff gdcm::UIDGenerator uid; gdcm::DataElement de( Tag(0x8,0x18) ); // SOP Instance UID de.SetVR( VR::UI ); const char *u = uid.Generate(); de.SetByteValue( u, (uint32_t)strlen(u) ); ds.Insert( de ); de.SetTag( Tag(0x8,0x16) ); // SOP Class UID de.SetVR( VR::UI ); gdcm::MediaStorage ms( gdcm::MediaStorage::RawDataStorage ); de.SetByteValue( ms.GetString(), (uint32_t)strlen(ms.GetString())); ds.Insert( de ); gdcm::FileMetaInformation &fmi = f.GetHeader(); //fmi.SetDataSetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian ); fmi.SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); w.SetCheckFileMetaInformation( true ); w.SetFileName( outfilename ); if (!w.Write() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/GenFakeIdentifyFile.cxx000066400000000000000000000122271412732066400211560ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmGlobal.h" #include "gdcmDummyValueGenerator.h" #include "gdcmMediaStorage.h" #include "gdcmWriter.h" #include "gdcmItem.h" #include "gdcmImageReader.h" #include "gdcmSequenceOfItems.h" #include "gdcmAttribute.h" #include "gdcmFile.h" #include "gdcmTag.h" #include "gdcmDict.h" #include "gdcmDictEntry.h" #include "gdcmDicts.h" #include "gdcmTransferSyntax.h" #include "gdcmUIDGenerator.h" #include "gdcmAnonymizer.h" #include #include gdcm::DataElement CreateFakeElement(gdcm::Tag const &tag, bool toremove) { static const gdcm::Global &g = gdcm::Global::GetInstance(); static const gdcm::Dicts &dicts = g.GetDicts(); static const gdcm::Dict &pubdict = dicts.GetPublicDict(); static size_t countglobal = 0; static std::vector balcptags = gdcm::Anonymizer::GetBasicApplicationLevelConfidentialityProfileAttributes(); size_t count = countglobal % balcptags.size(); const gdcm::DictEntry &dictentry = pubdict.GetDictEntry(tag); gdcm::DataElement de; de.SetTag( tag ); using gdcm::VR; const VR &vr = dictentry.GetVR(); //if( vr != VR::INVALID ) if( vr.IsDual() ) { if( vr == VR::US_SS ) { de.SetVR( VR::US ); } else if( vr == VR::US_SS_OW ) { de.SetVR( VR::OW ); } else if( vr == VR::OB_OW ) { de.SetVR( VR::OB ); } } else { de.SetVR( vr ); } const char str[] = "BasicApplicationLevelConfidentialityProfileAttributes"; const char safe[] = "This is safe to keep"; if( de.GetVR() != VR::SQ ) { if( toremove ) de.SetByteValue( str, (uint32_t)strlen(str) ); else de.SetByteValue( safe, (uint32_t)strlen(safe) ); } else { // Create an item gdcm::Item it; it.SetVLToUndefined(); gdcm::DataSet &nds = it.GetNestedDataSet(); // Insert sequence into data set assert(de.GetVR() == gdcm::VR::SQ ); gdcm::SmartPointer sq = new gdcm::SequenceOfItems(); sq->SetLengthToUndefined(); de.SetValue(*sq); de.SetVLToUndefined(); //ds.Insert(de); if( !toremove ) { nds.Insert( CreateFakeElement( balcptags[count], true ) ); countglobal++; } else { gdcm::Attribute<0x0008,0x0000> at1 = { 0 }; // This element has no reason to be 'anonymized'... nds.Insert( at1.GetAsDataElement() ); gdcm::Attribute<0x000a,0x0000> at2 = { 0 }; nds.Insert( at2.GetAsDataElement() ); } sq->AddItem(it); } return de; } /* */ int main(int argc, char *argv[]) { if( argc < 2 ) { std::cerr << argv[0] << " output.dcm" << std::endl; return 1; } using gdcm::Tag; using gdcm::VR; const char *outfilename = argv[1]; std::vector balcptags = gdcm::Anonymizer::GetBasicApplicationLevelConfidentialityProfileAttributes(); gdcm::Writer w; gdcm::File &f = w.GetFile(); gdcm::DataSet &ds = f.GetDataSet(); // Add attribute that need to be anonymized: std::vector::const_iterator it = balcptags.begin(); for(; it != balcptags.end(); ++it) { ds.Insert( CreateFakeElement( *it, true ) ); } // Add attribute that do NOT need to be anonymized: static const gdcm::Global &g = gdcm::Global::GetInstance(); static const gdcm::Dicts &dicts = g.GetDicts(); static const gdcm::Dict &pubdict = dicts.GetPublicDict(); using gdcm::Dict; Dict::ConstIterator dictit = pubdict.Begin(); for(; dictit != pubdict.End(); ++dictit) { const gdcm::Tag &dicttag = dictit->first; if( dicttag == Tag(0x6e65,0x6146) ) break; //const gdcm::DictEntry &dictentry = dictit->second; ds.Insert( CreateFakeElement( dicttag, false ) ); } ds.Remove( gdcm::Tag(0x400,0x500) ); ds.Remove( gdcm::Tag(0x12,0x62) ); ds.Remove( gdcm::Tag(0x12,0x63) ); // Make sure to override any UID stuff gdcm::UIDGenerator uid; gdcm::DataElement de( Tag(0x8,0x18) ); // SOP Instance UID de.SetVR( VR::UI ); const char *u = uid.Generate(); de.SetByteValue( u, (uint32_t)strlen(u) ); //ds.Insert( de ); ds.Replace( de ); de.SetTag( Tag(0x8,0x16) ); // SOP Class UID de.SetVR( VR::UI ); gdcm::MediaStorage ms( gdcm::MediaStorage::RawDataStorage ); de.SetByteValue( ms.GetString(), (uint32_t)strlen(ms.GetString())); ds.Replace( de ); // replace ! gdcm::FileMetaInformation &fmi = f.GetHeader(); //fmi.SetDataSetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian ); fmi.SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); w.SetCheckFileMetaInformation( true ); w.SetFileName( outfilename ); if (!w.Write() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/GenFakeImage.cxx000066400000000000000000000077131412732066400176310ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImage.h" #include "gdcmImageWriter.h" #include "gdcmFileDerivation.h" #include "gdcmUIDGenerator.h" //#include "gdcmImageChangePhotometricInterpretation.h" /* * This example shows two things: * 1. How to create an image ex-nihilo * 2. How to use the gdcm.FileDerivation filter. This filter is meant to create "DERIVED" image * object. FileDerivation has a simple API where you can reference *all* the input image that have been * used to generate the image. The API also allows user to specify the purpose of reference (see CID 7202, * PS 3.16 - 2008), and the image derivation type (CID 7203, PS 3.16 - 2008). */ int main(int, char *[]) { // Step 1: Fake Image gdcm::SmartPointer im = new gdcm::Image; char * buffer = new char[ 256 * 256 * 3]; char * p = buffer; int b = 128; //int ybr[3]; int ybr2[3]; //int rgb[3]; for(int r = 0; r < 256; ++r) for(int g = 0; g < 256; ++g) //for(int b = 0; b < 256; ++b) { //rgb[0] = r; //rgb[1] = g; //rgb[1] = 128; //rgb[2] = b; //ybr[0] = r; //ybr[1] = g; //ybr[1] = 128; //ybr[2] = b; ybr2[0] = r; ybr2[1] = g; ybr2[1] = 128; ybr2[2] = b; //gdcm::ImageChangePhotometricInterpretation::YBR2RGB(rgb, ybr); //gdcm::ImageChangePhotometricInterpretation::RGB2YBR(ybr2, rgb); *p++ = (char)ybr2[0]; *p++ = (char)ybr2[1]; *p++ = (char)ybr2[2]; } im->SetNumberOfDimensions( 2 ); im->SetDimension(0, 256 ); im->SetDimension(1, 256 ); im->GetPixelFormat().SetSamplesPerPixel(3); //im->SetPhotometricInterpretation( gdcm::PhotometricInterpretation::RGB ); im->SetPhotometricInterpretation( gdcm::PhotometricInterpretation::YBR_FULL ); unsigned long l = im->GetBufferLength(); if( l != 256 * 256 * 3 ) { return 1; } gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0,0x0010) ); pixeldata.SetByteValue( buffer, (uint32_t)l ); delete[] buffer; im->SetDataElement( pixeldata ); gdcm::UIDGenerator uid; // helper for uid generation gdcm::SmartPointer file = new gdcm::File; // empty file // Step 2: DERIVED object gdcm::FileDerivation fd; // For the pupose of this execise we will pretend that this image is referencing // two source image (we need to generate fake UID for that). const char ReferencedSOPClassUID[] = "1.2.840.10008.5.1.4.1.1.7"; // Secondary Capture fd.AddReference( ReferencedSOPClassUID, uid.Generate() ); fd.AddReference( ReferencedSOPClassUID, uid.Generate() ); // Again for the purpose of the exercise we will pretend that the image is a // multiplanar reformat (MPR): // CID 7202 Source Image Purposes of Reference // {"DCM",121322,"Source image for image processing operation"}, fd.SetPurposeOfReferenceCodeSequenceCodeValue( 121322 ); // CID 7203 Image Derivation // { "DCM",113072,"Multiplanar reformatting" }, fd.SetDerivationCodeSequenceCodeValue( 113072 ); fd.SetFile( *file ); // If all Code Value are ok the filter will execute properly if( !fd.Derive() ) { std::cerr << "Sorry could not derive using input info" << std::endl; return 1; } // We pass both : // 1. the fake generated image // 2. the 'DERIVED' dataset object // to the writer. gdcm::ImageWriter w; w.SetImage( *im ); w.SetFile( fd.GetFile() ); // Set the filename: w.SetFileName( "ybr2.dcm" ); if( !w.Write() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/GenLongSeqs.cxx000066400000000000000000000054731412732066400175540ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmItem.h" #include "gdcmImageReader.h" #include "gdcmSequenceOfItems.h" #include "gdcmFile.h" #include "gdcmTag.h" /* * This example is used to generate the file: * * * There is a flaw in the DICOM design were it is assumed that Sequence can be * either represented as undefined length or defined length. This should work * in most case, but the undefined length is a little more general and can * store sequence of items that a defined length cannot. * We need to make sure that we can store numerous Item in a SQ * * Warning: do not try to compute the group length elements ! * Warning: You may need a 64bits machine for this example to work. */ int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { return 1; } gdcm::File &file = reader.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); // Create a Sequence gdcm::SmartPointer sq = new gdcm::SequenceOfItems(); sq->SetLengthToUndefined(); const char owner_str[] = "GDCM CONFORMANCE TESTS"; gdcm::DataElement owner( gdcm::Tag(0x4d4d, 0x10) ); owner.SetByteValue(owner_str, (uint32_t)strlen(owner_str)); owner.SetVR( gdcm::VR::LO ); size_t nitems = 1000; nitems += std::numeric_limits::max(); for(unsigned int idx = 0; idx < nitems; ++idx) { // Create a dataelement //gdcm::DataElement de( gdcm::Tag(0x4d4d, 0x1002) ); //de.SetByteValue(ptr, ptr_len); //de.SetVR( gdcm::VR::OB ); // Create an item gdcm::Item it; it.SetVLToUndefined(); //gdcm::DataSet &nds = it.GetNestedDataSet(); //nds.Insert(owner); //nds.Insert(de); sq->AddItem(it); } // Insert sequence into data set gdcm::DataElement des( gdcm::Tag(0x4d4d,0x1001) ); des.SetVR(gdcm::VR::SQ); des.SetValue(*sq); des.SetVLToUndefined(); ds.Insert(owner); ds.Insert(des); gdcm::Writer w; w.SetFile( file ); //w.SetCheckFileMetaInformation( true ); w.SetFileName( outfilename ); if (!w.Write() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/GenSeqs.cxx000066400000000000000000000060761412732066400167340ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmItem.h" #include "gdcmImageReader.h" #include "gdcmSequenceOfItems.h" #include "gdcmFile.h" #include "gdcmTag.h" /* * This example is used to generate the file: * * gdcmConformanceTests/SequenceWithUndefinedLengthNotConvertibleToDefinedLength.dcm * * There is a flaw in the DICOM design were it is assumed that Sequence can be * either represented as undefined length or defined length. This should work * in most case, but the undefined length is a little more general and can * store sequence of items that a defined length cannot. * Deflated syntax was used in this case since this synthetic example can be * nicely compressed using this transfer syntax. * * Warning: do not try to compute the group length elements ! * Warning: You may need a 64bits machine for this example to work. */ int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { return 1; } gdcm::File &file = reader.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); //const unsigned int nitems = 1000; const unsigned int ptr_len = 42; /*94967296 / nitems; */ //assert( ptr_len == 42949672 ); char *ptr = new char[ptr_len]; memset(ptr,0,ptr_len); // Create a Sequence gdcm::SmartPointer sq = new gdcm::SequenceOfItems(); sq->SetLengthToUndefined(); const char owner_str[] = "GDCM CONFORMANCE TESTS"; gdcm::DataElement owner( gdcm::Tag(0x4d4d, 0x10) ); owner.SetByteValue(owner_str, (uint32_t)strlen(owner_str)); owner.SetVR( gdcm::VR::LO ); for(unsigned int idx = 0; idx < 10/* nitems*/; ++idx) { // Create a dataelement gdcm::DataElement de( gdcm::Tag(0x4d4d, 0x1002) ); de.SetByteValue(ptr, ptr_len); de.SetVR( gdcm::VR::OB ); // Create an item gdcm::Item it; it.SetVLToUndefined(); gdcm::DataSet &nds = it.GetNestedDataSet(); nds.Insert(owner); nds.Insert(de); sq->AddItem(it); } // Insert sequence into data set gdcm::DataElement des( gdcm::Tag(0x4d4d,0x1001) ); des.SetVR(gdcm::VR::SQ); des.SetValue(*sq); des.SetVLToUndefined(); ds.Insert(owner); ds.Insert(des); gdcm::Writer w; w.SetFile( file ); //w.SetCheckFileMetaInformation( true ); w.SetFileName( outfilename ); if (!w.Write() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/GenerateStandardSOPClasses.cxx000066400000000000000000000040751412732066400224770ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDefs.h" #include "gdcmUIDs.h" #include "gdcmGlobal.h" #include "gdcmMediaStorage.h" #include "gdcmSOPClassUIDToIOD.h" int main(int , char *[]) { using gdcm::MediaStorage; gdcm::Global& g = gdcm::Global::GetInstance(); if( !g.LoadResourcesFiles() ) { std::cerr << "Could not LoadResourcesFiles" << std::endl; return 1; } const gdcm::Defs &defs = g.GetDefs(); int ret = 0; //std::cout << "Table B.5-1 STANDARD SOP CLASSES" << std::endl; std::cout << "SOP Class Name,SOP Class UID,IOD Specification (defined in PS 3.3)" << std::endl; gdcm::MediaStorage::MSType mst; for ( mst = gdcm::MediaStorage::MediaStorageDirectoryStorage; mst < gdcm::MediaStorage::MS_END; mst = (gdcm::MediaStorage::MSType)(mst + 1) ) { const char *iod = defs.GetIODNameFromMediaStorage(mst); gdcm::UIDs uid; uid.SetFromUID( gdcm::MediaStorage::GetMSString(mst) /*mst.GetString()*/ ); if( iod ) { const char *iod_ref = gdcm::SOPClassUIDToIOD::GetIOD(uid); if( iod_ref ) { std::string iod_ref_str = iod_ref; //iod_ref_str += " IOD Modules"; //if( iod_ref_str != iod ) { //std::cout << "UID: " << uid << " "; std::cout << '"' << uid.GetName() << '"' <<"," << '"' < #include int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.jpg" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } // The output of gdcm::Reader is a gdcm::File const gdcm::File &file = reader.GetFile(); const gdcm::Image &image = reader.GetImage(); const gdcm::TransferSyntax &ts = file.GetHeader().GetDataSetTransferSyntax(); if( ts != gdcm::TransferSyntax::JPEGLosslessProcess14 && ts != gdcm::TransferSyntax::JPEGLosslessProcess14_1 ) { std::cerr << "Input is not a lossless JPEG" << std::endl; return 1; } // the dataset is the the set of element we are interested in: const gdcm::DataSet &ds = file.GetDataSet(); const gdcm::Tag rawTag(0x7fe0, 0x0010); // Default to Pixel Data const gdcm::DataElement& pdde = ds.GetDataElement( rawTag ); const gdcm::SequenceOfFragments *sf = pdde.GetSequenceOfFragments(); if( sf ) { std::ofstream output(outfilename, std::ios::binary); sf->WriteBuffer(output); } else { std::cerr << "Error" << std::endl; return 1; } gdcm::JPEGCodec jpeg; std::ifstream is(outfilename, std::ios::binary); gdcm::PixelFormat pf ( gdcm::PixelFormat::UINT8 ); // let's pretend it's a 8bits jpeg jpeg.SetPixelFormat( pf ); gdcm::TransferSyntax ts_jpg; bool b = jpeg.GetHeaderInfo( is, ts_jpg ); if( !b ) { return 1; } //jpeg.Print( std::cout ); if( jpeg.GetPixelFormat().GetBitsAllocated() != image.GetPixelFormat().GetBitsAllocated() || jpeg.GetPixelFormat().GetBitsStored() != image.GetPixelFormat().GetBitsStored() ) { std::cerr << "There is a mismatch in between DICOM declared Pixel Format and Sample Precision used in the JPEG stream" << std::endl; return 0; } std::cout << jpeg.GetPixelFormat() << std::endl; std::cout << image.GetPixelFormat() << std::endl; return 1; } GDCM-3.0.10/Examples/Cxx/GetSequenceUltrasound.cxx000066400000000000000000000102321412732066400216450ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmAttribute.h" bool Region ( char* nomefile, unsigned int* X_min, unsigned int* Y_min, unsigned int* X_max, unsigned int* Y_max ); int main(int argc, char* argv[] ) { // Controllo del numero di argomenti introdotti da riga di comando if( argc < 2 ) { std::cerr << "Usage: " << std::endl; std::cerr << argv[0] << " inputImageFile " << std::endl; return EXIT_FAILURE; } unsigned int x_min = 1; unsigned int y_min = 1; unsigned int x_max = 1; unsigned int y_max = 1; if( Region ( argv[1], &x_min, &y_min, &x_max, &y_max ) ) { std::cout << "x_min = " << x_min << std::endl; std::cout << "y_min = " << y_min << std::endl; std::cout << "x_max = " << x_max << std::endl; std::cout << "y_max = " << y_max << std::endl; } else { std::cout << "no\n"; } } bool Region ( char* nomefile, unsigned int* X_min, unsigned int* Y_min, unsigned int* X_max, unsigned int* Y_max ) { gdcm::Reader reader; reader.SetFileName( nomefile ); if( !reader.Read() ) { std::cerr << "Could not read: " << nomefile << std::endl; return false; } gdcm::File &file = reader.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); gdcm::Tag tsqur(0x0018,0x6011); if( !ds.FindDataElement( tsqur ) ) { return false; } const gdcm::DataElement &squr= ds.GetDataElement( tsqur ); //std::cout << squr << std::endl; const gdcm::SequenceOfItems *sqi = squr.GetValueAsSQ(); if( !sqi || !sqi->GetNumberOfItems() ) { return false; } //std::cout << sqi << std::endl; const gdcm::Item & item = sqi->GetItem(1); //std::cout << item << std::endl; const gdcm::DataSet& nestedds = item.GetNestedDataSet(); //std::cout << nestedds << std::endl; gdcm::Tag tX0(0x0018,0x6018); gdcm::Tag tY0(0x0018,0x601a); gdcm::Tag tX1(0x0018,0x601c); gdcm::Tag tY1(0x0018,0x601e); if( (!nestedds.FindDataElement( tX0 ))||(!nestedds.FindDataElement( tY0 ))||(!nestedds.FindDataElement( tX1 ))||(!nestedds.FindDataElement( tY1 )) ) { return false; } const gdcm::DataElement& deX0 = nestedds.GetDataElement( tX0 ); const gdcm::DataElement& deY0 = nestedds.GetDataElement( tY0 ); const gdcm::DataElement& deX1 = nestedds.GetDataElement( tX1 ); const gdcm::DataElement& deY1 = nestedds.GetDataElement( tY1 ); //std::cout << deX0 << std::endl << deY0 << std::endl << deX1 << std::endl << deY1 << std::endl; //const gdcm::ByteValue *bvX0 = deX0.GetByteValue(); //const gdcm::ByteValue *bvY0 = deY0.GetByteValue(); //const gdcm::ByteValue *bvX1 = deX1.GetByteValue(); //const gdcm::ByteValue *bvY1 = deY1.GetByteValue(); //std::cout << bvX0 << std::endl << bvY0 << std::endl << bvX1 << std::endl << bvY1 << std::endl; gdcm::Attribute<0x0018,0x6018> atX0; gdcm::Attribute<0x0018,0x601a> atY0; gdcm::Attribute<0x0018,0x601c> atX1; gdcm::Attribute<0x0018,0x601e> atY1; atX0.SetFromDataElement( deX0 ); atY0.SetFromDataElement( deY0 ); atX1.SetFromDataElement( deX1 ); atY1.SetFromDataElement( deY1 ); uint32_t X0 = atX0.GetValue(); uint32_t Y0 = atY0.GetValue(); uint32_t X1 = atX1.GetValue(); uint32_t Y1 = atY1.GetValue(); std::cout << X0 << std::endl << Y0 << std::endl << X1 << std::endl << Y1 << std::endl; *X_min = static_cast(X0); *Y_min = static_cast(Y0); *X_max = static_cast(X1); *Y_max = static_cast(Y1); //std::cout << "X_min = " << *X_min << std::endl; //std::cout << "Y_min = " << *Y_min << std::endl; //std::cout << "X_max = " << *X_max << std::endl; //std::cout << "Y_max = " << *Y_max << std::endl; return true; } GDCM-3.0.10/Examples/Cxx/GetSubSequenceData.cxx000066400000000000000000000145031412732066400210350ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmImage.h" #include "gdcmImageWriter.h" #include "gdcmDataElement.h" #include "gdcmPrivateTag.h" #include "gdcmUIDGenerator.h" #include #include #include /* * This example will extract the Movie from the private group of * GEMS_Ultrasound_MovieGroup_001 See Attribute * (7fe1,60,GEMS_Ultrasound_MovieGroup_001) * * The output file will be stored in `outvid.dcm` as * MultiframeGrayscaleByteSecondaryCaptureImageStorage */ int main(int argc, char *argv[]) { if( argc < 2 ) return 1; using namespace gdcm; const char *filename = argv[1]; gdcm::Reader reader; reader.SetFileName( filename ); reader.Read(); gdcm::File &file = reader.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); const PrivateTag tseq(0x7fe1,0x1,"GEMS_Ultrasound_MovieGroup_001"); if( !ds.FindDataElement( tseq ) ) return 1; const DataElement& seq = ds.GetDataElement( tseq ); SmartPointer sqi = seq.GetValueAsSQ(); assert( sqi->GetNumberOfItems() == 1 ); Item &item = sqi->GetItem(1); DataSet &subds = item.GetNestedDataSet(); const PrivateTag tseq1(0x7fe1,0x10,"GEMS_Ultrasound_MovieGroup_001"); if( !subds.FindDataElement( tseq1 ) ) return 1; const DataElement& seq1 = subds.GetDataElement( tseq1 ); SmartPointer sqi2 = seq1.GetValueAsSQ(); //int n = sqi2->GetNumberOfItems(); int index = 1; Item &item2 = sqi2->GetItem(index); DataSet &subds2 = item2.GetNestedDataSet(); const PrivateTag tseq2(0x7fe1,0x20,"GEMS_Ultrasound_MovieGroup_001"); if( !subds2.FindDataElement( tseq2 ) ) return 1; const DataElement& seq2 = subds2.GetDataElement( tseq2 ); // std::cout << seq2 << std::endl; SmartPointer sqi3 = seq2.GetValueAsSQ(); size_t ni3 = sqi3->GetNumberOfItems(); (void)ni3; assert( sqi3->GetNumberOfItems() >= 1 ); Item &item3 = sqi3->GetItem(1); DataSet &subds3 = item3.GetNestedDataSet(); const PrivateTag tseq6(0x7fe1,0x26,"GEMS_Ultrasound_MovieGroup_001"); if( !subds3.FindDataElement( tseq6 ) ) return 1; const DataElement& seq6 = subds3.GetDataElement( tseq6 ); SmartPointer sqi6 = seq6.GetValueAsSQ(); size_t ni6= sqi6->GetNumberOfItems(); assert( sqi6->GetNumberOfItems() >= 1 ); const PrivateTag tseq7(0x7fe1,0x86,"GEMS_Ultrasound_MovieGroup_001"); int dimx = 0, dimy = 0; for( size_t i6 = 1; i6 <= ni6; ++i6 ) { Item &item6 = sqi6->GetItem(i6); DataSet &subds6 = item6.GetNestedDataSet(); if( subds6.FindDataElement( tseq7 ) ) { Element el; el.SetFromDataElement( subds6.GetDataElement( tseq7 ) ); std::cout << "El= " << el.GetValue() << std::endl; dimx = el.GetValue(0); dimy = el.GetValue(1); } } const PrivateTag tseq3(0x7fe1,0x36,"GEMS_Ultrasound_MovieGroup_001"); if( !subds3.FindDataElement( tseq3 ) ) return 1; const DataElement& seq3 = subds3.GetDataElement( tseq3 ); // std::cout << seq3 << std::endl; SmartPointer sqi4 = seq3.GetValueAsSQ(); size_t ni4= sqi4->GetNumberOfItems(); assert( sqi4->GetNumberOfItems() >= 1 ); const PrivateTag tseq8(0x7fe1,0x37,"GEMS_Ultrasound_MovieGroup_001"); const PrivateTag tseq4(0x7fe1,0x43,"GEMS_Ultrasound_MovieGroup_001"); const PrivateTag tseq5(0x7fe1,0x60,"GEMS_Ultrasound_MovieGroup_001"); std::vector imbuffer; int dimz = 0; for( size_t i4 = 1; i4 <= ni4; ++i4 ) { Item &item4 = sqi4->GetItem(i4); DataSet &subds4 = item4.GetNestedDataSet(); if( !subds4.FindDataElement( tseq8 ) ) return 1; const DataElement& de8 = subds4.GetDataElement( tseq8 ); Element ldimz; ldimz.SetFromDataElement( de8 ); dimz += ldimz.GetValue(); if( !subds4.FindDataElement( tseq4 ) ) return 1; const DataElement& seq4 = subds4.GetDataElement( tseq4 ); if( !subds4.FindDataElement( tseq5 ) ) return 1; const DataElement& seq5 = subds4.GetDataElement( tseq5 ); // std::cout << seq4 << std::endl; // std::cout << seq5 << std::endl; const ByteValue *bv4 = seq4.GetByteValue(); (void)bv4; #if 0 { std::ofstream out( "/tmp/mo4", std::ios::binary ); out.write( bv4->GetPointer(), bv4->GetLength()); out.close(); } #endif const ByteValue *bv5 = seq5.GetByteValue(); #if 0 { std::ofstream out( "/tmp/mo5", std::ios::binary ); out.write( bv5->GetPointer(), bv5->GetLength()); out.close(); } #endif std::cout << bv5->GetLength() << std::endl; imbuffer.insert( imbuffer.begin(), bv5->GetPointer(), bv5->GetPointer() + bv5->GetLength() ); } DataElement fakedata; fakedata.SetByteValue( &imbuffer[0], (uint32_t)imbuffer.size() ); gdcm::SmartPointer im = new gdcm::Image; im->SetNumberOfDimensions( 3 ); im->SetDimension(0, dimx ); im->SetDimension(1, dimy ); im->SetDimension(2, dimz ); size_t l1 = imbuffer.size(); (void)l1; size_t l2 = im->GetBufferLength(); (void)l2; assert( im->GetBufferLength() == imbuffer.size() ); im->SetPhotometricInterpretation( gdcm::PhotometricInterpretation::MONOCHROME2 ); im->SetDataElement( fakedata ); gdcm::ImageWriter w; w.SetImage( *im ); DataSet &dataset = w.GetFile().GetDataSet(); gdcm::UIDGenerator uid; gdcm::DataElement de( Tag(0x8,0x18) ); // SOP Instance UID de.SetVR( VR::UI ); const char *u = uid.Generate(); de.SetByteValue( u, (uint32_t)strlen(u) ); //ds.Insert( de ); dataset.Replace( de ); de.SetTag( Tag(0x8,0x16) ); // SOP Class UID de.SetVR( VR::UI ); gdcm::MediaStorage ms( gdcm::MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage ); de.SetByteValue( ms.GetString(), (uint32_t)strlen(ms.GetString())); dataset.Replace( de ); // replace ! w.SetFileName( "outvid.dcm" ); if( !w.Write() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/HelloVizWorld.cxx000066400000000000000000000050701412732066400201240ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Basic example for dealing with a DICOM file that contains an Image * (read: Pixel Data element) */ #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmImage.h" #include "gdcmPhotometricInterpretation.h" #include int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; // Instanciate the image reader: gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } // If we reach here, we know for sure 2 things: // 1. It is a valid DICOM // 2. And it contains an Image ! // The output of superclass gdcm::Reader is a gdcm::File //gdcm::File &file = reader.GetFile(); // The other output of gdcm::ImageReader is a gdcm::Image const gdcm::Image &image = reader.GetImage(); // Let's get some property from the image: unsigned int ndim = image.GetNumberOfDimensions(); // Dimensions of the image: const unsigned int *dims = image.GetDimensions(); // Origin const double *origin = image.GetOrigin(); const gdcm::PhotometricInterpretation &pi = image.GetPhotometricInterpretation(); for(unsigned int i = 0; i < ndim; ++i) { std::cout << "Dim(" << i << "): " << dims[i] << std::endl; } for(unsigned int i = 0; i < ndim; ++i) { std::cout << "Origin(" << i << "): " << origin[i] << std::endl; } std::cout << "PhotometricInterpretation: " << pi << std::endl; // Write the modified DataSet back to disk gdcm::ImageWriter writer; writer.SetImage( image ); writer.SetFileName( outfilename ); //writer.SetFile( file ); // We purposely NOT copy the meta information from the input // file, and instead only pass the image if( !writer.Write() ) { std::cerr << "Could not write: " << outfilename << std::endl; return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/HelloWorld.cxx000066400000000000000000000045771412732066400174460ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This example is ... guess what this is for :) */ #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmAttribute.h" #include int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; // Instanciate the reader: gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } // If we reach here, we know for sure only 1 thing: // It is a valid DICOM file (potentially an old ACR-NEMA 1.0/2.0 file) // (Maybe, it's NOT a Dicom image -could be a DICOMDIR, a RTSTRUCT, etc-) // The output of gdcm::Reader is a gdcm::File gdcm::File &file = reader.GetFile(); // the dataset is the the set of element we are interested in: gdcm::DataSet &ds = file.GetDataSet(); // Contruct a static(*) type for Image Comments : gdcm::Attribute<0x0020,0x4000> imagecomments; imagecomments.SetValue( "Hello, World !" ); // Now replace the Image Comments from the dataset with our: ds.Replace( imagecomments.GetAsDataElement() ); // Write the modified DataSet back to disk gdcm::Writer writer; writer.CheckFileMetaInformationOff(); // Do not attempt to reconstruct the file meta to preserve the file // as close to the original as possible. writer.SetFileName( outfilename ); writer.SetFile( file ); if( !writer.Write() ) { std::cerr << "Could not write: " << outfilename << std::endl; return 1; } return 0; } /* * (*) static type, means that extra DICOM information VR & VM are computed at compilation time. * The compiler is deducing those values from the template arguments of the class. */ GDCM-3.0.10/Examples/Cxx/LargeVRDSExplicit.cxx000066400000000000000000000133721412732066400206170ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmAttribute.h" #include "gdcmFileExplicitFilter.h" #include "gdcmSequenceOfItems.h" /** * This example is used to generate the file: * * gdcmConformanceTests/RTStruct_VRDSAsVRUN.dcm * * This is an advanced example. Its goal is to explain one dark corner of DICOM PS 3.10 * file format. The idea is that when writting an Attribute in an Explicit Transfer * Syntax one, cannot always use V:DS for writing a VR:DS attribute since dong so * would imply using a VL:16bits. * This example shows that converting from Implicit to Explicit should preserver VR:UN * when the VL is larger than 16bits limit. * * Usage: * ./LargeVRDSExplicit gdcmDataExtra/gdcmNonImageData/RT/RTStruct.dcm out.dcm */ bool interpolate(const double * pts, size_t npts, std::vector &out ) { out.clear(); for(size_t i = 0; i < 2*npts; ++i ) { const size_t j = i / 2; if( i % 2 ) { if( j != npts - 1 ) { assert( 3*j+5 < 3*npts ); const double midpointx = (pts[3*j+0] + pts[3*j+3]) / 2; const double midpointy = (pts[3*j+1] + pts[3*j+4]) / 2; const double midpointz = (pts[3*j+2] + pts[3*j+5]) / 2; out.push_back( midpointx ); out.push_back( midpointy ); out.push_back( midpointz ); } } else { assert( j < npts ); out.push_back( pts[3*j+0] ); out.push_back( pts[3*j+1] ); out.push_back( pts[3*j+2] ); } } assert( out.size() == 2 * npts * 3 - 3 ); return true; } int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { return 1; } gdcm::File &file = reader.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); gdcm::FileExplicitFilter fef; //fef.SetChangePrivateTags( changeprivatetags ); fef.SetFile( reader.GetFile() ); if( !fef.Change() ) { std::cerr << "Failed to change: " << filename << std::endl; return 1; } // (3006,0039) SQ (Sequence with undefined length #=4) # u/l, 1 ROIContourSequence gdcm::Tag tag(0x3006,0x0039); const gdcm::DataElement &roicsq = ds.GetDataElement( tag ); gdcm::SmartPointer sqi = roicsq.GetValueAsSQ(); //sqi->SetNumberOfItems( 1 ); const gdcm::Item & item = sqi->GetItem(1); // Item start at #1 const gdcm::DataSet& nestedds = item.GetNestedDataSet(); gdcm::Tag tcsq(0x3006,0x0040); if( !nestedds.FindDataElement( tcsq ) ) { return 0; } const gdcm::DataElement& csq = nestedds.GetDataElement( tcsq ); gdcm::SmartPointer sqi2 = csq.GetValueAsSQ(); if( !sqi2 || !sqi2->GetNumberOfItems() ) { return 0; } //unsigned int nitems = sqi2->GetNumberOfItems(); gdcm::Item & item2 = sqi2->GetItem(1); // Item start at #1 gdcm::DataSet& nestedds2 = item2.GetNestedDataSet(); //item2.SetVLToUndefined(); //std::cout << nestedds2 << std::endl; // (3006,0050) DS [43.57636\65.52504\-10.0\46.043102\62.564945\-10.0\49.126537\60.714... # 398,48 ContourData gdcm::Tag tcontourdata(0x3006,0x0050); const gdcm::DataElement & contourdata = nestedds2.GetDataElement( tcontourdata ); //std::cout << contourdata << std::endl; //const gdcm::ByteValue *bv = contourdata.GetByteValue(); gdcm::Attribute<0x3006,0x0046> ncontourpoints; ncontourpoints.Set( nestedds2 ); gdcm::Attribute<0x3006,0x0050> at; at.SetFromDataElement( contourdata ); const double* pts = at.GetValues(); unsigned int npts = at.GetNumberOfValues() / 3; std::vector out( pts, pts + npts * 3 ); std::vector out2; //const unsigned int niter = 7; const unsigned int niter = 8; for( unsigned int i = 0; i < niter; ++i) { //bool b = interpolate(&out[0], out.size() / 3, out2); //const double *pout = &out[0]; out = out2; out2.clear(); } assert( out.size() % 3 == 0 ); gdcm::Attribute<0x3006,0x0050> at_interpolate; at_interpolate.SetNumberOfValues( (unsigned int)(out.size() / 3) ); at_interpolate.SetValues( &out[0], (uint32_t)out.size() ); ncontourpoints.SetValue( at_interpolate.GetNumberOfValues() / 3 ); nestedds2.Replace( at_interpolate.GetAsDataElement() ); nestedds2.Replace( ncontourpoints.GetAsDataElement() ); //assert(0); // Let's take item one and subdivide it gdcm::TransferSyntax ts = gdcm::TransferSyntax::ImplicitVRLittleEndian; ts = gdcm::TransferSyntax::ExplicitVRLittleEndian; gdcm::FileMetaInformation &fmi = file.GetHeader(); const char *tsuid = gdcm::TransferSyntax::GetTSString( ts ); // const char * is ok since padding is \0 anyway... gdcm::DataElement de( gdcm::Tag(0x0002,0x0010) ); de.SetByteValue( tsuid, (uint32_t)strlen(tsuid) ); de.SetVR( gdcm::Attribute<0x0002, 0x0010>::GetVR() ); fmi.Replace( de ); fmi.Remove( gdcm::Tag(0x0002,0x0012) ); // will be regenerated fmi.Remove( gdcm::Tag(0x0002,0x0013) ); // ' ' ' fmi.SetDataSetTransferSyntax(ts); gdcm::Writer w; w.SetFile( file ); w.SetFileName( outfilename ); if (!w.Write() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/MakeTemplate.cxx000066400000000000000000000035501412732066400177320ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileAnonymizer.h" #include "gdcmReader.h" #include "gdcmWriter.h" int main(int argc, char *argv[]) { if( argc < 3 ) return 1; const char* filename = argv[1]; const char* outfilename = argv[2]; //gdcm::Trace::DebugOn(); // Remove Pixel Data element: gdcm::FileAnonymizer fa; fa.SetInputFileName( filename ); fa.SetOutputFileName( outfilename ); fa.Empty( gdcm::Tag(0x7fe0,0x10) ); // cannot replace in-place DICOM header: //fa.Replace( gdcm::Tag(0x2,0x2), "1.2.840.10008.5.1.4.1.1.7" ); if( !fa.Write() ) { std::cerr << "impossible to remove Pixel Data attribute" << std::endl; return 1; } // Update the DICOM Header: gdcm::Reader reader; reader.SetFileName( outfilename ); if( !reader.Read() ) { std::cerr << "could not read back" << std::endl; return 1; } gdcm::File & file = reader.GetFile(); gdcm::FileMetaInformation &fmi = file.GetHeader(); gdcm::TransferSyntax ts = gdcm::TransferSyntax::ImplicitVRLittleEndian; ts = gdcm::TransferSyntax::ExplicitVRLittleEndian; fmi.SetDataSetTransferSyntax(ts); gdcm::Writer writer; writer.SetFile( file ); writer.SetFileName( outfilename ); // warning overwrite file ! if( !writer.Write() ) { std::cerr << "could not write back" << std::endl; return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/MergeTwoFiles.cxx000066400000000000000000000050451412732066400200760ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This example will show how one can read in two DICOM files, use the dataset * from file1 and use image from file2 to save it in a 3rd file. * * Eg: * MergeTwoFiles gdcmData/012345.002.050.dcm gdcmData/test.acr merge.dcm */ #include "gdcmReader.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmWriter.h" #include "gdcmDataSet.h" #include "gdcmAttribute.h" int main(int argc, char *argv[]) { if( argc < 3 ) { return 1; } const char *file1 = argv[1]; const char *file2 = argv[2]; const char *file3 = argv[3]; // Read file1 gdcm::ImageReader reader1; reader1.SetFileName( file1 ); if( !reader1.Read() ) { return 1; } // Read file2 gdcm::ImageReader reader2; reader2.SetFileName( file2 ); if( !reader2.Read() ) { return 1; } // Ok now let's take the DataSet from file1 and the Image from file2 // Warning: if file2 is -for example- a Secondary Capture Storage, then it has no // Image Orientation (Patient) thus any Image Orientation (Patient) from file1 // will be discarded... // let's be fancy. In case reader2 contains explicit, but reader1 is implicit // we would rather see an implicit output if( reader1.GetFile().GetHeader().GetDataSetTransferSyntax() == gdcm::TransferSyntax::ImplicitVRLittleEndian ) { reader2.GetImage().SetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian ); } gdcm::ImageWriter writer; writer.SetFileName( file3 ); writer.SetFile( reader1.GetFile() ); // ImageWriter will always use all of gdcm::Image information an override anything wrong from // reader1.GetFile(), including the Transfer Syntax writer.SetImage( reader2.GetImage() ); gdcm::DataSet &ds = reader1.GetFile().GetDataSet(); // Make sure that SOPInstanceUID are different // Simply removing it is sufficient as gdcm::ImageWriter will generate one by default // if not found. ds.Remove( gdcm::Tag(0x0008,0x0018) ); if( !writer.Write() ) { return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/MrProtocol.cxx000066400000000000000000000557661412732066400175010ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * */ /* 28 - 'MrProtocol' VM 1, VR UN, SyngoDT 0, NoOfItems 6, Data '### ASCCONV BEGIN ### ulVersion = 0xbee332 tSequenceFileName = "%SiemensSeq%\fl_fq_shphs" tProtocolName = "flash+AF8-100+AF8-through-plane+AF8-V" tReferenceImage0 = "1.3.12.2.1107.5.2.9.16041.30000007062106100181200004658" tReferenceImage1 = "1.3.12.2.1107.5.2.9.16041.30000007062106100181200004635" tReferenceImage2 = "1.3.12.2.1107.5.2.9.16041.30000007062106100181200004683" ucScanRegionPosValid = 0x1 sProtConsistencyInfo.tBaselineString = "N4_VB11A_LATEST_20031004" sProtConsistencyInfo.flNominalB0 = 1.494 sProtConsistencyInfo.flGMax = 22 sProtConsistencyInfo.flRiseTime = 10 sGRADSPEC.sEddyCompensationX.aflAmplitude[0] = 0.0141111 sGRADSPEC.sEddyCompensationX.aflAmplitude[1] = 0.057038 sGRADSPEC.sEddyCompensationX.aflAmplitude[2] = -0.00986504 sGRADSPEC.sEddyCompensationX.aflAmplitude[3] = 0.00247627 sGRADSPEC.sEddyCompensationX.aflAmplitude[4] = 0.0026377 sGRADSPEC.sEddyCompensationX.aflTimeConstant[0] = 1.53826 sGRADSPEC.sEddyCompensationX.aflTimeConstant[1] = 0.746617 sGRADSPEC.sEddyCompensationX.aflTimeConstant[2] = 0.339236 sGRADSPEC.sEddyCompensationX.aflTimeConstant[3] = 0.0309809 sGRADSPEC.sEddyCompensationX.aflTimeConstant[4] = 0.00067694 sGRADSPEC.sEddyCompensationY.aflAmplitude[0] = 0.0156411 sGRADSPEC.sEddyCompensationY.aflAmplitude[1] = 0.0440623 sGRADSPEC.sEddyCompensationY.aflAmplitude[2] = -0.00782663 sGRADSPEC.sEddyCompensationY.aflAmplitude[3] = 0.00186828 sGRADSPEC.sEddyCompensationY.aflAmplitude[4] = 0.00154504 sGRADSPEC.sEddyCompensationY.aflTimeConstant[0] = 1.47145 sGRADSPEC.sEddyCompensationY.aflTimeConstant[1] = 0.750538 sGRADSPEC.sEddyCompensationY.aflTimeConstant[2] = 0.339397 sGRADSPEC.sEddyCompensationY.aflTimeConstant[3] = 0.0312962 sGRADSPEC.sEddyCompensationY.aflTimeConstant[4] = 0.000895133 sGRADSPEC.sEddyCompensationZ.aflAmplitude[0] = 0.00618504 sGRADSPEC.sEddyCompensationZ.aflAmplitude[1] = 0.00313121 sGRADSPEC.sEddyCompensationZ.aflAmplitude[2] = 0.000289346 sGRADSPEC.sEddyCompensationZ.aflAmplitude[3] = -0.00019677 sGRADSPEC.sEddyCompensationZ.aflAmplitude[4] = 7.66445e-005 sGRADSPEC.sEddyCompensationZ.aflTimeConstant[0] = 3.37462 sGRADSPEC.sEddyCompensationZ.aflTimeConstant[1] = 0.999351 sGRADSPEC.sEddyCompensationZ.aflTimeConstant[2] = 0.0174646 sGRADSPEC.sEddyCompensationZ.aflTimeConstant[3] = 0.0110094 sGRADSPEC.sEddyCompensationZ.aflTimeConstant[4] = 0.00199922 sGRADSPEC.bEddyCompensationValid = 1 sGRADSPEC.sB0CompensationX.aflAmplitude[0] = 0.307474 sGRADSPEC.sB0CompensationX.aflAmplitude[1] = 0.029337 sGRADSPEC.sB0CompensationX.aflAmplitude[2] = -0.187118 sGRADSPEC.sB0CompensationX.aflTimeConstant[0] = 0.98583 sGRADSPEC.sB0CompensationX.aflTimeConstant[1] = 0.0308443 sGRADSPEC.sB0CompensationX.aflTimeConstant[2] = 0.000466792 sGRADSPEC.sB0CompensationY.aflAmplitude[0] = 0.365257 sGRADSPEC.sB0CompensationY.aflAmplitude[1] = -0.318647 sGRADSPEC.sB0CompensationY.aflAmplitude[2] = -0.0118978 sGRADSPEC.sB0CompensationY.aflTimeConstant[0] = 0.61535 sGRADSPEC.sB0CompensationY.aflTimeConstant[1] = 0.488831 sGRADSPEC.sB0CompensationY.aflTimeConstant[2] = 0.00199991 sGRADSPEC.sB0CompensationZ.aflAmplitude[0] = -0.44647 sGRADSPEC.sB0CompensationZ.aflAmplitude[1] = -0.0455154 sGRADSPEC.sB0CompensationZ.aflAmplitude[2] = -0.0304901 sGRADSPEC.sB0CompensationZ.aflTimeConstant[0] = 0.959231 sGRADSPEC.sB0CompensationZ.aflTimeConstant[1] = 0.0720189 sGRADSPEC.sB0CompensationZ.aflTimeConstant[2] = 0.00190141 sGRADSPEC.bB0CompensationValid = 1 sGRADSPEC.sCrossTermCompensationXY.aflAmplitude[0] = 0.00105046 sGRADSPEC.sCrossTermCompensationXY.aflTimeConstant[0] = 0.842014 sGRADSPEC.sCrossTermCompensationXZ.aflAmplitude[0] = -0.00150189 sGRADSPEC.sCrossTermCompensationXZ.aflTimeConstant[0] = 0.736169 sGRADSPEC.sCrossTermCompensationYX.aflAmplitude[0] = -5.5278e-005 sGRADSPEC.sCrossTermCompensationYX.aflTimeConstant[0] = 0.228697 sGRADSPEC.sCrossTermCompensationYZ.aflAmplitude[0] = 0.000307999 sGRADSPEC.sCrossTermCompensationYZ.aflTimeConstant[0] = 1.19431 sGRADSPEC.sCrossTermCompensationZX.aflAmplitude[0] = -0.000286868 sGRADSPEC.sCrossTermCompensationZX.aflTimeConstant[0] = 0.665979 sGRADSPEC.sCrossTermCompensationZY.aflAmplitude[0] = 0.000355175 sGRADSPEC.sCrossTermCompensationZY.aflTimeConstant[0] = 0.844189 sGRADSPEC.bCrossTermCompensationValid = 1 sGRADSPEC.lOffsetX = 25 sGRADSPEC.lOffsetY = 84 sGRADSPEC.lOffsetZ = 47 sGRADSPEC.bOffsetValid = 1 sGRADSPEC.lDelayX = 12 sGRADSPEC.lDelayY = 11 sGRADSPEC.lDelayZ = 9 sGRADSPEC.bDelayValid = 1 sGRADSPEC.flSensitivityX = 0.000264087 sGRADSPEC.flSensitivityY = 0.000272009 sGRADSPEC.flSensitivityZ = 0.000272677 sGRADSPEC.bSensitivityValid = 1 sGRADSPEC.alShimCurrent[0] = 183 sGRADSPEC.alShimCurrent[1] = -25 sGRADSPEC.alShimCurrent[2] = -85 sGRADSPEC.alShimCurrent[3] = 378 sGRADSPEC.alShimCurrent[4] = 82 sGRADSPEC.bShimCurrentValid = 1 sGRADSPEC.ucMode = 0x2 sTXSPEC.asNucleusInfo[0].tNucleus = "1H" sTXSPEC.asNucleusInfo[0].lFrequency = 63684693 sTXSPEC.asNucleusInfo[0].bFrequencyValid = 1 sTXSPEC.asNucleusInfo[0].flReferenceAmplitude = 359.734 sTXSPEC.asNucleusInfo[0].bReferenceAmplitudeValid = 1 sTXSPEC.asNucleusInfo[0].flAmplitudeCorrection = 1 sTXSPEC.asNucleusInfo[0].bAmplitudeCorrectionValid = 1 sTXSPEC.asNucleusInfo[1].bFrequencyValid = 1 sTXSPEC.asNucleusInfo[1].bReferenceAmplitudeValid = 1 sTXSPEC.asNucleusInfo[1].bAmplitudeCorrectionValid = 1 sTXSPEC.aRFPULSE[0].tName = "03GreFCE" sTXSPEC.aRFPULSE[0].bAmplitudeValid = 0x1 sTXSPEC.aRFPULSE[0].flAmplitude = 147.095 sTXSPEC.aRFPULSE[1].tName = "02GreFCE" sTXSPEC.aRFPULSE[1].bAmplitudeValid = 0x1 sTXSPEC.aRFPULSE[1].flAmplitude = 147.095 sTXSPEC.aRFPULSE[2].tName = "01GreFCE" sTXSPEC.aRFPULSE[2].bAmplitudeValid = 0x1 sTXSPEC.aRFPULSE[2].flAmplitude = 147.095 sTXSPEC.lNoOfTraPulses = 3 sTXSPEC.lBTB1ParallelCapacity = 2 sTXSPEC.lBTB1SerialCapacity = 24 sTXSPEC.lBTB2ParallelCapacity = 2 sTXSPEC.lBTB2SerialCapacity = 26 sTXSPEC.bBTBValid = 1 sTXSPEC.flKDynMagnitudeMin = 0.5 sTXSPEC.flKDynMagnitudeMax = 1.5 sTXSPEC.flKDynMagnitudeClipLow = 0.96 sTXSPEC.flKDynMagnitudeClipHigh = 1.04 sTXSPEC.flKDynPhaseMax = 0.698132 sTXSPEC.flKDynPhaseClip = 0.174533 sTXSPEC.bKDynValid = 1 sTXSPEC.ucRFPulseType = 0x1 sTXSPEC.ucExcitMode = 0x1 sTXSPEC.ucSimultaneousExcitation = 0x1 sRXSPEC.lGain = 1 sRXSPEC.bGainValid = 1 sRXSPEC.aFFT_SCALE[0].lRxChannel = 1 sRXSPEC.aFFT_SCALE[0].flFactor = 1.06857 sRXSPEC.aFFT_SCALE[0].bValid = 1 sRXSPEC.aFFT_SCALE[1].lRxChannel = 2 sRXSPEC.aFFT_SCALE[1].flFactor = 1.07454 sRXSPEC.aFFT_SCALE[1].bValid = 1 sRXSPEC.aFFT_SCALE[2].lRxChannel = 3 sRXSPEC.aFFT_SCALE[2].flFactor = 1.06622 sRXSPEC.aFFT_SCALE[2].bValid = 1 sRXSPEC.aFFT_SCALE[3].lRxChannel = 4 sRXSPEC.aFFT_SCALE[3].flFactor = 1.06524 sRXSPEC.aFFT_SCALE[3].bValid = 1 sRXSPEC.aFFT_SCALE[4].lRxChannel = 5 sRXSPEC.aFFT_SCALE[4].flFactor = 0.982692 sRXSPEC.aFFT_SCALE[4].bValid = 1 sRXSPEC.aFFT_SCALE[5].lRxChannel = 6 sRXSPEC.aFFT_SCALE[5].flFactor = 0.988603 sRXSPEC.aFFT_SCALE[5].bValid = 1 sRXSPEC.aFFT_SCALE[6].lRxChannel = 7 sRXSPEC.aFFT_SCALE[6].flFactor = 0.981538 sRXSPEC.aFFT_SCALE[6].bValid = 1 sRXSPEC.aFFT_SCALE[7].lRxChannel = 8 sRXSPEC.aFFT_SCALE[7].flFactor = 1.00856 sRXSPEC.aFFT_SCALE[7].bValid = 1 sRXSPEC.bVariCapVoltagesValid = 1 sRXSPEC.alDwellTime[0] = 8500 sAdjFreSpec.ulMode = 0x1 sAdjFreSpec.ucAdjWithBC = 0x1 sAdjTraSpec.ucAdjWithBC = 0x1 sAdjShimSpec.ulMode = 0x1 sAdjShimSpec.ucAdjWithBC = 0x1 sAdjWatSupSpec.ulMode = 0x1 sAdjWatSupSpec.ucAdjWithBC = 0x1 alTR[0] = 37000 lContrasts = 1 alTE[0] = 4000 acFlowComp[0] = 1 lCombinedEchoes = 1 sSliceArray.asSlice[0].sPosition.dSag = 35.31199581 sSliceArray.asSlice[0].sPosition.dCor = -8.387765754 sSliceArray.asSlice[0].sPosition.dTra = -23.13178296 sSliceArray.asSlice[0].sNormal.dSag = 0.771051253 sSliceArray.asSlice[0].sNormal.dCor = 0.5863890019 sSliceArray.asSlice[0].sNormal.dTra = -0.2482496801 sSliceArray.asSlice[0].dThickness = 6 sSliceArray.asSlice[0].dPhaseFOV = 187.5 sSliceArray.asSlice[0].dReadoutFOV = 250 sSliceArray.lSize = 1 sSliceArray.lSag = 1 sSliceArray.lConc = 1 sSliceArray.ucMode = 0x1 sSliceArray.sTSat.dThickness = 40 sSliceArray.sTSat.dGap = 10 sGroupArray.asGroup[0].nSize = 1 sGroupArray.asGroup[0].dDistFact = 0.2 sGroupArray.anMember[1] = -1 sGroupArray.lSize = 1 sGroupArray.sPSat.dThickness = 50 sGroupArray.sPSat.dGap = 10 sAutoAlign.dAAMatrix[0] = 1 sAutoAlign.dAAMatrix[5] = 1 sAutoAlign.dAAMatrix[10] = 1 sAutoAlign.dAAMatrix[15] = 1 sNavigatorPara.ucRespComp = 0x4 sPrepPulses.ucFatSat = 0x4 sPrepPulses.ucWaterSat = 0x4 sPrepPulses.ucInversion = 0x4 sPrepPulses.ucSatRecovery = 0x1 sPrepPulses.ucFatSatMode = 0x2 sKSpace.lBaseResolution = 256 sKSpace.lPhaseEncodingLines = 192 sKSpace.dPhaseResolution = 1 sKSpace.lPartitions = 32 sKSpace.lImagesPerSlab = 32 sKSpace.dSliceResolution = 1 sKSpace.ucPhasePartialFourier = 0x10 sKSpace.ucSlicePartialFourier = 0x10 sKSpace.ucAveragingMode = 0x2 sKSpace.ucMultiSliceMode = 0x1 sKSpace.ucDimension = 0x2 sKSpace.ucAsymmetricEchoAllowed = 0x1 sKSpace.unReordering = 0x1 sFastImaging.lEPIFactor = 1 sFastImaging.lTurboFactor = 1 sFastImaging.lSegments = 3 sFastImaging.ulEnableRFSpoiling = 0x1 sPhysioImaging.lSignal1 = 2 sPhysioImaging.lMethod1 = 2 sPhysioImaging.lSignal2 = 1 sPhysioImaging.lMethod2 = 1 sPhysioImaging.lPhases = 21 sPhysioImaging.lRetroGatedImages = 16 sPhysioImaging.sPhysioECG.lScanWindow = 805 sPhysioImaging.sPhysioECG.lTriggerPulses = 1 sPhysioImaging.sPhysioECG.lTriggerWindow = 5 sPhysioImaging.sPhysioECG.lArrhythmiaDetection = 1 sPhysioImaging.sPhysioECG.lCardiacGateOnThreshold = 100000 sPhysioImaging.sPhysioECG.lCardiacGateOffThreshold = 700000 sPhysioImaging.sPhysioPulse.lTriggerPulses = 1 sPhysioImaging.sPhysioPulse.lTriggerWindow = 5 sPhysioImaging.sPhysioPulse.lCardiacGateOnThreshold = 100000 sPhysioImaging.sPhysioPulse.lCardiacGateOffThreshold = 700000 sPhysioImaging.sPhysioExt.lTriggerPulses = 1 sPhysioImaging.sPhysioExt.lTriggerWindow = 5 sPhysioImaging.sPhysioExt.lCardiacGateOnThreshold = 100000 sPhysioImaging.sPhysioExt.lCardiacGateOffThreshold = 700000 sPhysioImaging.sPhysioResp.lRespGateThreshold = 20 sPhysioImaging.sPhysioResp.lRespGatePhase = 2 sPhysioImaging.sPhysioResp.dGatingRatio = 0.3 sSpecPara.lPhaseCyclingType = 1 sSpecPara.lPhaseEncodingType = 1 sSpecPara.lRFExcitationBandwidth = 1 sSpecPara.ucRemoveOversampling = 0x1 sSpecPara.lDecouplingType = 1 sSpecPara.lNOEType = 1 sSpecPara.lExcitationType = 1 sSpecPara.lSpectralSuppression = 1 sDiffusion.ulMode = 0x1 sAngio.sFlowArray.asElm[0].nVelocity = 100 sAngio.sFlowArray.asElm[0].nDir = 0x4 sAngio.sFlowArray.lSize = 1 sAngio.ucPCFlowMode = 0x2 sAngio.ucTOFInflow = 0x4 sAngio.ucRephasedImage = 0x1 sAngio.ucPhaseImage = 0x1 sEllipticalFilter.ucMode = 0x1 sPat.lAccelFactPE = 1 sPat.lAccelFact3D = 1 sPat.ucPATMode = 0x1 sPat.ucRefScanMode = 0x1 ucAutoMovie = 0x1 ucDisableChangeStoreImages = 0x1 ucReconstructionMode = 0x1 ucPHAPSMode = 0x1 ucDixon = 0x1 lAverages = 2 adFlipAngleDegree[0] = 30 lScanTimeSec = 103 lTotalScanTimeSec = 112 dRefSNR = 165404.1473 dRefSNR_VOI = 165404.1473 tdefaultEVAProt = "%SiemensEvaDefProt%\Inline\Inline.evp" tcurrentEVAProt = "%CURRENTEVAPROT%\EVA2A5.tmp" sCOIL_SELECT_MEAS.asList[0].sCoilElementID.tCoilID = "6_Ch_Body_P" sCOIL_SELECT_MEAS.asList[0].sCoilElementID.lCoilCopy = 1 sCOIL_SELECT_MEAS.asList[0].sCoilElementID.tElement = "PP6" sCOIL_SELECT_MEAS.asList[0].lElementSelected = 1 sCOIL_SELECT_MEAS.asList[0].lRxChannelConnected = 1 sCOIL_SELECT_MEAS.asList[1].sCoilElementID.tCoilID = "6_Ch_Body_P" sCOIL_SELECT_MEAS.asList[1].sCoilElementID.lCoilCopy = 1 sCOIL_SELECT_MEAS.asList[1].sCoilElementID.tElement = "PP5" sCOIL_SELECT_MEAS.asList[1].lElementSelected = 1 sCOIL_SELECT_MEAS.asList[1].lRxChannelConnected = 1 sCOIL_SELECT_MEAS.asList[2].sCoilElementID.tCoilID = "6_Ch_Body_P" sCOIL_SELECT_MEAS.asList[2].sCoilElementID.lCoilCopy = 1 sCOIL_SELECT_MEAS.asList[2].sCoilElementID.tElement = "PP3" sCOIL_SELECT_MEAS.asList[2].lElementSelected = 1 sCOIL_SELECT_MEAS.asList[2].lRxChannelConnected = 2 sCOIL_SELECT_MEAS.asList[3].sCoilElementID.tCoilID = "6_Ch_Body_P" sCOIL_SELECT_MEAS.asList[3].sCoilElementID.lCoilCopy = 1 sCOIL_SELECT_MEAS.asList[3].sCoilElementID.tElement = "PP4" sCOIL_SELECT_MEAS.asList[3].lElementSelected = 1 sCOIL_SELECT_MEAS.asList[3].lRxChannelConnected = 3 sCOIL_SELECT_MEAS.asList[4].sCoilElementID.tCoilID = "6_Ch_Body_P" sCOIL_SELECT_MEAS.asList[4].sCoilElementID.lCoilCopy = 1 sCOIL_SELECT_MEAS.asList[4].sCoilElementID.tElement = "PP2" sCOIL_SELECT_MEAS.asList[4].lElementSelected = 1 sCOIL_SELECT_MEAS.asList[4].lRxChannelConnected = 4 sCOIL_SELECT_MEAS.asList[5].sCoilElementID.tCoilID = "6_Ch_Body_P" sCOIL_SELECT_MEAS.asList[5].sCoilElementID.lCoilCopy = 1 sCOIL_SELECT_MEAS.asList[5].sCoilElementID.tElement = "PP1" sCOIL_SELECT_MEAS.asList[5].lElementSelected = 1 sCOIL_SELECT_MEAS.asList[5].lRxChannelConnected = 4 sCOIL_SELECT_MEAS.asList[6].sCoilElementID.tCoilID = "6_Ch_Body_A" sCOIL_SELECT_MEAS.asList[6].sCoilElementID.lCoilCopy = 1 sCOIL_SELECT_MEAS.asList[6].sCoilElementID.tElement = "PA6" sCOIL_SELECT_MEAS.asList[6].lElementSelected = 1 sCOIL_SELECT_MEAS.asList[6].lRxChannelConnected = 5 sCOIL_SELECT_MEAS.asList[7].sCoilElementID.tCoilID = "6_Ch_Body_A" sCOIL_SELECT_MEAS.asList[7].sCoilElementID.lCoilCopy = 1 sCOIL_SELECT_MEAS.asList[7].sCoilElementID.tElement = "PA5" sCOIL_SELECT_MEAS.asList[7].lElementSelected = 1 sCOIL_SELECT_MEAS.asList[7].lRxChannelConnected = 5 sCOIL_SELECT_MEAS.asList[8].sCoilElementID.tCoilID = "6_Ch_Body_A" sCOIL_SELECT_MEAS.asList[8].sCoilElementID.lCoilCopy = 1 sCOIL_SELECT_MEAS.asList[8].sCoilElementID.tElement = "PA3" sCOIL_SELECT_MEAS.asList[8].lElementSelected = 1 sCOIL_SELECT_MEAS.asList[8].lRxChannelConnected = 6 sCOIL_SELECT_MEAS.asList[9].sCoilElementID.tCoilID = "6_Ch_Body_A" sCOIL_SELECT_MEAS.asList[9].sCoilElementID.lCoilCopy = 1 sCOIL_SELECT_MEAS.asList[9].sCoilElementID.tElement = "PA4" sCOIL_SELECT_MEAS.asList[9].lElementSelected = 1 sCOIL_SELECT_MEAS.asList[9].lRxChannelConnected = 7 sCOIL_SELECT_MEAS.asList[10].sCoilElementID.tCoilID = "6_Ch_Body_A" sCOIL_SELECT_MEAS.asList[10].sCoilElementID.lCoilCopy = 1 sCOIL_SELECT_MEAS.asList[10].sCoilElementID.tElement = "PA2" sCOIL_SELECT_MEAS.asList[10].lElementSelected = 1 sCOIL_SELECT_MEAS.asList[10].lRxChannelConnected = 8 sCOIL_SELECT_MEAS.asList[11].sCoilElementID.tCoilID = "6_Ch_Body_A" sCOIL_SELECT_MEAS.asList[11].sCoilElementID.lCoilCopy = 1 sCOIL_SELECT_MEAS.asList[11].sCoilElementID.tElement = "PA1" sCOIL_SELECT_MEAS.asList[11].lElementSelected = 1 sCOIL_SELECT_MEAS.asList[11].lRxChannelConnected = 8 sCOIL_SELECT_MEAS.sCOILPLUGS.aulPlugId[0] = 0xff sCOIL_SELECT_MEAS.sCOILPLUGS.aulPlugId[1] = 0x76 sCOIL_SELECT_MEAS.sCOILPLUGS.aulPlugId[2] = 0x78 sCOIL_SELECT_MEAS.sCOILPLUGS.aulPlugId[3] = 0x87 sCOIL_SELECT_MEAS.sCOILPLUGS.aulPlugId[4] = 0x67 sCOIL_SELECT_MEAS.sCOILPLUGS.auiNmbrOfNibbles[0] = 0x2 sCOIL_SELECT_MEAS.sCOILPLUGS.auiNmbrOfNibbles[1] = 0x2 sCOIL_SELECT_MEAS.sCOILPLUGS.auiNmbrOfNibbles[2] = 0x2 sCOIL_SELECT_MEAS.sCOILPLUGS.auiNmbrOfNibbles[3] = 0x2 sCOIL_SELECT_MEAS.sCOILPLUGS.auiNmbrOfNibbles[4] = 0x2 sEFISPEC.bEFIDataValid = 1 ### ASCCONV END ### ' */ /* * Table of equivalence: * ulVersion = 0xbee332 <=> 27 - 'MrProtocolVersion' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '12510002' */ #include "gdcmReader.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmCSAHeader.h" #include "gdcmAttribute.h" #include "gdcmGlobal.h" #include "gdcmDicts.h" #include #include int main(int argc, char *argv []) { if( argc < 2 ) return 1; const char *filename = argv[1]; gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } gdcm::CSAHeader csa; const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); //const gdcm::PrivateTag &t1 = csa.GetCSAImageHeaderInfoTag(); const gdcm::PrivateTag &t2 = csa.GetCSASeriesHeaderInfoTag(); if( ds.FindDataElement( t2 ) ) { csa.LoadFromDataElement( ds.GetDataElement( t2 ) ); //csa.Print( std::cout ); } if( !csa.FindCSAElementByName( "MrProtocol" ) ) { return 1; } const gdcm::CSAElement &csael = csa.GetCSAElementByName( "MrProtocol" ); //std::cout << csael << std::endl; const gdcm::ByteValue *bv = csael.GetByteValue(); if( !bv ) { return 1; } std::string str(bv->GetPointer(), bv->GetLength()); std::istringstream is(str); std::string s; typedef std::map< std::string, std::string > MyMapType; MyMapType mymap; while( std::getline(is, s ) ) { std::string::size_type pos = s.find( '=' ); if( pos != std::string::npos ) { std::string sub1 = s.substr(0, pos); sub1.erase( sub1.find_last_not_of(' ') + 1); std::string sub2 = s.substr(pos+1); // skip the '=' char sub2.erase( 0, sub2.find_first_not_of(' ')); //std::cout << sub1 << std::endl; mymap.insert( MyMapType::value_type(sub1, sub2) ); } else { // ### ASCCONV BEGIN ### // ### ASCCONV END ### } } const char fourierstr[] = "sKSpace.ucSlicePartialFourier"; const gdcm::CSAHeaderDict &csadict = gdcm::Global::GetInstance().GetDicts().GetCSAHeaderDict(); const gdcm::CSAHeaderDictEntry &fourier = csadict.GetCSAHeaderDictEntry( fourierstr ); std::cout << fourier << std::endl; MyMapType::const_iterator it = mymap.find ( fourierstr ); if( it == mymap.end() ) return 1; //std::cout << it->second << std::endl; const std::string &partial_fourier = it->second; if( partial_fourier == "0x1" ) { std::cout << "partial fourier is 4/8" << std::endl; } else if( partial_fourier == "0x2" ) { std::cout << "partial fourier is 5/8" << std::endl; } else if( partial_fourier == "0x4" ) { std::cout << "partial fourier is 6/8" << std::endl; } else if( partial_fourier == "0x8" ) { std::cout << "partial fourier is 7/8" << std::endl; } else if( partial_fourier == "0x10" ) { std::cout << "partial fourier is 8/8" << std::endl; } else { std::cerr << "Impossible: " << partial_fourier << std::endl; return 1; } /* This is the Flip Angle: adFlipAngleDegree[0] = 30 One can find it also in the protocol: ... { ""T1mapFunctor@IceImagePostProcFunctors"" { } { 16 14.7378520000000000 } ... */ // Below is an attemp to play with the CSAHeader dict: #if 0 const char gspec[] = "sGRADSPEC.flSensitivityX"; it = mymap.find( gspec ); if( it == mymap.end() ) return 1; const std::string &dummy = it->second; std::cout << dummy << std::endl; const gdcm::CSAHeaderDictEntry &csaentry = csadict.GetCSAHeaderDictEntry( gspec ); std::cout << csaentry << std::endl; #endif /* sSliceArray.ucMode -- should be in (1, 2, 4) enum SeriesMode { ASCENDING = 0x01, DESCENDING = 0x02, INTERLEAVED = 0x04 }; */ const char sliceorderstr[] = "sSliceArray.ucMode"; const gdcm::CSAHeaderDictEntry &sliceorder = csadict.GetCSAHeaderDictEntry( sliceorderstr ); std::cout << sliceorder << std::endl; it = mymap.find ( sliceorderstr ); if( it == mymap.end() ) return 1; const std::string &slice_order = it->second; if( slice_order == "0x1" ) { std::cout << "slice_order: ASCENDING" << std::endl; } else if( slice_order == "0x2" ) { std::cout << "slice_order: DESCENDING" << std::endl; } else if( slice_order == "0x4" ) { std::cout << "slice_order: INTERLEAVED" << std::endl; } else { std::cerr << "Impossible: " << slice_order << std::endl; return 1; } gdcm::MrProtocol mrprot; if( csa.GetMrProtocol(ds, mrprot) ) { std::cout << mrprot << std::endl; } return 0; } GDCM-3.0.10/Examples/Cxx/PatchFile.cxx000066400000000000000000000061721412732066400172230ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * The image was a broken file where the Pixel Data element was 8 times too big * Apparently multiplying the BitsAllocated to 4 and multiplying the number of * frames by 2 would solve the problem * * This C++ code can be used to patch the header. */ #include "gdcmReader.h" #include "gdcmImageReader.h" #include "gdcmWriter.h" #include "gdcmDataSet.h" #include "gdcmAttribute.h" int main(int argc, char *argv[]) { if( argc < 3 ) { return 1; } const char *f = argv[1]; const char *out = argv[2]; gdcm::Reader r; r.SetFileName( f ); if( !r.Read() ) { return 1; } gdcm::File &file = r.GetFile(); gdcm::DataSet& ds = file.GetDataSet(); // (0028,0100) US 16 # 2, 1 BitsAllocated // (0028,0101) US 16 # 2, 1 BitsStored // (0028,0102) US 15 # 2, 1 HighBit // { gdcm::Attribute<0x28,0x100> at; at.SetFromDataElement( ds.GetDataElement( at.GetTag() ) ); if( at.GetValue() != 8 ) { return 1; } at.SetValue( 32 ); ds.Replace( at.GetAsDataElement() ); } { gdcm::Attribute<0x28,0x101> at; at.SetFromDataElement( ds.GetDataElement( at.GetTag() ) ); if( at.GetValue() != 8 ) { return 1; } at.SetValue( 32 ); ds.Replace( at.GetAsDataElement() ); } { gdcm::Attribute<0x28,0x102> at; at.SetFromDataElement( ds.GetDataElement( at.GetTag() ) ); if( at.GetValue() != 7 ) { return 1; } at.SetValue( 31 ); ds.Replace( at.GetAsDataElement() ); } // (0028,0008) IS [56] # 2, 1 NumberOfFrames { gdcm::Attribute<0x28,0x8> at; at.SetFromDataElement( ds.GetDataElement( at.GetTag() ) ); at.SetValue( at.GetValue() * 2 ); ds.Replace( at.GetAsDataElement() ); } gdcm::Writer w; w.SetFile( file ); w.SetCheckFileMetaInformation( false ); w.SetFileName( out ); if( !w.Write() ) { return 1; } // Now let's see if we can read it as an image: gdcm::ImageReader ir; ir.SetFileName( out ); if(!ir.Read()) { return 1; } gdcm::Image &image = ir.GetImage(); unsigned long len = image.GetBufferLength(); const gdcm::ByteValue *bv = ir.GetFile().GetDataSet().GetDataElement( gdcm::Tag(0x7fe0,0x0010) ).GetByteValue(); if( !bv || len != bv->GetLength() ) { return 1; } std::cout << bv->GetLength() << " " << len << std::endl; std::cout << "Sucess to rewrite image !" << std::endl; image.Print( std::cout ); return 0; } GDCM-3.0.10/Examples/Cxx/PrintLUT.cxx000066400000000000000000000023221412732066400170360ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmImage.h" #include "gdcmPhotometricInterpretation.h" #include int main(int argc, char *argv[]) { if( argc < 2 ) { std::cerr << argv[0] << " input.dcm" << std::endl; return 1; } const char *filename = argv[1]; // Instanciate the image reader: gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } const gdcm::Image &image = reader.GetImage(); const gdcm::LookupTable & lut = image.GetLUT(); lut.Print( std::cout ); return 0; } GDCM-3.0.10/Examples/Cxx/PublicDict.cxx000066400000000000000000000043421412732066400174030ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Dummy example to show GDCM Dict(s) API (Part 6) + Collected Private Attributes: */ #include "gdcmGlobal.h" #include "gdcmDicts.h" #include "gdcmDict.h" #include "gdcmCSAHeader.h" #include "gdcmPrivateTag.h" int main(int , char *[]) { const gdcm::Global& g = gdcm::Global::GetInstance(); // sum of all knowledge ! const gdcm::Dicts &dicts = g.GetDicts(); const gdcm::Dict &pub = dicts.GetPublicDict(); // Part 6 //std::cout << pub << std::endl; // 3 differents way to access the same information // 1. From the public dict only: gdcm::Tag patient_name(0x10,0x10); const gdcm::DictEntry &entry1 = pub.GetDictEntry(patient_name); std::cout << entry1 << std::endl; // 2. From all dicts: const gdcm::DictEntry &entry2 = dicts.GetDictEntry(patient_name); std::cout << entry2 << std::endl; // 3. This solution is the most flexible solution as you can request using the same // API either a public tag or a private tag const char *strowner = nullptr; const gdcm::DictEntry &entry3 = dicts.GetDictEntry(patient_name,strowner); std::cout << entry3 << std::endl; // Private attributes: // try with a private tag now: const gdcm::PrivateTag &private_tag = gdcm::CSAHeader::GetCSAImageHeaderInfoTag(); //std::cout << private_tag << std::endl; const gdcm::DictEntry &entry4 = dicts.GetDictEntry(private_tag,private_tag.GetOwner()); std::cout << entry4 << std::endl; // Let's pretend that private lookup is on 0x10xx elements: gdcm::PrivateTag dummy = private_tag; dummy.SetElement( (uint16_t)(0x1000 + dummy.GetElement()) ); const gdcm::DictEntry &entry5 = dicts.GetDictEntry(dummy,dummy.GetOwner()); std::cout << entry5 << std::endl; return 0; } GDCM-3.0.10/Examples/Cxx/QIDO-RS.cxx000066400000000000000000000026771412732066400164500ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmJSON.h" /* * Simple QIDO-RS round-trip to test implementation of gdcm::JSON * See Sup166 for details */ int main(int argc, char *argv[]) { if( argc < 2 ) return 1; using namespace gdcm; const char *filename = argv[1]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) return 1; gdcm::JSON json; json.PrettyPrintOn(); std::stringstream ss; const gdcm::File & f = reader.GetFile(); json.Code( f.GetDataSet(), ss); std::cout << ss.str() << std::endl; gdcm::Writer w; gdcm::File & ff = w.GetFile(); ff.GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); if( !json.Decode(ss, ff.GetDataSet() ) ) { std::cerr << "Could not decode" << std::endl; return 1; } w.SetFileName( "/tmp/debug.dcm" ); if( !w.Write() ) return 1; return 0; } GDCM-3.0.10/Examples/Cxx/ReadAndDumpDICOMDIR.cxx000066400000000000000000000200271412732066400206160ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This example shows how to read and dump a DICOMDIR File * * Thanks: * Tom Marynowski (lordglub gmail) for contributing this example */ #include "gdcmReader.h" #include "gdcmMediaStorage.h" typedef std::set DataElementSet; typedef DataElementSet::const_iterator ConstIterator; int main(int argc, char *argv []) { if( argc < 2 ) return 1; const char *filename = argv[1]; gdcm::Reader reader; reader.SetFileName( filename); if( !reader.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } std::stringstream strm; gdcm::File &file = reader.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); gdcm::FileMetaInformation &fmi = file.GetHeader(); gdcm::MediaStorage ms; ms.SetFromFile(file); if( ms != gdcm::MediaStorage::MediaStorageDirectoryStorage ) { std::cout << "This file is not a DICOMDIR" << std::endl; return 1; } if (fmi.FindDataElement( gdcm::Tag (0x0002, 0x0002))) { strm.str(""); fmi.GetDataElement( gdcm::Tag (0x0002, 0x0002) ).GetValue().Print(strm); } else { std::cerr << " Media Storage Sop Class UID not present" << std::endl; } //TODO il faut trimer strm.str() avant la comparaison au cas ou... if ("1.2.840.10008.1.3.10"!=strm.str()) { std::cout << "This file is not a DICOMDIR" << std::endl; return 1; } ConstIterator it = ds.GetDES().begin(); for( ; it != ds.GetDES().end(); ++it) { if (it->GetTag()==gdcm::Tag (0x0004, 0x1220)) { const gdcm::DataElement &de = (*it); // ne pas utiliser GetSequenceOfItems pour extraire les items gdcm::SmartPointer sqi =de.GetValueAsSQ(); unsigned int itemused = 1; while (itemused<=sqi->GetNumberOfItems()) { strm.str(""); if (sqi->GetItem(itemused).FindDataElement(gdcm::Tag (0x0004, 0x1430))) sqi->GetItem(itemused).GetDataElement(gdcm::Tag (0x0004, 0x1430)).GetValue().Print(strm); //TODO il faut trimer strm.str() avant la comparaison while((strm.str()=="PATIENT")||((strm.str()=="PATIENT "))) { std::cout << strm.str() << std::endl; strm.str(""); if (sqi->GetItem(itemused).FindDataElement(gdcm::Tag (0x0010, 0x0010))) sqi->GetItem(itemused).GetDataElement(gdcm::Tag (0x0010, 0x0010)).GetValue().Print(strm); std::cout << "PATIENT NAME : " << strm.str() << std::endl; //PATIENT ID strm.str(""); if (sqi->GetItem(itemused).FindDataElement(gdcm::Tag (0x0010, 0x0020))) sqi->GetItem(itemused).GetDataElement(gdcm::Tag (0x0010, 0x0020)).GetValue().Print(strm); std::cout << "PATIENT ID : " << strm.str() << std::endl; /*ADD TAG TO READ HERE*/ std::cout << "=========================== " << std::endl; itemused++; strm.str(""); if (sqi->GetItem(itemused).FindDataElement(gdcm::Tag (0x0004, 0x1430))) sqi->GetItem(itemused).GetDataElement(gdcm::Tag (0x0004, 0x1430)).GetValue().Print(strm); //TODO il faut trimer strm.str() avant la comparaison while((strm.str()=="STUDY")||((strm.str()=="STUDY "))) { std::cout << " " << strm.str() << std::endl; //UID strm.str(""); if (sqi->GetItem(itemused).FindDataElement(gdcm::Tag (0x0020, 0x000d))) sqi->GetItem(itemused).GetDataElement(gdcm::Tag (0x0020, 0x000d)).GetValue().Print(strm); std::cout << " STUDY UID : " << strm.str() << std::endl; //STUDY DATE strm.str(""); if (sqi->GetItem(itemused).FindDataElement(gdcm::Tag (0x0008, 0x0020))) sqi->GetItem(itemused).GetDataElement(gdcm::Tag (0x0008, 0x0020)).GetValue().Print(strm); std::cout << " STUDY DATE : " << strm.str() << std::endl; //STUDY DESCRIPTION strm.str(""); if (sqi->GetItem(itemused).FindDataElement(gdcm::Tag (0x0008, 0x1030))) sqi->GetItem(itemused).GetDataElement(gdcm::Tag (0x0008, 0x1030)).GetValue().Print(strm); std::cout << " STUDY DESCRIPTION : " << strm.str() << std::endl; /*ADD TAG TO READ HERE*/ std::cout << " " << "=========================== " << std::endl; itemused++; strm.str(""); if (sqi->GetItem(itemused).FindDataElement(gdcm::Tag (0x0004, 0x1430))) sqi->GetItem(itemused).GetDataElement(gdcm::Tag (0x0004, 0x1430)).GetValue().Print(strm); //TODO il faut trimer strm.str() avant la comparaison while((strm.str()=="SERIES")||((strm.str()=="SERIES "))) { std::cout << " " << strm.str() << std::endl; strm.str(""); if (sqi->GetItem(itemused).FindDataElement(gdcm::Tag (0x0020, 0x000e))) sqi->GetItem(itemused).GetDataElement(gdcm::Tag (0x0020, 0x000e)).GetValue().Print(strm); std::cout << " SERIE UID" << strm.str() << std::endl; //SERIE MODALITY strm.str(""); if (sqi->GetItem(itemused).FindDataElement(gdcm::Tag (0x0008, 0x0060))) sqi->GetItem(itemused).GetDataElement(gdcm::Tag (0x0008, 0x0060)).GetValue().Print(strm); std::cout << " SERIE MODALITY" << strm.str() << std::endl; //SERIE DESCRIPTION strm.str(""); if (sqi->GetItem(itemused).FindDataElement(gdcm::Tag (0x0008, 0x103e))) sqi->GetItem(itemused).GetDataElement(gdcm::Tag (0x0008, 0x103e)).GetValue().Print(strm); std::cout << " SERIE DESCRIPTION" << strm.str() << std::endl; /*ADD TAG TO READ HERE*/ std::cout << " " << "=========================== " << std::endl; itemused++; strm.str(""); if (sqi->GetItem(itemused).FindDataElement(gdcm::Tag (0x0004, 0x1430))) sqi->GetItem(itemused).GetDataElement(gdcm::Tag (0x0004, 0x1430)).GetValue().Print(strm); //TODO il faut trimer strm.str() avant la comparaison while ((strm.str()=="IMAGE")||((strm.str()=="IMAGE "))) // if(tmp=="IMAGE") { std::cout << " " << strm.str() << std::endl; //UID strm.str(""); if (sqi->GetItem(itemused).FindDataElement(gdcm::Tag (0x0004, 0x1511))) sqi->GetItem(itemused).GetDataElement(gdcm::Tag (0x0004, 0x1511)).GetValue().Print(strm); std::cout << " IMAGE UID : " << strm.str() << std::endl; //PATH de l'image strm.str(""); if (sqi->GetItem(itemused).FindDataElement(gdcm::Tag (0x0004, 0x1500))) sqi->GetItem(itemused).GetDataElement(gdcm::Tag (0x0004, 0x1500)).GetValue().Print(strm); std::cout << " IMAGE PATH : " << strm.str() << std::endl; /*ADD TAG TO READ HERE*/ if(itemused < sqi->GetNumberOfItems()) {itemused++; }else{break;} strm.str(""); if (sqi->GetItem(itemused).FindDataElement(gdcm::Tag (0x0004, 0x1430))) sqi->GetItem(itemused).GetDataElement(gdcm::Tag (0x0004, 0x1430)).GetValue().Print(strm); } } } } itemused++; } } } return 0; } GDCM-3.0.10/Examples/Cxx/ReadAndDumpDICOMDIR2.cxx000066400000000000000000000351211412732066400207010ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2017 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. =========================================================================*/ /* * This example shows how to read and dump a DICOMDIR File * * Thanks: * Tom Marynowski (lordglub gmail) for contributing the original * ReadAndDumpDICOMDIR.cxx example * Mihail Isakov for contributing offset calculation code here: * https://sourceforge.net/p/gdcm/mailman/gdcm-developers/?viewmonth=201707&viewday=15 * Tod Baudais for combining the above and cleaning up this example */ #include #include #include #include #include "gdcmReader.h" #include "gdcmAttribute.h" #include "gdcmDirectory.h" //============================================================================== //============================================================================== #define TAG_MEDIA_STORAGE_SOP_CLASS_UID 0x0002,0x0002 #define TAG_DIRECTORY_RECORD_SEQUENCE 0x0004,0x1220 #define TAG_DIRECTORY_RECORD_TYPE 0x0004,0x1430 #define TAG_PATIENTS_NAME 0x0010,0x0010 #define TAG_PATIENT_ID 0x0010,0x0020 #define TAG_STUDY_DATE 0x0008,0x0020 #define TAG_STUDY_DESCRIPTION 0x0008,0x1030 #define TAG_MODALITY 0x0008,0x0060 #define TAG_SERIES_DESCRIPTION 0x0008,0x103E #define TAG_REFERENCED_FILE_ID 0x0004,0x1500 #define TAG_REFERENCED_LOWER_LEVEL_DIRECTORY_ENTITY_OFFSET 0x0004,0x1420 #define TAG_NEXT_DIRECTORY_RECORD_OFFSET 0x0004,0x1400 //============================================================================== // Some handy utility functions //============================================================================== std::string left_trim(const std::string &s) { std::string ss(s); ss.erase(ss.begin(), std::find_if(ss.begin(), ss.end(), std::not1(std::ptr_fun(std::isspace)))); return ss; } std::string right_trim(const std::string &s) { std::string ss(s); ss.erase(std::find_if(ss.rbegin(), ss.rend(), std::not1(std::ptr_fun(std::isspace))).base(), ss.end()); return ss; } std::string trim(const std::string &s) { return left_trim(right_trim(s)); } //============================================================================== // This code could be put in a header file somewhere //============================================================================== class DICOMDIRReader { public: DICOMDIRReader (void) {} DICOMDIRReader (const DICOMDIRReader &rhs) = delete; DICOMDIRReader (DICOMDIRReader &&rhs) = delete; DICOMDIRReader & operator = (const DICOMDIRReader &rhs) = delete; DICOMDIRReader & operator = (DICOMDIRReader &&rhs) = delete; virtual ~DICOMDIRReader (void) {} public: struct Common { int64_t child_offset; int64_t sibling_offset; }; struct Image: public Common { std::string path; }; struct Series: public Common { std::string modality; std::string description; std::vector> children; }; struct Study: public Common { std::string date; std::string description; std::vector> children; }; struct Patient: public Common { std::string name; std::string id; std::vector> children; }; struct Other: public Common { }; /// Load DICOMDIR const std::vector>& load (const std::string &path); /// Return the results of the load const std::vector>& patients (void) { return _patients; } private: template std::string get_string (const T &ds, const gdcm::Tag &tag) { std::stringstream strm; if (ds.FindDataElement(tag)) { auto &de = ds.GetDataElement(tag); if (!de.IsEmpty() && !de.IsUndefinedLength()) de.GetValue().Print(strm); } return trim(strm.str()); } template void reassemble_hierarchy (P &parent_offsets, C &child_offsets, O &other_offsets) { for (auto &parent : parent_offsets) { int64_t sibling_offset; auto c = child_offsets[parent.second->child_offset]; if (!c) { auto o = other_offsets[parent.second->child_offset]; if (!o) { continue; } else { sibling_offset = o->sibling_offset; } } else { parent.second->children.push_back(c); sibling_offset = c->sibling_offset; } // Get all siblings while (sibling_offset) { c = child_offsets[sibling_offset]; if (!c) { auto o = other_offsets[sibling_offset]; if (!o) { break; } else { sibling_offset = o->sibling_offset; } } else { parent.second->children.push_back(c); sibling_offset = c->sibling_offset; } } } } std::vector> _patients; }; //============================================================================== // This code could be put in an implementation file somewhere //============================================================================== const std::vector>& DICOMDIRReader::load (const std::string &path) { _patients.clear(); // // Read the dataset from the DICOMDIR file // gdcm::Reader reader; reader.SetFileName(path.c_str()); if(!reader.Read()) { throw std::runtime_error("Unable to read file"); } // Retrieve information from file auto &file = reader.GetFile(); auto &data_set = file.GetDataSet(); auto &file_meta_information = file.GetHeader(); // Retrieve and check the Media Storage class from file gdcm::MediaStorage media_storage; media_storage.SetFromFile(file); if(media_storage != gdcm::MediaStorage::MediaStorageDirectoryStorage) { throw std::runtime_error("This file is not a DICOMDIR"); } auto media_storage_sop_class_uid = get_string(file_meta_information, gdcm::Tag(TAG_MEDIA_STORAGE_SOP_CLASS_UID)); // Make sure we have a DICOMDIR file if (media_storage_sop_class_uid != "1.2.840.10008.1.3.10") { throw std::runtime_error("This file is not a DICOMDIR"); } // // Offset to first item courtesy of Mihail Isakov // gdcm::VL first_item_offset = 0; auto it = data_set.Begin(); for(; it != data_set.End() && it->GetTag() != gdcm::Tag(TAG_DIRECTORY_RECORD_SEQUENCE); ++it) { first_item_offset += it->GetLength(); } // Tag (4 bytes) first_item_offset += it->GetTag().GetLength(); // VR field first_item_offset += it->GetVR().GetLength(); // VL field // For Explicit VR: adventitiously VL field lenght = VR field lenght, // for SQ 4 bytes: // http://dicom.nema.org/medical/dicom/current/output/html/part05.html#table_7.1-1 first_item_offset += it->GetVR().GetLength(); // // Iterate all data elements // // For each item in data set for(auto data_element : data_set.GetDES()) { // Only look at Directory sequence if (data_element.GetTag() != gdcm::Tag(TAG_DIRECTORY_RECORD_SEQUENCE)) continue; auto item_sequence = data_element.GetValueAsSQ(); auto num_items = item_sequence->GetNumberOfItems(); // // Compute an offset table // // Start calculation of offset to each item courtesy of Mihail Isakov std::vector item_offsets(num_items+1); item_offsets[0] = file_meta_information.GetFullLength() + static_cast(first_item_offset); // // Extract out all of the items // std::unordered_map> patient_offsets; std::unordered_map> study_offsets; std::unordered_map> series_offsets; std::unordered_map> image_offsets; std::unordered_map> other_offsets; for (uint32_t item_index = 1; item_index <= num_items; ++item_index) { auto &item = item_sequence->GetItem(item_index); // Add offset for item to offset table item_offsets[item_index] = item_offsets[item_index-1] + item.GetLength(); // Child offset gdcm::Attribute child_offset; child_offset.SetFromDataElement(item.GetDataElement(gdcm::Tag (TAG_REFERENCED_LOWER_LEVEL_DIRECTORY_ENTITY_OFFSET))); // Sibling offset gdcm::Attribute sibling_offset; sibling_offset.SetFromDataElement(item.GetDataElement(gdcm::Tag (TAG_NEXT_DIRECTORY_RECORD_OFFSET))); // Record Type auto record_type = trim(get_string(item, gdcm::Tag (TAG_DIRECTORY_RECORD_TYPE))); // std::cout << "record_type " << record_type << " at " << item_offsets[item_index-1] << std::endl; // std::cout << " child_offset " << child_offset.GetValue() << std::endl; // std::cout << " sibling_offset " << sibling_offset.GetValue() << std::endl; // Extract patient information if (record_type == "PATIENT") { auto patient = std::make_shared(); patient->name = get_string(item, gdcm::Tag (TAG_PATIENTS_NAME)); patient->id = get_string(item, gdcm::Tag (TAG_PATIENT_ID)); patient->child_offset = child_offset.GetValue(); patient->sibling_offset = sibling_offset.GetValue(); patient_offsets[item_offsets[item_index-1]] = patient; // Extract study information } else if (record_type == "STUDY") { auto study = std::make_shared(); study->date = get_string(item, gdcm::Tag (TAG_STUDY_DATE)); study->description = get_string(item, gdcm::Tag (TAG_STUDY_DESCRIPTION)); study->child_offset = child_offset.GetValue(); study->sibling_offset = sibling_offset.GetValue(); study_offsets[item_offsets[item_index-1]] = study; // Extract series information } else if (record_type == "SERIES") { auto series = std::make_shared(); series->modality = get_string(item, gdcm::Tag (TAG_MODALITY)); series->description = get_string(item, gdcm::Tag (TAG_SERIES_DESCRIPTION)); series->child_offset = child_offset.GetValue(); series->sibling_offset = sibling_offset.GetValue(); series_offsets[item_offsets[item_index-1]] = series; // Extract image information } else if (record_type == "IMAGE") { auto image = std::make_shared(); image->path = get_string(item, gdcm::Tag (TAG_REFERENCED_FILE_ID)); image->child_offset = child_offset.GetValue(); image->sibling_offset = sibling_offset.GetValue(); image_offsets[item_offsets[item_index-1]] = image; } else { auto other = std::make_shared(); other->child_offset = child_offset.GetValue(); other->sibling_offset = sibling_offset.GetValue(); other_offsets[item_offsets[item_index-1]] = other; } } // Check validity if (patient_offsets.size() == 0) throw std::runtime_error("Unable to find patient record"); reassemble_hierarchy(series_offsets, image_offsets, other_offsets); reassemble_hierarchy(study_offsets, series_offsets, other_offsets); reassemble_hierarchy(patient_offsets, study_offsets, other_offsets); // Set the new root for (auto &patient : patient_offsets) { _patients.push_back(patient.second); } } return _patients; } //============================================================================== // Quick test //============================================================================== int main(int argc, const char *argv[]) { DICOMDIRReader reader; try { if (argc != 2) throw std::runtime_error("Wrong number of arguments"); auto &patients = reader.load(argv[1]); for (auto &patient : patients) { std::cout << "PATIENT" << std::endl; std::cout << "NAME: " << patient->name << std::endl; std::cout << "ID: " << patient->id << std::endl; int x = 0; for (auto &study : patient->children) { std::cout << " STUDY" << std::endl; std::cout << " DESCRIPTION: " << study->description << std::endl; std::cout << " DATE: " << study->date << std::endl; for (auto &series : study->children) { x+=1; std::cout << " SERIES " << x << std::endl; std::cout << " DESCRIPTION: " << series->description << std::endl; std::cout << " MODALITY: " << series->modality << std::endl; for (auto &image : series->children) { std::cout << " IMAGE PATH: " << image->path << std::endl; } } } } } catch (...) { // TODO handle this return EXIT_FAILURE; } return EXIT_SUCCESS; } GDCM-3.0.10/Examples/Cxx/ReadAndPrintAttributes.cxx000066400000000000000000000066621412732066400217520ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This small example will show how one can read and print * a DICOM Attribute using different technique (by tag or by name) */ #include "gdcmReader.h" #include "gdcmGlobal.h" #include "gdcmDicts.h" #include "gdcmDict.h" #include "gdcmAttribute.h" #include "gdcmStringFilter.h" #include int main(int argc, char *argv[]) { if( argc < 2 ) { std::cerr << argv[0] << " input.dcm" << std::endl; return 1; } const char *filename = argv[1]; // Instanciate the reader: gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } // The output of gdcm::Reader is a gdcm::File gdcm::File &file = reader.GetFile(); // the dataset is the the set of element we are interested in: gdcm::DataSet &ds = file.GetDataSet(); const gdcm::Global& g = gdcm::Global::GetInstance(); const gdcm::Dicts &dicts = g.GetDicts(); const gdcm::Dict &pubdict = dicts.GetPublicDict(); using namespace gdcm; // In this example we will show why using name to lookup attribute can be // dangerous. Tag tPatientName(0x0,0x0); //const DictEntry &de1 = pubdict.GetDictEntryByName("Patient Name", tPatientName); std::cout << "Found: " << tPatientName << std::endl; // Indeed the attribute could not be found. Since DICOM 2003, Patient Name // has become Patient's Name. Tag tPatientsName; //const DictEntry &de2 = pubdict.GetDictEntryByName("Patient's Name", tPatientsName); std::cout << "Found: " << tPatientsName << std::endl; // Let's try to read an arbitrary DICOM Attribute: Tag tDoseGridScaling; //const DictEntry &de3 = pubdict.GetDictEntryByName("Dose Grid Scaling", tDoseGridScaling); std::cout << "Found: " << tDoseGridScaling << std::endl; if( ds.FindDataElement( tDoseGridScaling ) ) { gdcm::StringFilter sf; sf.SetFile(file); std::cout << "Attribute Value as String: " << sf.ToString( tDoseGridScaling ) << std::endl; // Let's check the name again: std::pair pss = sf.ToStringPair( tDoseGridScaling ); std::cout << "Attribute Name Checked: " << pss.first << std::endl; std::cout << "Attribute Value (string): " << pss.second << std::endl; //const DataElement &dgs = ds.GetDataElement( tDoseGridScaling ); // Let's assume for a moment we knew the tag number: Attribute<0x3004,0x000e> at; assert( at.GetTag() == tDoseGridScaling ); at.SetFromDataSet( ds ); // For the sake of long term maintenance, we will not write // that this particular attribute is stored as a double. What if // a user made a mistake. It is much safer to rely on GDCM internal // mechanism to deduce the VR::DS type (represented as a ieee double) Attribute<0x3004,0x000e>::ArrayType v = at.GetValue(); std::cout << "DoseGridScaling=" << v << std::endl; } return 0; } GDCM-3.0.10/Examples/Cxx/ReadExplicitLengthSQIVR.cxx000066400000000000000000000027421412732066400217270ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmImplicitDataElement.h" #include "gdcmDataSet.h" #include "gdcmPrivateTag.h" #include "gdcmPrivateTag.h" #include "gdcmByteValue.h" #include "gdcmSequenceOfItems.h" using namespace gdcm; int main(int argc, char *argv[]) { if ( argc < 2 ) return 1; const char *filename = argv[1]; gdcm::Reader r; r.SetFileName( filename ); r.Read(); //gdcm::PrivateTag pt(0xe1,0x42,"ELSCINT1"); //gdcm::Tag pt(0x88,0x200); gdcm::Tag pt(0x8,0x1140); DataSet &ds = r.GetFile().GetDataSet(); const DataElement &de = ds.GetDataElement( pt ); std::cout << de << std::endl; const ByteValue *bv = de.GetByteValue(); SmartPointer sqi = new SequenceOfItems; sqi->SetLength( bv->GetLength() ); std::stringstream ss; ss.str( std::string( bv->GetPointer(), bv->GetLength() ) ); sqi->Read( ss ); std::cout << *sqi << std::endl; return 0; } GDCM-3.0.10/Examples/Cxx/ReadGEMSSDO.cxx000066400000000000000000000115071412732066400172570ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmDataElement.h" #include "gdcmPrivateTag.h" #include #include using namespace gdcm; struct SDOElement { typedef std::vector::size_type SizeType; const char *GetData(SizeType index) const { return Data[index].c_str(); } SizeType GetNumberOfData() const { return Data.size(); } void SetData(SizeType index, const char *data) { Data[index] = data; } const char *GetDataFormat() const { return DataFormat.c_str(); } void SetDataFormat(const char *dataformat, SizeType num) { DataFormat = dataformat; Data.resize( num ); } void Print( std::ostream &os ) const { os << DataFormat << ":" << std::endl; std::vector::const_iterator it = Data.begin(); size_t s = 0; for( ; it != Data.end(); ++it ) { os << " (" << s++ << ") " << *it << std::endl; } } private: std::string DataFormat; std::vector Data; }; class SDOHeader { public: typedef std::vector SDOElements; typedef SDOElements::size_type SizeType; SizeType GetNumberOfSDOElements() const { return InternalSDODataSet.size(); } void AddSDOElement(SDOElement const &sdoelement) { InternalSDODataSet.push_back( sdoelement ); } const SDOElement &GetSDOElement(SizeType index) const { return InternalSDODataSet[index]; } const SDOElement &GetSDOElementByName(const char *) const { return InternalSDODataSet[0]; } void LoadFromAttributes(std::string const &s1, std::string const &s2) { std::string tok; std::string tok2; std::stringstream strstr(s1); std::stringstream strstr2(s2); SDOElement element; // Do format size_t count = 0; while ( std::getline ( strstr2, tok, '\\' ) ) { //std::cout << tok << " "; std::getline ( strstr2, tok2, '\\' ); //std::cout << tok2 << std::endl; count += atoi( tok2.c_str() ); element.SetDataFormat( tok.c_str(), atoi( tok2.c_str() ) ); for( size_t t = 0; t < element.GetNumberOfData(); ++t ) { std::getline ( strstr, tok, '\\' ); element.SetData(t, tok.c_str() ); } AddSDOElement( element ); } //while ( std::getline ( strstr, tok, '^' ) ) // while ( std::getline ( strstr, tok, '\\' ) ) // { // std::cout << tok << std::endl; // count++; // } // std::cout << "Count: " << count << std::endl; // count = 0; // std::cout << "Count: " << count << std::endl; } void Print( std::ostream &os ) const { SDOElements::const_iterator it = InternalSDODataSet.begin(); for( ; it != InternalSDODataSet.end(); ++it ) { it->Print ( os ); } } private: SDOElements InternalSDODataSet; }; bool sdo_decode( DataElement const &stringdata, DataElement const &stringdataformat ) { const char *sd = stringdata.GetByteValue()->GetPointer(); const size_t len_sd = stringdata.GetByteValue()->GetLength(); std::string s1 = std::string( sd, len_sd ); const char *sdf = stringdataformat.GetByteValue()->GetPointer(); const size_t len_sdf = stringdataformat.GetByteValue()->GetLength(); std::string s2 = std::string( sdf, len_sdf ); // std::cout << s1 << std::endl; // std::cout << s2 << std::endl; SDOHeader header; header.LoadFromAttributes( s1, s2 ); header.Print( std::cout ); return true; } int main(int argc, char *argv[]) { if( argc < 2 ) { std::cerr << argv[0] << " input.dcm" << std::endl; return 1; } const char *filename = argv[1]; Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { return 1; } File &file = reader.GetFile(); DataSet &ds = file.GetDataSet(); // StringData (0033,xx1F) 3 "GEMS_GENIE_1" List of SDO parameters stored as // list of strings const PrivateTag tstringdata(0x33,0x1f,"GEMS_GENIE_1"); // StringDataFormat (0033,xx23) 3 "GEMS_GENIE_1" Format of string parameters; // contains information about name and number of strings in list const PrivateTag tstringdataformat(0x33,0x23,"GEMS_GENIE_1"); if( !ds.FindDataElement( tstringdata ) ) return 1; const DataElement& stringdata = ds.GetDataElement( tstringdata ); if( !ds.FindDataElement( tstringdataformat ) ) return 1; const DataElement& stringdataformat = ds.GetDataElement( tstringdataformat ); sdo_decode( stringdata, stringdataformat ); return 0; } GDCM-3.0.10/Examples/Cxx/ReadMultiTimesException.cxx000066400000000000000000000035521412732066400221320ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // The intention of this sample program is to provoke bad_alloc exceptions in gdcm code #include "gdcmImageReader.h" int main(int argc, char* argv[]) { // We pre-allocate some memory (about 1Gb) to help the issue to show up earlier char *dummyBuffer = new char[1024*1024*1100]; (void)dummyBuffer; // Check the number of parameters given if (argc < 3) { std::cerr << "Usage: " << argv[0] << " Filename numberOfTries" << std::endl; return 1; } std::cout << "We are going to read the file: " << argv[1] << " " << argv[2] << " times" << std::endl; // We hold the pointers in an array to avoid the memory to be released // We read the input file n-times for (int i = 0; i < atoi(argv[2]); ++i) { gdcm::ImageReader reader; std::cout << "Reading try: " << i << std::endl; // Read files reader.SetFileName(argv[1]); try { reader.Read(); gdcm::Image & img = reader.GetImage(); unsigned long len = img.GetBufferLength(); char *buffer = new char[ len ]; img.GetBuffer( buffer ); // do NOT de-allocate buffer ! } catch (std::bad_alloc &ba) { (void)ba; std::cerr << "BAD ALLOC Exception caught!" << std::endl; } catch (...) { std::cerr << "Exception caught!" << std::endl; } } return 0; } GDCM-3.0.10/Examples/Cxx/ReadUTF8QtDir.cxx000066400000000000000000000063721412732066400176540ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * GDCM API expect a const char * as input for SetFileName * In order to use this API from Qt, here is a simple test that * shows how to do it in a portable manner: * * http://doc.qt.nokia.com/latest/qdir.html#navigation-and-directory-operations */ #include "gdcmReader.h" #include "gdcmDirectory.h" #include #include #include #include #include #include // fopen static int TestBothFuncs(const char *info , const char *ba_str) { int res = 0; FILE *f = fopen( ba_str, "r" ); if( f ) { std::cout << info << " fopen: " << ba_str << std::endl; fclose(f); ++res; } gdcm::Reader reader; std::ifstream is( ba_str, std::ios::binary ); if( is.is_open() ) { std::cout << info << " is_open: " << ba_str << std::endl; ++res; } reader.SetStream( is ); if( reader.CanRead() == true ) { std::cout << info << " SetStream/CanRead:" << ba_str << std::endl; ++res; } is.close(); reader.SetFileName( ba_str ); if( reader.CanRead() == true ) { std::cout << info << " SetFileName/CanRead:" << ba_str << std::endl; ++res; } return 4 - res; } static int scanFolder(const char dirname[]) { int res = 0; gdcm::Directory dir; unsigned int nfiles = dir.Load( dirname, true ); const gdcm::Directory::FilenamesType &filenames = dir.GetFilenames(); for( unsigned int i = 0; i < nfiles; ++i ) { const char *ba_str = filenames[i].c_str(); res += TestBothFuncs("GDCM",ba_str); } return res; } static int scanFolderQt(QDir const &dir, QStringList& files) { int res = 0; QFileInfoList children = dir.entryInfoList(QDir::AllEntries|QDir::NoDotAndDotDot); for ( int i=0; i(evt); const char *fn = pe.GetFileName(); std::cout << "FileName: " << fn << " FileSize: " << gdcm::System::FileSize( fn ) << std::endl; } }; int main(int argc, char *argv[]) { if( argc < 2 ) { return 1; } const char *filename = argv[1]; const char filename_invalid[] = "this is a file that may not exist on this disk.dcm"; gdcm::SmartPointer sp = new gdcm::StrictScanner; gdcm::StrictScanner &s = *sp; //gdcm::SimpleSubjectWatcher w(&s, "TestFileName" ); MyFileWatcher w(&s, "TestFileName" ); const gdcm::Tag tag_array[] = { gdcm::Tag(0x8,0x50), gdcm::Tag(0x8,0x51), gdcm::Tag(0x8,0x60), gdcm::Tag(0x8,0x80), }; s.AddTag( tag_array[0] ); s.AddTag( tag_array[1] ); s.AddTag( tag_array[2] ); s.AddTag( tag_array[3] ); gdcm::Directory::FilenamesType filenames; filenames.push_back( filename ); filenames.push_back( filename_invalid ); if( !s.Scan( filenames ) ) { return 1; } //s.Print( std::cout ); for(gdcm::Directory::FilenamesType::const_iterator it = filenames.begin(); it != filenames.end(); ++it ) { if( s.IsKey( it->c_str() ) ) { std::cout << "INFO:" << it->c_str() << " is a proper Key for the Scanner (this is a DICOM file)" << std::endl; } else { std::cout << "INFO:" << it->c_str() << " is not a proper Key for the Scanner (this is either not a DICOM file or file does not exist)" << std::endl; } } gdcm::StrictScanner::TagToValue const &ttv = s.GetMapping(filename); const gdcm::Tag *ptag = tag_array; for( ; ptag != tag_array + 3; ++ptag ) { gdcm::StrictScanner::TagToValue::const_iterator it = ttv.find( *ptag ); if( it != ttv.end() ) { std::cout << *ptag << " was properly found in this file" << std::endl; // it contains a pair of value. the first one is the actual tag, so the following is always true: // *ptag == it->first // The second part is the actual value (stored as RAW strings). You will have to reinterpret this string // if VR for *ptag is not VR::VRASCII ! const char *value = it->second; if( *value ) { std::cout << " It has the value: " << value << std::endl; } else { std::cout << " It has no value (empty)" << std::endl; } } else { std::cout << "Sorry " << *ptag << " could not be found in this file" << std::endl; } } return 0; } GDCM-3.0.10/Examples/Cxx/SortImage.cxx000066400000000000000000000065431412732066400172600ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSorter.h" #include "gdcmScanner.h" #include "gdcmDataSet.h" #include "gdcmAttribute.h" bool mysort(gdcm::DataSet const & ds1, gdcm::DataSet const & ds2 ) { //gdcm::Attribute<0x0020,0x0013> at1; // Instance Number gdcm::Attribute<0x0018,0x1060> at1; // Trigger Time gdcm::Attribute<0x0020,0x0032> at11; // Image Position (Patient) at1.Set( ds1 ); at11.Set( ds1 ); //gdcm::Attribute<0x0020,0x0013> at2; gdcm::Attribute<0x0018,0x1060> at2; gdcm::Attribute<0x0020,0x0032> at22; at2.Set( ds2 ); at22.Set( ds2 ); if( at11 == at22 ) { return at1 < at2; } return at11 < at22; } bool mysort_part1(gdcm::DataSet const & ds1, gdcm::DataSet const & ds2 ) { gdcm::Attribute<0x0018,0x1060> at1; at1.Set( ds1 ); gdcm::Attribute<0x0018,0x1060> at2; at2.Set( ds2 ); return at1 < at2; } bool mysort_part2(gdcm::DataSet const & ds1, gdcm::DataSet const & ds2 ) { gdcm::Attribute<0x0020,0x0032> at1; at1.Set( ds1 ); gdcm::Attribute<0x0020,0x0032> at2; at2.Set( ds2 ); return at1 < at2; } // technically all files are in the same Frame of Reference, so this function // should be a no-op bool mysort_dummy(gdcm::DataSet const & ds1, gdcm::DataSet const & ds2 ) { gdcm::Attribute<0x0020,0x0052> at1; // FrameOfReferenceUID at1.Set( ds1 ); gdcm::Attribute<0x0020,0x0052> at2; at2.Set( ds2 ); return at1 < at2; } int main(int argc, char *argv[]) { if (argc < 2 ) return 1; const char *dirname = argv[1]; gdcm::Directory dir; unsigned int nfiles = dir.Load( dirname ); dir.Print( std::cout ); gdcm::Sorter sorter; sorter.SetSortFunction( mysort ); sorter.Sort( dir.GetFilenames() ); std::cout << "Sorter:" << std::endl; sorter.Print( std::cout ); gdcm::Sorter sorter2; sorter2.SetSortFunction( mysort_part1 ); sorter2.StableSort( dir.GetFilenames() ); sorter2.SetSortFunction( mysort_part2 ); sorter2.StableSort( sorter2.GetFilenames() ); // IMPORTANT sorter2.SetSortFunction( mysort_dummy ); sorter2.StableSort( sorter2.GetFilenames() ); // IMPORTANT std::cout << "Sorter2:" << std::endl; sorter2.Print( std::cout ); gdcm::Scanner s; s.AddTag( gdcm::Tag(0x20,0x32) ); // Image Position (Patient) //s.AddTag( gdcm::Tag(0x20,0x37) ); // Image Orientation (Patient) s.Scan( dir.GetFilenames() ); //s.Print( std::cout ); // Count how many different IPP there are: const gdcm::Scanner::ValuesType &values = s.GetValues(); size_t nvalues = values.size(); std::cout << "There are " << nvalues << " different type of values" << std::endl; //std::cout << "nfiles=" << nfiles << std::endl; if( nfiles % nvalues != 0 ) { std::cerr << "Impossible: this is a not a proper series" << std::endl; return 1; } std::cout << "Series is composed of " << (nfiles/nvalues) << " different 3D volumes" << std::endl; return 0; } GDCM-3.0.10/Examples/Cxx/StreamImageReaderTest.cxx000066400000000000000000000212061412732066400215400ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // This work was realised during the GSOC 2011 by Manoj Alwani #include "gdcmStreamImageReader.h" #include "gdcmFileMetaInformation.h" #include "gdcmSystem.h" #include "gdcmFilename.h" #include "gdcmByteSwap.h" #include "gdcmTrace.h" #include "gdcmTesting.h" #include "gdcmImageHelper.h" #include "gdcmImageReader.h" #include "gdcmImage.h" #include "gdcmMediaStorage.h" #include "gdcmRAWCodec.h" #include "gdcmJPEGLSCodec.h" #include "gdcmUIDGenerator.h" #include "gdcmStreamImageWriter.h" #include "gdcmAttribute.h" #include "gdcmFile.h" #include "gdcmTag.h" bool StreamImageRead(gdcm::StreamImageWriter & theStreamWriter, const char* filename, const char* outfilename, int resolution) { gdcm::StreamImageReader reader; reader.SetFileName( filename ); if (!reader.ReadImageInformation()) { std::cerr << "unable to read image information" << std::endl; return 1; //unable to read tags as expected. } //let's be tricky; each image will be read in portions, first the top half, then the bottom //that way, we can test how the stream handles fragmentation of the data //we could also loop this to get various different size combinations, but I'm not sure //that's useful, yet. std::vector extent = gdcm::ImageHelper::GetDimensionsValue(reader.GetFile()); // std::cout << extent[0]; //at this point, these values aren't used, but may be in the future //unsigned short xmin = 0; //unsigned short xmax = extent[0]; //unsigned short ymin = 0; //unsigned short ymax = extent[1]; //unsigned short zmin = 0; //unsigned short zmax = extent[2]; std::cout<< "\n Row: "< Number_Of_Frames = {1}; ds.Insert( Number_Of_Frames.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0010> row = {extent[0]/a};// ds.Insert( row.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0011> col = {extent[1]/a};// ds.Insert( col.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0100> at = {8}; ds.Insert( at.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0002> at1 = {1};// ds.Insert( at1.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0101> at2 = {8}; ds.Insert( at2.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0102> at3 = {7}; ds.Insert( at3.GetAsDataElement() ); /* ds1.Remove( gdcm::Tag(0x0028,0x0008) ); gdcm::Attribute<0x0028,0x0008> Number_Of_Frames = {1}; ds1.Insert( Number_Of_Frames.GetAsDataElement() ); */ theStreamWriter.SetFile(file); if (!theStreamWriter.WriteImageInformation()) { std::cerr << "unable to write image information" << std::endl; return 1; //the CanWrite function should prevent getting here, else, //that's a test failure } std::vector extent1 = gdcm::ImageHelper::GetDimensionsValue(file); unsigned short xmax = extent1[0]; unsigned short ymax = extent1[1]; unsigned short theChunkSize = 1; unsigned short ychunk = extent1[1]/theChunkSize; //go in chunk sizes of theChunkSize unsigned short zmax = 1; std::cout<< "\n Row: "< ymax) nexty = ymax; theStreamWriter.DefinePixelExtent(0, xmax, y, nexty, z, z+1); unsigned long len = theStreamWriter.DefineProperBufferLength(); std::cout << "\n" < tags = gdcm::Anonymizer::GetBasicApplicationLevelConfidentialityProfileAttributes(); for( std::vector::const_iterator tit = tags.begin(); tit != tags.end(); ++tit ) { const Tag &tag = *tit; const DictEntry &dictentry = dicts.GetDictEntry(tag); std::cout << "Processing Attribute: " << tag << " " << dictentry << std::endl; IODs::IODMapTypeConstIterator it = iods.Begin(); for( ; it != iods.End(); ++it ) { const IODs::IODName &name = it->first; const IOD &iod = it->second; const size_t niods = iod.GetNumberOfIODs(); // Iterate over each iod entry in order: for(unsigned int idx = 0; idx < niods; ++idx) { const IODEntry &iodentry = iod.GetIODEntry(idx); const char *ref = iodentry.GetRef(); //Usage::UsageType ut = iodentry.GetUsageType(); const Module &module = modules.GetModule( ref ); if( module.FindModuleEntryInMacros(macros, tag ) ) { const ModuleEntry &module_entry = module.GetModuleEntryInMacros(macros,tag); Type type = module_entry.GetType(); std::cout << "IOD Name: " << name << std::endl; std::cout << "Type: " << type << std::endl; } } } } return 0; } GDCM-3.0.10/Examples/Cxx/VolumeSorter.cxx000066400000000000000000000121011412732066400200170ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSorter.h" #include "gdcmIPPSorter.h" #include "gdcmScanner.h" #include "gdcmDataSet.h" #include "gdcmAttribute.h" #include "gdcmTesting.h" bool mysort1(gdcm::DataSet const & ds1, gdcm::DataSet const & ds2 ) { gdcm::Attribute<0x0020,0x000d> at1; at1.Set( ds1 ); gdcm::Attribute<0x0020,0x000d> at2; at2.Set( ds2 ); return at1 < at2; } bool mysort2(gdcm::DataSet const & ds1, gdcm::DataSet const & ds2 ) { gdcm::Attribute<0x0020,0x000e> at1; at1.Set( ds1 ); gdcm::Attribute<0x0020,0x000e> at2; at2.Set( ds2 ); return at1 < at2; } bool mysort3(gdcm::DataSet const & ds1, gdcm::DataSet const & ds2 ) { // This is a floating point number is the comparison ok ? gdcm::Attribute<0x0020,0x0037> at1; at1.Set( ds1 ); gdcm::Attribute<0x0020,0x0037> at2; at2.Set( ds2 ); return at1 < at2; } bool mysort4(gdcm::DataSet const & ds1, gdcm::DataSet const & ds2 ) { // Do the IPP sorting here gdcm::Attribute<0x0020,0x0032> ipp1; gdcm::Attribute<0x0020,0x0037> iop1; ipp1.Set( ds1 ); iop1.Set( ds1 ); gdcm::Attribute<0x0020,0x0032> ipp2; gdcm::Attribute<0x0020,0x0037> iop2; ipp2.Set( ds2 ); iop2.Set( ds2 ); if( iop1 != iop2 ) { return false; } // else double normal[3]; normal[0] = iop1[1]*iop1[5] - iop1[2]*iop1[4]; normal[1] = iop1[2]*iop1[3] - iop1[0]*iop1[5]; normal[2] = iop1[0]*iop1[4] - iop1[1]*iop1[3]; double dist1 = 0; for (int i = 0; i < 3; ++i) dist1 += normal[i]*ipp1[i]; double dist2 = 0; for (int i = 0; i < 3; ++i) dist2 += normal[i]*ipp2[i]; std::cout << dist1 << "," << dist2 << std::endl; return dist1 < dist2; } int main(int argc, char *argv[]) { const char *extradataroot = gdcm::Testing::GetDataExtraRoot(); std::string dir1; if( argc < 2 ) { if( !extradataroot ) { return 1; } dir1 = extradataroot; dir1 += "/gdcmSampleData/ForSeriesTesting/VariousIncidences/ST1"; } else { dir1 = argv[1]; } gdcm::Directory d; d.Load( dir1.c_str(), true ); // recursive ! const gdcm::Directory::FilenamesType &l1 = d.GetFilenames(); const size_t nfiles = l1.size(); std::cout << nfiles << std::endl; //if( nfiles != 280 ) // { // return 1; // } //d.Print( std::cout ); gdcm::Scanner s0; const gdcm::Tag t1(0x0020,0x000d); // Study Instance UID const gdcm::Tag t2(0x0020,0x000e); // Series Instance UID //const gdcm::Tag t3(0x0010,0x0010); // Patient's Name s0.AddTag( t1 ); s0.AddTag( t2 ); //s0.AddTag( t3 ); //s0.AddTag( t4 ); //s0.AddTag( t5 ); //s0.AddTag( t6 ); bool b = s0.Scan( d.GetFilenames() ); if( !b ) { std::cerr << "Scanner failed" << std::endl; return 1; } //s0.Print( std::cout ); // Only get the DICOM files: gdcm::Directory::FilenamesType l2 = s0.GetKeys(); const size_t nfiles2 = l2.size(); std::cout << nfiles2 << std::endl; if ( nfiles2 > nfiles ) { return 1; } gdcm::Sorter sorter; sorter.SetSortFunction( mysort1 ); sorter.StableSort( l2 ); sorter.SetSortFunction( mysort2 ); sorter.StableSort( sorter.GetFilenames() ); sorter.SetSortFunction( mysort3 ); sorter.StableSort( sorter.GetFilenames() ); sorter.SetSortFunction( mysort4 ); sorter.StableSort( sorter.GetFilenames() ); //sorter.Print( std::cout ); // Let's try to check our result: // assume that IPP is precise enough so that we can test floating point equality: size_t nvalues = 0; { gdcm::Scanner s; s.AddTag( gdcm::Tag(0x20,0x32) ); // Image Position (Patient) //s.AddTag( gdcm::Tag(0x20,0x37) ); // Image Orientation (Patient) s.Scan( d.GetFilenames() ); //s.Print( std::cout ); const gdcm::Scanner::ValuesType &values = s.GetValues(); nvalues = values.size(); std::cout << "There are " << nvalues << " different type of values" << std::endl; assert( nfiles2 % nvalues == 0 ); std::cout << "Series is composed of " << (nfiles/nvalues) << " different 3D volumes" << std::endl; } gdcm::Directory::FilenamesType sorted_files = sorter.GetFilenames(); // Which means we can take nvalues files at a time and execute gdcm::IPPSorter on it: gdcm::IPPSorter ippsorter; gdcm::Directory::FilenamesType sub( sorted_files.begin(), sorted_files.begin() + nvalues); std::cout << sub.size() << std::endl; std::cout << sub[0] << std::endl; std::cout << sub[nvalues-1] << std::endl; ippsorter.SetComputeZSpacing( false ); if( !ippsorter.Sort( sub ) ) { std::cerr << "Could not sort" << std::endl; return 1; } std::cout << "IPPSorter:" << std::endl; ippsorter.Print( std::cout ); return 0; } GDCM-3.0.10/Examples/Cxx/csa2img.cxx000066400000000000000000000120761412732066400167110ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * I do not know what the format is, just guessing from info found on the net: * * http://atonal.ucdavis.edu/matlab/fmri/spm5/spm_dicom_convert.m * * This example is an attempt at understanding the format used by SIEMENS * their "SIEMENS CSA NON-IMAGE" DICOM file (1.3.12.2.1107.5.9.1) * * Everything done in this code is for the sole purpose of writing interoperable * software under Sect. 1201 (f) Reverse Engineering exception of the DMCA. * If you believe anything in this code violates any law or any of your rights, * please contact us (gdcm-developers@lists.sourceforge.net) so that we can * find a solution. * */ #include "gdcmReader.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmCSAHeader.h" #include "gdcmAttribute.h" #include "gdcmPrivateTag.h" #include int main(int argc, char *argv []) { if( argc < 2 ) return 1; // gdcmDataExtra/gdcmNonImageData/exCSA_Non-Image_Storage.dcm // PHANTOM.MR.CARDIO_COEUR_S_QUENCE_DE_REP_RAGE.9.257.2008.03.20.14.53.25.578125.43151705.IMA const char *filename = argv[1]; gdcm::Reader reader; // Do not use ImageReader reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } gdcm::CSAHeader csa; const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); const gdcm::PrivateTag &t1 = csa.GetCSAImageHeaderInfoTag(); //std::cout << t1 << std::endl; //const gdcm::PrivateTag &t2 = csa.GetCSASeriesHeaderInfoTag(); if( ds.FindDataElement( t1 ) ) { csa.LoadFromDataElement( ds.GetDataElement( t1 ) ); csa.Print( std::cout ); } int dims[2] = {}; if( csa.FindCSAElementByName( "Columns" ) ) { const gdcm::CSAElement &csael = csa.GetCSAElementByName( "Columns" ); std::cout << csael << std::endl; //const gdcm::ByteValue *bv = csael.GetByteValue(); gdcm::Element el; el.Set( csael.GetValue() ); dims[0] = el.GetValue(); std::cout << "Columns:" << el.GetValue() << std::endl; } if( csa.FindCSAElementByName( "Rows" ) ) { const gdcm::CSAElement &csael2 = csa.GetCSAElementByName( "Rows" ); std::cout << csael2 << std::endl; gdcm::Element el2; el2.Set( csael2.GetValue() ); dims[1] = el2.GetValue(); std::cout << "Rows:" << el2.GetValue() << std::endl; } double spacing[2] = { 1. , 1. }; bool spacingfound = false; if( csa.FindCSAElementByName( "PixelSpacing" ) ) { const gdcm::CSAElement &csael3 = csa.GetCSAElementByName( "PixelSpacing" ); if( !csael3.IsEmpty() ) { std::cout << csael3 << std::endl; gdcm::Element el3; el3.Set( csael3.GetValue() ); spacing[0] = el3.GetValue(0); spacing[1] = el3.GetValue(1); std::cout << "PixelSpacing:" << el3.GetValue() << "," << el3.GetValue(1) << std::endl; spacingfound = true; } } if( !spacingfound ) { std::cerr << "Problem with PixelSpacing" << std::endl; //return 1; } if( !dims[0] || !dims[1] ) { std::cerr << "Problem with dims" << std::endl; return 1; } gdcm::ImageWriter writer; gdcm::Image &image = writer.GetImage(); image.SetNumberOfDimensions( 2 ); // good default image.SetDimension(0, dims[0] ); image.SetDimension(1, dims[1] ); image.SetSpacing(0, spacing[0] ); image.SetSpacing(1, spacing[1] ); gdcm::PixelFormat pixeltype = gdcm::PixelFormat::INT16; // bytepix = spm_type('int16','bits')/8; //unsigned long l = image.GetBufferLength(); //const int p = l / (dims[0] * dims[1]); //image.SetNumberOfDimensions( 3 ); //image.SetDimension(2, p / pixeltype.GetPixelSize() ); gdcm::PhotometricInterpretation pi; pi = gdcm::PhotometricInterpretation::MONOCHROME2; //pixeltype.SetSamplesPerPixel( ); image.SetPhotometricInterpretation( pi ); image.SetPixelFormat( pixeltype ); //image.SetIntercept( inputimage.GetIntercept() ); //image.SetSlope( inputimage.GetSlope() ); //gdcm::DataElement pixeldata( gdcm::Tag(0x7fe1,0x1010) ); //pixeldata.SetByteValue( &outbuf[0], outbuf.size() ); gdcm::PrivateTag csanonimaget(0x7fe1,0x10,"SIEMENS CSA NON-IMAGE"); const gdcm::DataElement &pixeldata = ds.GetDataElement( csanonimaget ); image.SetDataElement( pixeldata ); std::string outfilename = "outcsa.dcm"; //writer.SetFile( reader.GetFile() ); writer.SetFileName( outfilename.c_str() ); if( !writer.Write() ) { std::cerr << "could not write: " << outfilename << std::endl; return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/iU22tomultisc.cxx000066400000000000000000000066771412732066400200630ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * iU22 Raw Data extractor */ #include "gdcmReader.h" #include "gdcmImageWriter.h" #include "gdcmAttribute.h" #include "gdcmPrivateTag.h" #include int main(int argc, char *argv []) { if( argc < 2 ) return 1; // IM_001 const char *filename = argv[1]; gdcm::Reader reader; // Do not use ImageReader reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } // * The data is simply 8-bit unsigned in the obvious x/y/z order // * 200D,300B contains the data // * 200D,3001 contains the no. of voxels (416,412,256 in this case) // * 200D,3003 contains the voxel sizes (0.156184527398215 / // 0.1223749613981957 / 0.328479990704639 in this case) const gdcm::File &file = reader.GetFile(); const gdcm::DataSet &ds = file.GetDataSet(); const gdcm::PrivateTag trawdataus( 0x200d, 0x0b, "Philips US Imaging DD 033" ); const gdcm::DataElement &rawdataus = ds.GetDataElement( trawdataus ); const gdcm::PrivateTag tcolsrowsframes( 0x200d, 0x01, "Philips US Imaging DD 036" ); const gdcm::DataElement &colsrowsframes = ds.GetDataElement( tcolsrowsframes ); // const gdcm::PrivateTag tcolsrowsframes( 0x200d, 0x02, "Philips US Imaging DD 036" ); // this is just a duplicate previous tag. const gdcm::PrivateTag tvoxelspacing( 0x200d, 0x03, "Philips US Imaging DD 036" ); const gdcm::DataElement &voxelspacing = ds.GetDataElement( tvoxelspacing ); gdcm::Element dims; // Use DS to interpret value stored in LO dims.SetFromDataElement( colsrowsframes ); gdcm::Element spacing; spacing.SetFromDataElement( voxelspacing ); gdcm::ImageWriter writer; gdcm::Image &image = writer.GetImage(); image.SetNumberOfDimensions( 3 ); // good default image.SetDimension(0, (unsigned int)dims[0] ); image.SetDimension(1, (unsigned int)dims[1] ); image.SetDimension(2, (unsigned int)dims[2] ); image.SetSpacing(0, spacing[0] ); image.SetSpacing(1, spacing[1] ); image.SetSpacing(2, spacing[2] ); gdcm::PixelFormat pixeltype = gdcm::PixelFormat::UINT8; gdcm::PhotometricInterpretation pi; pi = gdcm::PhotometricInterpretation::MONOCHROME2; image.SetPhotometricInterpretation( pi ); image.SetPixelFormat( pixeltype ); image.SetDataElement( rawdataus ); std::string outfilename = "outiu22.dcm"; gdcm::DataElement de( gdcm::Tag(0x8,0x16) ); // SOP Class UID de.SetVR( gdcm::VR::UI ); gdcm::MediaStorage ms( gdcm::MediaStorage::UltrasoundMultiFrameImageStorage ); // gdcm::MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage ); de.SetByteValue( ms.GetString(), (uint32_t)strlen(ms.GetString())); writer.GetFile().GetDataSet().Replace( de ); writer.SetFileName( outfilename.c_str() ); if( !writer.Write() ) { std::cerr << "could not write: " << outfilename << std::endl; return 1; } return 0; } GDCM-3.0.10/Examples/Cxx/pmsct_rgb1.cxx000066400000000000000000000172501412732066400174240ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This example shows how to rewrite a ELSCINT1/PMSCT_RGB1 compressed * image so that it is readable by most 3rd party software (DICOM does * not specify this particular encoding). * This is required for the sake of interoperability with any standard * conforming DICOM system. * * Everything done in this code is for the sole purpose of writing interoperable * software under Sect. 1201 (f) Reverse Engineering exception of the DMCA. * If you believe anything in this code violates any law or any of your rights, * please contact us (gdcm-developers@lists.sourceforge.net) so that we can * find a solution. * * Everything you do with this code is at your own risk, since decompression * algorithm was not written from specification documents. * * Special thanks to: * Jean-Pierre Roux for providing the sample datasets */ #include "gdcmReader.h" #include "gdcmPrivateTag.h" #include "gdcmAttribute.h" #include "gdcmImageWriter.h" void delta_decode(const unsigned char *data_in, size_t data_size, std::vector &new_stream, unsigned short pc, size_t w, size_t h) { const size_t plane_size = h * w; const size_t outputlen = 3 * plane_size; new_stream.resize( outputlen ); assert( data_size != outputlen ); if( data_size == outputlen ) { return; } typedef unsigned char byte; enum { COLORMODE = 0x81, ESCMODE = 0x82, REPEATMODE = 0x83 }; const byte* src = (const byte*)data_in; byte* dest = (byte*)&new_stream[0]; union { byte gray; byte rgb[3]; } pixel; pixel.rgb[0] = pixel.rgb[1] = pixel.rgb[2] = 0; // always start in grayscale mode bool graymode = true; size_t dx = 1; size_t dy = 3; // algorithm works with both planar configuration // It does produce surprising greenish background color for planar // configuration is 0, while the nested Icon SQ display a nice black // background if (pc) { dx = plane_size; dy = 1; } size_t ps = plane_size; // The following is highly unoptimized as we have nested if statement in a while loop // we need to switch from one algorithm to ther other (RGB <-> GRAY) while (ps) { // next byte: byte b = *src++; assert( src < data_in + data_size ); // mode selection: switch ( b ) { case ESCMODE: // Used to treat a byte 81/82/83 as a normal byte if (graymode) { pixel.gray += *src++; dest[0*dx] = pixel.gray; dest[1*dx] = pixel.gray; dest[2*dx] = pixel.gray; } else { pixel.rgb[0] += *src++; pixel.rgb[1] += *src++; pixel.rgb[2] += *src++; dest[0*dx] = pixel.rgb[0]; dest[1*dx] = pixel.rgb[1]; dest[2*dx] = pixel.rgb[2]; } dest += dy; ps--; break; case REPEATMODE: // repeat mode (RLE) b = *src++; ps -= b; if (graymode) { while (b-- > 0) { dest[0*dx] = pixel.gray; dest[1*dx] = pixel.gray; dest[2*dx] = pixel.gray; dest += dy; } } else { while (b-- > 0) { dest[0*dx] = pixel.rgb[0]; dest[1*dx] = pixel.rgb[1]; dest[2*dx] = pixel.rgb[2]; dest += dy; } } break; case COLORMODE: // We are swithing from one mode to the other. The stream contains an intermixed // compression of RGB codec and GRAY codec. Each one not knowing of the other // reset old value to 0. if (graymode) { graymode = false; pixel.rgb[0] = pixel.rgb[1] = pixel.rgb[2] = 0; } else { graymode = true; pixel.gray = 0; } break; default: // This is identical to ESCMODE, it would be nicer to use fall-through if (graymode) { pixel.gray += b; dest[0*dx] = pixel.gray; dest[1*dx] = pixel.gray; dest[2*dx] = pixel.gray; } else { pixel.rgb[0] += b; pixel.rgb[1] += *src++; pixel.rgb[2] += *src++; dest[0*dx] = pixel.rgb[0]; dest[1*dx] = pixel.rgb[1]; dest[2*dx] = pixel.rgb[2]; } dest += dy; ps--; break; } // end switch } // end while } int main(int argc, char *argv []) { if( argc < 2 ) return 1; const char *filename = argv[1]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); // (07a1,1011) CS [PMSCT_RGB1] # 10,1 Tamar Compression Type const gdcm::PrivateTag tcompressiontype(0x07a1,0x0011,"ELSCINT1"); if( !ds.FindDataElement( tcompressiontype ) ) return 1; const gdcm::DataElement& compressiontype = ds.GetDataElement( tcompressiontype ); if ( compressiontype.IsEmpty() ) return 1; const gdcm::ByteValue * bv = compressiontype.GetByteValue(); std::string comprle = "PMSCT_RLE1"; std::string comprgb = "PMSCT_RGB1"; bool isrle = false; bool isrgb = false; if( strncmp( bv->GetPointer(), comprle.c_str(), comprle.size() ) == 0 ) { isrle = true; return 1; } if( strncmp( bv->GetPointer(), comprgb.c_str(), comprgb.size() ) == 0 ) { isrgb = true; } if( !isrgb && !isrle ) return 1; const gdcm::PrivateTag tcompressedpixeldata(0x07a1,0x000a,"ELSCINT1"); if( !ds.FindDataElement( tcompressedpixeldata) ) return 1; const gdcm::DataElement& compressionpixeldata = ds.GetDataElement( tcompressedpixeldata); if ( compressionpixeldata.IsEmpty() ) return 1; const gdcm::ByteValue * bv2 = compressionpixeldata.GetByteValue(); gdcm::Attribute<0x0028,0x0006> at0; at0.SetFromDataSet( ds ); gdcm::Attribute<0x0028,0x0010> at1; at1.SetFromDataSet( ds ); gdcm::Attribute<0x0028,0x0011> at2; at2.SetFromDataSet( ds ); std::vector buffer; delta_decode((const unsigned char*)bv2->GetPointer(), bv2->GetLength(), buffer, at0.GetValue(), at1.GetValue(), at2.GetValue() ); gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0,0x0010) ); pixeldata.SetVR( gdcm::VR::OW ); pixeldata.SetByteValue( (char*)&buffer[0], (uint32_t)buffer.size() ); // TODO we should check that decompress byte buffer match the expected size (row*col*...) // Add the pixel data element reader.GetFile().GetDataSet().Replace( pixeldata ); reader.GetFile().GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian); gdcm::Writer writer; writer.SetFile( reader.GetFile() ); // Cleanup stuff: // remove the compressed pixel data: // FIXME: should I remove more private tags ? all of them ? // oh well this is just an example // use gdcm::Anonymizer::RemovePrivateTags if needed... writer.GetFile().GetDataSet().Remove( compressionpixeldata.GetTag() ); std::string outfilename; if (argc > 2) outfilename = argv[2]; else outfilename = "outrgb.dcm"; writer.SetFileName( outfilename.c_str() ); if( !writer.Write() ) { std::cerr << "Failed to write" << std::endl; return 1; } std::cout << "success !" << std::endl; return 0; } GDCM-3.0.10/Examples/Cxx/rle2img.cxx000066400000000000000000000166661412732066400167360ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This example shows how to rewrite a ELSCINT1/PMSCT_RLE1 compressed * image so that it is readable by most 3rd party software (DICOM does * not specify this particular encoding). * This is required for the sake of interoperability with any standard * conforming DICOM system. * * Everything done in this code is for the sole purpose of writing interoperable * software under Sect. 1201 (f) Reverse Engineering exception of the DMCA. * If you believe anything in this code violates any law or any of your rights, * please contact us (gdcm-developers@lists.sourceforge.net) so that we can * find a solution. * * Everything you do with this code is at your own risk, since decompression * algorithm was not written from specification documents. * * Special thanks to: * Mauro Maiorca for bringing to our attention on this new ELSCINT1 * compression algorithm : PMSCT_RLE1 (different from the 'LOSSLESS RICE') * See post at: * http://groups.google.com/group/comp.protocols.dicom/msg/f2b99bf706a7f8ca * * Thanks to Jesus Spinola, for more datasets, * http://www.itk.org/pipermail/insight-users/2008-April/025571.html * * And last but not least, a very big thank to Ivo van Poorten, without * whom we would still be looking at this compressed byte stream as if * it was RLE compressed. */ #include "gdcmReader.h" #include "gdcmPrivateTag.h" #include "gdcmAttribute.h" #include "gdcmImageWriter.h" /* FIXME: Why is PhilipsLosslessRice.dcm a 512x512 image ... */ void delta_decode(const char *inbuffer, size_t length, std::vector &output) { // RLE pass std::vector temp; for(size_t i = 0; i < length; ++i) { if( inbuffer[i] == (char)0xa5 ) { //unsigned char repeat = (unsigned char)inbuffer[i+1] + 1; //assert( (unsigned char)inbuffer[i+1] != 255 ); int repeat = (unsigned char)inbuffer[i+1] + 1; char value = inbuffer[i+2]; while(repeat) { temp.push_back( value ); --repeat; } i+=2; } else { temp.push_back( inbuffer[i] ); } } // Delta encoding pass unsigned short delta = 0; for(size_t i = 0; i < temp.size(); ++i) { if( temp[i] == 0x5a ) { unsigned char v1 = (unsigned char)temp[i+1]; unsigned char v2 = (unsigned char)temp[i+2]; unsigned short value = (unsigned short)(v2 * 256 + v1); output.push_back( value ); delta = value; i+=2; } else { unsigned short value = (unsigned short)(temp[i] + delta); output.push_back( value ); delta = value; } //assert( output[output.size()-1] == ref[output.size()-1] ); } if ( output.size() % 2 ) { output.resize( output.size() - 1 ); } std::cout << length << " -> " << output.size() * 2 << std::endl; } int main(int argc, char *argv []) { if( argc < 2 ) { std::cerr << argv[0] << "input.dcm [output.dcm]" << std::endl; std::cerr << "will default to 'outrle.dcm' unless output.dcm is specified." << std::endl; return 1; } const char *filename = argv[1]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); // (07a1,1011) CS [PMSCT_RLE1] # 10,1 Tamar Compression Type const gdcm::PrivateTag tcompressiontype(0x07a1,0x0011,"ELSCINT1"); if( !ds.FindDataElement( tcompressiontype ) ) return 1; const gdcm::DataElement& compressiontype = ds.GetDataElement( tcompressiontype ); if ( compressiontype.IsEmpty() ) return 1; const gdcm::ByteValue * bv = compressiontype.GetByteValue(); std::string comprle = "PMSCT_RLE1"; std::string comprgb = "PMSCT_RGB1"; bool isrle = false; bool isrgb = false; if( strncmp( bv->GetPointer(), comprle.c_str(), comprle.size() ) == 0 ) { isrle = true; } if( strncmp( bv->GetPointer(), comprgb.c_str(), comprgb.size() ) == 0 ) { isrgb = true; std::cerr << "See: pmsct_rgb1.cxx instead" << std::endl; return 1; } if( !isrgb && !isrle ) return 1; // check if compressed pixel data reside in private or standard tag const gdcm::PrivateTag tprivatepixeldata(0x07a1,0x100a,"ELSCINT1"); const gdcm::Tag tstandardpixeldata(0x7fe0, 0x0010); gdcm::Tag tpixeldata; if(ds.FindDataElement(tprivatepixeldata)) tpixeldata = tprivatepixeldata; else if(ds.FindDataElement(tstandardpixeldata)) tpixeldata = tstandardpixeldata; if(!ds.FindDataElement(tpixeldata)) return 1; const gdcm::DataElement& compressionpixeldata = ds.GetDataElement( tpixeldata); if ( compressionpixeldata.IsEmpty() ) return 1; const gdcm::ByteValue * bv2 = compressionpixeldata.GetByteValue(); gdcm::Attribute<0x0028,0x0010> at1; at1.SetFromDataSet( ds ); gdcm::Attribute<0x0028,0x0011> at2; at2.SetFromDataSet( ds ); gdcm::DataElement pixeldata; // if standard voxel data element does not exist, create it if( !reader.GetFile().GetDataSet().FindDataElement( tpixeldata ) ) { pixeldata = gdcm::DataElement( tpixeldata, 0, gdcm::VR::OW ); } else{ pixeldata = reader.GetFile().GetDataSet().GetDataElement( tpixeldata ); } pixeldata.SetVR( gdcm::VR::OW ); gdcm::VL bv2l = bv2->GetLength(); gdcm::VL at1l = at1.GetValue() * at2.GetValue() * 2; /* sizeof(unsigned short) == 2 */ // Handle special case that is not compressed: if( bv2l == at1l ) { pixeldata.SetByteValue( bv2->GetPointer(), bv2->GetLength() ); } else { std::vector buffer; delta_decode(bv2->GetPointer(), bv2->GetLength(), buffer); pixeldata.SetByteValue( (char*)&buffer[0], (uint32_t)(buffer.size() * sizeof( unsigned short )) ); } // TODO we should check that decompress byte buffer match the expected size (row*col*...) // Add the pixel data element if( reader.GetFile().GetDataSet().FindDataElement( tpixeldata ) ) { reader.GetFile().GetDataSet().Replace( pixeldata ); } else { reader.GetFile().GetDataSet().ReplaceEmpty( pixeldata ); } reader.GetFile().GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian); gdcm::Writer writer; writer.SetFile( reader.GetFile() ); // Cleanup stuff: // This makes the code equivalent to Philips workstation IntelliSpace Portal if( writer.GetFile().GetDataSet().FindDataElement( tcompressiontype ) ) { writer.GetFile().GetDataSet().Remove( gdcm::Tag(0x07a1,0x1011) ); } if( writer.GetFile().GetDataSet().FindDataElement( tprivatepixeldata ) ) { writer.GetFile().GetDataSet().Remove( gdcm::Tag(0x07a1,0x100a) ); } std::string outfilename; if (argc > 2) outfilename = argv[2]; else outfilename = "outrle.dcm"; writer.SetFileName( outfilename.c_str() ); if( !writer.Write() ) { std::cerr << "Failed to write" << std::endl; return 1; } std::cout << "success !" << std::endl; return 0; } GDCM-3.0.10/Examples/Cxx/uid_unique.cxx000066400000000000000000000030411412732066400175230ustar00rootroot00000000000000/*========================================================================= 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 "gdcmUIDGenerator.h" #include #include #include /** This is a toy program just to check how good the UID are uniq. The rule of thumb is that you should not have a long Root UID otherwise the algorithm might find twice the same UID... */ int main() { gdcm::UIDGenerator uid; //const char myroot[] = "9876543210.9876543210.9876543210.9876543210.9876543210"; // fails in ~40000 tries const char myroot[] = "9876543210.9876543210.9876543210"; uid.SetRoot( myroot ); std::set uids; uint64_t wrap = 0; uint64_t c = 0; while(true) { const char *unique = uid.Generate(); //std::cout << unique << std::endl; if( c % 10000 == 0 ) { std::cout << "wrap=" << wrap << ",c=" << c << std::endl; } ++c; if( c == 0 ) { wrap++; } if ( uids.count(unique) == 1 ) { std::cerr << "Failed with: " << unique << std::endl; return 1; } uids.insert( unique ); } } GDCM-3.0.10/Examples/Java/000077500000000000000000000000001412732066400147515ustar00rootroot00000000000000GDCM-3.0.10/Examples/Java/CMakeLists.txt000066400000000000000000000026471412732066400175220ustar00rootroot00000000000000find_package(Java ${GDCM_DEFAULT_JAVA_VERSION} REQUIRED) # javac, jar find_package(JNI REQUIRED) include_directories( #${JNI_INCLUDE_PATH} ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2} ${JAVA_AWT_INCLUDE_PATH} ) set(classfilesdep) set(examples HelloSimple ExtractImageRegion DecompressPixmap DecompressImage ScanDirectory ReadFiles SimplePrint FileAnonymize ) foreach(example ${examples}) add_custom_command( OUTPUT ${GDCM_EXECUTABLE_DIR}/${example}.class COMMAND ${Java_JAVAC_EXECUTABLE} ARGS -source ${GDCM_JAVA_SOURCE_VERSION} -target ${GDCM_JAVA_TARGET_VERSION} ${CMAKE_CURRENT_SOURCE_DIR}/${example}.java -d ${GDCM_EXECUTABLE_DIR} -classpath ${GDCM_LIBRARY_DIR}/gdcm.jar WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${example}.java COMMENT "javac ${example}.java" ) list(APPEND classfilesdep ${GDCM_EXECUTABLE_DIR}/${example}.class) endforeach() # 3. ok now add the target add_custom_target(GDCMJavaExample ALL DEPENDS ${classfilesdep} COMMENT "building gdcm java example" ) # make sure gdcm.jar is built add_dependencies(GDCMJavaExample GDCMJavaJar) if(BUILD_TESTING) if(GDCM_DATA_ROOT) set_source_files_properties(${GDCM_EXECUTABLE_DIR}/HelloSimple.class PROPERTIES CLASSPATH "${GDCM_LIBRARY_DIR}/gdcm.jar") ADD_JAVA_TEST(TestHelloSimpleJava ${GDCM_EXECUTABLE_DIR}/HelloSimple ${GDCM_DATA_ROOT}/012345.002.050.dcm) endif() endif() GDCM-3.0.10/Examples/Java/DecompressImage.java000066400000000000000000000040271412732066400206660ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This example will take in a DICOM file, and tries to decompress it (actually write it * as ImplicitVRLittleEndian Transfer Syntax). * * Compilation: * $ CLASSPATH=gdcm.jar javac ../../gdcm/Examples/Java/DecompressImage.java -d . * * Usage: * $ LD_LIBRARY_PATH=. CLASSPATH=gdcm.jar:. java DecompressImage gdcmData/012345.002.050.dcm out.dcm */ import gdcm.*; public class DecompressImage { public static void main(String[] args) throws Exception { String file1 = args[0]; String file2 = args[1]; ImageReader reader = new ImageReader(); reader.SetFileName( file1 ); boolean ret = reader.Read(); if( !ret ) { throw new Exception("Could not read: " + file1 ); } ImageChangeTransferSyntax change = new ImageChangeTransferSyntax(); change.SetTransferSyntax( new TransferSyntax(TransferSyntax.TSType.ImplicitVRLittleEndian) ); change.SetInput( reader.GetImage() ); if( !change.Change() ) { throw new Exception("Could not change: " + file1 ); } Image out = change.GetOutput(); System.out.println( out.toString() ); // Set the Source Application Entity Title FileMetaInformation.SetSourceApplicationEntityTitle( "Just For Fun" ); ImageWriter writer = new ImageWriter(); writer.SetFileName( file2 ); writer.SetFile( reader.GetFile() ); writer.SetImage( out ); ret = writer.Write(); if( !ret ) { throw new Exception("Could not write: " + file2 ); } } } GDCM-3.0.10/Examples/Java/DecompressPixmap.java000066400000000000000000000043471412732066400211070ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This example will take in a DICOM file, and tries to decompress it (actually write it * as ImplicitVRLittleEndian Transfer Syntax). * * Compilation: * $ CLASSPATH=gdcm.jar javac ../../gdcm/Examples/Java/DecompressPixmap.java -d . * * Usage: * $ LD_LIBRARY_PATH=. CLASSPATH=gdcm.jar:. java DecompressPixmap gdcmData/012345.002.050.dcm out.dcm */ import gdcm.*; public class DecompressPixmap { public static void main(String[] args) throws Exception { String file1 = args[0]; String file2 = args[1]; PixmapReader reader = new PixmapReader(); reader.SetFileName( file1 ); boolean ret = reader.Read(); if( !ret ) { throw new Exception("Could not read: " + file1 ); } ImageChangeTransferSyntax change = new ImageChangeTransferSyntax(); change.SetTransferSyntax( new TransferSyntax(TransferSyntax.TSType.ImplicitVRLittleEndian) ); PixmapToPixmapFilter filter = (PixmapToPixmapFilter)change; filter.SetInput( reader.GetPixmap() ); if( !change.Change() ) { throw new Exception("Could not change: " + file1 ); } // The following does not work in Java/swig 2.0.7 //Pixmap p = ((PixmapToPixmapFilter)change).GetOutput(); Pixmap p = change.GetOutputAsPixmap(); // be explicit //System.out.println( p.toString() ); // Set the Source Application Entity Title FileMetaInformation.SetSourceApplicationEntityTitle( "Just For Fun" ); PixmapWriter writer = new PixmapWriter(); writer.SetFileName( file2 ); writer.SetFile( reader.GetFile() ); writer.SetImage( p ); ret = writer.Write(); if( !ret ) { throw new Exception("Could not write: " + file2 ); } } } GDCM-3.0.10/Examples/Java/ExtractImageRegion.java000066400000000000000000000050171412732066400213400ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * This small code shows how to use the gdcm.ImageRegionReader API * In this example we are taking each frame by frame and dump them to * /tmp/frame.raw. * * Usage: * $ LD_LIBRARY_PATH=. CLASSPATH=gdcm.jar:. java ExtractImageRegion input.dcm */ import gdcm.*; import java.io.FileOutputStream; public class ExtractImageRegion { public static void main(String[] args) throws Exception { String filename = args[0]; // instantiate the reader: ImageRegionReader reader = new ImageRegionReader(); reader.SetFileName( filename ); // pull DICOM info: if (!reader.ReadInformation()) return; // Get file infos File f = reader.GetFile(); // get some info about image UIntArrayType dims = ImageHelper.GetDimensionsValue(f); PixelFormat pf = ImageHelper.GetPixelFormatValue (f); int pixelsize = pf.GetPixelSize(); // buffer to get the pixels long buffer_length = dims.get(0) * dims.get(1) * pixelsize; byte[] buffer = new byte[ (int)buffer_length ]; // define a simple box region. BoxRegion box = new BoxRegion(); for (int z = 0; z < dims.get(2); z++) { // Define that I want the image 0, full size (dimx x dimy pixels) // and do that for each z: box.SetDomain(0, dims.get(0) - 1, 0, dims.get(1) - 1, z, z); //System.Console.WriteLine( box.toString() ); reader.SetRegion( box ); // reader will try to load the uncompressed image region into buffer. // the call returns an error when buffer.Length is too small. For instance // one can call: // long buf_len = reader.ComputeBufferLength(); // take into account pixel size // to get the exact size of minimum buffer if (reader.ReadIntoBuffer(buffer, buffer_length)) { FileOutputStream fos = new FileOutputStream("/tmp/frame.raw"); fos.write(buffer); fos.close(); } else { throw new Exception("can't read pixels error"); } } } } GDCM-3.0.10/Examples/Java/FileAnonymize.java000066400000000000000000000037261412732066400203750ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /** * Usage: * $ LD_LIBRARY_PATH=. CLASSPATH=gdcm.jar:. java FileAnonymize input.dcm output.dcm */ import gdcm.*; public class FileAnonymize { public static class MyWatcher extends SimpleSubjectWatcher { public MyWatcher(Subject s) { super(s,"Override String"); } protected void ShowProgress(Subject caller, Event evt) { ProgressEvent pe = ProgressEvent.Cast(evt); System.out.println( "This is my progress: " + pe.GetProgress() ); } } public static void main(String[] args) throws Exception { String input = args[0]; String output = args[1]; FileAnonymizer fa = new FileAnonymizer(); fa.SetInputFileName( input ); fa.SetOutputFileName( output ); // Empty Operations // It will create elements, since those tags are non-registered public elements (2011): fa.Empty( new Tag(0x0008,0x1313) ); fa.Empty( new Tag(0x0008,0x1317) ); // Remove Operations // The following Tag are actually carefully chosen, since they refer to SQ: fa.Remove( new Tag(0x0008,0x2112) ); fa.Remove( new Tag(0x0008,0x9215) ); // Replace Operations // do not call replace operation on SQ attribute ! fa.Replace( new Tag(0x0018,0x5100), "MYVALUE " ); fa.Replace( new Tag(0x0008,0x1160), "MYOTHERVAL" ); if( !fa.Write() ) { System.out.println( "Could not write" ); return; } System.out.println( "success" ); } } GDCM-3.0.10/Examples/Java/HelloSimple.java000066400000000000000000000023651412732066400200370ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Compilation: * $ CLASSPATH=gdcm.jar javac ../../gdcm/Examples/Java/HelloSimple.java -d . * * Usage: * $ LD_LIBRARY_PATH=. CLASSPATH=gdcm.jar:. java HelloSimple gdcmData/012345.002.050.dcm */ import gdcm.*; public class HelloSimple { public static void main(String[] args) throws Exception { String filename = args[0]; Reader reader = new Reader(); reader.SetFileName( filename ); boolean ret = reader.Read(); if( !ret ) { throw new Exception("Could not read: " + filename ); } File f = reader.GetFile(); DataSet ds = f.GetDataSet(); System.out.println( ds.toString() ); System.out.println("Success reading: " + filename ); } } GDCM-3.0.10/Examples/Java/ReadFiles.java000066400000000000000000000055211412732066400174550ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /** * Simple example showing that Jav UTF-16 string are properly passed to * GDCM layer as locale 8bits * This example also explain the use of try {} finally {} in java to * make sure the C++ RAII design of gdcm.Reader is properly used from * Java and does not leak opened file destructor. * * Compilation: * $ CLASSPATH=gdcm.jar javac ../../gdcm/Examples/Java/ReadFiles.java -d . * * Usage: * $ LD_LIBRARY_PATH=. CLASSPATH=gdcm.jar:. java ReadFiles gdcmData */ import gdcm.*; import java.io.File; public class ReadFiles { static int i = 0; public static void process(String path) { //String path = file.getPath(); assert PosixEmulation.FileExists(path) : "Problem converting to 8bits"; System.out.println("Reading: " + path ); System.out.println("File: " + i++); Reader r = new Reader(); try { r.SetFileName( path ); TagSetType skip = new TagSetType(); skip.insert( new Tag(0x7fe0,0x10) ); boolean b = r.ReadUpToTag( new Tag(0x88,0x200), skip ); //System.out.println("DS:\n" + r.GetFile().GetDataSet().toString() ); } finally { r.delete(); // will properly call C++ destructor and close file descriptor } } // Process only files under dir public static void visitAllFiles(File dir) { if (dir.isDirectory()) { String[] children = dir.list(); for (int i=0; i" + val ); } } for( long idx = 0; idx < fns.size(); ++idx ) { Reader r = new Reader(); String fn = fns.get( (int)idx ); String outfn = fn + ".png"; r.SetFileName( fn ); TagSetType tst = new TagSetType(); tst.insert( new Tag(0x7fe0,0x10) ); b = r.ReadUpToTag( new Tag(0x88,0x200), tst ); UIntArrayType dims = ImageHelper.GetDimensionsValue( r.GetFile() ); if( b ) { IconImageFilter iif = new IconImageFilter(); System.out.println( "Processing: " + fn ); iif.SetFile( r.GetFile() ); b = iif.Extract(); if( b ) { Bitmap icon = iif.GetIconImage(0); WritePNG(icon, outfn); } else { ImageReader ir = new ImageReader(); ir.SetFileName( fn ); if( ir.Read() ) { Image img = ir.GetImage(); StringFilter sf = new StringFilter(); sf.SetFile( r.GetFile() ); String strval = sf.ToString( new Tag(0x0028,0x0120) ); IconImageGenerator iig = new IconImageGenerator(); iig.SetPixmap( img ); iig.AutoPixelMinMax( true ); try { double val = Double.parseDouble( strval ); iig.SetOutsideValuePixel( val ); } catch ( NumberFormatException e) { } iig.ConvertRGBToPaletteColor( false ); long idims[] = { 128, 128}; iig.SetOutputDimensions( idims ); iig.Generate(); Bitmap icon = iig.GetIconImage(); WritePNG(icon, outfn); } } } } System.out.println( "Scan:\n" + s.toString() ); System.out.println( "success" ); } } GDCM-3.0.10/Examples/Java/SimplePrint.java000066400000000000000000000044231412732066400200650ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Compilation: * $ CLASSPATH=gdcm.jar javac ../../gdcm/Examples/Java/SimplePrint.java -d . * * Usage: * $ LD_LIBRARY_PATH=. CLASSPATH=gdcm.jar:. java SimplePrint gdcmData/012345.002.050.dcm */ import gdcm.*; public class SimplePrint { public static void RecurseDataSet(File f, DataSet ds, String indent) { JavaDataSet cds = new JavaDataSet(ds); while(!cds.IsAtEnd()) { DataElement de = cds.GetCurrent(); // Compute VR from the toplevel file, and the currently processed dataset: VR vr = DataSetHelper.ComputeVR(f, ds, de.GetTag() ); if( vr.Compatible( new VR(VR.VRType.SQ) ) ) { long uvl = de.GetVL().GetValueLength(); // Test cast is ok System.out.println( indent + de.GetTag().toString() + ":" + uvl ); // why not ? //SequenceOfItems sq = de.GetSequenceOfItems(); // GetValueAsSQ handle more cases than GetSequenceOfItems SmartPtrSQ sq = de.GetValueAsSQ(); long n = sq.GetNumberOfItems(); for( long i = 1; i <= n; i++) // item starts at 1, not 0 { Item item = sq.GetItem( i ); DataSet nested = item.GetNestedDataSet(); RecurseDataSet( f, nested, indent + " " ); } } else { System.out.println( indent + de.toString() ); } cds.Next(); } } public static void main(String[] args) throws Exception { String filename = args[0]; Reader reader = new Reader(); reader.SetFileName( filename ); boolean ret = reader.Read(); if( !ret ) { throw new Exception("Could not read: " + filename ); } File f = reader.GetFile(); DataSet ds = f.GetDataSet(); RecurseDataSet( f, ds, "" ); } } GDCM-3.0.10/Examples/PHP/000077500000000000000000000000001412732066400145175ustar00rootroot00000000000000GDCM-3.0.10/Examples/PHP/README.txt000066400000000000000000000001201412732066400162060ustar00rootroot00000000000000php -d enable_dl=On test.php sudo cp bin/gdcm.so /usr/lib/php5/20090626/gdcm.so GDCM-3.0.10/Examples/PHP/export_pnm.php000066400000000000000000000022601412732066400174230ustar00rootroot00000000000000SetFilename( "test.dcm" ); if( !$reader->Read() ) { return; } $file = $reader->GetFile(); $pixmap = $reader->GetPixmap(); print $pixmap; $pnm = new PNMCodec(); $pnm->SetDimensions( $pixmap->GetDimensions() ); $pnm->SetPixelFormat( $pixmap->GetPixelFormat() ); $pnm->SetPhotometricInterpretation( $pixmap->GetPhotometricInterpretation() ); $in = $pixmap->GetDataElement(); $outfilename = 'test.pnm'; if( $pnm->Write( $outfilename, $in ) ) { print "Success"; } ?> GDCM-3.0.10/Examples/PHP/hello_world.php000066400000000000000000000050501412732066400175420ustar00rootroot00000000000000SetFilename( "test.dcm" ); $ret=$reader->Read(); if( !$ret ) { return 1; } $file = $reader->GetFile(); // The output of gdcm::Reader is a gdcm::File // the dataset is the the set of element we are interested in: $ds = $file->GetDataSet(); print_r($ds); $g = c_Global::getInstance(); $dicts = $g->GetDicts(); $pubdict = $dicts->GetPublicDict(); // In this example we will show why using name to lookup attribute can be // dangerous. $tPatientName= new Tag(0x0,0x0); $de1 = $pubdict->GetDictEntryByName("Patient Name", $tPatientName); printf("Found %s",$tPatientName); // Indeed the attribute could not be found. Since DICOM 2003, Patient Name // has become Patient's Name. $tPatientsName = new Tag(); $de2 = $pubdict->GetDictEntryByName("Patient's Name", $tPatientsName); printf("Found: %s",$tPatientsName); // Let's try to read an arbitrary DICOM Attribute: $tDoseGridScaling=new Tag(); $de3 = $pubdict->GetDictEntryByName("Dose Grid Scaling", $tDoseGridScaling); printf("Found: %s",$tDoseGridScaling); if( $ds->FindDataElement( $tDoseGridScaling ) ) { $sf= new StringFilter(); $sf->SetFile($file); printf("Attribute Value as String: %s",$sf->ToString( $tDoseGridScaling )); // Let's check the name again: $pss = $sf->ToStringPair( $tDoseGridScaling ); printf("Attribute Name Checked: %s", $pss->first); printf("Attribute Value (string): %s", $pss->second); $dgs = $ds->GetDataElement( $tDoseGridScaling ); // Let's assume for a moment we knew the tag number: $at=new Tag(0x3004,0x000e); assert( $at.GetTag() == $tDoseGridScaling ); $at->SetFromDataSet( $ds ); // For the sake of long term maintenance, we will not write // that this particular attribute is stored as a double. What if // a user made a mistake. It is much safer to rely on GDCM internal // mechanism to deduce the VR::DS type (represented as a ieee double) $v = $at->GetValue(); printf("DoseGridScaling=%s",$v); } ?> GDCM-3.0.10/Examples/PHP/modify_file.php000066400000000000000000000025131412732066400175170ustar00rootroot00000000000000SetFilename( "test.dcm" ); $ret=$reader->Read(); if( !$ret ) { return 1; } $file = $reader->GetFile(); $ano = new Anonymizer(); $ano->SetFile($file); $ano->RemovePrivateTags(); $ano->RemoveGroupLength(); $t = new Tag(0x10,0x10); $ano->Replace( $t, "GDCM^PHP^Test^Hello^World" ); $g = new UIDGenerator(); $ano->Replace( new Tag(0x0008,0x0018), $g->Generate() ); $ano->Replace( new Tag(0x0020,0x000d), $g->Generate() ); $ano->Replace( new Tag(0x0020,0x000e), $g->Generate() ); $ano->Replace( new Tag(0x0020,0x0052), $g->Generate() ); $writer = new Writer(); $writer->SetFileName( "test2.dcm" ); $writer->SetFile( $ano->GetFile() ); $ret = $writer->Write(); if( !$ret ) { return 1; } ?> GDCM-3.0.10/Examples/PHP/qido.php000066400000000000000000000025051412732066400161660ustar00rootroot00000000000000SetHostname( $remote ); $scu->SetPort( $portno ); $scu->SetTimeout( 1000 ); //$scu->SetCalledAETitle( "GDCM_STORE" ); $scu->InitializeConnection(); $generator = new PresentationContextGenerator(); $generator->GenerateFromUID( UIDs::VerificationSOPClass ); $scu->SetPresentationContexts( $generator->GetPresentationContexts() ); $scu->StartAssociation(); $scu->SendEcho(); $scu->StopAssociation(); $findds = new DataSet(); $findquery = CompositeNetworkFunctions::ConstructQuery( eStudyRootType, eStudy, $findds); // https://sourceforge.net/p/swig/bugs/1337/ // https://sourceforge.net/p/swig/bugs/1338/ // https://sourceforge.net/p/swig/bugs/1339/ ?> GDCM-3.0.10/Examples/PHP/rewrite_header.php000066400000000000000000000017151412732066400202250ustar00rootroot00000000000000SetFilename( "test.dcm" ); $reader->Read(); $file = $reader->GetFile(); $header = $file->GetHeader(); $header->Clear(); $writer = new Writer(); $writer->SetFilename( "test2.dcm" ); $writer->SetFile( $file ); $writer->Write(); ?> GDCM-3.0.10/Examples/Python/000077500000000000000000000000001412732066400153515ustar00rootroot00000000000000GDCM-3.0.10/Examples/Python/AddPrivateAttribute.py000066400000000000000000000021421412732066400216310ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Usage: python AddPrivateAttribute.py input.dcm output.dcm """ import sys import gdcm if __name__ == "__main__": file1 = sys.argv[1] file2 = sys.argv[2] r = gdcm.Reader() r.SetFileName( file1 ) if not r.Read(): sys.exit(1) f = r.GetFile() ds = f.GetDataSet() # Create a dataelement de = gdcm.DataElement(gdcm.Tag(0x0051, 0x1011)) de.SetByteStringValue("p2") de.SetVR(gdcm.VR(gdcm.VR.SH)) ds.Insert(de) w = gdcm.Writer() w.SetFile( f ) w.SetFileName( file2 ) if not w.Write(): sys.exit(1) GDCM-3.0.10/Examples/Python/CMakeLists.txt000066400000000000000000000000001412732066400200770ustar00rootroot00000000000000GDCM-3.0.10/Examples/Python/ConvertMPL.py000066400000000000000000000055401412732066400177200ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ display a DICOM image with matPlotLib via numpy Caveats: - Does not support UINT12/INT12 Usage: python ConvertNumpy.py "IM000000" Thanks: plotting example - Ray Schumacher 2009 """ import gdcm import numpy from pylab import * def get_gdcm_to_numpy_typemap(): """Returns the GDCM Pixel Format to numpy array type mapping.""" _gdcm_np = {gdcm.PixelFormat.UINT8 :numpy.int8, gdcm.PixelFormat.INT8 :numpy.uint8, gdcm.PixelFormat.UINT16 :numpy.uint16, gdcm.PixelFormat.INT16 :numpy.int16, gdcm.PixelFormat.UINT32 :numpy.uint32, gdcm.PixelFormat.INT32 :numpy.int32, gdcm.PixelFormat.FLOAT32:numpy.float32, gdcm.PixelFormat.FLOAT64:numpy.float64 } return _gdcm_np def get_numpy_array_type(gdcm_pixel_format): """Returns a numpy array typecode given a GDCM Pixel Format.""" return get_gdcm_to_numpy_typemap()[gdcm_pixel_format] def gdcm_to_numpy(image): """Converts a GDCM image to a numpy array. """ pf = image.GetPixelFormat().GetScalarType() print 'pf', pf print image.GetPixelFormat().GetScalarTypeAsString() assert pf in get_gdcm_to_numpy_typemap().keys(), \ "Unsupported array type %s"%pf d = image.GetDimension(0), image.GetDimension(1) print 'Image Size: %d x %d' % (d[0], d[1]) dtype = get_numpy_array_type(pf) gdcm_array = image.GetBuffer() ## use float for accurate scaling result = numpy.frombuffer(gdcm_array, dtype=dtype).astype(float) ## optional gamma scaling #maxV = float(result[result.argmax()]) #result = result + .5*(maxV-result) #result = numpy.log(result+50) ## apprx background level result.shape = d return result if __name__ == "__main__": import sys r = gdcm.ImageReader() filename = sys.argv[1] r.SetFileName( filename ) if not r.Read(): sys.exit(1) numpy_array = gdcm_to_numpy( r.GetImage() ) subplot(111)# one plot, on left title(filename) ## many colormaps are available imshow(numpy_array, interpolation='bilinear', cmap=cm.jet) ## set the plot sizes and placement subplots_adjust(bottom=0.1, right=0.8, top=0.9) cax = axes([0.85, 0.1, 0.075, 0.8]) colorbar(cax=cax) title('values') get_current_fig_manager().window.title('plot') show() GDCM-3.0.10/Examples/Python/ConvertNumpy.py000066400000000000000000000047371412732066400204070ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ This module add support for converting a gdcm.Image to a numpy array. Caveats: - Does not support UINT12/INT12 Removed: - float16 is defined in GDCM API but no implementation exist for it ... """ import gdcm import numpy def get_gdcm_to_numpy_typemap(): """Returns the GDCM Pixel Format to numpy array type mapping.""" _gdcm_np = {gdcm.PixelFormat.UINT8 :numpy.uint8, gdcm.PixelFormat.INT8 :numpy.int8, #gdcm.PixelFormat.UINT12 :numpy.uint12, #gdcm.PixelFormat.INT12 :numpy.int12, gdcm.PixelFormat.UINT16 :numpy.uint16, gdcm.PixelFormat.INT16 :numpy.int16, gdcm.PixelFormat.UINT32 :numpy.uint32, gdcm.PixelFormat.INT32 :numpy.int32, #gdcm.PixelFormat.FLOAT16:numpy.float16, gdcm.PixelFormat.FLOAT32:numpy.float32, gdcm.PixelFormat.FLOAT64:numpy.float64 } return _gdcm_np def get_numpy_array_type(gdcm_pixel_format): """Returns a numpy array typecode given a GDCM Pixel Format.""" return get_gdcm_to_numpy_typemap()[gdcm_pixel_format] def gdcm_to_numpy(image): """Converts a GDCM image to a numpy array. """ pf = image.GetPixelFormat() assert pf.GetScalarType() in get_gdcm_to_numpy_typemap().keys(), \ "Unsupported array type %s"%pf shape = image.GetDimension(0) * image.GetDimension(1), pf.GetSamplesPerPixel() if image.GetNumberOfDimensions() == 3: shape = shape[0] * image.GetDimension(2), shape[1] dtype = get_numpy_array_type(pf.GetScalarType()) gdcm_array = image.GetBuffer() result = numpy.frombuffer(gdcm_array, dtype=dtype) result.shape = shape return result if __name__ == "__main__": import sys r = gdcm.ImageReader() filename = sys.argv[1] r.SetFileName( filename ) if not r.Read(): sys.exit(1) numpy_array = gdcm_to_numpy( r.GetImage() ) print numpy_array GDCM-3.0.10/Examples/Python/ConvertPIL.py000066400000000000000000000057071412732066400177210ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ save a DICOM image with PIL via numpy Caveats: - Does not support UINT12/INT12 Usage: python ConvertNumpy.py "IM000000" Thanks: plotting example - Ray Schumacher 2009 """ import gdcm import numpy from PIL import Image, ImageOps def get_gdcm_to_numpy_typemap(): """Returns the GDCM Pixel Format to numpy array type mapping.""" _gdcm_np = {gdcm.PixelFormat.UINT8 :numpy.int8, gdcm.PixelFormat.INT8 :numpy.uint8, gdcm.PixelFormat.UINT16 :numpy.uint16, gdcm.PixelFormat.INT16 :numpy.int16, gdcm.PixelFormat.UINT32 :numpy.uint32, gdcm.PixelFormat.INT32 :numpy.int32, gdcm.PixelFormat.FLOAT32:numpy.float32, gdcm.PixelFormat.FLOAT64:numpy.float64 } return _gdcm_np def get_numpy_array_type(gdcm_pixel_format): """Returns a numpy array typecode given a GDCM Pixel Format.""" return get_gdcm_to_numpy_typemap()[gdcm_pixel_format] def gdcm_to_numpy(image): """Converts a GDCM image to a numpy array. """ pf = image.GetPixelFormat().GetScalarType() print 'pf', pf print image.GetPixelFormat().GetScalarTypeAsString() assert pf in get_gdcm_to_numpy_typemap().keys(), \ "Unsupported array type %s"%pf d = image.GetDimension(0), image.GetDimension(1) print 'Image Size: %d x %d' % (d[0], d[1]) dtype = get_numpy_array_type(pf) gdcm_array = image.GetBuffer() result = numpy.frombuffer(gdcm_array, dtype=dtype) maxV = float(result[result.argmax()]) ## linear gamma adjust #result = result + .5*(maxV-result) ## log gamma result = numpy.log(result+50) ## 50 is apprx background level maxV = float(result[result.argmax()]) result = result*(2.**8/maxV) ## histogram stretch result.shape = d return result if __name__ == "__main__": import sys r = gdcm.ImageReader() filename = sys.argv[1] r.SetFileName( filename ) if not r.Read(): sys.exit(1) numpy_array = gdcm_to_numpy( r.GetImage() ) ## L is 8 bit grey ## http://www.pythonware.com/library/pil/handbook/concepts.htm pilImage = Image.frombuffer('L', numpy_array.shape, numpy_array.astype(numpy.uint8), 'raw','L',0,1) ## cutoff removes background noise and spikes pilImage = ImageOps.autocontrast(pilImage, cutoff=.1) pilImage.save(sys.argv[1]+'.jpg') GDCM-3.0.10/Examples/Python/CreateRAWStorage.py000066400000000000000000000103171412732066400210270ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ """ import gdcm import sys,os if __name__ == "__main__": r = gdcm.Reader() # Will require Testing... dataroot = gdcm.Testing.GetDataRoot() filename = os.path.join( dataroot, '012345.002.050.dcm' ) r.SetFileName( filename ) r.Read() f = r.GetFile() ds = f.GetDataSet() uid = "1.2.840.10008.5.1.4.1.1.66" # f = gdcm.File() # ds = f.GetDataSet() de = gdcm.DataElement( gdcm.Tag(0x0008,0x0016) ) de.SetByteStringValue( uid ) vr = gdcm.VR( gdcm.VR.UI ) de.SetVR( vr ) ds.Replace( de ) ano = gdcm.Anonymizer() ano.SetFile( r.GetFile() ) ano.RemovePrivateTags() ano.RemoveGroupLength() taglist = [ gdcm.Tag(0x0008,0x0008), gdcm.Tag(0x0008,0x0022), gdcm.Tag(0x0008,0x0032), gdcm.Tag(0x0008,0x2111), gdcm.Tag(0x0008,0x1150), gdcm.Tag(0x0008,0x1155), gdcm.Tag(0x0008,0x0100), gdcm.Tag(0x0008,0x0102), gdcm.Tag(0x0008,0x0104), gdcm.Tag(0x0040,0xa170), gdcm.Tag(0x0008,0x2112), gdcm.Tag(0x0008,0x0100), gdcm.Tag(0x0008,0x0102), gdcm.Tag(0x0008,0x0104), gdcm.Tag(0x0008,0x9215), gdcm.Tag(0x0018,0x0010), gdcm.Tag(0x0018,0x0022), gdcm.Tag(0x0018,0x0050), gdcm.Tag(0x0018,0x0060), gdcm.Tag(0x0018,0x0088), gdcm.Tag(0x0018,0x0090), gdcm.Tag(0x0018,0x1040), gdcm.Tag(0x0018,0x1100), gdcm.Tag(0x0018,0x1110), gdcm.Tag(0x0018,0x1111), gdcm.Tag(0x0018,0x1120), gdcm.Tag(0x0018,0x1130), gdcm.Tag(0x0018,0x1150), gdcm.Tag(0x0018,0x1151), gdcm.Tag(0x0018,0x1152), gdcm.Tag(0x0018,0x1160), gdcm.Tag(0x0018,0x1190), gdcm.Tag(0x0018,0x1210), gdcm.Tag(0x0020,0x0012), gdcm.Tag(0x0020,0x0032), gdcm.Tag(0x0020,0x0037), gdcm.Tag(0x0020,0x1041), gdcm.Tag(0x0020,0x4000), gdcm.Tag(0x0028,0x0002), gdcm.Tag(0x0028,0x0004), gdcm.Tag(0x0028,0x0010), gdcm.Tag(0x0028,0x0011), gdcm.Tag(0x0028,0x0030), gdcm.Tag(0x0028,0x0100), gdcm.Tag(0x0028,0x0101), gdcm.Tag(0x0028,0x0102), gdcm.Tag(0x0028,0x0103), gdcm.Tag(0x0028,0x1052), gdcm.Tag(0x0028,0x1053), gdcm.Tag(0x0028,0x2110), gdcm.Tag(0x0028,0x2112), gdcm.Tag(0x7fe0,0x0010), gdcm.Tag(0x0018,0x0020), gdcm.Tag(0x0018,0x0021), gdcm.Tag(0x0018,0x0023), gdcm.Tag(0x0018,0x0025), gdcm.Tag(0x0018,0x0080), gdcm.Tag(0x0018,0x0081), gdcm.Tag(0x0018,0x0083), gdcm.Tag(0x0018,0x0084), gdcm.Tag(0x0018,0x0085), gdcm.Tag(0x0018,0x0086), gdcm.Tag(0x0018,0x0087), gdcm.Tag(0x0018,0x0091), gdcm.Tag(0x0018,0x0093), gdcm.Tag(0x0018,0x0094), gdcm.Tag(0x0018,0x0095), gdcm.Tag(0x0018,0x1088), gdcm.Tag(0x0018,0x1090), gdcm.Tag(0x0018,0x1094), gdcm.Tag(0x0018,0x1250), gdcm.Tag(0x0018,0x1251), gdcm.Tag(0x0018,0x1310), gdcm.Tag(0x0018,0x1312), gdcm.Tag(0x0018,0x1314), gdcm.Tag(0x0018,0x1315), gdcm.Tag(0x0018,0x1316), gdcm.Tag(0x0020,0x0110), gdcm.Tag(0x0028,0x0120), gdcm.Tag(0x0028,0x1050), gdcm.Tag(0x0028,0x1051) ] for tag in taglist: #print tag ano.Remove( tag ) # special handling gen = gdcm.UIDGenerator() ano.Replace( gdcm.Tag(0x0008,0x9123), gen.Generate() ) #ano.Empty( gdcm.Tag(0x0040,0x0555) ) # # uid = gen.Generate() # de.SetTag( gdcm.Tag(0x0008,0x0018) ) # de.SetByteStringValue( uid ) # ds.Insert( de ) # init FMI now: #fmi = f.GetHeader() #ts = gdcm.TransferSyntax() #print ts #fmi.SetDataSetTransferSyntax( ts ) # default #print fmi.GetDataSetTransferSyntax() #de.SetTag( gdcm.Tag(0x0002,0x0010) ) #uid = "1.2.840.10008.1.2" #de.SetByteStringValue( uid ) #fmi.Insert( de ) # f.SetHeader( r.GetFile().GetHeader() ) writer = gdcm.Writer() writer.SetFile( ano.GetFile() ) writer.SetFileName( "rawstorage.dcm" ); writer.Write() GDCM-3.0.10/Examples/Python/DecompressImage.py000066400000000000000000000036611412732066400210000ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Usage: python DecompressImage.py gdcmData/012345.002.050.dcm decompress.dcm """ import gdcm import sys if __name__ == "__main__": file1 = sys.argv[1] file2 = sys.argv[2] r = gdcm.ImageReader() r.SetFileName( file1 ) if not r.Read(): sys.exit(1) # check GetFragment API: pd = r.GetFile().GetDataSet().GetDataElement(gdcm.Tag(0x7fe0, 0x0010)) frags = pd.GetSequenceOfFragments(); frags.GetFragment(0); ir = r.GetImage() w = gdcm.ImageWriter() image = w.GetImage() image.SetNumberOfDimensions( ir.GetNumberOfDimensions() ); dims = ir.GetDimensions(); print ir.GetDimension(0); print ir.GetDimension(1); print "Dims:",dims # Just for fun: dircos = ir.GetDirectionCosines() t = gdcm.Orientation.GetType(tuple(dircos)) l = gdcm.Orientation.GetLabel(t) print "Orientation label:",l image.SetDimension(0, ir.GetDimension(0) ); image.SetDimension(1, ir.GetDimension(1) ); pixeltype = ir.GetPixelFormat(); image.SetPixelFormat( pixeltype ); pi = ir.GetPhotometricInterpretation(); image.SetPhotometricInterpretation( pi ); pixeldata = gdcm.DataElement( gdcm.Tag(0x7fe0,0x0010) ) str1 = ir.GetBuffer() #print ir.GetBufferLength() pixeldata.SetByteStringValue( str1 ) image.SetDataElement( pixeldata ) w.SetFileName( file2 ) w.SetFile( r.GetFile() ) w.SetImage( image ) if not w.Write(): sys.exit(1) GDCM-3.0.10/Examples/Python/DumbAnonymizer.py000066400000000000000000000074601412732066400206750ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ This example shows how one can use the gdcm.Anonymizer in 'dumb' mode. This class becomes really handy when one knows which particular tag to fill in. Usage: python DumbAnonymizer.py gdcmData/012345.002.050.dcm out.dcm """ import gdcm # http://www.oid-info.com/get/1.3.6.1.4.17434 THERALYS_ORG_ROOT = "1.3.6.1.4.17434" tag_rules={ # Value (0x0012,0x0010):("Value","MySponsorName"), (0x0012,0x0020):("Value","MyProtocolID"), (0x0012,0x0021):("Value","MyProtocolName"), (0x0012,0x0062):("Value","YES"), (0x0012,0x0063):("Value","MyDeidentificationMethod"), # Method #(0x0002,0x0003):("Method","GenerateMSOPId"), #(0x0008,0x1155):("Method","GenerateMSOPId"), (0x0008,0x0018):("Method","GenerateMSOPId"), (0x0010,0x0010):("Method","GetSponsorInitials"), (0x0010,0x0020):("Method","GetSponsorId"), (0x0012,0x0030):("Method","GetSiteId"), (0x0012,0x0031):("Method","GetSiteName"), (0x0012,0x0040):("Method","GetSponsorId"), (0x0012,0x0050):("Method","GetTPId"), (0x0018,0x0022):("Method","KeepIfExist"), (0x0018,0x1315):("Method","KeepIfExist"), (0x0020,0x000d):("Method","GenerateStudyId"), (0x0020,0x000e):("Method","GenerateSeriesId"), (0x0020,0x1002):("Method","GetNumberOfFrames"), (0x0020,0x0020):("Method","GetPatientOrientation"), # Other: (0x0012,0x0051):("Patient Field","Type Examen"), (0x0018,0x1250):("Sequence Field","Receive Coil"), (0x0018,0x0088):("Sequence Field","Spacing Between Slice"), (0x0018,0x0095):("Sequence Field","Pixel Bandwidth"), (0x0018,0x0082):("Sequence Field","Invertion Time"), } class MyAnon: def __init__(self): self.studyuid = None self.seriesuid = None generator = gdcm.UIDGenerator() if not self.studyuid: self.studyuid = generator.Generate() if not self.seriesuid: self.seriesuid = generator.Generate() def GetSponsorInitials(self): return "dummy^foobar" def GenerateStudyId(self): return self.studyuid def GenerateSeriesId(self): return self.seriesuid #def GenerateMSOPId(self): def GenerateMSOPId(self): generator = gdcm.UIDGenerator() return generator.Generate() def GetSiteId(self): return "MySiteId" def GetSiteName(self): return "MySiteName" def GetSponsorId(self): return "MySponsorId" def GetTPId(self): return "MyTP" if __name__ == "__main__": import sys gdcm.FileMetaInformation.SetSourceApplicationEntityTitle( "DumbAnonymizer" ) gdcm.UIDGenerator.SetRoot( THERALYS_ORG_ROOT ) r = gdcm.Reader() filename = sys.argv[1] r.SetFileName( filename ) if not r.Read(): sys.exit(1) obj = MyAnon() w = gdcm.Writer() ano = gdcm.Anonymizer() ano.SetFile( r.GetFile() ) ano.RemoveGroupLength() for tag,rule in tag_rules.items(): if rule[0] == 'Value': print tag,rule ano.Replace( gdcm.Tag( tag[0], tag[1] ), rule[1] ) elif rule[0] == 'Method': print tag,rule # result = locals()[rule[1]]() methodname = rule[1] if hasattr(obj, methodname): _member = getattr(obj, methodname) result = _member() ano.Replace( gdcm.Tag( tag[0], tag[1] ), result ) else: print "Problem with: ", methodname outfilename = sys.argv[2] w.SetFileName( outfilename ) w.SetFile( ano.GetFile() ) if not w.Write(): sys.exit(1) GDCM-3.0.10/Examples/Python/ExtractImageRegion.py000066400000000000000000000051321412732066400214450ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ This small code shows how to use the gdcm.ImageRegionReader API In this example we are taking each frame by frame and dump them to /tmp/frame.raw. Usage: $ ExtractImageRegion.py input.dcm Example: $ ExtractImageRegion.py gdcmData/012345.002.050.dcm $ md5sum /tmp/frame.raw d594a5e2fde12f32b6633ca859b4d4a6 /tmp/frame.raw $ gdcminfo --md5sum gdcmData/012345.002.050.dcm [...] md5sum: d594a5e2fde12f32b6633ca859b4d4a6 """ import gdcm if __name__ == "__main__": import sys filename = sys.argv[1] file_size = gdcm.System.FileSize(filename); # instantiate the reader: reader = gdcm.ImageRegionReader(); reader.SetFileName( filename ); # pull DICOM info: if not reader.ReadInformation(): sys.exit(1) # store current offset: cur_pos = reader.GetStreamCurrentPosition(); remaining = file_size - cur_pos; print("Remaining bytes to read (Pixel Data): %d" % remaining ); # Get file infos f = reader.GetFile(); # get some info about image dims = gdcm.ImageHelper.GetDimensionsValue(f); print(dims) pf = gdcm.ImageHelper.GetPixelFormatValue (f); pixelsize = pf.GetPixelSize(); pi = gdcm.ImageHelper.GetPhotometricInterpretationValue(f); print( pi ); # buffer to get the pixels buffer = bytearray( dims[0] * dims[1] * pixelsize ) # define a simple box region. box = gdcm.BoxRegion(); for z in range(0, dims[2]): # Define that I want the image 0, full size (dimx x dimy pixels) # and do that for each z: box.SetDomain(0, dims[0] - 1, 0, dims[1] - 1, z, z); #print( box.toString() ); reader.SetRegion( box ); # reader will try to load the uncompressed image region into buffer. # the call returns an error when buffer.Length is too small. For instance # one can call: # uint buf_len = reader.ComputeBufferLength(); // take into account pixel size # to get the exact size of minimum buffer if reader.ReadIntoBuffer(buffer): open('/tmp/frame.raw', 'wb').write(buffer) else: #throw new Exception("can't read pixels error"); sys.exit(1) GDCM-3.0.10/Examples/Python/FindAllPatientName.py000066400000000000000000000025061412732066400213650ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ This example shows how one can use the gdcm.CompositeNetworkFunctions class for executing a C-FIND query It will print the list of patient name found Usage: python FindAllPatientName.py """ import gdcm # Patient Name tag = gdcm.Tag(0x10,0x10) de = gdcm.DataElement(tag) # Search all patient name where string match 'F*' de.SetByteStringValue('F*') ds = gdcm.DataSet() ds.Insert(de) cnf = gdcm.CompositeNetworkFunctions() theQuery = cnf.ConstructQuery (gdcm.ePatientRootType,gdcm.ePatient,ds) #print theQuery.ValidateQuery() # prepare the variable for output ret = gdcm.DataSetArrayType() # Execute the C-FIND query cnf.CFind('dicom.example.com',11112,theQuery,ret,'GDCM_PYTHON','ANY-SCP') for i in range(0,ret.size()): print "Patient #",i print ret[i] GDCM-3.0.10/Examples/Python/FixCommaBug.py000066400000000000000000000035361412732066400200730ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Using LC_NUMERIC set to something not compatible with "C" it is possible to write out "," instead of "." as required by the DICOM standard Issue is still current (IMHO) with gdcm 2.0.9 """ import gdcm import sys filename = sys.argv[1] outname = sys.argv[2] # read r = gdcm.Reader() r.SetFileName( filename ) if not r.Read(): print "not valid" sys.exit(1) file = r.GetFile() dataset = file.GetDataSet() ano = gdcm.Anonymizer() ano.SetFile( file ) tags = [ gdcm.Tag(0x0018,0x1164), gdcm.Tag(0x0018,0x0088), gdcm.Tag(0x0018,0x0050), gdcm.Tag(0x0028,0x0030), ] for tag in tags: print tag if dataset.FindDataElement( tag ): pixelspacing = dataset.GetDataElement( tag ) #print pixelspacing bv = pixelspacing.GetByteValue() str = bv.GetBuffer() #print bv.GetLength() #print len(str) new_str = str.replace(",",".") # Need to explicitly pass bv.GetLength() to remove any trailing garbage ano.Replace( tag, new_str, bv.GetLength() ) #print dataset w = gdcm.Writer() w.SetFile( file ) w.SetFileName( outname ) if not w.Write(): print "Cannot write" sys.exit(1) # paranoid: image_reader = gdcm.ImageReader() image_reader.SetFileName( outname ) if not image_reader.Read(): print "there is still a comma" sys.exit(1) print "Sucess!" sys.exit(0) # success GDCM-3.0.10/Examples/Python/GetPortionCSAHeader.py000066400000000000000000000035261412732066400214630ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Usage: python GetPortionCSAHeader.py input.dcm Footnote: SIEMENS is not publishing any information on the CSA header. So any info extracted is at your own risk. """ import sys import gdcm if __name__ == "__main__": file = sys.argv[1] r = gdcm.Reader() r.SetFileName( file ) if not r.Read(): sys.exit(1) ds = r.GetFile().GetDataSet() csa_t1 = gdcm.CSAHeader() csa_t2 = gdcm.CSAHeader() #print csa t1 = csa_t1.GetCSAImageHeaderInfoTag(); print t1 t2 = csa_t2.GetCSASeriesHeaderInfoTag(); print t2 # Let's do it for t1: if ds.FindDataElement( t1 ): csa_t1.LoadFromDataElement( ds.GetDataElement( t1 ) ) print csa_t1 # Now let's pretend we are only interested in B_value and DiffusionGradientDirection entries: bvalues = csa_t1.GetCSAElementByName( "B_value" ) # WARNING: it is case sensitive ! print bvalues diffgraddir = csa_t1.GetCSAElementByName( "DiffusionGradientDirection" ) # WARNING: it is case sensitive ! print diffgraddir # repeat for t2 if you like it: if ds.FindDataElement( t2 ): csa_t2.LoadFromDataElement( ds.GetDataElement( t2 ) ) # print csa_t2 gdt = csa_t2.GetCSAElementByName( "GradientDelayTime" ) print gdt bv = gdt.GetByteValue(); #print bv str = bv.GetPointer() print str.split("\\") GDCM-3.0.10/Examples/Python/HelloWorld.py000066400000000000000000000031041412732066400177740ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Hello World ! """ import gdcm import sys if __name__ == "__main__": # verbosity: #gdcm.Trace.DebugOn() #gdcm.Trace.WarningOn() #gdcm.Trace.ErrorOn() # Get the filename from the command line filename = sys.argv[1] # Instanciate a gdcm.Reader # This is the main class to handle any type of DICOM object # You should check for gdcm.ImageReader for reading specifically DICOM Image file r = gdcm.Reader() r.SetFileName( filename ) # If the reader fails to read the file, we should stop ! if not r.Read(): print "Not a valid DICOM file" sys.exit(1) # Get the DICOM File structure file = r.GetFile() # Get the DataSet part of the file dataset = file.GetDataSet() # Ok let's print it ! print dataset # Use StringFilter to print a particular Tag: sf = gdcm.StringFilter() sf.SetFile(r.GetFile()) # Check if Attribute exist print dataset.FindDataElement( gdcm.Tag(0x0028,0x0010)) # Let's print it as string pair: print sf.ToStringPair(gdcm.Tag(0x0028,0x0010)) GDCM-3.0.10/Examples/Python/ManipulateFile.py000066400000000000000000000075161412732066400206330ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Usage: python ManipulateFile.py input.dcm output.dcm Footnote: GDCM 1.2.x would create incorrect Multiframes MR Image Storage file. Try to recover from the issues to recreate a MultiframeGrayscaleByteSecondaryCaptureImageStorage file. e.g: python ManipulateFile.py Insight/Testing/Temporary/itkGDCMImageIOTest5-j2k.dcm manipulated.dcm """ import sys import gdcm if __name__ == "__main__": file1 = sys.argv[1] file2 = sys.argv[2] r = gdcm.Reader() r.SetFileName( file1 ) if not r.Read(): sys.exit(1) ano = gdcm.Anonymizer() ano.SetFile( r.GetFile() ) ano.RemovePrivateTags() ano.Remove( gdcm.Tag(0x0032,0x1030) ) ano.Remove( gdcm.Tag(0x008,0x14) ) ano.Remove( gdcm.Tag(0x008,0x1111) ) ano.Remove( gdcm.Tag(0x008,0x1120) ) ano.Remove( gdcm.Tag(0x008,0x1140) ) ano.Remove( gdcm.Tag(0x10,0x21b0) ) ano.Empty( gdcm.Tag(0x10,0x10) ) ano.Empty( gdcm.Tag(0x10,0x20) ) ano.Empty( gdcm.Tag(0x10,0x30) ) ano.Empty( gdcm.Tag(0x20,0x10) ) ano.Empty( gdcm.Tag(0x32,0x1032) ) ano.Empty( gdcm.Tag(0x32,0x1033) ) ano.Empty( gdcm.Tag(0x40,0x241) ) ano.Empty( gdcm.Tag(0x40,0x254) ) ano.Empty( gdcm.Tag(0x40,0x253) ) ano.Empty( gdcm.Tag(0x40,0x1001) ) ano.Empty( gdcm.Tag(0x8,0x80) ) ano.Empty( gdcm.Tag(0x8,0x50) ) ano.Empty( gdcm.Tag(0x8,0x1030) ) ano.Empty( gdcm.Tag(0x8,0x103e) ) ano.Empty( gdcm.Tag(0x18,0x1030) ) ano.Empty( gdcm.Tag(0x38,0x300) ) g = gdcm.UIDGenerator() ano.Replace( gdcm.Tag(0x0008,0x0018), g.Generate() ) ano.Replace( gdcm.Tag(0x0020,0x00d), g.Generate() ) ano.Replace( gdcm.Tag(0x0020,0x00e), g.Generate() ) ano.Replace( gdcm.Tag(0x0020,0x052), g.Generate() ) #ano.Replace( gdcm.Tag(0x0008,0x0016), "1.2.840.10008.5.1.4.1.1.7.2" ) """ ano.Remove( gdcm.Tag(0x0018,0x0020) ) # ScanningSequence ano.Remove( gdcm.Tag(0x0018,0x0021) ) # SequenceVariant ano.Remove( gdcm.Tag(0x0018,0x0022) ) # ScanOptions ano.Remove( gdcm.Tag(0x0018,0x0023) ) # MRAcquisitionType ano.Remove( gdcm.Tag(0x0018,0x0050) ) # SliceThickness ano.Remove( gdcm.Tag(0x0018,0x0080) ) # RepetitionTime ano.Remove( gdcm.Tag(0x0018,0x0081) ) # EchoTime ano.Remove( gdcm.Tag(0x0018,0x0088) ) # SpacingBetweenSlices ano.Remove( gdcm.Tag(0x0018,0x0091) ) # EchoTrainLength ano.Remove( gdcm.Tag(0x0018,0x1164) ) # ImagerPixelSpacing ano.Remove( gdcm.Tag(0x0020,0x0032) ) # Image Position (Patient) ano.Remove( gdcm.Tag(0x0020,0x0037) ) # Image Orientation (Patient) ano.Remove( gdcm.Tag(0x0020,0x0052) ) # Frame of Reference UID ano.Remove( gdcm.Tag(0x0020,0x1040) ) # Position Reference Indicator ano.Replace( gdcm.Tag(0x0028,0x0301), "NO" ) # Burned In Annotation ano.Empty( gdcm.Tag(0x0020,0x0020) ) ano.Remove( gdcm.Tag(0x7fe0,0x0000) ) #ano.Empty( gdcm.Tag(0x0028,0x0009) ) # Frame Increment Pointer #ano.Empty( gdcm.Tag(0x0028,0x1052) ) # #ano.Empty( gdcm.Tag(0x0028,0x1053) ) # #ano.Replace( gdcm.Tag(0x0028,0x1054), "US" ) # ano.Replace( gdcm.Tag(0x2050, 0x0020), "IDENTITY") """ w = gdcm.Writer() w.SetFile( ano.GetFile() ) w.SetFileName( file2 ) if not w.Write(): sys.exit(1) GDCM-3.0.10/Examples/Python/ManipulateSequence.py000066400000000000000000000043541412732066400215210ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Usage: python ManipulateSequence.py input.dcm output.dcm This was tested using: python ManipulateSequence.py gdcmData/D_CLUNIE_CT1_J2KI.dcm myoutput.dcm This is a dummy example on how to modify a value set in a nested-nested dataset WARNING: Do not use as-is in production, this is just an example This example works in an undefined length Item only (you need to explicitly recompute the length otherwise) """ import sys import gdcm if __name__ == "__main__": file1 = sys.argv[1] file2 = sys.argv[2] r = gdcm.Reader() r.SetFileName( file1 ) if not r.Read(): sys.exit(1) f = r.GetFile() ds = f.GetDataSet() tsis = gdcm.Tag(0x0008,0x2112) # SourceImageSequence if ds.FindDataElement( tsis ): sis = ds.GetDataElement( tsis ) #sqsis = sis.GetSequenceOfItems() # GetValueAsSQ handle more cases sqsis = sis.GetValueAsSQ() if sqsis.GetNumberOfItems(): item1 = sqsis.GetItem(1) nestedds = item1.GetNestedDataSet() tprcs = gdcm.Tag(0x0040,0xa170) # PurposeOfReferenceCodeSequence if nestedds.FindDataElement( tprcs ): prcs = nestedds.GetDataElement( tprcs ) sqprcs = prcs.GetSequenceOfItems() if sqprcs.GetNumberOfItems(): item2 = sqprcs.GetItem(1) nestedds2 = item2.GetNestedDataSet() # (0008,0104) LO [Uncompressed predecessor] # 24, 1 CodeMeaning tcm = gdcm.Tag(0x0008,0x0104) if nestedds2.FindDataElement( tcm ): cm = nestedds2.GetDataElement( tcm ) mystr = "GDCM was here" cm.SetByteStringValue( mystr ) w = gdcm.Writer() w.SetFile( f ) w.SetFileName( file2 ) if not w.Write(): sys.exit(1) GDCM-3.0.10/Examples/Python/MergeFile.py000066400000000000000000000032631412732066400175660ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Usage: python MergeFile.py input1.dcm input2.dcm It will produce a 'merge.dcm' output file, which contains all meta information from input1.dcm and copy the Stored Pixel values from input2.dcm This script even works when input2.dcm is a Secondary Capture and does not contains information such as IOP and IPP... """ import sys import gdcm if __name__ == "__main__": file1 = sys.argv[1] file2 = sys.argv[2] r1 = gdcm.ImageReader() r1.SetFileName( file1 ) if not r1.Read(): sys.exit(1) r2 = gdcm.ImageReader() r2.SetFileName( file2 ) if not r2.Read(): sys.exit(1) # Image from r2 could be Secondary Capture and thus would not contains neither IPP nor IOP # Instead always prefer to only copy the Raw Data Element. # Warning ! Image need to be identical ! Only the value of Stored Pixel can be different. r1.GetImage().SetDataElement( r2.GetImage().GetDataElement() ) w = gdcm.ImageWriter() w.SetFile( r1.GetFile() ) #w.SetImage( r2.GetImage() ) # See comment above w.SetImage( r1.GetImage() ) w.SetFileName( "merge.dcm" ) if not w.Write(): sys.exit(1) sys.exit(0) GDCM-3.0.10/Examples/Python/NewSequence.py000066400000000000000000000031711412732066400201470ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Usage: python NewSequence.py input.dcm output.dcm Thanks to Robert Irie for code """ import sys import gdcm if __name__ == "__main__": file1 = sys.argv[1] file2 = sys.argv[2] r = gdcm.Reader() r.SetFileName( file1 ) if not r.Read(): sys.exit(1) f = r.GetFile() ds = f.GetDataSet() #tsis = gdcm.Tag(0x0008,0x2112) # SourceImageSequence # Create a dataelement de = gdcm.DataElement(gdcm.Tag(0x0010, 0x2180)) de.SetByteStringValue("Occupation") de.SetVR(gdcm.VR(gdcm.VR.SH)) # Create an item it=gdcm.Item() it.SetVLToUndefined() # Needed to not popup error message #it.InsertDataElement(de) nds=it.GetNestedDataSet() nds.Insert(de) # Create a Sequence sq=gdcm.SequenceOfItems().New() sq.SetLengthToUndefined() sq.AddItem(it) # Insert sequence into data set des=gdcm.DataElement(gdcm.Tag(0x0400,0x0550)) des.SetVR(gdcm.VR(gdcm.VR.SQ)) des.SetValue(sq.__ref__()) des.SetVLToUndefined() ds.Insert(des) w = gdcm.Writer() w.SetFile( f ) w.SetFileName( file2 ) if not w.Write(): sys.exit(1) GDCM-3.0.10/Examples/Python/PhilipsPrivateRescaleInterceptSlope.py000066400000000000000000000034611412732066400250520ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Usage: python """ import gdcm import sys filename = sys.argv[1] tmpfile = "/tmp/philips_rescaled.dcm" # Need to access some private tags, read the file : reader = gdcm.Reader() reader.SetFileName( filename ) if not reader.Read(): sys.exit(1) ds = reader.GetFile().GetDataSet() #print ds # (2005,1409) DS 4 0.0 # (2005,140a) DS 16 1.52283272283272 # (2005,0014) LO 26 Philips MR Imaging DD 005 tag1 = gdcm.PrivateTag(0x2005,0x09,"Philips MR Imaging DD 005") tag2 = gdcm.PrivateTag(0x2005,0x0a,"Philips MR Imaging DD 005") print tag1 print tag2 # make sure to do a copy, we want the private tag to remain # otherwise gdcm gives us a reference el1 = gdcm.DataElement( ds.GetDataElement( tag1 ) ) print el1 el2 = gdcm.DataElement( ds.GetDataElement( tag2 ) ) print el2 # (0028,1052) DS [-1000] # 6, 1 RescaleIntercept # (0028,1053) DS [1] # 2, 1 RescaleSlope el1.SetTag( gdcm.Tag(0x0028,0x1052) ) el2.SetTag( gdcm.Tag(0x0028,0x1053) ) ds.Insert( el1 ) ds.Insert( el2 ) w = gdcm.Writer() w.SetCheckFileMetaInformation( False ) w.SetFileName( tmpfile ) w.SetFile( reader.GetFile() ) if not w.Write(): sys.exit(1) print "success" GDCM-3.0.10/Examples/Python/PlaySound.py000066400000000000000000000044301412732066400176420ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Usage: python PlaySound.py input.dcm """ import gdcm import sys #filename = "/home/mmalaterre/Creatis/gdcmDataExtra/gdcmNonImageData/audio_from_rafael_sanguinetti.dcm" filename = sys.argv[1] print filename r = gdcm.Reader() r.SetFileName( filename ) if not r.Read(): sys.exit(1) ds = r.GetFile().GetDataSet() waveformtag = gdcm.Tag(0x5400,0x0100) waveformsq = ds.GetDataElement( waveformtag ) #print waveformsq #print dir(waveformsq) items = waveformsq.GetSequenceOfItems() if not items.GetNumberOfItems(): sys.exit(1) item = items.GetItem(1) #print item waveformds = item.GetNestedDataSet() #print waveformds waveformdatatag = gdcm.Tag(0x5400,0x1010) waveformdata = waveformds.GetDataElement( waveformdatatag ) #print waveformdata.GetPointer() bv = waveformdata.GetByteValue() print dir(bv) #print bv.GetPointer() print bv.GetLength() l = 116838 file='test.wav' myfile = open(file, "wb") s = bv.GetPointer() for i in range(0, l): myfile.write(s[i]) myfile.close() # http://mail.python.org/pipermail/python-list/2004-October/288905.html if sys.platform.startswith('win'): from winsound import PlaySound, SND_FILENAME, SND_ASYNC PlaySound(file, SND_FILENAME|SND_ASYNC) elif sys.platform.find('linux')>-1: from wave import open as waveOpen from ossaudiodev import open as ossOpen s = waveOpen(file,'rb') (nc,sw,fr,nf,comptype, compname) = s.getparams( ) dsp = ossOpen('/dev/dsp','w') try: from ossaudiodev import AFMT_S16_NE except ImportError: if byteorder == "little": AFMT_S16_NE = ossaudiodev.AFMT_S16_LE else: AFMT_S16_NE = ossaudiodev.AFMT_S16_BE dsp.setparameters(AFMT_S16_NE, nc, fr) data = s.readframes(nf) s.close() dsp.write(data) dsp.close() GDCM-3.0.10/Examples/Python/PrivateDict.py000066400000000000000000000022221412732066400201370ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ """ import gdcm import sys,os if __name__ == "__main__": #gdcm.Trace.DebugOn() globInst = gdcm.Global.GetInstance() # Try to load Part3.xml file # This fils is too big for being accessible directly at runtime. globInst.LoadResourcesFiles() # Get a private tag from the runtime dicts. LoadResourcesFiles could # have failed but this has no impact on the private dict d = globInst.GetDicts() print d.GetDictEntry( gdcm.Tag(0x0029,0x0010) ,"SIEMENS CSA HEADER" ) pd = d.GetPrivateDict() print pd.GetDictEntry( gdcm.PrivateTag(0x0029,0x0010,"SIEMENS CSA HEADER") ) GDCM-3.0.10/Examples/Python/ReWriteSCAsMR.py000066400000000000000000000061171412732066400202620ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ GDCM 1.x would write out MR Image Storage as Secondary Capture Object while still setting Rescale Slope/Intercept and saving the Pixel Spacing in (0028,0030) """ import gdcm import sys,os def CheckSecondaryCaptureObjectIsMRImageStorage(r): ds = r.GetFile().GetDataSet() # Check Source Image Sequence if ds.FindDataElement( gdcm.Tag(0x0008,0x2112) ): sis = ds.GetDataElement( gdcm.Tag(0x0008,0x2112) ) sqsis = sis.GetSequenceOfItems() if sqsis.GetNumberOfItems(): item1 = sqsis.GetItem(1) nestedds = item1.GetNestedDataSet() if nestedds.FindDataElement( gdcm.Tag(0x0008,0x1150) ): ReferencedSOPClassUID = nestedds.GetDataElement( gdcm.Tag(0x0008,0x1150) ) raw = ReferencedSOPClassUID.GetByteValue().GetPointer() uids = gdcm.UIDs() # what is the actual object we are looking at ? ms = gdcm.MediaStorage() ms.SetFromDataSet(ds) msuid = ms.GetString() uids.SetFromUID( msuid ) msuidname = uids.GetName() # real Media Storage Name uids.SetFromUID( raw ) sqmsuidname = uids.GetName() # Source Image Sequence Media Storage Name # If object is SC and Source derivation is MRImageStorage then we can assume 'Pixel Spacing' is correct if( sqmsuidname == 'MR Image Storage' and msuidname == 'Secondary Capture Image Storage' ): return True # in all other case simply return the currentspacing: return False if __name__ == "__main__": r = gdcm.ImageReader() filename = sys.argv[1] r.SetFileName( filename ) if not r.Read(): sys.exit(1) f = r.GetFile() if( CheckSecondaryCaptureObjectIsMRImageStorage(r) ): # Special handling of the spacing: # GDCM 1.2.0 would not rewrite correcly DICOM Object and would always set them as 'Secondary Capture Image Storage' # while we would rather have 'MR Image Storage' gdcm.ImageHelper.SetForcePixelSpacing( True ) mrspacing = gdcm.ImageHelper.GetSpacingValue( r.GetFile() ) # TODO: I cannot do simply the following: #image.SetSpacing( mrspacing ) image.SetSpacing(0, mrspacing[0] ) image.SetSpacing(1, mrspacing[1] ) image.SetSpacing(2, mrspacing[2] ) gdcm.ImageHelper.SetForceRescaleInterceptSlope( True ) ris = gdcm.ImageHelper.GetRescaleInterceptSlopeValue( r.GetFile() ) image.SetIntercept( ris[0] ) image.SetSlope( ris[1] ) outfilename = sys.argv[2] w = gdcm.ImageWriter() w.SetFileName( outfilename ) w.SetFile( r.GetFile() ) w.SetImage( image ) if not w.Write(): sys.exit(1) sys.exit(0) GDCM-3.0.10/Examples/Python/ReadAndDumpDICOMDIR.py000066400000000000000000000176611412732066400211750ustar00rootroot00000000000000################################################################################ # # 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. # # File: ReadAndDumpDICOMDIR.py # # Author: Lukas Batteau (lbatteau gmail) # # This example shows how to read and dump a DICOMDIR File. # Based on Tom Marynowski's (lordglub gmail) example. # # Usage: # python ReadAndDumpDICOMDIR.py [DICOMDIR file] ############################################################################ import sys import gdcm if __name__ == "__main__": # Check arguments if (len(sys.argv) < 2): # No filename passed print "No input filename found" quit() filename = sys.argv[1] # Read file reader = gdcm.Reader() reader.SetFileName(filename) if (not reader.Read()): print "Unable to read %s" % (filename) quit() file = reader.GetFile() # Retrieve header information fileMetaInformation = file.GetHeader() print fileMetaInformation # Retrieve data set dataSet = file.GetDataSet() #print dataSet # Check media storage mediaStorage = gdcm.MediaStorage() mediaStorage.SetFromFile(file) if (gdcm.MediaStorage.GetMSType(str(mediaStorage)) != gdcm.MediaStorage.MediaStorageDirectoryStorage): # File is not a DICOMDIR print "This file is not a DICOMDIR (Media storage type: %s)" % (str(mediaStorage)) quit() # Check Media Storage SOP Class if (fileMetaInformation.FindDataElement(gdcm.Tag(0x0002, 0x0002))): sopClassUid = str(fileMetaInformation.GetDataElement(gdcm.Tag(0x0002, 0x0002)).GetValue()) # Check SOP UID if (sopClassUid != "1.2.840.10008.1.3.10"): # File is not a DICOMDIR print "This file is not a DICOMDIR" else: # Not present print "Media Storage SOP Class not present" quit() # Iterate through the DICOMDIR data set iterator = dataSet.GetDES().begin() while (not iterator.equal(dataSet.GetDES().end())): dataElement = iterator.next() # Check the element tag if (dataElement.GetTag() == gdcm.Tag(0x004, 0x1220)): # The 'Directory Record Sequence' element sequence = dataElement.GetValueAsSQ() # Loop through the sequence items itemNr = 1 while (itemNr < sequence.GetNumberOfItems()): item = sequence.GetItem(itemNr) # Check the element tag if (item.FindDataElement(gdcm.Tag(0x0004, 0x1430))): # The 'Directory Record Type' element value = str(item.GetDataElement(gdcm.Tag(0x0004, 0x1430)).GetValue()) # PATIENT while (value.strip() == "PATIENT"): print value.strip() # Print patient name if (item.FindDataElement(gdcm.Tag(0x0010, 0x0010))): value = str(item.GetDataElement(gdcm.Tag(0x0010, 0x0010)).GetValue()) print value # Print patient ID if (item.FindDataElement(gdcm.Tag(0x0010, 0x0020))): value = str(item.GetDataElement(gdcm.Tag(0x0010, 0x0020)).GetValue()) print value # Next itemNr = itemNr + 1 item = sequence.GetItem(itemNr) if (item.FindDataElement(gdcm.Tag(0x0004, 0x1430))): value = str(item.GetDataElement(gdcm.Tag(0x0004, 0x1430)).GetValue()) # STUDY while (value.strip() == "STUDY"): print value.strip() # Print study UID if (item.FindDataElement(gdcm.Tag(0x0020, 0x000d))): value = str(item.GetDataElement(gdcm.Tag(0x0020, 0x000d)).GetValue()) print value # Print study date if (item.FindDataElement(gdcm.Tag(0x0008, 0x0020))): value = str(item.GetDataElement(gdcm.Tag(0x0008, 0x0020)).GetValue()) print value # Print study description if (item.FindDataElement(gdcm.Tag(0x0008, 0x1030))): value = str(item.GetDataElement(gdcm.Tag(0x0008, 0x1030)).GetValue()) print value # Next itemNr = itemNr + 1 item = sequence.GetItem(itemNr) if (item.FindDataElement(gdcm.Tag(0x0004, 0x1430))): value = str(item.GetDataElement(gdcm.Tag(0x0004, 0x1430)).GetValue()) # SERIES while (value.strip() == "SERIES"): print value.strip() # Print series UID if (item.FindDataElement(gdcm.Tag(0x0020, 0x000e))): value = str(item.GetDataElement(gdcm.Tag(0x0020, 0x000e)).GetValue()) print value # Print series modality if (item.FindDataElement(gdcm.Tag(0x0008, 0x0060))): value = str(item.GetDataElement(gdcm.Tag(0x0008, 0x0060)).GetValue()) print "Modality" print value # Print series description if (item.FindDataElement(gdcm.Tag(0x0008, 0x103e))): value = str(item.GetDataElement(gdcm.Tag(0x0008, 0x103e)).GetValue()) print "Description" print value # Next itemNr = itemNr + 1 item = sequence.GetItem(itemNr) if (item.FindDataElement(gdcm.Tag(0x0004, 0x1430))): value = str(item.GetDataElement(gdcm.Tag(0x0004, 0x1430)).GetValue()) # IMAGE while (value.strip() == "IMAGE"): print value.strip() # Print image UID if (item.FindDataElement(gdcm.Tag(0x0004, 0x1511))): value = str(item.GetDataElement(gdcm.Tag(0x0004, 0x1511)).GetValue()) print value # Next if (itemNr < sequence.GetNumberOfItems()): itemNr = itemNr + 1 else: break item = sequence.GetItem(itemNr) if (item.FindDataElement(gdcm.Tag(0x0004, 0x1430))): value = str(item.GetDataElement(gdcm.Tag(0x0004, 0x1430)).GetValue()) # Next itemNr = itemNr + 1 GDCM-3.0.10/Examples/Python/RemovePrivateTags.py000066400000000000000000000024621412732066400213360ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Usage: python RemovePrivateTags.py input.dcm output.dcm """ import sys import gdcm if __name__ == "__main__": file1 = sys.argv[1] file2 = sys.argv[2] # Instanciate the reader. r = gdcm.Reader() r.SetFileName( file1 ) if not r.Read(): sys.exit(1) # Remove private tags ano = gdcm.Anonymizer() ano.SetFile( r.GetFile() ) if not ano.RemovePrivateTags(): sys.exit(1) # Write DICOM file w = gdcm.Writer() w.SetFile( ano.GetFile() ) #w.CheckFileMetaInformationOff() # Do not attempt to check meta header w.SetFileName( file2 ) if not w.Write(): sys.exit(1) # It is usually a good idea to exit the script with an error, as gdcm does not remove partial (incorrect) DICOM file # (application level) GDCM-3.0.10/Examples/Python/ScanDirectory.py000066400000000000000000000036311412732066400204770ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import sys,os class ProgressWatcher(gdcm.SimpleSubjectWatcher): def ShowProgress(self, sender, event): pe = gdcm.ProgressEvent.Cast(event) print pe.GetProgress() def EndFilter(self): print "Yay ! I am done" if __name__ == "__main__": directory = sys.argv[1] # Define the set of tags we are interested in t1 = gdcm.Tag(0x8,0x8); t2 = gdcm.Tag(0x10,0x10); # Iterate over directory d = gdcm.Directory(); nfiles = d.Load( directory ); if(nfiles == 0): sys.exit(1); # System.Console.WriteLine( "Files:\n" + d.toString() ); filenames = d.GetFilenames() # Get rid of any Warning while parsing the DICOM files gdcm.Trace.WarningOff() # instanciate Scanner: sp = gdcm.Scanner.New(); s = sp.__ref__() w = ProgressWatcher(s, 'Watcher') s.AddTag( t1 ); s.AddTag( t2 ); b = s.Scan( filenames ); if(not b): sys.exit(1); print "success" ; #print s pttv = gdcm.PythonTagToValue( s.GetMapping( filenames[1] ) ) pttv.Start() # iterate until the end: while( not pttv.IsAtEnd() ): # get current value for tag and associated value: # if tag was not found, then it was simply not added to the internal std::map # Warning value can be None tag = pttv.GetCurrentTag() value = pttv.GetCurrentValue() print tag,"->",value # increment iterator pttv.Next() sys.exit(0) GDCM-3.0.10/Examples/Python/SortImage.py000066400000000000000000000021201412732066400176100ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Usage: python SortImage.py dirname """ import gdcm import sys def PrintProgress(object, event): assert event == "ProgressEvent" print "Progress:", object.GetProgress() def MySort(ds1, ds2): # compare ds1 return False if __name__ == "__main__": dirname = sys.argv[1] d = gdcm.Directory() d.Load( dirname ) print d sorter = gdcm.Sorter() sorter.SetSortFunction( MySort ) #sorter.AddObserver( "ProgressEvent", PrintProgress ) sorter.Sort( d.GetFilenames() ) print "Sorter:" print sorter GDCM-3.0.10/Examples/Python/WriteBuffer.py000066400000000000000000000072561412732066400201610ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Usage: http://chuckhahm.com/Ischem/Zurich/XX_0134 (2005,1132) SQ (Sequence with undefined length #=8) # u/l, 1 Unknown Tag & Data (fffe,e000) na (Item with undefined length #=9) # u/l, 1 Item (2005,0011) LO [Philips MR Imaging DD 002] # 26, 1 PrivateCreator (2005,1137) PN [PDF_CONTROL_GEN_PARS] # 20, 1 Unknown Tag & Data (2005,1138) PN (no value available) # 0, 0 Unknown Tag & Data (2005,1139) PN [IEEE_PDF] # 8, 1 Unknown Tag & Data (2005,1140) PN (no value available) # 0, 0 Unknown Tag & Data (2005,1141) PN (no value available) # 0, 0 Unknown Tag & Data (2005,1143) SL 3103 # 4, 1 Unknown Tag & Data (2005,1144) OW 0566\0000\013b\0000\0a4a\0000\000e\0000\0a7a\0000\0195\0000\0008... # 3104, 1 Unknown Tag & Data (2005,1147) CS [Y] # 2, 1 Unknown Tag & Data (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem (fffe,e000) na (Item with undefined length #=9) # u/l, 1 Item (2005,0011) LO [Philips MR Imaging DD 002] # 26, 1 PrivateCreator (2005,1137) PN [PDF_CONTROL_PREP_PARS] # 22, 1 Unknown Tag & Data (2005,1138) PN (no value available) # 0, 0 Unknown Tag & Data (2005,1139) PN [IEEE_PDF] # 8, 1 Unknown Tag & Data (2005,1140) PN (no value available) # 0, 0 Unknown Tag & Data (2005,1141) PN (no value available) # 0, 0 Unknown Tag & Data (2005,1143) SL 7934 # 4, 1 Unknown Tag & Data (2005,1144) OW 19b6\0000\005f\0000\1b2a\0000\00f3\0000\1eee\0000\0000\0000\0008... # 7934, 1 Unknown Tag & Data (2005,1147) CS [Y] # 2, 1 Unknown Tag & Data (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem ... """ import sys import gdcm if __name__ == "__main__": file1 = sys.argv[1] file2 = sys.argv[2] r = gdcm.Reader() r.SetFileName( file1 ) if not r.Read(): sys.exit(1) fg = gdcm.FilenameGenerator() f = r.GetFile() ds = f.GetDataSet() tsis = gdcm.Tag(0x2005,0x1132) # if ds.FindDataElement( tsis ): sis = ds.GetDataElement( tsis ) #sqsis = sis.GetSequenceOfItems() # GetValueAsSQ handle more cases sqsis = sis.GetValueAsSQ() if sqsis.GetNumberOfItems(): nitems = sqsis.GetNumberOfItems(); fg.SetNumberOfFilenames( nitems ) fg.SetPrefix( file2 ) if not fg.Generate(): print "problem" sys.exit(1) for i in range(0,nitems): item1 = sqsis.GetItem(i+1) # Item start at 1 nestedds = item1.GetNestedDataSet() tprcs = gdcm.Tag(0x2005,0x1144) # if nestedds.FindDataElement( tprcs ): prcs = nestedds.GetDataElement( tprcs ) bv = prcs.GetByteValue() print bv f = open( fg.GetFilename(i) , "w" ) f.write( bv.WriteBuffer() ) GDCM-3.0.10/INSTALL.txt000066400000000000000000000036551412732066400141720ustar00rootroot00000000000000See the wiki page at: http://gdcm.sourceforge.net/wiki/index.php/Getting_Started If you are reading this file, it certainly means you do not know how to build GDCM. See: http://gdcm.sourceforge.net/wiki/index.php/Configuring_and_Building On UNIX (with cmake) this is simply a matter of doing: * git clone --branch release git://git.code.sf.net/p/gdcm/gdcm * mkdir gdcmbin * cd gdcmbin * ccmake ../gdcm [select your configuration] * Press 'c' (configure), Press 'g' (generate) * make The following step is not required, as gdcm will work from a build tree too: * make install If you want to live on the edge, you should try the latest trunk instead: * git clone git://git.code.sf.net/p/gdcm/gdcm If you want to retrieve the gdcmData as part of your git clone, use instead: * git clone --recursive git://git.code.sf.net/p/gdcm/gdcm Major options explained: * GDCM_BUILD_SHARED_LIBS: Turn it on if you want shared libs (instead of static libs), greatly reduce executable size, allowing code reuse. * GDCM_WRAP_PYTHON: turn it on if you want to be able to access the GDCM API via python (required python dev files) * GDCM_WRAP_CSHARP: turn it on if you want to be able to access the GDCM API via C# (required mono or .NET environment) * GDCM_WRAP_JAVA: turn it on if you want to be able to access the GDCM API via java (required java sdk to compile) * GDCM_WRAP_PHP: turn it on if you want to be able to access the GDCM API via php (experimental) * GDCM_USE_VTK: turn if on if you want to be able to load DICOM file in VTK context (requires VTK) * GDCM_BUILD_APPLICATIONS: turn it on if you want the build gdcm applications (gdcmdump, gdcmconv, gdcminfo ...) * GDCM_BUILD_TESTING: Turn it on if you want to be able to exectute GDCM testing suite * GDCM_DOCUMENTATION: turn it on if you want to generate the developer documentation (require doxygen) * GDCM_BUILD_EXAMPLES: turn it on if you want to build simple examples that demonstrates GDCM usage. GDCM-3.0.10/PACKAGER000066400000000000000000000036421412732066400134170ustar00rootroot00000000000000Info for packagers: At a minimum you should consider the following cmake options: CMAKE_SKIP_RPATH:BOOL=YES CMAKE_INSTALL_PREFIX:PATH=/usr To build the cmd line applications: GDCM_BUILD_APPLICATIONS:BOOL=ON To build shared libs: GDCM_BUILD_SHARED_LIBS:BOOL=ON To build the documentation (need doxygen >= 1.6.1) GDCM_DOCUMENTATION:BOOL=ON You should really consider: GDCM_BUILD_TESTING:BOOL=OFF Otherwise it build extra code only needed to run the unit test of gdcm... unless you have some specific compiler optimization technique you should use the cmake default one: CMAKE_BUILD_TYPE:STRING=Release By default this will build pdf doc if you have all the required package, if you do not want the pdf: GDCM_PDF_DOCUMENTATION:BOOL=ON Wrapping: GDCM support the following wrapped language GDCM_WRAP_PYTHON:BOOL=ON GDCM_WRAP_CSHARP:BOOL=ON GDCM_WRAP_JAVA:BOOL=ON There is an ongoing effort to make PHP another supported language (very experimental ATM) GDCM_WRAP_PHP:BOOL=ON For VTK user: GDCM_USE_VTK:BOOL=ON System libs: - By default gdcm ships with system libs for ease of compilation on win32 system. So for most *nix system you may want: GDCM_USE_SYSTEM_EXPAT:BOOL=ON GDCM_USE_SYSTEM_ZLIB:BOOL=ON GDCM_USE_SYSTEM_UUID:BOOL=ON GDCM_USE_SYSTEM_OPENJPEG:BOOL=ON OpenSSL option is slightly different as not 'convenient' openssl is shipped within GDCM, so the only way to access the openssl functionalities is to have openssl installed in the target system. GDCM_USE_SYSTEM_OPENSSL:BOOL=ON Examples: GDCM comes with some examples for user, but setting the following: GDCM_BUILD_EXAMPLES:BOOL=ON will not do anything since there is no install rule for examples... The library attempts to provide a clean API, therefore it is highly suggested that you compile GDCM using: $ CFLAGS=-fvisibility=hidden CXXFLAGS=-fvisibility=hidden cmake /path/to/gdcm/sources This make sure that on UNIX, the API is actually identical at what is found on Windows. GDCM-3.0.10/README.Copyright.txt000066400000000000000000000004011412732066400157520ustar00rootroot00000000000000December 28, 2008 Historical note: Starting with gdcm 2.0.11, GDCM, Grassroots DICOM is distributed under the new simplified BSD license, approved by the Open Source Initiative (OSI) * http://www.opensource.org/licenses/bsd-license.php See Copyright.txt GDCM-3.0.10/README.md000066400000000000000000000035641412732066400136010ustar00rootroot00000000000000This is the source code of GDCM. It is available from sf.net website. Official GIT repository is at: https://sourceforge.net/p/gdcm/gdcm/ For a general introduction/features/limitations/requirement please refer to http://gdcm.sourceforge.net/ Just a quick note on the build process of GDCM. GDCM build process make use of the cmake software(*). This allow us: 1. To get rid of the autoconf/autotools insanity 2. Transparently generate Unix Makefiles, NMake Makefiles, VS8/9/10 Solution, Xcode projects, etc. 3. Automatic nightly testing, one of the most important things for a robust library/software development process. GDCM development is develop based on the XP definition, and to preserve backward compatibility make sure that code is working from one release to another: each night we configure, we build and we test GDCM. The result are then sent to the dashboard located at: https://open.cdash.org/index.php?project=GDCM A continuous dashboard also makes sure that any commit did not introduce any error on another platform, a warning or a broken test... Therefore you should be able to use GDCM from the bleeding edge without knowing too much about what is going on. All you need to do is have a look at the GDCM dashboard, and if your platform is 'green' then you can update your git copy and compile safely knowing that there is very little chance that something won't work. Cheers ! (*) http://www.cmake.org for more information For more help you can go online in the GDCM Wiki: * http://gdcm.sourceforge.net/ In Particular: * http://gdcm.sourceforge.net/wiki/index.php/GDCM_Release_2.0 * http://gdcm.sourceforge.net/wiki/index.php/FAQ And a page describing each tool can be found at: * http://gdcm.sourceforge.net/wiki/index.php/End_User_Applications Eg: * http://gdcm.sourceforge.net/wiki/index.php/Gdcminfo Need VTK: * http://gdcm.sourceforge.net/wiki/index.php/Gdcmviewer GDCM-3.0.10/Source/000077500000000000000000000000001412732066400135525ustar00rootroot00000000000000GDCM-3.0.10/Source/Attribute/000077500000000000000000000000001412732066400155155ustar00rootroot00000000000000GDCM-3.0.10/Source/Attribute/CMakeLists.txt000066400000000000000000000000001412732066400202430ustar00rootroot00000000000000GDCM-3.0.10/Source/Attribute/README.txt000066400000000000000000000000111412732066400172030ustar00rootroot00000000000000Part 3.1 GDCM-3.0.10/Source/CMakeLists.txt000066400000000000000000000004451412732066400163150ustar00rootroot00000000000000# ... add_subdirectory( Common ) add_subdirectory( Attribute ) add_subdirectory( DataDictionary ) add_subdirectory( DataStructureAndEncodingDefinition ) add_subdirectory( InformationObjectDefinition ) add_subdirectory( MediaStorageAndFileFormat ) add_subdirectory( MessageExchangeDefinition ) GDCM-3.0.10/Source/Common/000077500000000000000000000000001412732066400150025ustar00rootroot00000000000000GDCM-3.0.10/Source/Common/CMakeLists.txt000066400000000000000000000145271412732066400175530ustar00rootroot00000000000000#----------------------------------------------------------------------------- # Rebuild gdcm whenever a file starting with gdcm* is modified include_regular_expression("^gdcm.*$") # configure the .h file option(GDCM_ALWAYS_TRACE_MACRO "When set to ON, gdcm::Trace macros will dumps message (override NDEBUG settings)" OFF) option(GDCM_SUPPORT_BROKEN_IMPLEMENTATION "Handle broken DICOM" ON) mark_as_advanced( GDCM_ALWAYS_TRACE_MACRO GDCM_SUPPORT_BROKEN_IMPLEMENTATION GDCM_AUTOLOAD_GDCMJNI ) #if(WIN32) # if (BUILD_SHARED_LIBS) # add_definitions(-DPOLARSSL_DLL) # endif () #endif() CHECK_INCLUDE_FILE_CONCAT("sys/time.h" GDCM_HAVE_SYS_TIME_H) CHECK_INCLUDE_FILE_CONCAT("winsock.h" GDCM_HAVE_WINSOCK_H) CHECK_INCLUDE_FILE_CONCAT("byteswap.h" GDCM_HAVE_BYTESWAP_FILE_H) # see bug #324 if(GDCM_HAVE_BYTESWAP_FILE_H) include(CheckCXXSourceCompiles) CHECK_CXX_SOURCE_COMPILES( "\#include \nint main() { return bswap_32( 42 ); }" GDCM_HAVE_BYTESWAP_H) endif() CHECK_INCLUDE_FILE("rpc.h" GDCM_HAVE_RPC_H) CHECK_INCLUDE_FILE("langinfo.h" GDCM_HAVE_LANGINFO_H) include(CheckFunctionExists) # See http://public.kitware.com/Bug/view.php?id=8246 include(CheckSymbolExists) CHECK_SYMBOL_EXISTS(nl_langinfo "langinfo.h" GDCM_HAVE_NL_LANGINFO) #C99 #CHECK_FUNCTION_EXISTS(strcasecmp GDCM_HAVE_STRCASECMP) CHECK_SYMBOL_EXISTS(strcasecmp "strings.h" GDCM_HAVE_STRCASECMP) #CHECK_FUNCTION_EXISTS(strncasecmp GDCM_HAVE_STRNCASECMP) CHECK_SYMBOL_EXISTS(strncasecmp "strings.h" GDCM_HAVE_STRNCASECMP) #CHECK_SYMBOL_EXISTS(strptime "time.h" GDCM_HAVE_STRPTIME) CHECK_FUNCTION_EXISTS(strptime GDCM_HAVE_STRPTIME) #M$ extension: CHECK_FUNCTION_EXISTS(_stricmp GDCM_HAVE__STRICMP) CHECK_FUNCTION_EXISTS(_strnicmp GDCM_HAVE__STRNICMP) unset(CMAKE_REQUIRED_INCLUDES) unset(CMAKE_REQUIRED_LIBRARIES) #include(CheckSymbolExists) CHECK_FUNCTION_EXISTS(gettimeofday GDCM_HAVE_GETTIMEOFDAY) # json-c API changed: if(GDCM_USE_SYSTEM_JSON) set(CMAKE_REQUIRED_INCLUDES ${JSON_INCLUDE_DIRS}) set(CMAKE_REQUIRED_LIBRARIES ${JSON_LIBRARIES}) CHECK_SYMBOL_EXISTS(json_object_object_get_ex "json.h" GDCM_HAVE_JSON_OBJECT_OBJECT_GET_EX) endif() include(CheckCXXSourceCompiles) 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;}" GDCM_HAVE_WCHAR_IFSTREAM) if(GDCM_USE_SYSTEM_OPENSSL) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES} ${CMAKE_DL_LIBS} # FIXME ?? ) CHECK_CXX_SOURCE_COMPILES( # "\#include \nint main() { CMS_add0_recipient_key(0); return 0;}" #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) endif() #----------------------------------------------------------------------------- # Provide compatibility options. option(GDCM_LEGACY_REMOVE "Remove all legacy code completely." OFF) option(GDCM_LEGACY_SILENT "Silence all legacy code messages." OFF) mark_as_advanced(GDCM_LEGACY_REMOVE GDCM_LEGACY_SILENT) configure_file( "${GDCM_SOURCE_DIR}/Source/Common/gdcmConfigure.h.in" "${GDCM_BINARY_DIR}/Source/Common/gdcmConfigure.h" ) # Add the include paths include_directories( "${GDCM_BINARY_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition" "${GDCM_BINARY_DIR}/Testing/Source/Data" "${GDCM_SOURCE_DIR}/Testing/Source/Data" "${GDCM_SOURCE_DIR}/Utilities" ) if(GDCM_BUILD_TESTING) include_directories( "${GDCM_BINARY_DIR}/Utilities/gdcmmd5" ) endif() if(NOT GDCM_USE_SYSTEM_ZLIB) include_directories( "${GDCM_BINARY_DIR}/Utilities/gdcmzlib" ) endif() #if(NOT GDCM_USE_SYSTEM_POLARSSL) #include_directories( # "${GDCM_SOURCE_DIR}/Utilities/gdcmpolarssl/include" #) #endif() set(Common_SRCS gdcmVersion.cxx gdcmRegion.cxx gdcmBoxRegion.cxx gdcmEvent.cxx gdcmDataEvent.cxx gdcmProgressEvent.cxx gdcmFileNameEvent.cxx gdcmCommand.cxx gdcmMD5.cxx gdcmBase64.cxx gdcmSHA1.cxx gdcmDummyValueGenerator.cxx #gdcmCryptographicMessageSyntax.cxx gdcmCryptographicMessageSyntax.cxx gdcmCryptoFactory.cxx gdcmASN1.cxx gdcmObject.cxx gdcmSubject.cxx gdcmDirectory.cxx gdcmTerminal.cxx gdcmString.cxx gdcmFilename.cxx gdcmFilenameGenerator.cxx gdcmSwapCode.cxx gdcmSystem.cxx gdcmTrace.cxx gdcmException.cxx gdcmDeflateStream.cxx gdcmByteSwap.cxx gdcmUnpacker12Bits.cxx ) if(WIN32) set(Common_SRCS ${Common_SRCS} gdcmCAPICryptographicMessageSyntax.cxx gdcmCAPICryptoFactory.cxx ) endif() if(GDCM_USE_SYSTEM_OPENSSL) set(Common_SRCS ${Common_SRCS} gdcmOpenSSLP7CryptoFactory.cxx gdcmOpenSSLP7CryptographicMessageSyntax.cxx ) endif() if(GDCM_USE_SYSTEM_OPENSSL AND GDCM_HAVE_CMS_RECIPIENT_PASSWORD) set(Common_SRCS ${Common_SRCS} gdcmOpenSSLCryptoFactory.cxx gdcmOpenSSLCryptographicMessageSyntax.cxx ) endif() if(GDCM_BUILD_TESTING) set(Common_SRCS ${Common_SRCS} gdcmTesting.cxx ) endif() add_library(gdcmCommon ${Common_SRCS}) target_compile_features(gdcmCommon PUBLIC cxx_nullptr) # Prefer -std=c++11 over -std=gnu++11 set_target_properties(gdcmCommon PROPERTIES CXX_EXTENSIONS OFF) #target_link_libraries(gdcmCommon ${GDCM_ZLIB_LIBRARIES}) # ${GDCM_POLARSSL_LIBRARIES}) if(GDCM_BUILD_TESTING) target_link_libraries(gdcmCommon LINK_PRIVATE gdcmmd5) endif() if(APPLE) if(GDCM_USE_COREFOUNDATION_LIBRARY) target_link_libraries(gdcmCommon LINK_PRIVATE ${COREFOUNDATION_LIBRARY}) endif() endif() if(UNIX) target_link_libraries(gdcmCommon LINK_PRIVATE ${CMAKE_DL_LIBS}) endif() if(WIN32) target_link_libraries(gdcmCommon LINK_PRIVATE ws2_32) target_link_libraries(gdcmCommon LINK_PRIVATE crypt32) endif() if(GDCM_USE_SYSTEM_OPENSSL) include_directories(${OPENSSL_INCLUDE_DIR}) target_link_libraries(gdcmCommon LINK_PRIVATE ${OPENSSL_LIBRARIES}) endif() set_target_properties(gdcmCommon PROPERTIES ${GDCM_LIBRARY_PROPERTIES}) # libs install_library(gdcmCommon) # PDB install_pdb(gdcmCommon) # include files install_includes("*.h" "*.txx") # Install generated files if(NOT GDCM_INSTALL_NO_DEVELOPMENT) install(FILES ${header_files} "${GDCM_BINARY_DIR}/Source/Common/gdcmConfigure.h" DESTINATION ${GDCM_INSTALL_INCLUDE_DIR} COMPONENT Headers ) endif() GDCM-3.0.10/Source/Common/README.txt000066400000000000000000000001221412732066400164730ustar00rootroot00000000000000some sort of utilities. Like byte swapping not really defined in DICOM but useful GDCM-3.0.10/Source/Common/gdcmASN1.cxx000066400000000000000000000056201412732066400170660ustar00rootroot00000000000000/*========================================================================= 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 "gdcmASN1.h" #include "gdcmSystem.h" #include #ifdef GDCM_USE_SYSTEM_OPENSSL #include #include #include #include #include #include #include #endif #include /* */ namespace gdcm { class ASN1Internals { public: }; ASN1::ASN1() { Internals = new ASN1Internals; } ASN1::~ASN1() { delete Internals; } bool ASN1::ParseDumpFile(const char *filename) { if(!filename) return false; std::ifstream is(filename, std::ios::binary); if( !is.good() ) return false; size_t length = System::FileSize(filename); char * str = new char[length]; is.read( str, length ); bool b = ParseDump( str, length ); delete[] str; return b; } bool ASN1::ParseDump(const char *array, size_t length) { #ifdef GDCM_USE_SYSTEM_OPENSSL // check array pointer: // if length == 0, then return ok. This is an empty element. if( !array ) return !length; int indent = 1; // 0 is not visually nice int dump = 0; // -1 => will print hex stuff BIO *out=NULL; out=BIO_new(BIO_s_file()); assert( out ); BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); if (!ASN1_parse_dump(out,(const unsigned char*)array,length,indent,dump) ) { return false; } return true; #else (void)array; (void)length; gdcmDebugMacro( "GDCM_USE_SYSTEM_OPENSSL is OFF" ); return false; #endif } #ifdef GDCM_USE_SYSTEM_OPENSSL static int print_hex(unsigned char *buf, int len) { int i; int n; for(i=0,n=0;i 7){ printf("\n"); n = 0; } printf("0x%02x, ",buf[i]); n++; } printf("\n"); return(0); } #endif int ASN1::TestPBKDF2() { #ifdef GDCM_USE_SYSTEM_OPENSSL const char pass[] = "password"; const char salt[] = "12340000"; int ic = 1; unsigned char buf[1024]; ic = 1; PKCS5_PBKDF2_HMAC_SHA1(pass, (int)strlen(pass), (const unsigned char*)salt, (int)strlen(salt), ic, 32+16, buf); printf("PKCS5_PBKDF2_HMAC_SHA1(\"%s\", \"%s\", %d)=\n", pass, salt, ic); print_hex(buf, 32+16); ic = 1; EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), (const unsigned char*)salt, (const unsigned char*)pass, (int)strlen(pass), ic, buf, buf+32); printf("EVP_BytesToKey(\"%s\", \"%s\", %d)=\n", pass, salt, ic); print_hex(buf, 32+16); #endif return 0; } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmASN1.h000066400000000000000000000023001412732066400165030ustar00rootroot00000000000000/*========================================================================= 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 GDCMASN1_H #define GDCMASN1_H #include "gdcmTypes.h" namespace gdcm { //----------------------------------------------------------------------------- class ASN1Internals; /** * \brief Class for ASN1 * */ class GDCM_EXPORT ASN1 { public : ASN1(); ~ASN1(); static bool ParseDumpFile(const char *filename); static bool ParseDump(const char *array, size_t length); ASN1(const ASN1&) = delete; void operator=(const ASN1&) = delete; protected: int TestPBKDF2(); private: ASN1Internals *Internals; }; } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMASN1_H GDCM-3.0.10/Source/Common/gdcmBase64.cxx000066400000000000000000000126011412732066400174050ustar00rootroot00000000000000/*========================================================================= 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 "gdcmBase64.h" #include // memcpy #include namespace gdcm { /* base64.cpp and base64.h Copyright (C) 2004-2008 René Nyffenegger This source code is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this source code must not be misrepresented; you must not claim that you wrote the original source code. If you use this source code in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original source code. 3. This notice may not be removed or altered from any source distribution. René Nyffenegger rene.nyffenegger@adp-gmbh.ch */ static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; static inline bool is_base64(unsigned char c) { return (isalnum(c) || (c == '+') || (c == '/')); } static std::string base64_encode(unsigned char const* bytes_to_encode, size_t in_len) { std::string ret; size_t i = 0; size_t j = 0; unsigned char char_array_3[3]; unsigned char char_array_4[4]; while (in_len--) { char_array_3[i++] = *(bytes_to_encode++); if (i == 3) { char_array_4[0] = (unsigned char)((char_array_3[0] & 0xfc) >> 2); char_array_4[1] = (unsigned char)(((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4)); char_array_4[2] = (unsigned char)(((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6)); char_array_4[3] = (unsigned char)(char_array_3[2] & 0x3f); for(i = 0; i < 4; i++) ret += base64_chars[char_array_4[i]]; i = 0; } } if (i) { for(j = i; j < 3; j++) char_array_3[j] = '\0'; char_array_4[0] = (unsigned char)((char_array_3[0] & 0xfc) >> 2); char_array_4[1] = (unsigned char)(((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4)); char_array_4[2] = (unsigned char)(((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6)); char_array_4[3] = (unsigned char)(char_array_3[2] & 0x3f); for (j = 0; j < i + 1; j++) ret += base64_chars[char_array_4[j]]; while((i++ < 3)) ret += '='; } return ret; } static std::string base64_decode(std::string const& encoded_string) { size_t in_len = encoded_string.size(); size_t i = 0; size_t j = 0; size_t in_ = 0; unsigned char char_array_4[4], char_array_3[3]; std::string ret; while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { char_array_4[i++] = encoded_string[in_]; in_++; if (i ==4) { for (i = 0; i <4; i++) char_array_4[i] = (unsigned char)base64_chars.find(char_array_4[i]); char_array_3[0] = (unsigned char)((char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4)); char_array_3[1] = (unsigned char)(((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2)); char_array_3[2] = (unsigned char)(((char_array_4[2] & 0x3) << 6) + char_array_4[3]); for (i = 0; (i < 3); i++) ret += char_array_3[i]; i = 0; } } if (i) { for (j = i; j <4; j++) char_array_4[j] = 0; for (j = 0; j <4; j++) char_array_4[j] = (unsigned char)base64_chars.find(char_array_4[j]); char_array_3[0] = (unsigned char)((char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4)); char_array_3[1] = (unsigned char)(((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2)); char_array_3[2] = (unsigned char)(((char_array_4[2] & 0x3) << 6) + char_array_4[3]); for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; } return ret; } size_t Base64::GetEncodeLength(const char *src, size_t slen ) { std::string ret = base64_encode((const unsigned char*)src, slen); return ret.size(); } size_t Base64::Encode( char *dst, size_t dlen, const char *src, size_t slen ) { const std::string & ret = base64_encode((const unsigned char*)src, slen); if( ret.size() > dlen ) return 0; memcpy( dst, ret.c_str(), ret.size() ); return ret.size(); } size_t Base64::GetDecodeLength( const char *src, size_t slen ) { const std::string & ret = base64_decode( std::string( src, slen) ); return ret.size(); } size_t Base64::Decode( char *dst, size_t dlen, const char *src, size_t slen ) { const std::string & ret = base64_decode( std::string( src, slen) ); if( ret.size() > dlen ) return 0; memcpy( dst, ret.c_str(), ret.size() ); return ret.size(); } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmBase64.h000066400000000000000000000035671412732066400170450ustar00rootroot00000000000000/*========================================================================= 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 GDCMBASE64_H #define GDCMBASE64_H #include "gdcmTypes.h" namespace gdcm { /** * \brief Class for Base64 * */ class GDCM_EXPORT Base64 { public: /** * Call this function to obtain the required buffer size */ static size_t GetEncodeLength(const char *src, size_t srclen ); /** * \brief Encode a buffer into base64 format * * \param dst destination buffer * \param dlen size of the buffer * \param src source buffer * \param slen amount of data to be encoded * * \return 0 if not successful, size of encoded otherwise * */ static size_t Encode( char *dst, size_t dlen, const char *src, size_t slen ); /** * Call this function to obtain the required buffer size */ static size_t GetDecodeLength( const char *src, size_t len ); /** * \brief Decode a base64-formatted buffer * * \param dst destination buffer * \param dlen size of the buffer * \param src source buffer * \param slen amount of data to be decoded * * \return 0 if not successful, size of decoded otherwise */ static size_t Decode( char *dst, size_t dlen, const char *src, size_t slen ); Base64(const Base64&) = delete; void operator=(const Base64&) = delete; }; } // end namespace gdcm #endif // GDCMBASE64_H GDCM-3.0.10/Source/Common/gdcmBoxRegion.cxx000066400000000000000000000100371412732066400202560ustar00rootroot00000000000000/*========================================================================= 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 "gdcmBoxRegion.h" #include #include // req C++11 namespace gdcm { class BoxRegionInternals { public: BoxRegionInternals() { XMin = YMin = ZMin = std::numeric_limits::max(); XMax = YMax = ZMax = std::numeric_limits::min(); } unsigned int XMin, XMax; unsigned int YMin, YMax; unsigned int ZMin, ZMax; void Print(std::ostream &os) const { os << "Min:" << XMin << "," << YMin << "," << ZMin << "\n"; os << "Max:" << XMax << "," << YMax << "," << ZMax; } }; BoxRegion::BoxRegion() { Internals = new BoxRegionInternals; } BoxRegion::~BoxRegion() { delete Internals; } void BoxRegion::SetDomain(unsigned int xmin, unsigned int xmax, unsigned int ymin, unsigned int ymax, unsigned int zmin, unsigned int zmax) { Internals->XMin = xmin; Internals->YMin = ymin; Internals->ZMin = zmin; Internals->XMax = xmax; Internals->YMax = ymax; Internals->ZMax = zmax; } Region *BoxRegion::Clone() const { BoxRegion *br = new BoxRegion( *this ); return br; } bool BoxRegion::Empty() const { assert( 0 ); return false; } bool BoxRegion::IsValid() const { if (Internals->XMax < Internals->XMin || Internals->YMax < Internals->YMin || Internals->ZMax < Internals->ZMin ) { return false; } // Some properly crafted DICOM could have bigger values, reject them: // technically there is no such restrictions for Z direction if (Internals->XMax >= std::numeric_limits::max() || Internals->YMax >= std::numeric_limits::max() || Internals->ZMax == std::numeric_limits::max() ) { return false; } return true; } size_t BoxRegion::Area() const { // on some system size_t is too small: const uint64_t A = Internals->XMax - Internals->XMin + 1; const uint64_t B = Internals->YMax - Internals->YMin + 1; const uint64_t C = Internals->ZMax - Internals->ZMin + 1; const uint64_t tmp = A * B; if (tmp != 0 && (std::numeric_limits::max() / tmp) < C) { // multiplication exceed range of unsigned return 0; } return (size_t)(tmp * C); } unsigned int BoxRegion::GetXMin() const { return Internals->XMin; } unsigned int BoxRegion::GetXMax() const { return Internals->XMax; } unsigned int BoxRegion::GetYMin() const { return Internals->YMin; } unsigned int BoxRegion::GetYMax() const { return Internals->YMax; } unsigned int BoxRegion::GetZMin() const { return Internals->ZMin; } unsigned int BoxRegion::GetZMax() const { return Internals->ZMax; } BoxRegion BoxRegion::BoundingBox(BoxRegion const & b1, BoxRegion const & b2 ) { BoxRegion r; unsigned int xmin = std::min( b1.GetXMin(), b2.GetXMin() ); unsigned int xmax = std::min( b1.GetXMax(), b2.GetXMax() ); unsigned int ymin = std::min( b1.GetYMin(), b2.GetYMin() ); unsigned int ymax = std::min( b1.GetYMax(), b2.GetYMax() ); unsigned int zmin = std::min( b1.GetZMin(), b2.GetZMin() ); unsigned int zmax = std::min( b1.GetZMax(), b2.GetZMax() ); r.SetDomain(xmin, xmax, ymin, ymax, zmin, zmax); return r; } BoxRegion::BoxRegion(const BoxRegion& b) { assert( b.Internals ); Internals = new BoxRegionInternals; *Internals = *b.Internals; } void BoxRegion::operator=(const BoxRegion& b) { assert( b.Internals ); *Internals = *b.Internals; } BoxRegion BoxRegion::ComputeBoundingBox() { return *this; } void BoxRegion::Print(std::ostream &os) const { Region::Print( os ); os << "Domain:\n"; this->Internals->Print( os ); } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmBoxRegion.h000066400000000000000000000041271412732066400177060ustar00rootroot00000000000000/*========================================================================= 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 GDCMBOXREGION_H #define GDCMBOXREGION_H #include "gdcmRegion.h" namespace gdcm { class BoxRegionInternals; /** * \brief Class for manipulation box region * \details This is a very simple implementation of the Region class. * It only support 3D box type region. * It assumes the 3D Box does not have a tilt * Origin is as (0,0,0) */ //----------------------------------------------------------------------------- class GDCM_EXPORT BoxRegion : public Region { public : BoxRegion(); ~BoxRegion() override; /// Set domain void SetDomain(unsigned int xmin, unsigned int xmax, unsigned int ymin, unsigned int ymax, unsigned int zmin, unsigned int zmax); /// Get domain unsigned int GetXMin() const; unsigned int GetXMax() const; unsigned int GetYMin() const; unsigned int GetYMax() const; unsigned int GetZMin() const; unsigned int GetZMax() const; // Satisfy pure virtual parent class Region *Clone() const override; bool Empty() const override; bool IsValid() const override; size_t Area() const override; BoxRegion ComputeBoundingBox() override; void Print(std::ostream &os = std::cout) const override; /// Helper class to compute the bounding box of two BoxRegion static BoxRegion BoundingBox(BoxRegion const & b1, BoxRegion const & b2 ); /// copy/cstor and al. BoxRegion(const BoxRegion&); void operator=(const BoxRegion&); private: BoxRegionInternals *Internals; }; } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMREGION_H GDCM-3.0.10/Source/Common/gdcmByteSwap.cxx000066400000000000000000000011721412732066400201200ustar00rootroot00000000000000/*========================================================================= 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 "gdcmByteSwap.h" namespace gdcm { } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmByteSwap.h000066400000000000000000000027231412732066400175500ustar00rootroot00000000000000/*========================================================================= 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 GDCMBYTESWAP_H #define GDCMBYTESWAP_H #include "gdcmTypes.h" #include "gdcmSwapCode.h" namespace gdcm { /** * \brief ByteSwap * \details Perform machine dependent byte swapping (Little Endian, * Big Endian, Bad Little Endian, Bad Big Endian). * TODO: bswap_32 / bswap_64 ... */ template class ByteSwap { public: /** Query the machine Endian-ness. */ static bool SystemIsBigEndian (); static bool SystemIsLittleEndian (); static void Swap(T &p); static void SwapFromSwapCodeIntoSystem(T &p, SwapCode const &sc); static void SwapRange(T *p, unsigned int num); static void SwapRangeFromSwapCodeIntoSystem(T *p, SwapCode const &sc, std::streamoff num); protected: // ByteSwap() {} // ~ByteSwap() {} private: }; /** * \example TestByteSwap.cxx * This is a C++ example on how to use gdcm::ByteSwap */ } // end namespace gdcm #include "gdcmByteSwap.txx" #endif //GDCMBYTESWAP_H GDCM-3.0.10/Source/Common/gdcmByteSwap.txx000066400000000000000000000110611412732066400201370ustar00rootroot00000000000000/*========================================================================= 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 GDCMBYTESWAP_TXX #define GDCMBYTESWAP_TXX #include "gdcmByteSwap.h" #include #include // abort namespace gdcm { /* template (class T) { void bswap(inout T i) { byte* p = cast(byte*)&i; for (int b = 0; b < T.size/2; ++b) instance swap(byte).swap(p[b], p[T.size-1-b]); } } */ // Machine definitions #ifdef GDCM_WORDS_BIGENDIAN template bool ByteSwap::SystemIsBigEndian() { return true; } template bool ByteSwap::SystemIsLittleEndian() { return false; } #else template bool ByteSwap::SystemIsBigEndian() { return false; } template bool ByteSwap::SystemIsLittleEndian() { return true; } #endif template void ByteSwap::Swap(T &p) { #ifdef GDCM_WORDS_BIGENDIAN ByteSwap::SwapFromSwapCodeIntoSystem(p, SwapCode::LittleEndian); #else ByteSwap::SwapFromSwapCodeIntoSystem(p, SwapCode::BigEndian); #endif } // Swaps the bytes so they agree with the processor order template void ByteSwap::SwapFromSwapCodeIntoSystem(T &a, SwapCode const &swapcode) { //std::cerr << "sizeof(T)= " << sizeof(T) << " " << (int)a << std::endl; switch(sizeof(T)) { case 1: break; case 2: Swap4(a, swapcode); break; case 4: Swap8(a, swapcode); break; default: std::cerr << "Impossible" << std::endl; abort(); } } template void ByteSwap::SwapRange(T *p, unsigned int num) { for(unsigned int i=0; i::Swap(p[i]); } } template void ByteSwap::SwapRangeFromSwapCodeIntoSystem(T *p, SwapCode const &sc, std::streamoff num) { for( std::streamoff i=0; i::SwapFromSwapCodeIntoSystem(p[i], sc); } } // Private: // template void Swap4(T &a, SwapCode const &swapcode) { #ifndef GDCM_WORDS_BIGENDIAN if ( swapcode == 4321 || swapcode == 2143 ) a = (T)(( a << 8 ) | ( a >> 8 )); #else if ( swapcode == 1234 || swapcode == 3412 ) a = ( a << 8 ) | ( a >> 8 ); // On big endian as long as the SwapCode is Unknown let's pretend we were // on a LittleEndian system (might introduce overhead on those system). else if ( swapcode == SwapCode::Unknown ) a = ( a << 8 ) | ( a >> 8 ); #endif } //note: according to http://www.parashift.com/c++-faq-lite/templates.html#faq-35.8 //the inlining of the template class means that the specialization doesn't cause linker errors template inline void Swap8(T &a, SwapCode const &swapcode) { switch (swapcode) { case SwapCode::Unknown: #ifdef GDCM_WORDS_BIGENDIAN a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) ); #endif break; case 1234 : #ifdef GDCM_WORDS_BIGENDIAN a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) ); #endif break; case 4321 : #ifndef GDCM_WORDS_BIGENDIAN a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) ); #endif break; case 3412 : a= ((a<<16) | (a>>16) ); break; case 2143 : a= (((a<< 8) & 0xff00ff00) | ((a>>8) & 0x00ff00ff) ); break; default : std::cerr << "Unexpected swap code:" << swapcode; } } template <> inline void Swap8(uint16_t &a, SwapCode const &swapcode) { switch (swapcode) { case SwapCode::Unknown: #ifdef GDCM_WORDS_BIGENDIAN a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) ); #endif break; case 1234 : #ifdef GDCM_WORDS_BIGENDIAN a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) ); #endif break; case 4321 : #ifndef GDCM_WORDS_BIGENDIAN // probably not really useful since the lowest 0x0000 are what's used in unsigned shorts // a= (( a<<24) | ((a<<8) & 0x00ff0000) | ((a>>8) & 0x0000ff00) | (a>>24) ); #endif break; case 3412 : //a= ((a<<16) | (a>>16) );//do nothing, a = a break; case 2143 : a= (uint16_t)(((a<< 8) & 0xff00) | ((a>>8) & 0x00ff) ); break; default : std::cerr << "Unexpected swap code:" << swapcode; } } } // end namespace gdcm #endif // GDCMBYTESWAP_TXX GDCM-3.0.10/Source/Common/gdcmCAPICryptoFactory.cxx000066400000000000000000000020721412732066400216270ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCAPICryptoFactory.h" #include "gdcmCAPICryptographicMessageSyntax.h" namespace gdcm { CAPICryptoFactory::CAPICryptoFactory(CryptoLib id) : CryptoFactory(id) { gdcmDebugMacro( "CAPI Factory registered." << std::endl ); } CryptographicMessageSyntax* CAPICryptoFactory::CreateCMSProvider() { CAPICryptographicMessageSyntax* capicms = new CAPICryptographicMessageSyntax(); if (!capicms->GetInitialized()) { delete capicms; return NULL; } return capicms; } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmCAPICryptoFactory.h000066400000000000000000000016431412732066400212570ustar00rootroot00000000000000/*========================================================================= 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 GDCMCAPICRYPTOFACTORY_H #define GDCMCAPICRYPTOFACTORY_H #include "gdcmCryptoFactory.h" namespace gdcm { class GDCM_EXPORT CAPICryptoFactory : public CryptoFactory { public: CAPICryptoFactory(CryptoLib id); CryptographicMessageSyntax* CreateCMSProvider(); private: CAPICryptoFactory() {} }; } // end namespace gdcm #endif //GDCMCAPICRYPTOFACTORY_H GDCM-3.0.10/Source/Common/gdcmCAPICryptographicMessageSyntax.cxx000066400000000000000000000401231412732066400243500ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCAPICryptographicMessageSyntax.h" #include // fseek namespace gdcm { CAPICryptographicMessageSyntax::CAPICryptographicMessageSyntax() : hProv(0), hRsaPrivK(0), cipherType(AES128_CIPHER) { initialized = Initialize(); } CAPICryptographicMessageSyntax::~CAPICryptographicMessageSyntax() { for (std::vector::iterator it = certifList.begin(); it != certifList.end(); ++it) { CertFreeCertificateContext(*it); /*if (! CertFreeCertificateContext(*it)) { gdcmWarningMacro( "Error at releasing certificate context: " << std::hex << GetLastError() ); }*/ } if (hRsaPrivK) CryptDestroyKey(hRsaPrivK); if (!CryptReleaseContext(hProv, 0)) { gdcmWarningMacro("Error when releasing context: 0x" << std::hex << GetLastError()); } } // http://stackoverflow.com/questions/11709500/capi-does-not-support-password-based-encryption-pbe-encryption bool CAPICryptographicMessageSyntax::SetPassword(const char * , size_t ) { gdcmWarningMacro( "CAPI does not support Password Based Encryption." ); return false; } bool CAPICryptographicMessageSyntax::ParseCertificateFile( const char *filename ) { bool ret = false; unsigned char *certHexBuf = NULL, *certBin = NULL; DWORD certHexBufLen, certBinLen; if ( !LoadFile(filename, certHexBuf, certHexBufLen) ) goto err; // Call to get the needed amount of space if ( !CryptStringToBinaryA( (LPCSTR)certHexBuf, 0, CRYPT_STRING_BASE64_ANY, NULL, &certBinLen, NULL, NULL ) ) { gdcmErrorMacro( "CryptStringToBinary failed with error 0x" << std::hex << GetLastError() ); goto err; } certBin = new unsigned char[certBinLen]; // Convert from PEM format to DER format - removes header and footer and decodes from base64 if ( !CryptStringToBinaryA( (LPCSTR)certHexBuf, 0, CRYPT_STRING_BASE64_ANY, certBin, &certBinLen, NULL, NULL ) ) { gdcmErrorMacro( "CryptStringToBinary failed with error 0x" << std::hex << GetLastError() ); goto err; } PCCERT_CONTEXT certContext; certContext = CertCreateCertificateContext(X509_ASN_ENCODING, certBin, certBinLen); if (certContext == NULL) { gdcmErrorMacro( "CertCreateCertificateContext failed with error 0x" << std::hex << GetLastError() ); goto err; } certifList.push_back(certContext); ret = true; err: if (certBin) delete[] certBin; if (certHexBuf) delete[] certHexBuf; return ret; } bool CAPICryptographicMessageSyntax::ParseKeyFile( const char *filename ) { bool ret = false; unsigned char *keyHexBuffer = NULL, *keyBinBuffer = NULL, *keyBlob = NULL; DWORD keyHexBufferLen, keyBinBufferLen, keyBlobLen; HCRYPTKEY hKey = 0; if (!LoadFile(filename, keyHexBuffer, keyHexBufferLen)) goto err; if ( !CryptStringToBinaryA((LPCSTR)keyHexBuffer, 0, CRYPT_STRING_BASE64_ANY, NULL, &keyBinBufferLen, NULL, NULL) ) { gdcmErrorMacro( "Failed to convert from BASE64. CryptStringToBinary failed with error 0x" << std::hex << GetLastError() ); goto err; } keyBinBuffer = new unsigned char[keyBinBufferLen]; if ( !CryptStringToBinaryA((LPCSTR)keyHexBuffer, 0, CRYPT_STRING_BASE64_ANY, keyBinBuffer, &keyBinBufferLen, NULL, NULL) ) { gdcmErrorMacro( "Failed to convert from BASE64. CryptStringToBinary failed with error 0x" << std::hex << GetLastError() ); goto err; } if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, keyBinBuffer, keyBinBufferLen, 0, NULL, NULL, &keyBlobLen)) { gdcmErrorMacro( "Failed to parse private key. CryptDecodeObjectEx failed with error 0x" << std::hex << GetLastError() ); goto err; } keyBlob = new unsigned char[keyBlobLen]; if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, keyBinBuffer, keyBinBufferLen, 0, NULL, keyBlob, &keyBlobLen)) { gdcmErrorMacro( "Failed to parse private key. CryptDecodeObjectEx failed with error 0x" << std::hex << GetLastError() ); goto err; } if (!CryptImportKey(hProv, keyBlob, keyBlobLen, 0, 0, &hKey)) { gdcmErrorMacro( "CryptImportKey failed with error 0x" << std::hex << GetLastError() ); goto err; } if (hRsaPrivK) CryptDestroyKey(hRsaPrivK); hRsaPrivK = hKey; ret = true; err: if (keyHexBuffer) delete[] keyHexBuffer; if (keyBinBuffer) delete[] keyBinBuffer; if (keyBlob) delete[] keyBlob; return ret; } void CAPICryptographicMessageSyntax::SetCipherType(CryptographicMessageSyntax::CipherTypes type) { cipherType = type; } CryptographicMessageSyntax::CipherTypes CAPICryptographicMessageSyntax::GetCipherType() const { return cipherType; } bool CAPICryptographicMessageSyntax::Encrypt(char *output, size_t &outlen, const char *array, size_t len) const { CRYPT_ALGORITHM_IDENTIFIER EncryptAlgorithm = {0}; const char *objid = GetCipherObjId(); if( !objid ) { gdcmErrorMacro( "Could not GetCipherObjId" ); return false; } EncryptAlgorithm.pszObjId = (char*)objid; CRYPT_ENCRYPT_MESSAGE_PARA EncryptParams = {0}; EncryptParams.cbSize = sizeof(EncryptParams); EncryptParams.dwMsgEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING; EncryptParams.hCryptProv = hProv; EncryptParams.ContentEncryptionAlgorithm = EncryptAlgorithm; if (certifList.size() == 0) { gdcmErrorMacro("No recipients certificates loaded."); return false; } if(! CryptEncryptMessage(&EncryptParams, (DWORD)certifList.size(), (PCCERT_CONTEXT *)&certifList[0], (unsigned char *)array, (DWORD)len, (unsigned char *)output, (DWORD *)&outlen) ) { DWORD dwResult = GetLastError(); gdcmErrorMacro( "Couldn't encrypt message. CryptEncryptMessage failed with error 0x" << std::hex << dwResult ); if (dwResult == CRYPT_E_UNKNOWN_ALGO) { gdcmErrorMacro("Unknown encryption algorithm. If on Windows XP please use only 3DES."); } return false; } return true; } bool CAPICryptographicMessageSyntax::Decrypt(char *output, size_t &outlen, const char *array, size_t len) const { bool ret = false; unsigned char* cek = NULL; HCRYPTMSG hMsg = NULL; PCMSG_CMS_RECIPIENT_INFO recipientInfo = NULL; DWORD dwMessageType, cbMessageTypeLen = sizeof(DWORD); PCRYPT_ALGORITHM_IDENTIFIER cekAlg = NULL; ALG_ID kekAlg; DWORD kekAlgLen = sizeof(ALG_ID); DWORD nrOfRecipeints, nrOfRecipientsLen = sizeof(DWORD); unsigned char* bareContent = NULL; struct { BLOBHEADER header; DWORD cbKeySize; unsigned char rgbKeyData[32]; //the maximum is 256 bit for aes } keyBlob = {{0}}; if (hRsaPrivK == 0) { gdcmErrorMacro("No private key loaded loaded."); return false; } if (! (hMsg = CryptMsgOpenToDecode(CRYPT_ASN_ENCODING | X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED_DATA_PKCS_1_5_VERSION, 0, NULL, NULL)) ) { gdcmErrorMacro( "MsgOpenToDecode failed with error 0x" << std::hex << GetLastError() ); goto err; } if(! CryptMsgUpdate(hMsg, (unsigned char*)array, (DWORD)len, TRUE)) { gdcmErrorMacro( "MsgUpdate failed with error 0x" << std::hex << GetLastError() ); goto err; } if(! CryptMsgGetParam(hMsg, CMSG_TYPE_PARAM, 0, &dwMessageType, &cbMessageTypeLen)) { gdcmErrorMacro( "CryptMsgGetParam CMSG_TYPE_PARAM failed with error 0x" << std::hex << GetLastError() ); goto err; } if(dwMessageType != CMSG_ENVELOPED) { gdcmErrorMacro("Wrong message type ( != CMSG_ENVELOPED )"); goto err; } if(! CryptGetKeyParam(hRsaPrivK, KP_ALGID, (unsigned char*)&kekAlg, &kekAlgLen, 0)) { gdcmErrorMacro( "MsgGetParam KP_ALGID failed with error 0x" << std::hex << GetLastError() ); goto err; } if (kekAlg != CALG_RSA_KEYX) { gdcmErrorMacro( "Key encryption algorithm is not RSA." ); goto err; } if(! CryptMsgGetParam(hMsg, CMSG_RECIPIENT_COUNT_PARAM, 0, &nrOfRecipeints, &nrOfRecipientsLen)) { gdcmErrorMacro( "Decode CMSG_RECIPIENT_COUNT_PARAM failed with error 0x" << std::hex << GetLastError() ); goto err; } DWORD cekLen; { BOOL foundRecipient = FALSE; for (DWORD i=0; i < nrOfRecipeints; i++) { if (recipientInfo) delete[] recipientInfo; DWORD cbRecipientInfoLen; if(! CryptMsgGetParam(hMsg, CMSG_CMS_RECIPIENT_INFO_PARAM, i, NULL, &cbRecipientInfoLen)) { gdcmErrorMacro( "MsgGetParam CMSG_CMS_RECIPIENT_INFO_PARAM size failed with error 0x" << std::hex << GetLastError() ); goto err; } recipientInfo = (PCMSG_CMS_RECIPIENT_INFO) new unsigned char[cbRecipientInfoLen]; if(! CryptMsgGetParam(hMsg, CMSG_CMS_RECIPIENT_INFO_PARAM, i, recipientInfo, &cbRecipientInfoLen)) { gdcmErrorMacro( "MsgGetParam CMSG_CMS_RECIPIENT_INFO_PARAM failed with error 0x" << std::hex << GetLastError() ); goto err; } DWORD rsaPadding = 0; if (strcmp(recipientInfo->pKeyTrans->KeyEncryptionAlgorithm.pszObjId, szOID_RSAES_OAEP) == 0) { rsaPadding = CRYPT_OAEP; } //cek - content encryption key cekLen = recipientInfo->pKeyTrans->EncryptedKey.cbData; cek = recipientInfo->pKeyTrans->EncryptedKey.pbData; ReverseBytes(cek, cekLen); if ( (foundRecipient = CryptDecrypt(hRsaPrivK, 0, TRUE, rsaPadding, cek, &cekLen)) ) break; } // end loop recipients if (!foundRecipient) { gdcmErrorMacro( "No recipient found with the specified private key." ); goto err; } } DWORD cekAlgLen; if(! CryptMsgGetParam(hMsg, CMSG_ENVELOPE_ALGORITHM_PARAM, 0, NULL, &cekAlgLen)) { gdcmErrorMacro( "MsgGetParam CMSG_ENVELOPE_ALGORITHM_PARAM failed with error 0x" << std::hex << GetLastError() ); goto err; } cekAlg = (PCRYPT_ALGORITHM_IDENTIFIER) new unsigned char[cekAlgLen]; if(! CryptMsgGetParam(hMsg, CMSG_ENVELOPE_ALGORITHM_PARAM, 0, cekAlg, &cekAlgLen)) { gdcmErrorMacro( "MsgGetParam CMSG_ENVELOPE_ALGORITHM_PARAM failed with error 0x" << std::hex << GetLastError() ); goto err; } HCRYPTKEY hCEK; keyBlob.header.bType = PLAINTEXTKEYBLOB; keyBlob.header.bVersion = CUR_BLOB_VERSION; keyBlob.header.reserved = 0; keyBlob.header.aiKeyAlg = GetAlgIdByObjId(cekAlg->pszObjId); keyBlob.cbKeySize = cekLen; assert(cekLen <= 32); memcpy(keyBlob.rgbKeyData, cek, cekLen); if (!CryptImportKey(hProv, (unsigned char*)&keyBlob, sizeof(keyBlob), 0, 0, &hCEK)) { gdcmErrorMacro( "CryptImportKey failed with error 0x" << std::hex << GetLastError() ); goto err; } if(! CryptSetKeyParam(hCEK, KP_IV, (unsigned char *) cekAlg->Parameters.pbData+2, 0)) //+2 for ASN header ??? { gdcmErrorMacro( "SetKeyParam KP_IV failed with error 0x" << std::hex << GetLastError() ); goto err; } { DWORD dwMode = CRYPT_MODE_CBC; if(! CryptSetKeyParam(hCEK, KP_MODE, (unsigned char*) &dwMode, 0)) { gdcmErrorMacro( "SetKeyParam KP_MODE failed with error 0x" << std::hex << GetLastError() ); goto err; } } DWORD bareContentLen; if(! CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, NULL, &bareContentLen)) { gdcmErrorMacro( "MsgGetParam CMSG_BARE_CONTENT_PARAM size failed with error 0x" << std::hex << GetLastError() ); goto err; } bareContent = new unsigned char[bareContentLen]; if(! CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, bareContent, &bareContentLen)) { gdcmErrorMacro( "MsgGetParam CMSG_BARE_CONTENT_PARAM failed with error 0x" << std::hex << GetLastError() ); goto err; } if (! CryptDecrypt(hCEK, 0, TRUE, 0, bareContent, &bareContentLen)) { gdcmErrorMacro( "CryptDecrypt failed with error 0x" << std::hex << GetLastError() ); goto err; } if (bareContentLen > outlen) { gdcmErrorMacro( "Supplied output buffer too small: " << bareContentLen << " bytes needed." ); goto err; } memcpy(output, bareContent, bareContentLen); outlen = bareContentLen; ret = true; err: if (hMsg) CryptMsgClose(hMsg); if (recipientInfo) delete[] recipientInfo; if (bareContent) delete[] bareContent; if (cekAlg) delete[] cekAlg; return ret; } ALG_ID CAPICryptographicMessageSyntax::GetAlgIdByObjId(const char * pszObjId) { // HACK: fix compilation on mingw64: // See: http://sourceforge.net/tracker/?func=detail&aid=3561209&group_id=202880&atid=983354 #ifndef szOID_NIST_AES128_CBC #define szOID_NIST_AES128_CBC "2.16.840.1.101.3.4.1.2" #define szOID_NIST_AES192_CBC "2.16.840.1.101.3.4.1.22" #define szOID_NIST_AES256_CBC "2.16.840.1.101.3.4.1.42" #endif if (strcmp(pszObjId, szOID_NIST_AES128_CBC) == 0) { return CALG_AES_128; } else if (strcmp(pszObjId, szOID_NIST_AES192_CBC) == 0) { return CALG_AES_192; } else if (strcmp(pszObjId, szOID_NIST_AES256_CBC) == 0) { return CALG_AES_256; } else if (strcmp(pszObjId, szOID_RSA_DES_EDE3_CBC) == 0) { return CALG_3DES; } return 0; } const char *CAPICryptographicMessageSyntax::GetCipherObjId() const { switch( cipherType ) { case AES128_CIPHER: return szOID_NIST_AES128_CBC; case AES192_CIPHER: return szOID_NIST_AES192_CBC; case AES256_CIPHER: return szOID_NIST_AES256_CBC; case DES3_CIPHER: return szOID_RSA_DES_EDE3_CBC; } return 0; } bool CAPICryptographicMessageSyntax::Initialize() { DWORD dwResult; if (!CryptAcquireContextA(&hProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) //CRYPT_VERIFYCONTEXT aes decr in cryptmsgcontrol not working { dwResult = GetLastError(); if (dwResult == NTE_BAD_KEYSET) { if (!CryptAcquireContextA(&hProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_NEWKEYSET | CRYPT_VERIFYCONTEXT)) { dwResult = GetLastError(); gdcmErrorMacro( "CryptAcquireContext() failed:" << std::hex << dwResult); return false; } } else if (dwResult == NTE_KEYSET_NOT_DEF) { //Probably WinXP gdcmWarningMacro( "Certificate based encryption is supported on Windows XP only using 3DES." ); if (!CryptAcquireContextA(&hProv, NULL, MS_ENH_RSA_AES_PROV_A" (Prototype)" /*"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"*/, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) //CRYPT_VERIFYCONTEXT aes decr in cryptmsgcontrol not working { dwResult = GetLastError(); if (dwResult == NTE_BAD_KEYSET) { if (!CryptAcquireContextA(&hProv, NULL, MS_ENH_RSA_AES_PROV_A" (Prototype)" /*"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"*/, PROV_RSA_AES, CRYPT_NEWKEYSET | CRYPT_VERIFYCONTEXT)) { dwResult = GetLastError(); gdcmErrorMacro( "CryptAcquireContext() failed: " << std::hex << dwResult ); return false; } } else { dwResult = GetLastError(); return false; } } } else { dwResult = GetLastError(); return false; } } return true; } void CAPICryptographicMessageSyntax::ReverseBytes(unsigned char* data, DWORD len) { unsigned char temp; for (DWORD i = 0; i < len/2; i++) { temp = data[len-i-1]; data[len-i-1] = data[i]; data[i] = temp; } } bool CAPICryptographicMessageSyntax::LoadFile(const char * filename, unsigned char* & buffer, DWORD & bufLen) { assert( !buffer ); FILE * f = fopen(filename, "rb"); if (f == NULL) { gdcmErrorMacro("Couldn't open the file: " << filename); fclose(f); return false; } fseek(f, 0L, SEEK_END); long sz = ftell(f); rewind(f); buffer = new unsigned char[sz]; if( !buffer ) { fclose(f); return false; } bufLen = sz; while (sz) { size_t l = fread(buffer + bufLen - sz, sizeof(unsigned char), sz, f); sz -= (long)l; } fclose(f); return true; } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmCAPICryptographicMessageSyntax.h000066400000000000000000000037441412732066400240050ustar00rootroot00000000000000/*========================================================================= 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 GDCMCAPICRYPTOGRAPHICMESSAGESYNTAX_H #define GDCMCAPICRYPTOGRAPHICMESSAGESYNTAX_H #include "gdcmCryptographicMessageSyntax.h" #include #include #include namespace gdcm { class GDCM_EXPORT CAPICryptographicMessageSyntax : public CryptographicMessageSyntax { public: CAPICryptographicMessageSyntax(); ~CAPICryptographicMessageSyntax(); // X.509 bool ParseCertificateFile( const char *filename ); bool ParseKeyFile( const char *filename ); // PBE bool SetPassword(const char * pass, size_t passLen); void SetCipherType(CipherTypes type); CipherTypes GetCipherType() const; /// create a CMS envelopedData structure bool Encrypt(char *output, size_t &outlen, const char *array, size_t len) const; /// decrypt content from a CMS envelopedData structure bool Decrypt(char *output, size_t &outlen, const char *array, size_t len) const; bool GetInitialized() const { return initialized; } private: bool Initialize(); static ALG_ID GetAlgIdByObjId(const char * pszObjId); const char *GetCipherObjId() const; static void ReverseBytes(unsigned char* data, DWORD len); static bool LoadFile(const char * filename, unsigned char* & buffer, DWORD & bufLen); private: bool initialized; HCRYPTPROV hProv; std::vector certifList; HCRYPTKEY hRsaPrivK; CipherTypes cipherType; }; } // end namespace gdcm #endif //GDCMCAPICRYPTOGRAPHICMESSAGESYNTAX_H GDCM-3.0.10/Source/Common/gdcmCommand.cxx000066400000000000000000000012701412732066400177370ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCommand.h" namespace gdcm { Command::Command() = default; Command::~Command() = default; } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmCommand.h000066400000000000000000000120241412732066400173630ustar00rootroot00000000000000/*========================================================================= 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 GDCMCOMMAND_H #define GDCMCOMMAND_H #include "gdcmSubject.h" namespace gdcm { class Event; /** * \brief Command superclass for callback/observer methods * \see Subject */ class GDCM_EXPORT Command : public Subject { public : Command(const Command&) = delete; void operator=(const Command&) = delete; /// Abstract method that defines the action to be taken by the command. virtual void Execute(Subject *caller, const Event & event ) = 0; /** Abstract method that defines the action to be taken by the command. * This variant is expected to be used when requests comes from a * const Object */ virtual void Execute(const Subject *caller, const Event & event ) = 0; protected: Command(); ~Command() override; }; /** \class MemberCommand * \brief Command subclass that calls a pointer to a member function * * MemberCommand calls a pointer to a member function with the same * arguments as Execute on Command. * */ template class MemberCommand : public Command { public: /** pointer to a member function that takes a Subject* and the event */ typedef void (T::*TMemberFunctionPointer)(Subject*, const Event &); typedef void (T::*TConstMemberFunctionPointer)(const Subject*, const Event &); /** Standard class typedefs. */ typedef MemberCommand Self; //typedef SmartPointer Pointer; MemberCommand(const Self&) = delete; void operator=(const Self&) = delete; /** Method for creation through the object factory. */ static SmartPointer New() { return new MemberCommand; } /** Run-time type information (and related methods). */ //gdcmTypeMacro(MemberCommand,Command); /** Set the callback function along with the object that it will * be invoked on. */ void SetCallbackFunction(T* object, TMemberFunctionPointer memberFunction) { m_This = object; m_MemberFunction = memberFunction; } void SetCallbackFunction(T* object, TConstMemberFunctionPointer memberFunction) { m_This = object; m_ConstMemberFunction = memberFunction; } /** Invoke the member function. */ void Execute(Subject *caller, const Event & event ) override { if( m_MemberFunction ) { ((*m_This).*(m_MemberFunction))(caller, event); } } /** Invoke the member function with a const object. */ void Execute( const Subject *caller, const Event & event ) override { if( m_ConstMemberFunction ) { ((*m_This).*(m_ConstMemberFunction))(caller, event); } } protected: T* m_This; TMemberFunctionPointer m_MemberFunction; TConstMemberFunctionPointer m_ConstMemberFunction; MemberCommand():m_MemberFunction(nullptr),m_ConstMemberFunction(nullptr) {} ~MemberCommand() override= default; }; /** \class SimpleMemberCommand * \brief Command subclass that calls a pointer to a member function * * SimpleMemberCommand calls a pointer to a member function with no * arguments. */ template class SimpleMemberCommand : public Command { public: /** A method callback. */ typedef void (T::*TMemberFunctionPointer)(); /** Standard class typedefs. */ typedef SimpleMemberCommand Self; //typedef SmartPointer Pointer; SimpleMemberCommand(const Self&) = delete; void operator=(const Self&) = delete; /** Run-time type information (and related methods). */ //gdcmTypeMacro(SimpleMemberCommand,Command); /** Method for creation through the object factory. */ static SmartPointer New() { return new SimpleMemberCommand; } /** Specify the callback function. */ void SetCallbackFunction(T* object, TMemberFunctionPointer memberFunction) { m_This = object; m_MemberFunction = memberFunction; } /** Invoke the callback function. */ void Execute(Subject *,const Event & ) override { if( m_MemberFunction ) { ((*m_This).*(m_MemberFunction))(); } } void Execute(const Subject *,const Event & ) override { if( m_MemberFunction ) { ((*m_This).*(m_MemberFunction))(); } } protected: T* m_This; TMemberFunctionPointer m_MemberFunction; SimpleMemberCommand():m_This(nullptr),m_MemberFunction(nullptr) {} ~SimpleMemberCommand() override = default; }; } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMCOMMAND_H GDCM-3.0.10/Source/Common/gdcmConfigure.h.in000066400000000000000000000134021412732066400203340ustar00rootroot00000000000000/*========================================================================= 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 GDCMCONFIGURE_H #define GDCMCONFIGURE_H /* This header is configured by GDCM's build process. */ /*--------------------------------------------------------------------------*/ /* Platform Features */ /* Byte order. */ /* All compilers that support Mac OS X define either __BIG_ENDIAN__ or __LITTLE_ENDIAN__ to match the endianness of the architecture being compiled for. This is not necessarily the same as the architecture of the machine doing the building. In order to support Universal Binaries on Mac OS X, we prefer those defines to decide the endianness. Elsewhere use the platform check result. */ #if !defined(__APPLE__) #cmakedefine GDCM_WORDS_BIGENDIAN #elif defined(__BIG_ENDIAN__) # define GDCM_WORDS_BIGENDIAN #endif /* Allow access to UINT32_MAX , cf gdcmCommon.h */ #define __STDC_LIMIT_MACROS /* Hard code the path to the public dictionary */ #define PUB_DICT_PATH "@GDCM_PUB_DICT_PATH@" /* Useful in particular for loadshared where the full path * to the lib is needed */ #define GDCM_SOURCE_DIR "@GDCM_SOURCE_DIR@" #define GDCM_EXECUTABLE_OUTPUT_PATH "@EXECUTABLE_OUTPUT_PATH@" #define GDCM_LIBRARY_OUTPUT_PATH "@LIBRARY_OUTPUT_PATH@" #cmakedefine GDCM_BUILD_TESTING #cmakedefine GDCM_USE_SYSTEM_ZLIB #cmakedefine GDCM_USE_SYSTEM_UUID #cmakedefine GDCM_USE_SYSTEM_POPPLER #cmakedefine GDCM_USE_SYSTEM_LIBXML2 #cmakedefine GDCM_USE_SYSTEM_OPENSSL #cmakedefine GDCM_USE_SYSTEM_MD5 #cmakedefine GDCM_USE_SYSTEM_EXPAT #cmakedefine GDCM_USE_SYSTEM_JSON #cmakedefine GDCM_USE_SYSTEM_LJPEG #cmakedefine GDCM_USE_SYSTEM_OPENJPEG #cmakedefine GDCM_USE_SYSTEM_CHARLS #cmakedefine GDCM_USE_SYSTEM_KAKADU #cmakedefine GDCM_USE_SYSTEM_PVRG #cmakedefine GDCMV2_0_COMPATIBILITY #cmakedefine GDCM_USE_SYSTEM_PAPYRUS3 #ifndef GDCM_USE_SYSTEM_OPENJPEG #define OPENJPEG_VERSION_MAJOR 2 #else #define OPENJPEG_VERSION_MAJOR @OPENJPEG_VERSION_MAJOR@ #endif //GDCM_USE_SYSTEM_OPENJPEG #ifndef OPENJPEG_VERSION_MAJOR #error problem with openjpeg major version #endif // OPENJPEG_VERSION_MAJOR #cmakedefine GDCM_USE_PVRG #cmakedefine GDCM_USE_KAKADU #cmakedefine GDCM_USE_JPEGLS #cmakedefine GDCM_AUTOLOAD_GDCMJNI /* I guess something important */ #cmakedefine GDCM_HAVE_STDINT_H #cmakedefine GDCM_HAVE_INTTYPES_H /* This variable allows you to have helpful debug statement */ /* That are in between #ifdef / endif in the gdcm code */ /* That means if GDCM_DEBUG is OFF there shouldn't be any 'cout' at all ! */ /* only cerr, for instance 'invalid file' will be allowed */ #cmakedefine GDCM_DEBUG #define GDCM_CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@" #define GDCM_INSTALL_INCLUDE_DIR "@GDCM_INSTALL_INCLUDE_DIR@" #define GDCM_INSTALL_DATA_DIR "@GDCM_INSTALL_DATA_DIR@" /* Whether we are building shared libraries. */ #cmakedefine GDCM_BUILD_SHARED_LIBS /* GDCM uses __FUNCTION__ which is not ANSI C, but C99 */ #cmakedefine GDCM_CXX_HAS_FUNCTION /* Special time structure support */ #cmakedefine GDCM_HAVE_SYS_TIME_H #cmakedefine GDCM_HAVE_WINSOCK_H #cmakedefine GDCM_HAVE_BYTESWAP_H #cmakedefine GDCM_HAVE_RPC_H // CMS with PBE (added in OpenSSL 1.0.0 ~ Fri Nov 27 15:33:25 CET 2009) #cmakedefine GDCM_HAVE_CMS_RECIPIENT_PASSWORD #cmakedefine GDCM_HAVE_LANGINFO_H #cmakedefine GDCM_HAVE_NL_LANGINFO #cmakedefine GDCM_HAVE_STRCASECMP #cmakedefine GDCM_HAVE_STRNCASECMP #cmakedefine GDCM_HAVE_STRPTIME #cmakedefine GDCM_HAVE__STRICMP #cmakedefine GDCM_HAVE__STRNICMP #cmakedefine GDCM_HAVE_LROUND #cmakedefine GDCM_HAVE_GETTIMEOFDAY #cmakedefine GDCM_HAVE_ATOLL #cmakedefine GDCM_HAVE_JSON_OBJECT_OBJECT_GET_EX // MM: I have a feeling that if GDCM_HAVE_WCHAR_IFSTREAM, then UNICODE filename // are expected to be specified as UTF-16, but if no API exist for UTF-16 // at std::ifstream level, then const char* of std::ifstream might accept // UTF-8 #cmakedefine GDCM_HAVE_WCHAR_IFSTREAM #cmakedefine GDCM_FORCE_BIGENDIAN_EMULATION #ifndef GDCM_OVERRIDE_BROKEN_IMPLEMENTATION /* To Remove code that support broken DICOM implementation and therefore * add some over head. Turn Off at your own risk */ #cmakedefine GDCM_SUPPORT_BROKEN_IMPLEMENTATION #endif #ifndef gdcm_ns #define gdcm_ns gdcm #endif #define GDCM_PVRG_JPEG_EXECUTABLE "@PVRGJPEG_EXECUTABLE@" #define GDCM_KAKADU_EXPAND_EXECUTABLE "@KDU_EXPAND_EXECUTABLE@" /*--------------------------------------------------------------------------*/ /* GDCM Versioning */ /* Version number. */ #define GDCM_MAJOR_VERSION @GDCM_MAJOR_VERSION@ #define GDCM_MINOR_VERSION @GDCM_MINOR_VERSION@ #define GDCM_BUILD_VERSION @GDCM_BUILD_VERSION@ #define GDCM_VERSION "@GDCM_VERSION@" #define GDCM_API_VERSION "@GDCM_API_VERSION@" /* #define GDCM_FILE_META_INFORMATION_VERSION "\0\1" // echo "gdcm" | od -b #define GDCM_IMPLEMENTATION_CLASS_UID "107.104.103.115"; #define GDCM_IMPLEMENTATION_VERSION_NAME "GDCM " GDCM_VERSION #define GDCM_SOURCE_APPLICATION_ENTITY_TITLE "GDCM" */ /*--------------------------------------------------------------------------*/ /* GDCM deprecation mechanism */ #cmakedefine GDCM_LEGACY_REMOVE #cmakedefine GDCM_LEGACY_SILENT #cmakedefine GDCM_ALWAYS_TRACE_MACRO /* ITK Specific */ #cmakedefine GDCM_USE_COREFOUNDATION_LIBRARY #endif GDCM-3.0.10/Source/Common/gdcmCryptoFactory.cxx000066400000000000000000000035171412732066400211770ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCryptoFactory.h" #ifdef _WIN32 #include "gdcmCAPICryptoFactory.h" #endif #ifdef GDCM_USE_SYSTEM_OPENSSL #ifdef GDCM_HAVE_CMS_RECIPIENT_PASSWORD #include "gdcmOpenSSLCryptoFactory.h" #endif #include "gdcmOpenSSLP7CryptoFactory.h" #endif namespace gdcm { CryptoFactory* CryptoFactory::GetFactoryInstance(CryptoLib id) { #ifdef _WIN32 static CAPICryptoFactory capi(CryptoFactory::CAPI); #endif #ifdef GDCM_USE_SYSTEM_OPENSSL #ifdef GDCM_HAVE_CMS_RECIPIENT_PASSWORD static OpenSSLCryptoFactory ossl(CryptoFactory::OPENSSL); #endif static OpenSSLP7CryptoFactory osslp7(CryptoFactory::OPENSSLP7); #endif // If user specified DEFAULT: if( id == DEFAULT ) { #ifdef GDCM_USE_SYSTEM_OPENSSL #ifdef GDCM_HAVE_CMS_RECIPIENT_PASSWORD id = CryptoFactory::OPENSSL; #else id = CryptoFactory::OPENSSLP7; #endif // GDCM_HAVE_CMS_RECIPIENT_PASSWORD #endif // GDCM_USE_SYSTEM_OPENSSL // We always prefer native API (by default): #ifdef _WIN32 id = CryptoFactory::CAPI; #endif // _WIN32 } std::map::iterator it = getInstanceMap().find(id); if (it == getInstanceMap().end()) { gdcmErrorMacro( "No crypto factory registered with id " << (int)id ); return nullptr; } assert(it->second); return it->second; } } // end native gdcm GDCM-3.0.10/Source/Common/gdcmCryptoFactory.h000066400000000000000000000035671412732066400206310ustar00rootroot00000000000000/*========================================================================= 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 GDCMCRYPTOFACTORY_H #define GDCMCRYPTOFACTORY_H #include "gdcmCryptographicMessageSyntax.h" #include namespace gdcm { /** * \brief Class to do handle the crypto factory * \details GDCM needs to access in a platform independent way * the user specified crypto engine. It can be: * \li CAPI (windows only) * \li OPENSSL (portable) * \li OPENSSLP7 (portable) * By default the factory will try: * CAPI if on windows * OPENSSL if possible * OPENSSLP7 when older OpenSSL is used. */ class GDCM_EXPORT CryptoFactory { public: enum CryptoLib {DEFAULT = 0, OPENSSL = 1, CAPI = 2, OPENSSLP7 = 3}; virtual CryptographicMessageSyntax* CreateCMSProvider() = 0; static CryptoFactory* GetFactoryInstance(CryptoLib id = DEFAULT); protected: CryptoFactory(CryptoLib id) { AddLib(id, this); } private: static std::map& getInstanceMap() { static std::map libs; return libs; } static void AddLib(CryptoLib id, CryptoFactory* f) { if (getInstanceMap().insert(std::pair(id, f)).second == false) { gdcmErrorMacro( "Library already registered under id " << (int)id ); } } protected: CryptoFactory()= default; ~CryptoFactory()= default; }; } // end namespace gdcm #endif // GDCMCRYPTOFACTORY_H GDCM-3.0.10/Source/Common/gdcmCryptographicMessageSyntax.cxx000066400000000000000000000011401412732066400237070ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCryptographicMessageSyntax.h" GDCM-3.0.10/Source/Common/gdcmCryptographicMessageSyntax.h000066400000000000000000000034161412732066400233440ustar00rootroot00000000000000/*========================================================================= 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 GDCMCRYPTOGRAPHICMESSAGESYNTAX_H #define GDCMCRYPTOGRAPHICMESSAGESYNTAX_H #include "gdcmTypes.h" namespace gdcm { class GDCM_EXPORT CryptographicMessageSyntax { public: CryptographicMessageSyntax() = default; virtual ~CryptographicMessageSyntax() = default; CryptographicMessageSyntax(const CryptographicMessageSyntax&) = delete; void operator=(const CryptographicMessageSyntax&) = delete; typedef enum { DES3_CIPHER, // Triple DES AES128_CIPHER, // CBC AES AES192_CIPHER, // ' ' AES256_CIPHER // ' ' } CipherTypes; // X.509 virtual bool ParseCertificateFile( const char *filename ) = 0; virtual bool ParseKeyFile( const char *filename ) = 0; // PBE virtual bool SetPassword(const char * pass, size_t passLen) = 0; /// create a CMS envelopedData structure virtual bool Encrypt(char *output, size_t &outlen, const char *array, size_t len) const = 0; /// decrypt content from a CMS envelopedData structure virtual bool Decrypt(char *output, size_t &outlen, const char *array, size_t len) const = 0; virtual void SetCipherType(CipherTypes type) = 0; virtual CipherTypes GetCipherType() const = 0; }; } // end namespace gdcm #endif //GDCMCRYPTOGRAPHICMESSAGESYNTAX_H GDCM-3.0.10/Source/Common/gdcmDataEvent.cxx000066400000000000000000000011711412732066400202340ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDataEvent.h" namespace gdcm { } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmDataEvent.h000066400000000000000000000031011412732066400176540ustar00rootroot00000000000000/*========================================================================= 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 GDCMDATAEVENT_H #define GDCMDATAEVENT_H #include "gdcmEvent.h" namespace gdcm { /** * \brief DataEvent */ class DataEvent : public AnyEvent { public: typedef DataEvent Self; typedef AnyEvent Superclass; DataEvent(const char *bytes = nullptr, size_t len = 0):Bytes(bytes),Length(len) {} ~DataEvent() override = default; DataEvent(const Self&s) : AnyEvent(s){}; void operator=(const Self&) = delete; const char * GetEventName() const override { return "DataEvent"; } bool CheckEvent(const ::gdcm::Event* e) const override { return (dynamic_cast(e) == nullptr ? false : true) ; } ::gdcm::Event* MakeObject() const override { return new Self; } void SetData(const char *bytes, size_t len) { Bytes = bytes; Length = len; } size_t GetDataLength() const { return Length; } const char *GetData() const { return Bytes; } //std::string GetValueAsString() const { return; } private: const char *Bytes; size_t Length; }; } // end namespace gdcm #endif //GDCMDATAEVENT_H GDCM-3.0.10/Source/Common/gdcmDeflateStream.cxx000066400000000000000000000011471412732066400211040ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDeflateStream.h" namespace gdcm { } GDCM-3.0.10/Source/Common/gdcmDeflateStream.h000066400000000000000000000012461412732066400205310ustar00rootroot00000000000000/*========================================================================= 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 GDCMDEFLATESTREAM_H #define GDCMDEFLATESTREAM_H #include "zipstreamimpl.h" #endif //GDCMDEFLATESTREAM_H GDCM-3.0.10/Source/Common/gdcmDirectory.cxx000066400000000000000000000130661412732066400203330ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDirectory.h" #include "gdcmTrace.h" #include #include #include #include //stat function #include // strerror #ifdef _MSC_VER #include #include #else #include #include #endif namespace gdcm { unsigned int Directory::Load(FilenameType const &name, bool recursive) { Filenames.clear(); // clear previous Directories.clear(); // clear previous if( System::FileIsDirectory( name.c_str() ) ) { Toplevel = name; return Explore( Toplevel, recursive ); } return 0; } #ifdef _MSC_VER static inline std::string ToUtf8(std::wstring const &str) { std::string ret; int len = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), (int)str.length(), nullptr, 0, NULL, NULL); if (len > 0) { ret.resize(len); WideCharToMultiByte(CP_UTF8, 0, str.c_str(), (int)str.length(), &ret[0], len, NULL, NULL); } return ret; } #endif unsigned int Directory::Explore(FilenameType const &name, bool recursive) { unsigned int nFiles = 0; #ifdef _MSC_VER std::wstring fileName; 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] ); const std::wstring firstfile = dirName+L"*"; HANDLE hFile = FindFirstFileW(firstfile.c_str(), &fileData); for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b; b = FindNextFileW(hFile, &fileData)) { fileName = fileData.cFileName; if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) { // Need to check for . and .. to avoid infinite loop if ( fileName != L"." && fileName != L".." && fileName[0] != '.' // discard any hidden dir && recursive ) { nFiles += Explore(ToUtf8(dirName + fileName), recursive); } } else { if (fileName[0] != '.') // discard "unix like" hidden files such as .git in submodules { Filenames.push_back(ToUtf8(dirName+fileName)); nFiles++; } } } DWORD dwError = GetLastError(); if (hFile != INVALID_HANDLE_VALUE) FindClose(hFile); if (dwError != ERROR_NO_MORE_FILES) { //gdcmErrorMacro("FindNextFile error. Error is " << dwError); return 0; } #else std::string fileName; std::string dirName = name; // assert( System::FileIsDirectory( dirName ) ); Directories.push_back(dirName); // Real POSIX implementation: scandir is a BSD extension only, and doesn't // work on debian for example DIR* dir = opendir(dirName.c_str()); if (!dir) { const char *str = strerror(errno); (void)str; gdcmErrorMacro( "Error was: " << str << " when opening directory: " << dirName ); return 0; } // According to POSIX, the dirent structure contains a field char d_name[] // of unspecified size, with at most NAME_MAX characters preceding the // terminating null character. Use of other fields will harm the porta- // bility of your programs. struct stat buf; dirent *d; if ('/' != dirName[dirName.size()-1]) dirName.push_back('/'); assert( '/' == dirName[dirName.size()-1] ); for (d = readdir(dir); d; d = readdir(dir)) { fileName = dirName + d->d_name; if( stat(fileName.c_str(), &buf) != 0 ) { const char *str = strerror(errno); (void)str; gdcmErrorMacro( "Last Error was: " << str << " for file: " << fileName ); break; } if ( S_ISREG(buf.st_mode) ) //is it a regular file? { if( d->d_name[0] != '.' ) { Filenames.push_back( fileName ); nFiles++; } } else if ( S_ISDIR(buf.st_mode) ) //directory? { // discard . and .. if( strcmp( d->d_name, "." ) == 0 || strcmp( d->d_name, ".." ) == 0 || d->d_name[0] == '.' ) // discard any hidden dir continue; assert( d->d_name[0] != '.' ); // hidden directory ?? if ( recursive ) { nFiles += Explore( fileName, recursive); } } else { gdcmErrorMacro( "Unexpected type for file: " << fileName ); break; } } if( closedir(dir) != 0 ) { const char *str = strerror(errno); (void)str; gdcmErrorMacro( "Last error was: " << str << " when closing directory: " << fileName ); } #endif return nFiles; } void Directory::Print(std::ostream &_os) const { // FIXME Both structures are FilenamesType I could factorize the code _os << "Directories: "; if( Directories.empty() ) _os << "(None)" << std::endl; else { std::copy(Directories.begin(), Directories.end(), std::ostream_iterator(_os << std::endl, "\n")); } _os << "Filenames: "; if( Filenames.empty() ) _os << "(None)" << std::endl; else { std::copy(Filenames.begin(), Filenames.end(), std::ostream_iterator(_os << std::endl, "\n")); } } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmDirectory.h000066400000000000000000000061431412732066400177560ustar00rootroot00000000000000/*========================================================================= 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 GDCMDIRECTORY_H #define GDCMDIRECTORY_H #include "gdcmTypes.h" #include #include #include #include namespace gdcm { /** * \brief Class for manipulation directories * * \note This implementation provide a cross platform implementation * for manipulating directories: basically traversing directories * and harvesting files * * \note * will not take into account unix type hidden file * recursive option will not look into UNIX type hidden directory (those starting with a '.') * * \note * Since python or C# provide there own equivalent implementation, * in which case gdcm::Directory does not make much sense. */ //----------------------------------------------------------------------------- class GDCM_EXPORT Directory { friend std::ostream& operator<<(std::ostream &_os, const Directory &d); public : Directory() = default; ~Directory() = default; typedef std::string FilenameType; typedef std::vector FilenamesType; /// Print void Print(std::ostream &os = std::cout) const; /// Get the name of the toplevel directory FilenameType const &GetToplevel() const { return Toplevel; } /// Set/Get the file names within the directory FilenamesType const &GetFilenames() const { assert( !(Toplevel.empty()) && "Need to call Explore first" ); return Filenames; } /// Return the Directories traversed FilenamesType const &GetDirectories() const { return Directories; } /// construct a list of filenames and subdirectory beneath directory: name /// \warning: hidden file and hidden directory are not loaded. unsigned int Load(FilenameType const &name, bool recursive = false); // \todo later: GLOB // The glob() function searches for all the pathnames matching pattern according to // the rules used by the shell (see glob(7)). No tilde expansion or parameter // substitution is done; if you want these, use wordexp(3). // int Glob(...); protected: /// Return number of file found when 'recursive'ly exploring directory `name` unsigned int Explore(FilenameType const &name, bool recursive); private : /// List of file names FilenamesType Filenames; FilenamesType Directories; /// name of the toplevel directory to explore FilenameType Toplevel; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const Directory &d) { d.Print( os ); return os; } } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMDIRECTORY_H GDCM-3.0.10/Source/Common/gdcmDummyValueGenerator.cxx000066400000000000000000000021521412732066400223200ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDummyValueGenerator.h" #include "gdcmTrace.h" #include "gdcmSystem.h" #include "gdcmSHA1.h" #include "gdcmMD5.h" #include // strlen namespace gdcm { const char* DummyValueGenerator::Generate(const char *input) { static char digest[2*20+1] = {}; bool b = false; if( input ) { // Cannot use MD5 as it has been broken multiple time (2005) b = MD5::Compute(input, strlen(input), digest); //b = SHA1::Compute(input, strlen(input), digest); } if( b ) return digest; return nullptr; } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmDummyValueGenerator.h000066400000000000000000000022331412732066400217450ustar00rootroot00000000000000/*========================================================================= 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 GDCMDUMMYVALUEGENERATOR_H #define GDCMDUMMYVALUEGENERATOR_H #include "gdcmTypes.h" namespace gdcm { /** * \brief Class for generating dummy value * \see Anonymizer */ class GDCM_EXPORT DummyValueGenerator { public: /** Generate a dummy value from an input value. This is guarantee to always * return the same output value when input is identical. Return an array of * bytes that can be used for anonymization purpose, return NULL on error * NOT THREAD SAFE */ static const char* Generate(const char *input); private: }; } // end namespace gdcm #endif //GDCMDUMMYVALUEGENERATOR_H GDCM-3.0.10/Source/Common/gdcmEvent.cxx000066400000000000000000000014331412732066400174430ustar00rootroot00000000000000/*========================================================================= 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 "gdcmEvent.h" namespace gdcm { Event::Event() = default; Event::Event(const Event&) = default; Event::~Event() = default; void Event::Print(std::ostream& os) const { os << GetEventName(); } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmEvent.h000066400000000000000000000061151412732066400170720ustar00rootroot00000000000000/*========================================================================= 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 GDCMEVENT_H #define GDCMEVENT_H #include "gdcmTypes.h" namespace gdcm { //----------------------------------------------------------------------------- /** * \brief superclass for callback/observer methods * \see Command Subject */ class GDCM_EXPORT Event { public : Event(); virtual ~Event(); Event(const Event&); void operator=(const Event&) = delete; /** Create an Event of this type This method work as a Factory for * creating events of each particular type. */ virtual Event* MakeObject() const = 0; /** Print Event information. This method can be overridden by * specific Event subtypes. The default is to print out the type of * the event. */ virtual void Print(std::ostream& os) const; /** Return the StringName associated with the event. */ virtual const char * GetEventName() const = 0; /** Check if given event matches or derives from this event. */ virtual bool CheckEvent(const Event*) const = 0; }; /// Generic inserter operator for Event and its subclasses. inline std::ostream& operator<<(std::ostream& os, Event &e) { e.Print(os); return os; } /* * Macro for creating new Events */ #define gdcmEventMacro( classname , super ) \ /** \brief classname */ \ class classname : public super { \ public: \ typedef classname Self; \ typedef super Superclass; \ classname() {} \ virtual ~classname() override = default; \ virtual const char * GetEventName() const override { return #classname; } \ virtual bool CheckEvent(const ::gdcm::Event* e) const override \ { return dynamic_cast(e) ? true : false; } \ virtual ::gdcm::Event* MakeObject() const override \ { return new Self; } \ classname(const Self&s) : super(s){}; \ private: \ void operator=(const Self&); \ } /** * Define some common GDCM events */ gdcmEventMacro( NoEvent , Event ); gdcmEventMacro( AnyEvent , Event ); gdcmEventMacro( StartEvent , AnyEvent ); gdcmEventMacro( EndEvent , AnyEvent ); //gdcmEventMacro( ProgressEvent , AnyEvent ); gdcmEventMacro( ExitEvent , AnyEvent ); gdcmEventMacro( AbortEvent , AnyEvent ); gdcmEventMacro( ModifiedEvent , AnyEvent ); gdcmEventMacro( InitializeEvent , AnyEvent ); gdcmEventMacro( IterationEvent , AnyEvent ); //gdcmEventMacro( AnonymizeEvent , AnyEvent ); gdcmEventMacro( UserEvent , AnyEvent ); } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMEVENT_H GDCM-3.0.10/Source/Common/gdcmException.cxx000066400000000000000000000011721412732066400203200ustar00rootroot00000000000000/*========================================================================= 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 "gdcmException.h" namespace gdcm { } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmException.h000066400000000000000000000064131412732066400177500ustar00rootroot00000000000000/*========================================================================= 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 GDCMEXCEPTION_H #define GDCMEXCEPTION_H #include #include // NULL #include #include // ostringstream #include // logic_error #include // Disable clang warning "dynamic exception specifications are deprecated". // We need to be C++03 and C++11 compatible, and if we remove the 'throw()' // specifier we'll get an error in C++03 by not matching the superclass. #if defined(__clang__) && defined(__has_warning) # if __has_warning("-Wdeprecated") # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wdeprecated" # endif #endif namespace gdcm { /** * \brief Exception * \details Standard exception handling object. * \note Its copy-constructor and assignment operator are generated by the * compiler. */ class Exception : public std::exception { /// std::logic_error is used to internally hold a string. /// It has the nice property of having a copy-constructor /// that never fails. Thereby it provides the same guarantee to /// the copy-constructor of gdcm::Exception. typedef std::logic_error StringHolder; /// Creates the text to be returned by Exception:what(). static StringHolder CreateWhat(const char* const desc, const char* const file, const unsigned int lineNumber, const char* const func) { assert(desc != nullptr); assert(file != nullptr); assert(func != nullptr); std::ostringstream oswhat; oswhat << file << ":" << lineNumber << " (" << func << "):\n"; oswhat << desc; return StringHolder( oswhat.str() ); } public: /// Explicit constructor, initializing the description and the /// text returned by what(). /// \note The last parameter is ignored for the time being. /// It may be used to specify the function where the exception /// was thrown. explicit Exception(const char *desc = "None", const char *file = __FILE__, unsigned int lineNumber = __LINE__, // FIXME: __PRETTY_FUNCTION__ is the non-mangled version for __GNUC__ compiler const char *func = "" /*__FUNCTION__*/) : What( CreateWhat(desc, file, lineNumber, func) ), Description(desc) { } ~Exception() throw() override {} /// what implementation const char* what() const throw() override { return What.what(); } /// Return the Description const char * GetDescription() const { return Description.what(); } private: StringHolder What; StringHolder Description; }; } // end namespace gdcm // Undo warning suppression. #if defined(__clang__) && defined(__has_warning) # if __has_warning("-Wdeprecated") # pragma clang diagnostic pop # endif #endif #endif GDCM-3.0.10/Source/Common/gdcmFileNameEvent.cxx000066400000000000000000000011751412732066400210470ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileNameEvent.h" namespace gdcm { } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmFileNameEvent.h000066400000000000000000000030501412732066400204660ustar00rootroot00000000000000/*========================================================================= 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 GDCMFILENAMEEVENT_H #define GDCMFILENAMEEVENT_H #include "gdcmEvent.h" #include "gdcmTag.h" namespace gdcm { /** * \brief FileNameEvent * \details Special type of event triggered during processing of FileSet * * \see AnyEvent */ class FileNameEvent : public AnyEvent { public: typedef FileNameEvent Self; typedef AnyEvent Superclass; FileNameEvent(const char *s = ""):m_FileName(s) {} ~FileNameEvent() override = default; FileNameEvent(const Self&s) : AnyEvent(s){}; void operator=(const Self&) = delete; const char * GetEventName() const override { return "FileNameEvent"; } bool CheckEvent(const ::gdcm::Event* e) const override { return dynamic_cast(e) ? true : false; } ::gdcm::Event* MakeObject() const override { return new Self; } void SetFileName(const char *f) { m_FileName = f; } const char *GetFileName() const { return m_FileName.c_str(); } private: std::string m_FileName; }; } // end namespace gdcm #endif //GDCMFILENAMEEVENT_H GDCM-3.0.10/Source/Common/gdcmFilename.cxx000066400000000000000000000104531412732066400201040ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFilename.h" #include #include // realpath #include #include namespace gdcm { /** * Return path of a full filename (no trailing slashes). * Warning: returned path is converted to Unix slashes format. */ const char *Filename::GetPath() { std::string fn = ToUnixSlashes(); std::string::size_type slash_pos = fn.rfind("/"); if(slash_pos != std::string::npos) { Path = fn.substr(0, slash_pos); } else { Path = ""; } return Path.c_str(); } /** * Return file name of a full filename (i.e. file name without path). */ const char *Filename::GetName() { std::string filename = FileName; assert( !filename.empty() ); #if defined(_WIN32) std::string::size_type slash_pos = filename.find_last_of("/\\"); #else 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[0]; } const char *Filename::ToWindowsSlashes() { Conversion = FileName; //assert( !Conversion.empty() ); for (std::string::iterator it = Conversion.begin(); it != Conversion.end(); ++it ) { if( *it == '/' ) { *it = '\\'; } } return Conversion.c_str(); } // convert windows slashes to unix slashes const char *Filename::ToUnixSlashes() { Conversion = FileName; //std::string::size_type s = Conversion.find("\\"); //assert( s == std::string::npos ); assert( !Conversion.empty() ); for (std::string::iterator it = Conversion.begin(); it != Conversion.end(); ++it ) { if( *it == '\\' ) { assert( it+1 == Conversion.end() || *(it+1) != ' ' ); // is it an escaped space ? *it = '/'; } } return Conversion.c_str(); } #if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__MINGW32__)) #include inline void Realpath(const char *path, std::string & resolved_path) { char *ptemp; char fullpath[MAX_PATH]; if( GetFullPathName(path, sizeof(fullpath), fullpath, &ptemp) ) { Filename fn( fullpath ); resolved_path = fn.ToUnixSlashes(); } else { resolved_path = ""; } } #else /* The maximum length of a file name. */ #if defined(PATH_MAX) # define GDCM_FILENAME_MAXPATH PATH_MAX #elif defined(MAXPATHLEN) # define GDCM_FILENAME_MAXPATH MAXPATHLEN #else # define GDCM_FILENAME_MAXPATH 16384 #endif inline void Realpath(const char *path, std::string & resolved_path) { char resolved_name[GDCM_FILENAME_MAXPATH]; char *ret = realpath(path, resolved_name); if( ret ) { resolved_path = resolved_name; } else { resolved_path = ""; } } #endif const char *Filename::GetExtension() { std::string name = GetName(); std::string::size_type dot_pos = name.rfind("."); if(dot_pos != std::string::npos) { return GetName() + dot_pos; } return nullptr; } bool Filename::IsIdentical(Filename const &fn) const { std::string realpath1; std::string realpath2; Realpath(FileName.c_str(), realpath1); Realpath(fn.GetFileName(), realpath2); gdcmDebugMacro( "IsIdentical: " << realpath1 << " vs " << realpath2 ); return realpath1 == realpath2; } const char *Filename::Join(const char *path, const char *filename) { static std::string s; // warning C4640: 's' : construction of local static object is not thread-safe s = path; s += '/'; s += filename; return s.c_str(); } bool Filename::EndWith(const char ending[]) const { if( !ending ) return false; const char *str = FileName.c_str(); size_t str_len = FileName.size(); size_t ending_len = strlen(ending); if(ending_len > str_len) return false; return 0 == strncmp( str + str_len - ending_len, ending, ending_len ); } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmFilename.h000066400000000000000000000044161412732066400175330ustar00rootroot00000000000000/*========================================================================= 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 GDCMFILENAME_H #define GDCMFILENAME_H #include "gdcmTypes.h" #include namespace gdcm { /** * \brief Class to manipulate file name's * \note OS independent representation of a filename (to query path, name and extension from a filename) */ class GDCM_EXPORT Filename { public: Filename(const char* filename = ""):FileName(filename ? filename : ""),Path(),Conversion() {} /// Return the full filename const char *GetFileName() const { return FileName.c_str(); } /// Return only the path component of a filename const char *GetPath(); /// return only the name part of a filename const char *GetName(); /// return only the extension part of a filename const char *GetExtension(); /// Convert backslash (windows style) to UNIX style slash. const char *ToUnixSlashes(); /// Convert forward slash (UNIX style) to windows style slash. const char *ToWindowsSlashes(); /// Join two paths /// NOT THREAD SAFE static const char *Join(const char *path, const char *filename); /// return whether the filename is empty bool IsEmpty() const { return FileName.empty(); } /// Simple operator to allow /// Filename myfilename( "..." ); /// const char * s = myfilename; operator const char * () const { return GetFileName(); } // FIXME: I don't like this function // It hides the realpath call (maybe useful) // and it forces file to exist on the disk whereas Filename // should be independent from file existence. bool IsIdentical(Filename const &fn) const; /// Does the filename ends with a particular string ? bool EndWith(const char ending[]) const; private: std::string FileName; std::string Path; std::string Conversion; }; } // end namespace gdcm #endif //GDCMFILENAME_H GDCM-3.0.10/Source/Common/gdcmFilenameGenerator.cxx000066400000000000000000000064541412732066400217610ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFilenameGenerator.h" #include "gdcmTrace.h" #include // strchr #include // snprintf #if defined(_MSC_VER) && (_MSC_VER < 1900) #define snprintf _snprintf #endif namespace gdcm { //----------------------------------------------------------------------------- FilenameGenerator::SizeType FilenameGenerator::GetNumberOfFilenames() const { return Filenames.size(); } //----------------------------------------------------------------------------- void FilenameGenerator::SetNumberOfFilenames(SizeType nfiles) { Filenames.resize( nfiles ); } //----------------------------------------------------------------------------- const char * FilenameGenerator::GetFilename(SizeType n) const { if( n < Filenames.size() ) return Filenames[n].c_str(); return nullptr; } //----------------------------------------------------------------------------- bool FilenameGenerator::Generate() { if( Pattern.empty() && Prefix.empty() ) { return false; } else if( Pattern.empty() && !Prefix.empty() ) // no pattern but a prefix { const SizeType numfiles = Filenames.size(); for( SizeType i = 0; i < numfiles; ++i) { std::ostringstream os; os << Prefix; os << i; Filenames[i] = os.str(); } return true; } else if( !Pattern.empty() ) { std::string::size_type pat_len = Pattern.size(); const SizeType padding = 10; // FIXME is this large enough for all cases ? const SizeType internal_len = pat_len + padding; const SizeType numfiles = Filenames.size(); if( numfiles == 0 ) { gdcmDebugMacro( "Need to specify the number of files" ); // I am pretty sure this is an error: return false; } const char *pattern = Pattern.c_str(); int num_percent = 0; while( (pattern = strchr( pattern, '%')) ) { ++pattern; ++num_percent; } if ( num_percent != 1 ) { // Bug: what if someone wants to output file such as %%%02 ... oh well gdcmDebugMacro( "No more than one % in string formatting please" ); return false; } bool success = true; char *internal = new char[internal_len]; for( SizeType i = 0; i < numfiles && success; ++i) { int res = snprintf( internal, internal_len, Pattern.c_str(), i ); assert( res >= 0 ); success = (SizeType)res < internal_len; if( Pattern.empty() ) { Filenames[i] = internal; } else { Filenames[i] = Prefix + internal; } //assert( Filenames[i].size() == res ); // upon success only } delete[] internal; if( !success ) { Filenames.clear(); // invalidate size too ?? } return success; } return false; } } // namespace gdcm GDCM-3.0.10/Source/Common/gdcmFilenameGenerator.h000066400000000000000000000041511412732066400213760ustar00rootroot00000000000000/*========================================================================= 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 GDCMFILENAMEGENERATOR_H #define GDCMFILENAMEGENERATOR_H #include "gdcmTypes.h" #include #include namespace gdcm { /** * \brief FilenameGenerator * \details class to generate filenames based on a pattern (C-style) * * Output will be: * * for i = 0, number of filenames: * outfilename[i] = prefix + (pattern % i) * * where pattern % i means C-style snprintf of Pattern using value 'i' */ class GDCM_EXPORT FilenameGenerator { public: FilenameGenerator():Pattern(),Prefix(),Filenames() {} ~FilenameGenerator() = default; // FIXME: already defines in gdcm::Directory typedef std::string FilenameType; typedef std::vector FilenamesType; typedef FilenamesType::size_type SizeType; /// Set/Get pattern void SetPattern(const char *pattern) { Pattern = pattern; } const char *GetPattern() const { return Pattern.c_str(); } /// Set/Get prefix void SetPrefix(const char *prefix) { Prefix = prefix; } const char *GetPrefix() const { return Prefix.c_str(); } /// Generate (return success) bool Generate(); /// Set/Get the number of filenames to generate void SetNumberOfFilenames(SizeType nfiles); SizeType GetNumberOfFilenames() const; /// Get a particular filename (call after Generate) const char * GetFilename(SizeType n) const; /// Return all filenames FilenamesType const & GetFilenames() const { assert( !Pattern.empty() ); return Filenames; } private: FilenameType Pattern; FilenameType Prefix; FilenamesType Filenames; }; } // end namespace gdcm #endif //GDCMFILENAMEGENERATOR_H GDCM-3.0.10/Source/Common/gdcmLegacyMacro.h000066400000000000000000000064101412732066400201750ustar00rootroot00000000000000/*========================================================================= 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 GDCMLEGACYMACRO_H #define GDCMLEGACYMACRO_H #if !defined(GDCMTYPES_H) && !defined(SWIG) #error you need to include gdcmTypes.h instead #endif #include "gdcmException.h" //---------------------------------------------------------------------------- // Setup legacy code policy. // Define GDCM_LEGACY macro to mark legacy methods where they are // declared in their class. Example usage: // // // @deprecated Replaced by MyOtherMethod() as of GDCM 2.0. // GDCM_LEGACY(void MyMethod()); #if defined(GDCM_LEGACY_REMOVE) # define GDCM_LEGACY(method) #elif defined(GDCM_LEGACY_SILENT) || defined(SWIG) // Provide legacy methods with no warnings. # define GDCM_LEGACY(method) method; #else // Setup compile-time warnings for uses of deprecated methods if // possible on this compiler. # if defined(__GNUC__) && !defined(__INTEL_COMPILER) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) # define GDCM_LEGACY(method) method __attribute__((deprecated)); # elif defined(_MSC_VER) && _MSC_VER >= 1300 # define GDCM_LEGACY(method) __declspec(deprecated) method; # else # define GDCM_LEGACY(method) method; # endif #endif /** The `static_assert(true, "")` idiom is commonly employed for * C++11 or greater to ensure that it is compile-time only * check that can not be part of the binary file. * This allows a macro to be used anywhere that a statement * is expected, and to enforce consistent use of ; after * a macro. The static_assert is a constexpr that can be used * in places where raw statements (i.e. 'do{} while(0)') are * not allowed (i.e. after class member function definitions). * */ # define GDCM_NOOP_STATEMENT static_assert(true, "") // Macros to create runtime deprecation warning messages in function // bodies. Example usage: // // #if !defined(GDCM_LEGACY_REMOVE) // void gdcm::MyClass::MyOldMethod() // { // GDCM_LEGACY_BODY(gdcm::MyClass::MyOldMethod, "GDCM 2.0"); // } // #endif // // #if !defined(GDCM_LEGACY_REMOVE) // void gdcm::MyClass::MyMethod() // { // GDCM_LEGACY_REPLACED_BODY(gdcm::MyClass::MyMethod, "GDCM 2.0", // gdcm::MyClass::MyOtherMethod); // } // #endif #if defined(GDCM_LEGACY_REMOVE) || defined(GDCM_LEGACY_SILENT) # define GDCM_LEGACY_BODY(method, version) # define GDCM_LEGACY_REPLACED_BODY(method, version, replace) #else # define GDCM_LEGACY_BODY(method, version) \ gdcmWarningMacro(#method " was deprecated for " version " and will be removed in a future version.") # define GDCM_LEGACY_REPLACED_BODY(method, version, replace) \ gdcmWarningMacro(#method " was deprecated for " version " and will be removed in a future version. Use " #replace " instead.") #endif #include "gdcmTrace.h" #endif // GDCMLEGACYMACRO_H GDCM-3.0.10/Source/Common/gdcmMD5.cxx000066400000000000000000000062731412732066400167560ustar00rootroot00000000000000/*========================================================================= 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 "gdcmMD5.h" #include "gdcmSystem.h" #ifdef GDCM_USE_SYSTEM_OPENSSL #include #elif defined(GDCM_BUILD_TESTING) #include "gdcm_md5.h" #endif #include #include // http://stackoverflow.com/questions/13256446/compute-md5-hash-value-by-c-winapi namespace gdcm { bool MD5::Compute(const char *buffer, size_t buf_len, char digest_str[33]) { if( !buffer || !buf_len ) { return false; } #ifdef GDCM_USE_SYSTEM_OPENSSL unsigned char digest[16]; MD5_CTX ctx; MD5_Init(&ctx); 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]); digest_str[2*16] = '\0'; return true; #elif defined(GDCM_BUILD_TESTING) md5_byte_t digest[16]; md5_state_t state; md5_init(&state); md5_append(&state, (const md5_byte_t *)buffer, (int)buf_len); md5_finish(&state, digest); for (int di = 0; di < 16; ++di) sprintf(digest_str+2*di, "%02x", digest[di]); digest_str[2*16] = '\0'; return true; #else (void)digest_str; return false; #endif } #ifdef GDCM_USE_SYSTEM_OPENSSL static bool process_file(const char *filename, unsigned char *digest) { if( !filename || !digest ) return false; std::ifstream file(filename, std::ios::binary); if(!file) return false; const size_t file_size = System::FileSize(filename); std::vector v( file_size ); char *buffer = &v[0]; file.read(buffer, file_size); MD5_CTX ctx; MD5_Init(&ctx); MD5_Update(&ctx, buffer, file_size); MD5_Final(digest, &ctx); return true; } #elif defined(GDCM_BUILD_TESTING) static bool process_file(const char *filename, md5_byte_t *digest) { if( !filename || !digest ) return false; std::ifstream file(filename, std::ios::binary); if(!file) return false; const size_t file_size = System::FileSize(filename); std::vector v( file_size ); char *buffer = &v[0]; file.read(buffer, file_size); md5_state_t state; md5_init(&state); md5_append(&state, (const md5_byte_t *)buffer, (int)file_size); md5_finish(&state, digest); return true; } #else static inline bool process_file(const char *, unsigned char *) { return false; } #endif bool MD5::ComputeFile(const char *filename, char digest_str[33]) { #ifdef GDCM_USE_SYSTEM_OPENSSL unsigned char digest[16]; #elif defined(GDCM_BUILD_TESTING) md5_byte_t digest[16]; #else unsigned char digest[16] = {}; #endif /* Do the file */ if( !process_file(filename, digest) ) { return false; } for (int di = 0; di < 16; ++di) { sprintf(digest_str+2*di, "%02x", digest[di]); } digest_str[2*16] = '\0'; return true; } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmMD5.h000066400000000000000000000026421412732066400163770ustar00rootroot00000000000000/*========================================================================= 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 GDCMMD5_H #define GDCMMD5_H #include "gdcmTypes.h" namespace gdcm { //----------------------------------------------------------------------------- /** * \brief Class for MD5 * * \warning this class is able to pick from two implementations: * * 1. a lightweight md5 implementation (when GDCM_BUILD_TESTING is turned ON) * 2. the one from OpenSSL (when GDCM_USE_SYSTEM_OPENSSL is turned ON) * * In all other cases it will return an error */ class GDCM_EXPORT MD5 { public : // Compute md5 from memory pointed by `pointer` of size `buf_len` static bool Compute(const char *buffer, size_t buf_len, char digest_str[33]); /// Compute md5 from a file `filename` static bool ComputeFile(const char *filename, char digest_str[33]); }; } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMMD5_H GDCM-3.0.10/Source/Common/gdcmObject.cxx000066400000000000000000000016001412732066400175640ustar00rootroot00000000000000/*========================================================================= 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 "gdcmObject.h" namespace gdcm { // Don't ask why, but this is EXTREMELY important on Win32 // Apparently the compiler is doing something special the first time it compiles // this instantiation unit // If this fake file is not present I get an unresolved symbol for each function // of the gdcm::Object class } GDCM-3.0.10/Source/Common/gdcmObject.h000066400000000000000000000057541412732066400172270ustar00rootroot00000000000000/*========================================================================= 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 GDCMOBJECT_H #define GDCMOBJECT_H #include "gdcmTypes.h" #include #include // grrrr //namespace std { class ostream; } namespace gdcm { template class SmartPointer; /** * \brief Object * * \note main superclass for object that want to use SmartPointer * invasive ref counting system * * \see SmartPointer */ class GDCM_EXPORT Object { template friend class SmartPointer; friend std::ostream& operator<<(std::ostream &os, const Object &obj); public: Object():ReferenceCount(0) {} // Implementation note: // If I move ~Object in the protected section I can prevent people // from writing: // SmartPointer p = new Object; // delete p; // due to SmartPointer::operator ObjectType * () const // but on the other hand one could not define an Object on the stack // Object obj; // Furthermore it would not prevent anyone from doing: // class MyObject : public Object {}; // SmartPointer o = new MyObject; // delete o; // grrrrrr virtual ~Object() { // If your debugger reach here it means you are doing something silly // like using SmartPointer on object allocated on the stack (vs heap) assert(ReferenceCount == 0); } // http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.24 // Set the ref count to 0 // Do NOT copy the reference count ! /// Special requirement for copy/cstor, assignment operator Object(const Object&):ReferenceCount(0){} void operator=(const Object&){} //static Object* New() { return new Object; } protected: // For the purpose of the invasive SmartPointer implementation void Register() { ReferenceCount++; assert( ReferenceCount > 0 ); } void UnRegister() { assert( ReferenceCount > 0 ); ReferenceCount--; if(!ReferenceCount) { delete this; } } public: // For dealing with printing of object and polymorphism virtual void Print(std::ostream &) const {} private: long ReferenceCount; }; //---------------------------------------------------------------------------- // function do not carry vtable. Thus define in the base class the operator // and use the member function ->Print() to call the appropriate function // NOTE: All subclass of Object needs to implement the Print function inline std::ostream& operator<<(std::ostream &os, const Object &obj) { obj.Print(os); return os; } } // end namespace gdcm #endif //GDCMOBJECT_H GDCM-3.0.10/Source/Common/gdcmOpenSSLCryptoFactory.cxx000066400000000000000000000016021412732066400223740ustar00rootroot00000000000000/*========================================================================= 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 "gdcmOpenSSLCryptoFactory.h" #include #include namespace gdcm { void OpenSSLCryptoFactory::InitOpenSSL() { static bool Initialized = false; if (!Initialized) { OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); Initialized = true; } } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmOpenSSLCryptoFactory.h000066400000000000000000000022641412732066400220260ustar00rootroot00000000000000/*========================================================================= 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 GDCMOPENSSLCRYPTOFACTORY_H #define GDCMOPENSSLCRYPTOFACTORY_H #include "gdcmCryptoFactory.h" #include "gdcmOpenSSLCryptographicMessageSyntax.h" namespace gdcm { class GDCM_EXPORT OpenSSLCryptoFactory : public CryptoFactory { public: OpenSSLCryptoFactory(CryptoLib id) : CryptoFactory(id) { gdcmDebugMacro( "OpenSSL Factory registered." ); } public: CryptographicMessageSyntax* CreateCMSProvider() { InitOpenSSL(); return new OpenSSLCryptographicMessageSyntax(); } protected: void InitOpenSSL(); private: OpenSSLCryptoFactory(){} }; } // end namespace gdcm #endif //GDCMOPENSSLCRYPTOFACTORY_H GDCM-3.0.10/Source/Common/gdcmOpenSSLCryptographicMessageSyntax.cxx000066400000000000000000000157321412732066400251270ustar00rootroot00000000000000/*========================================================================= 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 "gdcmOpenSSLCryptographicMessageSyntax.h" #include // numeric_limits #include // memcpy #include #include #include #include #include #include namespace gdcm { OpenSSLCryptographicMessageSyntax::OpenSSLCryptographicMessageSyntax() : recips(sk_X509_new_null()), pkey(NULL), password(NULL) { cipherType = AES128_CIPHER; internalCipherType = CreateCipher(cipherType); } OpenSSLCryptographicMessageSyntax::~OpenSSLCryptographicMessageSyntax() { EVP_PKEY_free(pkey); sk_X509_free(recips); if (password) delete[] password; } void OpenSSLCryptographicMessageSyntax::SetCipherType( CryptographicMessageSyntax::CipherTypes type ) { internalCipherType = CreateCipher(type); cipherType = type; } CryptographicMessageSyntax::CipherTypes OpenSSLCryptographicMessageSyntax::GetCipherType() const { return cipherType; } bool OpenSSLCryptographicMessageSyntax::SetPassword(const char * pass, size_t passLen) { assert(pass); if (password) { delete[] password; } passwordLength = passLen; password = new char[passLen]; memcpy(password, pass, passLen); return true; } bool OpenSSLCryptographicMessageSyntax::Encrypt(char *output, size_t &outlen, const char *array, size_t len) const { BIO *in = NULL, *out = NULL; CMS_ContentInfo *cms = NULL; int flags = CMS_BINARY | CMS_PARTIAL; bool ret = false; if (!password && ::sk_X509_num(recips) == 0) { gdcmErrorMacro( "No password or recipients added." ); goto err; } // RAND_status() and RAND_event() return 1 if the PRNG has been seeded with // enough data, 0 otherwise. if( !RAND_status() ) { gdcmErrorMacro( "PRNG was not seeded properly" ); goto err; } if( len > (size_t)std::numeric_limits::max() ) { gdcmErrorMacro( "len is too big: " << len ); goto err; } in = BIO_new_mem_buf((const void*)array, (int)len); if(!in) { gdcmErrorMacro( "Error at creating the input memory buffer." ); goto err; } out = BIO_new(BIO_s_mem()); if (!out) { gdcmErrorMacro( "Error at creating the output memory buffer." ); goto err; } cms = CMS_encrypt(recips, in, internalCipherType, flags); if (!cms) { gdcmErrorMacro( "Error at creating the CMS structure." ); goto err; } if (password) { unsigned char* pwri_tmp = (unsigned char *)BUF_memdup(password, passwordLength); if (!pwri_tmp) goto err; if (!CMS_add0_recipient_password(cms, -1, NID_undef, NID_undef, pwri_tmp, passwordLength, NULL)) goto err; pwri_tmp = NULL; } if (!CMS_final(cms, in, NULL, flags)) goto err; if (! i2d_CMS_bio(out, cms)) { gdcmErrorMacro( "Error at writing CMS structure to output." ); goto err; } BUF_MEM *bptr; BIO_get_mem_ptr(out, &bptr); if (bptr->length > outlen) { gdcmErrorMacro( "Supplied output buffer too small: " << bptr->length << " bytes needed." ); goto err; } memcpy(output, bptr->data, bptr->length); outlen = bptr->length; ret = true; err: if (!ret) { outlen = 0; gdcmErrorMacro( ERR_error_string(ERR_peek_error(), NULL) ); } if (cms) CMS_ContentInfo_free(cms); if (in) BIO_free(in); if (out) BIO_free(out); return ret; } bool OpenSSLCryptographicMessageSyntax::Decrypt(char *output, size_t &outlen, const char *array, size_t len) const { BIO *in = NULL, *out = NULL; CMS_ContentInfo *cms = NULL; bool ret = false; int flags = /*CMS_DETACHED | */CMS_BINARY; if (!password && pkey == NULL) { gdcmErrorMacro( "No password or private key specified." ); goto err; } in = BIO_new_mem_buf((const void*)array, (int)len); if (!in) { gdcmErrorMacro( "Error at creating the input memory buffer." ); goto err; } cms = d2i_CMS_bio(in, NULL); if (!cms) { gdcmErrorMacro( "Error when parsing the CMS structure." ); goto err; } out = BIO_new(BIO_s_mem()); if (!out) { gdcmErrorMacro( "Error at creating the output memory buffer." ); goto err; } if (password) if (!CMS_decrypt_set1_password(cms, (unsigned char*)password, passwordLength)) { gdcmErrorMacro( "Error at setting the decryption password." ); goto err; } if (!CMS_decrypt(cms, pkey, NULL, NULL, out, flags)) { gdcmErrorMacro( "Error at decrypting CMS structure" ); goto err; } BUF_MEM *bptr; BIO_get_mem_ptr(out, &bptr); if (bptr->length > outlen) { gdcmErrorMacro( "Supplied output buffer too small: " << bptr->length << " bytes needed." ); goto err; } memcpy(output, bptr->data, bptr->length); outlen = bptr->length; ret = true; err: if (!ret) { outlen = 0; gdcmErrorMacro( ERR_error_string(ERR_peek_error(), NULL) ); } if (cms) CMS_ContentInfo_free(cms); if (in) BIO_free(in); if (out) BIO_free(out); return ret; } bool OpenSSLCryptographicMessageSyntax::ParseKeyFile( const char *keyfile) { ::BIO *in; ::EVP_PKEY *new_pkey; if ((in=::BIO_new_file(keyfile,"r")) == NULL) { return false; } (void)BIO_reset(in); if ((new_pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,NULL)) == NULL) { return false; } BIO_free(in); if (pkey != NULL) { EVP_PKEY_free(pkey); } this->pkey = new_pkey; return true; } bool OpenSSLCryptographicMessageSyntax::ParseCertificateFile( const char *keyfile) { assert( recips ); ::X509 *x509 = NULL; ::BIO *in; if (!(in=::BIO_new_file(keyfile,"r"))) { return false; } // -> LEAK reported by valgrind... if (!(x509=::PEM_read_bio_X509(in,NULL,NULL,NULL))) { return false; } ::BIO_free(in); in = NULL; ::sk_X509_push(recips, x509); //::X509_free(x509); return true; } const EVP_CIPHER* OpenSSLCryptographicMessageSyntax::CreateCipher( CryptographicMessageSyntax::CipherTypes ciphertype) { const EVP_CIPHER *cipher = 0; switch( ciphertype ) { case CryptographicMessageSyntax::DES3_CIPHER: // Triple DES cipher = EVP_des_ede3_cbc(); break; case CryptographicMessageSyntax::AES128_CIPHER: // CBC AES cipher = EVP_aes_128_cbc(); break; case CryptographicMessageSyntax::AES192_CIPHER: // ' ' cipher = EVP_aes_192_cbc(); break; case CryptographicMessageSyntax::AES256_CIPHER: // ' ' cipher = EVP_aes_256_cbc(); break; } return cipher; } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmOpenSSLCryptographicMessageSyntax.h000066400000000000000000000041351412732066400245470ustar00rootroot00000000000000/*========================================================================= 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 GDCMOPENSSLCRYPTOGRAPHICMESSAGESYNTAX_H #define GDCMOPENSSLCRYPTOGRAPHICMESSAGESYNTAX_H #include "gdcmCryptographicMessageSyntax.h" #include #include namespace gdcm { class GDCM_EXPORT OpenSSLCryptographicMessageSyntax : public CryptographicMessageSyntax { public: OpenSSLCryptographicMessageSyntax(); ~OpenSSLCryptographicMessageSyntax(); // X.509 bool ParseCertificateFile( const char *filename ); bool ParseKeyFile( const char *filename ); // PBE bool SetPassword(const char * pass, size_t passLen); /// Set Cipher Type. /// Default is: AES256_CIPHER void SetCipherType(CipherTypes type); CipherTypes GetCipherType() const; /// create a CMS envelopedData structure bool Encrypt(char *output, size_t &outlen, const char *array, size_t len) const; /// decrypt content from a PKCS#7 envelopedData structure bool Decrypt(char *output, size_t &outlen, const char *array, size_t len) const; private: //#ifdef GDCM_HAVE_CMS_RECIPIENT_PASSWORD // ::stack_st_X509 *recips; //#else STACK_OF(X509) *recips; //#endif ::EVP_PKEY *pkey; const EVP_CIPHER *internalCipherType; char * password; size_t passwordLength; CipherTypes cipherType; private: OpenSSLCryptographicMessageSyntax(const OpenSSLCryptographicMessageSyntax&); // Not implemented. void operator=(const OpenSSLCryptographicMessageSyntax&); // Not implemented. const EVP_CIPHER *CreateCipher( CryptographicMessageSyntax::CipherTypes ciphertype); }; } // end namespace gdcm #endif //GDCMOPENSSLCRYPTOGRAPHICMESSAGESYNTAX_H GDCM-3.0.10/Source/Common/gdcmOpenSSLP7CryptoFactory.cxx000066400000000000000000000012321412732066400226020ustar00rootroot00000000000000/*========================================================================= 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 "gdcmOpenSSLP7CryptoFactory.h" //namespace gdcm{ //gdcm::OpenSSLCryptoFactory osslf; //} GDCM-3.0.10/Source/Common/gdcmOpenSSLP7CryptoFactory.h000066400000000000000000000021771412732066400222400ustar00rootroot00000000000000/*========================================================================= 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 GDCMOPENSSLP7CRYPTOFACTORY_H #define GDCMOPENSSLP7CRYPTOFACTORY_H #include "gdcmCryptoFactory.h" #include "gdcmOpenSSLP7CryptographicMessageSyntax.h" namespace gdcm { class GDCM_EXPORT OpenSSLP7CryptoFactory : public CryptoFactory { public: OpenSSLP7CryptoFactory(CryptoLib id) : CryptoFactory(id) { gdcmDebugMacro( "OpenSSL (PKCS7) Factory registered." ); } public: CryptographicMessageSyntax* CreateCMSProvider() { return new OpenSSLP7CryptographicMessageSyntax(); } private: OpenSSLP7CryptoFactory(){} }; } #endif //GDCMOPENSSLP7CRYPTOFACTORY_H GDCM-3.0.10/Source/Common/gdcmOpenSSLP7CryptographicMessageSyntax.cxx000066400000000000000000000272031412732066400253320ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCryptographicMessageSyntax.h" #include "gdcmOpenSSLP7CryptographicMessageSyntax.h" #include "gdcmTrace.h" #include // numeric_limits #include // stderr #include // strcmp #include #include // time() #ifdef GDCM_USE_SYSTEM_OPENSSL #include #include #include #include #include #endif /* * http://en.wikipedia.org/wiki/PKCS * PKCS#7 <=> Cryptographic Message Syntax Standard */ namespace gdcm { /* * openssl genrsa -out CA_key.pem 2048 * * openssl req -new -key CA_key.pem -x509 -days 365 -out CA_cert.cer */ /* * openssl smime -encrypt -aes256 -in inputfile.txt -out outputfile.txt -outform DER /tmp/server.pem */ #ifdef GDCM_USE_SYSTEM_OPENSSL const EVP_CIPHER *CreateCipher( CryptographicMessageSyntax::CipherTypes ciphertype) { const EVP_CIPHER *cipher = 0; switch( ciphertype ) { case CryptographicMessageSyntax::DES3_CIPHER: // Triple DES cipher = EVP_des_ede3_cbc(); break; case CryptographicMessageSyntax::AES128_CIPHER: // CBC AES cipher = EVP_aes_128_cbc(); break; case CryptographicMessageSyntax::AES192_CIPHER: // ' ' cipher = EVP_aes_192_cbc(); break; case CryptographicMessageSyntax::AES256_CIPHER: // ' ' cipher = EVP_aes_256_cbc(); break; } return cipher; } #endif class CryptographicMessageSyntaxInternals { #ifdef GDCM_USE_SYSTEM_OPENSSL public: CryptographicMessageSyntaxInternals():recips(NULL),pkey(NULL),CipherType( CryptographicMessageSyntax::AES256_CIPHER ),cipher(NULL),p7(PKCS7_new()){ recips = sk_X509_new_null(); PKCS7_set_type(p7,NID_pkcs7_enveloped); bio_buffer = BIO_new(BIO_s_mem()); Initialized = false; } ~CryptographicMessageSyntaxInternals() { EVP_PKEY_free(pkey); PKCS7_free(p7); p7 = NULL; BIO_free_all(bio_buffer); } unsigned int GetNumberOfRecipients() const { //::STACK_OF(X509) *recips = recips; if(!recips) { return 0; } return ::sk_X509_num(recips); } STACK_OF(X509)* GetRecipients( ) const { return recips; } ::X509* GetRecipient( unsigned int i ) const { //::STACK_OF(X509) *recips = Internals->recips; ::X509 *ret = sk_X509_value(recips, i); return ret; } void SetPrivateKey(::EVP_PKEY* thepkey) { this->pkey = thepkey; } ::EVP_PKEY* GetPrivateKey() const { return pkey; } void SetCipherType(CryptographicMessageSyntax::CipherTypes ciphertype) { CipherType = ciphertype; } bool Initialize() { if(!cipher) { cipher = CreateCipher( GetCipherType() ); } if(!cipher) return false; // The following is inspired by PKCS7_encrypt // and openssl/crypto/pkcs7/enc.c if( !PKCS7_set_cipher(p7,cipher) ) return false; for(unsigned int i = 0; i < GetNumberOfRecipients(); i++) { ::X509* recip = GetRecipient(i); if (!PKCS7_add_recipient(p7,recip)) return false; } sk_X509_pop_free(recips, X509_free); /* Set the content of the signed to 'data' */ /* PKCS7_content_new(p7,NID_pkcs7_data); not used in envelope */ /* could be used, but not in this version :-) if (!nodetach) PKCS7_set_detached(p7,1); */ return true; } bool Encrypt(char *output, size_t &outlen, const char *array, size_t len) { if( !Initialized ) { bool b = Initialize(); if ( !b ) { gdcmErrorMacro( "Initialize" ); return false; } Initialized = true; } if( len > (size_t)std::numeric_limits::max() ) { gdcmErrorMacro( "len is too big: " << len ); return false; } BIO *data = BIO_new_mem_buf((const void*)array, (int)len); if(!data) { gdcmErrorMacro( "BIO_new_mem_buf" ); return false; } char buf[256]; BIO *p7bio; if ((p7bio=PKCS7_dataInit(p7,NULL)) == NULL) return false; for (;;) { int i = BIO_read(data,buf,sizeof(buf)); if (i <= 0) break; BIO_write(p7bio,buf,i); } // BIO_flush() returns 1 for success and 0 or -1 for failure. int bflush = BIO_flush(p7bio); if( bflush != 1 ) { gdcmErrorMacro( "BIO_flush: " << bflush ); return false; } if (!PKCS7_dataFinal(p7,p7bio)) { gdcmErrorMacro( "PKCS7_dataFinal" ); return false; } // WARNING: // BIO_reset() normally returns 1 for success and 0 or -1 for failure. File // BIOs are an exception, they return 0 for success and -1 for failure. if( BIO_reset(bio_buffer) != 1 ) { gdcmErrorMacro( "BIO_reset" ); return false; } i2d_PKCS7_bio(bio_buffer,p7); // (void)BIO_flush(wbio); char *binary; long biolen = BIO_get_mem_data(bio_buffer,&binary); gdcmAssertMacro( biolen >= 0 ); if ( outlen < (size_t)biolen ) { gdcmErrorMacro( "Allocation issue: " << outlen << " vs " << biolen << " from " << len ); return false; } outlen = biolen; memcpy( output, binary, outlen ); BIO_free(data); BIO_free_all(p7bio); return true; } CryptographicMessageSyntax::CipherTypes GetCipherType() const { return CipherType; } ::PKCS7 *GetP7() const { return p7; } private: STACK_OF(X509) *recips; ::EVP_PKEY *pkey; CryptographicMessageSyntax::CipherTypes CipherType; const EVP_CIPHER *cipher; ::PKCS7 *p7; BIO *bio_buffer; bool Initialized; #endif }; OpenSSLP7CryptographicMessageSyntax::OpenSSLP7CryptographicMessageSyntax() { Internals = new CryptographicMessageSyntaxInternals; } OpenSSLP7CryptographicMessageSyntax::~OpenSSLP7CryptographicMessageSyntax() { delete Internals; } void OpenSSLP7CryptographicMessageSyntax::SetCipherType( CryptographicMessageSyntax::CipherTypes type ) { #ifdef GDCM_USE_SYSTEM_OPENSSL Internals->SetCipherType( type ); #else (void)type; #endif } CryptographicMessageSyntax::CipherTypes OpenSSLP7CryptographicMessageSyntax::GetCipherType() const { #ifdef GDCM_USE_SYSTEM_OPENSSL return Internals->GetCipherType(); #else return AES256_CIPHER; // why not :) #endif } bool OpenSSLP7CryptographicMessageSyntax::Encrypt(char *output, size_t &outlen, const char *array, size_t len) const { #ifdef GDCM_USE_SYSTEM_OPENSSL // RAND_status() and RAND_event() return 1 if the PRNG has been seeded with // enough data, 0 otherwise. if( !RAND_status() ) { gdcmErrorMacro( "PRNG was not seeded properly" ); outlen = 0; return false; } return Internals->Encrypt(output, outlen, array, len); #else (void)output; (void)array; (void)len; outlen = 0; gdcmDebugMacro( "GDCM_USE_SYSTEM_OPENSSL is OFF" ); return false; #endif /* GDCM_USE_SYSTEM_OPENSSL */ } /* $ openssl smime -decrypt -in /tmp/debug.der -inform DER -recip /tmp/server.pem -inkey CA_key.pem */ bool OpenSSLP7CryptographicMessageSyntax::Decrypt(char *output, size_t &outlen, const char *array, size_t len) const { #ifdef GDCM_USE_SYSTEM_OPENSSL CryptographicMessageSyntaxInternals *x509 = Internals; ::PKCS7 *p7; #undef PKCS7_SIGNER_INFO ::PKCS7_SIGNER_INFO *si; X509_STORE_CTX *cert_ctx=NULL; X509_STORE *cert_store=NULL; BIO *data,*detached=NULL,*p7bio=NULL; char buf[1024*4]; unsigned char *pp; int i; STACK_OF(PKCS7_SIGNER_INFO) *sk; char * ptr = output; outlen = 0; OpenSSL_add_all_algorithms(); //bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); //data=BIO_new(BIO_s_file()); pp=NULL; EVP_PKEY *pkey = x509->GetPrivateKey(); if( len > (size_t)std::numeric_limits::max() ) { gdcmErrorMacro( "len is too big: " << len ); return false; } data = BIO_new_mem_buf((const void*)array, (int)len); if(!data) goto err; if (pp == NULL) BIO_set_fp(data,stdin,BIO_NOCLOSE); /* Load the PKCS7 object from a file */ //if ((p7=PEM_read_bio_PKCS7(data,NULL,NULL,NULL)) == NULL) goto err; if ((p7=d2i_PKCS7_bio(data,NULL)) == NULL) goto err; if(!PKCS7_type_is_enveloped(p7)) { goto err; } // if(cert && !X509_check_private_key(cert, pkey)) { // PKCS7err(PKCS7_F_PKCS7_DECRYPT, // PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); // return 0; // } cert_ctx=X509_STORE_CTX_new(); /* This stuff is being setup for certificate verification. * When using SSL, it could be replaced with a * cert_stre=SSL_CTX_get_cert_store(ssl_ctx); */ cert_store=X509_STORE_new(); X509_STORE_set_default_paths(cert_store); X509_STORE_load_locations(cert_store,NULL,"../../certs"); //X509_STORE_set_verify_cb_func(cert_store,verify_callback); ERR_clear_error(); /* We need to process the data */ /* We cannot support detached encryption */ p7bio=PKCS7_dataDecode(p7,pkey,detached,NULL); if (p7bio == NULL) { printf("problems decoding\n"); goto err; } /* We now have to 'read' from p7bio to calculate digests etc. */ for (;;) { i=BIO_read(p7bio,buf,sizeof(buf)); /* print it? */ if (i <= 0) break; //fwrite(buf,1, i, stdout); memcpy(ptr, buf, i); ptr += i; outlen += i; } /* We can now verify signatures */ sk=PKCS7_get_signer_info(p7); if (sk == NULL) { //fprintf(stderr, "there are no signatures on this data\n"); } else { /* Ok, first we need to, for each subject entry, * see if we can verify */ ERR_clear_error(); for (i=0; iSetPrivateKey( pkey ); return true; #else (void)keyfile; gdcmDebugMacro( "GDCM_USE_SYSTEM_OPENSSL is OFF" ); return false; #endif } bool OpenSSLP7CryptographicMessageSyntax::ParseCertificateFile( const char *keyfile) { #ifdef GDCM_USE_SYSTEM_OPENSSL STACK_OF(X509) *recips = Internals->GetRecipients(); assert( recips ); ::X509 *x509 = NULL; ::BIO *in; if (!(in=::BIO_new_file(keyfile,"r"))) { return false; } // -> LEAK reported by valgrind... if (!(x509=::PEM_read_bio_X509(in,NULL,NULL,NULL))) { return false; } ::BIO_free(in); in = NULL; ::sk_X509_push(recips, x509); return true; #else (void)keyfile; gdcmDebugMacro( "GDCM_USE_SYSTEM_OPENSSL is OFF" ); return false; #endif } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmOpenSSLP7CryptographicMessageSyntax.h000066400000000000000000000045751412732066400247660ustar00rootroot00000000000000/*========================================================================= 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 GDCMOPENSSLP7CRYPTOGRAPHICMESSAGESYNTAX_H #define GDCMOPENSSLP7CRYPTOGRAPHICMESSAGESYNTAX_H #include "gdcmCryptographicMessageSyntax.h" #include "gdcmTypes.h" namespace gdcm { class CryptographicMessageSyntaxInternals; //----------------------------------------------------------------------------- /** * \brief * \details Class for CryptographicMessageSyntax encryption. This is just a simple * wrapper around openssl PKCS7_encrypt functionalities * * See online documentation * http://www.openssl.org/docs/crypto/PKCS7_encrypt.html * */ class GDCM_EXPORT OpenSSLP7CryptographicMessageSyntax : public CryptographicMessageSyntax { public: OpenSSLP7CryptographicMessageSyntax(); ~OpenSSLP7CryptographicMessageSyntax(); // X.509 bool ParseCertificateFile( const char *filename ); bool ParseKeyFile( const char *filename ); // PBE bool SetPassword(const char * /*pass*/, size_t /*passLen*/) { gdcmWarningMacro( "Openssl using PKCS7 does not support Password Based Encryption." ); return false; } /// Set Cipher Type. /// Default is: AES256_CIPHER void SetCipherType(CipherTypes type); CipherTypes GetCipherType() const; /// create a PKCS#7 envelopedData structure bool Encrypt(char *output, size_t &outlen, const char *array, size_t len) const; /// decrypt content from a PKCS#7 envelopedData structure bool Decrypt(char *output, size_t &outlen, const char *array, size_t len) const; private: CryptographicMessageSyntaxInternals *Internals; private: OpenSSLP7CryptographicMessageSyntax(const OpenSSLP7CryptographicMessageSyntax&); // Not implemented. void operator=(const OpenSSLP7CryptographicMessageSyntax&); // Not implemented. }; } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMOPENSSLP7CRYPTOGRAPHICMESSAGESYNTAX_H GDCM-3.0.10/Source/Common/gdcmProgressEvent.cxx000066400000000000000000000011751412732066400211730ustar00rootroot00000000000000/*========================================================================= 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 "gdcmProgressEvent.h" namespace gdcm { } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmProgressEvent.h000066400000000000000000000027621412732066400206230ustar00rootroot00000000000000/*========================================================================= 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 GDCMPROGRESSEVENT_H #define GDCMPROGRESSEVENT_H #include "gdcmEvent.h" #include "gdcmTag.h" namespace gdcm { /** * \brief ProgressEvent * \details Special type of event triggered during * * \see AnyEvent */ class ProgressEvent : public AnyEvent { public: typedef ProgressEvent Self; typedef AnyEvent Superclass; ProgressEvent(double p = 0):m_Progress(p) {} ~ProgressEvent() override = default; ProgressEvent(const Self&s) : AnyEvent(s){}; void operator=(const Self&) = delete; const char * GetEventName() const override { return "ProgressEvent"; } bool CheckEvent(const ::gdcm::Event* e) const override { return dynamic_cast(e) ? true : false; } ::gdcm::Event* MakeObject() const override { return new Self; } void SetProgress(double p) { m_Progress = p; } double GetProgress() const { return m_Progress; } private: double m_Progress; }; } // end namespace gdcm #endif //GDCMPROGRESSEVENT_H GDCM-3.0.10/Source/Common/gdcmRegion.cxx000066400000000000000000000013731412732066400176100ustar00rootroot00000000000000/*========================================================================= 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 "gdcmRegion.h" #include "gdcmBoxRegion.h" namespace gdcm { Region::Region() = default; Region::~Region() = default; void Region::Print(std::ostream &) const { } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmRegion.h000066400000000000000000000032671412732066400172410ustar00rootroot00000000000000/*========================================================================= 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 GDCMREGION_H #define GDCMREGION_H #include "gdcmTypes.h" #include #include namespace gdcm { class BoxRegion; /** * \brief Class for manipulation region */ //----------------------------------------------------------------------------- class GDCM_EXPORT Region { public : Region(); virtual ~Region(); /// Print virtual void Print(std::ostream &os = std::cout) const; /// return whether this domain is empty: virtual bool Empty() const = 0; /// return whether this is valid domain virtual bool IsValid() const = 0; /// compute the area virtual size_t Area() const = 0; // implementation detail of heterogeneous container in C++ virtual Region *Clone() const = 0; /// Return the Axis-Aligned minimum bounding box for all regions virtual BoxRegion ComputeBoundingBox() = 0; private: }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const Region&r) { r.Print( os ); return os; } } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMREGION_H GDCM-3.0.10/Source/Common/gdcmSHA1.cxx000066400000000000000000000054541412732066400170650ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSHA1.h" #include "gdcmSystem.h" #ifdef GDCM_USE_SYSTEM_OPENSSL #include #endif #include // memcmp #include // malloc #include // sprintf /* */ namespace gdcm { class SHA1Internals { public: #ifdef GDCM_USE_SYSTEM_OPENSSL SHA_CTX ctx; #endif }; SHA1::SHA1() { Internals = new SHA1Internals; } SHA1::~SHA1() { delete Internals; } bool SHA1::Compute(const char *buffer, unsigned long buf_len, char digest[]) { #ifdef GDCM_USE_SYSTEM_OPENSSL if( !buffer || !buf_len ) { return false; } unsigned char output[20]; SHA_CTX ctx; SHA1_Init(&ctx); SHA1_Update(&ctx, buffer, buf_len); SHA1_Final(output, &ctx); for (int di = 0; di < 20; ++di) { sprintf(digest+2*di, "%02x", output[di]); } digest[2*20] = '\0'; return true; #else (void)buffer; (void)buf_len; (void)digest; return false; #endif } #ifdef GDCM_USE_SYSTEM_OPENSSL static bool process_file(const char *filename, unsigned char *digest) { if( !filename || !digest ) return false; FILE *file = fopen(filename, "rb"); if(!file) { return false; } size_t file_size = System::FileSize(filename); void *buffer = malloc(file_size); if(!buffer) { fclose(file); return false; } size_t read = fread(buffer, 1, file_size, file); if( read != file_size ) return false; SHA_CTX ctx; int ret = SHA1_Init(&ctx); if( !ret ) return false; ret = SHA1_Update(&ctx, buffer, file_size); if( !ret ) return false; ret = SHA1_Final(digest, &ctx); if( !ret ) return false; /*printf("MD5 (\"%s\") = ", test[i]); */ /*for (int di = 0; di < 16; ++di) { printf("%02x", digest[di]); }*/ //printf("\t%s\n", filename); free(buffer); fclose(file); return true; } #endif bool SHA1::ComputeFile(const char *filename, char digest_str[20*2+1]) { #ifdef GDCM_USE_SYSTEM_OPENSSL // If not file exist // return false; unsigned char digest[20]; /* Do the file */ if( !process_file(filename, digest) ) { return false; } for (int di = 0; di < 20; ++di) { sprintf(digest_str+2*di, "%02x", digest[di]); } digest_str[2*20] = '\0'; return true; #else (void)filename; (void)digest_str; return false; #endif } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmSHA1.h000066400000000000000000000026211412732066400165030ustar00rootroot00000000000000/*========================================================================= 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 GDCMSHA1_H #define GDCMSHA1_H #include "gdcmTypes.h" namespace gdcm { //----------------------------------------------------------------------------- class SHA1Internals; /** * \brief Class for SHA1 * * \warning this class is able to pick from one implementation: * * 1. the one from OpenSSL (when GDCM_USE_SYSTEM_OPENSSL is turned ON) * * In all other cases it will return an error */ class GDCM_EXPORT SHA1 { public : SHA1(); ~SHA1(); SHA1(const SHA1&) = delete; void operator=(const SHA1&) = delete; static bool Compute(const char *buffer, unsigned long buf_len, char digest_str[20*2+1]); static bool ComputeFile(const char *filename, char digest_str[20*2+1]); private: SHA1Internals *Internals; }; } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMSHA1_H GDCM-3.0.10/Source/Common/gdcmSmartPointer.h000066400000000000000000000056001412732066400204360ustar00rootroot00000000000000/*========================================================================= 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 GDCMSMARTPOINTER_H #define GDCMSMARTPOINTER_H #include "gdcmObject.h" namespace gdcm { /** * \brief Class for Smart Pointer * \details * Will only work for subclass of gdcm::Object * See tr1/shared_ptr for a more general approach (not invasive) * #include * { * shared_ptr b(new Bla); * } * \note * Class partly based on post by Bill Hubauer: * http://groups.google.com/group/comp.lang.c++/msg/173ddc38a827a930 * \see * http://www.davethehat.com/articles/smartp.htm * * and itk::SmartPointer */ template class SmartPointer { public: SmartPointer():Pointer(nullptr) {} SmartPointer(const SmartPointer& p):Pointer(p.Pointer) { Register(); } SmartPointer(ObjectType* p):Pointer(p) { Register(); } SmartPointer(ObjectType const & p) { Pointer = const_cast(&p); Register(); } ~SmartPointer() { UnRegister(); Pointer = nullptr; } /// Overload operator -> ObjectType *operator -> () const { return Pointer; } ObjectType& operator * () const { assert( Pointer ); return *Pointer; } /// Return pointer to object. operator ObjectType * () const { return Pointer; } /// Overload operator assignment. SmartPointer &operator = (SmartPointer const &r) { return operator = (r.Pointer); } /// Overload operator assignment. SmartPointer &operator = (ObjectType *r) { // http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.22 // DO NOT CHANGE THE ORDER OF THESE STATEMENTS! // (This order properly handles self-assignment) // (This order also properly handles recursion, e.g., if a ObjectType contains SmartPointers) if( Pointer != r ) { ObjectType* old = Pointer; Pointer = r; Register(); if ( old ) { old->UnRegister(); } } return *this; } SmartPointer &operator = (ObjectType const &r) { ObjectType* tmp = const_cast(&r); return operator = (tmp); } /// Explicit function to retrieve the pointer ObjectType *GetPointer() const { return Pointer; } private: void Register() { if(Pointer) Pointer->Register(); } void UnRegister() { if(Pointer) Pointer->UnRegister(); } ObjectType* Pointer; }; } // end namespace gdcm #endif //GDCMSMARTPOINTER_H GDCM-3.0.10/Source/Common/gdcmStaticAssert.h000066400000000000000000000027441412732066400204260ustar00rootroot00000000000000/*========================================================================= 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 GDCMSTATICASSERT_H #define GDCMSTATICASSERT_H // the following was shamelessly borowed from BOOST static assert: namespace gdcm { template struct STATIC_ASSERTION_FAILURE; template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; template struct static_assert_test {}; } #define GDCM_JOIN( X, Y ) GDCM_DO_JOIN( X, Y ) #define GDCM_DO_JOIN( X, Y ) GDCM_DO_JOIN2(X,Y) #define GDCM_DO_JOIN2( X, Y ) X##Y /// The GDCM_JOIN + __LINE__ is needed to create a uniq identifier #define GDCM_STATIC_ASSERT( B ) \ typedef ::gdcm::static_assert_test<\ sizeof(::gdcm::STATIC_ASSERTION_FAILURE< (bool)( B ) >)>\ GDCM_JOIN(gdcm_static_assert_typedef_, __LINE__) /* Example of use: * * template * struct must_not_be_instantiated * { * // this will be triggered if this type is instantiated * GDCM_STATIC_ASSERT(sizeof(T) == 0); * }; * */ #endif // GDCMSTATICASSERT_H GDCM-3.0.10/Source/Common/gdcmString.cxx000066400000000000000000000011671412732066400176340ustar00rootroot00000000000000/*========================================================================= 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 "gdcmString.h" namespace gdcm { } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmString.h000066400000000000000000000106401412732066400172550ustar00rootroot00000000000000/*========================================================================= 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 GDCMSTRING_H #define GDCMSTRING_H #include "gdcmTypes.h" #include "gdcmStaticAssert.h" namespace gdcm { /** * \brief String * * \note TDelimiter template parameter is used to separate multiple String (VM1 >) * TMaxLength is only a hint. No one actually respect the max length * TPadChar is the string padding (0 or space) */ template class /*GDCM_EXPORT*/ String : public std::string /* PLEASE do not export me */ { // UI wants \0 for pad character, while ASCII ones wants space char... do not allow anything else GDCM_STATIC_ASSERT( TPadChar == ' ' || TPadChar == 0 ); public: // typedef are not inherited: typedef std::string::value_type value_type; typedef std::string::pointer pointer; typedef std::string::reference reference; typedef std::string::const_reference const_reference; typedef std::string::size_type size_type; typedef std::string::difference_type difference_type; typedef std::string::iterator iterator; typedef std::string::const_iterator const_iterator; typedef std::string::reverse_iterator reverse_iterator; typedef std::string::const_reverse_iterator const_reverse_iterator; /// String constructors. String(): std::string() {} String(const value_type* s): std::string(s) { if( size() % 2 ) { push_back( TPadChar ); } } String(const value_type* s, size_type n): std::string(s, n) { // We are being passed a const char* pointer, so s[n] == 0 (guaranteed!) if( n % 2 ) { push_back( TPadChar ); } } String(const std::string& s, size_type pos=0, size_type n=npos): std::string(s, pos, n) { // FIXME: some users might already have padded the string 's' with a trailing \0... if( size() % 2 ) { push_back( TPadChar ); } } /// WARNING: Trailing \0 might be lost in this operation: operator const char *() const { return this->c_str(); } /// return if string is valid bool IsValid() const { // Check Length: size_type l = size(); if( l > TMaxLength ) return false; return true; } gdcm::String Truncate() const { if( IsValid() ) return *this; std::string str = *this; // copy str.resize( TMaxLength ); return str; } /// Trim function is required to return a std::string object, otherwise we /// could not create a gdcm::String object with an odd number of bytes... std::string Trim() const { std::string str = *this; // copy std::string::size_type pos1 = str.find_first_not_of(' '); std::string::size_type pos2 = str.find_last_not_of(' '); str = str.substr( (pos1 == std::string::npos) ? 0 : pos1, (pos2 == std::string::npos) ? (str.size() - 1) : (pos2 - pos1 + 1)); return str; } static std::string Trim(const char *input) { if( !input ) return ""; std::string str = input; std::string::size_type pos1 = str.find_first_not_of(' '); std::string::size_type pos2 = str.find_last_not_of(' '); str = str.substr( (pos1 == std::string::npos) ? 0 : pos1, (pos2 == std::string::npos) ? (str.size() - 1) : (pos2 - pos1 + 1)); return str; } }; template inline std::istream& operator>>(std::istream &is, String &ms) { if(is) { std::getline(is, ms, TDelimiter); // no such thing as std::get where the delim char would be left, so I need to manually add it back... // hopefully this is the right thing to do (no overhead) if( !is.eof() ) is.putback( TDelimiter ); } return is; } //template //String String::Trim() const //{ // String s; // return s; //} } // end namespace gdcm #endif //GDCMSTRING_H GDCM-3.0.10/Source/Common/gdcmSubject.cxx000066400000000000000000000126001412732066400177570ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSubject.h" #include "gdcmSmartPointer.h" #include "gdcmCommand.h" #include "gdcmEvent.h" #include namespace gdcm { class Observer { public: Observer(Command* c, const Event * event, unsigned long tag) :m_Command(c), m_Event(event), m_Tag(tag) { } virtual ~Observer() { delete m_Event; } SmartPointer m_Command; const Event * m_Event; unsigned long m_Tag; }; class SubjectInternals { public: SubjectInternals() {m_Count = 0;} ~SubjectInternals(); unsigned long AddObserver(const Event & event, Command* cmd); unsigned long AddObserver(const Event & event, Command* cmd) const; void RemoveObserver(unsigned long tag); void RemoveAllObservers(); void InvokeEvent( const Event & event, Subject* self); void InvokeEvent( const Event & event, const Subject* self); Command *GetCommand(unsigned long tag); bool HasObserver(const Event & event) const; bool PrintObservers(std::ostream& os, std::string indent) const; private: std::list m_Observers; unsigned long m_Count; }; SubjectInternals:: ~SubjectInternals() { for(std::list::iterator i = m_Observers.begin(); i != m_Observers.end(); ++i) { delete (*i); } } unsigned long SubjectInternals:: AddObserver(const Event & event, Command* cmd) { Observer* ptr = new Observer(cmd, event.MakeObject(), m_Count); m_Observers.push_back(ptr); m_Count++; return ptr->m_Tag; } unsigned long SubjectInternals:: AddObserver(const Event & event, Command* cmd) const { Observer* ptr = new Observer(cmd, event.MakeObject(), m_Count); SubjectInternals * me = const_cast( this ); me->m_Observers.push_back(ptr); me->m_Count++; return ptr->m_Tag; } void SubjectInternals:: RemoveObserver(unsigned long tag) { for(std::list::iterator i = m_Observers.begin(); i != m_Observers.end(); ++i) { if((*i)->m_Tag == tag) { delete (*i); m_Observers.erase(i); return; } } } void SubjectInternals:: RemoveAllObservers() { for(std::list::iterator i = m_Observers.begin(); i != m_Observers.end(); ++i) { delete (*i); } m_Observers.clear(); } void SubjectInternals:: InvokeEvent( const Event & event, Subject* self) { for(std::list::iterator i = m_Observers.begin(); i != m_Observers.end(); ++i) { const Event * e = (*i)->m_Event; if(e->CheckEvent(&event)) { (*i)->m_Command->Execute(self, event); } } } void SubjectInternals:: InvokeEvent( const Event & event, const Subject* self) { for(std::list::iterator i = m_Observers.begin(); i != m_Observers.end(); ++i) { const Event * e = (*i)->m_Event; if(e->CheckEvent(&event)) { (*i)->m_Command->Execute(self, event); } } } Command* SubjectInternals:: GetCommand(unsigned long tag) { for(std::list::iterator i = m_Observers.begin(); i != m_Observers.end(); ++i) { if ( (*i)->m_Tag == tag) { return (*i)->m_Command; } } return nullptr; } bool SubjectInternals:: HasObserver(const Event & event) const { for(std::list::const_iterator i = m_Observers.begin(); i != m_Observers.end(); ++i) { const Event * e = (*i)->m_Event; if(e->CheckEvent(&event)) { return true; } } return false; } bool SubjectInternals:: PrintObservers(std::ostream& os, std::string indent) const { if(m_Observers.empty()) { return false; } for(std::list::const_iterator i = m_Observers.begin(); i != m_Observers.end(); ++i) { const Event * e = (*i)->m_Event; const Command* c = (*i)->m_Command; (void)c; os << indent << e->GetEventName() << "(" /*<< c->GetNameOfClass()*/ << ")\n"; } return true; } Subject::Subject():Internals(new SubjectInternals) { } Subject::~Subject() { delete Internals; } unsigned long Subject::AddObserver(const Event & event, Command *cmd) { return this->Internals->AddObserver(event,cmd); } unsigned long Subject::AddObserver(const Event & event, Command *cmd) const { return this->Internals->AddObserver(event,cmd); } Command* Subject::GetCommand(unsigned long tag) { return this->Internals->GetCommand(tag); } void Subject::InvokeEvent( const Event & event) { this->Internals->InvokeEvent(event,this); } void Subject::InvokeEvent( const Event & event) const { this->Internals->InvokeEvent(event,this); } void Subject::RemoveObserver(unsigned long tag) { this->Internals->RemoveObserver(tag); } void Subject::RemoveAllObservers() { this->Internals->RemoveAllObservers(); } bool Subject::HasObserver( const Event & event ) const { return this->Internals->HasObserver(event); } } GDCM-3.0.10/Source/Common/gdcmSubject.h000066400000000000000000000047061412732066400174140ustar00rootroot00000000000000/*========================================================================= 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 GDCMSUBJECT_H #define GDCMSUBJECT_H #include "gdcmObject.h" namespace gdcm { class Event; class Command; class SubjectInternals; /** * \brief Subject * \see Command Event */ class GDCM_EXPORT Subject : public Object { public: Subject(); ~Subject() override; /** Allow people to add/remove/invoke observers (callbacks) to any GDCM * object. This is an implementation of the subject/observer design * pattern. An observer is added by specifying an event to respond to * and an gdcm::Command to execute. It returns an unsigned long tag * which can be used later to remove the event or retrieve the * command. The memory for the Command becomes the responsibility of * this object, so don't pass the same instance of a command to two * different objects */ unsigned long AddObserver(const Event & event, Command *); unsigned long AddObserver(const Event & event, Command *) const; /** Get the command associated with the given tag. NOTE: This returns * a pointer to a Command, but it is safe to assign this to a * Command::Pointer. Since Command inherits from LightObject, at this * point in the code, only a pointer or a reference to the Command can * be used. */ Command* GetCommand(unsigned long tag); /** Call Execute on all the Commands observing this event id. */ void InvokeEvent( const Event & ); /** Call Execute on all the Commands observing this event id. * The actions triggered by this call doesn't modify this object. */ void InvokeEvent( const Event & ) const; /** Remove the observer with this tag value. */ void RemoveObserver(unsigned long tag); /** Remove all observers . */ void RemoveAllObservers(); /** Return true if an observer is registered for this event. */ bool HasObserver( const Event & event ) const; protected: private: SubjectInternals *Internals; private: }; } // end namespace gdcm #endif //GDCMSUBJECT_H GDCM-3.0.10/Source/Common/gdcmSwapCode.cxx000066400000000000000000000026321412732066400200710ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSwapCode.h" #include namespace gdcm { static const char *SwapCodeStrings[] = { "Unknown", "LittleEndian", "BigEndian", "BadLittleEndian", "BadBigEndian", nullptr }; int SwapCode::GetIndex(SwapCode const & sc) { int idx = 0; switch(sc) { case Unknown: idx = 0; break; case LittleEndian: idx = 1; break; case BigEndian: idx = 2; break; case BadLittleEndian: idx = 3; break; case BadBigEndian: idx = 4; break; default: assert(0 && "Should not happen" ); } assert( idx < 5 ); return idx; } const char* SwapCode::GetSwapCodeString(SwapCode const & sc) { int idx = GetIndex(sc); return SwapCodeStrings[idx]; } /* std::ostream& operator<<(std::ostream& os, const SwapCode& sc) { os << SwapCode::GetSwapCodeString(sc); return os; } */ } // namespace gdcm GDCM-3.0.10/Source/Common/gdcmSwapCode.h000066400000000000000000000030231412732066400175110ustar00rootroot00000000000000/*========================================================================= 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 GDCMSWAPCODE_H #define GDCMSWAPCODE_H #include "gdcmTypes.h" #include namespace gdcm { /** * \brief SwapCode representation * \details */ class GDCM_EXPORT SwapCode { public: typedef enum { Unknown = 0, LittleEndian = 1234, BigEndian = 4321, BadLittleEndian = 3412, BadBigEndian = 2143 } SwapCodeType; operator SwapCode::SwapCodeType() const { return SwapCodeValue; } SwapCode(SwapCodeType sc = Unknown):SwapCodeValue(sc) { } static const char* GetSwapCodeString(SwapCode const & sc); friend std::ostream& operator<<(std::ostream& os, const SwapCode& sc); protected: static int GetIndex(SwapCode const & sc); private: SwapCodeType SwapCodeValue; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& os, const SwapCode& sc) { os << SwapCode::GetSwapCodeString(sc); return os; } } // end namespace gdcm #endif //GDCMSWAPCODE_H GDCM-3.0.10/Source/Common/gdcmSwapper.h000066400000000000000000000031461412732066400174330ustar00rootroot00000000000000/*========================================================================= 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 GDCMSWAPPER_H #define GDCMSWAPPER_H #include "gdcmSwapCode.h" namespace gdcm { #ifdef GDCM_WORDS_BIGENDIAN class SwapperDoOp { public: template static T Swap(T val) {return val;} template static void SwapArray(T *, unsigned int ) {} }; class SwapperNoOp { public: template static T Swap(T val); template static void SwapArray(T *array, unsigned int n) { // TODO: need to unroll loop: for(unsigned int i = 0; i < n; ++i) { array[i] = Swap(array[i]); } } }; #else class SwapperNoOp { public: template static T Swap(T val) {return val;} template static void SwapArray(T *, size_t ) {} }; class SwapperDoOp { public: template static T Swap(T val); template static void SwapArray(T *array, size_t n) { // TODO: need to unroll loop: for(size_t i = 0; i < n; ++i) { array[i] = Swap(array[i]); } } }; #endif } // end namespace gdcm #include "gdcmSwapper.txx" #endif //GDCMSWAPPER_H GDCM-3.0.10/Source/Common/gdcmSwapper.txx000066400000000000000000000142171412732066400200300ustar00rootroot00000000000000/*========================================================================= 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 GDCMSWAPPER_TXX #define GDCMSWAPPER_TXX #if defined(_MSC_VER) // http://msdn.microsoft.com/en-us/library/a3140177 #include #define bswap_16(X) _byteswap_ushort(X) #define bswap_32(X) _byteswap_ulong(X) #define bswap_64(X) _byteswap_uint64(X) #elif defined(GDCM_HAVE_BYTESWAP_H) #include #include #elif defined(__APPLE__) #include #include #define bswap_16(X) OSSwapInt16(X) #define bswap_32(X) OSSwapInt32(X) #define bswap_64(X) OSSwapInt64(X) #elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) #include #define bswap_16(X) bswap16(X) #define bswap_32(X) bswap32(X) #define bswap_64(X) bswap64(X) #elif defined(__OpenBSD__) #include #define bswap_16(X) swap16(X) #define bswap_32(X) swap32(X) #define bswap_64(X) swap64(X) #elif defined(__MINGW32__) // https://www.gnu.org/software/gnulib/manual/html_node/bswap_005f16.html // -> This function is missing on some platforms: Mac OS X 10.5, FreeBSD 6.0, // NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 // 5.1, Solaris 11 2011-11, Cygwin, mingw, MSVC 9, Interix 3.5, BeOS. //#pragma message ("Fallback on defaults functions for bswap_*") # define bswap_16(x) ((((x) & 0x00FF) << 8) | \ (((x) & 0xFF00) >> 8)) # define bswap_32(x) ((((x) & 0x000000FF) << 24) | \ (((x) & 0x0000FF00) << 8) | \ (((x) & 0x00FF0000) >> 8) | \ (((x) & 0xFF000000) >> 24)) # define bswap_64(x) ((((x) & 0x00000000000000FFULL) << 56) | \ (((x) & 0x000000000000FF00ULL) << 40) | \ (((x) & 0x0000000000FF0000ULL) << 24) | \ (((x) & 0x00000000FF000000ULL) << 8) | \ (((x) & 0x000000FF00000000ULL) >> 8) | \ (((x) & 0x0000FF0000000000ULL) >> 24) | \ (((x) & 0x00FF000000000000ULL) >> 40) | \ (((x) & 0xFF00000000000000ULL) >> 56)) #else // If this condition is encountered, first check whether the platform has the functions required. // If not, test whether the workaround for __MINGW32__ can be used for this platform. #error "Byte swap methods are not available." #endif #include "gdcmTag.h" namespace gdcm { #ifdef GDCM_WORDS_BIGENDIAN template <> inline uint16_t SwapperNoOp::Swap(uint16_t val) { return bswap_16(val); } template <> inline int16_t SwapperNoOp::Swap(int16_t val) { return Swap((uint16_t)val); } template <> inline uint32_t SwapperNoOp::Swap(uint32_t val) { return bswap_32(val); } template <> inline int32_t SwapperNoOp::Swap(int32_t val) { return Swap((uint32_t)val); } template <> inline float SwapperNoOp::Swap(float val) { return Swap((uint32_t)val); } template <> inline uint64_t SwapperNoOp::Swap(uint64_t val) { return bswap_64(val); } template <> inline int64_t SwapperNoOp::Swap(int64_t val) { return Swap((uint64_t)val); } template <> inline double SwapperNoOp::Swap(double val) { return Swap((uint64_t)val); } template <> inline Tag SwapperNoOp::Swap(Tag val) { return Tag( Swap(val.GetGroup()), Swap(val.GetElement()) ); } template <> inline void SwapperNoOp::SwapArray(uint8_t *, unsigned int ) {} template <> inline void SwapperNoOp::SwapArray(float *array, unsigned int n) { switch( sizeof(float) ) { case 4: SwapperNoOp::SwapArray((uint32_t*)array,n); break; default: assert(0); } } template <> inline void SwapperNoOp::SwapArray(double *array, unsigned int n) { switch( sizeof(double) ) { case 8: SwapperNoOp::SwapArray((uint64_t*)array,n); break; default: assert(0); } } #else template <> inline uint16_t SwapperDoOp::Swap(uint16_t val) { return bswap_16(val); } template <> inline int16_t SwapperDoOp::Swap(int16_t val) { return Swap((uint16_t)val); } template <> inline uint32_t SwapperDoOp::Swap(uint32_t val) { return bswap_32(val); } template <> inline int32_t SwapperDoOp::Swap(int32_t val) { return Swap((uint32_t)val); } template <> inline float SwapperDoOp::Swap(float val) { return static_cast(Swap((uint32_t)val)); } template <> inline uint64_t SwapperDoOp::Swap(uint64_t val) { return bswap_64(val); } template <> inline int64_t SwapperDoOp::Swap(int64_t val) { return Swap((uint64_t)val); } template <> inline double SwapperDoOp::Swap(double val) { return static_cast(Swap((uint64_t)val)); } template <> inline Tag SwapperDoOp::Swap(Tag val) { return Tag( Swap((uint32_t)val.GetElementTag()) ); } template <> inline void SwapperDoOp::SwapArray(uint8_t *, size_t ) {} template <> inline void SwapperDoOp::SwapArray(float *array, size_t n) { switch( sizeof(float) ) { case 4: SwapperDoOp::SwapArray((uint32_t*)array,n); break; default: assert(0); } } template <> inline void SwapperDoOp::SwapArray(double *array, size_t n) { switch( sizeof(double) ) { case 8: SwapperDoOp::SwapArray((uint64_t*)array,n); break; default: assert(0); } } #endif } // end namespace gdcm #endif // GDCMSWAPPER_TXX GDCM-3.0.10/Source/Common/gdcmSystem.cxx000066400000000000000000000663361412732066400176630ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2016 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 "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmFilename.h" #include "gdcmDirectory.h" #include "gdcmException.h" #include #include #include #include #include // strspn #include #include #include #include // PATH_MAX // gettimeofday #ifdef GDCM_HAVE_SYS_TIME_H #include #endif #include #ifdef GDCM_HAVE_WINSOCK_H #include #endif #include // snprintf #if defined(_MSC_VER) && (_MSC_VER < 1900) #define snprintf _snprintf #endif #ifdef GDCM_USE_COREFOUNDATION_LIBRARY #include #endif #if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) ||defined(__BORLANDC__) || defined(__MINGW32__)) #include #include #define _unlink unlink #else //#include // we want GNU extensions #include #include #include #include /* gethostname */ #include // strncasecmp #endif #if defined(GDCM_HAVE_LANGINFO_H) #include // nl_langinfo #endif // TODO: WIN32 replacement for C99 stuff: // #if defined(_WIN32) || defined(_WIN64) // #define vsnprintf _vsnprintf // #define strcasecmp _stricmp // #define strncasecmp _strnicmp // #endif namespace gdcm { #if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__MINGW32__)) inline int Mkdir(const char* dir) { return _mkdir(dir); } inline int Rmdir(const char* dir) { return _rmdir(dir); } inline const char* Getcwd(char* buf, unsigned int len) { const char* ret = _getcwd(buf, len); return ret; } #else inline int Mkdir(const char* dir) { return mkdir(dir, 00777); } inline int Rmdir(const char* dir) { return rmdir(dir); } inline const char* Getcwd(char* buf, unsigned int len) { const char* ret = getcwd(buf, len); return ret; } #endif /* // 1.14 How can I find a process' executable file? // http://www.faqs.org/faqs/unix-faq/programmer/faq/ static std::string Argv0; void System::SetArgv0(const char *argv0) { Argv0 = argv0; //std::cout << "Set:" << Argv0 << std::endl; } const char* System::GetArgv0() { //std::cout << "Get:" << Argv0 << std::endl; return Argv0.c_str(); } */ const char * System::GetCWD() { static char buf[2048]; const char* cwd = Getcwd(buf, 2048); return cwd; /* std::string path; if ( cwd ) { path = cwd; } return path; */ } static inline int Mkdir2(const char *utf8) { #ifdef _MSC_VER const std::wstring unc = System::ConvertToUNC(utf8); return _wmkdir(unc.c_str()); #else return Mkdir(utf8); #endif } bool System::MakeDirectory(const char *path) { if( !path || !*path ) return false; if(System::FileExists(path)) { return true; } Filename fn(path); std::string dir = fn.ToUnixSlashes(); std::string::size_type pos = dir.find(':'); if(pos == std::string::npos) { pos = 0; } std::string topdir; bool ok = true; while(ok && (pos = dir.find('/', pos)) != std::string::npos) { topdir = dir.substr(0, pos+1); ok = ok && (System::FileIsDirectory(topdir.c_str()) || 0 == Mkdir2(topdir.c_str())); pos++; } if( !ok ) return false; if(dir[dir.size()-1] == '/') { topdir = dir.substr(0, dir.size()); } else { topdir = dir; } if(Mkdir2(topdir.c_str()) != 0) { // There is a bug in the Borland Run time library which makes MKDIR // return EACCES when it should return EEXISTS // if it is some other error besides directory exists // then return false if( (errno != EEXIST) #ifdef __BORLANDC__ && (errno != EACCES) #endif ) { return false; } } return true; } // return true if the file exists bool System::FileExists(const char* filename) { #ifndef R_OK # define R_OK 04 #endif #ifdef _MSC_VER const std::wstring unc = System::ConvertToUNC(filename); if (_waccess(unc.c_str(), R_OK) != 0) #else if ( access(filename, R_OK) != 0 ) #endif { return false; } else { //assert( !FileIsDirectory(filename) ); return true; } } bool System::FileIsDirectory(const char* name) { #ifdef _MSC_VER struct _stat64i32 fs; const std::wstring wname = System::ConvertToUNC(name); if (_wstat(wname.c_str(), &fs) == 0) #else struct stat fs; if(stat(name, &fs) == 0) #endif { #if _WIN32 return ((fs.st_mode & _S_IFDIR) != 0); #else return S_ISDIR(fs.st_mode); #endif } else { return false; } } bool System::FileIsSymlink(const char* name) { #if defined( _WIN32 ) (void)name; #else struct stat fs; if(lstat(name, &fs) == 0) { return S_ISLNK(fs.st_mode); } #endif return false; } // TODO st_mtimensec time_t System::FileTime(const char* filename) { struct stat fs; if(stat(filename, &fs) == 0) { // man 2 stat // time_t st_atime; /* time of last access */ // time_t st_mtime; /* time of last modification */ // time_t st_ctime; /* time of last status change */ return fs.st_mtime; // Since kernel 2.5.48, the stat structure supports nanosecond resolution // for the three file timestamp fields. Glibc exposes the nanosecond com- // ponent of each field using names either of the form st_atim.tv_nsec, if // the _BSD_SOURCE or _SVID_SOURCE feature test macro is defined, or of // the form st_atimensec, if neither of these macros is defined. On file // systems that do not support sub-second timestamps, these nanosecond // fields are returned with the value 0. } return 0; } const char *System::GetLastSystemError() { int e = errno; return strerror(e); } bool System::GetPermissions(const char* file, unsigned short& mode) { if ( !file ) { return false; } struct stat st; if ( stat(file, &st) < 0 ) { return false; } mode = (short)st.st_mode; return true; } bool System::SetPermissions(const char* file, unsigned short mode) { if ( !file ) { return false; } if ( !System::FileExists(file) ) { return false; } if ( chmod(file, mode) < 0 ) { return false; } return true; } bool System::RemoveFile(const char* source) { #ifdef _WIN32 unsigned short mode; if ( !System::GetPermissions(source, mode) ) { return false; } /* Win32 unlink is stupid --- it fails if the file is read-only */ System::SetPermissions(source, S_IWRITE); #endif bool res = unlink(source) != 0 ? false : true; #ifdef _WIN32 if ( !res ) { System::SetPermissions(source, mode); } #endif return res; } // RemoveDirectory is a WIN32 function, use different name bool System::DeleteDirectory(const char *source) { unsigned short mode; if(System::GetPermissions(source, mode)) { #if defined(_WIN32) && !defined(__CYGWIN__) mode |= S_IWRITE; #else mode |= S_IWUSR; #endif System::SetPermissions(source, mode); } Directory dir; unsigned int numfiles = dir.Load(source, false); (void)numfiles; Directory::FilenamesType const & files = dir.GetFilenames(); for ( Directory::FilenamesType::const_iterator it = files.begin(); it != files.end(); ++it ) { const char *filename = it->c_str(); if( System::FileIsDirectory(filename) && !System::FileIsSymlink(filename) ) { if (!System::DeleteDirectory(filename)) { return false; } } else { if(!System::RemoveFile(filename)) { return false; } } } return Rmdir(source) == 0; } #ifndef PATH_MAX #define PATH_MAX 4096 #endif #ifdef _MSC_VER namespace { static inline std::wstring ToUtf16(std::string const &str) { std::wstring ret; int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.length(), nullptr, 0); if (len > 0) { ret.resize(len); MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.length(), &ret[0], len); } return ret; } // http://arsenmk.blogspot.com/2015/12/handling-long-paths-on-windows.html static inline bool ComputeFullPath(std::wstring const &in, std::wstring &out) { // consider an input fileName of type PCWSTR (const wchar_t*) const wchar_t *fileName = in.c_str(); DWORD requiredBufferLength = GetFullPathNameW(fileName, 0, nullptr, nullptr); if (0 == requiredBufferLength) // means failure { return false; } out.resize(requiredBufferLength); wchar_t *buffer = &out[0]; DWORD result = GetFullPathNameW(fileName, requiredBufferLength, buffer, nullptr); if (0 == result) { return false; } // buffer now contains the full path name of fileName, use it. return true; } static inline std::wstring HandleMaxPath(std::wstring const &in) { if (in.size() >= MAX_PATH) { std::wstring out; bool ret = ComputeFullPath(in, out); if (!ret) return in; if (out.size() < 4) return in; if (out[0] == '\\' && out[1] == '\\' && out[2] == '?') { // nothing to do } else if (out[0] == '\\' && out[1] == '\\' && out[2] != '?') { // server path const std::wstring prefix = LR"(\\?\UNC\)"; out = prefix + (out.c_str() + 2); } else { // regular C:\ style path: assert(out[1] == ':'); const std::wstring prefix = LR"(\\?\)"; out = prefix + out.c_str(); } return out; } return in; } } // namespace #endif std::wstring System::ConvertToUNC(const char *utf8path) { #ifdef _MSC_VER const std::wstring uft16path = ToUtf16(utf8path); const std::wstring uncpath = HandleMaxPath(uft16path); return uncpath; #else (void)utf8path; return std::wstring(); #endif } // return size of file; also returns zero if no file exists size_t System::FileSize(const char* filename) { #if 0 All of these system calls return a stat structure, which contains the following fields: struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* inode number */ mode_t st_mode; /* protection */ nlink_t st_nlink; /* number of hard links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ dev_t st_rdev; /* device ID (if special file) */ off_t st_size; /* total size, in bytes */ blksize_t st_blksize; /* blocksize for filesystem I/O */ blkcnt_t st_blocks; /* number of blocks allocated */ time_t st_atime; /* time of last access */ time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last status change */ }; #endif struct stat fs; if (stat(filename, &fs) != 0) { return 0; } off_t size = fs.st_size; size_t size2 = size; // off_t can be larger than size_t if( size != (off_t)size2 ) return 0; return size2; } /* * TODO: * check cygwin * check beos : get_next_image_info * check solaris * check hpux * check os2: DosGetInfoBlocks / DosQueryModuleName * ... */ const char *System::GetCurrentProcessFileName() { #ifdef _WIN32 static char buf[MAX_PATH]; if ( ::GetModuleFileName(0, buf, sizeof(buf)) ) { return buf; } #elif defined(GDCM_USE_COREFOUNDATION_LIBRARY) static char buf[PATH_MAX]; Boolean success = false; CFURLRef pathURL = CFBundleCopyExecutableURL(CFBundleGetMainBundle()); if ( pathURL) { success = CFURLGetFileSystemRepresentation(pathURL, true /*resolveAgainstBase*/, (unsigned char*) buf, PATH_MAX); CFRelease(pathURL); } if (success) { return buf; } #elif defined (__SVR4) && defined (__sun) // solaris const char *ret = getexecname(); if( ret ) return ret; //#elif defined(__NetBSD__) // static char path[PATH_MAX]; // if ( readlink ("/proc/curproc/exe", path, sizeof(path)) > 0) // { // return path; // } #elif defined(__DragonFly__) || defined(__OpenBSD__) || defined(__FreeBSD__) static char path[PATH_MAX]; if ( readlink ("/proc/curproc/file", path, sizeof(path)) > 0) { return path; } #elif defined(__linux__) static char path[PATH_MAX]; if ( readlink ("/proc/self/exe", path, sizeof(path)) > 0) // Technically 0 is not an error, but that would mean // 0 byte were copied ... thus considered it as an error { return path; } #else gdcmErrorMacro( "missing implementation" ); #endif return nullptr; } #ifdef __USE_GNU static void where_am_i() {} #endif const char *System::GetCurrentModuleFileName() { #ifdef __USE_GNU static char path[PATH_MAX]; Dl_info info; if (dladdr( (void*)&where_am_i, &info ) == 0) { size_t len = strlen(info.dli_fname); if( len >= PATH_MAX ) return nullptr; // throw error ? // else strcpy(path,info.dli_fname); return path; } #elif defined(_WIN32) // GetModuleFileName works the same on Win32 for library AFAIK return System::GetCurrentProcessFileName(); #endif return nullptr; } const char *System::GetCurrentResourcesDirectory() { #ifdef GDCM_USE_COREFOUNDATION_LIBRARY static char path[PATH_MAX]; Boolean success = false; CFURLRef pathURL = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); if (pathURL != nullptr) { success = CFURLGetFileSystemRepresentation(pathURL, true /*resolveAgainstBase*/, (unsigned char*) path, PATH_MAX); CFRelease(pathURL); } if (success) { strlcat(path, "/" GDCM_INSTALL_DATA_DIR, PATH_MAX); return path; } #endif // Is there such beast on *any* other system but APPLE ? return nullptr; } /** * \brief Encode the mac address on a fixed length string of 15 characters. * we save space this way. */ inline int getlastdigit(unsigned char *data, unsigned long size) { int extended, carry = 0; for(unsigned int i=0;i= 0 && carry < 10 ); return carry; } size_t System::EncodeBytes(char *out, const unsigned char *data, int size) { bool zero = false; int res; std::string sres; unsigned char buffer[32]; unsigned char *addr = buffer; memcpy(addr, data, size); while(!zero) { res = getlastdigit(addr, size); const char v = (char)('0' + res); sres.insert(sres.begin(), v); zero = true; for(int i = 0; i < size; ++i) { zero = zero && (addr[i] == 0); } } //return sres; strcpy(out, sres.c_str()); //, sres.size() ); return sres.size(); } #if defined(_WIN32) && !defined(GDCM_HAVE_GETTIMEOFDAY) #include // http://www.openasthra.com/c-tidbits/gettimeofday-function-for-windows/ // http://www.sisvia.com/blog/?p=24 // -> srand + gettimeofday // http://csl.sublevel3.org/c++/ static int gettimeofday2(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 = 0; GetSystemTimeAsFileTime(&ft); filetime |= ft.dwHighDateTime; filetime <<= 32; filetime |= ft.dwLowDateTime; filetime -= OFFSET; tv->tv_sec = (long)(filetime / 10000000); /* seconds since epoch */ tv->tv_usec = (uint32_t)((filetime % 10000000) / 10); return 0; } #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 #else #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL #endif //struct timezone //{ // int tz_minuteswest; /* minutes W of Greenwich */ // int tz_dsttime; /* type of dst correction */ //}; int gettimeofday(struct timeval *tv, struct timezone *tz) { /* The use of the timezone structure is obsolete; the tz argument should normally be specified as NULL. The tz_dsttime field has never been used under Linux; it has not been and will not be supported by libc or glibc. Each and every occurrence of this field in the kernel source (other than the declaration) is a bug. Thus, the following is purely of historic interest. */ assert( tz == 0 ); FILETIME ft; unsigned __int64 tmpres = 0; //static int tzflag; if (NULL != tv) { GetSystemTimeAsFileTime(&ft); tmpres |= ft.dwHighDateTime; tmpres <<= 32; tmpres |= ft.dwLowDateTime; /*converting file time to unix epoch*/ tmpres /= 10; /*convert into microseconds*/ tmpres -= DELTA_EPOCH_IN_MICROSECS; tv->tv_sec = (long)(tmpres / 1000000UL); tv->tv_usec = (long)(tmpres % 1000000UL); } // if (NULL != tz) // { // if (!tzflag) // { // _tzset(); // tzflag++; // } // tz->tz_minuteswest = _timezone / 60; // tz->tz_dsttime = _daylight; // } return 0; } #endif /** Implementation note. We internally use mktime which seems to be quite relaxed when it comes to invalid date. It handles : "17890714172557"; "19891714172557"; "19890014172557"; While the DICOM PS 3.5-2008 would prohibit them. I leave it this way so that we correctly read in /almost/ valid date. What we write out is always valid anyway which is what is important. */ bool System::ParseDateTime(time_t &timep, const char date[22]) { long milliseconds; return ParseDateTime(timep, milliseconds, date); } bool System::ParseDateTime(time_t &timep, long &milliseconds, const char date[22]) { if(!date) return false; size_t len = strlen(date); if( len < 4 ) return false; // need at least the full year if( len > 21 ) return false; struct tm ptm; // No such thing as strptime on some st*$^% platform #if defined(GDCM_HAVE_STRPTIME) && 0 char *ptr1 = strptime(date, "%Y%m%d%H%M%S", &ptm); if( ptr1 != date + 14 ) { // We stopped parsing the string at some point, assume this is an error return false; } #else // instead write our own: int year, mon, day, hour, min, sec, n; if ((n = sscanf(date, "%4d%2d%2d%2d%2d%2d", &year, &mon, &day, &hour, &min, &sec)) >= 1) { switch (n) { case 1: mon = 1; /* Falls through. */ case 2: day = 1; /* Falls through. */ case 3: hour = 0; /* Falls through. */ case 4: min = 0; /* Falls through. */ case 5: sec = 0; /* Falls through. */ break; // http://security.coverity.com/blog/2013/Sep/gimme-a-break.html } ptm.tm_year = year - 1900; if( mon < 1 || mon > 12 ) return false; ptm.tm_mon = mon - 1; if( day < 1 || day > 31 ) return false; ptm.tm_mday = day; if( hour > 24 ) return false; ptm.tm_hour = hour; if( min > 60 ) return false; ptm.tm_min = min; if( sec > 60 ) return false; ptm.tm_sec = sec; ptm.tm_wday = -1; ptm.tm_yday = -1; ptm.tm_isdst = -1; } else { return false; } #endif timep = mktime(&ptm); if( timep == (time_t)-1) return false; milliseconds = 0; if( len > 14 ) // more data to process { const char *ptr = date + 14; if( *ptr != '.' ) return false; ++ptr; if( !*ptr || sscanf( ptr, "%06ld", &milliseconds ) != 1 ) { // Could not parse milliseconds but date looks ok, should I return false anyway ? // -> yes this is an error ! return false; } } return true; } const char *System::GetTimezoneOffsetFromUTC() { static std::string buffer; char outstr[10]; time_t t = time(nullptr); struct tm *tmp = localtime(&t); size_t l = strftime(outstr, sizeof(outstr), "%z", tmp); assert( l == 5 ); (void)l; buffer = outstr; return buffer.c_str(); } bool System::FormatDateTime(char date[22], time_t timep, long milliseconds) { // \precondition if( !(milliseconds >= 0 && milliseconds < 1000000) ) { return false; } // YYYYMMDDHHMMSS.FFFFFF&ZZXX if(!date) { return false; } const size_t maxsize = 40; char tmp[maxsize]; // Obtain the time of day, and convert it to a tm struct. struct tm *ptm = localtime (&timep); if(!ptm) { return false; } // Format the date and time, down to a single second. size_t ret = strftime (tmp, sizeof (tmp), "%Y%m%d%H%M%S", ptm); assert( ret == 14 ); if( ret == 0 || ret >= maxsize ) { return false; } // Add milliseconds const size_t maxsizall = 22; const int ret2 = snprintf(date,maxsizall,"%s.%06ld",tmp,milliseconds); if( ret2 < 0 ) return false; if( (size_t)ret2 >= maxsizall ) { return false; } // Ok ! return true; } bool System::GetCurrentDateTime(char date[22]) { long milliseconds; time_t timep; #if 0 The functions gettimeofday() and settimeofday() can get and set the time as well as a timezone. The tv argument is a struct timeval (as specified in ): struct timeval { time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* microseconds */ }; and gives the number of seconds and microseconds since the Epoch (see time(2)). The tz argument is a struct timezone: struct timezone { int tz_minuteswest; /* minutes west of Greenwich */ int tz_dsttime; /* type of DST correction */ }; If either tv or tz is NULL, the corresponding structure is not set or returned. The use of the timezone structure is obsolete; the tz argument should normally be specified as NULL. The tz_dsttime field has never been used under Linux; it has not been and will not be supported by libc or glibc. Each and every occurrence of this field in the kernel source (other than the declaration) is a bug. Thus, the following is purely of historic interest. #endif // Apparently suseconds_t is defined as long on linux system... why would this be signed ? struct timeval tv; gettimeofday (&tv, nullptr); timep = tv.tv_sec; // A concatenated date-time character string in the format: // YYYYMMDDHHMMSS.FFFFFF&ZZXX // The components of this string, from left to right, are YYYY = Year, MM = // Month, DD = Day, HH = Hour (range "00" - "23"), MM = Minute (range "00" - // "59"), SS = Second (range "00" - "60"). // FFFFFF = Fractional Second contains a fractional part of a second as small // as 1 millionth of a second (range 000000 - 999999). assert( tv.tv_usec >= 0 && tv.tv_usec < 1000000 ); milliseconds = tv.tv_usec; return FormatDateTime(date, timep, milliseconds); } int System::StrNCaseCmp(const char *s1, const char *s2, size_t n) { #if defined(GDCM_HAVE_STRNCASECMP) return strncasecmp(s1,s2,n); #elif defined(GDCM_HAVE__STRNICMP) return _strnicmp(s1,s2,n); #else // default implementation #error assert( n ); // TODO while (--n && *s1 && (tolower(*s1) == tolower(*s2))) { s1++; s2++; } return tolower(*s1) - tolower(*s2); #endif } int System::StrCaseCmp(const char *s1, const char *s2) { #if defined(GDCM_HAVE_STRCASECMP) return strcasecmp(s1,s2); #elif defined(GDCM_HAVE__STRNICMP) return _stricmp(s1,s2); #else // default implementation #error while (*s1 && (tolower(*s1) == tolower(*s2))) { s1++; s2++; } return tolower(*s1) - tolower(*s2); #endif } bool System::GetHostName(char name[255]) { // http://msdn.microsoft.com/en-us/library/ms738527.aspx // WSANOTINITIALISED A successful WSAStartup call must occur before using this function. #if _WIN32 // Get the hostname WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(2,0); if ( WSAStartup( wVersionRequested, &wsaData ) == 0 ) { bool ret = false; if( gethostname(name,255) == 0 ) { ret = true; } else { *name = 0; } WSACleanup( ); return ret; } #else if( gethostname(name, 255) == 0 ) { return true; } #endif // If reach here gethostname failed, uninit name just in case *name = 0; return false; } char *System::StrTokR(char *str, const char *delim, char **nextp) { #if 1 // http://groups.google.com/group/comp.lang.c/msg/2ab1ecbb86646684 // PD -> http://groups.google.com/group/comp.lang.c/msg/7c7b39328fefab9c char *ret; if (str == nullptr) { str = *nextp; } str += strspn(str, delim); if (*str == '\0') { return nullptr; } ret = str; str += strcspn(str, delim); if (*str) { *str++ = '\0'; } *nextp = str; return ret; #else return strtok_r(str,delim,nextp); #endif } char *System::StrSep(char **sp, const char *sep) { // http://unixpapa.com/incnote/string.html // http://stackoverflow.com/questions/8512958/is-there-a-windows-variant-of-strsep #if 1 char *p, *s; if (sp == nullptr || *sp == nullptr || **sp == '\0') return nullptr; s = *sp; p = s + strcspn(s, sep); if (*p != '\0') *p++ = '\0'; *sp = p; return s; #else return strsep(sp, sep); #endif } struct CharsetAliasType { const char *alias; const char *name; }; #if defined(_WIN32) static const char *CharsetAliasToName(const char *alias) { assert( alias ); //gdcmDebugMacro( alias ); // http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx // 1252 windows-1252 ANSI Latin 1; Western European (Windows) static CharsetAliasType aliases[] = { { "CP1252", "ISO-8859-1" }, // mingw + debian/6.0 { NULL, NULL }, }; for( CharsetAliasType *a = aliases; a->alias; a++) { if (strcmp (a->alias, alias) == 0) { return a->name; } } // We need to tell the user... gdcmWarningMacro( std::string("Could not find Charset from alias: ") + alias ); return NULL; } #endif //_WIN32 const char *System::GetLocaleCharset() { const char *codeset = nullptr; #if defined(GDCM_HAVE_NL_LANGINFO) //setlocale (LC_CTYPE, NULL); /* According to documentation nl_langinfo needs : setlocale(3) needs to be executed with proper arguments before. However even if CODESET only required LC_TYPE only setting LC_TYPE is not enough to get it working on a debian/6.0 system within c++ so instead call setlocale on LC_ALL to fix it. */ char *oldlocale = strdup(setlocale(LC_ALL, "")); // TODO: what if setlocale return NULL ? codeset = nl_langinfo (CODESET); setlocale(LC_ALL, oldlocale); free(oldlocale); #endif // GDCM_HAVE_NL_LANGINFO #if defined(_WIN32) #if 0 char buf1[128]; char buf2[128]; const char *codeset1; const char *codeset2; codeset1 = buf1; codeset2 = buf2; sprintf(buf1, "CP%d", GetConsoleCP()); sprintf(buf2, "CP%d", GetConsoleOutputCP()); // BUG: both returns 'CP437' on debian + mingw32... // instead prefer GetACP() call: #endif static char buf[2+10+1]; // 2 char, 10 bytes + 0 // GetACP: Retrieves the current Windows ANSI code page identifier for the // operating system. sprintf (buf, "CP%u", GetACP ()); codeset = CharsetAliasToName(buf); #endif // warning ANSI_X3.4-1968 means ASCII return codeset; } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmSystem.h000066400000000000000000000126361412732066400173020ustar00rootroot00000000000000/*========================================================================= 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 GDCMSYSTEM_H #define GDCMSYSTEM_H #include "gdcmTypes.h" namespace gdcm { /** * \brief Class to do system operation * \details OS independent functionalities */ class GDCM_EXPORT System { public: /// Create a directory name path static bool MakeDirectory(const char *path); /// Check whether the specified file exist on the system static bool FileExists(const char* filename); /// Check whether the file specified is a directory: static bool FileIsDirectory(const char* name); /// Check whether name is a symlink static bool FileIsSymlink(const char* name); /// remove a file named source static bool RemoveFile(const char* source); /// remove a directory named source static bool DeleteDirectory(const char *source); /// When needed convert a PATH into a UNC equivalent. This allow /// transparent support for path longer that MAX_PATH. /// Only on _MSC_VER compiler, return empty string otherwise. static std::wstring ConvertToUNC(const char *utf8path); /// Return the last error static const char *GetLastSystemError(); /// Return the filesize. 0 if file does not exist. /// \warning you need to use FileExists to differentiate between empty file and missing file. /// \warning for very large size file and on system where size_t is not appropriate to store /// off_t value the function will return 0. static size_t FileSize(const char* filename); /// Return the time of last modification of file /// 0 if the file does not exist static time_t FileTime(const char* filename); /// Return the directory the current process (executable) is located: /// NOT THREAD SAFE static const char *GetCurrentProcessFileName(); /// Return the directory the current module is located: /// NOT THREAD SAFE static const char *GetCurrentModuleFileName(); /// On some system (Apple) return the path to the current bundled 'Resources' directory /// NOT THREAD SAFE static const char *GetCurrentResourcesDirectory(); // TODO some system calls // Chdir // copy a file /// Retrieve the hostname, only the first 255 byte are copied. /// This may come handy to specify the Station Name static bool GetHostName(char hostname[255]); // In the following the size '22' is explicitly listed. You need to pass in // at least 22bytes of array. If the string is an output it will be // automatically padded ( array[21] == 0 ) for you. // Those functions: GetCurrentDateTime / FormatDateTime / ParseDateTime do // not return the &YYZZ part of the DT structure as defined in DICOM PS 3.5 - // 2008 In this case it is simple to split the date[22] into a DA and TM // structure /// Return the current data time, and format it as ASCII text. /// This is simply a call to gettimeofday + FormatDateTime, since WIN32 do not have an /// implementation for gettimeofday, this is more portable. /// The call time(0) is not precise for our resolution static bool GetCurrentDateTime(char date[22]); /// format as ASCII text a time_t with milliseconds /// See VR::DT from DICOM PS 3.5 /// milliseconds is in the range [0, 999999] static bool FormatDateTime(char date[22], time_t t, long milliseconds = 0); /// Parse a date stored as ASCII text into a time_t structured (discard millisecond if any) static bool ParseDateTime(time_t &timep, const char date[22]); /// Parse a date stored as ASCII text into a time_t structured and millisecond /// \see FormatDateTime static bool ParseDateTime(time_t &timep, long &milliseconds, const char date[22]); /// Return the value for Timezone Offset From UTC as string. /// \warning not thread safe static const char *GetTimezoneOffsetFromUTC(); /// Used internally by the UIDGenerator class to convert a uuid tape to a /// DICOM VR:UI type static size_t EncodeBytes(char *out, const unsigned char *data, int size); /// consistent func for C99 spec of strcasecmp/strncasecmp static int StrCaseCmp(const char *s1, const char *s2); /// \pre n != 0 static int StrNCaseCmp(const char *s1, const char *s2, size_t n); /// Return current working directory /// Warning: if current working path is too long (>2048 bytes) the call will fail /// and call will return NULL /// NOT THREAD SAFE static const char * GetCWD(); /// strtok_r static char *StrTokR(char *ptr, const char *sep, char **end); /// strsep /// param stringp is passed by pointer, it may be modified, you'll need to /// make a copy, in case you want to free the memory pointed at static char *StrSep(char **stringp, const char *delim); /// return `locale charmap` static const char *GetLocaleCharset(); /// NOT THREAD SAFE /* static void SetArgv0(const char *); static const char* GetArgv0(); */ protected: static bool GetPermissions(const char* file, unsigned short& mode); static bool SetPermissions(const char* file, unsigned short mode); private: }; } // end namespace gdcm #endif //GDCMSYSTEM_H GDCM-3.0.10/Source/Common/gdcmTerminal.cxx000066400000000000000000000146331412732066400201430ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTerminal.h" #include #include #include #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include /* SetConsoleTextAttribute */ #endif // FIXME on ming32 a couple of stuff are not defined: #ifndef COMMON_LVB_REVERSE_VIDEO #define COMMON_LVB_REVERSE_VIDEO 0x4000 #endif #ifndef COMMON_LVB_UNDERSCORE #define COMMON_LVB_UNDERSCORE 0x8000 #endif namespace gdcm { namespace terminal { class ConsoleImp { private: // console implementation details: #ifdef _WIN32 HANDLE hConsoleHandle; CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo; WORD wNormalAttributes; #endif // vt100 implementation details: int attribute; int fgcolor; int bgcolor; public: ConsoleImp() { #ifdef _WIN32 hConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(hConsoleHandle, &ConsoleInfo); wNormalAttributes = ConsoleInfo.wAttributes; #endif attribute = fgcolor = bgcolor = 9; } ~ConsoleImp() { #ifdef _WIN32 SetConsoleTextAttribute(hConsoleHandle, wNormalAttributes); } WORD get_attributes() { GetConsoleScreenBufferInfo(hConsoleHandle, &ConsoleInfo); return ConsoleInfo.wAttributes; #endif } void setattribute(int att) { attribute = att; } void setfgcolor(int col) { fgcolor = col; } void setbgcolor(int col) { bgcolor = col; } //std::string resettextcolor() const { // char command[13]; // sprintf(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); assert( n < 16 ); (void)n; return command; } void set_attributes(int color) { #ifdef _WIN32 static const int colors[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; WORD wAttributes; wAttributes = get_attributes(); // http://swapoff.org/browser/todo/trunk/util/Terminal.cc // http://www.koders.com/cpp/fid5D5965EDC640274BE13A63CFEC649FA76F65A59D.aspx // http://cvs.4suite.org/viewcvs/4Suite/Ft/Lib/Terminal.py?rev=1.1&content-type=text/vnd.viewcvs-markup // http://linuxgazette.net/issue65/padala.html // https://svn.linux.ncsu.edu/svn/cls/branches/ncsu-gdm/pre-gdm-2.14/Xdefaults.old // http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/475116 // http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=linux&db=man&fname=/usr/share/catman/man4/console_codes.4.html // http://www.columbia.edu/kermit/ftp/k95/terminal.txt // http://www.codeproject.com/KB/cpp/Colored_Conslole_Messages.aspx // http://www.betarun.com/Pages/ConsoleColor/ // http://support.microsoft.com/?scid=kb%3Ben-us%3B319883&x=20&y=8 //http://www.dreamincode.net/code/snippet921.htm //http://www.codeproject.com/KB/cpp/Colored_Conslole_Messages.aspx //http://fabrizio.net/ccode/Old/20070427/Console.cpp //http://www.opensource.apple.com/darwinsource/10.4.8.x86/tcsh-46/tcsh/win32/console.c //http://msdn2.microsoft.com/en-us/library/ms682088(VS.85).aspx // { int n = color; if (n == 0) // Normal (default) wAttributes = wNormalAttributes; else if (n == 1) // Bold wAttributes |= FOREGROUND_INTENSITY; else if (n == 4) // Underlined wAttributes |= COMMON_LVB_UNDERSCORE; else if (n == 5) // Blink (appears as BACKGROUND_INTENSITY) wAttributes |= BACKGROUND_INTENSITY; else if (n == 7) // Inverse wAttributes |= COMMON_LVB_REVERSE_VIDEO; else if (n == 21) // Not bold wAttributes &= ~FOREGROUND_INTENSITY; else if (n == 24) // Not underlined wAttributes &= ~COMMON_LVB_UNDERSCORE; else if (n == 25) // Steady (not blinking) wAttributes &= ~BACKGROUND_INTENSITY; else if (n == 27) // Positive (not inverse) wAttributes &= ~COMMON_LVB_REVERSE_VIDEO; else if (30 <= n && n <= 37) // Set foreground color wAttributes = (wAttributes & ~0x0007) | colors[n - 30]; else if (n == 39) // Set foreground color to default wAttributes = (wAttributes & ~0x0007) | (wNormalAttributes & 0x0007); else if (40 <= n && n <= 47) // Set background color wAttributes = (wAttributes & ~0x0070) | (colors[n - 40] << 4); else if (n == 49) // Set background color to default wAttributes = (wAttributes & ~0x0070) | (wNormalAttributes & 0x0070); else if (90 <= n && n <= 97) // Set foreground color (bright) wAttributes = (wAttributes & ~0x0007) | colors[n - 90] | FOREGROUND_INTENSITY; else if (100 <= n && n <= 107) // Set background color (bright) wAttributes = (wAttributes & ~0x0070) | (colors[n - 100] << 4) | BACKGROUND_INTENSITY; else // (default) wAttributes = wNormalAttributes; } // Though Windows' console supports COMMON_LVB_REVERSE_VIDEO, // it seems to be buggy. So we must simulate it. if (wAttributes & COMMON_LVB_REVERSE_VIDEO) wAttributes = (wAttributes & COMMON_LVB_UNDERSCORE) | ((wAttributes & 0x00f0) >> 4) | ((wAttributes & 0x000f) << 4); SetConsoleTextAttribute(hConsoleHandle, wAttributes); #else (void)color; #endif //_WIN32 } }; // http://linuxgazette.net/issue65/padala.html // The Color Code: [{attr};{fg};{bg}m static ConsoleImp cimp; static Mode mode; void setmode( Mode m) { mode = m; } std::string setfgcolor( Color c) { if( mode == VT100 ) { cimp.setfgcolor(c); return cimp.textcolor(); } else if( mode == CONSOLE ) cimp.set_attributes(30+c); return ""; } std::string setbgcolor( Color c ) { if( mode == VT100 ) { cimp.setbgcolor(c); return cimp.textcolor(); } else if( mode == CONSOLE ) cimp.set_attributes(40+c); return ""; } std::string setattribute( Attribute att ) { if( mode == VT100 ) { cimp.setattribute(att); return cimp.textcolor(); } else if( mode == CONSOLE ) cimp.set_attributes(att); return ""; } } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmTerminal.h000066400000000000000000000030731412732066400175640ustar00rootroot00000000000000/*========================================================================= 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 GDCMTERMINAL_H #define GDCMTERMINAL_H #include "gdcmTypes.h" namespace gdcm { /** * \brief Class for Terminal * \details Allow one to print in color in a shell * - support VT100 compatible shell * - win32 console */ //----------------------------------------------------------------------------- namespace terminal { typedef enum { CONSOLE = 0, VT100 } Mode; typedef enum { black = 0, red, green, yellow, // brown ?? blue, magenta, cyan, white } Color; typedef enum { reset = 0, bright = 1, // bold dim = 2, underline = 3, blink = 5, reverse = 7, hidden = 8 } Attribute; GDCM_EXPORT std::string setattribute( Attribute att ); GDCM_EXPORT std::string setfgcolor( Color c ); GDCM_EXPORT std::string setbgcolor( Color c ); GDCM_EXPORT void setmode( Mode m); } } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMTERMINAL_H GDCM-3.0.10/Source/Common/gdcmTestDriver.h000066400000000000000000000017411412732066400201040ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // This header is included by all the C++ test drivers in GDCM. #ifndef GDCMTESTDRIVER_H #define GDCMTESTDRIVER_H // CREATE_TEST_SOURCELIST supports the flag EXTRA_INCLUDE but only one per call. // So there is no way to specify we want to include two files... instead // gather the #include in a single file and include that one... #include // C setlocale() #include // C++ locale #endif // GDCMTESTDRIVER_H GDCM-3.0.10/Source/Common/gdcmTesting.cxx000066400000000000000000000417401412732066400200040ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTesting.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmMD5.h" #include // strcmp #include // malloc namespace gdcm { #ifndef GDCM_BUILD_TESTING #error how did that happen ? #endif #include "gdcmDataFileNames.cxx" #include "gdcmMD5DataImages.cxx" #include "gdcmMD5DataBrokenImages.cxx" #include "gdcmMediaStorageDataFiles.cxx" #include "gdcmStreamOffsetDataFiles.cxx" // After gdcmStreamOffsetDataFiles: #include "gdcmSelectedTagsOffsetDataFiles.cxx" #include "gdcmSelectedPrivateGroupOffsetDataFiles.cxx" bool Testing::ComputeMD5(const char *buffer, size_t buf_len, char digest_str[33]) { return MD5::Compute(buffer, buf_len, digest_str); } bool Testing::ComputeFileMD5(const char *filename, char *digest_str) { return MD5::ComputeFile(filename, digest_str); } const char * const *Testing::GetFileNames() { return gdcmDataFileNames; } unsigned int Testing::GetNumberOfFileNames() { // Do not count NULL value: static const unsigned int size = sizeof(gdcmDataFileNames)/sizeof(*gdcmDataFileNames) - 1; return size; } const char * Testing::GetFileName(unsigned int file) { if( file < Testing::GetNumberOfFileNames() ) return gdcmDataFileNames[file]; return nullptr; } Testing::MediaStorageDataFilesType Testing::GetMediaStorageDataFiles() { return gdcmMediaStorageDataFiles; } unsigned int Testing::GetNumberOfMediaStorageDataFiles() { // Do not count NULL value: static const unsigned int size = sizeof(gdcmMediaStorageDataFiles)/sizeof(*gdcmMediaStorageDataFiles) - 1; return size; } const char * const * Testing::GetMediaStorageDataFile(unsigned int file) { if( file < Testing::GetNumberOfMediaStorageDataFiles() ) return gdcmMediaStorageDataFiles[file]; // else return the {0x0, 0x0} sentinel: assert( *gdcmMediaStorageDataFiles[ Testing::GetNumberOfMediaStorageDataFiles() ] == nullptr ); return gdcmMediaStorageDataFiles[ Testing::GetNumberOfMediaStorageDataFiles() ]; } const char * Testing::GetMediaStorageFromFile(const char *filepath) { unsigned int i = 0; MediaStorageDataFilesType mediastorages = GetMediaStorageDataFiles(); const char *p = mediastorages[i][0]; Filename comp(filepath); const char *filename = comp.GetName(); while( p != nullptr ) { if( strcmp( filename, p ) == 0 ) { break; } ++i; p = mediastorages[i][0]; } // \postcondition always valid (before sentinel) assert( i <= GetNumberOfMediaStorageDataFiles() ); return mediastorages[i][1]; } Testing::MD5DataImagesType Testing::GetMD5DataImages() { return gdcmMD5DataImages; } unsigned int Testing::GetNumberOfMD5DataImages() { // Do not count NULL value: static const unsigned int size = sizeof(gdcmMD5DataImages)/sizeof(*gdcmMD5DataImages) - 1; return size; } const char * const * Testing::GetMD5DataImage(unsigned int file) { if( file < Testing::GetNumberOfMD5DataImages() ) return gdcmMD5DataImages[file]; // else return the {0x0, 0x0} sentinel: assert( *gdcmMD5DataImages[ Testing::GetNumberOfMD5DataImages() ] == nullptr ); return gdcmMD5DataImages[ Testing::GetNumberOfMD5DataImages() ]; } const char * Testing::GetMD5FromFile(const char *filepath) { if(!filepath) return nullptr; unsigned int i = 0; MD5DataImagesType md5s = GetMD5DataImages(); const char *p = md5s[i][1]; Filename comp(filepath); const char *filename = comp.GetName(); while( p != nullptr ) { if( strcmp( filename, p ) == 0 ) { break; } ++i; p = md5s[i][1]; } // \postcondition always valid (before sentinel) assert( i <= GetNumberOfMD5DataImages() ); return md5s[i][0]; } const char * Testing::GetMD5FromBrokenFile(const char *filepath) { int i = 0; Testing::MD5DataImagesType md5s = gdcmMD5DataBrokenImages; //GetMD5DataImages(); const char *p = md5s[i][1]; Filename comp(filepath); const char *filename = comp.GetName(); while( p != nullptr ) { if( strcmp( filename, p ) == 0 ) { break; } ++i; p = md5s[i][1]; } return md5s[i][0]; } std::streamoff Testing::GetStreamOffsetFromFile(const char *filepath) { if(!filepath) return 0; unsigned int i = 0; const StreamOffset* so = gdcmStreamOffsetDataFiles; const char *p = so[i].filename; Filename comp(filepath); const char *filename = comp.GetName(); while( p != nullptr ) { if( strcmp( filename, p ) == 0 ) { break; } ++i; p = so[i].filename; } return so[i].offset; } std::streamoff Testing::GetSelectedPrivateGroupOffsetFromFile(const char *filepath) { if(!filepath) return 0; unsigned int i = 0; const StreamOffset* so = gdcmSelectedPrivateGroupOffsetDataFiles; const char *p = so[i].filename; Filename comp(filepath); const char *filename = comp.GetName(); while( p != nullptr ) { if( strcmp( filename, p ) == 0 ) { break; } ++i; p = so[i].filename; } return so[i].offset; } std::streamoff Testing::GetSelectedTagsOffsetFromFile(const char *filepath) { if(!filepath) return 0; unsigned int i = 0; const StreamOffset* so = gdcmSelectedTagsOffsetDataFiles; const char *p = so[i].filename; Filename comp(filepath); const char *filename = comp.GetName(); while( p != nullptr ) { if( strcmp( filename, p ) == 0 ) { break; } ++i; p = so[i].filename; } return so[i].offset; } // See TestImageReader + lossydump = true to generate this list: struct LossyFile { int lossyflag; const char *filename; }; static const LossyFile gdcmLossyFilenames[] = { { 0,"SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs.acr" }, { 0,"MR-MONO2-12-an2.acr" }, { 0,"gdcm-ACR-LibIDO.acr" }, { 0,"test.acr" }, { 0,"MR-MONO2-12-angio-an1.acr" }, { 0,"LIBIDO-8-ACR_NEMA-Lena_128_128.acr" }, { 0,"libido1.0-vol.acr" }, { 0,"gdcm-MR-SIEMENS-16-2.acr" }, { 0,"CT-MONO2-12-lomb-an2.acr" }, { 0,"LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm" }, { 0,"00191113.dcm" }, { 0,"SignedShortLosslessBug.dcm" }, { 0,"gdcm-MR-PHILIPS-16-NonSquarePixels.dcm" }, { 0,"MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm" }, { 0,"ACUSON-24-YBR_FULL-RLE.dcm" }, { 0,"D_CLUNIE_VL2_RLE.dcm" }, { 0,"MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm" }, { 0,"MR_Philips-Intera_BreaksNOSHADOW.dcm" }, { 0,"D_CLUNIE_MR2_JPLL.dcm" }, { 0,"D_CLUNIE_XA1_JPLL.dcm" }, { 1,"JPEG_LossyYBR.dcm" }, { 0,"ALOKA_SSD-8-MONO2-RLE-SQ.dcm" }, { 0,"PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm" }, { 0,"MR-MONO2-12-shoulder.dcm" }, { 1,"D_CLUNIE_RG3_JPLY.dcm" }, { 1,"PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm" }, { 0,"MR-MONO2-8-16x-heart.dcm" }, { 0,"SIEMENS_ImageLocationUN.dcm" }, { 0,"US-PAL-8-10x-echo.dcm" }, { 0,"PHILIPS_Brilliance_ExtraBytesInOverlay.dcm" }, { 0,"SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm" }, { 0,"LEADTOOLS_FLOWERS-8-PAL-RLE.dcm" }, { 0,"US-RGB-8-esopecho.dcm" }, { 0,"GE_RHAPSODE-16-MONO2-JPEG-Fragments.dcm" }, { 0,"CT-SIEMENS-Icone-With-PaletteColor.dcm" }, { 0,"LEADTOOLS_FLOWERS-16-MONO2-Uncompressed.dcm" }, { 0,"FUJI-10-MONO1-ACR_NEMA_2.dcm" }, { 0,"D_CLUNIE_CT1_RLE.dcm" }, { 0,"undefined_length_un_vr.dcm" }, { 0,"D_CLUNIE_MR4_JPLL.dcm" }, { 1,"DCMTK_JPEGExt_12Bits.dcm" }, { 0,"CT_16b_signed-UsedBits13.dcm" }, { 0,"DX_J2K_0Padding.dcm" }, { 0,"KODAK_CompressedIcon.dcm" }, { 0,"D_CLUNIE_CT2_JPLL.dcm" }, { 0,"DermaColorLossLess.dcm" }, { 0,"GE_GENESIS-16-MONO2-Uncompressed-UnusualVR.dcm" }, { 1,"D_CLUNIE_NM1_JPLY.dcm" }, { 0,"MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm" }, { 1,"LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm" }, { 0,"D_CLUNIE_CT1_J2KR.dcm" }, { 0,"LEADTOOLS_FLOWERS-16-MONO2-RLE.dcm" }, { 0,"US-RGB-8-epicard.dcm" }, { 0,"D_CLUNIE_MR3_RLE.dcm" }, { 0,"LEADTOOLS_FLOWERS-8-MONO2-Uncompressed.dcm" }, { 0,"US-IRAD-NoPreambleStartWith0005.dcm" }, { 0,"D_CLUNIE_RG2_JPLL.dcm" }, { 0,"DMCPACS_ExplicitImplicit_BogusIOP.dcm" }, { 0,"MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm" }, { 0,"MR-SIEMENS-DICOM-WithOverlays.dcm" }, { 0,"SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm" }, { 0,"JDDICOM_Sample2-dcmdjpeg.dcm" }, { 0,"SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm" }, { 1,"D_CLUNIE_MR3_JPLY.dcm" }, { 0,"MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm" }, { 0,"TheralysGDCM120Bug.dcm" }, { 0,"PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm" }, { 1,"US-GE-4AICL142.dcm" }, { 0,"MR16BitsAllocated_8BitsStored.dcm" }, { 0,"3E768EB7.dcm" }, { 0,"SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm" }, { 0,"GE_MR_0025xx1bProtocolDataBlock.dcm" }, { 0,"MR_GE_with_Private_Compressed_Icon_0009_1110.dcm" }, { 0,"ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm" }, { 1,"D_CLUNIE_SC1_JPLY.dcm" }, { 0,"CT-MONO2-16-chest.dcm" }, { 0,"D_CLUNIE_MR4_RLE.dcm" }, { 0,"SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm" }, { 1,"ELSCINT1_JP2vsJ2K.dcm" }, { 0,"D_CLUNIE_CT2_RLE.dcm" }, { 0,"D_CLUNIE_MR2_RLE.dcm" }, { 0,"OT-MONO2-8-a7.dcm" }, { 0,"MR-MONO2-16-head.dcm" }, { 0,"PICKER-16-MONO2-No_DicomV3_Preamble.dcm" }, { 1,"gdcm-JPEG-Extended.dcm" }, { 0,"BugGDCM2_UndefItemWrongVL.dcm" }, { 0,"D_CLUNIE_MR1_RLE.dcm" }, { 0,"PICKER-16-MONO2-Nested_icon.dcm" }, { 0,"D_CLUNIE_VL4_RLE.dcm" }, { 0,"D_CLUNIE_RG1_RLE.dcm" }, { 1,"JDDICOM_Sample2.dcm" }, { 0,"AMIInvalidPrivateDefinedLengthSQasUN.dcm" }, { 0,"SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm" }, { 0,"CT-MONO2-8-abdo.dcm" }, { 0,"D_CLUNIE_SC1_RLE.dcm" }, { 0,"LEADTOOLS_FLOWERS-24-RGB-JpegLossless.dcm" }, { 0,"D_CLUNIE_RG3_JPLL.dcm" }, { 0,"SIEMENS_CSA2.dcm" }, { 0,"LJPEG_BuginGDCM12.dcm" }, { 0,"CT-SIEMENS-MissingPixelDataInIconSQ.dcm" }, { 0,"05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm" }, { 0,"GE_CT_With_Private_compressed-icon.dcm" }, { 1,"D_CLUNIE_XA1_JPLY.dcm" }, { 0,"012345.002.050.dcm" }, { 0,"TOSHIBA_MRT150-16-MONO2-ACR_NEMA_2.dcm" }, { 1,"LEADTOOLS_FLOWERS-8-MONO2-JpegLossy.dcm" }, { 0,"gdcm-US-ALOKA-16.dcm" }, { 0,"THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm" }, { 0,"D_CLUNIE_CT1_JPLL.dcm" }, { 0,"rle16loo.dcm" }, { 0,"D_CLUNIE_US1_RLE.dcm" }, { 0,"LEADTOOLS_FLOWERS-8-MONO2-RLE.dcm" }, { 0,"RadBWLossLess.dcm" }, { 1,"D_CLUNIE_MR1_JPLY.dcm" }, { 0,"JPEGDefinedLengthSequenceOfFragments.dcm" }, { 0,"GE_DLX-8-MONO2-PrivateSyntax.dcm" }, { 0,"gdcm-JPEG-LossLess3a.dcm" }, { 0,"TG18-CH-2k-01.dcm" }, { 0,"OT-PAL-8-face.dcm" }, { 0,"D_CLUNIE_NM1_RLE.dcm" }, { 0,"rle16sti.dcm" }, { 0,"GE_GENESIS-16-MONO2-WrongLengthItem.dcm" }, { 1,"D_CLUNIE_CT1_J2KI.dcm" }, { 0,"SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm" }, { 0,"LEADTOOLS_FLOWERS-24-RGB-Uncompressed.dcm" }, { 1,"D_CLUNIE_MR4_JPLY.dcm" }, { 0,"OsirixFake16BitsStoredFakeSpacing.dcm" }, { 0,"PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm" }, { 0,"MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm" }, { 0,"D_CLUNIE_CT1_JLSL.dcm" }, { 1,"D_CLUNIE_CT1_JLSN.dcm" }, { 0,"D_CLUNIE_RG3_RLE.dcm" }, { 1,"SIEMENS-12-Jpeg_Process_2_4-Lossy-a.dcm" }, { 0,"CT-MONO2-16-brain.dcm" }, { 1,"D_CLUNIE_RG2_JPLY.dcm" }, { 1,"MAROTECH_CT_JP2Lossy.dcm" }, { 0,"D_CLUNIE_MR1_JPLL.dcm" }, { 0,"ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm" }, { 0,"SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm" }, { 0,"MR_SIEMENS_forceLoad29-1010_29-1020.dcm" }, { 0,"simpleImageWithIcon.dcm" }, { 0,"D_CLUNIE_MR3_JPLL.dcm" }, { 0,"D_CLUNIE_RG1_JPLL.dcm" }, { 0,"US-MONO2-8-8x-execho.dcm" }, { 0,"XA-MONO2-8-12x-catheter.dcm" }, { 0,"GE_LOGIQBook-8-RGB-HugePreview.dcm" }, { 0,"gdcm-MR-PHILIPS-16-Multi-Seq.dcm" }, { 0,"D_CLUNIE_XA1_RLE.dcm" }, { 0,"NM-MONO2-16-13x-heart.dcm" }, { 0,"gdcm-JPEG-LossLessThoravision.dcm" }, { 0,"GE_DLX-8-MONO2-Multiframe.dcm" }, { 0,"PHILIPS_Intera-16-MONO2-Uncompress.dcm" }, { 1,"D_CLUNIE_MR2_JPLY.dcm" }, { 0,"05148044-mr-siemens-avanto-syngo.dcm" }, { 0,"D_CLUNIE_VL3_RLE.dcm" }, { 0,"D_CLUNIE_RG2_RLE.dcm" }, { 0,"SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm" }, { 0,"KODAK-12-MONO1-Odd_Terminated_Sequence.dcm" }, { 0,"SIEMENS-MR-RGB-16Bits.dcm" }, { 0,"CR-MONO1-10-chest.dcm" }, { 0,"DX_GE_FALCON_SNOWY-VOI.dcm" }, { 0,"US-IRAD-NoPreambleStartWith0003.dcm" }, { 0,"MR-Brucker-CineTagging-NonSquarePixels.dcm" }, { 0,"D_CLUNIE_VL6_RLE.dcm" }, { 0,"MR_Philips_Intera_PrivateSequenceImplicitVR.dcm" }, { 0,"fffc0000UN.dcm" }, { 0,"SIEMENS_Sonata-12-MONO2-SQ.dcm" }, { 0,"ACUSON-24-YBR_FULL-RLE-b.dcm" }, { 0,"CT-MONO2-16-ankle.dcm" }, { 0,"GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm" }, { 0,"CT-MONO2-16-ort.dcm" }, { 0,"LEADTOOLS_FLOWERS-16-MONO2-JpegLossless.dcm" }, { 0,"D_CLUNIE_NM1_JPLL.dcm" }, { 0,"D_CLUNIE_VL1_RLE.dcm" }, { 0,"SIEMENS_MAGNETOM-12-MONO2-VRUN.dcm" }, { 0,"00191113.dcm" }, { 0,"TestVRSQUN2.dcm" }, { 0,"PHILIPS_GDCM12xBug.dcm"}, { 0,"PHILIPS_GDCM12xBug2.dcm"}, { 0,"TestVRSQUN1.dcm"} , { 1,"multiframegrayscalebytescis.dcm" }, { 1,"multiframegrayscalewordscis.dcm" }, { 1,"multiframesinglebitscis.dcm" }, { 1,"multiframetruecolorscis.dcm" }, { 1,"SinglePrecisionSC.dcm" }, { 0,"signedtruecoloroldsc.dcm" }, { 0,"o.dcm" }, { 0,"UnexpectedSequenceDelimiterInFixedLengthSequence.dcm" }, { 0,"IM-0001-0066.CommandTag00.dcm" }, { 0,"NM_Kakadu44_SOTmarkerincons.dcm" }, { 0,"GDCMJ2K_TextGBR.dcm" }, { 0,"PhilipsInteraSeqTermInvLen.dcm" }, { 0,"LIBIDO-24-ACR_NEMA-Rectangle.dcm" }, { 0,"TOSHIBA_J2K_SIZ1_PixRep0.dcm" }, { 0,"TOSHIBA_J2K_SIZ0_PixRep1.dcm" }, { 0,"TOSHIBA_J2K_OpenJPEGv2Regression.dcm" }, { 0,"NM-PAL-16-PixRep1.dcm" }, { 0,"MEDILABInvalidCP246_EVRLESQasUN.dcm" }, { 0,"JPEGInvalidSecondFrag.dcm" }, { 0,"SC16BitsAllocated_8BitsStoredJ2K.dcm" }, { 0,"SC16BitsAllocated_8BitsStoredJPEG.dcm" }, { 0,"SIEMENS_SYNGO-12-MONO2-LUTWrongLength512.dcm" }, { 0,"JPEGLS_CharLS_10742.dcm" }, { 1,"JPEGLosslessYBR_FULL_422.dcm" }, { 1,"JPEGNote_empty.dcm" }, { 1,"JPEGNote_missing.dcm" }, { 1,"JPEGNote_bogus.dcm" }, { 0,"RLEDebianBug816607Orig.dcm" }, { 0,"IllegalGroup2ImplicitTS.dcm" }, { 0,"GE_MR_0025xx1bProtocolDataBlockXML.dcm" }, { 0,"EmptyIcon_Bug417.dcm" }, { 0,"EnhancedWithIPPPerFrameIOPShared.dcm" }, { 0,"FUJI-ffff-MONO1-J2K.dcm" }, { 0,"JPEGLosslessSeNonZero.dcm" }, { 1,"US-YBR_FULL_422-EVRLE.dcm" }, { 0,"Osirix10vs8BitsStored.dcm" }, { 0,"Bug_Siemens_PrivateIconNoItem.dcm" }, { 0,"HardcopyColor_YBR_RCT_J2K_PC1.dcm" }, { 0,"PET-GE-dicomwrite-PixelDataSQUNv2.dcm" }, { 0, nullptr } }; int Testing::GetLossyFlagFromFile(const char *filename) { if( !filename ) return 0; gdcm::Filename fn = filename; const char *file = fn.GetName(); const LossyFile *pfiles = gdcmLossyFilenames; while( pfiles->filename && strcmp(pfiles->filename, file) != 0 ) { ++pfiles; } if( !(pfiles->filename) ) { std::cerr << "Error: No ref table for: " << filename << std::endl; return -1; } assert( pfiles->filename ); // need to update ref table return pfiles->lossyflag; } const char *Testing::GetDataRoot() { return GDCM_DATA_ROOT; } const char *Testing::GetDataExtraRoot() { return GDCM_DATA_EXTRA_ROOT; } const char *Testing::GetPixelSpacingDataRoot() { return GDCM_PIXEL_SPACING_DATA_ROOT; } const char *Testing::GetTempDirectory(const char * subdir) { if( !subdir ) return GDCM_TEMP_DIRECTORY; // else static std::string buffer; std::string tmpdir = GDCM_TEMP_DIRECTORY; tmpdir += "/"; tmpdir += subdir; buffer = tmpdir; return buffer.c_str(); } const wchar_t *Testing::GetTempDirectoryW(const wchar_t * subdir) { static std::wstring buffer; wchar_t wname[4096]; // FIXME size_t len = mbstowcs(wname,GDCM_TEMP_DIRECTORY,sizeof(wname)/sizeof(wchar_t)); (void)len; if( !subdir ) { buffer = wname; return buffer.c_str(); } // else std::wstring tmpdir = wname; tmpdir += L"/"; tmpdir += subdir; buffer = tmpdir; return buffer.c_str(); } const char * Testing::GetTempFilename(const char *filename, const char * subdir) { if( !filename ) return nullptr; static std::string buffer; std::string outfilename = GetTempDirectory(subdir); outfilename += "/"; gdcm::Filename out(filename); outfilename += out.GetName(); buffer = outfilename; return buffer.c_str(); } void Testing::Print(std::ostream &os) { os << "DataFileNames:\n"; const char * const * filenames = gdcmDataFileNames; while( *filenames ) { os << *filenames << "\n"; ++filenames; } os << "MD5DataImages:\n"; MD5DataImagesType md5s = gdcmMD5DataImages; while( (*md5s)[0] ) { os << (*md5s)[0] << " -> " << (*md5s)[1] << "\n"; ++md5s; } } const wchar_t* Testing::GetTempFilenameW(const wchar_t *filename, const wchar_t* subdir) { // mbsrtowcs // mbstowcs if( !filename ) return nullptr; static std::wstring buffer; std::wstring outfilename = GetTempDirectoryW(subdir); outfilename += L"/"; //gdcm::Filename out(filename); //outfilename += out.GetName(); buffer = outfilename; buffer += filename; return buffer.c_str(); } const char *Testing::GetSourceDirectory() { return GDCM_SOURCE_DIR; } } // end of namespace gdcm GDCM-3.0.10/Source/Common/gdcmTesting.h000066400000000000000000000106601412732066400174260ustar00rootroot00000000000000/*========================================================================= 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 GDCMTESTING_H #define GDCMTESTING_H #include "gdcmTypes.h" #include namespace gdcm { /** * \brief class for testing * \details this class is used for the nightly regression system for GDCM * It makes heavily use of md5 computation * * \see gdcm::MD5 class for md5 computation */ //----------------------------------------------------------------------------- class GDCM_EXPORT Testing { public : Testing() = default;; ~Testing() = default;; /// MD5 stuff /// digest_str needs to be at least : strlen = [2*16+1]; /// string will be \0 padded. (md5 are 32 bytes long) /// Testing is not meant to be shipped with an installed GDCM release, always /// prefer the gdcm::MD5 API when doing md5 computation. static bool ComputeMD5(const char *buffer, size_t buf_len, char digest_str[33]); static bool ComputeFileMD5(const char *filename, char digest_str[33]); /// Print void Print(std::ostream &os = std::cout); /// return the table of fullpath to gdcmData DICOM files: static const char * const * GetFileNames(); static unsigned int GetNumberOfFileNames(); static const char * GetFileName(unsigned int file); /// return the table that map the media storage (as string) of a filename (gdcmData) typedef const char* const (*MediaStorageDataFilesType)[2]; static MediaStorageDataFilesType GetMediaStorageDataFiles(); static unsigned int GetNumberOfMediaStorageDataFiles(); static const char * const * GetMediaStorageDataFile(unsigned int file); static const char * GetMediaStorageFromFile(const char *filepath); /// return the table that map the md5 (as in md5sum) of the Pixel Data associated /// to a filename typedef const char* const (*MD5DataImagesType)[2]; static MD5DataImagesType GetMD5DataImages(); static unsigned int GetNumberOfMD5DataImages(); static const char * const * GetMD5DataImage(unsigned int file); static const char * GetMD5FromFile(const char *filepath); /// Return what should have been the md5 of file 'filepath' /// This is based on current GDCM implementation to decipher a broken DICOM file. static const char * GetMD5FromBrokenFile(const char *filepath); /// Return the offset of the very first pixel cell in the PixelData /// -1 if not found static std::streamoff GetStreamOffsetFromFile(const char *filepath); /// Return the offset just after Pixel Data Length (7fe0,0000) if found. /// Otherwise the offset of the very first pixel cell in Pixel Data /// -1 if not found static std::streamoff GetSelectedTagsOffsetFromFile(const char *filepath); /// Return the offset just after private attribute (0009,0010,"GEMS_IDEN_01") if found. /// Otherwise the offset of the next attribute /// -1 if not found static std::streamoff GetSelectedPrivateGroupOffsetFromFile(const char *filepath); /// Return the lossy flag of the given filename /// -1 -> Error /// 0 -> Lossless /// 1 -> Lossy static int GetLossyFlagFromFile(const char *filepath); /// Return the GDCM DATA ROOT static const char * GetDataRoot(); /// Return the GDCM DATA EXTRA ROOT static const char * GetDataExtraRoot(); /// Return the GDCM PIXEL SPACING DATA ROOT (See David Clunie website for dataset) static const char * GetPixelSpacingDataRoot(); /// NOT THREAD SAFE /// Returns the temp directory as used in testing needing to output data: static const char * GetTempDirectory(const char * subdir = nullptr); /// NOT THREAD SAFE static const wchar_t *GetTempDirectoryW(const wchar_t * subdir = nullptr); /// NOT THREAD SAFE static const char * GetTempFilename(const char *filename, const char * subdir = nullptr); /// NOT THREAD SAFE static const wchar_t* GetTempFilenameW(const wchar_t *filename, const wchar_t* subdir = nullptr); static const char *GetSourceDirectory(); }; } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMTESTING_H GDCM-3.0.10/Source/Common/gdcmTrace.cxx000066400000000000000000000064661412732066400174330ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTrace.h" #include #include namespace gdcm { //----------------------------------------------------------------------------- // Warning message level to be displayed static bool DebugFlag = false; static bool WarningFlag = true; static bool ErrorFlag = true; // Stream based API: static std::ostream * DebugStream = &std::cerr; static std::ostream * WarningStream = &std::cerr; static std::ostream * ErrorStream = &std::cerr; // File based API: static bool UseStreamToFile = false; static std::ofstream * FileStream = nullptr; void Trace::SetStreamToFile( const char *filename ) { if( !filename ) return; if( UseStreamToFile ) { assert( FileStream ); FileStream->close(); FileStream = nullptr; UseStreamToFile = false; } std::ofstream * out = new std::ofstream; if( !out ) return; out->open( filename ); if( !out->good() ) return; assert( !FileStream && !UseStreamToFile ); FileStream = out; UseStreamToFile = true; DebugStream = FileStream; WarningStream = FileStream; ErrorStream = FileStream; } void Trace::SetStream(std::ostream &os) { if( !os.good() ) return; if( UseStreamToFile ) { assert( FileStream ); FileStream->close(); FileStream = nullptr; UseStreamToFile = false; } DebugStream = &os; WarningStream = &os; ErrorStream = &os; } std::ostream &Trace::GetStream() { return *DebugStream; } void Trace::SetDebugStream(std::ostream &os) { DebugStream = &os; } std::ostream &Trace::GetDebugStream() { return *DebugStream; } void Trace::SetWarningStream(std::ostream &os) { WarningStream = &os; } std::ostream &Trace::GetWarningStream() { return *WarningStream; } void Trace::SetErrorStream(std::ostream &os) { ErrorStream = &os; } std::ostream &Trace::GetErrorStream() { return *ErrorStream; } //----------------------------------------------------------------------------- // Constructor / Destructor Trace::Trace() { DebugFlag = WarningFlag = ErrorFlag = false; } Trace::~Trace() { if( UseStreamToFile ) { assert( FileStream ); FileStream->close(); FileStream = nullptr; } } void Trace::SetDebug(bool debug) { DebugFlag = debug; } void Trace::DebugOn() { DebugFlag = true; } void Trace::DebugOff() { DebugFlag = false; } bool Trace::GetDebugFlag() { return DebugFlag; } void Trace::SetWarning(bool warning) { WarningFlag = warning; } void Trace::WarningOn() { WarningFlag = true; } void Trace::WarningOff() { WarningFlag = false; } bool Trace::GetWarningFlag() { return WarningFlag; } void Trace::SetError(bool error) { ErrorFlag = error; } void Trace::ErrorOn() { ErrorFlag = true; } void Trace::ErrorOff() { ErrorFlag = false; } bool Trace::GetErrorFlag() { return ErrorFlag; } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmTrace.h000066400000000000000000000216451412732066400170540ustar00rootroot00000000000000/*========================================================================= 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 GDCMTRACE_H #define GDCMTRACE_H #include "gdcmTypes.h" #include "gdcmSystem.h" #include #include namespace gdcm { /** * \brief Trace * \details Debug / Warning and Error are encapsulated in this class * by default the Trace class will redirect any debug/warning/error * to std::cerr. Unless SetStream was specified with another (open) stream or * SetStreamToFile was specified to a writable file on the system. * * \warning * All string messages are removed during compilation time when compiled with * CMAKE_BUILD_TYPE being set to either: * - Release * - MinSizeRel * It is recommended to compile with RelWithDebInfo and/or Debug during * prototyping of applications. */ class GDCM_EXPORT Trace { public : Trace(); ~Trace(); /// Explicitly set the ostream for gdcm::Trace to report to /// This will set the DebugStream, WarningStream and ErrorStream at once: static void SetStream(std::ostream &os); static std::ostream &GetStream(); /// Explicitly set the stream which receive Debug messages: static void SetDebugStream(std::ostream &os); static std::ostream &GetDebugStream(); /// Explicitly set the stream which receive Warning messages: static void SetWarningStream(std::ostream &os); static std::ostream &GetWarningStream(); /// Explicitly set the stream which receive Error messages: static void SetErrorStream(std::ostream &os); static std::ostream &GetErrorStream(); /// Explicitly set the filename for gdcm::Trace to report to /// The file will be created (it will not append to existing file) static void SetStreamToFile( const char *filename ); /// Turn debug messages on (default: false) static void SetDebug(bool debug); static void DebugOn(); static void DebugOff(); static bool GetDebugFlag(); /// Turn warning messages on (default: true) static void SetWarning(bool debug); static void WarningOn(); static void WarningOff(); static bool GetWarningFlag(); /// Turn error messages on (default: true) static void SetError(bool debug); static void ErrorOn(); static void ErrorOff(); static bool GetErrorFlag(); protected: private: }; // Here we define function this is the only way to be able to pass // stuff with indirection like: // gdcmDebug( "my message:" << i << '\t' ); // You cannot use function unless you use vnsprintf ... // __FUNCTION is not always defined by preprocessor // In c++ we should use __PRETTY_FUNCTION__ instead... #ifdef GDCM_CXX_HAS_FUNCTION // Handle particular case for GNU C++ which also defines __PRETTY_FUNCTION__ // which is a lot nice in C++ #ifdef __BORLANDC__ # define __FUNCTION__ __FUNC__ #endif #ifdef __GNUC__ # define GDCM_FUNCTION __PRETTY_FUNCTION__ #else # define GDCM_FUNCTION __FUNCTION__ #endif //__GNUC__ #else # define GDCM_FUNCTION "" #endif //GDCM_CXX_HAS_FUNCTION /** * \brief Debug * @param msg message part */ #if defined(NDEBUG) && !defined(GDCM_ALWAYS_TRACE_MACRO) #define gdcmDebugMacro(msg) GDCM_NOOP_STATEMENT #else #define gdcmDebugMacro(msg) \ { \ if( gdcm::Trace::GetDebugFlag() ) \ { \ std::ostringstream osmacro; \ osmacro << "Debug: In " __FILE__ ", line " << __LINE__ \ << ", function " << GDCM_FUNCTION << '\n' \ << "Last system error was: " \ << gdcm::System::GetLastSystemError() << '\n' << msg; \ std::ostream &_os = gdcm::Trace::GetDebugStream(); \ _os << osmacro.str() << "\n\n" << std::endl; \ } \ } \ GDCM_NOOP_STATEMENT #endif //NDEBUG /** * \brief Warning * @param msg message part */ #if defined(NDEBUG) && !defined(GDCM_ALWAYS_TRACE_MACRO) #define gdcmWarningMacro(msg) GDCM_NOOP_STATEMENT #else #define gdcmWarningMacro(msg) \ { \ if( gdcm::Trace::GetWarningFlag() ) \ { \ std::ostringstream osmacro; \ osmacro << "Warning: In " __FILE__ ", line " << __LINE__ \ << ", function " << GDCM_FUNCTION << "\n" \ << msg << "\n\n"; \ std::ostream &_os = gdcm::Trace::GetWarningStream(); \ _os << osmacro.str() << std::endl; \ } \ } \ GDCM_NOOP_STATEMENT #endif //NDEBUG /** * \brief Error this is pretty bad, more than just warning * It could mean lost of data, something not handle... * @param msg second message part */ #if defined(NDEBUG) && !defined(GDCM_ALWAYS_TRACE_MACRO) #define gdcmErrorMacro(msg) GDCM_NOOP_STATEMENT #else #define gdcmErrorMacro(msg) \ { \ if( gdcm::Trace::GetErrorFlag() ) \ { \ std::ostringstream osmacro; \ osmacro << "Error: In " __FILE__ ", line " << __LINE__ \ << ", function " << GDCM_FUNCTION << '\n' \ << msg << "\n\n"; \ std::ostream &_os = gdcm::Trace::GetErrorStream(); \ _os << osmacro.str() << std::endl; \ } \ } \ GDCM_NOOP_STATEMENT #endif //NDEBUG /** * \brief Assert * @param arg argument to test * An easy solution to pass also a message is to do: * gdcmAssertMacro( "my message" && 2 < 3 ) */ #if defined(NDEBUG) && !defined(GDCM_ALWAYS_TRACE_MACRO) #define gdcmAssertMacro(arg) GDCM_NOOP_STATEMENT #else #define gdcmAssertMacro(arg) \ { \ if( !(arg) ) \ { \ std::ostringstream osmacro; \ osmacro << "Assert: In " __FILE__ ", line " << __LINE__ \ << ", function " << GDCM_FUNCTION \ << "\n\n"; \ std::ostream &_os = gdcm::Trace::GetErrorStream(); \ _os << osmacro.str() << std::endl; \ assert ( arg ); \ } \ } \ GDCM_NOOP_STATEMENT #endif //NDEBUG /** * \brief AssertAlways * @param arg argument to test * An easy solution to pass also a message is to do: * gdcmAssertMacro( "my message" && 2 < 3 ) */ #if defined(NDEBUG) // User asked for release compilation, but still need to report // if grave issue. #define gdcmAssertAlwaysMacro(arg) \ { \ if( !(arg) ) \ { \ std::ostringstream osmacro; \ osmacro << "Assert: In " __FILE__ ", line " << __LINE__ \ << ", function " << GDCM_FUNCTION \ << "\n\n"; \ throw osmacro.str(); \ } \ } \ GDCM_NOOP_STATEMENT #else // Simply reproduce gdcmAssertMacro behavior: #define gdcmAssertAlwaysMacro(arg) gdcmAssertMacro(arg) #endif //NDEBUG } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMTRACE_H GDCM-3.0.10/Source/Common/gdcmTypes.h000066400000000000000000000037221412732066400171160ustar00rootroot00000000000000/*========================================================================= 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 GDCMTYPES_H #define GDCMTYPES_H #include "gdcmConfigure.h" #include "gdcmWin32.h" #include "gdcmLegacyMacro.h" //----------------------------------------------------------------------------- #ifdef GDCM_HAVE_STDINT_H #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS #endif // __STDC_LIMIT_MACROS #include //#undef __STDC_LIMIT_MACROS #else #ifdef GDCM_HAVE_INTTYPES_H // Old system only have this #include // For uint8_t uint16_t and uint32_t #else // Broken plateforms do not respect C99 and do not provide those typedef // Special case for recent Borland compiler, comes with stdint.h #if defined(__BORLANDC__) && (__BORLANDC__ < 0x0560) || defined(__MINGW32__) typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; typedef unsigned __int64 uint64_t; #elif defined(_MSC_VER) #include "stdint.h" #else #error "Sorry, your platform is not supported" #endif // defined(_MSC_VER) || defined(__BORLANDC__) && (__BORLANDC__ < 0x0560) || defined(__MINGW32__) #endif // GDCM_HAVE_INTTYPES_H #endif // GDCM_HAVE_STDINT_H // Basically for VS6 and bcc 5.5.1: #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif //----------------------------------------------------------------------------- #endif //GDCMTYPES_H GDCM-3.0.10/Source/Common/gdcmUnpacker12Bits.cxx000066400000000000000000000033201412732066400211140ustar00rootroot00000000000000/*========================================================================= 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 "gdcmUnpacker12Bits.h" namespace gdcm { bool Unpacker12Bits::Unpack(char *out, const char *in, size_t n) { if( n % 3 ) return false; // 3bytes are actually 2 words // http://groups.google.com/group/comp.lang.c/msg/572bc9b085c717f3 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++; *q++ = (short)(((b1 & 0xf) << 8) + b0); *q++ = (short)((b1>>4) + (b2<<4)); } return true; } bool Unpacker12Bits::Pack(char *out, const char *in, size_t n) { if( n % 4 ) return false; // we need an even number of 'words' so that 2 words are split in 3 bytes 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++; *q++ = (unsigned char)(b0 & 0xff); *q++ = (unsigned char)((b0 >> 8) + ((b1 & 0xf) << 4)); *q++ = (unsigned char)(b1 >> 4); } return true; } } // end namespace gdcm GDCM-3.0.10/Source/Common/gdcmUnpacker12Bits.h000066400000000000000000000033401412732066400205430ustar00rootroot00000000000000/*========================================================================= 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 GDCMUNPACKER12BITS_H #define GDCMUNPACKER12BITS_H #include "gdcmTypes.h" 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 * * 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 * more standard 16bits Stored Pixel Value. * * \see Rescaler */ class GDCM_EXPORT Unpacker12Bits { public: /// Pack an array of 16bits where all values are 12bits into a pack form. n /// is the length in bytes of array in, out will be a fake 8bits array of size /// (n / 2) * 3 static bool Pack(char *out, const char *in, size_t n); /// Unpack an array of 'packed' 12bits data into a more conventional 16bits /// array. n is the length in bytes of array in, out will be a 16bits array of /// size (n / 3) * 2 static bool Unpack(char *out, const char *in, size_t n); }; } // end namespace gdcm #endif //GDCMUNPACKER12BITS_H GDCM-3.0.10/Source/Common/gdcmVersion.cxx000066400000000000000000000016641412732066400200150ustar00rootroot00000000000000/*========================================================================= 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 "gdcmVersion.h" namespace gdcm { void Version::Print(std::ostream &os) const { os << Version::GetVersion(); } const char * Version::GetVersion() { return GDCM_VERSION; } int Version::GetMajorVersion() { return GDCM_MAJOR_VERSION; } int Version::GetMinorVersion() { return GDCM_MINOR_VERSION; } int Version::GetBuildVersion() { return GDCM_BUILD_VERSION; } } GDCM-3.0.10/Source/Common/gdcmVersion.h000066400000000000000000000027111412732066400174340ustar00rootroot00000000000000/*========================================================================= 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 GDCMVERSION_H #define GDCMVERSION_H #include "gdcmTypes.h" #include namespace gdcm { /** * \class Version * \brief major/minor and build version */ //----------------------------------------------------------------------------- class GDCM_EXPORT Version { friend std::ostream& operator<<(std::ostream &_os, const Version &v); public : static const char *GetVersion(); static int GetMajorVersion(); static int GetMinorVersion(); static int GetBuildVersion(); void Print(std::ostream &os = std::cout) const; //protected: Version() = default; ~Version() = default; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const Version &v) { v.Print( os ); return os; } } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMVERSION_H GDCM-3.0.10/Source/Common/gdcmWin32.h000066400000000000000000000061341412732066400167140ustar00rootroot00000000000000/*========================================================================= 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 GDCMWIN32_H #define GDCMWIN32_H #if !defined(GDCMTYPES_H) #error you need to include gdcmTypes.h instead #endif //----------------------------------------------------------------------------- // http://gcc.gnu.org/wiki/Visibility #if defined(_WIN32) && defined(GDCM_BUILD_SHARED_LIBS) #if (defined(gdcmCommon_EXPORTS) || defined(gdcmDICT_EXPORTS) || defined(gdcmDSED_EXPORTS) || defined(gdcmIOD_EXPORTS) || defined(gdcmMSFF_EXPORTS) || defined(gdcmMEXD_EXPORTS)|| defined(_gdcmswig_EXPORTS)) || defined(vtkgdcm_EXPORTS) #define GDCM_EXPORT __declspec( dllexport ) #else #define GDCM_EXPORT __declspec( dllimport ) #endif #else #if __GNUC__ >= 4 && defined(GDCM_BUILD_SHARED_LIBS) #define GDCM_EXPORT __attribute__ ((visibility ("default"))) #define GDCM_LOCAL __attribute__ ((visibility ("hidden"))) #else #define GDCM_EXPORT #endif #endif #if defined(GDCM_OVERRIDE_BROKEN_IMPLEMENTATION) && !defined(GDCM_FORCE_EXPORT) #undef GDCM_EXPORT #define GDCM_EXPORT #endif // In VTK 4.2 vtkWrapPython does not like anything other than VTK_*EXPORT // [ 86%] Generating vtkGDCMImageReaderPython.cxx // syntax error // *** SYNTAX ERROR found in parsing the header file /usr/local/src/gdcm2/tags/gdcm-2-0-11/Utilities/VTK/vtkGDCMImageReader.h before line 128*** // make[2]: *** [Utilities/VTK/vtkGDCMImageReaderPython.cxx] Error 1 // make[1]: *** [Utilities/VTK/CMakeFiles/vtkgdcmPythonD.dir/all] Error 2 // make: *** [all] Error 2 #if defined(VTK_MAJOR_VERSION) && ( VTK_MAJOR_VERSION == 4 ) #undef VTK_EXPORT #define VTK_EXPORT GDCM_EXPORT #endif //----------------------------------------------------------------------------- //This is needed when compiling in debug mode #ifdef _MSC_VER // to allow construct such as: std::numeric_limits::max() we need the following: // warning C4003: not enough actual parameters for macro 'max' #ifndef NOMINMAX #define NOMINMAX #endif # pragma warning ( default : 4263 ) /* no override, call convention differs */ // 'identifier' : class 'type' needs to have dll-interface to be used by // clients of class 'type2' #pragma warning ( disable : 4251 ) // non dll-interface class 'type' used as base for dll-interface class 'type2' #pragma warning ( disable : 4275 ) // 'identifier' : identifier was truncated to 'number' characters in the // debug information #pragma warning ( disable : 4786 ) //'identifier' : decorated name length exceeded, name was truncated #pragma warning ( disable : 4503 ) #endif //_MSC_VER //----------------------------------------------------------------------------- #endif //GDCMWIN32_H GDCM-3.0.10/Source/Common/zipstreamimpl.h000066400000000000000000000252121412732066400200550ustar00rootroot00000000000000/* zipstream Library License: -------------------------- The zlib/libpng License Copyright (c) 2003 Jonathan de Halleux. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution Author: Jonathan de Halleux, dehalleux@pelikhan.com, 2003 Altered by: Andreas Zieringer 2003 for OpenSG project made it platform independent, gzip conform, fixed gzip footer Altered by: Geoffrey Hutchison 2005 for Open Babel project minor namespace modifications, VC++ compatibility Altered by: Mathieu Malaterre 2008, for GDCM project when reading deflate bit stream in DICOM special handling of \0 is needed also when writing deflate back to disk, the add_footer must be called */ /* Code is from: http://www.codeproject.com/KB/stl/zipstream.aspx TODO: zran.c index a zlib or gzip stream and randomly access it - illustrates the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary() to provide random access So I might after all be able to implement seeking :) */ #ifndef _ZIPSTREAM_H_ #define _ZIPSTREAM_H_ #include #include #include #include #include #include #include // memcpy #include // EOF #include #ifdef _WIN32 /* Window 95 & Windows NT */ # define OS_CODE 0x0b #endif #if defined(MACOS) || defined(TARGET_OS_MAC) # define OS_CODE 0x07 #endif #ifndef OS_CODE # define OS_CODE 0x03 /* assume Unix */ #endif namespace zlib_stream { namespace detail { const int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ /* gzip flag byte */ const int gz_ascii_flag = 0x01; /* bit 0 set: file probably ascii text */ const int gz_head_crc = 0x02; /* bit 1 set: header CRC present */ const int gz_extra_field = 0x04; /* bit 2 set: extra field present */ const int gz_orig_name = 0x08; /* bit 3 set: original file name present */ const int gz_comment = 0x10; /* bit 4 set: file comment present */ const int gz_reserved = 0xE0; /* bits 5..7: reserved */ } /// default gzip buffer size, /// change this to suite your needs const size_t zstream_default_buffer_size = 4096; /// Compression strategy, see zlib doc. enum EStrategy { StrategyFiltered = 1, StrategyHuffmanOnly = 2, DefaultStrategy = 0 }; //***************************************************************************** // template class basic_zip_streambuf //***************************************************************************** /** \brief A stream decorator that takes raw input and zips it to a ostream. The class wraps up the inflate method of the zlib library 1.1.4 http://www.gzip.org/zlib/ */ template > class basic_zip_streambuf : public std::basic_streambuf { public: typedef std::basic_ostream& ostream_reference; typedef unsigned char byte_type; typedef char char_type; typedef byte_type* byte_buffer_type; typedef std::vector byte_vector_type; typedef std::vector char_vector_type; typedef int int_type; basic_zip_streambuf(ostream_reference ostream, int level, EStrategy strategy, int window_size, int memory_level, size_t buffer_size); ~basic_zip_streambuf() override; int sync () override; int_type overflow (int_type c) override; std::streamsize flush (); inline ostream_reference get_ostream () const; inline int get_zerr () const; inline unsigned long get_crc () const; inline unsigned long get_in_size () const; inline long get_out_size() const; private: bool zip_to_stream(char_type *buffer, std::streamsize buffer_size); ostream_reference _ostream; z_stream _zip_stream; int _err; byte_vector_type _output_buffer; char_vector_type _buffer; unsigned long _crc; }; //***************************************************************************** // template class basic_unzip_streambuf //***************************************************************************** /** \brief A stream decorator that takes compressed input and unzips it to a istream. The class wraps up the deflate method of the zlib library 1.1.4 http://www.gzip.org/zlib/ */ template > class basic_unzip_streambuf : public std::basic_streambuf { public: typedef std::basic_istream& istream_reference; typedef unsigned char byte_type; typedef charT char_type; typedef byte_type* byte_buffer_type; typedef std::vector byte_vector_type; typedef std::vector char_vector_type; typedef int int_type; /** Construct a unzip stream * More info on the following parameters can be found in the zlib documentation. */ basic_unzip_streambuf(istream_reference istream, int window_size, size_t read_buffer_size, size_t input_buffer_size); ~basic_unzip_streambuf() override; int_type underflow() override; /// returns the compressed input istream inline istream_reference get_istream (); inline z_stream& get_zip_stream (); inline int get_zerr () const; inline unsigned long get_crc () const; inline long get_out_size () const; inline long get_in_size () const; private: void put_back_from_zip_stream (); std::streamsize unzip_from_stream (char_type* buffer, std::streamsize buffer_size); size_t fill_input_buffer (); istream_reference _istream; z_stream _zip_stream; int _err; byte_vector_type _input_buffer; char_vector_type _buffer; unsigned long _crc; }; //***************************************************************************** // template class basic_zip_ostream //***************************************************************************** template > class basic_zip_ostream : public basic_zip_streambuf, public std::basic_ostream { public: typedef char char_type; typedef std::basic_ostream& ostream_reference; typedef std::basic_ostream ostream_type; inline explicit basic_zip_ostream(ostream_reference ostream, bool is_gzip = false, int level = Z_DEFAULT_COMPRESSION, EStrategy strategy = DefaultStrategy, int window_size = -15 /*windowBits is passed < 0 to suppress zlib header */, int memory_level = 8, size_t buffer_size = zstream_default_buffer_size); ~basic_zip_ostream() override; inline bool is_gzip () const; inline basic_zip_ostream& zflush (); void finished (); // void make_gzip() // { add_header(); _is_gzip = true; } private: basic_zip_ostream& add_header(); basic_zip_ostream& add_footer(); bool _is_gzip; bool _added_footer; }; //***************************************************************************** // template class basic_zip_istream //***************************************************************************** template > class basic_zip_istream : public basic_unzip_streambuf, public std::basic_istream { public: typedef std::basic_istream& istream_reference; typedef std::basic_istream istream_type; explicit basic_zip_istream(istream_reference istream, int window_size = -15 /*windowBits is passed < 0 to suppress zlib header */, size_t read_buffer_size = zstream_default_buffer_size, size_t input_buffer_size = zstream_default_buffer_size); inline bool is_gzip () const; inline bool check_crc (); inline bool check_data_size () const; inline long get_gzip_crc () const; inline long get_gzip_data_size() const; protected: int check_header (); void read_footer (); bool _is_gzip; long _gzip_crc; long _gzip_data_size; }; /// A typedef for basic_zip_ostream typedef basic_zip_ostream zip_ostream; /// A typedef for basic_zip_istream typedef basic_zip_istream zip_istream; /// A typedef for basic_zip_ostream //typedef basic_zip_ostream zip_wostream; /// A typedef for basic_zip_istream //typedef basic_zip_istream zip_wistream; //! Helper function to check whether stream is compressed or not. inline bool isGZip(std::istream &is) { const int gz_magic[2] = {0x1f, 0x8b}; int c1 = is.get(); if(c1 != gz_magic[0]) { is.putback((char)c1); return false; } int c2 = is.get(); if(c2 != gz_magic[1]) { is.putback((char)c2); is.putback((char)c1); return false; } is.putback((char)c2); is.putback((char)c1); return true; } #include "zipstreamimpl.hpp" } #endif // _ZIPSTREAM_H_ GDCM-3.0.10/Source/Common/zipstreamimpl.hpp000066400000000000000000000571611412732066400204250ustar00rootroot00000000000000/* zipstream Library License: -------------------------- The zlib/libpng License Copyright (c) 2003 Jonathan de Halleux. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution Author: Jonathan de Halleux, dehalleux@pelikhan.com, 2003 Altered by: Andreas Zieringer 2003 for OpenSG project made it platform independent, gzip conform, fixed gzip footer Altered by: Geoffrey Hutchison 2005 for Open Babel project minor namespace modifications, VC++ compatibility Altered by: Mathieu Malaterre 2008, for GDCM project when reading deflate bit stream in DICOM special handling of \0 is needed also when writing deflate back to disk, the add_footer must be called */ //***************************************************************************** // template class basic_zip_streambuf //***************************************************************************** //----------------------------------------------------------------------------- // PUBLIC //----------------------------------------------------------------------------- /** Construct a zip stream * More info on the following parameters can be found in the zlib documentation. */ template basic_zip_streambuf::basic_zip_streambuf(ostream_reference ostream, int level, EStrategy strategy, int window_size, int memory_level, size_t buffer_size) : _ostream(ostream), _output_buffer(buffer_size, 0), _buffer(buffer_size, 0), _crc(0) { _zip_stream.zalloc = (alloc_func) nullptr; _zip_stream.zfree = (free_func) nullptr; _zip_stream.next_in = nullptr; _zip_stream.avail_in = 0; _zip_stream.avail_out = 0; _zip_stream.next_out = nullptr; if(level > 9) level = 9; if(memory_level > 9) memory_level = 9; _err=deflateInit2(&_zip_stream, level, Z_DEFLATED, window_size, memory_level, static_cast(strategy)); this->setp( &(_buffer[0]), &(_buffer[_buffer.size()-1])); } /** Destructor */ template basic_zip_streambuf::~basic_zip_streambuf() { flush(); // _ostream.flush(); CM already done in flush() _err=deflateEnd(&_zip_stream); } /** Do the synchronization * @todo * document correctly! */ template int basic_zip_streambuf::sync() { if(this->pptr() && this->pptr() > this->pbase()) { /*int c =*/ overflow(EOF); // ACHTUNG wenn das drin ist hoert er nach dem ersten endl auf! /* if ( c == EOF) return -1; */ } return 0; } /** * @todo * document correctly! */ template typename basic_zip_streambuf::int_type basic_zip_streambuf::overflow(int_type c) { int w = static_cast(this->pptr() - this->pbase()); if (c != EOF) { *this->pptr() = (char)c; ++w; } if (zip_to_stream(this->pbase(), w)) { this->setp(this->pbase(), this->epptr() - 1); return c; } else { return EOF; } } /** flushes the zip buffer and output buffer. * * This method should be called at the end of the compression. Calling flush * multiple times, will lower the compression ratio. */ template std::streamsize basic_zip_streambuf::flush() { std::streamsize written_byte_size = 0, total_written_byte_size = 0; size_t remainder = 0; // updating crc _crc = crc32(_crc, _zip_stream.next_in, _zip_stream.avail_in); do { _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; 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) { // copy to the beginning of the stream std::streamsize theDiff = written_byte_size-remainder; //assert (theDiff > 0 && theDiff < std::numeric_limits::max()); memcpy(&(_output_buffer[0]), &(_output_buffer[(unsigned int)theDiff]), remainder); } _zip_stream.avail_out = static_cast(_output_buffer.size() - remainder); _zip_stream.next_out = &_output_buffer[remainder]; } } while(_err == Z_OK); _ostream.flush(); return total_written_byte_size; } /** returns a reference to the output stream */ template inline typename basic_zip_streambuf::ostream_reference basic_zip_streambuf::get_ostream() const { return _ostream; } /** returns the latest zlib error status */ template inline int basic_zip_streambuf::get_zerr() const { return _err; } /** returns the crc of the input data compressed so far. */ template inline unsigned long basic_zip_streambuf:: get_crc() const { return _crc; } /** returns the size (bytes) of the input data compressed so far. */ template inline unsigned long basic_zip_streambuf::get_in_size() const { return _zip_stream.total_in; } /** returns the size (bytes) of the compressed data so far. */ template inline long basic_zip_streambuf::get_out_size() const { return _zip_stream.total_out; } //----------------------------------------------------------------------------- // PRIVATE //----------------------------------------------------------------------------- /** * @todo * document! */ template 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; _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, _zip_stream.avail_in); do { _err = deflate(&_zip_stream, 0); if (_err == Z_OK || _err == Z_STREAM_END) { 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))); // checking if some bytes were not written. if((remainder = written_byte_size % sizeof(char_type)) != 0) { // copy to the beginning of the stream std::streamsize theDiff = written_byte_size-remainder; //assert(theDiff > 0 && theDiff < std::numeric_limits::max()); memcpy(&_output_buffer[0], &_output_buffer[(unsigned int)theDiff], remainder); } _zip_stream.avail_out = static_cast(_output_buffer.size()-remainder); _zip_stream.next_out = &_output_buffer[remainder]; } } while(_zip_stream.avail_in != 0 && _err == Z_OK); return _err == Z_OK; } //***************************************************************************** // template class basic_unzip_streambuf //***************************************************************************** //----------------------------------------------------------------------------- // PUBLIC //----------------------------------------------------------------------------- /** Constructor */ template basic_unzip_streambuf::basic_unzip_streambuf(istream_reference istream, int window_size, size_t read_buffer_size, size_t input_buffer_size) : _istream(istream), _input_buffer(input_buffer_size), _buffer(read_buffer_size), _crc(0) { // setting zalloc, zfree and opaque _zip_stream.zalloc = (alloc_func) nullptr; _zip_stream.zfree = (free_func) nullptr; _zip_stream.next_in = nullptr; _zip_stream.avail_in = 0; _zip_stream.avail_out = 0; _zip_stream.next_out = nullptr; _err = inflateInit2(&_zip_stream, window_size); this->setg(&_buffer[0] + 4, // beginning of putback area &_buffer[0] + 4, // read position &_buffer[0] + 4); // end position } /** * @todo document! */ template basic_unzip_streambuf::~basic_unzip_streambuf() { inflateEnd(&_zip_stream); } /** * @todo document! */ template typename basic_unzip_streambuf::int_type basic_unzip_streambuf::underflow() { if(this->gptr() && ( this->gptr() < this->egptr())) return * reinterpret_cast(this->gptr()); int n_putback = static_cast(this->gptr() - this->eback()); if(n_putback > 4) n_putback = 4; memcpy(&_buffer[0] + (4 - n_putback), this->gptr() - n_putback, n_putback * sizeof(char_type)); std::streamsize num = unzip_from_stream(&_buffer[0] + 4, static_cast((_buffer.size() - 4) * sizeof(char_type))); if(num <= 0) // ERROR or EOF return EOF; // reset buffer pointers this->setg(&_buffer[0] + (4 - n_putback), // beginning of putback area &_buffer[0] + 4, // read position &_buffer[0] + 4 + num); // end of buffer // return next character return * reinterpret_cast(this->gptr()); } /** returns the compressed input istream */ template inline typename basic_unzip_streambuf::istream_reference basic_unzip_streambuf::get_istream() { return _istream; } /** returns the zlib stream structure */ template inline z_stream & basic_unzip_streambuf::get_zip_stream() { return _zip_stream; } /** returns the latest zlib error state */ template inline int basic_unzip_streambuf::get_zerr() const { return _err; } /** returns the crc of the uncompressed data so far */ template inline unsigned long basic_unzip_streambuf::get_crc() const { return _crc; } /** returns the number of uncompressed bytes */ template inline long basic_unzip_streambuf::get_out_size() const { return _zip_stream.total_out; } /** returns the number of read compressed bytes */ template inline long basic_unzip_streambuf::get_in_size() const { return _zip_stream.total_in; } //----------------------------------------------------------------------------- // PRIVATE //----------------------------------------------------------------------------- /** */ template inline void basic_unzip_streambuf::put_back_from_zip_stream() { if(_zip_stream.avail_in == 0) return; _istream.clear(std::ios::goodbit); _istream.seekg(-intf(_zip_stream.avail_in), std::ios_base::cur); _zip_stream.avail_in = 0; } /** */ template inline std::streamsize basic_unzip_streambuf::unzip_from_stream(char_type* buffer, std::streamsize buffer_size) { _zip_stream.next_out = (byte_buffer_type) buffer; _zip_stream.avail_out = static_cast(buffer_size * sizeof(char_type)); size_t count = _zip_stream.avail_in; do { if(_zip_stream.avail_in == 0) count=fill_input_buffer(); if(_zip_stream.avail_in) { _err = inflate(&_zip_stream, Z_SYNC_FLUSH); } } while(_err==Z_OK && _zip_stream.avail_out != 0 && count != 0); std::streamsize theSize = buffer_size - ((std::streamsize)_zip_stream.avail_out) / sizeof(char_type); // assert (theSize >= 0 && theSize < std::numeric_limits::max()); // updating crc _crc = crc32(_crc, (byte_buffer_type) buffer,(uInt)theSize); std::streamsize n_read = buffer_size - _zip_stream.avail_out / sizeof(char_type); // check if it is the end if (_err == Z_STREAM_END) put_back_from_zip_stream(); return n_read; } /** */ template inline size_t basic_unzip_streambuf::fill_input_buffer() { _zip_stream.next_in = &_input_buffer[0]; _istream.read((char_type*) &_input_buffer[0], static_cast(_input_buffer.size() / sizeof(char_type))); std::streamsize nbytesread = _istream.gcount()*sizeof(char_type); if( !_istream ) { if( _istream.eof() ) { // Ok so we reached the end of file, since we did not read no header // we have to explicitly tell zlib the compress stream ends, therefore // we add an extra \0 character...it may not always be needed... assert( nbytesread < (std::streamsize)(_input_buffer.size() / sizeof(char_type)) ); _input_buffer[ (unsigned int)nbytesread ] = 0; ++nbytesread; } } return _zip_stream.avail_in = (uInt)nbytesread; } //***************************************************************************** // template class basic_zip_ostream //***************************************************************************** //----------------------------------------------------------------------------- // PUBLIC //----------------------------------------------------------------------------- #if defined(_MSC_VER) # pragma warning (push) # pragma warning (disable:4355) #endif /** */ template inline basic_zip_ostream::basic_zip_ostream(ostream_reference ostream, bool isgzip, int level, EStrategy strategy, int window_size, int memory_level, size_t buffer_size) : basic_zip_streambuf(ostream, level, strategy, window_size, memory_level, buffer_size), std::basic_ostream(this), _is_gzip(isgzip), _added_footer(false) { if(_is_gzip) add_header(); } #if defined(_MSC_VER) # pragma warning (pop) #endif /** Destructor */ template basic_zip_ostream::~basic_zip_ostream() { //if(_is_gzip) add_footer(); } /** returns true if it is a gzip */ template inline bool basic_zip_ostream::is_gzip() const { return _is_gzip; } /** flush inner buffer and zipper buffer */ template inline basic_zip_ostream& basic_zip_ostream::zflush() { static_cast *>(this)->flush(); static_cast *>(this)->flush(); return *this; } template inline void basic_zip_ostream::finished() { if(_is_gzip) add_footer(); else zflush(); } //----------------------------------------------------------------------------- // PRIVATE //----------------------------------------------------------------------------- /** * @todo document! */ template basic_zip_ostream& basic_zip_ostream::add_header() { char_type zero = 0; this->get_ostream() << static_cast(detail::gz_magic[0]) << static_cast(detail::gz_magic[1]) << static_cast(Z_DEFLATED) << zero //flags << zero<(OS_CODE); return *this; } /** * @todo document! */ template basic_zip_ostream& basic_zip_ostream::add_footer() { if(_added_footer) return *this; zflush(); _added_footer = true; // Writes crc and length in LSB order to the stream. unsigned long crc = this->get_crc(); for(int n=0;n<4;++n) { this->get_ostream().put((char)(crc & 0xff)); crc >>= 8; } unsigned long length = this->get_in_size(); for(int m=0;m<4;++m) { this->get_ostream().put((char)(length & 0xff)); length >>= 8; } return *this; } //***************************************************************************** // template class basic_zip_istream //***************************************************************************** //----------------------------------------------------------------------------- // PUBLIC //----------------------------------------------------------------------------- #if defined(_MSC_VER) # pragma warning (push) # pragma warning (disable:4355) #endif /** Constructor */ template basic_zip_istream::basic_zip_istream(istream_reference istream, int window_size, size_t read_buffer_size, size_t input_buffer_size) : basic_unzip_streambuf(istream, window_size, read_buffer_size, input_buffer_size), std::basic_istream(this), _is_gzip(false), _gzip_crc(0), _gzip_data_size(0) { if(this->get_zerr() == Z_OK) { int check = check_header();(void)check; //std::cerr << "check_header:" << check << std::endl; } } #if defined(_MSC_VER) # pragma warning (pop) #endif /** returns true if it is a gzip file */ template inline bool basic_zip_istream::is_gzip() const { return _is_gzip; } /** return crc check result * * This must be called after the reading of compressed data is finished! This * method compares it to the crc of the uncompressed data. * * \return true if crc check is successful */ template inline bool basic_zip_istream::check_crc() { read_footer(); return this->get_crc() == _gzip_crc; } /** return data size check */ template inline bool basic_zip_istream::check_data_size() const { return this->get_out_size() == _gzip_data_size; } /** return the crc value in the file */ template inline long basic_zip_istream::get_gzip_crc() const { return _gzip_crc; } /** return the data size in the file */ template inline long basic_zip_istream::get_gzip_data_size() const { return _gzip_data_size; } //----------------------------------------------------------------------------- // PROTECTED //----------------------------------------------------------------------------- /** * @todo document! */ template int basic_zip_istream::check_header() { int method; /* method byte */ int flagsbyte; /* flags byte */ uInt len; int c; int err=0; z_stream &zip_stream = this->get_zip_stream(); /* Check the gzip magic header */ for(len = 0; len < 2; len++) { c = (int)this->get_istream().get(); if (c != detail::gz_magic[len]) { if (len != 0) this->get_istream().unget(); if (c!= EOF) { this->get_istream().unget(); } err = zip_stream.avail_in != 0 ? Z_OK : Z_STREAM_END; _is_gzip = false; return err; } } _is_gzip = true; method = (int)this->get_istream().get(); flagsbyte = (int)this->get_istream().get(); if (method != Z_DEFLATED || (flagsbyte & detail::gz_reserved) != 0) { err = Z_DATA_ERROR; return err; } /* Discard time, xflags and OS code: */ for (len = 0; len < 6; len++) this->get_istream().get(); if ((flagsbyte & detail::gz_extra_field) != 0) { /* skip the extra field */ len = (uInt)this->get_istream().get(); len += ((uInt)this->get_istream().get())<<8; /* len is garbage if EOF but the loop below will quit anyway */ while (len-- != 0 && this->get_istream().get() != EOF) ; } if ((flagsbyte & detail::gz_orig_name) != 0) { /* skip the original file name */ while ((c = this->get_istream().get()) != 0 && c != EOF) ; } if ((flagsbyte & detail::gz_comment) != 0) { /* skip the .gz file comment */ while ((c = this->get_istream().get()) != 0 && c != EOF) ; } if ((flagsbyte & detail::gz_head_crc) != 0) { /* skip the header crc */ for (len = 0; len < 2; len++) this->get_istream().get(); } err = this->get_istream().eof() ? Z_DATA_ERROR : Z_OK; return err; } /** * @todo document! */ template void basic_zip_istream::read_footer() { if(_is_gzip) { _gzip_crc = 0; for(int n=0;n<4;++n) _gzip_crc += ((((int) this->get_istream().get()) & 0xff) << (8*n)); _gzip_data_size = 0; for(int n=0;n<4;++n) _gzip_data_size += ((((int) this->get_istream().get()) & 0xff) << (8*n)); } } GDCM-3.0.10/Source/DataDictionary/000077500000000000000000000000001412732066400164515ustar00rootroot00000000000000GDCM-3.0.10/Source/DataDictionary/06_03_list.txt000066400000000000000000000216031412732066400207760ustar00rootroot00000000000000# Created using: # pdftotext -raw -nopgbrk 06_03pu.pdf 06_03.txt # grep -B 1 "Attribute Name Tag Type Attribute Description" 06_03.txt > log # cat log | grep -v "Attribute Name Tag Type Attribute Description" | grep -v "\-\-" > 06_03_list.txt Person Identification Macro Attributes Description Content Item Macro Attributes Description IMAGE SOP INSTANCE REFERENCE MACRO ATTRIBUTES SERIES AND INSTANCE REFERENCE MACRO ATTRIBUTES GENERAL ANATOMY MANDATORY MACRO ATTRIBUTES GENERAL ANATOMY REQUIRED MACRO ATTRIBUTES GENERAL ANATOMY OPTIONAL MACRO ATTRIBUTES REQUEST ATTRIBUTES MACRO ATTRIBUTES BASIC PIXEL SPACING CALIBRATION MACRO ATTRIBUTES PATIENT MODULE ATTRIBUTES SPECIMEN IDENTIFICATION MODULE ATTRIBUTES CLINICAL TRIAL SUBJECT MODULE ATTRIBUTES GENERAL STUDY MODULE ATTRIBUTES PATIENT STUDY MODULE ATTRIBUTES CLINICAL TRIAL STUDY MODULE ATTRIBUTES GENERAL SERIES MODULE ATTRIBUTES CLINICAL TRIAL SERIES MODULE ATTRIBUTES FRAME OF REFERENCE MODULE ATTRIBUTES Synchronization Module Attributes GENERAL EQUIPMENT MODULE ATTRIBUTES ENHANCED GENERAL EQUIPMENT MODULE ATTRIBUTES GENERAL IMAGE MODULE ATTRIBUTES IMAGE PLANE MODULE ATTRIBUTES IMAGE PIXEL MODULE ATTRIBUTES IMAGE PIXEL MACRO ATTRIBUTES CONTRAST/BOLUS MODULE ATTRIBUTES ENHANCED CONTRAST/BOLUS MODULE ATTRIBUTES CINE MODULE ATTRIBUTES MULTI-FRAME MODULE ATTRIBUTES FRAME POINTERS MODULE ATTRIBUTES MASK MODULE ATTRIBUTES DISPLAY SHUTTER MODULE ATTRIBUTES DISPLAY SHUTTER MACRO ATTRIBUTES DEVICE MODULE ATTRIBUTES INTERVENTION MODULE ATTRIBUTES Table C.7.6.14-1 - ACQUISITION CONTEXT MODULE ATTRIBUTES BITMAP DISPLAY SHUTTER MODULE ATTRIBUTES MULTI-FRAME FUNCTIONAL GROUPS MODULE ATTRIBUTES PIXEL MEASURES MACRO ATTRIBUTES FRAME CONTENT MACRO ATTRIBUTES PLANE POSITION MACRO ATTRIBUTES PLANE ORIENTATION MACRO ATTRIBUTES REFERENCED IMAGE MACRO ATTRIBUTES DERIVATION IMAGE MACRO ATTRIBUTES CARDIAC TRIGGER MACRO ATTRIBUTES FRAME ANATOMY MACRO ATTRIBUTES PIXEL VALUE TRANSFORMATION MACRO ATTRIBUTES FRAME VOI LUT MACRO ATTRIBUTES REAL WORLD VALUE MAPPING MACRO ATTRIBUTES CONTRAST/BOLUS USAGE FUNCTIONAL GROUP MACRO ATTRIBUTES PIXEL INTENSITY RELATIONSHIP LUT MACRO ATTRIBUTES FRAME PIXEL SHIFT MACRO ATTRIBUTES PATIENT ORIENTATION IN FRAME MACRO ATTRIBUTES FRAME DISPLAY SHUTTER MACRO ATTRIBUTES RESPIRATORY TRIGGER MACRO ATTRIBUTES IRRADIATION EVENT IDENTIFICATION MACRO ATTRIBUTES MULTI-FRAME DIMENSION MODULE ATTRIBUTES CARDIAC SYNCHRONIZATION MODULE ATTRIBUTES RESPIRATORY SYNCHRONIZATION MODULE ATTRIBUTES BULK MOTION SYNCHRONIZATION MODULE ATTRIBUTES SUPPLEMENTAL PALETTE COLOR TABLE LOOKUP MODULE ATTRIBUTES PALETTE COLOR LOOKUP MODULE CR SERIES MODULE ATTRIBUTES CR IMAGE MODULE ATTRIBUTES CT IMAGE MODULE ATTRIBUTES MR IMAGE MODULE ATTRIBUTES NM/PET PATIENT ORIENTATION MODULE ATTRIBUTES NM IMAGE PIXEL MODULE ATTRIBUTES NM MULTI-FRAME MODULE ATTRIBUTES NM IMAGE MODULE ATTRIBUTES NM ISOTOPE MODULE ATTRIBUTES NM DETECTOR MODULE ATTRIBUTES NM TOMO ACQUISITION MODULE ATTRIBUTES NM MULTI-GATED ACQUISITION MODULE ATTRIBUTES NM PHASE MODULE ATTRIBUTES NM RECONSTRUCTION MODULE ATTRIBUTES US REGION CALIBRATION MODULE ATTRIBUTES US IMAGE MODULE ATTRIBUTES SC EQUIPMENT MODULE ATTRIBUTES SC IMAGE MODULE ATTRIBUTES SC MULTI-FRAME IMAGE MODULE ATTRIBUTES SC MULTI-FRAME VECTOR MODULE ATTRIBUTES X-RAY IMAGE MODULE ATTRIBUTES X-RAY ACQUISITION MODULE ATTRIBUTES X-RAY COLLIMATOR MODULE ATTRIBUTES X-RAY TABLE MODULE ATTRIBUTES XA POSITIONER MODULE ATTRIBUTES XRF POSITIONER MODULE ATTRIBUTES X-RAY TOMOGRAPHY ACQUISITION MODULE ATTRIBUTES X-RAY ACQUISITION DOSE MODULE ATTRIBUTES X-RAY GENERATION MODULE ATTRIBUTES X-RAY FILTRATION MODULE ATTRIBUTES X-RAY GRID MODULE ATTRIBUTES Table C.8-37 - RT SERIES MODULE ATTRIBUTES Table C.8-60 - PET SERIES MODULE ATTRIBUTES Table C.8-61 - PET ISOTOPE MODULE ATTRIBUTES Table C.8-62 - PET MULTI-GATED ACQUISITION MODULE ATTRIBUTES Table C.8-63 - PET IMAGE MODULE ATTRIBUTES DX SERIES MODULE ATTRIBUTES DX ANATOMY IMAGED MODULE ATTRIBUTES DX IMAGE MODULE ATTRIBUTES DX DETECTOR MODULE ATTRIBUTES DIGITAL X-RAY DETECTOR MACRO ATTRIBUTES DX POSITIONING MODULE ATTRIBUTES MAMMOGRAPHY SERIES MODULE ATTRIBUTES MAMMOGRAPHY IMAGE MODULE ATTRIBUTES INTRA-ORAL SERIES MODULE ATTRIBUTES INTRA-ORAL IMAGE MODULE ATTRIBUTES VL IMAGE MODULE ATTRIBUTES Slide Coordinates Module Attributes ENHANCED MR IMAGE MODULE ATTRIBUTES MR IMAGE AND SPECTROSCOPY INSTANCE MACRO MR IMAGE DESCRIPTION MACRO ATTRIBUTES MR PULSE SEQUENCE MODULE ATTRIBUTES MR IMAGE FRAME TYPE MACRO ATTRIBUTES MR TIMING AND RELATED PARAMETERS MACRO ATTRIBUTES MR FOV/GEOMETRY MACRO ATTRIBUTES MR ECHO MACRO ATTRIBUTES MR MODIFIER MACRO ATTRIBUTES MR IMAGING MODIFIER MACRO ATTRIBUTES MR RECEIVE COIL MACRO ATTRIBUTES MR TRANSMIT COIL MACRO ATTRIBUTES MR DIFFUSION MACRO ATTRIBUTES MR AVERAGES MACRO ATTRIBUTES MR SPATIAL SATURATION MACRO ATTRIBUTES MR METABOLITE MAP MACRO ATTRIBUTES MR VELOCITY ENCODING MACRO ATTRIBUTES MR SERIES MODULE ATTRIBUTES MR SPECTROSCOPY MODULE ATTRIBUTES MR SPECTROSCOPY PULSE SEQUENCE MODULE ATTRIBUTES MR SPECTROSCOPY FRAME TYPE MACRO ATTRIBUTES MR SPECTROSCOPY FOV/GEOMETRY MACRO ATTRIBUTES MR SPECTROSCOPY DATA MODULE ATTRIBUTES MR SPECTROSCOPY DESCRIPTION MACRO ATTRIBUTES CT SERIES MODULE ATTRIBUTES ENHANCED CT IMAGE MODULE ATTRIBUTES CT IMAGE FRAME TYPE MACRO ATTRIBUTES CT ACQUISITION TYPE MACRO ATTRIBUTES CT ACQUISITION DETAILS MACRO ATTRIBUTES CT TABLE DYNAMICS MACRO ATTRIBUTES CT GEOMETRY MACRO ATTRIBUTES CT RECONSTRUCTION MACRO ATTRIBUTES CT EXPOSURE MACRO ATTRIBUTES CT X-RAY DETAILS SEQUENCE MACRO ATTRIBUTES CT PIXEL VALUE TRANSFORMATION MACRO ATTRIBUTES COMMON CT/MR IMAGE DESCRIPTION MACRO ATTRIBUTES OPHTHALMIC PHOTOGRAPHY SERIES MODULE ATTRIBUTES OPHTHALMIC PHOTOGRAPHY IMAGE MODULE ATTRIBUTES OPHTHALMIC PHOTOGRAPHIC PARAMETERS MODULE ATTRIBUTES OPHTHALMIC PHOTOGRAPHY ACQUISITION PARAMETERS MODULE ATTRIBUTES OCULAR REGION IMAGED MODULE ATTRIBUTES STEREOMETRIC SERIES MODULE ATTRIBUTES STEREOMETRIC RELATIONSHIP MODULE ATTRIBUTES XA/XRF SERIES MODULE ATTRIBUTES Enhanced XA/XRF Image Module Table XA/XRF ACQUISITION MODULE ATTRIBUTES X-RAY IMAGE INTENSIFIER MODULE ATTRIBUTES X-RAY DETECTOR MODULE ATTRIBUTES XA/XRF FRAME CHARACTERISTICS MACRO ATTRIBUTES X-RAY FIELD OF VIEW MACRO ATTRIBUTES X-RAY EXPOSURE CONTROL SENSING REGIONS MACRO ATTRIBUTES XA/XRF FRAME PIXEL DATA PROPERTIES MACRO ATTRIBUTES X-RAY CALIBRATION DEVICE USAGE MACRO ATTRIBUTES X-RAY OBJECT THICKNESS MACRO ATTRIBUTES X-RAY FRAME ACQUISITION MACRO ATTRIBUTES X-RAY PROJECTION PIXEL CALIBRATION MACRO ATTRIBUTES X-RAY POSITIONER MACRO ATTRIBUTES X-RAY TABLE POSITION MACRO ATTRIBUTES X-RAY COLLIMATOR MACRO ATTRIBUTES X-RAY ISOCENTER REFERENCE SYSTEM MACRO ATTRIBUTES X-RAY GEOMETRY MACRO ATTRIBUTES XA/XRF MULTI-FRAME PRESENTATION MODULE ATTRIBUTES OVERLAY PLANE MODULE ATTRIBUTES MULTI-FRAME OVERLAY MODULE ATTRIBUTES DISPLAYED AREA MODULE ATTRIBUTES GRAPHIC ANNOTATION MODULE ATTRIBUTES SPATIAL TRANSFORMATION MODULE ATTRIBUTES GRAPHIC LAYER MODULE ATTRIBUTES Waveform Identification Module Attributes Waveform Module Attributes Table C.10-11 Waveform Annotation Module Attributes MODALITY LUT MODULE ATTRIBUTES MODALITY LUT MACRO ATTRIBUTES VOI LUT MODULE ATTRIBUTES VOI LUT MACRO ATTRIBUTES LUT Identification Module Attributes OVERLAY ACTIVATION MODULE ATTRIBUTES SOFTCOPY VOI LUT MODULE ATTRIBUTES PRESENTATION SERIES MODULE ATTRIBUTES PRESENTATION STATE IDENTIFICATION MODULE ATTRIBUTES PRESENTATION STATE RELATIONSHIP MODULE ATTRIBUTES PRESENTATION STATE RELATIONSHIP MACRO ATTRIBUTES PRESENTATION STATE SHUTTER MODULE ATTRIBUTES PRESENTATION STATE MASK MODULE ATTRIBUTES PRESENTATION STATE BLENDING MODULE ATTRIBUTES ICC PROFILE MODULE ATTRIBUTES SOP COMMON MODULE ATTRIBUTES ENCRYPTED ATTRIBUTES DATA SET ATTRIBUTES COMMON INSTANCE REFERENCE MODULE ATTRIBUTES SR DOCUMENT SERIES MODULE ATTRIBUTES SR DOCUMENT GENERAL MODULE ATTRIBUTES SOP INSTANCE REFERENCE MACRO ATTRIBUTES Identified Person or Device Macro Attributes SR DOCUMENT CONTENT MODULE ATTRIBUTES DOCUMENT CONTENT MACRO ATTRIBUTES DOCUMENT RELATIONSHIP MACRO ATTRIBUTES KEY OBJECT DOCUMENT SERIES MODULE ATTRIBUTES KEY OBJECT DOCUMENT MODULE ATTRIBUTES NUMERIC MEASUREMENT MACRO ATTRIBUTES CODE MACRO ATTRIBUTES COMPOSITE OBJECT REFERENCE MACRO ATTRIBUTES IMAGE REFERENCE MACRO ATTRIBUTES WAVEFORM REFERENCE MACRO ATTRIBUTES SPATIAL COORDINATES MACRO ATTRIBUTES TEMPORAL COORDINATES MACRO ATTRIBUTES CONTAINER MACRO ATTRIBUTES RAW DATA MODULE ATTRIBUTES SPATIAL REGISTRATION SERIES MODULE ATTRIBUTES SPATIAL REGISTRATION MODULE ATTRIBUTES SPATIAL FIDUCIALS SERIES MODULE ATTRIBUTES SPATIAL FIDUCIALS MODULE ATTRIBUTES Hanging Protocol Definition Module Attributes Hanging Protocol Environment Module Attributes Hanging Protocol Display Module Attributes Hanging Protocol Selector Attribute Context Macro Attributes Hanging Protocol Selector Attribute Value Macro Attributes Encapsulated Document Series Module Attributes Encapsulated Document Module Attributes REAL WORLD VALUE MAPPING SERIES MODULE ATTRIBUTES REAL WORLD VALUE MAPPING MODULE ATTRIBUTES FILE-SET IDENTIFICATION MODULE DIRECTORY INFORMATION MODULE HANGING PROTOCOL KEYS GDCM-3.0.10/Source/DataDictionary/Agfa.xml000066400000000000000000000057341412732066400200420ustar00rootroot00000000000000 GDCM-3.0.10/Source/DataDictionary/CMakeLists.txt000066400000000000000000000072201412732066400212120ustar00rootroot00000000000000# Define the srcs for Data Dictionary # DICT # Add the include paths include_directories( "${GDCM_SOURCE_DIR}/Source/Common" "${GDCM_BINARY_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition" "${GDCM_SOURCE_DIR}/Source/DataDictionary" "${GDCM_SOURCE_DIR}/Source/InformationObjectDefinition" ) #----------------------------------------------------------------------------- # DICOM dictionary stuff #set(PREP_DICT_SRCS # ${GDCM_SOURCE_DIR}/Source/DataDictionary/gdcmDictConverter.cxx # ${GDCM_SOURCE_DIR}/Source/DataDictionary/gdcmPrepDict.cxx # ) # #add_executable(PrepDict ${PREP_DICT_SRCS} # "${GDCM_SOURCE_DIR}/Source/Common/gdcmSwapCode.cxx" # "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition/gdcmVR.cxx" # "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition/gdcmVM.cxx" # ) # #add_executable(PrepGroupName # ${GDCM_SOURCE_DIR}/Source/DataDictionary/gdcmPrepGroupName.cxx # ) # # get_target_property( PREP_DICT # PrepDict # LOCATION # ) # get_target_property( PREP_GROUPNAME # PrepGroupName # LOCATION # ) #set(DICT_LIST # DICOMV3 # NIH # SPI # ) # ## List of file needed to get all dict into c++ code #set(DICT_SRCS) #set(DEFAULT_DICTS) #foreach(dict ${DICT_LIST}) # set(CXX_DICT ${GDCM_BINARY_DIR}/Source/DataDictionary/gdcm${dict}.cxx) # set(DICT_SRCS ${DICT_SRCS} ${CXX_DICT}) # add_custom_command( # OUTPUT ${CXX_DICT} # COMMAND ${PREP_DICT} # ARGS ${GDCM_SOURCE_DIR}/Source/DataDictionary/${dict}.dic # ${CXX_DICT} # ${dict} # DEPENDS ${GDCM_SOURCE_DIR}/Source/DataDictionary/${dict}.dic # ${PREP_DICT} # COMMENT "Generating gdcm${dict}.cxx based on ${dict}.dic" # ) #endforeach() # #add_custom_command( # OUTPUT ${GDCM_BINARY_DIR}/Source/DataDictionary/gdcmDefaultGroupNames.cxx # COMMAND ${PREP_GROUPNAME} # ARGS ${GDCM_SOURCE_DIR}/Source/DataDictionary/GroupName.dic # ${GDCM_BINARY_DIR}/Source/DataDictionary/gdcmDefaultGroupNames.cxx # DEPENDS ${GDCM_SOURCE_DIR}/Source/DataDictionary/GroupName.dic # ${PREP_GROUPNAME} # COMMENT "Generating gdcmDefaultGroupNames.cxx based on GroupName.dic" # ) # # Since the file gdcmDefaultDicts.cxx does not exist, mark it as GENERATED: #set_source_files_properties( # "${GDCM_BINARY_DIR}/Source/gdcmDefaultDicts.cxx" GENERATED) #configure_file( # ${GDCM_SOURCE_DIR}/Source/DataDictionary/gdcmDefaultDicts.cxx # ${GDCM_BINARY_DIR}/Source/DataDictionary/gdcmDefaultDicts.cxx # @ONLY # ) set(DICT_SRCS #${DICT_SRCS} # All the dicts cxx resources gdcmDicts.cxx gdcmDictEntry.cxx gdcmDefaultDicts.cxx # pseudo generated file gdcmPrivateDefaultDicts.cxx # pseudo generated file gdcmGlobal.cxx gdcmGroupDict.cxx gdcmDefaultGroupNames.cxx gdcmUIDs.cxx gdcmSOPClassUIDToIOD.cxx gdcmCSAHeaderDefaultDicts.cxx ) add_library(gdcmDICT ${DICT_SRCS}) target_link_libraries(gdcmDICT LINK_PRIVATE gdcmDSED gdcmIOD) set_target_properties(gdcmDICT PROPERTIES ${GDCM_LIBRARY_PROPERTIES}) # libs install_library(gdcmDICT) # PDB install_pdb(gdcmDICT) # include files install_includes("*.h") set(XML_FILES ${CMAKE_CURRENT_SOURCE_DIR}/CSAHeader.xml ${CMAKE_CURRENT_SOURCE_DIR}/Part6.xml ${CMAKE_CURRENT_SOURCE_DIR}/Part7a.xml ${CMAKE_CURRENT_SOURCE_DIR}/Part7b.xml ${CMAKE_CURRENT_SOURCE_DIR}/UIDs.xml ${CMAKE_CURRENT_SOURCE_DIR}/cp699.xml ) set_source_files_properties( ${XML_FILES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources ) #----------------------------------------------------------------------------- # Install Part6.xml install(FILES ${XML_FILES} DESTINATION ${GDCM_INSTALL_DATA_DIR}/XML COMPONENT Libraries ) GDCM-3.0.10/Source/DataDictionary/COPYRIGHT.dicom3tools000066400000000000000000000033021412732066400222000ustar00rootroot00000000000000Copyright (c) 1993-2006, David A. Clunie DBA PixelMed Publishing. All rights reserved. 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, this list of conditions and the following disclaimers. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. 3. Neither the name of PixelMed Publishing nor the names of its contributors may be used to endorse or promote products derived from this software. This software is provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the copyright owner or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage. This software has neither been tested nor approved for clinical use or for incorporation in a medical device. It is the redistributor's or user's responsibility to comply with any applicable local, state, national or international regulations. GDCM-3.0.10/Source/DataDictionary/CSADefaultDicts.xsl000066400000000000000000000342111412732066400221040ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc CSADefaultDicts.xsl CSAHeader.xml > gdcmCSAHeaderDefaultDicts.cxx /*========================================================================= 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 GDCMCSAHEADERDICT_CXX #define GDCMCSAHEADERDICT_CXX #include "gdcmCSAHeaderDict.h" #include "gdcmCSAHeaderDictEntry.h" #include "gdcmVR.h" #include "gdcmVM.h" namespace gdcm { typedef struct { const char *name; const char *type; VR::VRType vr; VM::VMType vm; const char *description; } CSA_DICT_ENTRY; static const CSA_DICT_ENTRY CSAHeaderDataDict [] = { Problem with element:(,) {0,0,VR::INVALID,VM::VM0,0 } // Guard }; void CSAHeaderDict::LoadDefault() { unsigned int i = 0; CSA_DICT_ENTRY n = CSAHeaderDataDict[i]; while( n.name != 0 ) { CSAHeaderDictEntry e( n.name, n.vr, n.vm, n.description ); AddCSAHeaderDictEntry( e ); n = CSAHeaderDataDict[++i]; } } } // end namespace gdcm #endif // GDCMCSAHEADERDICT_CXX {" "," " ,VR:: INVALID ,VM:: ," "}, 0 GDCM-3.0.10/Source/DataDictionary/CSAHeader.xml000066400000000000000000001204551412732066400207210ustar00rootroot00000000000000 GDCM-3.0.10/Source/DataDictionary/DefaultDicts.xsl000066400000000000000000000342551412732066400215650ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc DefaultDicts.xsl Part6.xml > gdcmDefaultDicts.cxx /*========================================================================= 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 GDCMDEFAULTDICTS_CXX #define GDCMDEFAULTDICTS_CXX #include "gdcmDicts.h" #include "gdcmVR.h" #include "gdcmDict.h" #include "gdcmDictEntry.h" namespace gdcm { typedef struct { uint16_t group; uint16_t element; VR::VRType vr; VM::VMType vm; const char *name; const char *keyword; bool ret; } DICT_ENTRY; static const DICT_ENTRY DICOMV3DataDict [] = { Problem with element:(,) // FIXME: need a dummy element {0xffff,0xffff,VR::INVALID,VM::VM0,"","",true }, // dummy {0xffff,0xffff,VR::INVALID,VM::VM0,0,0,true } // Guard }; void Dict::LoadDefault() { unsigned int i = 0; DICT_ENTRY n = DICOMV3DataDict[i]; while( n.name != 0 ) { Tag t(n.group, n.element); DictEntry e( n.name, n.keyword, n.vr, n.vm, n.ret ); assert( DictEntry::CheckKeywordAgainstName(n.name, n.keyword) ); AddDictEntry( t, e ); n = DICOMV3DataDict[++i]; } } /* void PrivateDict::LoadDefault() { // TODO } */ } // end namespace gdcm #endif // GDCMDEFAULTDICTS_CXX // {0x ,0x ,VR:: INVALID ,VM:: ," "," ", }, 0 GDCM-3.0.10/Source/DataDictionary/DefaultPrivateDicts.xsl000066400000000000000000000326641412732066400231220ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc DefaultPrivateDicts.xsl privatedicts.xml > gdcmPrivateDefaultDicts.cxx /*========================================================================= 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 GDCMDEFAULTDICTS_CXX #define GDCMDEFAULTDICTS_CXX #include "gdcmDicts.h" #include "gdcmVR.h" #include "gdcmDict.h" #include "gdcmDictEntry.h" namespace gdcm { typedef struct { uint16_t group; uint16_t element; const char *owner; VR::VRType vr; VM::VMType vm; const char *name; bool ret; } DICT_ENTRY; static const DICT_ENTRY DICOMV3DataDict [] = { Problem with element:(,) {0xffff,0xffff,0,VR::INVALID,VM::VM0,0,true } // Guard }; void Dict::LoadDefault() { unsigned int i = 0; DICT_ENTRY n = DICOMV3DataDict[i]; while( n.name != 0 ) { if( n.group % 2 == 0 ) { assert( n.owner == 0 ); Tag t(n.group, n.element); DictEntry e( n.name, n.vr, n.vm, n.ret ); AddDictEntry( t, e ); } n = DICOMV3DataDict[++i]; } } void PrivateDict::LoadDefault() { unsigned int i = 0; DICT_ENTRY n = DICOMV3DataDict[i]; while( n.name != 0 ) { if( n.group % 2 != 0 ) { assert( n.owner != 0 ); PrivateTag t(n.group, n.element,n.owner); DictEntry e( n.name, n.vr, n.vm, n.ret ); AddDictEntry( t, e ); } n = DICOMV3DataDict[++i]; } } } // end namespace gdcm #endif // GDCMDEFAULTDICTS_CXX {0x ,0x ," " ,VR:: INVALID ,VM:: ," ", }, 0 GDCM-3.0.10/Source/DataDictionary/HarvestedPrivate.xml000066400000000000000000007027531412732066400224710ustar00rootroot00000000000000 GDCM-3.0.10/Source/DataDictionary/ParseDicts.py000077500000000000000000000271541412732066400211000ustar00rootroot00000000000000#!/usr/bin/env python """ WARNING: This script has no meaning today (post 2008). Since the standard is now available as .doc. If we assume that the .doc is valid (according to standard only pdf should) then there is not point in using this parser anymore today. Let's write our own python parser to clean up the pdf (after pdftotext of course). Instructions: run pdftotext like this: $ pdftotext -f 9 -l 81 -raw -nopgbrk 04_06PU.PDF 04_06PU-3.txt then run the python parser like this: $ python ParseDict.py 04_06PU.txt dicomV3.dic """ import re,os """ PdfTextParser takes as input a text file (produced by pdftotext) and create as output a clean file (ready to be processed) by DicomV3Expander Warning: PdfTextParser does not expand: - (xxxx,xxxx to xxxx) xxxxxxxxxxxx or - (12xx, 3456) comment... """ class PdfTextParser: # Cstor def __init__(self): self._InputFilename = '' self._OutputFilename = '' self._Infile = 0 self._OutLines = [] self._PreviousBuffers = [] def SetInputFileName(self,s): self._InputFilename = s def SetOutputFileName(self,s): self._OutputFilename = s # Function returning if s is a comment for sure def IsAComment(self,s): #print s, len(s) if s == "Tag Name VR VM": return True elif s == "PS 3.6-2003": return True elif s == "PS 3.6-2004": return True elif s == "PS 3.6-2006": return True elif s == "PS 3.6-2007": return True patt = re.compile('^Page [0-9]+$') if( patt.match(s) ): return True patt = re.compile('^(.*)PS 3.6-2007(.*)$') if( patt.match(s) ): return True patt = re.compile('^\s*(- Standard -)\s*') if( patt.match(s) ): return True patt = re.compile('^\s*Tag\s+Name\s+VR\s+VM\s*$') if( patt.match(s) ): return True return False def IsAStartingLine(self,s): patt = re.compile('^\\([0-9a-fA-Fx]+,[0-9a-fA-F]+\\) (.*)$') if( patt.match(s) ): return True return False def IsAFullLine(self,s): #patt = re.compile('^\\([0-9a-fA-Fx]+,[0-9a-fA-F]+\\) (.*) [A-Z][A-Z] [0-9]$') patt = re.compile('^\\([0-9a-fA-Fx]+,[0-9a-fA-F]+\\)\s+(.*)\s+[A-Z][A-Z]\s+([0-9n-]+)\s*$') if( patt.match(s) ): return True patt = re.compile('^\\([0-9a-fA-Fx]+,[0-9a-fA-F]+\\)\s+(.*)\s+[A-Z][A-Z]\s+([0-9n-]+)\s+RET\s*$') if( patt.match(s) ): return True print "IsAFullLine failed on", s return False # FIXME this function could be avoided... def IsSuspicious(self,s): l = len(s) if l > 80: return True return False def AddOutputLine(self,s): assert not self.IsAComment(s) self._OutLines.append(s + '\n') def Open(self): self._Infile = file(self._InputFilename, 'r') for line in self._Infile.readlines(): line = line[:-1] # remove '\n' if not self.IsAComment( line ): if self.IsAStartingLine(line): #print "Previous buffer:",self._PreviousBuffers previousbuffer = ' '.join(self._PreviousBuffers) if self.IsAStartingLine(previousbuffer): if not self.IsSuspicious(previousbuffer): self.AddOutputLine(previousbuffer) else: # this case should not happen if I were to rewrite the # thing I should be able to clean that #print "Suspicious:", previousbuffer #print "List is:", self._PreviousBuffers s = self._PreviousBuffers[0] if self.IsAFullLine(s): # That means we have a weird line that does not start # as usual (xxxx,xxxx) therefore we tried constructing # a buffer using a the complete previous line... #print "Full line:", s self.AddOutputLine(s) s2 = ' '.join(self._PreviousBuffers[1:]) #print "Other Full line:", s2 self.AddOutputLine(s2) else: # we have a suspicioulsy long line, so what that could # happen, let's check: if self.IsAFullLine(previousbuffer): self.AddOutputLine(previousbuffer) else: # This is the only case where we do not add # previousbuffer to the _OutLines print "Suspicious and Not a full line:", s else: if previousbuffer: print "Not a buffer:", previousbuffer # We can clean buffer, since only the case 'suspicious' + # 'Not a full line' has not added buffer to the list self._PreviousBuffers = [] # In all cases save the line for potentially growing this line assert not self.IsAComment(line) self._PreviousBuffers.append(line) else: #print "Not a line",line assert not self.IsAComment(line) self._PreviousBuffers.append(line) else: #print "Comment:",line previousbuffer = ' '.join(self._PreviousBuffers) if previousbuffer and self.IsAStartingLine(previousbuffer): #print "This line is added:", previousbuffer self.AddOutputLine( previousbuffer ) else: #print "Line is comment:", line print "Buffer is:", previousbuffer # Ok this is a comment we can safely clean the buffer: self._PreviousBuffers = [] self.Write() def Write(self): outfile = file(self._OutputFilename, 'w') outfile.writelines( self._OutLines ) outfile.close() self._Infile.close() # Main function to call for parsing def Parse(self): self.Open() """ This class is meant to expand line like: - (xxxx,xxxx to xxxx) xxxxxxxxxxxx or - (12xx, 3456) comment... """ class DicomV3Expander: def __init__(self): self._InputFilename = '' self._OutputFilename = '' self._OutLines = [] def SetInputFileName(self,s): self._InputFilename = s def SetOutputFileName(self,s): self._OutputFilename = s # Function to turn into lower case a tag: # ex: (ABCD, EF01) -> (abcd, ef01) def LowerCaseTag(self,s): #print "Before:", s[:-1] patt = re.compile('^(\\([0-9a-fA-F]+,[0-9a-fA-F]+\\))(.*)$') m = patt.match(s) if m: s1 = m.group(1) s2 = m.group(2) return s1.lower() + s2 else: patt = re.compile('^[0-9a-fA-F]+ [0-9a-fA-F]+ [A-Z][A-Z] [0-9n-] .*$') if patt.match(s): return s else: print "Impossible case:", s #os.sys.exit(1) return "" def AddOutputLine(self,s): if s.__class__ == list: for i in s: self._OutLines.append(i + '\n') else: self._OutLines.append(s + '\n') # Expand the line approriaetkly and also add it to the # _OutLines list def ExpandLine(self, s): assert s[-1] == '\n' s = s[:-1] # remove \n list = [] if self.NeedToExpansion(s, list): self.AddOutputLine(list) # list != [] elif self.NeedGroupXXExpansion(s, list): self.AddOutputLine(list) # list != [] elif self.NeedElemXXExpansion(s, list): self.AddOutputLine(list) # list != [] else: self.AddOutputLine(self.LowerCaseTag(s)) # If line is like: # (0020,3100 to 31FF) Source Image Ids RET def NeedToExpansion(self,s, list): patt = re.compile('^\\(([0-9a-fA-F]+),([0-9a-fA-F]+) to ([0-9a-fA-F]+)\\)(.*)$') m = patt.match(s) if m: #print m.groups() gr = m.group(1) el_start = '0x'+m.group(2) el_end = '0x'+m.group(3) for i in range(eval(el_start), eval(el_end)): el = hex(i)[2:] l = '('+gr+','+el+')'+m.group(4) list.append(l) return True return False # If line is like: # (50xx,1200) Number of Patient Related Studies IS 1 def NeedGroupXXExpansion(self,s,list): patt = re.compile('^\\(([0-9a-fA-F]+)xx,([0-9a-fA-F]+)\\)(.*)$') m = patt.match(s) if m: #print m.groups() gr_start = m.group(1) el = m.group(2) #el_start = '0x'+m.group(2) #el_end = '0x'+m.group(3) start = '0x'+gr_start+'00' end = '0x'+gr_start+'FF' for i in range(eval(start), eval(end)): gr = hex(i)[2:] l = '('+gr+','+el+')'+m.group(3) #print l list.append(l) return True return False # If line is like: # (2001,xx00) Number of Patient Related Studies IS 1 def NeedElemXXExpansion(self,s,list): patt = re.compile('^([0-9a-fA-F]+) ([0-9a-fA-F]+)xx(.*)$') m = patt.match(s) if m: #print m.groups() gr = m.group(1) el_start = m.group(2) start = '0x00' end = '0xFF' for i in range(eval(start), eval(end)): el = '%02x'% i l = '('+gr+','+el_start+el+')'+m.group(3) print l list.append(l) return True else: patt = re.compile('^([0-9a-fA-F]+) xx([0-9a-fA-F]+)(.*)$') m = patt.match(s) if m: #print m.groups() gr = m.group(1) el_start = m.group(2) start = '0x00' end = '0xFF' for i in range(eval(start), eval(end)): el = '%02x'% i l = '('+gr+','+el+el_start+')'+m.group(3) print l list.append(l) return True return False def Write(self): outfile = file(self._OutputFilename, 'w') outfile.writelines( self._OutLines ) outfile.close() def Expand(self): infile = file(self._InputFilename,'r') for line in infile.readlines(): # ExpandLine also LowerCase the line self.ExpandLine(line) # l is [1,n] lines self.Write() infile.close() """ Converter class Input is of type: (0008,0001) Length to End UL 1 RET output should be: 0008 0001 UL 1 Length to End RET """ class Converter: def __init__(self): self._InputFilename = '' self._OutputFilename = '' self._OutLines = [] def SetInputFileName(self,s): self._InputFilename = s def SetOutputFileName(self,s): self._OutputFilename = s def Open(self): self._Infile = file(self._InputFilename, 'r') for line in self._Infile.readlines(): line = line[:-1] # remove '\n' if (not self.IsAFullLine(line) ): print "Convert pb:", line def IsAFullLine(self,s): patt = re.compile('^\\(([0-9a-fA-Fx]+),([0-9a-fA-F]+)\\)\s+(.*)\s+([A-Z][A-Z])\s+([0-9n-]+)\s*$') m = patt.match(s) if( m ): output = '' output = m.group(1).lower() + ' ' + m.group(2).lower() + ' ' + m.group(4) + ' ' + m.group(5) + ' ' + m.group(3).strip() self.AddOutputLine( output ) return True patt_ret = re.compile('^\\(([0-9a-fA-Fx]+),([0-9a-fA-F]+)\\)\s+(.*)\s+([A-Z][A-Z])\s+([0-9n-]+)\s+(RET)\s*$') m = patt_ret.match(s) if( m ): output = '' output = m.group(1).lower() + ' ' + m.group(2).lower() + ' ' + m.group(4) + ' ' + m.group(5) + ' ' + m.group(3).strip() + ' (' + m.group(6) + ')' self.AddOutputLine( output ) return True return False def AddOutputLine(self,s): self._OutLines.append(s + '\n') def Write(self): outfile = file(self._OutputFilename, 'w') outfile.writelines( self._OutLines ) outfile.close() self._Infile.close() def Convert(self): self.Open() self.Write() if __name__ == "__main__": argc = len(os.sys.argv ) if ( argc < 3 ): print "Sorry, wrong list of args" os.sys.exit(1) #error inputfilename = os.sys.argv[1] outputfilename = os.sys.argv[2] tempfile = "/tmp/mytemp" dp = PdfTextParser() dp.SetInputFileName( inputfilename ) dp.SetOutputFileName( tempfile ) dp.Parse() exp = DicomV3Expander() exp.SetInputFileName( tempfile ) exp.SetOutputFileName( outputfilename ) exp.Expand() conv = Converter() conv.SetInputFileName( tempfile ) conv.SetOutputFileName( '/tmp/myconv' ) conv.Convert() #print dp.IsAStartingLine( "(0004,1212) File-set Consistency Flag US 1\n" ) GDCM-3.0.10/Source/DataDictionary/Part6.xml000066400000000000000000022262541412732066400202040ustar00rootroot00000000000000 ]> &part7a; &part7b;
GDCM-3.0.10/Source/DataDictionary/Part6.xsl000066400000000000000000000322321412732066400201770ustar00rootroot00000000000000 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. This file was automatically created from a docbook version of PS 3.6-2011, which was then process by Part67.xsl Manual changes: 1. DateTime -> Date Time (0008,002a) <!DOCTYPE doc [ <!ENTITY part7a SYSTEM "Part7a.xml"> <!ENTITY part7b SYSTEM "Part7b.xml"> ]> &part7a; &part7b;
GDCM-3.0.10/Source/DataDictionary/Part67.xsl000066400000000000000000000316341412732066400202730ustar00rootroot00000000000000 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. true ’–μ '-µµ   ­ Unhandled
GDCM-3.0.10/Source/DataDictionary/Part6PDF.xsl000066400000000000000000000143031412732066400205300ustar00rootroot00000000000000 PS 3.6-2007 Page - Standard - Tag Name VR VM Retired abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ ( , ) RET GDCM-3.0.10/Source/DataDictionary/Part6todcm4che.xsl000066400000000000000000000137521412732066400220000ustar00rootroot00000000000000 ' De-identification 's Sub-operations RET GDCM-3.0.10/Source/DataDictionary/Part7.xsl000066400000000000000000000021641412732066400202010ustar00rootroot00000000000000 GDCM-3.0.10/Source/DataDictionary/Part7a.xml000066400000000000000000000201161412732066400203310ustar00rootroot00000000000000 The even number of bytes from the end of the value field to the beginning of the next group. The affected SOP Class UID associated with the operation. The requested SOP Class UID associated with the operation. This field distinguishes the DIMSE operation conveyed by this Message. This field shall be set to one of the following values: 0001H       C-STORE-RQ 8001H       C-STORE-RSP 0010H       C-GET-RQ 8010H       C-GET-RSP 0020H       C-FIND-RQ 8020H       C-FIND-RSP 0021H       C-MOVE-RQ 8021H       C-MOVE-RSP 0030H       C-ECHO-RQ 8030H       C-ECHO-RSP 0100H       N-EVENT-REPORT-RQ 8100H       N-EVENT-REPORT-RSP 0110H       N-GET-RQ 8110H       N-GET-RSP 0120H       N-SET-RQ 8120H       N-SET-RSP 0130H       N-ACTION-RQ 8130H       N-ACTION-RSP 0140H       N-CREATE-RQ 8140H       N-CREATE-RSP 0150H       N-DELETE-RQ 8150H       N-DELETE-RSP 0FFFH       C-CANCEL-RQ Implementation-specific value that distinguishes this Message from other Messages. Shall be set to the value of the Message ID (0000,0110) field used in associated request Message. Shall be set to the DICOM AE Title of the destination DICOM AE to which the C-STORE sub-operations are being performed. The priority shall be set to one of the following values: LOW = 0002H MEDIUM = 0000H HIGH = 0001H This field indicates if a Data Set is present in the Message. This field shall be set to the value of 0101H if no Data Set is present; any other value indicates a Data Set is included in the Message. Confirmation status of the operation. See Annex C. If status is Cxxx, then this field contains a list of  the elements in which the error was detected. This field contains an application-specific text description of the error detected. This field shall optionally contain an application-specific error code. Contains the UID of the SOP Instance for which this operation occurred. Contains the UID of the SOP Instance for which this operation occurred. Values for this field are application-specific. This field contains an Attribute Tag for each of the n Attributes applicable. Values for this field are application-specific. The number of remaining C-STORE sub-operations to be invoked for the operation. The number of C-STORE sub-operations associated with this operation that have completed successfully. The number of C-STORE sub-operations associated with this operation that have failed. The number of C-STORE sub-operations associated with this operation that generated warning responses. Contains the DICOM AE Title of the DICOM AE that invoked the C-MOVE operation from which this C-STORE sub-operation is being performed. Contains the Message ID (0000,0110) of the C-MOVE-RQ Message from which this C-STORE sub-operation is being performed. GDCM-3.0.10/Source/DataDictionary/Part7b.xml000066400000000000000000000060031412732066400203310ustar00rootroot00000000000000 GDCM-3.0.10/Source/DataDictionary/PartToGDCM.xsl000066400000000000000000000040701412732066400210460ustar00rootroot00000000000000 This file was generated using the following commands: $ xsltproc PartToGDCM.xsl Part6.xml > tmp.xml $ xsltproc order.xsl tmp.xml > DICOMV3.xml Program: GDCM (Grass Root 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. 2009 GDCM-3.0.10/Source/DataDictionary/README.txt000066400000000000000000000016461412732066400201560ustar00rootroot00000000000000Part 3.6 The following files: acuson.xml agfa.xml camtron.xml dicom3.xml elscint.xml gems.xml isg.xml other.xml papyrus.xml philips.xml picker.xml siemens.xml spi.xml toshiba.xml where all converted from the dicom3tools (see COPYRIGHT.dicom3tools) own format into an XML form GroupName.dic is missing the Variable Pixel Data Design of DICOMV3.xml At one point in time the name attribute used to be in the character data of a description sub-element of entry. This was done to cope with case where the name would be a multi-line description. This was nice for some weird private attribute name in private dictionary...but this was adding more troubles than solving them. Indeed one would have to traverse each name to check for return line and handle them in a GUI. Therefore the attribute name in a public/private element should be single line (no \t, \n or \r) TODO: should name be ASCII (issue with which is not ASCII) ? GDCM-3.0.10/Source/DataDictionary/Siemens.xml000066400000000000000000000136561412732066400206110ustar00rootroot00000000000000 GDCM-3.0.10/Source/DataDictionary/TagKeywords.xsl000066400000000000000000000042471412732066400214530ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc TagKeywords.xsl Part6.xml > gdcmTagKeywords.h /*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2012 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 GDCMTAGKEYWORDS_H #define GDCMTAGKEYWORDS_H #include "gdcmAttribute.h" namespace gdcm { namespace Keywords { } } #endif // 0x , 0x SHALL NOT BE USED typedef gdcm::Attribute<0x , 0x > ; GDCM-3.0.10/Source/DataDictionary/TagToType.xsl000066400000000000000000000105651412732066400210700ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc TagToType.xsl Part6.xml > gdcmTagToType.h /*========================================================================= 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 GDCMTAGTOTYPE_H #define GDCMTAGTOTYPE_H #include "gdcmVR.h" #include "gdcmVM.h" #include "gdcmStaticAssert.h" namespace gdcm { // default template: the compiler should only pick it up when the element is private: template <uint16_t group,uint16_t element> struct TagToType { //GDCM_STATIC_ASSERT( group % 2 ); enum : long long { VRType = VR::VRALL }; enum { VMType = VM::VM1_n }; }; // template for group length: template <uint16_t group> struct TagToType<group,0x0000> { static const char* GetVRString() { return "UL"; } typedef VRToType<VR::UL>::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; TagToType<0x ,0x > template <> struct { static const char* GetVRString() { return " "; } typedef VRToType<VR:: >::Type Type; enum : long long { VRType = VR:: }; enum { VMType = VM:: }; static const char* GetVMString() { return " "; } }; } // end namespace gdcm #endif // GDCMTAGTOTYPE_H GDCM-3.0.10/Source/DataDictionary/TagToVR.xsl000066400000000000000000000051771412732066400205010ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc TagToVR.xsl Part6.xml > gdcmTagToVR.cxx /*========================================================================= 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 "gdcmVR.h" #include "gdcmVM.h" #include "gdcmStaticAssert.h" namespace gdcm { VR::VRType GetVRFromTag( Tag const & t ) { if( t.IsGroupLength() ) return VR::UL; uint32_t tag = t.GetElementTag(); switch( tag ) { case 0x : return VR:: ; default: return VR::INVALID; } } } // end namespace gdcm GDCM-3.0.10/Source/DataDictionary/UIDToC++.xsl000066400000000000000000000067571412732066400203750ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc UIDToC++.xsl Part6.xml > gdcmUIDs.cxx /*========================================================================= 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 GDCMUIDS_H #define GDCMUIDS_H typedef enum { uid_ frameref_ unhandled_ = , // } TSType; typedef enum { // Retired = , // } TSName; #endif // GDCMUIDS_H #ifdef GDCMUIDS_CXX static const char * const TransferSyntaxStrings[][2] = { {" "," "}, { 0, 0 } }; #endif // GDCMUIDS_CXX GDCM-3.0.10/Source/DataDictionary/UIDs.xml000066400000000000000000001075301412732066400200050ustar00rootroot00000000000000
GDCM-3.0.10/Source/DataDictionary/VM.xsl000066400000000000000000000021311412732066400175200ustar00rootroot00000000000000 GDCM-3.0.10/Source/DataDictionary/cp699.xml000066400000000000000000000300741412732066400200510ustar00rootroot00000000000000 Corrected Image Compression Recognition Code Compression Code Compression Originator Compression Label Compression Description Compression Sequence Compression Step Pointers Repeat Interval Bits Grouped Perimeter Table Perimeter Value Predictor Rows Predictor Columns Predictor Constants Blocked Pixels Block Rows Block Columns Row Overlap Column Overlap Bits Allocated Burned In Annotation Transform Label Transform Version Number Number of Transform Steps Sequence of Compressed Data Details of Coefficients Rows For Nth Order Coefficients Columns For Nth Order Coefficients Coefficient Coding Coefficient Coding Pointers DCT Label Data Block Description Data Block Normalization Factor Format Zonal Map Number Format Zonal Map Location Zonal Map Format Adaptive Map Format Code Number Format Code Label Number of Table Code Table Location Bits For Code Word Image Data Location Pixel Spacing Calibration Type Pixel Spacing Calibration Description Pixel Intensity Relationship Pixel Intensity Relationship Sign Escape Triplet Run Length Triplet Huffman Table Size Huffman Table Triplet Shift Table Size Shift Table Triplet Zonal Map Overlay Plane Origin Overlay Compression Code Overlay Compression Originator Overlay Compression Label Overlay Compression Description Overlay Compression Step Pointers Overlay Repeat Interval Overlay Bits Grouped Overlay Bits Allocated Overlay Bit Position Overlay Format Overlay Location Overlay Code Label Overlay Number of Tables Overlay Code Table Location Overlay Bits For Code Word Overlay Activation Layer Pixel Data Coefficients SDVN Coefficients SDHN Coefficients SDDN Variable Pixel Data Variable Next Data Group Variable Coefficients SDVN Variable Coefficients SDHN Variable Coefficients SDDN GDCM-3.0.10/Source/DataDictionary/dcmtk.xsl000066400000000000000000000207331412732066400203100ustar00rootroot00000000000000 # # Copyright (C) 1994-2012, OFFIS e.V. # All rights reserved. See COPYRIGHT file for details. # # This software and supporting documentation were developed by # # OFFIS e.V. # R&D Division Health # Escherweg 2 # D-26121 Oldenburg, Germany # # # Module: dcmdata # # Author: Andrew Hewett, Marco Eichelberg, Joerg Riesmeier # # Purpose: This is the global standard DICOM data dictionary for the DCMTK. # # This file contains the complete data dictionary from the 2011 edition of the # DICOM standard. This also includes the non-private definitions from the # DICONDE (Digital Imaging and Communication in Nondestructive Evaluation) and # DICOS (Digital Imaging and Communications in Security) standard. # # In addition, the data dictionary entries from the following final text # supplements and correction items have been incorporated: # - Supplement 152. # - CP 1064, 1123, 1137, 1138, 1147, 1188, 1204. # # Each line represents an entry in the data dictionary. Each line has 5 fields # (Tag, VR, Name, VM, Version). Entries need not be in ascending tag order. # # Entries may override existing entries. # # Each field must be separated by a single tab. The tag values (gggg,eeee) # must be in hexedecimal and must be surrounded by parentheses. Repeating # groups are represented by indicating the range (gggg-gggg,eeee). By default # the repeating notation only represents even numbers. A range where only # odd numbers are valid is represented using the notation (gggg-o-gggg,eeee). # A range can represent both even and odd numbers using the notation # (gggg-u-gggg,eeee). The element part of the tag can also be a range. # # Comments have a '#' at the beginning of the line. # # Tag VR Name VM Version # # #--------------------------------------------------------------------------- # # Private Creator Data Elements # (0009-o-ffff,0000) UL PrivateGroupLength 1 PRIVATE (0009-o-ffff,0010-u-00ff) LO PrivateCreator 1 PRIVATE (0001-o-0007,0000) UL IllegalGroupLength 1 ILLEGAL (0001-o-0007,0010-u-00ff) LO IllegalPrivateCreator 1 ILLEGAL # #--------------------------------------------------------------------------- # # A "catch all" for group length elements # (0000-u-ffff,0000) UL GenericGroupLength 1 GENERIC # #--------------------------------------------------------------------------- # # Retired data elements from ACR/NEMA 2 (1988) # GDCM-3.0.10/Source/DataDictionary/dicom3tools.xsl000066400000000000000000000067331412732066400214510ustar00rootroot00000000000000 ( , ) VERS=" 3 RET " VR=" " VM=" " Keyword=" ' " Name=" " GDCM-3.0.10/Source/DataDictionary/dicomhdr.html000066400000000000000000005773341412732066400211530ustar00rootroot00000000000000 Dtattributeimage

Image Attributes


Attribute Name Tag Type VR VM Descriptiom Creator Unit
General Image Attributes        
AcquisitionDate 0008,0022 3 DA 1 A number identifying the single continuous gathering of data over a period of time which resulted in this image acquisition  
ContentDate 0008,0023 2C DA 1 The date the image data creation started. Required if image is part of a series in which the images are temporally related acquisition  
AcquisitionTime 0008,0032 3 TM 1 The time the acquisition of data that resulted in this image started acquisition  
ContentTime 0008,0033 2C TM 1 The time the image pixrl data creation started. Required if image is part of a series in which the images are temporally related acquisition  
Acquisition Datetime 0008,002A 3 DT 1 The date and time that the acquisition of dada that result in this image started    
DerivationDescription 0008,2111 3 ST 1 A text description of how this image was derived image creator  
AcquisitionNumber 0020,0012 2 IS 1 Image identification characteristics acquisition  
InstanceNumber 0020,0013 2 IS 1 A number that identifies this image acquisition  
ImageComments 0020,4000 3 LT 1 User-defined comments about the image acquisition user interface  
ImageInAcquisition 0020,1002 3 IS 1 Number of images that resulted from this acquisition of data    
ReferencedImageSequence 0008,1140 3 link 1 A sequence which provides reference to a set of Image SOP Class/Instance identifying other images significantly related to this image (localizer images) acquisition  
>Referenced SOP Class UID 0008,1150 1C UI 1 Uniquely identifies the referenced SOP Class acquisition  
>Referenced SOP Instance UID 0008,1155 1C UI 1 Uniquely identifies the referenced SOP Instance acquisition  
> Referenced Frame Number 0008,1160 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 acquisition  
SourceImageSequence 0008,2112 3 link 1 A sequence which identifies the set of Image SOP Class/Instance pairs of the images which were use to derive this image acquisition  
>Referenced SOP Class UID 0008,1150 1C UI 1 Uniquely identifies the referenced SOP Class acquisition  
>Referenced SOP Instance UID 0008,1155 1C UI 1 Uniquely identifies the referenced SOP Instance acquisition  
> Referenced Frame Number 0008,1160 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 acquisition  
ImageType 0008,0008 3 CS 1-n Image identification characteristics acquisition  
Lossy Image Compression 0028,0300 3 CS 1 Specifies whether an image has undergone lossy compression. Enumerated values: 00 = image has not been subjected to lossy compression. 01 = image has been subjected to lossy compression image creator  
Quality Control Image 0008,0005 1C CS 1 Indicates whether or not this image is a quality control or phantom image. Enumerated values: YES, NO image creator  
PatientOrientation 0020,0020 2 CS k Patient direction of the rows and columns of the image. Not required for MR images    
MR Image Attributes        
ImageType 0008,0008 1 CS 1-n Image identification characteristics acquisition  
Samples per Pixel 0028,0002 1 US 1 Number of samples (planes) in this image acquisition  
PhotometricInterpretation 0028,0004 1 CS 1 Specifies the intended interpretation of the pixel data acquisition  
BitsAllocated 0028,0100 1 US 1 Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated acquisition  
Scanning Sequence 0018,0020 1 CS 1-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 acquisition  
SequenceVariant 0018,0021 1 CS 1-n Variant of the Scanning Sequence acquisition  
ScanOptions 0018,0022 2 CS 1-n Parameters of scanning sequence acquisition  
MRAcquisitionType 0018,0023 2 CS 1 Identification of date encoding scheme. Enumerated Values: 2D = frequency x phase 3D = frequency x phase x phase acquisition  
               
SequenceName 0018,0024 3 SH 1 User defined name for the Scanning Sequence and Sequence Varaint combination acquisition  
AngioFlag 0018,0025 3 CS 1 Angio image indicator. Primary image for angio processing. Enumerated values: Y = image is Angio N = image is not Angio acquisition  
RepetitionTime 0018,0080 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 acquisition msec
EchoTime 0018,0081 2 DS 1 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) acquisition msec
InversionTime 0018,0082 2C DS 1 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 acquisition msec
NumberOfAverages 0018,0083 3 DS 1 Number of times a given pulse sequence is repeated before any parameter has changed acquisition  
ImagingFrequency 0018,0084 3 DS 1 Precession frquency in MHz of the nucleus being addressed acquisition MHz
ImagedNucleus 0018,0085 3 SH 1 Nucleus that is resonant at the imaging frequency acquisition  
EchoNumbers 0018,0086 3 IS 1-n The echo number used in generating this image. In the case of segmented k-space, it is the effective Echo Number acquisition  
MagneticFieldStrength 0018,0087 3 DS 1 Nominal Field strength of MR magnet, in Tesla acquisition Tesla
SpacingBetweenSlices 0018,0088 3 DS 1 Spacing between slices, in mm. The spacing is measured from the center-to-center of each slice acquisition mm
NumberOfPhaseEncodingSteps 0018,0089 3 IS 1 Total number of lines in k-space in the y-direction collecting during acquisition acquisition  
EchoTrainLength 0018,0091 2 IS 1 Number of lines in k-space acquired per excitation per image acquisition  
PercentSampling 0018,0093 3 DS 1 Fraction of acquisition matrix lines acquired, expressed as a percent acquisition  
PercentPhaseFieldOfView 0018,0094 3 DS 1 Ration of field of view dimension in phase direction to field of view dimension in frequency direction, expressed as a percent acquisition  
PixelBandwidth 0018,0095 3 DS 1 Reciprocal of the total sampling period, in hertz per pixel acquisition hertz/pixel
BeatRejectionFlag 0018,1080 3 CS 1 Beat length sorting has been applied. Enumerated values: Y = yes N = no acquisition  
Low R-R Value 0018,1081 3 IS 1 R-R interval low limit for beat rejection, in msec acquisition msec
High R-R Value 0018,1082 3 IS 1 R-R interval high limit for beat rejection, in msec acquisition msec
TriggerTime 0018,1060 2C DS 1 Time, in msec, between peak of the R wave and the peak of the echo produced. In the case of segmented k-space, the TE(eff) is the time between the peak of the echo that is used to cover the center of k-space. Required for Scan Options which include heart gating acquisition msec
NominalInterval 0018,1062 3 IS 1 Average R-R interval used for the scans, in msec acquisition msec
IntervalsAcquired 0018,1083 3 IS 1 Number of R-R intervals acquired acquisition  
IntervalsRejected 0018,1083 3 IS 1 Number of R-R intervals rejected acquisition  
PVC Rejection 0018,1085 3 LO 1 Description of type of PVC rejection criteria used acquisition  
Skip Beats 0018,1086 3 IS 1 Number of beats skipped after a detected arrhythmia acquisition  
HeartRate 0018,1088 3 IS 1 Beats per minute acquisition 1/min
CardiacNumberOfImages 0018,1090 3 IS 1 Number of imagesb per cardiac cycle acquisition  
TriggerWindow 0018,1094 3 IS 1 Percent of R-R interval, based on Heart Rate (0018,1088), prescriped as a window for a valid/usable trigger    
ReconstructionDiameter 0018,1100 3 DS 1 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 acquisition  
Receive Coil 0018,1250 3 SH 1 Received coil used acquisition  
TransmittingCoil 0018,1251 3 SH 1 Transmitted coil used acquisition  
AcquisitionMatrix 0018,1310 3 US 4 Dimension of acquired frequency/phase data before reconstruction. Multi-valued: frequency rows\frequency columns\phase rows\phase columns acquisition  
PhaseEncodingDirection 0018,1312 3 CS 1 The axis of phase encoding with respect to the image. Enumerated Values: ROW = phase encoded in rows COL = phase encoded in columns acquisition  
FlipAngle 0018,1314 3 DS 1 Steady state angle in degrees to which the magnetic vector is flipped from the magnetic vector to the primary field acquisition degree
VariableFlipAngleFlag 0018,1315 3 CS 1 Flip angle variation applied during image acquisition. Enumerated Values: Y = yes N = no acquisition  
SAR 0018,1316 3 DS 1 Calculated whole body specific absortion rate in watts/kilogram acquisition Watt/kilogram
dbdt 0018,1318 3 DS 1 The rate of change of the gradient coil magnetic flux density with time (T/s) acquisition Tesla/sec
Contrast Bolus Attributes        
ContrastBolusAgent 0018,0010 2 LO 1 Contrast or bolus agent acquisition user interface  
ContrastBolusStartTime 0018,1042 3 TM 1 Time of start of injection acquisition user interface  
ContrastBolusStopTime 0018,1043 3 TM 1 Time of end of contrast injection acquisition user interface  
ContrastBolusTotalDose 0018,1044 3 DS 1 Total amount in milliliters of the indiluted contrast agent acquisition user interface ml
Contrast Flow Rate(s) 0018,1046 3 DS 1-n Rate(s) of injection(s) in millilitres/sec acquisition user interface ml/sec
ContrastBolusVolume 0018,1041 3 DS 1 Volume injected in milliliters of diluted contrast agent acquisition user interface  
ContrastFlowDurations 0018,1047 3 DS 1-n Duration(s) of injection(s) in seconds. Each Contrast Flow Duration value shall correspond to a value of Contrast Flow Rate (0018,1046) acquisition user interface sec
               
Contrast/Bolus Ingredient 0018,1048 3 CS 1 Active ingredient of agent, Defined Terms: IODINE, GADOLIMIUM, CARBON DIOXIDE, BARIUM acquisition user interface  
Contrast/Bolus Ingredient Concentration 0018,1049 3 DS 1 Milligrams of active ingredient per milliliter of (diluted) agent acquisition user interface mg/ml
Image Pixel Attributes        
SamplesPerPixel 0028,0002 1 US 1 Number of samples (planes) in this image acquisition  
PhotometricInterpretation 0028,0004 1 CS 1 Specifies the intended interpretation of the pixel data acquisition  
Rows 0028,0010 1 US 1 Number of rows in the image acquisition  
Columns 0028,0010 1 US 1 Number of columns in the image acquisition  
PixelAspectRatio 0028,0034 1C IS 2 Ratio of the vertical size and horizontal size of the pixels in the image specified by a pair of integer values where the first value is the vertical pixel size, and the second value is the horizontal pixel size. Required if the aspect ratio is not 1/1 and the Image Plane Module is not applicable to this Image acquisition  
BitsAllocated 0028,0100 1 US 1 Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated acquisition  
BitsStored 0028,0101 1 US 1 Number of bits stored for each pixel sample. Each sample shall have the same number of bits stored acquisition  
HighBit 0028,0102 1 US 1 Most significant bit for pixel sample data. Each sample shall have the same high bit acquisition  
PixelRepresentation 0028,0103 1 US 1 Data representation of the pixel samples. Each sample shall have the same pixel representation. Enumerated values: 0000H = unsigned integer. 0001H = 2's complement. acquisition  
PixelData 7FE0,0010 1 OW/OB 1 A data stream of the pixel samples which comprises the image acquisition  
Smallest Image Pixel Value 0028,0106 3 US/SS 1 The minimum actual pixel value encountered in this image acquisition  
Largest Image Pixel Value 0028.0107 3 US/SS 1 The maximum actual pixel value encountered in this image acquisition  
Image Plane Attributes        
SliceThickness 0018,0050 2 DS 1 Nominal slice thickness, in mm acquisition mm
ImageOrientationPatient 0020,0037 1 DS 6 The direction cosines of the first row and the first column with respect to the patient acquisition  
ImagePositionPatient 0020,0032 1 DS 3 The x,y and z coordinates of the upper left and hand corner (first pixel transmitted) of the image, in mm acquisition mm
SliceLocation 0020,1041 3 DS 1 Relative position of exposure expressed in mm acquisition mm
PixelSpacing 0028,0030 1 DS 2 Physical distance in the patient between the center of each pixel, specified by a numeric pair-adjacent row spacing (delimiter) adjacent column spacing in mm acquisition mm
VOI Lookup Table        
WindowCenter 0028,1050 3 DS 1-n Window center acquisition/application  
WindowWidth 0028,1050 1C DS 1-n Window width acquisition/application  
WindowCenterWidthExplanation 0028,1055 3 LO 1-n Free form explanation of the meaning of the Window Center and Width. Multiple values correspond to multiple Window Center and Width values acquisition/application  
Equipment Attributes              
Manufacturer 0008,0070 2 LO 1 Manufacturer of the equipment that produced the digital images acquisition/application  
InstitutionName 0008,0080 3 LO 1 Institution where the equipment is located that produced the digital images acquisition/application  
InstitutionAddress 0008,0081 3 ST 1 Mailing address of the institution where the equipment is located that produced the digital images acquisition/application  
ManufacturersModelName 0008,1090 3 LO 1 Manufacturer's model number of the equipment that produced the digital images acquisition/application  
DeviceSerialNumber 0018,1000 3 LO 1 Manufacturer's seriel number of the equipment that produced the digital images acquisition/application  
SoftwareVersions 0018,1020 3 LO 1-n Manufacturer's designation of software of the equipment that produced the digital images acquisition/application  
Overlay Idendification Attributes              
OverlayRows 60xx,0010 1 US 1 Number of Rows in Overlay post-processing applications  
OverlayColumns 60xx,0011 1 US 1 Number of Columns in Overlay post-processing applications  
OverlayType 60xx,0040 1 CS 1 Indicates whether this overlay represents a region of interest or other graphics post-processing applications  
Overlay Origin 60xx,0050 1 US 1 Location of first overlay point with respect to pixel in the image, given as row\column post-processing applications  
OverlayBitsAllocated 60xx,0100 1 US 1 Number of bits allocated in the overlay post-processing applications  
OverlayBitPosition 60xx,0102 1 US 1 Bit in which overlay is stored post-processing applications  
Overlay Data 60xx,3000 1C OB/OW 1 Overlay pixel data post-processing applications  
MEDCOM Header              
HeaderType 0029,xx08 1C CS 1 Medcom header characteristics. Defined Terms: MEDCOM 1 acquisition  
HeaderVersion 0029,xx09 2C LO 1 Version of Medcom header acquisition  
HeaderInfo 0029,xx10 3 OB 1 Manufacturer header info acquisition  
HistoryInfo 0029,xx20 3   1 Patient registration history patient registration  
MR and SC Private Attributes              
EchoLinePosition stream 1 IS 1 Fourier line position with the maximal echo for the performed acquisition acquisition  
EchoColumnPosition stream 1 IS 1 Echo column position for the performed acquisition acquisition  
EchoPartitionPosition stream 1 IS 1 Echo partition position for the performed acquisition acquisition  
UsedChannelMask stream 1 UL 1 8 bit mask of the used receiver channels for the performed acquisition. Example: channel 0: 00000001 channel 3: 00000111 acquisition  
Actual3DImaPartNumber stream 1 IS 1 Number of a 3D partitions beginning with 0 acquisition  
ICE_Dims stream 1 LO 1 The 9 used ICE object dimensions of the performed acquisition. Combined/unset dimensions will be marked with "X". E.g.: X_2_1_1_1_1_2_1_1 acquisition  
B_value stream   IS 1 Diffusion effect in s/mm*mm of the ICE program for the performed acquisition acquisition sec/(mm*mm)
Filter1 stream 1 IS   Context vision filter acquisition  
Filter2 stream 1 IS   not used acquisition  
ProtocolSliceNumber stream 1 IS 1 Number of the slice beginning with 0 acquisition  
RealDwellTime stream 1 IS 1 The time in ns between the beginning of sampling one data point and the beginning of sampling of next data point in the acquired signal. This means the dwell time is the sampling rate during digital conversion of an acquired signal acquisition nanosec
PixelFile stream 1 UN 1 Used raw data file for the performed acquisition acquisition  
PixelFileName stream 1 UN 1 Used raw data file name for the performed acquisition    
SliceMeasurementDuration stream 1 DS 1 Time duration between two slices of the performed acquisition acquisition msec
AcquisitionMatrixText stream 1 SH 1 Used acquisition matrix description acquisition  
SequenceMask stream 1 UL 1 Parameters used for acquisition, e.g. door open, interpolation, raw filter, Siemens seqence .... acquisition  
MeasuredFourierLines stream 1 IS 1 Number of performed fourier lines acquisition  
FlowEncodingDirection stream   IS 1 Flow encoding direction acquisition  
FlowVenc stream   FD 1 Flow Quant attribute acquisition  
PhaseEncodingDirectionPositive stream   IS 1 Phase encoding direction: 0 = negative; 1 = positive acquisition  
NumberOfImagesInMosaic stream   US 1 Number of slices in a mosaic image acquisition  
DiffusionGradientDirection stream   FD 3 Diffusion in gradient direction acquisition  
ImageGroup stream   US 1 Group of images acquisition  
SliceNormalVector stream   FD 3 X,y and z normal vector of the slices acquisition  
DiffusionDirection stream   CS 1 Diffusion direction acquisition  
TimeAfterStart stream   DS 1 Time delay after start of measurment acquisition  
FlipAngle stream   DS 1 Flip angle for SC images acquisition degree
SequenceName stream   SH 1 Sequence name for SC images acquisition  
RepetitionTime stream   DS 1 Repetition time for SC images acquisition msec
EchoTime stream   DS 1 Echo time for SC images acquisition msec
NumberOfAverages stream   DS n Number of averages for SC images acquisition  
MR NonImage (Raw Data, Spectra) Attributes              
NonimageType 0029,xx08 1 CS 1 Data identification characteristics. Defined terms: RAW DATA NUM 4; SPEC NUM4 acquisition  
NonimageVersion 0029,xx09 3 LO 1 Version of Non-image data acquisition  
NonimageInfo 0029,xx10 3 OB 1 Description of Non-image data acquisition  
NonimageData 7FE1,xx10 2 OB 1 Binary data stream acquisition  
ImageType 0008,0008 3 CS 1-n Image identification characteristics acquisition  
AcquisitionDate 0008,0022 3 DA 1 The date the acquisition of data started acquisition  
AcquisitionTime 0008,0032 3 TM 1 The time the acquisition of data started acquisition  
DerivationDescription 0008,2111 3 ST 1 A text description of how this data set was derived acquisition  
AcquisitionNumber 0020,0012 2 IS 1 A number identifying the gathering of data over a period of time which resulted in this data set acquisition  
ImageNumber stream   IS 1 A number that identifies this image acquisition  
ImageComments stream   LT 1 User-defined comments about the image acquisition  
ReferencedImageSequence stream   UI n A sequence which provides reference to a set of Image SOP Class/Instance identifying other images significantly related to this image (localizer images) acquisition  
PatientOrientation stream   CS 1 Patient direction of the rows and columns of the image. Not required for MR images acquisition  
ScanningSequence stream   CS 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 acquisition  
SequenceName stream   SH 1 User defined name for the Scanning Sequence and Sequence Varaint combination acquisition  
RepetitionTime stream   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 acquisition  
EchoTime stream   DS 1 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) acquisition  
InversionTime stream   DS 1 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 acquisition  
NumberOfAverages stream   DS 1 Number of averages acquisition  
ImagingFrequency stream   DS 1 Precession frquency in MHz of the nucleus being addressed acquisition  
ImagedNucleus stream   SH 1 Nucleus that is resonant at the imaging frequency acquisition  
EchoNumbers stream   IS 1 The echo number used in generating this image. In the case of segmented k-space, it is the effective Echo Number acquisition  
MagneticFieldStrength stream   DS 1 Nominal Field strength of MR magnet, in Tesla acquisition Tesla
NumberOfPhaseEncodingSteps stream   IS 1 Total number of lines in k-space in the y-direction collecting during acquisition acquisition  
EchoTrainLength stream   IS 1 Number of lines in k-space acquired per excitation per image acquisition  
PercentSampling stream   DS 1 Fraction of acquisition matrix lines acquired, expressed as a percent acquisition  
PercentPhaseFieldOfView stream   DS 1 Ration of field of view dimension in phase direction to field of view dimension in frequency direction, expressed as a percent acquisition  
TriggerTime stream   DS 1 Time, in msec, between peak of the R wave and the peak of the echo produced. In the case of segmented k-space, the TE(eff) is the time between the peak of the echo that is used to cover the center of k-space. Required for Scan Options which include heart gating acquisition  
ReceivingCoil stream   SH 1 Received coil used acquisition  
TransmittingColi stream   SH 1 Transmitted coil used acquisition  
AcquisitionMatrixText stream   US 4 Dimension of acquired frequency/phase data before reconstruction. Multi-valued: frequency rows\frequency columns\phase rows\phase columns acquisition  
PhaseEncodingDirection stream   CS 1 The axis of phase encoding with respect to the image. Enumerated Values: ROW = phase encoded in rows COL = phase encoded in columns acquisition  
FlipAngle stream   DS 1 Steady state angle in degrees to which the magnetic vector is flipped from the magnetic vector to the primary field acquisition Degree
VariableFlipAngleFlag stream   CS 1 Flip angle variation applied during image acquisition. Enumerated Values: Y = yes N = no acquisition  
SAR stream   DS 1 Calculated whole body specific absortion rate in watts/kilogram acquisition Watt/kilogram
dBdt stream   DS 3 The rate of change of the gradient coil magnetic flux density with time (T/s) acquisition Tesla/sec
Rows stream   US 1 Number of rows in the image acquisition mm
Columns stream   US 1 Number of columns in the image acquisition mm
SliceThickness stream   DS 1 Nominal slice thickness, in mm acquisition mm
ImagePositionPatient stream   DS 3 The direction cosines of the first row and the first column with respect to the patient acquisition  
ImageOrientationPatient stream   DS 6 The x,y and z coordinates of the upper left and hand corner (first pixel transmitted) of the image, in mm. acquisition mm
SliceLocation stream   DS 1 Relative position of exposure expressed in mm acquisition mm
EchoLinePosition stream   IS 1 Fourier line position with the maximal echo for the performed acquisition acquisition  
EchoColumnPosition stream   IS 1 Echo column position for the performed acquisition acquisition  
EchoPartitionPosition stream   IS 1 Echo partition position for the performed acquisition acquisition  
Actual3DImaPartNumber stream   IS 1 Number of a 3D partitions beginning with 0 acquisition  
RealDwellTime stream   IS 1 The time in ns between the beginning of sampling one data point and the beginning of sampling of next data point in the acquired signal. This means the dwell time is the sampling rate during digital conversion of an acquired signal acquisition  
ProtocolSliceNumber stream   UN 1 Number of the slice beginning with 0 acquisition  
PixelFile stream   UN 1 Used raw data file for the performed acquisition acquisition  
PixelFileName stream   LO 1 Used raw data file name for the performed acquisition acquisition  
ICE_Dims stream   DS 1 The 9 used ICE object dimensions of the performed acquisition. Combined/unset dimensions will be marked with "X". E.g.: X_2_1_1_1_1_2_1_1 acquisition  
PixelSpacing stream   DS 2 Physical distance in the patient between the center of each pixel, specified by a numeric pair-adjacent row spacing (delimiter) adjacent column spacing in mm acquisition mm
SourceImageSequence stream   UI n A sequence which identifies the set of Image SOP Class/Instance pairs of the images which were use to derive this image acquisition  
PixelBandwidth stream   DS 1 Reciprocal of the total sampling period, in hertz per pixel acquisition  
SliceMeasurementDuration stream   DS 1 Time duration between two slices of the performed acquisition acquisition  
SequenceMask stream   UL 1 Parameters used for acquisition, e.g. door open, interpolation, raw filter, Siemens seqence . acquisition  
AcquisitionMatrixText stream   SH 1 Used acquisition matrix description acquisition  
MeasuredFourierLines stream   IS 1 Number of performed fourier lines acquisition  
MR Protocol              
ulVersion stream 3 UL 1 Protocol version acquisition  
tSequenceFileName stream 3 ST 1 Sequence file name for actual measurement protocol acquisition  
tProtocolName stream 3 ST 1 Name of actual measurement protocol acquisition  
tReferenceImage0 stream 3 LO 1 Referenced image acquisition  
tReferenceImage1 stream 3 LO 1 Referenced image acquisition  
tReferenceImage2 stream 3 LO 1 Referenced image acquisition  
lScanRegionPosSag stream 3 FD 1 Desired table position in series block coordinate system acquisition  
lScanRegionPosCor stream 3 FD 1 Desired table position in series block coordinate system acquisition  
lScanRegionPosTra stream 3 FD 1 Desired table position in series block coordinate system acquisition  
ucScanRegionPosValid stream 3 SH 1 Valid flag for desired table position in series block coordinate system acquisition  
aucSpare stream 3 SH 1 Reserved acquisition  
lScanRegionDelta stream 3 SL 1 Scan Region Position/Move [mm] acquisition mm
sProtConsistencyInfo.tBaselineString stream 3 LO 1 Baseline consistence info acquisition  
sProtConsistencyInfo.tGradCoilName stream 3 SH 1 Coil name consistence info acquisition  
sProtConsistencyInfo.tGradAmplifierName stream 3 LO 1 Gradient amplifier consistence info acquisition  
sProtConsistencyInfo.flNominalB0 stream 3 FD 1 Nominal Bo compensation consistence acquisition  
sGRADSPEC.sEddyCompensationX.aflAmplitude stream 3 FD 5 Eddy compensation x amplitude gradient system specification acquisition  
sGRADSPEC.sEddyCompensationX.aflTimeConstant stream 3 FD 5 Eddy compensation x time parameter gradient system specification acquisition  
sGRADSPEC.sEddyCompensationY.aflAmplitude stream 3 FD 5 Eddy compensation y amplitude gradient system specification acquisition  
sGRADSPEC.sEddyCompensationY.aflTimeConstant stream 3 FD 5 Eddy compensation y time parameter gradient system specification acquisition  
sGRADSPEC.sEddyCompensationZ.aflAmplitude stream 3 FD 5 Eddy compensation z amplitude gradient system specification acquisition  
sGRADSPEC.sEddyCompensationZ.aflTimeConstant stream 3 FD 5 Eddy compensation z time parameter gradient system specification acquisition  
sGRADSPEC.bB0CompensationValid stream 3 SL 1 B0 compensation gradient system specification valid flag acquisition  
sGRADSPEC.sCrossTermCompensationXY.aflAmplitude stream 3 FD 5 Crossterm compensation xy amplitude gradient system specification acquisition  
sGRADSPEC.sCrossTermCompensationXY.aflTimeConstant stream 3 FD 5 Crossterm compensation xy time parameter gradient system specification acquisition  
sGRADSPEC.sCrossTermCompensationXZ.aflAmplitude stream 3 FD 5 Crossterm compensation xz amplitude gradient system specification acquisition  
sGRADSPEC.sCrossTermCompensationXZ.aflTimeConstant stream 3 FD 5 Crossterm compensation xz time parameter gradient system specification acquisition  
sGRADSPEC.sCrossTermCompensationYX.aflAmplitude stream 3 FD 5 Crossterm compensation xz amplitude gradient system specification acquisition  
sGRADSPEC.sCrossTermCompensationYX.aflTimeConstant stream 3 FD 5 Crossterm compensation yx time parameter gradient system specification acquisition  
sGRADSPEC.sCrossTermCompensationYZ.aflAmplitude stream 3 FD 5 Crossterm compensation yz amplitude gradient system specification acquisition  
sGRADSPEC.sCrossTermCompensationYZ.aflTimeConstant stream 3 FD 5 Crossterm compensation yz time parameter gradient system specification acquisition  
sGRADSPEC.sCrossTermCompensationZX.aflAmplitude stream 3 FD 5 Crossterm compensation zx amplitude gradient system specification acquisition  
sGRADSPEC.sCrossTermCompensationZX.aflTimeConstant stream 3 FD 5 Crossterm compensation zx time parameter gradient system specification acquisition  
sGRADSPEC.sCrossTermCompensationZY.aflAmplitude stream 3 FD 5 Crossterm compensation zx amplitude gradient system specification acquisition  
sGRADSPEC.sCrossTermCompensationZY.aflTimeConstant stream 3 FD 5 Crossterm compensation zy time parameter gradient system specification acquisition  
sGRADSPEC.bCrossTermCompensationValid stream 3 SL 1 Crossterm compensation gradient system specification valid flag acquisition  
sGRADSPEC.lOffsetX stream 3 SL 1 Gradient offset x direction [bit pattern] acquisition  
sGRADSPEC.lOffsetY stream 3 SL 1 Gradient offset y direction [bit pattern] acquisition  
sGRADSPEC.lOffsetZ stream 3 SL 1 Gradient offset z direction [bit pattern] acquisition  
sGRADSPEC.bOffsetValid stream 3 SL 1 Gradient offsets valid flag acquisition  
sGRADSPEC.lDelayX stream 3 SL 1 Gradient delay x direction acquisition  
sGRADSPEC.lDelayY stream 3 SL 1 Gradient delay y direction acquisition  
sGRADSPEC.lDelayY stream 3 SL 1 Gradient delay z direction acquisition  
sGRADSPEC.bDelayValid stream 3 SL 1 Gradient delay valid flag acquisition  
sGRADSPEC.flSensitivityX stream 3 FD 1 Gradient sensitivity x direction [mT/m] acquisition mT/m
sGRADSPEC.flSensitivityY stream 3 FD 1 Gradient sensitivity y direction [mT/m] acquisition mT/m
sGRADSPEC.flSensitivityZ stream 3 FD 1 Gradient sensitivity z direction [mT/m] acquisition mT/m
sGRADSPEC.bSensitivityValid stream 3 SL 1 Gradient sensitivity valid flag acquisition  
sGRADSPEC.flGSWDMinRiseTime stream 3 FD 1 Minimum gradient rise time for mode GRAD_GSWD_RISETIME acquisition mA
sGRADSPEC.alShimCurrent stream 3 SL 15 Shim current parameter [mA] acquisition  
sGRADSPEC.bShimCurrentValid stream 3 SL 1 Shim current parameter valid flag acquisition  
sGRADSPEC.ucMode stream 3 SH 1 Gradient mode: fast, normal, whisper acquisition  
sGRADSPEC.ucSpare0 stream 3 SH 1 Reserved acquisition  
sGRADSPEC.ucSpare1 stream 3 SH 1 Reserved acquisition  
sGRADSPEC.ucSpare2 stream 3 SH 1 Reserved acquisition  
sTXSPEC.asNucleusInfo[0].tNucleus stream 3 SH 1 Transmitter system nucleus acquisition  
sTXSPEC.asNucleusInfo[0].lFrequency stream 3 SL 1 Transmitter system frequency [Hz] acquisition Hz
sTXSPEC.asNucleusInfo[0].bFrequencyValid stream 3 SL 1 Frequency valid flag acquisition  
sTXSPEC.asNucleusInfo[0].lDeltaFrequency stream 3 SL 1 Offset from center frequency (lFrequency) acquisition  
sTXSPEC.asNucleusInfo[0].flReferenceAmplitude stream 3 FD 1 Transmitter reference amplitude [V] acquisition V
sTXSPEC.asNucleusInfo[0].bReferenceAmplitudeValid stream 3 SL 1 Reference amplitude valid flag acquisition  
sTXSPEC.asNucleusInfo[0].flAmplitudeCorrection stream 3 FD 1 Transmitter amplitude correction factor, e.g. used for water suppression acquisition  
sTXSPEC.asNucleusInfo[0].bAmplitudeCorrectionValid stream 3 SL 1 Amplitude correction valid flag acquisition  


Last Updated on 07.02.2002
GDCM-3.0.10/Source/DataDictionary/dicomhdr.xsl000066400000000000000000000034641412732066400210010ustar00rootroot00000000000000 GDCM-3.0.10/Source/DataDictionary/gdcmCSAHeaderDefaultDicts.cxx000066400000000000000000001015751412732066400240540ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc CSADefaultDicts.xsl CSAHeader.xml > gdcmCSAHeaderDefaultDicts.cxx /*========================================================================= 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 GDCMCSAHEADERDEFAULTDICT_CXX #define GDCMCSAHEADERDEFAULTDICT_CXX #include "gdcmCSAHeaderDict.h" #include "gdcmCSAHeaderDictEntry.h" #include "gdcmVR.h" #include "gdcmVM.h" namespace gdcm { using CSA_DICT_ENTRY = struct { const char *name; const char *type; VR::VRType vr; VM::VMType vm; const char *description; }; static const CSA_DICT_ENTRY CSAHeaderDataDict [] = { {"AcquisitionDate","3",VR::DA,VM::VM1,"A number identifying the single continuous gathering of data over a period of time which resulted in this image"}, {"ContentDate","2C",VR::DA,VM::VM1,"The date the image data creation started. Required if image is part of a series in which the images are temporally related"}, {"AcquisitionTime","3",VR::TM,VM::VM1,"The time the acquisition of data that resulted in this image started"}, {"ContentTime","2C",VR::TM,VM::VM1,"The time the image pixrl data creation started. Required if image is part of a series in which the images are temporally related"}, {"Acquisition Datetime","3",VR::DT,VM::VM1,"The date and time that the acquisition of dada that result in this image started"}, {"DerivationDescription","3",VR::ST,VM::VM1,"A text description of how this image was derived"}, {"AcquisitionNumber","2",VR::IS,VM::VM1,"Image identification characteristics"}, {"InstanceNumber","2",VR::IS,VM::VM1,"A number that identifies this image"}, {"ImageComments","3",VR::LT,VM::VM1,"User-defined comments about the image"}, {"ImageInAcquisition","3",VR::IS,VM::VM1,"Number of images that resulted from this acquisition of data"}, {">Referenced SOP Class UID","1C",VR::UI,VM::VM1,"Uniquely identifies the referenced SOP Class"}, {">Referenced SOP Instance UID","1C",VR::UI,VM::VM1,"Uniquely identifies the referenced SOP Instance"}, {"> Referenced Frame Number","3",VR::IS,VM::VM1_n,"References one or more image frames of a Multi-frame Image SOP Instance, identifying which frames are significantly related to this image"}, //{">Referenced SOP Class UID","1C",VR::UI,VM::VM1,"Uniquely identifies the referenced SOP Class"}, //{">Referenced SOP Instance UID","1C",VR::UI,VM::VM1,"Uniquely identifies the referenced SOP Instance"}, //{"> Referenced Frame Number","3",VR::IS,VM::VM1_n,"References one or more image frames of a Multi-frame Image SOP Instance, identifying which frames are significantly related to this image"}, {"ImageType","3",VR::CS,VM::VM1_n,"Image identification characteristics"}, {"Lossy Image Compression","3",VR::CS,VM::VM1,"Specifies whether an image has undergone lossy compression. Enumerated values: 00 = image has not been subjected to lossy compression. 01 = image has been subjected to lossy compression"}, {"Quality Control Image","1C",VR::CS,VM::VM1,"Indicates whether or not this image is a quality control or phantom image. Enumerated values: YES, NO"}, {"PatientOrientation","2",VR::CS,VM::VM1,"Patient direction of the rows and columns of the image. Not required for MR images"}, //{"ImageType","1",VR::CS,VM::VM1_n,"Image identification characteristics"}, {"Samples per Pixel","1",VR::US,VM::VM1,"Number of samples (planes) in this image"}, {"PhotometricInterpretation","1",VR::CS,VM::VM1,"Specifies the intended interpretation of the pixel data"}, {"BitsAllocated","1",VR::US,VM::VM1,"Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated"}, {"Scanning Sequence","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"}, {"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"}, {"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"}, {"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"}, {"ImagingFrequency","3",VR::DS,VM::VM1,"Precession frquency in MHz of the nucleus being addressed"}, {"ImagedNucleus","3",VR::SH,VM::VM1,"Nucleus that is resonant at the imaging frequency"}, {"EchoNumbers","3",VR::IS,VM::VM1_n,"The echo number used in generating this image. In the case of segmented k-space, it is the effective Echo Number"}, {"MagneticFieldStrength","3",VR::DS,VM::VM1,"Nominal Field strength of MR magnet, in Tesla"}, {"SpacingBetweenSlices","3",VR::DS,VM::VM1,"Spacing between slices, in mm. The spacing is measured from the center-to-center of each slice"}, {"NumberOfPhaseEncodingSteps","3",VR::IS,VM::VM1,"Total number of lines in k-space in the y-direction collecting during acquisition"}, {"EchoTrainLength","2",VR::IS,VM::VM1,"Number of lines in k-space acquired per excitation per image"}, {"PercentSampling","3",VR::DS,VM::VM1,"Fraction of acquisition matrix lines acquired, expressed as a percent"}, {"PercentPhaseFieldOfView","3",VR::DS,VM::VM1,"Ration of field of view dimension in phase direction to field of view dimension in frequency direction, expressed as a percent"}, {"PixelBandwidth","3",VR::DS,VM::VM1,"Reciprocal of the total sampling period, in hertz per pixel"}, {"BeatRejectionFlag","3",VR::CS,VM::VM1,"Beat length sorting has been applied. Enumerated values: Y = yes N = no"}, {"Low R-R Value","3",VR::IS,VM::VM1,"R-R interval low limit for beat rejection, in msec"}, {"High R-R Value","3",VR::IS,VM::VM1,"R-R interval high limit for beat rejection, in msec"}, {"TriggerTime","2C",VR::DS,VM::VM1,"Time, in msec, between peak of the R wave and the peak of the echo produced. In the case of segmented k-space, the TE(eff) is the time between the peak of the echo that is used to cover the center of k-space. Required for Scan Options which include heart gating"}, {"NominalInterval","3",VR::IS,VM::VM1,"Average R-R interval used for the scans, in msec"}, {"IntervalsAcquired","3",VR::IS,VM::VM1,"Number of R-R intervals acquired"}, {"IntervalsRejected","3",VR::IS,VM::VM1,"Number of R-R intervals rejected"}, {"PVC Rejection","3",VR::LO,VM::VM1,"Description of type of PVC rejection criteria used"}, {"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"}, {"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"}, {"AcquisitionMatrix","3",VR::US,VM::VM4,"Dimension of acquired frequency/phase data before reconstruction. Multi-valued: frequency rows/frequency columns/phase rows/phase columns"}, {"PhaseEncodingDirection","3",VR::CS,VM::VM1,"The axis of phase encoding with respect to the image. Enumerated Values: ROW = phase encoded in rows COL = phase encoded in columns"}, {"FlipAngle","3",VR::DS,VM::VM1,"Steady state angle in degrees to which the magnetic vector is flipped from the magnetic vector to the primary field"}, {"VariableFlipAngleFlag","3",VR::CS,VM::VM1,"Flip angle variation applied during image acquisition. Enumerated Values: Y = yes N = no"}, {"SAR","3",VR::DS,VM::VM1,"Calculated whole body specific absortion rate in watts/kilogram"}, {"dBdt","3",VR::DS,VM::VM1,"The rate of change of the gradient coil magnetic flux density with time (T/s)"}, {"ContrastBolusAgent","2",VR::LO,VM::VM1,"Contrast or bolus agent"}, {"ContrastBolusStartTime","3",VR::TM,VM::VM1,"Time of start of injection"}, {"ContrastBolusStopTime","3",VR::TM,VM::VM1,"Time of end of contrast injection"}, {"ContrastBolusTotalDose","3",VR::DS,VM::VM1,"Total amount in milliliters of the indiluted contrast agent"}, {"Contrast Flow Rate(s)","3",VR::DS,VM::VM1_n,"Rate(s) of injection(s) in millilitres/sec"}, {"ContrastBolusVolume","3",VR::DS,VM::VM1,"Volume injected in milliliters of diluted contrast agent"}, {"ContrastFlowDurations","3",VR::DS,VM::VM1_n,"Duration(s) of injection(s) in seconds. Each Contrast Flow Duration value shall correspond to a value of Contrast Flow Rate (0018,1046)"}, {"Contrast/Bolus Ingredient","3",VR::CS,VM::VM1,"Active ingredient of agent, Defined Terms: IODINE, GADOLIMIUM, CARBON DIOXIDE, BARIUM"}, {"Contrast/Bolus Ingredient Concentration","3",VR::DS,VM::VM1,"Milligrams of active ingredient per milliliter of (diluted) agent"}, {"SamplesPerPixel","1",VR::US,VM::VM1,"Number of samples (planes) in this image"}, //{"PhotometricInterpretation","1",VR::CS,VM::VM1,"Specifies the intended interpretation of the pixel data"}, {"Rows","1",VR::US,VM::VM1,"Number of rows in the image"}, {"Columns","1",VR::US,VM::VM1,"Number of columns in the image"}, {"PixelAspectRatio","1C",VR::IS,VM::VM2,"Ratio of the vertical size and horizontal size of the pixels in the image specified by a pair of integer values where the first value is the vertical pixel size, and the second value is the horizontal pixel size. Required if the aspect ratio is not 1/1 and the Image Plane Module is not applicable to this Image"}, //{"BitsAllocated","1",VR::US,VM::VM1,"Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated"}, {"BitsStored","1",VR::US,VM::VM1,"Number of bits stored for each pixel sample. Each sample shall have the same number of bits stored"}, {"HighBit","1",VR::US,VM::VM1,"Most significant bit for pixel sample data. Each sample shall have the same high bit"}, {"PixelRepresentation","1",VR::US,VM::VM1,"Data representation of the pixel samples. Each sample shall have the same pixel representation. Enumerated values: 0000H = unsigned integer. 0001H = 2's complement."}, {"PixelData","1",VR::OB_OW,VM::VM1,"A data stream of the pixel samples which comprises the image"}, {"Smallest Image Pixel Value","3",VR::US_SS,VM::VM1,"The minimum actual pixel value encountered in this image"}, {"Largest Image Pixel Value","3",VR::US_SS,VM::VM1,"The maximum actual pixel value encountered in this image"}, {"SliceThickness","2",VR::DS,VM::VM1,"Nominal slice thickness, in mm"}, {"ImageOrientationPatient","1",VR::DS,VM::VM6,"The direction cosines of the first row and the first column with respect to the patient"}, {"ImagePositionPatient","1",VR::DS,VM::VM3,"The x,y and z coordinates of the upper left and hand corner (first pixel transmitted) of the image, in mm"}, {"SliceLocation","3",VR::DS,VM::VM1,"Relative position of exposure expressed in mm"}, {"PixelSpacing","1",VR::DS,VM::VM2,"Physical distance in the patient between the center of each pixel, specified by a numeric pair-adjacent row spacing (delimiter) adjacent column spacing in mm"}, {"WindowCenter","3",VR::DS,VM::VM1_n,"Window center"}, {"WindowWidth","1C",VR::DS,VM::VM1_n,"Window width"}, {"WindowCenterWidthExplanation","3",VR::LO,VM::VM1_n,"Free form explanation of the meaning of the Window Center and Width. Multiple values correspond to multiple Window Center and Width values"}, {"Manufacturer","2",VR::LO,VM::VM1,"Manufacturer of the equipment that produced the digital images"}, {"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"}, {"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"}, {"OverlayType","1",VR::CS,VM::VM1,"Indicates whether this overlay represents a region of interest or other graphics"}, {"Overlay Origin","1",VR::US,VM::VM1,"Location of first overlay point with respect to pixel in the image, given as row/column"}, {"OverlayBitsAllocated","1",VR::US,VM::VM1,"Number of bits allocated in the overlay"}, {"OverlayBitPosition","1",VR::US,VM::VM1,"Bit in which overlay is stored"}, {"Overlay Data","1C",VR::OB_OW,VM::VM1,"Overlay pixel data"}, {"HeaderType","1C",VR::CS,VM::VM1,"Medcom header characteristics. Defined Terms: MEDCOM 1"}, {"HeaderVersion","2C",VR::LO,VM::VM1,"Version of Medcom header"}, {"HeaderInfo","3",VR::OB,VM::VM1,"Manufacturer header info"}, {"HistoryInfo","3",VR::OB,VM::VM1,"Patient registration history"}, {"EchoLinePosition","1",VR::IS,VM::VM1,"Fourier line position with the maximal echo for the performed acquisition"}, {"EchoColumnPosition","1",VR::IS,VM::VM1,"Echo column position for the performed acquisition"}, {"EchoPartitionPosition","1",VR::IS,VM::VM1,"Echo partition position for the performed acquisition"}, {"UsedChannelMask","1",VR::UL,VM::VM1,"8 bit mask of the used receiver channels for the performed acquisition. Example: channel 0: 00000001 channel 3: 00000111"}, {"Actual3DImaPartNumber","1",VR::IS,VM::VM1,"Number of a 3D partitions beginning with 0"}, {"ICE_Dims","1",VR::LO,VM::VM1,"The 9 used ICE object dimensions of the performed acquisition. Combined/unset dimensions will be marked with 'X'. E.g.: X_2_1_1_1_1_2_1_1"}, {"B_value","1;",VR::IS,VM::VM1,"Diffusion effect in s/mm*mm of the ICE program for the performed acquisition"}, {"Filter1","1",VR::IS,VM::VM1,"Context vision filter"}, {"Filter2","1",VR::IS,VM::VM1,"not used"}, {"ProtocolSliceNumber","1",VR::IS,VM::VM1,"Number of the slice beginning with 0"}, {"RealDwellTime","1",VR::IS,VM::VM1,"The time in ns between the beginning of sampling one data point and the beginning of sampling of next data point in the acquired signal. This means the dwell time is the sampling rate during digital conversion of an acquired signal"}, {"PixelFile","1",VR::UN,VM::VM1,"Used raw data file for the performed acquisition"}, {"PixelFileName","1",VR::UN,VM::VM1,"Used raw data file name for the performed acquisition"}, {"SliceMeasurementDuration","1",VR::DS,VM::VM1,"Time duration between two slices of the performed acquisition"}, {"AcquisitionMatrixText","1",VR::SH,VM::VM1,"Used acquisition matrix description"}, {"SequenceMask","1",VR::UL,VM::VM1,"Parameters used for acquisition, e.g. door open, interpolation, raw filter, Siemens sequence ...."}, {"MeasuredFourierLines","1",VR::IS,VM::VM1,"Number of performed fourier lines"}, {"FlowEncodingDirection","1",VR::IS,VM::VM1,"Flow encoding direction"}, {"FlowVenc","1",VR::FD,VM::VM1,"Flow Quant attribute"}, {"PhaseEncodingDirectionPositive","1",VR::IS,VM::VM1,"Phase encoding direction: 0 = negative; 1 = positive"}, {"NumberOfImagesInMosaic","1",VR::US,VM::VM1,"Number of slices in a mosaic image"}, {"DiffusionGradientDirection","1",VR::FD,VM::VM3,"Diffusion in gradient direction"}, {"ImageGroup","1",VR::US,VM::VM1,"Group of images"}, {"SliceNormalVector","1",VR::FD,VM::VM3,"X,y and z normal vector of the slices"}, {"DiffusionDirection","1",VR::CS,VM::VM1,"Diffusion direction"}, {"TimeAfterStart","1",VR::DS,VM::VM1,"Time delay after start of measurement"}, //{"FlipAngle","1",VR::DS,VM::VM1,"Flip angle for SC images"}, //{"SequenceName","1",VR::SH,VM::VM1,"Sequence name for SC images"}, //{"RepetitionTime","1",VR::DS,VM::VM1,"Repetition time for SC images"}, //{"EchoTime","1",VR::DS,VM::VM1,"Echo time for SC images"}, //{"NumberOfAverages","1",VR::DS,VM::VM1_n,"Number of averages for SC images"}, {"NonimageType","1",VR::CS,VM::VM1,"Data identification characteristics. Defined terms: RAW DATA NUM 4; SPEC NUM4"}, {"NonimageVersion","3",VR::LO,VM::VM1,"Version of Non-image data"}, {"NonimageInfo","3",VR::OB,VM::VM1,"Description of Non-image data"}, {"NonimageData","2",VR::OB,VM::VM1,"Binary data stream"}, //{"ImageType","3",VR::CS,VM::VM1_n,"Image identification characteristics"}, //{"AcquisitionDate","3",VR::DA,VM::VM1,"The date the acquisition of data started"}, //{"AcquisitionTime","3",VR::TM,VM::VM1,"The time the acquisition of data started"}, //{"DerivationDescription","3",VR::ST,VM::VM1,"A text description of how this data set was derived"}, //{"AcquisitionNumber","2",VR::IS,VM::VM1,"A number identifying the gathering of data over a period of time which resulted in this data set"}, {"ImageNumber","1",VR::IS,VM::VM1,"A number that identifies this image"}, //{"ImageComments","1",VR::LT,VM::VM1,"User-defined comments about the image"}, {"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"}, //{"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"}, //{"ImagingFrequency","1",VR::DS,VM::VM1,"Precession frquency in MHz of the nucleus being addressed"}, //{"ImagedNucleus","1",VR::SH,VM::VM1,"Nucleus that is resonant at the imaging frequency"}, //{"EchoNumbers","1",VR::IS,VM::VM1,"The echo number used in generating this image. In the case of segmented k-space, it is the effective Echo Number"}, //{"MagneticFieldStrength","1",VR::DS,VM::VM1,"Nominal Field strength of MR magnet, in Tesla"}, //{"NumberOfPhaseEncodingSteps","1",VR::IS,VM::VM1,"Total number of lines in k-space in the y-direction collecting during acquisition"}, //{"EchoTrainLength","1",VR::IS,VM::VM1,"Number of lines in k-space acquired per excitation per image"}, //{"PercentSampling","1",VR::DS,VM::VM1,"Fraction of acquisition matrix lines acquired, expressed as a percent"}, //{"PercentPhaseFieldOfView","1",VR::DS,VM::VM1,"Ration of field of view dimension in phase direction to field of view dimension in frequency direction, expressed as a percent"}, //{"TriggerTime","1",VR::DS,VM::VM1,"Time, in msec, between peak of the R wave and the peak of the echo produced. In the case of segmented k-space, the TE(eff) is the time between the peak of the echo that is used to cover the center of k-space. Required for Scan Options which include heart gating"}, {"ReceivingCoil","1",VR::SH,VM::VM1,"Received coil used"}, {"TransmittingColi","1",VR::SH,VM::VM1,"Transmitted coil used"}, //{"AcquisitionMatrixText","1",VR::US,VM::VM4,"Dimension of acquired frequency/phase data before reconstruction. Multi-valued: frequency rows/frequency columns/phase rows/phase columns"}, //{"PhaseEncodingDirection","1",VR::CS,VM::VM1,"The axis of phase encoding with respect to the image. Enumerated Values: ROW = phase encoded in rows COL = phase encoded in columns"}, //{"FlipAngle","1",VR::DS,VM::VM1,"Steady state angle in degrees to which the magnetic vector is flipped from the magnetic vector to the primary field"}, //{"VariableFlipAngleFlag","1",VR::CS,VM::VM1,"Flip angle variation applied during image acquisition. Enumerated Values: Y = yes N = no"}, //{"SAR","1",VR::DS,VM::VM1,"Calculated whole body specific absortion rate in watts/kilogram"}, //{"dBdt","1",VR::DS,VM::VM3,"The rate of change of the gradient coil magnetic flux density with time (T/s)"}, //{"Rows","1",VR::US,VM::VM1,"Number of rows in the image"}, //{"Columns","1",VR::US,VM::VM1,"Number of columns in the image"}, //{"SliceThickness","1",VR::DS,VM::VM1,"Nominal slice thickness, in mm"}, //{"ImagePositionPatient","1",VR::DS,VM::VM3,"The direction cosines of the first row and the first column with respect to the patient"}, //{"ImageOrientationPatient","1",VR::DS,VM::VM6,"The x,y and z coordinates of the upper left and hand corner (first pixel transmitted) of the image, in mm."}, //{"SliceLocation","1",VR::DS,VM::VM1,"Relative position of exposure expressed in mm"}, //{"EchoLinePosition","1",VR::IS,VM::VM1,"Fourier line position with the maximal echo for the performed acquisition"}, //{"EchoColumnPosition","1",VR::IS,VM::VM1,"Echo column position for the performed acquisition"}, //{"EchoPartitionPosition","1",VR::IS,VM::VM1,"Echo partition position for the performed acquisition"}, //{"Actual3DImaPartNumber","1",VR::IS,VM::VM1,"Number of a 3D partitions beginning with 0"}, //{"RealDwellTime","1",VR::IS,VM::VM1,"The time in ns between the beginning of sampling one data point and the beginning of sampling of next data point in the acquired signal. This means the dwell time is the sampling rate during digital conversion of an acquired signal"}, //{"ProtocolSliceNumber","1",VR::UN,VM::VM1,"Number of the slice beginning with 0"}, //{"PixelFile","1",VR::UN,VM::VM1,"Used raw data file for the performed acquisition"}, //{"PixelFileName","1",VR::LO,VM::VM1,"Used raw data file name for the performed acquisition"}, //{"ICE_Dims","1",VR::DS,VM::VM1,"The 9 used ICE object dimensions of the performed acquisition. Combined/unset dimensions will be marked with 'X'. E.g.: X_2_1_1_1_1_2_1_1"}, //{"PixelSpacing","1",VR::DS,VM::VM2,"Physical distance in the patient between the center of each pixel, specified by a numeric pair-adjacent row spacing (delimiter) adjacent column spacing in mm"}, {"SourceImageSequence","1",VR::UI,VM::VM1_n,"A sequence which identifies the set of Image SOP Class/Instance pairs of the images which were use to derive this image"}, //{"PixelBandwidth","1",VR::DS,VM::VM1,"Reciprocal of the total sampling period, in hertz per pixel"}, //{"SliceMeasurementDuration","1",VR::DS,VM::VM1,"Time duration between two slices of the performed acquisition"}, //{"SequenceMask","1",VR::UL,VM::VM1,"Parameters used for acquisition, e.g. door open, interpolation, raw filter, Siemens sequence .·"}, //{"AcquisitionMatrixText","1",VR::SH,VM::VM1,"Used acquisition matrix description"}, //{"MeasuredFourierLines","1",VR::IS,VM::VM1,"Number of performed fourier lines"}, {"ulVersion","3",VR::UL,VM::VM1,"Protocol version"}, {"tSequenceFileName","3",VR::ST,VM::VM1,"Sequence file name for actual measurement protocol"}, {"tProtocolName","3",VR::ST,VM::VM1,"Name of actual measurement protocol"}, {"tReferenceImage0","3",VR::LO,VM::VM1,"Referenced image"}, {"tReferenceImage1","3",VR::LO,VM::VM1,"Referenced image"}, {"tReferenceImage2","3",VR::LO,VM::VM1,"Referenced image"}, {"lScanRegionPosSag","3",VR::FD,VM::VM1,"Desired table position in series block coordinate system"}, {"lScanRegionPosCor","3",VR::FD,VM::VM1,"Desired table position in series block coordinate system"}, {"lScanRegionPosTra","3",VR::FD,VM::VM1,"Desired table position in series block coordinate system"}, {"ucScanRegionPosValid","3",VR::SH,VM::VM1,"Valid flag for desired table position in series block coordinate system"}, {"aucSpare","3",VR::SH,VM::VM1,"Reserved"}, {"lScanRegionDelta","3",VR::SL,VM::VM1,"Scan Region Position/Move [mm]"}, {"sProtConsistencyInfo.tBaselineString","3",VR::LO,VM::VM1,"Baseline consistence info"}, {"sProtConsistencyInfo.tGradCoilName","3",VR::SH,VM::VM1,"Coil name consistence info"}, {"sProtConsistencyInfo.tGradAmplifierName","3",VR::LO,VM::VM1,"Gradient amplifier consistence info"}, {"sProtConsistencyInfo.flNominalB0","3",VR::FD,VM::VM1,"Nominal Bo compensation consistence"}, {"sGRADSPEC.sEddyCompensationX.aflAmplitude","3",VR::FD,VM::VM5,"Eddy compensation x amplitude gradient system specification"}, {"sGRADSPEC.sEddyCompensationX.aflTimeConstant","3",VR::FD,VM::VM5,"Eddy compensation x time parameter gradient system specification"}, {"sGRADSPEC.sEddyCompensationY.aflAmplitude","3",VR::FD,VM::VM5,"Eddy compensation y amplitude gradient system specification"}, {"sGRADSPEC.sEddyCompensationY.aflTimeConstant","3",VR::FD,VM::VM5,"Eddy compensation y time parameter gradient system specification"}, {"sGRADSPEC.sEddyCompensationZ.aflAmplitude","3",VR::FD,VM::VM5,"Eddy compensation z amplitude gradient system specification"}, {"sGRADSPEC.sEddyCompensationZ.aflTimeConstant","3",VR::FD,VM::VM5,"Eddy compensation z time parameter gradient system specification"}, {"sGRADSPEC.bB0CompensationValid","3",VR::SL,VM::VM1,"B0 compensation gradient system specification valid flag"}, {"sGRADSPEC.sCrossTermCompensationXY.aflAmplitude","3",VR::FD,VM::VM5,"Crossterm compensation xy amplitude gradient system specification"}, {"sGRADSPEC.sCrossTermCompensationXY.aflTimeConstant","3",VR::FD,VM::VM5,"Crossterm compensation xy time parameter gradient system specification"}, {"sGRADSPEC.sCrossTermCompensationXZ.aflAmplitude","3",VR::FD,VM::VM5,"Crossterm compensation xz amplitude gradient system specification"}, {"sGRADSPEC.sCrossTermCompensationXZ.aflTimeConstant","3",VR::FD,VM::VM5,"Crossterm compensation xz time parameter gradient system specification"}, {"sGRADSPEC.sCrossTermCompensationYX.aflAmplitude","3",VR::FD,VM::VM5,"Crossterm compensation xz amplitude gradient system specification"}, {"sGRADSPEC.sCrossTermCompensationYX.aflTimeConstant","3",VR::FD,VM::VM5,"Crossterm compensation yx time parameter gradient system specification"}, {"sGRADSPEC.sCrossTermCompensationYZ.aflAmplitude","3",VR::FD,VM::VM5,"Crossterm compensation yz amplitude gradient system specification"}, {"sGRADSPEC.sCrossTermCompensationYZ.aflTimeConstant","3",VR::FD,VM::VM5,"Crossterm compensation yz time parameter gradient system specification"}, {"sGRADSPEC.sCrossTermCompensationZX.aflAmplitude","3",VR::FD,VM::VM5,"Crossterm compensation zx amplitude gradient system specification"}, {"sGRADSPEC.sCrossTermCompensationZX.aflTimeConstant","3",VR::FD,VM::VM5,"Crossterm compensation zx time parameter gradient system specification"}, {"sGRADSPEC.sCrossTermCompensationZY.aflAmplitude","3",VR::FD,VM::VM5,"Crossterm compensation zx amplitude gradient system specification"}, {"sGRADSPEC.sCrossTermCompensationZY.aflTimeConstant","3",VR::FD,VM::VM5,"Crossterm compensation zy time parameter gradient system specification"}, {"sGRADSPEC.bCrossTermCompensationValid","3",VR::SL,VM::VM1,"Crossterm compensation gradient system specification valid flag"}, {"sGRADSPEC.lOffsetX","3",VR::SL,VM::VM1,"Gradient offset x direction [bit pattern]"}, {"sGRADSPEC.lOffsetY","3",VR::SL,VM::VM1,"Gradient offset y direction [bit pattern]"}, {"sGRADSPEC.lOffsetZ","3",VR::SL,VM::VM1,"Gradient offset z direction [bit pattern]"}, {"sGRADSPEC.bOffsetValid","3",VR::SL,VM::VM1,"Gradient offsets valid flag"}, {"sGRADSPEC.lDelayX","3",VR::SL,VM::VM1,"Gradient delay x direction"}, {"sGRADSPEC.lDelayY","3",VR::SL,VM::VM1,"Gradient delay y direction"}, {"sGRADSPEC.lDelayZ","3",VR::SL,VM::VM1,"Gradient delay z direction"}, {"sGRADSPEC.bDelayValid","3",VR::SL,VM::VM1,"Gradient delay valid flag"}, {"sGRADSPEC.flSensitivityX","3",VR::FD,VM::VM1,"Gradient sensitivity x direction [mT/m]"}, {"sGRADSPEC.flSensitivityY","3",VR::FD,VM::VM1,"Gradient sensitivity y direction [mT/m]"}, {"sGRADSPEC.flSensitivityZ","3",VR::FD,VM::VM1,"Gradient sensitivity z direction [mT/m]"}, {"sGRADSPEC.bSensitivityValid","3",VR::SL,VM::VM1,"Gradient sensitivity valid flag"}, {"sGRADSPEC.flGSWDMinRiseTime","3",VR::FD,VM::VM1,"Minimum gradient rise time for mode GRAD_GSWD_RISETIME"}, {"sGRADSPEC.alShimCurrent","3",VR::SL,VM::VM16,"Shim current parameter [mA]"}, {"sGRADSPEC.bShimCurrentValid","3",VR::SL,VM::VM1,"Shim current parameter valid flag"}, {"sGRADSPEC.ucMode","3",VR::SH,VM::VM1,"Gradient mode: fast, normal, whisper"}, {"sGRADSPEC.ucSpare0","3",VR::SH,VM::VM1,"Reserved"}, {"sGRADSPEC.ucSpare1","3",VR::SH,VM::VM1,"Reserved"}, {"sGRADSPEC.ucSpare2","3",VR::SH,VM::VM1,"Reserved"}, {"sTXSPEC.asNucleusInfo[0].tNucleus","3",VR::SH,VM::VM1,"Transmitter system nucleus"}, {"sTXSPEC.asNucleusInfo[0].lFrequency","3",VR::SL,VM::VM1,"Transmitter system frequency [Hz]"}, {"sTXSPEC.asNucleusInfo[0].bFrequencyValid","3",VR::SL,VM::VM1,"Frequency valid flag"}, {"sTXSPEC.asNucleusInfo[0].lDeltaFrequency","3",VR::SL,VM::VM1,"Offset from center frequency (lFrequency)"}, {"sTXSPEC.asNucleusInfo[0].flReferenceAmplitude","3",VR::FD,VM::VM1,"Transmitter reference amplitude [V]"}, {"sTXSPEC.asNucleusInfo[0].bReferenceAmplitudeValid","3",VR::SL,VM::VM1,"Reference amplitude valid flag"}, {"sTXSPEC.asNucleusInfo[0].flAmplitudeCorrection","3",VR::FD,VM::VM1,"Transmitter amplitude correction factor, e.g. used for water suppression"}, {"sTXSPEC.asNucleusInfo[0].bAmplitudeCorrectionValid","3",VR::SL,VM::VM1,"Amplitude correction valid flag"}, /* Manually added */ {"sKSpace.ucSlicePartialFourier","1",VR::US,VM::VM1,"Partial Fourier Information 0x1,0x2,0x4,0x8,0x10 resp. 4/8,5/8,6/8,7/8,8/8"}, // http://www.nmr.mgh.harvard.edu/~greve/dicom-unpack // http://web.archiveorange.com/archive/v/AW2a1uSBsvpLmfFd9xvy /* ASCCONV does contain most of the good info. In particular the slice ordering is encoded thus: sSliceArray.ucMode -- should be in (1, 2, 4) enum SeriesMode { ASCENDING = 0x01, DESCENDING = 0x02, INTERLEAVED = 0x04 }; And when interleaved, the slice ordering depends on whether the number of slices is even or odd. I have it coded (counting from zero) as: if ODD: slice_order = {0, 2, 4, ..., N-1, 1, 3, 5, ..., N-2} else: slice_order = {1, 3, 5, ..., N-1, 0, 2, 4, ..., N-2} which I can't immediately confirm, but I'm reasonably confident about it. It's all a bit of a mess, but there is some code available on the CIRL repo in bic/trunk/recon-tools/root/scanner/siemens.py check out parse_siemens_hdr() in that module, where I also documented various useful fields. And there are the helper functions ( strip_ascconv(), condense_array() ) in siemens_utils.py. No docstrings, so ping me if you need clarification. */ {"sSliceArray.ucMode","1",VR::US,VM::VM1,"slice ordering 0x1,0x2,0x4 resp. asc,desc,inter"}, {nullptr,nullptr,VR::INVALID,VM::VM0,nullptr } // Guard }; void CSAHeaderDict::LoadDefault() { unsigned int i = 0; CSA_DICT_ENTRY n = CSAHeaderDataDict[i]; while( n.name != nullptr ) { CSAHeaderDictEntry e( n.name, n.vr, n.vm, n.description ); AddCSAHeaderDictEntry( e ); n = CSAHeaderDataDict[++i]; } } } // end namespace gdcm #endif // GDCMCSAHEADERDEFAULTDICT_CXX GDCM-3.0.10/Source/DataDictionary/gdcmCSAHeaderDict.h000066400000000000000000000054701412732066400220060ustar00rootroot00000000000000/*========================================================================= 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 GDCMCSAHEADERDICT_H #define GDCMCSAHEADERDICT_H #include "gdcmTypes.h" #include "gdcmTag.h" #include "gdcmCSAHeaderDictEntry.h" #include #include #include #include namespace gdcm { class GDCM_EXPORT CSAHeaderDictException : public std::exception {}; /** * \brief Class to represent a map of CSAHeaderDictEntry */ class GDCM_EXPORT CSAHeaderDict { public: typedef std::set MapCSAHeaderDictEntry; typedef MapCSAHeaderDictEntry::iterator Iterator; typedef MapCSAHeaderDictEntry::const_iterator ConstIterator; //static CSAHeaderDictEntry GroupLengthCSAHeaderDictEntry; // = CSAHeaderDictEntry("Group Length",VR::UL,VM::VM1); CSAHeaderDict():CSAHeaderDictInternal() { assert( CSAHeaderDictInternal.empty() ); } CSAHeaderDict &operator=(const CSAHeaderDict &_val) = delete; CSAHeaderDict(const CSAHeaderDict &_val) = delete; friend std::ostream& operator<<(std::ostream& _os, const CSAHeaderDict &_val); ConstIterator Begin() const { return CSAHeaderDictInternal.begin(); } ConstIterator End() const { return CSAHeaderDictInternal.end(); } bool IsEmpty() const { return CSAHeaderDictInternal.empty(); } void AddCSAHeaderDictEntry(const CSAHeaderDictEntry &de) { #ifndef NDEBUG MapCSAHeaderDictEntry::size_type s = CSAHeaderDictInternal.size(); #endif CSAHeaderDictInternal.insert( de ); assert( s < CSAHeaderDictInternal.size() ); } const CSAHeaderDictEntry &GetCSAHeaderDictEntry(const char *name) const { MapCSAHeaderDictEntry::const_iterator it = CSAHeaderDictInternal.find( name ); if( it != CSAHeaderDictInternal.end() ) { return *it; } throw CSAHeaderDictException(); } protected: friend class Dicts; void LoadDefault(); private: MapCSAHeaderDictEntry CSAHeaderDictInternal; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& os, const CSAHeaderDict &val) { CSAHeaderDict::MapCSAHeaderDictEntry::const_iterator it = val.CSAHeaderDictInternal.begin(); for(;it != val.CSAHeaderDictInternal.end(); ++it) { const CSAHeaderDictEntry &de = *it; os << de << '\n'; } return os; } } // end namespace gdcm #endif //GDCMCSAHEADERDICT_H GDCM-3.0.10/Source/DataDictionary/gdcmCSAHeaderDictEntry.h000066400000000000000000000053651412732066400230330ustar00rootroot00000000000000/*========================================================================= 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 GDCMCSAHEADERDICTENTRY_H #define GDCMCSAHEADERDICTENTRY_H #include "gdcmVR.h" #include "gdcmVM.h" #include #include #include #include namespace gdcm { /** * \brief Class to represent an Entry in the Dict * \details Does not really exist within the DICOM definition, just a way to minimize * storage and have a mapping from gdcm::Tag to the needed information * \note bla * TODO FIXME: Need a PublicCSAHeaderDictEntry...indeed CSAHeaderDictEntry has a notion of retired which * does not exist in PrivateCSAHeaderDictEntry... * * \see gdcm::Dict */ class GDCM_EXPORT CSAHeaderDictEntry { public: CSAHeaderDictEntry(const char *name = "", VR const &vr = VR::INVALID, VM const &vm = VM::VM0, const char *desc = ""):Name(name),ValueRepresentation(vr),ValueMultiplicity(vm),Description(desc) { } friend std::ostream& operator<<(std::ostream& _os, const CSAHeaderDictEntry &_val); /// Set/Get VR const VR &GetVR() const { return ValueRepresentation; } void SetVR(const VR & vr) { ValueRepresentation = vr; } /// Set/Get VM const VM &GetVM() const { return ValueMultiplicity; } void SetVM(VM const & vm) { ValueMultiplicity = vm; } /// Set/Get Name const char *GetName() const { return Name.c_str(); } void SetName(const char* name) { Name = name; } /// Set/Get Description const char *GetDescription() const { return Description.c_str(); } void SetDescription(const char* desc) { Description = desc; } bool operator<(const CSAHeaderDictEntry &entry) const { return strcmp(GetName(),entry.GetName()) < 0; } private: std::string Name; VR ValueRepresentation; VM ValueMultiplicity; std::string Description; std::string Type; // TODO }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& os, const CSAHeaderDictEntry &val) { if( val.Name.empty() ) { os << "[No name]"; } else { os << val.Name; } os << "\t" << val.ValueRepresentation << "\t" << val.ValueMultiplicity; if( !val.Description.empty() ) { os << "\t" << val.Description; } return os; } } // end namespace gdcm #endif //GDCMCSAHEADERDICTENTRY_H GDCM-3.0.10/Source/DataDictionary/gdcmDefaultDicts.cxx000066400000000000000000044354171412732066400224250ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc DefaultDicts.xsl Part6.xml > gdcmDefaultDicts.cxx /*========================================================================= 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 GDCMDEFAULTDICTS_CXX #define GDCMDEFAULTDICTS_CXX #include "gdcmDicts.h" #include "gdcmVR.h" #include "gdcmDict.h" #include "gdcmDictEntry.h" namespace { using namespace gdcm; using DICT_ENTRY = struct { uint16_t group; uint16_t element; VR::VRType vr; VM::VMType vm; const char *name; const char *keyword; bool ret; }; static const DICT_ENTRY DICOMV3DataDict [] = { {0x0000,0x0000,VR::UL,VM::VM1,"Command Group Length","CommandGroupLength",false }, {0x0000,0x0001,VR::UL,VM::VM1,"Command Length to End","CommandLengthToEnd",true }, {0x0000,0x0002,VR::UI,VM::VM1,"Affected SOP Class UID","AffectedSOPClassUID",false }, {0x0000,0x0003,VR::UI,VM::VM1,"Requested SOP Class UID","RequestedSOPClassUID",false }, {0x0000,0x0010,VR::SH,VM::VM1,"Command Recognition Code","CommandRecognitionCode",true }, {0x0000,0x0100,VR::US,VM::VM1,"Command Field","CommandField",false }, {0x0000,0x0110,VR::US,VM::VM1,"Message ID","MessageID",false }, {0x0000,0x0120,VR::US,VM::VM1,"Message ID Being Responded To","MessageIDBeingRespondedTo",false }, {0x0000,0x0200,VR::AE,VM::VM1,"Initiator","Initiator",true }, {0x0000,0x0300,VR::AE,VM::VM1,"Receiver","Receiver",true }, {0x0000,0x0400,VR::AE,VM::VM1,"Find Location","FindLocation",true }, {0x0000,0x0600,VR::AE,VM::VM1,"Move Destination","MoveDestination",false }, {0x0000,0x0700,VR::US,VM::VM1,"Priority","Priority",false }, {0x0000,0x0800,VR::US,VM::VM1,"Command Data Set Type","CommandDataSetType",false }, {0x0000,0x0850,VR::US,VM::VM1,"Number of Matches","NumberOfMatches",true }, {0x0000,0x0860,VR::US,VM::VM1,"Response Sequence Number","ResponseSequenceNumber",true }, {0x0000,0x0900,VR::US,VM::VM1,"Status","Status",false }, {0x0000,0x0901,VR::AT,VM::VM1_n,"Offending Element","OffendingElement",false }, {0x0000,0x0902,VR::LO,VM::VM1,"Error Comment","ErrorComment",false }, {0x0000,0x0903,VR::US,VM::VM1,"Error ID","ErrorID",false }, {0x0000,0x1000,VR::UI,VM::VM1,"Affected SOP Instance UID","AffectedSOPInstanceUID",false }, {0x0000,0x1001,VR::UI,VM::VM1,"Requested SOP Instance UID","RequestedSOPInstanceUID",false }, {0x0000,0x1002,VR::US,VM::VM1,"Event Type ID","EventTypeID",false }, {0x0000,0x1005,VR::AT,VM::VM1_n,"Attribute Identifier List","AttributeIdentifierList",false }, {0x0000,0x1008,VR::US,VM::VM1,"Action Type ID","ActionTypeID",false }, {0x0000,0x1020,VR::US,VM::VM1,"Number of Remaining Sub-operations","NumberOfRemainingSuboperations",false }, {0x0000,0x1021,VR::US,VM::VM1,"Number of Completed Sub-operations","NumberOfCompletedSuboperations",false }, {0x0000,0x1022,VR::US,VM::VM1,"Number of Failed Sub-operations","NumberOfFailedSuboperations",false }, {0x0000,0x1023,VR::US,VM::VM1,"Number of Warning Sub-operations","NumberOfWarningSuboperations",false }, {0x0000,0x1030,VR::AE,VM::VM1,"Move Originator Application Entity Title","MoveOriginatorApplicationEntityTitle",false }, {0x0000,0x1031,VR::US,VM::VM1,"Move Originator Message ID","MoveOriginatorMessageID",false }, {0x0000,0x4000,VR::LT,VM::VM1,"Dialog Receiver","DialogReceiver",true }, {0x0000,0x4010,VR::LT,VM::VM1,"Terminal Type","TerminalType",true }, {0x0000,0x5010,VR::SH,VM::VM1,"Message Set ID","MessageSetID",true }, {0x0000,0x5020,VR::SH,VM::VM1,"End Message ID","EndMessageID",true }, {0x0000,0x5110,VR::LT,VM::VM1,"Display Format","DisplayFormat",true }, {0x0000,0x5120,VR::LT,VM::VM1,"Page Position ID","PagePositionID",true }, {0x0000,0x5130,VR::CS,VM::VM1,"Text Format ID","TextFormatID",true }, {0x0000,0x5140,VR::CS,VM::VM1,"Normal/Reverse","NormalReverse",true }, {0x0000,0x5150,VR::CS,VM::VM1,"Add Gray Scale","AddGrayScale",true }, {0x0000,0x5160,VR::CS,VM::VM1,"Borders","Borders",true }, {0x0000,0x5170,VR::IS,VM::VM1,"Copies","Copies",true }, {0x0000,0x5180,VR::CS,VM::VM1,"Command Magnification Type","CommandMagnificationType",true }, {0x0000,0x5190,VR::CS,VM::VM1,"Erase","Erase",true }, {0x0000,0x51a0,VR::CS,VM::VM1,"Print","Print",true }, {0x0000,0x51b0,VR::US,VM::VM1_n,"Overlays","Overlays",true }, {0x0002,0x0000,VR::UL,VM::VM1,"File Meta Information Group Length","FileMetaInformationGroupLength",false }, {0x0002,0x0001,VR::OB,VM::VM1,"File Meta Information Version","FileMetaInformationVersion",false }, {0x0002,0x0002,VR::UI,VM::VM1,"Media Storage SOP Class UID","MediaStorageSOPClassUID",false }, {0x0002,0x0003,VR::UI,VM::VM1,"Media Storage SOP Instance UID","MediaStorageSOPInstanceUID",false }, {0x0002,0x0010,VR::UI,VM::VM1,"Transfer Syntax UID","TransferSyntaxUID",false }, {0x0002,0x0012,VR::UI,VM::VM1,"Implementation Class UID","ImplementationClassUID",false }, {0x0002,0x0013,VR::SH,VM::VM1,"Implementation Version Name","ImplementationVersionName",false }, {0x0002,0x0016,VR::AE,VM::VM1,"Source Application Entity Title","SourceApplicationEntityTitle",false }, {0x0002,0x0017,VR::AE,VM::VM1,"Sending Application Entity Title","SendingApplicationEntityTitle",false }, {0x0002,0x0018,VR::AE,VM::VM1,"Receiving Application Entity Title","ReceivingApplicationEntityTitle",false }, {0x0002,0x0100,VR::UI,VM::VM1,"Private Information Creator UID","PrivateInformationCreatorUID",false }, {0x0002,0x0102,VR::OB,VM::VM1,"Private Information","PrivateInformation",false }, {0x0004,0x1130,VR::CS,VM::VM1,"File-set ID","FileSetID",false }, {0x0004,0x1141,VR::CS,VM::VM1_8,"File-set Descriptor File ID","FileSetDescriptorFileID",false }, {0x0004,0x1142,VR::CS,VM::VM1,"Specific Character Set of File-set Descriptor File","SpecificCharacterSetOfFileSetDescriptorFile",false }, {0x0004,0x1200,VR::UL,VM::VM1,"Offset of the First Directory Record of the Root Directory Entity","OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity",false }, {0x0004,0x1202,VR::UL,VM::VM1,"Offset of the Last Directory Record of the Root Directory Entity","OffsetOfTheLastDirectoryRecordOfTheRootDirectoryEntity",false }, {0x0004,0x1212,VR::US,VM::VM1,"File-set Consistency Flag","FileSetConsistencyFlag",false }, {0x0004,0x1220,VR::SQ,VM::VM1,"Directory Record Sequence","DirectoryRecordSequence",false }, {0x0004,0x1400,VR::UL,VM::VM1,"Offset of the Next Directory Record","OffsetOfTheNextDirectoryRecord",false }, {0x0004,0x1410,VR::US,VM::VM1,"Record In-use Flag","RecordInUseFlag",false }, {0x0004,0x1420,VR::UL,VM::VM1,"Offset of Referenced Lower-Level Directory Entity","OffsetOfReferencedLowerLevelDirectoryEntity",false }, {0x0004,0x1430,VR::CS,VM::VM1,"Directory Record Type","DirectoryRecordType",false }, {0x0004,0x1432,VR::UI,VM::VM1,"Private Record UID","PrivateRecordUID",false }, {0x0004,0x1500,VR::CS,VM::VM1_8,"Referenced File ID","ReferencedFileID",false }, {0x0004,0x1504,VR::UL,VM::VM1,"MRDR Directory Record Offset","MRDRDirectoryRecordOffset",true }, {0x0004,0x1510,VR::UI,VM::VM1,"Referenced SOP Class UID in File","ReferencedSOPClassUIDInFile",false }, {0x0004,0x1511,VR::UI,VM::VM1,"Referenced SOP Instance UID in File","ReferencedSOPInstanceUIDInFile",false }, {0x0004,0x1512,VR::UI,VM::VM1,"Referenced Transfer Syntax UID in File","ReferencedTransferSyntaxUIDInFile",false }, {0x0004,0x151a,VR::UI,VM::VM1_n,"Referenced Related General SOP Class UID in File","ReferencedRelatedGeneralSOPClassUIDInFile",false }, {0x0004,0x1600,VR::UL,VM::VM1,"Number of References","NumberOfReferences",true }, {0x0008,0x0001,VR::UL,VM::VM1,"Length to End","LengthToEnd",true }, {0x0008,0x0005,VR::CS,VM::VM1_n,"Specific Character Set","SpecificCharacterSet",false }, {0x0008,0x0006,VR::SQ,VM::VM1,"Language Code Sequence","LanguageCodeSequence",false }, {0x0008,0x0008,VR::CS,VM::VM2_n,"Image Type","ImageType",false }, {0x0008,0x0010,VR::SH,VM::VM1,"Recognition Code","RecognitionCode",true }, {0x0008,0x0012,VR::DA,VM::VM1,"Instance Creation Date","InstanceCreationDate",false }, {0x0008,0x0013,VR::TM,VM::VM1,"Instance Creation Time","InstanceCreationTime",false }, {0x0008,0x0014,VR::UI,VM::VM1,"Instance Creator UID","InstanceCreatorUID",false }, {0x0008,0x0015,VR::DT,VM::VM1,"Instance Coercion DateTime","InstanceCoercionDateTime",false }, {0x0008,0x0016,VR::UI,VM::VM1,"SOP Class UID","SOPClassUID",false }, {0x0008,0x0018,VR::UI,VM::VM1,"SOP Instance UID","SOPInstanceUID",false }, {0x0008,0x001a,VR::UI,VM::VM1_n,"Related General SOP Class UID","RelatedGeneralSOPClassUID",false }, {0x0008,0x001b,VR::UI,VM::VM1,"Original Specialized SOP Class UID","OriginalSpecializedSOPClassUID",false }, {0x0008,0x0020,VR::DA,VM::VM1,"Study Date","StudyDate",false }, {0x0008,0x0021,VR::DA,VM::VM1,"Series Date","SeriesDate",false }, {0x0008,0x0022,VR::DA,VM::VM1,"Acquisition Date","AcquisitionDate",false }, {0x0008,0x0023,VR::DA,VM::VM1,"Content Date","ContentDate",false }, {0x0008,0x0024,VR::DA,VM::VM1,"Overlay Date","OverlayDate",true }, {0x0008,0x0025,VR::DA,VM::VM1,"Curve Date","CurveDate",true }, {0x0008,0x002a,VR::DT,VM::VM1,"Acquisition DateTime","AcquisitionDateTime",false }, {0x0008,0x0030,VR::TM,VM::VM1,"Study Time","StudyTime",false }, {0x0008,0x0031,VR::TM,VM::VM1,"Series Time","SeriesTime",false }, {0x0008,0x0032,VR::TM,VM::VM1,"Acquisition Time","AcquisitionTime",false }, {0x0008,0x0033,VR::TM,VM::VM1,"Content Time","ContentTime",false }, {0x0008,0x0034,VR::TM,VM::VM1,"Overlay Time","OverlayTime",true }, {0x0008,0x0035,VR::TM,VM::VM1,"Curve Time","CurveTime",true }, {0x0008,0x0040,VR::US,VM::VM1,"Data Set Type","DataSetType",true }, {0x0008,0x0041,VR::LO,VM::VM1,"Data Set Subtype","DataSetSubtype",true }, {0x0008,0x0042,VR::CS,VM::VM1,"Nuclear Medicine Series Type","NuclearMedicineSeriesType",true }, {0x0008,0x0050,VR::SH,VM::VM1,"Accession Number","AccessionNumber",false }, {0x0008,0x0051,VR::SQ,VM::VM1,"Issuer of Accession Number Sequence","IssuerOfAccessionNumberSequence",false }, {0x0008,0x0052,VR::CS,VM::VM1,"Query/Retrieve Level","QueryRetrieveLevel",false }, {0x0008,0x0053,VR::CS,VM::VM1,"Query/Retrieve View","QueryRetrieveView",false }, {0x0008,0x0054,VR::AE,VM::VM1_n,"Retrieve AE Title","RetrieveAETitle",false }, {0x0008,0x0055,VR::AE,VM::VM1,"Station AE Title","StationAETitle",false }, {0x0008,0x0056,VR::CS,VM::VM1,"Instance Availability","InstanceAvailability",false }, {0x0008,0x0058,VR::UI,VM::VM1_n,"Failed SOP Instance UID List","FailedSOPInstanceUIDList",false }, {0x0008,0x0060,VR::CS,VM::VM1,"Modality","Modality",false }, {0x0008,0x0061,VR::CS,VM::VM1_n,"Modalities in Study","ModalitiesInStudy",false }, {0x0008,0x0062,VR::UI,VM::VM1_n,"SOP Classes in Study","SOPClassesInStudy",false }, {0x0008,0x0064,VR::CS,VM::VM1,"Conversion Type","ConversionType",false }, {0x0008,0x0068,VR::CS,VM::VM1,"Presentation Intent Type","PresentationIntentType",false }, {0x0008,0x0070,VR::LO,VM::VM1,"Manufacturer","Manufacturer",false }, {0x0008,0x0080,VR::LO,VM::VM1,"Institution Name","InstitutionName",false }, {0x0008,0x0081,VR::ST,VM::VM1,"Institution Address","InstitutionAddress",false }, {0x0008,0x0082,VR::SQ,VM::VM1,"Institution Code Sequence","InstitutionCodeSequence",false }, {0x0008,0x0090,VR::PN,VM::VM1,"Referring Physician's Name","ReferringPhysicianName",false }, {0x0008,0x0092,VR::ST,VM::VM1,"Referring Physician's Address","ReferringPhysicianAddress",false }, {0x0008,0x0094,VR::SH,VM::VM1_n,"Referring Physician's Telephone Numbers","ReferringPhysicianTelephoneNumbers",false }, {0x0008,0x0096,VR::SQ,VM::VM1,"Referring Physician Identification Sequence","ReferringPhysicianIdentificationSequence",false }, {0x0008,0x009c,VR::PN,VM::VM1_n,"Consulting Physician's Name","ConsultingPhysicianName",false }, {0x0008,0x009d,VR::SQ,VM::VM1,"Consulting Physician Identification Sequence","ConsultingPhysicianIdentificationSequence",false }, {0x0008,0x0100,VR::SH,VM::VM1,"Code Value","CodeValue",false }, {0x0008,0x0101,VR::LO,VM::VM1,"Extended Code Value","ExtendedCodeValue",false }, {0x0008,0x0102,VR::SH,VM::VM1,"Coding Scheme Designator","CodingSchemeDesignator",false }, {0x0008,0x0103,VR::SH,VM::VM1,"Coding Scheme Version","CodingSchemeVersion",false }, {0x0008,0x0104,VR::LO,VM::VM1,"Code Meaning","CodeMeaning",false }, {0x0008,0x0105,VR::CS,VM::VM1,"Mapping Resource","MappingResource",false }, {0x0008,0x0106,VR::DT,VM::VM1,"Context Group Version","ContextGroupVersion",false }, {0x0008,0x0107,VR::DT,VM::VM1,"Context Group Local Version","ContextGroupLocalVersion",false }, {0x0008,0x0108,VR::LT,VM::VM1,"Extended Code Meaning","ExtendedCodeMeaning",false }, {0x0008,0x010b,VR::CS,VM::VM1,"Context Group Extension Flag","ContextGroupExtensionFlag",false }, {0x0008,0x010c,VR::UI,VM::VM1,"Coding Scheme UID","CodingSchemeUID",false }, {0x0008,0x010d,VR::UI,VM::VM1,"Context Group Extension Creator UID","ContextGroupExtensionCreatorUID",false }, {0x0008,0x010f,VR::CS,VM::VM1,"Context Identifier","ContextIdentifier",false }, {0x0008,0x0110,VR::SQ,VM::VM1,"Coding Scheme Identification Sequence","CodingSchemeIdentificationSequence",false }, {0x0008,0x0112,VR::LO,VM::VM1,"Coding Scheme Registry","CodingSchemeRegistry",false }, {0x0008,0x0114,VR::ST,VM::VM1,"Coding Scheme External ID","CodingSchemeExternalID",false }, {0x0008,0x0115,VR::ST,VM::VM1,"Coding Scheme Name","CodingSchemeName",false }, {0x0008,0x0116,VR::ST,VM::VM1,"Coding Scheme Responsible Organization","CodingSchemeResponsibleOrganization",false }, {0x0008,0x0117,VR::UI,VM::VM1,"Context UID","ContextUID",false }, {0x0008,0x0118,VR::UI,VM::VM1,"Mapping Resource UID","MappingResourceUID",false }, {0x0008,0x0119,VR::UC,VM::VM1,"Long Code Value","LongCodeValue",false }, {0x0008,0x0120,VR::UR,VM::VM1,"URN Code Value","URNCodeValue",false }, {0x0008,0x0121,VR::SQ,VM::VM1,"Equivalent Code Sequence","EquivalentCodeSequence",false }, {0x0008,0x0122,VR::LO,VM::VM1,"Mapping Resource Name","MappingResourceName",false }, {0x0008,0x0123,VR::SQ,VM::VM1,"Context Group Identification Sequence","ContextGroupIdentificationSequence",false }, {0x0008,0x0124,VR::SQ,VM::VM1,"Mapping Resource Identification Sequence","MappingResourceIdentificationSequence",false }, {0x0008,0x0201,VR::SH,VM::VM1,"Timezone Offset From UTC","TimezoneOffsetFromUTC",false }, {0x0008,0x0220,VR::SQ,VM::VM1,"Responsible Group Code Sequence","ResponsibleGroupCodeSequence",false }, {0x0008,0x0221,VR::CS,VM::VM1,"Equipment Modality","EquipmentModality",false }, {0x0008,0x0222,VR::LO,VM::VM1,"Manufacturer's Related Model Group","ManufacturerRelatedModelGroup",false }, {0x0008,0x0300,VR::SQ,VM::VM1,"Private Data Element Characteristics Sequence","PrivateDataElementCharacteristicsSequence",false }, {0x0008,0x0301,VR::US,VM::VM1,"Private Group Reference","PrivateGroupReference",false }, {0x0008,0x0302,VR::LO,VM::VM1,"Private Creator Reference","PrivateCreatorReference",false }, {0x0008,0x0303,VR::CS,VM::VM1,"Block Identifying Information Status","BlockIdentifyingInformationStatus",false }, {0x0008,0x0304,VR::US,VM::VM1_n,"Nonidentifying Private Elements","NonidentifyingPrivateElements",false }, {0x0008,0x0305,VR::SQ,VM::VM1,"Deidentification Action Sequence","DeidentificationActionSequence",false }, {0x0008,0x0306,VR::US,VM::VM1_n,"Identifying Private Elements","IdentifyingPrivateElements",false }, {0x0008,0x0307,VR::CS,VM::VM1,"Deidentification Action","DeidentificationAction",false }, {0x0008,0x0308,VR::US,VM::VM1,"Private Data Element","PrivateDataElement",false }, {0x0008,0x0309,VR::UL,VM::VM1_3,"Private Data Element Value Multiplicity","PrivateDataElementValueMultiplicity",false }, {0x0008,0x030a,VR::CS,VM::VM1,"Private Data Element Value Representation","PrivateDataElementValueRepresentation",false }, {0x0008,0x030b,VR::UL,VM::VM1_2,"Private Data Element Number of Items","PrivateDataElementNumberOfItems",false }, {0x0008,0x030c,VR::UC,VM::VM1,"Private Data Element Name","PrivateDataElementName",false }, {0x0008,0x030d,VR::UC,VM::VM1,"Private Data Element Keyword","PrivateDataElementKeyword",false }, {0x0008,0x030e,VR::UT,VM::VM1,"Private Data Element Description","PrivateDataElementDescription",false }, {0x0008,0x030f,VR::UT,VM::VM1,"Private Data Element Encoding","PrivateDataElementEncoding",false }, {0x0008,0x0310,VR::SQ,VM::VM1,"Private Data Element Definition Sequence","PrivateDataElementDefinitionSequence",false }, {0x0008,0x1000,VR::AE,VM::VM1,"Network ID","NetworkID",true }, {0x0008,0x1010,VR::SH,VM::VM1,"Station Name","StationName",false }, {0x0008,0x1030,VR::LO,VM::VM1,"Study Description","StudyDescription",false }, {0x0008,0x1032,VR::SQ,VM::VM1,"Procedure Code Sequence","ProcedureCodeSequence",false }, {0x0008,0x103e,VR::LO,VM::VM1,"Series Description","SeriesDescription",false }, {0x0008,0x103f,VR::SQ,VM::VM1,"Series Description Code Sequence","SeriesDescriptionCodeSequence",false }, {0x0008,0x1040,VR::LO,VM::VM1,"Institutional Department Name","InstitutionalDepartmentName",false }, {0x0008,0x1048,VR::PN,VM::VM1_n,"Physician(s) of Record","PhysiciansOfRecord",false }, {0x0008,0x1049,VR::SQ,VM::VM1,"Physician(s) of Record Identification Sequence","PhysiciansOfRecordIdentificationSequence",false }, {0x0008,0x1050,VR::PN,VM::VM1_n,"Performing Physician's Name","PerformingPhysicianName",false }, {0x0008,0x1052,VR::SQ,VM::VM1,"Performing Physician Identification Sequence","PerformingPhysicianIdentificationSequence",false }, {0x0008,0x1060,VR::PN,VM::VM1_n,"Name of Physician(s) Reading Study","NameOfPhysiciansReadingStudy",false }, {0x0008,0x1062,VR::SQ,VM::VM1,"Physician(s) Reading Study Identification Sequence","PhysiciansReadingStudyIdentificationSequence",false }, {0x0008,0x1070,VR::PN,VM::VM1_n,"Operators' Name","OperatorsName",false }, {0x0008,0x1072,VR::SQ,VM::VM1,"Operator Identification Sequence","OperatorIdentificationSequence",false }, {0x0008,0x1080,VR::LO,VM::VM1_n,"Admitting Diagnoses Description","AdmittingDiagnosesDescription",false }, {0x0008,0x1084,VR::SQ,VM::VM1,"Admitting Diagnoses Code Sequence","AdmittingDiagnosesCodeSequence",false }, {0x0008,0x1090,VR::LO,VM::VM1,"Manufacturer's Model Name","ManufacturerModelName",false }, {0x0008,0x1100,VR::SQ,VM::VM1,"Referenced Results Sequence","ReferencedResultsSequence",true }, {0x0008,0x1110,VR::SQ,VM::VM1,"Referenced Study Sequence","ReferencedStudySequence",false }, {0x0008,0x1111,VR::SQ,VM::VM1,"Referenced Performed Procedure Step Sequence","ReferencedPerformedProcedureStepSequence",false }, {0x0008,0x1115,VR::SQ,VM::VM1,"Referenced Series Sequence","ReferencedSeriesSequence",false }, {0x0008,0x1120,VR::SQ,VM::VM1,"Referenced Patient Sequence","ReferencedPatientSequence",false }, {0x0008,0x1125,VR::SQ,VM::VM1,"Referenced Visit Sequence","ReferencedVisitSequence",false }, {0x0008,0x1130,VR::SQ,VM::VM1,"Referenced Overlay Sequence","ReferencedOverlaySequence",true }, {0x0008,0x1134,VR::SQ,VM::VM1,"Referenced Stereometric Instance Sequence","ReferencedStereometricInstanceSequence",false }, {0x0008,0x113a,VR::SQ,VM::VM1,"Referenced Waveform Sequence","ReferencedWaveformSequence",false }, {0x0008,0x1140,VR::SQ,VM::VM1,"Referenced Image Sequence","ReferencedImageSequence",false }, {0x0008,0x1145,VR::SQ,VM::VM1,"Referenced Curve Sequence","ReferencedCurveSequence",true }, {0x0008,0x114a,VR::SQ,VM::VM1,"Referenced Instance Sequence","ReferencedInstanceSequence",false }, {0x0008,0x114b,VR::SQ,VM::VM1,"Referenced Real World Value Mapping Instance Sequence","ReferencedRealWorldValueMappingInstanceSequence",false }, {0x0008,0x1150,VR::UI,VM::VM1,"Referenced SOP Class UID","ReferencedSOPClassUID",false }, {0x0008,0x1155,VR::UI,VM::VM1,"Referenced SOP Instance UID","ReferencedSOPInstanceUID",false }, {0x0008,0x115a,VR::UI,VM::VM1_n,"SOP Classes Supported","SOPClassesSupported",false }, {0x0008,0x1160,VR::IS,VM::VM1_n,"Referenced Frame Number","ReferencedFrameNumber",false }, {0x0008,0x1161,VR::UL,VM::VM1_n,"Simple Frame List","SimpleFrameList",false }, {0x0008,0x1162,VR::UL,VM::VM3_3n,"Calculated Frame List","CalculatedFrameList",false }, {0x0008,0x1163,VR::FD,VM::VM2,"Time Range","TimeRange",false }, {0x0008,0x1164,VR::SQ,VM::VM1,"Frame Extraction Sequence","FrameExtractionSequence",false }, {0x0008,0x1167,VR::UI,VM::VM1,"Multi-frame Source SOP Instance UID","MultiFrameSourceSOPInstanceUID",false }, {0x0008,0x1190,VR::UR,VM::VM1,"Retrieve URL","RetrieveURL",false }, {0x0008,0x1195,VR::UI,VM::VM1,"Transaction UID","TransactionUID",false }, {0x0008,0x1196,VR::US,VM::VM1,"Warning Reason","WarningReason",false }, {0x0008,0x1197,VR::US,VM::VM1,"Failure Reason","FailureReason",false }, {0x0008,0x1198,VR::SQ,VM::VM1,"Failed SOP Sequence","FailedSOPSequence",false }, {0x0008,0x1199,VR::SQ,VM::VM1,"Referenced SOP Sequence","ReferencedSOPSequence",false }, {0x0008,0x119a,VR::SQ,VM::VM1,"Other Failures Sequence","OtherFailuresSequence",false }, {0x0008,0x1200,VR::SQ,VM::VM1,"Studies Containing Other Referenced Instances Sequence","StudiesContainingOtherReferencedInstancesSequence",false }, {0x0008,0x1250,VR::SQ,VM::VM1,"Related Series Sequence","RelatedSeriesSequence",false }, {0x0008,0x2110,VR::CS,VM::VM1,"Lossy Image Compression (Retired)","LossyImageCompressionRetired",true }, {0x0008,0x2111,VR::ST,VM::VM1,"Derivation Description","DerivationDescription",false }, {0x0008,0x2112,VR::SQ,VM::VM1,"Source Image Sequence","SourceImageSequence",false }, {0x0008,0x2120,VR::SH,VM::VM1,"Stage Name","StageName",false }, {0x0008,0x2122,VR::IS,VM::VM1,"Stage Number","StageNumber",false }, {0x0008,0x2124,VR::IS,VM::VM1,"Number of Stages","NumberOfStages",false }, {0x0008,0x2127,VR::SH,VM::VM1,"View Name","ViewName",false }, {0x0008,0x2128,VR::IS,VM::VM1,"View Number","ViewNumber",false }, {0x0008,0x2129,VR::IS,VM::VM1,"Number of Event Timers","NumberOfEventTimers",false }, {0x0008,0x212a,VR::IS,VM::VM1,"Number of Views in Stage","NumberOfViewsInStage",false }, {0x0008,0x2130,VR::DS,VM::VM1_n,"Event Elapsed Time(s)","EventElapsedTimes",false }, {0x0008,0x2132,VR::LO,VM::VM1_n,"Event Timer Name(s)","EventTimerNames",false }, {0x0008,0x2133,VR::SQ,VM::VM1,"Event Timer Sequence","EventTimerSequence",false }, {0x0008,0x2134,VR::FD,VM::VM1,"Event Time Offset","EventTimeOffset",false }, {0x0008,0x2135,VR::SQ,VM::VM1,"Event Code Sequence","EventCodeSequence",false }, {0x0008,0x2142,VR::IS,VM::VM1,"Start Trim","StartTrim",false }, {0x0008,0x2143,VR::IS,VM::VM1,"Stop Trim","StopTrim",false }, {0x0008,0x2144,VR::IS,VM::VM1,"Recommended Display Frame Rate","RecommendedDisplayFrameRate",false }, {0x0008,0x2200,VR::CS,VM::VM1,"Transducer Position","TransducerPosition",true }, {0x0008,0x2204,VR::CS,VM::VM1,"Transducer Orientation","TransducerOrientation",true }, {0x0008,0x2208,VR::CS,VM::VM1,"Anatomic Structure","AnatomicStructure",true }, {0x0008,0x2218,VR::SQ,VM::VM1,"Anatomic Region Sequence","AnatomicRegionSequence",false }, {0x0008,0x2220,VR::SQ,VM::VM1,"Anatomic Region Modifier Sequence","AnatomicRegionModifierSequence",false }, {0x0008,0x2228,VR::SQ,VM::VM1,"Primary Anatomic Structure Sequence","PrimaryAnatomicStructureSequence",false }, {0x0008,0x2229,VR::SQ,VM::VM1,"Anatomic Structure, Space or Region Sequence","AnatomicStructureSpaceOrRegionSequence",false }, {0x0008,0x2230,VR::SQ,VM::VM1,"Primary Anatomic Structure Modifier Sequence","PrimaryAnatomicStructureModifierSequence",false }, {0x0008,0x2240,VR::SQ,VM::VM1,"Transducer Position Sequence","TransducerPositionSequence",true }, {0x0008,0x2242,VR::SQ,VM::VM1,"Transducer Position Modifier Sequence","TransducerPositionModifierSequence",true }, {0x0008,0x2244,VR::SQ,VM::VM1,"Transducer Orientation Sequence","TransducerOrientationSequence",true }, {0x0008,0x2246,VR::SQ,VM::VM1,"Transducer Orientation Modifier Sequence","TransducerOrientationModifierSequence",true }, {0x0008,0x2251,VR::SQ,VM::VM1,"Anatomic Structure Space Or Region Code Sequence (Trial)","AnatomicStructureSpaceOrRegionCodeSequenceTrial",true }, {0x0008,0x2253,VR::SQ,VM::VM1,"Anatomic Portal Of Entrance Code Sequence (Trial)","AnatomicPortalOfEntranceCodeSequenceTrial",true }, {0x0008,0x2255,VR::SQ,VM::VM1,"Anatomic Approach Direction Code Sequence (Trial)","AnatomicApproachDirectionCodeSequenceTrial",true }, {0x0008,0x2256,VR::ST,VM::VM1,"Anatomic Perspective Description (Trial)","AnatomicPerspectiveDescriptionTrial",true }, {0x0008,0x2257,VR::SQ,VM::VM1,"Anatomic Perspective Code Sequence (Trial)","AnatomicPerspectiveCodeSequenceTrial",true }, {0x0008,0x2258,VR::ST,VM::VM1,"Anatomic Location Of Examining Instrument Description (Trial)","AnatomicLocationOfExaminingInstrumentDescriptionTrial",true }, {0x0008,0x2259,VR::SQ,VM::VM1,"Anatomic Location Of Examining Instrument Code Sequence (Trial)","AnatomicLocationOfExaminingInstrumentCodeSequenceTrial",true }, {0x0008,0x225a,VR::SQ,VM::VM1,"Anatomic Structure Space Or Region Modifier Code Sequence (Trial)","AnatomicStructureSpaceOrRegionModifierCodeSequenceTrial",true }, {0x0008,0x225c,VR::SQ,VM::VM1,"On Axis Background Anatomic Structure Code Sequence (Trial)","OnAxisBackgroundAnatomicStructureCodeSequenceTrial",true }, {0x0008,0x3001,VR::SQ,VM::VM1,"Alternate Representation Sequence","AlternateRepresentationSequence",false }, {0x0008,0x3010,VR::UI,VM::VM1_n,"Irradiation Event UID","IrradiationEventUID",false }, {0x0008,0x3011,VR::SQ,VM::VM1,"Source Irradiation Event Sequence","SourceIrradiationEventSequence",false }, {0x0008,0x3012,VR::UI,VM::VM1,"Radiopharmaceutical Administration Event UID","RadiopharmaceuticalAdministrationEventUID",false }, {0x0008,0x4000,VR::LT,VM::VM1,"Identifying Comments","IdentifyingComments",true }, {0x0008,0x9007,VR::CS,VM::VM4,"Frame Type","FrameType",false }, {0x0008,0x9092,VR::SQ,VM::VM1,"Referenced Image Evidence Sequence","ReferencedImageEvidenceSequence",false }, {0x0008,0x9121,VR::SQ,VM::VM1,"Referenced Raw Data Sequence","ReferencedRawDataSequence",false }, {0x0008,0x9123,VR::UI,VM::VM1,"Creator-Version UID","CreatorVersionUID",false }, {0x0008,0x9124,VR::SQ,VM::VM1,"Derivation Image Sequence","DerivationImageSequence",false }, {0x0008,0x9154,VR::SQ,VM::VM1,"Source Image Evidence Sequence","SourceImageEvidenceSequence",false }, {0x0008,0x9205,VR::CS,VM::VM1,"Pixel Presentation","PixelPresentation",false }, {0x0008,0x9206,VR::CS,VM::VM1,"Volumetric Properties","VolumetricProperties",false }, {0x0008,0x9207,VR::CS,VM::VM1,"Volume Based Calculation Technique","VolumeBasedCalculationTechnique",false }, {0x0008,0x9208,VR::CS,VM::VM1,"Complex Image Component","ComplexImageComponent",false }, {0x0008,0x9209,VR::CS,VM::VM1,"Acquisition Contrast","AcquisitionContrast",false }, {0x0008,0x9215,VR::SQ,VM::VM1,"Derivation Code Sequence","DerivationCodeSequence",false }, {0x0008,0x9237,VR::SQ,VM::VM1,"Referenced Presentation State Sequence","ReferencedPresentationStateSequence",false }, {0x0008,0x9410,VR::SQ,VM::VM1,"Referenced Other Plane Sequence","ReferencedOtherPlaneSequence",false }, {0x0008,0x9458,VR::SQ,VM::VM1,"Frame Display Sequence","FrameDisplaySequence",false }, {0x0008,0x9459,VR::FL,VM::VM1,"Recommended Display Frame Rate in Float","RecommendedDisplayFrameRateInFloat",false }, {0x0008,0x9460,VR::CS,VM::VM1,"Skip Frame Range Flag","SkipFrameRangeFlag",false }, {0x0010,0x0010,VR::PN,VM::VM1,"Patient's Name","PatientName",false }, {0x0010,0x0020,VR::LO,VM::VM1,"Patient ID","PatientID",false }, {0x0010,0x0021,VR::LO,VM::VM1,"Issuer of Patient ID","IssuerOfPatientID",false }, {0x0010,0x0022,VR::CS,VM::VM1,"Type of Patient ID","TypeOfPatientID",false }, {0x0010,0x0024,VR::SQ,VM::VM1,"Issuer of Patient ID Qualifiers Sequence","IssuerOfPatientIDQualifiersSequence",false }, {0x0010,0x0026,VR::SQ,VM::VM1,"Source Patient Group Identification Sequence","SourcePatientGroupIdentificationSequence",false }, {0x0010,0x0027,VR::SQ,VM::VM1,"Group of Patients Identification Sequence","GroupOfPatientsIdentificationSequence",false }, {0x0010,0x0028,VR::US,VM::VM3,"Subject Relative Position in Image","SubjectRelativePositionInImage",false }, {0x0010,0x0030,VR::DA,VM::VM1,"Patient's Birth Date","PatientBirthDate",false }, {0x0010,0x0032,VR::TM,VM::VM1,"Patient's Birth Time","PatientBirthTime",false }, {0x0010,0x0033,VR::LO,VM::VM1,"Patient's Birth Date in Alternative Calendar","PatientBirthDateInAlternativeCalendar",false }, {0x0010,0x0034,VR::LO,VM::VM1,"Patient's Death Date in Alternative Calendar","PatientDeathDateInAlternativeCalendar",false }, {0x0010,0x0035,VR::CS,VM::VM1,"Patient's Alternative Calendar","PatientAlternativeCalendar",false }, {0x0010,0x0040,VR::CS,VM::VM1,"Patient's Sex","PatientSex",false }, {0x0010,0x0050,VR::SQ,VM::VM1,"Patient's Insurance Plan Code Sequence","PatientInsurancePlanCodeSequence",false }, {0x0010,0x0101,VR::SQ,VM::VM1,"Patient's Primary Language Code Sequence","PatientPrimaryLanguageCodeSequence",false }, {0x0010,0x0102,VR::SQ,VM::VM1,"Patient's Primary Language Modifier Code Sequence","PatientPrimaryLanguageModifierCodeSequence",false }, {0x0010,0x0200,VR::CS,VM::VM1,"Quality Control Subject","QualityControlSubject",false }, {0x0010,0x0201,VR::SQ,VM::VM1,"Quality Control Subject Type Code Sequence","QualityControlSubjectTypeCodeSequence",false }, {0x0010,0x0212,VR::UC,VM::VM1,"Strain Description","StrainDescription",false }, {0x0010,0x0213,VR::LO,VM::VM1,"Strain Nomenclature","StrainNomenclature",false }, {0x0010,0x0214,VR::LO,VM::VM1,"Strain Stock Number","StrainStockNumber",false }, {0x0010,0x0215,VR::SQ,VM::VM1,"Strain Source Registry Code Sequence","StrainSourceRegistryCodeSequence",false }, {0x0010,0x0216,VR::SQ,VM::VM1,"Strain Stock Sequence","StrainStockSequence",false }, {0x0010,0x0217,VR::LO,VM::VM1,"Strain Source","StrainSource",false }, {0x0010,0x0218,VR::UT,VM::VM1,"Strain Additional Information","StrainAdditionalInformation",false }, {0x0010,0x0219,VR::SQ,VM::VM1,"Strain Code Sequence","StrainCodeSequence",false }, {0x0010,0x1000,VR::LO,VM::VM1_n,"Other Patient IDs","OtherPatientIDs",false }, {0x0010,0x1001,VR::PN,VM::VM1_n,"Other Patient Names","OtherPatientNames",false }, {0x0010,0x1002,VR::SQ,VM::VM1,"Other Patient IDs Sequence","OtherPatientIDsSequence",false }, {0x0010,0x1005,VR::PN,VM::VM1,"Patient's Birth Name","PatientBirthName",false }, {0x0010,0x1010,VR::AS,VM::VM1,"Patient's Age","PatientAge",false }, {0x0010,0x1020,VR::DS,VM::VM1,"Patient's Size","PatientSize",false }, {0x0010,0x1021,VR::SQ,VM::VM1,"Patient's Size Code Sequence","PatientSizeCodeSequence",false }, {0x0010,0x1022,VR::DS,VM::VM1,"Patient's Body Mass Index","PatientBodyMassIndex",false }, {0x0010,0x1023,VR::DS,VM::VM1,"Measured AP Dimension","MeasuredAPDimension",false }, {0x0010,0x1024,VR::DS,VM::VM1,"Measured Lateral Dimension","MeasuredLateralDimension",false }, {0x0010,0x1030,VR::DS,VM::VM1,"Patient's Weight","PatientWeight",false }, {0x0010,0x1040,VR::LO,VM::VM1,"Patient's Address","PatientAddress",false }, {0x0010,0x1050,VR::LO,VM::VM1_n,"Insurance Plan Identification","InsurancePlanIdentification",true }, {0x0010,0x1060,VR::PN,VM::VM1,"Patient's Mother's Birth Name","PatientMotherBirthName",false }, {0x0010,0x1080,VR::LO,VM::VM1,"Military Rank","MilitaryRank",false }, {0x0010,0x1081,VR::LO,VM::VM1,"Branch of Service","BranchOfService",false }, {0x0010,0x1090,VR::LO,VM::VM1,"Medical Record Locator","MedicalRecordLocator",false }, {0x0010,0x1100,VR::SQ,VM::VM1,"Referenced Patient Photo Sequence","ReferencedPatientPhotoSequence",false }, {0x0010,0x2000,VR::LO,VM::VM1_n,"Medical Alerts","MedicalAlerts",false }, {0x0010,0x2110,VR::LO,VM::VM1_n,"Allergies","Allergies",false }, {0x0010,0x2150,VR::LO,VM::VM1,"Country of Residence","CountryOfResidence",false }, {0x0010,0x2152,VR::LO,VM::VM1,"Region of Residence","RegionOfResidence",false }, {0x0010,0x2154,VR::SH,VM::VM1_n,"Patient's Telephone Numbers","PatientTelephoneNumbers",false }, {0x0010,0x2155,VR::LT,VM::VM1,"Patient's Telecom Information","PatientTelecomInformation",false }, {0x0010,0x2160,VR::SH,VM::VM1,"Ethnic Group","EthnicGroup",false }, {0x0010,0x2180,VR::SH,VM::VM1,"Occupation","Occupation",false }, {0x0010,0x21a0,VR::CS,VM::VM1,"Smoking Status","SmokingStatus",false }, {0x0010,0x21b0,VR::LT,VM::VM1,"Additional Patient History","AdditionalPatientHistory",false }, {0x0010,0x21c0,VR::US,VM::VM1,"Pregnancy Status","PregnancyStatus",false }, {0x0010,0x21d0,VR::DA,VM::VM1,"Last Menstrual Date","LastMenstrualDate",false }, {0x0010,0x21f0,VR::LO,VM::VM1,"Patient's Religious Preference","PatientReligiousPreference",false }, {0x0010,0x2201,VR::LO,VM::VM1,"Patient Species Description","PatientSpeciesDescription",false }, {0x0010,0x2202,VR::SQ,VM::VM1,"Patient Species Code Sequence","PatientSpeciesCodeSequence",false }, {0x0010,0x2203,VR::CS,VM::VM1,"Patient's Sex Neutered","PatientSexNeutered",false }, {0x0010,0x2210,VR::CS,VM::VM1,"Anatomical Orientation Type","AnatomicalOrientationType",false }, {0x0010,0x2292,VR::LO,VM::VM1,"Patient Breed Description","PatientBreedDescription",false }, {0x0010,0x2293,VR::SQ,VM::VM1,"Patient Breed Code Sequence","PatientBreedCodeSequence",false }, {0x0010,0x2294,VR::SQ,VM::VM1,"Breed Registration Sequence","BreedRegistrationSequence",false }, {0x0010,0x2295,VR::LO,VM::VM1,"Breed Registration Number","BreedRegistrationNumber",false }, {0x0010,0x2296,VR::SQ,VM::VM1,"Breed Registry Code Sequence","BreedRegistryCodeSequence",false }, {0x0010,0x2297,VR::PN,VM::VM1,"Responsible Person","ResponsiblePerson",false }, {0x0010,0x2298,VR::CS,VM::VM1,"Responsible Person Role","ResponsiblePersonRole",false }, {0x0010,0x2299,VR::LO,VM::VM1,"Responsible Organization","ResponsibleOrganization",false }, {0x0010,0x4000,VR::LT,VM::VM1,"Patient Comments","PatientComments",false }, {0x0010,0x9431,VR::FL,VM::VM1,"Examined Body Thickness","ExaminedBodyThickness",false }, {0x0012,0x0010,VR::LO,VM::VM1,"Clinical Trial Sponsor Name","ClinicalTrialSponsorName",false }, {0x0012,0x0020,VR::LO,VM::VM1,"Clinical Trial Protocol ID","ClinicalTrialProtocolID",false }, {0x0012,0x0021,VR::LO,VM::VM1,"Clinical Trial Protocol Name","ClinicalTrialProtocolName",false }, {0x0012,0x0030,VR::LO,VM::VM1,"Clinical Trial Site ID","ClinicalTrialSiteID",false }, {0x0012,0x0031,VR::LO,VM::VM1,"Clinical Trial Site Name","ClinicalTrialSiteName",false }, {0x0012,0x0040,VR::LO,VM::VM1,"Clinical Trial Subject ID","ClinicalTrialSubjectID",false }, {0x0012,0x0042,VR::LO,VM::VM1,"Clinical Trial Subject Reading ID","ClinicalTrialSubjectReadingID",false }, {0x0012,0x0050,VR::LO,VM::VM1,"Clinical Trial Time Point ID","ClinicalTrialTimePointID",false }, {0x0012,0x0051,VR::ST,VM::VM1,"Clinical Trial Time Point Description","ClinicalTrialTimePointDescription",false }, {0x0012,0x0060,VR::LO,VM::VM1,"Clinical Trial Coordinating Center Name","ClinicalTrialCoordinatingCenterName",false }, {0x0012,0x0062,VR::CS,VM::VM1,"Patient Identity Removed","PatientIdentityRemoved",false }, {0x0012,0x0063,VR::LO,VM::VM1_n,"De-identification Method","DeidentificationMethod",false }, {0x0012,0x0064,VR::SQ,VM::VM1,"De-identification Method Code Sequence","DeidentificationMethodCodeSequence",false }, {0x0012,0x0071,VR::LO,VM::VM1,"Clinical Trial Series ID","ClinicalTrialSeriesID",false }, {0x0012,0x0072,VR::LO,VM::VM1,"Clinical Trial Series Description","ClinicalTrialSeriesDescription",false }, {0x0012,0x0081,VR::LO,VM::VM1,"Clinical Trial Protocol Ethics Committee Name","ClinicalTrialProtocolEthicsCommitteeName",false }, {0x0012,0x0082,VR::LO,VM::VM1,"Clinical Trial Protocol Ethics Committee Approval Number","ClinicalTrialProtocolEthicsCommitteeApprovalNumber",false }, {0x0012,0x0083,VR::SQ,VM::VM1,"Consent for Clinical Trial Use Sequence","ConsentForClinicalTrialUseSequence",false }, {0x0012,0x0084,VR::CS,VM::VM1,"Distribution Type","DistributionType",false }, {0x0012,0x0085,VR::CS,VM::VM1,"Consent for Distribution Flag","ConsentForDistributionFlag",false }, {0x0012,0x0086,VR::DA,VM::VM1,"Ethics Committee Approval Effectiveness Start Date","EthicsCommitteeApprovalEffectivenessStartDate",false }, {0x0012,0x0087,VR::DA,VM::VM1,"Ethics Committee Approval Effectiveness End Date","EthicsCommitteeApprovalEffectivenessEndDate",false }, {0x0014,0x0023,VR::ST,VM::VM1,"CAD File Format","CADFileFormat",true }, {0x0014,0x0024,VR::ST,VM::VM1,"Component Reference System","ComponentReferenceSystem",true }, {0x0014,0x0025,VR::ST,VM::VM1,"Component Manufacturing Procedure","ComponentManufacturingProcedure",false }, {0x0014,0x0028,VR::ST,VM::VM1,"Component Manufacturer","ComponentManufacturer",false }, {0x0014,0x0030,VR::DS,VM::VM1_n,"Material Thickness","MaterialThickness",false }, {0x0014,0x0032,VR::DS,VM::VM1_n,"Material Pipe Diameter","MaterialPipeDiameter",false }, {0x0014,0x0034,VR::DS,VM::VM1_n,"Material Isolation Diameter","MaterialIsolationDiameter",false }, {0x0014,0x0042,VR::ST,VM::VM1,"Material Grade","MaterialGrade",false }, {0x0014,0x0044,VR::ST,VM::VM1,"Material Properties Description","MaterialPropertiesDescription",false }, {0x0014,0x0045,VR::ST,VM::VM1,"Material Properties File Format (Retired)","MaterialPropertiesFileFormatRetired",true }, {0x0014,0x0046,VR::LT,VM::VM1,"Material Notes","MaterialNotes",false }, {0x0014,0x0050,VR::CS,VM::VM1,"Component Shape","ComponentShape",false }, {0x0014,0x0052,VR::CS,VM::VM1,"Curvature Type","CurvatureType",false }, {0x0014,0x0054,VR::DS,VM::VM1,"Outer Diameter","OuterDiameter",false }, {0x0014,0x0056,VR::DS,VM::VM1,"Inner Diameter","InnerDiameter",false }, {0x0014,0x0100,VR::LO,VM::VM1_n,"Component Welder IDs","ComponentWelderIDs",false }, {0x0014,0x0101,VR::CS,VM::VM1,"Secondary Approval Status","SecondaryApprovalStatus",false }, {0x0014,0x0102,VR::DA,VM::VM1,"Secondary Review Date","SecondaryReviewDate",false }, {0x0014,0x0103,VR::TM,VM::VM1,"Secondary Review Time","SecondaryReviewTime",false }, {0x0014,0x0104,VR::PN,VM::VM1,"Secondary Reviewer Name","SecondaryReviewerName",false }, {0x0014,0x0105,VR::ST,VM::VM1,"Repair ID","RepairID",false }, {0x0014,0x0106,VR::SQ,VM::VM1,"Multiple Component Approval Sequence","MultipleComponentApprovalSequence",false }, {0x0014,0x0107,VR::CS,VM::VM1_n,"Other Approval Status","OtherApprovalStatus",false }, {0x0014,0x0108,VR::CS,VM::VM1_n,"Other Secondary Approval Status","OtherSecondaryApprovalStatus",false }, {0x0014,0x1010,VR::ST,VM::VM1,"Actual Environmental Conditions","ActualEnvironmentalConditions",false }, {0x0014,0x1020,VR::DA,VM::VM1,"Expiry Date","ExpiryDate",false }, {0x0014,0x1040,VR::ST,VM::VM1,"Environmental Conditions","EnvironmentalConditions",false }, {0x0014,0x2002,VR::SQ,VM::VM1,"Evaluator Sequence","EvaluatorSequence",false }, {0x0014,0x2004,VR::IS,VM::VM1,"Evaluator Number","EvaluatorNumber",false }, {0x0014,0x2006,VR::PN,VM::VM1,"Evaluator Name","EvaluatorName",false }, {0x0014,0x2008,VR::IS,VM::VM1,"Evaluation Attempt","EvaluationAttempt",false }, {0x0014,0x2012,VR::SQ,VM::VM1,"Indication Sequence","IndicationSequence",false }, {0x0014,0x2014,VR::IS,VM::VM1,"Indication Number","IndicationNumber",false }, {0x0014,0x2016,VR::SH,VM::VM1,"Indication Label","IndicationLabel",false }, {0x0014,0x2018,VR::ST,VM::VM1,"Indication Description","IndicationDescription",false }, {0x0014,0x201a,VR::CS,VM::VM1_n,"Indication Type","IndicationType",false }, {0x0014,0x201c,VR::CS,VM::VM1,"Indication Disposition","IndicationDisposition",false }, {0x0014,0x201e,VR::SQ,VM::VM1,"Indication ROI Sequence","IndicationROISequence",false }, {0x0014,0x2030,VR::SQ,VM::VM1,"Indication Physical Property Sequence","IndicationPhysicalPropertySequence",false }, {0x0014,0x2032,VR::SH,VM::VM1,"Property Label","PropertyLabel",false }, {0x0014,0x2202,VR::IS,VM::VM1,"Coordinate System Number of Axes","CoordinateSystemNumberOfAxes",false }, {0x0014,0x2204,VR::SQ,VM::VM1,"Coordinate System Axes Sequence","CoordinateSystemAxesSequence",false }, {0x0014,0x2206,VR::ST,VM::VM1,"Coordinate System Axis Description","CoordinateSystemAxisDescription",false }, {0x0014,0x2208,VR::CS,VM::VM1,"Coordinate System Data Set Mapping","CoordinateSystemDataSetMapping",false }, {0x0014,0x220a,VR::IS,VM::VM1,"Coordinate System Axis Number","CoordinateSystemAxisNumber",false }, {0x0014,0x220c,VR::CS,VM::VM1,"Coordinate System Axis Type","CoordinateSystemAxisType",false }, {0x0014,0x220e,VR::CS,VM::VM1,"Coordinate System Axis Units","CoordinateSystemAxisUnits",false }, {0x0014,0x2210,VR::OB,VM::VM1,"Coordinate System Axis Values","CoordinateSystemAxisValues",false }, {0x0014,0x2220,VR::SQ,VM::VM1,"Coordinate System Transform Sequence","CoordinateSystemTransformSequence",false }, {0x0014,0x2222,VR::ST,VM::VM1,"Transform Description","TransformDescription",false }, {0x0014,0x2224,VR::IS,VM::VM1,"Transform Number of Axes","TransformNumberOfAxes",false }, {0x0014,0x2226,VR::IS,VM::VM1_n,"Transform Order of Axes","TransformOrderOfAxes",false }, {0x0014,0x2228,VR::CS,VM::VM1,"Transformed Axis Units","TransformedAxisUnits",false }, {0x0014,0x222a,VR::DS,VM::VM1_n,"Coordinate System Transform Rotation and Scale Matrix","CoordinateSystemTransformRotationAndScaleMatrix",false }, {0x0014,0x222c,VR::DS,VM::VM1_n,"Coordinate System Transform Translation Matrix","CoordinateSystemTransformTranslationMatrix",false }, {0x0014,0x3011,VR::DS,VM::VM1,"Internal Detector Frame Time","InternalDetectorFrameTime",false }, {0x0014,0x3012,VR::DS,VM::VM1,"Number of Frames Integrated","NumberOfFramesIntegrated",false }, {0x0014,0x3020,VR::SQ,VM::VM1,"Detector Temperature Sequence","DetectorTemperatureSequence",false }, {0x0014,0x3022,VR::ST,VM::VM1,"Sensor Name","SensorName",false }, {0x0014,0x3024,VR::DS,VM::VM1,"Horizontal Offset of Sensor","HorizontalOffsetOfSensor",false }, {0x0014,0x3026,VR::DS,VM::VM1,"Vertical Offset of Sensor","VerticalOffsetOfSensor",false }, {0x0014,0x3028,VR::DS,VM::VM1,"Sensor Temperature","SensorTemperature",false }, {0x0014,0x3040,VR::SQ,VM::VM1,"Dark Current Sequence","DarkCurrentSequence",false }, {0x0014,0x3050,VR::OB_OW,VM::VM1,"Dark Current Counts","DarkCurrentCounts",false }, {0x0014,0x3060,VR::SQ,VM::VM1,"Gain Correction Reference Sequence","GainCorrectionReferenceSequence",false }, {0x0014,0x3070,VR::OB_OW,VM::VM1,"Air Counts","AirCounts",false }, {0x0014,0x3071,VR::DS,VM::VM1,"KV Used in Gain Calibration","KVUsedInGainCalibration",false }, {0x0014,0x3072,VR::DS,VM::VM1,"MA Used in Gain Calibration","MAUsedInGainCalibration",false }, {0x0014,0x3073,VR::DS,VM::VM1,"Number of Frames Used for Integration","NumberOfFramesUsedForIntegration",false }, {0x0014,0x3074,VR::LO,VM::VM1,"Filter Material Used in Gain Calibration","FilterMaterialUsedInGainCalibration",false }, {0x0014,0x3075,VR::DS,VM::VM1,"Filter Thickness Used in Gain Calibration","FilterThicknessUsedInGainCalibration",false }, {0x0014,0x3076,VR::DA,VM::VM1,"Date of Gain Calibration","DateOfGainCalibration",false }, {0x0014,0x3077,VR::TM,VM::VM1,"Time of Gain Calibration","TimeOfGainCalibration",false }, {0x0014,0x3080,VR::OB,VM::VM1,"Bad Pixel Image","BadPixelImage",false }, {0x0014,0x3099,VR::LT,VM::VM1,"Calibration Notes","CalibrationNotes",false }, {0x0014,0x4002,VR::SQ,VM::VM1,"Pulser Equipment Sequence","PulserEquipmentSequence",false }, {0x0014,0x4004,VR::CS,VM::VM1,"Pulser Type","PulserType",false }, {0x0014,0x4006,VR::LT,VM::VM1,"Pulser Notes","PulserNotes",false }, {0x0014,0x4008,VR::SQ,VM::VM1,"Receiver Equipment Sequence","ReceiverEquipmentSequence",false }, {0x0014,0x400a,VR::CS,VM::VM1,"Amplifier Type","AmplifierType",false }, {0x0014,0x400c,VR::LT,VM::VM1,"Receiver Notes","ReceiverNotes",false }, {0x0014,0x400e,VR::SQ,VM::VM1,"Pre-Amplifier Equipment Sequence","PreAmplifierEquipmentSequence",false }, {0x0014,0x400f,VR::LT,VM::VM1,"Pre-Amplifier Notes","PreAmplifierNotes",false }, {0x0014,0x4010,VR::SQ,VM::VM1,"Transmit Transducer Sequence","TransmitTransducerSequence",false }, {0x0014,0x4011,VR::SQ,VM::VM1,"Receive Transducer Sequence","ReceiveTransducerSequence",false }, {0x0014,0x4012,VR::US,VM::VM1,"Number of Elements","NumberOfElements",false }, {0x0014,0x4013,VR::CS,VM::VM1,"Element Shape","ElementShape",false }, {0x0014,0x4014,VR::DS,VM::VM1,"Element Dimension A","ElementDimensionA",false }, {0x0014,0x4015,VR::DS,VM::VM1,"Element Dimension B","ElementDimensionB",false }, {0x0014,0x4016,VR::DS,VM::VM1,"Element Pitch A","ElementPitchA",false }, {0x0014,0x4017,VR::DS,VM::VM1,"Measured Beam Dimension A","MeasuredBeamDimensionA",false }, {0x0014,0x4018,VR::DS,VM::VM1,"Measured Beam Dimension B","MeasuredBeamDimensionB",false }, {0x0014,0x4019,VR::DS,VM::VM1,"Location of Measured Beam Diameter","LocationOfMeasuredBeamDiameter",false }, {0x0014,0x401a,VR::DS,VM::VM1,"Nominal Frequency","NominalFrequency",false }, {0x0014,0x401b,VR::DS,VM::VM1,"Measured Center Frequency","MeasuredCenterFrequency",false }, {0x0014,0x401c,VR::DS,VM::VM1,"Measured Bandwidth","MeasuredBandwidth",false }, {0x0014,0x401d,VR::DS,VM::VM1,"Element Pitch B","ElementPitchB",false }, {0x0014,0x4020,VR::SQ,VM::VM1,"Pulser Settings Sequence","PulserSettingsSequence",false }, {0x0014,0x4022,VR::DS,VM::VM1,"Pulse Width","PulseWidth",false }, {0x0014,0x4024,VR::DS,VM::VM1,"Excitation Frequency","ExcitationFrequency",false }, {0x0014,0x4026,VR::CS,VM::VM1,"Modulation Type","ModulationType",false }, {0x0014,0x4028,VR::DS,VM::VM1,"Damping","Damping",false }, {0x0014,0x4030,VR::SQ,VM::VM1,"Receiver Settings Sequence","ReceiverSettingsSequence",false }, {0x0014,0x4031,VR::DS,VM::VM1,"Acquired Soundpath Length","AcquiredSoundpathLength",false }, {0x0014,0x4032,VR::CS,VM::VM1,"Acquisition Compression Type","AcquisitionCompressionType",false }, {0x0014,0x4033,VR::IS,VM::VM1,"Acquisition Sample Size","AcquisitionSampleSize",false }, {0x0014,0x4034,VR::DS,VM::VM1,"Rectifier Smoothing","RectifierSmoothing",false }, {0x0014,0x4035,VR::SQ,VM::VM1,"DAC Sequence","DACSequence",false }, {0x0014,0x4036,VR::CS,VM::VM1,"DAC Type","DACType",false }, {0x0014,0x4038,VR::DS,VM::VM1_n,"DAC Gain Points","DACGainPoints",false }, {0x0014,0x403a,VR::DS,VM::VM1_n,"DAC Time Points","DACTimePoints",false }, {0x0014,0x403c,VR::DS,VM::VM1_n,"DAC Amplitude","DACAmplitude",false }, {0x0014,0x4040,VR::SQ,VM::VM1,"Pre-Amplifier Settings Sequence","PreAmplifierSettingsSequence",false }, {0x0014,0x4050,VR::SQ,VM::VM1,"Transmit Transducer Settings Sequence","TransmitTransducerSettingsSequence",false }, {0x0014,0x4051,VR::SQ,VM::VM1,"Receive Transducer Settings Sequence","ReceiveTransducerSettingsSequence",false }, {0x0014,0x4052,VR::DS,VM::VM1,"Incident Angle","IncidentAngle",false }, {0x0014,0x4054,VR::ST,VM::VM1,"Coupling Technique","CouplingTechnique",false }, {0x0014,0x4056,VR::ST,VM::VM1,"Coupling Medium","CouplingMedium",false }, {0x0014,0x4057,VR::DS,VM::VM1,"Coupling Velocity","CouplingVelocity",false }, {0x0014,0x4058,VR::DS,VM::VM1,"Probe Center Location X","ProbeCenterLocationX",false }, {0x0014,0x4059,VR::DS,VM::VM1,"Probe Center Location Z","ProbeCenterLocationZ",false }, {0x0014,0x405a,VR::DS,VM::VM1,"Sound Path Length","SoundPathLength",false }, {0x0014,0x405c,VR::ST,VM::VM1,"Delay Law Identifier","DelayLawIdentifier",false }, {0x0014,0x4060,VR::SQ,VM::VM1,"Gate Settings Sequence","GateSettingsSequence",false }, {0x0014,0x4062,VR::DS,VM::VM1,"Gate Threshold","GateThreshold",false }, {0x0014,0x4064,VR::DS,VM::VM1,"Velocity of Sound","VelocityOfSound",false }, {0x0014,0x4070,VR::SQ,VM::VM1,"Calibration Settings Sequence","CalibrationSettingsSequence",false }, {0x0014,0x4072,VR::ST,VM::VM1,"Calibration Procedure","CalibrationProcedure",false }, {0x0014,0x4074,VR::SH,VM::VM1,"Procedure Version","ProcedureVersion",false }, {0x0014,0x4076,VR::DA,VM::VM1,"Procedure Creation Date","ProcedureCreationDate",false }, {0x0014,0x4078,VR::DA,VM::VM1,"Procedure Expiration Date","ProcedureExpirationDate",false }, {0x0014,0x407a,VR::DA,VM::VM1,"Procedure Last Modified Date","ProcedureLastModifiedDate",false }, {0x0014,0x407c,VR::TM,VM::VM1_n,"Calibration Time","CalibrationTime",false }, {0x0014,0x407e,VR::DA,VM::VM1_n,"Calibration Date","CalibrationDate",false }, {0x0014,0x4080,VR::SQ,VM::VM1,"Probe Drive Equipment Sequence","ProbeDriveEquipmentSequence",false }, {0x0014,0x4081,VR::CS,VM::VM1,"Drive Type","DriveType",false }, {0x0014,0x4082,VR::LT,VM::VM1,"Probe Drive Notes","ProbeDriveNotes",false }, {0x0014,0x4083,VR::SQ,VM::VM1,"Drive Probe Sequence","DriveProbeSequence",false }, {0x0014,0x4084,VR::DS,VM::VM1,"Probe Inductance","ProbeInductance",false }, {0x0014,0x4085,VR::DS,VM::VM1,"Probe Resistance","ProbeResistance",false }, {0x0014,0x4086,VR::SQ,VM::VM1,"Receive Probe Sequence","ReceiveProbeSequence",false }, {0x0014,0x4087,VR::SQ,VM::VM1,"Probe Drive Settings Sequence","ProbeDriveSettingsSequence",false }, {0x0014,0x4088,VR::DS,VM::VM1,"Bridge Resistors","BridgeResistors",false }, {0x0014,0x4089,VR::DS,VM::VM1,"Probe Orientation Angle","ProbeOrientationAngle",false }, {0x0014,0x408b,VR::DS,VM::VM1,"User Selected Gain Y","UserSelectedGainY",false }, {0x0014,0x408c,VR::DS,VM::VM1,"User Selected Phase","UserSelectedPhase",false }, {0x0014,0x408d,VR::DS,VM::VM1,"User Selected Offset X","UserSelectedOffsetX",false }, {0x0014,0x408e,VR::DS,VM::VM1,"User Selected Offset Y","UserSelectedOffsetY",false }, {0x0014,0x4091,VR::SQ,VM::VM1,"Channel Settings Sequence","ChannelSettingsSequence",false }, {0x0014,0x4092,VR::DS,VM::VM1,"Channel Threshold","ChannelThreshold",false }, {0x0014,0x409a,VR::SQ,VM::VM1,"Scanner Settings Sequence","ScannerSettingsSequence",false }, {0x0014,0x409b,VR::ST,VM::VM1,"Scan Procedure","ScanProcedure",false }, {0x0014,0x409c,VR::DS,VM::VM1,"Translation Rate X","TranslationRateX",false }, {0x0014,0x409d,VR::DS,VM::VM1,"Translation Rate Y","TranslationRateY",false }, {0x0014,0x409f,VR::DS,VM::VM1,"Channel Overlap","ChannelOverlap",false }, {0x0014,0x40a0,VR::LO,VM::VM1,"Image Quality Indicator Type","ImageQualityIndicatorType",false }, {0x0014,0x40a1,VR::LO,VM::VM1,"Image Quality Indicator Material","ImageQualityIndicatorMaterial",false }, {0x0014,0x40a2,VR::LO,VM::VM1,"Image Quality Indicator Size","ImageQualityIndicatorSize",false }, {0x0014,0x5002,VR::IS,VM::VM1,"LINAC Energy","LINACEnergy",false }, {0x0014,0x5004,VR::IS,VM::VM1,"LINAC Output","LINACOutput",false }, {0x0014,0x5100,VR::US,VM::VM1,"Active Aperture","ActiveAperture",false }, {0x0014,0x5101,VR::DS,VM::VM1,"Total Aperture","TotalAperture",false }, {0x0014,0x5102,VR::DS,VM::VM1,"Aperture Elevation","ApertureElevation",false }, {0x0014,0x5103,VR::DS,VM::VM1,"Main Lobe Angle","MainLobeAngle",false }, {0x0014,0x5104,VR::DS,VM::VM1,"Main Roof Angle","MainRoofAngle",false }, {0x0014,0x5105,VR::CS,VM::VM1,"Connector Type","ConnectorType",false }, {0x0014,0x5106,VR::SH,VM::VM1,"Wedge Model Number","WedgeModelNumber",false }, {0x0014,0x5107,VR::DS,VM::VM1,"Wedge Angle Float","WedgeAngleFloat",false }, {0x0014,0x5108,VR::DS,VM::VM1,"Wedge Roof Angle","WedgeRoofAngle",false }, {0x0014,0x5109,VR::CS,VM::VM1,"Wedge Element 1 Position","WedgeElement1Position",false }, {0x0014,0x510a,VR::DS,VM::VM1,"Wedge Material Velocity","WedgeMaterialVelocity",false }, {0x0014,0x510b,VR::SH,VM::VM1,"Wedge Material","WedgeMaterial",false }, {0x0014,0x510c,VR::DS,VM::VM1,"Wedge Offset Z","WedgeOffsetZ",false }, {0x0014,0x510d,VR::DS,VM::VM1,"Wedge Origin Offset X","WedgeOriginOffsetX",false }, {0x0014,0x510e,VR::DS,VM::VM1,"Wedge Time Delay","WedgeTimeDelay",false }, {0x0014,0x510f,VR::SH,VM::VM1,"Wedge Name","WedgeName",false }, {0x0014,0x5110,VR::SH,VM::VM1,"Wedge Manufacturer Name","WedgeManufacturerName",false }, {0x0014,0x5111,VR::LO,VM::VM1,"Wedge Description","WedgeDescription",false }, {0x0014,0x5112,VR::DS,VM::VM1,"Nominal Beam Angle","NominalBeamAngle",false }, {0x0014,0x5113,VR::DS,VM::VM1,"Wedge Offset X","WedgeOffsetX",false }, {0x0014,0x5114,VR::DS,VM::VM1,"Wedge Offset Y","WedgeOffsetY",false }, {0x0014,0x5115,VR::DS,VM::VM1,"Wedge Total Length","WedgeTotalLength",false }, {0x0014,0x5116,VR::DS,VM::VM1,"Wedge In Contact Length","WedgeInContactLength",false }, {0x0014,0x5117,VR::DS,VM::VM1,"Wedge Front Gap","WedgeFrontGap",false }, {0x0014,0x5118,VR::DS,VM::VM1,"Wedge Total Height","WedgeTotalHeight",false }, {0x0014,0x5119,VR::DS,VM::VM1,"Wedge Front Height","WedgeFrontHeight",false }, {0x0014,0x511a,VR::DS,VM::VM1,"Wedge Rear Height","WedgeRearHeight",false }, {0x0014,0x511b,VR::DS,VM::VM1,"Wedge Total Width","WedgeTotalWidth",false }, {0x0014,0x511c,VR::DS,VM::VM1,"Wedge In Contact Width","WedgeInContactWidth",false }, {0x0014,0x511d,VR::DS,VM::VM1,"Wedge Chamfer Height","WedgeChamferHeight",false }, {0x0014,0x511e,VR::CS,VM::VM1,"Wedge Curve","WedgeCurve",false }, {0x0014,0x511f,VR::DS,VM::VM1,"Radius Along the Wedge","RadiusAlongWedge",false }, {0x0018,0x0010,VR::LO,VM::VM1,"Contrast/Bolus Agent","ContrastBolusAgent",false }, {0x0018,0x0012,VR::SQ,VM::VM1,"Contrast/Bolus Agent Sequence","ContrastBolusAgentSequence",false }, {0x0018,0x0013,VR::FL,VM::VM1,"Contrast/Bolus T1 Relaxivity","ContrastBolusT1Relaxivity",false }, {0x0018,0x0014,VR::SQ,VM::VM1,"Contrast/Bolus Administration Route Sequence","ContrastBolusAdministrationRouteSequence",false }, {0x0018,0x0015,VR::CS,VM::VM1,"Body Part Examined","BodyPartExamined",false }, {0x0018,0x0020,VR::CS,VM::VM1_n,"Scanning Sequence","ScanningSequence",false }, {0x0018,0x0021,VR::CS,VM::VM1_n,"Sequence Variant","SequenceVariant",false }, {0x0018,0x0022,VR::CS,VM::VM1_n,"Scan Options","ScanOptions",false }, {0x0018,0x0023,VR::CS,VM::VM1,"MR Acquisition Type","MRAcquisitionType",false }, {0x0018,0x0024,VR::SH,VM::VM1,"Sequence Name","SequenceName",false }, {0x0018,0x0025,VR::CS,VM::VM1,"Angio Flag","AngioFlag",false }, {0x0018,0x0026,VR::SQ,VM::VM1,"Intervention Drug Information Sequence","InterventionDrugInformationSequence",false }, {0x0018,0x0027,VR::TM,VM::VM1,"Intervention Drug Stop Time","InterventionDrugStopTime",false }, {0x0018,0x0028,VR::DS,VM::VM1,"Intervention Drug Dose","InterventionDrugDose",false }, {0x0018,0x0029,VR::SQ,VM::VM1,"Intervention Drug Code Sequence","InterventionDrugCodeSequence",false }, {0x0018,0x002a,VR::SQ,VM::VM1,"Additional Drug Sequence","AdditionalDrugSequence",false }, {0x0018,0x0030,VR::LO,VM::VM1_n,"Radionuclide","Radionuclide",true }, {0x0018,0x0031,VR::LO,VM::VM1,"Radiopharmaceutical","Radiopharmaceutical",false }, {0x0018,0x0032,VR::DS,VM::VM1,"Energy Window Centerline","EnergyWindowCenterline",true }, {0x0018,0x0033,VR::DS,VM::VM1_n,"Energy Window Total Width","EnergyWindowTotalWidth",true }, {0x0018,0x0034,VR::LO,VM::VM1,"Intervention Drug Name","InterventionDrugName",false }, {0x0018,0x0035,VR::TM,VM::VM1,"Intervention Drug Start Time","InterventionDrugStartTime",false }, {0x0018,0x0036,VR::SQ,VM::VM1,"Intervention Sequence","InterventionSequence",false }, {0x0018,0x0037,VR::CS,VM::VM1,"Therapy Type","TherapyType",true }, {0x0018,0x0038,VR::CS,VM::VM1,"Intervention Status","InterventionStatus",false }, {0x0018,0x0039,VR::CS,VM::VM1,"Therapy Description","TherapyDescription",true }, {0x0018,0x003a,VR::ST,VM::VM1,"Intervention Description","InterventionDescription",false }, {0x0018,0x0040,VR::IS,VM::VM1,"Cine Rate","CineRate",false }, {0x0018,0x0042,VR::CS,VM::VM1,"Initial Cine Run State","InitialCineRunState",false }, {0x0018,0x0050,VR::DS,VM::VM1,"Slice Thickness","SliceThickness",false }, {0x0018,0x0060,VR::DS,VM::VM1,"KVP","KVP",false }, {0x0018,0x0061,VR::DS,VM::VM1,"","",true }, {0x0018,0x0070,VR::IS,VM::VM1,"Counts Accumulated","CountsAccumulated",false }, {0x0018,0x0071,VR::CS,VM::VM1,"Acquisition Termination Condition","AcquisitionTerminationCondition",false }, {0x0018,0x0072,VR::DS,VM::VM1,"Effective Duration","EffectiveDuration",false }, {0x0018,0x0073,VR::CS,VM::VM1,"Acquisition Start Condition","AcquisitionStartCondition",false }, {0x0018,0x0074,VR::IS,VM::VM1,"Acquisition Start Condition Data","AcquisitionStartConditionData",false }, {0x0018,0x0075,VR::IS,VM::VM1,"Acquisition Termination Condition Data","AcquisitionTerminationConditionData",false }, {0x0018,0x0080,VR::DS,VM::VM1,"Repetition Time","RepetitionTime",false }, {0x0018,0x0081,VR::DS,VM::VM1,"Echo Time","EchoTime",false }, {0x0018,0x0082,VR::DS,VM::VM1,"Inversion Time","InversionTime",false }, {0x0018,0x0083,VR::DS,VM::VM1,"Number of Averages","NumberOfAverages",false }, {0x0018,0x0084,VR::DS,VM::VM1,"Imaging Frequency","ImagingFrequency",false }, {0x0018,0x0085,VR::SH,VM::VM1,"Imaged Nucleus","ImagedNucleus",false }, {0x0018,0x0086,VR::IS,VM::VM1_n,"Echo Number(s)","EchoNumbers",false }, {0x0018,0x0087,VR::DS,VM::VM1,"Magnetic Field Strength","MagneticFieldStrength",false }, {0x0018,0x0088,VR::DS,VM::VM1,"Spacing Between Slices","SpacingBetweenSlices",false }, {0x0018,0x0089,VR::IS,VM::VM1,"Number of Phase Encoding Steps","NumberOfPhaseEncodingSteps",false }, {0x0018,0x0090,VR::DS,VM::VM1,"Data Collection Diameter","DataCollectionDiameter",false }, {0x0018,0x0091,VR::IS,VM::VM1,"Echo Train Length","EchoTrainLength",false }, {0x0018,0x0093,VR::DS,VM::VM1,"Percent Sampling","PercentSampling",false }, {0x0018,0x0094,VR::DS,VM::VM1,"Percent Phase Field of View","PercentPhaseFieldOfView",false }, {0x0018,0x0095,VR::DS,VM::VM1,"Pixel Bandwidth","PixelBandwidth",false }, {0x0018,0x1000,VR::LO,VM::VM1,"Device Serial Number","DeviceSerialNumber",false }, {0x0018,0x1002,VR::UI,VM::VM1,"Device UID","DeviceUID",false }, {0x0018,0x1003,VR::LO,VM::VM1,"Device ID","DeviceID",false }, {0x0018,0x1004,VR::LO,VM::VM1,"Plate ID","PlateID",false }, {0x0018,0x1005,VR::LO,VM::VM1,"Generator ID","GeneratorID",false }, {0x0018,0x1006,VR::LO,VM::VM1,"Grid ID","GridID",false }, {0x0018,0x1007,VR::LO,VM::VM1,"Cassette ID","CassetteID",false }, {0x0018,0x1008,VR::LO,VM::VM1,"Gantry ID","GantryID",false }, {0x0018,0x1009,VR::UT,VM::VM1,"Unique Device Identifier","UniqueDeviceIdentifier",false }, {0x0018,0x100a,VR::SQ,VM::VM1,"UDI Sequence","UDISequence",false }, {0x0018,0x1010,VR::LO,VM::VM1,"Secondary Capture Device ID","SecondaryCaptureDeviceID",false }, {0x0018,0x1011,VR::LO,VM::VM1,"Hardcopy Creation Device ID","HardcopyCreationDeviceID",true }, {0x0018,0x1012,VR::DA,VM::VM1,"Date of Secondary Capture","DateOfSecondaryCapture",false }, {0x0018,0x1014,VR::TM,VM::VM1,"Time of Secondary Capture","TimeOfSecondaryCapture",false }, {0x0018,0x1016,VR::LO,VM::VM1,"Secondary Capture Device Manufacturer","SecondaryCaptureDeviceManufacturer",false }, {0x0018,0x1017,VR::LO,VM::VM1,"Hardcopy Device Manufacturer","HardcopyDeviceManufacturer",true }, {0x0018,0x1018,VR::LO,VM::VM1,"Secondary Capture Device Manufacturer's Model Name","SecondaryCaptureDeviceManufacturerModelName",false }, {0x0018,0x1019,VR::LO,VM::VM1_n,"Secondary Capture Device Software Versions","SecondaryCaptureDeviceSoftwareVersions",false }, {0x0018,0x101a,VR::LO,VM::VM1_n,"Hardcopy Device Software Version","HardcopyDeviceSoftwareVersion",true }, {0x0018,0x101b,VR::LO,VM::VM1,"Hardcopy Device Manufacturer's Model Name","HardcopyDeviceManufacturerModelName",true }, {0x0018,0x1020,VR::LO,VM::VM1_n,"Software Version(s)","SoftwareVersions",false }, {0x0018,0x1022,VR::SH,VM::VM1,"Video Image Format Acquired","VideoImageFormatAcquired",false }, {0x0018,0x1023,VR::LO,VM::VM1,"Digital Image Format Acquired","DigitalImageFormatAcquired",false }, {0x0018,0x1030,VR::LO,VM::VM1,"Protocol Name","ProtocolName",false }, {0x0018,0x1040,VR::LO,VM::VM1,"Contrast/Bolus Route","ContrastBolusRoute",false }, {0x0018,0x1041,VR::DS,VM::VM1,"Contrast/Bolus Volume","ContrastBolusVolume",false }, {0x0018,0x1042,VR::TM,VM::VM1,"Contrast/Bolus Start Time","ContrastBolusStartTime",false }, {0x0018,0x1043,VR::TM,VM::VM1,"Contrast/Bolus Stop Time","ContrastBolusStopTime",false }, {0x0018,0x1044,VR::DS,VM::VM1,"Contrast/Bolus Total Dose","ContrastBolusTotalDose",false }, {0x0018,0x1045,VR::IS,VM::VM1,"Syringe Counts","SyringeCounts",false }, {0x0018,0x1046,VR::DS,VM::VM1_n,"Contrast Flow Rate","ContrastFlowRate",false }, {0x0018,0x1047,VR::DS,VM::VM1_n,"Contrast Flow Duration","ContrastFlowDuration",false }, {0x0018,0x1048,VR::CS,VM::VM1,"Contrast/Bolus Ingredient","ContrastBolusIngredient",false }, {0x0018,0x1049,VR::DS,VM::VM1,"Contrast/Bolus Ingredient Concentration","ContrastBolusIngredientConcentration",false }, {0x0018,0x1050,VR::DS,VM::VM1,"Spatial Resolution","SpatialResolution",false }, {0x0018,0x1060,VR::DS,VM::VM1,"Trigger Time","TriggerTime",false }, {0x0018,0x1061,VR::LO,VM::VM1,"Trigger Source or Type","TriggerSourceOrType",false }, {0x0018,0x1062,VR::IS,VM::VM1,"Nominal Interval","NominalInterval",false }, {0x0018,0x1063,VR::DS,VM::VM1,"Frame Time","FrameTime",false }, {0x0018,0x1064,VR::LO,VM::VM1,"Cardiac Framing Type","CardiacFramingType",false }, {0x0018,0x1065,VR::DS,VM::VM1_n,"Frame Time Vector","FrameTimeVector",false }, {0x0018,0x1066,VR::DS,VM::VM1,"Frame Delay","FrameDelay",false }, {0x0018,0x1067,VR::DS,VM::VM1,"Image Trigger Delay","ImageTriggerDelay",false }, {0x0018,0x1068,VR::DS,VM::VM1,"Multiplex Group Time Offset","MultiplexGroupTimeOffset",false }, {0x0018,0x1069,VR::DS,VM::VM1,"Trigger Time Offset","TriggerTimeOffset",false }, {0x0018,0x106a,VR::CS,VM::VM1,"Synchronization Trigger","SynchronizationTrigger",false }, {0x0018,0x106c,VR::US,VM::VM2,"Synchronization Channel","SynchronizationChannel",false }, {0x0018,0x106e,VR::UL,VM::VM1,"Trigger Sample Position","TriggerSamplePosition",false }, {0x0018,0x1070,VR::LO,VM::VM1,"Radiopharmaceutical Route","RadiopharmaceuticalRoute",false }, {0x0018,0x1071,VR::DS,VM::VM1,"Radiopharmaceutical Volume","RadiopharmaceuticalVolume",false }, {0x0018,0x1072,VR::TM,VM::VM1,"Radiopharmaceutical Start Time","RadiopharmaceuticalStartTime",false }, {0x0018,0x1073,VR::TM,VM::VM1,"Radiopharmaceutical Stop Time","RadiopharmaceuticalStopTime",false }, {0x0018,0x1074,VR::DS,VM::VM1,"Radionuclide Total Dose","RadionuclideTotalDose",false }, {0x0018,0x1075,VR::DS,VM::VM1,"Radionuclide Half Life","RadionuclideHalfLife",false }, {0x0018,0x1076,VR::DS,VM::VM1,"Radionuclide Positron Fraction","RadionuclidePositronFraction",false }, {0x0018,0x1077,VR::DS,VM::VM1,"Radiopharmaceutical Specific Activity","RadiopharmaceuticalSpecificActivity",false }, {0x0018,0x1078,VR::DT,VM::VM1,"Radiopharmaceutical Start DateTime","RadiopharmaceuticalStartDateTime",false }, {0x0018,0x1079,VR::DT,VM::VM1,"Radiopharmaceutical Stop DateTime","RadiopharmaceuticalStopDateTime",false }, {0x0018,0x1080,VR::CS,VM::VM1,"Beat Rejection Flag","BeatRejectionFlag",false }, {0x0018,0x1081,VR::IS,VM::VM1,"Low R-R Value","LowRRValue",false }, {0x0018,0x1082,VR::IS,VM::VM1,"High R-R Value","HighRRValue",false }, {0x0018,0x1083,VR::IS,VM::VM1,"Intervals Acquired","IntervalsAcquired",false }, {0x0018,0x1084,VR::IS,VM::VM1,"Intervals Rejected","IntervalsRejected",false }, {0x0018,0x1085,VR::LO,VM::VM1,"PVC Rejection","PVCRejection",false }, {0x0018,0x1086,VR::IS,VM::VM1,"Skip Beats","SkipBeats",false }, {0x0018,0x1088,VR::IS,VM::VM1,"Heart Rate","HeartRate",false }, {0x0018,0x1090,VR::IS,VM::VM1,"Cardiac Number of Images","CardiacNumberOfImages",false }, {0x0018,0x1094,VR::IS,VM::VM1,"Trigger Window","TriggerWindow",false }, {0x0018,0x1100,VR::DS,VM::VM1,"Reconstruction Diameter","ReconstructionDiameter",false }, {0x0018,0x1110,VR::DS,VM::VM1,"Distance Source to Detector","DistanceSourceToDetector",false }, {0x0018,0x1111,VR::DS,VM::VM1,"Distance Source to Patient","DistanceSourceToPatient",false }, {0x0018,0x1114,VR::DS,VM::VM1,"Estimated Radiographic Magnification Factor","EstimatedRadiographicMagnificationFactor",false }, {0x0018,0x1120,VR::DS,VM::VM1,"Gantry/Detector Tilt","GantryDetectorTilt",false }, {0x0018,0x1121,VR::DS,VM::VM1,"Gantry/Detector Slew","GantryDetectorSlew",false }, {0x0018,0x1130,VR::DS,VM::VM1,"Table Height","TableHeight",false }, {0x0018,0x1131,VR::DS,VM::VM1,"Table Traverse","TableTraverse",false }, {0x0018,0x1134,VR::CS,VM::VM1,"Table Motion","TableMotion",false }, {0x0018,0x1135,VR::DS,VM::VM1_n,"Table Vertical Increment","TableVerticalIncrement",false }, {0x0018,0x1136,VR::DS,VM::VM1_n,"Table Lateral Increment","TableLateralIncrement",false }, {0x0018,0x1137,VR::DS,VM::VM1_n,"Table Longitudinal Increment","TableLongitudinalIncrement",false }, {0x0018,0x1138,VR::DS,VM::VM1,"Table Angle","TableAngle",false }, {0x0018,0x113a,VR::CS,VM::VM1,"Table Type","TableType",false }, {0x0018,0x1140,VR::CS,VM::VM1,"Rotation Direction","RotationDirection",false }, {0x0018,0x1141,VR::DS,VM::VM1,"Angular Position","AngularPosition",true }, {0x0018,0x1142,VR::DS,VM::VM1_n,"Radial Position","RadialPosition",false }, {0x0018,0x1143,VR::DS,VM::VM1,"Scan Arc","ScanArc",false }, {0x0018,0x1144,VR::DS,VM::VM1,"Angular Step","AngularStep",false }, {0x0018,0x1145,VR::DS,VM::VM1,"Center of Rotation Offset","CenterOfRotationOffset",false }, {0x0018,0x1146,VR::DS,VM::VM1_n,"Rotation Offset","RotationOffset",true }, {0x0018,0x1147,VR::CS,VM::VM1,"Field of View Shape","FieldOfViewShape",false }, {0x0018,0x1149,VR::IS,VM::VM1_2,"Field of View Dimension(s)","FieldOfViewDimensions",false }, {0x0018,0x1150,VR::IS,VM::VM1,"Exposure Time","ExposureTime",false }, {0x0018,0x1151,VR::IS,VM::VM1,"X-Ray Tube Current","XRayTubeCurrent",false }, {0x0018,0x1152,VR::IS,VM::VM1,"Exposure","Exposure",false }, {0x0018,0x1153,VR::IS,VM::VM1,"Exposure in µAs","ExposureInuAs",false }, {0x0018,0x1154,VR::DS,VM::VM1,"Average Pulse Width","AveragePulseWidth",false }, {0x0018,0x1155,VR::CS,VM::VM1,"Radiation Setting","RadiationSetting",false }, {0x0018,0x1156,VR::CS,VM::VM1,"Rectification Type","RectificationType",false }, {0x0018,0x115a,VR::CS,VM::VM1,"Radiation Mode","RadiationMode",false }, {0x0018,0x115e,VR::DS,VM::VM1,"Image and Fluoroscopy Area Dose Product","ImageAndFluoroscopyAreaDoseProduct",false }, {0x0018,0x1160,VR::SH,VM::VM1,"Filter Type","FilterType",false }, {0x0018,0x1161,VR::LO,VM::VM1_n,"Type of Filters","TypeOfFilters",false }, {0x0018,0x1162,VR::DS,VM::VM1,"Intensifier Size","IntensifierSize",false }, {0x0018,0x1164,VR::DS,VM::VM2,"Imager Pixel Spacing","ImagerPixelSpacing",false }, {0x0018,0x1166,VR::CS,VM::VM1_n,"Grid","Grid",false }, {0x0018,0x1170,VR::IS,VM::VM1,"Generator Power","GeneratorPower",false }, {0x0018,0x1180,VR::SH,VM::VM1,"Collimator/grid Name","CollimatorGridName",false }, {0x0018,0x1181,VR::CS,VM::VM1,"Collimator Type","CollimatorType",false }, {0x0018,0x1182,VR::IS,VM::VM1_2,"Focal Distance","FocalDistance",false }, {0x0018,0x1183,VR::DS,VM::VM1_2,"X Focus Center","XFocusCenter",false }, {0x0018,0x1184,VR::DS,VM::VM1_2,"Y Focus Center","YFocusCenter",false }, {0x0018,0x1190,VR::DS,VM::VM1_n,"Focal Spot(s)","FocalSpots",false }, {0x0018,0x1191,VR::CS,VM::VM1,"Anode Target Material","AnodeTargetMaterial",false }, {0x0018,0x11a0,VR::DS,VM::VM1,"Body Part Thickness","BodyPartThickness",false }, {0x0018,0x11a2,VR::DS,VM::VM1,"Compression Force","CompressionForce",false }, {0x0018,0x11a4,VR::LO,VM::VM1,"Paddle Description","PaddleDescription",false }, {0x0018,0x1200,VR::DA,VM::VM1_n,"Date of Last Calibration","DateOfLastCalibration",false }, {0x0018,0x1201,VR::TM,VM::VM1_n,"Time of Last Calibration","TimeOfLastCalibration",false }, {0x0018,0x1202,VR::DT,VM::VM1,"DateTime of Last Calibration","DateTimeOfLastCalibration",false }, {0x0018,0x1210,VR::SH,VM::VM1_n,"Convolution Kernel","ConvolutionKernel",false }, {0x0018,0x1240,VR::IS,VM::VM1_n,"Upper/Lower Pixel Values","UpperLowerPixelValues",true }, {0x0018,0x1242,VR::IS,VM::VM1,"Actual Frame Duration","ActualFrameDuration",false }, {0x0018,0x1243,VR::IS,VM::VM1,"Count Rate","CountRate",false }, {0x0018,0x1244,VR::US,VM::VM1,"Preferred Playback Sequencing","PreferredPlaybackSequencing",false }, {0x0018,0x1250,VR::SH,VM::VM1,"Receive Coil Name","ReceiveCoilName",false }, {0x0018,0x1251,VR::SH,VM::VM1,"Transmit Coil Name","TransmitCoilName",false }, {0x0018,0x1260,VR::SH,VM::VM1,"Plate Type","PlateType",false }, {0x0018,0x1261,VR::LO,VM::VM1,"Phosphor Type","PhosphorType",false }, {0x0018,0x1271,VR::FD,VM::VM1,"Water Equivalent Diameter","WaterEquivalentDiameter",false }, {0x0018,0x1272,VR::SQ,VM::VM1,"Water Equivalent Diameter Calculation Method Code Sequence","WaterEquivalentDiameterCalculationMethodCodeSequence",false }, {0x0018,0x1300,VR::DS,VM::VM1,"Scan Velocity","ScanVelocity",false }, {0x0018,0x1301,VR::CS,VM::VM1_n,"Whole Body Technique","WholeBodyTechnique",false }, {0x0018,0x1302,VR::IS,VM::VM1,"Scan Length","ScanLength",false }, {0x0018,0x1310,VR::US,VM::VM4,"Acquisition Matrix","AcquisitionMatrix",false }, {0x0018,0x1312,VR::CS,VM::VM1,"In-plane Phase Encoding Direction","InPlanePhaseEncodingDirection",false }, {0x0018,0x1314,VR::DS,VM::VM1,"Flip Angle","FlipAngle",false }, {0x0018,0x1315,VR::CS,VM::VM1,"Variable Flip Angle Flag","VariableFlipAngleFlag",false }, {0x0018,0x1316,VR::DS,VM::VM1,"SAR","SAR",false }, {0x0018,0x1318,VR::DS,VM::VM1,"dB/dt","dBdt",false }, {0x0018,0x1320,VR::FL,VM::VM1,"B1rms","B1rms",false }, {0x0018,0x1400,VR::LO,VM::VM1,"Acquisition Device Processing Description","AcquisitionDeviceProcessingDescription",false }, {0x0018,0x1401,VR::LO,VM::VM1,"Acquisition Device Processing Code","AcquisitionDeviceProcessingCode",false }, {0x0018,0x1402,VR::CS,VM::VM1,"Cassette Orientation","CassetteOrientation",false }, {0x0018,0x1403,VR::CS,VM::VM1,"Cassette Size","CassetteSize",false }, {0x0018,0x1404,VR::US,VM::VM1,"Exposures on Plate","ExposuresOnPlate",false }, {0x0018,0x1405,VR::IS,VM::VM1,"Relative X-Ray Exposure","RelativeXRayExposure",false }, {0x0018,0x1411,VR::DS,VM::VM1,"Exposure Index","ExposureIndex",false }, {0x0018,0x1412,VR::DS,VM::VM1,"Target Exposure Index","TargetExposureIndex",false }, {0x0018,0x1413,VR::DS,VM::VM1,"Deviation Index","DeviationIndex",false }, {0x0018,0x1450,VR::DS,VM::VM1,"Column Angulation","ColumnAngulation",false }, {0x0018,0x1460,VR::DS,VM::VM1,"Tomo Layer Height","TomoLayerHeight",false }, {0x0018,0x1470,VR::DS,VM::VM1,"Tomo Angle","TomoAngle",false }, {0x0018,0x1480,VR::DS,VM::VM1,"Tomo Time","TomoTime",false }, {0x0018,0x1490,VR::CS,VM::VM1,"Tomo Type","TomoType",false }, {0x0018,0x1491,VR::CS,VM::VM1,"Tomo Class","TomoClass",false }, {0x0018,0x1495,VR::IS,VM::VM1,"Number of Tomosynthesis Source Images","NumberOfTomosynthesisSourceImages",false }, {0x0018,0x1500,VR::CS,VM::VM1,"Positioner Motion","PositionerMotion",false }, {0x0018,0x1508,VR::CS,VM::VM1,"Positioner Type","PositionerType",false }, {0x0018,0x1510,VR::DS,VM::VM1,"Positioner Primary Angle","PositionerPrimaryAngle",false }, {0x0018,0x1511,VR::DS,VM::VM1,"Positioner Secondary Angle","PositionerSecondaryAngle",false }, {0x0018,0x1520,VR::DS,VM::VM1_n,"Positioner Primary Angle Increment","PositionerPrimaryAngleIncrement",false }, {0x0018,0x1521,VR::DS,VM::VM1_n,"Positioner Secondary Angle Increment","PositionerSecondaryAngleIncrement",false }, {0x0018,0x1530,VR::DS,VM::VM1,"Detector Primary Angle","DetectorPrimaryAngle",false }, {0x0018,0x1531,VR::DS,VM::VM1,"Detector Secondary Angle","DetectorSecondaryAngle",false }, {0x0018,0x1600,VR::CS,VM::VM1_3,"Shutter Shape","ShutterShape",false }, {0x0018,0x1602,VR::IS,VM::VM1,"Shutter Left Vertical Edge","ShutterLeftVerticalEdge",false }, {0x0018,0x1604,VR::IS,VM::VM1,"Shutter Right Vertical Edge","ShutterRightVerticalEdge",false }, {0x0018,0x1606,VR::IS,VM::VM1,"Shutter Upper Horizontal Edge","ShutterUpperHorizontalEdge",false }, {0x0018,0x1608,VR::IS,VM::VM1,"Shutter Lower Horizontal Edge","ShutterLowerHorizontalEdge",false }, {0x0018,0x1610,VR::IS,VM::VM2,"Center of Circular Shutter","CenterOfCircularShutter",false }, {0x0018,0x1612,VR::IS,VM::VM1,"Radius of Circular Shutter","RadiusOfCircularShutter",false }, {0x0018,0x1620,VR::IS,VM::VM2_2n,"Vertices of the Polygonal Shutter","VerticesOfThePolygonalShutter",false }, {0x0018,0x1622,VR::US,VM::VM1,"Shutter Presentation Value","ShutterPresentationValue",false }, {0x0018,0x1623,VR::US,VM::VM1,"Shutter Overlay Group","ShutterOverlayGroup",false }, {0x0018,0x1624,VR::US,VM::VM3,"Shutter Presentation Color CIELab Value","ShutterPresentationColorCIELabValue",false }, {0x0018,0x1700,VR::CS,VM::VM1_3,"Collimator Shape","CollimatorShape",false }, {0x0018,0x1702,VR::IS,VM::VM1,"Collimator Left Vertical Edge","CollimatorLeftVerticalEdge",false }, {0x0018,0x1704,VR::IS,VM::VM1,"Collimator Right Vertical Edge","CollimatorRightVerticalEdge",false }, {0x0018,0x1706,VR::IS,VM::VM1,"Collimator Upper Horizontal Edge","CollimatorUpperHorizontalEdge",false }, {0x0018,0x1708,VR::IS,VM::VM1,"Collimator Lower Horizontal Edge","CollimatorLowerHorizontalEdge",false }, {0x0018,0x1710,VR::IS,VM::VM2,"Center of Circular Collimator","CenterOfCircularCollimator",false }, {0x0018,0x1712,VR::IS,VM::VM1,"Radius of Circular Collimator","RadiusOfCircularCollimator",false }, {0x0018,0x1720,VR::IS,VM::VM2_2n,"Vertices of the Polygonal Collimator","VerticesOfThePolygonalCollimator",false }, {0x0018,0x1800,VR::CS,VM::VM1,"Acquisition Time Synchronized","AcquisitionTimeSynchronized",false }, {0x0018,0x1801,VR::SH,VM::VM1,"Time Source","TimeSource",false }, {0x0018,0x1802,VR::CS,VM::VM1,"Time Distribution Protocol","TimeDistributionProtocol",false }, {0x0018,0x1803,VR::LO,VM::VM1,"NTP Source Address","NTPSourceAddress",false }, {0x0018,0x2001,VR::IS,VM::VM1_n,"Page Number Vector","PageNumberVector",false }, {0x0018,0x2002,VR::SH,VM::VM1_n,"Frame Label Vector","FrameLabelVector",false }, {0x0018,0x2003,VR::DS,VM::VM1_n,"Frame Primary Angle Vector","FramePrimaryAngleVector",false }, {0x0018,0x2004,VR::DS,VM::VM1_n,"Frame Secondary Angle Vector","FrameSecondaryAngleVector",false }, {0x0018,0x2005,VR::DS,VM::VM1_n,"Slice Location Vector","SliceLocationVector",false }, {0x0018,0x2006,VR::SH,VM::VM1_n,"Display Window Label Vector","DisplayWindowLabelVector",false }, {0x0018,0x2010,VR::DS,VM::VM2,"Nominal Scanned Pixel Spacing","NominalScannedPixelSpacing",false }, {0x0018,0x2020,VR::CS,VM::VM1,"Digitizing Device Transport Direction","DigitizingDeviceTransportDirection",false }, {0x0018,0x2030,VR::DS,VM::VM1,"Rotation of Scanned Film","RotationOfScannedFilm",false }, {0x0018,0x2041,VR::SQ,VM::VM1,"Biopsy Target Sequence","BiopsyTargetSequence",false }, {0x0018,0x2042,VR::UI,VM::VM1,"Target UID","TargetUID",false }, {0x0018,0x2043,VR::FL,VM::VM2,"Localizing Cursor Position","LocalizingCursorPosition",false }, {0x0018,0x2044,VR::FL,VM::VM3,"Calculated Target Position","CalculatedTargetPosition",false }, {0x0018,0x2045,VR::SH,VM::VM1,"Target Label","TargetLabel",false }, {0x0018,0x2046,VR::FL,VM::VM1,"Displayed Z Value","DisplayedZValue",false }, {0x0018,0x3100,VR::CS,VM::VM1,"IVUS Acquisition","IVUSAcquisition",false }, {0x0018,0x3101,VR::DS,VM::VM1,"IVUS Pullback Rate","IVUSPullbackRate",false }, {0x0018,0x3102,VR::DS,VM::VM1,"IVUS Gated Rate","IVUSGatedRate",false }, {0x0018,0x3103,VR::IS,VM::VM1,"IVUS Pullback Start Frame Number","IVUSPullbackStartFrameNumber",false }, {0x0018,0x3104,VR::IS,VM::VM1,"IVUS Pullback Stop Frame Number","IVUSPullbackStopFrameNumber",false }, {0x0018,0x3105,VR::IS,VM::VM1_n,"Lesion Number","LesionNumber",false }, {0x0018,0x4000,VR::LT,VM::VM1,"Acquisition Comments","AcquisitionComments",true }, {0x0018,0x5000,VR::SH,VM::VM1_n,"Output Power","OutputPower",false }, {0x0018,0x5010,VR::LO,VM::VM1_n,"Transducer Data","TransducerData",false }, {0x0018,0x5012,VR::DS,VM::VM1,"Focus Depth","FocusDepth",false }, {0x0018,0x5020,VR::LO,VM::VM1,"Processing Function","ProcessingFunction",false }, {0x0018,0x5021,VR::LO,VM::VM1,"Postprocessing Function","PostprocessingFunction",true }, {0x0018,0x5022,VR::DS,VM::VM1,"Mechanical Index","MechanicalIndex",false }, {0x0018,0x5024,VR::DS,VM::VM1,"Bone Thermal Index","BoneThermalIndex",false }, {0x0018,0x5026,VR::DS,VM::VM1,"Cranial Thermal Index","CranialThermalIndex",false }, {0x0018,0x5027,VR::DS,VM::VM1,"Soft Tissue Thermal Index","SoftTissueThermalIndex",false }, {0x0018,0x5028,VR::DS,VM::VM1,"Soft Tissue-focus Thermal Index","SoftTissueFocusThermalIndex",false }, {0x0018,0x5029,VR::DS,VM::VM1,"Soft Tissue-surface Thermal Index","SoftTissueSurfaceThermalIndex",false }, {0x0018,0x5030,VR::DS,VM::VM1,"Dynamic Range","DynamicRange",true }, {0x0018,0x5040,VR::DS,VM::VM1,"Total Gain","TotalGain",true }, {0x0018,0x5050,VR::IS,VM::VM1,"Depth of Scan Field","DepthOfScanField",false }, {0x0018,0x5100,VR::CS,VM::VM1,"Patient Position","PatientPosition",false }, {0x0018,0x5101,VR::CS,VM::VM1,"View Position","ViewPosition",false }, {0x0018,0x5104,VR::SQ,VM::VM1,"Projection Eponymous Name Code Sequence","ProjectionEponymousNameCodeSequence",false }, {0x0018,0x5210,VR::DS,VM::VM6,"Image Transformation Matrix","ImageTransformationMatrix",true }, {0x0018,0x5212,VR::DS,VM::VM3,"Image Translation Vector","ImageTranslationVector",true }, {0x0018,0x6000,VR::DS,VM::VM1,"Sensitivity","Sensitivity",false }, {0x0018,0x6011,VR::SQ,VM::VM1,"Sequence of Ultrasound Regions","SequenceOfUltrasoundRegions",false }, {0x0018,0x6012,VR::US,VM::VM1,"Region Spatial Format","RegionSpatialFormat",false }, {0x0018,0x6014,VR::US,VM::VM1,"Region Data Type","RegionDataType",false }, {0x0018,0x6016,VR::UL,VM::VM1,"Region Flags","RegionFlags",false }, {0x0018,0x6018,VR::UL,VM::VM1,"Region Location Min X0","RegionLocationMinX0",false }, {0x0018,0x601a,VR::UL,VM::VM1,"Region Location Min Y0","RegionLocationMinY0",false }, {0x0018,0x601c,VR::UL,VM::VM1,"Region Location Max X1","RegionLocationMaxX1",false }, {0x0018,0x601e,VR::UL,VM::VM1,"Region Location Max Y1","RegionLocationMaxY1",false }, {0x0018,0x6020,VR::SL,VM::VM1,"Reference Pixel X0","ReferencePixelX0",false }, {0x0018,0x6022,VR::SL,VM::VM1,"Reference Pixel Y0","ReferencePixelY0",false }, {0x0018,0x6024,VR::US,VM::VM1,"Physical Units X Direction","PhysicalUnitsXDirection",false }, {0x0018,0x6026,VR::US,VM::VM1,"Physical Units Y Direction","PhysicalUnitsYDirection",false }, {0x0018,0x6028,VR::FD,VM::VM1,"Reference Pixel Physical Value X","ReferencePixelPhysicalValueX",false }, {0x0018,0x602a,VR::FD,VM::VM1,"Reference Pixel Physical Value Y","ReferencePixelPhysicalValueY",false }, {0x0018,0x602c,VR::FD,VM::VM1,"Physical Delta X","PhysicalDeltaX",false }, {0x0018,0x602e,VR::FD,VM::VM1,"Physical Delta Y","PhysicalDeltaY",false }, {0x0018,0x6030,VR::UL,VM::VM1,"Transducer Frequency","TransducerFrequency",false }, {0x0018,0x6031,VR::CS,VM::VM1,"Transducer Type","TransducerType",false }, {0x0018,0x6032,VR::UL,VM::VM1,"Pulse Repetition Frequency","PulseRepetitionFrequency",false }, {0x0018,0x6034,VR::FD,VM::VM1,"Doppler Correction Angle","DopplerCorrectionAngle",false }, {0x0018,0x6036,VR::FD,VM::VM1,"Steering Angle","SteeringAngle",false }, {0x0018,0x6038,VR::UL,VM::VM1,"Doppler Sample Volume X Position (Retired)","DopplerSampleVolumeXPositionRetired",true }, {0x0018,0x6039,VR::SL,VM::VM1,"Doppler Sample Volume X Position","DopplerSampleVolumeXPosition",false }, {0x0018,0x603a,VR::UL,VM::VM1,"Doppler Sample Volume Y Position (Retired)","DopplerSampleVolumeYPositionRetired",true }, {0x0018,0x603b,VR::SL,VM::VM1,"Doppler Sample Volume Y Position","DopplerSampleVolumeYPosition",false }, {0x0018,0x603c,VR::UL,VM::VM1,"TM-Line Position X0 (Retired)","TMLinePositionX0Retired",true }, {0x0018,0x603d,VR::SL,VM::VM1,"TM-Line Position X0","TMLinePositionX0",false }, {0x0018,0x603e,VR::UL,VM::VM1,"TM-Line Position Y0 (Retired)","TMLinePositionY0Retired",true }, {0x0018,0x603f,VR::SL,VM::VM1,"TM-Line Position Y0","TMLinePositionY0",false }, {0x0018,0x6040,VR::UL,VM::VM1,"TM-Line Position X1 (Retired)","TMLinePositionX1Retired",true }, {0x0018,0x6041,VR::SL,VM::VM1,"TM-Line Position X1","TMLinePositionX1",false }, {0x0018,0x6042,VR::UL,VM::VM1,"TM-Line Position Y1 (Retired)","TMLinePositionY1Retired",true }, {0x0018,0x6043,VR::SL,VM::VM1,"TM-Line Position Y1","TMLinePositionY1",false }, {0x0018,0x6044,VR::US,VM::VM1,"Pixel Component Organization","PixelComponentOrganization",false }, {0x0018,0x6046,VR::UL,VM::VM1,"Pixel Component Mask","PixelComponentMask",false }, {0x0018,0x6048,VR::UL,VM::VM1,"Pixel Component Range Start","PixelComponentRangeStart",false }, {0x0018,0x604a,VR::UL,VM::VM1,"Pixel Component Range Stop","PixelComponentRangeStop",false }, {0x0018,0x604c,VR::US,VM::VM1,"Pixel Component Physical Units","PixelComponentPhysicalUnits",false }, {0x0018,0x604e,VR::US,VM::VM1,"Pixel Component Data Type","PixelComponentDataType",false }, {0x0018,0x6050,VR::UL,VM::VM1,"Number of Table Break Points","NumberOfTableBreakPoints",false }, {0x0018,0x6052,VR::UL,VM::VM1_n,"Table of X Break Points","TableOfXBreakPoints",false }, {0x0018,0x6054,VR::FD,VM::VM1_n,"Table of Y Break Points","TableOfYBreakPoints",false }, {0x0018,0x6056,VR::UL,VM::VM1,"Number of Table Entries","NumberOfTableEntries",false }, {0x0018,0x6058,VR::UL,VM::VM1_n,"Table of Pixel Values","TableOfPixelValues",false }, {0x0018,0x605a,VR::FL,VM::VM1_n,"Table of Parameter Values","TableOfParameterValues",false }, {0x0018,0x6060,VR::FL,VM::VM1_n,"R Wave Time Vector","RWaveTimeVector",false }, {0x0018,0x7000,VR::CS,VM::VM1,"Detector Conditions Nominal Flag","DetectorConditionsNominalFlag",false }, {0x0018,0x7001,VR::DS,VM::VM1,"Detector Temperature","DetectorTemperature",false }, {0x0018,0x7004,VR::CS,VM::VM1,"Detector Type","DetectorType",false }, {0x0018,0x7005,VR::CS,VM::VM1,"Detector Configuration","DetectorConfiguration",false }, {0x0018,0x7006,VR::LT,VM::VM1,"Detector Description","DetectorDescription",false }, {0x0018,0x7008,VR::LT,VM::VM1,"Detector Mode","DetectorMode",false }, {0x0018,0x700a,VR::SH,VM::VM1,"Detector ID","DetectorID",false }, {0x0018,0x700c,VR::DA,VM::VM1,"Date of Last Detector Calibration","DateOfLastDetectorCalibration",false }, {0x0018,0x700e,VR::TM,VM::VM1,"Time of Last Detector Calibration","TimeOfLastDetectorCalibration",false }, {0x0018,0x7010,VR::IS,VM::VM1,"Exposures on Detector Since Last Calibration","ExposuresOnDetectorSinceLastCalibration",false }, {0x0018,0x7011,VR::IS,VM::VM1,"Exposures on Detector Since Manufactured","ExposuresOnDetectorSinceManufactured",false }, {0x0018,0x7012,VR::DS,VM::VM1,"Detector Time Since Last Exposure","DetectorTimeSinceLastExposure",false }, {0x0018,0x7014,VR::DS,VM::VM1,"Detector Active Time","DetectorActiveTime",false }, {0x0018,0x7016,VR::DS,VM::VM1,"Detector Activation Offset From Exposure","DetectorActivationOffsetFromExposure",false }, {0x0018,0x701a,VR::DS,VM::VM2,"Detector Binning","DetectorBinning",false }, {0x0018,0x7020,VR::DS,VM::VM2,"Detector Element Physical Size","DetectorElementPhysicalSize",false }, {0x0018,0x7022,VR::DS,VM::VM2,"Detector Element Spacing","DetectorElementSpacing",false }, {0x0018,0x7024,VR::CS,VM::VM1,"Detector Active Shape","DetectorActiveShape",false }, {0x0018,0x7026,VR::DS,VM::VM1_2,"Detector Active Dimension(s)","DetectorActiveDimensions",false }, {0x0018,0x7028,VR::DS,VM::VM2,"Detector Active Origin","DetectorActiveOrigin",false }, {0x0018,0x702a,VR::LO,VM::VM1,"Detector Manufacturer Name","DetectorManufacturerName",false }, {0x0018,0x702b,VR::LO,VM::VM1,"Detector Manufacturer's Model Name","DetectorManufacturerModelName",false }, {0x0018,0x7030,VR::DS,VM::VM2,"Field of View Origin","FieldOfViewOrigin",false }, {0x0018,0x7032,VR::DS,VM::VM1,"Field of View Rotation","FieldOfViewRotation",false }, {0x0018,0x7034,VR::CS,VM::VM1,"Field of View Horizontal Flip","FieldOfViewHorizontalFlip",false }, {0x0018,0x7036,VR::FL,VM::VM2,"Pixel Data Area Origin Relative To FOV","PixelDataAreaOriginRelativeToFOV",false }, {0x0018,0x7038,VR::FL,VM::VM1,"Pixel Data Area Rotation Angle Relative To FOV","PixelDataAreaRotationAngleRelativeToFOV",false }, {0x0018,0x7040,VR::LT,VM::VM1,"Grid Absorbing Material","GridAbsorbingMaterial",false }, {0x0018,0x7041,VR::LT,VM::VM1,"Grid Spacing Material","GridSpacingMaterial",false }, {0x0018,0x7042,VR::DS,VM::VM1,"Grid Thickness","GridThickness",false }, {0x0018,0x7044,VR::DS,VM::VM1,"Grid Pitch","GridPitch",false }, {0x0018,0x7046,VR::IS,VM::VM2,"Grid Aspect Ratio","GridAspectRatio",false }, {0x0018,0x7048,VR::DS,VM::VM1,"Grid Period","GridPeriod",false }, {0x0018,0x704c,VR::DS,VM::VM1,"Grid Focal Distance","GridFocalDistance",false }, {0x0018,0x7050,VR::CS,VM::VM1_n,"Filter Material","FilterMaterial",false }, {0x0018,0x7052,VR::DS,VM::VM1_n,"Filter Thickness Minimum","FilterThicknessMinimum",false }, {0x0018,0x7054,VR::DS,VM::VM1_n,"Filter Thickness Maximum","FilterThicknessMaximum",false }, {0x0018,0x7056,VR::FL,VM::VM1_n,"Filter Beam Path Length Minimum","FilterBeamPathLengthMinimum",false }, {0x0018,0x7058,VR::FL,VM::VM1_n,"Filter Beam Path Length Maximum","FilterBeamPathLengthMaximum",false }, {0x0018,0x7060,VR::CS,VM::VM1,"Exposure Control Mode","ExposureControlMode",false }, {0x0018,0x7062,VR::LT,VM::VM1,"Exposure Control Mode Description","ExposureControlModeDescription",false }, {0x0018,0x7064,VR::CS,VM::VM1,"Exposure Status","ExposureStatus",false }, {0x0018,0x7065,VR::DS,VM::VM1,"Phototimer Setting","PhototimerSetting",false }, {0x0018,0x8150,VR::DS,VM::VM1,"Exposure Time in µS","ExposureTimeInuS",false }, {0x0018,0x8151,VR::DS,VM::VM1,"X-Ray Tube Current in µA","XRayTubeCurrentInuA",false }, {0x0018,0x9004,VR::CS,VM::VM1,"Content Qualification","ContentQualification",false }, {0x0018,0x9005,VR::SH,VM::VM1,"Pulse Sequence Name","PulseSequenceName",false }, {0x0018,0x9006,VR::SQ,VM::VM1,"MR Imaging Modifier Sequence","MRImagingModifierSequence",false }, {0x0018,0x9008,VR::CS,VM::VM1,"Echo Pulse Sequence","EchoPulseSequence",false }, {0x0018,0x9009,VR::CS,VM::VM1,"Inversion Recovery","InversionRecovery",false }, {0x0018,0x9010,VR::CS,VM::VM1,"Flow Compensation","FlowCompensation",false }, {0x0018,0x9011,VR::CS,VM::VM1,"Multiple Spin Echo","MultipleSpinEcho",false }, {0x0018,0x9012,VR::CS,VM::VM1,"Multi-planar Excitation","MultiPlanarExcitation",false }, {0x0018,0x9014,VR::CS,VM::VM1,"Phase Contrast","PhaseContrast",false }, {0x0018,0x9015,VR::CS,VM::VM1,"Time of Flight Contrast","TimeOfFlightContrast",false }, {0x0018,0x9016,VR::CS,VM::VM1,"Spoiling","Spoiling",false }, {0x0018,0x9017,VR::CS,VM::VM1,"Steady State Pulse Sequence","SteadyStatePulseSequence",false }, {0x0018,0x9018,VR::CS,VM::VM1,"Echo Planar Pulse Sequence","EchoPlanarPulseSequence",false }, {0x0018,0x9019,VR::FD,VM::VM1,"Tag Angle First Axis","TagAngleFirstAxis",false }, {0x0018,0x9020,VR::CS,VM::VM1,"Magnetization Transfer","MagnetizationTransfer",false }, {0x0018,0x9021,VR::CS,VM::VM1,"T2 Preparation","T2Preparation",false }, {0x0018,0x9022,VR::CS,VM::VM1,"Blood Signal Nulling","BloodSignalNulling",false }, {0x0018,0x9024,VR::CS,VM::VM1,"Saturation Recovery","SaturationRecovery",false }, {0x0018,0x9025,VR::CS,VM::VM1,"Spectrally Selected Suppression","SpectrallySelectedSuppression",false }, {0x0018,0x9026,VR::CS,VM::VM1,"Spectrally Selected Excitation","SpectrallySelectedExcitation",false }, {0x0018,0x9027,VR::CS,VM::VM1,"Spatial Pre-saturation","SpatialPresaturation",false }, {0x0018,0x9028,VR::CS,VM::VM1,"Tagging","Tagging",false }, {0x0018,0x9029,VR::CS,VM::VM1,"Oversampling Phase","OversamplingPhase",false }, {0x0018,0x9030,VR::FD,VM::VM1,"Tag Spacing First Dimension","TagSpacingFirstDimension",false }, {0x0018,0x9032,VR::CS,VM::VM1,"Geometry of k-Space Traversal","GeometryOfKSpaceTraversal",false }, {0x0018,0x9033,VR::CS,VM::VM1,"Segmented k-Space Traversal","SegmentedKSpaceTraversal",false }, {0x0018,0x9034,VR::CS,VM::VM1,"Rectilinear Phase Encode Reordering","RectilinearPhaseEncodeReordering",false }, {0x0018,0x9035,VR::FD,VM::VM1,"Tag Thickness","TagThickness",false }, {0x0018,0x9036,VR::CS,VM::VM1,"Partial Fourier Direction","PartialFourierDirection",false }, {0x0018,0x9037,VR::CS,VM::VM1,"Cardiac Synchronization Technique","CardiacSynchronizationTechnique",false }, {0x0018,0x9041,VR::LO,VM::VM1,"Receive Coil Manufacturer Name","ReceiveCoilManufacturerName",false }, {0x0018,0x9042,VR::SQ,VM::VM1,"MR Receive Coil Sequence","MRReceiveCoilSequence",false }, {0x0018,0x9043,VR::CS,VM::VM1,"Receive Coil Type","ReceiveCoilType",false }, {0x0018,0x9044,VR::CS,VM::VM1,"Quadrature Receive Coil","QuadratureReceiveCoil",false }, {0x0018,0x9045,VR::SQ,VM::VM1,"Multi-Coil Definition Sequence","MultiCoilDefinitionSequence",false }, {0x0018,0x9046,VR::LO,VM::VM1,"Multi-Coil Configuration","MultiCoilConfiguration",false }, {0x0018,0x9047,VR::SH,VM::VM1,"Multi-Coil Element Name","MultiCoilElementName",false }, {0x0018,0x9048,VR::CS,VM::VM1,"Multi-Coil Element Used","MultiCoilElementUsed",false }, {0x0018,0x9049,VR::SQ,VM::VM1,"MR Transmit Coil Sequence","MRTransmitCoilSequence",false }, {0x0018,0x9050,VR::LO,VM::VM1,"Transmit Coil Manufacturer Name","TransmitCoilManufacturerName",false }, {0x0018,0x9051,VR::CS,VM::VM1,"Transmit Coil Type","TransmitCoilType",false }, {0x0018,0x9052,VR::FD,VM::VM1_2,"Spectral Width","SpectralWidth",false }, {0x0018,0x9053,VR::FD,VM::VM1_2,"Chemical Shift Reference","ChemicalShiftReference",false }, {0x0018,0x9054,VR::CS,VM::VM1,"Volume Localization Technique","VolumeLocalizationTechnique",false }, {0x0018,0x9058,VR::US,VM::VM1,"MR Acquisition Frequency Encoding Steps","MRAcquisitionFrequencyEncodingSteps",false }, {0x0018,0x9059,VR::CS,VM::VM1,"De-coupling","Decoupling",false }, {0x0018,0x9060,VR::CS,VM::VM1_2,"De-coupled Nucleus","DecoupledNucleus",false }, {0x0018,0x9061,VR::FD,VM::VM1_2,"De-coupling Frequency","DecouplingFrequency",false }, {0x0018,0x9062,VR::CS,VM::VM1,"De-coupling Method","DecouplingMethod",false }, {0x0018,0x9063,VR::FD,VM::VM1_2,"De-coupling Chemical Shift Reference","DecouplingChemicalShiftReference",false }, {0x0018,0x9064,VR::CS,VM::VM1,"k-space Filtering","KSpaceFiltering",false }, {0x0018,0x9065,VR::CS,VM::VM1_2,"Time Domain Filtering","TimeDomainFiltering",false }, {0x0018,0x9066,VR::US,VM::VM1_2,"Number of Zero Fills","NumberOfZeroFills",false }, {0x0018,0x9067,VR::CS,VM::VM1,"Baseline Correction","BaselineCorrection",false }, {0x0018,0x9069,VR::FD,VM::VM1,"Parallel Reduction Factor In-plane","ParallelReductionFactorInPlane",false }, {0x0018,0x9070,VR::FD,VM::VM1,"Cardiac R-R Interval Specified","CardiacRRIntervalSpecified",false }, {0x0018,0x9073,VR::FD,VM::VM1,"Acquisition Duration","AcquisitionDuration",false }, {0x0018,0x9074,VR::DT,VM::VM1,"Frame Acquisition DateTime","FrameAcquisitionDateTime",false }, {0x0018,0x9075,VR::CS,VM::VM1,"Diffusion Directionality","DiffusionDirectionality",false }, {0x0018,0x9076,VR::SQ,VM::VM1,"Diffusion Gradient Direction Sequence","DiffusionGradientDirectionSequence",false }, {0x0018,0x9077,VR::CS,VM::VM1,"Parallel Acquisition","ParallelAcquisition",false }, {0x0018,0x9078,VR::CS,VM::VM1,"Parallel Acquisition Technique","ParallelAcquisitionTechnique",false }, {0x0018,0x9079,VR::FD,VM::VM1_n,"Inversion Times","InversionTimes",false }, {0x0018,0x9080,VR::ST,VM::VM1,"Metabolite Map Description","MetaboliteMapDescription",false }, {0x0018,0x9081,VR::CS,VM::VM1,"Partial Fourier","PartialFourier",false }, {0x0018,0x9082,VR::FD,VM::VM1,"Effective Echo Time","EffectiveEchoTime",false }, {0x0018,0x9083,VR::SQ,VM::VM1,"Metabolite Map Code Sequence","MetaboliteMapCodeSequence",false }, {0x0018,0x9084,VR::SQ,VM::VM1,"Chemical Shift Sequence","ChemicalShiftSequence",false }, {0x0018,0x9085,VR::CS,VM::VM1,"Cardiac Signal Source","CardiacSignalSource",false }, {0x0018,0x9087,VR::FD,VM::VM1,"Diffusion b-value","DiffusionBValue",false }, {0x0018,0x9089,VR::FD,VM::VM3,"Diffusion Gradient Orientation","DiffusionGradientOrientation",false }, {0x0018,0x9090,VR::FD,VM::VM3,"Velocity Encoding Direction","VelocityEncodingDirection",false }, {0x0018,0x9091,VR::FD,VM::VM1,"Velocity Encoding Minimum Value","VelocityEncodingMinimumValue",false }, {0x0018,0x9092,VR::SQ,VM::VM1,"Velocity Encoding Acquisition Sequence","VelocityEncodingAcquisitionSequence",false }, {0x0018,0x9093,VR::US,VM::VM1,"Number of k-Space Trajectories","NumberOfKSpaceTrajectories",false }, {0x0018,0x9094,VR::CS,VM::VM1,"Coverage of k-Space","CoverageOfKSpace",false }, {0x0018,0x9095,VR::UL,VM::VM1,"Spectroscopy Acquisition Phase Rows","SpectroscopyAcquisitionPhaseRows",false }, {0x0018,0x9096,VR::FD,VM::VM1,"Parallel Reduction Factor In-plane (Retired)","ParallelReductionFactorInPlaneRetired",true }, {0x0018,0x9098,VR::FD,VM::VM1_2,"Transmitter Frequency","TransmitterFrequency",false }, {0x0018,0x9100,VR::CS,VM::VM1_2,"Resonant Nucleus","ResonantNucleus",false }, {0x0018,0x9101,VR::CS,VM::VM1,"Frequency Correction","FrequencyCorrection",false }, {0x0018,0x9103,VR::SQ,VM::VM1,"MR Spectroscopy FOV/Geometry Sequence","MRSpectroscopyFOVGeometrySequence",false }, {0x0018,0x9104,VR::FD,VM::VM1,"Slab Thickness","SlabThickness",false }, {0x0018,0x9105,VR::FD,VM::VM3,"Slab Orientation","SlabOrientation",false }, {0x0018,0x9106,VR::FD,VM::VM3,"Mid Slab Position","MidSlabPosition",false }, {0x0018,0x9107,VR::SQ,VM::VM1,"MR Spatial Saturation Sequence","MRSpatialSaturationSequence",false }, {0x0018,0x9112,VR::SQ,VM::VM1,"MR Timing and Related Parameters Sequence","MRTimingAndRelatedParametersSequence",false }, {0x0018,0x9114,VR::SQ,VM::VM1,"MR Echo Sequence","MREchoSequence",false }, {0x0018,0x9115,VR::SQ,VM::VM1,"MR Modifier Sequence","MRModifierSequence",false }, {0x0018,0x9117,VR::SQ,VM::VM1,"MR Diffusion Sequence","MRDiffusionSequence",false }, {0x0018,0x9118,VR::SQ,VM::VM1,"Cardiac Synchronization Sequence","CardiacSynchronizationSequence",false }, {0x0018,0x9119,VR::SQ,VM::VM1,"MR Averages Sequence","MRAveragesSequence",false }, {0x0018,0x9125,VR::SQ,VM::VM1,"MR FOV/Geometry Sequence","MRFOVGeometrySequence",false }, {0x0018,0x9126,VR::SQ,VM::VM1,"Volume Localization Sequence","VolumeLocalizationSequence",false }, {0x0018,0x9127,VR::UL,VM::VM1,"Spectroscopy Acquisition Data Columns","SpectroscopyAcquisitionDataColumns",false }, {0x0018,0x9147,VR::CS,VM::VM1,"Diffusion Anisotropy Type","DiffusionAnisotropyType",false }, {0x0018,0x9151,VR::DT,VM::VM1,"Frame Reference DateTime","FrameReferenceDateTime",false }, {0x0018,0x9152,VR::SQ,VM::VM1,"MR Metabolite Map Sequence","MRMetaboliteMapSequence",false }, {0x0018,0x9155,VR::FD,VM::VM1,"Parallel Reduction Factor out-of-plane","ParallelReductionFactorOutOfPlane",false }, {0x0018,0x9159,VR::UL,VM::VM1,"Spectroscopy Acquisition Out-of-plane Phase Steps","SpectroscopyAcquisitionOutOfPlanePhaseSteps",false }, {0x0018,0x9166,VR::CS,VM::VM1,"Bulk Motion Status","BulkMotionStatus",true }, {0x0018,0x9168,VR::FD,VM::VM1,"Parallel Reduction Factor Second In-plane","ParallelReductionFactorSecondInPlane",false }, {0x0018,0x9169,VR::CS,VM::VM1,"Cardiac Beat Rejection Technique","CardiacBeatRejectionTechnique",false }, {0x0018,0x9170,VR::CS,VM::VM1,"Respiratory Motion Compensation Technique","RespiratoryMotionCompensationTechnique",false }, {0x0018,0x9171,VR::CS,VM::VM1,"Respiratory Signal Source","RespiratorySignalSource",false }, {0x0018,0x9172,VR::CS,VM::VM1,"Bulk Motion Compensation Technique","BulkMotionCompensationTechnique",false }, {0x0018,0x9173,VR::CS,VM::VM1,"Bulk Motion Signal Source","BulkMotionSignalSource",false }, {0x0018,0x9174,VR::CS,VM::VM1,"Applicable Safety Standard Agency","ApplicableSafetyStandardAgency",false }, {0x0018,0x9175,VR::LO,VM::VM1,"Applicable Safety Standard Description","ApplicableSafetyStandardDescription",false }, {0x0018,0x9176,VR::SQ,VM::VM1,"Operating Mode Sequence","OperatingModeSequence",false }, {0x0018,0x9177,VR::CS,VM::VM1,"Operating Mode Type","OperatingModeType",false }, {0x0018,0x9178,VR::CS,VM::VM1,"Operating Mode","OperatingMode",false }, {0x0018,0x9179,VR::CS,VM::VM1,"Specific Absorption Rate Definition","SpecificAbsorptionRateDefinition",false }, {0x0018,0x9180,VR::CS,VM::VM1,"Gradient Output Type","GradientOutputType",false }, {0x0018,0x9181,VR::FD,VM::VM1,"Specific Absorption Rate Value","SpecificAbsorptionRateValue",false }, {0x0018,0x9182,VR::FD,VM::VM1,"Gradient Output","GradientOutput",false }, {0x0018,0x9183,VR::CS,VM::VM1,"Flow Compensation Direction","FlowCompensationDirection",false }, {0x0018,0x9184,VR::FD,VM::VM1,"Tagging Delay","TaggingDelay",false }, {0x0018,0x9185,VR::ST,VM::VM1,"Respiratory Motion Compensation Technique Description","RespiratoryMotionCompensationTechniqueDescription",false }, {0x0018,0x9186,VR::SH,VM::VM1,"Respiratory Signal Source ID","RespiratorySignalSourceID",false }, {0x0018,0x9195,VR::FD,VM::VM1,"Chemical Shift Minimum Integration Limit in Hz","ChemicalShiftMinimumIntegrationLimitInHz",true }, {0x0018,0x9196,VR::FD,VM::VM1,"Chemical Shift Maximum Integration Limit in Hz","ChemicalShiftMaximumIntegrationLimitInHz",true }, {0x0018,0x9197,VR::SQ,VM::VM1,"MR Velocity Encoding Sequence","MRVelocityEncodingSequence",false }, {0x0018,0x9198,VR::CS,VM::VM1,"First Order Phase Correction","FirstOrderPhaseCorrection",false }, {0x0018,0x9199,VR::CS,VM::VM1,"Water Referenced Phase Correction","WaterReferencedPhaseCorrection",false }, {0x0018,0x9200,VR::CS,VM::VM1,"MR Spectroscopy Acquisition Type","MRSpectroscopyAcquisitionType",false }, {0x0018,0x9214,VR::CS,VM::VM1,"Respiratory Cycle Position","RespiratoryCyclePosition",false }, {0x0018,0x9217,VR::FD,VM::VM1,"Velocity Encoding Maximum Value","VelocityEncodingMaximumValue",false }, {0x0018,0x9218,VR::FD,VM::VM1,"Tag Spacing Second Dimension","TagSpacingSecondDimension",false }, {0x0018,0x9219,VR::SS,VM::VM1,"Tag Angle Second Axis","TagAngleSecondAxis",false }, {0x0018,0x9220,VR::FD,VM::VM1,"Frame Acquisition Duration","FrameAcquisitionDuration",false }, {0x0018,0x9226,VR::SQ,VM::VM1,"MR Image Frame Type Sequence","MRImageFrameTypeSequence",false }, {0x0018,0x9227,VR::SQ,VM::VM1,"MR Spectroscopy Frame Type Sequence","MRSpectroscopyFrameTypeSequence",false }, {0x0018,0x9231,VR::US,VM::VM1,"MR Acquisition Phase Encoding Steps in-plane","MRAcquisitionPhaseEncodingStepsInPlane",false }, {0x0018,0x9232,VR::US,VM::VM1,"MR Acquisition Phase Encoding Steps out-of-plane","MRAcquisitionPhaseEncodingStepsOutOfPlane",false }, {0x0018,0x9234,VR::UL,VM::VM1,"Spectroscopy Acquisition Phase Columns","SpectroscopyAcquisitionPhaseColumns",false }, {0x0018,0x9236,VR::CS,VM::VM1,"Cardiac Cycle Position","CardiacCyclePosition",false }, {0x0018,0x9239,VR::SQ,VM::VM1,"Specific Absorption Rate Sequence","SpecificAbsorptionRateSequence",false }, {0x0018,0x9240,VR::US,VM::VM1,"RF Echo Train Length","RFEchoTrainLength",false }, {0x0018,0x9241,VR::US,VM::VM1,"Gradient Echo Train Length","GradientEchoTrainLength",false }, {0x0018,0x9250,VR::CS,VM::VM1,"Arterial Spin Labeling Contrast","ArterialSpinLabelingContrast",false }, {0x0018,0x9251,VR::SQ,VM::VM1,"MR Arterial Spin Labeling Sequence","MRArterialSpinLabelingSequence",false }, {0x0018,0x9252,VR::LO,VM::VM1,"ASL Technique Description","ASLTechniqueDescription",false }, {0x0018,0x9253,VR::US,VM::VM1,"ASL Slab Number","ASLSlabNumber",false }, {0x0018,0x9254,VR::FD,VM::VM1,"ASL Slab Thickness","ASLSlabThickness",false }, {0x0018,0x9255,VR::FD,VM::VM3,"ASL Slab Orientation","ASLSlabOrientation",false }, {0x0018,0x9256,VR::FD,VM::VM3,"ASL Mid Slab Position","ASLMidSlabPosition",false }, {0x0018,0x9257,VR::CS,VM::VM1,"ASL Context","ASLContext",false }, {0x0018,0x9258,VR::UL,VM::VM1,"ASL Pulse Train Duration","ASLPulseTrainDuration",false }, {0x0018,0x9259,VR::CS,VM::VM1,"ASL Crusher Flag","ASLCrusherFlag",false }, {0x0018,0x925a,VR::FD,VM::VM1,"ASL Crusher Flow Limit","ASLCrusherFlowLimit",false }, {0x0018,0x925b,VR::LO,VM::VM1,"ASL Crusher Description","ASLCrusherDescription",false }, {0x0018,0x925c,VR::CS,VM::VM1,"ASL Bolus Cut-off Flag","ASLBolusCutoffFlag",false }, {0x0018,0x925d,VR::SQ,VM::VM1,"ASL Bolus Cut-off Timing Sequence","ASLBolusCutoffTimingSequence",false }, {0x0018,0x925e,VR::LO,VM::VM1,"ASL Bolus Cut-off Technique","ASLBolusCutoffTechnique",false }, {0x0018,0x925f,VR::UL,VM::VM1,"ASL Bolus Cut-off Delay Time","ASLBolusCutoffDelayTime",false }, {0x0018,0x9260,VR::SQ,VM::VM1,"ASL Slab Sequence","ASLSlabSequence",false }, {0x0018,0x9295,VR::FD,VM::VM1,"Chemical Shift Minimum Integration Limit in ppm","ChemicalShiftMinimumIntegrationLimitInppm",false }, {0x0018,0x9296,VR::FD,VM::VM1,"Chemical Shift Maximum Integration Limit in ppm","ChemicalShiftMaximumIntegrationLimitInppm",false }, {0x0018,0x9297,VR::CS,VM::VM1,"Water Reference Acquisition","WaterReferenceAcquisition",false }, {0x0018,0x9298,VR::IS,VM::VM1,"Echo Peak Position","EchoPeakPosition",false }, {0x0018,0x9301,VR::SQ,VM::VM1,"CT Acquisition Type Sequence","CTAcquisitionTypeSequence",false }, {0x0018,0x9302,VR::CS,VM::VM1,"Acquisition Type","AcquisitionType",false }, {0x0018,0x9303,VR::FD,VM::VM1,"Tube Angle","TubeAngle",false }, {0x0018,0x9304,VR::SQ,VM::VM1,"CT Acquisition Details Sequence","CTAcquisitionDetailsSequence",false }, {0x0018,0x9305,VR::FD,VM::VM1,"Revolution Time","RevolutionTime",false }, {0x0018,0x9306,VR::FD,VM::VM1,"Single Collimation Width","SingleCollimationWidth",false }, {0x0018,0x9307,VR::FD,VM::VM1,"Total Collimation Width","TotalCollimationWidth",false }, {0x0018,0x9308,VR::SQ,VM::VM1,"CT Table Dynamics Sequence","CTTableDynamicsSequence",false }, {0x0018,0x9309,VR::FD,VM::VM1,"Table Speed","TableSpeed",false }, {0x0018,0x9310,VR::FD,VM::VM1,"Table Feed per Rotation","TableFeedPerRotation",false }, {0x0018,0x9311,VR::FD,VM::VM1,"Spiral Pitch Factor","SpiralPitchFactor",false }, {0x0018,0x9312,VR::SQ,VM::VM1,"CT Geometry Sequence","CTGeometrySequence",false }, {0x0018,0x9313,VR::FD,VM::VM3,"Data Collection Center (Patient)","DataCollectionCenterPatient",false }, {0x0018,0x9314,VR::SQ,VM::VM1,"CT Reconstruction Sequence","CTReconstructionSequence",false }, {0x0018,0x9315,VR::CS,VM::VM1,"Reconstruction Algorithm","ReconstructionAlgorithm",false }, {0x0018,0x9316,VR::CS,VM::VM1,"Convolution Kernel Group","ConvolutionKernelGroup",false }, {0x0018,0x9317,VR::FD,VM::VM2,"Reconstruction Field of View","ReconstructionFieldOfView",false }, {0x0018,0x9318,VR::FD,VM::VM3,"Reconstruction Target Center (Patient)","ReconstructionTargetCenterPatient",false }, {0x0018,0x9319,VR::FD,VM::VM1,"Reconstruction Angle","ReconstructionAngle",false }, {0x0018,0x9320,VR::SH,VM::VM1,"Image Filter","ImageFilter",false }, {0x0018,0x9321,VR::SQ,VM::VM1,"CT Exposure Sequence","CTExposureSequence",false }, {0x0018,0x9322,VR::FD,VM::VM2,"Reconstruction Pixel Spacing","ReconstructionPixelSpacing",false }, {0x0018,0x9323,VR::CS,VM::VM1_n,"Exposure Modulation Type","ExposureModulationType",false }, {0x0018,0x9324,VR::FD,VM::VM1,"Estimated Dose Saving","EstimatedDoseSaving",false }, {0x0018,0x9325,VR::SQ,VM::VM1,"CT X-Ray Details Sequence","CTXRayDetailsSequence",false }, {0x0018,0x9326,VR::SQ,VM::VM1,"CT Position Sequence","CTPositionSequence",false }, {0x0018,0x9327,VR::FD,VM::VM1,"Table Position","TablePosition",false }, {0x0018,0x9328,VR::FD,VM::VM1,"Exposure Time in ms","ExposureTimeInms",false }, {0x0018,0x9329,VR::SQ,VM::VM1,"CT Image Frame Type Sequence","CTImageFrameTypeSequence",false }, {0x0018,0x9330,VR::FD,VM::VM1,"X-Ray Tube Current in mA","XRayTubeCurrentInmA",false }, {0x0018,0x9332,VR::FD,VM::VM1,"Exposure in mAs","ExposureInmAs",false }, {0x0018,0x9333,VR::CS,VM::VM1,"Constant Volume Flag","ConstantVolumeFlag",false }, {0x0018,0x9334,VR::CS,VM::VM1,"Fluoroscopy Flag","FluoroscopyFlag",false }, {0x0018,0x9335,VR::FD,VM::VM1,"Distance Source to Data Collection Center","DistanceSourceToDataCollectionCenter",false }, {0x0018,0x9337,VR::US,VM::VM1,"Contrast/Bolus Agent Number","ContrastBolusAgentNumber",false }, {0x0018,0x9338,VR::SQ,VM::VM1,"Contrast/Bolus Ingredient Code Sequence","ContrastBolusIngredientCodeSequence",false }, {0x0018,0x9340,VR::SQ,VM::VM1,"Contrast Administration Profile Sequence","ContrastAdministrationProfileSequence",false }, {0x0018,0x9341,VR::SQ,VM::VM1,"Contrast/Bolus Usage Sequence","ContrastBolusUsageSequence",false }, {0x0018,0x9342,VR::CS,VM::VM1,"Contrast/Bolus Agent Administered","ContrastBolusAgentAdministered",false }, {0x0018,0x9343,VR::CS,VM::VM1,"Contrast/Bolus Agent Detected","ContrastBolusAgentDetected",false }, {0x0018,0x9344,VR::CS,VM::VM1,"Contrast/Bolus Agent Phase","ContrastBolusAgentPhase",false }, {0x0018,0x9345,VR::FD,VM::VM1,"CTDIvol","CTDIvol",false }, {0x0018,0x9346,VR::SQ,VM::VM1,"CTDI Phantom Type Code Sequence","CTDIPhantomTypeCodeSequence",false }, {0x0018,0x9351,VR::FL,VM::VM1,"Calcium Scoring Mass Factor Patient","CalciumScoringMassFactorPatient",false }, {0x0018,0x9352,VR::FL,VM::VM3,"Calcium Scoring Mass Factor Device","CalciumScoringMassFactorDevice",false }, {0x0018,0x9353,VR::FL,VM::VM1,"Energy Weighting Factor","EnergyWeightingFactor",false }, {0x0018,0x9360,VR::SQ,VM::VM1,"CT Additional X-Ray Source Sequence","CTAdditionalXRaySourceSequence",false }, {0x0018,0x9401,VR::SQ,VM::VM1,"Projection Pixel Calibration Sequence","ProjectionPixelCalibrationSequence",false }, {0x0018,0x9402,VR::FL,VM::VM1,"Distance Source to Isocenter","DistanceSourceToIsocenter",false }, {0x0018,0x9403,VR::FL,VM::VM1,"Distance Object to Table Top","DistanceObjectToTableTop",false }, {0x0018,0x9404,VR::FL,VM::VM2,"Object Pixel Spacing in Center of Beam","ObjectPixelSpacingInCenterOfBeam",false }, {0x0018,0x9405,VR::SQ,VM::VM1,"Positioner Position Sequence","PositionerPositionSequence",false }, {0x0018,0x9406,VR::SQ,VM::VM1,"Table Position Sequence","TablePositionSequence",false }, {0x0018,0x9407,VR::SQ,VM::VM1,"Collimator Shape Sequence","CollimatorShapeSequence",false }, {0x0018,0x9410,VR::CS,VM::VM1,"Planes in Acquisition","PlanesInAcquisition",false }, {0x0018,0x9412,VR::SQ,VM::VM1,"XA/XRF Frame Characteristics Sequence","XAXRFFrameCharacteristicsSequence",false }, {0x0018,0x9417,VR::SQ,VM::VM1,"Frame Acquisition Sequence","FrameAcquisitionSequence",false }, {0x0018,0x9420,VR::CS,VM::VM1,"X-Ray Receptor Type","XRayReceptorType",false }, {0x0018,0x9423,VR::LO,VM::VM1,"Acquisition Protocol Name","AcquisitionProtocolName",false }, {0x0018,0x9424,VR::LT,VM::VM1,"Acquisition Protocol Description","AcquisitionProtocolDescription",false }, {0x0018,0x9425,VR::CS,VM::VM1,"Contrast/Bolus Ingredient Opaque","ContrastBolusIngredientOpaque",false }, {0x0018,0x9426,VR::FL,VM::VM1,"Distance Receptor Plane to Detector Housing","DistanceReceptorPlaneToDetectorHousing",false }, {0x0018,0x9427,VR::CS,VM::VM1,"Intensifier Active Shape","IntensifierActiveShape",false }, {0x0018,0x9428,VR::FL,VM::VM1_2,"Intensifier Active Dimension(s)","IntensifierActiveDimensions",false }, {0x0018,0x9429,VR::FL,VM::VM2,"Physical Detector Size","PhysicalDetectorSize",false }, {0x0018,0x9430,VR::FL,VM::VM2,"Position of Isocenter Projection","PositionOfIsocenterProjection",false }, {0x0018,0x9432,VR::SQ,VM::VM1,"Field of View Sequence","FieldOfViewSequence",false }, {0x0018,0x9433,VR::LO,VM::VM1,"Field of View Description","FieldOfViewDescription",false }, {0x0018,0x9434,VR::SQ,VM::VM1,"Exposure Control Sensing Regions Sequence","ExposureControlSensingRegionsSequence",false }, {0x0018,0x9435,VR::CS,VM::VM1,"Exposure Control Sensing Region Shape","ExposureControlSensingRegionShape",false }, {0x0018,0x9436,VR::SS,VM::VM1,"Exposure Control Sensing Region Left Vertical Edge","ExposureControlSensingRegionLeftVerticalEdge",false }, {0x0018,0x9437,VR::SS,VM::VM1,"Exposure Control Sensing Region Right Vertical Edge","ExposureControlSensingRegionRightVerticalEdge",false }, {0x0018,0x9438,VR::SS,VM::VM1,"Exposure Control Sensing Region Upper Horizontal Edge","ExposureControlSensingRegionUpperHorizontalEdge",false }, {0x0018,0x9439,VR::SS,VM::VM1,"Exposure Control Sensing Region Lower Horizontal Edge","ExposureControlSensingRegionLowerHorizontalEdge",false }, {0x0018,0x9440,VR::SS,VM::VM2,"Center of Circular Exposure Control Sensing Region","CenterOfCircularExposureControlSensingRegion",false }, {0x0018,0x9441,VR::US,VM::VM1,"Radius of Circular Exposure Control Sensing Region","RadiusOfCircularExposureControlSensingRegion",false }, {0x0018,0x9442,VR::SS,VM::VM2_n,"Vertices of the Polygonal Exposure Control Sensing Region","VerticesOfThePolygonalExposureControlSensingRegion",false }, {0x0018,0x9445,VR::INVALID,VM::VM0,"","",true }, {0x0018,0x9447,VR::FL,VM::VM1,"Column Angulation (Patient)","ColumnAngulationPatient",false }, {0x0018,0x9449,VR::FL,VM::VM1,"Beam Angle","BeamAngle",false }, {0x0018,0x9451,VR::SQ,VM::VM1,"Frame Detector Parameters Sequence","FrameDetectorParametersSequence",false }, {0x0018,0x9452,VR::FL,VM::VM1,"Calculated Anatomy Thickness","CalculatedAnatomyThickness",false }, {0x0018,0x9455,VR::SQ,VM::VM1,"Calibration Sequence","CalibrationSequence",false }, {0x0018,0x9456,VR::SQ,VM::VM1,"Object Thickness Sequence","ObjectThicknessSequence",false }, {0x0018,0x9457,VR::CS,VM::VM1,"Plane Identification","PlaneIdentification",false }, {0x0018,0x9461,VR::FL,VM::VM1_2,"Field of View Dimension(s) in Float","FieldOfViewDimensionsInFloat",false }, {0x0018,0x9462,VR::SQ,VM::VM1,"Isocenter Reference System Sequence","IsocenterReferenceSystemSequence",false }, {0x0018,0x9463,VR::FL,VM::VM1,"Positioner Isocenter Primary Angle","PositionerIsocenterPrimaryAngle",false }, {0x0018,0x9464,VR::FL,VM::VM1,"Positioner Isocenter Secondary Angle","PositionerIsocenterSecondaryAngle",false }, {0x0018,0x9465,VR::FL,VM::VM1,"Positioner Isocenter Detector Rotation Angle","PositionerIsocenterDetectorRotationAngle",false }, {0x0018,0x9466,VR::FL,VM::VM1,"Table X Position to Isocenter","TableXPositionToIsocenter",false }, {0x0018,0x9467,VR::FL,VM::VM1,"Table Y Position to Isocenter","TableYPositionToIsocenter",false }, {0x0018,0x9468,VR::FL,VM::VM1,"Table Z Position to Isocenter","TableZPositionToIsocenter",false }, {0x0018,0x9469,VR::FL,VM::VM1,"Table Horizontal Rotation Angle","TableHorizontalRotationAngle",false }, {0x0018,0x9470,VR::FL,VM::VM1,"Table Head Tilt Angle","TableHeadTiltAngle",false }, {0x0018,0x9471,VR::FL,VM::VM1,"Table Cradle Tilt Angle","TableCradleTiltAngle",false }, {0x0018,0x9472,VR::SQ,VM::VM1,"Frame Display Shutter Sequence","FrameDisplayShutterSequence",false }, {0x0018,0x9473,VR::FL,VM::VM1,"Acquired Image Area Dose Product","AcquiredImageAreaDoseProduct",false }, {0x0018,0x9474,VR::CS,VM::VM1,"C-arm Positioner Tabletop Relationship","CArmPositionerTabletopRelationship",false }, {0x0018,0x9476,VR::SQ,VM::VM1,"X-Ray Geometry Sequence","XRayGeometrySequence",false }, {0x0018,0x9477,VR::SQ,VM::VM1,"Irradiation Event Identification Sequence","IrradiationEventIdentificationSequence",false }, {0x0018,0x9504,VR::SQ,VM::VM1,"X-Ray 3D Frame Type Sequence","XRay3DFrameTypeSequence",false }, {0x0018,0x9506,VR::SQ,VM::VM1,"Contributing Sources Sequence","ContributingSourcesSequence",false }, {0x0018,0x9507,VR::SQ,VM::VM1,"X-Ray 3D Acquisition Sequence","XRay3DAcquisitionSequence",false }, {0x0018,0x9508,VR::FL,VM::VM1,"Primary Positioner Scan Arc","PrimaryPositionerScanArc",false }, {0x0018,0x9509,VR::FL,VM::VM1,"Secondary Positioner Scan Arc","SecondaryPositionerScanArc",false }, {0x0018,0x9510,VR::FL,VM::VM1,"Primary Positioner Scan Start Angle","PrimaryPositionerScanStartAngle",false }, {0x0018,0x9511,VR::FL,VM::VM1,"Secondary Positioner Scan Start Angle","SecondaryPositionerScanStartAngle",false }, {0x0018,0x9514,VR::FL,VM::VM1,"Primary Positioner Increment","PrimaryPositionerIncrement",false }, {0x0018,0x9515,VR::FL,VM::VM1,"Secondary Positioner Increment","SecondaryPositionerIncrement",false }, {0x0018,0x9516,VR::DT,VM::VM1,"Start Acquisition DateTime","StartAcquisitionDateTime",false }, {0x0018,0x9517,VR::DT,VM::VM1,"End Acquisition DateTime","EndAcquisitionDateTime",false }, {0x0018,0x9518,VR::SS,VM::VM1,"Primary Positioner Increment Sign","PrimaryPositionerIncrementSign",false }, {0x0018,0x9519,VR::SS,VM::VM1,"Secondary Positioner Increment Sign","SecondaryPositionerIncrementSign",false }, {0x0018,0x9524,VR::LO,VM::VM1,"Application Name","ApplicationName",false }, {0x0018,0x9525,VR::LO,VM::VM1,"Application Version","ApplicationVersion",false }, {0x0018,0x9526,VR::LO,VM::VM1,"Application Manufacturer","ApplicationManufacturer",false }, {0x0018,0x9527,VR::CS,VM::VM1,"Algorithm Type","AlgorithmType",false }, {0x0018,0x9528,VR::LO,VM::VM1,"Algorithm Description","AlgorithmDescription",false }, {0x0018,0x9530,VR::SQ,VM::VM1,"X-Ray 3D Reconstruction Sequence","XRay3DReconstructionSequence",false }, {0x0018,0x9531,VR::LO,VM::VM1,"Reconstruction Description","ReconstructionDescription",false }, {0x0018,0x9538,VR::SQ,VM::VM1,"Per Projection Acquisition Sequence","PerProjectionAcquisitionSequence",false }, {0x0018,0x9541,VR::SQ,VM::VM1,"Detector Position Sequence","DetectorPositionSequence",false }, {0x0018,0x9542,VR::SQ,VM::VM1,"X-Ray Acquisition Dose Sequence","XRayAcquisitionDoseSequence",false }, {0x0018,0x9543,VR::FD,VM::VM1,"X-Ray Source Isocenter Primary Angle","XRaySourceIsocenterPrimaryAngle",false }, {0x0018,0x9544,VR::FD,VM::VM1,"X-Ray Source Isocenter Secondary Angle","XRaySourceIsocenterSecondaryAngle",false }, {0x0018,0x9545,VR::FD,VM::VM1,"Breast Support Isocenter Primary Angle","BreastSupportIsocenterPrimaryAngle",false }, {0x0018,0x9546,VR::FD,VM::VM1,"Breast Support Isocenter Secondary Angle","BreastSupportIsocenterSecondaryAngle",false }, {0x0018,0x9547,VR::FD,VM::VM1,"Breast Support X Position to Isocenter","BreastSupportXPositionToIsocenter",false }, {0x0018,0x9548,VR::FD,VM::VM1,"Breast Support Y Position to Isocenter","BreastSupportYPositionToIsocenter",false }, {0x0018,0x9549,VR::FD,VM::VM1,"Breast Support Z Position to Isocenter","BreastSupportZPositionToIsocenter",false }, {0x0018,0x9550,VR::FD,VM::VM1,"Detector Isocenter Primary Angle","DetectorIsocenterPrimaryAngle",false }, {0x0018,0x9551,VR::FD,VM::VM1,"Detector Isocenter Secondary Angle","DetectorIsocenterSecondaryAngle",false }, {0x0018,0x9552,VR::FD,VM::VM1,"Detector X Position to Isocenter","DetectorXPositionToIsocenter",false }, {0x0018,0x9553,VR::FD,VM::VM1,"Detector Y Position to Isocenter","DetectorYPositionToIsocenter",false }, {0x0018,0x9554,VR::FD,VM::VM1,"Detector Z Position to Isocenter","DetectorZPositionToIsocenter",false }, {0x0018,0x9555,VR::SQ,VM::VM1,"X-Ray Grid Sequence","XRayGridSequence",false }, {0x0018,0x9556,VR::SQ,VM::VM1,"X-Ray Filter Sequence","XRayFilterSequence",false }, {0x0018,0x9557,VR::FD,VM::VM3,"Detector Active Area TLHC Position","DetectorActiveAreaTLHCPosition",false }, {0x0018,0x9558,VR::FD,VM::VM6,"Detector Active Area Orientation","DetectorActiveAreaOrientation",false }, {0x0018,0x9559,VR::CS,VM::VM1,"Positioner Primary Angle Direction","PositionerPrimaryAngleDirection",false }, {0x0018,0x9601,VR::SQ,VM::VM1,"Diffusion b-matrix Sequence","DiffusionBMatrixSequence",false }, {0x0018,0x9602,VR::FD,VM::VM1,"Diffusion b-value XX","DiffusionBValueXX",false }, {0x0018,0x9603,VR::FD,VM::VM1,"Diffusion b-value XY","DiffusionBValueXY",false }, {0x0018,0x9604,VR::FD,VM::VM1,"Diffusion b-value XZ","DiffusionBValueXZ",false }, {0x0018,0x9605,VR::FD,VM::VM1,"Diffusion b-value YY","DiffusionBValueYY",false }, {0x0018,0x9606,VR::FD,VM::VM1,"Diffusion b-value YZ","DiffusionBValueYZ",false }, {0x0018,0x9607,VR::FD,VM::VM1,"Diffusion b-value ZZ","DiffusionBValueZZ",false }, {0x0018,0x9621,VR::SQ,VM::VM1,"Functional MR Sequence","FunctionalMRSequence",false }, {0x0018,0x9622,VR::CS,VM::VM1,"Functional Settling Phase Frames Present","FunctionalSettlingPhaseFramesPresent",false }, {0x0018,0x9623,VR::DT,VM::VM1,"Functional Sync Pulse","FunctionalSyncPulse",false }, {0x0018,0x9624,VR::CS,VM::VM1,"Settling Phase Frame","SettlingPhaseFrame",false }, {0x0018,0x9701,VR::DT,VM::VM1,"Decay Correction DateTime","DecayCorrectionDateTime",false }, {0x0018,0x9715,VR::FD,VM::VM1,"Start Density Threshold","StartDensityThreshold",false }, {0x0018,0x9716,VR::FD,VM::VM1,"Start Relative Density Difference Threshold","StartRelativeDensityDifferenceThreshold",false }, {0x0018,0x9717,VR::FD,VM::VM1,"Start Cardiac Trigger Count Threshold","StartCardiacTriggerCountThreshold",false }, {0x0018,0x9718,VR::FD,VM::VM1,"Start Respiratory Trigger Count Threshold","StartRespiratoryTriggerCountThreshold",false }, {0x0018,0x9719,VR::FD,VM::VM1,"Termination Counts Threshold","TerminationCountsThreshold",false }, {0x0018,0x9720,VR::FD,VM::VM1,"Termination Density Threshold","TerminationDensityThreshold",false }, {0x0018,0x9721,VR::FD,VM::VM1,"Termination Relative Density Threshold","TerminationRelativeDensityThreshold",false }, {0x0018,0x9722,VR::FD,VM::VM1,"Termination Time Threshold","TerminationTimeThreshold",false }, {0x0018,0x9723,VR::FD,VM::VM1,"Termination Cardiac Trigger Count Threshold","TerminationCardiacTriggerCountThreshold",false }, {0x0018,0x9724,VR::FD,VM::VM1,"Termination Respiratory Trigger Count Threshold","TerminationRespiratoryTriggerCountThreshold",false }, {0x0018,0x9725,VR::CS,VM::VM1,"Detector Geometry","DetectorGeometry",false }, {0x0018,0x9726,VR::FD,VM::VM1,"Transverse Detector Separation","TransverseDetectorSeparation",false }, {0x0018,0x9727,VR::FD,VM::VM1,"Axial Detector Dimension","AxialDetectorDimension",false }, {0x0018,0x9729,VR::US,VM::VM1,"Radiopharmaceutical Agent Number","RadiopharmaceuticalAgentNumber",false }, {0x0018,0x9732,VR::SQ,VM::VM1,"PET Frame Acquisition Sequence","PETFrameAcquisitionSequence",false }, {0x0018,0x9733,VR::SQ,VM::VM1,"PET Detector Motion Details Sequence","PETDetectorMotionDetailsSequence",false }, {0x0018,0x9734,VR::SQ,VM::VM1,"PET Table Dynamics Sequence","PETTableDynamicsSequence",false }, {0x0018,0x9735,VR::SQ,VM::VM1,"PET Position Sequence","PETPositionSequence",false }, {0x0018,0x9736,VR::SQ,VM::VM1,"PET Frame Correction Factors Sequence","PETFrameCorrectionFactorsSequence",false }, {0x0018,0x9737,VR::SQ,VM::VM1,"Radiopharmaceutical Usage Sequence","RadiopharmaceuticalUsageSequence",false }, {0x0018,0x9738,VR::CS,VM::VM1,"Attenuation Correction Source","AttenuationCorrectionSource",false }, {0x0018,0x9739,VR::US,VM::VM1,"Number of Iterations","NumberOfIterations",false }, {0x0018,0x9740,VR::US,VM::VM1,"Number of Subsets","NumberOfSubsets",false }, {0x0018,0x9749,VR::SQ,VM::VM1,"PET Reconstruction Sequence","PETReconstructionSequence",false }, {0x0018,0x9751,VR::SQ,VM::VM1,"PET Frame Type Sequence","PETFrameTypeSequence",false }, {0x0018,0x9755,VR::CS,VM::VM1,"Time of Flight Information Used","TimeOfFlightInformationUsed",false }, {0x0018,0x9756,VR::CS,VM::VM1,"Reconstruction Type","ReconstructionType",false }, {0x0018,0x9758,VR::CS,VM::VM1,"Decay Corrected","DecayCorrected",false }, {0x0018,0x9759,VR::CS,VM::VM1,"Attenuation Corrected","AttenuationCorrected",false }, {0x0018,0x9760,VR::CS,VM::VM1,"Scatter Corrected","ScatterCorrected",false }, {0x0018,0x9761,VR::CS,VM::VM1,"Dead Time Corrected","DeadTimeCorrected",false }, {0x0018,0x9762,VR::CS,VM::VM1,"Gantry Motion Corrected","GantryMotionCorrected",false }, {0x0018,0x9763,VR::CS,VM::VM1,"Patient Motion Corrected","PatientMotionCorrected",false }, {0x0018,0x9764,VR::CS,VM::VM1,"Count Loss Normalization Corrected","CountLossNormalizationCorrected",false }, {0x0018,0x9765,VR::CS,VM::VM1,"Randoms Corrected","RandomsCorrected",false }, {0x0018,0x9766,VR::CS,VM::VM1,"Non-uniform Radial Sampling Corrected","NonUniformRadialSamplingCorrected",false }, {0x0018,0x9767,VR::CS,VM::VM1,"Sensitivity Calibrated","SensitivityCalibrated",false }, {0x0018,0x9768,VR::CS,VM::VM1,"Detector Normalization Correction","DetectorNormalizationCorrection",false }, {0x0018,0x9769,VR::CS,VM::VM1,"Iterative Reconstruction Method","IterativeReconstructionMethod",false }, {0x0018,0x9770,VR::CS,VM::VM1,"Attenuation Correction Temporal Relationship","AttenuationCorrectionTemporalRelationship",false }, {0x0018,0x9771,VR::SQ,VM::VM1,"Patient Physiological State Sequence","PatientPhysiologicalStateSequence",false }, {0x0018,0x9772,VR::SQ,VM::VM1,"Patient Physiological State Code Sequence","PatientPhysiologicalStateCodeSequence",false }, {0x0018,0x9801,VR::FD,VM::VM1_n,"Depth(s) of Focus","DepthsOfFocus",false }, {0x0018,0x9803,VR::SQ,VM::VM1,"Excluded Intervals Sequence","ExcludedIntervalsSequence",false }, {0x0018,0x9804,VR::DT,VM::VM1,"Exclusion Start DateTime","ExclusionStartDateTime",false }, {0x0018,0x9805,VR::FD,VM::VM1,"Exclusion Duration","ExclusionDuration",false }, {0x0018,0x9806,VR::SQ,VM::VM1,"US Image Description Sequence","USImageDescriptionSequence",false }, {0x0018,0x9807,VR::SQ,VM::VM1,"Image Data Type Sequence","ImageDataTypeSequence",false }, {0x0018,0x9808,VR::CS,VM::VM1,"Data Type","DataType",false }, {0x0018,0x9809,VR::SQ,VM::VM1,"Transducer Scan Pattern Code Sequence","TransducerScanPatternCodeSequence",false }, {0x0018,0x980b,VR::CS,VM::VM1,"Aliased Data Type","AliasedDataType",false }, {0x0018,0x980c,VR::CS,VM::VM1,"Position Measuring Device Used","PositionMeasuringDeviceUsed",false }, {0x0018,0x980d,VR::SQ,VM::VM1,"Transducer Geometry Code Sequence","TransducerGeometryCodeSequence",false }, {0x0018,0x980e,VR::SQ,VM::VM1,"Transducer Beam Steering Code Sequence","TransducerBeamSteeringCodeSequence",false }, {0x0018,0x980f,VR::SQ,VM::VM1,"Transducer Application Code Sequence","TransducerApplicationCodeSequence",false }, {0x0018,0x9810,VR::US_SS,VM::VM1,"Zero Velocity Pixel Value","ZeroVelocityPixelValue",false }, {0x0018,0x9900,VR::LO,VM::VM1,"Reference Location Label","ReferenceLocationLabel",false }, {0x0018,0x9901,VR::UT,VM::VM1,"Reference Location Description","ReferenceLocationDescription",false }, {0x0018,0x9902,VR::SQ,VM::VM1,"Reference Basis Code Sequence","ReferenceBasisCodeSequence",false }, {0x0018,0x9903,VR::SQ,VM::VM1,"Reference Geometry Code Sequence","ReferenceGeometryCodeSequence",false }, {0x0018,0x9904,VR::DS,VM::VM1,"Offset Distance","OffsetDistance",false }, {0x0018,0x9905,VR::CS,VM::VM1,"Offset Direction","OffsetDirection",false }, {0x0018,0x9906,VR::SQ,VM::VM1,"Potential Scheduled Protocol Code Sequence","PotentialScheduledProtocolCodeSequence",false }, {0x0018,0x9907,VR::SQ,VM::VM1,"Potential Requested Procedure Code Sequence","PotentialRequestedProcedureCodeSequence",false }, {0x0018,0x9908,VR::UC,VM::VM1_n,"Potential Reasons for Procedure","PotentialReasonsForProcedure",false }, {0x0018,0x9909,VR::SQ,VM::VM1,"Potential Reasons for Procedure Code Sequence","PotentialReasonsForProcedureCodeSequence",false }, {0x0018,0x990a,VR::UC,VM::VM1_n,"Potential Diagnostic Tasks","PotentialDiagnosticTasks",false }, {0x0018,0x990b,VR::SQ,VM::VM1,"Contraindications Code Sequence","ContraindicationsCodeSequence",false }, {0x0018,0x990c,VR::SQ,VM::VM1,"Referenced Defined Protocol Sequence","ReferencedDefinedProtocolSequence",false }, {0x0018,0x990d,VR::SQ,VM::VM1,"Referenced Performed Protocol Sequence","ReferencedPerformedProtocolSequence",false }, {0x0018,0x990e,VR::SQ,VM::VM1,"Predecessor Protocol Sequence","PredecessorProtocolSequence",false }, {0x0018,0x990f,VR::UT,VM::VM1,"Protocol Planning Information","ProtocolPlanningInformation",false }, {0x0018,0x9910,VR::UT,VM::VM1,"Protocol Design Rationale","ProtocolDesignRationale",false }, {0x0018,0x9911,VR::SQ,VM::VM1,"Patient Specification Sequence","PatientSpecificationSequence",false }, {0x0018,0x9912,VR::SQ,VM::VM1,"Model Specification Sequence","ModelSpecificationSequence",false }, {0x0018,0x9913,VR::SQ,VM::VM1,"Parameters Specification Sequence","ParametersSpecificationSequence",false }, {0x0018,0x9914,VR::SQ,VM::VM1,"Instruction Sequence","InstructionSequence",false }, {0x0018,0x9915,VR::US,VM::VM1,"Instruction Index","InstructionIndex",false }, {0x0018,0x9916,VR::LO,VM::VM1,"Instruction Text","InstructionText",false }, {0x0018,0x9917,VR::UT,VM::VM1,"Instruction Description","InstructionDescription",false }, {0x0018,0x9918,VR::CS,VM::VM1,"Instruction Performed Flag","InstructionPerformedFlag",false }, {0x0018,0x9919,VR::DT,VM::VM1,"Instruction Performed DateTime","InstructionPerformedDateTime",false }, {0x0018,0x991a,VR::UT,VM::VM1,"Instruction Performance Comment","InstructionPerformanceComment",false }, {0x0018,0x991b,VR::SQ,VM::VM1,"Patient Positioning Instruction Sequence","PatientPositioningInstructionSequence",false }, {0x0018,0x991c,VR::SQ,VM::VM1,"Positioning Method Code Sequence","PositioningMethodCodeSequence",false }, {0x0018,0x991d,VR::SQ,VM::VM1,"Positioning Landmark Sequence","PositioningLandmarkSequence",false }, {0x0018,0x991e,VR::UI,VM::VM1,"Target Frame of Reference UID","TargetFrameOfReferenceUID",false }, {0x0018,0x991f,VR::SQ,VM::VM1,"Acquisition Protocol Element Specification Sequence","AcquisitionProtocolElementSpecificationSequence",false }, {0x0018,0x9920,VR::SQ,VM::VM1,"Acquisition Protocol Element Sequence","AcquisitionProtocolElementSequence",false }, {0x0018,0x9921,VR::US,VM::VM1,"Protocol Element Number","ProtocolElementNumber",false }, {0x0018,0x9922,VR::LO,VM::VM1,"Protocol Element Name","ProtocolElementName",false }, {0x0018,0x9923,VR::UT,VM::VM1,"Protocol Element Characteristics Summary","ProtocolElementCharacteristicsSummary",false }, {0x0018,0x9924,VR::UT,VM::VM1,"Protocol Element Purpose","ProtocolElementPurpose",false }, {0x0018,0x9930,VR::CS,VM::VM1,"Acquisition Motion","AcquisitionMotion",false }, {0x0018,0x9931,VR::SQ,VM::VM1,"Acquisition Start Location Sequence","AcquisitionStartLocationSequence",false }, {0x0018,0x9932,VR::SQ,VM::VM1,"Acquisition End Location Sequence","AcquisitionEndLocationSequence",false }, {0x0018,0x9933,VR::SQ,VM::VM1,"Reconstruction Protocol Element Specification Sequence","ReconstructionProtocolElementSpecificationSequence",false }, {0x0018,0x9934,VR::SQ,VM::VM1,"Reconstruction Protocol Element Sequence","ReconstructionProtocolElementSequence",false }, {0x0018,0x9935,VR::SQ,VM::VM1,"Storage Protocol Element Specification Sequence","StorageProtocolElementSpecificationSequence",false }, {0x0018,0x9936,VR::SQ,VM::VM1,"Storage Protocol Element Sequence","StorageProtocolElementSequence",false }, {0x0018,0x9937,VR::LO,VM::VM1,"Requested Series Description","RequestedSeriesDescription",false }, {0x0018,0x9938,VR::US,VM::VM1_n,"Source Acquisition Protocol Element Number","SourceAcquisitionProtocolElementNumber",false }, {0x0018,0x9939,VR::US,VM::VM1_n,"Source Acquisition Beam Number","SourceAcquisitionBeamNumber",false }, {0x0018,0x993a,VR::US,VM::VM1_n,"Source Reconstruction Protocol Element Number","SourceReconstructionProtocolElementNumber",false }, {0x0018,0x993b,VR::SQ,VM::VM1,"Reconstruction Start Location Sequence","ReconstructionStartLocationSequence",false }, {0x0018,0x993c,VR::SQ,VM::VM1,"Reconstruction End Location Sequence","ReconstructionEndLocationSequence",false }, {0x0018,0x993d,VR::SQ,VM::VM1,"Reconstruction Algorithm Sequence","ReconstructionAlgorithmSequence",false }, {0x0018,0x993e,VR::SQ,VM::VM1,"Reconstruction Target Center Location Sequence","ReconstructionTargetCenterLocationSequence",false }, {0x0018,0x9941,VR::UT,VM::VM1,"Image Filter Description","ImageFilterDescription",false }, {0x0018,0x9942,VR::FD,VM::VM1,"CTDIvol Notification Trigger","CTDIvolNotificationTrigger",false }, {0x0018,0x9943,VR::FD,VM::VM1,"DLP Notification Trigger","DLPNotificationTrigger",false }, {0x0018,0x9944,VR::CS,VM::VM1,"Auto KVP Selection Type","AutoKVPSelectionType",false }, {0x0018,0x9945,VR::FD,VM::VM1,"Auto KVP Upper Bound","AutoKVPUpperBound",false }, {0x0018,0x9946,VR::FD,VM::VM1,"Auto KVP Lower Bound","AutoKVPLowerBound",false }, {0x0018,0x9947,VR::CS,VM::VM1,"Protocol Defined Patient Position","ProtocolDefinedPatientPosition",false }, {0x0018,0xa001,VR::SQ,VM::VM1,"Contributing Equipment Sequence","ContributingEquipmentSequence",false }, {0x0018,0xa002,VR::DT,VM::VM1,"Contribution DateTime","ContributionDateTime",false }, {0x0018,0xa003,VR::ST,VM::VM1,"Contribution Description","ContributionDescription",false }, {0x0020,0x000d,VR::UI,VM::VM1,"Study Instance UID","StudyInstanceUID",false }, {0x0020,0x000e,VR::UI,VM::VM1,"Series Instance UID","SeriesInstanceUID",false }, {0x0020,0x0010,VR::SH,VM::VM1,"Study ID","StudyID",false }, {0x0020,0x0011,VR::IS,VM::VM1,"Series Number","SeriesNumber",false }, {0x0020,0x0012,VR::IS,VM::VM1,"Acquisition Number","AcquisitionNumber",false }, {0x0020,0x0013,VR::IS,VM::VM1,"Instance Number","InstanceNumber",false }, {0x0020,0x0014,VR::IS,VM::VM1,"Isotope Number","IsotopeNumber",true }, {0x0020,0x0015,VR::IS,VM::VM1,"Phase Number","PhaseNumber",true }, {0x0020,0x0016,VR::IS,VM::VM1,"Interval Number","IntervalNumber",true }, {0x0020,0x0017,VR::IS,VM::VM1,"Time Slot Number","TimeSlotNumber",true }, {0x0020,0x0018,VR::IS,VM::VM1,"Angle Number","AngleNumber",true }, {0x0020,0x0019,VR::IS,VM::VM1,"Item Number","ItemNumber",false }, {0x0020,0x0020,VR::CS,VM::VM2,"Patient Orientation","PatientOrientation",false }, {0x0020,0x0022,VR::IS,VM::VM1,"Overlay Number","OverlayNumber",true }, {0x0020,0x0024,VR::IS,VM::VM1,"Curve Number","CurveNumber",true }, {0x0020,0x0026,VR::IS,VM::VM1,"LUT Number","LUTNumber",true }, {0x0020,0x0030,VR::DS,VM::VM3,"Image Position","ImagePosition",true }, {0x0020,0x0032,VR::DS,VM::VM3,"Image Position (Patient)","ImagePositionPatient",false }, {0x0020,0x0035,VR::DS,VM::VM6,"Image Orientation","ImageOrientation",true }, {0x0020,0x0037,VR::DS,VM::VM6,"Image Orientation (Patient)","ImageOrientationPatient",false }, {0x0020,0x0050,VR::DS,VM::VM1,"Location","Location",true }, {0x0020,0x0052,VR::UI,VM::VM1,"Frame of Reference UID","FrameOfReferenceUID",false }, {0x0020,0x0060,VR::CS,VM::VM1,"Laterality","Laterality",false }, {0x0020,0x0062,VR::CS,VM::VM1,"Image Laterality","ImageLaterality",false }, {0x0020,0x0070,VR::LO,VM::VM1,"Image Geometry Type","ImageGeometryType",true }, {0x0020,0x0080,VR::CS,VM::VM1_n,"Masking Image","MaskingImage",true }, {0x0020,0x00aa,VR::IS,VM::VM1,"Report Number","ReportNumber",true }, {0x0020,0x0100,VR::IS,VM::VM1,"Temporal Position Identifier","TemporalPositionIdentifier",false }, {0x0020,0x0105,VR::IS,VM::VM1,"Number of Temporal Positions","NumberOfTemporalPositions",false }, {0x0020,0x0110,VR::DS,VM::VM1,"Temporal Resolution","TemporalResolution",false }, {0x0020,0x0200,VR::UI,VM::VM1,"Synchronization Frame of Reference UID","SynchronizationFrameOfReferenceUID",false }, {0x0020,0x0242,VR::UI,VM::VM1,"SOP Instance UID of Concatenation Source","SOPInstanceUIDOfConcatenationSource",false }, {0x0020,0x1000,VR::IS,VM::VM1,"Series in Study","SeriesInStudy",true }, {0x0020,0x1001,VR::IS,VM::VM1,"Acquisitions in Series","AcquisitionsInSeries",true }, {0x0020,0x1002,VR::IS,VM::VM1,"Images in Acquisition","ImagesInAcquisition",false }, {0x0020,0x1003,VR::IS,VM::VM1,"Images in Series","ImagesInSeries",true }, {0x0020,0x1004,VR::IS,VM::VM1,"Acquisitions in Study","AcquisitionsInStudy",true }, {0x0020,0x1005,VR::IS,VM::VM1,"Images in Study","ImagesInStudy",true }, {0x0020,0x1020,VR::LO,VM::VM1_n,"Reference","Reference",true }, {0x0020,0x103f,VR::LO,VM::VM1,"Target Position Reference Indicator","TargetPositionReferenceIndicator",false }, {0x0020,0x1040,VR::LO,VM::VM1,"Position Reference Indicator","PositionReferenceIndicator",false }, {0x0020,0x1041,VR::DS,VM::VM1,"Slice Location","SliceLocation",false }, {0x0020,0x1070,VR::IS,VM::VM1_n,"Other Study Numbers","OtherStudyNumbers",true }, {0x0020,0x1200,VR::IS,VM::VM1,"Number of Patient Related Studies","NumberOfPatientRelatedStudies",false }, {0x0020,0x1202,VR::IS,VM::VM1,"Number of Patient Related Series","NumberOfPatientRelatedSeries",false }, {0x0020,0x1204,VR::IS,VM::VM1,"Number of Patient Related Instances","NumberOfPatientRelatedInstances",false }, {0x0020,0x1206,VR::IS,VM::VM1,"Number of Study Related Series","NumberOfStudyRelatedSeries",false }, {0x0020,0x1208,VR::IS,VM::VM1,"Number of Study Related Instances","NumberOfStudyRelatedInstances",false }, {0x0020,0x1209,VR::IS,VM::VM1,"Number of Series Related Instances","NumberOfSeriesRelatedInstances",false }, {0x0020,0x3100,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3101,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3102,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3103,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3104,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3105,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3106,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3107,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3108,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3109,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x310a,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x310b,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x310c,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x310d,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x310e,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x310f,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3110,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3111,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3112,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3113,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3114,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3115,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3116,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3117,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3118,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3119,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x311a,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x311b,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x311c,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x311d,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x311e,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x311f,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3120,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3121,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3122,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3123,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3124,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3125,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3126,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3127,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3128,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3129,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x312a,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x312b,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x312c,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x312d,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x312e,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x312f,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3130,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3131,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3132,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3133,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3134,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3135,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3136,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3137,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3138,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3139,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x313a,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x313b,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x313c,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x313d,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x313e,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x313f,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3140,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3141,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3142,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3143,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3144,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3145,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3146,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3147,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3148,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3149,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x314a,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x314b,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x314c,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x314d,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x314e,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x314f,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3150,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3151,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3152,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3153,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3154,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3155,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3156,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3157,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3158,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3159,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x315a,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x315b,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x315c,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x315d,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x315e,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x315f,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3160,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3161,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3162,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3163,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3164,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3165,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3166,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3167,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3168,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3169,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x316a,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x316b,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x316c,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x316d,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x316e,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x316f,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3170,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3171,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3172,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3173,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3174,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3175,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3176,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3177,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3178,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3179,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x317a,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x317b,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x317c,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x317d,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x317e,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x317f,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3180,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3181,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3182,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3183,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3184,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3185,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3186,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3187,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3188,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3189,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x318a,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x318b,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x318c,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x318d,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x318e,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x318f,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3190,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3191,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3192,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3193,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3194,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3195,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3196,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3197,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3198,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3199,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x319a,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x319b,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x319c,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x319d,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x319e,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x319f,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31a0,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31a1,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31a2,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31a3,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31a4,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31a5,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31a6,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31a7,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31a8,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31a9,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31aa,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31ab,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31ac,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31ad,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31ae,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31af,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31b0,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31b1,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31b2,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31b3,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31b4,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31b5,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31b6,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31b7,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31b8,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31b9,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31ba,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31bb,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31bc,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31bd,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31be,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31bf,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31c0,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31c1,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31c2,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31c3,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31c4,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31c5,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31c6,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31c7,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31c8,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31c9,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31ca,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31cb,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31cc,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31cd,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31ce,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31cf,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31d0,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31d1,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31d2,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31d3,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31d4,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31d5,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31d6,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31d7,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31d8,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31d9,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31da,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31db,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31dc,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31dd,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31de,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31df,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31e0,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31e1,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31e2,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31e3,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31e4,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31e5,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31e6,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31e7,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31e8,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31e9,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31ea,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31eb,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31ec,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31ed,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31ee,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31ef,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31f0,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31f1,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31f2,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31f3,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31f4,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31f5,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31f6,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31f7,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31f8,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31f9,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31fa,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31fb,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31fc,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31fd,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31fe,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x31ff,VR::CS,VM::VM1_n,"Source Image IDs","SourceImageIDs",true }, {0x0020,0x3401,VR::CS,VM::VM1,"Modifying Device ID","ModifyingDeviceID",true }, {0x0020,0x3402,VR::CS,VM::VM1,"Modified Image ID","ModifiedImageID",true }, {0x0020,0x3403,VR::DA,VM::VM1,"Modified Image Date","ModifiedImageDate",true }, {0x0020,0x3404,VR::LO,VM::VM1,"Modifying Device Manufacturer","ModifyingDeviceManufacturer",true }, {0x0020,0x3405,VR::TM,VM::VM1,"Modified Image Time","ModifiedImageTime",true }, {0x0020,0x3406,VR::LO,VM::VM1,"Modified Image Description","ModifiedImageDescription",true }, {0x0020,0x4000,VR::LT,VM::VM1,"Image Comments","ImageComments",false }, {0x0020,0x5000,VR::AT,VM::VM1_n,"Original Image Identification","OriginalImageIdentification",true }, {0x0020,0x5002,VR::LO,VM::VM1_n,"Original Image Identification Nomenclature","OriginalImageIdentificationNomenclature",true }, {0x0020,0x9056,VR::SH,VM::VM1,"Stack ID","StackID",false }, {0x0020,0x9057,VR::UL,VM::VM1,"In-Stack Position Number","InStackPositionNumber",false }, {0x0020,0x9071,VR::SQ,VM::VM1,"Frame Anatomy Sequence","FrameAnatomySequence",false }, {0x0020,0x9072,VR::CS,VM::VM1,"Frame Laterality","FrameLaterality",false }, {0x0020,0x9111,VR::SQ,VM::VM1,"Frame Content Sequence","FrameContentSequence",false }, {0x0020,0x9113,VR::SQ,VM::VM1,"Plane Position Sequence","PlanePositionSequence",false }, {0x0020,0x9116,VR::SQ,VM::VM1,"Plane Orientation Sequence","PlaneOrientationSequence",false }, {0x0020,0x9128,VR::UL,VM::VM1,"Temporal Position Index","TemporalPositionIndex",false }, {0x0020,0x9153,VR::FD,VM::VM1,"Nominal Cardiac Trigger Delay Time","NominalCardiacTriggerDelayTime",false }, {0x0020,0x9154,VR::FL,VM::VM1,"Nominal Cardiac Trigger Time Prior To R-Peak","NominalCardiacTriggerTimePriorToRPeak",false }, {0x0020,0x9155,VR::FL,VM::VM1,"Actual Cardiac Trigger Time Prior To R-Peak","ActualCardiacTriggerTimePriorToRPeak",false }, {0x0020,0x9156,VR::US,VM::VM1,"Frame Acquisition Number","FrameAcquisitionNumber",false }, {0x0020,0x9157,VR::UL,VM::VM1_n,"Dimension Index Values","DimensionIndexValues",false }, {0x0020,0x9158,VR::LT,VM::VM1,"Frame Comments","FrameComments",false }, {0x0020,0x9161,VR::UI,VM::VM1,"Concatenation UID","ConcatenationUID",false }, {0x0020,0x9162,VR::US,VM::VM1,"In-concatenation Number","InConcatenationNumber",false }, {0x0020,0x9163,VR::US,VM::VM1,"In-concatenation Total Number","InConcatenationTotalNumber",false }, {0x0020,0x9164,VR::UI,VM::VM1,"Dimension Organization UID","DimensionOrganizationUID",false }, {0x0020,0x9165,VR::AT,VM::VM1,"Dimension Index Pointer","DimensionIndexPointer",false }, {0x0020,0x9167,VR::AT,VM::VM1,"Functional Group Pointer","FunctionalGroupPointer",false }, {0x0020,0x9170,VR::SQ,VM::VM1,"Unassigned Shared Converted Attributes Sequence","UnassignedSharedConvertedAttributesSequence",false }, {0x0020,0x9171,VR::SQ,VM::VM1,"Unassigned Per-Frame Converted Attributes Sequence","UnassignedPerFrameConvertedAttributesSequence",false }, {0x0020,0x9172,VR::SQ,VM::VM1,"Conversion Source Attributes Sequence","ConversionSourceAttributesSequence",false }, {0x0020,0x9213,VR::LO,VM::VM1,"Dimension Index Private Creator","DimensionIndexPrivateCreator",false }, {0x0020,0x9221,VR::SQ,VM::VM1,"Dimension Organization Sequence","DimensionOrganizationSequence",false }, {0x0020,0x9222,VR::SQ,VM::VM1,"Dimension Index Sequence","DimensionIndexSequence",false }, {0x0020,0x9228,VR::UL,VM::VM1,"Concatenation Frame Offset Number","ConcatenationFrameOffsetNumber",false }, {0x0020,0x9238,VR::LO,VM::VM1,"Functional Group Private Creator","FunctionalGroupPrivateCreator",false }, {0x0020,0x9241,VR::FL,VM::VM1,"Nominal Percentage of Cardiac Phase","NominalPercentageOfCardiacPhase",false }, {0x0020,0x9245,VR::FL,VM::VM1,"Nominal Percentage of Respiratory Phase","NominalPercentageOfRespiratoryPhase",false }, {0x0020,0x9246,VR::FL,VM::VM1,"Starting Respiratory Amplitude","StartingRespiratoryAmplitude",false }, {0x0020,0x9247,VR::CS,VM::VM1,"Starting Respiratory Phase","StartingRespiratoryPhase",false }, {0x0020,0x9248,VR::FL,VM::VM1,"Ending Respiratory Amplitude","EndingRespiratoryAmplitude",false }, {0x0020,0x9249,VR::CS,VM::VM1,"Ending Respiratory Phase","EndingRespiratoryPhase",false }, {0x0020,0x9250,VR::CS,VM::VM1,"Respiratory Trigger Type","RespiratoryTriggerType",false }, {0x0020,0x9251,VR::FD,VM::VM1,"R-R Interval Time Nominal","RRIntervalTimeNominal",false }, {0x0020,0x9252,VR::FD,VM::VM1,"Actual Cardiac Trigger Delay Time","ActualCardiacTriggerDelayTime",false }, {0x0020,0x9253,VR::SQ,VM::VM1,"Respiratory Synchronization Sequence","RespiratorySynchronizationSequence",false }, {0x0020,0x9254,VR::FD,VM::VM1,"Respiratory Interval Time","RespiratoryIntervalTime",false }, {0x0020,0x9255,VR::FD,VM::VM1,"Nominal Respiratory Trigger Delay Time","NominalRespiratoryTriggerDelayTime",false }, {0x0020,0x9256,VR::FD,VM::VM1,"Respiratory Trigger Delay Threshold","RespiratoryTriggerDelayThreshold",false }, {0x0020,0x9257,VR::FD,VM::VM1,"Actual Respiratory Trigger Delay Time","ActualRespiratoryTriggerDelayTime",false }, {0x0020,0x9301,VR::FD,VM::VM3,"Image Position (Volume)","ImagePositionVolume",false }, {0x0020,0x9302,VR::FD,VM::VM6,"Image Orientation (Volume)","ImageOrientationVolume",false }, {0x0020,0x9307,VR::CS,VM::VM1,"Ultrasound Acquisition Geometry","UltrasoundAcquisitionGeometry",false }, {0x0020,0x9308,VR::FD,VM::VM3,"Apex Position","ApexPosition",false }, {0x0020,0x9309,VR::FD,VM::VM16,"Volume to Transducer Mapping Matrix","VolumeToTransducerMappingMatrix",false }, {0x0020,0x930a,VR::FD,VM::VM16,"Volume to Table Mapping Matrix","VolumeToTableMappingMatrix",false }, {0x0020,0x930b,VR::CS,VM::VM1,"Volume to Transducer Relationship","VolumeToTransducerRelationship",false }, {0x0020,0x930c,VR::CS,VM::VM1,"Patient Frame of Reference Source","PatientFrameOfReferenceSource",false }, {0x0020,0x930d,VR::FD,VM::VM1,"Temporal Position Time Offset","TemporalPositionTimeOffset",false }, {0x0020,0x930e,VR::SQ,VM::VM1,"Plane Position (Volume) Sequence","PlanePositionVolumeSequence",false }, {0x0020,0x930f,VR::SQ,VM::VM1,"Plane Orientation (Volume) Sequence","PlaneOrientationVolumeSequence",false }, {0x0020,0x9310,VR::SQ,VM::VM1,"Temporal Position Sequence","TemporalPositionSequence",false }, {0x0020,0x9311,VR::CS,VM::VM1,"Dimension Organization Type","DimensionOrganizationType",false }, {0x0020,0x9312,VR::UI,VM::VM1,"Volume Frame of Reference UID","VolumeFrameOfReferenceUID",false }, {0x0020,0x9313,VR::UI,VM::VM1,"Table Frame of Reference UID","TableFrameOfReferenceUID",false }, {0x0020,0x9421,VR::LO,VM::VM1,"Dimension Description Label","DimensionDescriptionLabel",false }, {0x0020,0x9450,VR::SQ,VM::VM1,"Patient Orientation in Frame Sequence","PatientOrientationInFrameSequence",false }, {0x0020,0x9453,VR::LO,VM::VM1,"Frame Label","FrameLabel",false }, {0x0020,0x9518,VR::US,VM::VM1_n,"Acquisition Index","AcquisitionIndex",false }, {0x0020,0x9529,VR::SQ,VM::VM1,"Contributing SOP Instances Reference Sequence","ContributingSOPInstancesReferenceSequence",false }, {0x0020,0x9536,VR::US,VM::VM1,"Reconstruction Index","ReconstructionIndex",false }, {0x0022,0x0001,VR::US,VM::VM1,"Light Path Filter Pass-Through Wavelength","LightPathFilterPassThroughWavelength",false }, {0x0022,0x0002,VR::US,VM::VM2,"Light Path Filter Pass Band","LightPathFilterPassBand",false }, {0x0022,0x0003,VR::US,VM::VM1,"Image Path Filter Pass-Through Wavelength","ImagePathFilterPassThroughWavelength",false }, {0x0022,0x0004,VR::US,VM::VM2,"Image Path Filter Pass Band","ImagePathFilterPassBand",false }, {0x0022,0x0005,VR::CS,VM::VM1,"Patient Eye Movement Commanded","PatientEyeMovementCommanded",false }, {0x0022,0x0006,VR::SQ,VM::VM1,"Patient Eye Movement Command Code Sequence","PatientEyeMovementCommandCodeSequence",false }, {0x0022,0x0007,VR::FL,VM::VM1,"Spherical Lens Power","SphericalLensPower",false }, {0x0022,0x0008,VR::FL,VM::VM1,"Cylinder Lens Power","CylinderLensPower",false }, {0x0022,0x0009,VR::FL,VM::VM1,"Cylinder Axis","CylinderAxis",false }, {0x0022,0x000a,VR::FL,VM::VM1,"Emmetropic Magnification","EmmetropicMagnification",false }, {0x0022,0x000b,VR::FL,VM::VM1,"Intra Ocular Pressure","IntraOcularPressure",false }, {0x0022,0x000c,VR::FL,VM::VM1,"Horizontal Field of View","HorizontalFieldOfView",false }, {0x0022,0x000d,VR::CS,VM::VM1,"Pupil Dilated","PupilDilated",false }, {0x0022,0x000e,VR::FL,VM::VM1,"Degree of Dilation","DegreeOfDilation",false }, {0x0022,0x0010,VR::FL,VM::VM1,"Stereo Baseline Angle","StereoBaselineAngle",false }, {0x0022,0x0011,VR::FL,VM::VM1,"Stereo Baseline Displacement","StereoBaselineDisplacement",false }, {0x0022,0x0012,VR::FL,VM::VM1,"Stereo Horizontal Pixel Offset","StereoHorizontalPixelOffset",false }, {0x0022,0x0013,VR::FL,VM::VM1,"Stereo Vertical Pixel Offset","StereoVerticalPixelOffset",false }, {0x0022,0x0014,VR::FL,VM::VM1,"Stereo Rotation","StereoRotation",false }, {0x0022,0x0015,VR::SQ,VM::VM1,"Acquisition Device Type Code Sequence","AcquisitionDeviceTypeCodeSequence",false }, {0x0022,0x0016,VR::SQ,VM::VM1,"Illumination Type Code Sequence","IlluminationTypeCodeSequence",false }, {0x0022,0x0017,VR::SQ,VM::VM1,"Light Path Filter Type Stack Code Sequence","LightPathFilterTypeStackCodeSequence",false }, {0x0022,0x0018,VR::SQ,VM::VM1,"Image Path Filter Type Stack Code Sequence","ImagePathFilterTypeStackCodeSequence",false }, {0x0022,0x0019,VR::SQ,VM::VM1,"Lenses Code Sequence","LensesCodeSequence",false }, {0x0022,0x001a,VR::SQ,VM::VM1,"Channel Description Code Sequence","ChannelDescriptionCodeSequence",false }, {0x0022,0x001b,VR::SQ,VM::VM1,"Refractive State Sequence","RefractiveStateSequence",false }, {0x0022,0x001c,VR::SQ,VM::VM1,"Mydriatic Agent Code Sequence","MydriaticAgentCodeSequence",false }, {0x0022,0x001d,VR::SQ,VM::VM1,"Relative Image Position Code Sequence","RelativeImagePositionCodeSequence",false }, {0x0022,0x001e,VR::FL,VM::VM1,"Camera Angle of View","CameraAngleOfView",false }, {0x0022,0x0020,VR::SQ,VM::VM1,"Stereo Pairs Sequence","StereoPairsSequence",false }, {0x0022,0x0021,VR::SQ,VM::VM1,"Left Image Sequence","LeftImageSequence",false }, {0x0022,0x0022,VR::SQ,VM::VM1,"Right Image Sequence","RightImageSequence",false }, {0x0022,0x0028,VR::CS,VM::VM1,"Stereo Pairs Present","StereoPairsPresent",false }, {0x0022,0x0030,VR::FL,VM::VM1,"Axial Length of the Eye","AxialLengthOfTheEye",false }, {0x0022,0x0031,VR::SQ,VM::VM1,"Ophthalmic Frame Location Sequence","OphthalmicFrameLocationSequence",false }, {0x0022,0x0032,VR::FL,VM::VM2_2n,"Reference Coordinates","ReferenceCoordinates",false }, {0x0022,0x0035,VR::FL,VM::VM1,"Depth Spatial Resolution","DepthSpatialResolution",false }, {0x0022,0x0036,VR::FL,VM::VM1,"Maximum Depth Distortion","MaximumDepthDistortion",false }, {0x0022,0x0037,VR::FL,VM::VM1,"Along-scan Spatial Resolution","AlongScanSpatialResolution",false }, {0x0022,0x0038,VR::FL,VM::VM1,"Maximum Along-scan Distortion","MaximumAlongScanDistortion",false }, {0x0022,0x0039,VR::CS,VM::VM1,"Ophthalmic Image Orientation","OphthalmicImageOrientation",false }, {0x0022,0x0041,VR::FL,VM::VM1,"Depth of Transverse Image","DepthOfTransverseImage",false }, {0x0022,0x0042,VR::SQ,VM::VM1,"Mydriatic Agent Concentration Units Sequence","MydriaticAgentConcentrationUnitsSequence",false }, {0x0022,0x0048,VR::FL,VM::VM1,"Across-scan Spatial Resolution","AcrossScanSpatialResolution",false }, {0x0022,0x0049,VR::FL,VM::VM1,"Maximum Across-scan Distortion","MaximumAcrossScanDistortion",false }, {0x0022,0x004e,VR::DS,VM::VM1,"Mydriatic Agent Concentration","MydriaticAgentConcentration",false }, {0x0022,0x0055,VR::FL,VM::VM1,"Illumination Wave Length","IlluminationWaveLength",false }, {0x0022,0x0056,VR::FL,VM::VM1,"Illumination Power","IlluminationPower",false }, {0x0022,0x0057,VR::FL,VM::VM1,"Illumination Bandwidth","IlluminationBandwidth",false }, {0x0022,0x0058,VR::SQ,VM::VM1,"Mydriatic Agent Sequence","MydriaticAgentSequence",false }, {0x0022,0x1007,VR::SQ,VM::VM1,"Ophthalmic Axial Measurements Right Eye Sequence","OphthalmicAxialMeasurementsRightEyeSequence",false }, {0x0022,0x1008,VR::SQ,VM::VM1,"Ophthalmic Axial Measurements Left Eye Sequence","OphthalmicAxialMeasurementsLeftEyeSequence",false }, {0x0022,0x1009,VR::CS,VM::VM1,"Ophthalmic Axial Measurements Device Type","OphthalmicAxialMeasurementsDeviceType",false }, {0x0022,0x1010,VR::CS,VM::VM1,"Ophthalmic Axial Length Measurements Type","OphthalmicAxialLengthMeasurementsType",false }, {0x0022,0x1012,VR::SQ,VM::VM1,"Ophthalmic Axial Length Sequence","OphthalmicAxialLengthSequence",false }, {0x0022,0x1019,VR::FL,VM::VM1,"Ophthalmic Axial Length","OphthalmicAxialLength",false }, {0x0022,0x1024,VR::SQ,VM::VM1,"Lens Status Code Sequence","LensStatusCodeSequence",false }, {0x0022,0x1025,VR::SQ,VM::VM1,"Vitreous Status Code Sequence","VitreousStatusCodeSequence",false }, {0x0022,0x1028,VR::SQ,VM::VM1,"IOL Formula Code Sequence","IOLFormulaCodeSequence",false }, {0x0022,0x1029,VR::LO,VM::VM1,"IOL Formula Detail","IOLFormulaDetail",false }, {0x0022,0x1033,VR::FL,VM::VM1,"Keratometer Index","KeratometerIndex",false }, {0x0022,0x1035,VR::SQ,VM::VM1,"Source of Ophthalmic Axial Length Code Sequence","SourceOfOphthalmicAxialLengthCodeSequence",false }, {0x0022,0x1037,VR::FL,VM::VM1,"Target Refraction","TargetRefraction",false }, {0x0022,0x1039,VR::CS,VM::VM1,"Refractive Procedure Occurred","RefractiveProcedureOccurred",false }, {0x0022,0x1040,VR::SQ,VM::VM1,"Refractive Surgery Type Code Sequence","RefractiveSurgeryTypeCodeSequence",false }, {0x0022,0x1044,VR::SQ,VM::VM1,"Ophthalmic Ultrasound Method Code Sequence","OphthalmicUltrasoundMethodCodeSequence",false }, {0x0022,0x1050,VR::SQ,VM::VM1,"Ophthalmic Axial Length Measurements Sequence","OphthalmicAxialLengthMeasurementsSequence",false }, {0x0022,0x1053,VR::FL,VM::VM1,"IOL Power","IOLPower",false }, {0x0022,0x1054,VR::FL,VM::VM1,"Predicted Refractive Error","PredictedRefractiveError",false }, {0x0022,0x1059,VR::FL,VM::VM1,"Ophthalmic Axial Length Velocity","OphthalmicAxialLengthVelocity",false }, {0x0022,0x1065,VR::LO,VM::VM1,"Lens Status Description","LensStatusDescription",false }, {0x0022,0x1066,VR::LO,VM::VM1,"Vitreous Status Description","VitreousStatusDescription",false }, {0x0022,0x1090,VR::SQ,VM::VM1,"IOL Power Sequence","IOLPowerSequence",false }, {0x0022,0x1092,VR::SQ,VM::VM1,"Lens Constant Sequence","LensConstantSequence",false }, {0x0022,0x1093,VR::LO,VM::VM1,"IOL Manufacturer","IOLManufacturer",false }, {0x0022,0x1094,VR::LO,VM::VM1,"Lens Constant Description","LensConstantDescription",true }, {0x0022,0x1095,VR::LO,VM::VM1,"Implant Name","ImplantName",false }, {0x0022,0x1096,VR::SQ,VM::VM1,"Keratometry Measurement Type Code Sequence","KeratometryMeasurementTypeCodeSequence",false }, {0x0022,0x1097,VR::LO,VM::VM1,"Implant Part Number","ImplantPartNumber",false }, {0x0022,0x1100,VR::SQ,VM::VM1,"Referenced Ophthalmic Axial Measurements Sequence","ReferencedOphthalmicAxialMeasurementsSequence",false }, {0x0022,0x1101,VR::SQ,VM::VM1,"Ophthalmic Axial Length Measurements Segment Name Code Sequence","OphthalmicAxialLengthMeasurementsSegmentNameCodeSequence",false }, {0x0022,0x1103,VR::SQ,VM::VM1,"Refractive Error Before Refractive Surgery Code Sequence","RefractiveErrorBeforeRefractiveSurgeryCodeSequence",false }, {0x0022,0x1121,VR::FL,VM::VM1,"IOL Power For Exact Emmetropia","IOLPowerForExactEmmetropia",false }, {0x0022,0x1122,VR::FL,VM::VM1,"IOL Power For Exact Target Refraction","IOLPowerForExactTargetRefraction",false }, {0x0022,0x1125,VR::SQ,VM::VM1,"Anterior Chamber Depth Definition Code Sequence","AnteriorChamberDepthDefinitionCodeSequence",false }, {0x0022,0x1127,VR::SQ,VM::VM1,"Lens Thickness Sequence","LensThicknessSequence",false }, {0x0022,0x1128,VR::SQ,VM::VM1,"Anterior Chamber Depth Sequence","AnteriorChamberDepthSequence",false }, {0x0022,0x1130,VR::FL,VM::VM1,"Lens Thickness","LensThickness",false }, {0x0022,0x1131,VR::FL,VM::VM1,"Anterior Chamber Depth","AnteriorChamberDepth",false }, {0x0022,0x1132,VR::SQ,VM::VM1,"Source of Lens Thickness Data Code Sequence","SourceOfLensThicknessDataCodeSequence",false }, {0x0022,0x1133,VR::SQ,VM::VM1,"Source of Anterior Chamber Depth Data Code Sequence","SourceOfAnteriorChamberDepthDataCodeSequence",false }, {0x0022,0x1134,VR::SQ,VM::VM1,"Source of Refractive Measurements Sequence","SourceOfRefractiveMeasurementsSequence",false }, {0x0022,0x1135,VR::SQ,VM::VM1,"Source of Refractive Measurements Code Sequence","SourceOfRefractiveMeasurementsCodeSequence",false }, {0x0022,0x1140,VR::CS,VM::VM1,"Ophthalmic Axial Length Measurement Modified","OphthalmicAxialLengthMeasurementModified",false }, {0x0022,0x1150,VR::SQ,VM::VM1,"Ophthalmic Axial Length Data Source Code Sequence","OphthalmicAxialLengthDataSourceCodeSequence",false }, {0x0022,0x1153,VR::SQ,VM::VM1,"Ophthalmic Axial Length Acquisition Method Code Sequence","OphthalmicAxialLengthAcquisitionMethodCodeSequence",true }, {0x0022,0x1155,VR::FL,VM::VM1,"Signal to Noise Ratio","SignalToNoiseRatio",false }, {0x0022,0x1159,VR::LO,VM::VM1,"Ophthalmic Axial Length Data Source Description","OphthalmicAxialLengthDataSourceDescription",false }, {0x0022,0x1210,VR::SQ,VM::VM1,"Ophthalmic Axial Length Measurements Total Length Sequence","OphthalmicAxialLengthMeasurementsTotalLengthSequence",false }, {0x0022,0x1211,VR::SQ,VM::VM1,"Ophthalmic Axial Length Measurements Segmental Length Sequence","OphthalmicAxialLengthMeasurementsSegmentalLengthSequence",false }, {0x0022,0x1212,VR::SQ,VM::VM1,"Ophthalmic Axial Length Measurements Length Summation Sequence","OphthalmicAxialLengthMeasurementsLengthSummationSequence",false }, {0x0022,0x1220,VR::SQ,VM::VM1,"Ultrasound Ophthalmic Axial Length Measurements Sequence","UltrasoundOphthalmicAxialLengthMeasurementsSequence",false }, {0x0022,0x1225,VR::SQ,VM::VM1,"Optical Ophthalmic Axial Length Measurements Sequence","OpticalOphthalmicAxialLengthMeasurementsSequence",false }, {0x0022,0x1230,VR::SQ,VM::VM1,"Ultrasound Selected Ophthalmic Axial Length Sequence","UltrasoundSelectedOphthalmicAxialLengthSequence",false }, {0x0022,0x1250,VR::SQ,VM::VM1,"Ophthalmic Axial Length Selection Method Code Sequence","OphthalmicAxialLengthSelectionMethodCodeSequence",false }, {0x0022,0x1255,VR::SQ,VM::VM1,"Optical Selected Ophthalmic Axial Length Sequence","OpticalSelectedOphthalmicAxialLengthSequence",false }, {0x0022,0x1257,VR::SQ,VM::VM1,"Selected Segmental Ophthalmic Axial Length Sequence","SelectedSegmentalOphthalmicAxialLengthSequence",false }, {0x0022,0x1260,VR::SQ,VM::VM1,"Selected Total Ophthalmic Axial Length Sequence","SelectedTotalOphthalmicAxialLengthSequence",false }, {0x0022,0x1262,VR::SQ,VM::VM1,"Ophthalmic Axial Length Quality Metric Sequence","OphthalmicAxialLengthQualityMetricSequence",false }, {0x0022,0x1265,VR::SQ,VM::VM1,"Ophthalmic Axial Length Quality Metric Type Code Sequence","OphthalmicAxialLengthQualityMetricTypeCodeSequence",true }, {0x0022,0x1273,VR::LO,VM::VM1,"Ophthalmic Axial Length Quality Metric Type Description","OphthalmicAxialLengthQualityMetricTypeDescription",true }, {0x0022,0x1300,VR::SQ,VM::VM1,"Intraocular Lens Calculations Right Eye Sequence","IntraocularLensCalculationsRightEyeSequence",false }, {0x0022,0x1310,VR::SQ,VM::VM1,"Intraocular Lens Calculations Left Eye Sequence","IntraocularLensCalculationsLeftEyeSequence",false }, {0x0022,0x1330,VR::SQ,VM::VM1,"Referenced Ophthalmic Axial Length Measurement QC Image Sequence","ReferencedOphthalmicAxialLengthMeasurementQCImageSequence",false }, {0x0022,0x1415,VR::CS,VM::VM1,"Ophthalmic Mapping Device Type","OphthalmicMappingDeviceType",false }, {0x0022,0x1420,VR::SQ,VM::VM1,"Acquisition Method Code Sequence","AcquisitionMethodCodeSequence",false }, {0x0022,0x1423,VR::SQ,VM::VM1,"Acquisition Method Algorithm Sequence","AcquisitionMethodAlgorithmSequence",false }, {0x0022,0x1436,VR::SQ,VM::VM1,"Ophthalmic Thickness Map Type Code Sequence","OphthalmicThicknessMapTypeCodeSequence",false }, {0x0022,0x1443,VR::SQ,VM::VM1,"Ophthalmic Thickness Mapping Normals Sequence","OphthalmicThicknessMappingNormalsSequence",false }, {0x0022,0x1445,VR::SQ,VM::VM1,"Retinal Thickness Definition Code Sequence","RetinalThicknessDefinitionCodeSequence",false }, {0x0022,0x1450,VR::SQ,VM::VM1,"Pixel Value Mapping to Coded Concept Sequence","PixelValueMappingToCodedConceptSequence",false }, {0x0022,0x1452,VR::US_SS,VM::VM1,"Mapped Pixel Value","MappedPixelValue",false }, {0x0022,0x1454,VR::LO,VM::VM1,"Pixel Value Mapping Explanation","PixelValueMappingExplanation",false }, {0x0022,0x1458,VR::SQ,VM::VM1,"Ophthalmic Thickness Map Quality Threshold Sequence","OphthalmicThicknessMapQualityThresholdSequence",false }, {0x0022,0x1460,VR::FL,VM::VM1,"Ophthalmic Thickness Map Threshold Quality Rating","OphthalmicThicknessMapThresholdQualityRating",false }, {0x0022,0x1463,VR::FL,VM::VM2,"Anatomic Structure Reference Point","AnatomicStructureReferencePoint",false }, {0x0022,0x1465,VR::SQ,VM::VM1,"Registration to Localizer Sequence","RegistrationToLocalizerSequence",false }, {0x0022,0x1466,VR::CS,VM::VM1,"Registered Localizer Units","RegisteredLocalizerUnits",false }, {0x0022,0x1467,VR::FL,VM::VM2,"Registered Localizer Top Left Hand Corner","RegisteredLocalizerTopLeftHandCorner",false }, {0x0022,0x1468,VR::FL,VM::VM2,"Registered Localizer Bottom Right Hand Corner","RegisteredLocalizerBottomRightHandCorner",false }, {0x0022,0x1470,VR::SQ,VM::VM1,"Ophthalmic Thickness Map Quality Rating Sequence","OphthalmicThicknessMapQualityRatingSequence",false }, {0x0022,0x1472,VR::SQ,VM::VM1,"Relevant OPT Attributes Sequence","RelevantOPTAttributesSequence",false }, {0x0022,0x1512,VR::SQ,VM::VM1,"Transformation Method Code Sequence","TransformationMethodCodeSequence",false }, {0x0022,0x1513,VR::SQ,VM::VM1,"Transformation Algorithm Sequence","TransformationAlgorithmSequence",false }, {0x0022,0x1515,VR::CS,VM::VM1,"Ophthalmic Axial Length Method","OphthalmicAxialLengthMethod",false }, {0x0022,0x1517,VR::FL,VM::VM1,"Ophthalmic FOV","OphthalmicFOV",false }, {0x0022,0x1518,VR::SQ,VM::VM1,"Two Dimensional to Three Dimensional Map Sequence","TwoDimensionalToThreeDimensionalMapSequence",false }, {0x0022,0x1525,VR::SQ,VM::VM1,"Wide Field Ophthalmic Photography Quality Rating Sequence","WideFieldOphthalmicPhotographyQualityRatingSequence",false }, {0x0022,0x1526,VR::SQ,VM::VM1,"Wide Field Ophthalmic Photography Quality Threshold Sequence","WideFieldOphthalmicPhotographyQualityThresholdSequence",false }, {0x0022,0x1527,VR::FL,VM::VM1,"Wide Field Ophthalmic Photography Threshold Quality Rating","WideFieldOphthalmicPhotographyThresholdQualityRating",false }, {0x0022,0x1528,VR::FL,VM::VM1,"X Coordinates Center Pixel View Angle","XCoordinatesCenterPixelViewAngle",false }, {0x0022,0x1529,VR::FL,VM::VM1,"Y Coordinates Center Pixel View Angle","YCoordinatesCenterPixelViewAngle",false }, {0x0022,0x1530,VR::UL,VM::VM1,"Number of Map Points","NumberOfMapPoints",false }, {0x0022,0x1531,VR::OF,VM::VM1,"Two Dimensional to Three Dimensional Map Data","TwoDimensionalToThreeDimensionalMapData",false }, {0x0024,0x0010,VR::FL,VM::VM1,"Visual Field Horizontal Extent","VisualFieldHorizontalExtent",false }, {0x0024,0x0011,VR::FL,VM::VM1,"Visual Field Vertical Extent","VisualFieldVerticalExtent",false }, {0x0024,0x0012,VR::CS,VM::VM1,"Visual Field Shape","VisualFieldShape",false }, {0x0024,0x0016,VR::SQ,VM::VM1,"Screening Test Mode Code Sequence","ScreeningTestModeCodeSequence",false }, {0x0024,0x0018,VR::FL,VM::VM1,"Maximum Stimulus Luminance","MaximumStimulusLuminance",false }, {0x0024,0x0020,VR::FL,VM::VM1,"Background Luminance","BackgroundLuminance",false }, {0x0024,0x0021,VR::SQ,VM::VM1,"Stimulus Color Code Sequence","StimulusColorCodeSequence",false }, {0x0024,0x0024,VR::SQ,VM::VM1,"Background Illumination Color Code Sequence","BackgroundIlluminationColorCodeSequence",false }, {0x0024,0x0025,VR::FL,VM::VM1,"Stimulus Area","StimulusArea",false }, {0x0024,0x0028,VR::FL,VM::VM1,"Stimulus Presentation Time","StimulusPresentationTime",false }, {0x0024,0x0032,VR::SQ,VM::VM1,"Fixation Sequence","FixationSequence",false }, {0x0024,0x0033,VR::SQ,VM::VM1,"Fixation Monitoring Code Sequence","FixationMonitoringCodeSequence",false }, {0x0024,0x0034,VR::SQ,VM::VM1,"Visual Field Catch Trial Sequence","VisualFieldCatchTrialSequence",false }, {0x0024,0x0035,VR::US,VM::VM1,"Fixation Checked Quantity","FixationCheckedQuantity",false }, {0x0024,0x0036,VR::US,VM::VM1,"Patient Not Properly Fixated Quantity","PatientNotProperlyFixatedQuantity",false }, {0x0024,0x0037,VR::CS,VM::VM1,"Presented Visual Stimuli Data Flag","PresentedVisualStimuliDataFlag",false }, {0x0024,0x0038,VR::US,VM::VM1,"Number of Visual Stimuli","NumberOfVisualStimuli",false }, {0x0024,0x0039,VR::CS,VM::VM1,"Excessive Fixation Losses Data Flag","ExcessiveFixationLossesDataFlag",false }, {0x0024,0x0040,VR::CS,VM::VM1,"Excessive Fixation Losses","ExcessiveFixationLosses",false }, {0x0024,0x0042,VR::US,VM::VM1,"Stimuli Retesting Quantity","StimuliRetestingQuantity",false }, {0x0024,0x0044,VR::LT,VM::VM1,"Comments on Patient's Performance of Visual Field","CommentsOnPatientPerformanceOfVisualField",false }, {0x0024,0x0045,VR::CS,VM::VM1,"False Negatives Estimate Flag","FalseNegativesEstimateFlag",false }, {0x0024,0x0046,VR::FL,VM::VM1,"False Negatives Estimate","FalseNegativesEstimate",false }, {0x0024,0x0048,VR::US,VM::VM1,"Negative Catch Trials Quantity","NegativeCatchTrialsQuantity",false }, {0x0024,0x0050,VR::US,VM::VM1,"False Negatives Quantity","FalseNegativesQuantity",false }, {0x0024,0x0051,VR::CS,VM::VM1,"Excessive False Negatives Data Flag","ExcessiveFalseNegativesDataFlag",false }, {0x0024,0x0052,VR::CS,VM::VM1,"Excessive False Negatives","ExcessiveFalseNegatives",false }, {0x0024,0x0053,VR::CS,VM::VM1,"False Positives Estimate Flag","FalsePositivesEstimateFlag",false }, {0x0024,0x0054,VR::FL,VM::VM1,"False Positives Estimate","FalsePositivesEstimate",false }, {0x0024,0x0055,VR::CS,VM::VM1,"Catch Trials Data Flag","CatchTrialsDataFlag",false }, {0x0024,0x0056,VR::US,VM::VM1,"Positive Catch Trials Quantity","PositiveCatchTrialsQuantity",false }, {0x0024,0x0057,VR::CS,VM::VM1,"Test Point Normals Data Flag","TestPointNormalsDataFlag",false }, {0x0024,0x0058,VR::SQ,VM::VM1,"Test Point Normals Sequence","TestPointNormalsSequence",false }, {0x0024,0x0059,VR::CS,VM::VM1,"Global Deviation Probability Normals Flag","GlobalDeviationProbabilityNormalsFlag",false }, {0x0024,0x0060,VR::US,VM::VM1,"False Positives Quantity","FalsePositivesQuantity",false }, {0x0024,0x0061,VR::CS,VM::VM1,"Excessive False Positives Data Flag","ExcessiveFalsePositivesDataFlag",false }, {0x0024,0x0062,VR::CS,VM::VM1,"Excessive False Positives","ExcessiveFalsePositives",false }, {0x0024,0x0063,VR::CS,VM::VM1,"Visual Field Test Normals Flag","VisualFieldTestNormalsFlag",false }, {0x0024,0x0064,VR::SQ,VM::VM1,"Results Normals Sequence","ResultsNormalsSequence",false }, {0x0024,0x0065,VR::SQ,VM::VM1,"Age Corrected Sensitivity Deviation Algorithm Sequence","AgeCorrectedSensitivityDeviationAlgorithmSequence",false }, {0x0024,0x0066,VR::FL,VM::VM1,"Global Deviation From Normal","GlobalDeviationFromNormal",false }, {0x0024,0x0067,VR::SQ,VM::VM1,"Generalized Defect Sensitivity Deviation Algorithm Sequence","GeneralizedDefectSensitivityDeviationAlgorithmSequence",false }, {0x0024,0x0068,VR::FL,VM::VM1,"Localized Deviation From Normal","LocalizedDeviationFromNormal",false }, {0x0024,0x0069,VR::LO,VM::VM1,"Patient Reliability Indicator","PatientReliabilityIndicator",false }, {0x0024,0x0070,VR::FL,VM::VM1,"Visual Field Mean Sensitivity","VisualFieldMeanSensitivity",false }, {0x0024,0x0071,VR::FL,VM::VM1,"Global Deviation Probability","GlobalDeviationProbability",false }, {0x0024,0x0072,VR::CS,VM::VM1,"Local Deviation Probability Normals Flag","LocalDeviationProbabilityNormalsFlag",false }, {0x0024,0x0073,VR::FL,VM::VM1,"Localized Deviation Probability","LocalizedDeviationProbability",false }, {0x0024,0x0074,VR::CS,VM::VM1,"Short Term Fluctuation Calculated","ShortTermFluctuationCalculated",false }, {0x0024,0x0075,VR::FL,VM::VM1,"Short Term Fluctuation","ShortTermFluctuation",false }, {0x0024,0x0076,VR::CS,VM::VM1,"Short Term Fluctuation Probability Calculated","ShortTermFluctuationProbabilityCalculated",false }, {0x0024,0x0077,VR::FL,VM::VM1,"Short Term Fluctuation Probability","ShortTermFluctuationProbability",false }, {0x0024,0x0078,VR::CS,VM::VM1,"Corrected Localized Deviation From Normal Calculated","CorrectedLocalizedDeviationFromNormalCalculated",false }, {0x0024,0x0079,VR::FL,VM::VM1,"Corrected Localized Deviation From Normal","CorrectedLocalizedDeviationFromNormal",false }, {0x0024,0x0080,VR::CS,VM::VM1,"Corrected Localized Deviation From Normal Probability Calculated","CorrectedLocalizedDeviationFromNormalProbabilityCalculated",false }, {0x0024,0x0081,VR::FL,VM::VM1,"Corrected Localized Deviation From Normal Probability","CorrectedLocalizedDeviationFromNormalProbability",false }, {0x0024,0x0083,VR::SQ,VM::VM1,"Global Deviation Probability Sequence","GlobalDeviationProbabilitySequence",false }, {0x0024,0x0085,VR::SQ,VM::VM1,"Localized Deviation Probability Sequence","LocalizedDeviationProbabilitySequence",false }, {0x0024,0x0086,VR::CS,VM::VM1,"Foveal Sensitivity Measured","FovealSensitivityMeasured",false }, {0x0024,0x0087,VR::FL,VM::VM1,"Foveal Sensitivity","FovealSensitivity",false }, {0x0024,0x0088,VR::FL,VM::VM1,"Visual Field Test Duration","VisualFieldTestDuration",false }, {0x0024,0x0089,VR::SQ,VM::VM1,"Visual Field Test Point Sequence","VisualFieldTestPointSequence",false }, {0x0024,0x0090,VR::FL,VM::VM1,"Visual Field Test Point X-Coordinate","VisualFieldTestPointXCoordinate",false }, {0x0024,0x0091,VR::FL,VM::VM1,"Visual Field Test Point Y-Coordinate","VisualFieldTestPointYCoordinate",false }, {0x0024,0x0092,VR::FL,VM::VM1,"Age Corrected Sensitivity Deviation Value","AgeCorrectedSensitivityDeviationValue",false }, {0x0024,0x0093,VR::CS,VM::VM1,"Stimulus Results","StimulusResults",false }, {0x0024,0x0094,VR::FL,VM::VM1,"Sensitivity Value","SensitivityValue",false }, {0x0024,0x0095,VR::CS,VM::VM1,"Retest Stimulus Seen","RetestStimulusSeen",false }, {0x0024,0x0096,VR::FL,VM::VM1,"Retest Sensitivity Value","RetestSensitivityValue",false }, {0x0024,0x0097,VR::SQ,VM::VM1,"Visual Field Test Point Normals Sequence","VisualFieldTestPointNormalsSequence",false }, {0x0024,0x0098,VR::FL,VM::VM1,"Quantified Defect","QuantifiedDefect",false }, {0x0024,0x0100,VR::FL,VM::VM1,"Age Corrected Sensitivity Deviation Probability Value","AgeCorrectedSensitivityDeviationProbabilityValue",false }, {0x0024,0x0102,VR::CS,VM::VM1,"Generalized Defect Corrected Sensitivity Deviation Flag","GeneralizedDefectCorrectedSensitivityDeviationFlag",false }, {0x0024,0x0103,VR::FL,VM::VM1,"Generalized Defect Corrected Sensitivity Deviation Value","GeneralizedDefectCorrectedSensitivityDeviationValue",false }, {0x0024,0x0104,VR::FL,VM::VM1,"Generalized Defect Corrected Sensitivity Deviation Probability Value","GeneralizedDefectCorrectedSensitivityDeviationProbabilityValue",false }, {0x0024,0x0105,VR::FL,VM::VM1,"Minimum Sensitivity Value","MinimumSensitivityValue",false }, {0x0024,0x0106,VR::CS,VM::VM1,"Blind Spot Localized","BlindSpotLocalized",false }, {0x0024,0x0107,VR::FL,VM::VM1,"Blind Spot X-Coordinate","BlindSpotXCoordinate",false }, {0x0024,0x0108,VR::FL,VM::VM1,"Blind Spot Y-Coordinate","BlindSpotYCoordinate",false }, {0x0024,0x0110,VR::SQ,VM::VM1,"Visual Acuity Measurement Sequence","VisualAcuityMeasurementSequence",false }, {0x0024,0x0112,VR::SQ,VM::VM1,"Refractive Parameters Used on Patient Sequence","RefractiveParametersUsedOnPatientSequence",false }, {0x0024,0x0113,VR::CS,VM::VM1,"Measurement Laterality","MeasurementLaterality",false }, {0x0024,0x0114,VR::SQ,VM::VM1,"Ophthalmic Patient Clinical Information Left Eye Sequence","OphthalmicPatientClinicalInformationLeftEyeSequence",false }, {0x0024,0x0115,VR::SQ,VM::VM1,"Ophthalmic Patient Clinical Information Right Eye Sequence","OphthalmicPatientClinicalInformationRightEyeSequence",false }, {0x0024,0x0117,VR::CS,VM::VM1,"Foveal Point Normative Data Flag","FovealPointNormativeDataFlag",false }, {0x0024,0x0118,VR::FL,VM::VM1,"Foveal Point Probability Value","FovealPointProbabilityValue",false }, {0x0024,0x0120,VR::CS,VM::VM1,"Screening Baseline Measured","ScreeningBaselineMeasured",false }, {0x0024,0x0122,VR::SQ,VM::VM1,"Screening Baseline Measured Sequence","ScreeningBaselineMeasuredSequence",false }, {0x0024,0x0124,VR::CS,VM::VM1,"Screening Baseline Type","ScreeningBaselineType",false }, {0x0024,0x0126,VR::FL,VM::VM1,"Screening Baseline Value","ScreeningBaselineValue",false }, {0x0024,0x0202,VR::LO,VM::VM1,"Algorithm Source","AlgorithmSource",false }, {0x0024,0x0306,VR::LO,VM::VM1,"Data Set Name","DataSetName",false }, {0x0024,0x0307,VR::LO,VM::VM1,"Data Set Version","DataSetVersion",false }, {0x0024,0x0308,VR::LO,VM::VM1,"Data Set Source","DataSetSource",false }, {0x0024,0x0309,VR::LO,VM::VM1,"Data Set Description","DataSetDescription",false }, {0x0024,0x0317,VR::SQ,VM::VM1,"Visual Field Test Reliability Global Index Sequence","VisualFieldTestReliabilityGlobalIndexSequence",false }, {0x0024,0x0320,VR::SQ,VM::VM1,"Visual Field Global Results Index Sequence","VisualFieldGlobalResultsIndexSequence",false }, {0x0024,0x0325,VR::SQ,VM::VM1,"Data Observation Sequence","DataObservationSequence",false }, {0x0024,0x0338,VR::CS,VM::VM1,"Index Normals Flag","IndexNormalsFlag",false }, {0x0024,0x0341,VR::FL,VM::VM1,"Index Probability","IndexProbability",false }, {0x0024,0x0344,VR::SQ,VM::VM1,"Index Probability Sequence","IndexProbabilitySequence",false }, {0x0028,0x0002,VR::US,VM::VM1,"Samples per Pixel","SamplesPerPixel",false }, {0x0028,0x0003,VR::US,VM::VM1,"Samples per Pixel Used","SamplesPerPixelUsed",false }, {0x0028,0x0004,VR::CS,VM::VM1,"Photometric Interpretation","PhotometricInterpretation",false }, {0x0028,0x0005,VR::US,VM::VM1,"Image Dimensions","ImageDimensions",true }, {0x0028,0x0006,VR::US,VM::VM1,"Planar Configuration","PlanarConfiguration",false }, {0x0028,0x0008,VR::IS,VM::VM1,"Number of Frames","NumberOfFrames",false }, {0x0028,0x0009,VR::AT,VM::VM1_n,"Frame Increment Pointer","FrameIncrementPointer",false }, {0x0028,0x000a,VR::AT,VM::VM1_n,"Frame Dimension Pointer","FrameDimensionPointer",false }, {0x0028,0x0010,VR::US,VM::VM1,"Rows","Rows",false }, {0x0028,0x0011,VR::US,VM::VM1,"Columns","Columns",false }, {0x0028,0x0012,VR::US,VM::VM1,"Planes","Planes",true }, {0x0028,0x0014,VR::US,VM::VM1,"Ultrasound Color Data Present","UltrasoundColorDataPresent",false }, {0x0028,0x0020,VR::INVALID,VM::VM0,"","",true }, {0x0028,0x0030,VR::DS,VM::VM2,"Pixel Spacing","PixelSpacing",false }, {0x0028,0x0031,VR::DS,VM::VM2,"Zoom Factor","ZoomFactor",false }, {0x0028,0x0032,VR::DS,VM::VM2,"Zoom Center","ZoomCenter",false }, {0x0028,0x0034,VR::IS,VM::VM2,"Pixel Aspect Ratio","PixelAspectRatio",false }, {0x0028,0x0040,VR::CS,VM::VM1,"Image Format","ImageFormat",true }, {0x0028,0x0050,VR::LO,VM::VM1_n,"Manipulated Image","ManipulatedImage",true }, {0x0028,0x0051,VR::CS,VM::VM1_n,"Corrected Image","CorrectedImage",false }, {0x0028,0x005f,VR::LO,VM::VM1,"Compression Recognition Code","CompressionRecognitionCode",true }, {0x0028,0x0060,VR::CS,VM::VM1,"Compression Code","CompressionCode",true }, {0x0028,0x0061,VR::SH,VM::VM1,"Compression Originator","CompressionOriginator",true }, {0x0028,0x0062,VR::LO,VM::VM1,"Compression Label","CompressionLabel",true }, {0x0028,0x0063,VR::SH,VM::VM1,"Compression Description","CompressionDescription",true }, {0x0028,0x0065,VR::CS,VM::VM1_n,"Compression Sequence","CompressionSequence",true }, {0x0028,0x0066,VR::AT,VM::VM1_n,"Compression Step Pointers","CompressionStepPointers",true }, {0x0028,0x0068,VR::US,VM::VM1,"Repeat Interval","RepeatInterval",true }, {0x0028,0x0069,VR::US,VM::VM1,"Bits Grouped","BitsGrouped",true }, {0x0028,0x0070,VR::US,VM::VM1_n,"Perimeter Table","PerimeterTable",true }, {0x0028,0x0071,VR::US_SS,VM::VM1,"Perimeter Value","PerimeterValue",true }, {0x0028,0x0080,VR::US,VM::VM1,"Predictor Rows","PredictorRows",true }, {0x0028,0x0081,VR::US,VM::VM1,"Predictor Columns","PredictorColumns",true }, {0x0028,0x0082,VR::US,VM::VM1_n,"Predictor Constants","PredictorConstants",true }, {0x0028,0x0090,VR::CS,VM::VM1,"Blocked Pixels","BlockedPixels",true }, {0x0028,0x0091,VR::US,VM::VM1,"Block Rows","BlockRows",true }, {0x0028,0x0092,VR::US,VM::VM1,"Block Columns","BlockColumns",true }, {0x0028,0x0093,VR::US,VM::VM1,"Row Overlap","RowOverlap",true }, {0x0028,0x0094,VR::US,VM::VM1,"Column Overlap","ColumnOverlap",true }, {0x0028,0x0100,VR::US,VM::VM1,"Bits Allocated","BitsAllocated",false }, {0x0028,0x0101,VR::US,VM::VM1,"Bits Stored","BitsStored",false }, {0x0028,0x0102,VR::US,VM::VM1,"High Bit","HighBit",false }, {0x0028,0x0103,VR::US,VM::VM1,"Pixel Representation","PixelRepresentation",false }, {0x0028,0x0104,VR::US_SS,VM::VM1,"Smallest Valid Pixel Value","SmallestValidPixelValue",true }, {0x0028,0x0105,VR::US_SS,VM::VM1,"Largest Valid Pixel Value","LargestValidPixelValue",true }, {0x0028,0x0106,VR::US_SS,VM::VM1,"Smallest Image Pixel Value","SmallestImagePixelValue",false }, {0x0028,0x0107,VR::US_SS,VM::VM1,"Largest Image Pixel Value","LargestImagePixelValue",false }, {0x0028,0x0108,VR::US_SS,VM::VM1,"Smallest Pixel Value in Series","SmallestPixelValueInSeries",false }, {0x0028,0x0109,VR::US_SS,VM::VM1,"Largest Pixel Value in Series","LargestPixelValueInSeries",false }, {0x0028,0x0110,VR::US_SS,VM::VM1,"Smallest Image Pixel Value in Plane","SmallestImagePixelValueInPlane",true }, {0x0028,0x0111,VR::US_SS,VM::VM1,"Largest Image Pixel Value in Plane","LargestImagePixelValueInPlane",true }, {0x0028,0x0120,VR::US_SS,VM::VM1,"Pixel Padding Value","PixelPaddingValue",false }, {0x0028,0x0121,VR::US_SS,VM::VM1,"Pixel Padding Range Limit","PixelPaddingRangeLimit",false }, {0x0028,0x0122,VR::FL,VM::VM1,"Float Pixel Padding Value","FloatPixelPaddingValue",false }, {0x0028,0x0123,VR::FD,VM::VM1,"Double Float Pixel Padding Value","DoubleFloatPixelPaddingValue",false }, {0x0028,0x0124,VR::FL,VM::VM1,"Float Pixel Padding Range Limit","FloatPixelPaddingRangeLimit",false }, {0x0028,0x0125,VR::FD,VM::VM1,"Double Float Pixel Padding Range Limit","DoubleFloatPixelPaddingRangeLimit",false }, {0x0028,0x0200,VR::US,VM::VM1,"Image Location","ImageLocation",true }, {0x0028,0x0300,VR::CS,VM::VM1,"Quality Control Image","QualityControlImage",false }, {0x0028,0x0301,VR::CS,VM::VM1,"Burned In Annotation","BurnedInAnnotation",false }, {0x0028,0x0302,VR::CS,VM::VM1,"Recognizable Visual Features","RecognizableVisualFeatures",false }, {0x0028,0x0303,VR::CS,VM::VM1,"Longitudinal Temporal Information Modified","LongitudinalTemporalInformationModified",false }, {0x0028,0x0304,VR::UI,VM::VM1,"Referenced Color Palette Instance UID","ReferencedColorPaletteInstanceUID",false }, {0x0028,0x0400,VR::LO,VM::VM1,"Transform Label","TransformLabel",true }, {0x0028,0x0401,VR::LO,VM::VM1,"Transform Version Number","TransformVersionNumber",true }, {0x0028,0x0402,VR::US,VM::VM1,"Number of Transform Steps","NumberOfTransformSteps",true }, {0x0028,0x0403,VR::LO,VM::VM1_n,"Sequence of Compressed Data","SequenceOfCompressedData",true }, {0x0028,0x0404,VR::AT,VM::VM1_n,"Details of Coefficients","DetailsOfCoefficients",true }, {0x0028,0x0700,VR::LO,VM::VM1,"DCT Label","DCTLabel",true }, {0x0028,0x0701,VR::CS,VM::VM1_n,"Data Block Description","DataBlockDescription",true }, {0x0028,0x0702,VR::AT,VM::VM1_n,"Data Block","DataBlock",true }, {0x0028,0x0710,VR::US,VM::VM1,"Normalization Factor Format","NormalizationFactorFormat",true }, {0x0028,0x0720,VR::US,VM::VM1,"Zonal Map Number Format","ZonalMapNumberFormat",true }, {0x0028,0x0721,VR::AT,VM::VM1_n,"Zonal Map Location","ZonalMapLocation",true }, {0x0028,0x0722,VR::US,VM::VM1,"Zonal Map Format","ZonalMapFormat",true }, {0x0028,0x0730,VR::US,VM::VM1,"Adaptive Map Format","AdaptiveMapFormat",true }, {0x0028,0x0740,VR::US,VM::VM1,"Code Number Format","CodeNumberFormat",true }, {0x0028,0x0a02,VR::CS,VM::VM1,"Pixel Spacing Calibration Type","PixelSpacingCalibrationType",false }, {0x0028,0x0a04,VR::LO,VM::VM1,"Pixel Spacing Calibration Description","PixelSpacingCalibrationDescription",false }, {0x0028,0x1040,VR::CS,VM::VM1,"Pixel Intensity Relationship","PixelIntensityRelationship",false }, {0x0028,0x1041,VR::SS,VM::VM1,"Pixel Intensity Relationship Sign","PixelIntensityRelationshipSign",false }, {0x0028,0x1050,VR::DS,VM::VM1_n,"Window Center","WindowCenter",false }, {0x0028,0x1051,VR::DS,VM::VM1_n,"Window Width","WindowWidth",false }, {0x0028,0x1052,VR::DS,VM::VM1,"Rescale Intercept","RescaleIntercept",false }, {0x0028,0x1053,VR::DS,VM::VM1,"Rescale Slope","RescaleSlope",false }, {0x0028,0x1054,VR::LO,VM::VM1,"Rescale Type","RescaleType",false }, {0x0028,0x1055,VR::LO,VM::VM1_n,"Window Center & Width Explanation","WindowCenterWidthExplanation",false }, {0x0028,0x1056,VR::CS,VM::VM1,"VOI LUT Function","VOILUTFunction",false }, {0x0028,0x1080,VR::CS,VM::VM1,"Gray Scale","GrayScale",true }, {0x0028,0x1090,VR::CS,VM::VM1,"Recommended Viewing Mode","RecommendedViewingMode",false }, {0x0028,0x1100,VR::US_SS,VM::VM3,"Gray Lookup Table Descriptor","GrayLookupTableDescriptor",true }, {0x0028,0x1101,VR::US_SS,VM::VM3,"Red Palette Color Lookup Table Descriptor","RedPaletteColorLookupTableDescriptor",false }, {0x0028,0x1102,VR::US_SS,VM::VM3,"Green Palette Color Lookup Table Descriptor","GreenPaletteColorLookupTableDescriptor",false }, {0x0028,0x1103,VR::US_SS,VM::VM3,"Blue Palette Color Lookup Table Descriptor","BluePaletteColorLookupTableDescriptor",false }, {0x0028,0x1104,VR::US,VM::VM3,"Alpha Palette Color Lookup Table Descriptor","AlphaPaletteColorLookupTableDescriptor",false }, {0x0028,0x1111,VR::US_SS,VM::VM4,"Large Red Palette Color Lookup Table Descriptor","LargeRedPaletteColorLookupTableDescriptor",true }, {0x0028,0x1112,VR::US_SS,VM::VM4,"Large Green Palette Color Lookup Table Descriptor","LargeGreenPaletteColorLookupTableDescriptor",true }, {0x0028,0x1113,VR::US_SS,VM::VM4,"Large Blue Palette Color Lookup Table Descriptor","LargeBluePaletteColorLookupTableDescriptor",true }, {0x0028,0x1199,VR::UI,VM::VM1,"Palette Color Lookup Table UID","PaletteColorLookupTableUID",false }, {0x0028,0x1200,VR::US_SS_OW,VM::VM1_n,"Gray Lookup Table Data","GrayLookupTableData",true }, {0x0028,0x1201,VR::OW,VM::VM1,"Red Palette Color Lookup Table Data","RedPaletteColorLookupTableData",false }, {0x0028,0x1202,VR::OW,VM::VM1,"Green Palette Color Lookup Table Data","GreenPaletteColorLookupTableData",false }, {0x0028,0x1203,VR::OW,VM::VM1,"Blue Palette Color Lookup Table Data","BluePaletteColorLookupTableData",false }, {0x0028,0x1204,VR::OW,VM::VM1,"Alpha Palette Color Lookup Table Data","AlphaPaletteColorLookupTableData",false }, {0x0028,0x1211,VR::OW,VM::VM1,"Large Red Palette Color Lookup Table Data","LargeRedPaletteColorLookupTableData",true }, {0x0028,0x1212,VR::OW,VM::VM1,"Large Green Palette Color Lookup Table Data","LargeGreenPaletteColorLookupTableData",true }, {0x0028,0x1213,VR::OW,VM::VM1,"Large Blue Palette Color Lookup Table Data","LargeBluePaletteColorLookupTableData",true }, {0x0028,0x1214,VR::UI,VM::VM1,"Large Palette Color Lookup Table UID","LargePaletteColorLookupTableUID",true }, {0x0028,0x1221,VR::OW,VM::VM1,"Segmented Red Palette Color Lookup Table Data","SegmentedRedPaletteColorLookupTableData",false }, {0x0028,0x1222,VR::OW,VM::VM1,"Segmented Green Palette Color Lookup Table Data","SegmentedGreenPaletteColorLookupTableData",false }, {0x0028,0x1223,VR::OW,VM::VM1,"Segmented Blue Palette Color Lookup Table Data","SegmentedBluePaletteColorLookupTableData",false }, {0x0028,0x1224,VR::OW,VM::VM1,"Segmented Alpha Palette Color Lookup Table Data","SegmentedAlphaPaletteColorLookupTableData",false }, {0x0028,0x1230,VR::SQ,VM::VM1,"Stored Value Color Range Sequence","StoredValueColorRangeSequence",false }, {0x0028,0x1231,VR::FD,VM::VM1,"Minimum Stored Value Mapped","MinimumStoredValueMapped",false }, {0x0028,0x1232,VR::FD,VM::VM1,"Maximum Stored Value Mapped","MaximumStoredValueMapped",false }, {0x0028,0x1300,VR::CS,VM::VM1,"Breast Implant Present","BreastImplantPresent",false }, {0x0028,0x1350,VR::CS,VM::VM1,"Partial View","PartialView",false }, {0x0028,0x1351,VR::ST,VM::VM1,"Partial View Description","PartialViewDescription",false }, {0x0028,0x1352,VR::SQ,VM::VM1,"Partial View Code Sequence","PartialViewCodeSequence",false }, {0x0028,0x135a,VR::CS,VM::VM1,"Spatial Locations Preserved","SpatialLocationsPreserved",false }, {0x0028,0x1401,VR::SQ,VM::VM1,"Data Frame Assignment Sequence","DataFrameAssignmentSequence",false }, {0x0028,0x1402,VR::CS,VM::VM1,"Data Path Assignment","DataPathAssignment",false }, {0x0028,0x1403,VR::US,VM::VM1,"Bits Mapped to Color Lookup Table","BitsMappedToColorLookupTable",false }, {0x0028,0x1404,VR::SQ,VM::VM1,"Blending LUT 1 Sequence","BlendingLUT1Sequence",false }, {0x0028,0x1405,VR::CS,VM::VM1,"Blending LUT 1 Transfer Function","BlendingLUT1TransferFunction",false }, {0x0028,0x1406,VR::FD,VM::VM1,"Blending Weight Constant","BlendingWeightConstant",false }, {0x0028,0x1407,VR::US,VM::VM3,"Blending Lookup Table Descriptor","BlendingLookupTableDescriptor",false }, {0x0028,0x1408,VR::OW,VM::VM1,"Blending Lookup Table Data","BlendingLookupTableData",false }, {0x0028,0x140b,VR::SQ,VM::VM1,"Enhanced Palette Color Lookup Table Sequence","EnhancedPaletteColorLookupTableSequence",false }, {0x0028,0x140c,VR::SQ,VM::VM1,"Blending LUT 2 Sequence","BlendingLUT2Sequence",false }, {0x0028,0x140d,VR::CS,VM::VM1,"Blending LUT 2 Transfer Function","BlendingLUT2TransferFunction",false }, {0x0028,0x140e,VR::CS,VM::VM1,"Data Path ID","DataPathID",false }, {0x0028,0x140f,VR::CS,VM::VM1,"RGB LUT Transfer Function","RGBLUTTransferFunction",false }, {0x0028,0x1410,VR::CS,VM::VM1,"Alpha LUT Transfer Function","AlphaLUTTransferFunction",false }, {0x0028,0x2000,VR::OB,VM::VM1,"ICC Profile","ICCProfile",false }, {0x0028,0x2002,VR::CS,VM::VM1,"Color Space","ColorSpace",false }, {0x0028,0x2110,VR::CS,VM::VM1,"Lossy Image Compression","LossyImageCompression",false }, {0x0028,0x2112,VR::DS,VM::VM1_n,"Lossy Image Compression Ratio","LossyImageCompressionRatio",false }, {0x0028,0x2114,VR::CS,VM::VM1_n,"Lossy Image Compression Method","LossyImageCompressionMethod",false }, {0x0028,0x3000,VR::SQ,VM::VM1,"Modality LUT Sequence","ModalityLUTSequence",false }, {0x0028,0x3002,VR::US_SS,VM::VM3,"LUT Descriptor","LUTDescriptor",false }, {0x0028,0x3003,VR::LO,VM::VM1,"LUT Explanation","LUTExplanation",false }, {0x0028,0x3004,VR::LO,VM::VM1,"Modality LUT Type","ModalityLUTType",false }, {0x0028,0x3006,VR::US_OW,VM::VM1_n,"LUT Data","LUTData",false }, {0x0028,0x3010,VR::SQ,VM::VM1,"VOI LUT Sequence","VOILUTSequence",false }, {0x0028,0x3110,VR::SQ,VM::VM1,"Softcopy VOI LUT Sequence","SoftcopyVOILUTSequence",false }, {0x0028,0x4000,VR::LT,VM::VM1,"Image Presentation Comments","ImagePresentationComments",true }, {0x0028,0x5000,VR::SQ,VM::VM1,"Bi-Plane Acquisition Sequence","BiPlaneAcquisitionSequence",true }, {0x0028,0x6010,VR::US,VM::VM1,"Representative Frame Number","RepresentativeFrameNumber",false }, {0x0028,0x6020,VR::US,VM::VM1_n,"Frame Numbers of Interest (FOI)","FrameNumbersOfInterestFOI",false }, {0x0028,0x6022,VR::LO,VM::VM1_n,"Frame of Interest Description","FrameOfInterestDescription",false }, {0x0028,0x6023,VR::CS,VM::VM1_n,"Frame of Interest Type","FrameOfInterestType",false }, {0x0028,0x6030,VR::US,VM::VM1_n,"Mask Pointer(s)","MaskPointers",true }, {0x0028,0x6040,VR::US,VM::VM1_n,"R Wave Pointer","RWavePointer",false }, {0x0028,0x6100,VR::SQ,VM::VM1,"Mask Subtraction Sequence","MaskSubtractionSequence",false }, {0x0028,0x6101,VR::CS,VM::VM1,"Mask Operation","MaskOperation",false }, {0x0028,0x6102,VR::US,VM::VM2_2n,"Applicable Frame Range","ApplicableFrameRange",false }, {0x0028,0x6110,VR::US,VM::VM1_n,"Mask Frame Numbers","MaskFrameNumbers",false }, {0x0028,0x6112,VR::US,VM::VM1,"Contrast Frame Averaging","ContrastFrameAveraging",false }, {0x0028,0x6114,VR::FL,VM::VM2,"Mask Sub-pixel Shift","MaskSubPixelShift",false }, {0x0028,0x6120,VR::SS,VM::VM1,"TID Offset","TIDOffset",false }, {0x0028,0x6190,VR::ST,VM::VM1,"Mask Operation Explanation","MaskOperationExplanation",false }, {0x0028,0x7000,VR::SQ,VM::VM1,"Equipment Administrator Sequence","EquipmentAdministratorSequence",false }, {0x0028,0x7001,VR::US,VM::VM1,"Number of Display Subsystems","NumberOfDisplaySubsystems",false }, {0x0028,0x7002,VR::US,VM::VM1,"Current Configuration ID","CurrentConfigurationID",false }, {0x0028,0x7003,VR::US,VM::VM1,"Display Subsystem ID","DisplaySubsystemID",false }, {0x0028,0x7004,VR::SH,VM::VM1,"Display Subsystem Name","DisplaySubsystemName",false }, {0x0028,0x7005,VR::LO,VM::VM1,"Display Subsystem Description","DisplaySubsystemDescription",false }, {0x0028,0x7006,VR::CS,VM::VM1,"System Status","SystemStatus",false }, {0x0028,0x7007,VR::LO,VM::VM1,"System Status Comment","SystemStatusComment",false }, {0x0028,0x7008,VR::SQ,VM::VM1,"Target Luminance Characteristics Sequence","TargetLuminanceCharacteristicsSequence",false }, {0x0028,0x7009,VR::US,VM::VM1,"Luminance Characteristics ID","LuminanceCharacteristicsID",false }, {0x0028,0x700a,VR::SQ,VM::VM1,"Display Subsystem Configuration Sequence","DisplaySubsystemConfigurationSequence",false }, {0x0028,0x700b,VR::US,VM::VM1,"Configuration ID","ConfigurationID",false }, {0x0028,0x700c,VR::SH,VM::VM1,"Configuration Name","ConfigurationName",false }, {0x0028,0x700d,VR::LO,VM::VM1,"Configuration Description","ConfigurationDescription",false }, {0x0028,0x700e,VR::US,VM::VM1,"Referenced Target Luminance Characteristics ID","ReferencedTargetLuminanceCharacteristicsID",false }, {0x0028,0x700f,VR::SQ,VM::VM1,"QA Results Sequence","QAResultsSequence",false }, {0x0028,0x7010,VR::SQ,VM::VM1,"Display Subsystem QA Results Sequence","DisplaySubsystemQAResultsSequence",false }, {0x0028,0x7011,VR::SQ,VM::VM1,"Configuration QA Results Sequence","ConfigurationQAResultsSequence",false }, {0x0028,0x7012,VR::SQ,VM::VM1,"Measurement Equipment Sequence","MeasurementEquipmentSequence",false }, {0x0028,0x7013,VR::CS,VM::VM1_n,"Measurement Functions","MeasurementFunctions",false }, {0x0028,0x7014,VR::CS,VM::VM1,"Measurement Equipment Type","MeasurementEquipmentType",false }, {0x0028,0x7015,VR::SQ,VM::VM1,"Visual Evaluation Result Sequence","VisualEvaluationResultSequence",false }, {0x0028,0x7016,VR::SQ,VM::VM1,"Display Calibration Result Sequence","DisplayCalibrationResultSequence",false }, {0x0028,0x7017,VR::US,VM::VM1,"DDL Value","DDLValue",false }, {0x0028,0x7018,VR::FL,VM::VM2,"CIExy White Point","CIExyWhitePoint",false }, {0x0028,0x7019,VR::CS,VM::VM1,"Display Function Type","DisplayFunctionType",false }, {0x0028,0x701a,VR::FL,VM::VM1,"Gamma Value","GammaValue",false }, {0x0028,0x701b,VR::US,VM::VM1,"Number of Luminance Points","NumberOfLuminancePoints",false }, {0x0028,0x701c,VR::SQ,VM::VM1,"Luminance Response Sequence","LuminanceResponseSequence",false }, {0x0028,0x701d,VR::FL,VM::VM1,"Target Minimum Luminance","TargetMinimumLuminance",false }, {0x0028,0x701e,VR::FL,VM::VM1,"Target Maximum Luminance","TargetMaximumLuminance",false }, {0x0028,0x701f,VR::FL,VM::VM1,"Luminance Value","LuminanceValue",false }, {0x0028,0x7020,VR::LO,VM::VM1,"Luminance Response Description","LuminanceResponseDescription",false }, {0x0028,0x7021,VR::CS,VM::VM1,"White Point Flag","WhitePointFlag",false }, {0x0028,0x7022,VR::SQ,VM::VM1,"Display Device Type Code Sequence","DisplayDeviceTypeCodeSequence",false }, {0x0028,0x7023,VR::SQ,VM::VM1,"Display Subsystem Sequence","DisplaySubsystemSequence",false }, {0x0028,0x7024,VR::SQ,VM::VM1,"Luminance Result Sequence","LuminanceResultSequence",false }, {0x0028,0x7025,VR::CS,VM::VM1,"Ambient Light Value Source","AmbientLightValueSource",false }, {0x0028,0x7026,VR::CS,VM::VM1_n,"Measured Characteristics","MeasuredCharacteristics",false }, {0x0028,0x7027,VR::SQ,VM::VM1,"Luminance Uniformity Result Sequence","LuminanceUniformityResultSequence",false }, {0x0028,0x7028,VR::SQ,VM::VM1,"Visual Evaluation Test Sequence","VisualEvaluationTestSequence",false }, {0x0028,0x7029,VR::CS,VM::VM1,"Test Result","TestResult",false }, {0x0028,0x702a,VR::LO,VM::VM1,"Test Result Comment","TestResultComment",false }, {0x0028,0x702b,VR::CS,VM::VM1,"Test Image Validation","TestImageValidation",false }, {0x0028,0x702c,VR::SQ,VM::VM1,"Test Pattern Code Sequence","TestPatternCodeSequence",false }, {0x0028,0x702d,VR::SQ,VM::VM1,"Measurement Pattern Code Sequence","MeasurementPatternCodeSequence",false }, {0x0028,0x702e,VR::SQ,VM::VM1,"Visual Evaluation Method Code Sequence","VisualEvaluationMethodCodeSequence",false }, {0x0028,0x7fe0,VR::UR,VM::VM1,"Pixel Data Provider URL","PixelDataProviderURL",false }, {0x0028,0x9001,VR::UL,VM::VM1,"Data Point Rows","DataPointRows",false }, {0x0028,0x9002,VR::UL,VM::VM1,"Data Point Columns","DataPointColumns",false }, {0x0028,0x9003,VR::CS,VM::VM1,"Signal Domain Columns","SignalDomainColumns",false }, {0x0028,0x9099,VR::US,VM::VM1,"Largest Monochrome Pixel Value","LargestMonochromePixelValue",true }, {0x0028,0x9108,VR::CS,VM::VM1,"Data Representation","DataRepresentation",false }, {0x0028,0x9110,VR::SQ,VM::VM1,"Pixel Measures Sequence","PixelMeasuresSequence",false }, {0x0028,0x9132,VR::SQ,VM::VM1,"Frame VOI LUT Sequence","FrameVOILUTSequence",false }, {0x0028,0x9145,VR::SQ,VM::VM1,"Pixel Value Transformation Sequence","PixelValueTransformationSequence",false }, {0x0028,0x9235,VR::CS,VM::VM1,"Signal Domain Rows","SignalDomainRows",false }, {0x0028,0x9411,VR::FL,VM::VM1,"Display Filter Percentage","DisplayFilterPercentage",false }, {0x0028,0x9415,VR::SQ,VM::VM1,"Frame Pixel Shift Sequence","FramePixelShiftSequence",false }, {0x0028,0x9416,VR::US,VM::VM1,"Subtraction Item ID","SubtractionItemID",false }, {0x0028,0x9422,VR::SQ,VM::VM1,"Pixel Intensity Relationship LUT Sequence","PixelIntensityRelationshipLUTSequence",false }, {0x0028,0x9443,VR::SQ,VM::VM1,"Frame Pixel Data Properties Sequence","FramePixelDataPropertiesSequence",false }, {0x0028,0x9444,VR::CS,VM::VM1,"Geometrical Properties","GeometricalProperties",false }, {0x0028,0x9445,VR::FL,VM::VM1,"Geometric Maximum Distortion","GeometricMaximumDistortion",false }, {0x0028,0x9446,VR::CS,VM::VM1_n,"Image Processing Applied","ImageProcessingApplied",false }, {0x0028,0x9454,VR::CS,VM::VM1,"Mask Selection Mode","MaskSelectionMode",false }, {0x0028,0x9474,VR::CS,VM::VM1,"LUT Function","LUTFunction",false }, {0x0028,0x9478,VR::FL,VM::VM1,"Mask Visibility Percentage","MaskVisibilityPercentage",false }, {0x0028,0x9501,VR::SQ,VM::VM1,"Pixel Shift Sequence","PixelShiftSequence",false }, {0x0028,0x9502,VR::SQ,VM::VM1,"Region Pixel Shift Sequence","RegionPixelShiftSequence",false }, {0x0028,0x9503,VR::SS,VM::VM2_2n,"Vertices of the Region","VerticesOfTheRegion",false }, {0x0028,0x9505,VR::SQ,VM::VM1,"Multi-frame Presentation Sequence","MultiFramePresentationSequence",false }, {0x0028,0x9506,VR::US,VM::VM2_2n,"Pixel Shift Frame Range","PixelShiftFrameRange",false }, {0x0028,0x9507,VR::US,VM::VM2_2n,"LUT Frame Range","LUTFrameRange",false }, {0x0028,0x9520,VR::DS,VM::VM16,"Image to Equipment Mapping Matrix","ImageToEquipmentMappingMatrix",false }, {0x0028,0x9537,VR::CS,VM::VM1,"Equipment Coordinate System Identification","EquipmentCoordinateSystemIdentification",false }, {0x0032,0x000a,VR::CS,VM::VM1,"Study Status ID","StudyStatusID",true }, {0x0032,0x000c,VR::CS,VM::VM1,"Study Priority ID","StudyPriorityID",true }, {0x0032,0x0012,VR::LO,VM::VM1,"Study ID Issuer","StudyIDIssuer",true }, {0x0032,0x0032,VR::DA,VM::VM1,"Study Verified Date","StudyVerifiedDate",true }, {0x0032,0x0033,VR::TM,VM::VM1,"Study Verified Time","StudyVerifiedTime",true }, {0x0032,0x0034,VR::DA,VM::VM1,"Study Read Date","StudyReadDate",true }, {0x0032,0x0035,VR::TM,VM::VM1,"Study Read Time","StudyReadTime",true }, {0x0032,0x1000,VR::DA,VM::VM1,"Scheduled Study Start Date","ScheduledStudyStartDate",true }, {0x0032,0x1001,VR::TM,VM::VM1,"Scheduled Study Start Time","ScheduledStudyStartTime",true }, {0x0032,0x1010,VR::DA,VM::VM1,"Scheduled Study Stop Date","ScheduledStudyStopDate",true }, {0x0032,0x1011,VR::TM,VM::VM1,"Scheduled Study Stop Time","ScheduledStudyStopTime",true }, {0x0032,0x1020,VR::LO,VM::VM1,"Scheduled Study Location","ScheduledStudyLocation",true }, {0x0032,0x1021,VR::AE,VM::VM1_n,"Scheduled Study Location AE Title","ScheduledStudyLocationAETitle",true }, {0x0032,0x1030,VR::LO,VM::VM1,"Reason for Study","ReasonForStudy",true }, {0x0032,0x1031,VR::SQ,VM::VM1,"Requesting Physician Identification Sequence","RequestingPhysicianIdentificationSequence",false }, {0x0032,0x1032,VR::PN,VM::VM1,"Requesting Physician","RequestingPhysician",false }, {0x0032,0x1033,VR::LO,VM::VM1,"Requesting Service","RequestingService",false }, {0x0032,0x1034,VR::SQ,VM::VM1,"Requesting Service Code Sequence","RequestingServiceCodeSequence",false }, {0x0032,0x1040,VR::DA,VM::VM1,"Study Arrival Date","StudyArrivalDate",true }, {0x0032,0x1041,VR::TM,VM::VM1,"Study Arrival Time","StudyArrivalTime",true }, {0x0032,0x1050,VR::DA,VM::VM1,"Study Completion Date","StudyCompletionDate",true }, {0x0032,0x1051,VR::TM,VM::VM1,"Study Completion Time","StudyCompletionTime",true }, {0x0032,0x1055,VR::CS,VM::VM1,"Study Component Status ID","StudyComponentStatusID",true }, {0x0032,0x1060,VR::LO,VM::VM1,"Requested Procedure Description","RequestedProcedureDescription",false }, {0x0032,0x1064,VR::SQ,VM::VM1,"Requested Procedure Code Sequence","RequestedProcedureCodeSequence",false }, {0x0032,0x1070,VR::LO,VM::VM1,"Requested Contrast Agent","RequestedContrastAgent",false }, {0x0032,0x4000,VR::LT,VM::VM1,"Study Comments","StudyComments",true }, {0x0038,0x0004,VR::SQ,VM::VM1,"Referenced Patient Alias Sequence","ReferencedPatientAliasSequence",false }, {0x0038,0x0008,VR::CS,VM::VM1,"Visit Status ID","VisitStatusID",false }, {0x0038,0x0010,VR::LO,VM::VM1,"Admission ID","AdmissionID",false }, {0x0038,0x0011,VR::LO,VM::VM1,"Issuer of Admission ID","IssuerOfAdmissionID",true }, {0x0038,0x0014,VR::SQ,VM::VM1,"Issuer of Admission ID Sequence","IssuerOfAdmissionIDSequence",false }, {0x0038,0x0016,VR::LO,VM::VM1,"Route of Admissions","RouteOfAdmissions",false }, {0x0038,0x001a,VR::DA,VM::VM1,"Scheduled Admission Date","ScheduledAdmissionDate",true }, {0x0038,0x001b,VR::TM,VM::VM1,"Scheduled Admission Time","ScheduledAdmissionTime",true }, {0x0038,0x001c,VR::DA,VM::VM1,"Scheduled Discharge Date","ScheduledDischargeDate",true }, {0x0038,0x001d,VR::TM,VM::VM1,"Scheduled Discharge Time","ScheduledDischargeTime",true }, {0x0038,0x001e,VR::LO,VM::VM1,"Scheduled Patient Institution Residence","ScheduledPatientInstitutionResidence",true }, {0x0038,0x0020,VR::DA,VM::VM1,"Admitting Date","AdmittingDate",false }, {0x0038,0x0021,VR::TM,VM::VM1,"Admitting Time","AdmittingTime",false }, {0x0038,0x0030,VR::DA,VM::VM1,"Discharge Date","DischargeDate",true }, {0x0038,0x0032,VR::TM,VM::VM1,"Discharge Time","DischargeTime",true }, {0x0038,0x0040,VR::LO,VM::VM1,"Discharge Diagnosis Description","DischargeDiagnosisDescription",true }, {0x0038,0x0044,VR::SQ,VM::VM1,"Discharge Diagnosis Code Sequence","DischargeDiagnosisCodeSequence",true }, {0x0038,0x0050,VR::LO,VM::VM1,"Special Needs","SpecialNeeds",false }, {0x0038,0x0060,VR::LO,VM::VM1,"Service Episode ID","ServiceEpisodeID",false }, {0x0038,0x0061,VR::LO,VM::VM1,"Issuer of Service Episode ID","IssuerOfServiceEpisodeID",true }, {0x0038,0x0062,VR::LO,VM::VM1,"Service Episode Description","ServiceEpisodeDescription",false }, {0x0038,0x0064,VR::SQ,VM::VM1,"Issuer of Service Episode ID Sequence","IssuerOfServiceEpisodeIDSequence",false }, {0x0038,0x0100,VR::SQ,VM::VM1,"Pertinent Documents Sequence","PertinentDocumentsSequence",false }, {0x0038,0x0101,VR::SQ,VM::VM1,"Pertinent Resources Sequence","PertinentResourcesSequence",false }, {0x0038,0x0102,VR::LO,VM::VM1,"Resource Description","ResourceDescription",false }, {0x0038,0x0300,VR::LO,VM::VM1,"Current Patient Location","CurrentPatientLocation",false }, {0x0038,0x0400,VR::LO,VM::VM1,"Patient's Institution Residence","PatientInstitutionResidence",false }, {0x0038,0x0500,VR::LO,VM::VM1,"Patient State","PatientState",false }, {0x0038,0x0502,VR::SQ,VM::VM1,"Patient Clinical Trial Participation Sequence","PatientClinicalTrialParticipationSequence",false }, {0x0038,0x4000,VR::LT,VM::VM1,"Visit Comments","VisitComments",false }, {0x003a,0x0004,VR::CS,VM::VM1,"Waveform Originality","WaveformOriginality",false }, {0x003a,0x0005,VR::US,VM::VM1,"Number of Waveform Channels","NumberOfWaveformChannels",false }, {0x003a,0x0010,VR::UL,VM::VM1,"Number of Waveform Samples","NumberOfWaveformSamples",false }, {0x003a,0x001a,VR::DS,VM::VM1,"Sampling Frequency","SamplingFrequency",false }, {0x003a,0x0020,VR::SH,VM::VM1,"Multiplex Group Label","MultiplexGroupLabel",false }, {0x003a,0x0200,VR::SQ,VM::VM1,"Channel Definition Sequence","ChannelDefinitionSequence",false }, {0x003a,0x0202,VR::IS,VM::VM1,"Waveform Channel Number","WaveformChannelNumber",false }, {0x003a,0x0203,VR::SH,VM::VM1,"Channel Label","ChannelLabel",false }, {0x003a,0x0205,VR::CS,VM::VM1_n,"Channel Status","ChannelStatus",false }, {0x003a,0x0208,VR::SQ,VM::VM1,"Channel Source Sequence","ChannelSourceSequence",false }, {0x003a,0x0209,VR::SQ,VM::VM1,"Channel Source Modifiers Sequence","ChannelSourceModifiersSequence",false }, {0x003a,0x020a,VR::SQ,VM::VM1,"Source Waveform Sequence","SourceWaveformSequence",false }, {0x003a,0x020c,VR::LO,VM::VM1,"Channel Derivation Description","ChannelDerivationDescription",false }, {0x003a,0x0210,VR::DS,VM::VM1,"Channel Sensitivity","ChannelSensitivity",false }, {0x003a,0x0211,VR::SQ,VM::VM1,"Channel Sensitivity Units Sequence","ChannelSensitivityUnitsSequence",false }, {0x003a,0x0212,VR::DS,VM::VM1,"Channel Sensitivity Correction Factor","ChannelSensitivityCorrectionFactor",false }, {0x003a,0x0213,VR::DS,VM::VM1,"Channel Baseline","ChannelBaseline",false }, {0x003a,0x0214,VR::DS,VM::VM1,"Channel Time Skew","ChannelTimeSkew",false }, {0x003a,0x0215,VR::DS,VM::VM1,"Channel Sample Skew","ChannelSampleSkew",false }, {0x003a,0x0218,VR::DS,VM::VM1,"Channel Offset","ChannelOffset",false }, {0x003a,0x021a,VR::US,VM::VM1,"Waveform Bits Stored","WaveformBitsStored",false }, {0x003a,0x0220,VR::DS,VM::VM1,"Filter Low Frequency","FilterLowFrequency",false }, {0x003a,0x0221,VR::DS,VM::VM1,"Filter High Frequency","FilterHighFrequency",false }, {0x003a,0x0222,VR::DS,VM::VM1,"Notch Filter Frequency","NotchFilterFrequency",false }, {0x003a,0x0223,VR::DS,VM::VM1,"Notch Filter Bandwidth","NotchFilterBandwidth",false }, {0x003a,0x0230,VR::FL,VM::VM1,"Waveform Data Display Scale","WaveformDataDisplayScale",false }, {0x003a,0x0231,VR::US,VM::VM3,"Waveform Display Background CIELab Value","WaveformDisplayBackgroundCIELabValue",false }, {0x003a,0x0240,VR::SQ,VM::VM1,"Waveform Presentation Group Sequence","WaveformPresentationGroupSequence",false }, {0x003a,0x0241,VR::US,VM::VM1,"Presentation Group Number","PresentationGroupNumber",false }, {0x003a,0x0242,VR::SQ,VM::VM1,"Channel Display Sequence","ChannelDisplaySequence",false }, {0x003a,0x0244,VR::US,VM::VM3,"Channel Recommended Display CIELab Value","ChannelRecommendedDisplayCIELabValue",false }, {0x003a,0x0245,VR::FL,VM::VM1,"Channel Position","ChannelPosition",false }, {0x003a,0x0246,VR::CS,VM::VM1,"Display Shading Flag","DisplayShadingFlag",false }, {0x003a,0x0247,VR::FL,VM::VM1,"Fractional Channel Display Scale","FractionalChannelDisplayScale",false }, {0x003a,0x0248,VR::FL,VM::VM1,"Absolute Channel Display Scale","AbsoluteChannelDisplayScale",false }, {0x003a,0x0300,VR::SQ,VM::VM1,"Multiplexed Audio Channels Description Code Sequence","MultiplexedAudioChannelsDescriptionCodeSequence",false }, {0x003a,0x0301,VR::IS,VM::VM1,"Channel Identification Code","ChannelIdentificationCode",false }, {0x003a,0x0302,VR::CS,VM::VM1,"Channel Mode","ChannelMode",false }, {0x0040,0x0001,VR::AE,VM::VM1_n,"Scheduled Station AE Title","ScheduledStationAETitle",false }, {0x0040,0x0002,VR::DA,VM::VM1,"Scheduled Procedure Step Start Date","ScheduledProcedureStepStartDate",false }, {0x0040,0x0003,VR::TM,VM::VM1,"Scheduled Procedure Step Start Time","ScheduledProcedureStepStartTime",false }, {0x0040,0x0004,VR::DA,VM::VM1,"Scheduled Procedure Step End Date","ScheduledProcedureStepEndDate",false }, {0x0040,0x0005,VR::TM,VM::VM1,"Scheduled Procedure Step End Time","ScheduledProcedureStepEndTime",false }, {0x0040,0x0006,VR::PN,VM::VM1,"Scheduled Performing Physician's Name","ScheduledPerformingPhysicianName",false }, {0x0040,0x0007,VR::LO,VM::VM1,"Scheduled Procedure Step Description","ScheduledProcedureStepDescription",false }, {0x0040,0x0008,VR::SQ,VM::VM1,"Scheduled Protocol Code Sequence","ScheduledProtocolCodeSequence",false }, {0x0040,0x0009,VR::SH,VM::VM1,"Scheduled Procedure Step ID","ScheduledProcedureStepID",false }, {0x0040,0x000a,VR::SQ,VM::VM1,"Stage Code Sequence","StageCodeSequence",false }, {0x0040,0x000b,VR::SQ,VM::VM1,"Scheduled Performing Physician Identification Sequence","ScheduledPerformingPhysicianIdentificationSequence",false }, {0x0040,0x0010,VR::SH,VM::VM1_n,"Scheduled Station Name","ScheduledStationName",false }, {0x0040,0x0011,VR::SH,VM::VM1,"Scheduled Procedure Step Location","ScheduledProcedureStepLocation",false }, {0x0040,0x0012,VR::LO,VM::VM1,"Pre-Medication","PreMedication",false }, {0x0040,0x0020,VR::CS,VM::VM1,"Scheduled Procedure Step Status","ScheduledProcedureStepStatus",false }, {0x0040,0x0026,VR::SQ,VM::VM1,"Order Placer Identifier Sequence","OrderPlacerIdentifierSequence",false }, {0x0040,0x0027,VR::SQ,VM::VM1,"Order Filler Identifier Sequence","OrderFillerIdentifierSequence",false }, {0x0040,0x0031,VR::UT,VM::VM1,"Local Namespace Entity ID","LocalNamespaceEntityID",false }, {0x0040,0x0032,VR::UT,VM::VM1,"Universal Entity ID","UniversalEntityID",false }, {0x0040,0x0033,VR::CS,VM::VM1,"Universal Entity ID Type","UniversalEntityIDType",false }, {0x0040,0x0035,VR::CS,VM::VM1,"Identifier Type Code","IdentifierTypeCode",false }, {0x0040,0x0036,VR::SQ,VM::VM1,"Assigning Facility Sequence","AssigningFacilitySequence",false }, {0x0040,0x0039,VR::SQ,VM::VM1,"Assigning Jurisdiction Code Sequence","AssigningJurisdictionCodeSequence",false }, {0x0040,0x003a,VR::SQ,VM::VM1,"Assigning Agency or Department Code Sequence","AssigningAgencyOrDepartmentCodeSequence",false }, {0x0040,0x0100,VR::SQ,VM::VM1,"Scheduled Procedure Step Sequence","ScheduledProcedureStepSequence",false }, {0x0040,0x0220,VR::SQ,VM::VM1,"Referenced Non-Image Composite SOP Instance Sequence","ReferencedNonImageCompositeSOPInstanceSequence",false }, {0x0040,0x0241,VR::AE,VM::VM1,"Performed Station AE Title","PerformedStationAETitle",false }, {0x0040,0x0242,VR::SH,VM::VM1,"Performed Station Name","PerformedStationName",false }, {0x0040,0x0243,VR::SH,VM::VM1,"Performed Location","PerformedLocation",false }, {0x0040,0x0244,VR::DA,VM::VM1,"Performed Procedure Step Start Date","PerformedProcedureStepStartDate",false }, {0x0040,0x0245,VR::TM,VM::VM1,"Performed Procedure Step Start Time","PerformedProcedureStepStartTime",false }, {0x0040,0x0250,VR::DA,VM::VM1,"Performed Procedure Step End Date","PerformedProcedureStepEndDate",false }, {0x0040,0x0251,VR::TM,VM::VM1,"Performed Procedure Step End Time","PerformedProcedureStepEndTime",false }, {0x0040,0x0252,VR::CS,VM::VM1,"Performed Procedure Step Status","PerformedProcedureStepStatus",false }, {0x0040,0x0253,VR::SH,VM::VM1,"Performed Procedure Step ID","PerformedProcedureStepID",false }, {0x0040,0x0254,VR::LO,VM::VM1,"Performed Procedure Step Description","PerformedProcedureStepDescription",false }, {0x0040,0x0255,VR::LO,VM::VM1,"Performed Procedure Type Description","PerformedProcedureTypeDescription",false }, {0x0040,0x0260,VR::SQ,VM::VM1,"Performed Protocol Code Sequence","PerformedProtocolCodeSequence",false }, {0x0040,0x0261,VR::CS,VM::VM1,"Performed Protocol Type","PerformedProtocolType",false }, {0x0040,0x0270,VR::SQ,VM::VM1,"Scheduled Step Attributes Sequence","ScheduledStepAttributesSequence",false }, {0x0040,0x0275,VR::SQ,VM::VM1,"Request Attributes Sequence","RequestAttributesSequence",false }, {0x0040,0x0280,VR::ST,VM::VM1,"Comments on the Performed Procedure Step","CommentsOnThePerformedProcedureStep",false }, {0x0040,0x0281,VR::SQ,VM::VM1,"Performed Procedure Step Discontinuation Reason Code Sequence","PerformedProcedureStepDiscontinuationReasonCodeSequence",false }, {0x0040,0x0293,VR::SQ,VM::VM1,"Quantity Sequence","QuantitySequence",false }, {0x0040,0x0294,VR::DS,VM::VM1,"Quantity","Quantity",false }, {0x0040,0x0295,VR::SQ,VM::VM1,"Measuring Units Sequence","MeasuringUnitsSequence",false }, {0x0040,0x0296,VR::SQ,VM::VM1,"Billing Item Sequence","BillingItemSequence",false }, {0x0040,0x0300,VR::US,VM::VM1,"Total Time of Fluoroscopy","TotalTimeOfFluoroscopy",false }, {0x0040,0x0301,VR::US,VM::VM1,"Total Number of Exposures","TotalNumberOfExposures",false }, {0x0040,0x0302,VR::US,VM::VM1,"Entrance Dose","EntranceDose",false }, {0x0040,0x0303,VR::US,VM::VM1_2,"Exposed Area","ExposedArea",false }, {0x0040,0x0306,VR::DS,VM::VM1,"Distance Source to Entrance","DistanceSourceToEntrance",false }, {0x0040,0x0307,VR::DS,VM::VM1,"Distance Source to Support","DistanceSourceToSupport",true }, {0x0040,0x030e,VR::SQ,VM::VM1,"Exposure Dose Sequence","ExposureDoseSequence",false }, {0x0040,0x0310,VR::ST,VM::VM1,"Comments on Radiation Dose","CommentsOnRadiationDose",false }, {0x0040,0x0312,VR::DS,VM::VM1,"X-Ray Output","XRayOutput",false }, {0x0040,0x0314,VR::DS,VM::VM1,"Half Value Layer","HalfValueLayer",false }, {0x0040,0x0316,VR::DS,VM::VM1,"Organ Dose","OrganDose",false }, {0x0040,0x0318,VR::CS,VM::VM1,"Organ Exposed","OrganExposed",false }, {0x0040,0x0320,VR::SQ,VM::VM1,"Billing Procedure Step Sequence","BillingProcedureStepSequence",false }, {0x0040,0x0321,VR::SQ,VM::VM1,"Film Consumption Sequence","FilmConsumptionSequence",false }, {0x0040,0x0324,VR::SQ,VM::VM1,"Billing Supplies and Devices Sequence","BillingSuppliesAndDevicesSequence",false }, {0x0040,0x0330,VR::SQ,VM::VM1,"Referenced Procedure Step Sequence","ReferencedProcedureStepSequence",true }, {0x0040,0x0340,VR::SQ,VM::VM1,"Performed Series Sequence","PerformedSeriesSequence",false }, {0x0040,0x0400,VR::LT,VM::VM1,"Comments on the Scheduled Procedure Step","CommentsOnTheScheduledProcedureStep",false }, {0x0040,0x0440,VR::SQ,VM::VM1,"Protocol Context Sequence","ProtocolContextSequence",false }, {0x0040,0x0441,VR::SQ,VM::VM1,"Content Item Modifier Sequence","ContentItemModifierSequence",false }, {0x0040,0x0500,VR::SQ,VM::VM1,"Scheduled Specimen Sequence","ScheduledSpecimenSequence",false }, {0x0040,0x050a,VR::LO,VM::VM1,"Specimen Accession Number","SpecimenAccessionNumber",true }, {0x0040,0x0512,VR::LO,VM::VM1,"Container Identifier","ContainerIdentifier",false }, {0x0040,0x0513,VR::SQ,VM::VM1,"Issuer of the Container Identifier Sequence","IssuerOfTheContainerIdentifierSequence",false }, {0x0040,0x0515,VR::SQ,VM::VM1,"Alternate Container Identifier Sequence","AlternateContainerIdentifierSequence",false }, {0x0040,0x0518,VR::SQ,VM::VM1,"Container Type Code Sequence","ContainerTypeCodeSequence",false }, {0x0040,0x051a,VR::LO,VM::VM1,"Container Description","ContainerDescription",false }, {0x0040,0x0520,VR::SQ,VM::VM1,"Container Component Sequence","ContainerComponentSequence",false }, {0x0040,0x0550,VR::SQ,VM::VM1,"Specimen Sequence","SpecimenSequence",true }, {0x0040,0x0551,VR::LO,VM::VM1,"Specimen Identifier","SpecimenIdentifier",false }, {0x0040,0x0552,VR::SQ,VM::VM1,"Specimen Description Sequence (Trial)","SpecimenDescriptionSequenceTrial",true }, {0x0040,0x0553,VR::ST,VM::VM1,"Specimen Description (Trial)","SpecimenDescriptionTrial",true }, {0x0040,0x0554,VR::UI,VM::VM1,"Specimen UID","SpecimenUID",false }, {0x0040,0x0555,VR::SQ,VM::VM1,"Acquisition Context Sequence","AcquisitionContextSequence",false }, {0x0040,0x0556,VR::ST,VM::VM1,"Acquisition Context Description","AcquisitionContextDescription",false }, {0x0040,0x0560,VR::SQ,VM::VM1,"Specimen Description Sequence","SpecimenDescriptionSequence",false }, {0x0040,0x0562,VR::SQ,VM::VM1,"Issuer of the Specimen Identifier Sequence","IssuerOfTheSpecimenIdentifierSequence",false }, {0x0040,0x059a,VR::SQ,VM::VM1,"Specimen Type Code Sequence","SpecimenTypeCodeSequence",false }, {0x0040,0x0600,VR::LO,VM::VM1,"Specimen Short Description","SpecimenShortDescription",false }, {0x0040,0x0602,VR::UT,VM::VM1,"Specimen Detailed Description","SpecimenDetailedDescription",false }, {0x0040,0x0610,VR::SQ,VM::VM1,"Specimen Preparation Sequence","SpecimenPreparationSequence",false }, {0x0040,0x0612,VR::SQ,VM::VM1,"Specimen Preparation Step Content Item Sequence","SpecimenPreparationStepContentItemSequence",false }, {0x0040,0x0620,VR::SQ,VM::VM1,"Specimen Localization Content Item Sequence","SpecimenLocalizationContentItemSequence",false }, {0x0040,0x06fa,VR::LO,VM::VM1,"Slide Identifier","SlideIdentifier",true }, {0x0040,0x071a,VR::SQ,VM::VM1,"Image Center Point Coordinates Sequence","ImageCenterPointCoordinatesSequence",false }, {0x0040,0x072a,VR::DS,VM::VM1,"X Offset in Slide Coordinate System","XOffsetInSlideCoordinateSystem",false }, {0x0040,0x073a,VR::DS,VM::VM1,"Y Offset in Slide Coordinate System","YOffsetInSlideCoordinateSystem",false }, {0x0040,0x074a,VR::DS,VM::VM1,"Z Offset in Slide Coordinate System","ZOffsetInSlideCoordinateSystem",false }, {0x0040,0x08d8,VR::SQ,VM::VM1,"Pixel Spacing Sequence","PixelSpacingSequence",true }, {0x0040,0x08da,VR::SQ,VM::VM1,"Coordinate System Axis Code Sequence","CoordinateSystemAxisCodeSequence",true }, {0x0040,0x08ea,VR::SQ,VM::VM1,"Measurement Units Code Sequence","MeasurementUnitsCodeSequence",false }, {0x0040,0x09f8,VR::SQ,VM::VM1,"Vital Stain Code Sequence (Trial)","VitalStainCodeSequenceTrial",true }, {0x0040,0x1001,VR::SH,VM::VM1,"Requested Procedure ID","RequestedProcedureID",false }, {0x0040,0x1002,VR::LO,VM::VM1,"Reason for the Requested Procedure","ReasonForTheRequestedProcedure",false }, {0x0040,0x1003,VR::SH,VM::VM1,"Requested Procedure Priority","RequestedProcedurePriority",false }, {0x0040,0x1004,VR::LO,VM::VM1,"Patient Transport Arrangements","PatientTransportArrangements",false }, {0x0040,0x1005,VR::LO,VM::VM1,"Requested Procedure Location","RequestedProcedureLocation",false }, {0x0040,0x1006,VR::SH,VM::VM1,"Placer Order Number / Procedure","PlacerOrderNumberProcedure",true }, {0x0040,0x1007,VR::SH,VM::VM1,"Filler Order Number / Procedure","FillerOrderNumberProcedure",true }, {0x0040,0x1008,VR::LO,VM::VM1,"Confidentiality Code","ConfidentialityCode",false }, {0x0040,0x1009,VR::SH,VM::VM1,"Reporting Priority","ReportingPriority",false }, {0x0040,0x100a,VR::SQ,VM::VM1,"Reason for Requested Procedure Code Sequence","ReasonForRequestedProcedureCodeSequence",false }, {0x0040,0x1010,VR::PN,VM::VM1_n,"Names of Intended Recipients of Results","NamesOfIntendedRecipientsOfResults",false }, {0x0040,0x1011,VR::SQ,VM::VM1,"Intended Recipients of Results Identification Sequence","IntendedRecipientsOfResultsIdentificationSequence",false }, {0x0040,0x1012,VR::SQ,VM::VM1,"Reason For Performed Procedure Code Sequence","ReasonForPerformedProcedureCodeSequence",false }, {0x0040,0x1060,VR::LO,VM::VM1,"Requested Procedure Description (Trial)","RequestedProcedureDescriptionTrial",true }, {0x0040,0x1101,VR::SQ,VM::VM1,"Person Identification Code Sequence","PersonIdentificationCodeSequence",false }, {0x0040,0x1102,VR::ST,VM::VM1,"Person's Address","PersonAddress",false }, {0x0040,0x1103,VR::LO,VM::VM1_n,"Person's Telephone Numbers","PersonTelephoneNumbers",false }, {0x0040,0x1104,VR::LT,VM::VM1,"Person's Telecom Information","PersonTelecomInformation",false }, {0x0040,0x1400,VR::LT,VM::VM1,"Requested Procedure Comments","RequestedProcedureComments",false }, {0x0040,0x2001,VR::LO,VM::VM1,"Reason for the Imaging Service Request","ReasonForTheImagingServiceRequest",true }, {0x0040,0x2004,VR::DA,VM::VM1,"Issue Date of Imaging Service Request","IssueDateOfImagingServiceRequest",false }, {0x0040,0x2005,VR::TM,VM::VM1,"Issue Time of Imaging Service Request","IssueTimeOfImagingServiceRequest",false }, {0x0040,0x2006,VR::SH,VM::VM1,"Placer Order Number / Imaging Service Request (Retired)","PlacerOrderNumberImagingServiceRequestRetired",true }, {0x0040,0x2007,VR::SH,VM::VM1,"Filler Order Number / Imaging Service Request (Retired)","FillerOrderNumberImagingServiceRequestRetired",true }, {0x0040,0x2008,VR::PN,VM::VM1,"Order Entered By","OrderEnteredBy",false }, {0x0040,0x2009,VR::SH,VM::VM1,"Order Enterer's Location","OrderEntererLocation",false }, {0x0040,0x2010,VR::SH,VM::VM1,"Order Callback Phone Number","OrderCallbackPhoneNumber",false }, {0x0040,0x2011,VR::LT,VM::VM1,"Order Callback Telecom Information","OrderCallbackTelecomInformation",false }, {0x0040,0x2016,VR::LO,VM::VM1,"Placer Order Number / Imaging Service Request","PlacerOrderNumberImagingServiceRequest",false }, {0x0040,0x2017,VR::LO,VM::VM1,"Filler Order Number / Imaging Service Request","FillerOrderNumberImagingServiceRequest",false }, {0x0040,0x2400,VR::LT,VM::VM1,"Imaging Service Request Comments","ImagingServiceRequestComments",false }, {0x0040,0x3001,VR::LO,VM::VM1,"Confidentiality Constraint on Patient Data Description","ConfidentialityConstraintOnPatientDataDescription",false }, {0x0040,0x4001,VR::CS,VM::VM1,"General Purpose Scheduled Procedure Step Status","GeneralPurposeScheduledProcedureStepStatus",true }, {0x0040,0x4002,VR::CS,VM::VM1,"General Purpose Performed Procedure Step Status","GeneralPurposePerformedProcedureStepStatus",true }, {0x0040,0x4003,VR::CS,VM::VM1,"General Purpose Scheduled Procedure Step Priority","GeneralPurposeScheduledProcedureStepPriority",true }, {0x0040,0x4004,VR::SQ,VM::VM1,"Scheduled Processing Applications Code Sequence","ScheduledProcessingApplicationsCodeSequence",true }, {0x0040,0x4005,VR::DT,VM::VM1,"Scheduled Procedure Step Start DateTime","ScheduledProcedureStepStartDateTime",false }, {0x0040,0x4006,VR::CS,VM::VM1,"Multiple Copies Flag","MultipleCopiesFlag",true }, {0x0040,0x4007,VR::SQ,VM::VM1,"Performed Processing Applications Code Sequence","PerformedProcessingApplicationsCodeSequence",false }, {0x0040,0x4009,VR::SQ,VM::VM1,"Human Performer Code Sequence","HumanPerformerCodeSequence",false }, {0x0040,0x4010,VR::DT,VM::VM1,"Scheduled Procedure Step Modification DateTime","ScheduledProcedureStepModificationDateTime",false }, {0x0040,0x4011,VR::DT,VM::VM1,"Expected Completion DateTime","ExpectedCompletionDateTime",false }, {0x0040,0x4015,VR::SQ,VM::VM1,"Resulting General Purpose Performed Procedure Steps Sequence","ResultingGeneralPurposePerformedProcedureStepsSequence",true }, {0x0040,0x4016,VR::SQ,VM::VM1,"Referenced General Purpose Scheduled Procedure Step Sequence","ReferencedGeneralPurposeScheduledProcedureStepSequence",true }, {0x0040,0x4018,VR::SQ,VM::VM1,"Scheduled Workitem Code Sequence","ScheduledWorkitemCodeSequence",false }, {0x0040,0x4019,VR::SQ,VM::VM1,"Performed Workitem Code Sequence","PerformedWorkitemCodeSequence",false }, {0x0040,0x4020,VR::CS,VM::VM1,"Input Availability Flag","InputAvailabilityFlag",false }, {0x0040,0x4021,VR::SQ,VM::VM1,"Input Information Sequence","InputInformationSequence",false }, {0x0040,0x4022,VR::SQ,VM::VM1,"Relevant Information Sequence","RelevantInformationSequence",true }, {0x0040,0x4023,VR::UI,VM::VM1,"Referenced General Purpose Scheduled Procedure Step Transaction UID","ReferencedGeneralPurposeScheduledProcedureStepTransactionUID",true }, {0x0040,0x4025,VR::SQ,VM::VM1,"Scheduled Station Name Code Sequence","ScheduledStationNameCodeSequence",false }, {0x0040,0x4026,VR::SQ,VM::VM1,"Scheduled Station Class Code Sequence","ScheduledStationClassCodeSequence",false }, {0x0040,0x4027,VR::SQ,VM::VM1,"Scheduled Station Geographic Location Code Sequence","ScheduledStationGeographicLocationCodeSequence",false }, {0x0040,0x4028,VR::SQ,VM::VM1,"Performed Station Name Code Sequence","PerformedStationNameCodeSequence",false }, {0x0040,0x4029,VR::SQ,VM::VM1,"Performed Station Class Code Sequence","PerformedStationClassCodeSequence",false }, {0x0040,0x4030,VR::SQ,VM::VM1,"Performed Station Geographic Location Code Sequence","PerformedStationGeographicLocationCodeSequence",false }, {0x0040,0x4031,VR::SQ,VM::VM1,"Requested Subsequent Workitem Code Sequence","RequestedSubsequentWorkitemCodeSequence",true }, {0x0040,0x4032,VR::SQ,VM::VM1,"Non-DICOM Output Code Sequence","NonDICOMOutputCodeSequence",true }, {0x0040,0x4033,VR::SQ,VM::VM1,"Output Information Sequence","OutputInformationSequence",false }, {0x0040,0x4034,VR::SQ,VM::VM1,"Scheduled Human Performers Sequence","ScheduledHumanPerformersSequence",false }, {0x0040,0x4035,VR::SQ,VM::VM1,"Actual Human Performers Sequence","ActualHumanPerformersSequence",false }, {0x0040,0x4036,VR::LO,VM::VM1,"Human Performer's Organization","HumanPerformerOrganization",false }, {0x0040,0x4037,VR::PN,VM::VM1,"Human Performer's Name","HumanPerformerName",false }, {0x0040,0x4040,VR::CS,VM::VM1,"Raw Data Handling","RawDataHandling",false }, {0x0040,0x4041,VR::CS,VM::VM1,"Input Readiness State","InputReadinessState",false }, {0x0040,0x4050,VR::DT,VM::VM1,"Performed Procedure Step Start DateTime","PerformedProcedureStepStartDateTime",false }, {0x0040,0x4051,VR::DT,VM::VM1,"Performed Procedure Step End DateTime","PerformedProcedureStepEndDateTime",false }, {0x0040,0x4052,VR::DT,VM::VM1,"Procedure Step Cancellation DateTime","ProcedureStepCancellationDateTime",false }, {0x0040,0x4070,VR::SQ,VM::VM1,"Output Destination Sequence","OutputDestinationSequence",false }, {0x0040,0x4071,VR::SQ,VM::VM1,"DICOM Storage Sequence","DICOMStorageSequence",false }, {0x0040,0x4072,VR::SQ,VM::VM1,"STOW-RS Storage Sequence","STOWRSStorageSequence",false }, {0x0040,0x4073,VR::UR,VM::VM1,"Storage URL","StorageURL",false }, {0x0040,0x4074,VR::SQ,VM::VM1,"XDS Storage Sequence","XDSStorageSequence",false }, {0x0040,0x8302,VR::DS,VM::VM1,"Entrance Dose in mGy","EntranceDoseInmGy",false }, {0x0040,0x9092,VR::SQ,VM::VM1,"Parametric Map Frame Type Sequence","ParametricMapFrameTypeSequence",false }, {0x0040,0x9094,VR::SQ,VM::VM1,"Referenced Image Real World Value Mapping Sequence","ReferencedImageRealWorldValueMappingSequence",false }, {0x0040,0x9096,VR::SQ,VM::VM1,"Real World Value Mapping Sequence","RealWorldValueMappingSequence",false }, {0x0040,0x9098,VR::SQ,VM::VM1,"Pixel Value Mapping Code Sequence","PixelValueMappingCodeSequence",false }, {0x0040,0x9210,VR::SH,VM::VM1,"LUT Label","LUTLabel",false }, {0x0040,0x9211,VR::US_SS,VM::VM1,"Real World Value Last Value Mapped","RealWorldValueLastValueMapped",false }, {0x0040,0x9212,VR::FD,VM::VM1_n,"Real World Value LUT Data","RealWorldValueLUTData",false }, {0x0040,0x9213,VR::FD,VM::VM1,"Double Float Real World Value Last Value Mapped","DoubleFloatRealWorldValueLastValueMapped",false }, {0x0040,0x9214,VR::FD,VM::VM1,"Double Float Real World Value First Value Mapped","DoubleFloatRealWorldValueFirstValueMapped",false }, {0x0040,0x9216,VR::US_SS,VM::VM1,"Real World Value First Value Mapped","RealWorldValueFirstValueMapped",false }, {0x0040,0x9220,VR::SQ,VM::VM1,"Quantity Definition Sequence","QuantityDefinitionSequence",false }, {0x0040,0x9224,VR::FD,VM::VM1,"Real World Value Intercept","RealWorldValueIntercept",false }, {0x0040,0x9225,VR::FD,VM::VM1,"Real World Value Slope","RealWorldValueSlope",false }, {0x0040,0xa007,VR::CS,VM::VM1,"Findings Flag (Trial)","FindingsFlagTrial",true }, {0x0040,0xa010,VR::CS,VM::VM1,"Relationship Type","RelationshipType",false }, {0x0040,0xa020,VR::SQ,VM::VM1,"Findings Sequence (Trial)","FindingsSequenceTrial",true }, {0x0040,0xa021,VR::UI,VM::VM1,"Findings Group UID (Trial)","FindingsGroupUIDTrial",true }, {0x0040,0xa022,VR::UI,VM::VM1,"Referenced Findings Group UID (Trial)","ReferencedFindingsGroupUIDTrial",true }, {0x0040,0xa023,VR::DA,VM::VM1,"Findings Group Recording Date (Trial)","FindingsGroupRecordingDateTrial",true }, {0x0040,0xa024,VR::TM,VM::VM1,"Findings Group Recording Time (Trial)","FindingsGroupRecordingTimeTrial",true }, {0x0040,0xa026,VR::SQ,VM::VM1,"Findings Source Category Code Sequence (Trial)","FindingsSourceCategoryCodeSequenceTrial",true }, {0x0040,0xa027,VR::LO,VM::VM1,"Verifying Organization","VerifyingOrganization",false }, {0x0040,0xa028,VR::SQ,VM::VM1,"Documenting Organization Identifier Code Sequence (Trial)","DocumentingOrganizationIdentifierCodeSequenceTrial",true }, {0x0040,0xa030,VR::DT,VM::VM1,"Verification DateTime","VerificationDateTime",false }, {0x0040,0xa032,VR::DT,VM::VM1,"Observation DateTime","ObservationDateTime",false }, {0x0040,0xa040,VR::CS,VM::VM1,"Value Type","ValueType",false }, {0x0040,0xa043,VR::SQ,VM::VM1,"Concept Name Code Sequence","ConceptNameCodeSequence",false }, {0x0040,0xa047,VR::LO,VM::VM1,"Measurement Precision Description (Trial)","MeasurementPrecisionDescriptionTrial",true }, {0x0040,0xa050,VR::CS,VM::VM1,"Continuity Of Content","ContinuityOfContent",false }, {0x0040,0xa057,VR::CS,VM::VM1_n,"Urgency or Priority Alerts (Trial)","UrgencyOrPriorityAlertsTrial",true }, {0x0040,0xa060,VR::LO,VM::VM1,"Sequencing Indicator (Trial)","SequencingIndicatorTrial",true }, {0x0040,0xa066,VR::SQ,VM::VM1,"Document Identifier Code Sequence (Trial)","DocumentIdentifierCodeSequenceTrial",true }, {0x0040,0xa067,VR::PN,VM::VM1,"Document Author (Trial)","DocumentAuthorTrial",true }, {0x0040,0xa068,VR::SQ,VM::VM1,"Document Author Identifier Code Sequence (Trial)","DocumentAuthorIdentifierCodeSequenceTrial",true }, {0x0040,0xa070,VR::SQ,VM::VM1,"Identifier Code Sequence (Trial)","IdentifierCodeSequenceTrial",true }, {0x0040,0xa073,VR::SQ,VM::VM1,"Verifying Observer Sequence","VerifyingObserverSequence",false }, {0x0040,0xa074,VR::OB,VM::VM1,"Object Binary Identifier (Trial)","ObjectBinaryIdentifierTrial",true }, {0x0040,0xa075,VR::PN,VM::VM1,"Verifying Observer Name","VerifyingObserverName",false }, {0x0040,0xa076,VR::SQ,VM::VM1,"Documenting Observer Identifier Code Sequence (Trial)","DocumentingObserverIdentifierCodeSequenceTrial",true }, {0x0040,0xa078,VR::SQ,VM::VM1,"Author Observer Sequence","AuthorObserverSequence",false }, {0x0040,0xa07a,VR::SQ,VM::VM1,"Participant Sequence","ParticipantSequence",false }, {0x0040,0xa07c,VR::SQ,VM::VM1,"Custodial Organization Sequence","CustodialOrganizationSequence",false }, {0x0040,0xa080,VR::CS,VM::VM1,"Participation Type","ParticipationType",false }, {0x0040,0xa082,VR::DT,VM::VM1,"Participation DateTime","ParticipationDateTime",false }, {0x0040,0xa084,VR::CS,VM::VM1,"Observer Type","ObserverType",false }, {0x0040,0xa085,VR::SQ,VM::VM1,"Procedure Identifier Code Sequence (Trial)","ProcedureIdentifierCodeSequenceTrial",true }, {0x0040,0xa088,VR::SQ,VM::VM1,"Verifying Observer Identification Code Sequence","VerifyingObserverIdentificationCodeSequence",false }, {0x0040,0xa089,VR::OB,VM::VM1,"Object Directory Binary Identifier (Trial)","ObjectDirectoryBinaryIdentifierTrial",true }, {0x0040,0xa090,VR::SQ,VM::VM1,"Equivalent CDA Document Sequence","EquivalentCDADocumentSequence",true }, {0x0040,0xa0b0,VR::US,VM::VM2_2n,"Referenced Waveform Channels","ReferencedWaveformChannels",false }, {0x0040,0xa110,VR::DA,VM::VM1,"Date of Document or Verbal Transaction (Trial)","DateOfDocumentOrVerbalTransactionTrial",true }, {0x0040,0xa112,VR::TM,VM::VM1,"Time of Document Creation or Verbal Transaction (Trial)","TimeOfDocumentCreationOrVerbalTransactionTrial",true }, {0x0040,0xa120,VR::DT,VM::VM1,"DateTime","DateTime",false }, {0x0040,0xa121,VR::DA,VM::VM1,"Date","Date",false }, {0x0040,0xa122,VR::TM,VM::VM1,"Time","Time",false }, {0x0040,0xa123,VR::PN,VM::VM1,"Person Name","PersonName",false }, {0x0040,0xa124,VR::UI,VM::VM1,"UID","UID",false }, {0x0040,0xa125,VR::CS,VM::VM2,"Report Status ID (Trial)","ReportStatusIDTrial",true }, {0x0040,0xa130,VR::CS,VM::VM1,"Temporal Range Type","TemporalRangeType",false }, {0x0040,0xa132,VR::UL,VM::VM1_n,"Referenced Sample Positions","ReferencedSamplePositions",false }, {0x0040,0xa136,VR::US,VM::VM1_n,"Referenced Frame Numbers","ReferencedFrameNumbers",false }, {0x0040,0xa138,VR::DS,VM::VM1_n,"Referenced Time Offsets","ReferencedTimeOffsets",false }, {0x0040,0xa13a,VR::DT,VM::VM1_n,"Referenced DateTime","ReferencedDateTime",false }, {0x0040,0xa160,VR::UT,VM::VM1,"Text Value","TextValue",false }, {0x0040,0xa161,VR::FD,VM::VM1_n,"Floating Point Value","FloatingPointValue",false }, {0x0040,0xa162,VR::SL,VM::VM1_n,"Rational Numerator Value","RationalNumeratorValue",false }, {0x0040,0xa163,VR::UL,VM::VM1_n,"Rational Denominator Value","RationalDenominatorValue",false }, {0x0040,0xa167,VR::SQ,VM::VM1,"Observation Category Code Sequence (Trial)","ObservationCategoryCodeSequenceTrial",true }, {0x0040,0xa168,VR::SQ,VM::VM1,"Concept Code Sequence","ConceptCodeSequence",false }, {0x0040,0xa16a,VR::ST,VM::VM1,"Bibliographic Citation (Trial)","BibliographicCitationTrial",true }, {0x0040,0xa170,VR::SQ,VM::VM1,"Purpose of Reference Code Sequence","PurposeOfReferenceCodeSequence",false }, {0x0040,0xa171,VR::UI,VM::VM1,"Observation UID","ObservationUID",false }, {0x0040,0xa172,VR::UI,VM::VM1,"Referenced Observation UID (Trial)","ReferencedObservationUIDTrial",true }, {0x0040,0xa173,VR::CS,VM::VM1,"Referenced Observation Class (Trial)","ReferencedObservationClassTrial",true }, {0x0040,0xa174,VR::CS,VM::VM1,"Referenced Object Observation Class (Trial)","ReferencedObjectObservationClassTrial",true }, {0x0040,0xa180,VR::US,VM::VM1,"Annotation Group Number","AnnotationGroupNumber",false }, {0x0040,0xa192,VR::DA,VM::VM1,"Observation Date (Trial)","ObservationDateTrial",true }, {0x0040,0xa193,VR::TM,VM::VM1,"Observation Time (Trial)","ObservationTimeTrial",true }, {0x0040,0xa194,VR::CS,VM::VM1,"Measurement Automation (Trial)","MeasurementAutomationTrial",true }, {0x0040,0xa195,VR::SQ,VM::VM1,"Modifier Code Sequence","ModifierCodeSequence",false }, {0x0040,0xa224,VR::ST,VM::VM1,"Identification Description (Trial)","IdentificationDescriptionTrial",true }, {0x0040,0xa290,VR::CS,VM::VM1,"Coordinates Set Geometric Type (Trial)","CoordinatesSetGeometricTypeTrial",true }, {0x0040,0xa296,VR::SQ,VM::VM1,"Algorithm Code Sequence (Trial)","AlgorithmCodeSequenceTrial",true }, {0x0040,0xa297,VR::ST,VM::VM1,"Algorithm Description (Trial)","AlgorithmDescriptionTrial",true }, {0x0040,0xa29a,VR::SL,VM::VM2_2n,"Pixel Coordinates Set (Trial)","PixelCoordinatesSetTrial",true }, {0x0040,0xa300,VR::SQ,VM::VM1,"Measured Value Sequence","MeasuredValueSequence",false }, {0x0040,0xa301,VR::SQ,VM::VM1,"Numeric Value Qualifier Code Sequence","NumericValueQualifierCodeSequence",false }, {0x0040,0xa307,VR::PN,VM::VM1,"Current Observer (Trial)","CurrentObserverTrial",true }, {0x0040,0xa30a,VR::DS,VM::VM1_n,"Numeric Value","NumericValue",false }, {0x0040,0xa313,VR::SQ,VM::VM1,"Referenced Accession Sequence (Trial)","ReferencedAccessionSequenceTrial",true }, {0x0040,0xa33a,VR::ST,VM::VM1,"Report Status Comment (Trial)","ReportStatusCommentTrial",true }, {0x0040,0xa340,VR::SQ,VM::VM1,"Procedure Context Sequence (Trial)","ProcedureContextSequenceTrial",true }, {0x0040,0xa352,VR::PN,VM::VM1,"Verbal Source (Trial)","VerbalSourceTrial",true }, {0x0040,0xa353,VR::ST,VM::VM1,"Address (Trial)","AddressTrial",true }, {0x0040,0xa354,VR::LO,VM::VM1,"Telephone Number (Trial)","TelephoneNumberTrial",true }, {0x0040,0xa358,VR::SQ,VM::VM1,"Verbal Source Identifier Code Sequence (Trial)","VerbalSourceIdentifierCodeSequenceTrial",true }, {0x0040,0xa360,VR::SQ,VM::VM1,"Predecessor Documents Sequence","PredecessorDocumentsSequence",false }, {0x0040,0xa370,VR::SQ,VM::VM1,"Referenced Request Sequence","ReferencedRequestSequence",false }, {0x0040,0xa372,VR::SQ,VM::VM1,"Performed Procedure Code Sequence","PerformedProcedureCodeSequence",false }, {0x0040,0xa375,VR::SQ,VM::VM1,"Current Requested Procedure Evidence Sequence","CurrentRequestedProcedureEvidenceSequence",false }, {0x0040,0xa380,VR::SQ,VM::VM1,"Report Detail Sequence (Trial)","ReportDetailSequenceTrial",true }, {0x0040,0xa385,VR::SQ,VM::VM1,"Pertinent Other Evidence Sequence","PertinentOtherEvidenceSequence",false }, {0x0040,0xa390,VR::SQ,VM::VM1,"HL7 Structured Document Reference Sequence","HL7StructuredDocumentReferenceSequence",false }, {0x0040,0xa402,VR::UI,VM::VM1,"Observation Subject UID (Trial)","ObservationSubjectUIDTrial",true }, {0x0040,0xa403,VR::CS,VM::VM1,"Observation Subject Class (Trial)","ObservationSubjectClassTrial",true }, {0x0040,0xa404,VR::SQ,VM::VM1,"Observation Subject Type Code Sequence (Trial)","ObservationSubjectTypeCodeSequenceTrial",true }, {0x0040,0xa491,VR::CS,VM::VM1,"Completion Flag","CompletionFlag",false }, {0x0040,0xa492,VR::LO,VM::VM1,"Completion Flag Description","CompletionFlagDescription",false }, {0x0040,0xa493,VR::CS,VM::VM1,"Verification Flag","VerificationFlag",false }, {0x0040,0xa494,VR::CS,VM::VM1,"Archive Requested","ArchiveRequested",false }, {0x0040,0xa496,VR::CS,VM::VM1,"Preliminary Flag","PreliminaryFlag",false }, {0x0040,0xa504,VR::SQ,VM::VM1,"Content Template Sequence","ContentTemplateSequence",false }, {0x0040,0xa525,VR::SQ,VM::VM1,"Identical Documents Sequence","IdenticalDocumentsSequence",false }, {0x0040,0xa600,VR::CS,VM::VM1,"Observation Subject Context Flag (Trial)","ObservationSubjectContextFlagTrial",true }, {0x0040,0xa601,VR::CS,VM::VM1,"Observer Context Flag (Trial)","ObserverContextFlagTrial",true }, {0x0040,0xa603,VR::CS,VM::VM1,"Procedure Context Flag (Trial)","ProcedureContextFlagTrial",true }, {0x0040,0xa730,VR::SQ,VM::VM1,"Content Sequence","ContentSequence",false }, {0x0040,0xa731,VR::SQ,VM::VM1,"Relationship Sequence (Trial)","RelationshipSequenceTrial",true }, {0x0040,0xa732,VR::SQ,VM::VM1,"Relationship Type Code Sequence (Trial)","RelationshipTypeCodeSequenceTrial",true }, {0x0040,0xa744,VR::SQ,VM::VM1,"Language Code Sequence (Trial)","LanguageCodeSequenceTrial",true }, {0x0040,0xa992,VR::ST,VM::VM1,"Uniform Resource Locator (Trial)","UniformResourceLocatorTrial",true }, {0x0040,0xb020,VR::SQ,VM::VM1,"Waveform Annotation Sequence","WaveformAnnotationSequence",false }, {0x0040,0xdb00,VR::CS,VM::VM1,"Template Identifier","TemplateIdentifier",false }, {0x0040,0xdb06,VR::DT,VM::VM1,"Template Version","TemplateVersion",true }, {0x0040,0xdb07,VR::DT,VM::VM1,"Template Local Version","TemplateLocalVersion",true }, {0x0040,0xdb0b,VR::CS,VM::VM1,"Template Extension Flag","TemplateExtensionFlag",true }, {0x0040,0xdb0c,VR::UI,VM::VM1,"Template Extension Organization UID","TemplateExtensionOrganizationUID",true }, {0x0040,0xdb0d,VR::UI,VM::VM1,"Template Extension Creator UID","TemplateExtensionCreatorUID",true }, {0x0040,0xdb73,VR::UL,VM::VM1_n,"Referenced Content Item Identifier","ReferencedContentItemIdentifier",false }, {0x0040,0xe001,VR::ST,VM::VM1,"HL7 Instance Identifier","HL7InstanceIdentifier",false }, {0x0040,0xe004,VR::DT,VM::VM1,"HL7 Document Effective Time","HL7DocumentEffectiveTime",false }, {0x0040,0xe006,VR::SQ,VM::VM1,"HL7 Document Type Code Sequence","HL7DocumentTypeCodeSequence",false }, {0x0040,0xe008,VR::SQ,VM::VM1,"Document Class Code Sequence","DocumentClassCodeSequence",false }, {0x0040,0xe010,VR::UR,VM::VM1,"Retrieve URI","RetrieveURI",false }, {0x0040,0xe011,VR::UI,VM::VM1,"Retrieve Location UID","RetrieveLocationUID",false }, {0x0040,0xe020,VR::CS,VM::VM1,"Type of Instances","TypeOfInstances",false }, {0x0040,0xe021,VR::SQ,VM::VM1,"DICOM Retrieval Sequence","DICOMRetrievalSequence",false }, {0x0040,0xe022,VR::SQ,VM::VM1,"DICOM Media Retrieval Sequence","DICOMMediaRetrievalSequence",false }, {0x0040,0xe023,VR::SQ,VM::VM1,"WADO Retrieval Sequence","WADORetrievalSequence",false }, {0x0040,0xe024,VR::SQ,VM::VM1,"XDS Retrieval Sequence","XDSRetrievalSequence",false }, {0x0040,0xe025,VR::SQ,VM::VM1,"WADO-RS Retrieval Sequence","WADORSRetrievalSequence",false }, {0x0040,0xe030,VR::UI,VM::VM1,"Repository Unique ID","RepositoryUniqueID",false }, {0x0040,0xe031,VR::UI,VM::VM1,"Home Community ID","HomeCommunityID",false }, {0x0042,0x0010,VR::ST,VM::VM1,"Document Title","DocumentTitle",false }, {0x0042,0x0011,VR::OB,VM::VM1,"Encapsulated Document","EncapsulatedDocument",false }, {0x0042,0x0012,VR::LO,VM::VM1,"MIME Type of Encapsulated Document","MIMETypeOfEncapsulatedDocument",false }, {0x0042,0x0013,VR::SQ,VM::VM1,"Source Instance Sequence","SourceInstanceSequence",false }, {0x0042,0x0014,VR::LO,VM::VM1_n,"List of MIME Types","ListOfMIMETypes",false }, {0x0044,0x0001,VR::ST,VM::VM1,"Product Package Identifier","ProductPackageIdentifier",false }, {0x0044,0x0002,VR::CS,VM::VM1,"Substance Administration Approval","SubstanceAdministrationApproval",false }, {0x0044,0x0003,VR::LT,VM::VM1,"Approval Status Further Description","ApprovalStatusFurtherDescription",false }, {0x0044,0x0004,VR::DT,VM::VM1,"Approval Status DateTime","ApprovalStatusDateTime",false }, {0x0044,0x0007,VR::SQ,VM::VM1,"Product Type Code Sequence","ProductTypeCodeSequence",false }, {0x0044,0x0008,VR::LO,VM::VM1_n,"Product Name","ProductName",false }, {0x0044,0x0009,VR::LT,VM::VM1,"Product Description","ProductDescription",false }, {0x0044,0x000a,VR::LO,VM::VM1,"Product Lot Identifier","ProductLotIdentifier",false }, {0x0044,0x000b,VR::DT,VM::VM1,"Product Expiration DateTime","ProductExpirationDateTime",false }, {0x0044,0x0010,VR::DT,VM::VM1,"Substance Administration DateTime","SubstanceAdministrationDateTime",false }, {0x0044,0x0011,VR::LO,VM::VM1,"Substance Administration Notes","SubstanceAdministrationNotes",false }, {0x0044,0x0012,VR::LO,VM::VM1,"Substance Administration Device ID","SubstanceAdministrationDeviceID",false }, {0x0044,0x0013,VR::SQ,VM::VM1,"Product Parameter Sequence","ProductParameterSequence",false }, {0x0044,0x0019,VR::SQ,VM::VM1,"Substance Administration Parameter Sequence","SubstanceAdministrationParameterSequence",false }, {0x0046,0x0012,VR::LO,VM::VM1,"Lens Description","LensDescription",false }, {0x0046,0x0014,VR::SQ,VM::VM1,"Right Lens Sequence","RightLensSequence",false }, {0x0046,0x0015,VR::SQ,VM::VM1,"Left Lens Sequence","LeftLensSequence",false }, {0x0046,0x0016,VR::SQ,VM::VM1,"Unspecified Laterality Lens Sequence","UnspecifiedLateralityLensSequence",false }, {0x0046,0x0018,VR::SQ,VM::VM1,"Cylinder Sequence","CylinderSequence",false }, {0x0046,0x0028,VR::SQ,VM::VM1,"Prism Sequence","PrismSequence",false }, {0x0046,0x0030,VR::FD,VM::VM1,"Horizontal Prism Power","HorizontalPrismPower",false }, {0x0046,0x0032,VR::CS,VM::VM1,"Horizontal Prism Base","HorizontalPrismBase",false }, {0x0046,0x0034,VR::FD,VM::VM1,"Vertical Prism Power","VerticalPrismPower",false }, {0x0046,0x0036,VR::CS,VM::VM1,"Vertical Prism Base","VerticalPrismBase",false }, {0x0046,0x0038,VR::CS,VM::VM1,"Lens Segment Type","LensSegmentType",false }, {0x0046,0x0040,VR::FD,VM::VM1,"Optical Transmittance","OpticalTransmittance",false }, {0x0046,0x0042,VR::FD,VM::VM1,"Channel Width","ChannelWidth",false }, {0x0046,0x0044,VR::FD,VM::VM1,"Pupil Size","PupilSize",false }, {0x0046,0x0046,VR::FD,VM::VM1,"Corneal Size","CornealSize",false }, {0x0046,0x0050,VR::SQ,VM::VM1,"Autorefraction Right Eye Sequence","AutorefractionRightEyeSequence",false }, {0x0046,0x0052,VR::SQ,VM::VM1,"Autorefraction Left Eye Sequence","AutorefractionLeftEyeSequence",false }, {0x0046,0x0060,VR::FD,VM::VM1,"Distance Pupillary Distance","DistancePupillaryDistance",false }, {0x0046,0x0062,VR::FD,VM::VM1,"Near Pupillary Distance","NearPupillaryDistance",false }, {0x0046,0x0063,VR::FD,VM::VM1,"Intermediate Pupillary Distance","IntermediatePupillaryDistance",false }, {0x0046,0x0064,VR::FD,VM::VM1,"Other Pupillary Distance","OtherPupillaryDistance",false }, {0x0046,0x0070,VR::SQ,VM::VM1,"Keratometry Right Eye Sequence","KeratometryRightEyeSequence",false }, {0x0046,0x0071,VR::SQ,VM::VM1,"Keratometry Left Eye Sequence","KeratometryLeftEyeSequence",false }, {0x0046,0x0074,VR::SQ,VM::VM1,"Steep Keratometric Axis Sequence","SteepKeratometricAxisSequence",false }, {0x0046,0x0075,VR::FD,VM::VM1,"Radius of Curvature","RadiusOfCurvature",false }, {0x0046,0x0076,VR::FD,VM::VM1,"Keratometric Power","KeratometricPower",false }, {0x0046,0x0077,VR::FD,VM::VM1,"Keratometric Axis","KeratometricAxis",false }, {0x0046,0x0080,VR::SQ,VM::VM1,"Flat Keratometric Axis Sequence","FlatKeratometricAxisSequence",false }, {0x0046,0x0092,VR::CS,VM::VM1,"Background Color","BackgroundColor",false }, {0x0046,0x0094,VR::CS,VM::VM1,"Optotype","Optotype",false }, {0x0046,0x0095,VR::CS,VM::VM1,"Optotype Presentation","OptotypePresentation",false }, {0x0046,0x0097,VR::SQ,VM::VM1,"Subjective Refraction Right Eye Sequence","SubjectiveRefractionRightEyeSequence",false }, {0x0046,0x0098,VR::SQ,VM::VM1,"Subjective Refraction Left Eye Sequence","SubjectiveRefractionLeftEyeSequence",false }, {0x0046,0x0100,VR::SQ,VM::VM1,"Add Near Sequence","AddNearSequence",false }, {0x0046,0x0101,VR::SQ,VM::VM1,"Add Intermediate Sequence","AddIntermediateSequence",false }, {0x0046,0x0102,VR::SQ,VM::VM1,"Add Other Sequence","AddOtherSequence",false }, {0x0046,0x0104,VR::FD,VM::VM1,"Add Power","AddPower",false }, {0x0046,0x0106,VR::FD,VM::VM1,"Viewing Distance","ViewingDistance",false }, {0x0046,0x0121,VR::SQ,VM::VM1,"Visual Acuity Type Code Sequence","VisualAcuityTypeCodeSequence",false }, {0x0046,0x0122,VR::SQ,VM::VM1,"Visual Acuity Right Eye Sequence","VisualAcuityRightEyeSequence",false }, {0x0046,0x0123,VR::SQ,VM::VM1,"Visual Acuity Left Eye Sequence","VisualAcuityLeftEyeSequence",false }, {0x0046,0x0124,VR::SQ,VM::VM1,"Visual Acuity Both Eyes Open Sequence","VisualAcuityBothEyesOpenSequence",false }, {0x0046,0x0125,VR::CS,VM::VM1,"Viewing Distance Type","ViewingDistanceType",false }, {0x0046,0x0135,VR::SS,VM::VM2,"Visual Acuity Modifiers","VisualAcuityModifiers",false }, {0x0046,0x0137,VR::FD,VM::VM1,"Decimal Visual Acuity","DecimalVisualAcuity",false }, {0x0046,0x0139,VR::LO,VM::VM1,"Optotype Detailed Definition","OptotypeDetailedDefinition",false }, {0x0046,0x0145,VR::SQ,VM::VM1,"Referenced Refractive Measurements Sequence","ReferencedRefractiveMeasurementsSequence",false }, {0x0046,0x0146,VR::FD,VM::VM1,"Sphere Power","SpherePower",false }, {0x0046,0x0147,VR::FD,VM::VM1,"Cylinder Power","CylinderPower",false }, {0x0046,0x0201,VR::CS,VM::VM1,"Corneal Topography Surface","CornealTopographySurface",false }, {0x0046,0x0202,VR::FL,VM::VM2,"Corneal Vertex Location","CornealVertexLocation",false }, {0x0046,0x0203,VR::FL,VM::VM1,"Pupil Centroid X-Coordinate","PupilCentroidXCoordinate",false }, {0x0046,0x0204,VR::FL,VM::VM1,"Pupil Centroid Y-Coordinate","PupilCentroidYCoordinate",false }, {0x0046,0x0205,VR::FL,VM::VM1,"Equivalent Pupil Radius","EquivalentPupilRadius",false }, {0x0046,0x0207,VR::SQ,VM::VM1,"Corneal Topography Map Type Code Sequence","CornealTopographyMapTypeCodeSequence",false }, {0x0046,0x0208,VR::IS,VM::VM2_2n,"Vertices of the Outline of Pupil","VerticesOfTheOutlineOfPupil",false }, {0x0046,0x0210,VR::SQ,VM::VM1,"Corneal Topography Mapping Normals Sequence","CornealTopographyMappingNormalsSequence",false }, {0x0046,0x0211,VR::SQ,VM::VM1,"Maximum Corneal Curvature Sequence","MaximumCornealCurvatureSequence",false }, {0x0046,0x0212,VR::FL,VM::VM1,"Maximum Corneal Curvature","MaximumCornealCurvature",false }, {0x0046,0x0213,VR::FL,VM::VM2,"Maximum Corneal Curvature Location","MaximumCornealCurvatureLocation",false }, {0x0046,0x0215,VR::SQ,VM::VM1,"Minimum Keratometric Sequence","MinimumKeratometricSequence",false }, {0x0046,0x0218,VR::SQ,VM::VM1,"Simulated Keratometric Cylinder Sequence","SimulatedKeratometricCylinderSequence",false }, {0x0046,0x0220,VR::FL,VM::VM1,"Average Corneal Power","AverageCornealPower",false }, {0x0046,0x0224,VR::FL,VM::VM1,"Corneal I-S Value","CornealISValue",false }, {0x0046,0x0227,VR::FL,VM::VM1,"Analyzed Area","AnalyzedArea",false }, {0x0046,0x0230,VR::FL,VM::VM1,"Surface Regularity Index","SurfaceRegularityIndex",false }, {0x0046,0x0232,VR::FL,VM::VM1,"Surface Asymmetry Index","SurfaceAsymmetryIndex",false }, {0x0046,0x0234,VR::FL,VM::VM1,"Corneal Eccentricity Index","CornealEccentricityIndex",false }, {0x0046,0x0236,VR::FL,VM::VM1,"Keratoconus Prediction Index","KeratoconusPredictionIndex",false }, {0x0046,0x0238,VR::FL,VM::VM1,"Decimal Potential Visual Acuity","DecimalPotentialVisualAcuity",false }, {0x0046,0x0242,VR::CS,VM::VM1,"Corneal Topography Map Quality Evaluation","CornealTopographyMapQualityEvaluation",false }, {0x0046,0x0244,VR::SQ,VM::VM1,"Source Image Corneal Processed Data Sequence","SourceImageCornealProcessedDataSequence",false }, {0x0046,0x0247,VR::FL,VM::VM3,"Corneal Point Location","CornealPointLocation",false }, {0x0046,0x0248,VR::CS,VM::VM1,"Corneal Point Estimated","CornealPointEstimated",false }, {0x0046,0x0249,VR::FL,VM::VM1,"Axial Power","AxialPower",false }, {0x0046,0x0250,VR::FL,VM::VM1,"Tangential Power","TangentialPower",false }, {0x0046,0x0251,VR::FL,VM::VM1,"Refractive Power","RefractivePower",false }, {0x0046,0x0252,VR::FL,VM::VM1,"Relative Elevation","RelativeElevation",false }, {0x0046,0x0253,VR::FL,VM::VM1,"Corneal Wavefront","CornealWavefront",false }, {0x0048,0x0001,VR::FL,VM::VM1,"Imaged Volume Width","ImagedVolumeWidth",false }, {0x0048,0x0002,VR::FL,VM::VM1,"Imaged Volume Height","ImagedVolumeHeight",false }, {0x0048,0x0003,VR::FL,VM::VM1,"Imaged Volume Depth","ImagedVolumeDepth",false }, {0x0048,0x0006,VR::UL,VM::VM1,"Total Pixel Matrix Columns","TotalPixelMatrixColumns",false }, {0x0048,0x0007,VR::UL,VM::VM1,"Total Pixel Matrix Rows","TotalPixelMatrixRows",false }, {0x0048,0x0008,VR::SQ,VM::VM1,"Total Pixel Matrix Origin Sequence","TotalPixelMatrixOriginSequence",false }, {0x0048,0x0010,VR::CS,VM::VM1,"Specimen Label in Image","SpecimenLabelInImage",false }, {0x0048,0x0011,VR::CS,VM::VM1,"Focus Method","FocusMethod",false }, {0x0048,0x0012,VR::CS,VM::VM1,"Extended Depth of Field","ExtendedDepthOfField",false }, {0x0048,0x0013,VR::US,VM::VM1,"Number of Focal Planes","NumberOfFocalPlanes",false }, {0x0048,0x0014,VR::FL,VM::VM1,"Distance Between Focal Planes","DistanceBetweenFocalPlanes",false }, {0x0048,0x0015,VR::US,VM::VM3,"Recommended Absent Pixel CIELab Value","RecommendedAbsentPixelCIELabValue",false }, {0x0048,0x0100,VR::SQ,VM::VM1,"Illuminator Type Code Sequence","IlluminatorTypeCodeSequence",false }, {0x0048,0x0102,VR::DS,VM::VM6,"Image Orientation (Slide)","ImageOrientationSlide",false }, {0x0048,0x0105,VR::SQ,VM::VM1,"Optical Path Sequence","OpticalPathSequence",false }, {0x0048,0x0106,VR::SH,VM::VM1,"Optical Path Identifier","OpticalPathIdentifier",false }, {0x0048,0x0107,VR::ST,VM::VM1,"Optical Path Description","OpticalPathDescription",false }, {0x0048,0x0108,VR::SQ,VM::VM1,"Illumination Color Code Sequence","IlluminationColorCodeSequence",false }, {0x0048,0x0110,VR::SQ,VM::VM1,"Specimen Reference Sequence","SpecimenReferenceSequence",false }, {0x0048,0x0111,VR::DS,VM::VM1,"Condenser Lens Power","CondenserLensPower",false }, {0x0048,0x0112,VR::DS,VM::VM1,"Objective Lens Power","ObjectiveLensPower",false }, {0x0048,0x0113,VR::DS,VM::VM1,"Objective Lens Numerical Aperture","ObjectiveLensNumericalAperture",false }, {0x0048,0x0120,VR::SQ,VM::VM1,"Palette Color Lookup Table Sequence","PaletteColorLookupTableSequence",false }, {0x0048,0x0200,VR::SQ,VM::VM1,"Referenced Image Navigation Sequence","ReferencedImageNavigationSequence",false }, {0x0048,0x0201,VR::US,VM::VM2,"Top Left Hand Corner of Localizer Area","TopLeftHandCornerOfLocalizerArea",false }, {0x0048,0x0202,VR::US,VM::VM2,"Bottom Right Hand Corner of Localizer Area","BottomRightHandCornerOfLocalizerArea",false }, {0x0048,0x0207,VR::SQ,VM::VM1,"Optical Path Identification Sequence","OpticalPathIdentificationSequence",false }, {0x0048,0x021a,VR::SQ,VM::VM1,"Plane Position (Slide) Sequence","PlanePositionSlideSequence",false }, {0x0048,0x021e,VR::SL,VM::VM1,"Column Position In Total Image Pixel Matrix","ColumnPositionInTotalImagePixelMatrix",false }, {0x0048,0x021f,VR::SL,VM::VM1,"Row Position In Total Image Pixel Matrix","RowPositionInTotalImagePixelMatrix",false }, {0x0048,0x0301,VR::CS,VM::VM1,"Pixel Origin Interpretation","PixelOriginInterpretation",false }, {0x0050,0x0004,VR::CS,VM::VM1,"Calibration Image","CalibrationImage",false }, {0x0050,0x0010,VR::SQ,VM::VM1,"Device Sequence","DeviceSequence",false }, {0x0050,0x0012,VR::SQ,VM::VM1,"Container Component Type Code Sequence","ContainerComponentTypeCodeSequence",false }, {0x0050,0x0013,VR::FD,VM::VM1,"Container Component Thickness","ContainerComponentThickness",false }, {0x0050,0x0014,VR::DS,VM::VM1,"Device Length","DeviceLength",false }, {0x0050,0x0015,VR::FD,VM::VM1,"Container Component Width","ContainerComponentWidth",false }, {0x0050,0x0016,VR::DS,VM::VM1,"Device Diameter","DeviceDiameter",false }, {0x0050,0x0017,VR::CS,VM::VM1,"Device Diameter Units","DeviceDiameterUnits",false }, {0x0050,0x0018,VR::DS,VM::VM1,"Device Volume","DeviceVolume",false }, {0x0050,0x0019,VR::DS,VM::VM1,"Inter-Marker Distance","InterMarkerDistance",false }, {0x0050,0x001a,VR::CS,VM::VM1,"Container Component Material","ContainerComponentMaterial",false }, {0x0050,0x001b,VR::LO,VM::VM1,"Container Component ID","ContainerComponentID",false }, {0x0050,0x001c,VR::FD,VM::VM1,"Container Component Length","ContainerComponentLength",false }, {0x0050,0x001d,VR::FD,VM::VM1,"Container Component Diameter","ContainerComponentDiameter",false }, {0x0050,0x001e,VR::LO,VM::VM1,"Container Component Description","ContainerComponentDescription",false }, {0x0050,0x0020,VR::LO,VM::VM1,"Device Description","DeviceDescription",false }, {0x0052,0x0001,VR::FL,VM::VM1,"Contrast/Bolus Ingredient Percent by Volume","ContrastBolusIngredientPercentByVolume",false }, {0x0052,0x0002,VR::FD,VM::VM1,"OCT Focal Distance","OCTFocalDistance",false }, {0x0052,0x0003,VR::FD,VM::VM1,"Beam Spot Size","BeamSpotSize",false }, {0x0052,0x0004,VR::FD,VM::VM1,"Effective Refractive Index","EffectiveRefractiveIndex",false }, {0x0052,0x0006,VR::CS,VM::VM1,"OCT Acquisition Domain","OCTAcquisitionDomain",false }, {0x0052,0x0007,VR::FD,VM::VM1,"OCT Optical Center Wavelength","OCTOpticalCenterWavelength",false }, {0x0052,0x0008,VR::FD,VM::VM1,"Axial Resolution","AxialResolution",false }, {0x0052,0x0009,VR::FD,VM::VM1,"Ranging Depth","RangingDepth",false }, {0x0052,0x0011,VR::FD,VM::VM1,"A-line Rate","ALineRate",false }, {0x0052,0x0012,VR::US,VM::VM1,"A-lines Per Frame","ALinesPerFrame",false }, {0x0052,0x0013,VR::FD,VM::VM1,"Catheter Rotational Rate","CatheterRotationalRate",false }, {0x0052,0x0014,VR::FD,VM::VM1,"A-line Pixel Spacing","ALinePixelSpacing",false }, {0x0052,0x0016,VR::SQ,VM::VM1,"Mode of Percutaneous Access Sequence","ModeOfPercutaneousAccessSequence",false }, {0x0052,0x0025,VR::SQ,VM::VM1,"Intravascular OCT Frame Type Sequence","IntravascularOCTFrameTypeSequence",false }, {0x0052,0x0026,VR::CS,VM::VM1,"OCT Z Offset Applied","OCTZOffsetApplied",false }, {0x0052,0x0027,VR::SQ,VM::VM1,"Intravascular Frame Content Sequence","IntravascularFrameContentSequence",false }, {0x0052,0x0028,VR::FD,VM::VM1,"Intravascular Longitudinal Distance","IntravascularLongitudinalDistance",false }, {0x0052,0x0029,VR::SQ,VM::VM1,"Intravascular OCT Frame Content Sequence","IntravascularOCTFrameContentSequence",false }, {0x0052,0x0030,VR::SS,VM::VM1,"OCT Z Offset Correction","OCTZOffsetCorrection",false }, {0x0052,0x0031,VR::CS,VM::VM1,"Catheter Direction of Rotation","CatheterDirectionOfRotation",false }, {0x0052,0x0033,VR::FD,VM::VM1,"Seam Line Location","SeamLineLocation",false }, {0x0052,0x0034,VR::FD,VM::VM1,"First A-line Location","FirstALineLocation",false }, {0x0052,0x0036,VR::US,VM::VM1,"Seam Line Index","SeamLineIndex",false }, {0x0052,0x0038,VR::US,VM::VM1,"Number of Padded A-lines","NumberOfPaddedALines",false }, {0x0052,0x0039,VR::CS,VM::VM1,"Interpolation Type","InterpolationType",false }, {0x0052,0x003a,VR::CS,VM::VM1,"Refractive Index Applied","RefractiveIndexApplied",false }, {0x0054,0x0010,VR::US,VM::VM1_n,"Energy Window Vector","EnergyWindowVector",false }, {0x0054,0x0011,VR::US,VM::VM1,"Number of Energy Windows","NumberOfEnergyWindows",false }, {0x0054,0x0012,VR::SQ,VM::VM1,"Energy Window Information Sequence","EnergyWindowInformationSequence",false }, {0x0054,0x0013,VR::SQ,VM::VM1,"Energy Window Range Sequence","EnergyWindowRangeSequence",false }, {0x0054,0x0014,VR::DS,VM::VM1,"Energy Window Lower Limit","EnergyWindowLowerLimit",false }, {0x0054,0x0015,VR::DS,VM::VM1,"Energy Window Upper Limit","EnergyWindowUpperLimit",false }, {0x0054,0x0016,VR::SQ,VM::VM1,"Radiopharmaceutical Information Sequence","RadiopharmaceuticalInformationSequence",false }, {0x0054,0x0017,VR::IS,VM::VM1,"Residual Syringe Counts","ResidualSyringeCounts",false }, {0x0054,0x0018,VR::SH,VM::VM1,"Energy Window Name","EnergyWindowName",false }, {0x0054,0x0020,VR::US,VM::VM1_n,"Detector Vector","DetectorVector",false }, {0x0054,0x0021,VR::US,VM::VM1,"Number of Detectors","NumberOfDetectors",false }, {0x0054,0x0022,VR::SQ,VM::VM1,"Detector Information Sequence","DetectorInformationSequence",false }, {0x0054,0x0030,VR::US,VM::VM1_n,"Phase Vector","PhaseVector",false }, {0x0054,0x0031,VR::US,VM::VM1,"Number of Phases","NumberOfPhases",false }, {0x0054,0x0032,VR::SQ,VM::VM1,"Phase Information Sequence","PhaseInformationSequence",false }, {0x0054,0x0033,VR::US,VM::VM1,"Number of Frames in Phase","NumberOfFramesInPhase",false }, {0x0054,0x0036,VR::IS,VM::VM1,"Phase Delay","PhaseDelay",false }, {0x0054,0x0038,VR::IS,VM::VM1,"Pause Between Frames","PauseBetweenFrames",false }, {0x0054,0x0039,VR::CS,VM::VM1,"Phase Description","PhaseDescription",false }, {0x0054,0x0050,VR::US,VM::VM1_n,"Rotation Vector","RotationVector",false }, {0x0054,0x0051,VR::US,VM::VM1,"Number of Rotations","NumberOfRotations",false }, {0x0054,0x0052,VR::SQ,VM::VM1,"Rotation Information Sequence","RotationInformationSequence",false }, {0x0054,0x0053,VR::US,VM::VM1,"Number of Frames in Rotation","NumberOfFramesInRotation",false }, {0x0054,0x0060,VR::US,VM::VM1_n,"R-R Interval Vector","RRIntervalVector",false }, {0x0054,0x0061,VR::US,VM::VM1,"Number of R-R Intervals","NumberOfRRIntervals",false }, {0x0054,0x0062,VR::SQ,VM::VM1,"Gated Information Sequence","GatedInformationSequence",false }, {0x0054,0x0063,VR::SQ,VM::VM1,"Data Information Sequence","DataInformationSequence",false }, {0x0054,0x0070,VR::US,VM::VM1_n,"Time Slot Vector","TimeSlotVector",false }, {0x0054,0x0071,VR::US,VM::VM1,"Number of Time Slots","NumberOfTimeSlots",false }, {0x0054,0x0072,VR::SQ,VM::VM1,"Time Slot Information Sequence","TimeSlotInformationSequence",false }, {0x0054,0x0073,VR::DS,VM::VM1,"Time Slot Time","TimeSlotTime",false }, {0x0054,0x0080,VR::US,VM::VM1_n,"Slice Vector","SliceVector",false }, {0x0054,0x0081,VR::US,VM::VM1,"Number of Slices","NumberOfSlices",false }, {0x0054,0x0090,VR::US,VM::VM1_n,"Angular View Vector","AngularViewVector",false }, {0x0054,0x0100,VR::US,VM::VM1_n,"Time Slice Vector","TimeSliceVector",false }, {0x0054,0x0101,VR::US,VM::VM1,"Number of Time Slices","NumberOfTimeSlices",false }, {0x0054,0x0200,VR::DS,VM::VM1,"Start Angle","StartAngle",false }, {0x0054,0x0202,VR::CS,VM::VM1,"Type of Detector Motion","TypeOfDetectorMotion",false }, {0x0054,0x0210,VR::IS,VM::VM1_n,"Trigger Vector","TriggerVector",false }, {0x0054,0x0211,VR::US,VM::VM1,"Number of Triggers in Phase","NumberOfTriggersInPhase",false }, {0x0054,0x0220,VR::SQ,VM::VM1,"View Code Sequence","ViewCodeSequence",false }, {0x0054,0x0222,VR::SQ,VM::VM1,"View Modifier Code Sequence","ViewModifierCodeSequence",false }, {0x0054,0x0300,VR::SQ,VM::VM1,"Radionuclide Code Sequence","RadionuclideCodeSequence",false }, {0x0054,0x0302,VR::SQ,VM::VM1,"Administration Route Code Sequence","AdministrationRouteCodeSequence",false }, {0x0054,0x0304,VR::SQ,VM::VM1,"Radiopharmaceutical Code Sequence","RadiopharmaceuticalCodeSequence",false }, {0x0054,0x0306,VR::SQ,VM::VM1,"Calibration Data Sequence","CalibrationDataSequence",false }, {0x0054,0x0308,VR::US,VM::VM1,"Energy Window Number","EnergyWindowNumber",false }, {0x0054,0x0400,VR::SH,VM::VM1,"Image ID","ImageID",false }, {0x0054,0x0410,VR::SQ,VM::VM1,"Patient Orientation Code Sequence","PatientOrientationCodeSequence",false }, {0x0054,0x0412,VR::SQ,VM::VM1,"Patient Orientation Modifier Code Sequence","PatientOrientationModifierCodeSequence",false }, {0x0054,0x0414,VR::SQ,VM::VM1,"Patient Gantry Relationship Code Sequence","PatientGantryRelationshipCodeSequence",false }, {0x0054,0x0500,VR::CS,VM::VM1,"Slice Progression Direction","SliceProgressionDirection",false }, {0x0054,0x0501,VR::CS,VM::VM1,"Scan Progression Direction","ScanProgressionDirection",false }, {0x0054,0x1000,VR::CS,VM::VM2,"Series Type","SeriesType",false }, {0x0054,0x1001,VR::CS,VM::VM1,"Units","Units",false }, {0x0054,0x1002,VR::CS,VM::VM1,"Counts Source","CountsSource",false }, {0x0054,0x1004,VR::CS,VM::VM1,"Reprojection Method","ReprojectionMethod",false }, {0x0054,0x1006,VR::CS,VM::VM1,"SUV Type","SUVType",false }, {0x0054,0x1100,VR::CS,VM::VM1,"Randoms Correction Method","RandomsCorrectionMethod",false }, {0x0054,0x1101,VR::LO,VM::VM1,"Attenuation Correction Method","AttenuationCorrectionMethod",false }, {0x0054,0x1102,VR::CS,VM::VM1,"Decay Correction","DecayCorrection",false }, {0x0054,0x1103,VR::LO,VM::VM1,"Reconstruction Method","ReconstructionMethod",false }, {0x0054,0x1104,VR::LO,VM::VM1,"Detector Lines of Response Used","DetectorLinesOfResponseUsed",false }, {0x0054,0x1105,VR::LO,VM::VM1,"Scatter Correction Method","ScatterCorrectionMethod",false }, {0x0054,0x1200,VR::DS,VM::VM1,"Axial Acceptance","AxialAcceptance",false }, {0x0054,0x1201,VR::IS,VM::VM2,"Axial Mash","AxialMash",false }, {0x0054,0x1202,VR::IS,VM::VM1,"Transverse Mash","TransverseMash",false }, {0x0054,0x1203,VR::DS,VM::VM2,"Detector Element Size","DetectorElementSize",false }, {0x0054,0x1210,VR::DS,VM::VM1,"Coincidence Window Width","CoincidenceWindowWidth",false }, {0x0054,0x1220,VR::CS,VM::VM1_n,"Secondary Counts Type","SecondaryCountsType",false }, {0x0054,0x1300,VR::DS,VM::VM1,"Frame Reference Time","FrameReferenceTime",false }, {0x0054,0x1310,VR::IS,VM::VM1,"Primary (Prompts) Counts Accumulated","PrimaryPromptsCountsAccumulated",false }, {0x0054,0x1311,VR::IS,VM::VM1_n,"Secondary Counts Accumulated","SecondaryCountsAccumulated",false }, {0x0054,0x1320,VR::DS,VM::VM1,"Slice Sensitivity Factor","SliceSensitivityFactor",false }, {0x0054,0x1321,VR::DS,VM::VM1,"Decay Factor","DecayFactor",false }, {0x0054,0x1322,VR::DS,VM::VM1,"Dose Calibration Factor","DoseCalibrationFactor",false }, {0x0054,0x1323,VR::DS,VM::VM1,"Scatter Fraction Factor","ScatterFractionFactor",false }, {0x0054,0x1324,VR::DS,VM::VM1,"Dead Time Factor","DeadTimeFactor",false }, {0x0054,0x1330,VR::US,VM::VM1,"Image Index","ImageIndex",false }, {0x0054,0x1400,VR::CS,VM::VM1_n,"Counts Included","CountsIncluded",true }, {0x0054,0x1401,VR::CS,VM::VM1,"Dead Time Correction Flag","DeadTimeCorrectionFlag",true }, {0x0060,0x3000,VR::SQ,VM::VM1,"Histogram Sequence","HistogramSequence",false }, {0x0060,0x3002,VR::US,VM::VM1,"Histogram Number of Bins","HistogramNumberOfBins",false }, {0x0060,0x3004,VR::US_SS,VM::VM1,"Histogram First Bin Value","HistogramFirstBinValue",false }, {0x0060,0x3006,VR::US_SS,VM::VM1,"Histogram Last Bin Value","HistogramLastBinValue",false }, {0x0060,0x3008,VR::US,VM::VM1,"Histogram Bin Width","HistogramBinWidth",false }, {0x0060,0x3010,VR::LO,VM::VM1,"Histogram Explanation","HistogramExplanation",false }, {0x0060,0x3020,VR::UL,VM::VM1_n,"Histogram Data","HistogramData",false }, {0x0062,0x0001,VR::CS,VM::VM1,"Segmentation Type","SegmentationType",false }, {0x0062,0x0002,VR::SQ,VM::VM1,"Segment Sequence","SegmentSequence",false }, {0x0062,0x0003,VR::SQ,VM::VM1,"Segmented Property Category Code Sequence","SegmentedPropertyCategoryCodeSequence",false }, {0x0062,0x0004,VR::US,VM::VM1,"Segment Number","SegmentNumber",false }, {0x0062,0x0005,VR::LO,VM::VM1,"Segment Label","SegmentLabel",false }, {0x0062,0x0006,VR::ST,VM::VM1,"Segment Description","SegmentDescription",false }, {0x0062,0x0007,VR::SQ,VM::VM1,"Segmentation Algorithm Identification Sequence","SegmentationAlgorithmIdentificationSequence",false }, {0x0062,0x0008,VR::CS,VM::VM1,"Segment Algorithm Type","SegmentAlgorithmType",false }, {0x0062,0x0009,VR::LO,VM::VM1,"Segment Algorithm Name","SegmentAlgorithmName",false }, {0x0062,0x000a,VR::SQ,VM::VM1,"Segment Identification Sequence","SegmentIdentificationSequence",false }, {0x0062,0x000b,VR::US,VM::VM1_n,"Referenced Segment Number","ReferencedSegmentNumber",false }, {0x0062,0x000c,VR::US,VM::VM1,"Recommended Display Grayscale Value","RecommendedDisplayGrayscaleValue",false }, {0x0062,0x000d,VR::US,VM::VM3,"Recommended Display CIELab Value","RecommendedDisplayCIELabValue",false }, {0x0062,0x000e,VR::US,VM::VM1,"Maximum Fractional Value","MaximumFractionalValue",false }, {0x0062,0x000f,VR::SQ,VM::VM1,"Segmented Property Type Code Sequence","SegmentedPropertyTypeCodeSequence",false }, {0x0062,0x0010,VR::CS,VM::VM1,"Segmentation Fractional Type","SegmentationFractionalType",false }, {0x0062,0x0011,VR::SQ,VM::VM1,"Segmented Property Type Modifier Code Sequence","SegmentedPropertyTypeModifierCodeSequence",false }, {0x0062,0x0012,VR::SQ,VM::VM1,"Used Segments Sequence","UsedSegmentsSequence",false }, {0x0062,0x0020,VR::UT,VM::VM1,"Tracking ID","TrackingID",false }, {0x0062,0x0021,VR::UI,VM::VM1,"Tracking UID","TrackingUID",false }, {0x0064,0x0002,VR::SQ,VM::VM1,"Deformable Registration Sequence","DeformableRegistrationSequence",false }, {0x0064,0x0003,VR::UI,VM::VM1,"Source Frame of Reference UID","SourceFrameOfReferenceUID",false }, {0x0064,0x0005,VR::SQ,VM::VM1,"Deformable Registration Grid Sequence","DeformableRegistrationGridSequence",false }, {0x0064,0x0007,VR::UL,VM::VM3,"Grid Dimensions","GridDimensions",false }, {0x0064,0x0008,VR::FD,VM::VM3,"Grid Resolution","GridResolution",false }, {0x0064,0x0009,VR::OF,VM::VM1,"Vector Grid Data","VectorGridData",false }, {0x0064,0x000f,VR::SQ,VM::VM1,"Pre Deformation Matrix Registration Sequence","PreDeformationMatrixRegistrationSequence",false }, {0x0064,0x0010,VR::SQ,VM::VM1,"Post Deformation Matrix Registration Sequence","PostDeformationMatrixRegistrationSequence",false }, {0x0066,0x0001,VR::UL,VM::VM1,"Number of Surfaces","NumberOfSurfaces",false }, {0x0066,0x0002,VR::SQ,VM::VM1,"Surface Sequence","SurfaceSequence",false }, {0x0066,0x0003,VR::UL,VM::VM1,"Surface Number","SurfaceNumber",false }, {0x0066,0x0004,VR::LT,VM::VM1,"Surface Comments","SurfaceComments",false }, {0x0066,0x0009,VR::CS,VM::VM1,"Surface Processing","SurfaceProcessing",false }, {0x0066,0x000a,VR::FL,VM::VM1,"Surface Processing Ratio","SurfaceProcessingRatio",false }, {0x0066,0x000b,VR::LO,VM::VM1,"Surface Processing Description","SurfaceProcessingDescription",false }, {0x0066,0x000c,VR::FL,VM::VM1,"Recommended Presentation Opacity","RecommendedPresentationOpacity",false }, {0x0066,0x000d,VR::CS,VM::VM1,"Recommended Presentation Type","RecommendedPresentationType",false }, {0x0066,0x000e,VR::CS,VM::VM1,"Finite Volume","FiniteVolume",false }, {0x0066,0x0010,VR::CS,VM::VM1,"Manifold","Manifold",false }, {0x0066,0x0011,VR::SQ,VM::VM1,"Surface Points Sequence","SurfacePointsSequence",false }, {0x0066,0x0012,VR::SQ,VM::VM1,"Surface Points Normals Sequence","SurfacePointsNormalsSequence",false }, {0x0066,0x0013,VR::SQ,VM::VM1,"Surface Mesh Primitives Sequence","SurfaceMeshPrimitivesSequence",false }, {0x0066,0x0015,VR::UL,VM::VM1,"Number of Surface Points","NumberOfSurfacePoints",false }, {0x0066,0x0016,VR::OF,VM::VM1,"Point Coordinates Data","PointCoordinatesData",false }, {0x0066,0x0017,VR::FL,VM::VM3,"Point Position Accuracy","PointPositionAccuracy",false }, {0x0066,0x0018,VR::FL,VM::VM1,"Mean Point Distance","MeanPointDistance",false }, {0x0066,0x0019,VR::FL,VM::VM1,"Maximum Point Distance","MaximumPointDistance",false }, {0x0066,0x001a,VR::FL,VM::VM6,"Points Bounding Box Coordinates","PointsBoundingBoxCoordinates",false }, {0x0066,0x001b,VR::FL,VM::VM3,"Axis of Rotation","AxisOfRotation",false }, {0x0066,0x001c,VR::FL,VM::VM3,"Center of Rotation","CenterOfRotation",false }, {0x0066,0x001e,VR::UL,VM::VM1,"Number of Vectors","NumberOfVectors",false }, {0x0066,0x001f,VR::US,VM::VM1,"Vector Dimensionality","VectorDimensionality",false }, {0x0066,0x0020,VR::FL,VM::VM1_n,"Vector Accuracy","VectorAccuracy",false }, {0x0066,0x0021,VR::OF,VM::VM1,"Vector Coordinate Data","VectorCoordinateData",false }, {0x0066,0x0023,VR::OW,VM::VM1,"Triangle Point Index List","TrianglePointIndexList",true }, {0x0066,0x0024,VR::OW,VM::VM1,"Edge Point Index List","EdgePointIndexList",true }, {0x0066,0x0025,VR::OW,VM::VM1,"Vertex Point Index List","VertexPointIndexList",true }, {0x0066,0x0026,VR::SQ,VM::VM1,"Triangle Strip Sequence","TriangleStripSequence",false }, {0x0066,0x0027,VR::SQ,VM::VM1,"Triangle Fan Sequence","TriangleFanSequence",false }, {0x0066,0x0028,VR::SQ,VM::VM1,"Line Sequence","LineSequence",false }, {0x0066,0x0029,VR::OW,VM::VM1,"Primitive Point Index List","PrimitivePointIndexList",true }, {0x0066,0x002a,VR::UL,VM::VM1,"Surface Count","SurfaceCount",false }, {0x0066,0x002b,VR::SQ,VM::VM1,"Referenced Surface Sequence","ReferencedSurfaceSequence",false }, {0x0066,0x002c,VR::UL,VM::VM1,"Referenced Surface Number","ReferencedSurfaceNumber",false }, {0x0066,0x002d,VR::SQ,VM::VM1,"Segment Surface Generation Algorithm Identification Sequence","SegmentSurfaceGenerationAlgorithmIdentificationSequence",false }, {0x0066,0x002e,VR::SQ,VM::VM1,"Segment Surface Source Instance Sequence","SegmentSurfaceSourceInstanceSequence",false }, {0x0066,0x002f,VR::SQ,VM::VM1,"Algorithm Family Code Sequence","AlgorithmFamilyCodeSequence",false }, {0x0066,0x0030,VR::SQ,VM::VM1,"Algorithm Name Code Sequence","AlgorithmNameCodeSequence",false }, {0x0066,0x0031,VR::LO,VM::VM1,"Algorithm Version","AlgorithmVersion",false }, {0x0066,0x0032,VR::LT,VM::VM1,"Algorithm Parameters","AlgorithmParameters",false }, {0x0066,0x0034,VR::SQ,VM::VM1,"Facet Sequence","FacetSequence",false }, {0x0066,0x0035,VR::SQ,VM::VM1,"Surface Processing Algorithm Identification Sequence","SurfaceProcessingAlgorithmIdentificationSequence",false }, {0x0066,0x0036,VR::LO,VM::VM1,"Algorithm Name","AlgorithmName",false }, {0x0066,0x0037,VR::FL,VM::VM1,"Recommended Point Radius","RecommendedPointRadius",false }, {0x0066,0x0038,VR::FL,VM::VM1,"Recommended Line Thickness","RecommendedLineThickness",false }, {0x0066,0x0040,VR::OL,VM::VM1,"Long Primitive Point Index List","LongPrimitivePointIndexList",false }, {0x0066,0x0041,VR::OL,VM::VM1,"Long Triangle Point Index List","LongTrianglePointIndexList",false }, {0x0066,0x0042,VR::OL,VM::VM1,"Long Edge Point Index List","LongEdgePointIndexList",false }, {0x0066,0x0043,VR::OL,VM::VM1,"Long Vertex Point Index List","LongVertexPointIndexList",false }, {0x0066,0x0101,VR::SQ,VM::VM1,"Track Set Sequence","TrackSetSequence",false }, {0x0066,0x0102,VR::SQ,VM::VM1,"Track Sequence","TrackSequence",false }, {0x0066,0x0103,VR::OW,VM::VM1,"Recommended Display CIELab Value List","RecommendedDisplayCIELabValueList",false }, {0x0066,0x0104,VR::SQ,VM::VM1,"Tracking Algorithm Identification Sequence","TrackingAlgorithmIdentificationSequence",false }, {0x0066,0x0105,VR::UL,VM::VM1,"Track Set Number","TrackSetNumber",false }, {0x0066,0x0106,VR::LO,VM::VM1,"Track Set Label","TrackSetLabel",false }, {0x0066,0x0107,VR::UT,VM::VM1,"Track Set Description","TrackSetDescription",false }, {0x0066,0x0108,VR::SQ,VM::VM1,"Track Set Anatomical Type Code Sequence","TrackSetAnatomicalTypeCodeSequence",false }, {0x0066,0x0121,VR::SQ,VM::VM1,"Measurements Sequence","MeasurementsSequence",false }, {0x0066,0x0124,VR::SQ,VM::VM1,"Track Set Statistics Sequence","TrackSetStatisticsSequence",false }, {0x0066,0x0125,VR::OF,VM::VM1,"Floating Point Values","FloatingPointValues",false }, {0x0066,0x0129,VR::OL,VM::VM1,"Track Point Index List","TrackPointIndexList",false }, {0x0066,0x0130,VR::SQ,VM::VM1,"Track Statistics Sequence","TrackStatisticsSequence",false }, {0x0066,0x0132,VR::SQ,VM::VM1,"Measurement Values Sequence","MeasurementValuesSequence",false }, {0x0066,0x0133,VR::SQ,VM::VM1,"Diffusion Acquisition Code Sequence","DiffusionAcquisitionCodeSequence",false }, {0x0066,0x0134,VR::SQ,VM::VM1,"Diffusion Model Code Sequence","DiffusionModelCodeSequence",false }, {0x0068,0x6210,VR::LO,VM::VM1,"Implant Size","ImplantSize",false }, {0x0068,0x6221,VR::LO,VM::VM1,"Implant Template Version","ImplantTemplateVersion",false }, {0x0068,0x6222,VR::SQ,VM::VM1,"Replaced Implant Template Sequence","ReplacedImplantTemplateSequence",false }, {0x0068,0x6223,VR::CS,VM::VM1,"Implant Type","ImplantType",false }, {0x0068,0x6224,VR::SQ,VM::VM1,"Derivation Implant Template Sequence","DerivationImplantTemplateSequence",false }, {0x0068,0x6225,VR::SQ,VM::VM1,"Original Implant Template Sequence","OriginalImplantTemplateSequence",false }, {0x0068,0x6226,VR::DT,VM::VM1,"Effective DateTime","EffectiveDateTime",false }, {0x0068,0x6230,VR::SQ,VM::VM1,"Implant Target Anatomy Sequence","ImplantTargetAnatomySequence",false }, {0x0068,0x6260,VR::SQ,VM::VM1,"Information From Manufacturer Sequence","InformationFromManufacturerSequence",false }, {0x0068,0x6265,VR::SQ,VM::VM1,"Notification From Manufacturer Sequence","NotificationFromManufacturerSequence",false }, {0x0068,0x6270,VR::DT,VM::VM1,"Information Issue DateTime","InformationIssueDateTime",false }, {0x0068,0x6280,VR::ST,VM::VM1,"Information Summary","InformationSummary",false }, {0x0068,0x62a0,VR::SQ,VM::VM1,"Implant Regulatory Disapproval Code Sequence","ImplantRegulatoryDisapprovalCodeSequence",false }, {0x0068,0x62a5,VR::FD,VM::VM1,"Overall Template Spatial Tolerance","OverallTemplateSpatialTolerance",false }, {0x0068,0x62c0,VR::SQ,VM::VM1,"HPGL Document Sequence","HPGLDocumentSequence",false }, {0x0068,0x62d0,VR::US,VM::VM1,"HPGL Document ID","HPGLDocumentID",false }, {0x0068,0x62d5,VR::LO,VM::VM1,"HPGL Document Label","HPGLDocumentLabel",false }, {0x0068,0x62e0,VR::SQ,VM::VM1,"View Orientation Code Sequence","ViewOrientationCodeSequence",false }, {0x0068,0x62f0,VR::FD,VM::VM9,"View Orientation Modifier","ViewOrientationModifier",false }, {0x0068,0x62f2,VR::FD,VM::VM1,"HPGL Document Scaling","HPGLDocumentScaling",false }, {0x0068,0x6300,VR::OB,VM::VM1,"HPGL Document","HPGLDocument",false }, {0x0068,0x6310,VR::US,VM::VM1,"HPGL Contour Pen Number","HPGLContourPenNumber",false }, {0x0068,0x6320,VR::SQ,VM::VM1,"HPGL Pen Sequence","HPGLPenSequence",false }, {0x0068,0x6330,VR::US,VM::VM1,"HPGL Pen Number","HPGLPenNumber",false }, {0x0068,0x6340,VR::LO,VM::VM1,"HPGL Pen Label","HPGLPenLabel",false }, {0x0068,0x6345,VR::ST,VM::VM1,"HPGL Pen Description","HPGLPenDescription",false }, {0x0068,0x6346,VR::FD,VM::VM2,"Recommended Rotation Point","RecommendedRotationPoint",false }, {0x0068,0x6347,VR::FD,VM::VM4,"Bounding Rectangle","BoundingRectangle",false }, {0x0068,0x6350,VR::US,VM::VM1_n,"Implant Template 3D Model Surface Number","ImplantTemplate3DModelSurfaceNumber",false }, {0x0068,0x6360,VR::SQ,VM::VM1,"Surface Model Description Sequence","SurfaceModelDescriptionSequence",false }, {0x0068,0x6380,VR::LO,VM::VM1,"Surface Model Label","SurfaceModelLabel",false }, {0x0068,0x6390,VR::FD,VM::VM1,"Surface Model Scaling Factor","SurfaceModelScalingFactor",false }, {0x0068,0x63a0,VR::SQ,VM::VM1,"Materials Code Sequence","MaterialsCodeSequence",false }, {0x0068,0x63a4,VR::SQ,VM::VM1,"Coating Materials Code Sequence","CoatingMaterialsCodeSequence",false }, {0x0068,0x63a8,VR::SQ,VM::VM1,"Implant Type Code Sequence","ImplantTypeCodeSequence",false }, {0x0068,0x63ac,VR::SQ,VM::VM1,"Fixation Method Code Sequence","FixationMethodCodeSequence",false }, {0x0068,0x63b0,VR::SQ,VM::VM1,"Mating Feature Sets Sequence","MatingFeatureSetsSequence",false }, {0x0068,0x63c0,VR::US,VM::VM1,"Mating Feature Set ID","MatingFeatureSetID",false }, {0x0068,0x63d0,VR::LO,VM::VM1,"Mating Feature Set Label","MatingFeatureSetLabel",false }, {0x0068,0x63e0,VR::SQ,VM::VM1,"Mating Feature Sequence","MatingFeatureSequence",false }, {0x0068,0x63f0,VR::US,VM::VM1,"Mating Feature ID","MatingFeatureID",false }, {0x0068,0x6400,VR::SQ,VM::VM1,"Mating Feature Degree of Freedom Sequence","MatingFeatureDegreeOfFreedomSequence",false }, {0x0068,0x6410,VR::US,VM::VM1,"Degree of Freedom ID","DegreeOfFreedomID",false }, {0x0068,0x6420,VR::CS,VM::VM1,"Degree of Freedom Type","DegreeOfFreedomType",false }, {0x0068,0x6430,VR::SQ,VM::VM1,"2D Mating Feature Coordinates Sequence","TwoDMatingFeatureCoordinatesSequence",false }, {0x0068,0x6440,VR::US,VM::VM1,"Referenced HPGL Document ID","ReferencedHPGLDocumentID",false }, {0x0068,0x6450,VR::FD,VM::VM2,"2D Mating Point","TwoDMatingPoint",false }, {0x0068,0x6460,VR::FD,VM::VM4,"2D Mating Axes","TwoDMatingAxes",false }, {0x0068,0x6470,VR::SQ,VM::VM1,"2D Degree of Freedom Sequence","TwoDDegreeOfFreedomSequence",false }, {0x0068,0x6490,VR::FD,VM::VM3,"3D Degree of Freedom Axis","ThreeDDegreeOfFreedomAxis",false }, {0x0068,0x64a0,VR::FD,VM::VM2,"Range of Freedom","RangeOfFreedom",false }, {0x0068,0x64c0,VR::FD,VM::VM3,"3D Mating Point","ThreeDMatingPoint",false }, {0x0068,0x64d0,VR::FD,VM::VM9,"3D Mating Axes","ThreeDMatingAxes",false }, {0x0068,0x64f0,VR::FD,VM::VM3,"2D Degree of Freedom Axis","TwoDDegreeOfFreedomAxis",false }, {0x0068,0x6500,VR::SQ,VM::VM1,"Planning Landmark Point Sequence","PlanningLandmarkPointSequence",false }, {0x0068,0x6510,VR::SQ,VM::VM1,"Planning Landmark Line Sequence","PlanningLandmarkLineSequence",false }, {0x0068,0x6520,VR::SQ,VM::VM1,"Planning Landmark Plane Sequence","PlanningLandmarkPlaneSequence",false }, {0x0068,0x6530,VR::US,VM::VM1,"Planning Landmark ID","PlanningLandmarkID",false }, {0x0068,0x6540,VR::LO,VM::VM1,"Planning Landmark Description","PlanningLandmarkDescription",false }, {0x0068,0x6545,VR::SQ,VM::VM1,"Planning Landmark Identification Code Sequence","PlanningLandmarkIdentificationCodeSequence",false }, {0x0068,0x6550,VR::SQ,VM::VM1,"2D Point Coordinates Sequence","TwoDPointCoordinatesSequence",false }, {0x0068,0x6560,VR::FD,VM::VM2,"2D Point Coordinates","TwoDPointCoordinates",false }, {0x0068,0x6590,VR::FD,VM::VM3,"3D Point Coordinates","ThreeDPointCoordinates",false }, {0x0068,0x65a0,VR::SQ,VM::VM1,"2D Line Coordinates Sequence","TwoDLineCoordinatesSequence",false }, {0x0068,0x65b0,VR::FD,VM::VM4,"2D Line Coordinates","TwoDLineCoordinates",false }, {0x0068,0x65d0,VR::FD,VM::VM6,"3D Line Coordinates","ThreeDLineCoordinates",false }, {0x0068,0x65e0,VR::SQ,VM::VM1,"2D Plane Coordinates Sequence","TwoDPlaneCoordinatesSequence",false }, {0x0068,0x65f0,VR::FD,VM::VM4,"2D Plane Intersection","TwoDPlaneIntersection",false }, {0x0068,0x6610,VR::FD,VM::VM3,"3D Plane Origin","ThreeDPlaneOrigin",false }, {0x0068,0x6620,VR::FD,VM::VM3,"3D Plane Normal","ThreeDPlaneNormal",false }, {0x0070,0x0001,VR::SQ,VM::VM1,"Graphic Annotation Sequence","GraphicAnnotationSequence",false }, {0x0070,0x0002,VR::CS,VM::VM1,"Graphic Layer","GraphicLayer",false }, {0x0070,0x0003,VR::CS,VM::VM1,"Bounding Box Annotation Units","BoundingBoxAnnotationUnits",false }, {0x0070,0x0004,VR::CS,VM::VM1,"Anchor Point Annotation Units","AnchorPointAnnotationUnits",false }, {0x0070,0x0005,VR::CS,VM::VM1,"Graphic Annotation Units","GraphicAnnotationUnits",false }, {0x0070,0x0006,VR::ST,VM::VM1,"Unformatted Text Value","UnformattedTextValue",false }, {0x0070,0x0008,VR::SQ,VM::VM1,"Text Object Sequence","TextObjectSequence",false }, {0x0070,0x0009,VR::SQ,VM::VM1,"Graphic Object Sequence","GraphicObjectSequence",false }, {0x0070,0x0010,VR::FL,VM::VM2,"Bounding Box Top Left Hand Corner","BoundingBoxTopLeftHandCorner",false }, {0x0070,0x0011,VR::FL,VM::VM2,"Bounding Box Bottom Right Hand Corner","BoundingBoxBottomRightHandCorner",false }, {0x0070,0x0012,VR::CS,VM::VM1,"Bounding Box Text Horizontal Justification","BoundingBoxTextHorizontalJustification",false }, {0x0070,0x0014,VR::FL,VM::VM2,"Anchor Point","AnchorPoint",false }, {0x0070,0x0015,VR::CS,VM::VM1,"Anchor Point Visibility","AnchorPointVisibility",false }, {0x0070,0x0020,VR::US,VM::VM1,"Graphic Dimensions","GraphicDimensions",false }, {0x0070,0x0021,VR::US,VM::VM1,"Number of Graphic Points","NumberOfGraphicPoints",false }, {0x0070,0x0022,VR::FL,VM::VM2_n,"Graphic Data","GraphicData",false }, {0x0070,0x0023,VR::CS,VM::VM1,"Graphic Type","GraphicType",false }, {0x0070,0x0024,VR::CS,VM::VM1,"Graphic Filled","GraphicFilled",false }, {0x0070,0x0040,VR::IS,VM::VM1,"Image Rotation (Retired)","ImageRotationRetired",true }, {0x0070,0x0041,VR::CS,VM::VM1,"Image Horizontal Flip","ImageHorizontalFlip",false }, {0x0070,0x0042,VR::US,VM::VM1,"Image Rotation","ImageRotation",false }, {0x0070,0x0050,VR::US,VM::VM2,"Displayed Area Top Left Hand Corner (Trial)","DisplayedAreaTopLeftHandCornerTrial",true }, {0x0070,0x0051,VR::US,VM::VM2,"Displayed Area Bottom Right Hand Corner (Trial)","DisplayedAreaBottomRightHandCornerTrial",true }, {0x0070,0x0052,VR::SL,VM::VM2,"Displayed Area Top Left Hand Corner","DisplayedAreaTopLeftHandCorner",false }, {0x0070,0x0053,VR::SL,VM::VM2,"Displayed Area Bottom Right Hand Corner","DisplayedAreaBottomRightHandCorner",false }, {0x0070,0x005a,VR::SQ,VM::VM1,"Displayed Area Selection Sequence","DisplayedAreaSelectionSequence",false }, {0x0070,0x0060,VR::SQ,VM::VM1,"Graphic Layer Sequence","GraphicLayerSequence",false }, {0x0070,0x0062,VR::IS,VM::VM1,"Graphic Layer Order","GraphicLayerOrder",false }, {0x0070,0x0066,VR::US,VM::VM1,"Graphic Layer Recommended Display Grayscale Value","GraphicLayerRecommendedDisplayGrayscaleValue",false }, {0x0070,0x0067,VR::US,VM::VM3,"Graphic Layer Recommended Display RGB Value","GraphicLayerRecommendedDisplayRGBValue",true }, {0x0070,0x0068,VR::LO,VM::VM1,"Graphic Layer Description","GraphicLayerDescription",false }, {0x0070,0x0080,VR::CS,VM::VM1,"Content Label","ContentLabel",false }, {0x0070,0x0081,VR::LO,VM::VM1,"Content Description","ContentDescription",false }, {0x0070,0x0082,VR::DA,VM::VM1,"Presentation Creation Date","PresentationCreationDate",false }, {0x0070,0x0083,VR::TM,VM::VM1,"Presentation Creation Time","PresentationCreationTime",false }, {0x0070,0x0084,VR::PN,VM::VM1,"Content Creator's Name","ContentCreatorName",false }, {0x0070,0x0086,VR::SQ,VM::VM1,"Content Creator's Identification Code Sequence","ContentCreatorIdentificationCodeSequence",false }, {0x0070,0x0087,VR::SQ,VM::VM1,"Alternate Content Description Sequence","AlternateContentDescriptionSequence",false }, {0x0070,0x0100,VR::CS,VM::VM1,"Presentation Size Mode","PresentationSizeMode",false }, {0x0070,0x0101,VR::DS,VM::VM2,"Presentation Pixel Spacing","PresentationPixelSpacing",false }, {0x0070,0x0102,VR::IS,VM::VM2,"Presentation Pixel Aspect Ratio","PresentationPixelAspectRatio",false }, {0x0070,0x0103,VR::FL,VM::VM1,"Presentation Pixel Magnification Ratio","PresentationPixelMagnificationRatio",false }, {0x0070,0x0207,VR::LO,VM::VM1,"Graphic Group Label","GraphicGroupLabel",false }, {0x0070,0x0208,VR::ST,VM::VM1,"Graphic Group Description","GraphicGroupDescription",false }, {0x0070,0x0209,VR::SQ,VM::VM1,"Compound Graphic Sequence","CompoundGraphicSequence",false }, {0x0070,0x0226,VR::UL,VM::VM1,"Compound Graphic Instance ID","CompoundGraphicInstanceID",false }, {0x0070,0x0227,VR::LO,VM::VM1,"Font Name","FontName",false }, {0x0070,0x0228,VR::CS,VM::VM1,"Font Name Type","FontNameType",false }, {0x0070,0x0229,VR::LO,VM::VM1,"CSS Font Name","CSSFontName",false }, {0x0070,0x0230,VR::FD,VM::VM1,"Rotation Angle","RotationAngle",false }, {0x0070,0x0231,VR::SQ,VM::VM1,"Text Style Sequence","TextStyleSequence",false }, {0x0070,0x0232,VR::SQ,VM::VM1,"Line Style Sequence","LineStyleSequence",false }, {0x0070,0x0233,VR::SQ,VM::VM1,"Fill Style Sequence","FillStyleSequence",false }, {0x0070,0x0234,VR::SQ,VM::VM1,"Graphic Group Sequence","GraphicGroupSequence",false }, {0x0070,0x0241,VR::US,VM::VM3,"Text Color CIELab Value","TextColorCIELabValue",false }, {0x0070,0x0242,VR::CS,VM::VM1,"Horizontal Alignment","HorizontalAlignment",false }, {0x0070,0x0243,VR::CS,VM::VM1,"Vertical Alignment","VerticalAlignment",false }, {0x0070,0x0244,VR::CS,VM::VM1,"Shadow Style","ShadowStyle",false }, {0x0070,0x0245,VR::FL,VM::VM1,"Shadow Offset X","ShadowOffsetX",false }, {0x0070,0x0246,VR::FL,VM::VM1,"Shadow Offset Y","ShadowOffsetY",false }, {0x0070,0x0247,VR::US,VM::VM3,"Shadow Color CIELab Value","ShadowColorCIELabValue",false }, {0x0070,0x0248,VR::CS,VM::VM1,"Underlined","Underlined",false }, {0x0070,0x0249,VR::CS,VM::VM1,"Bold","Bold",false }, {0x0070,0x0250,VR::CS,VM::VM1,"Italic","Italic",false }, {0x0070,0x0251,VR::US,VM::VM3,"Pattern On Color CIELab Value","PatternOnColorCIELabValue",false }, {0x0070,0x0252,VR::US,VM::VM3,"Pattern Off Color CIELab Value","PatternOffColorCIELabValue",false }, {0x0070,0x0253,VR::FL,VM::VM1,"Line Thickness","LineThickness",false }, {0x0070,0x0254,VR::CS,VM::VM1,"Line Dashing Style","LineDashingStyle",false }, {0x0070,0x0255,VR::UL,VM::VM1,"Line Pattern","LinePattern",false }, {0x0070,0x0256,VR::OB,VM::VM1,"Fill Pattern","FillPattern",false }, {0x0070,0x0257,VR::CS,VM::VM1,"Fill Mode","FillMode",false }, {0x0070,0x0258,VR::FL,VM::VM1,"Shadow Opacity","ShadowOpacity",false }, {0x0070,0x0261,VR::FL,VM::VM1,"Gap Length","GapLength",false }, {0x0070,0x0262,VR::FL,VM::VM1,"Diameter of Visibility","DiameterOfVisibility",false }, {0x0070,0x0273,VR::FL,VM::VM2,"Rotation Point","RotationPoint",false }, {0x0070,0x0274,VR::CS,VM::VM1,"Tick Alignment","TickAlignment",false }, {0x0070,0x0278,VR::CS,VM::VM1,"Show Tick Label","ShowTickLabel",false }, {0x0070,0x0279,VR::CS,VM::VM1,"Tick Label Alignment","TickLabelAlignment",false }, {0x0070,0x0282,VR::CS,VM::VM1,"Compound Graphic Units","CompoundGraphicUnits",false }, {0x0070,0x0284,VR::FL,VM::VM1,"Pattern On Opacity","PatternOnOpacity",false }, {0x0070,0x0285,VR::FL,VM::VM1,"Pattern Off Opacity","PatternOffOpacity",false }, {0x0070,0x0287,VR::SQ,VM::VM1,"Major Ticks Sequence","MajorTicksSequence",false }, {0x0070,0x0288,VR::FL,VM::VM1,"Tick Position","TickPosition",false }, {0x0070,0x0289,VR::SH,VM::VM1,"Tick Label","TickLabel",false }, {0x0070,0x0294,VR::CS,VM::VM1,"Compound Graphic Type","CompoundGraphicType",false }, {0x0070,0x0295,VR::UL,VM::VM1,"Graphic Group ID","GraphicGroupID",false }, {0x0070,0x0306,VR::CS,VM::VM1,"Shape Type","ShapeType",false }, {0x0070,0x0308,VR::SQ,VM::VM1,"Registration Sequence","RegistrationSequence",false }, {0x0070,0x0309,VR::SQ,VM::VM1,"Matrix Registration Sequence","MatrixRegistrationSequence",false }, {0x0070,0x030a,VR::SQ,VM::VM1,"Matrix Sequence","MatrixSequence",false }, {0x0070,0x030b,VR::FD,VM::VM16,"Frame of Reference to Displayed Coordinate System Transformation Matrix","FrameOfReferenceToDisplayedCoordinateSystemTransformationMatrix",false }, {0x0070,0x030c,VR::CS,VM::VM1,"Frame of Reference Transformation Matrix Type","FrameOfReferenceTransformationMatrixType",false }, {0x0070,0x030d,VR::SQ,VM::VM1,"Registration Type Code Sequence","RegistrationTypeCodeSequence",false }, {0x0070,0x030f,VR::ST,VM::VM1,"Fiducial Description","FiducialDescription",false }, {0x0070,0x0310,VR::SH,VM::VM1,"Fiducial Identifier","FiducialIdentifier",false }, {0x0070,0x0311,VR::SQ,VM::VM1,"Fiducial Identifier Code Sequence","FiducialIdentifierCodeSequence",false }, {0x0070,0x0312,VR::FD,VM::VM1,"Contour Uncertainty Radius","ContourUncertaintyRadius",false }, {0x0070,0x0314,VR::SQ,VM::VM1,"Used Fiducials Sequence","UsedFiducialsSequence",false }, {0x0070,0x0318,VR::SQ,VM::VM1,"Graphic Coordinates Data Sequence","GraphicCoordinatesDataSequence",false }, {0x0070,0x031a,VR::UI,VM::VM1,"Fiducial UID","FiducialUID",false }, {0x0070,0x031c,VR::SQ,VM::VM1,"Fiducial Set Sequence","FiducialSetSequence",false }, {0x0070,0x031e,VR::SQ,VM::VM1,"Fiducial Sequence","FiducialSequence",false }, {0x0070,0x031f,VR::SQ,VM::VM1,"Fiducials Property Category Code Sequence","FiducialsPropertyCategoryCodeSequence",false }, {0x0070,0x0401,VR::US,VM::VM3,"Graphic Layer Recommended Display CIELab Value","GraphicLayerRecommendedDisplayCIELabValue",false }, {0x0070,0x0402,VR::SQ,VM::VM1,"Blending Sequence","BlendingSequence",false }, {0x0070,0x0403,VR::FL,VM::VM1,"Relative Opacity","RelativeOpacity",false }, {0x0070,0x0404,VR::SQ,VM::VM1,"Referenced Spatial Registration Sequence","ReferencedSpatialRegistrationSequence",false }, {0x0070,0x0405,VR::CS,VM::VM1,"Blending Position","BlendingPosition",false }, {0x0070,0x1101,VR::UI,VM::VM1,"Presentation Display Collection UID","PresentationDisplayCollectionUID",false }, {0x0070,0x1102,VR::UI,VM::VM1,"Presentation Sequence Collection UID","PresentationSequenceCollectionUID",false }, {0x0070,0x1103,VR::US,VM::VM1,"Presentation Sequence Position Index","PresentationSequencePositionIndex",false }, {0x0070,0x1104,VR::SQ,VM::VM1,"Rendered Image Reference Sequence","RenderedImageReferenceSequence",false }, {0x0070,0x1201,VR::SQ,VM::VM1,"Volumetric Presentation State Input Sequence","VolumetricPresentationStateInputSequence",false }, {0x0070,0x1202,VR::CS,VM::VM1,"Presentation Input Type","PresentationInputType",false }, {0x0070,0x1203,VR::US,VM::VM1,"Input Sequence Position Index","InputSequencePositionIndex",false }, {0x0070,0x1204,VR::CS,VM::VM1,"Crop","Crop",false }, {0x0070,0x1205,VR::US,VM::VM1_n,"Cropping Specification Index","CroppingSpecificationIndex",false }, {0x0070,0x1206,VR::CS,VM::VM1,"Compositing Method","CompositingMethod",false }, {0x0070,0x1207,VR::US,VM::VM1,"Volumetric Presentation Input Number","VolumetricPresentationInputNumber",false }, {0x0070,0x1208,VR::CS,VM::VM1,"Image Volume Geometry","ImageVolumeGeometry",false }, {0x0070,0x1301,VR::SQ,VM::VM1,"Volume Cropping Sequence","VolumeCroppingSequence",false }, {0x0070,0x1302,VR::CS,VM::VM1,"Volume Cropping Method","VolumeCroppingMethod",false }, {0x0070,0x1303,VR::FD,VM::VM6,"Bounding Box Crop","BoundingBoxCrop",false }, {0x0070,0x1304,VR::SQ,VM::VM1,"Oblique Cropping Plane Sequence","ObliqueCroppingPlaneSequence",false }, {0x0070,0x1305,VR::FD,VM::VM4,"Plane","Plane",false }, {0x0070,0x1306,VR::FD,VM::VM3,"Plane Normal","PlaneNormal",false }, {0x0070,0x1309,VR::US,VM::VM1,"Cropping Specification Number","CroppingSpecificationNumber",false }, {0x0070,0x1501,VR::CS,VM::VM1,"Multi-Planar Reconstruction Style","MultiPlanarReconstructionStyle",false }, {0x0070,0x1502,VR::CS,VM::VM1,"MPR Thickness Type","MPRThicknessType",false }, {0x0070,0x1503,VR::FD,VM::VM1,"MPR Slab Thickness","MPRSlabThickness",false }, {0x0070,0x1505,VR::FD,VM::VM3,"MPR Top Left Hand Corner","MPRTopLeftHandCorner",false }, {0x0070,0x1507,VR::FD,VM::VM3,"MPR View Width Direction","MPRViewWidthDirection",false }, {0x0070,0x1508,VR::FD,VM::VM1,"MPR View Width","MPRViewWidth",false }, {0x0070,0x150c,VR::UL,VM::VM1,"Number of Volumetric Curve Points","NumberOfVolumetricCurvePoints",false }, {0x0070,0x150d,VR::OD,VM::VM1,"Volumetric Curve Points","VolumetricCurvePoints",false }, {0x0070,0x1511,VR::FD,VM::VM3,"MPR View Height Direction","MPRViewHeightDirection",false }, {0x0070,0x1512,VR::FD,VM::VM1,"MPR View Height","MPRViewHeight",false }, {0x0070,0x1801,VR::SQ,VM::VM1,"Presentation State Classification Component Sequence","PresentationStateClassificationComponentSequence",false }, {0x0070,0x1802,VR::CS,VM::VM1,"Component Type","ComponentType",false }, {0x0070,0x1803,VR::SQ,VM::VM1,"Component Input Sequence","ComponentInputSequence",false }, {0x0070,0x1804,VR::US,VM::VM1,"Volumetric Presentation Input Index","VolumetricPresentationInputIndex",false }, {0x0070,0x1805,VR::SQ,VM::VM1,"Presentation State Compositor Component Sequence","PresentationStateCompositorComponentSequence",false }, {0x0070,0x1806,VR::SQ,VM::VM1,"Weighting Transfer Function Sequence","WeightingTransferFunctionSequence",false }, {0x0070,0x1807,VR::US,VM::VM3,"Weighting Lookup Table Descriptor","WeightingLookupTableDescriptor",false }, {0x0070,0x1808,VR::OB,VM::VM1,"Weighting Lookup Table Data","WeightingLookupTableData",false }, {0x0070,0x1901,VR::SQ,VM::VM1,"Volumetric Annotation Sequence","VolumetricAnnotationSequence",false }, {0x0070,0x1903,VR::SQ,VM::VM1,"Referenced Structured Context Sequence","ReferencedStructuredContextSequence",false }, {0x0070,0x1904,VR::UI,VM::VM1,"Referenced Content Item","ReferencedContentItem",false }, {0x0070,0x1905,VR::SQ,VM::VM1,"Volumetric Presentation Input Annotation Sequence","VolumetricPresentationInputAnnotationSequence",false }, {0x0070,0x1907,VR::CS,VM::VM1,"Annotation Clipping","AnnotationClipping",false }, {0x0070,0x1a01,VR::CS,VM::VM1,"Presentation Animation Style","PresentationAnimationStyle",false }, {0x0070,0x1a03,VR::FD,VM::VM1,"Recommended Animation Rate","RecommendedAnimationRate",false }, {0x0070,0x1a04,VR::SQ,VM::VM1,"Animation Curve Sequence","AnimationCurveSequence",false }, {0x0070,0x1a05,VR::FD,VM::VM1,"Animation Step Size","AnimationStepSize",false }, {0x0072,0x0002,VR::SH,VM::VM1,"Hanging Protocol Name","HangingProtocolName",false }, {0x0072,0x0004,VR::LO,VM::VM1,"Hanging Protocol Description","HangingProtocolDescription",false }, {0x0072,0x0006,VR::CS,VM::VM1,"Hanging Protocol Level","HangingProtocolLevel",false }, {0x0072,0x0008,VR::LO,VM::VM1,"Hanging Protocol Creator","HangingProtocolCreator",false }, {0x0072,0x000a,VR::DT,VM::VM1,"Hanging Protocol Creation DateTime","HangingProtocolCreationDateTime",false }, {0x0072,0x000c,VR::SQ,VM::VM1,"Hanging Protocol Definition Sequence","HangingProtocolDefinitionSequence",false }, {0x0072,0x000e,VR::SQ,VM::VM1,"Hanging Protocol User Identification Code Sequence","HangingProtocolUserIdentificationCodeSequence",false }, {0x0072,0x0010,VR::LO,VM::VM1,"Hanging Protocol User Group Name","HangingProtocolUserGroupName",false }, {0x0072,0x0012,VR::SQ,VM::VM1,"Source Hanging Protocol Sequence","SourceHangingProtocolSequence",false }, {0x0072,0x0014,VR::US,VM::VM1,"Number of Priors Referenced","NumberOfPriorsReferenced",false }, {0x0072,0x0020,VR::SQ,VM::VM1,"Image Sets Sequence","ImageSetsSequence",false }, {0x0072,0x0022,VR::SQ,VM::VM1,"Image Set Selector Sequence","ImageSetSelectorSequence",false }, {0x0072,0x0024,VR::CS,VM::VM1,"Image Set Selector Usage Flag","ImageSetSelectorUsageFlag",false }, {0x0072,0x0026,VR::AT,VM::VM1,"Selector Attribute","SelectorAttribute",false }, {0x0072,0x0028,VR::US,VM::VM1,"Selector Value Number","SelectorValueNumber",false }, {0x0072,0x0030,VR::SQ,VM::VM1,"Time Based Image Sets Sequence","TimeBasedImageSetsSequence",false }, {0x0072,0x0032,VR::US,VM::VM1,"Image Set Number","ImageSetNumber",false }, {0x0072,0x0034,VR::CS,VM::VM1,"Image Set Selector Category","ImageSetSelectorCategory",false }, {0x0072,0x0038,VR::US,VM::VM2,"Relative Time","RelativeTime",false }, {0x0072,0x003a,VR::CS,VM::VM1,"Relative Time Units","RelativeTimeUnits",false }, {0x0072,0x003c,VR::SS,VM::VM2,"Abstract Prior Value","AbstractPriorValue",false }, {0x0072,0x003e,VR::SQ,VM::VM1,"Abstract Prior Code Sequence","AbstractPriorCodeSequence",false }, {0x0072,0x0040,VR::LO,VM::VM1,"Image Set Label","ImageSetLabel",false }, {0x0072,0x0050,VR::CS,VM::VM1,"Selector Attribute VR","SelectorAttributeVR",false }, {0x0072,0x0052,VR::AT,VM::VM1_n,"Selector Sequence Pointer","SelectorSequencePointer",false }, {0x0072,0x0054,VR::LO,VM::VM1_n,"Selector Sequence Pointer Private Creator","SelectorSequencePointerPrivateCreator",false }, {0x0072,0x0056,VR::LO,VM::VM1,"Selector Attribute Private Creator","SelectorAttributePrivateCreator",false }, {0x0072,0x005e,VR::AE,VM::VM1_n,"Selector AE Value","SelectorAEValue",false }, {0x0072,0x005f,VR::AS,VM::VM1_n,"Selector AS Value","SelectorASValue",false }, {0x0072,0x0060,VR::AT,VM::VM1_n,"Selector AT Value","SelectorATValue",false }, {0x0072,0x0061,VR::DA,VM::VM1_n,"Selector DA Value","SelectorDAValue",false }, {0x0072,0x0062,VR::CS,VM::VM1_n,"Selector CS Value","SelectorCSValue",false }, {0x0072,0x0063,VR::DT,VM::VM1_n,"Selector DT Value","SelectorDTValue",false }, {0x0072,0x0064,VR::IS,VM::VM1_n,"Selector IS Value","SelectorISValue",false }, {0x0072,0x0065,VR::OB,VM::VM1,"Selector OB Value","SelectorOBValue",false }, {0x0072,0x0066,VR::LO,VM::VM1_n,"Selector LO Value","SelectorLOValue",false }, {0x0072,0x0067,VR::OF,VM::VM1,"Selector OF Value","SelectorOFValue",false }, {0x0072,0x0068,VR::LT,VM::VM1,"Selector LT Value","SelectorLTValue",false }, {0x0072,0x0069,VR::OW,VM::VM1,"Selector OW Value","SelectorOWValue",false }, {0x0072,0x006a,VR::PN,VM::VM1_n,"Selector PN Value","SelectorPNValue",false }, {0x0072,0x006b,VR::TM,VM::VM1_n,"Selector TM Value","SelectorTMValue",false }, {0x0072,0x006c,VR::SH,VM::VM1_n,"Selector SH Value","SelectorSHValue",false }, {0x0072,0x006d,VR::UN,VM::VM1,"Selector UN Value","SelectorUNValue",false }, {0x0072,0x006e,VR::ST,VM::VM1,"Selector ST Value","SelectorSTValue",false }, {0x0072,0x006f,VR::UC,VM::VM1_n,"Selector UC Value","SelectorUCValue",false }, {0x0072,0x0070,VR::UT,VM::VM1,"Selector UT Value","SelectorUTValue",false }, {0x0072,0x0071,VR::UR,VM::VM1,"Selector UR Value","SelectorURValue",false }, {0x0072,0x0072,VR::DS,VM::VM1_n,"Selector DS Value","SelectorDSValue",false }, {0x0072,0x0073,VR::OD,VM::VM1,"Selector OD Value","SelectorODValue",false }, {0x0072,0x0074,VR::FD,VM::VM1_n,"Selector FD Value","SelectorFDValue",false }, {0x0072,0x0075,VR::OL,VM::VM1,"Selector OL Value","SelectorOLValue",false }, {0x0072,0x0076,VR::FL,VM::VM1_n,"Selector FL Value","SelectorFLValue",false }, {0x0072,0x0078,VR::UL,VM::VM1_n,"Selector UL Value","SelectorULValue",false }, {0x0072,0x007a,VR::US,VM::VM1_n,"Selector US Value","SelectorUSValue",false }, {0x0072,0x007c,VR::SL,VM::VM1_n,"Selector SL Value","SelectorSLValue",false }, {0x0072,0x007e,VR::SS,VM::VM1_n,"Selector SS Value","SelectorSSValue",false }, {0x0072,0x007f,VR::UI,VM::VM1_n,"Selector UI Value","SelectorUIValue",false }, {0x0072,0x0080,VR::SQ,VM::VM1,"Selector Code Sequence Value","SelectorCodeSequenceValue",false }, {0x0072,0x0100,VR::US,VM::VM1,"Number of Screens","NumberOfScreens",false }, {0x0072,0x0102,VR::SQ,VM::VM1,"Nominal Screen Definition Sequence","NominalScreenDefinitionSequence",false }, {0x0072,0x0104,VR::US,VM::VM1,"Number of Vertical Pixels","NumberOfVerticalPixels",false }, {0x0072,0x0106,VR::US,VM::VM1,"Number of Horizontal Pixels","NumberOfHorizontalPixels",false }, {0x0072,0x0108,VR::FD,VM::VM4,"Display Environment Spatial Position","DisplayEnvironmentSpatialPosition",false }, {0x0072,0x010a,VR::US,VM::VM1,"Screen Minimum Grayscale Bit Depth","ScreenMinimumGrayscaleBitDepth",false }, {0x0072,0x010c,VR::US,VM::VM1,"Screen Minimum Color Bit Depth","ScreenMinimumColorBitDepth",false }, {0x0072,0x010e,VR::US,VM::VM1,"Application Maximum Repaint Time","ApplicationMaximumRepaintTime",false }, {0x0072,0x0200,VR::SQ,VM::VM1,"Display Sets Sequence","DisplaySetsSequence",false }, {0x0072,0x0202,VR::US,VM::VM1,"Display Set Number","DisplaySetNumber",false }, {0x0072,0x0203,VR::LO,VM::VM1,"Display Set Label","DisplaySetLabel",false }, {0x0072,0x0204,VR::US,VM::VM1,"Display Set Presentation Group","DisplaySetPresentationGroup",false }, {0x0072,0x0206,VR::LO,VM::VM1,"Display Set Presentation Group Description","DisplaySetPresentationGroupDescription",false }, {0x0072,0x0208,VR::CS,VM::VM1,"Partial Data Display Handling","PartialDataDisplayHandling",false }, {0x0072,0x0210,VR::SQ,VM::VM1,"Synchronized Scrolling Sequence","SynchronizedScrollingSequence",false }, {0x0072,0x0212,VR::US,VM::VM2_n,"Display Set Scrolling Group","DisplaySetScrollingGroup",false }, {0x0072,0x0214,VR::SQ,VM::VM1,"Navigation Indicator Sequence","NavigationIndicatorSequence",false }, {0x0072,0x0216,VR::US,VM::VM1,"Navigation Display Set","NavigationDisplaySet",false }, {0x0072,0x0218,VR::US,VM::VM1_n,"Reference Display Sets","ReferenceDisplaySets",false }, {0x0072,0x0300,VR::SQ,VM::VM1,"Image Boxes Sequence","ImageBoxesSequence",false }, {0x0072,0x0302,VR::US,VM::VM1,"Image Box Number","ImageBoxNumber",false }, {0x0072,0x0304,VR::CS,VM::VM1,"Image Box Layout Type","ImageBoxLayoutType",false }, {0x0072,0x0306,VR::US,VM::VM1,"Image Box Tile Horizontal Dimension","ImageBoxTileHorizontalDimension",false }, {0x0072,0x0308,VR::US,VM::VM1,"Image Box Tile Vertical Dimension","ImageBoxTileVerticalDimension",false }, {0x0072,0x0310,VR::CS,VM::VM1,"Image Box Scroll Direction","ImageBoxScrollDirection",false }, {0x0072,0x0312,VR::CS,VM::VM1,"Image Box Small Scroll Type","ImageBoxSmallScrollType",false }, {0x0072,0x0314,VR::US,VM::VM1,"Image Box Small Scroll Amount","ImageBoxSmallScrollAmount",false }, {0x0072,0x0316,VR::CS,VM::VM1,"Image Box Large Scroll Type","ImageBoxLargeScrollType",false }, {0x0072,0x0318,VR::US,VM::VM1,"Image Box Large Scroll Amount","ImageBoxLargeScrollAmount",false }, {0x0072,0x0320,VR::US,VM::VM1,"Image Box Overlap Priority","ImageBoxOverlapPriority",false }, {0x0072,0x0330,VR::FD,VM::VM1,"Cine Relative to Real-Time","CineRelativeToRealTime",false }, {0x0072,0x0400,VR::SQ,VM::VM1,"Filter Operations Sequence","FilterOperationsSequence",false }, {0x0072,0x0402,VR::CS,VM::VM1,"Filter-by Category","FilterByCategory",false }, {0x0072,0x0404,VR::CS,VM::VM1,"Filter-by Attribute Presence","FilterByAttributePresence",false }, {0x0072,0x0406,VR::CS,VM::VM1,"Filter-by Operator","FilterByOperator",false }, {0x0072,0x0420,VR::US,VM::VM3,"Structured Display Background CIELab Value","StructuredDisplayBackgroundCIELabValue",false }, {0x0072,0x0421,VR::US,VM::VM3,"Empty Image Box CIELab Value","EmptyImageBoxCIELabValue",false }, {0x0072,0x0422,VR::SQ,VM::VM1,"Structured Display Image Box Sequence","StructuredDisplayImageBoxSequence",false }, {0x0072,0x0424,VR::SQ,VM::VM1,"Structured Display Text Box Sequence","StructuredDisplayTextBoxSequence",false }, {0x0072,0x0427,VR::SQ,VM::VM1,"Referenced First Frame Sequence","ReferencedFirstFrameSequence",false }, {0x0072,0x0430,VR::SQ,VM::VM1,"Image Box Synchronization Sequence","ImageBoxSynchronizationSequence",false }, {0x0072,0x0432,VR::US,VM::VM2_n,"Synchronized Image Box List","SynchronizedImageBoxList",false }, {0x0072,0x0434,VR::CS,VM::VM1,"Type of Synchronization","TypeOfSynchronization",false }, {0x0072,0x0500,VR::CS,VM::VM1,"Blending Operation Type","BlendingOperationType",false }, {0x0072,0x0510,VR::CS,VM::VM1,"Reformatting Operation Type","ReformattingOperationType",false }, {0x0072,0x0512,VR::FD,VM::VM1,"Reformatting Thickness","ReformattingThickness",false }, {0x0072,0x0514,VR::FD,VM::VM1,"Reformatting Interval","ReformattingInterval",false }, {0x0072,0x0516,VR::CS,VM::VM1,"Reformatting Operation Initial View Direction","ReformattingOperationInitialViewDirection",false }, {0x0072,0x0520,VR::CS,VM::VM1_n,"3D Rendering Type","ThreeDRenderingType",false }, {0x0072,0x0600,VR::SQ,VM::VM1,"Sorting Operations Sequence","SortingOperationsSequence",false }, {0x0072,0x0602,VR::CS,VM::VM1,"Sort-by Category","SortByCategory",false }, {0x0072,0x0604,VR::CS,VM::VM1,"Sorting Direction","SortingDirection",false }, {0x0072,0x0700,VR::CS,VM::VM2,"Display Set Patient Orientation","DisplaySetPatientOrientation",false }, {0x0072,0x0702,VR::CS,VM::VM1,"VOI Type","VOIType",false }, {0x0072,0x0704,VR::CS,VM::VM1,"Pseudo-Color Type","PseudoColorType",false }, {0x0072,0x0705,VR::SQ,VM::VM1,"Pseudo-Color Palette Instance Reference Sequence","PseudoColorPaletteInstanceReferenceSequence",false }, {0x0072,0x0706,VR::CS,VM::VM1,"Show Grayscale Inverted","ShowGrayscaleInverted",false }, {0x0072,0x0710,VR::CS,VM::VM1,"Show Image True Size Flag","ShowImageTrueSizeFlag",false }, {0x0072,0x0712,VR::CS,VM::VM1,"Show Graphic Annotation Flag","ShowGraphicAnnotationFlag",false }, {0x0072,0x0714,VR::CS,VM::VM1,"Show Patient Demographics Flag","ShowPatientDemographicsFlag",false }, {0x0072,0x0716,VR::CS,VM::VM1,"Show Acquisition Techniques Flag","ShowAcquisitionTechniquesFlag",false }, {0x0072,0x0717,VR::CS,VM::VM1,"Display Set Horizontal Justification","DisplaySetHorizontalJustification",false }, {0x0072,0x0718,VR::CS,VM::VM1,"Display Set Vertical Justification","DisplaySetVerticalJustification",false }, {0x0074,0x0120,VR::FD,VM::VM1,"Continuation Start Meterset","ContinuationStartMeterset",false }, {0x0074,0x0121,VR::FD,VM::VM1,"Continuation End Meterset","ContinuationEndMeterset",false }, {0x0074,0x1000,VR::CS,VM::VM1,"Procedure Step State","ProcedureStepState",false }, {0x0074,0x1002,VR::SQ,VM::VM1,"Procedure Step Progress Information Sequence","ProcedureStepProgressInformationSequence",false }, {0x0074,0x1004,VR::DS,VM::VM1,"Procedure Step Progress","ProcedureStepProgress",false }, {0x0074,0x1006,VR::ST,VM::VM1,"Procedure Step Progress Description","ProcedureStepProgressDescription",false }, {0x0074,0x1008,VR::SQ,VM::VM1,"Procedure Step Communications URI Sequence","ProcedureStepCommunicationsURISequence",false }, {0x0074,0x100a,VR::UR,VM::VM1,"Contact URI","ContactURI",false }, {0x0074,0x100c,VR::LO,VM::VM1,"Contact Display Name","ContactDisplayName",false }, {0x0074,0x100e,VR::SQ,VM::VM1,"Procedure Step Discontinuation Reason Code Sequence","ProcedureStepDiscontinuationReasonCodeSequence",false }, {0x0074,0x1020,VR::SQ,VM::VM1,"Beam Task Sequence","BeamTaskSequence",false }, {0x0074,0x1022,VR::CS,VM::VM1,"Beam Task Type","BeamTaskType",false }, {0x0074,0x1024,VR::IS,VM::VM1,"Beam Order Index (Trial)","BeamOrderIndexTrial",true }, {0x0074,0x1025,VR::CS,VM::VM1,"Autosequence Flag","AutosequenceFlag",false }, {0x0074,0x1026,VR::FD,VM::VM1,"Table Top Vertical Adjusted Position","TableTopVerticalAdjustedPosition",false }, {0x0074,0x1027,VR::FD,VM::VM1,"Table Top Longitudinal Adjusted Position","TableTopLongitudinalAdjustedPosition",false }, {0x0074,0x1028,VR::FD,VM::VM1,"Table Top Lateral Adjusted Position","TableTopLateralAdjustedPosition",false }, {0x0074,0x102a,VR::FD,VM::VM1,"Patient Support Adjusted Angle","PatientSupportAdjustedAngle",false }, {0x0074,0x102b,VR::FD,VM::VM1,"Table Top Eccentric Adjusted Angle","TableTopEccentricAdjustedAngle",false }, {0x0074,0x102c,VR::FD,VM::VM1,"Table Top Pitch Adjusted Angle","TableTopPitchAdjustedAngle",false }, {0x0074,0x102d,VR::FD,VM::VM1,"Table Top Roll Adjusted Angle","TableTopRollAdjustedAngle",false }, {0x0074,0x1030,VR::SQ,VM::VM1,"Delivery Verification Image Sequence","DeliveryVerificationImageSequence",false }, {0x0074,0x1032,VR::CS,VM::VM1,"Verification Image Timing","VerificationImageTiming",false }, {0x0074,0x1034,VR::CS,VM::VM1,"Double Exposure Flag","DoubleExposureFlag",false }, {0x0074,0x1036,VR::CS,VM::VM1,"Double Exposure Ordering","DoubleExposureOrdering",false }, {0x0074,0x1038,VR::DS,VM::VM1,"Double Exposure Meterset (Trial)","DoubleExposureMetersetTrial",true }, {0x0074,0x103a,VR::DS,VM::VM4,"Double Exposure Field Delta (Trial)","DoubleExposureFieldDeltaTrial",true }, {0x0074,0x1040,VR::SQ,VM::VM1,"Related Reference RT Image Sequence","RelatedReferenceRTImageSequence",false }, {0x0074,0x1042,VR::SQ,VM::VM1,"General Machine Verification Sequence","GeneralMachineVerificationSequence",false }, {0x0074,0x1044,VR::SQ,VM::VM1,"Conventional Machine Verification Sequence","ConventionalMachineVerificationSequence",false }, {0x0074,0x1046,VR::SQ,VM::VM1,"Ion Machine Verification Sequence","IonMachineVerificationSequence",false }, {0x0074,0x1048,VR::SQ,VM::VM1,"Failed Attributes Sequence","FailedAttributesSequence",false }, {0x0074,0x104a,VR::SQ,VM::VM1,"Overridden Attributes Sequence","OverriddenAttributesSequence",false }, {0x0074,0x104c,VR::SQ,VM::VM1,"Conventional Control Point Verification Sequence","ConventionalControlPointVerificationSequence",false }, {0x0074,0x104e,VR::SQ,VM::VM1,"Ion Control Point Verification Sequence","IonControlPointVerificationSequence",false }, {0x0074,0x1050,VR::SQ,VM::VM1,"Attribute Occurrence Sequence","AttributeOccurrenceSequence",false }, {0x0074,0x1052,VR::AT,VM::VM1,"Attribute Occurrence Pointer","AttributeOccurrencePointer",false }, {0x0074,0x1054,VR::UL,VM::VM1,"Attribute Item Selector","AttributeItemSelector",false }, {0x0074,0x1056,VR::LO,VM::VM1,"Attribute Occurrence Private Creator","AttributeOccurrencePrivateCreator",false }, {0x0074,0x1057,VR::IS,VM::VM1_n,"Selector Sequence Pointer Items","SelectorSequencePointerItems",false }, {0x0074,0x1200,VR::CS,VM::VM1,"Scheduled Procedure Step Priority","ScheduledProcedureStepPriority",false }, {0x0074,0x1202,VR::LO,VM::VM1,"Worklist Label","WorklistLabel",false }, {0x0074,0x1204,VR::LO,VM::VM1,"Procedure Step Label","ProcedureStepLabel",false }, {0x0074,0x1210,VR::SQ,VM::VM1,"Scheduled Processing Parameters Sequence","ScheduledProcessingParametersSequence",false }, {0x0074,0x1212,VR::SQ,VM::VM1,"Performed Processing Parameters Sequence","PerformedProcessingParametersSequence",false }, {0x0074,0x1216,VR::SQ,VM::VM1,"Unified Procedure Step Performed Procedure Sequence","UnifiedProcedureStepPerformedProcedureSequence",false }, {0x0074,0x1220,VR::SQ,VM::VM1,"Related Procedure Step Sequence","RelatedProcedureStepSequence",true }, {0x0074,0x1222,VR::LO,VM::VM1,"Procedure Step Relationship Type","ProcedureStepRelationshipType",true }, {0x0074,0x1224,VR::SQ,VM::VM1,"Replaced Procedure Step Sequence","ReplacedProcedureStepSequence",false }, {0x0074,0x1230,VR::LO,VM::VM1,"Deletion Lock","DeletionLock",false }, {0x0074,0x1234,VR::AE,VM::VM1,"Receiving AE","ReceivingAE",false }, {0x0074,0x1236,VR::AE,VM::VM1,"Requesting AE","RequestingAE",false }, {0x0074,0x1238,VR::LT,VM::VM1,"Reason for Cancellation","ReasonForCancellation",false }, {0x0074,0x1242,VR::CS,VM::VM1,"SCP Status","SCPStatus",false }, {0x0074,0x1244,VR::CS,VM::VM1,"Subscription List Status","SubscriptionListStatus",false }, {0x0074,0x1246,VR::CS,VM::VM1,"Unified Procedure Step List Status","UnifiedProcedureStepListStatus",false }, {0x0074,0x1324,VR::UL,VM::VM1,"Beam Order Index","BeamOrderIndex",false }, {0x0074,0x1338,VR::FD,VM::VM1,"Double Exposure Meterset","DoubleExposureMeterset",false }, {0x0074,0x133a,VR::FD,VM::VM4,"Double Exposure Field Delta","DoubleExposureFieldDelta",false }, {0x0074,0x1401,VR::SQ,VM::VM1,"Brachy Task Sequence","BrachyTaskSequence",false }, {0x0074,0x1402,VR::DS,VM::VM1,"Continuation Start Total Reference Air Kerma","ContinuationStartTotalReferenceAirKerma",false }, {0x0074,0x1403,VR::DS,VM::VM1,"Continuation End Total Reference Air Kerma","ContinuationEndTotalReferenceAirKerma",false }, {0x0074,0x1404,VR::IS,VM::VM1,"Continuation Pulse Number","ContinuationPulseNumber",false }, {0x0074,0x1405,VR::SQ,VM::VM1,"Channel Delivery Order Sequence","ChannelDeliveryOrderSequence",false }, {0x0074,0x1406,VR::IS,VM::VM1,"Referenced Channel Number","ReferencedChannelNumber",false }, {0x0074,0x1407,VR::DS,VM::VM1,"Start Cumulative Time Weight","StartCumulativeTimeWeight",false }, {0x0074,0x1408,VR::DS,VM::VM1,"End Cumulative Time Weight","EndCumulativeTimeWeight",false }, {0x0074,0x1409,VR::SQ,VM::VM1,"Omitted Channel Sequence","OmittedChannelSequence",false }, {0x0074,0x140a,VR::CS,VM::VM1,"Reason for Channel Omission","ReasonForChannelOmission",false }, {0x0074,0x140b,VR::LO,VM::VM1,"Reason for Channel Omission Description","ReasonForChannelOmissionDescription",false }, {0x0074,0x140c,VR::IS,VM::VM1,"Channel Delivery Order Index","ChannelDeliveryOrderIndex",false }, {0x0074,0x140d,VR::SQ,VM::VM1,"Channel Delivery Continuation Sequence","ChannelDeliveryContinuationSequence",false }, {0x0074,0x140e,VR::SQ,VM::VM1,"Omitted Application Setup Sequence","OmittedApplicationSetupSequence",false }, {0x0076,0x0001,VR::LO,VM::VM1,"Implant Assembly Template Name","ImplantAssemblyTemplateName",false }, {0x0076,0x0003,VR::LO,VM::VM1,"Implant Assembly Template Issuer","ImplantAssemblyTemplateIssuer",false }, {0x0076,0x0006,VR::LO,VM::VM1,"Implant Assembly Template Version","ImplantAssemblyTemplateVersion",false }, {0x0076,0x0008,VR::SQ,VM::VM1,"Replaced Implant Assembly Template Sequence","ReplacedImplantAssemblyTemplateSequence",false }, {0x0076,0x000a,VR::CS,VM::VM1,"Implant Assembly Template Type","ImplantAssemblyTemplateType",false }, {0x0076,0x000c,VR::SQ,VM::VM1,"Original Implant Assembly Template Sequence","OriginalImplantAssemblyTemplateSequence",false }, {0x0076,0x000e,VR::SQ,VM::VM1,"Derivation Implant Assembly Template Sequence","DerivationImplantAssemblyTemplateSequence",false }, {0x0076,0x0010,VR::SQ,VM::VM1,"Implant Assembly Template Target Anatomy Sequence","ImplantAssemblyTemplateTargetAnatomySequence",false }, {0x0076,0x0020,VR::SQ,VM::VM1,"Procedure Type Code Sequence","ProcedureTypeCodeSequence",false }, {0x0076,0x0030,VR::LO,VM::VM1,"Surgical Technique","SurgicalTechnique",false }, {0x0076,0x0032,VR::SQ,VM::VM1,"Component Types Sequence","ComponentTypesSequence",false }, {0x0076,0x0034,VR::CS,VM::VM1,"Component Type Code Sequence","ComponentTypeCodeSequence",false }, {0x0076,0x0036,VR::CS,VM::VM1,"Exclusive Component Type","ExclusiveComponentType",false }, {0x0076,0x0038,VR::CS,VM::VM1,"Mandatory Component Type","MandatoryComponentType",false }, {0x0076,0x0040,VR::SQ,VM::VM1,"Component Sequence","ComponentSequence",false }, {0x0076,0x0055,VR::US,VM::VM1,"Component ID","ComponentID",false }, {0x0076,0x0060,VR::SQ,VM::VM1,"Component Assembly Sequence","ComponentAssemblySequence",false }, {0x0076,0x0070,VR::US,VM::VM1,"Component 1 Referenced ID","Component1ReferencedID",false }, {0x0076,0x0080,VR::US,VM::VM1,"Component 1 Referenced Mating Feature Set ID","Component1ReferencedMatingFeatureSetID",false }, {0x0076,0x0090,VR::US,VM::VM1,"Component 1 Referenced Mating Feature ID","Component1ReferencedMatingFeatureID",false }, {0x0076,0x00a0,VR::US,VM::VM1,"Component 2 Referenced ID","Component2ReferencedID",false }, {0x0076,0x00b0,VR::US,VM::VM1,"Component 2 Referenced Mating Feature Set ID","Component2ReferencedMatingFeatureSetID",false }, {0x0076,0x00c0,VR::US,VM::VM1,"Component 2 Referenced Mating Feature ID","Component2ReferencedMatingFeatureID",false }, {0x0078,0x0001,VR::LO,VM::VM1,"Implant Template Group Name","ImplantTemplateGroupName",false }, {0x0078,0x0010,VR::ST,VM::VM1,"Implant Template Group Description","ImplantTemplateGroupDescription",false }, {0x0078,0x0020,VR::LO,VM::VM1,"Implant Template Group Issuer","ImplantTemplateGroupIssuer",false }, {0x0078,0x0024,VR::LO,VM::VM1,"Implant Template Group Version","ImplantTemplateGroupVersion",false }, {0x0078,0x0026,VR::SQ,VM::VM1,"Replaced Implant Template Group Sequence","ReplacedImplantTemplateGroupSequence",false }, {0x0078,0x0028,VR::SQ,VM::VM1,"Implant Template Group Target Anatomy Sequence","ImplantTemplateGroupTargetAnatomySequence",false }, {0x0078,0x002a,VR::SQ,VM::VM1,"Implant Template Group Members Sequence","ImplantTemplateGroupMembersSequence",false }, {0x0078,0x002e,VR::US,VM::VM1,"Implant Template Group Member ID","ImplantTemplateGroupMemberID",false }, {0x0078,0x0050,VR::FD,VM::VM3,"3D Implant Template Group Member Matching Point","ThreeDImplantTemplateGroupMemberMatchingPoint",false }, {0x0078,0x0060,VR::FD,VM::VM9,"3D Implant Template Group Member Matching Axes","ThreeDImplantTemplateGroupMemberMatchingAxes",false }, {0x0078,0x0070,VR::SQ,VM::VM1,"Implant Template Group Member Matching 2D Coordinates Sequence","ImplantTemplateGroupMemberMatching2DCoordinatesSequence",false }, {0x0078,0x0090,VR::FD,VM::VM2,"2D Implant Template Group Member Matching Point","TwoDImplantTemplateGroupMemberMatchingPoint",false }, {0x0078,0x00a0,VR::FD,VM::VM4,"2D Implant Template Group Member Matching Axes","TwoDImplantTemplateGroupMemberMatchingAxes",false }, {0x0078,0x00b0,VR::SQ,VM::VM1,"Implant Template Group Variation Dimension Sequence","ImplantTemplateGroupVariationDimensionSequence",false }, {0x0078,0x00b2,VR::LO,VM::VM1,"Implant Template Group Variation Dimension Name","ImplantTemplateGroupVariationDimensionName",false }, {0x0078,0x00b4,VR::SQ,VM::VM1,"Implant Template Group Variation Dimension Rank Sequence","ImplantTemplateGroupVariationDimensionRankSequence",false }, {0x0078,0x00b6,VR::US,VM::VM1,"Referenced Implant Template Group Member ID","ReferencedImplantTemplateGroupMemberID",false }, {0x0078,0x00b8,VR::US,VM::VM1,"Implant Template Group Variation Dimension Rank","ImplantTemplateGroupVariationDimensionRank",false }, {0x0080,0x0001,VR::SQ,VM::VM1,"Surface Scan Acquisition Type Code Sequence","SurfaceScanAcquisitionTypeCodeSequence",false }, {0x0080,0x0002,VR::SQ,VM::VM1,"Surface Scan Mode Code Sequence","SurfaceScanModeCodeSequence",false }, {0x0080,0x0003,VR::SQ,VM::VM1,"Registration Method Code Sequence","RegistrationMethodCodeSequence",false }, {0x0080,0x0004,VR::FD,VM::VM1,"Shot Duration Time","ShotDurationTime",false }, {0x0080,0x0005,VR::FD,VM::VM1,"Shot Offset Time","ShotOffsetTime",false }, {0x0080,0x0006,VR::US,VM::VM1_n,"Surface Point Presentation Value Data","SurfacePointPresentationValueData",false }, {0x0080,0x0007,VR::US,VM::VM3_3n,"Surface Point Color CIELab Value Data","SurfacePointColorCIELabValueData",false }, {0x0080,0x0008,VR::SQ,VM::VM1,"UV Mapping Sequence","UVMappingSequence",false }, {0x0080,0x0009,VR::SH,VM::VM1,"Texture Label","TextureLabel",false }, {0x0080,0x0010,VR::OF,VM::VM1_n,"U Value Data","UValueData",false }, {0x0080,0x0011,VR::OF,VM::VM1_n,"V Value Data","VValueData",false }, {0x0080,0x0012,VR::SQ,VM::VM1,"Referenced Texture Sequence","ReferencedTextureSequence",false }, {0x0080,0x0013,VR::SQ,VM::VM1,"Referenced Surface Data Sequence","ReferencedSurfaceDataSequence",false }, {0x0082,0x0001,VR::CS,VM::VM1,"Assessment Summary","AssessmentSummary",false }, {0x0082,0x0003,VR::UT,VM::VM1,"Assessment Summary Description","AssessmentSummaryDescription",false }, {0x0082,0x0004,VR::SQ,VM::VM1,"Assessed SOP Instance Sequence","AssessedSOPInstanceSequence",false }, {0x0082,0x0005,VR::SQ,VM::VM1,"Referenced Comparison SOP Instance Sequence","ReferencedComparisonSOPInstanceSequence",false }, {0x0082,0x0006,VR::UL,VM::VM1,"Number of Assessment Observations","NumberOfAssessmentObservations",false }, {0x0082,0x0007,VR::SQ,VM::VM1,"Assessment Observations Sequence","AssessmentObservationsSequence",false }, {0x0082,0x0008,VR::CS,VM::VM1,"Observation Significance","ObservationSignificance",false }, {0x0082,0x000a,VR::UT,VM::VM1,"Observation Description","ObservationDescription",false }, {0x0082,0x000c,VR::SQ,VM::VM1,"Structured Constraint Observation Sequence","StructuredContraintObservationSequence",false }, {0x0082,0x0010,VR::SQ,VM::VM1,"Assessed Attribute Value Sequence","AssessedAttributeValueSequence",false }, {0x0082,0x0016,VR::LO,VM::VM1,"Assessment Set ID","AssessmentSetID",false }, {0x0082,0x0017,VR::SQ,VM::VM1,"Assessment Requester Sequence","AssessmentRequesterSequence",false }, {0x0082,0x0018,VR::LO,VM::VM1,"Selector Attribute Name","SelectorAttributeName",false }, {0x0082,0x0019,VR::LO,VM::VM1,"Selector Attribute Keyword","SelectorAttributeKeyword",false }, {0x0082,0x0021,VR::SQ,VM::VM1,"Assessment Type Code Sequence","AssessmentTypeCodeSequence",false }, {0x0082,0x0022,VR::SQ,VM::VM1,"Observation Basis Code Sequence","ObservationBasisCodeSequence",false }, {0x0082,0x0023,VR::LO,VM::VM1,"Assessment Label","AssessmentLabel",false }, {0x0082,0x0032,VR::CS,VM::VM1,"Constraint Type","ConstraintType",false }, {0x0082,0x0033,VR::UT,VM::VM1,"Specification Selection Guidance","SpecificationSelectionGuidance",false }, {0x0082,0x0034,VR::SQ,VM::VM1,"Constraint Value Sequence","ConstraintValueSequence",false }, {0x0082,0x0035,VR::SQ,VM::VM1,"Recommended Default Value Sequence","RecommendedDefaultValueSequence",false }, {0x0082,0x0036,VR::CS,VM::VM1,"Constraint Violation Significance","ConstraintViolationSignificance",false }, {0x0082,0x0037,VR::UT,VM::VM1,"Constraint Violation Condition","ConstraintViolationCondition",false }, {0x0082,0x0038,VR::CS,VM::VM1,"Modifiable Constraint Flag","ModifiableConstraintFlag",false }, {0x0088,0x0130,VR::SH,VM::VM1,"Storage Media File-set ID","StorageMediaFileSetID",false }, {0x0088,0x0140,VR::UI,VM::VM1,"Storage Media File-set UID","StorageMediaFileSetUID",false }, {0x0088,0x0200,VR::SQ,VM::VM1,"Icon Image Sequence","IconImageSequence",false }, {0x0088,0x0904,VR::LO,VM::VM1,"Topic Title","TopicTitle",true }, {0x0088,0x0906,VR::ST,VM::VM1,"Topic Subject","TopicSubject",true }, {0x0088,0x0910,VR::LO,VM::VM1,"Topic Author","TopicAuthor",true }, {0x0088,0x0912,VR::LO,VM::VM1_32,"Topic Keywords","TopicKeywords",true }, {0x0100,0x0410,VR::CS,VM::VM1,"SOP Instance Status","SOPInstanceStatus",false }, {0x0100,0x0420,VR::DT,VM::VM1,"SOP Authorization DateTime","SOPAuthorizationDateTime",false }, {0x0100,0x0424,VR::LT,VM::VM1,"SOP Authorization Comment","SOPAuthorizationComment",false }, {0x0100,0x0426,VR::LO,VM::VM1,"Authorization Equipment Certification Number","AuthorizationEquipmentCertificationNumber",false }, {0x0400,0x0005,VR::US,VM::VM1,"MAC ID Number","MACIDNumber",false }, {0x0400,0x0010,VR::UI,VM::VM1,"MAC Calculation Transfer Syntax UID","MACCalculationTransferSyntaxUID",false }, {0x0400,0x0015,VR::CS,VM::VM1,"MAC Algorithm","MACAlgorithm",false }, {0x0400,0x0020,VR::AT,VM::VM1_n,"Data Elements Signed","DataElementsSigned",false }, {0x0400,0x0100,VR::UI,VM::VM1,"Digital Signature UID","DigitalSignatureUID",false }, {0x0400,0x0105,VR::DT,VM::VM1,"Digital Signature DateTime","DigitalSignatureDateTime",false }, {0x0400,0x0110,VR::CS,VM::VM1,"Certificate Type","CertificateType",false }, {0x0400,0x0115,VR::OB,VM::VM1,"Certificate of Signer","CertificateOfSigner",false }, {0x0400,0x0120,VR::OB,VM::VM1,"Signature","Signature",false }, {0x0400,0x0305,VR::CS,VM::VM1,"Certified Timestamp Type","CertifiedTimestampType",false }, {0x0400,0x0310,VR::OB,VM::VM1,"Certified Timestamp","CertifiedTimestamp",false }, {0x0400,0x0315,VR::FL,VM::VM1,"","",true }, {0x0400,0x0401,VR::SQ,VM::VM1,"Digital Signature Purpose Code Sequence","DigitalSignaturePurposeCodeSequence",false }, {0x0400,0x0402,VR::SQ,VM::VM1,"Referenced Digital Signature Sequence","ReferencedDigitalSignatureSequence",false }, {0x0400,0x0403,VR::SQ,VM::VM1,"Referenced SOP Instance MAC Sequence","ReferencedSOPInstanceMACSequence",false }, {0x0400,0x0404,VR::OB,VM::VM1,"MAC","MAC",false }, {0x0400,0x0500,VR::SQ,VM::VM1,"Encrypted Attributes Sequence","EncryptedAttributesSequence",false }, {0x0400,0x0510,VR::UI,VM::VM1,"Encrypted Content Transfer Syntax UID","EncryptedContentTransferSyntaxUID",false }, {0x0400,0x0520,VR::OB,VM::VM1,"Encrypted Content","EncryptedContent",false }, {0x0400,0x0550,VR::SQ,VM::VM1,"Modified Attributes Sequence","ModifiedAttributesSequence",false }, {0x0400,0x0561,VR::SQ,VM::VM1,"Original Attributes Sequence","OriginalAttributesSequence",false }, {0x0400,0x0562,VR::DT,VM::VM1,"Attribute Modification DateTime","AttributeModificationDateTime",false }, {0x0400,0x0563,VR::LO,VM::VM1,"Modifying System","ModifyingSystem",false }, {0x0400,0x0564,VR::LO,VM::VM1,"Source of Previous Values","SourceOfPreviousValues",false }, {0x0400,0x0565,VR::CS,VM::VM1,"Reason for the Attribute Modification","ReasonForTheAttributeModification",false }, // {0x1010,0x0000,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0001,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0002,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0003,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0004,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0005,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0006,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0007,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0008,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0009,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x000a,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x000b,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x000c,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x000d,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x000e,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x000f,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0010,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0011,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0012,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0013,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0014,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0015,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0016,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0017,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0018,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0019,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x001a,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x001b,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x001c,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x001d,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x001e,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x001f,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0020,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0021,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0022,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0023,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0024,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0025,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0026,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0027,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0028,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0029,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x002a,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x002b,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x002c,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x002d,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x002e,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x002f,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0030,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0031,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0032,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0033,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0034,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0035,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0036,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0037,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0038,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0039,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x003a,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x003b,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x003c,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x003d,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x003e,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x003f,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0040,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0041,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0042,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0043,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0044,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0045,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0046,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0047,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0048,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0049,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x004a,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x004b,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x004c,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x004d,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x004e,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x004f,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0050,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0051,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0052,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0053,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0054,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0055,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0056,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0057,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0058,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0059,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x005a,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x005b,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x005c,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x005d,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x005e,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x005f,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0060,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0061,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0062,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0063,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0064,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0065,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0066,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0067,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0068,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0069,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x006a,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x006b,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x006c,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x006d,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x006e,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x006f,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0070,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0071,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0072,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0073,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0074,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0075,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0076,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0077,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0078,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0079,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x007a,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x007b,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x007c,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x007d,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x007e,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x007f,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0080,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0081,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0082,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0083,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0084,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0085,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0086,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0087,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0088,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0089,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x008a,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x008b,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x008c,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x008d,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x008e,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x008f,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0090,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0091,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0092,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0093,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0094,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0095,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0096,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0097,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0098,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x0099,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x009a,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x009b,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x009c,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x009d,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x009e,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x009f,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00a0,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00a1,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00a2,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00a3,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00a4,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00a5,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00a6,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00a7,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00a8,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00a9,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00aa,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00ab,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00ac,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00ad,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00ae,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00af,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00b0,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00b1,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00b2,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00b3,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00b4,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00b5,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00b6,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00b7,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00b8,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00b9,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00ba,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00bb,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00bc,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00bd,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00be,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00bf,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00c0,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00c1,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00c2,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00c3,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00c4,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00c5,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00c6,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00c7,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00c8,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00c9,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00ca,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00cb,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00cc,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00cd,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00ce,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00cf,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00d0,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00d1,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00d2,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00d3,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00d4,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00d5,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00d6,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00d7,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00d8,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00d9,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00da,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00db,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00dc,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00dd,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00de,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00df,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00e0,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00e1,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00e2,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00e3,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00e4,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00e5,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00e6,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00e7,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00e8,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00e9,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00ea,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00eb,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00ec,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00ed,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00ee,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00ef,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00f0,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00f1,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00f2,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00f3,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00f4,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00f5,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00f6,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00f7,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00f8,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00f9,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00fa,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00fb,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00fc,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00fd,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00fe,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x1010,0x00ff,VR::US,VM::VM1_n,"Zonal Map","ZonalMap",true }, {0x2000,0x0010,VR::IS,VM::VM1,"Number of Copies","NumberOfCopies",false }, {0x2000,0x001e,VR::SQ,VM::VM1,"Printer Configuration Sequence","PrinterConfigurationSequence",false }, {0x2000,0x0020,VR::CS,VM::VM1,"Print Priority","PrintPriority",false }, {0x2000,0x0030,VR::CS,VM::VM1,"Medium Type","MediumType",false }, {0x2000,0x0040,VR::CS,VM::VM1,"Film Destination","FilmDestination",false }, {0x2000,0x0050,VR::LO,VM::VM1,"Film Session Label","FilmSessionLabel",false }, {0x2000,0x0060,VR::IS,VM::VM1,"Memory Allocation","MemoryAllocation",false }, {0x2000,0x0061,VR::IS,VM::VM1,"Maximum Memory Allocation","MaximumMemoryAllocation",false }, {0x2000,0x0062,VR::CS,VM::VM1,"Color Image Printing Flag","ColorImagePrintingFlag",true }, {0x2000,0x0063,VR::CS,VM::VM1,"Collation Flag","CollationFlag",true }, {0x2000,0x0065,VR::CS,VM::VM1,"Annotation Flag","AnnotationFlag",true }, {0x2000,0x0067,VR::CS,VM::VM1,"Image Overlay Flag","ImageOverlayFlag",true }, {0x2000,0x0069,VR::CS,VM::VM1,"Presentation LUT Flag","PresentationLUTFlag",true }, {0x2000,0x006a,VR::CS,VM::VM1,"Image Box Presentation LUT Flag","ImageBoxPresentationLUTFlag",true }, {0x2000,0x00a0,VR::US,VM::VM1,"Memory Bit Depth","MemoryBitDepth",false }, {0x2000,0x00a1,VR::US,VM::VM1,"Printing Bit Depth","PrintingBitDepth",false }, {0x2000,0x00a2,VR::SQ,VM::VM1,"Media Installed Sequence","MediaInstalledSequence",false }, {0x2000,0x00a4,VR::SQ,VM::VM1,"Other Media Available Sequence","OtherMediaAvailableSequence",false }, {0x2000,0x00a8,VR::SQ,VM::VM1,"Supported Image Display Formats Sequence","SupportedImageDisplayFormatsSequence",false }, {0x2000,0x0500,VR::SQ,VM::VM1,"Referenced Film Box Sequence","ReferencedFilmBoxSequence",false }, {0x2000,0x0510,VR::SQ,VM::VM1,"Referenced Stored Print Sequence","ReferencedStoredPrintSequence",true }, {0x2010,0x0010,VR::ST,VM::VM1,"Image Display Format","ImageDisplayFormat",false }, {0x2010,0x0030,VR::CS,VM::VM1,"Annotation Display Format ID","AnnotationDisplayFormatID",false }, {0x2010,0x0040,VR::CS,VM::VM1,"Film Orientation","FilmOrientation",false }, {0x2010,0x0050,VR::CS,VM::VM1,"Film Size ID","FilmSizeID",false }, {0x2010,0x0052,VR::CS,VM::VM1,"Printer Resolution ID","PrinterResolutionID",false }, {0x2010,0x0054,VR::CS,VM::VM1,"Default Printer Resolution ID","DefaultPrinterResolutionID",false }, {0x2010,0x0060,VR::CS,VM::VM1,"Magnification Type","MagnificationType",false }, {0x2010,0x0080,VR::CS,VM::VM1,"Smoothing Type","SmoothingType",false }, {0x2010,0x00a6,VR::CS,VM::VM1,"Default Magnification Type","DefaultMagnificationType",false }, {0x2010,0x00a7,VR::CS,VM::VM1_n,"Other Magnification Types Available","OtherMagnificationTypesAvailable",false }, {0x2010,0x00a8,VR::CS,VM::VM1,"Default Smoothing Type","DefaultSmoothingType",false }, {0x2010,0x00a9,VR::CS,VM::VM1_n,"Other Smoothing Types Available","OtherSmoothingTypesAvailable",false }, {0x2010,0x0100,VR::CS,VM::VM1,"Border Density","BorderDensity",false }, {0x2010,0x0110,VR::CS,VM::VM1,"Empty Image Density","EmptyImageDensity",false }, {0x2010,0x0120,VR::US,VM::VM1,"Min Density","MinDensity",false }, {0x2010,0x0130,VR::US,VM::VM1,"Max Density","MaxDensity",false }, {0x2010,0x0140,VR::CS,VM::VM1,"Trim","Trim",false }, {0x2010,0x0150,VR::ST,VM::VM1,"Configuration Information","ConfigurationInformation",false }, {0x2010,0x0152,VR::LT,VM::VM1,"Configuration Information Description","ConfigurationInformationDescription",false }, {0x2010,0x0154,VR::IS,VM::VM1,"Maximum Collated Films","MaximumCollatedFilms",false }, {0x2010,0x015e,VR::US,VM::VM1,"Illumination","Illumination",false }, {0x2010,0x0160,VR::US,VM::VM1,"Reflected Ambient Light","ReflectedAmbientLight",false }, {0x2010,0x0376,VR::DS,VM::VM2,"Printer Pixel Spacing","PrinterPixelSpacing",false }, {0x2010,0x0500,VR::SQ,VM::VM1,"Referenced Film Session Sequence","ReferencedFilmSessionSequence",false }, {0x2010,0x0510,VR::SQ,VM::VM1,"Referenced Image Box Sequence","ReferencedImageBoxSequence",false }, {0x2010,0x0520,VR::SQ,VM::VM1,"Referenced Basic Annotation Box Sequence","ReferencedBasicAnnotationBoxSequence",false }, {0x2020,0x0010,VR::US,VM::VM1,"Image Box Position","ImageBoxPosition",false }, {0x2020,0x0020,VR::CS,VM::VM1,"Polarity","Polarity",false }, {0x2020,0x0030,VR::DS,VM::VM1,"Requested Image Size","RequestedImageSize",false }, {0x2020,0x0040,VR::CS,VM::VM1,"Requested Decimate/Crop Behavior","RequestedDecimateCropBehavior",false }, {0x2020,0x0050,VR::CS,VM::VM1,"Requested Resolution ID","RequestedResolutionID",false }, {0x2020,0x00a0,VR::CS,VM::VM1,"Requested Image Size Flag","RequestedImageSizeFlag",false }, {0x2020,0x00a2,VR::CS,VM::VM1,"Decimate/Crop Result","DecimateCropResult",false }, {0x2020,0x0110,VR::SQ,VM::VM1,"Basic Grayscale Image Sequence","BasicGrayscaleImageSequence",false }, {0x2020,0x0111,VR::SQ,VM::VM1,"Basic Color Image Sequence","BasicColorImageSequence",false }, {0x2020,0x0130,VR::SQ,VM::VM1,"Referenced Image Overlay Box Sequence","ReferencedImageOverlayBoxSequence",true }, {0x2020,0x0140,VR::SQ,VM::VM1,"Referenced VOI LUT Box Sequence","ReferencedVOILUTBoxSequence",true }, {0x2030,0x0010,VR::US,VM::VM1,"Annotation Position","AnnotationPosition",false }, {0x2030,0x0020,VR::LO,VM::VM1,"Text String","TextString",false }, {0x2040,0x0010,VR::SQ,VM::VM1,"Referenced Overlay Plane Sequence","ReferencedOverlayPlaneSequence",true }, {0x2040,0x0011,VR::US,VM::VM1_99,"Referenced Overlay Plane Groups","ReferencedOverlayPlaneGroups",true }, {0x2040,0x0020,VR::SQ,VM::VM1,"Overlay Pixel Data Sequence","OverlayPixelDataSequence",true }, {0x2040,0x0060,VR::CS,VM::VM1,"Overlay Magnification Type","OverlayMagnificationType",true }, {0x2040,0x0070,VR::CS,VM::VM1,"Overlay Smoothing Type","OverlaySmoothingType",true }, {0x2040,0x0072,VR::CS,VM::VM1,"Overlay or Image Magnification","OverlayOrImageMagnification",true }, {0x2040,0x0074,VR::US,VM::VM1,"Magnify to Number of Columns","MagnifyToNumberOfColumns",true }, {0x2040,0x0080,VR::CS,VM::VM1,"Overlay Foreground Density","OverlayForegroundDensity",true }, {0x2040,0x0082,VR::CS,VM::VM1,"Overlay Background Density","OverlayBackgroundDensity",true }, {0x2040,0x0090,VR::CS,VM::VM1,"Overlay Mode","OverlayMode",true }, {0x2040,0x0100,VR::CS,VM::VM1,"Threshold Density","ThresholdDensity",true }, {0x2040,0x0500,VR::SQ,VM::VM1,"Referenced Image Box Sequence (Retired)","ReferencedImageBoxSequenceRetired",true }, {0x2050,0x0010,VR::SQ,VM::VM1,"Presentation LUT Sequence","PresentationLUTSequence",false }, {0x2050,0x0020,VR::CS,VM::VM1,"Presentation LUT Shape","PresentationLUTShape",false }, {0x2050,0x0500,VR::SQ,VM::VM1,"Referenced Presentation LUT Sequence","ReferencedPresentationLUTSequence",false }, {0x2100,0x0010,VR::SH,VM::VM1,"Print Job ID","PrintJobID",true }, {0x2100,0x0020,VR::CS,VM::VM1,"Execution Status","ExecutionStatus",false }, {0x2100,0x0030,VR::CS,VM::VM1,"Execution Status Info","ExecutionStatusInfo",false }, {0x2100,0x0040,VR::DA,VM::VM1,"Creation Date","CreationDate",false }, {0x2100,0x0050,VR::TM,VM::VM1,"Creation Time","CreationTime",false }, {0x2100,0x0070,VR::AE,VM::VM1,"Originator","Originator",false }, {0x2100,0x0140,VR::AE,VM::VM1,"Destination AE","DestinationAE",false }, {0x2100,0x0160,VR::SH,VM::VM1,"Owner ID","OwnerID",false }, {0x2100,0x0170,VR::IS,VM::VM1,"Number of Films","NumberOfFilms",false }, {0x2100,0x0500,VR::SQ,VM::VM1,"Referenced Print Job Sequence (Pull Stored Print)","ReferencedPrintJobSequencePullStoredPrint",true }, {0x2110,0x0010,VR::CS,VM::VM1,"Printer Status","PrinterStatus",false }, {0x2110,0x0020,VR::CS,VM::VM1,"Printer Status Info","PrinterStatusInfo",false }, {0x2110,0x0030,VR::LO,VM::VM1,"Printer Name","PrinterName",false }, {0x2110,0x0099,VR::SH,VM::VM1,"Print Queue ID","PrintQueueID",true }, {0x2120,0x0010,VR::CS,VM::VM1,"Queue Status","QueueStatus",true }, {0x2120,0x0050,VR::SQ,VM::VM1,"Print Job Description Sequence","PrintJobDescriptionSequence",true }, {0x2120,0x0070,VR::SQ,VM::VM1,"Referenced Print Job Sequence","ReferencedPrintJobSequence",true }, {0x2130,0x0010,VR::SQ,VM::VM1,"Print Management Capabilities Sequence","PrintManagementCapabilitiesSequence",true }, {0x2130,0x0015,VR::SQ,VM::VM1,"Printer Characteristics Sequence","PrinterCharacteristicsSequence",true }, {0x2130,0x0030,VR::SQ,VM::VM1,"Film Box Content Sequence","FilmBoxContentSequence",true }, {0x2130,0x0040,VR::SQ,VM::VM1,"Image Box Content Sequence","ImageBoxContentSequence",true }, {0x2130,0x0050,VR::SQ,VM::VM1,"Annotation Content Sequence","AnnotationContentSequence",true }, {0x2130,0x0060,VR::SQ,VM::VM1,"Image Overlay Box Content Sequence","ImageOverlayBoxContentSequence",true }, {0x2130,0x0080,VR::SQ,VM::VM1,"Presentation LUT Content Sequence","PresentationLUTContentSequence",true }, {0x2130,0x00a0,VR::SQ,VM::VM1,"Proposed Study Sequence","ProposedStudySequence",true }, {0x2130,0x00c0,VR::SQ,VM::VM1,"Original Image Sequence","OriginalImageSequence",true }, {0x2200,0x0001,VR::CS,VM::VM1,"Label Using Information Extracted From Instances","LabelUsingInformationExtractedFromInstances",false }, {0x2200,0x0002,VR::UT,VM::VM1,"Label Text","LabelText",false }, {0x2200,0x0003,VR::CS,VM::VM1,"Label Style Selection","LabelStyleSelection",false }, {0x2200,0x0004,VR::LT,VM::VM1,"Media Disposition","MediaDisposition",false }, {0x2200,0x0005,VR::LT,VM::VM1,"Barcode Value","BarcodeValue",false }, {0x2200,0x0006,VR::CS,VM::VM1,"Barcode Symbology","BarcodeSymbology",false }, {0x2200,0x0007,VR::CS,VM::VM1,"Allow Media Splitting","AllowMediaSplitting",false }, {0x2200,0x0008,VR::CS,VM::VM1,"Include Non-DICOM Objects","IncludeNonDICOMObjects",false }, {0x2200,0x0009,VR::CS,VM::VM1,"Include Display Application","IncludeDisplayApplication",false }, {0x2200,0x000a,VR::CS,VM::VM1,"Preserve Composite Instances After Media Creation","PreserveCompositeInstancesAfterMediaCreation",false }, {0x2200,0x000b,VR::US,VM::VM1,"Total Number of Pieces of Media Created","TotalNumberOfPiecesOfMediaCreated",false }, {0x2200,0x000c,VR::LO,VM::VM1,"Requested Media Application Profile","RequestedMediaApplicationProfile",false }, {0x2200,0x000d,VR::SQ,VM::VM1,"Referenced Storage Media Sequence","ReferencedStorageMediaSequence",false }, {0x2200,0x000e,VR::AT,VM::VM1_n,"Failure Attributes","FailureAttributes",false }, {0x2200,0x000f,VR::CS,VM::VM1,"Allow Lossy Compression","AllowLossyCompression",false }, {0x2200,0x0020,VR::CS,VM::VM1,"Request Priority","RequestPriority",false }, {0x3002,0x0002,VR::SH,VM::VM1,"RT Image Label","RTImageLabel",false }, {0x3002,0x0003,VR::LO,VM::VM1,"RT Image Name","RTImageName",false }, {0x3002,0x0004,VR::ST,VM::VM1,"RT Image Description","RTImageDescription",false }, {0x3002,0x000a,VR::CS,VM::VM1,"Reported Values Origin","ReportedValuesOrigin",false }, {0x3002,0x000c,VR::CS,VM::VM1,"RT Image Plane","RTImagePlane",false }, {0x3002,0x000d,VR::DS,VM::VM3,"X-Ray Image Receptor Translation","XRayImageReceptorTranslation",false }, {0x3002,0x000e,VR::DS,VM::VM1,"X-Ray Image Receptor Angle","XRayImageReceptorAngle",false }, {0x3002,0x0010,VR::DS,VM::VM6,"RT Image Orientation","RTImageOrientation",false }, {0x3002,0x0011,VR::DS,VM::VM2,"Image Plane Pixel Spacing","ImagePlanePixelSpacing",false }, {0x3002,0x0012,VR::DS,VM::VM2,"RT Image Position","RTImagePosition",false }, {0x3002,0x0020,VR::SH,VM::VM1,"Radiation Machine Name","RadiationMachineName",false }, {0x3002,0x0022,VR::DS,VM::VM1,"Radiation Machine SAD","RadiationMachineSAD",false }, {0x3002,0x0024,VR::DS,VM::VM1,"Radiation Machine SSD","RadiationMachineSSD",false }, {0x3002,0x0026,VR::DS,VM::VM1,"RT Image SID","RTImageSID",false }, {0x3002,0x0028,VR::DS,VM::VM1,"Source to Reference Object Distance","SourceToReferenceObjectDistance",false }, {0x3002,0x0029,VR::IS,VM::VM1,"Fraction Number","FractionNumber",false }, {0x3002,0x0030,VR::SQ,VM::VM1,"Exposure Sequence","ExposureSequence",false }, {0x3002,0x0032,VR::DS,VM::VM1,"Meterset Exposure","MetersetExposure",false }, {0x3002,0x0034,VR::DS,VM::VM4,"Diaphragm Position","DiaphragmPosition",false }, {0x3002,0x0040,VR::SQ,VM::VM1,"Fluence Map Sequence","FluenceMapSequence",false }, {0x3002,0x0041,VR::CS,VM::VM1,"Fluence Data Source","FluenceDataSource",false }, {0x3002,0x0042,VR::DS,VM::VM1,"Fluence Data Scale","FluenceDataScale",false }, {0x3002,0x0050,VR::SQ,VM::VM1,"Primary Fluence Mode Sequence","PrimaryFluenceModeSequence",false }, {0x3002,0x0051,VR::CS,VM::VM1,"Fluence Mode","FluenceMode",false }, {0x3002,0x0052,VR::SH,VM::VM1,"Fluence Mode ID","FluenceModeID",false }, {0x3004,0x0001,VR::CS,VM::VM1,"DVH Type","DVHType",false }, {0x3004,0x0002,VR::CS,VM::VM1,"Dose Units","DoseUnits",false }, {0x3004,0x0004,VR::CS,VM::VM1,"Dose Type","DoseType",false }, {0x3004,0x0005,VR::CS,VM::VM1,"Spatial Transform of Dose","SpatialTransformOfDose",false }, {0x3004,0x0006,VR::LO,VM::VM1,"Dose Comment","DoseComment",false }, {0x3004,0x0008,VR::DS,VM::VM3,"Normalization Point","NormalizationPoint",false }, {0x3004,0x000a,VR::CS,VM::VM1,"Dose Summation Type","DoseSummationType",false }, {0x3004,0x000c,VR::DS,VM::VM2_n,"Grid Frame Offset Vector","GridFrameOffsetVector",false }, {0x3004,0x000e,VR::DS,VM::VM1,"Dose Grid Scaling","DoseGridScaling",false }, {0x3004,0x0010,VR::SQ,VM::VM1,"RT Dose ROI Sequence","RTDoseROISequence",false }, {0x3004,0x0012,VR::DS,VM::VM1,"Dose Value","DoseValue",false }, {0x3004,0x0014,VR::CS,VM::VM1_3,"Tissue Heterogeneity Correction","TissueHeterogeneityCorrection",false }, {0x3004,0x0040,VR::DS,VM::VM3,"DVH Normalization Point","DVHNormalizationPoint",false }, {0x3004,0x0042,VR::DS,VM::VM1,"DVH Normalization Dose Value","DVHNormalizationDoseValue",false }, {0x3004,0x0050,VR::SQ,VM::VM1,"DVH Sequence","DVHSequence",false }, {0x3004,0x0052,VR::DS,VM::VM1,"DVH Dose Scaling","DVHDoseScaling",false }, {0x3004,0x0054,VR::CS,VM::VM1,"DVH Volume Units","DVHVolumeUnits",false }, {0x3004,0x0056,VR::IS,VM::VM1,"DVH Number of Bins","DVHNumberOfBins",false }, {0x3004,0x0058,VR::DS,VM::VM2_2n,"DVH Data","DVHData",false }, {0x3004,0x0060,VR::SQ,VM::VM1,"DVH Referenced ROI Sequence","DVHReferencedROISequence",false }, {0x3004,0x0062,VR::CS,VM::VM1,"DVH ROI Contribution Type","DVHROIContributionType",false }, {0x3004,0x0070,VR::DS,VM::VM1,"DVH Minimum Dose","DVHMinimumDose",false }, {0x3004,0x0072,VR::DS,VM::VM1,"DVH Maximum Dose","DVHMaximumDose",false }, {0x3004,0x0074,VR::DS,VM::VM1,"DVH Mean Dose","DVHMeanDose",false }, {0x3006,0x0002,VR::SH,VM::VM1,"Structure Set Label","StructureSetLabel",false }, {0x3006,0x0004,VR::LO,VM::VM1,"Structure Set Name","StructureSetName",false }, {0x3006,0x0006,VR::ST,VM::VM1,"Structure Set Description","StructureSetDescription",false }, {0x3006,0x0008,VR::DA,VM::VM1,"Structure Set Date","StructureSetDate",false }, {0x3006,0x0009,VR::TM,VM::VM1,"Structure Set Time","StructureSetTime",false }, {0x3006,0x0010,VR::SQ,VM::VM1,"Referenced Frame of Reference Sequence","ReferencedFrameOfReferenceSequence",false }, {0x3006,0x0012,VR::SQ,VM::VM1,"RT Referenced Study Sequence","RTReferencedStudySequence",false }, {0x3006,0x0014,VR::SQ,VM::VM1,"RT Referenced Series Sequence","RTReferencedSeriesSequence",false }, {0x3006,0x0016,VR::SQ,VM::VM1,"Contour Image Sequence","ContourImageSequence",false }, {0x3006,0x0018,VR::SQ,VM::VM1,"Predecessor Structure Set Sequence","PredecessorStructureSetSequence",false }, {0x3006,0x0020,VR::SQ,VM::VM1,"Structure Set ROI Sequence","StructureSetROISequence",false }, {0x3006,0x0022,VR::IS,VM::VM1,"ROI Number","ROINumber",false }, {0x3006,0x0024,VR::UI,VM::VM1,"Referenced Frame of Reference UID","ReferencedFrameOfReferenceUID",false }, {0x3006,0x0026,VR::LO,VM::VM1,"ROI Name","ROIName",false }, {0x3006,0x0028,VR::ST,VM::VM1,"ROI Description","ROIDescription",false }, {0x3006,0x002a,VR::IS,VM::VM3,"ROI Display Color","ROIDisplayColor",false }, {0x3006,0x002c,VR::DS,VM::VM1,"ROI Volume","ROIVolume",false }, {0x3006,0x0030,VR::SQ,VM::VM1,"RT Related ROI Sequence","RTRelatedROISequence",false }, {0x3006,0x0033,VR::CS,VM::VM1,"RT ROI Relationship","RTROIRelationship",false }, {0x3006,0x0036,VR::CS,VM::VM1,"ROI Generation Algorithm","ROIGenerationAlgorithm",false }, {0x3006,0x0038,VR::LO,VM::VM1,"ROI Generation Description","ROIGenerationDescription",false }, {0x3006,0x0039,VR::SQ,VM::VM1,"ROI Contour Sequence","ROIContourSequence",false }, {0x3006,0x0040,VR::SQ,VM::VM1,"Contour Sequence","ContourSequence",false }, {0x3006,0x0042,VR::CS,VM::VM1,"Contour Geometric Type","ContourGeometricType",false }, {0x3006,0x0044,VR::DS,VM::VM1,"Contour Slab Thickness","ContourSlabThickness",false }, {0x3006,0x0045,VR::DS,VM::VM3,"Contour Offset Vector","ContourOffsetVector",false }, {0x3006,0x0046,VR::IS,VM::VM1,"Number of Contour Points","NumberOfContourPoints",false }, {0x3006,0x0048,VR::IS,VM::VM1,"Contour Number","ContourNumber",false }, {0x3006,0x0049,VR::IS,VM::VM1_n,"Attached Contours","AttachedContours",false }, {0x3006,0x0050,VR::DS,VM::VM3_3n,"Contour Data","ContourData",false }, {0x3006,0x0080,VR::SQ,VM::VM1,"RT ROI Observations Sequence","RTROIObservationsSequence",false }, {0x3006,0x0082,VR::IS,VM::VM1,"Observation Number","ObservationNumber",false }, {0x3006,0x0084,VR::IS,VM::VM1,"Referenced ROI Number","ReferencedROINumber",false }, {0x3006,0x0085,VR::SH,VM::VM1,"ROI Observation Label","ROIObservationLabel",false }, {0x3006,0x0086,VR::SQ,VM::VM1,"RT ROI Identification Code Sequence","RTROIIdentificationCodeSequence",false }, {0x3006,0x0088,VR::ST,VM::VM1,"ROI Observation Description","ROIObservationDescription",false }, {0x3006,0x00a0,VR::SQ,VM::VM1,"Related RT ROI Observations Sequence","RelatedRTROIObservationsSequence",false }, {0x3006,0x00a4,VR::CS,VM::VM1,"RT ROI Interpreted Type","RTROIInterpretedType",false }, {0x3006,0x00a6,VR::PN,VM::VM1,"ROI Interpreter","ROIInterpreter",false }, {0x3006,0x00b0,VR::SQ,VM::VM1,"ROI Physical Properties Sequence","ROIPhysicalPropertiesSequence",false }, {0x3006,0x00b2,VR::CS,VM::VM1,"ROI Physical Property","ROIPhysicalProperty",false }, {0x3006,0x00b4,VR::DS,VM::VM1,"ROI Physical Property Value","ROIPhysicalPropertyValue",false }, {0x3006,0x00b6,VR::SQ,VM::VM1,"ROI Elemental Composition Sequence","ROIElementalCompositionSequence",false }, {0x3006,0x00b7,VR::US,VM::VM1,"ROI Elemental Composition Atomic Number","ROIElementalCompositionAtomicNumber",false }, {0x3006,0x00b8,VR::FL,VM::VM1,"ROI Elemental Composition Atomic Mass Fraction","ROIElementalCompositionAtomicMassFraction",false }, {0x3006,0x00b9,VR::SQ,VM::VM1,"Additional RT ROI Identification Code Sequence","AdditionalRTROIIdentificationCodeSequence",true }, {0x3006,0x00c0,VR::SQ,VM::VM1,"Frame of Reference Relationship Sequence","FrameOfReferenceRelationshipSequence",true }, {0x3006,0x00c2,VR::UI,VM::VM1,"Related Frame of Reference UID","RelatedFrameOfReferenceUID",true }, {0x3006,0x00c4,VR::CS,VM::VM1,"Frame of Reference Transformation Type","FrameOfReferenceTransformationType",true }, {0x3006,0x00c6,VR::DS,VM::VM16,"Frame of Reference Transformation Matrix","FrameOfReferenceTransformationMatrix",false }, {0x3006,0x00c8,VR::LO,VM::VM1,"Frame of Reference Transformation Comment","FrameOfReferenceTransformationComment",false }, {0x3008,0x0010,VR::SQ,VM::VM1,"Measured Dose Reference Sequence","MeasuredDoseReferenceSequence",false }, {0x3008,0x0012,VR::ST,VM::VM1,"Measured Dose Description","MeasuredDoseDescription",false }, {0x3008,0x0014,VR::CS,VM::VM1,"Measured Dose Type","MeasuredDoseType",false }, {0x3008,0x0016,VR::DS,VM::VM1,"Measured Dose Value","MeasuredDoseValue",false }, {0x3008,0x0020,VR::SQ,VM::VM1,"Treatment Session Beam Sequence","TreatmentSessionBeamSequence",false }, {0x3008,0x0021,VR::SQ,VM::VM1,"Treatment Session Ion Beam Sequence","TreatmentSessionIonBeamSequence",false }, {0x3008,0x0022,VR::IS,VM::VM1,"Current Fraction Number","CurrentFractionNumber",false }, {0x3008,0x0024,VR::DA,VM::VM1,"Treatment Control Point Date","TreatmentControlPointDate",false }, {0x3008,0x0025,VR::TM,VM::VM1,"Treatment Control Point Time","TreatmentControlPointTime",false }, {0x3008,0x002a,VR::CS,VM::VM1,"Treatment Termination Status","TreatmentTerminationStatus",false }, {0x3008,0x002b,VR::SH,VM::VM1,"Treatment Termination Code","TreatmentTerminationCode",false }, {0x3008,0x002c,VR::CS,VM::VM1,"Treatment Verification Status","TreatmentVerificationStatus",false }, {0x3008,0x0030,VR::SQ,VM::VM1,"Referenced Treatment Record Sequence","ReferencedTreatmentRecordSequence",false }, {0x3008,0x0032,VR::DS,VM::VM1,"Specified Primary Meterset","SpecifiedPrimaryMeterset",false }, {0x3008,0x0033,VR::DS,VM::VM1,"Specified Secondary Meterset","SpecifiedSecondaryMeterset",false }, {0x3008,0x0036,VR::DS,VM::VM1,"Delivered Primary Meterset","DeliveredPrimaryMeterset",false }, {0x3008,0x0037,VR::DS,VM::VM1,"Delivered Secondary Meterset","DeliveredSecondaryMeterset",false }, {0x3008,0x003a,VR::DS,VM::VM1,"Specified Treatment Time","SpecifiedTreatmentTime",false }, {0x3008,0x003b,VR::DS,VM::VM1,"Delivered Treatment Time","DeliveredTreatmentTime",false }, {0x3008,0x0040,VR::SQ,VM::VM1,"Control Point Delivery Sequence","ControlPointDeliverySequence",false }, {0x3008,0x0041,VR::SQ,VM::VM1,"Ion Control Point Delivery Sequence","IonControlPointDeliverySequence",false }, {0x3008,0x0042,VR::DS,VM::VM1,"Specified Meterset","SpecifiedMeterset",false }, {0x3008,0x0044,VR::DS,VM::VM1,"Delivered Meterset","DeliveredMeterset",false }, {0x3008,0x0045,VR::FL,VM::VM1,"Meterset Rate Set","MetersetRateSet",false }, {0x3008,0x0046,VR::FL,VM::VM1,"Meterset Rate Delivered","MetersetRateDelivered",false }, {0x3008,0x0047,VR::FL,VM::VM1_n,"Scan Spot Metersets Delivered","ScanSpotMetersetsDelivered",false }, {0x3008,0x0048,VR::DS,VM::VM1,"Dose Rate Delivered","DoseRateDelivered",false }, {0x3008,0x0050,VR::SQ,VM::VM1,"Treatment Summary Calculated Dose Reference Sequence","TreatmentSummaryCalculatedDoseReferenceSequence",false }, {0x3008,0x0052,VR::DS,VM::VM1,"Cumulative Dose to Dose Reference","CumulativeDoseToDoseReference",false }, {0x3008,0x0054,VR::DA,VM::VM1,"First Treatment Date","FirstTreatmentDate",false }, {0x3008,0x0056,VR::DA,VM::VM1,"Most Recent Treatment Date","MostRecentTreatmentDate",false }, {0x3008,0x005a,VR::IS,VM::VM1,"Number of Fractions Delivered","NumberOfFractionsDelivered",false }, {0x3008,0x0060,VR::SQ,VM::VM1,"Override Sequence","OverrideSequence",false }, {0x3008,0x0061,VR::AT,VM::VM1,"Parameter Sequence Pointer","ParameterSequencePointer",false }, {0x3008,0x0062,VR::AT,VM::VM1,"Override Parameter Pointer","OverrideParameterPointer",false }, {0x3008,0x0063,VR::IS,VM::VM1,"Parameter Item Index","ParameterItemIndex",false }, {0x3008,0x0064,VR::IS,VM::VM1,"Measured Dose Reference Number","MeasuredDoseReferenceNumber",false }, {0x3008,0x0065,VR::AT,VM::VM1,"Parameter Pointer","ParameterPointer",false }, {0x3008,0x0066,VR::ST,VM::VM1,"Override Reason","OverrideReason",false }, {0x3008,0x0067,VR::US,VM::VM1,"Parameter Value Number","ParameterValueNumber",false }, {0x3008,0x0068,VR::SQ,VM::VM1,"Corrected Parameter Sequence","CorrectedParameterSequence",false }, {0x3008,0x006a,VR::FL,VM::VM1,"Correction Value","CorrectionValue",false }, {0x3008,0x0070,VR::SQ,VM::VM1,"Calculated Dose Reference Sequence","CalculatedDoseReferenceSequence",false }, {0x3008,0x0072,VR::IS,VM::VM1,"Calculated Dose Reference Number","CalculatedDoseReferenceNumber",false }, {0x3008,0x0074,VR::ST,VM::VM1,"Calculated Dose Reference Description","CalculatedDoseReferenceDescription",false }, {0x3008,0x0076,VR::DS,VM::VM1,"Calculated Dose Reference Dose Value","CalculatedDoseReferenceDoseValue",false }, {0x3008,0x0078,VR::DS,VM::VM1,"Start Meterset","StartMeterset",false }, {0x3008,0x007a,VR::DS,VM::VM1,"End Meterset","EndMeterset",false }, {0x3008,0x0080,VR::SQ,VM::VM1,"Referenced Measured Dose Reference Sequence","ReferencedMeasuredDoseReferenceSequence",false }, {0x3008,0x0082,VR::IS,VM::VM1,"Referenced Measured Dose Reference Number","ReferencedMeasuredDoseReferenceNumber",false }, {0x3008,0x0090,VR::SQ,VM::VM1,"Referenced Calculated Dose Reference Sequence","ReferencedCalculatedDoseReferenceSequence",false }, {0x3008,0x0092,VR::IS,VM::VM1,"Referenced Calculated Dose Reference Number","ReferencedCalculatedDoseReferenceNumber",false }, {0x3008,0x00a0,VR::SQ,VM::VM1,"Beam Limiting Device Leaf Pairs Sequence","BeamLimitingDeviceLeafPairsSequence",false }, {0x3008,0x00b0,VR::SQ,VM::VM1,"Recorded Wedge Sequence","RecordedWedgeSequence",false }, {0x3008,0x00c0,VR::SQ,VM::VM1,"Recorded Compensator Sequence","RecordedCompensatorSequence",false }, {0x3008,0x00d0,VR::SQ,VM::VM1,"Recorded Block Sequence","RecordedBlockSequence",false }, {0x3008,0x00e0,VR::SQ,VM::VM1,"Treatment Summary Measured Dose Reference Sequence","TreatmentSummaryMeasuredDoseReferenceSequence",false }, {0x3008,0x00f0,VR::SQ,VM::VM1,"Recorded Snout Sequence","RecordedSnoutSequence",false }, {0x3008,0x00f2,VR::SQ,VM::VM1,"Recorded Range Shifter Sequence","RecordedRangeShifterSequence",false }, {0x3008,0x00f4,VR::SQ,VM::VM1,"Recorded Lateral Spreading Device Sequence","RecordedLateralSpreadingDeviceSequence",false }, {0x3008,0x00f6,VR::SQ,VM::VM1,"Recorded Range Modulator Sequence","RecordedRangeModulatorSequence",false }, {0x3008,0x0100,VR::SQ,VM::VM1,"Recorded Source Sequence","RecordedSourceSequence",false }, {0x3008,0x0105,VR::LO,VM::VM1,"Source Serial Number","SourceSerialNumber",false }, {0x3008,0x0110,VR::SQ,VM::VM1,"Treatment Session Application Setup Sequence","TreatmentSessionApplicationSetupSequence",false }, {0x3008,0x0116,VR::CS,VM::VM1,"Application Setup Check","ApplicationSetupCheck",false }, {0x3008,0x0120,VR::SQ,VM::VM1,"Recorded Brachy Accessory Device Sequence","RecordedBrachyAccessoryDeviceSequence",false }, {0x3008,0x0122,VR::IS,VM::VM1,"Referenced Brachy Accessory Device Number","ReferencedBrachyAccessoryDeviceNumber",false }, {0x3008,0x0130,VR::SQ,VM::VM1,"Recorded Channel Sequence","RecordedChannelSequence",false }, {0x3008,0x0132,VR::DS,VM::VM1,"Specified Channel Total Time","SpecifiedChannelTotalTime",false }, {0x3008,0x0134,VR::DS,VM::VM1,"Delivered Channel Total Time","DeliveredChannelTotalTime",false }, {0x3008,0x0136,VR::IS,VM::VM1,"Specified Number of Pulses","SpecifiedNumberOfPulses",false }, {0x3008,0x0138,VR::IS,VM::VM1,"Delivered Number of Pulses","DeliveredNumberOfPulses",false }, {0x3008,0x013a,VR::DS,VM::VM1,"Specified Pulse Repetition Interval","SpecifiedPulseRepetitionInterval",false }, {0x3008,0x013c,VR::DS,VM::VM1,"Delivered Pulse Repetition Interval","DeliveredPulseRepetitionInterval",false }, {0x3008,0x0140,VR::SQ,VM::VM1,"Recorded Source Applicator Sequence","RecordedSourceApplicatorSequence",false }, {0x3008,0x0142,VR::IS,VM::VM1,"Referenced Source Applicator Number","ReferencedSourceApplicatorNumber",false }, {0x3008,0x0150,VR::SQ,VM::VM1,"Recorded Channel Shield Sequence","RecordedChannelShieldSequence",false }, {0x3008,0x0152,VR::IS,VM::VM1,"Referenced Channel Shield Number","ReferencedChannelShieldNumber",false }, {0x3008,0x0160,VR::SQ,VM::VM1,"Brachy Control Point Delivered Sequence","BrachyControlPointDeliveredSequence",false }, {0x3008,0x0162,VR::DA,VM::VM1,"Safe Position Exit Date","SafePositionExitDate",false }, {0x3008,0x0164,VR::TM,VM::VM1,"Safe Position Exit Time","SafePositionExitTime",false }, {0x3008,0x0166,VR::DA,VM::VM1,"Safe Position Return Date","SafePositionReturnDate",false }, {0x3008,0x0168,VR::TM,VM::VM1,"Safe Position Return Time","SafePositionReturnTime",false }, {0x3008,0x0171,VR::SQ,VM::VM1,"Pulse Specific Brachy Control Point Delivered Sequence","PulseSpecificBrachyControlPointDeliveredSequence",false }, {0x3008,0x0172,VR::US,VM::VM1,"Pulse Number","PulseNumber",false }, {0x3008,0x0173,VR::SQ,VM::VM1,"Brachy Pulse Control Point Delivered Sequence","BrachyPulseControlPointDeliveredSequence",false }, {0x3008,0x0200,VR::CS,VM::VM1,"Current Treatment Status","CurrentTreatmentStatus",false }, {0x3008,0x0202,VR::ST,VM::VM1,"Treatment Status Comment","TreatmentStatusComment",false }, {0x3008,0x0220,VR::SQ,VM::VM1,"Fraction Group Summary Sequence","FractionGroupSummarySequence",false }, {0x3008,0x0223,VR::IS,VM::VM1,"Referenced Fraction Number","ReferencedFractionNumber",false }, {0x3008,0x0224,VR::CS,VM::VM1,"Fraction Group Type","FractionGroupType",false }, {0x3008,0x0230,VR::CS,VM::VM1,"Beam Stopper Position","BeamStopperPosition",false }, {0x3008,0x0240,VR::SQ,VM::VM1,"Fraction Status Summary Sequence","FractionStatusSummarySequence",false }, {0x3008,0x0250,VR::DA,VM::VM1,"Treatment Date","TreatmentDate",false }, {0x3008,0x0251,VR::TM,VM::VM1,"Treatment Time","TreatmentTime",false }, {0x300a,0x0002,VR::SH,VM::VM1,"RT Plan Label","RTPlanLabel",false }, {0x300a,0x0003,VR::LO,VM::VM1,"RT Plan Name","RTPlanName",false }, {0x300a,0x0004,VR::ST,VM::VM1,"RT Plan Description","RTPlanDescription",false }, {0x300a,0x0006,VR::DA,VM::VM1,"RT Plan Date","RTPlanDate",false }, {0x300a,0x0007,VR::TM,VM::VM1,"RT Plan Time","RTPlanTime",false }, {0x300a,0x0009,VR::LO,VM::VM1_n,"Treatment Protocols","TreatmentProtocols",false }, {0x300a,0x000a,VR::CS,VM::VM1,"Plan Intent","PlanIntent",false }, {0x300a,0x000b,VR::LO,VM::VM1_n,"Treatment Sites","TreatmentSites",false }, {0x300a,0x000c,VR::CS,VM::VM1,"RT Plan Geometry","RTPlanGeometry",false }, {0x300a,0x000e,VR::ST,VM::VM1,"Prescription Description","PrescriptionDescription",false }, {0x300a,0x0010,VR::SQ,VM::VM1,"Dose Reference Sequence","DoseReferenceSequence",false }, {0x300a,0x0012,VR::IS,VM::VM1,"Dose Reference Number","DoseReferenceNumber",false }, {0x300a,0x0013,VR::UI,VM::VM1,"Dose Reference UID","DoseReferenceUID",false }, {0x300a,0x0014,VR::CS,VM::VM1,"Dose Reference Structure Type","DoseReferenceStructureType",false }, {0x300a,0x0015,VR::CS,VM::VM1,"Nominal Beam Energy Unit","NominalBeamEnergyUnit",false }, {0x300a,0x0016,VR::LO,VM::VM1,"Dose Reference Description","DoseReferenceDescription",false }, {0x300a,0x0018,VR::DS,VM::VM3,"Dose Reference Point Coordinates","DoseReferencePointCoordinates",false }, {0x300a,0x001a,VR::DS,VM::VM1,"Nominal Prior Dose","NominalPriorDose",false }, {0x300a,0x0020,VR::CS,VM::VM1,"Dose Reference Type","DoseReferenceType",false }, {0x300a,0x0021,VR::DS,VM::VM1,"Constraint Weight","ConstraintWeight",false }, {0x300a,0x0022,VR::DS,VM::VM1,"Delivery Warning Dose","DeliveryWarningDose",false }, {0x300a,0x0023,VR::DS,VM::VM1,"Delivery Maximum Dose","DeliveryMaximumDose",false }, {0x300a,0x0025,VR::DS,VM::VM1,"Target Minimum Dose","TargetMinimumDose",false }, {0x300a,0x0026,VR::DS,VM::VM1,"Target Prescription Dose","TargetPrescriptionDose",false }, {0x300a,0x0027,VR::DS,VM::VM1,"Target Maximum Dose","TargetMaximumDose",false }, {0x300a,0x0028,VR::DS,VM::VM1,"Target Underdose Volume Fraction","TargetUnderdoseVolumeFraction",false }, {0x300a,0x002a,VR::DS,VM::VM1,"Organ at Risk Full-volume Dose","OrganAtRiskFullVolumeDose",false }, {0x300a,0x002b,VR::DS,VM::VM1,"Organ at Risk Limit Dose","OrganAtRiskLimitDose",false }, {0x300a,0x002c,VR::DS,VM::VM1,"Organ at Risk Maximum Dose","OrganAtRiskMaximumDose",false }, {0x300a,0x002d,VR::DS,VM::VM1,"Organ at Risk Overdose Volume Fraction","OrganAtRiskOverdoseVolumeFraction",false }, {0x300a,0x0040,VR::SQ,VM::VM1,"Tolerance Table Sequence","ToleranceTableSequence",false }, {0x300a,0x0042,VR::IS,VM::VM1,"Tolerance Table Number","ToleranceTableNumber",false }, {0x300a,0x0043,VR::SH,VM::VM1,"Tolerance Table Label","ToleranceTableLabel",false }, {0x300a,0x0044,VR::DS,VM::VM1,"Gantry Angle Tolerance","GantryAngleTolerance",false }, {0x300a,0x0046,VR::DS,VM::VM1,"Beam Limiting Device Angle Tolerance","BeamLimitingDeviceAngleTolerance",false }, {0x300a,0x0048,VR::SQ,VM::VM1,"Beam Limiting Device Tolerance Sequence","BeamLimitingDeviceToleranceSequence",false }, {0x300a,0x004a,VR::DS,VM::VM1,"Beam Limiting Device Position Tolerance","BeamLimitingDevicePositionTolerance",false }, {0x300a,0x004b,VR::FL,VM::VM1,"Snout Position Tolerance","SnoutPositionTolerance",false }, {0x300a,0x004c,VR::DS,VM::VM1,"Patient Support Angle Tolerance","PatientSupportAngleTolerance",false }, {0x300a,0x004e,VR::DS,VM::VM1,"Table Top Eccentric Angle Tolerance","TableTopEccentricAngleTolerance",false }, {0x300a,0x004f,VR::FL,VM::VM1,"Table Top Pitch Angle Tolerance","TableTopPitchAngleTolerance",false }, {0x300a,0x0050,VR::FL,VM::VM1,"Table Top Roll Angle Tolerance","TableTopRollAngleTolerance",false }, {0x300a,0x0051,VR::DS,VM::VM1,"Table Top Vertical Position Tolerance","TableTopVerticalPositionTolerance",false }, {0x300a,0x0052,VR::DS,VM::VM1,"Table Top Longitudinal Position Tolerance","TableTopLongitudinalPositionTolerance",false }, {0x300a,0x0053,VR::DS,VM::VM1,"Table Top Lateral Position Tolerance","TableTopLateralPositionTolerance",false }, {0x300a,0x0055,VR::CS,VM::VM1,"RT Plan Relationship","RTPlanRelationship",false }, {0x300a,0x0070,VR::SQ,VM::VM1,"Fraction Group Sequence","FractionGroupSequence",false }, {0x300a,0x0071,VR::IS,VM::VM1,"Fraction Group Number","FractionGroupNumber",false }, {0x300a,0x0072,VR::LO,VM::VM1,"Fraction Group Description","FractionGroupDescription",false }, {0x300a,0x0078,VR::IS,VM::VM1,"Number of Fractions Planned","NumberOfFractionsPlanned",false }, {0x300a,0x0079,VR::IS,VM::VM1,"Number of Fraction Pattern Digits Per Day","NumberOfFractionPatternDigitsPerDay",false }, {0x300a,0x007a,VR::IS,VM::VM1,"Repeat Fraction Cycle Length","RepeatFractionCycleLength",false }, {0x300a,0x007b,VR::LT,VM::VM1,"Fraction Pattern","FractionPattern",false }, {0x300a,0x0080,VR::IS,VM::VM1,"Number of Beams","NumberOfBeams",false }, {0x300a,0x0082,VR::DS,VM::VM3,"Beam Dose Specification Point","BeamDoseSpecificationPoint",false }, {0x300a,0x0084,VR::DS,VM::VM1,"Beam Dose","BeamDose",false }, {0x300a,0x0086,VR::DS,VM::VM1,"Beam Meterset","BeamMeterset",false }, {0x300a,0x0088,VR::FL,VM::VM1,"Beam Dose Point Depth","BeamDosePointDepth",true }, {0x300a,0x0089,VR::FL,VM::VM1,"Beam Dose Point Equivalent Depth","BeamDosePointEquivalentDepth",true }, {0x300a,0x008a,VR::FL,VM::VM1,"Beam Dose Point SSD","BeamDosePointSSD",true }, {0x300a,0x008b,VR::CS,VM::VM1,"Beam Dose Meaning","BeamDoseMeaning",false }, {0x300a,0x008c,VR::SQ,VM::VM1,"Beam Dose Verification Control Point Sequence","BeamDoseVerificationControlPointSequence",false }, {0x300a,0x008d,VR::FL,VM::VM1,"Average Beam Dose Point Depth","AverageBeamDosePointDepth",false }, {0x300a,0x008e,VR::FL,VM::VM1,"Average Beam Dose Point Equivalent Depth","AverageBeamDosePointEquivalentDepth",false }, {0x300a,0x008f,VR::FL,VM::VM1,"Average Beam Dose Point SSD","AverageBeamDosePointSSD",false }, {0x300a,0x0090,VR::CS,VM::VM1,"Beam Dose Type","BeamDoseType",false }, {0x300a,0x0091,VR::DS,VM::VM1,"Alternate Beam Dose","AlternateBeamDose",false }, {0x300a,0x0092,VR::CS,VM::VM1,"Alternate Beam Dose Type","AlternateBeamDoseType",false }, {0x300a,0x00a0,VR::IS,VM::VM1,"Number of Brachy Application Setups","NumberOfBrachyApplicationSetups",false }, {0x300a,0x00a2,VR::DS,VM::VM3,"Brachy Application Setup Dose Specification Point","BrachyApplicationSetupDoseSpecificationPoint",false }, {0x300a,0x00a4,VR::DS,VM::VM1,"Brachy Application Setup Dose","BrachyApplicationSetupDose",false }, {0x300a,0x00b0,VR::SQ,VM::VM1,"Beam Sequence","BeamSequence",false }, {0x300a,0x00b2,VR::SH,VM::VM1,"Treatment Machine Name","TreatmentMachineName",false }, {0x300a,0x00b3,VR::CS,VM::VM1,"Primary Dosimeter Unit","PrimaryDosimeterUnit",false }, {0x300a,0x00b4,VR::DS,VM::VM1,"Source-Axis Distance","SourceAxisDistance",false }, {0x300a,0x00b6,VR::SQ,VM::VM1,"Beam Limiting Device Sequence","BeamLimitingDeviceSequence",false }, {0x300a,0x00b8,VR::CS,VM::VM1,"RT Beam Limiting Device Type","RTBeamLimitingDeviceType",false }, {0x300a,0x00ba,VR::DS,VM::VM1,"Source to Beam Limiting Device Distance","SourceToBeamLimitingDeviceDistance",false }, {0x300a,0x00bb,VR::FL,VM::VM1,"Isocenter to Beam Limiting Device Distance","IsocenterToBeamLimitingDeviceDistance",false }, {0x300a,0x00bc,VR::IS,VM::VM1,"Number of Leaf/Jaw Pairs","NumberOfLeafJawPairs",false }, {0x300a,0x00be,VR::DS,VM::VM3_n,"Leaf Position Boundaries","LeafPositionBoundaries",false }, {0x300a,0x00c0,VR::IS,VM::VM1,"Beam Number","BeamNumber",false }, {0x300a,0x00c2,VR::LO,VM::VM1,"Beam Name","BeamName",false }, {0x300a,0x00c3,VR::ST,VM::VM1,"Beam Description","BeamDescription",false }, {0x300a,0x00c4,VR::CS,VM::VM1,"Beam Type","BeamType",false }, {0x300a,0x00c5,VR::FD,VM::VM1,"Beam Delivery Duration Limit","BeamDeliveryDurationLimit",false }, {0x300a,0x00c6,VR::CS,VM::VM1,"Radiation Type","RadiationType",false }, {0x300a,0x00c7,VR::CS,VM::VM1,"High-Dose Technique Type","HighDoseTechniqueType",false }, {0x300a,0x00c8,VR::IS,VM::VM1,"Reference Image Number","ReferenceImageNumber",false }, {0x300a,0x00ca,VR::SQ,VM::VM1,"Planned Verification Image Sequence","PlannedVerificationImageSequence",false }, {0x300a,0x00cc,VR::LO,VM::VM1_n,"Imaging Device-Specific Acquisition Parameters","ImagingDeviceSpecificAcquisitionParameters",false }, {0x300a,0x00ce,VR::CS,VM::VM1,"Treatment Delivery Type","TreatmentDeliveryType",false }, {0x300a,0x00d0,VR::IS,VM::VM1,"Number of Wedges","NumberOfWedges",false }, {0x300a,0x00d1,VR::SQ,VM::VM1,"Wedge Sequence","WedgeSequence",false }, {0x300a,0x00d2,VR::IS,VM::VM1,"Wedge Number","WedgeNumber",false }, {0x300a,0x00d3,VR::CS,VM::VM1,"Wedge Type","WedgeType",false }, {0x300a,0x00d4,VR::SH,VM::VM1,"Wedge ID","WedgeID",false }, {0x300a,0x00d5,VR::IS,VM::VM1,"Wedge Angle","WedgeAngle",false }, {0x300a,0x00d6,VR::DS,VM::VM1,"Wedge Factor","WedgeFactor",false }, {0x300a,0x00d7,VR::FL,VM::VM1,"Total Wedge Tray Water-Equivalent Thickness","TotalWedgeTrayWaterEquivalentThickness",false }, {0x300a,0x00d8,VR::DS,VM::VM1,"Wedge Orientation","WedgeOrientation",false }, {0x300a,0x00d9,VR::FL,VM::VM1,"Isocenter to Wedge Tray Distance","IsocenterToWedgeTrayDistance",false }, {0x300a,0x00da,VR::DS,VM::VM1,"Source to Wedge Tray Distance","SourceToWedgeTrayDistance",false }, {0x300a,0x00db,VR::FL,VM::VM1,"Wedge Thin Edge Position","WedgeThinEdgePosition",false }, {0x300a,0x00dc,VR::SH,VM::VM1,"Bolus ID","BolusID",false }, {0x300a,0x00dd,VR::ST,VM::VM1,"Bolus Description","BolusDescription",false }, {0x300a,0x00de,VR::DS,VM::VM1,"Effective Wedge Angle","EffectiveWedgeAngle",false }, {0x300a,0x00e0,VR::IS,VM::VM1,"Number of Compensators","NumberOfCompensators",false }, {0x300a,0x00e1,VR::SH,VM::VM1,"Material ID","MaterialID",false }, {0x300a,0x00e2,VR::DS,VM::VM1,"Total Compensator Tray Factor","TotalCompensatorTrayFactor",false }, {0x300a,0x00e3,VR::SQ,VM::VM1,"Compensator Sequence","CompensatorSequence",false }, {0x300a,0x00e4,VR::IS,VM::VM1,"Compensator Number","CompensatorNumber",false }, {0x300a,0x00e5,VR::SH,VM::VM1,"Compensator ID","CompensatorID",false }, {0x300a,0x00e6,VR::DS,VM::VM1,"Source to Compensator Tray Distance","SourceToCompensatorTrayDistance",false }, {0x300a,0x00e7,VR::IS,VM::VM1,"Compensator Rows","CompensatorRows",false }, {0x300a,0x00e8,VR::IS,VM::VM1,"Compensator Columns","CompensatorColumns",false }, {0x300a,0x00e9,VR::DS,VM::VM2,"Compensator Pixel Spacing","CompensatorPixelSpacing",false }, {0x300a,0x00ea,VR::DS,VM::VM2,"Compensator Position","CompensatorPosition",false }, {0x300a,0x00eb,VR::DS,VM::VM1_n,"Compensator Transmission Data","CompensatorTransmissionData",false }, {0x300a,0x00ec,VR::DS,VM::VM1_n,"Compensator Thickness Data","CompensatorThicknessData",false }, {0x300a,0x00ed,VR::IS,VM::VM1,"Number of Boli","NumberOfBoli",false }, {0x300a,0x00ee,VR::CS,VM::VM1,"Compensator Type","CompensatorType",false }, {0x300a,0x00ef,VR::SH,VM::VM1,"Compensator Tray ID","CompensatorTrayID",false }, {0x300a,0x00f0,VR::IS,VM::VM1,"Number of Blocks","NumberOfBlocks",false }, {0x300a,0x00f2,VR::DS,VM::VM1,"Total Block Tray Factor","TotalBlockTrayFactor",false }, {0x300a,0x00f3,VR::FL,VM::VM1,"Total Block Tray Water-Equivalent Thickness","TotalBlockTrayWaterEquivalentThickness",false }, {0x300a,0x00f4,VR::SQ,VM::VM1,"Block Sequence","BlockSequence",false }, {0x300a,0x00f5,VR::SH,VM::VM1,"Block Tray ID","BlockTrayID",false }, {0x300a,0x00f6,VR::DS,VM::VM1,"Source to Block Tray Distance","SourceToBlockTrayDistance",false }, {0x300a,0x00f7,VR::FL,VM::VM1,"Isocenter to Block Tray Distance","IsocenterToBlockTrayDistance",false }, {0x300a,0x00f8,VR::CS,VM::VM1,"Block Type","BlockType",false }, {0x300a,0x00f9,VR::LO,VM::VM1,"Accessory Code","AccessoryCode",false }, {0x300a,0x00fa,VR::CS,VM::VM1,"Block Divergence","BlockDivergence",false }, {0x300a,0x00fb,VR::CS,VM::VM1,"Block Mounting Position","BlockMountingPosition",false }, {0x300a,0x00fc,VR::IS,VM::VM1,"Block Number","BlockNumber",false }, {0x300a,0x00fe,VR::LO,VM::VM1,"Block Name","BlockName",false }, {0x300a,0x0100,VR::DS,VM::VM1,"Block Thickness","BlockThickness",false }, {0x300a,0x0102,VR::DS,VM::VM1,"Block Transmission","BlockTransmission",false }, {0x300a,0x0104,VR::IS,VM::VM1,"Block Number of Points","BlockNumberOfPoints",false }, {0x300a,0x0106,VR::DS,VM::VM2_2n,"Block Data","BlockData",false }, {0x300a,0x0107,VR::SQ,VM::VM1,"Applicator Sequence","ApplicatorSequence",false }, {0x300a,0x0108,VR::SH,VM::VM1,"Applicator ID","ApplicatorID",false }, {0x300a,0x0109,VR::CS,VM::VM1,"Applicator Type","ApplicatorType",false }, {0x300a,0x010a,VR::LO,VM::VM1,"Applicator Description","ApplicatorDescription",false }, {0x300a,0x010c,VR::DS,VM::VM1,"Cumulative Dose Reference Coefficient","CumulativeDoseReferenceCoefficient",false }, {0x300a,0x010e,VR::DS,VM::VM1,"Final Cumulative Meterset Weight","FinalCumulativeMetersetWeight",false }, {0x300a,0x0110,VR::IS,VM::VM1,"Number of Control Points","NumberOfControlPoints",false }, {0x300a,0x0111,VR::SQ,VM::VM1,"Control Point Sequence","ControlPointSequence",false }, {0x300a,0x0112,VR::IS,VM::VM1,"Control Point Index","ControlPointIndex",false }, {0x300a,0x0114,VR::DS,VM::VM1,"Nominal Beam Energy","NominalBeamEnergy",false }, {0x300a,0x0115,VR::DS,VM::VM1,"Dose Rate Set","DoseRateSet",false }, {0x300a,0x0116,VR::SQ,VM::VM1,"Wedge Position Sequence","WedgePositionSequence",false }, {0x300a,0x0118,VR::CS,VM::VM1,"Wedge Position","WedgePosition",false }, {0x300a,0x011a,VR::SQ,VM::VM1,"Beam Limiting Device Position Sequence","BeamLimitingDevicePositionSequence",false }, {0x300a,0x011c,VR::DS,VM::VM2_2n,"Leaf/Jaw Positions","LeafJawPositions",false }, {0x300a,0x011e,VR::DS,VM::VM1,"Gantry Angle","GantryAngle",false }, {0x300a,0x011f,VR::CS,VM::VM1,"Gantry Rotation Direction","GantryRotationDirection",false }, {0x300a,0x0120,VR::DS,VM::VM1,"Beam Limiting Device Angle","BeamLimitingDeviceAngle",false }, {0x300a,0x0121,VR::CS,VM::VM1,"Beam Limiting Device Rotation Direction","BeamLimitingDeviceRotationDirection",false }, {0x300a,0x0122,VR::DS,VM::VM1,"Patient Support Angle","PatientSupportAngle",false }, {0x300a,0x0123,VR::CS,VM::VM1,"Patient Support Rotation Direction","PatientSupportRotationDirection",false }, {0x300a,0x0124,VR::DS,VM::VM1,"Table Top Eccentric Axis Distance","TableTopEccentricAxisDistance",false }, {0x300a,0x0125,VR::DS,VM::VM1,"Table Top Eccentric Angle","TableTopEccentricAngle",false }, {0x300a,0x0126,VR::CS,VM::VM1,"Table Top Eccentric Rotation Direction","TableTopEccentricRotationDirection",false }, {0x300a,0x0128,VR::DS,VM::VM1,"Table Top Vertical Position","TableTopVerticalPosition",false }, {0x300a,0x0129,VR::DS,VM::VM1,"Table Top Longitudinal Position","TableTopLongitudinalPosition",false }, {0x300a,0x012a,VR::DS,VM::VM1,"Table Top Lateral Position","TableTopLateralPosition",false }, {0x300a,0x012c,VR::DS,VM::VM3,"Isocenter Position","IsocenterPosition",false }, {0x300a,0x012e,VR::DS,VM::VM3,"Surface Entry Point","SurfaceEntryPoint",false }, {0x300a,0x0130,VR::DS,VM::VM1,"Source to Surface Distance","SourceToSurfaceDistance",false }, {0x300a,0x0131,VR::FL,VM::VM1,"Average Beam Dose Point Source to External Contour Distance","AverageBeamDosePointSourceToExternalContourDistance",false }, {0x300a,0x0132,VR::FL,VM::VM1,"Source to External Contour Distance","SourceToExternalContourDistance",false }, {0x300a,0x0133,VR::FL,VM::VM3,"External Contour Entry Point","ExternalContourEntryPoint",false }, {0x300a,0x0134,VR::DS,VM::VM1,"Cumulative Meterset Weight","CumulativeMetersetWeight",false }, {0x300a,0x0140,VR::FL,VM::VM1,"Table Top Pitch Angle","TableTopPitchAngle",false }, {0x300a,0x0142,VR::CS,VM::VM1,"Table Top Pitch Rotation Direction","TableTopPitchRotationDirection",false }, {0x300a,0x0144,VR::FL,VM::VM1,"Table Top Roll Angle","TableTopRollAngle",false }, {0x300a,0x0146,VR::CS,VM::VM1,"Table Top Roll Rotation Direction","TableTopRollRotationDirection",false }, {0x300a,0x0148,VR::FL,VM::VM1,"Head Fixation Angle","HeadFixationAngle",false }, {0x300a,0x014a,VR::FL,VM::VM1,"Gantry Pitch Angle","GantryPitchAngle",false }, {0x300a,0x014c,VR::CS,VM::VM1,"Gantry Pitch Rotation Direction","GantryPitchRotationDirection",false }, {0x300a,0x014e,VR::FL,VM::VM1,"Gantry Pitch Angle Tolerance","GantryPitchAngleTolerance",false }, {0x300a,0x0150,VR::CS,VM::VM1,"Fixation Eye","FixationEye",false }, {0x300a,0x0151,VR::DS,VM::VM1,"Chair Head Frame Position","ChairHeadFramePosition",false }, {0x300a,0x0152,VR::DS,VM::VM1,"Head Fixation Angle Tolerance","HeadFixationAngleTolerance",false }, {0x300a,0x0153,VR::DS,VM::VM1,"Chair Head Frame Position Tolerance","ChairHeadFramePositionTolerance",false }, {0x300a,0x0154,VR::DS,VM::VM1,"Fixation Light Azimuthal Angle Tolerance","FixationLightAzimuthalAngleTolerance",false }, {0x300a,0x0155,VR::DS,VM::VM1,"Fixation Light Polar Angle Tolerance","FixationLightPolarAngleTolerance",false }, {0x300a,0x0180,VR::SQ,VM::VM1,"Patient Setup Sequence","PatientSetupSequence",false }, {0x300a,0x0182,VR::IS,VM::VM1,"Patient Setup Number","PatientSetupNumber",false }, {0x300a,0x0183,VR::LO,VM::VM1,"Patient Setup Label","PatientSetupLabel",false }, {0x300a,0x0184,VR::LO,VM::VM1,"Patient Additional Position","PatientAdditionalPosition",false }, {0x300a,0x0190,VR::SQ,VM::VM1,"Fixation Device Sequence","FixationDeviceSequence",false }, {0x300a,0x0192,VR::CS,VM::VM1,"Fixation Device Type","FixationDeviceType",false }, {0x300a,0x0194,VR::SH,VM::VM1,"Fixation Device Label","FixationDeviceLabel",false }, {0x300a,0x0196,VR::ST,VM::VM1,"Fixation Device Description","FixationDeviceDescription",false }, {0x300a,0x0198,VR::SH,VM::VM1,"Fixation Device Position","FixationDevicePosition",false }, {0x300a,0x0199,VR::FL,VM::VM1,"Fixation Device Pitch Angle","FixationDevicePitchAngle",false }, {0x300a,0x019a,VR::FL,VM::VM1,"Fixation Device Roll Angle","FixationDeviceRollAngle",false }, {0x300a,0x01a0,VR::SQ,VM::VM1,"Shielding Device Sequence","ShieldingDeviceSequence",false }, {0x300a,0x01a2,VR::CS,VM::VM1,"Shielding Device Type","ShieldingDeviceType",false }, {0x300a,0x01a4,VR::SH,VM::VM1,"Shielding Device Label","ShieldingDeviceLabel",false }, {0x300a,0x01a6,VR::ST,VM::VM1,"Shielding Device Description","ShieldingDeviceDescription",false }, {0x300a,0x01a8,VR::SH,VM::VM1,"Shielding Device Position","ShieldingDevicePosition",false }, {0x300a,0x01b0,VR::CS,VM::VM1,"Setup Technique","SetupTechnique",false }, {0x300a,0x01b2,VR::ST,VM::VM1,"Setup Technique Description","SetupTechniqueDescription",false }, {0x300a,0x01b4,VR::SQ,VM::VM1,"Setup Device Sequence","SetupDeviceSequence",false }, {0x300a,0x01b6,VR::CS,VM::VM1,"Setup Device Type","SetupDeviceType",false }, {0x300a,0x01b8,VR::SH,VM::VM1,"Setup Device Label","SetupDeviceLabel",false }, {0x300a,0x01ba,VR::ST,VM::VM1,"Setup Device Description","SetupDeviceDescription",false }, {0x300a,0x01bc,VR::DS,VM::VM1,"Setup Device Parameter","SetupDeviceParameter",false }, {0x300a,0x01d0,VR::ST,VM::VM1,"Setup Reference Description","SetupReferenceDescription",false }, {0x300a,0x01d2,VR::DS,VM::VM1,"Table Top Vertical Setup Displacement","TableTopVerticalSetupDisplacement",false }, {0x300a,0x01d4,VR::DS,VM::VM1,"Table Top Longitudinal Setup Displacement","TableTopLongitudinalSetupDisplacement",false }, {0x300a,0x01d6,VR::DS,VM::VM1,"Table Top Lateral Setup Displacement","TableTopLateralSetupDisplacement",false }, {0x300a,0x0200,VR::CS,VM::VM1,"Brachy Treatment Technique","BrachyTreatmentTechnique",false }, {0x300a,0x0202,VR::CS,VM::VM1,"Brachy Treatment Type","BrachyTreatmentType",false }, {0x300a,0x0206,VR::SQ,VM::VM1,"Treatment Machine Sequence","TreatmentMachineSequence",false }, {0x300a,0x0210,VR::SQ,VM::VM1,"Source Sequence","SourceSequence",false }, {0x300a,0x0212,VR::IS,VM::VM1,"Source Number","SourceNumber",false }, {0x300a,0x0214,VR::CS,VM::VM1,"Source Type","SourceType",false }, {0x300a,0x0216,VR::LO,VM::VM1,"Source Manufacturer","SourceManufacturer",false }, {0x300a,0x0218,VR::DS,VM::VM1,"Active Source Diameter","ActiveSourceDiameter",false }, {0x300a,0x021a,VR::DS,VM::VM1,"Active Source Length","ActiveSourceLength",false }, {0x300a,0x021b,VR::SH,VM::VM1,"Source Model ID","SourceModelID",false }, {0x300a,0x021c,VR::LO,VM::VM1,"Source Description","SourceDescription",false }, {0x300a,0x0222,VR::DS,VM::VM1,"Source Encapsulation Nominal Thickness","SourceEncapsulationNominalThickness",false }, {0x300a,0x0224,VR::DS,VM::VM1,"Source Encapsulation Nominal Transmission","SourceEncapsulationNominalTransmission",false }, {0x300a,0x0226,VR::LO,VM::VM1,"Source Isotope Name","SourceIsotopeName",false }, {0x300a,0x0228,VR::DS,VM::VM1,"Source Isotope Half Life","SourceIsotopeHalfLife",false }, {0x300a,0x0229,VR::CS,VM::VM1,"Source Strength Units","SourceStrengthUnits",false }, {0x300a,0x022a,VR::DS,VM::VM1,"Reference Air Kerma Rate","ReferenceAirKermaRate",false }, {0x300a,0x022b,VR::DS,VM::VM1,"Source Strength","SourceStrength",false }, {0x300a,0x022c,VR::DA,VM::VM1,"Source Strength Reference Date","SourceStrengthReferenceDate",false }, {0x300a,0x022e,VR::TM,VM::VM1,"Source Strength Reference Time","SourceStrengthReferenceTime",false }, {0x300a,0x0230,VR::SQ,VM::VM1,"Application Setup Sequence","ApplicationSetupSequence",false }, {0x300a,0x0232,VR::CS,VM::VM1,"Application Setup Type","ApplicationSetupType",false }, {0x300a,0x0234,VR::IS,VM::VM1,"Application Setup Number","ApplicationSetupNumber",false }, {0x300a,0x0236,VR::LO,VM::VM1,"Application Setup Name","ApplicationSetupName",false }, {0x300a,0x0238,VR::LO,VM::VM1,"Application Setup Manufacturer","ApplicationSetupManufacturer",false }, {0x300a,0x0240,VR::IS,VM::VM1,"Template Number","TemplateNumber",false }, {0x300a,0x0242,VR::SH,VM::VM1,"Template Type","TemplateType",false }, {0x300a,0x0244,VR::LO,VM::VM1,"Template Name","TemplateName",false }, {0x300a,0x0250,VR::DS,VM::VM1,"Total Reference Air Kerma","TotalReferenceAirKerma",false }, {0x300a,0x0260,VR::SQ,VM::VM1,"Brachy Accessory Device Sequence","BrachyAccessoryDeviceSequence",false }, {0x300a,0x0262,VR::IS,VM::VM1,"Brachy Accessory Device Number","BrachyAccessoryDeviceNumber",false }, {0x300a,0x0263,VR::SH,VM::VM1,"Brachy Accessory Device ID","BrachyAccessoryDeviceID",false }, {0x300a,0x0264,VR::CS,VM::VM1,"Brachy Accessory Device Type","BrachyAccessoryDeviceType",false }, {0x300a,0x0266,VR::LO,VM::VM1,"Brachy Accessory Device Name","BrachyAccessoryDeviceName",false }, {0x300a,0x026a,VR::DS,VM::VM1,"Brachy Accessory Device Nominal Thickness","BrachyAccessoryDeviceNominalThickness",false }, {0x300a,0x026c,VR::DS,VM::VM1,"Brachy Accessory Device Nominal Transmission","BrachyAccessoryDeviceNominalTransmission",false }, {0x300a,0x0280,VR::SQ,VM::VM1,"Channel Sequence","ChannelSequence",false }, {0x300a,0x0282,VR::IS,VM::VM1,"Channel Number","ChannelNumber",false }, {0x300a,0x0284,VR::DS,VM::VM1,"Channel Length","ChannelLength",false }, {0x300a,0x0286,VR::DS,VM::VM1,"Channel Total Time","ChannelTotalTime",false }, {0x300a,0x0288,VR::CS,VM::VM1,"Source Movement Type","SourceMovementType",false }, {0x300a,0x028a,VR::IS,VM::VM1,"Number of Pulses","NumberOfPulses",false }, {0x300a,0x028c,VR::DS,VM::VM1,"Pulse Repetition Interval","PulseRepetitionInterval",false }, {0x300a,0x0290,VR::IS,VM::VM1,"Source Applicator Number","SourceApplicatorNumber",false }, {0x300a,0x0291,VR::SH,VM::VM1,"Source Applicator ID","SourceApplicatorID",false }, {0x300a,0x0292,VR::CS,VM::VM1,"Source Applicator Type","SourceApplicatorType",false }, {0x300a,0x0294,VR::LO,VM::VM1,"Source Applicator Name","SourceApplicatorName",false }, {0x300a,0x0296,VR::DS,VM::VM1,"Source Applicator Length","SourceApplicatorLength",false }, {0x300a,0x0298,VR::LO,VM::VM1,"Source Applicator Manufacturer","SourceApplicatorManufacturer",false }, {0x300a,0x029c,VR::DS,VM::VM1,"Source Applicator Wall Nominal Thickness","SourceApplicatorWallNominalThickness",false }, {0x300a,0x029e,VR::DS,VM::VM1,"Source Applicator Wall Nominal Transmission","SourceApplicatorWallNominalTransmission",false }, {0x300a,0x02a0,VR::DS,VM::VM1,"Source Applicator Step Size","SourceApplicatorStepSize",false }, {0x300a,0x02a2,VR::IS,VM::VM1,"Transfer Tube Number","TransferTubeNumber",false }, {0x300a,0x02a4,VR::DS,VM::VM1,"Transfer Tube Length","TransferTubeLength",false }, {0x300a,0x02b0,VR::SQ,VM::VM1,"Channel Shield Sequence","ChannelShieldSequence",false }, {0x300a,0x02b2,VR::IS,VM::VM1,"Channel Shield Number","ChannelShieldNumber",false }, {0x300a,0x02b3,VR::SH,VM::VM1,"Channel Shield ID","ChannelShieldID",false }, {0x300a,0x02b4,VR::LO,VM::VM1,"Channel Shield Name","ChannelShieldName",false }, {0x300a,0x02b8,VR::DS,VM::VM1,"Channel Shield Nominal Thickness","ChannelShieldNominalThickness",false }, {0x300a,0x02ba,VR::DS,VM::VM1,"Channel Shield Nominal Transmission","ChannelShieldNominalTransmission",false }, {0x300a,0x02c8,VR::DS,VM::VM1,"Final Cumulative Time Weight","FinalCumulativeTimeWeight",false }, {0x300a,0x02d0,VR::SQ,VM::VM1,"Brachy Control Point Sequence","BrachyControlPointSequence",false }, {0x300a,0x02d2,VR::DS,VM::VM1,"Control Point Relative Position","ControlPointRelativePosition",false }, {0x300a,0x02d4,VR::DS,VM::VM3,"Control Point 3D Position","ControlPoint3DPosition",false }, {0x300a,0x02d6,VR::DS,VM::VM1,"Cumulative Time Weight","CumulativeTimeWeight",false }, {0x300a,0x02e0,VR::CS,VM::VM1,"Compensator Divergence","CompensatorDivergence",false }, {0x300a,0x02e1,VR::CS,VM::VM1,"Compensator Mounting Position","CompensatorMountingPosition",false }, {0x300a,0x02e2,VR::DS,VM::VM1_n,"Source to Compensator Distance","SourceToCompensatorDistance",false }, {0x300a,0x02e3,VR::FL,VM::VM1,"Total Compensator Tray Water-Equivalent Thickness","TotalCompensatorTrayWaterEquivalentThickness",false }, {0x300a,0x02e4,VR::FL,VM::VM1,"Isocenter to Compensator Tray Distance","IsocenterToCompensatorTrayDistance",false }, {0x300a,0x02e5,VR::FL,VM::VM1,"Compensator Column Offset","CompensatorColumnOffset",false }, {0x300a,0x02e6,VR::FL,VM::VM1_n,"Isocenter to Compensator Distances","IsocenterToCompensatorDistances",false }, {0x300a,0x02e7,VR::FL,VM::VM1,"Compensator Relative Stopping Power Ratio","CompensatorRelativeStoppingPowerRatio",false }, {0x300a,0x02e8,VR::FL,VM::VM1,"Compensator Milling Tool Diameter","CompensatorMillingToolDiameter",false }, {0x300a,0x02ea,VR::SQ,VM::VM1,"Ion Range Compensator Sequence","IonRangeCompensatorSequence",false }, {0x300a,0x02eb,VR::LT,VM::VM1,"Compensator Description","CompensatorDescription",false }, {0x300a,0x0302,VR::IS,VM::VM1,"Radiation Mass Number","RadiationMassNumber",false }, {0x300a,0x0304,VR::IS,VM::VM1,"Radiation Atomic Number","RadiationAtomicNumber",false }, {0x300a,0x0306,VR::SS,VM::VM1,"Radiation Charge State","RadiationChargeState",false }, {0x300a,0x0308,VR::CS,VM::VM1,"Scan Mode","ScanMode",false }, {0x300a,0x0309,VR::CS,VM::VM1,"Modulated Scan Mode Type","ModulatedScanModeType",false }, {0x300a,0x030a,VR::FL,VM::VM2,"Virtual Source-Axis Distances","VirtualSourceAxisDistances",false }, {0x300a,0x030c,VR::SQ,VM::VM1,"Snout Sequence","SnoutSequence",false }, {0x300a,0x030d,VR::FL,VM::VM1,"Snout Position","SnoutPosition",false }, {0x300a,0x030f,VR::SH,VM::VM1,"Snout ID","SnoutID",false }, {0x300a,0x0312,VR::IS,VM::VM1,"Number of Range Shifters","NumberOfRangeShifters",false }, {0x300a,0x0314,VR::SQ,VM::VM1,"Range Shifter Sequence","RangeShifterSequence",false }, {0x300a,0x0316,VR::IS,VM::VM1,"Range Shifter Number","RangeShifterNumber",false }, {0x300a,0x0318,VR::SH,VM::VM1,"Range Shifter ID","RangeShifterID",false }, {0x300a,0x0320,VR::CS,VM::VM1,"Range Shifter Type","RangeShifterType",false }, {0x300a,0x0322,VR::LO,VM::VM1,"Range Shifter Description","RangeShifterDescription",false }, {0x300a,0x0330,VR::IS,VM::VM1,"Number of Lateral Spreading Devices","NumberOfLateralSpreadingDevices",false }, {0x300a,0x0332,VR::SQ,VM::VM1,"Lateral Spreading Device Sequence","LateralSpreadingDeviceSequence",false }, {0x300a,0x0334,VR::IS,VM::VM1,"Lateral Spreading Device Number","LateralSpreadingDeviceNumber",false }, {0x300a,0x0336,VR::SH,VM::VM1,"Lateral Spreading Device ID","LateralSpreadingDeviceID",false }, {0x300a,0x0338,VR::CS,VM::VM1,"Lateral Spreading Device Type","LateralSpreadingDeviceType",false }, {0x300a,0x033a,VR::LO,VM::VM1,"Lateral Spreading Device Description","LateralSpreadingDeviceDescription",false }, {0x300a,0x033c,VR::FL,VM::VM1,"Lateral Spreading Device Water Equivalent Thickness","LateralSpreadingDeviceWaterEquivalentThickness",false }, {0x300a,0x0340,VR::IS,VM::VM1,"Number of Range Modulators","NumberOfRangeModulators",false }, {0x300a,0x0342,VR::SQ,VM::VM1,"Range Modulator Sequence","RangeModulatorSequence",false }, {0x300a,0x0344,VR::IS,VM::VM1,"Range Modulator Number","RangeModulatorNumber",false }, {0x300a,0x0346,VR::SH,VM::VM1,"Range Modulator ID","RangeModulatorID",false }, {0x300a,0x0348,VR::CS,VM::VM1,"Range Modulator Type","RangeModulatorType",false }, {0x300a,0x034a,VR::LO,VM::VM1,"Range Modulator Description","RangeModulatorDescription",false }, {0x300a,0x034c,VR::SH,VM::VM1,"Beam Current Modulation ID","BeamCurrentModulationID",false }, {0x300a,0x0350,VR::CS,VM::VM1,"Patient Support Type","PatientSupportType",false }, {0x300a,0x0352,VR::SH,VM::VM1,"Patient Support ID","PatientSupportID",false }, {0x300a,0x0354,VR::LO,VM::VM1,"Patient Support Accessory Code","PatientSupportAccessoryCode",false }, {0x300a,0x0355,VR::LO,VM::VM1,"Tray Accessory Code","TrayAccessoryCode",false }, {0x300a,0x0356,VR::FL,VM::VM1,"Fixation Light Azimuthal Angle","FixationLightAzimuthalAngle",false }, {0x300a,0x0358,VR::FL,VM::VM1,"Fixation Light Polar Angle","FixationLightPolarAngle",false }, {0x300a,0x035a,VR::FL,VM::VM1,"Meterset Rate","MetersetRate",false }, {0x300a,0x0360,VR::SQ,VM::VM1,"Range Shifter Settings Sequence","RangeShifterSettingsSequence",false }, {0x300a,0x0362,VR::LO,VM::VM1,"Range Shifter Setting","RangeShifterSetting",false }, {0x300a,0x0364,VR::FL,VM::VM1,"Isocenter to Range Shifter Distance","IsocenterToRangeShifterDistance",false }, {0x300a,0x0366,VR::FL,VM::VM1,"Range Shifter Water Equivalent Thickness","RangeShifterWaterEquivalentThickness",false }, {0x300a,0x0370,VR::SQ,VM::VM1,"Lateral Spreading Device Settings Sequence","LateralSpreadingDeviceSettingsSequence",false }, {0x300a,0x0372,VR::LO,VM::VM1,"Lateral Spreading Device Setting","LateralSpreadingDeviceSetting",false }, {0x300a,0x0374,VR::FL,VM::VM1,"Isocenter to Lateral Spreading Device Distance","IsocenterToLateralSpreadingDeviceDistance",false }, {0x300a,0x0380,VR::SQ,VM::VM1,"Range Modulator Settings Sequence","RangeModulatorSettingsSequence",false }, {0x300a,0x0382,VR::FL,VM::VM1,"Range Modulator Gating Start Value","RangeModulatorGatingStartValue",false }, {0x300a,0x0384,VR::FL,VM::VM1,"Range Modulator Gating Stop Value","RangeModulatorGatingStopValue",false }, {0x300a,0x0386,VR::FL,VM::VM1,"Range Modulator Gating Start Water Equivalent Thickness","RangeModulatorGatingStartWaterEquivalentThickness",false }, {0x300a,0x0388,VR::FL,VM::VM1,"Range Modulator Gating Stop Water Equivalent Thickness","RangeModulatorGatingStopWaterEquivalentThickness",false }, {0x300a,0x038a,VR::FL,VM::VM1,"Isocenter to Range Modulator Distance","IsocenterToRangeModulatorDistance",false }, {0x300a,0x038f,VR::FL,VM::VM1_n,"Scan Spot Time Offset","ScanSpotTimeOffset",false }, {0x300a,0x0390,VR::SH,VM::VM1,"Scan Spot Tune ID","ScanSpotTuneID",false }, {0x300a,0x0391,VR::IS,VM::VM1_n,"Scan Spot Prescribed Indices","ScanSpotPrescribedIndices",false }, {0x300a,0x0392,VR::IS,VM::VM1,"Number of Scan Spot Positions","NumberOfScanSpotPositions",false }, {0x300a,0x0393,VR::CS,VM::VM1,"Scan Spot Reordered","ScanSpotReordered",false }, {0x300a,0x0394,VR::FL,VM::VM1_n,"Scan Spot Position Map","ScanSpotPositionMap",false }, {0x300a,0x0395,VR::CS,VM::VM1,"Scan Spot Reordering Allowed","ScanSpotReorderingAllowed",false }, {0x300a,0x0396,VR::FL,VM::VM1_n,"Scan Spot Meterset Weights","ScanSpotMetersetWeights",false }, {0x300a,0x0398,VR::FL,VM::VM2,"Scanning Spot Size","ScanningSpotSize",false }, {0x300a,0x039a,VR::IS,VM::VM1,"Number of Paintings","NumberOfPaintings",false }, {0x300a,0x03a0,VR::SQ,VM::VM1,"Ion Tolerance Table Sequence","IonToleranceTableSequence",false }, {0x300a,0x03a2,VR::SQ,VM::VM1,"Ion Beam Sequence","IonBeamSequence",false }, {0x300a,0x03a4,VR::SQ,VM::VM1,"Ion Beam Limiting Device Sequence","IonBeamLimitingDeviceSequence",false }, {0x300a,0x03a6,VR::SQ,VM::VM1,"Ion Block Sequence","IonBlockSequence",false }, {0x300a,0x03a8,VR::SQ,VM::VM1,"Ion Control Point Sequence","IonControlPointSequence",false }, {0x300a,0x03aa,VR::SQ,VM::VM1,"Ion Wedge Sequence","IonWedgeSequence",false }, {0x300a,0x03ac,VR::SQ,VM::VM1,"Ion Wedge Position Sequence","IonWedgePositionSequence",false }, {0x300a,0x0401,VR::SQ,VM::VM1,"Referenced Setup Image Sequence","ReferencedSetupImageSequence",false }, {0x300a,0x0402,VR::ST,VM::VM1,"Setup Image Comment","SetupImageComment",false }, {0x300a,0x0410,VR::SQ,VM::VM1,"Motion Synchronization Sequence","MotionSynchronizationSequence",false }, {0x300a,0x0412,VR::FL,VM::VM3,"Control Point Orientation","ControlPointOrientation",false }, {0x300a,0x0420,VR::SQ,VM::VM1,"General Accessory Sequence","GeneralAccessorySequence",false }, {0x300a,0x0421,VR::SH,VM::VM1,"General Accessory ID","GeneralAccessoryID",false }, {0x300a,0x0422,VR::ST,VM::VM1,"General Accessory Description","GeneralAccessoryDescription",false }, {0x300a,0x0423,VR::CS,VM::VM1,"General Accessory Type","GeneralAccessoryType",false }, {0x300a,0x0424,VR::IS,VM::VM1,"General Accessory Number","GeneralAccessoryNumber",false }, {0x300a,0x0425,VR::FL,VM::VM1,"Source to General Accessory Distance","SourceToGeneralAccessoryDistance",false }, {0x300a,0x0431,VR::SQ,VM::VM1,"Applicator Geometry Sequence","ApplicatorGeometrySequence",false }, {0x300a,0x0432,VR::CS,VM::VM1,"Applicator Aperture Shape","ApplicatorApertureShape",false }, {0x300a,0x0433,VR::FL,VM::VM1,"Applicator Opening","ApplicatorOpening",false }, {0x300a,0x0434,VR::FL,VM::VM1,"Applicator Opening X","ApplicatorOpeningX",false }, {0x300a,0x0435,VR::FL,VM::VM1,"Applicator Opening Y","ApplicatorOpeningY",false }, {0x300a,0x0436,VR::FL,VM::VM1,"Source to Applicator Mounting Position Distance","SourceToApplicatorMountingPositionDistance",false }, {0x300a,0x0440,VR::IS,VM::VM1,"Number of Block Slab Items","NumberOfBlockSlabItems",false }, {0x300a,0x0441,VR::SQ,VM::VM1,"Block Slab Sequence","BlockSlabSequence",false }, {0x300a,0x0442,VR::DS,VM::VM1,"Block Slab Thickness","BlockSlabThickness",false }, {0x300a,0x0443,VR::US,VM::VM1,"Block Slab Number","BlockSlabNumber",false }, {0x300a,0x0450,VR::SQ,VM::VM1,"Device Motion Control Sequence","DeviceMotionControlSequence",false }, {0x300a,0x0451,VR::CS,VM::VM1,"Device Motion Execution Mode","DeviceMotionExecutionMode",false }, {0x300a,0x0452,VR::CS,VM::VM1,"Device Motion Observation Mode","DeviceMotionObservationMode",false }, {0x300a,0x0453,VR::SQ,VM::VM1,"Device Motion Parameter Code Sequence","DeviceMotionParameterCodeSequence",false }, {0x300a,0x0501,VR::FL,VM::VM1,"Distal Depth Fraction","DistalDepthFraction",false }, {0x300a,0x0502,VR::FL,VM::VM1,"Distal Depth","DistalDepth",false }, {0x300a,0x0503,VR::FL,VM::VM2,"Nominal Range Modulation Fractions","NominalRangeModulationFractions",false }, {0x300a,0x0504,VR::FL,VM::VM2,"Nominal Range Modulated Region Depths","NominalRangeModulatedRegionDepths",false }, {0x300a,0x0505,VR::SQ,VM::VM1,"Depth Dose Parameters Sequence","DepthDoseParametersSequence",false }, {0x300a,0x0506,VR::SQ,VM::VM1,"Delivered Depth Dose Parameters Sequence","DeliveredDepthDoseParametersSequence",false }, {0x300a,0x0507,VR::FL,VM::VM1,"Delivered Distal Depth Fraction","DeliveredDistalDepthFraction",false }, {0x300a,0x0508,VR::FL,VM::VM1,"Delivered Distal Depth","DeliveredDistalDepth",false }, {0x300a,0x0509,VR::FL,VM::VM2,"Delivered Nominal Range Modulation Fractions","DeliveredNominalRangeModulationFractions",false }, {0x300a,0x0510,VR::FL,VM::VM2,"Delivered Nominal Range Modulated Region Depths","DeliveredNominalRangeModulatedRegionDepths",false }, {0x300a,0x0511,VR::CS,VM::VM1,"Delivered Reference Dose Definition","DeliveredReferenceDoseDefinition",false }, {0x300a,0x0512,VR::CS,VM::VM1,"Reference Dose Definition","ReferenceDoseDefinition",false }, {0x300c,0x0002,VR::SQ,VM::VM1,"Referenced RT Plan Sequence","ReferencedRTPlanSequence",false }, {0x300c,0x0004,VR::SQ,VM::VM1,"Referenced Beam Sequence","ReferencedBeamSequence",false }, {0x300c,0x0006,VR::IS,VM::VM1,"Referenced Beam Number","ReferencedBeamNumber",false }, {0x300c,0x0007,VR::IS,VM::VM1,"Referenced Reference Image Number","ReferencedReferenceImageNumber",false }, {0x300c,0x0008,VR::DS,VM::VM1,"Start Cumulative Meterset Weight","StartCumulativeMetersetWeight",false }, {0x300c,0x0009,VR::DS,VM::VM1,"End Cumulative Meterset Weight","EndCumulativeMetersetWeight",false }, {0x300c,0x000a,VR::SQ,VM::VM1,"Referenced Brachy Application Setup Sequence","ReferencedBrachyApplicationSetupSequence",false }, {0x300c,0x000c,VR::IS,VM::VM1,"Referenced Brachy Application Setup Number","ReferencedBrachyApplicationSetupNumber",false }, {0x300c,0x000e,VR::IS,VM::VM1,"Referenced Source Number","ReferencedSourceNumber",false }, {0x300c,0x0020,VR::SQ,VM::VM1,"Referenced Fraction Group Sequence","ReferencedFractionGroupSequence",false }, {0x300c,0x0022,VR::IS,VM::VM1,"Referenced Fraction Group Number","ReferencedFractionGroupNumber",false }, {0x300c,0x0040,VR::SQ,VM::VM1,"Referenced Verification Image Sequence","ReferencedVerificationImageSequence",false }, {0x300c,0x0042,VR::SQ,VM::VM1,"Referenced Reference Image Sequence","ReferencedReferenceImageSequence",false }, {0x300c,0x0050,VR::SQ,VM::VM1,"Referenced Dose Reference Sequence","ReferencedDoseReferenceSequence",false }, {0x300c,0x0051,VR::IS,VM::VM1,"Referenced Dose Reference Number","ReferencedDoseReferenceNumber",false }, {0x300c,0x0055,VR::SQ,VM::VM1,"Brachy Referenced Dose Reference Sequence","BrachyReferencedDoseReferenceSequence",false }, {0x300c,0x0060,VR::SQ,VM::VM1,"Referenced Structure Set Sequence","ReferencedStructureSetSequence",false }, {0x300c,0x006a,VR::IS,VM::VM1,"Referenced Patient Setup Number","ReferencedPatientSetupNumber",false }, {0x300c,0x0080,VR::SQ,VM::VM1,"Referenced Dose Sequence","ReferencedDoseSequence",false }, {0x300c,0x00a0,VR::IS,VM::VM1,"Referenced Tolerance Table Number","ReferencedToleranceTableNumber",false }, {0x300c,0x00b0,VR::SQ,VM::VM1,"Referenced Bolus Sequence","ReferencedBolusSequence",false }, {0x300c,0x00c0,VR::IS,VM::VM1,"Referenced Wedge Number","ReferencedWedgeNumber",false }, {0x300c,0x00d0,VR::IS,VM::VM1,"Referenced Compensator Number","ReferencedCompensatorNumber",false }, {0x300c,0x00e0,VR::IS,VM::VM1,"Referenced Block Number","ReferencedBlockNumber",false }, {0x300c,0x00f0,VR::IS,VM::VM1,"Referenced Control Point Index","ReferencedControlPointIndex",false }, {0x300c,0x00f2,VR::SQ,VM::VM1,"Referenced Control Point Sequence","ReferencedControlPointSequence",false }, {0x300c,0x00f4,VR::IS,VM::VM1,"Referenced Start Control Point Index","ReferencedStartControlPointIndex",false }, {0x300c,0x00f6,VR::IS,VM::VM1,"Referenced Stop Control Point Index","ReferencedStopControlPointIndex",false }, {0x300c,0x0100,VR::IS,VM::VM1,"Referenced Range Shifter Number","ReferencedRangeShifterNumber",false }, {0x300c,0x0102,VR::IS,VM::VM1,"Referenced Lateral Spreading Device Number","ReferencedLateralSpreadingDeviceNumber",false }, {0x300c,0x0104,VR::IS,VM::VM1,"Referenced Range Modulator Number","ReferencedRangeModulatorNumber",false }, {0x300c,0x0111,VR::SQ,VM::VM1,"Omitted Beam Task Sequence","OmittedBeamTaskSequence",false }, {0x300c,0x0112,VR::CS,VM::VM1,"Reason for Omission","ReasonForOmission",false }, {0x300c,0x0113,VR::LO,VM::VM1,"Reason for Omission Description","ReasonForOmissionDescription",false }, {0x300e,0x0002,VR::CS,VM::VM1,"Approval Status","ApprovalStatus",false }, {0x300e,0x0004,VR::DA,VM::VM1,"Review Date","ReviewDate",false }, {0x300e,0x0005,VR::TM,VM::VM1,"Review Time","ReviewTime",false }, {0x300e,0x0008,VR::PN,VM::VM1,"Reviewer Name","ReviewerName",false }, {0x4000,0x0010,VR::LT,VM::VM1,"Arbitrary","Arbitrary",true }, {0x4000,0x4000,VR::LT,VM::VM1,"Text Comments","TextComments",true }, {0x4008,0x0040,VR::SH,VM::VM1,"Results ID","ResultsID",true }, {0x4008,0x0042,VR::LO,VM::VM1,"Results ID Issuer","ResultsIDIssuer",true }, {0x4008,0x0050,VR::SQ,VM::VM1,"Referenced Interpretation Sequence","ReferencedInterpretationSequence",true }, {0x4008,0x00ff,VR::CS,VM::VM1,"Report Production Status (Trial)","ReportProductionStatusTrial",true }, {0x4008,0x0100,VR::DA,VM::VM1,"Interpretation Recorded Date","InterpretationRecordedDate",true }, {0x4008,0x0101,VR::TM,VM::VM1,"Interpretation Recorded Time","InterpretationRecordedTime",true }, {0x4008,0x0102,VR::PN,VM::VM1,"Interpretation Recorder","InterpretationRecorder",true }, {0x4008,0x0103,VR::LO,VM::VM1,"Reference to Recorded Sound","ReferenceToRecordedSound",true }, {0x4008,0x0108,VR::DA,VM::VM1,"Interpretation Transcription Date","InterpretationTranscriptionDate",true }, {0x4008,0x0109,VR::TM,VM::VM1,"Interpretation Transcription Time","InterpretationTranscriptionTime",true }, {0x4008,0x010a,VR::PN,VM::VM1,"Interpretation Transcriber","InterpretationTranscriber",true }, {0x4008,0x010b,VR::ST,VM::VM1,"Interpretation Text","InterpretationText",true }, {0x4008,0x010c,VR::PN,VM::VM1,"Interpretation Author","InterpretationAuthor",true }, {0x4008,0x0111,VR::SQ,VM::VM1,"Interpretation Approver Sequence","InterpretationApproverSequence",true }, {0x4008,0x0112,VR::DA,VM::VM1,"Interpretation Approval Date","InterpretationApprovalDate",true }, {0x4008,0x0113,VR::TM,VM::VM1,"Interpretation Approval Time","InterpretationApprovalTime",true }, {0x4008,0x0114,VR::PN,VM::VM1,"Physician Approving Interpretation","PhysicianApprovingInterpretation",true }, {0x4008,0x0115,VR::LT,VM::VM1,"Interpretation Diagnosis Description","InterpretationDiagnosisDescription",true }, {0x4008,0x0117,VR::SQ,VM::VM1,"Interpretation Diagnosis Code Sequence","InterpretationDiagnosisCodeSequence",true }, {0x4008,0x0118,VR::SQ,VM::VM1,"Results Distribution List Sequence","ResultsDistributionListSequence",true }, {0x4008,0x0119,VR::PN,VM::VM1,"Distribution Name","DistributionName",true }, {0x4008,0x011a,VR::LO,VM::VM1,"Distribution Address","DistributionAddress",true }, {0x4008,0x0200,VR::SH,VM::VM1,"Interpretation ID","InterpretationID",true }, {0x4008,0x0202,VR::LO,VM::VM1,"Interpretation ID Issuer","InterpretationIDIssuer",true }, {0x4008,0x0210,VR::CS,VM::VM1,"Interpretation Type ID","InterpretationTypeID",true }, {0x4008,0x0212,VR::CS,VM::VM1,"Interpretation Status ID","InterpretationStatusID",true }, {0x4008,0x0300,VR::ST,VM::VM1,"Impressions","Impressions",true }, {0x4008,0x4000,VR::ST,VM::VM1,"Results Comments","ResultsComments",true }, {0x4010,0x0001,VR::CS,VM::VM1,"Low Energy Detectors","LowEnergyDetectors",false }, {0x4010,0x0002,VR::CS,VM::VM1,"High Energy Detectors","HighEnergyDetectors",false }, {0x4010,0x0004,VR::SQ,VM::VM1,"Detector Geometry Sequence","DetectorGeometrySequence",false }, {0x4010,0x1001,VR::SQ,VM::VM1,"Threat ROI Voxel Sequence","ThreatROIVoxelSequence",false }, {0x4010,0x1004,VR::FL,VM::VM3,"Threat ROI Base","ThreatROIBase",false }, {0x4010,0x1005,VR::FL,VM::VM3,"Threat ROI Extents","ThreatROIExtents",false }, {0x4010,0x1006,VR::OB,VM::VM1,"Threat ROI Bitmap","ThreatROIBitmap",false }, {0x4010,0x1007,VR::SH,VM::VM1,"Route Segment ID","RouteSegmentID",false }, {0x4010,0x1008,VR::CS,VM::VM1,"Gantry Type","GantryType",false }, {0x4010,0x1009,VR::CS,VM::VM1,"OOI Owner Type","OOIOwnerType",false }, {0x4010,0x100a,VR::SQ,VM::VM1,"Route Segment Sequence","RouteSegmentSequence",false }, {0x4010,0x1010,VR::US,VM::VM1,"Potential Threat Object ID","PotentialThreatObjectID",false }, {0x4010,0x1011,VR::SQ,VM::VM1,"Threat Sequence","ThreatSequence",false }, {0x4010,0x1012,VR::CS,VM::VM1,"Threat Category","ThreatCategory",false }, {0x4010,0x1013,VR::LT,VM::VM1,"Threat Category Description","ThreatCategoryDescription",false }, {0x4010,0x1014,VR::CS,VM::VM1,"ATD Ability Assessment","ATDAbilityAssessment",false }, {0x4010,0x1015,VR::CS,VM::VM1,"ATD Assessment Flag","ATDAssessmentFlag",false }, {0x4010,0x1016,VR::FL,VM::VM1,"ATD Assessment Probability","ATDAssessmentProbability",false }, {0x4010,0x1017,VR::FL,VM::VM1,"Mass","Mass",false }, {0x4010,0x1018,VR::FL,VM::VM1,"Density","Density",false }, {0x4010,0x1019,VR::FL,VM::VM1,"Z Effective","ZEffective",false }, {0x4010,0x101a,VR::SH,VM::VM1,"Boarding Pass ID","BoardingPassID",false }, {0x4010,0x101b,VR::FL,VM::VM3,"Center of Mass","CenterOfMass",false }, {0x4010,0x101c,VR::FL,VM::VM3,"Center of PTO","CenterOfPTO",false }, {0x4010,0x101d,VR::FL,VM::VM6_n,"Bounding Polygon","BoundingPolygon",false }, {0x4010,0x101e,VR::SH,VM::VM1,"Route Segment Start Location ID","RouteSegmentStartLocationID",false }, {0x4010,0x101f,VR::SH,VM::VM1,"Route Segment End Location ID","RouteSegmentEndLocationID",false }, {0x4010,0x1020,VR::CS,VM::VM1,"Route Segment Location ID Type","RouteSegmentLocationIDType",false }, {0x4010,0x1021,VR::CS,VM::VM1_n,"Abort Reason","AbortReason",false }, {0x4010,0x1023,VR::FL,VM::VM1,"Volume of PTO","VolumeOfPTO",false }, {0x4010,0x1024,VR::CS,VM::VM1,"Abort Flag","AbortFlag",false }, {0x4010,0x1025,VR::DT,VM::VM1,"Route Segment Start Time","RouteSegmentStartTime",false }, {0x4010,0x1026,VR::DT,VM::VM1,"Route Segment End Time","RouteSegmentEndTime",false }, {0x4010,0x1027,VR::CS,VM::VM1,"TDR Type","TDRType",false }, {0x4010,0x1028,VR::CS,VM::VM1,"International Route Segment","InternationalRouteSegment",false }, {0x4010,0x1029,VR::LO,VM::VM1_n,"Threat Detection Algorithm and Version","ThreatDetectionAlgorithmandVersion",false }, {0x4010,0x102a,VR::SH,VM::VM1,"Assigned Location","AssignedLocation",false }, {0x4010,0x102b,VR::DT,VM::VM1,"Alarm Decision Time","AlarmDecisionTime",false }, {0x4010,0x1031,VR::CS,VM::VM1,"Alarm Decision","AlarmDecision",false }, {0x4010,0x1033,VR::US,VM::VM1,"Number of Total Objects","NumberOfTotalObjects",false }, {0x4010,0x1034,VR::US,VM::VM1,"Number of Alarm Objects","NumberOfAlarmObjects",false }, {0x4010,0x1037,VR::SQ,VM::VM1,"PTO Representation Sequence","PTORepresentationSequence",false }, {0x4010,0x1038,VR::SQ,VM::VM1,"ATD Assessment Sequence","ATDAssessmentSequence",false }, {0x4010,0x1039,VR::CS,VM::VM1,"TIP Type","TIPType",false }, {0x4010,0x103a,VR::CS,VM::VM1,"DICOS Version","DICOSVersion",false }, {0x4010,0x1041,VR::DT,VM::VM1,"OOI Owner Creation Time","OOIOwnerCreationTime",false }, {0x4010,0x1042,VR::CS,VM::VM1,"OOI Type","OOIType",false }, {0x4010,0x1043,VR::FL,VM::VM3,"OOI Size","OOISize",false }, {0x4010,0x1044,VR::CS,VM::VM1,"Acquisition Status","AcquisitionStatus",false }, {0x4010,0x1045,VR::SQ,VM::VM1,"Basis Materials Code Sequence","BasisMaterialsCodeSequence",false }, {0x4010,0x1046,VR::CS,VM::VM1,"Phantom Type","PhantomType",false }, {0x4010,0x1047,VR::SQ,VM::VM1,"OOI Owner Sequence","OOIOwnerSequence",false }, {0x4010,0x1048,VR::CS,VM::VM1,"Scan Type","ScanType",false }, {0x4010,0x1051,VR::LO,VM::VM1,"Itinerary ID","ItineraryID",false }, {0x4010,0x1052,VR::SH,VM::VM1,"Itinerary ID Type","ItineraryIDType",false }, {0x4010,0x1053,VR::LO,VM::VM1,"Itinerary ID Assigning Authority","ItineraryIDAssigningAuthority",false }, {0x4010,0x1054,VR::SH,VM::VM1,"Route ID","RouteID",false }, {0x4010,0x1055,VR::SH,VM::VM1,"Route ID Assigning Authority","RouteIDAssigningAuthority",false }, {0x4010,0x1056,VR::CS,VM::VM1,"Inbound Arrival Type","InboundArrivalType",false }, {0x4010,0x1058,VR::SH,VM::VM1,"Carrier ID","CarrierID",false }, {0x4010,0x1059,VR::CS,VM::VM1,"Carrier ID Assigning Authority","CarrierIDAssigningAuthority",false }, {0x4010,0x1060,VR::FL,VM::VM3,"Source Orientation","SourceOrientation",false }, {0x4010,0x1061,VR::FL,VM::VM3,"Source Position","SourcePosition",false }, {0x4010,0x1062,VR::FL,VM::VM1,"Belt Height","BeltHeight",false }, {0x4010,0x1064,VR::SQ,VM::VM1,"Algorithm Routing Code Sequence","AlgorithmRoutingCodeSequence",false }, {0x4010,0x1067,VR::CS,VM::VM1,"Transport Classification","TransportClassification",false }, {0x4010,0x1068,VR::LT,VM::VM1,"OOI Type Descriptor","OOITypeDescriptor",false }, {0x4010,0x1069,VR::FL,VM::VM1,"Total Processing Time","TotalProcessingTime",false }, {0x4010,0x106c,VR::OB,VM::VM1,"Detector Calibration Data","DetectorCalibrationData",false }, {0x4010,0x106d,VR::CS,VM::VM1,"Additional Screening Performed","AdditionalScreeningPerformed",false }, {0x4010,0x106e,VR::CS,VM::VM1,"Additional Inspection Selection Criteria","AdditionalInspectionSelectionCriteria",false }, {0x4010,0x106f,VR::SQ,VM::VM1,"Additional Inspection Method Sequence","AdditionalInspectionMethodSequence",false }, {0x4010,0x1070,VR::CS,VM::VM1,"AIT Device Type","AITDeviceType",false }, {0x4010,0x1071,VR::SQ,VM::VM1,"QR Measurements Sequence","QRMeasurementsSequence",false }, {0x4010,0x1072,VR::SQ,VM::VM1,"Target Material Sequence","TargetMaterialSequence",false }, {0x4010,0x1073,VR::FD,VM::VM1,"SNR Threshold","SNRThreshold",false }, {0x4010,0x1075,VR::DS,VM::VM1,"Image Scale Representation","ImageScaleRepresentation",false }, {0x4010,0x1076,VR::SQ,VM::VM1,"Referenced PTO Sequence","ReferencedPTOSequence",false }, {0x4010,0x1077,VR::SQ,VM::VM1,"Referenced TDR Instance Sequence","ReferencedTDRInstanceSequence",false }, {0x4010,0x1078,VR::ST,VM::VM1,"PTO Location Description","PTOLocationDescription",false }, {0x4010,0x1079,VR::SQ,VM::VM1,"Anomaly Locator Indicator Sequence","AnomalyLocatorIndicatorSequence",false }, {0x4010,0x107a,VR::FL,VM::VM3,"Anomaly Locator Indicator","AnomalyLocatorIndicator",false }, {0x4010,0x107b,VR::SQ,VM::VM1,"PTO Region Sequence","PTORegionSequence",false }, {0x4010,0x107c,VR::CS,VM::VM1,"Inspection Selection Criteria","InspectionSelectionCriteria",false }, {0x4010,0x107d,VR::SQ,VM::VM1,"Secondary Inspection Method Sequence","SecondaryInspectionMethodSequence",false }, {0x4010,0x107e,VR::DS,VM::VM6,"PRCS to RCS Orientation","PRCSToRCSOrientation",false }, {0x4ffe,0x0001,VR::SQ,VM::VM1,"MAC Parameters Sequence","MACParametersSequence",false }, {0x5000,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5002,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5004,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5006,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5008,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x500a,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x500c,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x500e,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5010,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5012,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5014,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5016,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5018,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x501a,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x501c,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x501e,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5020,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5022,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5024,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5026,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5028,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x502a,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x502c,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x502e,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5030,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5032,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5034,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5036,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5038,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x503a,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x503c,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x503e,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5040,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5042,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5044,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5046,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5048,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x504a,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x504c,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x504e,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5050,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5052,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5054,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5056,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5058,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x505a,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x505c,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x505e,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5060,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5062,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5064,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5066,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5068,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x506a,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x506c,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x506e,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5070,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5072,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5074,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5076,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5078,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x507a,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x507c,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x507e,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5080,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5082,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5084,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5086,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5088,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x508a,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x508c,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x508e,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5090,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5092,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5094,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5096,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5098,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x509a,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x509c,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x509e,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50a0,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50a2,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50a4,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50a6,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50a8,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50aa,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50ac,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50ae,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50b0,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50b2,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50b4,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50b6,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50b8,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50ba,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50bc,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50be,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50c0,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50c2,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50c4,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50c6,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50c8,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50ca,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50cc,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50ce,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50d0,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50d2,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50d4,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50d6,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50d8,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50da,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50dc,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50de,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50e0,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50e2,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50e4,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50e6,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50e8,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50ea,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50ec,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50ee,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50f0,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50f2,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50f4,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50f6,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50f8,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50fa,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50fc,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x50fe,0x0005,VR::US,VM::VM1,"Curve Dimensions","CurveDimensions",true }, {0x5000,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5002,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5004,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5006,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5008,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x500a,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x500c,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x500e,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5010,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5012,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5014,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5016,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5018,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x501a,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x501c,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x501e,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5020,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5022,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5024,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5026,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5028,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x502a,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x502c,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x502e,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5030,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5032,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5034,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5036,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5038,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x503a,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x503c,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x503e,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5040,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5042,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5044,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5046,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5048,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x504a,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x504c,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x504e,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5050,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5052,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5054,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5056,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5058,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x505a,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x505c,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x505e,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5060,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5062,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5064,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5066,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5068,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x506a,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x506c,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x506e,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5070,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5072,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5074,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5076,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5078,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x507a,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x507c,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x507e,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5080,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5082,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5084,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5086,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5088,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x508a,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x508c,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x508e,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5090,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5092,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5094,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5096,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5098,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x509a,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x509c,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x509e,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50a0,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50a2,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50a4,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50a6,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50a8,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50aa,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50ac,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50ae,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50b0,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50b2,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50b4,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50b6,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50b8,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50ba,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50bc,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50be,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50c0,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50c2,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50c4,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50c6,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50c8,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50ca,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50cc,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50ce,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50d0,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50d2,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50d4,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50d6,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50d8,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50da,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50dc,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50de,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50e0,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50e2,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50e4,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50e6,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50e8,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50ea,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50ec,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50ee,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50f0,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50f2,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50f4,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50f6,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50f8,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50fa,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50fc,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x50fe,0x0010,VR::US,VM::VM1,"Number of Points","NumberOfPoints",true }, {0x5000,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5002,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5004,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5006,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5008,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x500a,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x500c,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x500e,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5010,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5012,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5014,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5016,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5018,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x501a,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x501c,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x501e,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5020,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5022,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5024,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5026,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5028,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x502a,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x502c,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x502e,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5030,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5032,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5034,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5036,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5038,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x503a,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x503c,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x503e,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5040,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5042,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5044,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5046,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5048,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x504a,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x504c,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x504e,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5050,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5052,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5054,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5056,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5058,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x505a,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x505c,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x505e,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5060,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5062,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5064,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5066,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5068,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x506a,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x506c,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x506e,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5070,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5072,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5074,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5076,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5078,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x507a,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x507c,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x507e,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5080,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5082,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5084,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5086,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5088,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x508a,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x508c,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x508e,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5090,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5092,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5094,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5096,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5098,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x509a,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x509c,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x509e,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50a0,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50a2,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50a4,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50a6,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50a8,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50aa,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50ac,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50ae,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50b0,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50b2,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50b4,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50b6,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50b8,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50ba,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50bc,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50be,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50c0,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50c2,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50c4,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50c6,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50c8,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50ca,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50cc,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50ce,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50d0,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50d2,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50d4,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50d6,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50d8,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50da,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50dc,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50de,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50e0,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50e2,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50e4,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50e6,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50e8,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50ea,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50ec,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50ee,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50f0,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50f2,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50f4,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50f6,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50f8,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50fa,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50fc,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x50fe,0x0020,VR::CS,VM::VM1,"Type of Data","TypeOfData",true }, {0x5000,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5002,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5004,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5006,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5008,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x500a,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x500c,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x500e,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5010,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5012,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5014,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5016,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5018,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x501a,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x501c,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x501e,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5020,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5022,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5024,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5026,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5028,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x502a,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x502c,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x502e,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5030,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5032,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5034,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5036,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5038,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x503a,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x503c,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x503e,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5040,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5042,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5044,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5046,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5048,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x504a,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x504c,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x504e,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5050,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5052,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5054,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5056,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5058,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x505a,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x505c,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x505e,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5060,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5062,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5064,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5066,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5068,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x506a,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x506c,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x506e,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5070,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5072,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5074,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5076,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5078,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x507a,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x507c,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x507e,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5080,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5082,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5084,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5086,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5088,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x508a,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x508c,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x508e,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5090,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5092,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5094,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5096,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5098,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x509a,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x509c,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x509e,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50a0,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50a2,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50a4,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50a6,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50a8,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50aa,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50ac,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50ae,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50b0,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50b2,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50b4,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50b6,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50b8,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50ba,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50bc,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50be,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50c0,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50c2,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50c4,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50c6,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50c8,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50ca,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50cc,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50ce,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50d0,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50d2,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50d4,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50d6,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50d8,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50da,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50dc,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50de,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50e0,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50e2,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50e4,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50e6,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50e8,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50ea,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50ec,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50ee,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50f0,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50f2,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50f4,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50f6,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50f8,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50fa,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50fc,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x50fe,0x0022,VR::LO,VM::VM1,"Curve Description","CurveDescription",true }, {0x5000,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5002,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5004,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5006,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5008,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x500a,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x500c,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x500e,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5010,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5012,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5014,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5016,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5018,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x501a,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x501c,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x501e,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5020,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5022,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5024,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5026,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5028,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x502a,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x502c,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x502e,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5030,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5032,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5034,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5036,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5038,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x503a,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x503c,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x503e,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5040,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5042,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5044,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5046,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5048,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x504a,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x504c,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x504e,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5050,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5052,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5054,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5056,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5058,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x505a,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x505c,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x505e,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5060,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5062,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5064,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5066,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5068,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x506a,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x506c,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x506e,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5070,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5072,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5074,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5076,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5078,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x507a,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x507c,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x507e,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5080,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5082,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5084,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5086,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5088,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x508a,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x508c,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x508e,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5090,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5092,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5094,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5096,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5098,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x509a,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x509c,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x509e,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50a0,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50a2,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50a4,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50a6,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50a8,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50aa,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50ac,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50ae,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50b0,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50b2,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50b4,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50b6,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50b8,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50ba,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50bc,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50be,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50c0,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50c2,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50c4,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50c6,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50c8,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50ca,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50cc,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50ce,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50d0,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50d2,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50d4,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50d6,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50d8,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50da,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50dc,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50de,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50e0,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50e2,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50e4,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50e6,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50e8,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50ea,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50ec,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50ee,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50f0,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50f2,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50f4,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50f6,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50f8,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50fa,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50fc,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x50fe,0x0030,VR::SH,VM::VM1_n,"Axis Units","AxisUnits",true }, {0x5000,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5002,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5004,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5006,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5008,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x500a,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x500c,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x500e,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5010,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5012,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5014,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5016,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5018,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x501a,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x501c,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x501e,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5020,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5022,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5024,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5026,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5028,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x502a,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x502c,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x502e,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5030,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5032,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5034,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5036,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5038,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x503a,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x503c,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x503e,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5040,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5042,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5044,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5046,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5048,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x504a,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x504c,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x504e,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5050,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5052,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5054,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5056,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5058,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x505a,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x505c,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x505e,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5060,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5062,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5064,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5066,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5068,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x506a,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x506c,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x506e,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5070,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5072,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5074,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5076,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5078,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x507a,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x507c,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x507e,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5080,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5082,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5084,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5086,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5088,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x508a,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x508c,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x508e,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5090,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5092,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5094,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5096,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5098,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x509a,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x509c,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x509e,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50a0,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50a2,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50a4,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50a6,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50a8,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50aa,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50ac,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50ae,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50b0,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50b2,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50b4,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50b6,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50b8,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50ba,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50bc,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50be,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50c0,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50c2,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50c4,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50c6,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50c8,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50ca,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50cc,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50ce,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50d0,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50d2,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50d4,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50d6,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50d8,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50da,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50dc,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50de,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50e0,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50e2,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50e4,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50e6,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50e8,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50ea,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50ec,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50ee,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50f0,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50f2,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50f4,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50f6,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50f8,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50fa,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50fc,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x50fe,0x0040,VR::SH,VM::VM1_n,"Axis Labels","AxisLabels",true }, {0x5000,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5002,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5004,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5006,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5008,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x500a,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x500c,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x500e,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5010,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5012,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5014,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5016,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5018,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x501a,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x501c,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x501e,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5020,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5022,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5024,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5026,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5028,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x502a,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x502c,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x502e,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5030,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5032,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5034,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5036,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5038,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x503a,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x503c,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x503e,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5040,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5042,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5044,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5046,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5048,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x504a,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x504c,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x504e,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5050,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5052,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5054,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5056,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5058,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x505a,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x505c,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x505e,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5060,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5062,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5064,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5066,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5068,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x506a,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x506c,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x506e,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5070,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5072,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5074,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5076,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5078,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x507a,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x507c,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x507e,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5080,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5082,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5084,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5086,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5088,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x508a,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x508c,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x508e,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5090,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5092,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5094,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5096,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5098,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x509a,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x509c,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x509e,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50a0,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50a2,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50a4,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50a6,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50a8,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50aa,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50ac,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50ae,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50b0,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50b2,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50b4,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50b6,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50b8,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50ba,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50bc,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50be,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50c0,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50c2,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50c4,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50c6,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50c8,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50ca,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50cc,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50ce,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50d0,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50d2,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50d4,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50d6,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50d8,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50da,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50dc,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50de,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50e0,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50e2,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50e4,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50e6,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50e8,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50ea,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50ec,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50ee,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50f0,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50f2,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50f4,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50f6,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50f8,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50fa,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50fc,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x50fe,0x0103,VR::US,VM::VM1,"Data Value Representation","DataValueRepresentation",true }, {0x5000,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5002,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5004,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5006,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5008,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x500a,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x500c,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x500e,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5010,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5012,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5014,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5016,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5018,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x501a,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x501c,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x501e,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5020,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5022,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5024,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5026,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5028,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x502a,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x502c,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x502e,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5030,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5032,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5034,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5036,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5038,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x503a,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x503c,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x503e,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5040,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5042,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5044,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5046,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5048,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x504a,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x504c,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x504e,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5050,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5052,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5054,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5056,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5058,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x505a,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x505c,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x505e,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5060,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5062,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5064,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5066,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5068,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x506a,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x506c,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x506e,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5070,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5072,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5074,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5076,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5078,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x507a,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x507c,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x507e,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5080,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5082,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5084,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5086,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5088,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x508a,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x508c,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x508e,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5090,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5092,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5094,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5096,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5098,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x509a,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x509c,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x509e,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50a0,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50a2,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50a4,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50a6,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50a8,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50aa,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50ac,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50ae,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50b0,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50b2,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50b4,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50b6,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50b8,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50ba,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50bc,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50be,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50c0,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50c2,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50c4,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50c6,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50c8,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50ca,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50cc,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50ce,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50d0,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50d2,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50d4,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50d6,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50d8,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50da,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50dc,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50de,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50e0,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50e2,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50e4,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50e6,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50e8,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50ea,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50ec,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50ee,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50f0,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50f2,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50f4,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50f6,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50f8,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50fa,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50fc,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x50fe,0x0104,VR::US,VM::VM1_n,"Minimum Coordinate Value","MinimumCoordinateValue",true }, {0x5000,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5002,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5004,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5006,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5008,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x500a,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x500c,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x500e,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5010,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5012,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5014,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5016,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5018,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x501a,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x501c,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x501e,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5020,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5022,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5024,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5026,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5028,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x502a,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x502c,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x502e,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5030,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5032,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5034,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5036,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5038,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x503a,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x503c,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x503e,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5040,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5042,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5044,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5046,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5048,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x504a,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x504c,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x504e,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5050,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5052,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5054,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5056,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5058,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x505a,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x505c,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x505e,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5060,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5062,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5064,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5066,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5068,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x506a,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x506c,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x506e,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5070,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5072,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5074,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5076,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5078,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x507a,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x507c,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x507e,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5080,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5082,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5084,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5086,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5088,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x508a,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x508c,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x508e,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5090,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5092,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5094,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5096,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5098,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x509a,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x509c,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x509e,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50a0,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50a2,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50a4,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50a6,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50a8,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50aa,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50ac,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50ae,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50b0,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50b2,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50b4,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50b6,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50b8,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50ba,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50bc,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50be,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50c0,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50c2,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50c4,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50c6,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50c8,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50ca,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50cc,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50ce,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50d0,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50d2,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50d4,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50d6,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50d8,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50da,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50dc,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50de,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50e0,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50e2,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50e4,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50e6,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50e8,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50ea,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50ec,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50ee,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50f0,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50f2,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50f4,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50f6,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50f8,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50fa,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50fc,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x50fe,0x0105,VR::US,VM::VM1_n,"Maximum Coordinate Value","MaximumCoordinateValue",true }, {0x5000,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5002,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5004,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5006,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5008,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x500a,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x500c,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x500e,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5010,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5012,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5014,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5016,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5018,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x501a,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x501c,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x501e,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5020,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5022,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5024,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5026,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5028,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x502a,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x502c,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x502e,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5030,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5032,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5034,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5036,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5038,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x503a,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x503c,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x503e,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5040,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5042,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5044,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5046,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5048,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x504a,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x504c,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x504e,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5050,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5052,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5054,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5056,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5058,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x505a,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x505c,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x505e,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5060,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5062,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5064,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5066,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5068,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x506a,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x506c,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x506e,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5070,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5072,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5074,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5076,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5078,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x507a,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x507c,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x507e,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5080,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5082,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5084,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5086,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5088,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x508a,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x508c,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x508e,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5090,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5092,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5094,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5096,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5098,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x509a,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x509c,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x509e,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50a0,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50a2,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50a4,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50a6,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50a8,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50aa,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50ac,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50ae,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50b0,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50b2,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50b4,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50b6,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50b8,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50ba,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50bc,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50be,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50c0,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50c2,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50c4,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50c6,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50c8,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50ca,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50cc,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50ce,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50d0,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50d2,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50d4,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50d6,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50d8,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50da,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50dc,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50de,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50e0,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50e2,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50e4,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50e6,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50e8,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50ea,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50ec,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50ee,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50f0,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50f2,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50f4,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50f6,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50f8,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50fa,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50fc,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x50fe,0x0106,VR::SH,VM::VM1_n,"Curve Range","CurveRange",true }, {0x5000,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5002,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5004,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5006,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5008,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x500a,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x500c,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x500e,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5010,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5012,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5014,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5016,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5018,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x501a,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x501c,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x501e,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5020,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5022,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5024,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5026,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5028,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x502a,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x502c,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x502e,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5030,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5032,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5034,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5036,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5038,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x503a,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x503c,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x503e,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5040,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5042,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5044,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5046,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5048,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x504a,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x504c,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x504e,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5050,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5052,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5054,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5056,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5058,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x505a,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x505c,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x505e,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5060,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5062,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5064,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5066,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5068,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x506a,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x506c,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x506e,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5070,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5072,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5074,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5076,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5078,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x507a,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x507c,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x507e,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5080,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5082,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5084,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5086,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5088,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x508a,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x508c,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x508e,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5090,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5092,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5094,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5096,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5098,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x509a,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x509c,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x509e,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50a0,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50a2,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50a4,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50a6,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50a8,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50aa,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50ac,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50ae,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50b0,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50b2,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50b4,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50b6,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50b8,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50ba,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50bc,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50be,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50c0,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50c2,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50c4,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50c6,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50c8,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50ca,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50cc,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50ce,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50d0,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50d2,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50d4,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50d6,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50d8,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50da,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50dc,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50de,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50e0,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50e2,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50e4,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50e6,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50e8,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50ea,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50ec,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50ee,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50f0,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50f2,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50f4,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50f6,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50f8,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50fa,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50fc,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x50fe,0x0110,VR::US,VM::VM1_n,"Curve Data Descriptor","CurveDataDescriptor",true }, {0x5000,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5002,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5004,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5006,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5008,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x500a,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x500c,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x500e,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5010,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5012,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5014,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5016,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5018,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x501a,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x501c,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x501e,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5020,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5022,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5024,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5026,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5028,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x502a,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x502c,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x502e,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5030,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5032,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5034,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5036,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5038,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x503a,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x503c,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x503e,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5040,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5042,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5044,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5046,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5048,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x504a,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x504c,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x504e,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5050,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5052,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5054,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5056,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5058,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x505a,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x505c,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x505e,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5060,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5062,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5064,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5066,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5068,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x506a,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x506c,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x506e,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5070,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5072,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5074,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5076,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5078,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x507a,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x507c,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x507e,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5080,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5082,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5084,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5086,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5088,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x508a,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x508c,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x508e,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5090,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5092,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5094,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5096,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5098,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x509a,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x509c,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x509e,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50a0,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50a2,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50a4,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50a6,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50a8,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50aa,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50ac,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50ae,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50b0,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50b2,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50b4,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50b6,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50b8,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50ba,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50bc,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50be,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50c0,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50c2,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50c4,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50c6,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50c8,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50ca,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50cc,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50ce,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50d0,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50d2,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50d4,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50d6,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50d8,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50da,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50dc,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50de,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50e0,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50e2,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50e4,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50e6,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50e8,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50ea,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50ec,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50ee,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50f0,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50f2,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50f4,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50f6,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50f8,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50fa,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50fc,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x50fe,0x0112,VR::US,VM::VM1_n,"Coordinate Start Value","CoordinateStartValue",true }, {0x5000,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5002,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5004,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5006,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5008,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x500a,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x500c,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x500e,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5010,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5012,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5014,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5016,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5018,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x501a,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x501c,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x501e,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5020,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5022,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5024,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5026,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5028,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x502a,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x502c,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x502e,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5030,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5032,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5034,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5036,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5038,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x503a,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x503c,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x503e,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5040,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5042,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5044,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5046,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5048,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x504a,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x504c,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x504e,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5050,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5052,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5054,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5056,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5058,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x505a,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x505c,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x505e,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5060,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5062,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5064,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5066,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5068,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x506a,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x506c,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x506e,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5070,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5072,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5074,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5076,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5078,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x507a,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x507c,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x507e,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5080,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5082,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5084,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5086,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5088,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x508a,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x508c,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x508e,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5090,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5092,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5094,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5096,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5098,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x509a,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x509c,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x509e,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50a0,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50a2,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50a4,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50a6,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50a8,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50aa,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50ac,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50ae,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50b0,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50b2,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50b4,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50b6,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50b8,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50ba,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50bc,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50be,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50c0,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50c2,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50c4,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50c6,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50c8,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50ca,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50cc,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50ce,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50d0,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50d2,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50d4,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50d6,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50d8,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50da,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50dc,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50de,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50e0,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50e2,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50e4,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50e6,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50e8,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50ea,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50ec,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50ee,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50f0,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50f2,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50f4,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50f6,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50f8,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50fa,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50fc,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x50fe,0x0114,VR::US,VM::VM1_n,"Coordinate Step Value","CoordinateStepValue",true }, {0x5000,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5002,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5004,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5006,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5008,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x500a,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x500c,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x500e,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5010,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5012,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5014,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5016,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5018,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x501a,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x501c,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x501e,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5020,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5022,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5024,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5026,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5028,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x502a,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x502c,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x502e,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5030,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5032,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5034,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5036,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5038,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x503a,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x503c,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x503e,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5040,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5042,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5044,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5046,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5048,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x504a,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x504c,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x504e,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5050,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5052,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5054,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5056,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5058,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x505a,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x505c,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x505e,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5060,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5062,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5064,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5066,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5068,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x506a,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x506c,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x506e,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5070,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5072,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5074,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5076,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5078,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x507a,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x507c,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x507e,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5080,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5082,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5084,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5086,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5088,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x508a,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x508c,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x508e,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5090,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5092,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5094,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5096,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5098,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x509a,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x509c,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x509e,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50a0,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50a2,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50a4,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50a6,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50a8,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50aa,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50ac,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50ae,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50b0,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50b2,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50b4,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50b6,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50b8,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50ba,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50bc,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50be,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50c0,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50c2,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50c4,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50c6,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50c8,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50ca,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50cc,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50ce,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50d0,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50d2,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50d4,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50d6,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50d8,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50da,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50dc,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50de,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50e0,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50e2,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50e4,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50e6,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50e8,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50ea,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50ec,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50ee,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50f0,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50f2,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50f4,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50f6,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50f8,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50fa,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50fc,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x50fe,0x1001,VR::CS,VM::VM1,"Curve Activation Layer","CurveActivationLayer",true }, {0x5000,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5002,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5004,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5006,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5008,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x500a,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x500c,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x500e,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5010,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5012,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5014,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5016,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5018,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x501a,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x501c,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x501e,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5020,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5022,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5024,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5026,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5028,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x502a,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x502c,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x502e,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5030,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5032,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5034,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5036,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5038,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x503a,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x503c,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x503e,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5040,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5042,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5044,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5046,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5048,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x504a,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x504c,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x504e,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5050,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5052,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5054,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5056,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5058,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x505a,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x505c,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x505e,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5060,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5062,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5064,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5066,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5068,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x506a,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x506c,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x506e,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5070,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5072,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5074,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5076,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5078,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x507a,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x507c,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x507e,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5080,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5082,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5084,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5086,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5088,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x508a,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x508c,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x508e,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5090,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5092,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5094,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5096,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5098,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x509a,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x509c,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x509e,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50a0,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50a2,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50a4,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50a6,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50a8,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50aa,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50ac,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50ae,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50b0,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50b2,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50b4,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50b6,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50b8,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50ba,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50bc,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50be,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50c0,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50c2,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50c4,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50c6,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50c8,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50ca,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50cc,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50ce,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50d0,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50d2,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50d4,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50d6,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50d8,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50da,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50dc,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50de,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50e0,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50e2,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50e4,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50e6,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50e8,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50ea,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50ec,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50ee,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50f0,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50f2,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50f4,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50f6,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50f8,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50fa,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50fc,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x50fe,0x2000,VR::US,VM::VM1,"Audio Type","AudioType",true }, {0x5000,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5002,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5004,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5006,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5008,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x500a,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x500c,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x500e,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5010,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5012,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5014,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5016,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5018,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x501a,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x501c,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x501e,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5020,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5022,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5024,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5026,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5028,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x502a,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x502c,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x502e,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5030,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5032,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5034,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5036,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5038,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x503a,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x503c,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x503e,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5040,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5042,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5044,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5046,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5048,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x504a,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x504c,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x504e,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5050,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5052,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5054,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5056,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5058,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x505a,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x505c,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x505e,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5060,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5062,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5064,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5066,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5068,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x506a,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x506c,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x506e,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5070,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5072,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5074,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5076,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5078,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x507a,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x507c,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x507e,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5080,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5082,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5084,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5086,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5088,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x508a,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x508c,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x508e,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5090,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5092,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5094,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5096,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5098,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x509a,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x509c,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x509e,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50a0,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50a2,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50a4,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50a6,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50a8,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50aa,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50ac,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50ae,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50b0,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50b2,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50b4,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50b6,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50b8,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50ba,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50bc,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50be,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50c0,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50c2,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50c4,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50c6,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50c8,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50ca,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50cc,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50ce,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50d0,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50d2,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50d4,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50d6,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50d8,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50da,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50dc,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50de,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50e0,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50e2,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50e4,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50e6,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50e8,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50ea,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50ec,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50ee,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50f0,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50f2,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50f4,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50f6,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50f8,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50fa,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50fc,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x50fe,0x2002,VR::US,VM::VM1,"Audio Sample Format","AudioSampleFormat",true }, {0x5000,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5002,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5004,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5006,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5008,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x500a,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x500c,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x500e,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5010,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5012,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5014,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5016,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5018,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x501a,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x501c,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x501e,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5020,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5022,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5024,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5026,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5028,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x502a,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x502c,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x502e,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5030,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5032,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5034,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5036,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5038,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x503a,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x503c,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x503e,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5040,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5042,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5044,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5046,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5048,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x504a,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x504c,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x504e,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5050,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5052,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5054,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5056,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5058,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x505a,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x505c,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x505e,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5060,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5062,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5064,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5066,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5068,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x506a,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x506c,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x506e,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5070,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5072,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5074,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5076,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5078,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x507a,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x507c,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x507e,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5080,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5082,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5084,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5086,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5088,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x508a,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x508c,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x508e,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5090,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5092,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5094,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5096,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5098,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x509a,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x509c,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x509e,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50a0,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50a2,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50a4,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50a6,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50a8,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50aa,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50ac,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50ae,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50b0,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50b2,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50b4,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50b6,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50b8,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50ba,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50bc,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50be,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50c0,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50c2,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50c4,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50c6,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50c8,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50ca,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50cc,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50ce,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50d0,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50d2,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50d4,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50d6,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50d8,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50da,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50dc,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50de,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50e0,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50e2,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50e4,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50e6,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50e8,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50ea,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50ec,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50ee,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50f0,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50f2,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50f4,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50f6,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50f8,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50fa,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50fc,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x50fe,0x2004,VR::US,VM::VM1,"Number of Channels","NumberOfChannels",true }, {0x5000,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5002,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5004,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5006,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5008,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x500a,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x500c,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x500e,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5010,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5012,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5014,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5016,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5018,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x501a,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x501c,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x501e,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5020,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5022,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5024,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5026,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5028,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x502a,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x502c,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x502e,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5030,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5032,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5034,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5036,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5038,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x503a,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x503c,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x503e,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5040,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5042,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5044,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5046,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5048,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x504a,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x504c,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x504e,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5050,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5052,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5054,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5056,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5058,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x505a,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x505c,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x505e,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5060,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5062,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5064,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5066,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5068,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x506a,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x506c,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x506e,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5070,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5072,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5074,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5076,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5078,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x507a,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x507c,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x507e,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5080,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5082,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5084,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5086,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5088,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x508a,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x508c,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x508e,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5090,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5092,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5094,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5096,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5098,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x509a,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x509c,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x509e,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50a0,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50a2,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50a4,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50a6,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50a8,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50aa,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50ac,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50ae,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50b0,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50b2,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50b4,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50b6,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50b8,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50ba,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50bc,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50be,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50c0,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50c2,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50c4,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50c6,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50c8,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50ca,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50cc,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50ce,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50d0,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50d2,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50d4,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50d6,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50d8,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50da,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50dc,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50de,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50e0,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50e2,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50e4,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50e6,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50e8,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50ea,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50ec,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50ee,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50f0,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50f2,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50f4,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50f6,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50f8,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50fa,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50fc,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x50fe,0x2006,VR::UL,VM::VM1,"Number of Samples","NumberOfSamples",true }, {0x5000,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5002,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5004,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5006,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5008,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x500a,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x500c,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x500e,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5010,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5012,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5014,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5016,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5018,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x501a,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x501c,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x501e,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5020,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5022,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5024,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5026,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5028,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x502a,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x502c,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x502e,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5030,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5032,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5034,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5036,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5038,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x503a,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x503c,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x503e,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5040,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5042,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5044,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5046,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5048,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x504a,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x504c,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x504e,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5050,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5052,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5054,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5056,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5058,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x505a,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x505c,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x505e,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5060,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5062,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5064,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5066,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5068,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x506a,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x506c,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x506e,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5070,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5072,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5074,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5076,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5078,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x507a,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x507c,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x507e,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5080,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5082,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5084,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5086,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5088,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x508a,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x508c,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x508e,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5090,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5092,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5094,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5096,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5098,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x509a,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x509c,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x509e,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50a0,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50a2,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50a4,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50a6,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50a8,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50aa,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50ac,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50ae,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50b0,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50b2,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50b4,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50b6,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50b8,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50ba,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50bc,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50be,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50c0,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50c2,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50c4,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50c6,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50c8,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50ca,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50cc,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50ce,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50d0,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50d2,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50d4,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50d6,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50d8,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50da,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50dc,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50de,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50e0,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50e2,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50e4,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50e6,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50e8,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50ea,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50ec,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50ee,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50f0,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50f2,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50f4,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50f6,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50f8,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50fa,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50fc,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x50fe,0x2008,VR::UL,VM::VM1,"Sample Rate","SampleRate",true }, {0x5000,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5002,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5004,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5006,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5008,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x500a,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x500c,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x500e,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5010,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5012,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5014,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5016,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5018,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x501a,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x501c,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x501e,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5020,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5022,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5024,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5026,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5028,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x502a,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x502c,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x502e,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5030,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5032,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5034,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5036,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5038,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x503a,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x503c,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x503e,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5040,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5042,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5044,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5046,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5048,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x504a,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x504c,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x504e,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5050,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5052,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5054,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5056,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5058,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x505a,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x505c,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x505e,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5060,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5062,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5064,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5066,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5068,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x506a,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x506c,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x506e,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5070,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5072,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5074,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5076,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5078,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x507a,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x507c,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x507e,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5080,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5082,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5084,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5086,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5088,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x508a,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x508c,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x508e,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5090,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5092,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5094,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5096,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5098,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x509a,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x509c,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x509e,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50a0,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50a2,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50a4,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50a6,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50a8,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50aa,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50ac,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50ae,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50b0,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50b2,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50b4,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50b6,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50b8,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50ba,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50bc,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50be,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50c0,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50c2,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50c4,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50c6,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50c8,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50ca,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50cc,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50ce,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50d0,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50d2,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50d4,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50d6,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50d8,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50da,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50dc,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50de,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50e0,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50e2,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50e4,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50e6,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50e8,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50ea,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50ec,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50ee,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50f0,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50f2,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50f4,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50f6,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50f8,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50fa,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50fc,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x50fe,0x200a,VR::UL,VM::VM1,"Total Time","TotalTime",true }, {0x5000,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5002,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5004,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5006,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5008,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x500a,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x500c,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x500e,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5010,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5012,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5014,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5016,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5018,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x501a,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x501c,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x501e,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5020,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5022,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5024,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5026,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5028,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x502a,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x502c,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x502e,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5030,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5032,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5034,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5036,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5038,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x503a,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x503c,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x503e,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5040,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5042,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5044,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5046,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5048,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x504a,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x504c,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x504e,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5050,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5052,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5054,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5056,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5058,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x505a,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x505c,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x505e,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5060,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5062,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5064,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5066,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5068,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x506a,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x506c,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x506e,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5070,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5072,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5074,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5076,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5078,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x507a,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x507c,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x507e,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5080,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5082,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5084,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5086,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5088,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x508a,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x508c,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x508e,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5090,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5092,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5094,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5096,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5098,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x509a,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x509c,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x509e,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50a0,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50a2,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50a4,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50a6,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50a8,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50aa,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50ac,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50ae,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50b0,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50b2,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50b4,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50b6,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50b8,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50ba,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50bc,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50be,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50c0,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50c2,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50c4,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50c6,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50c8,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50ca,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50cc,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50ce,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50d0,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50d2,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50d4,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50d6,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50d8,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50da,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50dc,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50de,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50e0,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50e2,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50e4,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50e6,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50e8,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50ea,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50ec,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50ee,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50f0,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50f2,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50f4,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50f6,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50f8,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50fa,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50fc,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x50fe,0x200c,VR::OB_OW,VM::VM1,"Audio Sample Data","AudioSampleData",true }, {0x5000,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5002,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5004,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5006,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5008,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x500a,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x500c,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x500e,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5010,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5012,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5014,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5016,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5018,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x501a,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x501c,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x501e,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5020,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5022,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5024,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5026,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5028,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x502a,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x502c,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x502e,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5030,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5032,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5034,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5036,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5038,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x503a,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x503c,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x503e,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5040,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5042,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5044,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5046,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5048,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x504a,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x504c,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x504e,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5050,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5052,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5054,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5056,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5058,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x505a,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x505c,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x505e,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5060,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5062,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5064,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5066,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5068,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x506a,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x506c,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x506e,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5070,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5072,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5074,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5076,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5078,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x507a,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x507c,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x507e,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5080,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5082,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5084,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5086,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5088,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x508a,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x508c,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x508e,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5090,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5092,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5094,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5096,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5098,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x509a,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x509c,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x509e,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50a0,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50a2,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50a4,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50a6,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50a8,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50aa,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50ac,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50ae,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50b0,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50b2,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50b4,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50b6,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50b8,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50ba,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50bc,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50be,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50c0,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50c2,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50c4,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50c6,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50c8,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50ca,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50cc,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50ce,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50d0,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50d2,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50d4,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50d6,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50d8,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50da,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50dc,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50de,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50e0,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50e2,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50e4,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50e6,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50e8,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50ea,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50ec,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50ee,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50f0,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50f2,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50f4,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50f6,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50f8,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50fa,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50fc,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x50fe,0x200e,VR::LT,VM::VM1,"Audio Comments","AudioComments",true }, {0x5000,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5002,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5004,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5006,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5008,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x500a,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x500c,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x500e,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5010,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5012,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5014,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5016,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5018,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x501a,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x501c,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x501e,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5020,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5022,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5024,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5026,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5028,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x502a,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x502c,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x502e,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5030,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5032,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5034,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5036,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5038,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x503a,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x503c,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x503e,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5040,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5042,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5044,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5046,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5048,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x504a,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x504c,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x504e,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5050,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5052,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5054,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5056,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5058,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x505a,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x505c,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x505e,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5060,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5062,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5064,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5066,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5068,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x506a,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x506c,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x506e,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5070,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5072,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5074,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5076,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5078,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x507a,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x507c,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x507e,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5080,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5082,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5084,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5086,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5088,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x508a,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x508c,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x508e,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5090,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5092,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5094,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5096,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5098,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x509a,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x509c,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x509e,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50a0,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50a2,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50a4,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50a6,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50a8,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50aa,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50ac,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50ae,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50b0,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50b2,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50b4,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50b6,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50b8,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50ba,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50bc,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50be,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50c0,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50c2,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50c4,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50c6,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50c8,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50ca,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50cc,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50ce,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50d0,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50d2,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50d4,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50d6,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50d8,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50da,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50dc,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50de,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50e0,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50e2,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50e4,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50e6,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50e8,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50ea,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50ec,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50ee,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50f0,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50f2,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50f4,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50f6,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50f8,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50fa,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50fc,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x50fe,0x2500,VR::LO,VM::VM1,"Curve Label","CurveLabel",true }, {0x5000,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5002,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5004,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5006,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5008,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x500a,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x500c,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x500e,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5010,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5012,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5014,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5016,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5018,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x501a,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x501c,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x501e,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5020,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5022,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5024,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5026,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5028,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x502a,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x502c,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x502e,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5030,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5032,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5034,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5036,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5038,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x503a,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x503c,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x503e,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5040,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5042,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5044,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5046,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5048,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x504a,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x504c,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x504e,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5050,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5052,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5054,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5056,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5058,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x505a,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x505c,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x505e,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5060,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5062,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5064,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5066,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5068,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x506a,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x506c,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x506e,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5070,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5072,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5074,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5076,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5078,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x507a,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x507c,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x507e,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5080,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5082,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5084,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5086,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5088,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x508a,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x508c,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x508e,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5090,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5092,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5094,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5096,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5098,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x509a,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x509c,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x509e,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50a0,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50a2,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50a4,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50a6,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50a8,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50aa,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50ac,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50ae,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50b0,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50b2,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50b4,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50b6,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50b8,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50ba,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50bc,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50be,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50c0,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50c2,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50c4,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50c6,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50c8,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50ca,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50cc,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50ce,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50d0,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50d2,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50d4,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50d6,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50d8,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50da,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50dc,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50de,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50e0,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50e2,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50e4,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50e6,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50e8,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50ea,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50ec,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50ee,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50f0,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50f2,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50f4,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50f6,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50f8,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50fa,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50fc,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x50fe,0x2600,VR::SQ,VM::VM1,"Curve Referenced Overlay Sequence","CurveReferencedOverlaySequence",true }, {0x5000,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5002,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5004,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5006,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5008,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x500a,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x500c,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x500e,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5010,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5012,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5014,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5016,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5018,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x501a,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x501c,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x501e,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5020,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5022,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5024,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5026,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5028,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x502a,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x502c,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x502e,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5030,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5032,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5034,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5036,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5038,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x503a,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x503c,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x503e,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5040,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5042,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5044,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5046,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5048,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x504a,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x504c,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x504e,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5050,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5052,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5054,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5056,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5058,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x505a,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x505c,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x505e,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5060,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5062,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5064,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5066,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5068,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x506a,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x506c,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x506e,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5070,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5072,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5074,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5076,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5078,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x507a,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x507c,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x507e,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5080,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5082,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5084,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5086,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5088,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x508a,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x508c,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x508e,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5090,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5092,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5094,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5096,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5098,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x509a,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x509c,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x509e,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50a0,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50a2,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50a4,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50a6,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50a8,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50aa,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50ac,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50ae,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50b0,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50b2,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50b4,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50b6,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50b8,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50ba,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50bc,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50be,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50c0,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50c2,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50c4,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50c6,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50c8,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50ca,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50cc,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50ce,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50d0,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50d2,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50d4,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50d6,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50d8,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50da,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50dc,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50de,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50e0,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50e2,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50e4,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50e6,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50e8,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50ea,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50ec,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50ee,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50f0,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50f2,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50f4,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50f6,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50f8,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50fa,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50fc,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x50fe,0x2610,VR::US,VM::VM1,"Curve Referenced Overlay Group","CurveReferencedOverlayGroup",true }, {0x5000,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5002,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5004,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5006,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5008,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x500a,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x500c,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x500e,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5010,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5012,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5014,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5016,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5018,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x501a,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x501c,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x501e,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5020,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5022,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5024,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5026,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5028,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x502a,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x502c,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x502e,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5030,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5032,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5034,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5036,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5038,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x503a,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x503c,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x503e,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5040,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5042,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5044,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5046,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5048,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x504a,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x504c,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x504e,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5050,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5052,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5054,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5056,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5058,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x505a,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x505c,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x505e,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5060,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5062,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5064,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5066,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5068,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x506a,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x506c,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x506e,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5070,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5072,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5074,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5076,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5078,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x507a,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x507c,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x507e,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5080,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5082,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5084,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5086,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5088,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x508a,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x508c,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x508e,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5090,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5092,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5094,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5096,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5098,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x509a,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x509c,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x509e,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50a0,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50a2,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50a4,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50a6,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50a8,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50aa,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50ac,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50ae,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50b0,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50b2,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50b4,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50b6,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50b8,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50ba,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50bc,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50be,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50c0,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50c2,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50c4,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50c6,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50c8,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50ca,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50cc,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50ce,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50d0,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50d2,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50d4,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50d6,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50d8,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50da,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50dc,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50de,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50e0,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50e2,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50e4,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50e6,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50e8,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50ea,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50ec,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50ee,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50f0,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50f2,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50f4,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50f6,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50f8,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50fa,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50fc,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x50fe,0x3000,VR::OB_OW,VM::VM1,"Curve Data","CurveData",true }, {0x5200,0x9229,VR::SQ,VM::VM1,"Shared Functional Groups Sequence","SharedFunctionalGroupsSequence",false }, {0x5200,0x9230,VR::SQ,VM::VM1,"Per-frame Functional Groups Sequence","PerFrameFunctionalGroupsSequence",false }, {0x5400,0x0100,VR::SQ,VM::VM1,"Waveform Sequence","WaveformSequence",false }, {0x5400,0x0110,VR::OB_OW,VM::VM1,"Channel Minimum Value","ChannelMinimumValue",false }, {0x5400,0x0112,VR::OB_OW,VM::VM1,"Channel Maximum Value","ChannelMaximumValue",false }, {0x5400,0x1004,VR::US,VM::VM1,"Waveform Bits Allocated","WaveformBitsAllocated",false }, {0x5400,0x1006,VR::CS,VM::VM1,"Waveform Sample Interpretation","WaveformSampleInterpretation",false }, {0x5400,0x100a,VR::OB_OW,VM::VM1,"Waveform Padding Value","WaveformPaddingValue",false }, {0x5400,0x1010,VR::OB_OW,VM::VM1,"Waveform Data","WaveformData",false }, {0x5600,0x0010,VR::OF,VM::VM1,"First Order Phase Correction Angle","FirstOrderPhaseCorrectionAngle",false }, {0x5600,0x0020,VR::OF,VM::VM1,"Spectroscopy Data","SpectroscopyData",false }, {0x6000,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6002,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6004,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6006,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6008,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x600a,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x600c,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x600e,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6010,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6012,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6014,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6016,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6018,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x601a,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x601c,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x601e,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6020,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6022,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6024,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6026,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6028,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x602a,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x602c,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x602e,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6030,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6032,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6034,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6036,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6038,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x603a,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x603c,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x603e,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6040,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6042,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6044,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6046,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6048,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x604a,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x604c,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x604e,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6050,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6052,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6054,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6056,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6058,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x605a,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x605c,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x605e,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6060,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6062,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6064,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6066,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6068,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x606a,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x606c,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x606e,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6070,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6072,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6074,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6076,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6078,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x607a,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x607c,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x607e,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6080,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6082,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6084,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6086,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6088,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x608a,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x608c,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x608e,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6090,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6092,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6094,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6096,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6098,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x609a,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x609c,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x609e,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60a0,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60a2,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60a4,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60a6,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60a8,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60aa,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60ac,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60ae,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60b0,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60b2,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60b4,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60b6,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60b8,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60ba,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60bc,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60be,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60c0,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60c2,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60c4,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60c6,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60c8,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60ca,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60cc,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60ce,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60d0,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60d2,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60d4,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60d6,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60d8,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60da,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60dc,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60de,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60e0,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60e2,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60e4,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60e6,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60e8,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60ea,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60ec,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60ee,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60f0,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60f2,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60f4,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60f6,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60f8,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60fa,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60fc,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x60fe,0x0010,VR::US,VM::VM1,"Overlay Rows","OverlayRows",false }, {0x6000,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6002,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6004,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6006,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6008,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x600a,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x600c,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x600e,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6010,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6012,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6014,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6016,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6018,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x601a,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x601c,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x601e,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6020,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6022,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6024,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6026,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6028,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x602a,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x602c,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x602e,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6030,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6032,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6034,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6036,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6038,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x603a,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x603c,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x603e,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6040,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6042,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6044,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6046,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6048,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x604a,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x604c,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x604e,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6050,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6052,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6054,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6056,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6058,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x605a,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x605c,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x605e,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6060,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6062,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6064,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6066,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6068,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x606a,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x606c,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x606e,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6070,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6072,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6074,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6076,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6078,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x607a,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x607c,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x607e,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6080,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6082,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6084,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6086,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6088,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x608a,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x608c,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x608e,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6090,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6092,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6094,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6096,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6098,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x609a,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x609c,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x609e,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60a0,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60a2,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60a4,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60a6,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60a8,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60aa,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60ac,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60ae,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60b0,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60b2,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60b4,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60b6,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60b8,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60ba,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60bc,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60be,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60c0,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60c2,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60c4,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60c6,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60c8,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60ca,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60cc,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60ce,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60d0,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60d2,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60d4,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60d6,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60d8,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60da,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60dc,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60de,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60e0,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60e2,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60e4,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60e6,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60e8,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60ea,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60ec,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60ee,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60f0,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60f2,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60f4,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60f6,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60f8,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60fa,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60fc,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x60fe,0x0011,VR::US,VM::VM1,"Overlay Columns","OverlayColumns",false }, {0x6000,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6002,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6004,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6006,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6008,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x600a,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x600c,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x600e,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6010,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6012,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6014,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6016,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6018,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x601a,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x601c,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x601e,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6020,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6022,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6024,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6026,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6028,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x602a,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x602c,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x602e,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6030,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6032,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6034,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6036,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6038,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x603a,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x603c,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x603e,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6040,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6042,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6044,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6046,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6048,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x604a,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x604c,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x604e,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6050,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6052,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6054,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6056,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6058,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x605a,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x605c,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x605e,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6060,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6062,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6064,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6066,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6068,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x606a,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x606c,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x606e,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6070,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6072,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6074,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6076,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6078,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x607a,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x607c,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x607e,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6080,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6082,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6084,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6086,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6088,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x608a,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x608c,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x608e,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6090,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6092,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6094,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6096,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6098,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x609a,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x609c,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x609e,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60a0,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60a2,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60a4,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60a6,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60a8,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60aa,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60ac,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60ae,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60b0,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60b2,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60b4,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60b6,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60b8,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60ba,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60bc,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60be,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60c0,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60c2,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60c4,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60c6,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60c8,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60ca,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60cc,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60ce,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60d0,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60d2,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60d4,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60d6,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60d8,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60da,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60dc,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60de,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60e0,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60e2,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60e4,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60e6,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60e8,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60ea,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60ec,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60ee,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60f0,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60f2,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60f4,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60f6,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60f8,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60fa,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60fc,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x60fe,0x0012,VR::US,VM::VM1,"Overlay Planes","OverlayPlanes",true }, {0x6000,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6002,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6004,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6006,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6008,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x600a,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x600c,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x600e,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6010,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6012,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6014,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6016,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6018,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x601a,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x601c,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x601e,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6020,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6022,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6024,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6026,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6028,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x602a,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x602c,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x602e,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6030,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6032,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6034,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6036,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6038,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x603a,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x603c,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x603e,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6040,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6042,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6044,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6046,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6048,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x604a,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x604c,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x604e,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6050,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6052,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6054,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6056,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6058,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x605a,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x605c,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x605e,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6060,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6062,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6064,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6066,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6068,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x606a,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x606c,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x606e,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6070,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6072,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6074,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6076,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6078,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x607a,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x607c,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x607e,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6080,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6082,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6084,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6086,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6088,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x608a,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x608c,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x608e,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6090,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6092,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6094,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6096,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6098,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x609a,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x609c,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x609e,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60a0,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60a2,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60a4,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60a6,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60a8,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60aa,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60ac,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60ae,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60b0,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60b2,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60b4,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60b6,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60b8,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60ba,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60bc,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60be,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60c0,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60c2,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60c4,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60c6,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60c8,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60ca,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60cc,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60ce,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60d0,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60d2,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60d4,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60d6,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60d8,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60da,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60dc,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60de,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60e0,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60e2,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60e4,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60e6,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60e8,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60ea,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60ec,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60ee,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60f0,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60f2,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60f4,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60f6,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60f8,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60fa,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60fc,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x60fe,0x0015,VR::IS,VM::VM1,"Number of Frames in Overlay","NumberOfFramesInOverlay",false }, {0x6000,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6002,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6004,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6006,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6008,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x600a,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x600c,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x600e,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6010,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6012,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6014,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6016,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6018,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x601a,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x601c,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x601e,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6020,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6022,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6024,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6026,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6028,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x602a,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x602c,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x602e,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6030,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6032,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6034,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6036,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6038,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x603a,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x603c,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x603e,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6040,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6042,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6044,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6046,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6048,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x604a,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x604c,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x604e,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6050,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6052,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6054,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6056,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6058,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x605a,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x605c,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x605e,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6060,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6062,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6064,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6066,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6068,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x606a,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x606c,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x606e,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6070,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6072,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6074,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6076,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6078,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x607a,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x607c,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x607e,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6080,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6082,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6084,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6086,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6088,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x608a,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x608c,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x608e,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6090,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6092,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6094,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6096,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6098,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x609a,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x609c,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x609e,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60a0,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60a2,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60a4,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60a6,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60a8,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60aa,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60ac,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60ae,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60b0,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60b2,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60b4,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60b6,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60b8,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60ba,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60bc,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60be,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60c0,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60c2,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60c4,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60c6,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60c8,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60ca,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60cc,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60ce,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60d0,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60d2,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60d4,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60d6,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60d8,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60da,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60dc,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60de,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60e0,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60e2,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60e4,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60e6,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60e8,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60ea,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60ec,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60ee,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60f0,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60f2,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60f4,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60f6,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60f8,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60fa,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60fc,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x60fe,0x0022,VR::LO,VM::VM1,"Overlay Description","OverlayDescription",false }, {0x6000,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6002,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6004,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6006,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6008,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x600a,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x600c,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x600e,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6010,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6012,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6014,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6016,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6018,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x601a,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x601c,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x601e,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6020,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6022,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6024,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6026,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6028,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x602a,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x602c,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x602e,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6030,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6032,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6034,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6036,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6038,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x603a,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x603c,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x603e,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6040,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6042,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6044,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6046,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6048,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x604a,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x604c,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x604e,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6050,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6052,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6054,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6056,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6058,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x605a,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x605c,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x605e,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6060,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6062,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6064,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6066,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6068,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x606a,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x606c,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x606e,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6070,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6072,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6074,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6076,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6078,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x607a,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x607c,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x607e,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6080,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6082,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6084,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6086,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6088,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x608a,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x608c,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x608e,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6090,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6092,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6094,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6096,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6098,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x609a,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x609c,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x609e,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60a0,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60a2,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60a4,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60a6,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60a8,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60aa,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60ac,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60ae,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60b0,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60b2,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60b4,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60b6,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60b8,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60ba,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60bc,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60be,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60c0,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60c2,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60c4,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60c6,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60c8,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60ca,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60cc,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60ce,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60d0,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60d2,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60d4,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60d6,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60d8,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60da,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60dc,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60de,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60e0,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60e2,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60e4,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60e6,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60e8,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60ea,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60ec,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60ee,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60f0,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60f2,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60f4,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60f6,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60f8,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60fa,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60fc,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x60fe,0x0040,VR::CS,VM::VM1,"Overlay Type","OverlayType",false }, {0x6000,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6002,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6004,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6006,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6008,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x600a,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x600c,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x600e,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6010,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6012,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6014,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6016,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6018,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x601a,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x601c,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x601e,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6020,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6022,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6024,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6026,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6028,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x602a,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x602c,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x602e,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6030,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6032,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6034,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6036,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6038,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x603a,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x603c,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x603e,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6040,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6042,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6044,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6046,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6048,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x604a,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x604c,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x604e,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6050,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6052,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6054,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6056,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6058,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x605a,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x605c,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x605e,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6060,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6062,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6064,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6066,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6068,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x606a,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x606c,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x606e,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6070,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6072,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6074,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6076,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6078,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x607a,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x607c,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x607e,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6080,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6082,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6084,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6086,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6088,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x608a,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x608c,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x608e,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6090,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6092,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6094,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6096,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6098,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x609a,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x609c,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x609e,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60a0,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60a2,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60a4,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60a6,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60a8,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60aa,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60ac,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60ae,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60b0,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60b2,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60b4,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60b6,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60b8,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60ba,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60bc,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60be,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60c0,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60c2,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60c4,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60c6,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60c8,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60ca,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60cc,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60ce,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60d0,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60d2,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60d4,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60d6,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60d8,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60da,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60dc,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60de,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60e0,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60e2,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60e4,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60e6,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60e8,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60ea,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60ec,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60ee,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60f0,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60f2,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60f4,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60f6,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60f8,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60fa,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60fc,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x60fe,0x0045,VR::LO,VM::VM1,"Overlay Subtype","OverlaySubtype",false }, {0x6000,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6002,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6004,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6006,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6008,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x600a,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x600c,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x600e,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6010,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6012,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6014,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6016,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6018,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x601a,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x601c,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x601e,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6020,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6022,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6024,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6026,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6028,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x602a,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x602c,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x602e,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6030,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6032,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6034,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6036,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6038,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x603a,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x603c,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x603e,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6040,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6042,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6044,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6046,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6048,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x604a,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x604c,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x604e,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6050,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6052,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6054,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6056,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6058,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x605a,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x605c,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x605e,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6060,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6062,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6064,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6066,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6068,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x606a,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x606c,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x606e,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6070,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6072,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6074,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6076,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6078,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x607a,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x607c,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x607e,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6080,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6082,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6084,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6086,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6088,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x608a,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x608c,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x608e,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6090,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6092,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6094,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6096,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6098,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x609a,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x609c,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x609e,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60a0,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60a2,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60a4,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60a6,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60a8,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60aa,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60ac,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60ae,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60b0,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60b2,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60b4,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60b6,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60b8,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60ba,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60bc,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60be,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60c0,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60c2,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60c4,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60c6,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60c8,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60ca,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60cc,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60ce,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60d0,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60d2,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60d4,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60d6,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60d8,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60da,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60dc,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60de,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60e0,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60e2,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60e4,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60e6,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60e8,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60ea,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60ec,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60ee,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60f0,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60f2,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60f4,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60f6,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60f8,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60fa,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60fc,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x60fe,0x0050,VR::SS,VM::VM2,"Overlay Origin","OverlayOrigin",false }, {0x6000,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6002,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6004,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6006,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6008,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x600a,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x600c,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x600e,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6010,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6012,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6014,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6016,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6018,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x601a,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x601c,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x601e,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6020,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6022,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6024,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6026,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6028,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x602a,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x602c,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x602e,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6030,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6032,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6034,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6036,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6038,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x603a,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x603c,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x603e,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6040,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6042,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6044,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6046,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6048,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x604a,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x604c,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x604e,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6050,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6052,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6054,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6056,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6058,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x605a,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x605c,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x605e,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6060,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6062,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6064,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6066,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6068,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x606a,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x606c,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x606e,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6070,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6072,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6074,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6076,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6078,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x607a,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x607c,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x607e,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6080,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6082,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6084,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6086,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6088,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x608a,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x608c,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x608e,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6090,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6092,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6094,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6096,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6098,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x609a,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x609c,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x609e,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60a0,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60a2,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60a4,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60a6,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60a8,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60aa,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60ac,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60ae,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60b0,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60b2,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60b4,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60b6,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60b8,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60ba,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60bc,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60be,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60c0,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60c2,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60c4,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60c6,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60c8,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60ca,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60cc,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60ce,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60d0,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60d2,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60d4,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60d6,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60d8,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60da,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60dc,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60de,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60e0,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60e2,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60e4,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60e6,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60e8,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60ea,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60ec,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60ee,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60f0,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60f2,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60f4,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60f6,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60f8,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60fa,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60fc,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x60fe,0x0051,VR::US,VM::VM1,"Image Frame Origin","ImageFrameOrigin",false }, {0x6000,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6002,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6004,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6006,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6008,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x600a,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x600c,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x600e,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6010,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6012,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6014,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6016,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6018,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x601a,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x601c,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x601e,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6020,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6022,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6024,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6026,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6028,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x602a,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x602c,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x602e,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6030,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6032,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6034,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6036,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6038,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x603a,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x603c,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x603e,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6040,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6042,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6044,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6046,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6048,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x604a,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x604c,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x604e,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6050,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6052,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6054,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6056,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6058,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x605a,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x605c,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x605e,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6060,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6062,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6064,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6066,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6068,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x606a,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x606c,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x606e,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6070,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6072,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6074,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6076,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6078,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x607a,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x607c,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x607e,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6080,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6082,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6084,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6086,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6088,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x608a,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x608c,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x608e,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6090,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6092,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6094,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6096,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6098,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x609a,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x609c,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x609e,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60a0,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60a2,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60a4,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60a6,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60a8,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60aa,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60ac,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60ae,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60b0,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60b2,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60b4,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60b6,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60b8,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60ba,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60bc,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60be,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60c0,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60c2,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60c4,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60c6,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60c8,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60ca,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60cc,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60ce,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60d0,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60d2,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60d4,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60d6,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60d8,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60da,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60dc,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60de,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60e0,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60e2,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60e4,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60e6,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60e8,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60ea,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60ec,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60ee,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60f0,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60f2,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60f4,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60f6,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60f8,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60fa,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60fc,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x60fe,0x0052,VR::US,VM::VM1,"Overlay Plane Origin","OverlayPlaneOrigin",true }, {0x6000,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6002,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6004,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6006,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6008,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x600a,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x600c,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x600e,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6010,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6012,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6014,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6016,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6018,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x601a,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x601c,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x601e,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6020,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6022,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6024,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6026,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6028,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x602a,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x602c,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x602e,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6030,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6032,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6034,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6036,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6038,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x603a,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x603c,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x603e,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6040,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6042,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6044,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6046,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6048,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x604a,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x604c,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x604e,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6050,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6052,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6054,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6056,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6058,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x605a,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x605c,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x605e,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6060,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6062,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6064,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6066,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6068,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x606a,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x606c,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x606e,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6070,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6072,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6074,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6076,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6078,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x607a,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x607c,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x607e,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6080,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6082,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6084,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6086,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6088,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x608a,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x608c,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x608e,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6090,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6092,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6094,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6096,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6098,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x609a,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x609c,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x609e,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60a0,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60a2,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60a4,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60a6,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60a8,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60aa,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60ac,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60ae,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60b0,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60b2,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60b4,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60b6,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60b8,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60ba,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60bc,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60be,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60c0,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60c2,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60c4,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60c6,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60c8,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60ca,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60cc,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60ce,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60d0,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60d2,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60d4,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60d6,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60d8,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60da,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60dc,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60de,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60e0,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60e2,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60e4,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60e6,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60e8,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60ea,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60ec,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60ee,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60f0,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60f2,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60f4,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60f6,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60f8,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60fa,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60fc,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x60fe,0x0060,VR::CS,VM::VM1,"Overlay Compression Code","OverlayCompressionCode",true }, {0x6000,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6002,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6004,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6006,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6008,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x600a,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x600c,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x600e,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6010,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6012,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6014,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6016,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6018,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x601a,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x601c,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x601e,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6020,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6022,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6024,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6026,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6028,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x602a,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x602c,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x602e,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6030,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6032,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6034,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6036,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6038,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x603a,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x603c,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x603e,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6040,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6042,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6044,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6046,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6048,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x604a,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x604c,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x604e,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6050,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6052,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6054,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6056,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6058,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x605a,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x605c,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x605e,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6060,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6062,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6064,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6066,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6068,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x606a,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x606c,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x606e,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6070,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6072,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6074,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6076,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6078,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x607a,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x607c,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x607e,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6080,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6082,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6084,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6086,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6088,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x608a,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x608c,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x608e,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6090,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6092,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6094,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6096,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6098,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x609a,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x609c,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x609e,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60a0,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60a2,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60a4,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60a6,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60a8,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60aa,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60ac,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60ae,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60b0,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60b2,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60b4,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60b6,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60b8,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60ba,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60bc,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60be,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60c0,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60c2,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60c4,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60c6,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60c8,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60ca,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60cc,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60ce,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60d0,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60d2,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60d4,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60d6,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60d8,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60da,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60dc,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60de,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60e0,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60e2,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60e4,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60e6,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60e8,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60ea,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60ec,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60ee,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60f0,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60f2,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60f4,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60f6,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60f8,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60fa,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60fc,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x60fe,0x0061,VR::SH,VM::VM1,"Overlay Compression Originator","OverlayCompressionOriginator",true }, {0x6000,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6002,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6004,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6006,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6008,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x600a,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x600c,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x600e,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6010,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6012,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6014,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6016,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6018,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x601a,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x601c,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x601e,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6020,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6022,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6024,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6026,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6028,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x602a,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x602c,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x602e,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6030,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6032,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6034,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6036,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6038,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x603a,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x603c,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x603e,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6040,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6042,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6044,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6046,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6048,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x604a,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x604c,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x604e,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6050,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6052,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6054,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6056,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6058,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x605a,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x605c,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x605e,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6060,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6062,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6064,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6066,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6068,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x606a,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x606c,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x606e,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6070,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6072,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6074,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6076,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6078,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x607a,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x607c,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x607e,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6080,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6082,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6084,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6086,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6088,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x608a,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x608c,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x608e,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6090,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6092,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6094,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6096,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6098,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x609a,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x609c,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x609e,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60a0,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60a2,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60a4,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60a6,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60a8,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60aa,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60ac,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60ae,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60b0,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60b2,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60b4,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60b6,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60b8,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60ba,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60bc,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60be,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60c0,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60c2,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60c4,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60c6,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60c8,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60ca,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60cc,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60ce,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60d0,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60d2,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60d4,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60d6,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60d8,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60da,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60dc,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60de,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60e0,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60e2,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60e4,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60e6,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60e8,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60ea,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60ec,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60ee,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60f0,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60f2,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60f4,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60f6,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60f8,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60fa,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60fc,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x60fe,0x0062,VR::SH,VM::VM1,"Overlay Compression Label","OverlayCompressionLabel",true }, {0x6000,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6002,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6004,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6006,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6008,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x600a,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x600c,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x600e,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6010,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6012,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6014,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6016,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6018,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x601a,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x601c,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x601e,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6020,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6022,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6024,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6026,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6028,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x602a,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x602c,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x602e,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6030,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6032,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6034,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6036,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6038,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x603a,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x603c,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x603e,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6040,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6042,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6044,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6046,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6048,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x604a,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x604c,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x604e,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6050,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6052,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6054,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6056,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6058,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x605a,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x605c,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x605e,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6060,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6062,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6064,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6066,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6068,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x606a,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x606c,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x606e,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6070,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6072,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6074,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6076,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6078,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x607a,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x607c,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x607e,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6080,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6082,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6084,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6086,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6088,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x608a,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x608c,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x608e,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6090,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6092,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6094,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6096,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6098,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x609a,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x609c,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x609e,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60a0,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60a2,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60a4,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60a6,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60a8,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60aa,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60ac,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60ae,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60b0,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60b2,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60b4,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60b6,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60b8,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60ba,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60bc,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60be,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60c0,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60c2,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60c4,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60c6,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60c8,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60ca,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60cc,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60ce,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60d0,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60d2,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60d4,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60d6,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60d8,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60da,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60dc,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60de,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60e0,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60e2,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60e4,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60e6,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60e8,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60ea,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60ec,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60ee,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60f0,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60f2,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60f4,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60f6,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60f8,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60fa,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60fc,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x60fe,0x0063,VR::CS,VM::VM1,"Overlay Compression Description","OverlayCompressionDescription",true }, {0x6000,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6002,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6004,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6006,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6008,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x600a,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x600c,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x600e,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6010,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6012,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6014,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6016,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6018,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x601a,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x601c,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x601e,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6020,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6022,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6024,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6026,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6028,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x602a,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x602c,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x602e,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6030,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6032,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6034,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6036,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6038,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x603a,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x603c,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x603e,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6040,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6042,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6044,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6046,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6048,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x604a,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x604c,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x604e,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6050,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6052,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6054,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6056,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6058,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x605a,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x605c,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x605e,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6060,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6062,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6064,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6066,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6068,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x606a,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x606c,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x606e,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6070,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6072,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6074,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6076,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6078,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x607a,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x607c,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x607e,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6080,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6082,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6084,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6086,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6088,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x608a,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x608c,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x608e,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6090,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6092,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6094,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6096,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6098,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x609a,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x609c,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x609e,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60a0,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60a2,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60a4,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60a6,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60a8,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60aa,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60ac,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60ae,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60b0,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60b2,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60b4,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60b6,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60b8,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60ba,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60bc,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60be,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60c0,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60c2,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60c4,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60c6,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60c8,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60ca,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60cc,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60ce,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60d0,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60d2,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60d4,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60d6,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60d8,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60da,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60dc,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60de,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60e0,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60e2,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60e4,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60e6,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60e8,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60ea,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60ec,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60ee,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60f0,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60f2,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60f4,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60f6,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60f8,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60fa,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60fc,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x60fe,0x0066,VR::AT,VM::VM1_n,"Overlay Compression Step Pointers","OverlayCompressionStepPointers",true }, {0x6000,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6002,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6004,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6006,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6008,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x600a,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x600c,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x600e,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6010,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6012,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6014,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6016,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6018,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x601a,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x601c,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x601e,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6020,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6022,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6024,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6026,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6028,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x602a,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x602c,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x602e,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6030,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6032,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6034,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6036,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6038,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x603a,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x603c,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x603e,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6040,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6042,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6044,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6046,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6048,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x604a,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x604c,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x604e,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6050,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6052,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6054,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6056,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6058,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x605a,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x605c,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x605e,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6060,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6062,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6064,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6066,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6068,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x606a,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x606c,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x606e,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6070,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6072,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6074,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6076,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6078,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x607a,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x607c,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x607e,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6080,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6082,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6084,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6086,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6088,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x608a,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x608c,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x608e,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6090,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6092,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6094,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6096,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6098,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x609a,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x609c,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x609e,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60a0,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60a2,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60a4,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60a6,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60a8,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60aa,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60ac,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60ae,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60b0,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60b2,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60b4,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60b6,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60b8,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60ba,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60bc,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60be,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60c0,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60c2,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60c4,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60c6,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60c8,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60ca,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60cc,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60ce,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60d0,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60d2,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60d4,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60d6,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60d8,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60da,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60dc,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60de,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60e0,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60e2,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60e4,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60e6,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60e8,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60ea,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60ec,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60ee,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60f0,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60f2,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60f4,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60f6,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60f8,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60fa,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60fc,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x60fe,0x0068,VR::US,VM::VM1,"Overlay Repeat Interval","OverlayRepeatInterval",true }, {0x6000,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6002,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6004,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6006,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6008,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x600a,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x600c,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x600e,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6010,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6012,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6014,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6016,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6018,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x601a,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x601c,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x601e,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6020,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6022,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6024,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6026,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6028,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x602a,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x602c,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x602e,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6030,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6032,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6034,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6036,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6038,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x603a,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x603c,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x603e,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6040,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6042,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6044,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6046,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6048,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x604a,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x604c,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x604e,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6050,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6052,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6054,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6056,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6058,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x605a,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x605c,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x605e,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6060,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6062,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6064,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6066,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6068,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x606a,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x606c,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x606e,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6070,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6072,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6074,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6076,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6078,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x607a,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x607c,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x607e,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6080,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6082,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6084,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6086,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6088,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x608a,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x608c,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x608e,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6090,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6092,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6094,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6096,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6098,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x609a,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x609c,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x609e,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60a0,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60a2,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60a4,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60a6,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60a8,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60aa,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60ac,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60ae,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60b0,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60b2,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60b4,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60b6,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60b8,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60ba,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60bc,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60be,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60c0,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60c2,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60c4,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60c6,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60c8,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60ca,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60cc,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60ce,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60d0,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60d2,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60d4,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60d6,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60d8,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60da,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60dc,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60de,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60e0,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60e2,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60e4,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60e6,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60e8,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60ea,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60ec,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60ee,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60f0,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60f2,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60f4,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60f6,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60f8,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60fa,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60fc,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x60fe,0x0069,VR::US,VM::VM1,"Overlay Bits Grouped","OverlayBitsGrouped",true }, {0x6000,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6002,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6004,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6006,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6008,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x600a,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x600c,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x600e,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6010,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6012,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6014,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6016,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6018,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x601a,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x601c,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x601e,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6020,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6022,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6024,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6026,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6028,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x602a,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x602c,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x602e,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6030,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6032,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6034,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6036,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6038,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x603a,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x603c,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x603e,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6040,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6042,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6044,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6046,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6048,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x604a,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x604c,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x604e,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6050,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6052,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6054,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6056,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6058,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x605a,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x605c,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x605e,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6060,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6062,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6064,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6066,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6068,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x606a,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x606c,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x606e,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6070,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6072,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6074,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6076,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6078,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x607a,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x607c,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x607e,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6080,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6082,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6084,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6086,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6088,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x608a,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x608c,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x608e,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6090,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6092,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6094,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6096,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6098,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x609a,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x609c,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x609e,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60a0,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60a2,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60a4,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60a6,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60a8,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60aa,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60ac,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60ae,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60b0,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60b2,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60b4,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60b6,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60b8,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60ba,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60bc,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60be,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60c0,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60c2,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60c4,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60c6,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60c8,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60ca,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60cc,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60ce,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60d0,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60d2,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60d4,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60d6,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60d8,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60da,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60dc,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60de,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60e0,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60e2,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60e4,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60e6,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60e8,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60ea,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60ec,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60ee,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60f0,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60f2,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60f4,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60f6,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60f8,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60fa,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60fc,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x60fe,0x0100,VR::US,VM::VM1,"Overlay Bits Allocated","OverlayBitsAllocated",false }, {0x6000,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6002,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6004,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6006,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6008,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x600a,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x600c,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x600e,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6010,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6012,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6014,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6016,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6018,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x601a,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x601c,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x601e,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6020,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6022,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6024,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6026,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6028,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x602a,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x602c,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x602e,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6030,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6032,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6034,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6036,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6038,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x603a,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x603c,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x603e,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6040,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6042,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6044,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6046,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6048,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x604a,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x604c,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x604e,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6050,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6052,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6054,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6056,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6058,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x605a,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x605c,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x605e,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6060,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6062,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6064,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6066,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6068,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x606a,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x606c,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x606e,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6070,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6072,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6074,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6076,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6078,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x607a,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x607c,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x607e,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6080,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6082,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6084,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6086,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6088,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x608a,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x608c,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x608e,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6090,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6092,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6094,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6096,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6098,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x609a,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x609c,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x609e,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60a0,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60a2,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60a4,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60a6,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60a8,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60aa,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60ac,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60ae,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60b0,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60b2,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60b4,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60b6,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60b8,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60ba,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60bc,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60be,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60c0,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60c2,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60c4,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60c6,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60c8,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60ca,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60cc,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60ce,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60d0,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60d2,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60d4,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60d6,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60d8,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60da,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60dc,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60de,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60e0,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60e2,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60e4,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60e6,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60e8,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60ea,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60ec,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60ee,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60f0,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60f2,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60f4,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60f6,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60f8,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60fa,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60fc,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x60fe,0x0102,VR::US,VM::VM1,"Overlay Bit Position","OverlayBitPosition",false }, {0x6000,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6002,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6004,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6006,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6008,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x600a,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x600c,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x600e,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6010,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6012,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6014,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6016,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6018,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x601a,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x601c,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x601e,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6020,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6022,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6024,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6026,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6028,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x602a,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x602c,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x602e,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6030,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6032,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6034,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6036,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6038,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x603a,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x603c,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x603e,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6040,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6042,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6044,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6046,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6048,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x604a,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x604c,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x604e,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6050,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6052,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6054,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6056,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6058,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x605a,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x605c,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x605e,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6060,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6062,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6064,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6066,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6068,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x606a,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x606c,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x606e,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6070,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6072,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6074,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6076,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6078,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x607a,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x607c,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x607e,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6080,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6082,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6084,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6086,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6088,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x608a,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x608c,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x608e,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6090,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6092,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6094,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6096,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6098,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x609a,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x609c,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x609e,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60a0,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60a2,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60a4,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60a6,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60a8,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60aa,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60ac,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60ae,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60b0,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60b2,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60b4,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60b6,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60b8,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60ba,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60bc,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60be,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60c0,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60c2,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60c4,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60c6,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60c8,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60ca,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60cc,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60ce,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60d0,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60d2,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60d4,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60d6,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60d8,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60da,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60dc,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60de,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60e0,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60e2,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60e4,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60e6,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60e8,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60ea,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60ec,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60ee,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60f0,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60f2,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60f4,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60f6,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60f8,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60fa,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60fc,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x60fe,0x0110,VR::CS,VM::VM1,"Overlay Format","OverlayFormat",true }, {0x6000,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6002,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6004,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6006,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6008,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x600a,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x600c,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x600e,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6010,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6012,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6014,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6016,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6018,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x601a,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x601c,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x601e,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6020,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6022,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6024,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6026,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6028,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x602a,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x602c,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x602e,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6030,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6032,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6034,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6036,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6038,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x603a,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x603c,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x603e,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6040,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6042,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6044,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6046,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6048,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x604a,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x604c,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x604e,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6050,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6052,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6054,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6056,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6058,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x605a,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x605c,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x605e,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6060,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6062,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6064,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6066,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6068,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x606a,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x606c,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x606e,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6070,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6072,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6074,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6076,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6078,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x607a,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x607c,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x607e,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6080,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6082,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6084,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6086,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6088,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x608a,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x608c,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x608e,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6090,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6092,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6094,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6096,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6098,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x609a,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x609c,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x609e,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60a0,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60a2,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60a4,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60a6,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60a8,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60aa,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60ac,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60ae,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60b0,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60b2,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60b4,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60b6,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60b8,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60ba,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60bc,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60be,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60c0,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60c2,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60c4,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60c6,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60c8,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60ca,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60cc,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60ce,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60d0,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60d2,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60d4,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60d6,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60d8,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60da,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60dc,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60de,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60e0,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60e2,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60e4,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60e6,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60e8,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60ea,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60ec,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60ee,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60f0,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60f2,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60f4,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60f6,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60f8,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60fa,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60fc,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x60fe,0x0200,VR::US,VM::VM1,"Overlay Location","OverlayLocation",true }, {0x6000,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6002,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6004,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6006,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6008,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x600a,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x600c,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x600e,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6010,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6012,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6014,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6016,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6018,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x601a,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x601c,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x601e,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6020,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6022,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6024,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6026,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6028,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x602a,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x602c,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x602e,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6030,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6032,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6034,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6036,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6038,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x603a,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x603c,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x603e,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6040,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6042,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6044,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6046,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6048,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x604a,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x604c,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x604e,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6050,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6052,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6054,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6056,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6058,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x605a,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x605c,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x605e,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6060,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6062,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6064,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6066,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6068,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x606a,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x606c,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x606e,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6070,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6072,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6074,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6076,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6078,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x607a,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x607c,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x607e,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6080,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6082,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6084,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6086,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6088,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x608a,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x608c,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x608e,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6090,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6092,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6094,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6096,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6098,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x609a,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x609c,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x609e,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60a0,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60a2,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60a4,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60a6,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60a8,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60aa,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60ac,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60ae,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60b0,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60b2,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60b4,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60b6,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60b8,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60ba,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60bc,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60be,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60c0,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60c2,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60c4,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60c6,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60c8,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60ca,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60cc,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60ce,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60d0,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60d2,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60d4,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60d6,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60d8,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60da,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60dc,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60de,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60e0,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60e2,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60e4,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60e6,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60e8,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60ea,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60ec,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60ee,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60f0,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60f2,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60f4,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60f6,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60f8,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60fa,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60fc,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x60fe,0x0800,VR::CS,VM::VM1_n,"Overlay Code Label","OverlayCodeLabel",true }, {0x6000,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6002,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6004,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6006,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6008,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x600a,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x600c,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x600e,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6010,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6012,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6014,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6016,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6018,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x601a,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x601c,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x601e,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6020,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6022,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6024,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6026,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6028,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x602a,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x602c,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x602e,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6030,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6032,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6034,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6036,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6038,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x603a,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x603c,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x603e,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6040,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6042,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6044,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6046,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6048,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x604a,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x604c,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x604e,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6050,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6052,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6054,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6056,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6058,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x605a,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x605c,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x605e,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6060,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6062,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6064,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6066,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6068,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x606a,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x606c,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x606e,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6070,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6072,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6074,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6076,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6078,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x607a,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x607c,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x607e,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6080,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6082,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6084,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6086,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6088,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x608a,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x608c,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x608e,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6090,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6092,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6094,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6096,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6098,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x609a,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x609c,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x609e,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60a0,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60a2,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60a4,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60a6,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60a8,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60aa,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60ac,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60ae,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60b0,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60b2,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60b4,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60b6,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60b8,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60ba,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60bc,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60be,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60c0,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60c2,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60c4,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60c6,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60c8,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60ca,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60cc,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60ce,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60d0,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60d2,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60d4,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60d6,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60d8,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60da,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60dc,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60de,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60e0,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60e2,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60e4,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60e6,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60e8,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60ea,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60ec,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60ee,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60f0,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60f2,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60f4,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60f6,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60f8,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60fa,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60fc,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x60fe,0x0802,VR::US,VM::VM1,"Overlay Number of Tables","OverlayNumberOfTables",true }, {0x6000,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6002,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6004,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6006,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6008,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x600a,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x600c,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x600e,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6010,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6012,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6014,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6016,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6018,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x601a,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x601c,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x601e,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6020,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6022,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6024,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6026,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6028,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x602a,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x602c,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x602e,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6030,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6032,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6034,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6036,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6038,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x603a,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x603c,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x603e,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6040,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6042,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6044,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6046,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6048,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x604a,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x604c,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x604e,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6050,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6052,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6054,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6056,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6058,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x605a,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x605c,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x605e,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6060,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6062,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6064,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6066,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6068,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x606a,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x606c,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x606e,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6070,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6072,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6074,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6076,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6078,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x607a,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x607c,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x607e,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6080,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6082,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6084,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6086,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6088,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x608a,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x608c,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x608e,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6090,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6092,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6094,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6096,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6098,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x609a,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x609c,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x609e,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60a0,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60a2,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60a4,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60a6,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60a8,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60aa,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60ac,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60ae,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60b0,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60b2,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60b4,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60b6,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60b8,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60ba,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60bc,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60be,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60c0,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60c2,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60c4,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60c6,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60c8,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60ca,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60cc,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60ce,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60d0,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60d2,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60d4,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60d6,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60d8,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60da,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60dc,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60de,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60e0,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60e2,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60e4,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60e6,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60e8,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60ea,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60ec,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60ee,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60f0,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60f2,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60f4,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60f6,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60f8,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60fa,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60fc,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x60fe,0x0803,VR::AT,VM::VM1_n,"Overlay Code Table Location","OverlayCodeTableLocation",true }, {0x6000,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6002,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6004,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6006,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6008,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x600a,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x600c,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x600e,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6010,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6012,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6014,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6016,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6018,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x601a,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x601c,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x601e,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6020,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6022,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6024,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6026,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6028,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x602a,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x602c,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x602e,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6030,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6032,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6034,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6036,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6038,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x603a,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x603c,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x603e,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6040,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6042,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6044,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6046,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6048,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x604a,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x604c,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x604e,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6050,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6052,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6054,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6056,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6058,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x605a,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x605c,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x605e,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6060,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6062,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6064,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6066,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6068,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x606a,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x606c,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x606e,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6070,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6072,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6074,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6076,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6078,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x607a,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x607c,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x607e,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6080,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6082,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6084,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6086,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6088,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x608a,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x608c,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x608e,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6090,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6092,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6094,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6096,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6098,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x609a,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x609c,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x609e,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60a0,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60a2,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60a4,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60a6,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60a8,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60aa,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60ac,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60ae,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60b0,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60b2,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60b4,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60b6,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60b8,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60ba,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60bc,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60be,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60c0,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60c2,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60c4,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60c6,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60c8,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60ca,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60cc,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60ce,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60d0,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60d2,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60d4,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60d6,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60d8,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60da,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60dc,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60de,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60e0,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60e2,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60e4,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60e6,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60e8,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60ea,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60ec,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60ee,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60f0,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60f2,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60f4,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60f6,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60f8,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60fa,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60fc,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x60fe,0x0804,VR::US,VM::VM1,"Overlay Bits For Code Word","OverlayBitsForCodeWord",true }, {0x6000,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6002,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6004,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6006,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6008,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x600a,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x600c,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x600e,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6010,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6012,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6014,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6016,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6018,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x601a,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x601c,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x601e,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6020,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6022,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6024,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6026,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6028,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x602a,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x602c,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x602e,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6030,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6032,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6034,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6036,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6038,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x603a,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x603c,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x603e,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6040,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6042,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6044,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6046,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6048,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x604a,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x604c,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x604e,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6050,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6052,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6054,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6056,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6058,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x605a,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x605c,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x605e,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6060,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6062,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6064,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6066,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6068,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x606a,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x606c,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x606e,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6070,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6072,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6074,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6076,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6078,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x607a,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x607c,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x607e,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6080,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6082,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6084,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6086,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6088,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x608a,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x608c,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x608e,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6090,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6092,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6094,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6096,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6098,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x609a,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x609c,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x609e,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60a0,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60a2,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60a4,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60a6,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60a8,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60aa,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60ac,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60ae,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60b0,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60b2,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60b4,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60b6,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60b8,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60ba,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60bc,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60be,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60c0,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60c2,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60c4,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60c6,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60c8,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60ca,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60cc,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60ce,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60d0,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60d2,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60d4,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60d6,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60d8,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60da,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60dc,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60de,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60e0,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60e2,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60e4,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60e6,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60e8,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60ea,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60ec,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60ee,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60f0,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60f2,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60f4,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60f6,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60f8,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60fa,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60fc,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x60fe,0x1001,VR::CS,VM::VM1,"Overlay Activation Layer","OverlayActivationLayer",false }, {0x6000,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6002,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6004,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6006,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6008,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x600a,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x600c,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x600e,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6010,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6012,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6014,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6016,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6018,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x601a,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x601c,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x601e,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6020,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6022,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6024,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6026,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6028,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x602a,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x602c,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x602e,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6030,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6032,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6034,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6036,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6038,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x603a,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x603c,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x603e,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6040,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6042,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6044,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6046,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6048,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x604a,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x604c,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x604e,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6050,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6052,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6054,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6056,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6058,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x605a,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x605c,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x605e,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6060,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6062,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6064,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6066,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6068,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x606a,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x606c,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x606e,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6070,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6072,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6074,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6076,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6078,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x607a,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x607c,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x607e,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6080,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6082,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6084,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6086,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6088,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x608a,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x608c,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x608e,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6090,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6092,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6094,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6096,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6098,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x609a,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x609c,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x609e,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60a0,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60a2,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60a4,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60a6,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60a8,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60aa,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60ac,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60ae,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60b0,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60b2,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60b4,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60b6,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60b8,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60ba,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60bc,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60be,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60c0,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60c2,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60c4,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60c6,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60c8,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60ca,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60cc,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60ce,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60d0,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60d2,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60d4,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60d6,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60d8,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60da,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60dc,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60de,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60e0,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60e2,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60e4,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60e6,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60e8,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60ea,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60ec,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60ee,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60f0,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60f2,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60f4,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60f6,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60f8,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60fa,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60fc,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x60fe,0x1100,VR::US,VM::VM1,"Overlay Descriptor - Gray","OverlayDescriptorGray",true }, {0x6000,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6002,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6004,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6006,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6008,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x600a,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x600c,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x600e,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6010,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6012,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6014,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6016,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6018,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x601a,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x601c,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x601e,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6020,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6022,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6024,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6026,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6028,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x602a,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x602c,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x602e,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6030,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6032,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6034,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6036,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6038,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x603a,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x603c,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x603e,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6040,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6042,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6044,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6046,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6048,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x604a,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x604c,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x604e,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6050,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6052,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6054,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6056,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6058,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x605a,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x605c,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x605e,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6060,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6062,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6064,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6066,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6068,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x606a,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x606c,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x606e,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6070,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6072,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6074,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6076,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6078,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x607a,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x607c,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x607e,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6080,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6082,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6084,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6086,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6088,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x608a,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x608c,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x608e,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6090,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6092,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6094,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6096,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6098,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x609a,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x609c,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x609e,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60a0,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60a2,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60a4,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60a6,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60a8,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60aa,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60ac,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60ae,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60b0,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60b2,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60b4,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60b6,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60b8,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60ba,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60bc,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60be,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60c0,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60c2,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60c4,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60c6,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60c8,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60ca,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60cc,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60ce,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60d0,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60d2,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60d4,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60d6,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60d8,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60da,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60dc,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60de,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60e0,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60e2,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60e4,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60e6,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60e8,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60ea,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60ec,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60ee,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60f0,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60f2,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60f4,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60f6,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60f8,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60fa,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60fc,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x60fe,0x1101,VR::US,VM::VM1,"Overlay Descriptor - Red","OverlayDescriptorRed",true }, {0x6000,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6002,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6004,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6006,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6008,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x600a,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x600c,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x600e,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6010,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6012,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6014,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6016,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6018,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x601a,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x601c,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x601e,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6020,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6022,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6024,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6026,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6028,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x602a,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x602c,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x602e,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6030,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6032,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6034,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6036,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6038,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x603a,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x603c,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x603e,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6040,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6042,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6044,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6046,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6048,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x604a,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x604c,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x604e,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6050,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6052,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6054,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6056,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6058,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x605a,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x605c,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x605e,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6060,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6062,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6064,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6066,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6068,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x606a,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x606c,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x606e,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6070,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6072,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6074,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6076,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6078,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x607a,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x607c,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x607e,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6080,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6082,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6084,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6086,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6088,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x608a,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x608c,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x608e,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6090,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6092,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6094,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6096,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6098,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x609a,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x609c,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x609e,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60a0,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60a2,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60a4,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60a6,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60a8,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60aa,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60ac,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60ae,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60b0,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60b2,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60b4,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60b6,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60b8,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60ba,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60bc,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60be,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60c0,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60c2,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60c4,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60c6,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60c8,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60ca,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60cc,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60ce,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60d0,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60d2,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60d4,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60d6,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60d8,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60da,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60dc,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60de,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60e0,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60e2,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60e4,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60e6,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60e8,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60ea,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60ec,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60ee,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60f0,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60f2,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60f4,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60f6,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60f8,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60fa,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60fc,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x60fe,0x1102,VR::US,VM::VM1,"Overlay Descriptor - Green","OverlayDescriptorGreen",true }, {0x6000,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6002,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6004,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6006,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6008,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x600a,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x600c,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x600e,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6010,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6012,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6014,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6016,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6018,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x601a,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x601c,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x601e,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6020,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6022,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6024,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6026,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6028,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x602a,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x602c,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x602e,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6030,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6032,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6034,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6036,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6038,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x603a,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x603c,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x603e,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6040,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6042,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6044,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6046,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6048,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x604a,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x604c,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x604e,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6050,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6052,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6054,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6056,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6058,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x605a,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x605c,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x605e,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6060,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6062,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6064,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6066,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6068,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x606a,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x606c,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x606e,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6070,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6072,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6074,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6076,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6078,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x607a,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x607c,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x607e,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6080,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6082,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6084,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6086,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6088,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x608a,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x608c,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x608e,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6090,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6092,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6094,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6096,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6098,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x609a,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x609c,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x609e,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60a0,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60a2,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60a4,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60a6,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60a8,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60aa,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60ac,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60ae,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60b0,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60b2,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60b4,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60b6,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60b8,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60ba,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60bc,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60be,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60c0,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60c2,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60c4,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60c6,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60c8,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60ca,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60cc,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60ce,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60d0,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60d2,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60d4,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60d6,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60d8,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60da,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60dc,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60de,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60e0,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60e2,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60e4,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60e6,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60e8,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60ea,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60ec,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60ee,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60f0,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60f2,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60f4,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60f6,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60f8,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60fa,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60fc,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x60fe,0x1103,VR::US,VM::VM1,"Overlay Descriptor - Blue","OverlayDescriptorBlue",true }, {0x6000,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6002,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6004,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6006,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6008,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x600a,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x600c,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x600e,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6010,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6012,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6014,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6016,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6018,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x601a,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x601c,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x601e,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6020,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6022,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6024,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6026,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6028,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x602a,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x602c,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x602e,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6030,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6032,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6034,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6036,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6038,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x603a,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x603c,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x603e,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6040,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6042,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6044,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6046,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6048,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x604a,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x604c,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x604e,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6050,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6052,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6054,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6056,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6058,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x605a,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x605c,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x605e,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6060,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6062,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6064,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6066,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6068,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x606a,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x606c,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x606e,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6070,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6072,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6074,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6076,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6078,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x607a,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x607c,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x607e,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6080,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6082,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6084,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6086,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6088,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x608a,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x608c,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x608e,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6090,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6092,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6094,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6096,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6098,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x609a,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x609c,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x609e,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60a0,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60a2,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60a4,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60a6,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60a8,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60aa,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60ac,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60ae,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60b0,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60b2,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60b4,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60b6,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60b8,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60ba,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60bc,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60be,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60c0,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60c2,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60c4,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60c6,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60c8,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60ca,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60cc,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60ce,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60d0,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60d2,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60d4,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60d6,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60d8,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60da,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60dc,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60de,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60e0,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60e2,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60e4,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60e6,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60e8,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60ea,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60ec,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60ee,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60f0,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60f2,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60f4,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60f6,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60f8,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60fa,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60fc,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x60fe,0x1200,VR::US,VM::VM1_n,"Overlays - Gray","OverlaysGray",true }, {0x6000,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6002,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6004,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6006,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6008,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x600a,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x600c,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x600e,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6010,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6012,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6014,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6016,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6018,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x601a,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x601c,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x601e,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6020,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6022,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6024,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6026,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6028,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x602a,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x602c,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x602e,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6030,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6032,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6034,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6036,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6038,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x603a,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x603c,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x603e,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6040,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6042,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6044,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6046,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6048,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x604a,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x604c,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x604e,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6050,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6052,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6054,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6056,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6058,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x605a,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x605c,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x605e,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6060,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6062,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6064,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6066,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6068,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x606a,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x606c,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x606e,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6070,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6072,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6074,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6076,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6078,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x607a,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x607c,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x607e,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6080,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6082,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6084,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6086,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6088,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x608a,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x608c,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x608e,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6090,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6092,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6094,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6096,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6098,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x609a,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x609c,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x609e,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60a0,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60a2,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60a4,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60a6,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60a8,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60aa,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60ac,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60ae,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60b0,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60b2,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60b4,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60b6,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60b8,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60ba,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60bc,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60be,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60c0,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60c2,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60c4,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60c6,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60c8,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60ca,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60cc,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60ce,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60d0,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60d2,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60d4,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60d6,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60d8,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60da,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60dc,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60de,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60e0,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60e2,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60e4,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60e6,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60e8,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60ea,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60ec,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60ee,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60f0,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60f2,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60f4,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60f6,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60f8,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60fa,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60fc,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x60fe,0x1201,VR::US,VM::VM1_n,"Overlays - Red","OverlaysRed",true }, {0x6000,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6002,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6004,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6006,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6008,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x600a,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x600c,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x600e,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6010,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6012,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6014,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6016,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6018,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x601a,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x601c,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x601e,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6020,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6022,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6024,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6026,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6028,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x602a,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x602c,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x602e,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6030,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6032,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6034,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6036,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6038,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x603a,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x603c,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x603e,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6040,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6042,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6044,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6046,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6048,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x604a,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x604c,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x604e,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6050,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6052,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6054,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6056,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6058,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x605a,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x605c,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x605e,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6060,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6062,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6064,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6066,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6068,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x606a,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x606c,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x606e,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6070,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6072,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6074,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6076,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6078,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x607a,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x607c,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x607e,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6080,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6082,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6084,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6086,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6088,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x608a,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x608c,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x608e,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6090,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6092,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6094,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6096,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6098,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x609a,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x609c,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x609e,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60a0,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60a2,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60a4,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60a6,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60a8,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60aa,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60ac,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60ae,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60b0,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60b2,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60b4,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60b6,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60b8,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60ba,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60bc,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60be,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60c0,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60c2,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60c4,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60c6,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60c8,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60ca,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60cc,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60ce,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60d0,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60d2,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60d4,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60d6,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60d8,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60da,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60dc,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60de,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60e0,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60e2,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60e4,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60e6,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60e8,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60ea,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60ec,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60ee,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60f0,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60f2,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60f4,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60f6,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60f8,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60fa,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60fc,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x60fe,0x1202,VR::US,VM::VM1_n,"Overlays - Green","OverlaysGreen",true }, {0x6000,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6002,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6004,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6006,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6008,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x600a,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x600c,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x600e,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6010,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6012,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6014,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6016,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6018,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x601a,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x601c,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x601e,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6020,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6022,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6024,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6026,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6028,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x602a,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x602c,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x602e,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6030,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6032,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6034,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6036,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6038,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x603a,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x603c,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x603e,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6040,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6042,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6044,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6046,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6048,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x604a,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x604c,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x604e,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6050,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6052,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6054,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6056,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6058,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x605a,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x605c,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x605e,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6060,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6062,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6064,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6066,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6068,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x606a,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x606c,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x606e,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6070,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6072,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6074,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6076,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6078,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x607a,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x607c,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x607e,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6080,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6082,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6084,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6086,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6088,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x608a,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x608c,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x608e,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6090,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6092,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6094,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6096,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6098,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x609a,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x609c,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x609e,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60a0,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60a2,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60a4,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60a6,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60a8,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60aa,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60ac,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60ae,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60b0,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60b2,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60b4,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60b6,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60b8,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60ba,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60bc,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60be,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60c0,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60c2,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60c4,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60c6,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60c8,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60ca,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60cc,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60ce,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60d0,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60d2,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60d4,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60d6,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60d8,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60da,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60dc,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60de,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60e0,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60e2,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60e4,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60e6,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60e8,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60ea,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60ec,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60ee,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60f0,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60f2,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60f4,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60f6,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60f8,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60fa,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60fc,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x60fe,0x1203,VR::US,VM::VM1_n,"Overlays - Blue","OverlaysBlue",true }, {0x6000,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6002,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6004,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6006,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6008,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x600a,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x600c,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x600e,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6010,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6012,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6014,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6016,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6018,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x601a,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x601c,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x601e,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6020,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6022,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6024,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6026,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6028,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x602a,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x602c,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x602e,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6030,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6032,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6034,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6036,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6038,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x603a,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x603c,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x603e,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6040,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6042,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6044,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6046,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6048,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x604a,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x604c,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x604e,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6050,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6052,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6054,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6056,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6058,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x605a,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x605c,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x605e,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6060,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6062,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6064,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6066,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6068,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x606a,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x606c,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x606e,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6070,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6072,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6074,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6076,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6078,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x607a,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x607c,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x607e,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6080,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6082,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6084,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6086,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6088,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x608a,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x608c,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x608e,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6090,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6092,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6094,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6096,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6098,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x609a,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x609c,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x609e,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60a0,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60a2,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60a4,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60a6,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60a8,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60aa,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60ac,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60ae,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60b0,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60b2,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60b4,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60b6,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60b8,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60ba,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60bc,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60be,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60c0,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60c2,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60c4,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60c6,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60c8,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60ca,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60cc,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60ce,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60d0,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60d2,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60d4,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60d6,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60d8,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60da,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60dc,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60de,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60e0,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60e2,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60e4,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60e6,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60e8,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60ea,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60ec,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60ee,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60f0,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60f2,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60f4,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60f6,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60f8,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60fa,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60fc,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x60fe,0x1301,VR::IS,VM::VM1,"ROI Area","ROIArea",false }, {0x6000,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6002,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6004,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6006,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6008,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x600a,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x600c,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x600e,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6010,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6012,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6014,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6016,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6018,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x601a,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x601c,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x601e,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6020,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6022,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6024,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6026,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6028,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x602a,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x602c,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x602e,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6030,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6032,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6034,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6036,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6038,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x603a,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x603c,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x603e,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6040,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6042,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6044,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6046,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6048,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x604a,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x604c,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x604e,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6050,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6052,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6054,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6056,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6058,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x605a,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x605c,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x605e,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6060,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6062,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6064,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6066,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6068,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x606a,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x606c,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x606e,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6070,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6072,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6074,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6076,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6078,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x607a,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x607c,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x607e,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6080,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6082,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6084,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6086,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6088,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x608a,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x608c,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x608e,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6090,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6092,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6094,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6096,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6098,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x609a,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x609c,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x609e,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60a0,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60a2,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60a4,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60a6,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60a8,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60aa,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60ac,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60ae,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60b0,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60b2,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60b4,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60b6,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60b8,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60ba,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60bc,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60be,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60c0,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60c2,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60c4,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60c6,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60c8,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60ca,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60cc,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60ce,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60d0,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60d2,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60d4,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60d6,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60d8,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60da,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60dc,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60de,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60e0,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60e2,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60e4,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60e6,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60e8,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60ea,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60ec,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60ee,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60f0,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60f2,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60f4,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60f6,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60f8,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60fa,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60fc,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x60fe,0x1302,VR::DS,VM::VM1,"ROI Mean","ROIMean",false }, {0x6000,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6002,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6004,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6006,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6008,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x600a,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x600c,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x600e,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6010,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6012,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6014,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6016,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6018,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x601a,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x601c,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x601e,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6020,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6022,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6024,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6026,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6028,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x602a,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x602c,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x602e,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6030,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6032,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6034,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6036,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6038,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x603a,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x603c,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x603e,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6040,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6042,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6044,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6046,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6048,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x604a,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x604c,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x604e,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6050,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6052,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6054,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6056,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6058,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x605a,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x605c,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x605e,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6060,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6062,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6064,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6066,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6068,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x606a,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x606c,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x606e,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6070,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6072,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6074,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6076,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6078,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x607a,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x607c,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x607e,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6080,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6082,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6084,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6086,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6088,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x608a,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x608c,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x608e,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6090,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6092,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6094,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6096,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6098,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x609a,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x609c,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x609e,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60a0,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60a2,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60a4,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60a6,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60a8,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60aa,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60ac,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60ae,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60b0,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60b2,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60b4,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60b6,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60b8,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60ba,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60bc,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60be,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60c0,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60c2,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60c4,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60c6,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60c8,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60ca,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60cc,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60ce,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60d0,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60d2,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60d4,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60d6,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60d8,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60da,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60dc,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60de,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60e0,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60e2,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60e4,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60e6,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60e8,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60ea,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60ec,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60ee,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60f0,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60f2,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60f4,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60f6,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60f8,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60fa,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60fc,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x60fe,0x1303,VR::DS,VM::VM1,"ROI Standard Deviation","ROIStandardDeviation",false }, {0x6000,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6002,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6004,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6006,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6008,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x600a,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x600c,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x600e,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6010,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6012,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6014,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6016,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6018,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x601a,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x601c,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x601e,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6020,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6022,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6024,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6026,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6028,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x602a,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x602c,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x602e,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6030,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6032,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6034,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6036,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6038,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x603a,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x603c,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x603e,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6040,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6042,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6044,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6046,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6048,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x604a,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x604c,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x604e,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6050,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6052,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6054,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6056,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6058,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x605a,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x605c,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x605e,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6060,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6062,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6064,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6066,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6068,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x606a,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x606c,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x606e,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6070,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6072,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6074,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6076,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6078,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x607a,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x607c,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x607e,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6080,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6082,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6084,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6086,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6088,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x608a,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x608c,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x608e,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6090,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6092,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6094,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6096,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6098,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x609a,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x609c,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x609e,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60a0,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60a2,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60a4,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60a6,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60a8,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60aa,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60ac,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60ae,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60b0,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60b2,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60b4,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60b6,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60b8,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60ba,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60bc,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60be,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60c0,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60c2,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60c4,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60c6,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60c8,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60ca,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60cc,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60ce,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60d0,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60d2,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60d4,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60d6,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60d8,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60da,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60dc,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60de,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60e0,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60e2,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60e4,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60e6,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60e8,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60ea,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60ec,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60ee,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60f0,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60f2,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60f4,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60f6,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60f8,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60fa,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60fc,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x60fe,0x1500,VR::LO,VM::VM1,"Overlay Label","OverlayLabel",false }, {0x6000,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6002,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6004,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6006,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6008,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x600a,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x600c,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x600e,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6010,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6012,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6014,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6016,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6018,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x601a,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x601c,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x601e,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6020,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6022,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6024,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6026,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6028,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x602a,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x602c,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x602e,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6030,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6032,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6034,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6036,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6038,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x603a,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x603c,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x603e,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6040,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6042,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6044,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6046,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6048,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x604a,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x604c,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x604e,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6050,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6052,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6054,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6056,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6058,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x605a,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x605c,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x605e,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6060,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6062,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6064,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6066,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6068,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x606a,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x606c,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x606e,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6070,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6072,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6074,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6076,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6078,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x607a,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x607c,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x607e,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6080,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6082,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6084,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6086,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6088,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x608a,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x608c,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x608e,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6090,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6092,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6094,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6096,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6098,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x609a,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x609c,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x609e,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60a0,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60a2,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60a4,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60a6,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60a8,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60aa,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60ac,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60ae,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60b0,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60b2,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60b4,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60b6,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60b8,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60ba,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60bc,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60be,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60c0,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60c2,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60c4,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60c6,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60c8,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60ca,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60cc,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60ce,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60d0,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60d2,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60d4,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60d6,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60d8,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60da,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60dc,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60de,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60e0,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60e2,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60e4,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60e6,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60e8,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60ea,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60ec,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60ee,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60f0,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60f2,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60f4,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60f6,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60f8,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60fa,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60fc,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x60fe,0x3000,VR::OB_OW,VM::VM1,"Overlay Data","OverlayData",false }, {0x6000,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6002,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6004,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6006,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6008,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x600a,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x600c,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x600e,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6010,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6012,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6014,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6016,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6018,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x601a,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x601c,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x601e,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6020,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6022,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6024,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6026,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6028,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x602a,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x602c,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x602e,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6030,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6032,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6034,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6036,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6038,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x603a,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x603c,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x603e,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6040,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6042,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6044,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6046,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6048,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x604a,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x604c,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x604e,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6050,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6052,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6054,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6056,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6058,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x605a,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x605c,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x605e,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6060,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6062,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6064,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6066,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6068,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x606a,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x606c,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x606e,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6070,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6072,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6074,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6076,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6078,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x607a,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x607c,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x607e,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6080,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6082,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6084,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6086,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6088,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x608a,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x608c,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x608e,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6090,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6092,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6094,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6096,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x6098,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x609a,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x609c,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x609e,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60a0,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60a2,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60a4,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60a6,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60a8,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60aa,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60ac,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60ae,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60b0,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60b2,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60b4,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60b6,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60b8,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60ba,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60bc,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60be,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60c0,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60c2,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60c4,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60c6,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60c8,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60ca,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60cc,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60ce,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60d0,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60d2,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60d4,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60d6,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60d8,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60da,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60dc,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60de,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60e0,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60e2,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60e4,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60e6,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60e8,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60ea,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60ec,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60ee,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60f0,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60f2,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60f4,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60f6,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60f8,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60fa,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60fc,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x60fe,0x4000,VR::LT,VM::VM1,"Overlay Comments","OverlayComments",true }, {0x7fe0,0x0008,VR::OF,VM::VM1,"Float Pixel Data","FloatPixelData",false }, {0x7fe0,0x0009,VR::OD,VM::VM1,"Double Float Pixel Data","DoubleFloatPixelData",false }, {0x7fe0,0x0010,VR::OB_OW,VM::VM1,"Pixel Data","PixelData",false }, {0x7fe0,0x0020,VR::OW,VM::VM1,"Coefficients SDVN","CoefficientsSDVN",true }, {0x7fe0,0x0030,VR::OW,VM::VM1,"Coefficients SDHN","CoefficientsSDHN",true }, {0x7fe0,0x0040,VR::OW,VM::VM1,"Coefficients SDDN","CoefficientsSDDN",true }, {0x7f00,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f02,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f04,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f06,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f08,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f0a,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f0c,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f0e,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f10,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f12,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f14,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f16,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f18,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f1a,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f1c,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f1e,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f20,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f22,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f24,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f26,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f28,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f2a,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f2c,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f2e,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f30,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f32,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f34,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f36,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f38,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f3a,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f3c,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f3e,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f40,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f42,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f44,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f46,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f48,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f4a,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f4c,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f4e,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f50,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f52,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f54,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f56,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f58,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f5a,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f5c,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f5e,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f60,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f62,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f64,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f66,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f68,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f6a,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f6c,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f6e,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f70,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f72,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f74,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f76,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f78,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f7a,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f7c,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f7e,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f80,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f82,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f84,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f86,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f88,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f8a,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f8c,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f8e,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f90,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f92,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f94,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f96,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f98,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f9a,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f9c,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f9e,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fa0,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fa2,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fa4,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fa6,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fa8,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7faa,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fac,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fae,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fb0,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fb2,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fb4,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fb6,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fb8,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fba,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fbc,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fbe,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fc0,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fc2,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fc4,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fc6,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fc8,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fca,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fcc,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fce,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fd0,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fd2,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fd4,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fd6,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fd8,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fda,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fdc,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fde,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, // {0x7fe0,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fe2,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fe4,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fe6,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fe8,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fea,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fec,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7fee,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7ff0,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7ff2,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7ff4,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7ff6,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7ff8,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7ffa,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7ffc,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7ffe,0x0010,VR::OB_OW,VM::VM1,"Variable Pixel Data","VariablePixelData",true }, {0x7f00,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f02,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f04,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f06,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f08,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f0a,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f0c,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f0e,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f10,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f12,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f14,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f16,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f18,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f1a,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f1c,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f1e,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f20,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f22,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f24,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f26,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f28,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f2a,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f2c,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f2e,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f30,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f32,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f34,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f36,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f38,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f3a,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f3c,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f3e,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f40,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f42,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f44,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f46,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f48,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f4a,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f4c,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f4e,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f50,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f52,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f54,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f56,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f58,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f5a,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f5c,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f5e,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f60,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f62,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f64,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f66,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f68,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f6a,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f6c,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f6e,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f70,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f72,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f74,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f76,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f78,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f7a,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f7c,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f7e,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f80,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f82,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f84,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f86,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f88,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f8a,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f8c,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f8e,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f90,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f92,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f94,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f96,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f98,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f9a,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f9c,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f9e,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fa0,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fa2,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fa4,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fa6,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fa8,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7faa,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fac,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fae,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fb0,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fb2,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fb4,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fb6,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fb8,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fba,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fbc,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fbe,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fc0,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fc2,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fc4,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fc6,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fc8,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fca,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fcc,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fce,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fd0,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fd2,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fd4,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fd6,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fd8,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fda,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fdc,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fde,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fe0,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fe2,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fe4,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fe6,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fe8,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fea,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fec,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7fee,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7ff0,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7ff2,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7ff4,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7ff6,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7ff8,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7ffa,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7ffc,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7ffe,0x0011,VR::US,VM::VM1,"Variable Next Data Group","VariableNextDataGroup",true }, {0x7f00,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f02,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f04,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f06,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f08,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f0a,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f0c,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f0e,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f10,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f12,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f14,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f16,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f18,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f1a,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f1c,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f1e,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f20,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f22,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f24,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f26,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f28,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f2a,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f2c,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f2e,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f30,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f32,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f34,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f36,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f38,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f3a,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f3c,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f3e,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f40,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f42,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f44,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f46,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f48,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f4a,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f4c,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f4e,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f50,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f52,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f54,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f56,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f58,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f5a,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f5c,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f5e,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f60,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f62,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f64,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f66,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f68,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f6a,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f6c,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f6e,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f70,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f72,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f74,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f76,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f78,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f7a,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f7c,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f7e,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f80,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f82,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f84,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f86,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f88,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f8a,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f8c,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f8e,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f90,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f92,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f94,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f96,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f98,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f9a,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f9c,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f9e,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fa0,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fa2,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fa4,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fa6,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fa8,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7faa,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fac,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fae,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fb0,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fb2,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fb4,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fb6,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fb8,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fba,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fbc,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fbe,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fc0,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fc2,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fc4,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fc6,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fc8,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fca,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fcc,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fce,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fd0,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fd2,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fd4,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fd6,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fd8,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fda,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fdc,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fde,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, // {0x7fe0,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fe2,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fe4,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fe6,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fe8,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fea,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fec,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7fee,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7ff0,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7ff2,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7ff4,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7ff6,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7ff8,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7ffa,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7ffc,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7ffe,0x0020,VR::OW,VM::VM1,"Variable Coefficients SDVN","VariableCoefficientsSDVN",true }, {0x7f00,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f02,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f04,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f06,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f08,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f0a,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f0c,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f0e,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f10,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f12,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f14,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f16,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f18,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f1a,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f1c,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f1e,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f20,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f22,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f24,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f26,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f28,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f2a,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f2c,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f2e,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f30,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f32,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f34,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f36,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f38,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f3a,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f3c,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f3e,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f40,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f42,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f44,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f46,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f48,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f4a,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f4c,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f4e,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f50,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f52,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f54,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f56,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f58,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f5a,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f5c,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f5e,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f60,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f62,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f64,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f66,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f68,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f6a,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f6c,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f6e,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f70,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f72,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f74,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f76,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f78,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f7a,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f7c,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f7e,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f80,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f82,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f84,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f86,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f88,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f8a,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f8c,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f8e,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f90,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f92,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f94,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f96,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f98,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f9a,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f9c,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f9e,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fa0,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fa2,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fa4,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fa6,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fa8,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7faa,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fac,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fae,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fb0,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fb2,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fb4,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fb6,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fb8,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fba,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fbc,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fbe,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fc0,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fc2,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fc4,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fc6,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fc8,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fca,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fcc,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fce,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fd0,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fd2,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fd4,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fd6,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fd8,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fda,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fdc,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fde,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, // {0x7fe0,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fe2,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fe4,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fe6,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fe8,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fea,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fec,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7fee,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7ff0,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7ff2,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7ff4,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7ff6,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7ff8,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7ffa,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7ffc,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7ffe,0x0030,VR::OW,VM::VM1,"Variable Coefficients SDHN","VariableCoefficientsSDHN",true }, {0x7f00,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f02,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f04,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f06,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f08,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f0a,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f0c,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f0e,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f10,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f12,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f14,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f16,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f18,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f1a,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f1c,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f1e,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f20,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f22,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f24,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f26,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f28,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f2a,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f2c,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f2e,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f30,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f32,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f34,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f36,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f38,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f3a,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f3c,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f3e,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f40,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f42,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f44,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f46,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f48,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f4a,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f4c,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f4e,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f50,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f52,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f54,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f56,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f58,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f5a,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f5c,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f5e,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f60,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f62,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f64,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f66,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f68,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f6a,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f6c,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f6e,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f70,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f72,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f74,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f76,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f78,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f7a,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f7c,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f7e,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f80,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f82,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f84,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f86,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f88,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f8a,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f8c,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f8e,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f90,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f92,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f94,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f96,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f98,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f9a,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f9c,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7f9e,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fa0,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fa2,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fa4,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fa6,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fa8,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7faa,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fac,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fae,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fb0,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fb2,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fb4,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fb6,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fb8,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fba,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fbc,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fbe,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fc0,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fc2,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fc4,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fc6,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fc8,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fca,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fcc,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fce,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fd0,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fd2,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fd4,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fd6,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fd8,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fda,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fdc,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fde,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, // {0x7fe0,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fe2,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fe4,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fe6,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fe8,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fea,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fec,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7fee,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7ff0,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7ff2,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7ff4,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7ff6,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7ff8,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7ffa,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7ffc,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0x7ffe,0x0040,VR::OW,VM::VM1,"Variable Coefficients SDDN","VariableCoefficientsSDDN",true }, {0xfffa,0xfffa,VR::SQ,VM::VM1,"Digital Signatures Sequence","DigitalSignaturesSequence",false }, {0xfffc,0xfffc,VR::OB,VM::VM1,"Data Set Trailing Padding","DataSetTrailingPadding",false }, {0xfffe,0xe000,VR::INVALID,VM::VM1,"Item","Item",false }, {0xfffe,0xe00d,VR::INVALID,VM::VM1,"Item Delimitation Item","ItemDelimitationItem",false }, {0xfffe,0xe0dd,VR::INVALID,VM::VM1,"Sequence Delimitation Item","SequenceDelimitationItem",false }, // {0x0008,0x0000,VR::UL,VM::VM1,"Group Length 0008","",true }, // {0x0010,0x0000,VR::UL,VM::VM1,"Group Length 0010","",true }, // {0x0012,0x0000,VR::UL,VM::VM1,"Group Length 0012","",true }, // {0x0014,0x0000,VR::UL,VM::VM1,"Group Length 0014","",true }, // {0x0018,0x0000,VR::UL,VM::VM1,"Group Length 0018","",true }, // {0x0020,0x0000,VR::UL,VM::VM1,"Group Length 0020","",true }, // {0x0022,0x0000,VR::UL,VM::VM1,"Group Length 0022","",true }, // {0x0024,0x0000,VR::UL,VM::VM1,"Group Length 0024","",true }, // {0x0028,0x0000,VR::UL,VM::VM1,"Group Length 0028","",true }, // {0x0032,0x0000,VR::UL,VM::VM1,"Group Length 0032","",true }, // {0x0038,0x0000,VR::UL,VM::VM1,"Group Length 0038","",true }, // {0x003a,0x0000,VR::UL,VM::VM1,"Group Length 003a","",true }, // {0x0040,0x0000,VR::UL,VM::VM1,"Group Length 0040","",true }, // {0x0042,0x0000,VR::UL,VM::VM1,"Group Length 0042","",true }, // {0x0044,0x0000,VR::UL,VM::VM1,"Group Length 0044","",true }, // {0x0046,0x0000,VR::UL,VM::VM1,"Group Length 0046","",true }, // {0x0048,0x0000,VR::UL,VM::VM1,"Group Length 0048","",true }, // {0x0050,0x0000,VR::UL,VM::VM1,"Group Length 0050","",true }, // {0x0052,0x0000,VR::UL,VM::VM1,"Group Length 0052","",true }, // {0x0054,0x0000,VR::UL,VM::VM1,"Group Length 0054","",true }, // {0x0060,0x0000,VR::UL,VM::VM1,"Group Length 0060","",true }, // {0x0062,0x0000,VR::UL,VM::VM1,"Group Length 0062","",true }, // {0x0064,0x0000,VR::UL,VM::VM1,"Group Length 0064","",true }, // {0x0066,0x0000,VR::UL,VM::VM1,"Group Length 0066","",true }, // {0x0068,0x0000,VR::UL,VM::VM1,"Group Length 0068","",true }, // {0x0070,0x0000,VR::UL,VM::VM1,"Group Length 0070","",true }, // {0x0072,0x0000,VR::UL,VM::VM1,"Group Length 0072","",true }, // {0x0074,0x0000,VR::UL,VM::VM1,"Group Length 0074","",true }, // {0x0076,0x0000,VR::UL,VM::VM1,"Group Length 0076","",true }, // {0x0078,0x0000,VR::UL,VM::VM1,"Group Length 0078","",true }, // {0x0080,0x0000,VR::UL,VM::VM1,"Group Length 0080","",true }, // {0x0082,0x0000,VR::UL,VM::VM1,"Group Length 0082","",true }, // {0x0088,0x0000,VR::UL,VM::VM1,"Group Length 0088","",true }, // {0x0100,0x0000,VR::UL,VM::VM1,"Group Length 0100","",true }, // {0x0400,0x0000,VR::UL,VM::VM1,"Group Length 0400","",true }, // {0x1000,0x0000,VR::UL,VM::VM1,"Group Length 1000","",true }, // {0x1010,0x0000,VR::UL,VM::VM1,"Group Length 1010","",true }, // {0x2000,0x0000,VR::UL,VM::VM1,"Group Length 2000","",true }, // {0x2010,0x0000,VR::UL,VM::VM1,"Group Length 2010","",true }, // {0x2020,0x0000,VR::UL,VM::VM1,"Group Length 2020","",true }, // {0x2030,0x0000,VR::UL,VM::VM1,"Group Length 2030","",true }, // {0x2040,0x0000,VR::UL,VM::VM1,"Group Length 2040","",true }, // {0x2050,0x0000,VR::UL,VM::VM1,"Group Length 2050","",true }, // {0x2100,0x0000,VR::UL,VM::VM1,"Group Length 2100","",true }, // {0x2110,0x0000,VR::UL,VM::VM1,"Group Length 2110","",true }, // {0x2120,0x0000,VR::UL,VM::VM1,"Group Length 2120","",true }, // {0x2130,0x0000,VR::UL,VM::VM1,"Group Length 2130","",true }, // {0x2200,0x0000,VR::UL,VM::VM1,"Group Length 2200","",true }, // {0x3002,0x0000,VR::UL,VM::VM1,"Group Length 3002","",true }, // {0x3004,0x0000,VR::UL,VM::VM1,"Group Length 3004","",true }, // {0x3006,0x0000,VR::UL,VM::VM1,"Group Length 3006","",true }, // {0x3008,0x0000,VR::UL,VM::VM1,"Group Length 3008","",true }, // {0x300a,0x0000,VR::UL,VM::VM1,"Group Length 300a","",true }, // {0x300c,0x0000,VR::UL,VM::VM1,"Group Length 300c","",true }, // {0x300e,0x0000,VR::UL,VM::VM1,"Group Length 300e","",true }, // {0x4000,0x0000,VR::UL,VM::VM1,"Group Length 4000","",true }, // {0x4008,0x0000,VR::UL,VM::VM1,"Group Length 4008","",true }, // {0x4010,0x0000,VR::UL,VM::VM1,"Group Length 4010","",true }, // {0x4ffe,0x0000,VR::UL,VM::VM1,"Group Length 4ffe","",true }, // {0x5200,0x0000,VR::UL,VM::VM1,"Group Length 5200","",true }, // {0x5400,0x0000,VR::UL,VM::VM1,"Group Length 5400","",true }, // {0x5600,0x0000,VR::UL,VM::VM1,"Group Length 5600","",true }, // {0x7fe0,0x0000,VR::UL,VM::VM1,"Group Length 7fe0","",true }, // {0xfffa,0x0000,VR::UL,VM::VM1,"Group Length fffa","",true }, // {0xfffc,0x0000,VR::UL,VM::VM1,"Group Length fffc","",true }, // {0xfffe,0x0000,VR::UL,VM::VM1,"Group Length fffe","",true }, // {0x0004,0x0000,VR::UL,VM::VM1,"Group Length 0004","",true }, // FIXME: need a dummy element {0xffff,0xffff,VR::INVALID,VM::VM0,"","",true }, // dummy {0xffff,0xffff,VR::INVALID,VM::VM0,nullptr,nullptr,true } // Guard }; } // end anonymous namespace namespace gdcm { void Dict::LoadDefault() { unsigned int i = 0; DICT_ENTRY n = DICOMV3DataDict[i]; while( n.name != nullptr ) { Tag t(n.group, n.element); DictEntry e( n.name, n.keyword, n.vr, n.vm, n.ret ); assert( DictEntry::CheckKeywordAgainstName(n.name, n.keyword) ); AddDictEntry( t, e ); n = DICOMV3DataDict[++i]; } } /* void PrivateDict::LoadDefault() { // TODO } */ } // end namespace gdcm #endif // GDCMDEFAULTDICTS_CXX GDCM-3.0.10/Source/DataDictionary/gdcmDefaultGroupNames.cxx000066400000000000000000000064131412732066400234210ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT /*========================================================================= 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 "gdcmTypes.h" #include "gdcmGroupDict.h" namespace gdcm { using GROUP_ENTRY = struct { uint16_t group; const char *abbreviation; const char *name; }; static GROUP_ENTRY groupname[] = { {0x0000,"CMD","Command"}, {0x0002,"META","Meta Element"}, {0x0004,"DIR","Directory"}, {0x0004,"FST","File Set"}, {0x0008,"ID","Identifying"}, {0x0009,"SPII","SPI Identifying"}, {0x0010,"PAT","Patient"}, {0x0012,"CLI","Clinical Trial"}, {0x0018,"ACQ","Acquisition"}, {0x0019,"SPIA","SPI Acquisition"}, {0x0020,"IMG","Image"}, {0x0021,"SPIIM","SPI Image"}, {0x0022,"OPHY","Ophtalmology"}, {0x0028,"IMGP","Image Presentation"}, {0x0032,"SDY","Study"}, {0x0038,"VIS","Visit"}, {0x003a,"WAV","Waveform"}, {0x0040,"PRC","Procedure"}, {0x0040,"MOD","Modality Worklist"}, {0x0042,"EDOC","Encapsulated Document"}, {0x0050,"XAD","XRay Angio Device"}, {0x0050,"DEV","Device Information"}, {0x0054,"NMI","Nuclear Medicine"}, {0x0060,"HIS","Histogram"}, {0x0070,"PRS","Presentation State"}, {0x0072,"HST","Hanging Protocol"}, {0x0088,"STO","Storage"}, {0x0088,"MED","Medicine"}, {0x0100,"AUTH","Authorization"}, {0x0400,"DSIG","Digital Signature"}, {0x1000,"COT","Code Table"}, {0x1010,"ZMAP","Zonal Map"}, {0x2000,"BFS","Film Session"}, {0x2010,"BFB","Film Box"}, {0x2020,"BIB","Image Box"}, {0x2030,"BAB","Annotation"}, {0x2040,"IOB","Overlay Box"}, {0x2050,"PLUT","Presentation LUT"}, {0x2100,"PJ","Print Job"}, {0x2110,"PRINTER","Printer"}, {0x2120,"QUE","Queue"}, {0x2130,"PCT","Print Content"}, {0x2200,"MEDIAC","Media Creation"}, {0x3002,"RTI","RT Image"}, {0x3004,"RTD","RT Dose"}, {0x3006,"SSET","RT StructureSet"}, {0x3008,"RTT","RT Treatment"}, {0x300a,"RTP","RT Plan"}, {0x300c,"RTR","RT Relationship"}, {0x300e,"RTA","RT Approval"}, {0x4000,"TXT","Text"}, {0x4008,"RES","Results"}, {0x4ffe,"MAC","MAC Parameters"}, {0x5000,"CRV","Curve"}, {0x5002,"CRV","Curve"}, {0x5004,"CRV","Curve"}, {0x5006,"CRV","Curve"}, {0x5008,"CRV","Curve"}, {0x500a,"CRV","Curve"}, {0x500c,"CRV","Curve"}, {0x500e,"CRV","Curve"}, {0x5400,"WFM","Waveform Data"}, {0x6000,"OLY","Overlays"}, {0x6002,"OLY","Overlays"}, {0x6004,"OLY","Overlays"}, {0x6008,"OLY","Overlays"}, {0x600a,"OLY","Overlays"}, {0x600c,"OLY","Overlays"}, {0x600e,"OLY","Overlays"}, {0xfffc,"GEN","Generic"}, {0x7fe0,"PXL","Pixel Data"}, {0xffff,"UNK","Unknown"}, {0,nullptr,nullptr} // will not be added to the dict }; void GroupDict::FillDefaultGroupName() { unsigned int i = 0; GROUP_ENTRY n = groupname[i]; while( n.name != nullptr ) { Insert( n.group, n.abbreviation, n.name ); n = groupname[++i]; } } } // namespace gdcm GDCM-3.0.10/Source/DataDictionary/gdcmDict.h000066400000000000000000000227441412732066400203510ustar00rootroot00000000000000/*========================================================================= 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 GDCMDICT_H #define GDCMDICT_H #include "gdcmTypes.h" #include "gdcmTag.h" #include "gdcmPrivateTag.h" #include "gdcmDictEntry.h" #include "gdcmSystem.h" #include #include #include /* * FIXME / TODO * I need to seriously rewrite this mess. a class template should work for both a public * and a private dict */ namespace gdcm { // Data Element Tag /** * \brief Class to represent a map of DictEntry * \note bla * TODO FIXME: For Element == 0x0 need to return * Name = Group Length * ValueRepresentation = UL * ValueMultiplicity = 1 */ class GDCM_EXPORT Dict { public: typedef std::map MapDictEntry; typedef MapDictEntry::iterator Iterator; typedef MapDictEntry::const_iterator ConstIterator; //static DictEntry GroupLengthDictEntry; // = DictEntry("Group Length",VR::UL,VM::VM1); Dict():DictInternal() { assert( DictInternal.empty() ); } Dict &operator=(const Dict &_val) = delete; Dict(const Dict &_val) = delete; friend std::ostream& operator<<(std::ostream& _os, const Dict &_val); ConstIterator Begin() const { return DictInternal.begin(); } ConstIterator End() const { return DictInternal.end(); } bool IsEmpty() const { return DictInternal.empty(); } void AddDictEntry(const Tag &tag, const DictEntry &de) { #ifndef NDEBUG MapDictEntry::size_type s = DictInternal.size(); #endif DictInternal.insert( MapDictEntry::value_type(tag, de)); assert( s < DictInternal.size() ); } const DictEntry &GetDictEntry(const Tag &tag) const { MapDictEntry::const_iterator it = DictInternal.find(tag); if (it == DictInternal.end()) { #ifdef UNKNOWNPUBLICTAG // test.acr if( tag != Tag(0x28,0x15) && tag != Tag(0x28,0x16) && tag != Tag(0x28,0x199) // gdcmData/TheralysGDCM1.dcm && tag != Tag(0x20,0x1) // gdcmData/0019004_Baseline_IMG1.dcm && tag != Tag(0x8348,0x339) && tag != Tag(0xb5e8,0x338) // gdcmData/dicomdir_Acusson_WithPrivate_WithSR && tag != Tag(0x40,0xa125) ) { assert( 0 && "Impossible" ); } #endif it = DictInternal.find( Tag(0xffff,0xffff) ); return it->second; } assert( DictInternal.count(tag) == 1 ); return it->second; } /// Function to return the Keyword from a Tag const char *GetKeywordFromTag(Tag const & tag) const { MapDictEntry::const_iterator it = DictInternal.find(tag); if (it == DictInternal.end()) { return nullptr; } assert( DictInternal.count(tag) == 1 ); return it->second.GetKeyword(); } /// Lookup DictEntry by keyword. Even if DICOM standard defines keyword /// as being unique. The lookup table is built on Tag. Therefore /// looking up a DictEntry by Keyword is more inefficient than looking up /// by Tag. const DictEntry &GetDictEntryByKeyword(const char *keyword, Tag & tag) const { MapDictEntry::const_iterator it = DictInternal.begin(); if( keyword ) { for(; it != DictInternal.end(); ++it) { if( strcmp( keyword, it->second.GetKeyword() ) == 0 ) { // Found a match ! tag = it->first; break; } } } else { it = DictInternal.end(); } if (it == DictInternal.end()) { tag = Tag(0xffff,0xffff); it = DictInternal.find( tag ); return it->second; } assert( DictInternal.count(tag) == 1 ); return it->second; } /// Inefficient way of looking up tag by name. Technically DICOM /// does not guarantee uniqueness (and Curve / Overlay are there to prove it). /// But most of the time name is in fact uniq and can be uniquely link to a tag const DictEntry &GetDictEntryByName(const char *name, Tag & tag) const { MapDictEntry::const_iterator it = DictInternal.begin(); if( name ) { for(; it != DictInternal.end(); ++it) { if( strcmp( name, it->second.GetName() ) == 0 ) { // Found a match ! tag = it->first; break; } } } else { it = DictInternal.end(); } if (it == DictInternal.end()) { tag = Tag(0xffff,0xffff); it = DictInternal.find( tag ); return it->second; } assert( DictInternal.count(tag) == 1 ); return it->second; } protected: friend class Dicts; void LoadDefault(); private: MapDictEntry DictInternal; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& os, const Dict &val) { Dict::MapDictEntry::const_iterator it = val.DictInternal.begin(); for(;it != val.DictInternal.end(); ++it) { const Tag &t = it->first; const DictEntry &de = it->second; os << t << " " << de << '\n'; } return os; } // TODO // For private dict, element < 0x10 should automatically defined: // Name = "Private Creator" // ValueRepresentation = LO // ValueMultiplicity = 1 // Owner = "" /** * \brief Private Dict */ class GDCM_EXPORT PrivateDict { typedef std::map MapDictEntry; friend std::ostream& operator<<(std::ostream& os, const PrivateDict &val); public: PrivateDict() = default; ~PrivateDict() = default; void AddDictEntry(const PrivateTag &tag, const DictEntry &de) { #ifndef NDEBUG MapDictEntry::size_type s = DictInternal.size(); #endif DictInternal.insert( MapDictEntry::value_type(tag, de)); // The following code should only be used when manually constructing a Private.xml file by hand // it will get rid of VR::UN duplicate (ie. if a VR != VR::Un can be found) #if defined(NDEBUG) && 0 if( s == DictInternal.size() ) { MapDictEntry::iterator it = DictInternal.find(tag); assert( it != DictInternal.end() ); DictEntry &duplicate = it->second; assert( de.GetVR() == VR::UN || duplicate.GetVR() == VR::UN ); assert( de.GetVR() != duplicate.GetVR() ); if( duplicate.GetVR() == VR::UN ) { assert( de.GetVR() != VR::UN ); duplicate.SetVR( de.GetVR() ); duplicate.SetVM( de.GetVM() ); assert( GetDictEntry(tag).GetVR() != VR::UN ); assert( GetDictEntry(tag).GetVR() == de.GetVR() ); assert( GetDictEntry(tag).GetVM() == de.GetVM() ); } return; } #endif assert( s < DictInternal.size() /*&& std::cout << tag << "," << de << std::endl*/ ); } /// Remove entry 'tag'. Return true on success (element was found /// and remove). return false if element was not found. bool RemoveDictEntry(const PrivateTag &tag) { MapDictEntry::size_type s = DictInternal.erase(tag); assert( s == 1 || s == 0 ); return s == 1; } bool FindDictEntry(const PrivateTag &tag) const { MapDictEntry::const_iterator it = DictInternal.find(tag); if (it == DictInternal.end()) { return false; } return true; } const DictEntry &GetDictEntry(const PrivateTag &tag) const { // if 0x10 -> return Private Creator MapDictEntry::const_iterator it = DictInternal.find(tag); if (it == DictInternal.end()) { //assert( 0 && "Impossible" ); it = DictInternal.find( PrivateTag(0xffff,0xffff,"GDCM Private Sentinel" ) ); assert (it != DictInternal.end()); return it->second; } assert( DictInternal.count(tag) == 1 ); return it->second; } void PrintXML() const { MapDictEntry::const_iterator it = DictInternal.begin(); std::cout << "\n"; for(;it != DictInternal.end(); ++it) { const PrivateTag &t = it->first; const DictEntry &de = it->second; std::cout << " \n"; } else { std::cout << "\" name=\"" << de.GetName() << "\"/>\n"; } } std::cout << "\n"; } bool IsEmpty() const { return DictInternal.empty(); } protected: friend class Dicts; void LoadDefault(); private: PrivateDict &operator=(const PrivateDict &_val) = delete; PrivateDict(const PrivateDict &_val) = delete; MapDictEntry DictInternal; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& os, const PrivateDict &val) { PrivateDict::MapDictEntry::const_iterator it = val.DictInternal.begin(); for(;it != val.DictInternal.end(); ++it) { const PrivateTag &t = it->first; const DictEntry &de = it->second; os << t << " " << de << '\n'; } return os; } } // end namespace gdcm #endif //GDCMDICT_H GDCM-3.0.10/Source/DataDictionary/gdcmDictConverter.cxx000066400000000000000000000244441412732066400226130ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDictConverter.h" #include #include #include #include #include #include // isdigit #include // for strncmp #include // for sscanf namespace gdcm { // PIMPL Implementation struct DictConverterInternal { // Filename to the .dic file std::string InputFilename; // Path to the output file (either XML or CXX code) std::string OutputFilename; // std::ifstream InputStream; std::ofstream OutputStream; std::string DictName; }; DictConverter::DictConverter() { Internal = new DictConverterInternal; Internal->DictName = "Default"; OutputType = DICT_DEFAULT; } DictConverter::~DictConverter() { delete Internal; } const std::string &DictConverter::GetDictName() const { return Internal->DictName; } void DictConverter::SetDictName(const char *name) { Internal->DictName = name; } void DictConverter::SetInputFileName(const char* filename) { Internal->InputFilename = filename; } const std::string &DictConverter::GetInputFilename() const { return Internal->InputFilename; } void DictConverter::SetOutputFileName(const char* filename) { Internal->OutputFilename = filename; } const std::string &DictConverter::GetOutputFilename() const { return Internal->OutputFilename; } // \TODO this code reexecute... void DictConverter::Convert() { // Open files: std::ifstream &from = Internal->InputStream; //(filename, std::ios::binary); // Keep binary mode !!! from.open( Internal->InputFilename.c_str(), std::ios::binary); std::ofstream &into = Internal->OutputStream; //(outfilename); into.open( Internal->OutputFilename.c_str(), std::ios::binary ); WriteHeader(); std::string line; std::ostringstream os; while(std::getline(from, line)) { if( !line.empty() ) { std::string::iterator e(line.end()-1); if( *e == '\r' ) line.erase(e); } if( *(line.c_str()) == '\0' ) { // If an empty line is found then a new group starts AddGroupLength(); continue; } if( line[2] == 'x' && line[3] == 'x' ) { if(line[0] == '5') { uint16_t start = 0x5000; uint16_t end = 0x50ff; for(uint16_t i= start; i<=end; i+=2) { std::string s1 = line.c_str()+4; os.str(""); os << std::hex << i << s1; if( OutputType == DICT_XML ) { ConvertToXML(os.str().c_str(), s1); } else { ConvertToCXX(os.str().c_str(), s1); } into << s1 << std::endl; } } else if(line[0] == '6') { uint16_t start = 0x6000; uint16_t end = 0x60ff; for(uint16_t i= start; i<=end; i+=2) { std::string s1 = line.c_str()+4; os.str(""); os << std::hex << i << s1; if( OutputType == DICT_XML ) { ConvertToXML(os.str().c_str(), s1); } else { ConvertToCXX(os.str().c_str(), s1); } into << s1 << std::endl; } } else assert(0); } else if ( line[7] == 'x' && line[8] == 'x' ) { if( line[5] == '3' && line[6] == '1' ) { uint16_t start = 0x3100; uint16_t end = 0x31ff; for(uint16_t i= start; i<=end; ++i) { std::string s1(line.c_str(), line.c_str()+5); std::string s = line.c_str()+9; os.str(""); os << s1 << std::hex << i << s; if( OutputType == DICT_XML ) { ConvertToXML(os.str().c_str(), s); } else { ConvertToCXX(os.str().c_str(), s); } into << s << std::endl; } } else assert(0); } else { std::string s; if( OutputType == DICT_XML ) { ConvertToXML(line.c_str(), s); } else { ConvertToCXX(line.c_str(), s); } into << s << std::endl; } } WriteFooter(); } bool DictConverter::ReadVR(const char *raw, VR::VRType &type) { int i = 0; while( !isdigit(*(raw+i))) ++i; std::string vm(raw, raw+i-1); type = VR::GetVRType(vm.c_str()); assert( type != VR::VR_END ); return true; } bool DictConverter::ReadVM(const char *raw, VM::VMType &type) { char vm[8]; int r = sscanf(raw, "%s", vm); assert( r == 1 ); type = VM::GetVMType(vm); assert( type != VM::VM_END ); return true; } bool DictConverter::Readuint16(const char *raw, uint16_t &ov) { unsigned int v; int r = sscanf(raw, "%04x", &v); assert( r == 1 && "Wrong Value read for uint16"); char sv[4+1]; r = sprintf(sv, "%04x", v); assert( r == 4 && "Wrong Value printed for uint16"); assert( strncmp(raw, sv, 4) == 0 ); ov = v; return true; } void DictConverter::WriteHeader() { std::ofstream &of = Internal->OutputStream; const std::string &name = Internal->DictName; of << "#ifndef __gdcm" << name << "Dicts_cxx\n"; of << "#define __gdcm" << name << "Dicts_cxx\n\n"; of << "#include \"gdcmVR.h\"\n"; of << "#include \"gdcmDict.h\"\n"; of << "#include \"gdcmDictEntry.h\"\n\n"; of << "namespace gdcm\n{\n\n"; of << "typedef struct\n{\n"; of << " uint16_t group;\n"; of << " uint16_t element;\n"; if( OutputType == DICT_DEBUG ) { of << " const char *vr;\n"; of << " const char *vm;\n"; } else { of << " VR::VRType vr;\n"; of << " VM::VMType vm;\n"; } of << " const char *name;\n"; of << "} DICT_ENTRY;\n\n"; of << "static const DICT_ENTRY " << name << "DataDict [] = {\n"; } void DictConverter::WriteFooter() { std::ofstream &of = Internal->OutputStream; const std::string &name = Internal->DictName; if(OutputType == DICT_DEBUG ) of << " {0,0,0,0,0}\n"; else of << " {0,0,VR::VR_END,VM::VM_END,0}\n"; of << "};\n\n"; of << "void Dict::Fill" << name << "DataDict()\n"; of << "{\n"; of << " unsigned int i = 0;\n"; of << " DICT_ENTRY n = " << name << "DataDict[i];\n"; of << " while( n.name != 0 )\n"; of << " { \n"; of << " Tag t(n.group, n.element);\n"; of << " DictEntry e( n.name, n.vr, n.vm );\n"; of << " AddDictEntry( t, e );\n"; of << " n = " << name << "DataDict[++i];\n"; of << " }\n"; of << " //Tag t(0, 0);\n"; of << " //DictEntry e( \"\", (VR::VRType)0, (VM::VMType)0);\n"; of << " //AddDictEntry( t, e );\n"; of << "}\n\n"; of << "} //end gdcm namespace\n"; of << "\n#endif\n"; } // Takes as input a raw text file, and converts it into a xml line // Template is: // From // 0000 0000 UL 1 Group Length // into: // bool DictConverter::ConvertToXML(const char *raw, std::string &cxx) { uint16_t group; uint16_t element; VR::VRType vr; VM::VMType vm; Readuint16(raw, group); assert( !(group%2) ); Readuint16(raw+5, element); ReadVR(raw+10, vr); int len = 11+strlen(VR::GetVRString(vr)); ReadVM(raw+len, vm); len += strlen(VM::GetVMString(vm))+1; std::ostringstream os; os << " "; cxx = os.str(); return true; } // Takes as input a raw text file, and converts it into a c++ line // Template is: // From // 0000 0000 UL 1 Group Length // into: // {0x0000, 0x0000, "UL" , "1" , "Group Length"}, bool DictConverter::ConvertToCXX(const char *raw, std::string &cxx) { uint16_t group; uint16_t element; VR::VRType vr; VM::VMType vm; Readuint16(raw, group); //assert( !(group%2) ); // Readuint16(raw+5, element); ReadVR(raw+10, vr); int len = 11+strlen(VR::GetVRString(vr)); ReadVM(raw+len, vm); len += strlen(VM::GetVMString(vm))+1; std::ostringstream os; os << " {0x" << std::hex << std::setw(4) << std::setfill('0') << group << ", 0x" << std::setw(4) << std::setfill('0'); if( OutputType == DICT_DEBUG ) { os << element << ", \"" << vr << "\" , \"" << vm << "\" , \"" << (raw+len) << "\"}, "; } else { os << element << std::dec << ",(VR::VRType)" << (int)vr << ",(VM::VMType)" << (int)vm << ",\"" << (raw+len) << "\"},"; } cxx = os.str(); return true; } void DictConverter::AddGroupLength() { std::ifstream &from = Internal->InputStream; std::ofstream &into = Internal->OutputStream; std::streampos p = from.tellg(); char group[5]; from.get(group, 5); std::string in = group; const char group_str[] = " 0000 UL 1 Group Length"; std::ostringstream os; std::string out; if( in[2] == 'x' && in[3] == 'x' ) { std::string line = in; if(line[0] == '5') { uint16_t start = 0x5000; uint16_t end = 0x50ff; for(uint16_t i= start; i<=end; i+=2) { os.str(""); os << std::hex << i << group_str; if( OutputType != DICT_XML ) { ConvertToCXX(os.str().c_str(), out); into << out << std::endl; } } } else if(line[0] == '6') { uint16_t start = 0x6000; uint16_t end = 0x60ff; for(uint16_t i= start; i<=end; i+=2) { os.str(""); os << std::hex << i << group_str; if( OutputType != DICT_XML ) { ConvertToCXX(os.str().c_str(), out); into << out << std::endl; } } } } else { in += group_str; if( OutputType == DICT_XML ) { ConvertToXML(in.c_str(), out); } else { ConvertToCXX(in.c_str(), out); } into << out << std::endl; } // seek back from.seekg(p); } } // end namespace gdcm GDCM-3.0.10/Source/DataDictionary/gdcmDictConverter.h000066400000000000000000000040541412732066400222330ustar00rootroot00000000000000/*========================================================================= 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 GDCMDICTCONVERTER_H #define GDCMDICTCONVERTER_H #include "gdcmTypes.h" #include "gdcmVR.h" #include "gdcmVM.h" #include namespace gdcm { class DictConverterInternal; /** * \brief Class to convert a .dic file into something else: * \details * - CXX code : embed dict into shared lib (DICT_DEFAULT) * - Debug mode (DICT_DEBUG) * - XML dict (DICT_XML) * \note */ class GDCM_EXPORT DictConverter { public: DictConverter(); ~DictConverter(); void SetInputFileName(const char* filename); const std::string &GetInputFilename() const; void SetOutputFileName(const char* filename); const std::string &GetOutputFilename() const; int GetOutputType() const { return OutputType; } void SetOutputType(int type) { OutputType = type; } const std::string &GetDictName() const; void SetDictName(const char *name); void Convert(); // Leaving them public for now. Not really user oriented but may be // useful static bool ReadVR(const char *raw, VR::VRType &type); static bool ReadVM(const char *raw, VM::VMType &type); static bool Readuint16(const char *raw, uint16_t &ov); enum OutputTypes { DICT_DEFAULT = 0, DICT_DEBUG, DICT_XML }; protected: void WriteHeader(); void WriteFooter(); bool ConvertToXML(const char *raw, std::string &cxx); bool ConvertToCXX(const char *raw, std::string &cxx); void AddGroupLength(); private: DictConverterInternal *Internal; int OutputType; }; } // end namespace gdcm #endif //GDCMDICTCONVERTER_H GDCM-3.0.10/Source/DataDictionary/gdcmDictEntry.cxx000066400000000000000000000056221412732066400217420ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDictEntry.h" #include "gdcmSystem.h" #include // remove_if namespace gdcm { static bool IsToBeRemoved(int c) { if ( isspace ( c ) ) return true; if( c == '-' ) return true; if( c == '/' ) return true; if( c == '\'' ) return true; if( c == '(' ) return true; if( c == ')' ) return true; if( c == '&' ) return true; if( c == ',' ) return true; return false; } bool DictEntry::CheckKeywordAgainstName(const char *name, const char *keyword) { /* MM / Wed Aug 11 18:55:26 CEST 2010 I cannot get the following working: Problem with: LengthtoEnd vs CommandLengthToEnd Problem with: RecognitionCode vs CommandRecognitionCode Problem with: DataSetType vs CommandDataSetType Problem with: MagnificationType vs CommandMagnificationType Problem with: FrameNumbersofInterestFOI vs FrameNumbersOfInterest Problem with: 3DRenderingType vs ThreeDRenderingType */ if( !name ) return false; if( !keyword ) return false; std::string str = name; std::string::size_type found = str.find( "'s " ); while( found != std::string::npos ) { str.erase( found, 3 ); found = str.find( "'s " ); } std::string::size_type found_mu = str.find( "µ" ); while( found_mu != std::string::npos ) { str.replace( found_mu, 2, "u", 1 ); found_mu = str.find( "µ" ); } /* std::string::size_type found_two = str.find( "2" ); while( found_two != std::string::npos ) { str.replace( found_two, 2, "Two", 1 ); found_two = str.find( "2" ); } */ std::string::size_type found_the = str.find( " the " ); while( found_the != std::string::npos ) { // 'of the' is a special case const std::string ofthe = str.substr( found_the < 3 ? 0 : found_the - 3, 8 ); const std::string forthe = str.substr( found_the < 4 ? 0 : found_the - 4, 9 ); if( ofthe == " of the " || ofthe == " on the " ) { found_the = str.find( " the ", found_the + 5 ); } else if( forthe == " for the " ) { found_the = str.find( " the ", found_the + 5 ); } else { str.erase( found_the, 5 ); found_the = str.find( " the " ); } } str.erase(remove_if(str.begin(), str.end(), IsToBeRemoved), str.end()); if( System::StrCaseCmp(str.c_str(), keyword) == 0 ) return true; // std::cerr << "Problem with: " << str << " vs " << keyword << std::endl; return true; } } GDCM-3.0.10/Source/DataDictionary/gdcmDictEntry.h000066400000000000000000000104511412732066400213630ustar00rootroot00000000000000/*========================================================================= 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 GDCMDICTENTRY_H #define GDCMDICTENTRY_H #include "gdcmVR.h" #include "gdcmVM.h" #include #include #include namespace gdcm { /** * \brief Class to represent an Entry in the Dict * \details Does not really exist within the DICOM definition, just a way to minimize * storage and have a mapping from gdcm::Tag to the needed information * \note bla * TODO FIXME: Need a PublicDictEntry...indeed DictEntry has a notion of retired which * does not exist in PrivateDictEntry... * * \see gdcm::Dict */ class GDCM_EXPORT DictEntry { public: DictEntry(const char *name = "", const char *keyword = "", VR const &vr = VR::INVALID, VM const &vm = VM::VM0, bool ret = false): Name(name), Keyword(keyword), ValueRepresentation(vr), ValueMultiplicity(vm), Retired(ret), GroupXX(false), ElementXX(false) { } friend std::ostream& operator<<(std::ostream& _os, const DictEntry &_val); /// Set/Get VR const VR &GetVR() const { return ValueRepresentation; } void SetVR(const VR & vr) { ValueRepresentation = vr; } // bool IsValid() const { return ValueRepresentation != VR::VR_END; } // !Name.empty() /*&& ValueRepresentation && ValueMultiplicity*/; } /// Set/Get VM const VM &GetVM() const { return ValueMultiplicity; } void SetVM(VM const & vm) { ValueMultiplicity = vm; } /// Set/Get Name const char *GetName() const { return Name.c_str(); } void SetName(const char* name) { Name = name; } /// same as GetName but without spaces... const char *GetKeyword() const { return Keyword.c_str(); } void SetKeyword(const char* keyword) { Keyword = keyword; } /// Set/Get Retired flag bool GetRetired() const { return Retired; } void SetRetired(bool retired) { Retired = retired; } // /// Set whether element is shared in multiple groups (Curve/Overlay typically) void SetGroupXX(bool v) { GroupXX = v; } // /// Set whether element is shared in multiple elements (Source Image IDs typically) void SetElementXX(bool v) { ElementXX = v; } /// Return whether the name of the DataElement can be considered to be unique. /// As of 2008 all elements name were unique (except the expclitely 'XX' ones) bool IsUnique() const { return ElementXX == false && GroupXX == false; } private: // friend class Dict; static bool CheckKeywordAgainstName(const char *name, const char *keyword); private: std::string Name; std::string Keyword; VR ValueRepresentation; VM ValueMultiplicity; bool Retired : 1; bool GroupXX : 1; bool ElementXX : 1; }; #if 0 class GDCM_EXPORT PrivateDictEntry : public DictEntry { public: PrivateDictEntry(const char *name = "", VR::VRType const &vr = VR::INVALID, VM::VMType const &vm = VM::VM0 , bool ret = false, const char *owner = ""):DictEntry(name,vr,vm,ret),Owner(owner) {} PrivateDictEntry(const char *name, const char *vr, const char *vm):DictEntry(name,vr,vm) {} const char *GetOwner() const { return Owner.c_str(); } void SetOwner(const char *owner) { Owner = owner; } private: // SIEMENS MED, GEMS_PETD_01 ... std::string Owner; }; #endif //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& os, const DictEntry &val) { if( val.Name.empty() ) { os << "[No name]"; } else { os << val.Name; } if( val.Keyword.empty() ) { os << "[No keyword]"; } else { os << val.Keyword; } os << "\t" << val.ValueRepresentation << "\t" << val.ValueMultiplicity; if( val.Retired ) { os << "\t(RET)"; } return os; } } // end namespace gdcm #endif //GDCMDICTENTRY_H GDCM-3.0.10/Source/DataDictionary/gdcmDicts.cxx000066400000000000000000000073321412732066400211030ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDicts.h" namespace gdcm { Dicts::Dicts():PublicDict(),ShadowDict() { //PublicType = DICOMV3_DICT; //PublicDicts.resize(3, Dict() ); } Dicts::~Dicts() = default; //void Dicts::AddPublicDict(const Dict& dict) //{ // (void)dict; // //PublicDicts.push_back( dict ); //} //void Dicts::SetPublicType(int type) //{ // PublicType = type; //} const DictEntry &Dicts::GetDictEntry(const Tag& tag, const char *owner) const { if( tag.IsGroupLength() ) { const DictEntry & de = PublicDict.GetDictEntry(tag); const char *name = de.GetName(); if( name && *name ) { return de; } else { bool retired = true; // Since DICOM 2008, all (but 0002,0004) group length are retired static const DictEntry Dummy("Generic Group Length", "GenericGroupLength", VR::UL, VM::VM1, retired); return Dummy; } } else if( tag.IsPublic() ) { assert( owner == nullptr ); return PublicDict.GetDictEntry(tag); } else { assert( tag.IsPrivate() ); if( owner && *owner ) { size_t len = strlen(owner); (void)len; PrivateTag ptag(tag.GetGroup(), (uint16_t)(((uint16_t)(tag.GetElement() << 8)) >> 8), owner); const DictEntry &de = GetPrivateDict().GetDictEntry(ptag); return de; } else { // Check special private element: 0x0000 and [0x1,0xFF] are special cases: if( tag.IsIllegal() ) { static const DictEntry Dummy("Illegal Element", "IllegalElement", VR::INVALID, VM::VM0, false); return Dummy; } else if( tag.IsPrivateCreator() ) { assert( !tag.IsIllegal() ); assert( tag.GetElement() ); // Not a group length ! assert( tag.IsPrivate() ); assert( owner == nullptr ); static const DictEntry Dummy("Private Creator", "PrivateCreator", VR::LO, VM::VM1, false); return Dummy; } else { if( owner && *owner ) { static const DictEntry Dummy("Private Element Without Private Creator", "PrivateElementWithoutPrivateCreator", VR::INVALID, VM::VM0); return Dummy; } else { static const DictEntry Dummy("Private Element With Empty Private Creator", "PrivateElementWithEmptyPrivateCreator", VR::INVALID, VM::VM0); return Dummy; } } } } } const DictEntry &Dicts::GetDictEntry(const PrivateTag& tag) const { return GetDictEntry(tag, tag.GetOwner() ); } const char *Dicts::GetConstructorString(ConstructorType type) { (void)type; return ""; } const Dict &Dicts::GetPublicDict() const { //assert( PublicType < PublicDicts.size() ); return PublicDict; //[PublicType]; } const PrivateDict &Dicts::GetPrivateDict() const { return ShadowDict; } PrivateDict &Dicts::GetPrivateDict() { return ShadowDict; } const CSAHeaderDict &Dicts::GetCSAHeaderDict() const { return CSADict; } void Dicts::LoadDefaults() { // TODO: should the user be able to control which dict to load ? PublicDict.LoadDefault(); ShadowDict.LoadDefault(); CSADict.LoadDefault(); } } // end namespace gdcm GDCM-3.0.10/Source/DataDictionary/gdcmDicts.h000066400000000000000000000042661412732066400205330ustar00rootroot00000000000000/*========================================================================= 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 GDCMDICTS_H #define GDCMDICTS_H #include "gdcmDict.h" #include "gdcmCSAHeaderDict.h" #include namespace gdcm { /** * \brief Class to manipulate the sum of knowledge (all the dict user load) * \note bla */ class GDCM_EXPORT Dicts { friend std::ostream& operator<<(std::ostream &_os, const Dicts &d); public: Dicts(); ~Dicts(); Dicts &operator=(const Dicts &_val) = delete; Dicts(const Dicts &_val) = delete; /// works for both public and private dicts: /// owner is null for public dict /// \warning owner need to be set to appropriate owner for call to work. see // DataSet::GetPrivateCreator /// THREAD SAFE const DictEntry &GetDictEntry(const Tag& tag, const char *owner = nullptr) const; const DictEntry &GetDictEntry(const PrivateTag& tag) const; //enum PublicTypes { // DICOMV3_DICT, // ACRNEMA_DICT, // NIH_DICT //}; const Dict &GetPublicDict() const; const PrivateDict &GetPrivateDict() const; PrivateDict &GetPrivateDict(); const CSAHeaderDict &GetCSAHeaderDict() const; bool IsEmpty() const { return GetPublicDict().IsEmpty(); } protected: typedef enum { PHILIPS, GEMS, SIEMENS // ... } ConstructorType; static const char *GetConstructorString(ConstructorType type); friend class Global; void LoadDefaults(); private: // Public dict: Dict PublicDict; // Private Dicts: PrivateDict ShadowDict; CSAHeaderDict CSADict; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const Dicts &d) { (void)d; return os; } } // end namespace gdcm #endif //GDCMDICTS_H GDCM-3.0.10/Source/DataDictionary/gdcmGlobal.cxx000066400000000000000000000123601412732066400212320ustar00rootroot00000000000000/*========================================================================= 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 "gdcmGlobal.h" #include "gdcmDicts.h" #include "gdcmDefs.h" #include "gdcmFilename.h" #include // PATH_MAX #include // strcpy #ifdef _WIN32 #include // MAX_PATH #endif namespace gdcm { // Must NOT be initialized. Default initialization to zero is // necessary. unsigned int GlobalCount; class GlobalInternal { public: GlobalInternal():GlobalDicts(),GlobalDefs() {} Dicts GlobalDicts; // Part 6 + Part 4 elements // TODO need H table for TransferSyntax / MediaStorage / Part 3 ... Defs GlobalDefs; // Resource paths: // By default only construct two paths: // - The official install dir (need to keep in sync with cmakelist variable // - a dynamic one, so that gdcm is somewhat rellocatable // - on some system where it make sense the path where the Resource should be located void LoadDefaultPaths() { assert( ResourcePaths.empty() ); const char filename2[] = GDCM_CMAKE_INSTALL_PREFIX "/" GDCM_INSTALL_DATA_DIR "/XML/"; ResourcePaths.emplace_back(filename2 ); const char filename3[] = GDCM_CMAKE_INSTALL_PREFIX " " GDCM_API_VERSION "/" GDCM_INSTALL_DATA_DIR "/XML/"; ResourcePaths.emplace_back(filename3 ); const char *curprocfn = System::GetCurrentProcessFileName(); if( curprocfn ) { Filename fn( curprocfn ); std::string str = fn.GetPath(); str += "/../" GDCM_INSTALL_DATA_DIR "/XML/"; ResourcePaths.push_back( str ); } const char *respath = System::GetCurrentResourcesDirectory(); if( respath ) { ResourcePaths.emplace_back(respath ); } #ifdef GDCM_BUILD_TESTING // Needed for backward compat and dashboard const char src_path[] = GDCM_SOURCE_DIR "/Source/InformationObjectDefinition/"; ResourcePaths.emplace_back(src_path ); std::rotate(ResourcePaths.rbegin(), ResourcePaths.rbegin() + 1, ResourcePaths.rend()); #endif } std::vector ResourcePaths; }; Global::Global() { if(++GlobalCount == 1) { assert( Internals == nullptr ); // paranoid Internals = new GlobalInternal; assert( Internals->GlobalDicts.IsEmpty() ); // Fill in with default values now ! // at startup time is safer as later call might be from different thread // thus initialization of std::map would be all skrew up Internals->GlobalDicts.LoadDefaults(); assert( Internals->GlobalDefs.IsEmpty() ); // Same goes for GlobalDefs: //Internals->GlobalDefs.LoadDefaults(); Internals->LoadDefaultPaths(); } } Global::~Global() { if(--GlobalCount == 0) { //Internals->GlobalDicts.Unload(); delete Internals; Internals = nullptr; // paranoid } } bool Global::LoadResourcesFiles() { assert( Internals != nullptr ); // paranoid const char *filename = Locate( "Part3.xml" ); if( filename ) { if( Internals->GlobalDefs.IsEmpty() ) Internals->GlobalDefs.LoadFromFile(filename); return true; } // resource manager was not set properly return false; } bool Global::Append(const char *path) { if( !System::FileIsDirectory(path) ) { return false; } Internals->ResourcePaths.emplace_back(path ); return true; } bool Global::Prepend(const char *path) { if( !System::FileIsDirectory(path) ) { return false; } Internals->ResourcePaths.insert( Internals->ResourcePaths.begin(), path ); return true; } #ifndef PATH_MAX #define PATH_MAX 4096 #endif const char *Global::Locate(const char *resfile) const { #ifdef _WIN32 static char path[MAX_PATH]; #else static char path[PATH_MAX]; #endif std::vector::const_iterator it = Internals->ResourcePaths.begin(); for( ; it != Internals->ResourcePaths.end(); ++it) { const std::string &p = *it; gdcmDebugMacro( "Trying to locate in: " << p ); std::string fullpath = p + "/" + resfile; if( System::FileExists(fullpath.c_str()) ) { // we found a match // check no invalid write access possible: if( fullpath.size() >= sizeof(path) ) { gdcmDebugMacro( "Impossible happen: path is too long" ); return nullptr; } strcpy(path, fullpath.c_str() ); return path; } } // no match sorry :( return nullptr; } Dicts const &Global::GetDicts() const { assert( !Internals->GlobalDicts.IsEmpty() ); return Internals->GlobalDicts; } Dicts &Global::GetDicts() { assert( !Internals->GlobalDicts.IsEmpty() ); return Internals->GlobalDicts; } Defs const &Global::GetDefs() const { assert( !Internals->GlobalDefs.IsEmpty() ); return Internals->GlobalDefs; } Global& Global::GetInstance() { return GlobalInstance; } // Purposely not initialized. ClassInitialize will handle it. GlobalInternal * Global::Internals; } // end namespace gdcm GDCM-3.0.10/Source/DataDictionary/gdcmGlobal.h000066400000000000000000000065711412732066400206660ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // Implementation detail was shamelessly borowed from the VTK excellent // implementation of debug leak manager singleton: /*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkDebugLeaks.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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 GDCMGLOBAL_H #define GDCMGLOBAL_H #include "gdcmTypes.h" namespace gdcm { class GlobalInternal; class Dicts; class Defs; /** * \brief Global * \note * Global should be included in any translation unit * that will use Dict or that implements the singleton * pattern. It makes sure that the Dict singleton is created * before and destroyed after all other singletons in GDCM. * */ class GDCM_EXPORT Global // why expose the symbol I think I only need to expose the instance... { friend std::ostream& operator<<(std::ostream &_os, const Global &g); public: Global(); ~Global(); Global &operator=(const Global &_val) = delete; Global(const Global &_val) = delete; /// retrieve the default/internal dicts (Part 6) /// This dict is filled up at load time Dicts const &GetDicts() const; Dicts &GetDicts(); /// retrieve the default/internal (Part 3) /// You need to explicitly call LoadResourcesFiles before Defs const &GetDefs() const; /// return the singleton instance static Global& GetInstance(); /// Load all internal XML files, resource path need to have been /// set before calling this member function (see Append/Prepend members func) /// \warning not thread safe ! bool LoadResourcesFiles(); /// Append path at the end of the path list /// \warning not thread safe ! bool Append(const char *path); /// Prepend path at the beginning of the path list /// \warning not thread safe ! bool Prepend(const char *path); protected: /// Locate a resource file const char *Locate(const char *resfile) const; private: // PIMPL: // but we could have also directly exposed a Dicts *Internals; static GlobalInternal *Internals; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const Global &g) { (void)g; return os; } // This instance will show up in any translation unit that uses // Global or that has a singleton. It will make sure // Global is initialized before it is used and is the last // static object destroyed. static Global GlobalInstance; } // end namespace gdcm #endif //GDCMGLOBAL_H GDCM-3.0.10/Source/DataDictionary/gdcmGroupDict.cxx000066400000000000000000000024221412732066400217300ustar00rootroot00000000000000/*========================================================================= 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 "gdcmGroupDict.h" namespace gdcm { std::string const &GroupDict::GetAbbreviation(uint16_t num) const { assert(num < Abbreviations.size()); return Abbreviations[num]; } std::string const &GroupDict::GetName(uint16_t num) const { assert(num < Names.size()); return Names[num]; } void GroupDict::Add(std::string const &abbreviation, std::string const &name) { Abbreviations.push_back(abbreviation); Names.push_back(name); } void GroupDict::Insert(uint16_t num, std::string const &abbreviation, std::string const &name) { Abbreviations.resize(num+1); Names.resize(num+1); Abbreviations.insert(Abbreviations.begin()+num, abbreviation); Names.insert(Names.begin()+num, name); } } // end namespace gdcm GDCM-3.0.10/Source/DataDictionary/gdcmGroupDict.h000066400000000000000000000044551412732066400213650ustar00rootroot00000000000000/*========================================================================= 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 GDCMGROUPDICT_H #define GDCMGROUPDICT_H #include "gdcmTypes.h" #include #include #include #include #include namespace gdcm { /** * \brief Class to represent the mapping from group number to its abbreviation and name * \note Should I rewrite this class to use a std::map instead of std::vector for problem of * memory consumption ? */ class GDCM_EXPORT GroupDict { public: typedef std::vector GroupStringVector; GroupDict() { FillDefaultGroupName(); } ~GroupDict() = default; friend std::ostream& operator<<(std::ostream& _os, const GroupDict &_val); size_t Size() const { assert( Names.size() == Abbreviations.size() ); return Names.size(); } std::string const &GetAbbreviation(uint16_t num) const; std::string const &GetName(uint16_t num) const; protected: void Add(std::string const &abbreviation, std::string const &name); void Insert(uint16_t num, std::string const &abbreviation, std::string const &name); private: // Generated implementation, see gdcmDefaultGroupNames void FillDefaultGroupName(); GroupDict &operator=(const GroupDict &_val); // purposely not implemented GroupDict(const GroupDict &_val); // purposely not implemented GroupStringVector Abbreviations; GroupStringVector Names; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& _os, const GroupDict &_val) { size_t size = _val.Size(); for(size_t i=0; i #include #include // for std::getline #include #include #include // std::setw void write_header(std::ofstream &of) { of << "#include \"gdcmTypes.h\"\n" "#include \"gdcmGroupDict.h\"\n\n" "namespace gdcm {\n\n" "typedef struct\n{\n" " uint16_t group;\n" " const char *abbreviation;\n" " const char *name;\n" "} GROUP_ENTRY;\n\n" "static GROUP_ENTRY groupname[] = {\n"; } void write_footer(std::ofstream &of) { of << "\t{0,0,0} // will not be added to the dict \n" "};\n\n" "void GroupDict::FillDefaultGroupName()\n" "{\n" " unsigned int i = 0;\n" " GROUP_ENTRY n = groupname[i];\n" " while( n.name != 0 )\n" " {\n" " Insert( n.group, n.abbreviation, n.name );\n" " n = groupname[++i];\n" " }\n" "}\n\n" "} // namespace gdcm\n"; } bool check_abbr(std::string &abbr) { std::string::const_iterator it = abbr.begin(); for(; it != abbr.end(); ++it) { if ( *it < 'A' || *it > 'Z' ) return false; } return true; } int main(int argc, char *argv[]) { if( argc < 3 ) return 1; const char *filename = argv[1]; // Full path to the dict const char *outfilename = argv[2]; // Full path to output the dict //std::cerr << "open: " << filename << std::endl; std::ifstream from(filename, std::ios::binary); std::ofstream into(outfilename,std::ios::binary); if(!from) { std::cerr << "Problem opening the from file" << std::endl; return 1; } if(!into) { std::cerr << "Problem opening the into file" << std::endl; return 1; } write_header(into); int error = 0; std::string line; while(std::getline(from, line)) { if( !line.empty() ) { std::string::iterator e(line.end()-1); if( *e == '\r' ) line.erase(e); } unsigned int group; // Group Number std::string abbr; // NHI Abbreviation (when known) - not part of DICOM standard - std::string meaning; // Meaning (when known) - not part of DICOM standard - std::istringstream is(line); is >> std::hex >> group; if ( group > 0xffff) return 1; is >> abbr; if( !check_abbr(abbr) ) return 1; // skip any whitespace before calling getline is >> std::ws; // get all the remaining characters std::getline(is,meaning); into << "\t{0x" << std::hex << std::setw(4) << std::setfill('0') << group << ",\"" << abbr << "\",\"" << meaning << "\"},\n"; } write_footer(into); from.close(); into.close(); return error; } GDCM-3.0.10/Source/DataDictionary/gdcmPrivateDefaultDicts.cxx000066400000000000000000032133211412732066400237430ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc DefaultDicts.xsl DICOMV3.xml > gdcmDefaultDicts.cxx /*========================================================================= 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 GDCMPRIVATEDEFAULTDICTS_CXX #define GDCMPRIVATEDEFAULTDICTS_CXX #include "gdcmDicts.h" #include "gdcmVR.h" #include "gdcmDict.h" #include "gdcmDictEntry.h" namespace { using namespace gdcm; using DICT_ENTRY = struct { uint16_t group; uint16_t element; const char *owner; VR::VRType vr; VM::VMType vm; const char *name; bool ret; }; static const DICT_ENTRY DICOMV3DataDict [] = { {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 }, {0x0011,0x0005,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0011,0x0006,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {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 }, {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 }, {0x0019,0x0002,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0002,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0002,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x0002,"TOSHIBA_MEC_MR3^13",VR::US,VM::VM1,"?",false }, {0x0019,0x0003,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0003,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x0003,"TOSHIBA_MEC_MR3^13",VR::SL,VM::VM1,"?",false }, {0x0019,0x0003,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0004,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0004,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0004,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x0004,"TOSHIBA_MEC_MR3^13",VR::US,VM::VM1,"?",false }, {0x0019,0x0005,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0005,"TOSHIBA_MEC_MR3^12",VR::SH,VM::VM1,"?",false }, {0x0019,0x0005,"TOSHIBA_MEC_MR3^13",VR::SL,VM::VM1,"?",false }, {0x0019,0x0006,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x0006,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0007,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM3,"?",false }, {0x0019,0x0007,"TOSHIBA_MEC_MR3^12",VR::UL,VM::VM1_n,"?",false }, {0x0019,0x0008,"TOSHIBA_MEC_MR3^11",VR::SH,VM::VM1,"?",false }, {0x0019,0x0008,"TOSHIBA_MEC_MR3^13",VR::SL,VM::VM1,"?",false }, {0x0019,0x0008,"TOSHIBA_MEC_MR3^12",VR::UL,VM::VM1_n,"?",false }, {0x0019,0x0008,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0009,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0009,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x0009,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM2,"?",false }, {0x0019,0x0009,"TOSHIBA_MEC_MR3^13",VR::SQ,VM::VM1,"?",false }, {0x0019,0x000a,"TOSHIBA_MEC_MR3^13",VR::FD,VM::VM3,"?",false }, {0x0019,0x000a,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x000a,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x000a,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x000b,"TOSHIBA_MEC_MR3^13",VR::FD,VM::VM1,"?",false }, {0x0019,0x000b,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x000b,"TOSHIBA_MEC_MR3^11",VR::OB,VM::VM1,"?",false }, {0x0019,0x000b,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x000c,"TOSHIBA_MEC_MR3^13",VR::FD,VM::VM1,"?",false }, {0x0019,0x000c,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x000c,"TOSHIBA_MEC_MR3^12",VR::UL,VM::VM1,"?",false }, {0x0019,0x000c,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM3,"?",false }, {0x0019,0x000d,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM6,"?",false }, {0x0019,0x000d,"TOSHIBA_MEC_MR3^12",VR::SQ,VM::VM1,"?",false }, {0x0019,0x000e,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM6,"?",false }, {0x0019,0x000e,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM1,"?",false }, {0x0019,0x000f,"TOSHIBA_MEC_MR3^13",VR::SH,VM::VM1,"?",false }, {0x0019,0x000f,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM6,"?",false }, {0x0019,0x0010,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x0010,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM2,"?",false }, {0x0019,0x0011,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x0011,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM2,"?",false }, {0x0019,0x0012,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x0012,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {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^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 }, {0x0019,0x0017,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0018,"TOSHIBA_MEC_MR3^12",VR::UL,VM::VM1,"?",false }, {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,0x001a,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x001b,"TOSHIBA_MEC_MR3^10",VR::SL,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,0x0024,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0025,"TOSHIBA_MEC_MR3^11",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 }, {0x0019,0x0028,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0028,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0029,"TOSHIBA_MEC_MR3^10",VR::SH,VM::VM1,"?",false }, {0x0019,0x0029,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x002a,"TOSHIBA_MEC_MR3^12",VR::DS,VM::VM3,"?",false }, {0x0019,0x002a,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x002b,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x002b,"TOSHIBA_MEC_MR3^10",VR::SH,VM::VM1,"?",false }, {0x0019,0x002b,"TOSHIBA_MEC_MR3^12",VR::SQ,VM::VM1,"?",false }, {0x0019,0x002c,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x002c,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM3,"?",false }, {0x0019,0x002d,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x002d,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM3,"?",false }, {0x0019,0x002e,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x002e,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x002f,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0030,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0030,"TOSHIBA_MEC_MR3^10",VR::UL,VM::VM1,"?",false }, {0x0019,0x0031,"TOSHIBA_MEC_MR3^10",VR::OF,VM::VM1_n,"?",false }, {0x0019,0x0031,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0032,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0032,"TOSHIBA_MEC_MR3^12",VR::SH,VM::VM1,"?",false }, {0x0019,0x0032,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0033,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM3,"?",false }, {0x0019,0x0034,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0034,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0034,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x0035,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0035,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0036,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0036,"TOSHIBA_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, {0x0019,0x0037,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0038,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0038,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0039,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x003a,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x003a,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x003b,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM2,"?",false }, {0x0019,0x003c,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM3,"?",false }, {0x0019,0x003c,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x003d,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x003e,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM9,"?",false }, {0x0019,0x003e,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x003f,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x003f,"TOSHIBA_MEC_MR3^11",VR::UI,VM::VM1,"?",false }, {0x0019,0x0040,"TOSHIBA_MEC_MR3^11",VR::US,VM::VM1,"?",false }, {0x0019,0x0041,"TOSHIBA_MEC_MR3^11",VR::US,VM::VM1,"?",false }, {0x0019,0x0042,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0042,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0043,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0043,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0044,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0044,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0045,"TOSHIBA_MEC_MR3^10",VR::SS,VM::VM1,"?",false }, {0x0019,0x0046,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0046,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0047,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0048,"TOSHIBA_MEC_MR3^11",VR::LT,VM::VM1,"?",false }, {0x0019,0x0048,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0049,"TOSHIBA_MEC_MR3^11",VR::LT,VM::VM1,"?",false }, {0x0019,0x0049,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x004b,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {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,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 }, {0x0019,0x0050,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM2,"?",false }, {0x0019,0x0051,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM2,"?",false }, {0x0019,0x0052,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM2,"?",false }, {0x0019,0x0052,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x0054,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0055,"TOSHIBA_MEC_MR3^11",VR::LO,VM::VM1,"?",false }, {0x0019,0x0055,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0057,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0057,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM3,"?",false }, {0x0019,0x0058,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM3,"?",false }, {0x0019,0x0058,"TOSHIBA_MEC_MR3^11",VR::US,VM::VM1,"?",false }, {0x0019,0x0059,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0059,"TOSHIBA_MEC_MR3^11",VR::US,VM::VM1,"?",false }, {0x0019,0x005a,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1_n,"?",false }, {0x0019,0x005c,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x005d,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1_n,"?",false }, {0x0019,0x005d,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x005e,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x005f,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x005f,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0060,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0060,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0061,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0061,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0062,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0062,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0063,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0063,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0064,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0065,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM2,"?",false }, {0x0019,0x0067,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0068,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0069,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x006a,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x006b,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x006c,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x006d,"TOSHIBA_MEC_MR3^11",VR::SH,VM::VM1,"?",false }, {0x0019,0x006d,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x006e,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {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^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^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,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 }, {0x0019,0x007a,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM2,"?",false }, {0x0019,0x007b,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x007c,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x007c,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM3,"?",false }, {0x0019,0x007d,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x007d,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x007e,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x007e,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x007f,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {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,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 }, {0x0019,0x0086,"TOSHIBA_MEC_MR3^12",VR::LO,VM::VM1,"?",false }, {0x0019,0x0086,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0087,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0087,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0087,"TOSHIBA_MEC_MR3^12",VR::SQ,VM::VM1,"?",false }, {0x0019,0x0088,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x0088,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM1,"?",false }, {0x0019,0x0089,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {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^12",VR::US,VM::VM1,"?",false }, {0x0019,0x008c,"TOSHIBA_MEC_MR3^10",VR::UL,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 }, {0x0019,0x0091,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0092,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0092,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0093,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM3,"?",false }, {0x0019,0x0093,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x0094,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0094,"TOSHIBA_MEC_MR3^12",VR::UI,VM::VM1,"?",false }, {0x0019,0x0095,"TOSHIBA_MEC_MR3^12",VR::UI,VM::VM1,"?",false }, {0x0019,0x0096,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0098,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, {0x0019,0x0099,"TOSHIBA_MEC_MR3^12",VR::LO,VM::VM1,"?",false }, {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^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 }, {0x0019,0x009c,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x009d,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x009d,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM1,"?",false }, {0x0019,0x009e,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, {0x0019,0x009e,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x009f,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x009f,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00a0,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00a0,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00a0,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM4,"?",false }, {0x0019,0x00a1,"TOSHIBA_MEC_MR3^10",VR::DS,VM::VM1,"?",false }, {0x0019,0x00a1,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00a2,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00a2,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00a3,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00a3,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM3,"?",false }, {0x0019,0x00a4,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00a4,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM3,"?",false }, {0x0019,0x00a5,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00a5,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00a5,"TOSHIBA_MEC_MR3^11",VR::US,VM::VM1,"?",false }, {0x0019,0x00a6,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1_n,"?",false }, {0x0019,0x00a6,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00a6,"TOSHIBA_MEC_MR3^11",VR::US,VM::VM1,"?",false }, {0x0019,0x00a7,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00a8,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00a8,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00a8,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00a9,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {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,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 }, {0x0019,0x00ad,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, {0x0019,0x00ad,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00ae,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00ae,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, {0x0019,0x00ae,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00af,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, {0x0019,0x00af,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b0,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x00b0,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b1,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b1,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b2,"TOSHIBA_MEC_MR3^11",VR::US,VM::VM1,"?",false }, {0x0019,0x00b3,"TOSHIBA_MEC_MR3^12",VR::FD,VM::VM1,"?",false }, {0x0019,0x00b3,"TOSHIBA_MEC_MR3^11",VR::US,VM::VM1,"?",false }, {0x0019,0x00b4,"TOSHIBA_MEC_MR3^12",VR::LO,VM::VM1,"?",false }, {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,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 }, {0x0019,0x00b7,"TOSHIBA_MEC_MR3^11",VR::US,VM::VM1,"?",false }, {0x0019,0x00b9,"TOSHIBA_MEC_MR3^11",VR::US,VM::VM1,"?",false }, {0x0019,0x00ba,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00bb,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00bb,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x00bc,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM2,"?",false }, {0x0019,0x00bc,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00bd,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00bd,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00be,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x00be,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00bf,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c0,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c1,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c1,"TOSHIBA_MEC_MR3^11",VR::US,VM::VM1,"?",false }, {0x0019,0x00c2,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM1,"?",false }, {0x0019,0x00c3,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x00c3,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00c3,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c4,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c4,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c5,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c6,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM2,"?",false }, {0x0019,0x00c6,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c7,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00c9,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00ca,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x00cb,"TOSHIBA_MEC_MR3^10",VR::UL,VM::VM1,"?",false }, {0x0019,0x00cc,"TOSHIBA_MEC_MR3^10",VR::UL,VM::VM1,"?",false }, {0x0019,0x00cd,"TOSHIBA_MEC_MR3^12",VR::LO,VM::VM1,"?",false }, {0x0019,0x00cd,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00cd,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM3,"?",false }, {0x0019,0x00ce,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00ce,"TOSHIBA_MEC_MR3^12",VR::UL,VM::VM1,"?",false }, {0x0019,0x00cf,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00cf,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00d0,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x00d1,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, {0x0019,0x00d1,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00d2,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM3,"?",false }, {0x0019,0x00d2,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM3,"?",false }, {0x0019,0x00d3,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00d3,"TOSHIBA_MEC_MR3^12",VR::SS,VM::VM1,"?",false }, {0x0019,0x00d4,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00d4,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM2,"?",false }, {0x0019,0x00d5,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00d6,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, {0x0019,0x00d7,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM2,"?",false }, {0x0019,0x00d8,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1_n,"?",false }, {0x0019,0x00d8,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x00d9,"TOSHIBA_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, {0x0019,0x00da,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x00db,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00dc,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00de,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM1,"?",false }, {0x0019,0x00df,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM1,"?",false }, {0x0019,0x00e0,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x00e0,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM1,"?",false }, {0x0019,0x00e1,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x00e1,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, {0x0019,0x00e1,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00e2,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, {0x0019,0x00e3,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM3,"?",false }, {0x0019,0x00e3,"TOSHIBA_MEC_MR3^12",VR::TM,VM::VM1,"?",false }, {0x0019,0x00e4,"TOSHIBA_MEC_MR3^11",VR::DS,VM::VM1,"?",false }, {0x0019,0x00e4,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00e4,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM2,"?",false }, {0x0019,0x00e5,"TOSHIBA_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, {0x0019,0x00e5,"TOSHIBA_MEC_MR3^11",VR::SQ,VM::VM1,"?",false }, {0x0019,0x00e6,"TOSHIBA_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, {0x0019,0x00e6,"TOSHIBA_MEC_MR3^11",VR::SQ,VM::VM1,"?",false }, {0x0019,0x00e9,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00ea,"TOSHIBA_MEC_MR3^10",VR::UI,VM::VM1,"?",false }, {0x0019,0x00eb,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00eb,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM1,"?",false }, {0x0019,0x00ec,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x00ec,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM1,"?",false }, {0x0019,0x00ee,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00ef,"TOSHIBA_MEC_MR3^12",VR::DS,VM::VM1,"?",false }, {0x0019,0x00ef,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00f0,"TOSHIBA_MEC_MR3^12",VR::LO,VM::VM1,"?",false }, {0x0019,0x00f0,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00f0,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM4,"?",false }, {0x0019,0x00f1,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00f1,"TOSHIBA_MEC_MR3^12",VR::LO,VM::VM1,"?",false }, {0x0019,0x00f1,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM3,"?",false }, {0x0019,0x00f2,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00f2,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM3,"?",false }, {0x0019,0x00f3,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00f3,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00f4,"TOSHIBA_MEC_MR3^10",VR::FD,VM::VM1,"?",false }, {0x0019,0x00f4,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00f5,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00f5,"TOSHIBA_MEC_MR3^11",VR::SQ,VM::VM1,"?",false }, {0x0019,0x00f6,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00f6,"TOSHIBA_MEC_MR3^10",VR::UI,VM::VM1,"?",false }, {0x0019,0x00f7,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00f8,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00f8,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {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^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,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 }, {0x0019,0x00fe,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00fe,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00fe,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x00ff,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00ff,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM3,"?",false }, {0x0021,0x0002,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0021,0x0003,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0021,0x0004,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0021,0x0008,"TOSHIBA_MEC_MR3^10",VR::DS,VM::VM3,"?",false }, {0x0021,0x0009,"TOSHIBA_MEC_MR3^10",VR::DS,VM::VM3,"?",false }, {0x0021,0x000a,"TOSHIBA_MEC_MR3^10",VR::DS,VM::VM3,"?",false }, {0x0021,0x000b,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0021,0x000c,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0021,0x000d,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0021,0x000f,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0021,0x0012,"TOSHIBA_MEC_MR3^10",VR::DS,VM::VM3,"?",false }, {0x0021,0x0014,"TOSHIBA_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, {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,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 }, {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 }, {0x0029,0x0007,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0029,0x001c,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM2,"?",false }, {0x0029,0x0021,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM3,"?",false }, {0x0029,0x004e,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0029,0x0050,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, {0x0029,0x0051,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, {0x0029,0x0052,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, {0x0029,0x0054,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, {0x0029,0x0067,"TOSHIBA_MEC_MR3^10",VR::FD,VM::VM4,"?",false }, {0x0029,0x0068,"TOSHIBA_MEC_MR3^10",VR::SS,VM::VM1,"?",false }, {0x0029,0x006e,"TOSHIBA_MEC_MR3^10",VR::OB,VM::VM1,"?",false }, {0x0029,0x0089,"TOSHIBA_MEC_MR3",VR::LO,VM::VM1,"?",false }, {0x700d,0x0010,"TOSHIBA_MEC_MR3^10",VR::DS,VM::VM1,"2nd Flip Angle [degree]",false }, {0x700d,0x0011,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM2,"Acquisition Inner Matrix",false }, {0x700d,0x0012,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"MP2RAGE Flag",false }, {0x700d,0x0013,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"Inversion efficiency of inversion recovery pulse",false }, {0x700d,0x0014,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"Number of dummy shot",false }, {0x700d,0x0015,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"FFE total repetition time[s]",false }, {0x700d,0x0016,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM3,"PAS Name",false }, {0x700d,0x0017,"TOSHIBA_MEC_MR3^10",VR::LT,VM::VM1,"Intended Processing",false }, {0x700d,0x0018,"TOSHIBA_MEC_MR3^10",VR::SS,VM::VM1_n,"Scanned Orientation IDs",false }, {0x700d,0x0019,"TOSHIBA_MEC_MR3^10",VR::OB,VM::VM1,"PAS Reproduct Information",false }, {0x700d,0x0080,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0xe201,0x0002,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0xe301,0x0000,"TOSHIBA_MEC_MR3^10",VR::SH,VM::VM1,"?",false }, {0xe401,0x0000,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0xe401,0x0001,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0xe401,0x0002,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {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,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 }, {0xe401,0x0020,"TOSHIBA_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, {0xe401,0x0021,"TOSHIBA_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, {0xe401,0x0022,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, {0xe401,0x0023,"TOSHIBA_MEC_MR3^10",VR::SH,VM::VM1,"?",false }, {0xe401,0x0024,"TOSHIBA_MEC_MR3^10",VR::OB,VM::VM1,"?",false }, {0xe403,0x0000,"TOSHIBA_MEC_MR3^13",VR::SH,VM::VM1,"?",false }, {0xe403,0x0000,"TOSHIBA_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, {0xe403,0x0001,"TOSHIBA_MEC_MR3^13",VR::OB,VM::VM1,"?",false }, {0xe403,0x0002,"TOSHIBA_MEC_MR3^13",VR::OB,VM::VM1,"?",false }, {0xe403,0x0003,"TOSHIBA_MEC_MR3^13",VR::OB,VM::VM1,"?",false }, {0xee01,0x0000,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0xee01,0x0001,"TOSHIBA_MEC_MR3^10",VR::OB,VM::VM1,"?",false }, {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}, {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}, {0x2013,0x0011,"BioDICOMizer",VR::ST,VM::VM1,"Custom Storage Former Filename",false}, {0x2013,0x0012,"BioDICOMizer",VR::LO,VM::VM1,"Custom Storage Mime-Type",false}, {0x2013,0x0013,"BioDICOMizer",VR::UL,VM::VM1,"Custom Storage File Length",false}, {0x2013,0x0016,"BioDICOMizer",VR::ST,VM::VM1,"Custom Storage Information Description",false}, {0x2013,0x0017,"BioDICOMizer",VR::UL,VM::VM1,"Custom Storage Number Of Segments",false}, {0x2013,0x0018,"BioDICOMizer",VR::IS,VM::VM1,"Custom Storage Last Byte Padded",false}, {0x2013,0x0010,"BioClinicaImaging",VR::LO,VM::VM1,"Custom Storage Version",false}, {0x2013,0x0011,"BioClinicaImaging",VR::ST,VM::VM1,"Custom Storage Former Filename",false}, {0x2013,0x0012,"BioClinicaImaging",VR::LO,VM::VM1,"Custom Storage Mime-Type",false}, {0x2013,0x0013,"BioClinicaImaging",VR::UL,VM::VM1,"Custom Storage File Length",false}, {0x2013,0x0016,"BioClinicaImaging",VR::ST,VM::VM1,"Custom Storage Information Description",false}, {0x2013,0x0017,"BioClinicaImaging",VR::UL,VM::VM1,"Custom Storage Number Of Segments",false}, {0x2013,0x0018,"BioClinicaImaging",VR::IS,VM::VM1,"Custom Storage Last Byte Padded",false}, {0x2013,0x0001,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #1",false}, {0x2013,0x0002,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #2",false}, {0x2013,0x0003,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #3",false}, {0x2013,0x0004,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #4",false}, {0x2013,0x0005,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #5",false}, {0x2013,0x0006,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #6",false}, {0x2013,0x0007,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #7",false}, {0x2013,0x0008,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #8",false}, {0x2013,0x0009,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #9",false}, {0x7fe1,0x0001,"Bioclinica",VR::UT,VM::VM1,"??",false}, {0x7fe1,0x0002,"Bioclinica",VR::LO,VM::VM1,"??",false}, {0x7fe1,0x0003,"Bioclinica",VR::LO,VM::VM1,"??",false}, {0x5533,0x0033,"Visus Change",VR::SQ,VM::VM1,"Visus Data Save Sequence",false}, {0x5533,0x0035,"Visus Change",VR::DA,VM::VM1,"Visus Data Save Date",false}, {0x5533,0x0037,"Visus Change",VR::LO,VM::VM1,"Visus Data Save Originator",false}, {0x5533,0x0039,"Visus Change",VR::FD,VM::VM1,"Visus Data Save ID",false}, {0x5533,0x003b,"Visus Change",VR::TM,VM::VM1,"?Visus Data Save Time?",false}, {0x0071,0x0021,"SIEMENS MED PT",VR::UI,VM::VM1,"Registration Matrix UID",false}, {0x0071,0x0022,"SIEMENS MED PT",VR::DT,VM::VM1,"Decay Correction DateTime",false}, {0x0071,0x0023,"SIEMENS MED PT",VR::FD,VM::VM16,"Registration Matrix",false}, {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,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,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}, {0x0021,0x0008,"SIEMENS MR SDS 01",VR::SH,VM::VM1,"GradientMode",false}, {0x0021,0x0009,"SIEMENS MR SDS 01",VR::LO,VM::VM1,"PAT mode",false}, {0x0021,0x000a,"SIEMENS MR SDS 01",VR::DS,VM::VM1,"??",false}, {0x0021,0x000c,"SIEMENS MR SDS 01",VR::SH,VM::VM1,"?Orientation?",false}, {0x0021,0x000d,"SIEMENS MR SDS 01",VR::US,VM::VM1,"??",false}, {0x0021,0x000f,"SIEMENS MR SDS 01",VR::DS,VM::VM3,"?Stim_lim?",false}, {0x0021,0x0010,"SIEMENS MR SDS 01",VR::IS,VM::VM1,"PhoenixMetaProtocolVersion",false}, {0x0021,0x0011,"SIEMENS MR SDS 01",VR::DS,VM::VM1,"??",false}, {0x0021,0x0012,"SIEMENS MR SDS 01",VR::FD,VM::VM1,"??",false}, {0x0021,0x0013,"SIEMENS MR SDS 01",VR::DS,VM::VM1,"??",false}, {0x0021,0x0014,"SIEMENS MR SDS 01",VR::IS,VM::VM1,"??",false}, {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,0x001a,"SIEMENS MR SDI 02",VR::SH,VM::VM1,"?RFSWDDataType?",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,0x0022,"SIEMENS MR SDS 01",VR::SH,VM::VM1,"Manufacturer",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}, {0x0021,0x0027,"SIEMENS MR SDS 01",VR::US,VM::VM1,"??",false}, {0x0021,0x002a,"SIEMENS MR SDS 01",VR::IS,VM::VM1_n,"?CoilId?",false}, {0x0021,0x002b,"SIEMENS MR SDS 01",VR::ST,VM::VM1,"?ImaAbsTablePosition?",false}, {0x0021,0x002c,"SIEMENS MR SDS 01",VR::DS,VM::VM3,"??",false}, {0x0021,0x002d,"SIEMENS MR SDS 01",VR::DS,VM::VM3,"??",false}, {0x0021,0x002e,"SIEMENS MR SDS 01",VR::IS,VM::VM1,"??",false}, {0x0021,0x002f,"SIEMENS MR SDS 01",VR::DS,VM::VM3,"??",false}, {0x0021,0x0030,"SIEMENS MR SDS 01",VR::DS,VM::VM1,"??",false}, {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 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,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 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,0x0049,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"??",false}, {0x0021,0x004e,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"??",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,0x0053,"SIEMENS MR SDI 02",VR::FD,VM::VM1,"?BandwidthPerPixelPhaseEncode?",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,0x005d,"SIEMENS MR SDS 01",VR::SL,VM::VM1,"??",false}, {0x0021,0x005e,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"?FrameIndex?",false}, {0x0021,0x0063,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"?Acquisition Number?",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,0x0088,"SIEMENS MR SDI 02",VR::DS,VM::VM1,"Slice Location",false}, {0x0021,0x008a,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"Instance/Frame Number",false}, {0x0021,0x00fe,"SIEMENS MR SDI 02",VR::SQ,VM::VM1,"??",false}, {0x0021,0x00fe,"SIEMENS MR SDS 01",VR::SQ,VM::VM1,"??",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 }, {0x8ff1,0x0020,"SSI Image enhancement Group",VR::IS,VM::VM256,"RGB LUT",false }, {0x8ff1,0x0024,"SSI Image enhancement Group",VR::LO,VM::VM1,"LUT Description",false }, {0x0009,0x00ee,"MEDISO-1",VR::DT,VM::VM1,"?",false }, // ftp://dicom.nema.org/MEDICAL/dicom/DataSets/WG30/Mediso/PETCT/Rat%20C-2-3%20PETCT/Compliance/testratc23enhancedpet2.dcm.dcdump.txt {0x0009,0x00ef,"MEDISO-1",VR::DT,VM::VM1,"?",false }, {0x0009,0x00f0,"MEDISO-1",VR::FD,VM::VM1,"?",false }, {0x0009,0x00f1,"MEDISO-1",VR::FD,VM::VM1,"?",false }, {0x0009,0x00f2,"MEDISO-1",VR::FD,VM::VM1,"?",false }, {0x0009,0x00f3,"MEDISO-1",VR::FD,VM::VM1,"?",false }, {0x0009,0x00fa,"MEDISO-1",VR::ST,VM::VM1,"?",false }, {0x0009,0x00fb,"MEDISO-1",VR::US,VM::VM1,"?",false }, {0x0011,0x0006,"MEDISO-1",VR::LO,VM::VM1,"UUID (variant=RFC 4122,version=4)",false }, {0x0075,0x0000,"LLTech, Light-CT Viewer group",VR::CS,VM::VM1,"Enable MPR",false }, {0x0075,0x0001,"LLTech, Light-CT Viewer group",VR::LO,VM::VM1,"Imaged surface",false }, {0x0075,0x0002,"LLTech, Light-CT Viewer group",VR::LO,VM::VM1,"Imaged depth",false }, {0x0075,0x0003,"LLTech, Light-CT Viewer group",VR::LO,VM::VM1,"Sample description",false }, {0x0075,0x0004,"LLTech, Light-CT Viewer group",VR::SH,VM::VM1,"Number of accumulations",false }, // UL ? {0x0857,0x0000,"Nautilus Medical",VR::LO,VM::VM1,"?Product Name. Eg. DICOM_RAY?",false }, {0x0857,0x0001,"Nautilus Medical",VR::LO,VM::VM1,"?Source Application Entity Title?",false }, {0x0857,0x0002,"Nautilus Medical",VR::LO,VM::VM1,"?Burn date ISO 8601 with decimal second fraction?",false }, {0x0857,0x0003,"Nautilus Medical",VR::LO,VM::VM1,"?",false }, {0x0029,0x0004,"TELEMIS",VR::US,VM::VM1,"?",false }, {0x3129,0x0010,"RamSoft Race Identifier",VR::LO,VM::VM1,"?",false }, {0x7501,0x0001,"CoActiv_PvtTags",VR::LO,VM::VM1,"?",false }, {0x7501,0x0002,"CoActiv_PvtTags",VR::LO,VM::VM1,"?IP Address?",false }, {0x7501,0x0003,"CoActiv_PvtTags",VR::UI,VM::VM1,"?Transfer Syntax UID?",false }, {0x7501,0x0004,"CoActiv_PvtTags",VR::LO,VM::VM1,"?Transfer Syntax Name?",false }, {0x0009,0x0002,"PMTF INFORMATION DATA^10",VR::SH,VM::VM1,"Device Serial Number",false }, {0x0011,0x0003,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0011,0x0004,"PMTF INFORMATION DATA^10",VR::SQ,VM::VM1,"?",false }, {0x0011,0x0005,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0011,0x0006,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {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^12",VR::SL,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,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,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,0x0008,"PMTF INFORMATION DATA^11",VR::SH,VM::VM1,"?",false }, {0x0019,0x0008,"PMTF INFORMATION DATA^12",VR::UL,VM::VM2,"?",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,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,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,0x0011,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x0012,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0012,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x0013,"PMTF INFORMATION DATA^10",VR::SL,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,0x0014,"PMTF INFORMATION DATA^12",VR::FL,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,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,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,0x0024,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0025,"PMTF INFORMATION DATA^11",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^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,0x002b,"PMTF INFORMATION DATA^11",VR::FL,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,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,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,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^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,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,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,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,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,0x0043,"PMTF INFORMATION DATA^11",VR::SL,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,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,0x0049,"PMTF INFORMATION DATA^11",VR::LT,VM::VM1,"?Atlas Head?",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,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,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,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,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,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 }, {0x0019,0x0059,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, {0x0019,0x005a,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1_n,"?",false }, {0x0019,0x005c,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x005d,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1_n,"?",false }, {0x0019,0x005d,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {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,0x0061,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0062,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0062,"PMTF INFORMATION DATA^11",VR::FL,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,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,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,0x0070,"PMTF INFORMATION DATA^11",VR::FL,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 }, {0x0019,0x0073,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?Sequence Options?",false }, {0x0019,0x0075,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x0076,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x0076,"PMTF INFORMATION DATA^12",VR::OB,VM::VM1,"?",false }, {0x0019,0x0078,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x0078,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0079,"PMTF INFORMATION DATA^12",VR::SQ,VM::VM1,"?",false }, {0x0019,0x007a,"PMTF INFORMATION DATA^11",VR::SL,VM::VM2,"?",false }, {0x0019,0x007b,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x007c,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x007c,"PMTF INFORMATION DATA^11",VR::FL,VM::VM3,"?",false }, {0x0019,0x007d,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x007d,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x007e,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {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,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,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 }, {0x0019,0x0088,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?RxGain?",false }, {0x0019,0x0088,"PMTF INFORMATION DATA^12",VR::US,VM::VM1,"Series Number Global",false }, {0x0019,0x0089,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x008a,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1_n,"?",false }, {0x0019,0x008a,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, {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,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,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^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,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,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,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,0x009f,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00a0,"PMTF INFORMATION DATA^10",VR::SL,VM::VM4,"?",false }, {0x0019,0x00a0,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",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,0x00a2,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00a3,"PMTF INFORMATION DATA^10",VR::SL,VM::VM3,"?",false }, {0x0019,0x00a3,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00a4,"PMTF INFORMATION DATA^10",VR::FL,VM::VM3,"?",false }, {0x0019,0x00a4,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",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,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^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00a9,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00a9,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?",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,0x00ac,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?",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,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,0x00af,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?",false }, {0x0019,0x00b0,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b0,"PMTF INFORMATION DATA^11",VR::FL,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,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,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 }, {0x0019,0x00b7,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, {0x0019,0x00b9,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, {0x0019,0x00ba,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00bb,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00bb,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x00bc,"PMTF INFORMATION DATA^10",VR::FL,VM::VM2,"?",false }, {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,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,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 }, {0x0019,0x00c6,"PMTF INFORMATION DATA^10",VR::FL,VM::VM2,"?",false }, {0x0019,0x00c6,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c7,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, {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,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,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,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 }, {0x0019,0x00d3,"PMTF INFORMATION DATA^12",VR::SS,VM::VM1,"?",false }, {0x0019,0x00d4,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00d4,"PMTF INFORMATION DATA^12",VR::US,VM::VM2,"?",false }, {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,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 }, {0x0019,0x00dc,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00de,"PMTF INFORMATION DATA^12",VR::US,VM::VM1,"?num?",false }, {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,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^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 }, {0x0019,0x00e6,"PMTF INFORMATION DATA^10",VR::SQ,VM::VM1,"?",false }, {0x0019,0x00e6,"PMTF INFORMATION DATA^11",VR::SQ,VM::VM1,"?",false }, {0x0019,0x00e9,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00ea,"PMTF INFORMATION DATA^10",VR::UI,VM::VM1,"?",false }, {0x0019,0x00eb,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00eb,"PMTF INFORMATION DATA^12",VR::US,VM::VM1,"?num?",false }, {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,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,0x00f2,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00f2,"PMTF INFORMATION DATA^11",VR::FL,VM::VM3,"?",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,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,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,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 }, {0x0019,0x00fd,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00fd,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00fd,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, {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 }, {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 }, {0x0021,0x0008,"PMTF INFORMATION DATA^10",VR::DS,VM::VM3,"?vect1?",false }, {0x0021,0x0009,"PMTF INFORMATION DATA^10",VR::DS,VM::VM3,"?vect2?",false }, {0x0021,0x000a,"PMTF INFORMATION DATA^10",VR::DS,VM::VM3,"?vect3?",false }, {0x0021,0x000b,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0021,0x000c,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0021,0x000d,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0021,0x000f,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0021,0x0012,"PMTF INFORMATION DATA^10",VR::DS,VM::VM3,"?vect4?",false }, {0x0021,0x0014,"PMTF INFORMATION DATA^10",VR::SQ,VM::VM1,"?matrix?",false }, {0x0021,0x0015,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0021,0x0016,"PMTF INFORMATION DATA^10",VR::FL,VM::VM2,"?",false }, {0x0021,0x0018,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"Series Number Local",false }, {0x0021,0x001a,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?num2?",false }, {0x0021,0x001d,"PMTF INFORMATION DATA^10",VR::IS,VM::VM1,"?num3?",false }, {0x0021,0x001f,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?num?",false }, {0x0029,0x0001,"PMTF INFORMATION DATA^10",VR::SL,VM::VM3,"Diffusion Gradient Orientation / Toshiba Orientation ",false }, {0x0029,0x0005,"PMTF INFORMATION DATA^10",VR::SQ,VM::VM1,"?seq?",false }, {0x0029,0x0006,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?num?",false }, {0x0029,0x0007,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?num?",false }, {0x0029,0x001c,"PMTF INFORMATION DATA^10",VR::FL,VM::VM2,"?vect2?",false }, {0x0029,0x0021,"PMTF INFORMATION DATA^10",VR::SL,VM::VM3,"?vect3?",false }, {0x0029,0x004e,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?num?",false }, {0x0029,0x0050,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?root filepath?",false }, {0x0029,0x0051,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?series filepath?",false }, {0x0029,0x0052,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?instance filepath?",false }, {0x0029,0x0054,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?study filepath?",false }, {0x0029,0x0067,"PMTF INFORMATION DATA^10",VR::FD,VM::VM4,"Series Diffusion Info (b-value,x,y,z)",false }, {0x0029,0x0068,"PMTF INFORMATION DATA^10",VR::SS,VM::VM1,"?num 1?",false }, {0x0029,0x006e,"PMTF INFORMATION DATA^10",VR::OB,VM::VM1,"?",false }, //{0x0029,0x0089,"PMTF INFORMATION DATA",VR::LO,VM::VM1,"?",false }, /* defined below */ {0xe201,0x0002,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0xe301,0x0000,"PMTF INFORMATION DATA^10",VR::SH,VM::VM1,"Series Description",false }, {0xe401,0x0000,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?num?",false }, {0xe401,0x0001,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?num?",false }, {0xe401,0x0002,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?num?",false }, {0xe401,0x0003,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?num?",false }, {0xe401,0x0004,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?num?",false }, {0xe401,0x0005,"PMTF INFORMATION DATA^10",VR::OB,VM::VM1,"?blob?",false }, {0xe401,0x0007,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0xe401,0x0008,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?ADC factor?",false }, {0xe401,0x0012,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?num?",false }, {0xe401,0x0013,"PMTF INFORMATION DATA^10",VR::OB,VM::VM1,"Icon DIB (Microsoft Windows 3.X Packed Device-Independent Bitmap)",false }, {0xe401,0x0020,"PMTF INFORMATION DATA^10",VR::SQ,VM::VM1,"?seq?",false }, {0xe401,0x0021,"PMTF INFORMATION DATA^10",VR::SQ,VM::VM1,"?seq?",false }, {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,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 }, {0xee01,0x0000,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0xee01,0x0001,"PMTF INFORMATION DATA^10",VR::OB,VM::VM1,"?",false }, {0xee01,0x0002,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x3001,0x0001,"Philips3D",VR::UL,VM::VM1,"Number of Time Phases",false }, {0x3001,0x0002,"Philips3D",VR::US,VM::VM1,"Physical Units Z Direction",false }, {0x3001,0x0003,"Philips3D",VR::FD,VM::VM1,"Physical Delta Z",false }, {0x3001,0x0004,"Philips3D",VR::UI,VM::VM1,"?UID?",false }, {0x6301,0x0001,"KRETZ_PRIVATE",VR::IS,VM::VM1,"?",false }, {0x6301,0x0002,"KRETZ_PRIVATE",VR::IS,VM::VM1,"?",false }, {0x0029,0x0000,"VOLCANO-PCDE 1.0",VR::DS,VM::VM1,"Pullback Rate",false }, {0x0029,0x0001,"VOLCANO-PCDE 1.0",VR::FD,VM::VM1,"B Gain",false }, {0x0029,0x0002,"VOLCANO-PCDE 1.0",VR::US,VM::VM1,"B Persistence Index",false }, {0x0029,0x0003,"VOLCANO-PCDE 1.0",VR::FD,VM::VM1,"B ROI Diameter",false }, {0x0029,0x0004,"VOLCANO-PCDE 1.0",VR::US,VM::VM1,"CF Sensitivity Index",false }, {0x0029,0x0005,"VOLCANO-PCDE 1.0",VR::FD,VM::VM1,"CF ROI Diameter",false }, {0x0029,0x0006,"VOLCANO-PCDE 1.0",VR::US,VM::VM1,"Frame Capture Interleave Rate",false }, {0x0029,0x0007,"VOLCANO-PCDE 1.0",VR::US,VM::VM1,"Ringdown Subtraction",false }, {0x0029,0x0008,"VOLCANO-PCDE 1.0",VR::US,VM::VM1,"Graticule Spacing",false }, {0x0029,0x0010,"VOLCANO-PCDE 1.0",VR::SH,VM::VM1,"PIM Serial Number",false }, {0x0029,0x0011,"VOLCANO-PCDE 1.0",VR::OB,VM::VM1,"Color Palette",false }, {0x0029,0x0012,"VOLCANO-PCDE 1.0",VR::UT,VM::VM1,"Measurement Data",false }, {0x0029,0x0015,"VOLCANO-PCDE 1.0",VR::US,VM::VM1,"Still Image Number",false }, {0x0029,0x0016,"VOLCANO-PCDE 1.0",VR::US,VM::VM1,"Video Loop Number",false }, {0x0029,0x0030,"VOLCANO-PCDE 1.0",VR::SS,VM::VM1,"Catheter Boot Mode",false }, {0x0029,0x0010,"ShowcaseAppearance",VR::DS,VM::VM1,"?",false }, {0x0029,0x0011,"ShowcaseAppearance",VR::DS,VM::VM1,"?",false }, {0x0029,0x0012,"ShowcaseAppearance",VR::DS,VM::VM1,"?",false }, {0x0029,0x0013,"ShowcaseAppearance",VR::DS,VM::VM1,"?",false }, {0x0029,0x0014,"ShowcaseAppearance",VR::SQ,VM::VM1,"?",false }, {0x2111,0x0010,"Viztek OPALRAD PrivateGroup",VR::UT,VM::VM1,"XML annotations",false }, {0x0caf,0x0011,"Xinapse Systems",VR::LO,VM::VM1,"Private attributes Identification Code",false }, {0x0caf,0x0001,"Xinapse Systems",VR::OB,VM::VM1,"Regions of interest",false }, {0x0043,0x0014,"dcm4che/archive",VR::AE,VM::VM1,"ae name 1",false }, {0x0043,0x0015,"dcm4che/archive",VR::AE,VM::VM1,"ae name 2",false }, {0x0009,0x0001,"DicomUtils 20100512",VR::SQ,VM::VM1,"DICOMUTILS_PROCESSING_METHODS",false }, {0x0009,0x0002,"DicomUtils 20100512",VR::LO,VM::VM1,"DICOMUTILS_VERSION",false }, {0x0009,0x0003,"DicomUtils 20100512",VR::LT,VM::VM1,"DICOMUTILS_ARGS",false }, {0x0009,0x0004,"DicomUtils 20100512",VR::LT,VM::VM1,"DICOMUTILS_COMMENT",false }, {0x0009,0x0005,"DicomUtils 20100512",VR::LT,VM::VM1,"DICOMUTILS_SITE",false }, {0x0053,0x0001,"3Z_IMAGE_IMPORT_CLIENT_INFO",VR::LO,VM::VM1,"?Date+Time?",false }, {0x0053,0x0002,"3Z_IMAGE_IMPORT_CLIENT_INFO",VR::LO,VM::VM1,"?Org Name?",false }, {0x0053,0x0003,"3Z_IMAGE_IMPORT_CLIENT_INFO",VR::LO,VM::VM1,"?Software Version?",false }, {0x0053,0x0004,"3Z_IMAGE_IMPORT_CLIENT_INFO",VR::LO,VM::VM1,"?ID?",false }, {0x0053,0x0005,"3Z_IMAGE_IMPORT_CLIENT_INFO",VR::LO,VM::VM1,"?IP Address?",false }, {0x0053,0x0006,"3Z_IMAGE_IMPORT_CLIENT_INFO",VR::LO,VM::VM1,"?AE Title?",false }, {0x0055,0x0001,"3Z_IMAGE_IMPORT_GENERAL_HIST",VR::LO,VM::VM1_n,"Copy of Specific Character Set (0008,0005)",false }, {0x0055,0x0003,"3Z_IMAGE_IMPORT_GENERAL_HIST",VR::LO,VM::VM3,"Copy of Study Instance UID (0020,000d)",false }, {0x0055,0x0004,"3Z_IMAGE_IMPORT_GENERAL_HIST",VR::LO,VM::VM3,"Copy of Series Instance UID (0020,000e)",false }, {0x0055,0x0005,"3Z_IMAGE_IMPORT_GENERAL_HIST",VR::LO,VM::VM3,"Copy of SOP Instance UID (0008,0018)",false }, {0x0055,0x0006,"3Z_IMAGE_IMPORT_GENERAL_HIST",VR::LO,VM::VM3,"Copy of Patient ID (0010,0010)",false }, {0x0055,0x0007,"3Z_IMAGE_IMPORT_GENERAL_HIST",VR::LO,VM::VM3,"Copy of Patient's Name (0010,0010)",false }, {0x0055,0x0008,"3Z_IMAGE_IMPORT_GENERAL_HIST",VR::LO,VM::VM3,"Copy of Patient's Birth Date (0010,1030)",false }, {0x0055,0x0009,"3Z_IMAGE_IMPORT_GENERAL_HIST",VR::LO,VM::VM3,"Copy of Patient's Sex (0010,0040)",false }, {0x0055,0x0012,"3Z_IMAGE_IMPORT_GENERAL_HIST",VR::LO,VM::VM3,"Copy of Study Description (0008,1030)",false }, {0x0055,0x0013,"3Z_IMAGE_IMPORT_GENERAL_HIST",VR::LO,VM::VM3,"Copy of Accession Number (0008,0050)",false }, {0x0029,0x0000,"1.2.840.113663.1",VR::US,VM::VM1,"?",false }, {0x0029,0x0001,"1.2.840.113663.1",VR::US,VM::VM1,"?",false }, {0x0019,0x0010,"1.2.840.113681",VR::ST,VM::VM1,"CR Image Params Common",false }, {0x0019,0x0011,"1.2.840.113681",VR::ST,VM::VM1,"CR Image IP Params Single",false }, {0x0019,0x0012,"1.2.840.113681",VR::ST,VM::VM1,"CR Image IP Params Left",false }, {0x0019,0x0013,"1.2.840.113681",VR::ST,VM::VM1,"CR Image IP Params Right",false }, {0x0087,0x0010,"1.2.840.113708.794.1.1.2.0",VR::CS,VM::VM1,"Media Type",false }, {0x0087,0x0020,"1.2.840.113708.794.1.1.2.0",VR::CS,VM::VM1,"Media Location",false }, {0x0087,0x0030,"1.2.840.113708.794.1.1.2.0",VR::ST,VM::VM1,"Storage File ID",false }, {0x0087,0x0040,"1.2.840.113708.794.1.1.2.0",VR::DS,VM::VM1,"Study or Image Size in MB",false }, {0x0087,0x0050,"1.2.840.113708.794.1.1.2.0",VR::IS,VM::VM1,"Estimated Retrieve Time",false }, {0x0029,0x0020,"2.16.840.1.114059.1.1.6.1.50.1",VR::LT,VM::VM1,"Description",false }, {0x0029,0x0021,"2.16.840.1.114059.1.1.6.1.50.1",VR::ST,VM::VM1,"Orientation",false }, {0x0029,0x0022,"2.16.840.1.114059.1.1.6.1.50.1",VR::ST,VM::VM1,"Parameter 1",false }, {0x0029,0x0023,"2.16.840.1.114059.1.1.6.1.50.1",VR::ST,VM::VM1,"Parameter 2",false }, {0x0029,0x0024,"2.16.840.1.114059.1.1.6.1.50.1",VR::LO,VM::VM1,"Teeth",false }, {0x0029,0x0025,"2.16.840.1.114059.1.1.6.1.50.1",VR::LO,VM::VM1,"Jaw",false }, {0x0029,0x0026,"2.16.840.1.114059.1.1.6.1.50.1",VR::LO,VM::VM1,"Quadrant",false }, {0x0029,0x0027,"2.16.840.1.114059.1.1.6.1.50.1",VR::LO,VM::VM1,"CRC",false }, {0x3711,0x0001,"A.L.I. Technologies, Inc.",VR::LO,VM::VM1,"Filename",false }, {0x3711,0x0002,"A.L.I. Technologies, Inc.",VR::OB,VM::VM1,"Data Blob of a Visit",false }, {0x3711,0x0003,"A.L.I. Technologies, Inc.",VR::US,VM::VM1,"Revision Number",false }, {0x3711,0x0004,"A.L.I. Technologies, Inc.",VR::UL,VM::VM1,"Unix Timestamp",false }, {0x3711,0x0005,"A.L.I. Technologies, Inc.",VR::IS,VM::VM1,"Bag ID",false }, {0x3711,0x000c,"A.L.I. Technologies, Inc.",VR::UI,VM::VM1,"Original Study UID",false }, {0x3711,0x000d,"A.L.I. Technologies, Inc.",VR::US,VM::VM1,"Overlay Grayscale Value",false }, {0x3711,0x000e,"A.L.I. Technologies, Inc.",VR::CS,VM::VM1,"Anonymization Status",false }, {0x0009,0x0000,"ACUSON",VR::IS,VM::VM1,"?",false }, {0x0009,0x0001,"ACUSON",VR::IS,VM::VM1,"?",false }, {0x0009,0x0002,"ACUSON",VR::UN,VM::VM1,"?",false }, {0x0009,0x0003,"ACUSON",VR::UN,VM::VM1,"?",false }, {0x0009,0x0004,"ACUSON",VR::UN,VM::VM1,"?",false }, {0x0009,0x0005,"ACUSON",VR::UN,VM::VM1,"?",false }, {0x0009,0x0006,"ACUSON",VR::UN,VM::VM1,"?",false }, {0x0009,0x0007,"ACUSON",VR::UN,VM::VM1,"?",false }, {0x0009,0x0008,"ACUSON",VR::LT,VM::VM1,"?",false }, {0x0009,0x0009,"ACUSON",VR::LT,VM::VM1,"?",false }, {0x0009,0x000a,"ACUSON",VR::IS,VM::VM1,"?",false }, {0x0009,0x000b,"ACUSON",VR::IS,VM::VM1,"?",false }, {0x0009,0x000c,"ACUSON",VR::IS,VM::VM1,"?",false }, {0x0009,0x000d,"ACUSON",VR::IS,VM::VM1,"?",false }, {0x0009,0x000e,"ACUSON",VR::IS,VM::VM1,"?",false }, {0x0009,0x000f,"ACUSON",VR::UN,VM::VM1,"?",false }, {0x0009,0x0010,"ACUSON",VR::IS,VM::VM1,"?",false }, {0x0009,0x0011,"ACUSON",VR::UN,VM::VM1,"?",false }, {0x0009,0x0012,"ACUSON",VR::IS,VM::VM1,"?",false }, {0x0009,0x0013,"ACUSON",VR::IS,VM::VM1,"?",false }, {0x0009,0x0014,"ACUSON",VR::LT,VM::VM1,"?",false }, {0x0009,0x0015,"ACUSON",VR::UN,VM::VM1,"?",false }, {0x7fdf,0x0000,"ACUSON: 1.2.840.11386.1.0",VR::IS,VM::VM1,"Lossy Compression Ratio",false }, {0x7fdf,0x0001,"ACUSON: 1.2.840.11386.1.0",VR::US,VM::VM1,"Image Format",false }, {0x7fdf,0x0002,"ACUSON: 1.2.840.11386.1.0",VR::US,VM::VM1,"Acuson Region Type",false }, {0x7fdf,0x000b,"ACUSON: 1.2.840.11386.1.0",VR::UL,VM::VM1,"Acuson Image Apex X",false }, {0x7fdf,0x000c,"ACUSON: 1.2.840.11386.1.0",VR::UL,VM::VM1,"Acuson Image Apex Y",false }, {0x7fdf,0x000d,"ACUSON: 1.2.840.11386.1.0",VR::IS,VM::VM1,"B-Color-On Flag",false }, {0x0009,0x0020,"ACUSON:1.2.840.113680.1.0:0921",VR::UN,VM::VM1,"View Name",false }, {0x0009,0x002a,"ACUSON:1.2.840.113680.1.0:0921",VR::UN,VM::VM1,"View List",false }, {0x7fdf,0x0000,"ACUSON:1.2.840.113680.1.0:7f10",VR::IS,VM::VM1,"Lossy Compression Ratio",false }, {0x7fdf,0x0001,"ACUSON:1.2.840.113680.1.0:7f10",VR::US,VM::VM1,"Image Format",false }, {0x7fdf,0x0002,"ACUSON:1.2.840.113680.1.0:7f10",VR::US,VM::VM1,"Acuson Region Type",false }, {0x7fdf,0x000b,"ACUSON:1.2.840.113680.1.0:7f10",VR::UL,VM::VM1,"Acuson Image Apex X",false }, {0x7fdf,0x000c,"ACUSON:1.2.840.113680.1.0:7f10",VR::UL,VM::VM1,"Acuson Image Apex Y",false }, {0x7fdf,0x000d,"ACUSON:1.2.840.113680.1.0:7f10",VR::IS,VM::VM1,"B-Color-On Flag",false }, {0x7fdf,0x000e,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Acuson Mechanical Apex X",false }, {0x7fdf,0x000f,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Acuson Mechanical Apex Y",false }, {0x7fdf,0x0010,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Acquisition Type:",false }, {0x7fdf,0x0018,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Transformation Matrix Sequence",false }, {0x7fdf,0x0020,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Left angle",false }, {0x7fdf,0x0022,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Right angle",false }, {0x7fdf,0x0024,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Color Map Family",false }, {0x7fdf,0x0025,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Full Colormap.",false }, {0x7fdf,0x0026,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Color Invert",false }, {0x7fdf,0x0027,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Color Baseline",false }, {0x7fdf,0x0028,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Color Mix Points X1",false }, {0x7fdf,0x0029,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Color Mix Points Y1",false }, {0x7fdf,0x002a,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Color Mix Points X2",false }, {0x7fdf,0x002b,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Color Mix Points Y2",false }, {0x7fdf,0x002c,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Color Accent",false }, {0x7fdf,0x0030,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Persistence SQ",false }, {0x7fdf,0x0031,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Persistence Mode",false }, {0x7fdf,0x0032,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Persistence Coefficient Mode",false }, {0x7fdf,0x0033,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Alpha coefficient",false }, {0x7fdf,0x0034,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Gamma coefficient",false }, {0x7fdf,0x0035,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Persistence Time Flag",false }, {0x7fdf,0x0036,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Persistence adaptive flag",false }, {0x7fdf,0x0037,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Persistence Frame Rate",false }, {0x7fdf,0x0038,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Persistence ID",false }, {0x7fdf,0x0040,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Observation Date Time SQ",false }, {0x7fdf,0x0050,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Capture Type Name",false }, {0x7fdf,0x0052,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Capture Type Number",false }, {0x7fdf,0x0054,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Number of Capture Types",false }, {0x7fdf,0x0060,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Steering Angle",false }, {0x7fdf,0x0061,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD PRI",false }, {0x7fdf,0x0062,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Dynamic Range",false }, {0x7fdf,0x0063,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Velocity Scale Min",false }, {0x7fdf,0x0064,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Velocity Scale Max",false }, {0x7fdf,0x0065,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Color Mode",false }, {0x7fdf,0x0066,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Frequency",false }, {0x7fdf,0x0067,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Balance",false }, {0x7fdf,0x0068,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Delta",false }, {0x7fdf,0x0069,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Pan Box Min X0",false }, {0x7fdf,0x006a,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Pan Box Min Y0",false }, {0x7fdf,0x006b,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Pan Box Min X1",false }, {0x7fdf,0x006c,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CD Pan Box Min Y1",false }, {0x7fdf,0x006d,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CPS Map Type",false }, {0x7fdf,0x006e,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CPS Map Data",false }, {0x7fdf,0x006f,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"CPS Balance Setting",false }, {0x7fdf,0x0070,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"3DCard Step Angle",false }, {0x7fdf,0x0071,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"3DCard Xdcr Angle",false }, {0x7fdf,0x0072,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"B-mode Frequency",false }, {0x7fdf,0x0073,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"B-mode Dynamic Range",false }, {0x7fdf,0x0074,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"B-mode Frame Rate",false }, {0x7fdf,0x0075,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"B-mode Space Time",false }, {0x7fdf,0x0076,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"B-mode Persistence",false }, {0x7fdf,0x0077,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"B-mode Display Depth Start",false }, {0x7fdf,0x0078,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"B-mode Display Depth End",false }, {0x7fdf,0x0079,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"B-mode Res Mode",false }, {0x7fdf,0x007a,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"B-mode Preset Application",false }, {0x7fdf,0x007b,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Image Spec Name",false }, {0x7fdf,0x007c,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"B Preset Image Look",false }, {0x7fdf,0x007d,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"B-mode Post Processing",false }, {0x7fdf,0x007e,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"B Edge",false }, {0x7fdf,0x007f,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"B Delta",false }, {0x7fdf,0x0080,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"B-mode 1D Post Processing Curve",false }, {0x7fdf,0x0081,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"B-mode Delta (ECRI) Map Diagonal",false }, {0x7fdf,0x0082,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Bytes Per Timestamp",false }, {0x7fdf,0x0083,"ACUSON:1.2.840.113680.1.0:7f10",VR::UL,VM::VM1,"Microseconds in unit timestamp",false }, {0x7fdf,0x0084,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Start Stopwatch Timestamp",false }, {0x7fdf,0x0085,"ACUSON:1.2.840.113680.1.0:7f10",VR::OB,VM::VM1,"Acoustic Frame Timestamp",false }, {0x7fdf,0x0086,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"R-Wave Timestamp",false }, {0x7fdf,0x0087,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Last Destruction Timestamp",false }, {0x7fdf,0x0088,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Pixels Per Second",false }, {0x7fdf,0x0089,"ACUSON:1.2.840.113680.1.0:7f10",VR::OB,VM::VM1,"ECG Reference Timestamp",false }, {0x7fdf,0x008a,"ACUSON:1.2.840.113680.1.0:7f10",VR::FD,VM::VM1,"ECG Sampling Interval (milliseconds)",false }, {0x7fdf,0x008b,"ACUSON:1.2.840.113680.1.0:7f10",VR::UL,VM::VM1,"ECG Sample Count",false }, {0x7fdf,0x008c,"ACUSON:1.2.840.113680.1.0:7f10",VR::UL,VM::VM1,"ECG Sample Size",false }, {0x7fdf,0x008d,"ACUSON:1.2.840.113680.1.0:7f10",VR::OB,VM::VM1,"ECG Data Value",false }, {0x7fdf,0x008e,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Contrast/Active Image Indicator",false }, {0x7fdf,0x008f,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Live Dual Mode Indicator",false }, {0x7fdf,0x0090,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"3DCard Clipset ID",false }, {0x7fdf,0x0091,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"3DCard HRWave Min",false }, {0x7fdf,0x0092,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"3DCard HRWave Max",false }, {0x7fdf,0x0093,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Perspective Capture Type",false }, {0x7fdf,0x00f1,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Trigger Mask.",false }, {0x7fdf,0x00f2,"ACUSON:1.2.840.113680.1.0:7f10",VR::LO,VM::VM1,"Study Directory",false }, {0x7fdf,0x00f3,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Last Modify Date",false }, {0x7fdf,0x00f4,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Last Modify Time",false }, {0x7fdf,0x00f5,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Teaching Study",false }, {0x7fdf,0x00f6,"ACUSON:1.2.840.113680.1.0:7f10",VR::UN,VM::VM1,"Series Base UID",false }, {0x7fdf,0x0000,"ACUSON:1.2.840.113680.1.0:7ffe",VR::OB,VM::VM1,"Data Padding",false }, {0x0019,0x0002,"ADAC_IMG",VR::IS,VM::VM1,"Ver200 ADAC Pegasys File Size",false }, {0x0019,0x0010,"ADAC_IMG",VR::LO,VM::VM2,"ADAC Header Signature",false }, {0x0019,0x0011,"ADAC_IMG",VR::US,VM::VM1,"Number of ADAC Headers",false }, {0x0019,0x0012,"ADAC_IMG",VR::IS,VM::VM1_n,"ADAC Header/Image Sizes",false }, {0x0019,0x0020,"ADAC_IMG",VR::OB,VM::VM1,"ADAC Pegasys Headers",false }, {0x0019,0x0021,"ADAC_IMG",VR::US,VM::VM1,"Ver200 Number of ADAC Headers",false }, {0x0019,0x0041,"ADAC_IMG",VR::IS,VM::VM1_n,"Ver200 ADAC Header/Image Size",false }, {0x0019,0x0061,"ADAC_IMG",VR::OB,VM::VM1,"Ver200 ADAC Pegasys Headers",false }, {0x7043,0x0000,"ADAC_IMG",VR::SH,VM::VM1,"Cardiac Stress State",false }, {0x7043,0x0010,"ADAC_IMG",VR::LO,VM::VM1,"Philips NM Private Group",false }, {0x0003,0x0000,"AEGIS_DICOM_2.00",VR::US,VM::VM1_n,"?",false }, {0x0005,0x0000,"AEGIS_DICOM_2.00",VR::US,VM::VM1_n,"?",false }, {0x0009,0x0000,"AEGIS_DICOM_2.00",VR::US,VM::VM1_n,"?",false }, {0x0019,0x0000,"AEGIS_DICOM_2.00",VR::US,VM::VM1_n,"?",false }, {0x0029,0x0000,"AEGIS_DICOM_2.00",VR::US,VM::VM1_n,"?",false }, {0x1369,0x0000,"AEGIS_DICOM_2.00",VR::US,VM::VM1_n,"?",false }, {0x0009,0x0010,"AGFA",VR::LO,VM::VM1,"?",false }, {0x0009,0x0011,"AGFA",VR::LO,VM::VM1,"?",false }, {0x0009,0x0013,"AGFA",VR::LO,VM::VM1,"?",false }, {0x0009,0x0014,"AGFA",VR::LO,VM::VM1,"?",false }, {0x0009,0x0015,"AGFA",VR::LO,VM::VM1,"?",false }, {0x0019,0x0010,"AGFA",VR::SH,VM::VM1,"Private Identification Code",false }, {0x0019,0x0011,"AGFA",VR::LO,VM::VM3,"Identification Data (Note 2)",false }, {0x0019,0x0013,"AGFA",VR::LO,VM::VM1,"Sensitometry Name",false }, {0x0019,0x0014,"AGFA",VR::ST,VM::VM3,"Window/Level List (Note 3)",false }, {0x0019,0x0015,"AGFA",VR::LO,VM::VM1,"Dose Monitoring List",false }, {0x0019,0x0016,"AGFA",VR::LO,VM::VM3,"Other Info (Note 5)",false }, {0x0019,0x001a,"AGFA",VR::LO,VM::VM1,"Clipped Exposure Deviation",false }, {0x0019,0x001b,"AGFA",VR::LO,VM::VM1,"Logarithmic PLT Full Scale",false }, {0x0019,0x0060,"AGFA",VR::US,VM::VM1,"Total number of series",false }, {0x0019,0x0061,"AGFA",VR::SH,VM::VM1,"Session Number",false }, {0x0019,0x0062,"AGFA",VR::SH,VM::VM1,"ID Station name",false }, {0x0019,0x0065,"AGFA",VR::US,VM::VM1,"Number of images in study to be transmitted (only sent with autoverify: on)",false }, {0x0019,0x0070,"AGFA",VR::US,VM::VM1,"Total number of images",false }, {0x0019,0x0080,"AGFA",VR::ST,VM::VM1,"Geometrical Transformations",false }, {0x0019,0x0081,"AGFA",VR::ST,VM::VM1,"Roam Origin",false }, {0x0019,0x0082,"AGFA",VR::US,VM::VM1,"Zoom factor",false }, {0x0019,0x0093,"AGFA",VR::CS,VM::VM1,"Status",false }, {0x0031,0x0000,"AGFA PACS Archive Mirroring 1.0",VR::CS,VM::VM1,"study_status",false }, /* 001310_IMPAX_6.5.x_Solution_DICOM_Conformance_Statement.pdf states is is VR:CS */ {0x0031,0x0001,"AGFA PACS Archive Mirroring 1.0",VR::UL,VM::VM1,"date_time_verified",false }, {0x0035,0x0000,"AGFA STUDY COMMENTS 1.0",VR::LT,VM::VM1,"Array of Comments (illegal XML)",false }, {0x0071,0x0018,"AGFA-AG_HPState",VR::SQ,VM::VM1,"?",false }, {0x0071,0x0019,"AGFA-AG_HPState",VR::SQ,VM::VM1,"?",false }, {0x0071,0x001a,"AGFA-AG_HPState",VR::SQ,VM::VM1,"?",false }, {0x0071,0x001c,"AGFA-AG_HPState",VR::SQ,VM::VM1,"?",false }, {0x0071,0x001e,"AGFA-AG_HPState",VR::SQ,VM::VM1,"?",false }, {0x0071,0x0020,"AGFA-AG_HPState",VR::FL,VM::VM1_n,"?",false }, {0x0071,0x0021,"AGFA-AG_HPState",VR::FD,VM::VM1_n,"?",false }, {0x0071,0x0022,"AGFA-AG_HPState",VR::FD,VM::VM1_n,"?",false }, {0x0071,0x0023,"AGFA-AG_HPState",VR::FD,VM::VM1_n,"?",false }, {0x0071,0x0024,"AGFA-AG_HPState",VR::FD,VM::VM1,"?",false }, {0x0073,0x0023,"AGFA-AG_HPState",VR::SH,VM::VM1,"?",false }, {0x0073,0x0024,"AGFA-AG_HPState",VR::SQ,VM::VM1,"?",false }, {0x0073,0x0028,"AGFA-AG_HPState",VR::SQ,VM::VM1,"?",false }, {0x0073,0x0080,"AGFA-AG_HPState",VR::FL,VM::VM1,"?",false }, {0x0075,0x0010,"AGFA-AG_HPState",VR::LO,VM::VM1,"?",false }, {0x0087,0x0001,"AGFA-AG_HPState",VR::LO,VM::VM1,"?",false }, {0x0087,0x0002,"AGFA-AG_HPState",VR::LO,VM::VM1,"?",false }, {0x0019,0x0005,"AGFA_ADC_Compact",VR::ST,VM::VM1,"Data stream from cassette",false }, {0x0019,0x0010,"AGFA_ADC_Compact",VR::LO,VM::VM1,"Private Identification Code",false }, {0x0019,0x0030,"AGFA_ADC_Compact",VR::ST,VM::VM1,"Set of destination types",false }, {0x0019,0x0040,"AGFA_ADC_Compact",VR::ST,VM::VM1,"Set of destination Ids",false }, {0x0019,0x0050,"AGFA_ADC_Compact",VR::ST,VM::VM1,"Set of processing codes",false }, {0x0019,0x0060,"AGFA_ADC_Compact",VR::US,VM::VM1,"Number of series in study",false }, {0x0019,0x0061,"AGFA_ADC_Compact",VR::US,VM::VM1,"Session Number",false }, {0x0019,0x0062,"AGFA_ADC_Compact",VR::SH,VM::VM1,"ID station name",false }, {0x0019,0x0070,"AGFA_ADC_Compact",VR::US,VM::VM1,"Number of images in series",false }, {0x0019,0x0071,"AGFA_ADC_Compact",VR::US,VM::VM1,"Break condition",false }, {0x0019,0x0072,"AGFA_ADC_Compact",VR::US,VM::VM1,"Wait (or Hold) flag",false }, {0x0019,0x0073,"AGFA_ADC_Compact",VR::US,VM::VM1,"ScanRes flag",false }, {0x0019,0x0074,"AGFA_ADC_Compact",VR::SH,VM::VM1,"Operation code",false }, {0x0019,0x0095,"AGFA_ADC_Compact",VR::CS,VM::VM1,"Image quality",false }, {0x0009,0x0000,"ALOKA:1.2.392.200039.105.2",VR::SH,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0004,"ALOKA:1.2.392.200039.105.2",VR::US,VM::VM1_n,"Private attribute without PHI",false }, {0x0009,0x0006,"ALOKA:1.2.392.200039.105.2",VR::US,VM::VM1_n,"Private attribute without PHI",false }, {0x0009,0x000a,"ALOKA:1.2.392.200039.105.2",VR::SH,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0012,"ALOKA:1.2.392.200039.105.2",VR::US,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0014,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x001a,"ALOKA:1.2.392.200039.105.2",VR::LO,VM::VM1,"??",false }, // FIXME ? {0x0009,0x0020,"ALOKA:1.2.392.200039.105.2",VR::CS,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0022,"ALOKA:1.2.392.200039.105.2",VR::CS,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0024,"ALOKA:1.2.392.200039.105.2",VR::CS,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0026,"ALOKA:1.2.392.200039.105.2",VR::IS,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0028,"ALOKA:1.2.392.200039.105.2",VR::IS,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x002a,"ALOKA:1.2.392.200039.105.2",VR::DS,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x002c,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM6_6n,"Private attribute without PHI",false }, {0x0009,0x002e,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM3_3n,"Private attribute without PHI",false }, {0x0009,0x0030,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0032,"ALOKA:1.2.392.200039.105.2",VR::DS,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0034,"ALOKA:1.2.392.200039.105.2",VR::CS,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0036,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0038,"ALOKA:1.2.392.200039.105.2",VR::CS,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x003a,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x003c,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x003e,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0040,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0042,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0044,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0046,"ALOKA:1.2.392.200039.105.2",VR::US,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0048,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x004a,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x004c,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x004e,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0050,"ALOKA:1.2.392.200039.105.2",VR::US,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0052,"ALOKA:1.2.392.200039.105.2",VR::US,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0054,"ALOKA:1.2.392.200039.105.2",VR::LO,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x0008,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x000c,"ALOKA:1.2.392.200039.105.2",VR::CS,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x000e,"ALOKA:1.2.392.200039.105.2",VR::DS,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x0018,"ALOKA:1.2.392.200039.105.2",VR::SL,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x001a,"ALOKA:1.2.392.200039.105.2",VR::SL,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x0040,"ALOKA:1.2.392.200039.105.2",VR::SS,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x0046,"ALOKA:1.2.392.200039.105.2",VR::US,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x0050,"ALOKA:1.2.392.200039.105.2",VR::SL,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x0052,"ALOKA:1.2.392.200039.105.2",VR::DS,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x0054,"ALOKA:1.2.392.200039.105.2",VR::DS,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x0056,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x0060,"ALOKA:1.2.392.200039.105.2",VR::US,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x0061,"ALOKA:1.2.392.200039.105.2",VR::UL,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x0062,"ALOKA:1.2.392.200039.105.2",VR::US,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x0064,"ALOKA:1.2.392.200039.105.2",VR::US,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x0066,"ALOKA:1.2.392.200039.105.2",VR::US,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x006c,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0019,0x006e,"ALOKA:1.2.392.200039.105.2",VR::FD,VM::VM1,"Private attribute without PHI",false }, {0x0009,0x0000,"ALOKA:1.2.392.200039.103.2",VR::SH,VM::VM1,"?",false }, {0x0009,0x0004,"ALOKA:1.2.392.200039.103.2",VR::US,VM::VM1_n,"?",false }, {0x0009,0x0006,"ALOKA:1.2.392.200039.103.2",VR::US,VM::VM1_n,"?",false }, {0x0009,0x000a,"ALOKA:1.2.392.200039.103.2",VR::SH,VM::VM1,"?",false }, {0x0009,0x0020,"ALOKA:1.2.392.200039.103.2",VR::CS,VM::VM1,"?",false }, {0x0009,0x0022,"ALOKA:1.2.392.200039.103.2",VR::CS,VM::VM1,"?",false }, {0x0009,0x0024,"ALOKA:1.2.392.200039.103.2",VR::CS,VM::VM1,"?",false }, {0x0009,0x0026,"ALOKA:1.2.392.200039.103.2",VR::IS,VM::VM1,"?",false }, {0x0009,0x0028,"ALOKA:1.2.392.200039.103.2",VR::IS,VM::VM1,"?",false }, {0x0009,0x002a,"ALOKA:1.2.392.200039.103.2",VR::DS,VM::VM1,"?",false }, {0x0009,0x0030,"ALOKA:1.2.392.200039.103.2",VR::FD,VM::VM1,"?",false }, {0x0009,0x0032,"ALOKA:1.2.392.200039.103.2",VR::DS,VM::VM1,"?",false }, {0x0009,0x0034,"ALOKA:1.2.392.200039.103.2",VR::CS,VM::VM1,"?",false }, {0x0019,0x0008,"ALOKA:1.2.392.200039.103.2",VR::FD,VM::VM1,"?",false }, {0x0019,0x000c,"ALOKA:1.2.392.200039.103.2",VR::CS,VM::VM1,"?",false }, {0x0019,0x000e,"ALOKA:1.2.392.200039.103.2",VR::DS,VM::VM1,"?",false }, {0x0019,0x0018,"ALOKA:1.2.392.200039.103.2",VR::SL,VM::VM1,"?",false }, {0x0019,0x001a,"ALOKA:1.2.392.200039.103.2",VR::SL,VM::VM1,"?",false }, {0x0019,0x0040,"ALOKA:1.2.392.200039.103.2",VR::SS,VM::VM1,"?",false }, {0x0019,0x0046,"ALOKA:1.2.392.200039.103.2",VR::US,VM::VM1,"?",false }, {0x0019,0x0050,"ALOKA:1.2.392.200039.103.2",VR::SL,VM::VM1,"?",false }, {0x0019,0x0052,"ALOKA:1.2.392.200039.103.2",VR::DS,VM::VM1,"?",false }, {0x0019,0x0054,"ALOKA:1.2.392.200039.103.2",VR::DS,VM::VM1,"?",false }, {0x0019,0x0056,"ALOKA:1.2.392.200039.103.2",VR::FD,VM::VM1,"?",false }, {0x3101,0x0010,"AMI Annotations_01",VR::SQ,VM::VM1,"AMI Annotation Sequence (RET)",false }, {0x3101,0x0020,"AMI Annotations_02",VR::SQ,VM::VM1,"AMI Annotation Sequence (RET)",false }, {0x3107,0x00a0,"AMI ImageContextExt_01",VR::CS,VM::VM1,"AMI Window Function (RET)",false }, {0x3107,0x00b0,"AMI ImageContextExt_01",VR::DS,VM::VM1,"AMI Window Slope (RET)",false }, {0x3109,0x0010,"AMI ImageContext_01",VR::CS,VM::VM1,"AMI Window Invert (RET)",false }, {0x3109,0x0020,"AMI ImageContext_01",VR::IS,VM::VM1,"AMI Window Center (RET)",false }, {0x3109,0x0030,"AMI ImageContext_01",VR::IS,VM::VM1,"AMI Window Widith (RET)",false }, {0x3109,0x0040,"AMI ImageContext_01",VR::CS,VM::VM1,"AMI Pixel Aspect Ratio Swap (RET)",false }, {0x3109,0x0050,"AMI ImageContext_01",VR::CS,VM::VM1,"AMI Enable Averaging (RET)",false }, {0x3109,0x0060,"AMI ImageContext_01",VR::CS,VM::VM1,"AMI Quality (RET)",false }, {0x3109,0x0070,"AMI ImageContext_01",VR::CS,VM::VM1,"AMI Viewport Annotation Level (RET)",false }, {0x3109,0x0080,"AMI ImageContext_01",VR::CS,VM::VM1,"AMI Show Image Annotation (RET)",false }, {0x3109,0x0090,"AMI ImageContext_01",VR::CS,VM::VM1,"AMI Show Image Overlay (RET)",false }, {0x3107,0x0010,"AMI ImageTransform_01",VR::DS,VM::VM1,"AMI Transformation Matrix (RET)",false }, {0x3107,0x0020,"AMI ImageTransform_01",VR::DS,VM::VM1,"AMI Center Offset (RET)",false }, {0x3107,0x0030,"AMI ImageTransform_01",VR::DS,VM::VM1,"AMI Magnification (RET)",false }, {0x3107,0x0040,"AMI ImageTransform_01",VR::CS,VM::VM1,"AMI Magnification Type (RET)",false }, {0x3107,0x0050,"AMI ImageTransform_01",VR::DS,VM::VM1,"AMI Displayed Area (RET)",false }, {0x3107,0x0060,"AMI ImageTransform_01",VR::DS,VM::VM1,"AMI Calibration Factor (RET)",false }, {0x3105,0x0010,"AMI Sequence AnnotElements_01",VR::DS,VM::VM1,"AMI Annotation Element Position",false }, {0x3105,0x0020,"AMI Sequence AnnotElements_01",VR::LT,VM::VM1,"AMI Annotation Element Text",false }, {0x3103,0x0010,"AMI Sequence Annotations_01",VR::CS,VM::VM1,"AMI Annotation Sequence (RET)",false }, {0x3103,0x0020,"AMI Sequence Annotations_01",VR::UI,VM::VM1,"AMI Annotation UID (RET)",false }, {0x3103,0x0030,"AMI Sequence Annotations_01",VR::US,VM::VM1,"AMI Annotation Color (RET)",false }, {0x3103,0x0040,"AMI Sequence Annotations_01",VR::FD,VM::VM1,"FontSize",false }, {0x3103,0x0050,"AMI Sequence Annotations_01",VR::CS,VM::VM1,"AMI Annotation Line Style (RET)",false }, {0x3103,0x0060,"AMI Sequence Annotations_01",VR::SQ,VM::VM1,"AMI Annotation Elements (RET)",false }, {0x3103,0x0070,"AMI Sequence Annotations_01",VR::SH,VM::VM1,"AMI Annotation Label (RET)",false }, {0x3103,0x0080,"AMI Sequence Annotations_01",VR::PN,VM::VM1,"AMI Annotation Creator (RET)",false }, {0x3103,0x0090,"AMI Sequence Annotations_01",VR::PN,VM::VM1,"AMI Annotation Modifiers (RET)",false }, {0x3103,0x00a0,"AMI Sequence Annotations_01",VR::DA,VM::VM1,"AMI Annotation Creation Date (RET)",false }, {0x3103,0x00b0,"AMI Sequence Annotations_01",VR::TM,VM::VM1,"AMI Annotation Creation Time (RET)",false }, {0x3103,0x00c0,"AMI Sequence Annotations_01",VR::DA,VM::VM1,"AMI Annotation Modification Dates (RET)",false }, {0x3103,0x00d0,"AMI Sequence Annotations_01",VR::TM,VM::VM1,"AMI Annotation Modification Times (RET)",false }, {0x3103,0x00e0,"AMI Sequence Annotations_01",VR::US,VM::VM1,"AMI Annotation Frame Number (RET)",false }, {0x3103,0x0010,"AMI Sequence Annotations_02",VR::CS,VM::VM1,"AMI Annotation Sequence (RET)",false }, {0x3103,0x0020,"AMI Sequence Annotations_02",VR::UI,VM::VM1,"AMI Annotation UID (RET)",false }, {0x3103,0x0030,"AMI Sequence Annotations_02",VR::US,VM::VM1,"AMI Annotation Color (RET)",false }, {0x3103,0x0050,"AMI Sequence Annotations_02",VR::CS,VM::VM1,"AMI Annotation Line Style (RET)",false }, {0x3103,0x0060,"AMI Sequence Annotations_02",VR::SQ,VM::VM1,"AMI Annotation Elements (RET)",false }, {0x3103,0x0070,"AMI Sequence Annotations_02",VR::SH,VM::VM1,"AMI Annotation Label (RET)",false }, {0x3103,0x0080,"AMI Sequence Annotations_02",VR::PN,VM::VM1,"AMI Annotation Creator (RET)",false }, {0x3103,0x0090,"AMI Sequence Annotations_02",VR::PN,VM::VM1,"AMI Annotation Modifiers (RET)",false }, {0x3103,0x00a0,"AMI Sequence Annotations_02",VR::DA,VM::VM1,"AMI Annotation Creation Date (RET)",false }, {0x3103,0x00b0,"AMI Sequence Annotations_02",VR::TM,VM::VM1,"AMI Annotation Creation Time (RET)",false }, {0x3103,0x00c0,"AMI Sequence Annotations_02",VR::DA,VM::VM1,"AMI Annotation Modification Dates (RET)",false }, {0x3103,0x00d0,"AMI Sequence Annotations_02",VR::TM,VM::VM1,"AMI Annotation Modification Times (RET)",false }, {0x3103,0x00e0,"AMI Sequence Annotations_02",VR::US,VM::VM1,"AMI Annotation Frame Number (RET)",false }, {0x3111,0x0001,"AMI StudyExtensions_01",VR::UL,VM::VM1,"AMI Last Released Annot Label (RET)",false }, {0x0023,0x0001,"AMICAS0",VR::UI,VM::VM1,"?UID?",false }, {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,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 }, {0x0023,0x0055,"AMICAS0",VR::LO,VM::VM1,"?Patient's Birth Date?",false }, {0x0023,0x0056,"AMICAS0",VR::LO,VM::VM1,"?Institution Name?",false }, {0x0023,0x0057,"AMICAS0",VR::LO,VM::VM1,"?Truncated Study Time?",false }, {0x0023,0x0065,"AMICAS0",VR::LO,VM::VM1,"?",false }, {0x0027,0x0010,"APEX_PRIVATE",VR::LO,VM::VM1,"Private Creator",false }, {0x0027,0x0011,"APEX_PRIVATE",VR::DS,VM::VM1,"Bed Position",false }, {0x0009,0x0000,"ATL HDI V1.0",VR::UN,VM::VM1,"Private",false }, {0x0009,0x0010,"ATL HDI V1.0",VR::UN,VM::VM1,"Private",false }, {0x0009,0x0020,"ATL HDI V1.0",VR::UN,VM::VM1,"Private",false }, {0x0009,0x0030,"ATL HDI V1.0",VR::UN,VM::VM1,"Private",false }, {0x0009,0x0040,"ATL HDI V1.0",VR::UN,VM::VM1,"Private",false }, {0x0009,0x0050,"ATL HDI V1.0",VR::UN,VM::VM1,"Private",false }, {0x0009,0x0060,"ATL HDI V1.0",VR::UN,VM::VM1,"Private",false }, {0x0009,0x0070,"ATL HDI V1.0",VR::UN,VM::VM1,"Private",false }, {0x0009,0x0080,"ATL HDI V1.0",VR::UN,VM::VM1,"Private",false }, {0x0009,0x0090,"ATL HDI V1.0",VR::UN,VM::VM1,"Private",false }, {0x0009,0x0091,"ATL HDI V1.0",VR::UN,VM::VM1,"Private",false }, {0x0029,0x0030,"ATL HDI V1.0",VR::UN,VM::VM1,"Loop Mode",false }, {0x0029,0x0031,"ATL HDI V1.0",VR::UN,VM::VM1,"Trigger mode",false }, {0x0029,0x0032,"ATL HDI V1.0",VR::UN,VM::VM1,"Number of Loops",false }, {0x0029,0x0033,"ATL HDI V1.0",VR::UN,VM::VM1,"Loop Indexes",false }, {0x0029,0x0034,"ATL HDI V1.0",VR::UN,VM::VM1,"Loop Heart Rates",false }, {0x0029,0x0035,"ATL HDI V1.0",VR::UN,VM::VM1,"Medications",false }, {0x0029,0x0030,"ATL PRIVATE TAGS",VR::UL,VM::VM1,"Loop Mode",false }, {0x0029,0x0031,"ATL PRIVATE TAGS",VR::UL,VM::VM1,"Trigger mode",false }, {0x0029,0x0032,"ATL PRIVATE TAGS",VR::UL,VM::VM1,"Number of Loops",false }, {0x0029,0x0033,"ATL PRIVATE TAGS",VR::DS,VM::VM1_n,"Loop Indexes",false }, {0x0029,0x0034,"ATL PRIVATE TAGS",VR::DS,VM::VM1_n,"Loop Heart Rates",false }, {0x0029,0x0035,"ATL PRIVATE TAGS",VR::LO,VM::VM1,"Medications",false }, {0x0009,0x0020,"Acuson X500",VR::UN,VM::VM1,"(a)View Name",false }, {0x0009,0x002a,"Acuson X500",VR::UN,VM::VM1,"View List",false }, {0x0011,0x0010,"Acuson X500",VR::UN,VM::VM1,"Siemens Medical",false }, {0x0011,0x0011,"Acuson X500",VR::UN,VM::VM1,"DIMAQ Software",false }, {0x0011,0x0020,"Acuson X500",VR::UN,VM::VM1,"Private Data",false }, {0x0011,0x0021,"Acuson X500",VR::UN,VM::VM1,"Private Data",false }, {0x0013,0x0010,"Acuson X500",VR::UN,VM::VM1,"Siemens Medical",false }, {0x0013,0x0011,"Acuson X500",VR::UN,VM::VM1,"DIMAQ Software",false }, {0x0013,0x0020,"Acuson X500",VR::UN,VM::VM1,"Private Data",false }, {0x0015,0x0010,"Acuson X500",VR::UN,VM::VM1,"Siemens Medical",false }, {0x0015,0x0011,"Acuson X500",VR::UN,VM::VM1,"DIMAQ Software",false }, {0x0015,0x0020,"Acuson X500",VR::UN,VM::VM1,"Private Data",false }, {0x0017,0x0010,"Acuson X500",VR::UN,VM::VM1,"Siemens Medical",false }, {0x0017,0x0011,"Acuson X500",VR::UN,VM::VM1,"DIMAQ Software",false }, {0x0017,0x0020,"Acuson X500",VR::UN,VM::VM1,"Private Data",false }, {0x0019,0x0020,"Acuson X500",VR::UN,VM::VM1,"Import Structured",false }, {0x0019,0x0007,"Agfa ADC NX",VR::CS,VM::VM1,"Is Speedclass Free ",false }, {0x0019,0x0009,"Agfa ADC NX",VR::SQ,VM::VM1,"Collimator shape sequence ",false }, {0x0019,0x0021,"Agfa ADC NX",VR::FL,VM::VM1,"Calibration Factor ",false }, {0x0019,0x0028,"Agfa ADC NX",VR::CS,VM::VM1,"Is IPSR enabled",false }, {0x0019,0x00f5,"Agfa ADC NX",VR::CS,VM::VM1,"Cassette orientation",false }, {0x0019,0x00f6,"Agfa ADC NX",VR::DS,VM::VM1,"Image plate sensitivity",false }, {0x0019,0x00f7,"Agfa ADC NX",VR::DS,VM::VM1,"Image plate erasability",false }, {0x0019,0x00f8,"Agfa ADC NX",VR::IS,VM::VM1,"Breast density percentage",false }, {0x0019,0x00fa,"Agfa ADC NX",VR::IS,VM::VM1,"Exposure index",false }, {0x0019,0x00fb,"Agfa ADC NX",VR::FL,VM::VM1,"Deviation index",false }, {0x0019,0x00fc,"Agfa ADC NX",VR::IS,VM::VM1,"Target exposure index",false }, {0x0019,0x00fd,"Agfa ADC NX",VR::CS,VM::VM1,"Is overexposed",false }, {0x0019,0x00fe,"Agfa ADC NX",VR::CS,VM::VM1,"Study Priority ID",false }, {0x0029,0x0011,"AgilityRuntime",VR::CS,VM::VM1,"?",false }, {0x0029,0x0012,"AgilityRuntime",VR::US,VM::VM1,"?",false }, {0x0029,0x0013,"AgilityRuntime",VR::US,VM::VM1,"?",false }, {0x0029,0x0014,"AgilityRuntime",VR::US,VM::VM1,"?",false }, {0x0029,0x001f,"AgilityRuntime",VR::US,VM::VM1,"?",false }, {0x4109,0x0001,"Applicare/Centricity Radiology Web/Version 1.0",VR::SH,VM::VM1,"Mammography Laterality",false }, {0x4109,0x0002,"Applicare/Centricity Radiology Web/Version 1.0",VR::SH,VM::VM1,"Mammography View Name",false }, {0x4109,0x0003,"Applicare/Centricity Radiology Web/Version 1.0",VR::SH,VM::VM1,"Mammography View Modifier",false }, {0x4111,0x0001,"Applicare/Centricity Radiology Web/Version 2.0",VR::CS,VM::VM1,"Secondary Spine Label",false }, {0x4111,0x0002,"Applicare/Centricity Radiology Web/Version 2.0",VR::IS,VM::VM1,"Additional tags for Presentation State",false }, {0x4101,0x0001,"Applicare/Print/Version 5.1",VR::UL,VM::VM1," UL ? {0x0027,0x0035,"GEMS_IMAG_01",VR::SS,VM::VM1,"Plane Type",false }, {0x0027,0x0036,"GEMS_IMAG_01",VR::SL,VM::VM1,"Oblique Plane",false }, {0x0027,0x0040,"GEMS_IMAG_01",VR::SH,VM::VM1,"RAS letter of image location",false }, {0x0027,0x0041,"GEMS_IMAG_01",VR::FL,VM::VM1,"Image location",false }, {0x0027,0x0042,"GEMS_IMAG_01",VR::FL,VM::VM1,"Center R coord of plane image",false }, {0x0027,0x0043,"GEMS_IMAG_01",VR::FL,VM::VM1,"Center A coord of plane image",false }, {0x0027,0x0044,"GEMS_IMAG_01",VR::FL,VM::VM1,"Center S coord of plane image",false }, {0x0027,0x0045,"GEMS_IMAG_01",VR::FL,VM::VM1,"Normal R coord",false }, {0x0027,0x0046,"GEMS_IMAG_01",VR::FL,VM::VM1,"Normal A coord",false }, {0x0027,0x0047,"GEMS_IMAG_01",VR::FL,VM::VM1,"Normal S coord",false }, {0x0027,0x0048,"GEMS_IMAG_01",VR::FL,VM::VM1,"R Coord of Top Right Corner",false }, {0x0027,0x0049,"GEMS_IMAG_01",VR::FL,VM::VM1,"A Coord of Top Right Corner",false }, {0x0027,0x004a,"GEMS_IMAG_01",VR::FL,VM::VM1,"S Coord of Top Right Corner",false }, {0x0027,0x004b,"GEMS_IMAG_01",VR::FL,VM::VM1,"R Coord of Bottom Right Corner",false }, {0x0027,0x004c,"GEMS_IMAG_01",VR::FL,VM::VM1,"A Coord of Bottom Right Corner",false }, {0x0027,0x004d,"GEMS_IMAG_01",VR::FL,VM::VM1,"S Coord of Bottom Right Corner",false }, {0x0027,0x0050,"GEMS_IMAG_01",VR::FL,VM::VM1,"Scan Start Location",false }, {0x0027,0x0051,"GEMS_IMAG_01",VR::FL,VM::VM1,"Scan End Location",false }, {0x0027,0x0052,"GEMS_IMAG_01",VR::SH,VM::VM1,"RAS letter for side of image",false }, {0x0027,0x0053,"GEMS_IMAG_01",VR::SH,VM::VM1,"RAS letter for anterior/posterior",false }, {0x0027,0x0054,"GEMS_IMAG_01",VR::SH,VM::VM1,"RAS letter for scout start loc",false }, {0x0027,0x0055,"GEMS_IMAG_01",VR::SH,VM::VM1,"RAS letter for scout end loc",false }, {0x0027,0x0060,"GEMS_IMAG_01",VR::FL,VM::VM1,"Image dimension - X",false }, {0x0027,0x0061,"GEMS_IMAG_01",VR::FL,VM::VM1,"Image dimension - Y",false }, {0x0027,0x0062,"GEMS_IMAG_01",VR::FL,VM::VM1,"Number of Excitations",false }, {0x0029,0x0015,"GEMS_IMAG_01",VR::SL,VM::VM1,"Lower range of Pixels1",false }, {0x0029,0x0016,"GEMS_IMAG_01",VR::SL,VM::VM1,"Lower range of Pixels1",false }, {0x0029,0x0017,"GEMS_IMAG_01",VR::SL,VM::VM1,"Lower range of Pixels2",false }, {0x0029,0x0018,"GEMS_IMAG_01",VR::SL,VM::VM1,"Upper range of Pixels2",false }, {0x0029,0x001a,"GEMS_IMAG_01",VR::SL,VM::VM1,"Len of tot hdr in bytes No longer supported",false }, {0x0029,0x0026,"GEMS_IMAG_01",VR::SS,VM::VM1,"Version of the hdr struct",false }, {0x0029,0x0034,"GEMS_IMAG_01",VR::SL,VM::VM1,"Advantage comp. Overflow",false }, {0x0029,0x0035,"GEMS_IMAG_01",VR::SL,VM::VM1,"Advantage comp. Underflow",false }, {0x0029,0x0004,"GEMS_IMPS_01",VR::SL,VM::VM1,"Lower range of Pixels1",false }, {0x0029,0x0005,"GEMS_IMPS_01",VR::DS,VM::VM1,"Lower range of Pixels1",false }, {0x0029,0x0006,"GEMS_IMPS_01",VR::DS,VM::VM1,"Lower range of Pixels1",false }, {0x0029,0x0007,"GEMS_IMPS_01",VR::SL,VM::VM1,"Lower range of Pixels1",false }, {0x0029,0x0008,"GEMS_IMPS_01",VR::SH,VM::VM1,"Lower range of Pixels1",false }, {0x0029,0x0009,"GEMS_IMPS_01",VR::SH,VM::VM1,"Lower range of Pixels1",false }, {0x0029,0x000a,"GEMS_IMPS_01",VR::SS,VM::VM1,"Lower range of Pixels1",false }, {0x0029,0x0015,"GEMS_IMPS_01",VR::SL,VM::VM1,"Lower range of Pixels1",false }, {0x0029,0x0016,"GEMS_IMPS_01",VR::SL,VM::VM1,"Upper range of Pixels1",false }, {0x0029,0x0017,"GEMS_IMPS_01",VR::SL,VM::VM1,"Lower range of Pixels2",false }, {0x0029,0x0018,"GEMS_IMPS_01",VR::SL,VM::VM1,"Upper range of Pixels2",false }, {0x0029,0x001a,"GEMS_IMPS_01",VR::SL,VM::VM1,"Len of tot hdr in bytes",false }, {0x0029,0x0026,"GEMS_IMPS_01",VR::SS,VM::VM1,"Version of the hdr struct",false }, {0x0029,0x0034,"GEMS_IMPS_01",VR::SL,VM::VM1,"Advantage comp. Overflow",false }, {0x0029,0x0035,"GEMS_IMPS_01",VR::SL,VM::VM1,"Advantage comp. Underflow",false }, {0x0043,0x0013,"GEMS_IMPS_01",VR::SS,VM::VM5,"Decon kernel parameters",false }, {0x0047,0x0001,"GEMS_IQTB_IDEN_47",VR::SH,VM::VM1,"Image Path",false }, {0x0047,0x0002,"GEMS_IQTB_IDEN_47",VR::UL,VM::VM1,"Image Date/Time",false }, {0x0047,0x0003,"GEMS_IQTB_IDEN_47",VR::UL,VM::VM1,"Queue Sequence Number",false }, {0x0047,0x0004,"GEMS_IQTB_IDEN_47",VR::UL,VM::VM1,"Recon Sequence ID",false }, {0x0045,0x0011,"GEMS_IT_US_REPORT",VR::OW,VM::VM1,"Vivid excel file",false }, {0x0045,0x0012,"GEMS_IT_US_REPORT",VR::OW,VM::VM1,"Vivid CHM file",false }, {0x0045,0x0013,"GEMS_IT_US_REPORT",VR::OW,VM::VM1,"Vivid PDF file",false }, {0x7003,0x0001,"GEMS_LUNAR_RAW",VR::ST,VM::VM1,"enCORE File Name",false }, {0x7003,0x0002,"GEMS_LUNAR_RAW",VR::OB,VM::VM1,"enCORE File Data",false }, {0x7003,0x0003,"GEMS_LUNAR_RAW",VR::UL,VM::VM1,"enCORE File Length",false }, {0x7003,0x0004,"GEMS_LUNAR_RAW",VR::LO,VM::VM1,"enCORE File Modified Time",false }, {0x7001,0x0001,"GEMS_MR_RAW_01",VR::OB,VM::VM1,"rdb_hdr_rec",false }, {0x7001,0x0002,"GEMS_MR_RAW_01",VR::OB,VM::VM1,"rdb_hdr_per_pass_tab",false }, {0x7001,0x0003,"GEMS_MR_RAW_01",VR::OB,VM::VM1,"rdb_hdr_unlock_raw",false }, {0x7001,0x0004,"GEMS_MR_RAW_01",VR::OB,VM::VM1,"rdb_hdr_data_acq_tab",false }, {0x7001,0x0005,"GEMS_MR_RAW_01",VR::OB,VM::VM1,"rdb_hdr_nex_tab",false }, {0x7001,0x0006,"GEMS_MR_RAW_01",VR::OB,VM::VM1,"rdb_hdr_nex_abort_tab",false }, {0x7001,0x0007,"GEMS_MR_RAW_01",VR::OB,VM::VM1,"rdb_hdr_tool",false }, {0x7001,0x0008,"GEMS_MR_RAW_01",VR::OB,VM::VM1,"rdb_raw_data",false }, {0x7001,0x0009,"GEMS_MR_RAW_01",VR::OB,VM::VM1,"SSP save",false }, {0x7001,0x000a,"GEMS_MR_RAW_01",VR::OB,VM::VM1,"UDA save",false }, {0x7001,0x000b,"GEMS_MR_RAW_01",VR::OB,VM::VM1,"rdb_chemsat_data",false }, {0x0043,0x0001,"GEMS_PARM_01",VR::SS,VM::VM1,"Bitmap of prescan options",false }, {0x0043,0x0002,"GEMS_PARM_01",VR::SS,VM::VM1,"Gradient offset in X",false }, {0x0043,0x0003,"GEMS_PARM_01",VR::SS,VM::VM1,"Gradient offset in Y",false }, {0x0043,0x0004,"GEMS_PARM_01",VR::SS,VM::VM1,"Gradient offset in Z",false }, {0x0043,0x0005,"GEMS_PARM_01",VR::SS,VM::VM1,"Img is original or unoriginal",false }, {0x0043,0x0006,"GEMS_PARM_01",VR::SS,VM::VM1,"Number of EPI shots",false }, {0x0043,0x0007,"GEMS_PARM_01",VR::SS,VM::VM1,"Views per segment",false }, {0x0043,0x0008,"GEMS_PARM_01",VR::SS,VM::VM1,"Respiratory rate, bpm",false }, {0x0043,0x0009,"GEMS_PARM_01",VR::SS,VM::VM1,"Respiratory trigger point",false }, {0x0043,0x000a,"GEMS_PARM_01",VR::SS,VM::VM1,"Type of receiver used",false }, {0x0043,0x000b,"GEMS_PARM_01",VR::DS,VM::VM1,"DB/dt Peak rate of change of gradient field",false }, {0x0043,0x000c,"GEMS_PARM_01",VR::DS,VM::VM1,"dB/dt Limits in units of percent",false }, {0x0043,0x000d,"GEMS_PARM_01",VR::DS,VM::VM1,"PSD estimated limit",false }, {0x0043,0x000e,"GEMS_PARM_01",VR::DS,VM::VM1,"PSD estimated limit in tesla per second",false }, {0x0043,0x000f,"GEMS_PARM_01",VR::DS,VM::VM1,"Saravghead",false }, // (0043,1010) SS (US) 0 # 2,1 Window value // however http://www.gemed.com.ar/usen/interoperability/dicom/docs/DOC0636565r4_CS.pdf // indicates it to be US ! Is it a dual SS/US ? {0x0043,0x0010,"GEMS_PARM_01",VR::US,VM::VM1,"Window value",false }, {0x0043,0x0011,"GEMS_PARM_01",VR::US,VM::VM1,"Total input views",false }, {0x0043,0x0012,"GEMS_PARM_01",VR::SS,VM::VM3,"X-ray chain",false }, {0x0043,0x0013,"GEMS_PARM_01",VR::SS,VM::VM5,"Decon kernel parameters",false }, {0x0043,0x0014,"GEMS_PARM_01",VR::SS,VM::VM3,"Calibration parameters",false }, {0x0043,0x0015,"GEMS_PARM_01",VR::SS,VM::VM3,"Total output views",false }, {0x0043,0x0016,"GEMS_PARM_01",VR::SS,VM::VM5,"Number of overranges",false }, {0x0043,0x0017,"GEMS_PARM_01",VR::DS,VM::VM1,"IBH image scale factors",false }, {0x0043,0x0018,"GEMS_PARM_01",VR::DS,VM::VM3,"BBH coefficients",false }, {0x0043,0x0019,"GEMS_PARM_01",VR::SS,VM::VM1,"Number of BBH chains to blend",false }, {0x0043,0x001a,"GEMS_PARM_01",VR::SL,VM::VM1,"Starting channel number",false }, {0x0043,0x001b,"GEMS_PARM_01",VR::SS,VM::VM1,"Ppscan parameters",false }, {0x0043,0x001c,"GEMS_PARM_01",VR::SS,VM::VM1,"GE image integrity",false }, {0x0043,0x001d,"GEMS_PARM_01",VR::SS,VM::VM1,"Level value",false }, {0x0043,0x001e,"GEMS_PARM_01",VR::DS,VM::VM1,"Delta Start Time [msec]",false }, {0x0043,0x001f,"GEMS_PARM_01",VR::SL,VM::VM1,"Max overranges in a view",false }, {0x0043,0x0020,"GEMS_PARM_01",VR::DS,VM::VM1,"Avg overranges all views",false }, {0x0043,0x0021,"GEMS_PARM_01",VR::SS,VM::VM1,"Corrected after glow terms",false }, {0x0043,0x0025,"GEMS_PARM_01",VR::SS,VM::VM6,"Reference channels",false }, {0x0043,0x0026,"GEMS_PARM_01",VR::US,VM::VM6,"No views ref chans blocked",false }, {0x0043,0x0027,"GEMS_PARM_01",VR::SH,VM::VM1,"Scan Pitch Ratio",false }, {0x0043,0x0028,"GEMS_PARM_01",VR::OB,VM::VM1,"Unique image iden",false }, {0x0043,0x0029,"GEMS_PARM_01",VR::OB,VM::VM1,"Histogram tables",false }, {0x0043,0x002a,"GEMS_PARM_01",VR::OB,VM::VM1,"User defined data",false }, {0x0043,0x002b,"GEMS_PARM_01",VR::SS,VM::VM4,"Private Scan Options",false }, {0x0043,0x002c,"GEMS_PARM_01",VR::SS,VM::VM1,"Effective echo spacing",false }, {0x0043,0x002d,"GEMS_PARM_01",VR::SH,VM::VM1,"Filter Mode (String slop field 1 in legacy GE MR",false }, {0x0043,0x002e,"GEMS_PARM_01",VR::SH,VM::VM1,"String slop field 2",false }, {0x0043,0x002f,"GEMS_PARM_01",VR::SS,VM::VM1,"Image Type (real, imaginary, phase, magnitude)",false }, {0x0043,0x0030,"GEMS_PARM_01",VR::SS,VM::VM1,"Vas collapse flag",false }, {0x0043,0x0031,"GEMS_PARM_01",VR::DS,VM::VM2,"Recon Center Coordinates",false }, {0x0043,0x0032,"GEMS_PARM_01",VR::SS,VM::VM1,"Vas flags",false }, {0x0043,0x0033,"GEMS_PARM_01",VR::FL,VM::VM1,"Neg_scanspacing",false }, {0x0043,0x0034,"GEMS_PARM_01",VR::IS,VM::VM1,"Offset Frequency",false }, {0x0043,0x0035,"GEMS_PARM_01",VR::UL,VM::VM1,"User_usage_tag",false }, {0x0043,0x0036,"GEMS_PARM_01",VR::UL,VM::VM1,"User_fill_map_MSW",false }, {0x0043,0x0037,"GEMS_PARM_01",VR::UL,VM::VM1,"User_fill_map_LSW",false }, {0x0043,0x0038,"GEMS_PARM_01",VR::FL,VM::VM24,"User data 25...User data 48 {User48=Effective Resolution for spiral}",false }, {0x0043,0x0039,"GEMS_PARM_01",VR::IS,VM::VM4,"Slop_int_6... slop_int_9 (B_value/?/?/?)",false }, {0x0043,0x0040,"GEMS_PARM_01",VR::FL,VM::VM4,"Trigger on position",false }, {0x0043,0x0041,"GEMS_PARM_01",VR::FL,VM::VM4,"Degree of rotation",false }, {0x0043,0x0042,"GEMS_PARM_01",VR::SL,VM::VM4,"DAS trigger source",false }, {0x0043,0x0043,"GEMS_PARM_01",VR::SL,VM::VM4,"DAS fpa gain",false }, {0x0043,0x0044,"GEMS_PARM_01",VR::SL,VM::VM4,"DAS output source",false }, {0x0043,0x0045,"GEMS_PARM_01",VR::SL,VM::VM4,"DAS ad input",false }, {0x0043,0x0046,"GEMS_PARM_01",VR::SL,VM::VM4,"DAS cal mode",false }, {0x0043,0x0047,"GEMS_PARM_01",VR::SL,VM::VM4,"DAS cal frequency",false }, {0x0043,0x0048,"GEMS_PARM_01",VR::SL,VM::VM4,"DAS reg xm",false }, {0x0043,0x0049,"GEMS_PARM_01",VR::SL,VM::VM4,"DAS auto zero",false }, {0x0043,0x004a,"GEMS_PARM_01",VR::SS,VM::VM4,"Starting channel of view",false }, {0x0043,0x004b,"GEMS_PARM_01",VR::SL,VM::VM4,"DAS xm pattern",false }, {0x0043,0x004c,"GEMS_PARM_01",VR::SS,VM::VM4,"TGGC trigger mode",false }, {0x0043,0x004d,"GEMS_PARM_01",VR::FL,VM::VM4,"Start scan to X-ray on delay",false }, {0x0043,0x004e,"GEMS_PARM_01",VR::FL,VM::VM4,"Duration of X-ray on",false }, {0x0043,0x0060,"GEMS_PARM_01",VR::IS,VM::VM8,"Slop_int_10...slop_int_17",false }, {0x0043,0x0061,"GEMS_PARM_01",VR::UI,VM::VM1,"Scanner Study Entity UID",false }, {0x0043,0x0062,"GEMS_PARM_01",VR::SH,VM::VM1,"Scanner Study ID",false }, {0x0043,0x0063,"GEMS_PARM_01",VR::SH,VM::VM1,"Raw Data ID",false }, {0x0043,0x0064,"GEMS_PARM_01",VR::CS,VM::VM1_n,"Image Filter",false }, {0x0043,0x0065,"GEMS_PARM_01",VR::US,VM::VM1,"Motion Correction Indicator",false }, {0x0043,0x0066,"GEMS_PARM_01",VR::US,VM::VM1,"Helical Correction Indicator",false }, {0x0043,0x0067,"GEMS_PARM_01",VR::US,VM::VM1,"IBO Correction Indicator",false }, {0x0043,0x0068,"GEMS_PARM_01",VR::US,VM::VM1,"XT Correction Indicator",false }, {0x0043,0x0069,"GEMS_PARM_01",VR::US,VM::VM1,"Q-cal Correction Indicator",false }, {0x0043,0x006a,"GEMS_PARM_01",VR::US,VM::VM1,"AV Correction Indicator",false }, {0x0043,0x006b,"GEMS_PARM_01",VR::US,VM::VM1,"L-MDK Correction Indicator",false }, {0x0043,0x006c,"GEMS_PARM_01",VR::IS,VM::VM1,"Detector Row",false }, {0x0043,0x006d,"GEMS_PARM_01",VR::DS,VM::VM1,"Area Size",false }, // Corrected IS -> DS {0x0043,0x006e,"GEMS_PARM_01",VR::SH,VM::VM1,"Auto mA Mode",false }, {0x0043,0x006f,"GEMS_PARM_01",VR::DS,VM::VM3_4,"Scanner Table Entry (single gradient coil systems only)/Scanner Table Entry + Gradient Coil Selected",false }, {0x0043,0x0070,"GEMS_PARM_01",VR::LO,VM::VM1,"Paradigm Name",false }, {0x0043,0x0071,"GEMS_PARM_01",VR::ST,VM::VM1,"Paradigm Description",false }, {0x0043,0x0072,"GEMS_PARM_01",VR::UI,VM::VM1,"Paradigm UID",false }, {0x0043,0x0073,"GEMS_PARM_01",VR::US,VM::VM1,"Experiment Type",false }, {0x0043,0x0074,"GEMS_PARM_01",VR::US,VM::VM1,"#rest volumes",false }, {0x0043,0x0075,"GEMS_PARM_01",VR::US,VM::VM1,"#active volumes",false }, {0x0043,0x0076,"GEMS_PARM_01",VR::US,VM::VM1,"#dummy scans",false }, {0x0043,0x0077,"GEMS_PARM_01",VR::SH,VM::VM1,"Application Name",false }, {0x0043,0x0078,"GEMS_PARM_01",VR::SH,VM::VM1,"Application Version",false }, {0x0043,0x0079,"GEMS_PARM_01",VR::US,VM::VM1,"Slices Per Volume",false }, {0x0043,0x007a,"GEMS_PARM_01",VR::US,VM::VM1,"Expected Time Points",false }, {0x0043,0x007b,"GEMS_PARM_01",VR::FL,VM::VM1_n,"Regressor Values",false }, {0x0043,0x007c,"GEMS_PARM_01",VR::FL,VM::VM1,"Delay after slice group",false }, {0x0043,0x007d,"GEMS_PARM_01",VR::US,VM::VM1,"Recon mode flag word",false }, {0x0043,0x007e,"GEMS_PARM_01",VR::LO,VM::VM1_n,"PACC specific information",false }, {0x0043,0x007f,"GEMS_PARM_01",VR::DS,VM::VM1_n,"Reserved",false }, {0x0043,0x0080,"GEMS_PARM_01",VR::LO,VM::VM1_n,"Coil ID Data",false }, {0x0043,0x0081,"GEMS_PARM_01",VR::LO,VM::VM1,"GE Coil Name",false }, {0x0043,0x0082,"GEMS_PARM_01",VR::LO,VM::VM1_n,"System Configuration Information",false }, {0x0043,0x0083,"GEMS_PARM_01",VR::DS,VM::VM1_2,"Asset R Factors",false }, {0x0043,0x0084,"GEMS_PARM_01",VR::LO,VM::VM1_n,"Additional Asset Data",false }, {0x0043,0x0085,"GEMS_PARM_01",VR::UT,VM::VM1,"Debug Data (text format)",false }, {0x0043,0x0086,"GEMS_PARM_01",VR::OB,VM::VM1,"Debug Data (binary format)",false }, {0x0043,0x0087,"GEMS_PARM_01",VR::UT,VM::VM1,"Reserved",false }, {0x0043,0x0088,"GEMS_PARM_01",VR::UI,VM::VM1,"PURE Acquisition Calibration Series UID",false }, {0x0043,0x0089,"GEMS_PARM_01",VR::LO,VM::VM3,"Governing Body, dB/dt, and SAR definition",false }, {0x0043,0x008a,"GEMS_PARM_01",VR::CS,VM::VM1,"Private In-Plane Phase Encoding Direction",false }, {0x0043,0x008b,"GEMS_PARM_01",VR::OB,VM::VM1,"FMRI Binary Data Block",false }, {0x0043,0x008c,"GEMS_PARM_01",VR::DS,VM::VM6,"Voxel Location",false }, {0x0043,0x008d,"GEMS_PARM_01",VR::DS,VM::VM7_7n,"SAT Band Locations",false }, {0x0043,0x008e,"GEMS_PARM_01",VR::DS,VM::VM3,"Spectro Prescan Values",false }, {0x0043,0x008f,"GEMS_PARM_01",VR::DS,VM::VM3,"Spectro Parameters",false }, {0x0043,0x0090,"GEMS_PARM_01",VR::LO,VM::VM1_n,"SAR Definition",false }, {0x0043,0x0091,"GEMS_PARM_01",VR::DS,VM::VM1_n,"SAR value",false }, {0x0043,0x0092,"GEMS_PARM_01",VR::LO,VM::VM1,"Image Error Text",false }, {0x0043,0x0093,"GEMS_PARM_01",VR::DS,VM::VM1_n,"Spectro Quantitation Values",false }, {0x0043,0x0094,"GEMS_PARM_01",VR::DS,VM::VM1_n,"Spectro Ratio Values",false }, {0x0043,0x0095,"GEMS_PARM_01",VR::LO,VM::VM1,"Prescan Reuse String",false }, {0x0043,0x0096,"GEMS_PARM_01",VR::CS,VM::VM1,"Content Qualification",false }, {0x0043,0x0097,"GEMS_PARM_01",VR::LO,VM::VM1_n,"Image Filtering Parameters",false }, {0x0043,0x0098,"GEMS_PARM_01",VR::UI,VM::VM1,"ASSET Acquisition Calibration Series UID",false }, {0x0043,0x0099,"GEMS_PARM_01",VR::LO,VM::VM1_n,"Extended Options",false }, {0x0043,0x009a,"GEMS_PARM_01",VR::IS,VM::VM1,"Rx Stack Identification",false }, {0x0043,0x009b,"GEMS_PARM_01",VR::DS,VM::VM1,"NPW factor",false }, {0x0043,0x009c,"GEMS_PARM_01",VR::OB,VM::VM1,"Research Tag 1",false }, {0x0043,0x009d,"GEMS_PARM_01",VR::OB,VM::VM1,"Research Tag 2",false }, {0x0043,0x009e,"GEMS_PARM_01",VR::OB,VM::VM1,"Research Tag 3",false }, {0x0043,0x009f,"GEMS_PARM_01",VR::OB,VM::VM1,"Research Tag 4",false }, {0x0043,0x00a0,"GEMS_PARM_01",VR::SQ,VM::VM1,"Spectroscopy Pixel Sequence",false }, {0x0043,0x00a1,"GEMS_PARM_01",VR::SQ,VM::VM1,"Spectroscopy Default Display Sequence",false }, {0x0043,0x00a2,"GEMS_PARM_01",VR::DS,VM::VM1_n,"MEG Data",false }, {0x0043,0x00a3,"GEMS_PARM_01",VR::CS,VM::VM1,"ASL Contrast technique",false }, {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,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 }, {0x0043,0x00ad,"GEMS_PARM_01",VR::DS,VM::VM1_n,"Other Recovery Times Values",false }, {0x0043,0x00ae,"GEMS_PARM_01",VR::LO,VM::VM1_n,"Other Recovery Times Labels",false }, {0x0043,0x00af,"GEMS_PARM_01",VR::DS,VM::VM1_n,"Additional Echo Times",false }, {0x0043,0x00b0,"GEMS_PARM_01",VR::FL,VM::VM1,"Rescan Time in Acquisition",false }, {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,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 }, {0x0043,0x00b9,"GEMS_PARM_01",VR::LO,VM::VM1,"Parallel Transmit Information",false }, {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 }, {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 }, {0x2001,0x0011,"GEMS_PARM_01",VR::SH,VM::VM1,"DICOM Implementation Version",false }, {0x2001,0x0012,"GEMS_PARM_01",VR::UI,VM::VM1,"Within-DICOM-Implementation SOP Instance UID",false }, {0x2001,0x0013,"GEMS_PARM_01",VR::SH,VM::VM1,"Application Name",false }, {0x2001,0x0014,"GEMS_PARM_01",VR::SH,VM::VM1,"Application Version",false }, {0x2001,0x0015,"GEMS_PARM_01",VR::SH,VM::VM1,"Compatibility Version",false }, {0x2001,0x0021,"GEMS_PARM_01",VR::UI,VM::VM1_n,"Referenced Series UID",false }, {0x2001,0x0031,"GEMS_PARM_01",VR::US,VM::VM1,"Number of Objects Averaged",false }, {0x2001,0x0041,"GEMS_PARM_01",VR::US,VM::VM1,"Number of Expected Time Points",false }, {0x2001,0x0051,"GEMS_PARM_01",VR::US,VM::VM1,"Number of Slices Per Volume",false }, {0x2001,0x0060,"GEMS_PARM_01",VR::US,VM::VM1,"BW Image Type",false }, {0x2001,0x0061,"GEMS_PARM_01",VR::US,VM::VM1,"Experiment Type",false }, {0x2001,0x0071,"GEMS_PARM_01",VR::UI,VM::VM1,"Paradigm UID",false }, {0x2001,0x0072,"GEMS_PARM_01",VR::LO,VM::VM1,"Paradigm Name",false }, {0x2001,0x0073,"GEMS_PARM_01",VR::ST,VM::VM1,"Paradigm Description",false }, {0x2001,0x0080,"GEMS_PARM_01",VR::OB,VM::VM1,"Contrast",false }, {0x2001,0x0081,"GEMS_PARM_01",VR::FL,VM::VM1_n,"Regressor Values",false }, {0x2001,0x0086,"GEMS_PARM_01",VR::US,VM::VM1,"Number of Degrees of Freedom",false }, {0x2001,0x008a,"GEMS_PARM_01",VR::FL,VM::VM1,"Z Threshold",false }, {0x2001,0x008b,"GEMS_PARM_01",VR::FL,VM::VM1,"p Threshold",false }, {0x2001,0x0090,"GEMS_PARM_01",VR::OB,VM::VM1,"Processing parameters",false }, {0x2001,0x0091,"GEMS_PARM_01",VR::OB,VM::VM1,"Motion Plot",false }, {0x2001,0x0092,"GEMS_PARM_01",VR::OB,VM::VM1,"ROIs",false }, {0x2001,0x0093,"GEMS_PARM_01",VR::OB,VM::VM1,"Tracts",false }, {0x2001,0x0094,"GEMS_PARM_01",VR::OB,VM::VM1,"Report",false }, {0x2001,0x0095,"GEMS_PARM_01",VR::OB,VM::VM1,"Response Data",false }, {0x2001,0x00a0,"GEMS_PARM_01",VR::FL,VM::VM1_n,"Motion Parameters",false }, {0x2001,0x00a1,"GEMS_PARM_01",VR::FL,VM::VM1_n,"Registration Parameters",false }, {0x2001,0x00a2,"GEMS_PARM_01",VR::FL,VM::VM1_n,"Subject Data",false }, {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 }, {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 }, {0x0009,0x0004,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance Patient.software_version",false }, {0x0009,0x0005,"GEMS_PETD_01",VR::DT,VM::VM1,"PET patient_datetime",false }, {0x0009,0x0006,"GEMS_PETD_01",VR::SL,VM::VM1,"PET type",false }, {0x0009,0x0007,"GEMS_PETD_01",VR::UI,VM::VM1,"PET exam_id",false }, {0x0009,0x0008,"GEMS_PETD_01",VR::SH,VM::VM1,"PET compatible_version",false }, {0x0009,0x0009,"GEMS_PETD_01",VR::SH,VM::VM1,"PET software_version",false }, {0x0009,0x000a,"GEMS_PETD_01",VR::UI,VM::VM1,"PET scan_id",false }, {0x0009,0x000b,"GEMS_PETD_01",VR::SH,VM::VM1,"PET compatible_version",false }, {0x0009,0x000c,"GEMS_PETD_01",VR::SH,VM::VM1,"PET software_version",false }, {0x0009,0x000d,"GEMS_PETD_01",VR::DT,VM::VM1,"PET scan_datetime",false }, {0x0009,0x000e,"GEMS_PETD_01",VR::DT,VM::VM1,"PET scan_ready",false }, {0x0009,0x000f,"GEMS_PETD_01",VR::ST,VM::VM1,"PET scan_description",false }, {0x0009,0x0010,"GEMS_PETD_01",VR::LO,VM::VM1,"PET hospital_name",false }, {0x0009,0x0011,"GEMS_PETD_01",VR::LO,VM::VM1,"PET scanner_desc",false }, {0x0009,0x0012,"GEMS_PETD_01",VR::LO,VM::VM1,"PET manufacturer",false }, {0x0009,0x0013,"GEMS_PETD_01",VR::UI,VM::VM1,"PET for_identifier",false }, {0x0009,0x0014,"GEMS_PETD_01",VR::LO,VM::VM1,"PET landmark_name",false }, {0x0009,0x0015,"GEMS_PETD_01",VR::SH,VM::VM1,"PET landmark_abbrev",false }, {0x0009,0x0016,"GEMS_PETD_01",VR::SL,VM::VM1,"PET patient_position",false }, {0x0009,0x0017,"GEMS_PETD_01",VR::SL,VM::VM1,"PET scan_perspective",false }, {0x0009,0x0018,"GEMS_PETD_01",VR::SL,VM::VM1,"PET scan_type",false }, {0x0009,0x0019,"GEMS_PETD_01",VR::SL,VM::VM1,"PET scan_mode",false }, {0x0009,0x001a,"GEMS_PETD_01",VR::SL,VM::VM1,"PET start_condition",false }, {0x0009,0x001b,"GEMS_PETD_01",VR::SL,VM::VM1,"PET start_cond_data",false }, {0x0009,0x001c,"GEMS_PETD_01",VR::SL,VM::VM1,"PET sel_stop_cond",false }, {0x0009,0x001d,"GEMS_PETD_01",VR::SL,VM::VM1,"PET sel_stop_cond_data",false }, {0x0009,0x001e,"GEMS_PETD_01",VR::SL,VM::VM1,"PET collect_deadtime",false }, {0x0009,0x001f,"GEMS_PETD_01",VR::SL,VM::VM1,"PET collect_singles",false }, {0x0009,0x0020,"GEMS_PETD_01",VR::SL,VM::VM1,"PET collect_countrate",false }, {0x0009,0x0021,"GEMS_PETD_01",VR::SL,VM::VM1,"PET countrate_period",false }, {0x0009,0x0022,"GEMS_PETD_01",VR::SL,VM::VM1,"PET delayed_events",false }, {0x0009,0x0023,"GEMS_PETD_01",VR::SL,VM::VM1,"PET delayed_bias",false }, {0x0009,0x0024,"GEMS_PETD_01",VR::SL,VM::VM1,"PET word_size",false }, {0x0009,0x0025,"GEMS_PETD_01",VR::SL,VM::VM1,"PET axial_acceptance",false }, {0x0009,0x0026,"GEMS_PETD_01",VR::SL,VM::VM1,"PET axial_angle_3d",false }, {0x0009,0x0027,"GEMS_PETD_01",VR::SL,VM::VM1,"PET theta_compression",false }, {0x0009,0x0028,"GEMS_PETD_01",VR::SL,VM::VM1,"PET axial_compression",false }, {0x0009,0x0029,"GEMS_PETD_01",VR::FL,VM::VM1,"PET gantry_tilt_angle",false }, {0x0009,0x002a,"GEMS_PETD_01",VR::SL,VM::VM1,"PET collimation",false }, {0x0009,0x002b,"GEMS_PETD_01",VR::SL,VM::VM1,"PET scan_fov",false }, {0x0009,0x002c,"GEMS_PETD_01",VR::SL,VM::VM1,"PET axial_fov",false }, {0x0009,0x002d,"GEMS_PETD_01",VR::SL,VM::VM1,"PET event_separation",false }, {0x0009,0x002e,"GEMS_PETD_01",VR::SL,VM::VM1,"PET mask_width",false }, {0x0009,0x002f,"GEMS_PETD_01",VR::SL,VM::VM1,"PET binning_mode",false }, {0x0009,0x0030,"GEMS_PETD_01",VR::SL,VM::VM1,"PET trig_rej_method",false }, {0x0009,0x0031,"GEMS_PETD_01",VR::SL,VM::VM1,"PET number_for_reject",false }, {0x0009,0x0032,"GEMS_PETD_01",VR::SL,VM::VM1,"PET lower_reject_limit",false }, {0x0009,0x0033,"GEMS_PETD_01",VR::SL,VM::VM1,"PET upper_reject_limit",false }, {0x0009,0x0034,"GEMS_PETD_01",VR::SL,VM::VM1,"PET triggers_acquired",false }, {0x0009,0x0035,"GEMS_PETD_01",VR::SL,VM::VM1,"PET triggers_rejected",false }, {0x0009,0x0036,"GEMS_PETD_01",VR::LO,VM::VM1,"PET tracer_name",false }, {0x0009,0x0037,"GEMS_PETD_01",VR::LO,VM::VM1,"PET batch_description",false }, {0x0009,0x0038,"GEMS_PETD_01",VR::FL,VM::VM1,"PET tracer_activity",false }, {0x0009,0x0039,"GEMS_PETD_01",VR::DT,VM::VM1,"PET meas_datetime",false }, {0x0009,0x003a,"GEMS_PETD_01",VR::FL,VM::VM1,"PET pre_inj_volume",false }, {0x0009,0x003b,"GEMS_PETD_01",VR::DT,VM::VM1,"PET admin_datetime",false }, {0x0009,0x003c,"GEMS_PETD_01",VR::FL,VM::VM1,"PET post_inj_activity",false }, {0x0009,0x003d,"GEMS_PETD_01",VR::DT,VM::VM1,"PET post_inj_datetime",false }, {0x0009,0x003e,"GEMS_PETD_01",VR::SH,VM::VM1,"PET radionuclide_name",false }, {0x0009,0x003f,"GEMS_PETD_01",VR::FL,VM::VM1,"PET half_life",false }, {0x0009,0x0040,"GEMS_PETD_01",VR::FL,VM::VM1,"PET positron_fraction",false }, {0x0009,0x0041,"GEMS_PETD_01",VR::SL,VM::VM1,"PET source1_holder",false }, {0x0009,0x0042,"GEMS_PETD_01",VR::FL,VM::VM1,"PET source1_activity",false }, {0x0009,0x0043,"GEMS_PETD_01",VR::DT,VM::VM1,"PET source1_meas_dt",false }, {0x0009,0x0044,"GEMS_PETD_01",VR::SH,VM::VM1,"PET source1_radnuclide",false }, {0x0009,0x0045,"GEMS_PETD_01",VR::FL,VM::VM1,"PET source1_half_life",false }, {0x0009,0x0046,"GEMS_PETD_01",VR::SL,VM::VM1,"PET source2_holder",false }, {0x0009,0x0047,"GEMS_PETD_01",VR::FL,VM::VM1,"PET source2_activity",false }, {0x0009,0x0048,"GEMS_PETD_01",VR::DT,VM::VM1,"PET source2_meas_dt",false }, {0x0009,0x0049,"GEMS_PETD_01",VR::SH,VM::VM1,"PET source2_radnuclide",false }, {0x0009,0x004a,"GEMS_PETD_01",VR::FL,VM::VM1,"PET source2_half_life",false }, {0x0009,0x004b,"GEMS_PETD_01",VR::SL,VM::VM1,"PET source_speed",false }, {0x0009,0x004c,"GEMS_PETD_01",VR::FL,VM::VM1,"PET source_location",false }, {0x0009,0x004d,"GEMS_PETD_01",VR::SL,VM::VM1,"PET emission_present",false }, {0x0009,0x004e,"GEMS_PETD_01",VR::SL,VM::VM1,"PET lower_axial_acc",false }, {0x0009,0x004f,"GEMS_PETD_01",VR::SL,VM::VM1,"PET upper_axial_acc",false }, {0x0009,0x0050,"GEMS_PETD_01",VR::SL,VM::VM1,"PET lower_coinc_limit",false }, {0x0009,0x0051,"GEMS_PETD_01",VR::SL,VM::VM1,"PET upper_coinc_limit",false }, {0x0009,0x0052,"GEMS_PETD_01",VR::SL,VM::VM1,"PET coinc_delay_offset",false }, {0x0009,0x0053,"GEMS_PETD_01",VR::SL,VM::VM1,"PET coinc_output_mode",false }, {0x0009,0x0054,"GEMS_PETD_01",VR::SL,VM::VM1,"PET upper_energy_limit",false }, {0x0009,0x0055,"GEMS_PETD_01",VR::SL,VM::VM1,"PET lower_energy_limit",false }, {0x0009,0x0056,"GEMS_PETD_01",VR::UI,VM::VM1,"PET normal_cal_id",false }, {0x0009,0x0057,"GEMS_PETD_01",VR::UI,VM::VM1,"PET normal_2d_cal_id",false }, {0x0009,0x0058,"GEMS_PETD_01",VR::UI,VM::VM1,"PET blank_cal_id",false }, {0x0009,0x0059,"GEMS_PETD_01",VR::UI,VM::VM1,"PET wc_cal_id",false }, {0x0009,0x005a,"GEMS_PETD_01",VR::SL,VM::VM1,"PET derived",false }, {0x0009,0x005b,"GEMS_PETD_01",VR::LO,VM::VM1,"PET contrast_agent",false }, {0x0009,0x005c,"GEMS_PETD_01",VR::UI,VM::VM1,"PET frame_id",false }, {0x0009,0x005d,"GEMS_PETD_01",VR::UI,VM::VM1,"PET scan_id",false }, {0x0009,0x005e,"GEMS_PETD_01",VR::UI,VM::VM1,"PET exam_id",false }, {0x0009,0x005f,"GEMS_PETD_01",VR::LO,VM::VM1,"PET patient_id",false }, {0x0009,0x0060,"GEMS_PETD_01",VR::SH,VM::VM1,"PET compatible_version",false }, {0x0009,0x0061,"GEMS_PETD_01",VR::SH,VM::VM1,"PET software_version",false }, {0x0009,0x0062,"GEMS_PETD_01",VR::ST,VM::VM1,"PET where_is_frame",false }, {0x0009,0x0063,"GEMS_PETD_01",VR::SL,VM::VM1,"PET frame_size",false }, {0x0009,0x0064,"GEMS_PETD_01",VR::SL,VM::VM1,"PET file_exists",false }, {0x0009,0x0065,"GEMS_PETD_01",VR::SL,VM::VM1,"PET patient_entry",false }, {0x0009,0x0066,"GEMS_PETD_01",VR::FL,VM::VM1,"PET table_height",false }, {0x0009,0x0067,"GEMS_PETD_01",VR::FL,VM::VM1,"PET table_z_position",false }, {0x0009,0x0068,"GEMS_PETD_01",VR::DT,VM::VM1,"PET landmark_datetime",false }, {0x0009,0x0069,"GEMS_PETD_01",VR::SL,VM::VM1,"PET slice_count",false }, {0x0009,0x006a,"GEMS_PETD_01",VR::FL,VM::VM1,"PET start_location",false }, {0x0009,0x006b,"GEMS_PETD_01",VR::SL,VM::VM1,"PET acq_delay",false }, {0x0009,0x006c,"GEMS_PETD_01",VR::DT,VM::VM1,"PET acq_start",false }, {0x0009,0x006d,"GEMS_PETD_01",VR::SL,VM::VM1,"PET acq_duration",false }, {0x0009,0x006e,"GEMS_PETD_01",VR::SL,VM::VM1,"PET acq_bin_dur",false }, {0x0009,0x006f,"GEMS_PETD_01",VR::SL,VM::VM1,"PET acq_bin_start",false }, {0x0009,0x0070,"GEMS_PETD_01",VR::SL,VM::VM1,"PET actual_stop_cond",false }, {0x0009,0x0071,"GEMS_PETD_01",VR::FD,VM::VM1,"PET total_prompts",false }, {0x0009,0x0072,"GEMS_PETD_01",VR::FD,VM::VM1,"PET total_delays",false }, {0x0009,0x0073,"GEMS_PETD_01",VR::SL,VM::VM1,"PET frame_valid",false }, {0x0009,0x0074,"GEMS_PETD_01",VR::SL,VM::VM1,"PET validity_info",false }, {0x0009,0x0075,"GEMS_PETD_01",VR::SL,VM::VM1,"PET archived",false }, {0x0009,0x0076,"GEMS_PETD_01",VR::SL,VM::VM1,"PET compression",false }, {0x0009,0x0077,"GEMS_PETD_01",VR::SL,VM::VM1,"PET uncompressed_size",false }, {0x0009,0x0078,"GEMS_PETD_01",VR::SL,VM::VM1,"PET accum_bin_dur",false }, {0x0009,0x0079,"GEMS_PETD_01",VR::SH,VM::VM1,"PET compatible_version",false }, {0x0009,0x007a,"GEMS_PETD_01",VR::SH,VM::VM1,"PET software_version",false }, {0x0009,0x007b,"GEMS_PETD_01",VR::DT,VM::VM1,"PET is_datetime",false }, {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,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 }, {0x0009,0x0083,"GEMS_PETD_01",VR::SL,VM::VM1,"PET window_level_type",false }, {0x0009,0x0084,"GEMS_PETD_01",VR::FL,VM::VM1,"PET rotate",false }, {0x0009,0x0085,"GEMS_PETD_01",VR::SL,VM::VM1,"PET flip",false }, {0x0009,0x0086,"GEMS_PETD_01",VR::FL,VM::VM1,"PET zoom",false }, {0x0009,0x0087,"GEMS_PETD_01",VR::SL,VM::VM1,"PET pan_x",false }, {0x0009,0x0088,"GEMS_PETD_01",VR::SL,VM::VM1,"PET pan_y",false }, {0x0009,0x0089,"GEMS_PETD_01",VR::FL,VM::VM1,"PET window_level_min",false }, {0x0009,0x008a,"GEMS_PETD_01",VR::FL,VM::VM1,"PET window_level_max",false }, {0x0009,0x008b,"GEMS_PETD_01",VR::SL,VM::VM1,"PET recon_method",false }, {0x0009,0x008c,"GEMS_PETD_01",VR::SL,VM::VM1,"PET attenuation",false }, {0x0009,0x008d,"GEMS_PETD_01",VR::FL,VM::VM1,"PET atten_coefficient",false }, {0x0009,0x008e,"GEMS_PETD_01",VR::SL,VM::VM1,"PET bp_filter",false }, {0x0009,0x008f,"GEMS_PETD_01",VR::FL,VM::VM1,"PET bp_filter_cutoff",false }, {0x0009,0x0090,"GEMS_PETD_01",VR::SL,VM::VM1,"PET bp_filter_order",false }, {0x0009,0x0091,"GEMS_PETD_01",VR::FL,VM::VM1,"PET bp_center_l",false }, {0x0009,0x0092,"GEMS_PETD_01",VR::FL,VM::VM1,"PET bp_center_p",false }, {0x0009,0x0093,"GEMS_PETD_01",VR::SL,VM::VM1,"PET atten_smooth",false }, {0x0009,0x0094,"GEMS_PETD_01",VR::SL,VM::VM1,"PET atten_smooth_param",false }, {0x0009,0x0095,"GEMS_PETD_01",VR::SL,VM::VM1,"PET angle_smooth_param",false }, {0x0009,0x0096,"GEMS_PETD_01",VR::UI,VM::VM1,"PET wellcountercal_id",false }, {0x0009,0x0097,"GEMS_PETD_01",VR::UI,VM::VM1,"PET trans_scan_id",false }, {0x0009,0x0098,"GEMS_PETD_01",VR::UI,VM::VM1,"PET norm_cal_id",false }, {0x0009,0x0099,"GEMS_PETD_01",VR::UI,VM::VM1,"PET blnk_cal_id",false }, {0x0009,0x009a,"GEMS_PETD_01",VR::FL,VM::VM1,"PET cac_edge_threshold",false }, {0x0009,0x009b,"GEMS_PETD_01",VR::FL,VM::VM1,"PET cac_skull_offset",false }, {0x0009,0x009c,"GEMS_PETD_01",VR::UI,VM::VM1,"PET emiss_sub_id",false }, {0x0009,0x009d,"GEMS_PETD_01",VR::SS,VM::VM1,"PET radial_filter_3d",false }, {0x0009,0x009e,"GEMS_PETD_01",VR::FL,VM::VM1,"PET radial_cutoff_3d",false }, {0x0009,0x009f,"GEMS_PETD_01",VR::SL,VM::VM1,"PET axial_filter_3d",false }, {0x0009,0x00a0,"GEMS_PETD_01",VR::FL,VM::VM1,"PET axial_cutoff_3d",false }, {0x0009,0x00a1,"GEMS_PETD_01",VR::FL,VM::VM1,"PET axial_start",false }, {0x0009,0x00a2,"GEMS_PETD_01",VR::FL,VM::VM1,"PET axial_spacing",false }, {0x0009,0x00a3,"GEMS_PETD_01",VR::SL,VM::VM1,"PET axial_angles_used",false }, {0x0009,0x00a4,"GEMS_PETD_01",VR::SH,VM::VM1,"PET compatible_version",false }, {0x0009,0x00a5,"GEMS_PETD_01",VR::SH,VM::VM1,"PET software_version",false }, {0x0009,0x00a6,"GEMS_PETD_01",VR::SL,VM::VM1,"PET slice_number",false }, {0x0009,0x00a7,"GEMS_PETD_01",VR::FL,VM::VM1,"PET total_counts",false }, {0x0009,0x00a8,"GEMS_PETD_01",VR::OB,VM::VM1,"PET other_atts",false }, {0x0009,0x00a9,"GEMS_PETD_01",VR::SL,VM::VM1,"PET other_atts_size",false }, {0x0009,0x00aa,"GEMS_PETD_01",VR::SL,VM::VM1,"PET archived",false }, {0x0009,0x00ab,"GEMS_PETD_01",VR::FL,VM::VM1,"PET bp_center_x",false }, {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,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 }, {0x0009,0x00b4,"GEMS_PETD_01",VR::FL,VM::VM1,"PET ir_recon_fov",false }, {0x0009,0x00b5,"GEMS_PETD_01",VR::SS,VM::VM1,"PET ir_corr_model",false }, {0x0009,0x00b6,"GEMS_PETD_01",VR::SS,VM::VM1,"PET ir_loop_filter",false }, {0x0009,0x00b7,"GEMS_PETD_01",VR::FL,VM::VM1,"PET ir_pre_filt_parm",false }, {0x0009,0x00b8,"GEMS_PETD_01",VR::FL,VM::VM1,"PET ir_loop_filt_parm",false }, {0x0009,0x00b9,"GEMS_PETD_01",VR::FL,VM::VM1,"PET response_filt_parm",false }, {0x0009,0x00ba,"GEMS_PETD_01",VR::SS,VM::VM1,"PET post_filter",false }, {0x0009,0x00bb,"GEMS_PETD_01",VR::FL,VM::VM1,"PET post_filt_parm",false }, {0x0009,0x00bc,"GEMS_PETD_01",VR::SS,VM::VM1,"PET ir_regularize",false }, {0x0009,0x00bd,"GEMS_PETD_01",VR::FL,VM::VM1,"PET regularize_parm",false }, {0x0009,0x00be,"GEMS_PETD_01",VR::SS,VM::VM1,"PET ac_bp_filter",false }, {0x0009,0x00bf,"GEMS_PETD_01",VR::FL,VM::VM1,"PET ac_bp_filt_cut_off",false }, {0x0009,0x00c0,"GEMS_PETD_01",VR::SL,VM::VM1,"PET ac_bp_filt_order",false }, {0x0009,0x00c1,"GEMS_PETD_01",VR::SS,VM::VM1,"PET ac_img_smooth",false }, {0x0009,0x00c2,"GEMS_PETD_01",VR::FL,VM::VM1,"PET ac_img_smooth_parm",false }, {0x0009,0x00c3,"GEMS_PETD_01",VR::SL,VM::VM1,"PET scatter_method",false }, {0x0009,0x00c4,"GEMS_PETD_01",VR::SS,VM::VM1,"PET scatter_num_iter",false }, {0x0009,0x00c5,"GEMS_PETD_01",VR::FL,VM::VM1,"PET scatter_parm",false }, {0x0009,0x00c6,"GEMS_PETD_01",VR::FL,VM::VM1,"PET seg_qc_parm",false }, {0x0009,0x00c7,"GEMS_PETD_01",VR::SL,VM::VM1,"PET overlap",false }, {0x0009,0x00c8,"GEMS_PETD_01",VR::UI,VM::VM1,"PET ovlp_frm_id",false }, {0x0009,0x00c9,"GEMS_PETD_01",VR::UI,VM::VM1,"PET ovlp_trans_frm_id",false }, {0x0009,0x00ca,"GEMS_PETD_01",VR::UI,VM::VM1,"PET ovlp_tpulse_frm_id",false }, {0x0009,0x00cb,"GEMS_PETD_01",VR::FL,VM::VM1,"PET vqc_x_axis_trans",false }, {0x0009,0x00cc,"GEMS_PETD_01",VR::FL,VM::VM1,"PET vqc_x_axis_tilt",false }, {0x0009,0x00cd,"GEMS_PETD_01",VR::FL,VM::VM1,"PET vqc_y_axis_trans",false }, {0x0009,0x00ce,"GEMS_PETD_01",VR::FL,VM::VM1,"PET vqc_y_axis_swivel",false }, {0x0009,0x00cf,"GEMS_PETD_01",VR::FL,VM::VM1,"PET vqc_z_axis_trans",false }, {0x0009,0x00d0,"GEMS_PETD_01",VR::FL,VM::VM1,"PET vqc_z_axis_roll",false }, {0x0009,0x00d1,"GEMS_PETD_01",VR::LO,VM::VM1,"PET ctac_conv_scale",false }, {0x0009,0x00d2,"GEMS_PETD_01",VR::UI,VM::VM1,"PET image_set_id",false }, {0x0009,0x00d3,"GEMS_PETD_01",VR::SL,VM::VM1,"PET constrast_route",false }, {0x0009,0x00d4,"GEMS_PETD_01",VR::LO,VM::VM1,"PET ctac_conv_scale",false }, {0x0009,0x00d5,"GEMS_PETD_01",VR::FL,VM::VM1,"PET loop_filter_parm",false }, {0x0009,0x00d6,"GEMS_PETD_01",VR::FL,VM::VM1,"PET image_one_loc",false }, {0x0009,0x00d7,"GEMS_PETD_01",VR::FL,VM::VM1,"PET image_index_loc",false }, {0x0009,0x00d8,"GEMS_PETD_01",VR::SL,VM::VM1,"PET frame_number",false }, {0x0009,0x00d9,"GEMS_PETD_01",VR::SL,VM::VM1,"PET list_file_exists",false }, {0x0009,0x00da,"GEMS_PETD_01",VR::ST,VM::VM1,"PET where_is_list_frame",false }, {0x0009,0x00db,"GEMS_PETD_01",VR::SL,VM::VM1,"PET ir_z_filter_flag",false }, {0x0009,0x00dc,"GEMS_PETD_01",VR::FL,VM::VM1,"PET ir_z_filter_ratio",false }, {0x0009,0x00dd,"GEMS_PETD_01",VR::US,VM::VM1,"PET num_of_rr_interval",false }, {0x0009,0x00de,"GEMS_PETD_01",VR::US,VM::VM1,"PET num_of_time_slots",false }, {0x0009,0x00df,"GEMS_PETD_01",VR::US,VM::VM1,"PET num_of_slices",false }, {0x0009,0x00e0,"GEMS_PETD_01",VR::US,VM::VM1,"PET num_of_time_slices",false }, {0x0009,0x00e1,"GEMS_PETD_01",VR::SL,VM::VM1,"PET unlisted_scan",false }, {0x0009,0x00e2,"GEMS_PETD_01",VR::SL,VM::VM1,"PET rest_stress",false }, {0x0009,0x00e3,"GEMS_PETD_01",VR::FL,VM::VM1,"PET phase percentage",false }, {0x0009,0x00e4,"GEMS_PETD_01",VR::ST,VM::VM1,"Recon Protocol",false }, {0x0009,0x00e5,"GEMS_PETD_01",VR::FL,VM::VM1,"PET left shift",false }, {0x0009,0x00e6,"GEMS_PETD_01",VR::FL,VM::VM1,"PET posterior shift",false }, {0x0009,0x00e7,"GEMS_PETD_01",VR::FL,VM::VM1,"PET superior shift",false }, {0x0009,0x00e8,"GEMS_PETD_01",VR::SL,VM::VM1,"PET acq_bin_num",false }, {0x0009,0x00e9,"GEMS_PETD_01",VR::FL,VM::VM1,"PET acq_bin_dur_percent",false }, {0x0009,0x00ea,"GEMS_PETD_01",VR::SL,VM::VM1,"3D Filter flag",false }, {0x0009,0x00eb,"GEMS_PETD_01",VR::FL,VM::VM1,"3D Filter cutoff",false }, {0x0009,0x00ec,"GEMS_PETD_01",VR::SL,VM::VM1,"3D Filter order",false }, {0x0009,0x00f0,"GEMS_PETD_01",VR::UI,VM::VM1,"Reformat group",false }, {0x0009,0x00f1,"GEMS_PETD_01",VR::SL,VM::VM1,"PET prompt gamma",false }, {0x0009,0x00f2,"GEMS_PETD_01",VR::UI,VM::VM1,"PET tracerInjectionUID",false }, {0x0009,0x00f6,"GEMS_PETD_01",VR::SL,VM::VM1,"PET Q Static ScanMode",false }, {0x0009,0x00f7,"GEMS_PETD_01",VR::SL,VM::VM1,"PET Q Static Frame",false }, {0x0009,0x00f3,"GEMS_PETD_01",VR::FL,VM::VM1,"Blood Glucose Level",false }, {0x0009,0x00f4,"GEMS_PETD_01",VR::SL,VM::VM1,"IsPatientDiabetic",false }, {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 }, {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 }, {0x0011,0x0004,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance ROI.compatible_version",false }, {0x0011,0x0005,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance ROI.software_version",false }, {0x0011,0x0006,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance ROI.roi_name",false }, {0x0011,0x0007,"GEMS_PETD_01",VR::DT,VM::VM1,"GE Advance ROI.roi_datetime",false }, {0x0011,0x0008,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance ROI.roi_type",false }, {0x0011,0x0009,"GEMS_PETD_01",VR::FL,VM::VM1,"GE Advance ROI.center_x",false }, {0x0011,0x000a,"GEMS_PETD_01",VR::FL,VM::VM1,"GE Advance ROI.center_y",false }, {0x0011,0x000b,"GEMS_PETD_01",VR::FL,VM::VM1,"GE Advance ROI.width",false }, {0x0011,0x000c,"GEMS_PETD_01",VR::FL,VM::VM1,"GE Advance ROI.height",false }, {0x0011,0x000d,"GEMS_PETD_01",VR::FL,VM::VM1,"GE Advance ROI.angle",false }, {0x0011,0x000e,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance ROI.number_of_points",false }, {0x0011,0x000f,"GEMS_PETD_01",VR::OB,VM::VM1,"GE Advance ROI.roi_data",false }, {0x0011,0x0010,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance ROI.roi_size",false }, {0x0011,0x0011,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance ROI.color",false }, {0x0011,0x0012,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance ROI.line_type",false }, {0x0011,0x0013,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance ROI.line_width",false }, {0x0011,0x0014,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance ROI.roi_number",false }, {0x0011,0x0015,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance ROI.convex",false }, {0x0011,0x0016,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance ROI.atten_corr_flag",false }, {0x0011,0x0018,"GEMS_PETD_01",VR::OB,VM::VM1,"?",false }, {0x0013,0x0001,"GEMS_PETD_01",VR::SQ,VM::VM1,"GE Advance Annotation Sequence",false }, {0x0013,0x0002,"GEMS_PETD_01",VR::UI,VM::VM1,"GE Advance Annotation.annotation_id",false }, {0x0013,0x0003,"GEMS_PETD_01",VR::UI,VM::VM1,"GE Advance Annotation.image_id",false }, {0x0013,0x0004,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance Annotation.compatible_version",false }, {0x0013,0x0005,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance Annotation.software_version",false }, {0x0013,0x0006,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Annotation.type",false }, {0x0013,0x0007,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance Annotation.font_name",false }, {0x0013,0x0008,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance Annotation.font_size",false }, {0x0013,0x0009,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance Annotation.foreground_color",false }, {0x0013,0x000a,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance Annotation.background_color",false }, {0x0013,0x000b,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Annotation.coordinate_system",false }, {0x0013,0x000c,"GEMS_PETD_01",VR::FL,VM::VM1,"GE Advance Annotation.start_x",false }, {0x0013,0x000d,"GEMS_PETD_01",VR::FL,VM::VM1,"GE Advance Annotation.start_y",false }, {0x0013,0x000e,"GEMS_PETD_01",VR::FL,VM::VM1,"GE Advance Annotation.end_x",false }, {0x0013,0x000f,"GEMS_PETD_01",VR::FL,VM::VM1,"GE Advance Annotation.end_y",false }, {0x0013,0x0010,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Annotation.start_symbol",false }, {0x0013,0x0011,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Annotation.end_symbol",false }, {0x0013,0x0012,"GEMS_PETD_01",VR::OB,VM::VM1,"GE Advance Annotation.annotation_data",false }, {0x0013,0x0013,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Annotation.annotation_size",false }, {0x0013,0x0014,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance Annotation.label_id",false }, {0x0015,0x003d,"GEMS_PETD_01",VR::UL,VM::VM1,"PET Sharp IR Flag",false }, {0x0015,0x003e,"GEMS_PETD_01",VR::UL,VM::VM1,"PET Scatter Limit",false }, {0x0015,0x003f,"GEMS_PETD_01",VR::SH,VM::VM1,"PET Q Static Recon",false }, {0x0015,0x0039,"GEMS_PETD_01",VR::SL,VM::VM1,"Event histogram Format",false }, {0x0015,0x003a,"GEMS_PETD_01",VR::SL,VM::VM1,"Number of Detector Rows",false }, {0x0015,0x003b,"GEMS_PETD_01",VR::SL,VM::VM1,"Number of Detector Columns",false }, {0x0015,0x001a,"GEMS_PETD_01",VR::SL,VM::VM1,"Physio Gating Type",false }, {0x0015,0x001b,"GEMS_PETD_01",VR::SL,VM::VM1,"Total Number of Bins",false }, {0x0015,0x001d,"GEMS_PETD_01",VR::SL,VM::VM1,"Phase Matched Series",false }, {0x0015,0x001e,"GEMS_PETD_01",VR::SL,VM::VM1,"CTAC Percent Value",false }, {0x0015,0x003c,"GEMS_PETD_01",VR::US,VM::VM1,"Recon Matrix Size",false }, {0x0015,0x001f,"GEMS_PETD_01",VR::UL,VM::VM1,"PET Recon Parameters Exists",false }, {0x0015,0x0020,"GEMS_PETD_01",VR::SL,VM::VM1,"First Packet Number",false }, {0x0015,0x0021,"GEMS_PETD_01",VR::FL,VM::VM1,"IR Loop Filter Ratio",false }, {0x0015,0x0022,"GEMS_PETD_01",VR::FL,VM::VM1,"IR Loop Filter Correction",false }, {0x0015,0x0023,"GEMS_PETD_01",VR::UL,VM::VM1,"BP3d Filter FlagU",false }, {0x0015,0x0024,"GEMS_PETD_01",VR::FL,VM::VM1,"BP3d Filter CutoffU",false }, {0x0015,0x0025,"GEMS_PETD_01",VR::SL,VM::VM1,"BP3d Filter OrderU",false }, {0x0015,0x0026,"GEMS_PETD_01",VR::UL,VM::VM1,"BP3d Filter FlagV",false }, {0x0015,0x0027,"GEMS_PETD_01",VR::FL,VM::VM1,"BP3d Filter OrderV",false }, {0x0015,0x0028,"GEMS_PETD_01",VR::SL,VM::VM1,"BP3d Filter CutoffV",false }, {0x0015,0x0029,"GEMS_PETD_01",VR::UL,VM::VM1,"Decay Flag",false }, {0x0015,0x002e,"GEMS_PETD_01",VR::UL,VM::VM1,"Image filter 3d flag",false }, {0x0015,0x002f,"GEMS_PETD_01",VR::UL,VM::VM1,"WCC Cal Flag",false }, {0x0015,0x0030,"GEMS_PETD_01",VR::UL,VM::VM1,"Emission Scatter Flag",false }, {0x0015,0x0031,"GEMS_PETD_01",VR::UL,VM::VM1,"Recon Algorithm",false }, {0x0015,0x0032,"GEMS_PETD_01",VR::UL,VM::VM1,"Normalization Flag",false }, {0x0015,0x0033,"GEMS_PETD_01",VR::UL,VM::VM1,"Emission Deadtime Flag",false }, {0x0015,0x0034,"GEMS_PETD_01",VR::UL,VM::VM1,"Emission Random Flag",false }, {0x0015,0x0035,"GEMS_PETD_01",VR::UL,VM::VM1,"Blank Scan Flag",false }, {0x0015,0x0036,"GEMS_PETD_01",VR::UL,VM::VM1,"?",false }, {0x0015,0x0037,"GEMS_PETD_01",VR::UL,VM::VM1,"Trans Deadtime Flag",false }, {0x0015,0x0038,"GEMS_PETD_01",VR::UL,VM::VM1,"Natural Logarithm Flag",false }, {0x0017,0x0001,"GEMS_PETD_01",VR::UI,VM::VM1,"PET correction_cal_id",false }, {0x0017,0x0002,"GEMS_PETD_01",VR::SH,VM::VM1,"PET compatible_version",false }, {0x0017,0x0003,"GEMS_PETD_01",VR::SH,VM::VM1,"PET software_version",false }, {0x0017,0x0004,"GEMS_PETD_01",VR::DT,VM::VM1,"PET cal_datetime",false }, {0x0017,0x0005,"GEMS_PETD_01",VR::LO,VM::VM1,"PET cal_description",false }, {0x0017,0x0006,"GEMS_PETD_01",VR::SL,VM::VM1,"PET cal_type",false }, {0x0017,0x0007,"GEMS_PETD_01",VR::ST,VM::VM1,"PET where_is_corr",false }, {0x0017,0x0008,"GEMS_PETD_01",VR::SL,VM::VM1,"PET corr_file_size",false }, {0x0017,0x0009,"GEMS_PETD_01",VR::LO,VM::VM1,"PET scan_id",false }, {0x0017,0x000a,"GEMS_PETD_01",VR::DT,VM::VM1,"PET scan_datetime",false }, {0x0017,0x000b,"GEMS_PETD_01",VR::LO,VM::VM1,"PET norm_2d_cal_id",false }, {0x0017,0x000c,"GEMS_PETD_01",VR::SH,VM::VM1,"PET hosp_identifier",false }, {0x0017,0x000d,"GEMS_PETD_01",VR::SL,VM::VM1,"PET archived",false }, {0x0019,0x0001,"GEMS_PETD_01",VR::UI,VM::VM1,"PET wc_cal_id",false }, {0x0019,0x0002,"GEMS_PETD_01",VR::SH,VM::VM1,"PET compatible_version",false }, {0x0019,0x0003,"GEMS_PETD_01",VR::SH,VM::VM1,"PET software_version",false }, {0x0019,0x0004,"GEMS_PETD_01",VR::DT,VM::VM1,"PET cal_datetime",false }, {0x0019,0x0005,"GEMS_PETD_01",VR::SL,VM::VM1,"PET cal_type",false }, {0x0019,0x0006,"GEMS_PETD_01",VR::LO,VM::VM1,"PET cal_description",false }, {0x0019,0x0007,"GEMS_PETD_01",VR::LO,VM::VM1,"PET cal_hardware",false }, {0x0019,0x0008,"GEMS_PETD_01",VR::OB,VM::VM1,"PET coefficients",false }, {0x0019,0x0009,"GEMS_PETD_01",VR::FL,VM::VM1,"PET activity_factor_hr",false }, {0x0019,0x000a,"GEMS_PETD_01",VR::FL,VM::VM1,"PET activity_factor_hs",false }, {0x0019,0x000b,"GEMS_PETD_01",VR::FL,VM::VM1,"PET activity_factor_3d",false }, {0x0019,0x000c,"GEMS_PETD_01",VR::LO,VM::VM1,"PET scan_id",false }, {0x0019,0x000d,"GEMS_PETD_01",VR::DT,VM::VM1,"PET scan_datetime",false }, {0x0019,0x000e,"GEMS_PETD_01",VR::SH,VM::VM1,"PET hosp_identifier",false }, {0x0019,0x000f,"GEMS_PETD_01",VR::FL,VM::VM1,"PET meas_activity",false }, {0x0019,0x0010,"GEMS_PETD_01",VR::DT,VM::VM1,"PET meas_datetime",false }, {0x0019,0x0011,"GEMS_PETD_01",VR::SL,VM::VM1,"PET axial_filter_3d",false }, {0x0019,0x0012,"GEMS_PETD_01",VR::FL,VM::VM1,"PET axial_cutoff_3d",false }, {0x0019,0x0013,"GEMS_PETD_01",VR::SL,VM::VM1,"PET default_flag",false }, {0x0019,0x0014,"GEMS_PETD_01",VR::SL,VM::VM1,"PET archived",false }, {0x0019,0x0015,"GEMS_PETD_01",VR::SL,VM::VM1,"PET wc_cal_rec_method",false }, {0x0019,0x0016,"GEMS_PETD_01",VR::SL,VM::VM1,"PET activity_factor_2d",false }, {0x0019,0x0017,"GEMS_PETD_01",VR::SL,VM::VM1,"PET isotope",false }, {0x0021,0x0001,"GEMS_PETD_01",VR::US,VM::VM1,"PET raw_data_type",false }, {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 }, {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 }, {0x5001,0x0004,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Curve.statistics_type",false }, {0x5001,0x0005,"GEMS_PETD_01",VR::LT,VM::VM1,"GE Advance Curve.how_derived",false }, {0x5001,0x0006,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Curve.how_derived_size",false }, {0x5001,0x0007,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Curve.multi_patient",false }, {0x5001,0x0008,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Curve.deadtime",false }, {0x5003,0x0001,"GEMS_PETD_01",VR::SQ,VM::VM1,"GE Advance Graph Sequence",false }, {0x5003,0x0002,"GEMS_PETD_01",VR::UI,VM::VM1,"GE Advance Graph.graph_id",false }, {0x5003,0x0003,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance Graph.compatible_version",false }, {0x5003,0x0004,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance Graph.software_version",false }, {0x5003,0x0005,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance Graph.title",false }, {0x5003,0x0006,"GEMS_PETD_01",VR::DT,VM::VM1,"GE Advance Graph.graph_datetime",false }, {0x5003,0x0007,"GEMS_PETD_01",VR::ST,VM::VM1,"GE Advance Graph.graph_description",false }, {0x5003,0x0008,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance Graph.title_font_name",false }, {0x5003,0x0009,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance Graph.title_font_size",false }, {0x5003,0x000a,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance Graph.footer",false }, {0x5003,0x000b,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance Graph.footer_font_size",false }, {0x5003,0x000c,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance Graph.foreground_color",false }, {0x5003,0x000d,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance Graph.background_color",false }, {0x5003,0x000e,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Graph.graph_border",false }, {0x5003,0x000f,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Graph.graph_width",false }, {0x5003,0x0010,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Graph.graph_height",false }, {0x5003,0x0011,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Graph.grid",false }, {0x5003,0x0012,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance Graph.label_font_name",false }, {0x5003,0x0013,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance Graph.label_font_size",false }, {0x5003,0x0014,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance Graph.axes_color",false }, {0x5003,0x0015,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance Graph.x_axis_label",false }, {0x5003,0x0016,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Graph.x_axis_units",false }, {0x5003,0x0017,"GEMS_PETD_01",VR::FL,VM::VM1,"GE Advance Graph.x_major_tics",false }, {0x5003,0x0018,"GEMS_PETD_01",VR::FL,VM::VM1,"GE Advance Graph.x_axis_min",false }, {0x5003,0x0019,"GEMS_PETD_01",VR::FL,VM::VM1,"GE Advance Graph.x_axis_max",false }, {0x5003,0x001a,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance Graph.y_axis_label",false }, {0x5003,0x001b,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Graph.y_axis_units",false }, {0x5003,0x001c,"GEMS_PETD_01",VR::FL,VM::VM1,"GE Advance Graph.y_major_tics",false }, {0x5003,0x001d,"GEMS_PETD_01",VR::FL,VM::VM1,"GE Advance Graph.y_axis_min",false }, {0x5003,0x001e,"GEMS_PETD_01",VR::FL,VM::VM1,"GE Advance Graph.y_axis_max",false }, {0x5003,0x001f,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance Graph.legend_font_name",false }, {0x5003,0x0020,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance Graph.legend_font_size",false }, {0x5003,0x0021,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Graph.legend_location_x",false }, {0x5003,0x0022,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Graph.legend_location_y",false }, {0x5003,0x0023,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Graph.legend_width",false }, {0x5003,0x0024,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Graph.legend_height",false }, {0x5003,0x0025,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Graph.legend_border",false }, {0x5003,0x0026,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance Graph.multi_patient",false }, {0x5005,0x0001,"GEMS_PETD_01",VR::SQ,VM::VM1,"GE Advance CurvePresentation Sequence",false }, {0x5005,0x0002,"GEMS_PETD_01",VR::UI,VM::VM1,"GE Advance CurvePresentation.curvepresent_id",false }, {0x5005,0x0003,"GEMS_PETD_01",VR::UI,VM::VM1,"GE Advance CurvePresentation.graph_id",false }, {0x5005,0x0004,"GEMS_PETD_01",VR::UI,VM::VM1,"GE Advance CurvePresentation.curve_id",false }, {0x5005,0x0005,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance CurvePresentation.compatible_version",false }, {0x5005,0x0006,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance CurvePresentation.software_version",false }, {0x5005,0x0007,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance CurvePresentation.curve_label",false }, {0x5005,0x0008,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance CurvePresentation.color",false }, {0x5005,0x0009,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance CurvePresentation.line_type",false }, {0x5005,0x000a,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance CurvePresentation.line_width",false }, {0x5005,0x000b,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance CurvePresentation.point_symbol",false }, {0x5005,0x000c,"GEMS_PETD_01",VR::SL,VM::VM1,"GE Advance CurvePresentation.point_symbol_dim",false }, {0x5005,0x000d,"GEMS_PETD_01",VR::LO,VM::VM1,"GE Advance CurvePresentation.point_color",false }, {0x0009,0x0060,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"Dodge End Diastolic Volume ml",false }, {0x0009,0x0061,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"Dodge End Systolic Volume ml",false }, {0x0009,0x0062,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"Dodge Stroke Volume ml",false }, {0x0009,0x0063,"GEMS_QVA_PHOTO_01",VR::IS,VM::VM1,"Dodge Ejection Fraction",false }, {0x0009,0x0064,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"Simpson End Diastolic Volume ml",false }, {0x0009,0x0065,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"Simpson End Systolic Volume ml",false }, {0x0009,0x0066,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"Simpson Stroke Volume ml",false }, {0x0009,0x0067,"GEMS_QVA_PHOTO_01",VR::IS,VM::VM1,"Simpson Ejection Fraction",false }, {0x0009,0x0068,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"CFX Single Hypokinesia in Region",false }, {0x0009,0x0069,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"CFX Single Hyperkinesia in Opposite Region",false }, {0x0009,0x006a,"GEMS_QVA_PHOTO_01",VR::IS,VM::VM1,"CFX Single Total LV contour Percent",false }, {0x0009,0x006b,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"CFX Multiple Hypokinesia in Region",false }, {0x0009,0x006c,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"CFX Multiple Hyperkinesia in Opposite Region",false }, {0x0009,0x006d,"GEMS_QVA_PHOTO_01",VR::IS,VM::VM1,"CFX Multiple Total LV contour Percent",false }, {0x0009,0x006e,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"RCA Single Hypokinesia in Region",false }, {0x0009,0x006f,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"RCA Single Hyperkinesia in Opposite Region",false }, {0x0009,0x0070,"GEMS_QVA_PHOTO_01",VR::IS,VM::VM1,"RCA Single Total LV contour Percent",false }, {0x0009,0x0071,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"RCA Multiple Hypokinesia in Region",false }, {0x0009,0x0072,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"RCA Multiple Hyperkinesia in Opposite Region",false }, {0x0009,0x0073,"GEMS_QVA_PHOTO_01",VR::IS,VM::VM1,"RCA Multiple Total LV contour Percent",false }, {0x0009,0x0074,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"LAD Single Hypokinesia in Region",false }, {0x0009,0x0075,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"LAD Single Hyperkinesia in Opposite Region",false }, {0x0009,0x0076,"GEMS_QVA_PHOTO_01",VR::IS,VM::VM1,"LAD Single Total LV contour Percent",false }, {0x0009,0x0077,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"LAD Multiple Hypokinesia in Region",false }, {0x0009,0x0078,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"LAD Multiple Hyperkinesia in Opposite Region",false }, {0x0009,0x0079,"GEMS_QVA_PHOTO_01",VR::IS,VM::VM1,"LAD Multiple Total LV contour Percent",false }, {0x0009,0x007a,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"Dodge End Diastolic Volume ml/m2",false }, {0x0009,0x007c,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"Dodge End Systolic Volume ml/m2",false }, {0x0009,0x007e,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"Dodge Stroke Volume ml/m2",false }, {0x0009,0x0080,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"Simpson End Diastolic Volume ml/m2",false }, {0x0009,0x0082,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"Simpson End Systolic Volume ml/m2",false }, {0x0009,0x0084,"GEMS_QVA_PHOTO_01",VR::FL,VM::VM1,"Simpson Stroke Volume ml/m2",false }, {0x0021,0x0003,"GEMS_RELA_01",VR::SS,VM::VM1,"Series from which Prescribed",false }, {0x0021,0x0005,"GEMS_RELA_01",VR::SH,VM::VM1,"Genesis Version - now",false }, {0x0021,0x0007,"GEMS_RELA_01",VR::UL,VM::VM1,"Series Record checksum",false }, {0x0021,0x0015,"GEMS_RELA_01",VR::US,VM::VM1,"?",false }, {0x0021,0x0016,"GEMS_RELA_01",VR::SS,VM::VM1,"?",false }, {0x0021,0x0018,"GEMS_RELA_01",VR::SH,VM::VM1,"Genesis version - Now",false }, {0x0021,0x0019,"GEMS_RELA_01",VR::UL,VM::VM1,"Acq recon record checksum",false }, {0x0021,0x0020,"GEMS_RELA_01",VR::DS,VM::VM1,"Table start location",false }, {0x0021,0x0035,"GEMS_RELA_01",VR::SS,VM::VM1,"Series from which prescribed",false }, {0x0021,0x0036,"GEMS_RELA_01",VR::SS,VM::VM1,"Image from which prescribed",false }, {0x0021,0x0037,"GEMS_RELA_01",VR::SS,VM::VM1,"Screen Format",false }, {0x0021,0x004a,"GEMS_RELA_01",VR::LO,VM::VM1,"Anatomical reference for scout",false }, {0x0021,0x004e,"GEMS_RELA_01",VR::US,VM::VM1,"?",false }, {0x0021,0x004f,"GEMS_RELA_01",VR::SS,VM::VM1,"Locations in acquisition",false }, {0x0021,0x0050,"GEMS_RELA_01",VR::SS,VM::VM1,"Graphically prescribed",false }, {0x0021,0x0051,"GEMS_RELA_01",VR::DS,VM::VM1,"Rotation from source x rot",false }, {0x0021,0x0052,"GEMS_RELA_01",VR::DS,VM::VM1,"Rotation from source y rot",false }, {0x0021,0x0053,"GEMS_RELA_01",VR::DS,VM::VM1,"Rotation from source z rot",false }, {0x0021,0x0054,"GEMS_RELA_01",VR::SH,VM::VM3,"Image position",false }, {0x0021,0x0055,"GEMS_RELA_01",VR::SH,VM::VM6,"Image orientation",false }, {0x0021,0x0056,"GEMS_RELA_01",VR::SL,VM::VM1,"Num 3D slabs",false }, {0x0021,0x0057,"GEMS_RELA_01",VR::SL,VM::VM1,"Locs per 3D slab",false }, {0x0021,0x0058,"GEMS_RELA_01",VR::SL,VM::VM1,"Overlaps",false }, {0x0021,0x0059,"GEMS_RELA_01",VR::SL,VM::VM1,"Image Filtering 0.5/0.2T",false }, {0x0021,0x005a,"GEMS_RELA_01",VR::SL,VM::VM1,"Diffusion direction",false }, {0x0021,0x005b,"GEMS_RELA_01",VR::DS,VM::VM1,"Tagging Flip Angle",false }, {0x0021,0x005c,"GEMS_RELA_01",VR::DS,VM::VM1,"Tagging Orientation",false }, {0x0021,0x005d,"GEMS_RELA_01",VR::DS,VM::VM1,"Tag Spacing",false }, {0x0021,0x005e,"GEMS_RELA_01",VR::DS,VM::VM1,"RTIA_timer",false }, {0x0021,0x005f,"GEMS_RELA_01",VR::DS,VM::VM1,"Fps",false }, {0x0021,0x0070,"GEMS_RELA_01",VR::LT,VM::VM1,"?",false }, {0x0021,0x0071,"GEMS_RELA_01",VR::LT,VM::VM1,"?",false }, {0x0021,0x0081,"GEMS_RELA_01",VR::DS,VM::VM1,"Auto window/level alpha",false }, {0x0021,0x0082,"GEMS_RELA_01",VR::DS,VM::VM1,"Auto window/level beta",false }, {0x0021,0x0083,"GEMS_RELA_01",VR::DS,VM::VM1,"Auto window/level window",false }, {0x0021,0x0084,"GEMS_RELA_01",VR::DS,VM::VM1,"Auto window/level level",false }, {0x0021,0x0090,"GEMS_RELA_01",VR::SS,VM::VM1,"Tube focal spot position",false }, {0x0021,0x0091,"GEMS_RELA_01",VR::SS,VM::VM1,"Biopsy position",false }, {0x0021,0x0092,"GEMS_RELA_01",VR::FL,VM::VM1,"Biopsy T location",false }, {0x0021,0x0093,"GEMS_RELA_01",VR::FL,VM::VM1,"Biopsy ref location",false }, {0x0249,0x0011,"GEMS_RTEN_01",VR::DA,VM::VM1,"Plan Creation Date",false }, {0x0249,0x0013,"GEMS_RTEN_01",VR::TM,VM::VM1,"Plan Creation Time",false }, {0x0249,0x0014,"GEMS_RTEN_01",VR::PN,VM::VM1,"Operator Name",false }, {0x0249,0x0016,"GEMS_RTEN_01",VR::LO,VM::VM1,"Plan Comment",false }, {0x0249,0x0018,"GEMS_RTEN_01",VR::SQ,VM::VM1,"Plan Image Sequence",false }, {0x0249,0x001a,"GEMS_RTEN_01",VR::LO,VM::VM1,"Exam/Series/Image Identifier",false }, {0x0249,0x001b,"GEMS_RTEN_01",VR::IS,VM::VM1,"Additional Image Identifier",false }, {0x0249,0x001c,"GEMS_RTEN_01",VR::CS,VM::VM1,"Build Resolution",false }, {0x0249,0x0020,"GEMS_RTEN_01",VR::SQ,VM::VM1,"Structure Sequence",false }, {0x0249,0x0022,"GEMS_RTEN_01",VR::SH,VM::VM1,"Structure Name",false }, {0x0249,0x0024,"GEMS_RTEN_01",VR::CS,VM::VM1,"Structure Type",false }, {0x0249,0x0028,"GEMS_RTEN_01",VR::CS,VM::VM1,"Structure Color",false }, {0x0249,0x0030,"GEMS_RTEN_01",VR::SQ,VM::VM1,"Slab Sequence",false }, {0x0249,0x0032,"GEMS_RTEN_01",VR::SQ,VM::VM1,"Slab Image Sequence",false }, {0x0249,0x0036,"GEMS_RTEN_01",VR::DS,VM::VM1,"Z Plus Thickness",false }, {0x0249,0x0038,"GEMS_RTEN_01",VR::DS,VM::VM1,"Z Minus Thickness",false }, {0x0249,0x003a,"GEMS_RTEN_01",VR::DS,VM::VM3_n,"Slab Shape",false }, {0x0249,0x0040,"GEMS_RTEN_01",VR::SQ,VM::VM1,"Marker Sequence",false }, {0x0249,0x0042,"GEMS_RTEN_01",VR::SH,VM::VM1,"Marker Name",false }, {0x0249,0x0044,"GEMS_RTEN_01",VR::CS,VM::VM1,"Marker Color",false }, {0x0249,0x0046,"GEMS_RTEN_01",VR::DS,VM::VM3,"Marker Position",false }, {0x0249,0x0050,"GEMS_RTEN_01",VR::SQ,VM::VM1,"Beam Group Sequence",false }, {0x0249,0x0051,"GEMS_RTEN_01",VR::SH,VM::VM1,"Group Name",false }, {0x0249,0x0052,"GEMS_RTEN_01",VR::CS,VM::VM1_n,"Group Properties",false }, {0x0249,0x0054,"GEMS_RTEN_01",VR::SQ,VM::VM1,"Beam Sequence",false }, {0x0249,0x0060,"GEMS_RTEN_01",VR::SQ,VM::VM1,"Machine Reference Sequence",false }, {0x0249,0x0062,"GEMS_RTEN_01",VR::SH,VM::VM1,"Machine Name",false }, {0x0249,0x0064,"GEMS_RTEN_01",VR::SH,VM::VM1,"Beam Name",false }, {0x0249,0x0066,"GEMS_RTEN_01",VR::CS,VM::VM1,"Particle Type",false }, {0x0249,0x0068,"GEMS_RTEN_01",VR::DS,VM::VM1,"Nominal Particle Energy",false }, {0x0249,0x0070,"GEMS_RTEN_01",VR::SQ,VM::VM1,"Block Sequence",false }, {0x0249,0x0072,"GEMS_RTEN_01",VR::LO,VM::VM1,"Block Name",false }, {0x0249,0x0074,"GEMS_RTEN_01",VR::DS,VM::VM2_n,"Block Shape",false }, {0x0249,0x0080,"GEMS_RTEN_01",VR::SQ,VM::VM1,"Cutout Sequence",false }, {0x0249,0x0082,"GEMS_RTEN_01",VR::LO,VM::VM1,"Cutout Name",false }, {0x0249,0x0084,"GEMS_RTEN_01",VR::DS,VM::VM2_n,"Cutout Shape",false }, {0x0249,0x0090,"GEMS_RTEN_01",VR::SH,VM::VM1,"Collimator Name",false }, {0x0249,0x0092,"GEMS_RTEN_01",VR::CS,VM::VM1,"Collimator Type",false }, {0x0249,0x00a0,"GEMS_RTEN_01",VR::SQ,VM::VM1,"Dynamic Segment Sequence",false }, {0x0249,0x00a2,"GEMS_RTEN_01",VR::DS,VM::VM1,"Table Angle",false }, {0x0249,0x00a4,"GEMS_RTEN_01",VR::DS,VM::VM1,"Gantry Angle",false }, {0x0249,0x00a6,"GEMS_RTEN_01",VR::DS,VM::VM1,"Collimator Angle",false }, {0x0249,0x00a8,"GEMS_RTEN_01",VR::DS,VM::VM3,"Isocenter Position",false }, {0x0249,0x00a9,"GEMS_RTEN_01",VR::DS,VM::VM1,"Source-Surface Distance",false }, {0x0249,0x00aa,"GEMS_RTEN_01",VR::DS,VM::VM1,"X Symmetric Opening",false }, {0x0249,0x00ac,"GEMS_RTEN_01",VR::DS,VM::VM1,"Y Symmetric Opening",false }, {0x0249,0x00ae,"GEMS_RTEN_01",VR::DS,VM::VM1,"X Positive Jaw Position",false }, {0x0249,0x00b0,"GEMS_RTEN_01",VR::DS,VM::VM1,"X Negative Jaw Position",false }, {0x0249,0x00b2,"GEMS_RTEN_01",VR::DS,VM::VM1,"Y Positive Jaw Position",false }, {0x0249,0x00b4,"GEMS_RTEN_01",VR::DS,VM::VM1,"Y Negative Jaw Position",false }, {0x0249,0x00b6,"GEMS_RTEN_01",VR::DS,VM::VM2_n,"Leaf Positions",false }, {0x0249,0x00d0,"GEMS_RTEN_01",VR::CS,VM::VM1,"Treatment Position",false }, {0x0045,0x0004,"GEMS_SENO_02",VR::CS,VM::VM1,"AES",false }, {0x0045,0x0006,"GEMS_SENO_02",VR::DS,VM::VM1,"Stereo angle",false }, {0x0045,0x0009,"GEMS_SENO_02",VR::DS,VM::VM1,"Real Magnification Factor",false }, {0x0045,0x000b,"GEMS_SENO_02",VR::CS,VM::VM1,"Senograph Type",false }, {0x0045,0x000c,"GEMS_SENO_02",VR::DS,VM::VM1,"Integration Time",false }, {0x0045,0x000d,"GEMS_SENO_02",VR::DS,VM::VM1,"ROI Origin X and Y",false }, {0x0045,0x0011,"GEMS_SENO_02",VR::DS,VM::VM2,"Receptor Size cm X and Y",false }, {0x0045,0x0012,"GEMS_SENO_02",VR::IS,VM::VM2,"Receptor Size Pixels X and Y",false }, {0x0045,0x0013,"GEMS_SENO_02",VR::ST,VM::VM1,"Screen",false }, {0x0045,0x0014,"GEMS_SENO_02",VR::DS,VM::VM1,"Pixel Pitch Microns",false }, {0x0045,0x0015,"GEMS_SENO_02",VR::IS,VM::VM1,"Pixel Depth Bits",false }, {0x0045,0x0016,"GEMS_SENO_02",VR::IS,VM::VM2,"Binning Factor X and Y",false }, {0x0045,0x001b,"GEMS_SENO_02",VR::CS,VM::VM1,"Clinical View",false }, {0x0045,0x001d,"GEMS_SENO_02",VR::DS,VM::VM1,"Mean Of Raw Gray Levels",false }, {0x0045,0x001e,"GEMS_SENO_02",VR::DS,VM::VM1,"Mean Of Offset Gray Levels",false }, {0x0045,0x001f,"GEMS_SENO_02",VR::DS,VM::VM1,"Mean Of Corrected Gray Levels",false }, {0x0045,0x0020,"GEMS_SENO_02",VR::DS,VM::VM1,"Estimated Anat mean",false }, {0x0045,0x0021,"GEMS_SENO_02",VR::DS,VM::VM1,"Mean Of Log Region Gray Levels",false }, {0x0045,0x0022,"GEMS_SENO_02",VR::DS,VM::VM1,"Standard Deviation Of Raw Gray Levels",false }, {0x0045,0x0023,"GEMS_SENO_02",VR::DS,VM::VM1,"Standard Deviation Of Corrected Gray Levels",false }, {0x0045,0x0024,"GEMS_SENO_02",VR::DS,VM::VM1,"Standard Deviation Of Region Gray Levels",false }, {0x0045,0x0025,"GEMS_SENO_02",VR::DS,VM::VM1,"Standard Deviation Of Log Region Gray Levels",false }, {0x0045,0x0026,"GEMS_SENO_02",VR::OB,VM::VM1,"MAO Buffer",false }, {0x0045,0x0027,"GEMS_SENO_02",VR::IS,VM::VM1,"Set Number",false }, {0x0045,0x0028,"GEMS_SENO_02",VR::CS,VM::VM1,"WindowingType (LINEAR or GAMMA)",false }, {0x0045,0x0029,"GEMS_SENO_02",VR::DS,VM::VM2,"Windowing parameters",false }, {0x0045,0x002a,"GEMS_SENO_02",VR::IS,VM::VM1,"2DLocX",false }, {0x0045,0x002b,"GEMS_SENO_02",VR::IS,VM::VM1,"2DLocY",false }, {0x0045,0x0039,"GEMS_SENO_02",VR::US,VM::VM1,"Vignette Rows",false }, {0x0045,0x003a,"GEMS_SENO_02",VR::US,VM::VM1,"Vignette Columns",false }, {0x0045,0x003b,"GEMS_SENO_02",VR::US,VM::VM1,"Vignette Bits Allocated",false }, {0x0045,0x003c,"GEMS_SENO_02",VR::US,VM::VM1,"Vignette Bits Stored",false }, {0x0045,0x003d,"GEMS_SENO_02",VR::US,VM::VM1,"Vignette High Bit",false }, {0x0045,0x003e,"GEMS_SENO_02",VR::US,VM::VM1,"Vignette Pixel Representation",false }, {0x0045,0x003f,"GEMS_SENO_02",VR::OB,VM::VM1,"Vignette Pixel Data",false }, {0x0045,0x0049,"GEMS_SENO_02",VR::DS,VM::VM1,"Radiological Thickness",false }, {0x0045,0x0050,"GEMS_SENO_02",VR::UI,VM::VM1,"CR Instance UID",false }, {0x0045,0x0051,"GEMS_SENO_02",VR::UI,VM::VM1,"CR series UID",false }, {0x0045,0x0052,"GEMS_SENO_02",VR::IS,VM::VM1,"Raw Diagnostic Low",false }, {0x0045,0x0053,"GEMS_SENO_02",VR::IS,VM::VM1,"Raw Diagnostic High",false }, {0x0045,0x0054,"GEMS_SENO_02",VR::DS,VM::VM1,"Exponent",false }, {0x0045,0x0055,"GEMS_SENO_02",VR::IS,VM::VM1_n,"A Coefficients",false }, {0x0045,0x0056,"GEMS_SENO_02",VR::DS,VM::VM1,"Noise Reduction Sensitivity",false }, {0x0045,0x0057,"GEMS_SENO_02",VR::DS,VM::VM1,"Noise Reduction Threshold",false }, {0x0045,0x0058,"GEMS_SENO_02",VR::DS,VM::VM1,"mu",false }, {0x0045,0x0059,"GEMS_SENO_02",VR::IS,VM::VM1,"Threshold",false }, {0x0045,0x0060,"GEMS_SENO_02",VR::IS,VM::VM4,"Breast ROI X",false }, {0x0045,0x0061,"GEMS_SENO_02",VR::IS,VM::VM4,"Breast ROI Y",false }, {0x0045,0x0062,"GEMS_SENO_02",VR::IS,VM::VM1,"User Window Center",false }, {0x0045,0x0063,"GEMS_SENO_02",VR::IS,VM::VM1,"User Window Width",false }, {0x0045,0x0064,"GEMS_SENO_02",VR::IS,VM::VM1,"Segm Threshold",false }, {0x0045,0x0065,"GEMS_SENO_02",VR::IS,VM::VM1,"Detector Entrance Dose",false }, {0x0045,0x0066,"GEMS_SENO_02",VR::IS,VM::VM1,"Asymmetrical Collimation Information",false }, {0x0045,0x0067,"GEMS_SENO_02",VR::DS,VM::VM3_4,"LUT Asymmetry parameter",false }, {0x0045,0x0068,"GEMS_SENO_02",VR::CS,VM::VM3,"Acquisition Mode",false }, {0x0045,0x0069,"GEMS_SENO_02",VR::IS,VM::VM1,"Collimator Rotation",false }, {0x0045,0x0070,"GEMS_SENO_02",VR::DS,VM::VM1,"Brightness Adjustment",false }, {0x0045,0x0071,"GEMS_SENO_02",VR::DS,VM::VM1,"Contrast Adjustment",false }, {0x0045,0x0072,"GEMS_SENO_02",VR::DS,VM::VM1,"Collimator Width",false }, {0x0045,0x0073,"GEMS_SENO_02",VR::DS,VM::VM1,"Collimator Height",false }, {0x0025,0x0006,"GEMS_SERS_01",VR::SS,VM::VM1,"Last pulse sequence used",false }, {0x0025,0x0007,"GEMS_SERS_01",VR::SL,VM::VM1,"Images in Series",false }, {0x0025,0x0010,"GEMS_SERS_01",VR::SL,VM::VM1,"Landmark Counter",false }, {0x0025,0x0011,"GEMS_SERS_01",VR::SS,VM::VM1,"Number of Acquisitions",false }, {0x0025,0x0014,"GEMS_SERS_01",VR::SL,VM::VM1,"Indicates no. of updates to header",false }, {0x0025,0x0017,"GEMS_SERS_01",VR::SL,VM::VM1,"Series Complete Flag",false }, {0x0025,0x0018,"GEMS_SERS_01",VR::SL,VM::VM1,"Number of images archived",false }, {0x0025,0x0019,"GEMS_SERS_01",VR::SL,VM::VM1,"Last image number used",false }, {0x0025,0x001a,"GEMS_SERS_01",VR::SH,VM::VM1,"Primary Receiver Suite and Host",false }, {0x0025,0x001b,"GEMS_SERS_01",VR::OB,VM::VM1,"Protocol Data Block (compressed)",false }, {0x0023,0x0001,"GEMS_STDY_01",VR::SL,VM::VM1,"Number of series in Study",false }, {0x0023,0x0002,"GEMS_STDY_01",VR::SL,VM::VM1,"Number of unarchived Series",false }, {0x0023,0x0010,"GEMS_STDY_01",VR::SS,VM::VM1,"Reference image field",false }, {0x0023,0x0050,"GEMS_STDY_01",VR::SS,VM::VM1,"Summary image",false }, {0x0023,0x0070,"GEMS_STDY_01",VR::FD,VM::VM1,"Start time(secs) in first axial",false }, {0x0023,0x0074,"GEMS_STDY_01",VR::SL,VM::VM1,"No. of updates to header",false }, {0x0023,0x007d,"GEMS_STDY_01",VR::SS,VM::VM1,"Indicates study has complete info (DICOM/genesis)",false }, {0x0023,0x0080,"GEMS_STDY_01",VR::SQ,VM::VM1,"Has MPPS related tags",false }, {0x6003,0x0005,"GEMS_Ultrasound_ImageGroup_001",VR::LT,VM::VM1_n,"GEMS Image Information",false }, {0x6003,0x0010,"GEMS_Ultrasound_ImageGroup_001",VR::SQ,VM::VM1,"GEMS Image Thumbnail Sequence",false }, {0x6003,0x0011,"GEMS_Ultrasound_ImageGroup_001",VR::OB,VM::VM1,"GEMS Thumbnail Pixel Data (uncompressed)",false }, {0x7fe1,0x0001,"GEMS_Ultrasound_MovieGroup_001",VR::SQ,VM::VM1,"?",false }, {0x7fe1,0x0002,"GEMS_Ultrasound_MovieGroup_001",VR::LO,VM::VM1,"US MovieGroup Value 0008 Name",false }, {0x7fe1,0x0003,"GEMS_Ultrasound_MovieGroup_001",VR::UL,VM::VM1,"?",false }, {0x7fe1,0x0008,"GEMS_Ultrasound_MovieGroup_001",VR::SQ,VM::VM1,"US MovieGroup Value 0008 Sequence",false }, {0x7fe1,0x0010,"GEMS_Ultrasound_MovieGroup_001",VR::SQ,VM::VM1,"?",false }, {0x7fe1,0x0012,"GEMS_Ultrasound_MovieGroup_001",VR::LO,VM::VM1,"US MovieGroup Value 0018 Name",false }, {0x7fe1,0x0018,"GEMS_Ultrasound_MovieGroup_001",VR::SQ,VM::VM1,"US MovieGroup Value 0018 Sequence",false }, {0x7fe1,0x0020,"GEMS_Ultrasound_MovieGroup_001",VR::SQ,VM::VM1,"?",false }, {0x7fe1,0x0024,"GEMS_Ultrasound_MovieGroup_001",VR::SH,VM::VM1,"US MovieGroup Value 0026 Name",false }, {0x7fe1,0x0026,"GEMS_Ultrasound_MovieGroup_001",VR::SQ,VM::VM1,"US MovieGroup Value 0026 Sequence",false }, {0x7fe1,0x0030,"GEMS_Ultrasound_MovieGroup_001",VR::LO,VM::VM1,"?",false }, {0x7fe1,0x0032,"GEMS_Ultrasound_MovieGroup_001",VR::UL,VM::VM1,"?",false }, {0x7fe1,0x0036,"GEMS_Ultrasound_MovieGroup_001",VR::SQ,VM::VM1,"?",false }, {0x7fe1,0x0037,"GEMS_Ultrasound_MovieGroup_001",VR::UL,VM::VM1,"US MovieGroup Number of Frames",false }, {0x7fe1,0x003a,"GEMS_Ultrasound_MovieGroup_001",VR::SQ,VM::VM1,"?",false }, {0x7fe1,0x003c,"GEMS_Ultrasound_MovieGroup_001",VR::FD,VM::VM1,"?",false }, {0x7fe1,0x0043,"GEMS_Ultrasound_MovieGroup_001",VR::OB,VM::VM1,"?",false }, {0x7fe1,0x0048,"GEMS_Ultrasound_MovieGroup_001",VR::FD,VM::VM1_2,"US MovieGroup Value Index",false }, {0x7fe1,0x0049,"GEMS_Ultrasound_MovieGroup_001",VR::UL,VM::VM1,"US MovieGroup Value UL/1",false }, {0x7fe1,0x0051,"GEMS_Ultrasound_MovieGroup_001",VR::FL,VM::VM1,"US MovieGroup Value FL/1",false }, {0x7fe1,0x0052,"GEMS_Ultrasound_MovieGroup_001",VR::FD,VM::VM1,"US MovieGroup Value FD/1",false }, {0x7fe1,0x0053,"GEMS_Ultrasound_MovieGroup_001",VR::UL,VM::VM1,"US MovieGroup Value UL/1",false }, {0x7fe1,0x0054,"GEMS_Ultrasound_MovieGroup_001",VR::SL,VM::VM1,"US MovieGroup Value SL/1",false }, {0x7fe1,0x0055,"GEMS_Ultrasound_MovieGroup_001",VR::OB,VM::VM1,"US MovieGroup Value OB/1",false }, {0x7fe1,0x0057,"GEMS_Ultrasound_MovieGroup_001",VR::LT,VM::VM1,"US MovieGroup Value LT/1",false }, {0x7fe1,0x0060,"GEMS_Ultrasound_MovieGroup_001",VR::OB,VM::VM1,"US MovieGroup Image Data",false }, {0x7fe1,0x0061,"GEMS_Ultrasound_MovieGroup_001",VR::OW,VM::VM1,"?",false }, {0x7fe1,0x0069,"GEMS_Ultrasound_MovieGroup_001",VR::OW,VM::VM1,"?",false }, {0x7fe1,0x0070,"GEMS_Ultrasound_MovieGroup_001",VR::SQ,VM::VM1,"US MovieGroup Dict",false }, {0x7fe1,0x0071,"GEMS_Ultrasound_MovieGroup_001",VR::UL,VM::VM1,"US MovieGroup Dict Index",false }, {0x7fe1,0x0072,"GEMS_Ultrasound_MovieGroup_001",VR::LO,VM::VM1,"US MovieGroup Dict Name",false }, {0x7fe1,0x0073,"GEMS_Ultrasound_MovieGroup_001",VR::SQ,VM::VM1,"?",false }, {0x7fe1,0x0074,"GEMS_Ultrasound_MovieGroup_001",VR::LO,VM::VM1,"?",false }, {0x7fe1,0x0075,"GEMS_Ultrasound_MovieGroup_001",VR::SQ,VM::VM1,"?",false }, {0x7fe1,0x0077,"GEMS_Ultrasound_MovieGroup_001",VR::FD,VM::VM1_n,"US MovieGroup Value FD/1-N",false }, {0x7fe1,0x0079,"GEMS_Ultrasound_MovieGroup_001",VR::SL,VM::VM1_n,"US MovieGroup Value SL/1-N",false }, {0x7fe1,0x0083,"GEMS_Ultrasound_MovieGroup_001",VR::SQ,VM::VM1,"?",false }, {0x7fe1,0x0084,"GEMS_Ultrasound_MovieGroup_001",VR::LO,VM::VM1,"US MovieGroup Value 0085 Name",false }, {0x7fe1,0x0085,"GEMS_Ultrasound_MovieGroup_001",VR::SQ,VM::VM1,"US MovieGroup Value 0085 Sequence",false }, {0x7fe1,0x0086,"GEMS_Ultrasound_MovieGroup_001",VR::SL,VM::VM4,"US MovieGroup Value SL/4",false }, {0x7fe1,0x0087,"GEMS_Ultrasound_MovieGroup_001",VR::FD,VM::VM4,"US MovieGroup Value FD/4",false }, {0x7fe1,0x0088,"GEMS_Ultrasound_MovieGroup_001",VR::FD,VM::VM2,"US MovieGroup Value FD/2",false }, {0x0057,0x0005,"GEMS_VXTLSTATE_001",VR::SQ,VM::VM1,"Volumes_info",false }, {0x0057,0x0006,"GEMS_VXTLSTATE_001",VR::SQ,VM::VM1,"Image_UIDs",false }, {0x0057,0x0007,"GEMS_VXTLSTATE_001",VR::DT,VM::VM1,"SUV_ScanTime",false }, {0x0057,0x0008,"GEMS_VXTLSTATE_001",VR::DT,VM::VM1,"SUV_AdministredTime",false }, {0x0057,0x0009,"GEMS_VXTLSTATE_001",VR::DT,VM::VM1,"SUV_MeasuredTime",false }, {0x0057,0x0010,"GEMS_VXTLSTATE_001",VR::DT,VM::VM1,"SUV_PostInjectedTime",false }, {0x0057,0x0011,"GEMS_VXTLSTATE_001",VR::FL,VM::VM1,"SUV_TracerActivity",false }, {0x0057,0x0012,"GEMS_VXTLSTATE_001",VR::FL,VM::VM1,"SUV_PostInjectedActivity",false }, {0x0057,0x0013,"GEMS_VXTLSTATE_001",VR::FL,VM::VM1,"SUV_HalfLife",false }, {0x0057,0x0014,"GEMS_VXTLSTATE_001",VR::LO,VM::VM1,"SState_Version",false }, {0x0057,0x0015,"GEMS_VXTLSTATE_001",VR::SQ,VM::VM1,"SegList_Seq",false }, {0x0057,0x0016,"GEMS_VXTLSTATE_001",VR::IS,VM::VM1,"SegList_Count",false }, {0x0057,0x0017,"GEMS_VXTLSTATE_001",VR::OB,VM::VM1,"SegList_List",false }, {0x0057,0x0018,"GEMS_VXTLSTATE_001",VR::LO,VM::VM1,"SegList_Name",false }, {0x0057,0x0019,"GEMS_VXTLSTATE_001",VR::LO,VM::VM1,"Volume_Filename",false }, {0x0057,0x0020,"GEMS_VXTLSTATE_001",VR::LO,VM::VM1,"SegList_Label",false }, {0x0057,0x0021,"GEMS_VXTLSTATE_001",VR::SQ,VM::VM1,"Bookmark_Seq",false }, {0x0057,0x0022,"GEMS_VXTLSTATE_001",VR::LT,VM::VM1,"Bookmark",false }, {0x0057,0x0023,"GEMS_VXTLSTATE_001",VR::FL,VM::VM3,"Cursor_position",false }, {0x0057,0x0024,"GEMS_VXTLSTATE_001",VR::UL,VM::VM3_n,"Color_Value_Field",false }, {0x0057,0x0025,"GEMS_VXTLSTATE_001",VR::IS,VM::VM1,"Count",false }, {0x0057,0x0026,"GEMS_VXTLSTATE_001",VR::SQ,VM::VM1,"Views_info",false }, {0x0057,0x0027,"GEMS_VXTLSTATE_001",VR::LT,VM::VM1,"View_Slot",false }, {0x0057,0x0028,"GEMS_VXTLSTATE_001",VR::IS,VM::VM1,"Wireframe_Size",false }, {0x0057,0x0029,"GEMS_VXTLSTATE_001",VR::UT,VM::VM1,"Wireframe",false }, {0x0057,0x0030,"GEMS_VXTLSTATE_001",VR::IS,VM::VM1,"Annotation_Size",false }, {0x0057,0x0031,"GEMS_VXTLSTATE_001",VR::LT,VM::VM1,"Annotation",false }, {0x0057,0x0032,"GEMS_VXTLSTATE_001",VR::IS,VM::VM1,"Slider_State",false }, {0x0057,0x0033,"GEMS_VXTLSTATE_001",VR::LO,VM::VM1,"Proto_Name",false }, {0x0057,0x0034,"GEMS_VXTLSTATE_001",VR::LO,VM::VM1,"Proto_Title",false }, {0x0057,0x0035,"GEMS_VXTLSTATE_001",VR::LO,VM::VM1,"Proto_FilmName",false }, {0x0057,0x0036,"GEMS_VXTLSTATE_001",VR::LO,VM::VM1,"Proto_Step",false }, {0x0057,0x0038,"GEMS_VXTLSTATE_001",VR::LT,VM::VM1,"SegList_Slots",false }, {0x0057,0x0039,"GEMS_VXTLSTATE_001",VR::IS,VM::VM1,"VT_Points_Size",false }, {0x0057,0x0040,"GEMS_VXTLSTATE_001",VR::LT,VM::VM1,"VT_Points",false }, {0x0057,0x0041,"GEMS_VXTLSTATE_001",VR::IS,VM::VM1,"VT_Meas_Size",false }, {0x0057,0x0042,"GEMS_VXTLSTATE_001",VR::LT,VM::VM1,"VT_Meas",false }, {0x0057,0x0043,"GEMS_VXTLSTATE_001",VR::IS,VM::VM1,"VT_Tree_Size",false }, {0x0057,0x0044,"GEMS_VXTLSTATE_001",VR::UT,VM::VM1,"VT_Tree",false }, {0x0057,0x0046,"GEMS_VXTLSTATE_001",VR::IS,VM::VM1,"VT_Preset_Size",false }, {0x0057,0x0047,"GEMS_VXTLSTATE_001",VR::LT,VM::VM1,"VT_Preset",false }, {0x0057,0x0048,"GEMS_VXTLSTATE_001",VR::IS,VM::VM1,"VT_State_Size",false }, {0x0057,0x0049,"GEMS_VXTLSTATE_001",VR::LT,VM::VM1,"VT_State",false }, {0x0057,0x0050,"GEMS_VXTLSTATE_001",VR::IS,VM::VM1,"Preferences_Size",false }, {0x0057,0x0051,"GEMS_VXTLSTATE_001",VR::LT,VM::VM1,"Preferences",false }, {0x0057,0x0052,"GEMS_VXTLSTATE_001",VR::IS,VM::VM1,"Volume_ZComb_Filter",false }, {0x0057,0x0053,"GEMS_VXTLSTATE_001",VR::IS,VM::VM1,"HTML_Page_Size",false }, {0x0057,0x0054,"GEMS_VXTLSTATE_001",VR::LT,VM::VM1,"HTML_Page",false }, {0x0057,0x0055,"GEMS_VXTLSTATE_001",VR::FL,VM::VM3,"Camera_Position",false }, {0x0057,0x0056,"GEMS_VXTLSTATE_001",VR::IS,VM::VM1,"Slider_Size",false }, {0x0057,0x0057,"GEMS_VXTLSTATE_001",VR::LT,VM::VM1,"Slider",false }, {0x0057,0x0058,"GEMS_VXTLSTATE_001",VR::LO,VM::VM1,"SegList_Pretty_Name",false }, {0x0047,0x0011,"GEMS_VXTL_USERDATA_01",VR::LT,VM::VM1,"?",false }, {0x0033,0x0008,"GEMS_XELPRV_01",VR::CS,VM::VM1,"Object Type",false }, {0x0033,0x0010,"GEMS_XELPRV_01",VR::SL,VM::VM1,"Modified",false }, {0x0033,0x0011,"GEMS_XELPRV_01",VR::LO,VM::VM1,"Name",false }, {0x0033,0x0014,"GEMS_XELPRV_01",VR::LO,VM::VM1,"StudyId",false }, {0x0033,0x0016,"GEMS_XELPRV_01",VR::LO,VM::VM1,"ProtocolDataUID",false }, {0x0033,0x0017,"GEMS_XELPRV_01",VR::SH,VM::VM1,"Date",false }, {0x0033,0x0018,"GEMS_XELPRV_01",VR::SH,VM::VM1,"Time",false }, {0x0033,0x0019,"GEMS_XELPRV_01",VR::UL,VM::VM1,"ProtocoldataFlags",false }, {0x0033,0x001a,"GEMS_XELPRV_01",VR::LO,VM::VM1,"ProtocolName",false }, {0x0033,0x001b,"GEMS_XELPRV_01",VR::LO,VM::VM1,"StudyId",false }, {0x0033,0x001c,"GEMS_XELPRV_01",VR::OB,VM::VM1,"BulkData",false }, {0x0033,0x001d,"GEMS_XELPRV_01",VR::SL,VM::VM1_n,"IntData",false }, {0x0033,0x001e,"GEMS_XELPRV_01",VR::FD,VM::VM1_n,"DoubleData",false }, {0x0033,0x001f,"GEMS_XELPRV_01",VR::OB,VM::VM1,"StringData",false }, {0x0033,0x0020,"GEMS_XELPRV_01",VR::OB,VM::VM1,"BulkDataFormat",false }, {0x0033,0x0021,"GEMS_XELPRV_01",VR::OB,VM::VM1,"IntDataFormat",false }, {0x0033,0x0022,"GEMS_XELPRV_01",VR::OB,VM::VM1,"DoubleDataFormat",false }, {0x0033,0x0023,"GEMS_XELPRV_01",VR::OB,VM::VM1,"StringDataFormat",false }, {0x0033,0x0024,"GEMS_XELPRV_01",VR::LT,VM::VM1,"Description",false }, {0x0033,0x0028,"GEMS_XELPRV_01",VR::LO,VM::VM1,"RTName",false }, {0x0033,0x0029,"GEMS_XELPRV_01",VR::LT,VM::VM1,"RTSpecification",false }, {0x0033,0x002a,"GEMS_XELPRV_01",VR::UL,VM::VM1,"ReviewTemplatesFlags",false }, {0x0033,0x002b,"GEMS_XELPRV_01",VR::LT,VM::VM1,"DataValidationSpec",false }, {0x0033,0x002c,"GEMS_XELPRV_01",VR::LT,VM::VM1,"Description",false }, {0x0033,0x002d,"GEMS_XELPRV_01",VR::LT,VM::VM1,"IconDescription",false }, {0x0033,0x0050,"GEMS_XELPRV_01",VR::SQ,VM::VM1,"ProtocoldataSQ",false }, {0x0033,0x0051,"GEMS_XELPRV_01",VR::UI,VM::VM1,"PDOSOPClassUID",false }, {0x0033,0x0052,"GEMS_XELPRV_01",VR::UI,VM::VM1,"PDOSOPInstanceUID",false }, {0x0033,0x0060,"GEMS_XELPRV_01",VR::SQ,VM::VM1,"ReviewtemplateSQ",false }, {0x0033,0x0061,"GEMS_XELPRV_01",VR::UI,VM::VM1,"RTOSOPClassUID",false }, {0x0033,0x0062,"GEMS_XELPRV_01",VR::UI,VM::VM1,"RTOSOPInstanceUID",false }, {0x0033,0x0070,"GEMS_XELPRV_01",VR::SQ,VM::VM1,"SeriesdataSQ",false }, {0x0033,0x0071,"GEMS_XELPRV_01",VR::UI,VM::VM1,"SDOSOPClassUID",false }, {0x0033,0x0072,"GEMS_XELPRV_01",VR::UI,VM::VM1,"SDOSOPInstanceUID",false }, {0x0033,0x0073,"GEMS_XELPRV_01",VR::SQ,VM::VM1,"SDODoubleDataSQ",false }, {0x0057,0x0001,"GEMS_XELPRV_01",VR::SQ,VM::VM1,"ROISQ",false }, {0x0057,0x0002,"GEMS_XELPRV_01",VR::UI,VM::VM1,"SOPClassUID",false }, {0x0057,0x0003,"GEMS_XELPRV_01",VR::UI,VM::VM1,"SOPInstanceUID",false }, {0x0057,0x0010,"GEMS_XELPRV_01",VR::IS,VM::VM1,"ROINumber",false }, {0x0057,0x0011,"GEMS_XELPRV_01",VR::UI,VM::VM1,"Dimensions",false }, {0x0057,0x0012,"GEMS_XELPRV_01",VR::UI,VM::VM1,"Points",false }, {0x0057,0x0013,"GEMS_XELPRV_01",VR::UI,VM::VM1,"Type",false }, {0x0057,0x0014,"GEMS_XELPRV_01",VR::UI,VM::VM1,"Description",false }, {0x0057,0x0015,"GEMS_XELPRV_01",VR::UI,VM::VM1,"Data value Representation",false }, {0x0057,0x0016,"GEMS_XELPRV_01",VR::UI,VM::VM1,"Label",false }, {0x0057,0x0017,"GEMS_XELPRV_01",VR::UI,VM::VM1,"Data",false }, {0x0057,0x0041,"GEMS_XELPRV_01",VR::SL,VM::VM1,"Modified",false }, {0x0057,0x0042,"GEMS_XELPRV_01",VR::LO,VM::VM1,"Name",false }, {0x0057,0x0043,"GEMS_XELPRV_01",VR::SL,VM::VM1,"Rid",false }, {0x0057,0x0045,"GEMS_XELPRV_01",VR::LO,VM::VM1,"SOPClassUID",false }, {0x0057,0x0046,"GEMS_XELPRV_01",VR::LO,VM::VM1,"SOPInstanceUID",false }, {0x0057,0x0047,"GEMS_XELPRV_01",VR::LO,VM::VM1,"Normal Colour",false }, {0x0057,0x0048,"GEMS_XELPRV_01",VR::LT,VM::VM1,"NameFont",false }, {0x0057,0x0049,"GEMS_XELPRV_01",VR::SL,VM::VM1,"FillPattern",false }, {0x0057,0x004a,"GEMS_XELPRV_01",VR::SL,VM::VM1,"LineStyle",false }, {0x0057,0x004b,"GEMS_XELPRV_01",VR::SL,VM::VM1,"LineDashLength",false }, {0x0057,0x004c,"GEMS_XELPRV_01",VR::SL,VM::VM1,"LineThickness",false }, {0x0057,0x004d,"GEMS_XELPRV_01",VR::SL,VM::VM1,"Interactivity",false }, {0x0057,0x004e,"GEMS_XELPRV_01",VR::SL,VM::VM1,"NamePos",false }, {0x0057,0x004f,"GEMS_XELPRV_01",VR::SL,VM::VM1,"NameDisplay",false }, {0x0057,0x0050,"GEMS_XELPRV_01",VR::LO,VM::VM1,"Label",false }, {0x0057,0x0051,"GEMS_XELPRV_01",VR::SL,VM::VM1_n,"BpSeg",false }, {0x0057,0x0052,"GEMS_XELPRV_01",VR::US,VM::VM1_n,"BpSegpairs",false }, {0x0057,0x0053,"GEMS_XELPRV_01",VR::SL,VM::VM1,"SeedSpace",false }, {0x0057,0x0054,"GEMS_XELPRV_01",VR::FD,VM::VM1_n,"Seeds",false }, {0x0057,0x0055,"GEMS_XELPRV_01",VR::SL,VM::VM1_n,"Shape",false }, {0x0057,0x0056,"GEMS_XELPRV_01",VR::FD,VM::VM1_n,"ShapeTilt",false }, {0x0057,0x0059,"GEMS_XELPRV_01",VR::SL,VM::VM1_n,"ShapePtsSpace",false }, {0x0057,0x005a,"GEMS_XELPRV_01",VR::SL,VM::VM1_n,"ShapeCtrlPtsCount",false }, {0x0057,0x005b,"GEMS_XELPRV_01",VR::FD,VM::VM1_n,"Shap CtrlPts",false }, {0x0057,0x005c,"GEMS_XELPRV_01",VR::SL,VM::VM1,"ShapeCPSpace",false }, {0x0057,0x005d,"GEMS_XELPRV_01",VR::UL,VM::VM1_n,"ROIFlags",false }, {0x0057,0x005e,"GEMS_XELPRV_01",VR::UL,VM::VM1,"FrameNumber",false }, {0x0057,0x0060,"GEMS_XELPRV_01",VR::LO,VM::VM1_n,"DatasetROIMapping",false }, {0x0021,0x0001,"GEMS_XR3DCAL_01",VR::IS,VM::VM1,"3Dcal image rows",false }, {0x0021,0x0002,"GEMS_XR3DCAL_01",VR::IS,VM::VM1,"3Dcal image columns",false }, {0x0021,0x0003,"GEMS_XR3DCAL_01",VR::FL,VM::VM1,"3Dcal field of view",false }, {0x0021,0x0004,"GEMS_XR3DCAL_01",VR::DA,VM::VM1,"3Dcal acquisition date",false }, {0x0021,0x0005,"GEMS_XR3DCAL_01",VR::TM,VM::VM1,"3Dcal acquisition time",false }, {0x0021,0x0006,"GEMS_XR3DCAL_01",VR::DA,VM::VM1,"3Dcal calibration processing date",false }, {0x0021,0x0007,"GEMS_XR3DCAL_01",VR::TM,VM::VM1,"3Dcal calibration processing time",false }, {0x0021,0x0008,"GEMS_XR3DCAL_01",VR::FL,VM::VM1,"3Dcal L arm angle",false }, {0x0021,0x0009,"GEMS_XR3DCAL_01",VR::FL,VM::VM1_n,"3Dcal Pivot angle vector",false }, {0x0021,0x000a,"GEMS_XR3DCAL_01",VR::FL,VM::VM1,"3Dcal C arm angle",false }, {0x0021,0x000b,"GEMS_XR3DCAL_01",VR::SQ,VM::VM1,"3Dcal matrix sequence",false }, {0x0021,0x000c,"GEMS_XR3DCAL_01",VR::LO,VM::VM1_n,"3Dcal matrix elements",false }, {0x0021,0x000d,"GEMS_XR3DCAL_01",VR::LO,VM::VM1,"3Dcal algorithm version",false }, {0x0021,0x000e,"GEMS_XR3DCAL_01",VR::FL,VM::VM1,"3Dcal 3D frame unit size",false }, {0x0021,0x000f,"GEMS_XR3DCAL_01",VR::LO,VM::VM1,"3Dcal calibration mode",false }, {0x0021,0x0010,"GEMS_XR3DCAL_01",VR::FL,VM::VM1,"3Dcal image frame origin row",false }, {0x0021,0x0011,"GEMS_XR3DCAL_01",VR::FL,VM::VM1,"3Dcal image frame origin column",false }, {0x0021,0x0012,"GEMS_XR3DCAL_01",VR::IS,VM::VM1,"3Dcal positioner pivot rotation speed",false }, {0x0021,0x0013,"GEMS_XR3DCAL_01",VR::IS,VM::VM1,"3Dcal number of images",false }, {0x0021,0x0014,"GEMS_XR3DCAL_01",VR::UI,VM::VM1,"3Dcal Instance UID",false }, {0x0021,0x0015,"GEMS_XR3DCAL_01",VR::FL,VM::VM2,"3Dcal image pixel spacing",false }, {0x0021,0x0016,"GEMS_XR3DCAL_01",VR::CS,VM::VM1,"3Dcal centering mode",false }, {0x0033,0x0005,"GEMS_YMHD_01",VR::UN,VM::VM1,"?",false }, {0x0033,0x0006,"GEMS_YMHD_01",VR::UN,VM::VM1,"?",false }, {0x0019,0x0039,"GE_GENESIS_REV3.0",VR::SS,VM::VM1,"Axial Type",false }, {0x0019,0x008f,"GE_GENESIS_REV3.0",VR::SS,VM::VM1,"Swap Phase / Frequency Axis",false }, {0x0019,0x009c,"GE_GENESIS_REV3.0",VR::SS,VM::VM1,"Pulse Sequence Name",false }, {0x0019,0x009f,"GE_GENESIS_REV3.0",VR::SS,VM::VM1,"Coil Type",false }, {0x0019,0x00a4,"GE_GENESIS_REV3.0",VR::SS,VM::VM1,"SAT fat/water/none",false }, {0x0019,0x00c0,"GE_GENESIS_REV3.0",VR::SS,VM::VM1,"Bitmap of SAT Selections",false }, {0x0019,0x00c1,"GE_GENESIS_REV3.0",VR::SS,VM::VM1,"Surfacel Coil Iintensity Correction Flag",false }, {0x0019,0x00cb,"GE_GENESIS_REV3.0",VR::SS,VM::VM1,"Phase Contrast Flow Axis",false }, {0x0019,0x00cc,"GE_GENESIS_REV3.0",VR::SS,VM::VM1,"Phase Contrast Velocity Encoding",false }, {0x0019,0x00d5,"GE_GENESIS_REV3.0",VR::SS,VM::VM1,"Fractional Echo",false }, {0x0019,0x00d8,"GE_GENESIS_REV3.0",VR::SS,VM::VM1,"Variable Echo Flag",false }, {0x0019,0x00d9,"GE_GENESIS_REV3.0",VR::DS,VM::VM1,"Concatenated Sat",false }, {0x0019,0x00f2,"GE_GENESIS_REV3.0",VR::SS,VM::VM1,"Number of Phases",false }, {0x0043,0x001e,"GE_GENESIS_REV3.0",VR::DS,VM::VM1,"Delta Start Time",false }, {0x0043,0x0027,"GE_GENESIS_REV3.0",VR::SH,VM::VM1,"Pitch Ratio",false }, {0x6005,0x0010,"GE_GROUP",VR::UT,VM::VM1,"?",false }, {0x0009,0x0000,"HMC - CT - ID",VR::UN,VM::VM1,"Image ID Information (e.g. Patient Name, Patient ID)",false }, {0x0009,0x0001,"HMC - CT - ID",VR::UN,VM::VM1,"Image ID Information (e.g. Patient Comment)",false }, {0x0011,0x0000,"HOLOGIC",VR::LO,VM::VM1,"Hx Questionnaire",false }, {0x0021,0x0001,"HOLOGIC",VR::LT,VM::VM1,"Image Analysis Data in XML",false }, {0x0023,0x0000,"HOLOGIC",VR::LO,VM::VM1,"Encoding Scheme Version",false }, {0x0023,0x0001,"HOLOGIC",VR::LO,VM::VM1,"P File Name",false }, {0x0023,0x0002,"HOLOGIC",VR::OB,VM::VM1,"P File Data",false }, {0x0023,0x0003,"HOLOGIC",VR::UL,VM::VM1,"P File Length",false }, {0x0023,0x0004,"HOLOGIC",VR::OB,VM::VM1,"R File Data",false }, {0x0023,0x0005,"HOLOGIC",VR::UL,VM::VM1,"R File Length",false }, {0x0019,0x0006,"HOLOGIC, Inc.",VR::LO,VM::VM1,"?",false }, {0x0019,0x0007,"HOLOGIC, Inc.",VR::SH,VM::VM1,"?",false }, {0x0019,0x0008,"HOLOGIC, Inc.",VR::LO,VM::VM1,"?",false }, {0x0019,0x0016,"HOLOGIC, Inc.",VR::DS,VM::VM1,"?",false }, {0x0019,0x0025,"HOLOGIC, Inc.",VR::SH,VM::VM1,"?",false }, {0x0019,0x0026,"HOLOGIC, Inc.",VR::LO,VM::VM1,"?",false }, {0x0019,0x0027,"HOLOGIC, Inc.",VR::SH,VM::VM1,"?",false }, {0x0019,0x0028,"HOLOGIC, Inc.",VR::LO,VM::VM1,"?",false }, {0x0019,0x0029,"HOLOGIC, Inc.",VR::LO,VM::VM1,"?",false }, {0x0019,0x0030,"HOLOGIC, Inc.",VR::US,VM::VM1,"?",false }, {0x0019,0x0031,"HOLOGIC, Inc.",VR::US,VM::VM1,"?",false }, {0x0019,0x0032,"HOLOGIC, Inc.",VR::US,VM::VM1,"?",false }, {0x0019,0x0033,"HOLOGIC, Inc.",VR::US,VM::VM1,"?",false }, {0x0019,0x0034,"HOLOGIC, Inc.",VR::US,VM::VM1,"?",false }, {0x0019,0x0035,"HOLOGIC, Inc.",VR::US,VM::VM1,"?",false }, {0x0019,0x0037,"HOLOGIC, Inc.",VR::LO,VM::VM1,"?",false }, {0x0019,0x0040,"HOLOGIC, Inc.",VR::DS,VM::VM1,"?",false }, {0x0019,0x0041,"HOLOGIC, Inc.",VR::DS,VM::VM1,"?",false }, {0x0019,0x0042,"HOLOGIC, Inc.",VR::IS,VM::VM1,"?",false }, {0x0019,0x0043,"HOLOGIC, Inc.",VR::DS,VM::VM1,"?",false }, {0x0019,0x0044,"HOLOGIC, Inc.",VR::DS,VM::VM1,"?",false }, {0x0019,0x0045,"HOLOGIC, Inc.",VR::IS,VM::VM1,"?",false }, {0x0019,0x0046,"HOLOGIC, Inc.",VR::IS,VM::VM1,"?",false }, {0x0019,0x0060,"HOLOGIC, Inc.",VR::LT,VM::VM1,"?",false }, {0x0019,0x0061,"HOLOGIC, Inc.",VR::OB,VM::VM1,"?",false }, {0x0019,0x0062,"HOLOGIC, Inc.",VR::LT,VM::VM1,"?",false }, {0x0019,0x0070,"HOLOGIC, Inc.",VR::DS,VM::VM1,"?",false }, {0x0019,0x0085,"HOLOGIC, Inc.",VR::SH,VM::VM1,"?",false }, {0x0019,0x0087,"HOLOGIC, Inc.",VR::LO,VM::VM1,"?",false }, {0x0019,0x0088,"HOLOGIC, Inc.",VR::LO,VM::VM1,"?",false }, {0x0019,0x0089,"HOLOGIC, Inc.",VR::DS,VM::VM2,"?",false }, {0x0019,0x008a,"HOLOGIC, Inc.",VR::SQ,VM::VM1,"?",false }, {0x0019,0x0090,"HOLOGIC, Inc.",VR::DS,VM::VM1,"?",false }, {0x7e01,0x0001,"HOLOGIC, Inc.",VR::LO,VM::VM1,"?",false }, {0x7e01,0x0002,"HOLOGIC, Inc.",VR::LO,VM::VM1,"?",false }, {0x7e01,0x0010,"HOLOGIC, Inc.",VR::SQ,VM::VM1,"?",false }, {0x7e01,0x0011,"HOLOGIC, Inc.",VR::SQ,VM::VM1,"?",false }, {0x7e01,0x0012,"HOLOGIC, Inc.",VR::OB,VM::VM1,"?",false }, {0x7f01,0x0001,"HOLOGIC, Inc.",VR::LO,VM::VM1,"?",false }, {0x7f01,0x0002,"HOLOGIC, Inc.",VR::SH,VM::VM1,"?",false }, {0x7f01,0x0010,"HOLOGIC, Inc.",VR::SQ,VM::VM1,"?",false }, {0x7f01,0x0012,"HOLOGIC, Inc.",VR::OB,VM::VM1,"?",false }, /* {0x0011,0x0000,"Hologic",VR::LO,VM::VM1,"Hx Questionnaire",false }, {0x0021,0x0001,"Hologic",VR::LT,VM::VM1,"Image Analysis Data in XML",false }, {0x0023,0x0000,"Hologic",VR::LO,VM::VM1,"Encoding Scheme Version",false }, {0x0023,0x0001,"Hologic",VR::LO,VM::VM1,"P File Name",false }, {0x0023,0x0002,"Hologic",VR::OB,VM::VM1,"P File Data",false }, {0x0023,0x0003,"Hologic",VR::UL,VM::VM1,"P File Length",false }, {0x0023,0x0004,"Hologic",VR::OB,VM::VM1,"R File Data",false }, {0x0023,0x0005,"Hologic",VR::UL,VM::VM1,"R File Length",false }, */ {0x0011,0x0000,"IDEXX",VR::LO,VM::VM1,"Breed Name",false }, {0x0011,0x0001,"IDEXX",VR::LO,VM::VM1,"Species Name",false }, {0x0011,0x0002,"IDEXX",VR::PN,VM::VM1,"Owner",false }, {0x300b,0x0002,"IMPAC",VR::FL,VM::VM1,"?",false }, {0x300b,0x0004,"IMPAC",VR::FL,VM::VM1,"?",false }, {0x300b,0x000e,"IMPAC",VR::FL,VM::VM1,"?",false }, {0x1269,0x0001,"IMS s.r.l. Biopsy Private Code",VR::IS,VM::VM1,"Biopsy Image",false }, {0x1269,0x0010,"IMS s.r.l. Biopsy Private Code",VR::IS,VM::VM1_n,"Biopsy Markers X",false }, {0x1269,0x0011,"IMS s.r.l. Biopsy Private Code",VR::IS,VM::VM1_n,"Biopsy Markers Y",false }, {0x1269,0x0012,"IMS s.r.l. Biopsy Private Code",VR::IS,VM::VM1,"Biopsy Markers Number",false }, {0x1269,0x0020,"IMS s.r.l. Biopsy Private Code",VR::IS,VM::VM1,"Biopsy Area Left Border",false }, {0x1269,0x0021,"IMS s.r.l. Biopsy Private Code",VR::IS,VM::VM1,"Biopsy Area Right Border",false }, {0x1269,0x0022,"IMS s.r.l. Biopsy Private Code",VR::IS,VM::VM1,"Biopsy Area Top Border",false }, {0x1269,0x0023,"IMS s.r.l. Biopsy Private Code",VR::IS,VM::VM1,"Biopsy Area Bottom Border",false }, {0x1271,0x0001,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0002,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0010,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0011,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0012,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0013,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0020,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0021,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0022,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0038,"IMS s.r.l. Mammography Private Code",VR::LO,VM::VM1,"?",false }, {0x1271,0x0039,"IMS s.r.l. Mammography Private Code",VR::US,VM::VM1,"?",false }, {0x1271,0x0040,"IMS s.r.l. Mammography Private Code",VR::US,VM::VM1,"?",false }, {0x1271,0x0041,"IMS s.r.l. Mammography Private Code",VR::LO,VM::VM1,"?",false }, {0x1271,0x0042,"IMS s.r.l. Mammography Private Code",VR::LT,VM::VM1,"?",false }, {0x1271,0x0045,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0046,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0047,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0048,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0049,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0050,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0051,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0052,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x1271,0x0053,"IMS s.r.l. Mammography Private Code",VR::LO,VM::VM1,"?",false }, {0x1271,0x0054,"IMS s.r.l. Mammography Private Code",VR::IS,VM::VM1,"?",false }, {0x0015,0x0010,"INFINITT_FMX",VR::LO,VM::VM1,"?",false }, {0x0015,0x0011,"INFINITT_FMX",VR::LO,VM::VM1,"?",false }, {0x0009,0x0008,"INTEGRIS 1.0",VR::CS,VM::VM1,"Exposure Channel",false }, {0x0009,0x0032,"INTEGRIS 1.0",VR::TM,VM::VM1,"Exposure Start Time",false }, {0x0019,0x0000,"INTEGRIS 1.0",VR::LO,VM::VM1,"APR Name",false }, {0x0019,0x0040,"INTEGRIS 1.0",VR::DS,VM::VM1,"Frame Rate",false }, {0x0021,0x0012,"INTEGRIS 1.0",VR::IS,VM::VM1,"Exposure Number",false }, {0x0029,0x0000,"INTEGRIS 1.0",VR::SQ,VM::VM1,"Edge Enhancement Sequence",false }, {0x0029,0x0001,"INTEGRIS 1.0",VR::US,VM::VM2,"Convolution Kernel Size",false }, {0x0029,0x0002,"INTEGRIS 1.0",VR::US,VM::VM1_n,"Convolution Kernel Coefficients",false }, {0x0029,0x0003,"INTEGRIS 1.0",VR::FL,VM::VM1,"Edge Enhancement Gain",false }, {0x0029,0x0008,"INTEGRIS 1.0",VR::IS,VM::VM1,"Number of Exposure Results",false }, {0x0041,0x0020,"INTEGRIS 1.0",VR::DS,VM::VM1,"Accumulated Fluoroscopy Dose",false }, {0x0041,0x0030,"INTEGRIS 1.0",VR::DS,VM::VM1,"Accumulated Exposure Dose",false }, {0x0041,0x0040,"INTEGRIS 1.0",VR::DS,VM::VM1,"Total Dose",false }, {0x0041,0x0041,"INTEGRIS 1.0",VR::US,VM::VM1,"Total Number of Frames",false }, {0x0041,0x0050,"INTEGRIS 1.0",VR::SQ,VM::VM1,"Exposure Information Sequence",false }, {0x0029,0x0001,"INTELERAD MEDICAL SYSTEMS",VR::FD,VM::VM1,"Image Compression Fraction",false }, {0x0029,0x0002,"INTELERAD MEDICAL SYSTEMS",VR::FD,VM::VM1,"Image Quality",false }, {0x0029,0x0003,"INTELERAD MEDICAL SYSTEMS",VR::FD,VM::VM1,"Image Bytes Transferred",false }, {0x0029,0x0008,"INTELERAD MEDICAL SYSTEMS",VR::SL,VM::VM4,"Image Bounding Box",false }, {0x0029,0x0009,"INTELERAD MEDICAL SYSTEMS",VR::LO,VM::VM1,"Image Bounding Box Algorithm ID",false }, {0x0029,0x0010,"INTELERAD MEDICAL SYSTEMS",VR::SH,VM::VM1,"J2C Parameter Type",false }, {0x0029,0x0011,"INTELERAD MEDICAL SYSTEMS",VR::CS,VM::VM1,"J2C Pixel Representation",false }, {0x0029,0x0012,"INTELERAD MEDICAL SYSTEMS",VR::US,VM::VM1,"J2C Bits Allocated",false }, {0x0029,0x0013,"INTELERAD MEDICAL SYSTEMS",VR::US,VM::VM1,"J2C Pixel Shift Value",false }, {0x0029,0x0014,"INTELERAD MEDICAL SYSTEMS",VR::US,VM::VM1,"J2C Planar Configuration",false }, {0x0029,0x0015,"INTELERAD MEDICAL SYSTEMS",VR::DS,VM::VM1,"J2C Rescale Intercept",false }, {0x0029,0x0016,"INTELERAD MEDICAL SYSTEMS",VR::US,VM::VM1,"J2c Smallest Pixel Value",false }, {0x0029,0x0017,"INTELERAD MEDICAL SYSTEMS",VR::US,VM::VM1,"J2c Largest Pixel Value",false }, {0x0029,0x0020,"INTELERAD MEDICAL SYSTEMS",VR::LO,VM::VM1,"Pixel Data MD5 Sum Values",false }, {0x0029,0x0021,"INTELERAD MEDICAL SYSTEMS",VR::US,VM::VM1_n,"Pixel Data Histogram Percentiles",false }, {0x0029,0x0022,"INTELERAD MEDICAL SYSTEMS",VR::FD,VM::VM1_n,"Pixel Data Histogram Percentile Values",false }, {0x0029,0x0023,"INTELERAD MEDICAL SYSTEMS",VR::FD,VM::VM1,"VOI LUT Window Level Values",false }, {0x0029,0x0024,"INTELERAD MEDICAL SYSTEMS",VR::FD,VM::VM1,"VOI LUT Real Pixel Value Range",false }, {0x0029,0x0025,"INTELERAD MEDICAL SYSTEMS",VR::IS,VM::VM1,"VOI LUT Index",false }, {0x0029,0x0026,"INTELERAD MEDICAL SYSTEMS",VR::DS,VM::VM1,"J2C Rescale Slope",false }, {0x0029,0x0027,"INTELERAD MEDICAL SYSTEMS",VR::FD,VM::VM1,"Image Rotation Angle",true}, {0x0029,0x0028,"INTELERAD MEDICAL SYSTEMS",VR::FD,VM::VM1,"Displayed Area Top Left-Hand Corner",true}, {0x0029,0x0029,"INTELERAD MEDICAL SYSTEMS",VR::FD,VM::VM1,"Displayed Area Bottom Right-Hand Corner",true}, {0x3f01,0x0001,"INTELERAD MEDICAL SYSTEMS",VR::LO,VM::VM1,"Institution",false }, {0x3f01,0x0002,"INTELERAD MEDICAL SYSTEMS",VR::SH,VM::VM1,"AE Title Destination",false }, {0x3f01,0x0003,"INTELERAD MEDICAL SYSTEMS",VR::LO,VM::VM1,"Source AE Title",false }, {0x3f01,0x0004,"INTELERAD MEDICAL SYSTEMS",VR::SH,VM::VM1,"Deferred Validation",false }, {0x3f01,0x0005,"INTELERAD MEDICAL SYSTEMS",VR::LO,VM::VM1,"Series Owner",false }, {0x3f01,0x0006,"INTELERAD MEDICAL SYSTEMS",VR::LO,VM::VM1,"Group Number",false }, {0x3f01,0x0007,"INTELERAD MEDICAL SYSTEMS",VR::SH,VM::VM1,"Stripped Pixel Data",false }, {0x3f01,0x0008,"INTELERAD MEDICAL SYSTEMS",VR::SH,VM::VM1,"Pending Move Request",false }, {0x3f01,0x0009,"INTELERAD MEDICAL SYSTEMS",VR::LO,VM::VM1,"Dicom Premap Sites",false }, {0x3f01,0x000a,"INTELERAD MEDICAL SYSTEMS",VR::DA,VM::VM1,"Association Date",false }, {0x3f01,0x000b,"INTELERAD MEDICAL SYSTEMS",VR::TM,VM::VM1,"Association Time",false }, {0x3f01,0x000c,"INTELERAD MEDICAL SYSTEMS",VR::SH,VM::VM1,"Use Source AE",false }, {0x3f01,0x000e,"INTELERAD MEDICAL SYSTEMS",VR::SH,VM::VM1,"Relay to AE",false }, {0x3f01,0x000f,"INTELERAD MEDICAL SYSTEMS",VR::SH,VM::VM1,"ImsMoveRequestRedirectionCount",false }, {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 }, {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 }, {0x3f03,0x0004,"INTELERAD MEDICAL SYSTEMS",VR::ST,VM::VM1,"Change explanation",false }, {0x6001,0x0001,"INTELERAD MEDICAL SYSTEMS",VR::US,VM::VM1,"Overlay bit position",false }, {0x0071,0x0001,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::LO,VM::VM1,"InteleViewer Markup Type",false }, {0x0071,0x0002,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::ST,VM::VM1,"InteleViewer Markup Text",false }, {0x0071,0x0003,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Text Offset",false }, {0x0071,0x0004,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Position",false }, {0x0071,0x0005,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Half-Vector",false }, {0x0071,0x0006,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Vector 1",false }, {0x0071,0x0007,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Vector 2",false }, {0x0071,0x0008,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Orthogonal Position",false }, {0x0071,0x0009,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Orthogonal Half-Vector",false }, {0x0071,0x000a,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Minimum Length",false }, {0x0071,0x000b,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::SL,VM::VM1,"InteleViewer Markup Number of Polygons",false }, {0x0071,0x000c,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::SL,VM::VM1,"InteleViewer Markup Length of Polygons",false }, {0x0071,0x000d,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Points",false }, {0x0071,0x000e,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Slice Separation",false }, {0x0071,0x000f,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::US,VM::VM1,"InteleViewer Markup VOI Index",false }, {0x0071,0x0010,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Sagittal Text Offset",false }, {0x0071,0x0011,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Default Text Offset",false }, {0x0071,0x0020,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::LO,VM::VM1,"InteleViewer Markup Dataset Tool ID",false }, {0x0071,0x0021,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Distance Calibration",false }, {0x0071,0x0030,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Image Grid Origin",false }, {0x0071,0x0031,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Image Grid Pixel Row Vector",false }, {0x0071,0x0032,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Markup Image Grid Pixel Column Vector",false }, {0x0071,0x0033,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::CS,VM::VM1,"InteleViewer Markup Image Grid Is Calibrated",false }, {0x0071,0x0034,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"Image Rotation Angle",false }, {0x0071,0x0035,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"Displayed Area Top Left-Hand Corner",false }, {0x0071,0x0036,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"Displayed Area Bottom Right-Hand Corner",false }, {0x3f05,0x0001,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::LO,VM::VM1,"InteleViewer Source Name",false }, {0x3f05,0x0002,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::LO,VM::VM1,"Preview Image Id",false }, {0x3f0f,0x0001,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::US,VM::VM1,"InteleViewer Advanced Visualization Presentation Bin Size",false }, {0x3f0f,0x0002,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::SQ,VM::VM1,"InteleViewer Advanced Visualization Presentation Bin",false }, {0x3f0f,0x0003,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::LO,VM::VM1,"InteleViewer Advanced Visualization RenderType",false }, {0x3f0f,0x0004,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Advanced Visualization Row Vector",false }, {0x3f0f,0x0005,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Advanced Visualization Column Vector",false }, {0x3f0f,0x0006,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::FD,VM::VM1,"InteleViewer Advanced Visualization Slab Thickness",false }, {0x3f0f,0x0007,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::LO,VM::VM1,"InteleViewer Advanced Visualization Original Dataset Series UID",false }, {0x3f0f,0x0008,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::LO,VM::VM1,"InteleViewer Advanced Visualization Transfer Function Type",false }, {0x3f0f,0x0009,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::LO,VM::VM1,"InteleViewer Advanced Visualization Source Dataset Sub Volume First SOP UID",false }, {0x3f0f,0x0010,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::LO,VM::VM1,"InteleViewer Advanced Visualization Source Dataset Sub Volume Last SOP UID",false }, {0x3f0f,0x0011,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::LO,VM::VM1,"InteleViewer Advanced Visualization Sub volume creation algorithm",false }, {0x3f0f,0x0012,"INTELERAD MEDICAL SYSTEMS INTELEVIEWER",VR::US,VM::VM1,"InteleViewer Advanced Visualization Number of images in Sub volume",false }, {0x0065,0x0011,"ISG Image",VR::UL,VM::VM1,"Length in Byte of Image",false }, {0x0029,0x0070,"ISG shadow",VR::IS,VM::VM1,"?",false }, {0x0029,0x0080,"ISG shadow",VR::IS,VM::VM1,"?",false }, {0x0029,0x0090,"ISG shadow",VR::IS,VM::VM1,"?",false }, {0x0009,0x0001,"ISI",VR::SQ,VM::VM1,"SIENET General Purpose IMGF",false }, {0x8003,0x0000,"Image (ID, Version, Size, Dump, GUID)",VR::LO,VM::VM1,"ID",false }, {0x8003,0x0010,"Image (ID, Version, Size, Dump, GUID)",VR::LO,VM::VM1,"Version",false }, {0x8003,0x0020,"Image (ID, Version, Size, Dump, GUID)",VR::UL,VM::VM1,"Size",false }, {0x8003,0x0030,"Image (ID, Version, Size, Dump, GUID)",VR::OB,VM::VM1,"Dump",false }, {0x8003,0x0040,"Image (ID, Version, Size, Dump, GUID)",VR::LO,VM::VM1,"GUID",false }, {0x4321,0x0005,"Imaging Dynamics Company Ltd.",VR::UN,VM::VM1,"Custom Tag",false }, {0x4321,0x0010,"Imaging Dynamics Company Ltd.",VR::UN,VM::VM1,"Custom Tag",false }, {0x4321,0x0041,"Imaging Dynamics Company Ltd.",VR::CS,VM::VM1,"?",false }, {0x4321,0x0042,"Imaging Dynamics Company Ltd.",VR::US,VM::VM1,"?",false }, {0x4321,0x0050,"Imaging Dynamics Company Ltd.",VR::DS,VM::VM1,"Custom Tag",false }, {0x4321,0x0051,"Imaging Dynamics Company Ltd.",VR::DS,VM::VM1,"Custom Tag",false }, {0x4321,0x0064,"Imaging Dynamics Company Ltd.",VR::LO,VM::VM1,"Custom Tag",false }, {0x0021,0x00a5,"KINETDX",VR::US,VM::VM1,"?",false }, {0x0021,0x00a8,"KINETDX",VR::LO,VM::VM1,"?",false }, {0x0021,0x00aa,"KINETDX",VR::OB,VM::VM1,"?",false }, {0x0021,0x00a4,"KINETDX_GRAPHICS",VR::LT,VM::VM1,"?",false }, {0x7fe1,0x0001,"KRETZ_US",VR::OB,VM::VM1,"?",false }, {0x0029,0x0015,"Kodak Image Information",VR::LO,VM::VM1,"?",false }, {0x0029,0x0016,"Kodak Image Information",VR::LO,VM::VM1,"?",false }, {0x0029,0x0017,"Kodak Image Information",VR::LO,VM::VM1,"?",false }, {0x0029,0x0018,"Kodak Image Information",VR::UT,VM::VM1,"?",false }, {0x0029,0x0019,"Kodak Image Information",VR::IS,VM::VM1,"?",false }, {0x0029,0x001a,"Kodak Image Information",VR::IS,VM::VM1,"?",false }, {0x0019,0x0001,"LODOX_STATSCAN",VR::IS,VM::VM1_n,"?",false }, {0x0019,0x0002,"LODOX_STATSCAN",VR::IS,VM::VM1,"?",false }, {0x0019,0x0003,"LODOX_STATSCAN",VR::DS,VM::VM1,"?",false }, {0x0019,0x0004,"LODOX_STATSCAN",VR::DS,VM::VM1,"?",false }, {0x0019,0x0005,"LODOX_STATSCAN",VR::DS,VM::VM1,"?",false }, {0x0019,0x0006,"LODOX_STATSCAN",VR::DS,VM::VM1,"?",false }, {0x0019,0x0007,"LODOX_STATSCAN",VR::DS,VM::VM1,"?",false }, {0x0019,0x0008,"LODOX_STATSCAN",VR::DS,VM::VM1,"?",false }, {0x0019,0x0006,"LORAD Selenia",VR::OB,VM::VM1,"Paddle ID",false }, {0x0019,0x0007,"LORAD Selenia",VR::OB,VM::VM1,"Paddle Position",false }, {0x0019,0x0008,"LORAD Selenia",VR::OB,VM::VM1,"Collimation Size",false }, {0x0019,0x0026,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0027,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0028,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0029,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0030,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0031,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0032,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0033,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0034,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0035,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0040,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0041,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0050,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0051,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0052,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0053,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0070,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0019,0x0071,"LORAD Selenia",VR::OB,VM::VM1,"?",false }, {0x0037,0x0001,"MAROTECH Inc.",VR::LO,VM::VM1,"Some kind of version number",false }, {0x0037,0x0021,"MAROTECH Inc.",VR::US,VM::VM1,"Icon Row",false }, {0x0037,0x0022,"MAROTECH Inc.",VR::US,VM::VM1,"Icon Col",false }, {0x0037,0x0023,"MAROTECH Inc.",VR::OB,VM::VM1,"JPEG Compressed Icon",false }, {0x3005,0x0000,"MDS NORDION OTP ANATOMY MODELLING",VR::SQ,VM::VM1,"?",false }, {0x3005,0x0002,"MDS NORDION OTP ANATOMY MODELLING",VR::CS,VM::VM1,"?",false }, {0x3005,0x0004,"MDS NORDION OTP ANATOMY MODELLING",VR::DS,VM::VM1,"?",false }, {0x3005,0x0006,"MDS NORDION OTP ANATOMY MODELLING",VR::DS,VM::VM1,"?",false }, {0x3005,0x0008,"MDS NORDION OTP ANATOMY MODELLING",VR::DS,VM::VM1,"?",false }, {0x3005,0x000a,"MDS NORDION OTP ANATOMY MODELLING",VR::CS,VM::VM1,"?",false }, {0x3005,0x000c,"MDS NORDION OTP ANATOMY MODELLING",VR::CS,VM::VM1,"?",false }, {0x3005,0x000e,"MDS NORDION OTP ANATOMY MODELLING",VR::CS,VM::VM1,"?",false }, {0x3005,0x0010,"MDS NORDION OTP ANATOMY MODELLING",VR::DS,VM::VM1,"?",false }, {0x3005,0x0012,"MDS NORDION OTP ANATOMY MODELLING",VR::DS,VM::VM1,"?",false }, {0x0021,0x0001,"MEDIFACE",VR::SL,VM::VM1,"?",false }, {0x0021,0x0010,"MEDIFACE",VR::SH,VM::VM1,"?",false }, {0x0021,0x0011,"MEDIFACE",VR::LO,VM::VM1,"?",false }, {0x0021,0x0012,"MEDIFACE",VR::UL,VM::VM1,"?",false }, {0x0021,0x0021,"MEDIFACE",VR::LO,VM::VM1,"?",false }, {0x0021,0x0022,"MEDIFACE",VR::LO,VM::VM1,"?",false }, {0x0021,0x0030,"MEDIFACE",VR::DA,VM::VM1,"?",false }, {0x0021,0x0031,"MEDIFACE",VR::IS,VM::VM1,"?",false }, {0x0021,0x0040,"MEDIFACE",VR::SQ,VM::VM1,"?",false }, {0x0021,0x0041,"MEDIFACE",VR::SH,VM::VM1,"?",false }, {0x0021,0x0042,"MEDIFACE",VR::LO,VM::VM1,"?",false }, {0x0021,0x0050,"MEDIFACE",VR::SQ,VM::VM1,"?",false }, {0x0021,0x0051,"MEDIFACE",VR::SH,VM::VM1,"?",false }, {0x0021,0x0052,"MEDIFACE",VR::LO,VM::VM1,"?",false }, {0x0021,0x0060,"MEDIFACE",VR::SQ,VM::VM1,"?",false }, {0x0021,0x00f1,"MEDIFACE",VR::LO,VM::VM1,"?",false }, {0x0021,0x00f2,"MEDIFACE",VR::LO,VM::VM1,"?",false }, {0x0029,0x0001,"MEDIFACE",VR::UL,VM::VM1,"?",false }, {0x0029,0x0010,"MEDIFACE",VR::DS,VM::VM1,"Window Center",false }, {0x0029,0x0011,"MEDIFACE",VR::DS,VM::VM1,"Window Width",false }, {0x0029,0x0020,"MEDIFACE",VR::DS,VM::VM1,"?",false }, {0x0029,0x0021,"MEDIFACE",VR::UL,VM::VM1,"?",false }, {0x0029,0x0022,"MEDIFACE",VR::DS,VM::VM2,"MEDIFACE Pixel Spacing",false }, {0x0029,0x0030,"MEDIFACE",VR::LT,VM::VM1,"?",false }, {0x0003,0x0000,"MEDIS_IS&C 1.0",VR::US,VM::VM1,"?",false }, {0x0003,0x0003,"MEDIS_IS&C 1.0",VR::US,VM::VM1,"?",false }, {0x0003,0x0004,"MEDIS_IS&C 1.0",VR::CS,VM::VM1,"?",false }, {0x0003,0x0010,"MEDIS_IS&C 1.0",VR::DS,VM::VM1_n,"?",false }, {0x0003,0x0020,"MEDIS_IS&C 1.0",VR::UL,VM::VM1,"?",false }, {0x0003,0x0022,"MEDIS_IS&C 1.0",VR::UL,VM::VM1,"?",false }, {0x0003,0x0030,"MEDIS_IS&C 1.0",VR::US,VM::VM1,"?",false }, {0x0009,0x0000,"MERGE TECHNOLOGIES, INC.",VR::OB,VM::VM1,"?",false }, {0x0031,0x0020,"MITRA LINKED ATTRIBUTES 1.0",VR::IS,VM::VM1,"?",false }, /* {0x0029,0x0000,"MITRA MARKUP 1.0",VR::LO,VM::VM1_n,"?",false }, {0x0029,0x0001,"MITRA MARKUP 1.0",VR::LO,VM::VM1_n,"?",false },*/ {0x0033,0x0002,"MITRA OBJECT ATTRIBUTES 1.0",VR::LO,VM::VM1,"?",false }, {0x0033,0x0004,"MITRA OBJECT ATTRIBUTES 1.0",VR::LO,VM::VM1,"?",false }, {0x0033,0x0006,"MITRA OBJECT ATTRIBUTES 1.0",VR::LO,VM::VM1,"?",false }, {0x0033,0x0008,"MITRA OBJECT ATTRIBUTES 1.0",VR::LO,VM::VM1,"?",false }, {0x0033,0x000a,"MITRA OBJECT ATTRIBUTES 1.0",VR::LO,VM::VM1,"?",false }, // {0x0029,0x0000,"MITRA OBJECT DOCUMENT 1.0",VR::OB,VM::VM1,"?",false }, {0x0033,0x0002,"MITRA OBJECT UTF8 ATTRIBUTES 1.0",VR::OB,VM::VM1,"Patient Name (UTF8 Encoded)",false }, {0x0033,0x0004,"MITRA OBJECT UTF8 ATTRIBUTES 1.0",VR::CS,VM::VM1,"Study Description (UTF8 Encoded)",false }, {0x0033,0x0006,"MITRA OBJECT UTF8 ATTRIBUTES 1.0",VR::PN,VM::VM1,"Referring Physician Name (UTF8 Encoded)",false }, {0x0033,0x0008,"MITRA OBJECT UTF8 ATTRIBUTES 1.0",VR::OB,VM::VM1,"Requesting Physician Name (UTF8 Encoded)",false }, {0x0033,0x000a,"MITRA OBJECT UTF8 ATTRIBUTES 1.0",VR::PN,VM::VM1,"Performing Physician Name (UTF8 Encoded)",false }, {0x0033,0x000c,"MITRA OBJECT UTF8 ATTRIBUTES 1.0",VR::LO,VM::VM1,"Reason for Study (UTF8 Encoded)",false }, {0x0033,0x000e,"MITRA OBJECT UTF8 ATTRIBUTES 1.0",VR::LT,VM::VM1,"Study Comments (UTF8 Encoded)",false }, {0x0033,0x0013,"MITRA OBJECT UTF8 ATTRIBUTES 1.0",VR::PN,VM::VM1,"Patient's Name",false }, {0x0033,0x0014,"MITRA OBJECT UTF8 ATTRIBUTES 1.0",VR::OB,VM::VM1,"?",false }, {0x0033,0x0015,"MITRA OBJECT UTF8 ATTRIBUTES 1.0",VR::OB,VM::VM1,"?",false }, {0x0033,0x0016,"MITRA OBJECT UTF8 ATTRIBUTES 1.0",VR::CS,VM::VM1,"?",false }, {0x0033,0x0019,"MITRA OBJECT UTF8 ATTRIBUTES 1.0",VR::CS,VM::VM1,"?",false }, {0x0033,0x001c,"MITRA OBJECT UTF8 ATTRIBUTES 1.0",VR::PN,VM::VM1,"Referring Physician's Name",false }, /* {0x0029,0x0000,"MITRA PRESENTATION 1.0",VR::LO,VM::VM1,"?",false }, {0x0029,0x0001,"MITRA PRESENTATION 1.0",VR::UN,VM::VM1,"?",false }, {0x0029,0x0002,"MITRA PRESENTATION 1.0",VR::UN,VM::VM1,"?",false }, {0x0029,0x0003,"MITRA PRESENTATION 1.0",VR::LO,VM::VM1,"?",false },*/ /* {0x0029,0x0010,"MITRA PRESENTATION 1.0",VR::US,VM::VM1,"?",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 }, {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 }, {0x0021,0x0012,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x0013,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x0014,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x0015,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x0016,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x0017,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x0018,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x0019,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x001a,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x001b,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x001c,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x001d,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x001e,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x001f,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x0020,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x0040,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x0041,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x0050,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x0060,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x0065,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0019,0x0001,"MeVis BreastCare",VR::LO,VM::VM1,"?",false }, {0x0071,0x0001,"MeVis BreastCare",VR::LO,VM::VM1,"?",false }, {0x0009,0x0011,"MeVis eD: Geometry Information",VR::UN,VM::VM1,"GeoScannerOrigin",false }, {0x0009,0x0021,"MeVis eD: Geometry Information",VR::UN,VM::VM1,"SlicesID",false }, {0x0009,0x0010,"MeVis eD: Slice Information",VR::UN,VM::VM1,"SlicesSOPInstanceUID",false }, {0x0021,0x0010,"MeVis eD: Timepoint Information",VR::LT,VM::VM1,"TPDateTime",false }, {0x0021,0x0011,"MeVis eD: Timepoint Information",VR::CS,VM::VM1,"TPDateTimeType",false }, {0x0021,0x0012,"MeVis eD: Timepoint Information",VR::UN,VM::VM1,"TPSeriesDescription",false }, {0x0021,0x0013,"MeVis eD: Timepoint Information",VR::UN,VM::VM1,"TPGradientDirections",false }, {0x0021,0x0021,"MeVis eD: Timepoint Information",VR::UN,VM::VM1,"GeometryID",false }, {0x0009,0x0010,"MeVis eatDicom",VR::UN,VM::VM1,"EatDicomVersion",false }, {0x0009,0x0011,"MeVis eatDicom",VR::UN,VM::VM1,"EatDicomOptions",false }, {0x0009,0x0021,"MeVis eatDicom",VR::UN,VM::VM1,"TimepointsID",false }, {0x5473,0x0003,"MedIns HP Extensions",VR::LO,VM::VM1,"?",false }, {0x0029,0x0000,"Mitra Markup 1.0",VR::OB,VM::VM1_n,"Markup1",false }, {0x0029,0x0001,"Mitra Markup 1.0",VR::OB,VM::VM1_n,"Markup2",false }, {0x0029,0x0002,"Mitra Markup 1.0",VR::OB,VM::VM1_n,"Markup3",false }, {0x0029,0x0003,"Mitra Markup 1.0",VR::OB,VM::VM1_n,"Markup4",false }, {0x0029,0x0004,"Mitra Markup 1.0",VR::OB,VM::VM1_n,"Markup5",false }, {0x0029,0x0005,"Mitra Markup 1.0",VR::OB,VM::VM1_n,"Markup6",false }, {0x0029,0x0006,"Mitra Markup 1.0",VR::OB,VM::VM1_n,"Markup7",false }, {0x0029,0x0007,"Mitra Markup 1.0",VR::OB,VM::VM1_n,"Markup8",false }, {0x0029,0x0008,"Mitra Markup 1.0",VR::OB,VM::VM1_n,"Markup9",false }, {0x0029,0x0009,"Mitra Markup 1.0",VR::OB,VM::VM1_n,"Markup10",false }, {0x0029,0x0010,"Mitra Markup 1.0",VR::OB,VM::VM1_n,"Markup11",false }, {0x0029,0x0011,"Mitra Markup 1.0",VR::OB,VM::VM1_n,"Markup12",false }, {0x0029,0x0012,"Mitra Markup 1.0",VR::OB,VM::VM1,"Markup13",false }, {0x0029,0x0013,"Mitra Markup 1.0",VR::OB,VM::VM1,"Markup14",false }, {0x0029,0x0014,"Mitra Markup 1.0",VR::OB,VM::VM1,"Markup15",false }, {0x0029,0x0000,"Mitra Object Document 1.0",VR::OB,VM::VM1,"IMPAX object document",false }, {0x0029,0x0010,"Mitra Object Document 1.0",VR::OB,VM::VM1,"IMPAX markup XML stored",false }, {0x0029,0x0000,"MITRA PRESENTATION 1.0",VR::CS,VM::VM1,"Mitra Rotation",false }, {0x0029,0x0001,"MITRA PRESENTATION 1.0",VR::LO,VM::VM1,"Mitra Window Width",false }, {0x0029,0x0002,"MITRA PRESENTATION 1.0",VR::LO,VM::VM1,"Mitra Window Centre",false }, {0x0029,0x0003,"MITRA PRESENTATION 1.0",VR::IS,VM::VM1,"Mitra Invert",false }, {0x0029,0x0004,"MITRA PRESENTATION 1.0",VR::IS,VM::VM1,"Mitra Has Tabstop",false }, {0x0029,0x0005,"MITRA PRESENTATION 1.0",VR::CS,VM::VM1,"Smooth Rotation",false }, {0x0029,0x0010,"MITRA PRESENTATION 1.0",VR::CS,VM::VM1,"??",false }, {0x0029,0x0011,"MITRA PRESENTATION 1.0",VR::CS,VM::VM1,"??",false }, {0x0029,0x0012,"MITRA PRESENTATION 1.0",VR::CS,VM::VM1,"??",false }, {0x0029,0x0013,"MITRA PRESENTATION 1.0",VR::CS,VM::VM1,"??",false }, {0x1455,0x0000,"Mortara_Inc",VR::OW,VM::VM1,"ELI Interpretation Vector",false }, {0x1455,0x0001,"Mortara_Inc",VR::UN,VM::VM1,"Custom ID",false }, {0x1455,0x0002,"Mortara_Inc",VR::UT,VM::VM1,"Race",false }, {0x1455,0x0003,"Mortara_Inc",VR::UT,VM::VM1,"Social Security Number",false }, {0x1455,0x0004,"Mortara_Inc",VR::UT,VM::VM1,"Attending Physician",false }, {0x1455,0x0005,"Mortara_Inc",VR::UT,VM::VM1,"Procedural Diagnosis",false }, {0x1455,0x0006,"Mortara_Inc",VR::UT,VM::VM1,"Note1",false }, {0x1455,0x0007,"Mortara_Inc",VR::UT,VM::VM1,"Note2",false }, {0x1455,0x0008,"Mortara_Inc",VR::LO,VM::VM1,"Order Request Number",false }, {0x1455,0x0010,"Mortara_Inc",VR::LO,VM::VM1,"Manufacturer Name",false }, {0x7777,0x0002,"NUD_PRIVATE",VR::UT,VM::VM1,"Interfile",false }, {0x7777,0x0005,"NUD_PRIVATE",VR::IS,VM::VM1,"?",false }, {0x8101,0x0000,"ObjectModel (ID, Version, Place, PlaceDescription)",VR::LO,VM::VM1,"ID",false }, {0x8101,0x0010,"ObjectModel (ID, Version, Place, PlaceDescription)",VR::LO,VM::VM1,"Version",false }, {0x0009,0x0000,"PAPYRUS",VR::LT,VM::VM1,"Original File Name",false }, {0x0009,0x0010,"PAPYRUS",VR::LT,VM::VM1,"Original File Location",false }, {0x0009,0x0018,"PAPYRUS",VR::LT,VM::VM1,"Data Set Identifier",false }, {0x0041,0x0000,"PAPYRUS",VR::LT,VM::VM1_n,"Papyrus Comments",false }, {0x0041,0x0010,"PAPYRUS",VR::US,VM::VM1,"Folder Type",false }, {0x0041,0x0011,"PAPYRUS",VR::LT,VM::VM1,"Patient Folder Data Set ID",false }, {0x0041,0x0020,"PAPYRUS",VR::LT,VM::VM1,"Folder Name",false }, {0x0041,0x0030,"PAPYRUS",VR::DA,VM::VM1,"Creation Date",false }, {0x0041,0x0032,"PAPYRUS",VR::TM,VM::VM1,"Creation Time",false }, {0x0041,0x0034,"PAPYRUS",VR::DA,VM::VM1,"Modified Date",false }, {0x0041,0x0036,"PAPYRUS",VR::TM,VM::VM1,"Modified Time",false }, {0x0041,0x0040,"PAPYRUS",VR::LT,VM::VM1_n,"Owner Name",false }, {0x0041,0x0050,"PAPYRUS",VR::LT,VM::VM1,"Folder Status",false }, {0x0041,0x0060,"PAPYRUS",VR::UL,VM::VM1,"Number of Images",false }, {0x0041,0x0062,"PAPYRUS",VR::UL,VM::VM1,"Number of Other",false }, {0x0041,0x00a0,"PAPYRUS",VR::LT,VM::VM1_n,"External Folder Element DSID",false }, {0x0041,0x00a1,"PAPYRUS",VR::US,VM::VM1_n,"External Folder Element Data Set Type",false }, {0x0041,0x00a2,"PAPYRUS",VR::LT,VM::VM1_n,"External Folder Element File Location",false }, {0x0041,0x00a3,"PAPYRUS",VR::UL,VM::VM1_n,"External Folder Element Length",false }, {0x0041,0x00b0,"PAPYRUS",VR::LT,VM::VM1_n,"Internal Folder Element DSID",false }, {0x0041,0x00b1,"PAPYRUS",VR::US,VM::VM1_n,"Internal Folder Element Data Set Type",false }, {0x0041,0x00b2,"PAPYRUS",VR::UL,VM::VM1_n,"Internal Offset To Data Set",false }, {0x0041,0x00b3,"PAPYRUS",VR::UL,VM::VM1_n,"Internal Offset To Image",false }, {0x0041,0x0000,"PAPYRUS 3.0",VR::LT,VM::VM1,"Comments",false }, {0x0041,0x0010,"PAPYRUS 3.0",VR::SQ,VM::VM1,"Pointer Sequence",false }, {0x0041,0x0011,"PAPYRUS 3.0",VR::UL,VM::VM1,"Image Pointer",false }, {0x0041,0x0012,"PAPYRUS 3.0",VR::UL,VM::VM1,"Pixel Offset",false }, {0x0041,0x0013,"PAPYRUS 3.0",VR::SQ,VM::VM1,"Image Identifier Sequence",false }, {0x0041,0x0014,"PAPYRUS 3.0",VR::SQ,VM::VM1,"External PAPYRUS-File Reference Sequence",false }, {0x0041,0x0015,"PAPYRUS 3.0",VR::US,VM::VM1,"Number of images",false }, {0x0041,0x0021,"PAPYRUS 3.0",VR::UI,VM::VM1,"Referenced SOP Class UID",false }, {0x0041,0x0022,"PAPYRUS 3.0",VR::UI,VM::VM1,"Referenced SOP Instance UID",false }, {0x0041,0x0031,"PAPYRUS 3.0",VR::LO,VM::VM1,"Referenced File Name",false }, {0x0041,0x0032,"PAPYRUS 3.0",VR::LO,VM::VM1_n,"Referenced File Path",false }, {0x0041,0x0041,"PAPYRUS 3.0",VR::UI,VM::VM1,"Referenced Image SOP Class UID",false }, {0x0041,0x0042,"PAPYRUS 3.0",VR::UI,VM::VM1,"Referenced Image SOP Instance UID",false }, {0x0041,0x0050,"PAPYRUS 3.0",VR::SQ,VM::VM1,"Image Sequence",false }, // UIN: {0x6001,0x0000,"PAPYRUS 3.0",VR::IS,VM::VM1,"Overlay ID",false }, {0x6001,0x0001,"PAPYRUS 3.0",VR::LT,VM::VM1_n,"Linked Overlays",false }, {0x6001,0x0010,"PAPYRUS 3.0",VR::US,VM::VM1,"Overlays Rows",false }, {0x6001,0x0011,"PAPYRUS 3.0",VR::US,VM::VM1,"Overlays Cols",false }, {0x6001,0x0040,"PAPYRUS 3.0",VR::LO,VM::VM1,"Overlays Type",false }, {0x6001,0x0050,"PAPYRUS 3.0",VR::US,VM::VM1,"Overlays Origin",false }, {0x6001,0x0060,"PAPYRUS 3.0",VR::LO,VM::VM1,"Editable",false }, {0x6001,0x0070,"PAPYRUS 3.0",VR::LO,VM::VM1,"Overlay Font",false }, {0x6001,0x0072,"PAPYRUS 3.0",VR::LO,VM::VM1,"Overlay Style",false }, {0x6001,0x0074,"PAPYRUS 3.0",VR::US,VM::VM1,"Overlay Font Size",false }, {0x6001,0x0076,"PAPYRUS 3.0",VR::LO,VM::VM1,"Overlay Color",false }, {0x6001,0x0078,"PAPYRUS 3.0",VR::US,VM::VM1,"Shadow Size",false }, {0x6001,0x0080,"PAPYRUS 3.0",VR::LO,VM::VM1,"Fill Pattern",false }, {0x6001,0x0082,"PAPYRUS 3.0",VR::US,VM::VM1,"Overlay Pen Size",false }, {0x6001,0x00A0,"PAPYRUS 3.0",VR::LO,VM::VM1,"Label",false }, {0x6001,0x00A2,"PAPYRUS 3.0",VR::LT,VM::VM1,"Post It Text",false }, {0x6001,0x00A4,"PAPYRUS 3.0",VR::US,VM::VM1,"Anchor Point",false }, {0x6001,0x00b0,"PAPYRUS 3.0",VR::LO,VM::VM1,"ROI Type",false }, {0x6001,0x00b2,"PAPYRUS 3.0",VR::LT,VM::VM1,"Attached Annotation",false }, {0x6001,0x00ba,"PAPYRUS 3.0",VR::US,VM::VM1_n,"Contour Points",false }, {0x6001,0x00bc,"PAPYRUS 3.0",VR::US,VM::VM1_n,"Mask Data",false }, {0x6001,0x00c0,"PAPYRUS 3.0",VR::SQ,VM::VM1,"UIN Overlay Sequence",false }, {0x0009,0x0010,"PHILIPS MR",VR::LO,VM::VM1,"SPI Release",false }, {0x0009,0x0012,"PHILIPS MR",VR::DA,VM::VM1,"date",false }, {0x0019,0x0000,"PHILIPS MR R5.5/PART",VR::DS,VM::VM1,"Field of View",false }, {0x0019,0x0000,"PHILIPS MR R5.6/PART",VR::DS,VM::VM1,"Field of View",false }, {0x0019,0x0001,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0002,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0003,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0004,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0005,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0006,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0007,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0008,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0009,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0010,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0012,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0013,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0014,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0015,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1_n,"?",false }, {0x0019,0x0016,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0017,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0018,"PHILIPS MR SPECTRO;1",VR::UN,VM::VM1,"?",false }, {0x0019,0x0020,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0021,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0022,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0023,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0024,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0025,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0026,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0027,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0028,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0029,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1_n,"?",false }, {0x0019,0x0031,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0032,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0041,"PHILIPS MR SPECTRO;1",VR::LT,VM::VM1,"?",false }, {0x0019,0x0042,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM2,"?",false }, {0x0019,0x0043,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM2,"?",false }, {0x0019,0x0045,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0046,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0047,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0048,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0049,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0050,"PHILIPS MR SPECTRO;1",VR::UN,VM::VM1,"?",false }, {0x0019,0x0060,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0061,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0070,"PHILIPS MR SPECTRO;1",VR::UN,VM::VM1,"?",false }, {0x0019,0x0071,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1_n,"?",false }, {0x0019,0x0072,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0073,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0074,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0076,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0077,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0078,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0079,"PHILIPS MR SPECTRO;1",VR::US,VM::VM1,"?",false }, {0x0019,0x0080,"PHILIPS MR SPECTRO;1",VR::IS,VM::VM1,"?",false }, {0x0019,0x0009,"PHILIPS MR/LAST",VR::DS,VM::VM1,"Main Magnetic Field",false }, {0x0019,0x000e,"PHILIPS MR/LAST",VR::IS,VM::VM1,"Flow Compensation",false }, {0x0019,0x00b1,"PHILIPS MR/LAST",VR::IS,VM::VM1,"Minimum RR Interval",false }, {0x0019,0x00b2,"PHILIPS MR/LAST",VR::IS,VM::VM1,"Maximum RR Interval",false }, {0x0019,0x00b3,"PHILIPS MR/LAST",VR::IS,VM::VM1,"Number of Rejections",false }, {0x0019,0x00b4,"PHILIPS MR/LAST",VR::IS,VM::VM1_n,"Number of RR Intervals",false }, {0x0019,0x00b5,"PHILIPS MR/LAST",VR::IS,VM::VM1,"Arrhythmia Rejection",false }, {0x0019,0x00b7,"PHILIPS MR/LAST",VR::IS,VM::VM1,"?",false }, {0x0019,0x00c0,"PHILIPS MR/LAST",VR::DS,VM::VM1_n,"?",false }, {0x0019,0x00c6,"PHILIPS MR/LAST",VR::IS,VM::VM1,"Cycled Multiple Slice",false }, {0x0019,0x00ce,"PHILIPS MR/LAST",VR::IS,VM::VM1,"REST",false }, {0x0019,0x00d5,"PHILIPS MR/LAST",VR::DS,VM::VM1,"?",false }, {0x0019,0x00d6,"PHILIPS MR/LAST",VR::IS,VM::VM1,"Fourier Interpolation",false }, {0x0019,0x00d9,"PHILIPS MR/LAST",VR::IS,VM::VM1_n,"?",false }, {0x0019,0x00e0,"PHILIPS MR/LAST",VR::IS,VM::VM1,"Prepulse",false }, {0x0019,0x00e1,"PHILIPS MR/LAST",VR::DS,VM::VM1,"Prepulse Delay",false }, {0x0019,0x00e2,"PHILIPS MR/LAST",VR::IS,VM::VM1,"?",false }, {0x0019,0x00e3,"PHILIPS MR/LAST",VR::DS,VM::VM3,"?",false }, {0x0019,0x00e4,"PHILIPS MR/LAST",VR::IS,VM::VM1,"?",false }, {0x0019,0x00e5,"PHILIPS MR/LAST",VR::DS,VM::VM1,"?",false }, {0x0019,0x00f0,"PHILIPS MR/LAST",VR::LT,VM::VM1,"WS Protocol String 1",false }, {0x0019,0x00f1,"PHILIPS MR/LAST",VR::LT,VM::VM1,"WS Protocol String 2",false }, {0x0019,0x00f2,"PHILIPS MR/LAST",VR::LT,VM::VM1,"WS Protocol String 3",false }, {0x0019,0x00f3,"PHILIPS MR/LAST",VR::LT,VM::VM1,"WS Protocol String 4",false }, {0x0021,0x0000,"PHILIPS MR/LAST",VR::IS,VM::VM1,"?",false }, {0x0021,0x0010,"PHILIPS MR/LAST",VR::IS,VM::VM1,"?",false }, {0x0021,0x0020,"PHILIPS MR/LAST",VR::IS,VM::VM1,"?",false }, {0x0021,0x0021,"PHILIPS MR/LAST",VR::DS,VM::VM1,"Slice Gap",false }, {0x0021,0x0022,"PHILIPS MR/LAST",VR::DS,VM::VM1,"Stack Radial Angle",false }, {0x0027,0x0000,"PHILIPS MR/LAST",VR::US,VM::VM1,"?",false }, {0x0027,0x0011,"PHILIPS MR/LAST",VR::US,VM::VM1_n,"?",false }, {0x0027,0x0012,"PHILIPS MR/LAST",VR::DS,VM::VM1_n,"?",false }, {0x0027,0x0013,"PHILIPS MR/LAST",VR::DS,VM::VM1_n,"?",false }, {0x0027,0x0014,"PHILIPS MR/LAST",VR::DS,VM::VM1_n,"?",false }, {0x0027,0x0015,"PHILIPS MR/LAST",VR::DS,VM::VM1_n,"?",false }, {0x0027,0x0016,"PHILIPS MR/LAST",VR::LO,VM::VM1,"?",false }, {0x0029,0x0010,"PHILIPS MR/LAST",VR::DS,VM::VM1,"FP Min",false }, {0x0029,0x0020,"PHILIPS MR/LAST",VR::DS,VM::VM1,"FP Max",false }, {0x0029,0x0030,"PHILIPS MR/LAST",VR::DS,VM::VM1,"Scaled Minimum",false }, {0x0029,0x0040,"PHILIPS MR/LAST",VR::DS,VM::VM1,"Scaled Maximum",false }, {0x0029,0x0050,"PHILIPS MR/LAST",VR::DS,VM::VM1,"Window Minimum",false }, {0x0029,0x0060,"PHILIPS MR/LAST",VR::DS,VM::VM1,"Window Maximum",false }, {0x0029,0x0061,"PHILIPS MR/LAST",VR::IS,VM::VM1,"?",false }, {0x0029,0x0062,"PHILIPS MR/LAST",VR::IS,VM::VM1,"?",false }, {0x0029,0x0070,"PHILIPS MR/LAST",VR::DS,VM::VM1,"?",false }, {0x0029,0x0071,"PHILIPS MR/LAST",VR::DS,VM::VM1,"?",false }, {0x0029,0x0072,"PHILIPS MR/LAST",VR::IS,VM::VM1,"?",false }, {0x0029,0x0080,"PHILIPS MR/LAST",VR::IS,VM::VM2,"View Center",false }, {0x0029,0x0081,"PHILIPS MR/LAST",VR::IS,VM::VM2,"View Size",false }, {0x0029,0x0082,"PHILIPS MR/LAST",VR::IS,VM::VM1,"View Zoom",false }, {0x0029,0x0083,"PHILIPS MR/LAST",VR::IS,VM::VM1,"View Transform",false }, {0x0041,0x0007,"PHILIPS MR/LAST",VR::LO,VM::VM1,"?",false }, {0x0041,0x0009,"PHILIPS MR/LAST",VR::DS,VM::VM1,"?",false }, {0x6001,0x0000,"PHILIPS MR/LAST",VR::LT,VM::VM1,"?",false }, {0x0019,0x0000,"PHILIPS MR/PART",VR::DS,VM::VM1_2,"Field of View",false }, {0x0019,0x0001,"PHILIPS MR/PART",VR::DS,VM::VM1_n,"Stack Type",false }, {0x0019,0x0002,"PHILIPS MR/PART",VR::DS,VM::VM1_n,"?",false }, {0x0019,0x0003,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x0005,"PHILIPS MR/PART",VR::DS,VM::VM1,"CC Angulation",false }, {0x0019,0x0006,"PHILIPS MR/PART",VR::DS,VM::VM1,"AP Angulation",false }, {0x0019,0x0007,"PHILIPS MR/PART",VR::DS,VM::VM1,"LR Angulation",false }, {0x0019,0x0008,"PHILIPS MR/PART",VR::IS,VM::VM1,"Patient Orientation 1",false }, {0x0019,0x0009,"PHILIPS MR/PART",VR::IS,VM::VM1,"Patient Orientation",false }, {0x0019,0x000a,"PHILIPS MR/PART",VR::IS,VM::VM1,"Slice Orientation",false }, {0x0019,0x000b,"PHILIPS MR/PART",VR::DS,VM::VM1,"LR Offcenter",false }, {0x0019,0x000c,"PHILIPS MR/PART",VR::DS,VM::VM1,"CC Offcenter",false }, {0x0019,0x000d,"PHILIPS MR/PART",VR::DS,VM::VM1,"AP Offcenter",false }, {0x0019,0x000e,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x000f,"PHILIPS MR/PART",VR::IS,VM::VM1,"Number of Slices",false }, {0x0019,0x0010,"PHILIPS MR/PART",VR::DS,VM::VM1,"Slice Factor",false }, {0x0019,0x0011,"PHILIPS MR/PART",VR::DS,VM::VM1_n,"Echo Times",false }, {0x0019,0x0014,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x0015,"PHILIPS MR/PART",VR::IS,VM::VM1,"Dynamic Study",false }, {0x0019,0x0018,"PHILIPS MR/PART",VR::DS,VM::VM1,"Heartbeat Interval",false }, {0x0019,0x0019,"PHILIPS MR/PART",VR::DS,VM::VM1,"Repetition Time FFE",false }, {0x0019,0x001a,"PHILIPS MR/PART",VR::DS,VM::VM1,"FFE Flip Angle",false }, {0x0019,0x001b,"PHILIPS MR/PART",VR::IS,VM::VM1,"Number of Scans",false }, {0x0019,0x001c,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x001d,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x001e,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x0021,"PHILIPS MR/PART",VR::DS,VM::VM1_n,"?",false }, {0x0019,0x0022,"PHILIPS MR/PART",VR::DS,VM::VM1,"Dynamic Scan Time Begin",false }, {0x0019,0x0023,"PHILIPS MR/PART",VR::DS,VM::VM1_n,"?",false }, {0x0019,0x0024,"PHILIPS MR/PART",VR::IS,VM::VM1_n,"?",false }, {0x0019,0x0025,"PHILIPS MR/PART",VR::DS,VM::VM1_n,"?",false }, {0x0019,0x0026,"PHILIPS MR/PART",VR::DS,VM::VM1_n,"?",false }, {0x0019,0x0027,"PHILIPS MR/PART",VR::DS,VM::VM1_n,"?",false }, {0x0019,0x0028,"PHILIPS MR/PART",VR::LO,VM::VM1_n,"?",false }, {0x0019,0x0029,"PHILIPS MR/PART",VR::DS,VM::VM1_n,"?",false }, {0x0019,0x0030,"PHILIPS MR/PART",VR::LO,VM::VM1_n,"?",false }, {0x0019,0x0031,"PHILIPS MR/PART",VR::DS,VM::VM1_n,"?",false }, {0x0019,0x0040,"PHILIPS MR/PART",VR::US,VM::VM1,"?",false }, {0x0019,0x0045,"PHILIPS MR/PART",VR::IS,VM::VM1,"Reconstruction Resolution",false }, {0x0019,0x0050,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x0051,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x0052,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x0053,"PHILIPS MR/PART",VR::IS,VM::VM1,"?",false }, {0x0019,0x0054,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x0055,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x0056,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x0057,"PHILIPS MR/PART",VR::US,VM::VM1,"?",false }, {0x0019,0x0058,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x0059,"PHILIPS MR/PART",VR::US,VM::VM1,"?",false }, {0x0019,0x0060,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x0061,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x0062,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x0063,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x0064,"PHILIPS MR/PART",VR::DS,VM::VM1,"Repetition Time SE",false }, {0x0019,0x0065,"PHILIPS MR/PART",VR::DS,VM::VM1,"Repetition Time IR",false }, {0x0019,0x0066,"PHILIPS MR/PART",VR::US,VM::VM1,"?",false }, {0x0019,0x0067,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x0069,"PHILIPS MR/PART",VR::IS,VM::VM1,"Number of Phases",false }, {0x0019,0x006a,"PHILIPS MR/PART",VR::IS,VM::VM1,"Cardiac Frequency",false }, {0x0019,0x006b,"PHILIPS MR/PART",VR::DS,VM::VM1,"Inversion Delay",false }, {0x0019,0x006c,"PHILIPS MR/PART",VR::DS,VM::VM1,"Gate Delay",false }, {0x0019,0x006d,"PHILIPS MR/PART",VR::DS,VM::VM1,"Gate Width",false }, {0x0019,0x006e,"PHILIPS MR/PART",VR::DS,VM::VM1,"Trigger Delay Time",false }, {0x0019,0x0070,"PHILIPS MR/PART",VR::DS,VM::VM1_n,"?",false }, {0x0019,0x0080,"PHILIPS MR/PART",VR::IS,VM::VM1,"Number of Chemical Shifts",false }, {0x0019,0x0081,"PHILIPS MR/PART",VR::DS,VM::VM1,"Chemical Shift",false }, {0x0019,0x0084,"PHILIPS MR/PART",VR::IS,VM::VM1,"Number of Rows",false }, {0x0019,0x0085,"PHILIPS MR/PART",VR::IS,VM::VM1,"Number of Samples",false }, {0x0019,0x008a,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x008b,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x008c,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x008d,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x008e,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x008f,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x0090,"PHILIPS MR/PART",VR::IS,VM::VM1,"?",false }, {0x0019,0x0091,"PHILIPS MR/PART",VR::IS,VM::VM1,"?",false }, {0x0019,0x0092,"PHILIPS MR/PART",VR::IS,VM::VM1,"?",false }, {0x0019,0x0093,"PHILIPS MR/PART",VR::IS,VM::VM1,"?",false }, {0x0019,0x0094,"PHILIPS MR/PART",VR::LO,VM::VM1,"Magnetization Transfer Contrast",false }, {0x0019,0x0095,"PHILIPS MR/PART",VR::LO,VM::VM1,"Spectral Presaturation With Inversion Recovery",false }, {0x0019,0x0096,"PHILIPS MR/PART",VR::IS,VM::VM1,"?",false }, {0x0019,0x0097,"PHILIPS MR/PART",VR::LO,VM::VM1,"?",false }, {0x0019,0x0099,"PHILIPS MR/PART",VR::LO,VM::VM1,"?",false }, {0x0019,0x00a0,"PHILIPS MR/PART",VR::IS,VM::VM1,"?",false }, {0x0019,0x00a1,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x00a3,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x00a4,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x00b4,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x00b5,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x00b6,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x00c0,"PHILIPS MR/PART",VR::DS,VM::VM1,"Trigger Delay Times",false }, {0x0019,0x00c8,"PHILIPS MR/PART",VR::IS,VM::VM1,"?",false }, {0x0019,0x00c9,"PHILIPS MR/PART",VR::IS,VM::VM1,"Foldover Direction Transverse",false }, {0x0019,0x00ca,"PHILIPS MR/PART",VR::IS,VM::VM1,"Foldover Direction Sagittal",false }, {0x0019,0x00cb,"PHILIPS MR/PART",VR::IS,VM::VM1,"Foldover Direction Coronal",false }, {0x0019,0x00cc,"PHILIPS MR/PART",VR::IS,VM::VM1,"?",false }, {0x0019,0x00cd,"PHILIPS MR/PART",VR::IS,VM::VM1,"?",false }, {0x0019,0x00ce,"PHILIPS MR/PART",VR::IS,VM::VM1,"?",false }, {0x0019,0x00cf,"PHILIPS MR/PART",VR::IS,VM::VM1,"Number of Echoes",false }, {0x0019,0x00d0,"PHILIPS MR/PART",VR::IS,VM::VM1,"Scan Resolution",false }, {0x0019,0x00d1,"PHILIPS MR/PART",VR::US,VM::VM1,"?",false }, {0x0019,0x00d2,"PHILIPS MR/PART",VR::LO,VM::VM2,"Water Fat Shift",false }, {0x0019,0x00d3,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0019,0x00d4,"PHILIPS MR/PART",VR::IS,VM::VM1,"Artifact Reduction",false }, {0x0019,0x00d5,"PHILIPS MR/PART",VR::IS,VM::VM1,"?",false }, {0x0019,0x00d6,"PHILIPS MR/PART",VR::IS,VM::VM1,"?",false }, {0x0019,0x00d7,"PHILIPS MR/PART",VR::DS,VM::VM1,"Scan Percentage",false }, {0x0019,0x00d8,"PHILIPS MR/PART",VR::IS,VM::VM1,"Halfscan",false }, {0x0019,0x00d9,"PHILIPS MR/PART",VR::IS,VM::VM1,"EPI Factor",false }, {0x0019,0x00da,"PHILIPS MR/PART",VR::IS,VM::VM1,"Turbo Factor",false }, {0x0019,0x00db,"PHILIPS MR/PART",VR::IS,VM::VM1,"?",false }, {0x0019,0x00e0,"PHILIPS MR/PART",VR::IS,VM::VM1,"Percentage of Scan Completed",false }, {0x0019,0x00e1,"PHILIPS MR/PART",VR::IS,VM::VM1,"Prepulse Delay",false }, {0x0019,0x00e3,"PHILIPS MR/PART",VR::DS,VM::VM1,"Phase Contrast Velocity",false }, {0x0019,0x00f0,"PHILIPS MR/PART",VR::IS,VM::VM1,"?",false }, {0x0019,0x00f6,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x00f7,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x00f8,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x00f9,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x00fa,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x00fb,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0019,0x00fc,"PHILIPS MR/PART",VR::CS,VM::VM1,"Resonance Frequency",false }, {0x0019,0x00fe,"PHILIPS MR/PART",VR::CS,VM::VM1,"Resonance Frequency",false }, {0x0021,0x0000,"PHILIPS MR/PART",VR::DA,VM::VM1,"Scan Date",false }, {0x0021,0x0006,"PHILIPS MR/PART",VR::LO,VM::VM1,"?",false }, {0x0021,0x0007,"PHILIPS MR/PART",VR::DT,VM::VM1,"?",false }, {0x0021,0x0008,"PHILIPS MR/PART",VR::LO,VM::VM1,"?",false }, {0x0021,0x0009,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0021,0x000a,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0021,0x000f,"PHILIPS MR/PART",VR::LO,VM::VM1,"?",false }, {0x0021,0x0010,"PHILIPS MR/PART",VR::IS,VM::VM1,"Image Type",false }, {0x0021,0x0013,"PHILIPS MR/PART",VR::CS,VM::VM1,"?",false }, {0x0021,0x0014,"PHILIPS MR/PART",VR::LO,VM::VM1,"?",false }, {0x0021,0x0015,"PHILIPS MR/PART",VR::US,VM::VM1,"?",false }, {0x0021,0x0020,"PHILIPS MR/PART",VR::IS,VM::VM1,"Slice Number",false }, {0x0021,0x0021,"PHILIPS MR/PART",VR::IS,VM::VM1,"Slice Gap",false }, {0x0021,0x0030,"PHILIPS MR/PART",VR::IS,VM::VM1,"Echo Number",false }, {0x0021,0x0031,"PHILIPS MR/PART",VR::DS,VM::VM1,"Patient Reference ID",false }, {0x0021,0x0035,"PHILIPS MR/PART",VR::IS,VM::VM1,"Chemical Shift Number",false }, {0x0021,0x0040,"PHILIPS MR/PART",VR::IS,VM::VM1,"Phase Number",false }, {0x0021,0x0050,"PHILIPS MR/PART",VR::IS,VM::VM1,"Dynamic Scan Number",false }, {0x0021,0x0060,"PHILIPS MR/PART",VR::IS,VM::VM1,"Number of Rows In Object",false }, {0x0021,0x0061,"PHILIPS MR/PART",VR::IS,VM::VM1_n,"Row Number",false }, {0x0021,0x0062,"PHILIPS MR/PART",VR::IS,VM::VM1_n,"?",false }, {0x0029,0x0000,"PHILIPS MR/PART",VR::DS,VM::VM2,"?",false }, {0x0029,0x0004,"PHILIPS MR/PART",VR::US,VM::VM1,"?",false }, {0x0029,0x0010,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0029,0x0011,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0029,0x0020,"PHILIPS MR/PART",VR::LO,VM::VM1,"?",false }, {0x0029,0x0031,"PHILIPS MR/PART",VR::DS,VM::VM2,"?",false }, {0x0029,0x0032,"PHILIPS MR/PART",VR::DS,VM::VM2,"?",false }, {0x0029,0x0050,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0029,0x0051,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0029,0x0052,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0029,0x0053,"PHILIPS MR/PART",VR::DS,VM::VM1,"?",false }, {0x0029,0x00c3,"PHILIPS MR/PART",VR::IS,VM::VM1,"Scan Resolution",false }, {0x0029,0x00c4,"PHILIPS MR/PART",VR::IS,VM::VM1,"Field of View",false }, {0x0029,0x00d5,"PHILIPS MR/PART",VR::LT,VM::VM1,"Slice Thickness",false }, {0x0009,0x0010,"PHILIPS MR/PART 12",VR::US,VM::VM1,"?",false }, {0x0019,0x0010,"PHILIPS MR/PART 6",VR::IS,VM::VM1,"?",false }, {0x0019,0x0000,"PHILIPS MR/PART 7",VR::IS,VM::VM1,"?",false }, {0x7051,0x0000,"PHILIPS NM -Private",VR::US,VM::VM1,"Current Segment",false }, {0x7051,0x0001,"PHILIPS NM -Private",VR::US,VM::VM1,"Number of Segments",false }, {0x7051,0x0002,"PHILIPS NM -Private",VR::FL,VM::VM1,"Segment Start Position",false }, {0x7051,0x0003,"PHILIPS NM -Private",VR::FL,VM::VM1,"Segment Stop Position",false }, {0x7051,0x0004,"PHILIPS NM -Private",VR::FL,VM::VM1,"Rel. COR offset - X dir.",false }, {0x7051,0x0005,"PHILIPS NM -Private",VR::FL,VM::VM1,"Rel. COR offset - Z dir.",false }, {0x7051,0x0006,"PHILIPS NM -Private",VR::US,VM::VM1,"Current Rotation Number",false }, {0x7051,0x0007,"PHILIPS NM -Private",VR::US,VM::VM1,"Number of Rotations",false }, {0x7051,0x0010,"PHILIPS NM -Private",VR::DS,VM::VM3,"Alignment Translations",false }, {0x7051,0x0011,"PHILIPS NM -Private",VR::DS,VM::VM3,"Alignment Rotations",false }, {0x7051,0x0012,"PHILIPS NM -Private",VR::DS,VM::VM1,"Alignment Timestamp",false }, {0x7051,0x0015,"PHILIPS NM -Private",VR::UI,VM::VM1,"Related Xray Series Instance UID",false }, {0x7051,0x0016,"PHILIPS NM -Private",VR::UI,VM::VM1,"?UID?",false }, {0x7051,0x0025,"PHILIPS NM -Private",VR::LO,VM::VM1,"??",false }, {0x7051,0x0026,"PHILIPS NM -Private",VR::DS,VM::VM1,"??",false }, {0x7051,0x0027,"PHILIPS NM -Private",VR::DS,VM::VM1,"??",false }, {0x7051,0x0028,"PHILIPS NM -Private",VR::IS,VM::VM1,"??",false }, {0x7051,0x0029,"PHILIPS NM -Private",VR::IS,VM::VM1,"??",false }, {0x7051,0x0001,"PHILIPS XCT -Private",VR::DS,VM::VM1,"Attenuation threshold",false }, {0x7051,0x0002,"PHILIPS XCT -Private",VR::DS,VM::VM1,"DLP Estimate",false }, {0x7051,0x0003,"PHILIPS XCT -Private",VR::LO,VM::VM1,"??",false }, {0x5503,0x0012,"PHILIPS UNDOCUMENTED",VR::SL,VM::VM1,"Slice Thickness",false }, {0x5503,0x0024,"PHILIPS UNDOCUMENTED",VR::UT,VM::VM1,"Plane",false }, {0x5503,0x0030,"PHILIPS UNDOCUMENTED",VR::SS,VM::VM1,"Number of Slices",false }, {0x5503,0x00a5,"PHILIPS UNDOCUMENTED",VR::UT,VM::VM1,"Prepulse",false }, {0x5503,0x00ae,"PHILIPS UNDOCUMENTED",VR::SS,VM::VM1,"Contrast Agent Flag",false }, {0x5503,0x00bb,"PHILIPS UNDOCUMENTED",VR::SL,VM::VM1,"Coil ID",false }, {0x5503,0x00c2,"PHILIPS UNDOCUMENTED",VR::UT,VM::VM1,"Anatomy",false }, {0x5503,0x00c3,"PHILIPS UNDOCUMENTED",VR::UT,VM::VM1,"Indication",false }, {0x2001,0x0001,"PHILIPS UNKNOWN",VR::UN,VM::VM1,"MRSeriesNrOfEchoes",false }, {0x2001,0x0002,"PHILIPS UNKNOWN",VR::UN,VM::VM1,"MRSeriesScanningTechniqueDescription",false }, {0x2001,0x0005,"PHILIPS UNKNOWN",VR::UN,VM::VM1,"StackSequence",false }, {0x2001,0x0006,"PHILIPS UNKNOWN",VR::UN,VM::VM1,"Examination Source",false }, {0x2001,0x0007,"PHILIPS UNKNOWN",VR::UN,VM::VM1,"MRSeriesAcquisitionNumber",false }, {0x2001,0x0008,"PHILIPS UNKNOWN",VR::UN,VM::VM1,"MRSeriesNrOfDynamicScans",false }, {0x2005,0x0002,"PHILIPS UNKNOWN",VR::UN,VM::VM1,"MRSeriesNrOfChemicalShifts",false }, {0x2005,0x0003,"PHILIPS UNKNOWN",VR::UN,VM::VM1,"MRSeriesRepetitionTime",false }, {0x2005,0x0036,"PHILIPS UNKNOWN",VR::UN,VM::VM1,"MRVolumeSelection",false }, {0x0019,0x0011,"PHILIPS-MR-1",VR::IS,VM::VM1,"Chemical Shift Number",false }, {0x0019,0x0012,"PHILIPS-MR-1",VR::IS,VM::VM1,"Phase Number (Philips)",false }, {0x0021,0x0001,"PHILIPS-MR-1",VR::IS,VM::VM1,"Reconstruction Number",false }, {0x0021,0x0002,"PHILIPS-MR-1",VR::IS,VM::VM1,"Slice Number",false }, {0x0055,0x0001,"PMOD_1",VR::FD,VM::VM1_n,"Frame Start Times Vector",false }, {0x0055,0x0002,"PMOD_1",VR::FD,VM::VM3_3n,"Frame Positions Vector",false }, {0x0055,0x0003,"PMOD_1",VR::FD,VM::VM6_6n,"Frame Orientations Vector",false }, {0x0055,0x0004,"PMOD_1",VR::FD,VM::VM1_n,"Frame Durations (ms) Vector",false }, {0x0055,0x0005,"PMOD_1",VR::FD,VM::VM1_n,"Frame Rescale Slope Vector",false }, {0x7fe1,0x0001,"PMOD_GENPET",VR::UT,VM::VM1,"Slices Names",false }, {0x7fe1,0x0002,"PMOD_GENPET",VR::UT,VM::VM1,"Gene Codes",false }, {0x7fe1,0x0003,"PMOD_GENPET",VR::UT,VM::VM1,"Gene Labels",false }, {0x0089,0x0020,"PMS-THORA-5.1",VR::SQ,VM::VM1,"Stamp Image Sequence",false }, {0x0029,0x0001,"PMTF INFORMATION DATA",VR::SQ,VM::VM1,"?DTI Seq?",false }, {0x0029,0x0031,"PMTF INFORMATION DATA",VR::LO,VM::VM1,"PMTF Information 1",false }, {0x0029,0x0032,"PMTF INFORMATION DATA",VR::UL,VM::VM1,"PMTF Information 2",false }, {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 }, {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 }, {0x0009,0x0004,"POLYTRON-SMS 2.5",VR::UN,VM::VM1,"Private Data 3",false }, {0x0009,0x0006,"POLYTRON-SMS 2.5",VR::UN,VM::VM1,"Private Data 3",false }, {0x0009,0x0010,"POLYTRON-SMS 2.5",VR::UN,VM::VM1,"Private Data 4",false }, {0x0009,0x0011,"POLYTRON-SMS 2.5",VR::UN,VM::VM1,"Private Data 5",false }, {0x0009,0x0012,"POLYTRON-SMS 2.5",VR::UN,VM::VM1,"Private Data 6",false }, {0x0089,0x0010,"POLYTRON-SMS 2.5",VR::UN,VM::VM1,"Private Data",false }, {0x0021,0x0001,"PRIVATE ORIGINAL ATTRIBUTES",VR::SQ,VM::VM1,"Private Original Attribute Sequence",false }, {0x0021,0x0005,"PRIVATE ORIGINAL ATTRIBUTES",VR::DT,VM::VM1,"Replacement Date and Time",false }, {0x0021,0x0010,"PRIVATE ORIGINAL ATTRIBUTES",VR::LO,VM::VM1,"Replacement Originator Name",false }, {0x0021,0x0012,"PRIVATE ORIGINAL ATTRIBUTES",VR::LO,VM::VM1,"Replacement Reason",false }, {0x0021,0x0070,"PRIVATE ORIGINAL ATTRIBUTES",VR::PN,VM::VM1_n,"Original Operators'Name",false }, {0x2007,0x00b4,"Philips EV Imaging DD 017",VR::FL,VM::VM2,"?",false }, {0x2007,0x00ba,"Philips EV Imaging DD 017",VR::FD,VM::VM1,"?",false }, {0x2007,0x00bb,"Philips EV Imaging DD 017",VR::FD,VM::VM1,"?",false }, {0x2007,0x00bc,"Philips EV Imaging DD 017",VR::SL,VM::VM1,"?",false }, {0x2007,0x00d0,"Philips EV Imaging DD 017",VR::FD,VM::VM1,"?",false }, {0x2007,0x00d1,"Philips EV Imaging DD 017",VR::FD,VM::VM1,"?",false }, {0x2007,0x00d2,"Philips EV Imaging DD 017",VR::SL,VM::VM1,"?",false }, {0x2007,0x00c1,"Philips EV Imaging DD 017",VR::UI,VM::VM1,"? SOP Instance UID ?",false }, {0x2007,0x00c2,"Philips EV Imaging DD 017",VR::DA,VM::VM1,"?",false }, {0x2007,0x00c3,"Philips EV Imaging DD 017",VR::TM,VM::VM1,"?",false }, {0x2007,0x00c4,"Philips EV Imaging DD 017",VR::UL,VM::VM1,"?",false }, {0x2007,0x0000,"Philips EV Imaging DD 019",VR::LO,VM::VM1,"?",false }, {0x2007,0x0001,"Philips EV Imaging DD 019",VR::UT,VM::VM1,"?",false }, {0x2007,0x0004,"Philips EV Imaging DD 021",VR::SL,VM::VM1,"Vol Seg Edit Connectivity",false }, {0x2007,0x0051,"Philips EV Imaging DD 021",VR::US_SS,VM::VM1,"?US or SS?",false }, {0x2007,0x0000,"Philips EV Imaging DD 022",VR::ST,VM::VM1,"?",false }, {0x2007,0x0001,"Philips EV Imaging DD 022",VR::LO,VM::VM2,"?",false }, {0x2007,0x0012,"Philips EV Imaging DD 022",VR::LO,VM::VM1,"Volume Sequence Capture",false }, {0x2007,0x0017,"Philips EV Imaging DD 022",VR::UI,VM::VM1,"Original SOP Instance",false }, {0x2007,0x0033,"Philips EV Imaging DD 022",VR::LO,VM::VM1,"?",false }, {0x2007,0x0034,"Philips EV Imaging DD 022",VR::CS,VM::VM1,"?",false }, {0x7777,0x0001,"Philips EnVisor",VR::DA,VM::VM1,"Date 3D/PanView internal 'dataset' file was acquired",false }, {0x7777,0x0002,"Philips EnVisor",VR::CS,VM::VM1,"Type of 3D or PanView",false }, {0x7777,0x0003,"Philips EnVisor",VR::LO,VM::VM1,"Internal 3D/PanView software version number",false }, {0x7777,0x0014,"Philips EnVisor",VR::LT,VM::VM1,"Private string",false }, {0x2001,0x0001,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"Chemical Shift",false }, {0x2001,0x0002,"PHILIPS IMAGING DD 001",VR::IS,VM::VM1,"Chemical Shift Number MR",false }, {0x2001,0x0003,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"Diffusion B-Factor",false }, {0x2001,0x0004,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Diffusion Direction",false }, {0x2001,0x0005,"PHILIPS IMAGING DD 001",VR::SS,VM::VM1,"Graphic Annotation Parent ID",false }, {0x2001,0x0006,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Image Enhanced",false }, {0x2001,0x0007,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Image Type ED ES",false }, {0x2001,0x0008,"PHILIPS IMAGING DD 001",VR::IS,VM::VM1,"Phase Number",false }, {0x2001,0x0009,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"MRImagePrepulseDelay",false }, {0x2001,0x000a,"PHILIPS IMAGING DD 001",VR::IS,VM::VM1,"Slice Number MR (aka ImagePlaneNumber)",false }, {0x2001,0x000b,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Slice Orientation (aka ImagePlaneOrientation)",false }, {0x2001,0x000c,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"?MRSeriesArrhythmiaRejection",false }, {0x2001,0x000e,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"?MRSeriesCardiacCycled",false }, {0x2001,0x000f,"PHILIPS IMAGING DD 001",VR::SS,VM::VM1,"?MRSeriesCardiacGateWidth",false }, {0x2001,0x0010,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Cardiac Sync",false }, {0x2001,0x0011,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"Diffusion Echo Time",false }, {0x2001,0x0012,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Dynamic Series",false }, {0x2001,0x0013,"PHILIPS IMAGING DD 001",VR::SL,VM::VM1,"EPI Factor",false }, {0x2001,0x0014,"PHILIPS IMAGING DD 001",VR::SL,VM::VM1,"Number of Echoes",false }, {0x2001,0x0015,"PHILIPS IMAGING DD 001",VR::SS,VM::VM1,"Number of Locations",false }, {0x2001,0x0016,"PHILIPS IMAGING DD 001",VR::SS,VM::VM1,"Number of PC Directions",false }, {0x2001,0x0017,"PHILIPS IMAGING DD 001",VR::SL,VM::VM1,"Number of Phases MR",false }, {0x2001,0x0018,"PHILIPS IMAGING DD 001",VR::SL,VM::VM1,"Number of Slices MR",false }, {0x2001,0x0019,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Partial Matrix Scanned",false }, {0x2001,0x001a,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1_n,"PC Velocity",false }, {0x2001,0x001b,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"Prepulse Delay",false }, {0x2001,0x001c,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Prepulse Type",false }, {0x2001,0x001d,"PHILIPS IMAGING DD 001",VR::IS,VM::VM1,"Reconstruction Number MR",false }, {0x2001,0x001e,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"?MRSeriesReformatAccuracy",false }, {0x2001,0x001f,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Respiration Sync",false }, {0x2001,0x0020,"PHILIPS IMAGING DD 001",VR::LO,VM::VM1,"Scanning Technique Description MR",false }, {0x2001,0x0021,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"SPIR",false }, {0x2001,0x0022,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"Water Fat Shift",false }, {0x2001,0x0023,"PHILIPS IMAGING DD 001",VR::DS,VM::VM1,"Flip Angle Philips",false }, {0x2001,0x0024,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Interactive",false }, {0x2001,0x0025,"PHILIPS IMAGING DD 001",VR::SH,VM::VM1,"Echo Time Display MR",false }, {0x2001,0x0026,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Presentation State Subtraction Active",false }, {0x2001,0x0028,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"Edge Enhancement Gain Factor Sub",false }, {0x2001,0x0029,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"Edge Enhancement Gain Factor Non Sub",false }, {0x2001,0x002a,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Edge Enhancement Taste Adapt Sub",false }, {0x2001,0x002b,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Edge Enhancement Taste Non Sub",false }, {0x2001,0x002c,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"Harmonization Factor",false }, {0x2001,0x002d,"PHILIPS IMAGING DD 001",VR::SS,VM::VM1,"Number of Stack Slices",false }, {0x2001,0x002f,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"Harmonization Gain",false }, {0x2001,0x0030,"PHILIPS IMAGING DD 001",VR::UL,VM::VM1,"Log Subtraction Gain Step",false }, {0x2001,0x0031,"PHILIPS IMAGING DD 001",VR::US,VM::VM1,"Mixing NR of Mask Image Numbers",false }, {0x2001,0x0032,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1_n,"Stack Radial Angle",false }, {0x2001,0x0033,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1_n,"Stack Radial Axis",false }, {0x2001,0x0034,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Mixing Mask Operation",false }, {0x2001,0x0035,"PHILIPS IMAGING DD 001",VR::SS,VM::VM1_n,"Stack Slice Number",false }, {0x2001,0x0036,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1_n,"Stack Type",false }, {0x2001,0x0037,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Mixing Operation Type",false }, {0x2001,0x0039,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"?",false }, {0x2001,0x003a,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Pixel Shift",false }, {0x2001,0x003d,"PHILIPS IMAGING DD 001",VR::UL,VM::VM1,"?ContourFillColor",false }, {0x2001,0x003f,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Interpolation Method",false }, {0x2001,0x0042,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Subtraction Land Marking Active",false }, {0x2001,0x0046,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Graphic Line Style",false }, {0x2001,0x0047,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"Graphic Line Width",false }, {0x2001,0x0048,"PHILIPS IMAGING DD 001",VR::SS,VM::VM1,"Graphic Annotation ID",false }, {0x2001,0x004b,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Poly Line Interpolation Method",false }, {0x2001,0x004c,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Poly Line Begin Point Style",false }, {0x2001,0x004d,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Poly Line End Point Style",false }, {0x2001,0x004e,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Window Smoothing Taste",false }, {0x2001,0x004f,"PHILIPS IMAGING DD 001",VR::FD,VM::VM1,"Harmonization Offset",false }, {0x2001,0x0050,"PHILIPS IMAGING DD 001",VR::LO,VM::VM1,"?GraphicMarkerType",false }, {0x2001,0x0051,"PHILIPS IMAGING DD 001",VR::IS,VM::VM1,"?OverlayPlaneID",false }, {0x2001,0x0052,"PHILIPS IMAGING DD 001",VR::UI,VM::VM1,"?ImagePresentationStateUID",false }, {0x2001,0x0053,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Window Invert",false }, {0x2001,0x0055,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Graphic Line Color",false }, {0x2001,0x0056,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Graphic Type (Private)",false }, {0x2001,0x005a,"PHILIPS IMAGING DD 001",VR::ST,VM::VM1,"Graphic Annotation Model",false }, {0x2001,0x005d,"PHILIPS IMAGING DD 001",VR::ST,VM::VM1,"Measurement Text Units",false }, {0x2001,0x005e,"PHILIPS IMAGING DD 001",VR::ST,VM::VM1,"Measurement Text Type",false }, {0x2001,0x005f,"PHILIPS IMAGING DD 001",VR::SQ,VM::VM1,"Stack Sequence",false }, {0x2001,0x0060,"PHILIPS IMAGING DD 001",VR::SL,VM::VM1,"Number of Stacks",false }, {0x2001,0x0061,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"?SeriesTransmitted",false }, {0x2001,0x0062,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"?SeriesCommitted",false }, {0x2001,0x0063,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Examination Source",false }, {0x2001,0x0064,"PHILIPS IMAGING DD 001",VR::SH,VM::VM1,"Text Type",false }, {0x2001,0x0065,"PHILIPS IMAGING DD 001",VR::SQ,VM::VM1,"?GraphicOverlayPlane",false }, {0x2001,0x0067,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"?",false }, {0x2001,0x0068,"PHILIPS IMAGING DD 001",VR::SQ,VM::VM1,"?LinearModalityGLTrafo",false }, {0x2001,0x0069,"PHILIPS IMAGING DD 001",VR::SQ,VM::VM1,"Display Shutter Sequence",false }, {0x2001,0x006a,"PHILIPS IMAGING DD 001",VR::SQ,VM::VM1,"?SpatialTransformation",false }, {0x2001,0x006b,"PHILIPS IMAGING DD 001",VR::SQ,VM::VM1,"Has Edge Enhancement Sequence",false }, {0x2001,0x006d,"PHILIPS IMAGING DD 001",VR::LO,VM::VM1,"Text Font",false }, {0x2001,0x006e,"PHILIPS IMAGING DD 001",VR::SH,VM::VM1,"Series Type",false }, {0x2001,0x006f,"PHILIPS IMAGING DD 001",VR::SQ,VM::VM1,"Mixing Sequence",false }, {0x2001,0x0071,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"?GraphicConstraint",false }, {0x2001,0x0073,"PHILIPS IMAGING DD 001",VR::SQ,VM::VM1,"Referenced Mask Image Sequence",false }, {0x2001,0x0074,"PHILIPS IMAGING DD 001",VR::DS,VM::VM1_n,"Window Center Sub",false }, {0x2001,0x0075,"PHILIPS IMAGING DD 001",VR::DS,VM::VM1_n,"Window Width Sub",false }, {0x2001,0x0076,"PHILIPS IMAGING DD 001",VR::UL,VM::VM1,"?MRNumberOfFrames",false }, {0x2001,0x0077,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"GL TrafoType",false }, {0x2001,0x0079,"PHILIPS IMAGING DD 001",VR::SQ,VM::VM1,"Harmonisation Sequence",false }, {0x2001,0x007a,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"?WindowRoundingFactor",false }, {0x2001,0x007b,"PHILIPS IMAGING DD 001",VR::IS,VM::VM1,"Acquisition Number",false }, {0x2001,0x007e,"PHILIPS IMAGING DD 001",VR::US,VM::VM1,"Edge Enhancement Gain Taste",false }, {0x2001,0x007f,"PHILIPS IMAGING DD 001",VR::US,VM::VM1,"Edge Enhancement Gain Taste Sub",false }, {0x2001,0x0080,"PHILIPS IMAGING DD 001",VR::LO,VM::VM1,"Text Anchor Point Alignment",false }, {0x2001,0x0081,"PHILIPS IMAGING DD 001",VR::IS,VM::VM1,"Number of Dynamic Scans",false }, {0x2001,0x0082,"PHILIPS IMAGING DD 001",VR::IS,VM::VM1,"Echo Train Length",false }, {0x2001,0x0083,"PHILIPS IMAGING DD 001",VR::DS,VM::VM1,"Imaging Frequency",false }, {0x2001,0x0084,"PHILIPS IMAGING DD 001",VR::DS,VM::VM1,"Inversion Time",false }, {0x2001,0x0085,"PHILIPS IMAGING DD 001",VR::DS,VM::VM1,"Magnetic Field Strength",false }, {0x2001,0x0086,"PHILIPS IMAGING DD 001",VR::IS,VM::VM1,"?NrOfPhaseEncodingSteps?",false }, {0x2001,0x0087,"PHILIPS IMAGING DD 001",VR::SH,VM::VM1,"Imaged Nucleus",false }, {0x2001,0x0088,"PHILIPS IMAGING DD 001",VR::DS,VM::VM1,"Number of Averages",false }, {0x2001,0x0089,"PHILIPS IMAGING DD 001",VR::DS,VM::VM1,"Phase FOV Percent",false }, {0x2001,0x008a,"PHILIPS IMAGING DD 001",VR::DS,VM::VM1,"Sampling Percent",false }, {0x2001,0x008b,"PHILIPS IMAGING DD 001",VR::SH,VM::VM1,"?Transmitting Coil?",false }, {0x2001,0x0093,"PHILIPS IMAGING DD 001",VR::LO,VM::VM1,"Text Style",false }, {0x2001,0x0094,"PHILIPS IMAGING DD 001",VR::LO,VM::VM1,"Processing Order Specialization",false }, {0x2001,0x0097,"PHILIPS IMAGING DD 001",VR::SH,VM::VM1,"Nucleus",false }, {0x2001,0x009a,"PHILIPS IMAGING DD 001",VR::SQ,VM::VM1,"Graphic Number Sequence",false }, {0x2001,0x009b,"PHILIPS IMAGING DD 001",VR::UL,VM::VM1,"Graphic Number",false }, {0x2001,0x009c,"PHILIPS IMAGING DD 001",VR::LO,VM::VM1,"?GraphicAnnotationLabel",false }, {0x2001,0x009d,"PHILIPS IMAGING DD 001",VR::LO,VM::VM1,"PIIM Subtraction Type",false }, {0x2001,0x009f,"PHILIPS IMAGING DD 001",VR::US,VM::VM2,"Pixel Processing Kernel Size",false }, {0x2001,0x00a1,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Is Raw Image",false }, {0x2001,0x00a2,"PHILIPS IMAGING DD 001",VR::US,VM::VM1,"LOG Subtraction Curve Taste",false }, {0x2001,0x00a3,"PHILIPS IMAGING DD 001",VR::UL,VM::VM1,"Text Color Foreground",false }, {0x2001,0x00a4,"PHILIPS IMAGING DD 001",VR::UL,VM::VM1,"Text Color Background",false }, {0x2001,0x00a5,"PHILIPS IMAGING DD 001",VR::UL,VM::VM1,"Text Color Shadow",false }, {0x2001,0x00c1,"PHILIPS IMAGING DD 001",VR::LO,VM::VM1,"Nested Object Type Name",false }, {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,0x00f1,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1_n,"Prospective Motion Correction",false }, {0x2001,0x00f2,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"Retrospective Motion Correction",false }, // {0x2005,0x0014,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Diffusion",false }, // {0x2005,0x0020,"PHILIPS IMAGING DD 001",VR::SL,VM::VM1,"Number of Chemical Shifts",false }, // {0x2005,0x0030,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"Repetition Time",false }, // {0x2005,0x0033,"PHILIPS IMAGING DD 001",VR::FL,VM::VM1,"Scan Duration",false }, // {0x2005,0x0035,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Data Type",false }, // {0x2005,0x008b,"PHILIPS IMAGING DD 001",VR::SH,VM::VM1,"Transmitting Coil",false }, // {0x2005,0x009f,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Spectral Selective Excitation Pulse",false }, // {0x2005,0x00a1,"PHILIPS IMAGING DD 001",VR::CS,VM::VM1,"Syncra Scan Type",false }, {0x2001,0x0001,"Philips Imaging DD 001",VR::FL,VM::VM1,"Chemical Shift",false }, {0x2001,0x0002,"Philips Imaging DD 001",VR::IS,VM::VM1,"Chemical Shift Number MR",false }, {0x2001,0x0003,"Philips Imaging DD 001",VR::FL,VM::VM1,"Diffusion B-Factor",false }, {0x2001,0x0004,"Philips Imaging DD 001",VR::CS,VM::VM1,"Diffusion Direction",false }, {0x2001,0x0005,"Philips Imaging DD 001",VR::SS,VM::VM1,"Graphic Annotation Parent ID",false }, {0x2001,0x0006,"Philips Imaging DD 001",VR::CS,VM::VM1,"Image Enhanced",false }, {0x2001,0x0007,"Philips Imaging DD 001",VR::CS,VM::VM1,"Image Type ED ES",false }, {0x2001,0x0008,"Philips Imaging DD 001",VR::IS,VM::VM1,"Phase Number",false }, {0x2001,0x0009,"Philips Imaging DD 001",VR::FL,VM::VM1,"?ImagePrepulseDelay?",false }, {0x2001,0x000a,"Philips Imaging DD 001",VR::IS,VM::VM1,"Slice Number MR",false }, {0x2001,0x000b,"Philips Imaging DD 001",VR::CS,VM::VM1,"Slice Orientation",false }, {0x2001,0x000c,"Philips Imaging DD 001",VR::CS,VM::VM1,"?ArrhythmiaRejection",false }, {0x2001,0x000e,"Philips Imaging DD 001",VR::CS,VM::VM1,"?CardiacCycled",false }, {0x2001,0x000f,"Philips Imaging DD 001",VR::SS,VM::VM1,"?CardiacGateWidth",false }, {0x2001,0x0010,"Philips Imaging DD 001",VR::CS,VM::VM1,"Cardiac Sync",false }, {0x2001,0x0011,"Philips Imaging DD 001",VR::FL,VM::VM1,"Diffusion Echo Time",false }, {0x2001,0x0012,"Philips Imaging DD 001",VR::CS,VM::VM1,"Dynamic Series",false }, {0x2001,0x0013,"Philips Imaging DD 001",VR::SL,VM::VM1,"EPI Factor",false }, {0x2001,0x0014,"Philips Imaging DD 001",VR::SL,VM::VM1,"Number of Echoes",false }, {0x2001,0x0015,"Philips Imaging DD 001",VR::SS,VM::VM1,"Number of Locations",false }, {0x2001,0x0016,"Philips Imaging DD 001",VR::SS,VM::VM1,"Number of PC Directions",false }, {0x2001,0x0017,"Philips Imaging DD 001",VR::SL,VM::VM1,"Number of Phases MR",false }, {0x2001,0x0018,"Philips Imaging DD 001",VR::SL,VM::VM1,"Number of Slices MR",false }, {0x2001,0x0019,"Philips Imaging DD 001",VR::CS,VM::VM1,"Partial Matrix Scanned",false }, {0x2001,0x001a,"Philips Imaging DD 001",VR::FL,VM::VM1_n,"PC Velocity",false }, {0x2001,0x001b,"Philips Imaging DD 001",VR::FL,VM::VM1,"Prepulse Delay",false }, {0x2001,0x001c,"Philips Imaging DD 001",VR::CS,VM::VM1,"Prepulse Type",false }, {0x2001,0x001d,"Philips Imaging DD 001",VR::IS,VM::VM1,"Reconstruction Number MR",false }, {0x2001,0x001e,"Philips Imaging DD 001",VR::CS,VM::VM1,"?MRSeriesReformatAccuracy",false }, {0x2001,0x001f,"Philips Imaging DD 001",VR::CS,VM::VM1,"Respiration Sync",false }, {0x2001,0x0020,"Philips Imaging DD 001",VR::LO,VM::VM1,"Scanning Technique Description MR",false }, {0x2001,0x0021,"Philips Imaging DD 001",VR::CS,VM::VM1,"SPIR",false }, {0x2001,0x0022,"Philips Imaging DD 001",VR::FL,VM::VM1,"Water Fat Shift",false }, {0x2001,0x0023,"Philips Imaging DD 001",VR::DS,VM::VM1,"Flip Angle Philips",false }, {0x2001,0x0024,"Philips Imaging DD 001",VR::CS,VM::VM1,"Interactive",false }, {0x2001,0x0025,"Philips Imaging DD 001",VR::SH,VM::VM1,"Echo Time Display MR",false }, {0x2001,0x0026,"Philips Imaging DD 001",VR::CS,VM::VM1,"Presentation State Subtraction Active",false }, {0x2001,0x0028,"Philips Imaging DD 001",VR::FL,VM::VM1,"Edge Enhancement Gain Factor Sub",false }, {0x2001,0x0029,"Philips Imaging DD 001",VR::FL,VM::VM1,"Edge Enhancement Gain Factor Non Sub",false }, {0x2001,0x002a,"Philips Imaging DD 001",VR::CS,VM::VM1,"Edge Enhancement Taste Adapt Sub",false }, {0x2001,0x002b,"Philips Imaging DD 001",VR::CS,VM::VM1,"Edge Enhancement Taste Non Sub",false }, {0x2001,0x002c,"Philips Imaging DD 001",VR::FL,VM::VM1,"Harmonization Factor",false }, {0x2001,0x002d,"Philips Imaging DD 001",VR::SS,VM::VM1,"Number of Stack Slices",false }, {0x2001,0x002f,"Philips Imaging DD 001",VR::FL,VM::VM1,"Harmonization Gain",false }, {0x2001,0x0030,"Philips Imaging DD 001",VR::UL,VM::VM1,"Log Subtraction Gain Step",false }, {0x2001,0x0031,"Philips Imaging DD 001",VR::US,VM::VM1,"Mixing NR of Mask Image Numbers",false }, {0x2001,0x0032,"Philips Imaging DD 001",VR::FL,VM::VM1_n,"Stack Radial Angle",false }, {0x2001,0x0033,"Philips Imaging DD 001",VR::CS,VM::VM1_n,"Stack Radial Axis",false }, {0x2001,0x0034,"Philips Imaging DD 001",VR::CS,VM::VM1,"Mixing Mask Operation",false }, {0x2001,0x0035,"Philips Imaging DD 001",VR::SS,VM::VM1_n,"Stack Slice Number",false }, {0x2001,0x0036,"Philips Imaging DD 001",VR::CS,VM::VM1_n,"Stack Type",false }, {0x2001,0x0037,"Philips Imaging DD 001",VR::CS,VM::VM1,"Mixing Operation Type",false }, {0x2001,0x0039,"Philips Imaging DD 001",VR::FL,VM::VM1,"?",false }, {0x2001,0x003a,"Philips Imaging DD 001",VR::CS,VM::VM1,"Pixel Shift",false }, {0x2001,0x003d,"Philips Imaging DD 001",VR::UL,VM::VM1,"?ContourFillColor",false }, {0x2001,0x003f,"Philips Imaging DD 001",VR::CS,VM::VM1,"Interpolation Method",false }, {0x2001,0x0042,"Philips Imaging DD 001",VR::CS,VM::VM1,"Subtraction Land Marking Active",false }, {0x2001,0x0046,"Philips Imaging DD 001",VR::CS,VM::VM1,"Graphic Line Style",false }, {0x2001,0x0047,"Philips Imaging DD 001",VR::FL,VM::VM1,"Graphic Line Width",false }, {0x2001,0x0048,"Philips Imaging DD 001",VR::SS,VM::VM1,"Graphic Annotation ID",false }, {0x2001,0x004b,"Philips Imaging DD 001",VR::CS,VM::VM1,"Poly Line Interpolation Method",false }, {0x2001,0x004c,"Philips Imaging DD 001",VR::CS,VM::VM1,"Poly Line Begin Point Style",false }, {0x2001,0x004d,"Philips Imaging DD 001",VR::CS,VM::VM1,"Poly Line End Point Style",false }, {0x2001,0x004e,"Philips Imaging DD 001",VR::CS,VM::VM1,"Window Smoothing Taste",false }, {0x2001,0x004f,"Philips Imaging DD 001",VR::FD,VM::VM1,"Harmonization Offset",false }, {0x2001,0x0050,"Philips Imaging DD 001",VR::LO,VM::VM1,"?GraphicMarkerType",false }, {0x2001,0x0051,"Philips Imaging DD 001",VR::IS,VM::VM1,"?OverlayPlaneID",false }, {0x2001,0x0052,"Philips Imaging DD 001",VR::UI,VM::VM1,"?ImagePresentationStateUID",false }, {0x2001,0x0053,"Philips Imaging DD 001",VR::CS,VM::VM1,"Window Invert",false }, {0x2001,0x0055,"Philips Imaging DD 001",VR::CS,VM::VM1,"Graphic Line Color",false }, {0x2001,0x0056,"Philips Imaging DD 001",VR::CS,VM::VM1,"Graphic Type (Private)",false }, {0x2001,0x005a,"Philips Imaging DD 001",VR::ST,VM::VM1,"Graphic Annotation Model",false }, {0x2001,0x005d,"Philips Imaging DD 001",VR::ST,VM::VM1,"Measurement Text Units",false }, {0x2001,0x005e,"Philips Imaging DD 001",VR::ST,VM::VM1,"Measurement Text Type",false }, {0x2001,0x005f,"Philips Imaging DD 001",VR::SQ,VM::VM1,"Stack Sequence",false }, {0x2001,0x0060,"Philips Imaging DD 001",VR::SL,VM::VM1,"Number of Stacks",false }, {0x2001,0x0061,"Philips Imaging DD 001",VR::CS,VM::VM1,"?SeriesTransmitted",false }, {0x2001,0x0062,"Philips Imaging DD 001",VR::CS,VM::VM1,"?SeriesCommitted",false }, {0x2001,0x0063,"Philips Imaging DD 001",VR::CS,VM::VM1,"Examination Source",false }, {0x2001,0x0064,"Philips Imaging DD 001",VR::SH,VM::VM1,"Text Type",false }, {0x2001,0x0065,"Philips Imaging DD 001",VR::SQ,VM::VM1,"?GraphicOverlayPlane",false }, {0x2001,0x0067,"Philips Imaging DD 001",VR::CS,VM::VM1,"?",false }, {0x2001,0x0068,"Philips Imaging DD 001",VR::SQ,VM::VM1,"?LinearModalityGLTrafo",false }, {0x2001,0x0069,"Philips Imaging DD 001",VR::SQ,VM::VM1,"Display Shutter Sequence",false }, {0x2001,0x006a,"Philips Imaging DD 001",VR::SQ,VM::VM1,"?SpatialTransformation",false }, {0x2001,0x006b,"Philips Imaging DD 001",VR::SQ,VM::VM1,"Has Edge Enhancement Sequence",false }, {0x2001,0x006d,"Philips Imaging DD 001",VR::LO,VM::VM1,"Text Font",false }, {0x2001,0x006e,"Philips Imaging DD 001",VR::SH,VM::VM1,"Series Type",false }, {0x2001,0x006f,"Philips Imaging DD 001",VR::SQ,VM::VM1,"Mixing Sequence",false }, {0x2001,0x0071,"Philips Imaging DD 001",VR::CS,VM::VM1,"?GraphicConstraint",false }, {0x2001,0x0073,"Philips Imaging DD 001",VR::SQ,VM::VM1,"Referenced Mask Image Sequence",false }, {0x2001,0x0074,"Philips Imaging DD 001",VR::DS,VM::VM1_n,"Window Center Sub",false }, {0x2001,0x0075,"Philips Imaging DD 001",VR::DS,VM::VM1_n,"Window Width Sub",false }, {0x2001,0x0076,"Philips Imaging DD 001",VR::UL,VM::VM1,"?MRNumberOfFrames",false }, {0x2001,0x0077,"Philips Imaging DD 001",VR::CS,VM::VM1,"GL TrafoType",false }, {0x2001,0x0079,"Philips Imaging DD 001",VR::SQ,VM::VM1,"Harmonisation Sequence",false }, {0x2001,0x007a,"Philips Imaging DD 001",VR::FL,VM::VM1,"?WindowRoundingFactor",false }, {0x2001,0x007b,"Philips Imaging DD 001",VR::IS,VM::VM1,"Acquisition Number",false }, {0x2001,0x007e,"Philips Imaging DD 001",VR::US,VM::VM1,"Edge Enhancement Gain Taste",false }, {0x2001,0x007f,"Philips Imaging DD 001",VR::US,VM::VM1,"Edge Enhancement Gain Taste Sub",false }, {0x2001,0x0080,"Philips Imaging DD 001",VR::LO,VM::VM1,"Text Anchor Point Alignment",false }, {0x2001,0x0081,"Philips Imaging DD 001",VR::IS,VM::VM1,"Number of Dynamic Scans",false }, {0x2001,0x0082,"Philips Imaging DD 001",VR::IS,VM::VM1,"Echo Train Length",false }, {0x2001,0x0083,"Philips Imaging DD 001",VR::DS,VM::VM1,"Imaging Frequency",false }, {0x2001,0x0084,"Philips Imaging DD 001",VR::DS,VM::VM1,"Inversion Time",false }, {0x2001,0x0085,"Philips Imaging DD 001",VR::DS,VM::VM1,"Magnetic Field Strength",false }, {0x2001,0x0086,"Philips Imaging DD 001",VR::IS,VM::VM1,"?NrOfPhaseEncodingSteps?",false }, {0x2001,0x0087,"Philips Imaging DD 001",VR::SH,VM::VM1,"Imaged Nucleus",false }, {0x2001,0x0088,"Philips Imaging DD 001",VR::DS,VM::VM1,"Number of Averages",false }, {0x2001,0x0089,"Philips Imaging DD 001",VR::DS,VM::VM1,"Phase FOV Percent",false }, {0x2001,0x008a,"Philips Imaging DD 001",VR::DS,VM::VM1,"Sampling Percent",false }, {0x2001,0x008b,"Philips Imaging DD 001",VR::SH,VM::VM1,"?Transmitting Coil?",false }, {0x2001,0x0093,"Philips Imaging DD 001",VR::LO,VM::VM1,"Text Style",false }, {0x2001,0x0094,"Philips Imaging DD 001",VR::LO,VM::VM1,"Processing Order Specialization",false }, {0x2001,0x0097,"Philips Imaging DD 001",VR::SH,VM::VM1,"Nucleus",false }, {0x2001,0x009a,"Philips Imaging DD 001",VR::SQ,VM::VM1,"Graphic Number Sequence",false }, {0x2001,0x009b,"Philips Imaging DD 001",VR::UL,VM::VM1,"Graphic Number",false }, {0x2001,0x009c,"Philips Imaging DD 001",VR::LO,VM::VM1,"?GraphicAnnotationLabel",false }, {0x2001,0x009d,"Philips Imaging DD 001",VR::LO,VM::VM1,"PIIM Subtraction Type",false }, {0x2001,0x009f,"Philips Imaging DD 001",VR::US,VM::VM2,"Pixel Processing Kernel Size",false }, {0x2001,0x00a1,"Philips Imaging DD 001",VR::CS,VM::VM1,"Is Raw Image",false }, {0x2001,0x00a2,"Philips Imaging DD 001",VR::US,VM::VM1,"LOG Subtraction Curve Taste",false }, {0x2001,0x00a3,"Philips Imaging DD 001",VR::UL,VM::VM1,"Text Color Foreground",false }, {0x2001,0x00a4,"Philips Imaging DD 001",VR::UL,VM::VM1,"Text Color Background",false }, {0x2001,0x00a5,"Philips Imaging DD 001",VR::UL,VM::VM1,"Text Color Shadow",false }, {0x2001,0x00c1,"Philips Imaging DD 001",VR::LO,VM::VM1,"Nested Object Type Name",false }, {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,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 }, {0x2005,0x0014,"Philips Imaging DD 001",VR::CS,VM::VM1,"Diffusion",false }, {0x2005,0x0020,"Philips Imaging DD 001",VR::SL,VM::VM1,"Number of Chemical Shifts",false }, {0x2005,0x0030,"Philips Imaging DD 001",VR::FL,VM::VM1_n,"Repetition Time",false }, {0x2005,0x0033,"Philips Imaging DD 001",VR::FL,VM::VM1,"Scan Duration",false }, {0x2005,0x0035,"Philips Imaging DD 001",VR::CS,VM::VM1,"Data Type",false }, {0x2005,0x008b,"Philips Imaging DD 001",VR::SH,VM::VM1,"Transmitting Coil",false }, {0x2005,0x009f,"Philips Imaging DD 001",VR::CS,VM::VM1,"Spectral Selective Excitation Pulse",false }, {0x2005,0x00a1,"Philips Imaging DD 001",VR::CS,VM::VM1,"Syncra Scan Type",false }, {0x2001,0x0001,"Philips Imaging DD 002",VR::US,VM::VM1,"?",false }, {0x2001,0x0002,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0013,"Philips Imaging DD 002",VR::SS,VM::VM1,"?",false }, {0x2001,0x0014,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0015,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0016,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0017,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0018,"Philips Imaging DD 002",VR::CS,VM::VM1,"?",false }, {0x2001,0x0019,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x001a,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x001b,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x001c,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x001d,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x001e,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x001f,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0020,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0021,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0022,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0023,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0024,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0025,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0026,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0027,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0028,"Philips Imaging DD 002",VR::US,VM::VM1,"?",false }, {0x2001,0x0029,"Philips Imaging DD 002",VR::US,VM::VM1,"?",false }, {0x2001,0x002a,"Philips Imaging DD 002",VR::US,VM::VM1,"?",false }, {0x2001,0x002b,"Philips Imaging DD 002",VR::SS,VM::VM1,"?",false }, {0x2001,0x002c,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x002d,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x002e,"Philips Imaging DD 002",VR::SS,VM::VM1,"?",false }, {0x2001,0x002f,"Philips Imaging DD 002",VR::SS,VM::VM1,"?",false }, {0x2001,0x0030,"Philips Imaging DD 002",VR::SS,VM::VM1,"?",false }, {0x2001,0x0031,"Philips Imaging DD 002",VR::SS,VM::VM1,"?",false }, {0x2001,0x0032,"Philips Imaging DD 002",VR::SS,VM::VM1,"?",false }, {0x2001,0x0033,"Philips Imaging DD 002",VR::SS,VM::VM1,"?",false }, {0x2001,0x0034,"Philips Imaging DD 002",VR::SS,VM::VM1,"?",false }, {0x2001,0x0035,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0036,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0037,"Philips Imaging DD 002",VR::FD,VM::VM1,"?",false }, {0x2001,0x0039,"Philips Imaging DD 002",VR::CS,VM::VM1,"?",false }, {0x2001,0x003a,"Philips Imaging DD 002",VR::SQ,VM::VM1,"?",false }, {0x2001,0x003b,"Philips Imaging DD 002",VR::SQ,VM::VM1,"?",false }, {0x2001,0x003c,"Philips Imaging DD 002",VR::SQ,VM::VM1,"?",false }, {0x2001,0x003d,"Philips Imaging DD 002",VR::SQ,VM::VM1,"?",false }, {0x2001,0x003e,"Philips Imaging DD 002",VR::SS,VM::VM1,"?",false }, {0x2001,0x003f,"Philips Imaging DD 002",VR::SS,VM::VM1,"?",false }, {0x2001,0x0040,"Philips Imaging DD 002",VR::SS,VM::VM1,"?",false }, {0x2001,0x006b,"Philips Imaging DD 002",VR::LO,VM::VM1,"?",false }, {0x4007,0x0000,"Philips Imaging DD 065",VR::CS,VM::VM1,"?",false }, {0x4001,0x0000,"Philips Imaging DD 067",VR::SQ,VM::VM1,"?",false }, {0x4001,0x0001,"Philips Imaging DD 067",VR::CS,VM::VM1,"?",false }, {0x4001,0x0008,"Philips Imaging DD 067",VR::CS,VM::VM1,"?",false }, {0x4001,0x0010,"Philips Imaging DD 070",VR::SQ,VM::VM1,"?",false }, {0x4001,0x0011,"Philips Imaging DD 070",VR::SQ,VM::VM1,"?",false }, {0x4001,0x0012,"Philips Imaging DD 070",VR::SQ,VM::VM1,"?",false }, {0x4001,0x0016,"Philips Imaging DD 070",VR::ST,VM::VM1,"?",false }, {0x4001,0x0017,"Philips Imaging DD 070",VR::ST,VM::VM1,"?",false }, {0x4001,0x0018,"Philips Imaging DD 070",VR::ST,VM::VM1,"?",false }, {0x4001,0x001c,"Philips Imaging DD 070",VR::SQ,VM::VM1,"?",false }, {0x4001,0x001d,"Philips Imaging DD 070",VR::LT,VM::VM1,"?",false }, {0x4007,0x0048,"Philips Imaging DD 073",VR::FL,VM::VM1,"?",false }, {0x1001,0x0003,"Philips Imaging DD 124",VR::LO,VM::VM1,"?",false }, /* MR Import Filter 3/21/2014 1:57:35 PM */ {0x2001,0x0000,"Philips Imaging DD 129",VR::SQ,VM::VM1,"PresentationStateSequence",false }, {0x2001,0x0001,"Philips Imaging DD 129",VR::SQ,VM::VM1,"?",false }, {0x2005,0x0000,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?AngulationAP?",false }, {0x2005,0x0001,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?AngulationFH?",false }, {0x2005,0x0002,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?AngulationRL?",false }, {0x2005,0x0003,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"?ImageAnnotationCount",false }, {0x2005,0x0004,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?DisplayOrientation?",false }, {0x2005,0x0005,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"Synergy Reconstruction Type",false }, {0x2005,0x0006,"PHILIPS MR IMAGING DD 001",VR::UI,VM::VM1,"?",false }, {0x2005,0x0007,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"?ImageLineCount",false }, {0x2005,0x0008,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?OffCentreAP?",false }, {0x2005,0x0009,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?OffCentreFH?",false }, {0x2005,0x000a,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?OffCentreRL?",false }, {0x2005,0x000b,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?MaxFP?",false }, {0x2005,0x000c,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?MinFP?",false }, {0x2005,0x000d,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?ScaleIntercept?",false }, {0x2005,0x000e,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?ScaleSlope?",false }, {0x2005,0x000f,"PHILIPS MR IMAGING DD 001",VR::DS,VM::VM1,"Window Center Philips",false }, {0x2005,0x0010,"PHILIPS MR IMAGING DD 001",VR::DS,VM::VM1,"Window Width Philips",false }, {0x2005,0x0011,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"Image Type Philips",false }, {0x2005,0x0012,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?CardiacGating?",false }, {0x2005,0x0013,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?DevelopmentMode?",false }, {0x2005,0x0014,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"Diffusion",false }, {0x2005,0x0015,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?FatSaturationTechnique?",false }, {0x2005,0x0016,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?FlowCompensation",false }, {0x2005,0x0017,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?FourierInterpolation",false }, {0x2005,0x0018,"PHILIPS MR IMAGING DD 001",VR::LO,VM::VM1,"?HardcopyProtocol",false }, {0x2005,0x0019,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?InverseReconstructed",false }, {0x2005,0x001a,"PHILIPS MR IMAGING DD 001",VR::SS,VM::VM1,"?LabelSyntax",false }, {0x2005,0x001b,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?MagnetiPrepared",false }, {0x2005,0x001c,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?MagnetTransferConst",false }, {0x2005,0x001d,"PHILIPS MR IMAGING DD 001",VR::SS,VM::VM1,"?MeasurementScanResolution",false }, {0x2005,0x001e,"PHILIPS MR IMAGING DD 001",VR::SH,VM::VM1,"?MIPProtocol",false }, {0x2005,0x001f,"PHILIPS MR IMAGING DD 001",VR::SH,VM::VM1,"?MPRProtocol",false }, {0x2005,0x0020,"PHILIPS MR IMAGING DD 001",VR::SL,VM::VM1,"Number of Chemical Shift",false }, {0x2005,0x0021,"PHILIPS MR IMAGING DD 001",VR::SS,VM::VM1,"NumberOfMixes", false }, {0x2005,0x0022,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"NumberOfReferences", false }, {0x2005,0x0023,"PHILIPS MR IMAGING DD 001",VR::SS,VM::VM1,"NumberOfSlabs", false }, {0x2005,0x0025,"PHILIPS MR IMAGING DD 001",VR::SS,VM::VM1,"NumberOfVolumes", false }, {0x2005,0x0026,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"OverSampleingPhase", false }, {0x2005,0x0027,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"PackageMode", false }, {0x2005,0x0028,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"PartialFourierFrequency", false }, {0x2005,0x0029,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"PartialFourierPhase", false }, {0x2005,0x002a,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"PatientReferenceID", false }, {0x2005,0x002b,"PHILIPS MR IMAGING DD 001",VR::SS,VM::VM1,"PercentScanComplete", false }, {0x2005,0x002c,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"PhaseEncodedRecording", false }, {0x2005,0x002d,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"PlanScanSurveyNumberOfImages", false }, {0x2005,0x002e,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"PPGPPUGating", false }, {0x2005,0x002f,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"SpatialPresaturation", false }, {0x2005,0x0030,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1_n,"Repetition Time",false }, {0x2005,0x0031,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"RespiratoryGating", false }, {0x2005,0x0032,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?SampleRepresentation",false }, {0x2005,0x0033,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"Scan Duration",false }, {0x2005,0x0034,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"MRSegmentedKSpace", false }, {0x2005,0x0035,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"Data Type",false }, {0x2005,0x0036,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"SeriesIsCardiac", false }, {0x2005,0x0037,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"SeriesIsSpectro", false }, {0x2005,0x0038,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"Spoiled", false }, {0x2005,0x0039,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"SteadyState", false }, {0x2005,0x003a,"PHILIPS MR IMAGING DD 001",VR::SH,VM::VM1,"SubAnatomy", false }, {0x2005,0x003b,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"TimeReversedSteadyState", false }, {0x2005,0x003c,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"SeriesTone", false }, {0x2005,0x003d,"PHILIPS MR IMAGING DD 001",VR::SS,VM::VM1,"NumberOfRRIntervalRanges", false }, {0x2005,0x003e,"PHILIPS MR IMAGING DD 001",VR::SL,VM::VM1_n,"RRIntervalsDistribution", false }, {0x2005,0x003f,"PHILIPS MR IMAGING DD 001",VR::SL,VM::VM1,"PlanScanAcquisitionNo", false }, {0x2005,0x0040,"PHILIPS MR IMAGING DD 001",VR::SL,VM::VM1,"ChemicalShiftNo", false }, {0x2005,0x0041,"PHILIPS MR IMAGING DD 001",VR::SL,VM::VM1,"PlanScanDynamicScanNo", false }, {0x2005,0x0042,"PHILIPS MR IMAGING DD 001",VR::SL,VM::VM1,"PlanScanSurveyEchoNo", false }, {0x2005,0x0043,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"PlanScanImageType", false }, {0x2005,0x0044,"PHILIPS MR IMAGING DD 001",VR::SL,VM::VM1,"PlanScanPhaseNo", false }, {0x2005,0x0045,"PHILIPS MR IMAGING DD 001",VR::SL,VM::VM1,"PlanScanReconstructionNo", false }, {0x2005,0x0046,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"PlanScanScanningSequence", false }, {0x2005,0x0047,"PHILIPS MR IMAGING DD 001",VR::SL,VM::VM1,"PlanScanSliceNo", false }, {0x2005,0x0048,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"?MRReferenceAcquisitionNo",false }, {0x2005,0x0049,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"?MRReferenceChemicalShiftNo",false }, {0x2005,0x004a,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"?MRReferenceDynamicScanNo",false }, {0x2005,0x004b,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"?MRReferenceEchoNo",false }, {0x2005,0x004c,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?MRReferenceEntity",false }, {0x2005,0x004d,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?MRReferenceImageType",false }, {0x2005,0x004e,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?MRSlabFovRL",false }, {0x2005,0x004f,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?MRSlabOffcentreAP",false }, {0x2005,0x0050,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?MRSlabOffcentreFH",false }, {0x2005,0x0051,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?MRSlabOffcentreRL",false }, {0x2005,0x0052,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?MRSlabType",false }, {0x2005,0x0053,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?MRSlabViewAxis",false }, {0x2005,0x0054,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"SVS Voxel Angulation AP (deg)",false }, {0x2005,0x0055,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"SVS Voxel Angulation FH (deg)",false }, {0x2005,0x0056,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"SVS Voxel Angulation LR (deg)",false }, {0x2005,0x0057,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"SVS Voxel Size AP (mm)",false }, {0x2005,0x0058,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"SVS Voxel Size FH (mm)",false }, {0x2005,0x0059,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"SVS Voxel Size LR (mm)",false }, {0x2005,0x005a,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"SVS Voxel Offcenter AP (mm)",false }, {0x2005,0x005b,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"SVS Voxel Offcenter FH (mm)",false }, {0x2005,0x005c,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"SVS Voxel Offcenter LR (mm)",false }, {0x2005,0x005d,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"VolumeType", false }, {0x2005,0x005e,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"VolumeViewAxis", false }, {0x2005,0x005f,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"StudyOrigin", false }, {0x2005,0x0060,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"StudySequenceNumber", false }, {0x2005,0x0061,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"ImagePrepulseType", false }, {0x2005,0x0063,"PHILIPS MR IMAGING DD 001",VR::SS,VM::VM1,"fMRIStatusIndication", false }, {0x2005,0x0064,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"?MRReferencePhaseNo",false }, {0x2005,0x0065,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"?MRReferenceReconstructionNo",false }, {0x2005,0x0066,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?MRReferenceScanningSequence",false }, {0x2005,0x0067,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"?MRReferenceSliceNo",false }, {0x2005,0x0068,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?MRReferenceType",false }, {0x2005,0x0069,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?MRSlabAngulationAP",false }, {0x2005,0x006a,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?MRSlabAngulationFH",false }, {0x2005,0x006b,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?MRSlabAngulationRL",false }, {0x2005,0x006c,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?MRSlabFovAP",false }, {0x2005,0x006d,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"?MRSlabFovFH",false }, {0x2005,0x006e,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"ImageScanningSequencePrivate", false }, {0x2005,0x006f,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?AcquisitionType?", false }, {0x2005,0x0070,"PHILIPS MR IMAGING DD 001",VR::LO,VM::VM1,"?MRSeriesHardcopyProtocolEV",false }, {0x2005,0x0071,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"StackAngulationAP", false }, {0x2005,0x0072,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"StackAngulationFH", false }, {0x2005,0x0073,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"StackAngulationRL", false }, {0x2005,0x0074,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"StackFovAP", false }, {0x2005,0x0075,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"StackFovFH", false }, {0x2005,0x0076,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"StackFovRL", false }, {0x2005,0x0078,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"StackOffcentreAP", false }, {0x2005,0x0079,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"StackOffcentreFH", false }, {0x2005,0x007a,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"StackOffcentreRL", false }, {0x2005,0x007b,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"StackPreparationDirection", false }, {0x2005,0x007e,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"Z-Spacing (aka Stack Slice Distance)",false }, {0x2005,0x0080,"PHILIPS MR IMAGING DD 001",VR::SQ,VM::VM1,"SeriesPlanScan", false }, {0x2005,0x0081,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"StackViewAxis", false }, {0x2005,0x0083,"PHILIPS MR IMAGING DD 001",VR::SQ,VM::VM1,"SeriesSlab", false }, {0x2005,0x0084,"PHILIPS MR IMAGING DD 001",VR::SQ,VM::VM1,"SeriesReference", false }, {0x2005,0x0085,"PHILIPS MR IMAGING DD 001",VR::SQ,VM::VM1,"SeriesVolume", false }, {0x2005,0x0086,"PHILIPS MR IMAGING DD 001",VR::SS,VM::VM1,"NumberOfGeometry", false }, {0x2005,0x009e,"PHILIPS MR IMAGING DD 001",VR::SQ,VM::VM1,"SeriesGeom", false }, {0x2005,0x009f,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"MRSeriesSpectralSelectiveExcitationPulse", false }, {0x2005,0x00a0,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"Philips Temporal Position Identifier (aka ImageDynamicScanBeginTime)",false }, {0x2005,0x00a1,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"Syncra Scan Type",false }, {0x2005,0x00a2,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"IsCOCA", false }, {0x2005,0x00a3,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"StackCoilID", false }, {0x2005,0x00a4,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"StackCBBCoil1", false }, {0x2005,0x00a5,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"StackCBBCoil2", false }, {0x2005,0x00a6,"PHILIPS MR IMAGING DD 001",VR::IS,VM::VM1,"StackChannelCombi", false }, {0x2005,0x00a7,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"StackCoilConn", false }, {0x2005,0x00a8,"PHILIPS MR IMAGING DD 001",VR::DS,VM::VM1,"PrivateInversionTime", false }, {0x2005,0x00a9,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"SeriesGeometryCorrection", false }, {0x2005,0x00b0,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"Diffusion Direction RL (degree)",false }, {0x2005,0x00b1,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"Diffusion Direction AP (degree)",false }, {0x2005,0x00b2,"PHILIPS MR IMAGING DD 001",VR::FL,VM::VM1,"Diffusion Direction FH (degree)",false }, {0x2005,0x00c0,"PHILIPS MR IMAGING DD 001",VR::CS,VM::VM1,"?SequenceVariant?", false }, /* pay attention to the case */ {0x2005,0x0000,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?AngulationAP?",false }, {0x2005,0x0001,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?AngulationFH?",false }, {0x2005,0x0002,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?AngulationRL?",false }, {0x2005,0x0003,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"?ImageAnnotationCount",false }, {0x2005,0x0004,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?DisplayOrientation?",false }, {0x2005,0x0005,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"Synergy Reconstruction Type",false }, {0x2005,0x0006,"Philips MR Imaging DD 001",VR::UI,VM::VM1,"?",false }, {0x2005,0x0007,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"ImageLineCount",false }, {0x2005,0x0008,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?OffCentreAP?",false }, {0x2005,0x0009,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?OffCentreFH?",false }, {0x2005,0x000a,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?OffCentreRL?",false }, {0x2005,0x000b,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?MaxFP?",false }, {0x2005,0x000c,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?MinFP?",false }, {0x2005,0x000d,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?ScaleIntercept?",false }, {0x2005,0x000e,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?ScaleSlope?",false }, {0x2005,0x000f,"Philips MR Imaging DD 001",VR::DS,VM::VM1,"Window Center Philips",false }, {0x2005,0x0010,"Philips MR Imaging DD 001",VR::DS,VM::VM1,"Window Width Philips",false }, {0x2005,0x0011,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"Image Type Philips",false }, {0x2005,0x0012,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?CardiacGating?",false }, {0x2005,0x0013,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?DevelopmentMode?",false }, {0x2005,0x0014,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"Diffusion",false }, {0x2005,0x0015,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?FatSaturationTechnique?",false }, {0x2005,0x0016,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?FlowCompensation",false }, {0x2005,0x0017,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?FourierInterpolation",false }, {0x2005,0x0018,"Philips MR Imaging DD 001",VR::LO,VM::VM1,"?MRHardcopyProtocol",false }, {0x2005,0x0019,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?InverseReconstructed",false }, {0x2005,0x001a,"Philips MR Imaging DD 001",VR::SS,VM::VM1,"?LabelSyntax",false }, {0x2005,0x001b,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?MagnetiPrepared",false }, {0x2005,0x001c,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?MagnetTransferConst",false }, {0x2005,0x001d,"Philips MR Imaging DD 001",VR::SS,VM::VM1,"?MeasurementScanResolution",false }, {0x2005,0x001e,"Philips MR Imaging DD 001",VR::SH,VM::VM1,"?MIPProtocol",false }, {0x2005,0x001f,"Philips MR Imaging DD 001",VR::SH,VM::VM1,"?MPRProtocol",false }, {0x2005,0x0020,"Philips MR Imaging DD 001",VR::SL,VM::VM1,"Number of Chemical Shift",false }, {0x2005,0x0021,"Philips MR Imaging DD 001",VR::SS,VM::VM1,"NumberOfMixes", false }, {0x2005,0x0022,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"NumberOfReferences", false }, {0x2005,0x0023,"Philips MR Imaging DD 001",VR::SS,VM::VM1,"NumberOfSlabs", false }, {0x2005,0x0025,"Philips MR Imaging DD 001",VR::SS,VM::VM1,"NumberOfVolumes", false }, {0x2005,0x0026,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"OverSampleingPhase", false }, {0x2005,0x0027,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"PackageMode", false }, {0x2005,0x0028,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"PartialFourierFrequency", false }, {0x2005,0x0029,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"PartialFourierPhase", false }, {0x2005,0x002a,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"PatientReferenceID", false }, {0x2005,0x002b,"Philips MR Imaging DD 001",VR::SS,VM::VM1,"PercentScanComplete", false }, {0x2005,0x002c,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"PhaseEncodedRecording", false }, {0x2005,0x002d,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"PlanScanSurveyNumberOfImages", false }, {0x2005,0x002e,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"PPGPPUGating", false }, {0x2005,0x002f,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"SpatialPresaturation", false }, {0x2005,0x0030,"Philips MR Imaging DD 001",VR::FL,VM::VM1_n,"Repetition Time",false }, {0x2005,0x0031,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"RespiratoryGating", false }, {0x2005,0x0032,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?SampleRepresentation",false }, {0x2005,0x0033,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"Scan Duration",false }, {0x2005,0x0034,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"MRSegmentedKSpace", false }, {0x2005,0x0035,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"Data Type",false }, {0x2005,0x0036,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"SeriesIsCardiac", false }, {0x2005,0x0037,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"SeriesIsSpectro", false }, {0x2005,0x0038,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"Spoiled", false }, {0x2005,0x0039,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"SteadyState", false }, {0x2005,0x003a,"Philips MR Imaging DD 001",VR::SH,VM::VM1,"SubAnatomy", false }, {0x2005,0x003b,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"TimeReversedSteadyState", false }, {0x2005,0x003c,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"SeriesTone", false }, {0x2005,0x003d,"Philips MR Imaging DD 001",VR::SS,VM::VM1,"NumberOfRRIntervalRanges", false }, {0x2005,0x003e,"Philips MR Imaging DD 001",VR::SL,VM::VM1_n,"RRIntervalsDistribution", false }, {0x2005,0x003f,"Philips MR Imaging DD 001",VR::SL,VM::VM1,"PlanScanAcquisitionNo", false }, {0x2005,0x0040,"Philips MR Imaging DD 001",VR::SL,VM::VM1,"ChemicalShiftNo", false }, {0x2005,0x0041,"Philips MR Imaging DD 001",VR::SL,VM::VM1,"PlanScanDynamicScanNo", false }, {0x2005,0x0042,"Philips MR Imaging DD 001",VR::SL,VM::VM1,"PlanScanSurveyEchoNo", false }, {0x2005,0x0043,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"PlanScanImageType", false }, {0x2005,0x0044,"Philips MR Imaging DD 001",VR::SL,VM::VM1,"PlanScanPhaseNo", false }, {0x2005,0x0045,"Philips MR Imaging DD 001",VR::SL,VM::VM1,"PlanScanReconstructionNo", false }, {0x2005,0x0046,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"PlanScanScanningSequence", false }, {0x2005,0x0047,"Philips MR Imaging DD 001",VR::SL,VM::VM1,"PlanScanSliceNo", false }, {0x2005,0x0048,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"?MRReferenceAcquisitionNo",false }, {0x2005,0x0049,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"?MRReferenceChemicalShiftNo",false }, {0x2005,0x004a,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"?MRReferenceDynamicScanNo",false }, {0x2005,0x004b,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"?MRReferenceEchoNo",false }, {0x2005,0x004c,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?MRReferenceEntity",false }, {0x2005,0x004d,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?MRReferenceImageType",false }, {0x2005,0x004e,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?MRSlabFovRL",false }, {0x2005,0x004f,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?MRSlabOffcentreAP",false }, {0x2005,0x0050,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?MRSlabOffcentreFH",false }, {0x2005,0x0051,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?MRSlabOffcentreRL",false }, {0x2005,0x0052,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?MRSlabType",false }, {0x2005,0x0053,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?MRSlabViewAxis",false }, {0x2005,0x0054,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"SVS Voxel Angulation AP (deg)",false }, {0x2005,0x0055,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"SVS Voxel Angulation FH (deg)",false }, {0x2005,0x0056,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"SVS Voxel Angulation LR (deg)",false }, {0x2005,0x0057,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"SVS Voxel Size AP (mm)",false }, {0x2005,0x0058,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"SVS Voxel Size FH (mm)",false }, {0x2005,0x0059,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"SVS Voxel Size LR (mm)",false }, {0x2005,0x005a,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"SVS Voxel Offcenter AP (mm)",false }, {0x2005,0x005b,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"SVS Voxel Offcenter FH (mm)",false }, {0x2005,0x005c,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"SVS Voxel Offcenter LR (mm)",false }, {0x2005,0x005d,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"VolumeType", false }, {0x2005,0x005e,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"VolumeViewAxis", false }, {0x2005,0x005f,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"StudyOrigin", false }, {0x2005,0x0060,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"StudySequenceNumber", false }, {0x2005,0x0061,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"ImagePrepulseType", false }, {0x2005,0x0063,"Philips MR Imaging DD 001",VR::SS,VM::VM1,"fMRIStatusIndication", false }, {0x2005,0x0064,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"?MRReferencePhaseNo",false }, {0x2005,0x0065,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"?MRReferenceReconstructionNo",false }, {0x2005,0x0066,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?MRReferenceScanningSequence",false }, {0x2005,0x0067,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"?MRReferenceSliceNo",false }, {0x2005,0x0068,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?MRReferenceType",false }, {0x2005,0x0069,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?MRSlabAngulationAP",false }, {0x2005,0x006a,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?MRSlabAngulationFH",false }, {0x2005,0x006b,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?MRSlabAngulationRL",false }, {0x2005,0x006c,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?MRSlabFovAP",false }, {0x2005,0x006d,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"?MRSlabFovFH",false }, {0x2005,0x006e,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?Scanning Sequence / Sequence Type?",false }, {0x2005,0x006f,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?MR Acquisition Type?",false }, {0x2005,0x0070,"Philips MR Imaging DD 001",VR::LO,VM::VM1,"?MRSeriesHardcopyProtocolEV",false }, {0x2005,0x0071,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"StackAngulationAP", false }, {0x2005,0x0072,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"StackAngulationFH", false }, {0x2005,0x0073,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"StackAngulationRL", false }, {0x2005,0x0074,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"StackFovAP", false }, {0x2005,0x0075,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"StackFovFH", false }, {0x2005,0x0076,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"StackFovRL", false }, {0x2005,0x0078,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"StackOffcentreAP", false }, {0x2005,0x0079,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"StackOffcentreFH", false }, {0x2005,0x007a,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"StackOffcentreRL", false }, {0x2005,0x007b,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"StackPreparationDirection", false }, {0x2005,0x007e,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"Z-Spacing (aka Stack Slice Distance)",false }, {0x2005,0x0080,"Philips MR Imaging DD 001",VR::SQ,VM::VM1,"SeriesPlanScan", false }, {0x2005,0x0081,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"StackViewAxis", false }, {0x2005,0x0083,"Philips MR Imaging DD 001",VR::SQ,VM::VM1,"SeriesSlab", false }, {0x2005,0x0084,"Philips MR Imaging DD 001",VR::SQ,VM::VM1,"SeriesReference", false }, {0x2005,0x0085,"Philips MR Imaging DD 001",VR::SQ,VM::VM1,"SeriesVolume", false }, {0x2005,0x0086,"Philips MR Imaging DD 001",VR::SS,VM::VM1,"NumberOfGeometry", false }, {0x2005,0x009e,"Philips MR Imaging DD 001",VR::SQ,VM::VM1,"SeriesGeom", false }, {0x2005,0x009f,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"MRSeriesSpectralSelectiveExcitationPulse", false }, {0x2005,0x00a0,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"Philips Temporal Position Identifier (aka ImageDynamicScanBeginTime)",false }, {0x2005,0x00a1,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"Syncra Scan Type",false }, {0x2005,0x00a2,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"IsCOCA", false }, {0x2005,0x00a3,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"StackCoilID", false }, {0x2005,0x00a4,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"StackCBBCoil1", false }, {0x2005,0x00a5,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"StackCBBCoil2", false }, {0x2005,0x00a6,"Philips MR Imaging DD 001",VR::IS,VM::VM1,"StackChannelCombi", false }, {0x2005,0x00a7,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"StackCoilConn", false }, {0x2005,0x00a8,"Philips MR Imaging DD 001",VR::DS,VM::VM1,"PrivateInversionTime", false }, {0x2005,0x00a9,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?Oversampling Phase (aka SeriesGeometryCorrection)?",false }, {0x2005,0x00b0,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"Diffusion Direction RL (degree)",false }, {0x2005,0x00b1,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"Diffusion Direction AP (degree)",false }, {0x2005,0x00b2,"Philips MR Imaging DD 001",VR::FL,VM::VM1,"Diffusion Direction FH (degree)",false }, {0x2005,0x00c0,"Philips MR Imaging DD 001",VR::CS,VM::VM1,"?SequenceVariant?", false }, /* end of dups */ {0x2005,0x0032,"Philips MR Imaging DD 002",VR::SQ,VM::VM1,"Protocol Data Sequence",false }, {0x2005,0x0034,"Philips MR Imaging DD 002",VR::LT,VM::VM1,"?SeriesTransactionUID?",false }, {0x2005,0x0037,"Philips MR Imaging DD 002",VR::PN,VM::VM1,"Protocol Data Name",false }, {0x2005,0x0038,"Philips MR Imaging DD 002",VR::PN,VM::VM1,"?MRApplicationName",false }, {0x2005,0x0039,"Philips MR Imaging DD 002",VR::PN,VM::VM1,"Protocol Data Type",false }, {0x2005,0x0040,"Philips MR Imaging DD 002",VR::PN,VM::VM1,"?MRVersionStr",false }, {0x2005,0x0041,"Philips MR Imaging DD 002",VR::PN,VM::VM1,"?MRCommentStr",false }, {0x2005,0x0043,"Philips MR Imaging DD 002",VR::SL,VM::VM1,"Protocol Data Block Length (non-padded)",false }, {0x2005,0x0044,"Philips MR Imaging DD 002",VR::OW,VM::VM1,"Protocol Data Block",false }, {0x2005,0x0047,"Philips MR Imaging DD 002",VR::CS,VM::VM1,"Protocol Data Boolean",false }, {0x2005,0x0099,"Philips MR Imaging DD 002",VR::UL,VM::VM1,"?NumberOfRequestExcerpts?",false }, {0x2005,0x0000,"Philips MR Imaging DD 003",VR::UL,VM::VM1,"?NumberOfSOPCommon?",false }, {0x2005,0x0001,"Philips MR Imaging DD 003",VR::UL,VM::VM1,"?NoOfFilmConsumption?",false }, {0x2005,0x0013,"Philips MR Imaging DD 003",VR::UL,VM::VM1,"?NumberOfCodes?",false }, {0x2005,0x0034,"Philips MR Imaging DD 003",VR::SL,VM::VM1,"?MRNumberOfImagePerSeriesRef",false }, {0x2005,0x0043,"Philips MR Imaging DD 003",VR::SS,VM::VM1,"?NoDateOfLastCalibration?",false }, {0x2005,0x0044,"Philips MR Imaging DD 003",VR::SS,VM::VM1,"?NoTimeOfLastCalibration?",false }, {0x2005,0x0045,"Philips MR Imaging DD 003",VR::SS,VM::VM1,"?NrOfSoftwareVersion?",false }, {0x2005,0x0046,"Philips MR Imaging DD 003",VR::SS,VM::VM1,"?",false }, {0x2005,0x0047,"Philips MR Imaging DD 003",VR::SS,VM::VM1,"?NrOfPatientOtherNames?",false }, {0x2005,0x0048,"Philips MR Imaging DD 003",VR::SS,VM::VM1,"?NrOfReqRecipeOfResults?",false }, {0x2005,0x0049,"Philips MR Imaging DD 003",VR::SS,VM::VM1,"?NrOfSeriesOperatorsName?",false }, {0x2005,0x0050,"Philips MR Imaging DD 003",VR::SS,VM::VM1,"?NrOfSeriesPerfPhysiName?",false }, {0x2005,0x0051,"Philips MR Imaging DD 003",VR::SS,VM::VM1,"?NrOfStudyAdmittingDiagnosticDescr?",false }, {0x2005,0x0052,"Philips MR Imaging DD 003",VR::SS,VM::VM1,"?NrOfStudyPatientContrastAllergies?",false }, {0x2005,0x0053,"Philips MR Imaging DD 003",VR::SS,VM::VM1,"?NrOfStudyPatientMedicalAlerts?",false }, {0x2005,0x0054,"Philips MR Imaging DD 003",VR::SS,VM::VM1,"?NrOfStudyPhysiciansOfRecord?",false }, {0x2005,0x0055,"Philips MR Imaging DD 003",VR::SS,VM::VM1,"?NrOfStudyPhysiReadingStudy?",false }, {0x2005,0x0056,"Philips MR Imaging DD 003",VR::SS,VM::VM1,"?MRNrSCSoftwareVersions",false }, {0x2005,0x0057,"Philips MR Imaging DD 003",VR::SS,VM::VM1,"?MRNrRunningAttributes",false }, {0x2005,0x0070,"Philips MR Imaging DD 003",VR::OW,VM::VM1,"FID storage (array of ieee floats)",false }, {0x2005,0x0081,"Philips MR Imaging DD 003",VR::UI,VM::VM1,"?DefaultImageUID",false }, {0x2005,0x0082,"Philips MR Imaging DD 003",VR::CS,VM::VM1,"?RunningAttributes",false }, {0x2005,0x0000,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?MRSpectrumExtraNumber",false }, {0x2005,0x0001,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?MRSpectrumKxCoordinate",false }, {0x2005,0x0002,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?MRSpectrumKyCoordinate",false }, {0x2005,0x0003,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?MRSpectrumLocationNumber",false }, {0x2005,0x0004,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?MRSpectrumMixNumber",false }, {0x2005,0x0005,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?MRSpectrumXCoordinate",false }, {0x2005,0x0006,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?MRSpectrumYCoordinate",false }, {0x2005,0x0007,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"?MRSpectrumDCLevel",false }, {0x2005,0x0008,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"?MRSpectrumNoiseLevel",false }, {0x2005,0x0009,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"?MRSpectrumBeginTime",false }, {0x2005,0x0010,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"Echo Time (ms) (Spectroscopy only)",false }, {0x2005,0x0012,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"Inversion Time (ms) (Spectroscopy only)",false }, {0x2005,0x0013,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?MRSpectrumNumber",false }, {0x2005,0x0014,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?MRSpectrumNumberOfAverages",false }, {0x2005,0x0015,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?MRSpectrumNumberOfSamples",false }, {0x2005,0x0016,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?MRSpectrumScanSequenceNumber",false }, {0x2005,0x0017,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?MRSpectrumNumberOfPeaks",false }, {0x2005,0x0018,"Philips MR Imaging DD 004",VR::SQ,VM::VM1,"?MRSpectrumPeak",false }, {0x2005,0x0025,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRSpectroSIB0Correction",false }, {0x2005,0x0026,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"MRSpectroB0EchoTopPosition", false }, {0x2005,0x0027,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRSpectroComplexComponent", false }, {0x2005,0x0028,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRSpectroDataOrigin", false }, {0x2005,0x0029,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"MRSpectroEchoTopPosition", false }, {0x2005,0x0030,"Philips MR Imaging DD 004",VR::CS,VM::VM1_n,"MRInPlaneTransforms", false }, {0x2005,0x0031,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"MRNumberOfSpectraAcquired", false }, {0x2005,0x0033,"Philips MR Imaging DD 004",VR::FL,VM::VM3,"MRPhaseEncodingEchoTopPositions", false }, {0x2005,0x0034,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRPhysicalQuantityForChemicalShift", false }, {0x2005,0x0035,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRPhysicalQuantitySpatial", false }, {0x2005,0x0036,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"MRReferenceFrequency", false }, {0x2005,0x0037,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"MRSampleOffset", false }, {0x2005,0x0038,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"MRSamplePitch", false }, {0x2005,0x0039,"Philips MR Imaging DD 004",VR::SS,VM::VM2,"MRSearchIntervalForPeaks", false }, {0x2005,0x0040,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRSignalDomainForChemicalShift", false }, {0x2005,0x0041,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRSignalDomainSpatial", false }, {0x2005,0x0042,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRSignalType", false }, {0x2005,0x0043,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRSpectroAdditionalRotations", false }, {0x2005,0x0044,"Philips MR Imaging DD 004",VR::SS,VM::VM1_n,"MRSpectroDisplayRanges", false }, {0x2005,0x0045,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRSpectroEchoAcquisition", false }, {0x2005,0x0046,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRSpectroFrequencyUnit", false }, {0x2005,0x0047,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"MRSpectroGamma", false }, {0x2005,0x0048,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRSpectroHiddenLineRemoval", false }, {0x2005,0x0049,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"MRSpectroHorizontalShift", false }, {0x2005,0x0050,"Philips MR Imaging DD 004",VR::FL,VM::VM2,"MRSpectroHorizontalWindow", false }, {0x2005,0x0051,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"MRSpectroNumberOfDisplayRanges", false }, {0x2005,0x0052,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"MRSpectroNumberOfEchoPulses", false }, {0x2005,0x0053,"Philips MR Imaging DD 004",VR::LO,VM::VM1_n,"MRSpectroProcessingHistory", false }, {0x2005,0x0054,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRSpectroScanType", false }, {0x2005,0x0055,"Philips MR Imaging DD 004",VR::FL,VM::VM1_n,"MRSpectroSICSIntervals", false }, {0x2005,0x0056,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRSpectroSIMode", false }, {0x2005,0x0057,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"Sampling Frequency (aka MRSpectroSpectralBW)",false }, {0x2005,0x0058,"Philips MR Imaging DD 004",VR::LO,VM::VM1,"MRSpectroTitleLine", false }, {0x2005,0x0059,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"MRSpectroTurboEchoSpacing", false }, {0x2005,0x0060,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"MRSpectroVerticalShift", false }, {0x2005,0x0061,"Philips MR Imaging DD 004",VR::FL,VM::VM2,"MRSpectroVerticalWindow", false }, {0x2005,0x0062,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"MRSpectroOffset", false }, {0x2005,0x0063,"Philips MR Imaging DD 004",VR::FL,VM::VM1,"MRSpectrumPitch", false }, {0x2005,0x0064,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRVolumeSelection", false }, {0x2005,0x0070,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"MRNoMixesSpectro", false }, {0x2005,0x0071,"Philips MR Imaging DD 004",VR::SQ,VM::VM1,"MRSeriesSPMix", false }, {0x2005,0x0072,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?SPMixTResolution",false }, {0x2005,0x0073,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?SPMixKXResolution",false }, {0x2005,0x0074,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?SPMixKYResolution",false }, {0x2005,0x0075,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?SPMixFResolution",false }, {0x2005,0x0076,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?SPMixXResolution",false }, {0x2005,0x0077,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?SPMixYResolution",false }, {0x2005,0x0078,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?SPMixNoSpectraIntended",false }, {0x2005,0x0079,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?SPMixNoAverages",false }, {0x2005,0x0081,"Philips MR Imaging DD 004",VR::IS,VM::VM1,"MRScanoGramSurveyNumberOfImages", false }, {0x2005,0x0082,"Philips MR Imaging DD 004",VR::UL,VM::VM1,"MRNumberOfProcedureCodes", false }, {0x2005,0x0083,"Philips MR Imaging DD 004",VR::CS,VM::VM1_n,"?SortAttributes",false }, {0x2005,0x0084,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?MRNrSortAttributes",false }, {0x2005,0x0085,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"?ImageDisplayDirection",false }, {0x2005,0x0086,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"?InsetScanogram",false }, {0x2005,0x0087,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?MRDisplayLayoutNrColumns",false }, {0x2005,0x0088,"Philips MR Imaging DD 004",VR::SS,VM::VM1,"?MRDisplayLayoutNrRows",false }, {0x2005,0x0089,"Philips MR Imaging DD 004",VR::SQ,VM::VM1,"?ViewingProtocol",false }, {0x2005,0x0090,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRStackCoilFunction", false }, {0x2005,0x0091,"Philips MR Imaging DD 004",VR::PN,VM::VM1,"?PatientNameJobInParams",false }, {0x2005,0x0092,"Philips MR Imaging DD 004",VR::IS,VM::VM1,"MRGeolinkID", false }, {0x2005,0x0093,"Philips MR Imaging DD 004",VR::IS,VM::VM1,"MRStationNo", false }, {0x2005,0x0095,"Philips MR Imaging DD 004",VR::ST,VM::VM1,"?ViewProcedureString",false }, {0x2005,0x0096,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRFlowImagesPresent", false }, {0x2005,0x0097,"Philips MR Imaging DD 004",VR::LO,VM::VM1,"Anatomic Region Code Value",false }, {0x2005,0x0098,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRMobiviewEnabled", false }, {0x2005,0x0099,"Philips MR Imaging DD 004",VR::CS,VM::VM1,"MRIViewBoldEnabled", false }, /* new group */ {0x2005,0x0000,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"MRVolumeViewEnabled", false }, {0x2005,0x0001,"Philips MR Imaging DD 005",VR::UL,VM::VM1,"MRNumberOfStudyReference", false }, {0x2005,0x0002,"Philips MR Imaging DD 005",VR::SQ,VM::VM1,"SPSCode", false }, {0x2005,0x0003,"Philips MR Imaging DD 005",VR::UL,VM::VM1,"MRNumberOfSPSCodes", false }, {0x2005,0x0004,"Philips MR Imaging DD 005",VR::SS,VM::VM1,"?",false }, {0x2005,0x0006,"Philips MR Imaging DD 005",VR::SS,VM::VM1,"?",false }, {0x2005,0x0007,"Philips MR Imaging DD 005",VR::SS,VM::VM1,"MRNrOfSpecificCharacterSet", false }, {0x2005,0x0009,"Philips MR Imaging DD 005",VR::DS,VM::VM1,"Rescale Intercept Philips",false }, {0x2005,0x000a,"Philips MR Imaging DD 005",VR::DS,VM::VM1,"Rescale Slope Philips",false }, {0x2005,0x000b,"Philips MR Imaging DD 005",VR::LO,VM::VM1,"Rescale Type Philips",false }, {0x2005,0x000e,"Philips MR Imaging DD 005",VR::SQ,VM::VM1,"PrivateSharedSq", false }, {0x2005,0x000f,"Philips MR Imaging DD 005",VR::SQ,VM::VM1,"Acquisition Parameters (Philips) Sequence",false }, {0x2005,0x0010,"Philips MR Imaging DD 005",VR::IS,VM::VM1,"?MFConvTreatSpectorMixNo",false }, {0x2005,0x0011,"Philips MR Imaging DD 005",VR::UI,VM::VM1,"MFPrivateReferencedSOPInstanceUID", false }, {0x2005,0x0012,"Philips MR Imaging DD 005",VR::IS,VM::VM1,"MRImageDiffBValueNumber", false }, {0x2005,0x0013,"Philips MR Imaging DD 005",VR::IS,VM::VM1,"MRImageGradientOrientationNumber", false }, {0x2005,0x0014,"Philips MR Imaging DD 005",VR::SL,VM::VM1,"MRSeriesNrOfDiffBValues", false }, {0x2005,0x0015,"Philips MR Imaging DD 005",VR::SL,VM::VM1,"MRSeriesNrOfDiffGradOrients", false }, {0x2005,0x0016,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"MRSeriesPlanMode", false }, {0x2005,0x0017,"Philips MR Imaging DD 005",VR::FD,VM::VM1,"B_matrix / DiffusionBMatrix", false }, {0x2005,0x0018,"Philips MR Imaging DD 005",VR::CS,VM::VM3,"Operating Mode Type",false }, {0x2005,0x0019,"Philips MR Imaging DD 005",VR::CS,VM::VM3,"Operating Mode",false }, {0x2005,0x001a,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"MRFatSaturationTechnique", false }, {0x2005,0x001b,"Philips MR Imaging DD 005",VR::IS,VM::VM1,"MRVersionNumberDeletedImages", false }, {0x2005,0x001c,"Philips MR Imaging DD 005",VR::IS,VM::VM1,"MRVersionNumberDeletedSpectra", false }, {0x2005,0x001d,"Philips MR Imaging DD 005",VR::IS,VM::VM1,"MRVersionNumberDeletedBlobsets", false }, {0x2005,0x001e,"Philips MR Imaging DD 005",VR::UL,VM::VM1,"LUT1Offset?",false }, {0x2005,0x001f,"Philips MR Imaging DD 005",VR::UL,VM::VM1,"LUT1Range?",false }, {0x2005,0x0020,"Philips MR Imaging DD 005",VR::UL,VM::VM1,"?LUT1BeginColor",false }, {0x2005,0x0021,"Philips MR Imaging DD 005",VR::UL,VM::VM1,"?LUT1EndColor",false }, {0x2005,0x0022,"Philips MR Imaging DD 005",VR::UL,VM::VM1,"?LUT2Offset",false }, {0x2005,0x0023,"Philips MR Imaging DD 005",VR::UL,VM::VM1,"?LUT2Range",false }, {0x2005,0x0024,"Philips MR Imaging DD 005",VR::UL,VM::VM1,"?LUT2BeginColor",false }, {0x2005,0x0025,"Philips MR Imaging DD 005",VR::UL,VM::VM1,"?LUT2EndColor",false }, {0x2005,0x0026,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"ViewingHardcopyOnly", false }, {0x2005,0x0027,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"?PrivateEMR",false }, {0x2005,0x0028,"Philips MR Imaging DD 005",VR::SL,VM::VM1,"MRSeriesNrOfLabelTypes", false }, {0x2005,0x0029,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"?MRImageLabelType",false }, {0x2005,0x002a,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"ExamPrintStatus", false }, {0x2005,0x002b,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"ExamExportStatus", false }, {0x2005,0x002c,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"ExamStorageCommitStatus", false }, {0x2005,0x002d,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"ExamMediaWriteStatus", false }, {0x2005,0x002e,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"?MRSeriesDBdt",false }, {0x2005,0x002f,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"?MRSeriesProtonSAR",false }, {0x2005,0x0030,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"?MRSeriesNonProtonSAR",false }, {0x2005,0x0031,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"?MRSeriesLocalSAR",false }, {0x2005,0x0032,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"MRSeriesSafetyOverrideMode", false }, {0x2005,0x0035,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"SpectroExamcard", false }, {0x2005,0x0036,"Philips MR Imaging DD 005",VR::UI,VM::VM1,"?MRRefSeriesInstanceUID",false }, {0x2005,0x0037,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"?ColorLUTType",false }, {0x2005,0x0038,"Philips MR Imaging DD 005",VR::LT,VM::VM1,"?",false }, {0x2005,0x0039,"Philips MR Imaging DD 005",VR::LT,VM::VM1,"?",false }, {0x2005,0x003a,"Philips MR Imaging DD 005",VR::LT,VM::VM1,"DataDictionaryContentsVersion", false }, {0x2005,0x003b,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"MRIsCoilSurvey", false }, {0x2005,0x003c,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"MRStackTablePosLong", false }, {0x2005,0x003d,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"MRStackTablePosLat", false }, {0x2005,0x003e,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"MRStackPosteriorCoilPos", false }, {0x2005,0x003f,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"AIMDLimitsApplied", false }, {0x2005,0x0040,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"AIMDHeadSARLimit", false }, {0x2005,0x0041,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"AIMDWholeBodySARLimit", false }, {0x2005,0x0042,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"AIMDB1RMSLimit", false }, {0x2005,0x0043,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"AIMDdbDtLimit", false }, {0x2005,0x0044,"Philips MR Imaging DD 005",VR::IS,VM::VM1,"TFEFactor", false }, {0x2005,0x0045,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"AttenuationCorrection", false }, {0x2005,0x0046,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"?FWHMShim",false }, {0x2005,0x0047,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"PowerOptimization", false }, {0x2005,0x0048,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"?CoilQ",false }, {0x2005,0x0049,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"?ReceiverGain",false }, {0x2005,0x004a,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"DataWindowDuration", false }, {0x2005,0x004b,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"MixingTime", false }, {0x2005,0x004c,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"FirstEchoTime", false }, {0x2005,0x004d,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"IsB0Series", false }, {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,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 }, {0x2005,0x0054,"Philips MR Imaging DD 006",VR::FL,VM::VM1,"MRE Amplitude",false }, {0x2005,0x0055,"Philips MR Imaging DD 006",VR::FL,VM::VM1,"MREMEG Frequency",false }, {0x2005,0x0056,"Philips MR Imaging DD 006",VR::FL,VM::VM1,"MREMEG Pairs",false }, {0x2005,0x0057,"Philips MR Imaging DD 006",VR::CS,VM::VM1,"MREMEG Direction",false }, {0x2005,0x0058,"Philips MR Imaging DD 006",VR::FL,VM::VM1,"MREMEG Amplitude",false }, {0x2005,0x0059,"Philips MR Imaging DD 006",VR::FL,VM::VM1,"MRE Number of Phase Delays",false }, {0x2005,0x0060,"Philips MR Imaging DD 006",VR::IS,VM::VM1,"MRE Number of Motion Cycles",false }, {0x2005,0x0061,"Philips MR Imaging DD 006",VR::FL,VM::VM1,"MRE Motion Meg Phase Delay",false }, {0x2005,0x0062,"Philips MR Imaging DD 006",VR::LT,VM::VM1,"MRE Inversion Algorithm Version",false }, {0x2005,0x0063,"Philips MR Imaging DD 006",VR::CS,VM::VM1,"Sagittal Slice Order",false }, {0x2005,0x0064,"Philips MR Imaging DD 006",VR::CS,VM::VM1,"Coronal Slice Order",false }, {0x2005,0x0065,"Philips MR Imaging DD 006",VR::CS,VM::VM1,"Transversal Slice Order",false }, {0x2005,0x0066,"Philips MR Imaging DD 006",VR::CS,VM::VM1,"Series Orientation ",false }, {0x2005,0x0067,"Philips MR Imaging DD 006",VR::IS,VM::VM1,"MR Stack Reverse ",false }, {0x2005,0x0068,"Philips MR Imaging DD 006",VR::IS,VM::VM1,"MRE Phase Delay Number",false }, {0x2005,0x0071,"Philips MR Imaging DD 006",VR::IS,VM::VM1,"Number Of Inversion Delays",false }, {0x2005,0x0072,"Philips MR Imaging DD 006",VR::FL,VM::VM1,"Inversion Delay Time",false }, {0x2005,0x0073,"Philips MR Imaging DD 006",VR::IS,VM::VM1,"Inversion Delay Number",false }, {0x2005,0x0074,"Philips MR Imaging DD 006",VR::DS,VM::VM1,"Max DB DT",false }, {0x2005,0x0075,"Philips MR Imaging DD 006",VR::DS,VM::VM1,"Max SAR",false }, {0x2005,0x0076,"Philips MR Imaging DD 006",VR::LT,VM::VM1,"SAR Type",false }, {0x2005,0x0078,"Philips MR Imaging DD 006",VR::CS,VM::VM1,"Metal Implant Status",false }, {0x2005,0x0079,"Philips MR Imaging DD 006",VR::CS,VM::VM1_n,"Orientation Mirror Flip",false }, {0x2005,0x0081,"Philips MR Imaging DD 006",VR::CS,VM::VM1,"SAR Operation Mode",false }, {0x2005,0x0082,"Philips MR Imaging DD 006",VR::IS,VM::VM1,"Spatial Gradient",false }, {0x2005,0x0083,"Philips MR Imaging DD 006",VR::LT,VM::VM1,"Additional Constraints",false }, {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 }, /* new group */ {0x7043,0x0000,"Philips NM Private Group",VR::SH,VM::VM1,"?",false }, {0x0511,0x0000,"Philips PET Private Group",VR::US,VM::VM1,"?",false }, {0x0511,0x0001,"Philips PET Private Group",VR::US,VM::VM1,"?",false }, {0x0511,0x0002,"Philips PET Private Group",VR::OB,VM::VM1,"?",false }, {0x0511,0x0003,"Philips PET Private Group",VR::OB,VM::VM1,"?",false }, {0x0511,0x0032,"Philips PET Private Group",VR::DS,VM::VM1,"?",false }, {0x0511,0x0050,"Philips PET Private Group",VR::DS,VM::VM1,"?",false }, {0x7053,0x0000,"Philips PET Private Group",VR::DS,VM::VM1,"SUV Scale Factor",false }, {0x7053,0x0001,"Philips PET Private Group",VR::OB,VM::VM1,"Private",false }, {0x7053,0x0002,"Philips PET Private Group",VR::OB,VM::VM1,"Private",false }, {0x7053,0x0003,"Philips PET Private Group",VR::ST,VM::VM1,"Original image file name",false }, {0x7053,0x0004,"Philips PET Private Group",VR::OB,VM::VM1,"File Data",false }, {0x7053,0x0005,"Philips PET Private Group",VR::LO,VM::VM1,"Worklist Info File Name",false }, {0x7053,0x0006,"Philips PET Private Group",VR::OB,VM::VM1,"Private",false }, {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,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 }, {0x7053,0x0012,"Philips PET Private Group",VR::SQ,VM::VM1,"File Data Sequence",false }, {0x7053,0x0013,"Philips PET Private Group",VR::SS,VM::VM1,"Private",false }, {0x7053,0x0014,"Philips PET Private Group",VR::SS,VM::VM1,"Private",false }, {0x7053,0x0015,"Philips PET Private Group",VR::SS,VM::VM1,"Private",false }, {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,0x00c2,"Philips PET Private Group",VR::UI,VM::VM1,"PET-CT Multi Modality Name",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 }, {0x200b,0x0005,"Philips RAD Imaging DD 001",VR::IS,VM::VM1,"?",false }, {0x200b,0x0011,"Philips RAD Imaging DD 001",VR::LO,VM::VM1,"?",false }, {0x200b,0x0027,"Philips RAD Imaging DD 001",VR::DT,VM::VM1,"?",false }, {0x200b,0x0028,"Philips RAD Imaging DD 001",VR::DS,VM::VM1,"?",false }, {0x200b,0x0029,"Philips RAD Imaging DD 001",VR::DS,VM::VM1,"?",false }, {0x200b,0x002a,"Philips RAD Imaging DD 001",VR::UL,VM::VM1,"?",false }, {0x200b,0x002b,"Philips RAD Imaging DD 001",VR::DA,VM::VM1,"?",false }, {0x200b,0x002c,"Philips RAD Imaging DD 001",VR::TM,VM::VM1,"?",false }, {0x200b,0x002d,"Philips RAD Imaging DD 001",VR::LO,VM::VM1,"?",false }, {0x200b,0x003b,"Philips RAD Imaging DD 001",VR::LO,VM::VM1,"?",false }, {0x200b,0x0040,"Philips RAD Imaging DD 001",VR::SH,VM::VM1,"?",false }, {0x200b,0x0041,"Philips RAD Imaging DD 001",VR::SH,VM::VM1,"?",false }, {0x200b,0x0042,"Philips RAD Imaging DD 001",VR::UI,VM::VM1,"?",false }, {0x200b,0x0043,"Philips RAD Imaging DD 001",VR::UI,VM::VM1,"?",false }, {0x200b,0x0047,"Philips RAD Imaging DD 001",VR::DA,VM::VM1,"?",false }, {0x200b,0x0048,"Philips RAD Imaging DD 001",VR::SH,VM::VM1,"?",false }, {0x200b,0x004c,"Philips RAD Imaging DD 001",VR::SH,VM::VM1,"?",false }, {0x200b,0x004d,"Philips RAD Imaging DD 001",VR::SH,VM::VM1,"?",false }, {0x200b,0x004f,"Philips RAD Imaging DD 001",VR::DT,VM::VM1,"?",false }, {0x200b,0x0052,"Philips RAD Imaging DD 001",VR::SH,VM::VM1,"?",false }, {0x200b,0x0000,"Philips RAD Imaging DD 097",VR::ST,VM::VM1,"?",false }, {0x200b,0x0001,"Philips RAD Imaging DD 097",VR::CS,VM::VM1,"?",false }, {0x200b,0x0002,"Philips RAD Imaging DD 097",VR::SS,VM::VM1,"?",false }, {0x200b,0x0050,"Philips RAD Imaging DD 097",VR::SS,VM::VM1,"?",false }, {0x200b,0x0051,"Philips RAD Imaging DD 097",VR::SS,VM::VM1,"?",false }, {0x200b,0x0052,"Philips RAD Imaging DD 097",VR::SS,VM::VM1,"?",false }, {0x200b,0x0053,"Philips RAD Imaging DD 097",VR::SS,VM::VM1,"?",false }, {0x200b,0x0054,"Philips RAD Imaging DD 097",VR::ST,VM::VM1,"?",false }, {0x200b,0x0060,"Philips RAD Imaging DD 097",VR::LO,VM::VM1,"?",false }, {0x200b,0x0063,"Philips RAD Imaging DD 097",VR::LT,VM::VM1,"?",false }, {0x200b,0x0065,"Philips RAD Imaging DD 097",VR::SS,VM::VM1,"?",false }, {0x200b,0x006e,"Philips RAD Imaging DD 097",VR::US,VM::VM1,"?",false }, {0x200b,0x006f,"Philips RAD Imaging DD 097",VR::UI,VM::VM1,"?",false }, {0x200b,0x0072,"Philips RAD Imaging DD 097",VR::FD,VM::VM1,"?",false }, {0x200b,0x0073,"Philips RAD Imaging DD 097",VR::SS,VM::VM1,"?",false }, {0x200b,0x0074,"Philips RAD Imaging DD 097",VR::IS,VM::VM1,"?",false }, {0x200b,0x0075,"Philips RAD Imaging DD 097",VR::CS,VM::VM1,"?",false }, {0x200b,0x0076,"Philips RAD Imaging DD 097",VR::SH,VM::VM1,"?",false }, {0x200b,0x0078,"Philips RAD Imaging DD 097",VR::IS,VM::VM1_n,"?",false }, {0x200b,0x0079,"Philips RAD Imaging DD 097",VR::IS,VM::VM1,"?",false }, {0x200b,0x007a,"Philips RAD Imaging DD 097",VR::IS,VM::VM1,"?",false }, {0x200b,0x007b,"Philips RAD Imaging DD 097",VR::US,VM::VM1,"?",false }, {0x200b,0x007c,"Philips RAD Imaging DD 097",VR::US,VM::VM1,"?",false }, {0x200b,0x007d,"Philips RAD Imaging DD 097",VR::IS,VM::VM1_n,"?",false }, {0x200b,0x007e,"Philips RAD Imaging DD 097",VR::UI,VM::VM1,"?",false }, {0x200b,0x0081,"Philips RAD Imaging DD 097",VR::SH,VM::VM1,"?",false }, {0x200b,0x0082,"Philips RAD Imaging DD 097",VR::SH,VM::VM1,"?",false }, {0x200b,0x0085,"Philips RAD Imaging DD 097",VR::IS,VM::VM1,"?",false }, {0x200b,0x0086,"Philips RAD Imaging DD 097",VR::CS,VM::VM1,"?",false }, {0x200b,0x0088,"Philips RAD Imaging DD 097",VR::CS,VM::VM1,"?",false }, {0x200b,0x0089,"Philips RAD Imaging DD 097",VR::LO,VM::VM1,"?",false }, {0x200b,0x0090,"Philips RAD Imaging DD 097",VR::DS,VM::VM1,"?",false }, {0x200b,0x0096,"Philips RAD Imaging DD 097",VR::SH,VM::VM1,"?",false }, {0x200b,0x0099,"Philips RAD Imaging DD 097",VR::SH,VM::VM1,"?",false }, {0x200b,0x009a,"Philips RAD Imaging DD 097",VR::FD,VM::VM1,"?",false }, {0x200b,0x009b,"Philips RAD Imaging DD 097",VR::FD,VM::VM1,"?",false }, {0x200b,0x009f,"Philips RAD Imaging DD 097",VR::SQ,VM::VM1,"?",false }, {0x200b,0x00a0,"Philips RAD Imaging DD 097",VR::LT,VM::VM1,"?",false }, {0x200b,0x00a1,"Philips RAD Imaging DD 097",VR::CS,VM::VM1,"?bool?",false }, {0x0029,0x0050,"Philips US Imaging 60",VR::CS,VM::VM1,"?COLOR/CPA/NONE?",false }, {0x0031,0x0030,"Philips US Imaging 60",VR::UL,VM::VM1,"Private data",false }, {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,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,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 }, {0x200d,0x0003,"Philips US Imaging DD 033",VR::LO,VM::VM6,"?",false }, {0x200d,0x0004,"Philips US Imaging DD 033",VR::LO,VM::VM6,"?",false }, {0x200d,0x0005,"Philips US Imaging DD 033",VR::LO,VM::VM1_n,"?",false }, {0x200d,0x0006,"Philips US Imaging DD 033",VR::LO,VM::VM6,"?",false }, {0x200d,0x0007,"Philips US Imaging DD 033",VR::LO,VM::VM1,"?",false }, {0x200d,0x0008,"Philips US Imaging DD 033",VR::LO,VM::VM1,"?",false }, {0x200d,0x0009,"Philips US Imaging DD 033",VR::LO,VM::VM1,"?",false }, {0x200d,0x000a,"Philips US Imaging DD 033",VR::LO,VM::VM1,"?",false }, {0x200d,0x000b,"Philips US Imaging DD 033",VR::OB,VM::VM1,"Raw Data US",false }, {0x200d,0x000d,"Philips US Imaging DD 033",VR::LO,VM::VM1,"UDM USD DATATYPE DIN",false }, {0x200d,0x000f,"Philips US Imaging DD 033",VR::OB,VM::VM1,"XML: UAA / CaptureContext",false }, {0x200d,0x0010,"Philips US Imaging DD 033",VR::IS,VM::VM1,"Number of Frames",false }, {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,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 }, {0x200d,0x0004,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x0005,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x0006,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x0007,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x0008,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x0009,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x000a,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x000b,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x000c,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x000d,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x000e,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x000f,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x0010,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x0021,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x0022,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x0023,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x0024,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x0001,"Philips US Imaging DD 035",VR::LO,VM::VM1,"?",false }, {0x200d,0x0002,"Philips US Imaging DD 035",VR::LO,VM::VM1,"?",false }, {0x200d,0x0003,"Philips US Imaging DD 035",VR::LO,VM::VM1,"?",false }, {0x200d,0x0004,"Philips US Imaging DD 035",VR::LO,VM::VM1,"?",false }, {0x200d,0x0005,"Philips US Imaging DD 035",VR::LO,VM::VM1,"?",false }, {0x200d,0x0007,"Philips US Imaging DD 035",VR::LO,VM::VM1,"?",false }, {0x200d,0x0008,"Philips US Imaging DD 035",VR::LO,VM::VM1,"?",false }, {0x200d,0x0009,"Philips US Imaging DD 035",VR::LO,VM::VM1,"?",false }, {0x200d,0x000a,"Philips US Imaging DD 035",VR::LO,VM::VM1,"?",false }, {0x200d,0x000b,"Philips US Imaging DD 035",VR::LO,VM::VM1,"?",false }, {0x200d,0x000c,"Philips US Imaging DD 035",VR::LO,VM::VM1,"?",false }, {0x200d,0x000d,"Philips US Imaging DD 035",VR::LO,VM::VM1,"?",false }, {0x200d,0x0001,"Philips US Imaging DD 036",VR::LO,VM::VM3,"Cols/Rows/Frames",false }, {0x200d,0x0002,"Philips US Imaging DD 036",VR::LO,VM::VM3,"Cols/Rows/Frames",false }, {0x200d,0x0003,"Philips US Imaging DD 036",VR::LO,VM::VM3,"Voxel Spacing",false }, {0x200d,0x0004,"Philips US Imaging DD 036",VR::LO,VM::VM3,"?",false }, {0x200d,0x0001,"Philips US Imaging DD 038",VR::LO,VM::VM1,"?",false }, {0x200d,0x0001,"Philips US Imaging DD 039",VR::LO,VM::VM1,"?",false }, {0x200d,0x0004,"Philips US Imaging DD 039",VR::LO,VM::VM1,"?",false }, {0x200d,0x0005,"Philips US Imaging DD 039",VR::LO,VM::VM1,"?",false }, {0x200d,0x0006,"Philips US Imaging DD 039",VR::LO,VM::VM1,"?",false }, {0x200d,0x0007,"Philips US Imaging DD 039",VR::LO,VM::VM1,"?",false }, {0x200d,0x0008,"Philips US Imaging DD 039",VR::LO,VM::VM1,"?",false }, {0x200d,0x0009,"Philips US Imaging DD 039",VR::LO,VM::VM1,"?",false }, {0x200d,0x000a,"Philips US Imaging DD 039",VR::LO,VM::VM1,"?",false }, {0x200d,0x000b,"Philips US Imaging DD 039",VR::LO,VM::VM1,"?",false }, {0x200d,0x000c,"Philips US Imaging DD 039",VR::LO,VM::VM1,"?",false }, {0x200d,0x000d,"Philips US Imaging DD 039",VR::LO,VM::VM1,"?",false }, {0x200d,0x0001,"Philips US Imaging DD 040",VR::LO,VM::VM1,"?",false }, {0x200d,0x0002,"Philips US Imaging DD 040",VR::LO,VM::VM1,"?",false }, {0x200d,0x0003,"Philips US Imaging DD 040",VR::LO,VM::VM1,"?",false }, {0x200d,0x0004,"Philips US Imaging DD 040",VR::LO,VM::VM1,"?",false }, {0x200d,0x0005,"Philips US Imaging DD 040",VR::LO,VM::VM1,"?",false }, {0x200d,0x0006,"Philips US Imaging DD 040",VR::LO,VM::VM1,"?",false }, {0x200d,0x0007,"Philips US Imaging DD 040",VR::LO,VM::VM1,"?",false }, {0x200d,0x0020,"Philips US Imaging DD 040",VR::LO,VM::VM1,"?",false }, {0x200d,0x001e,"Philips US Imaging DD 041",VR::LO,VM::VM1,"?",false }, {0x200d,0x0015,"Philips US Imaging DD 042",VR::IS,VM::VM1,"?",false }, {0x200d,0x0016,"Philips US Imaging DD 042",VR::FD,VM::VM1,"?",false }, {0x200d,0x0050,"Philips US Imaging DD 042",VR::LO,VM::VM3,"?",false }, {0x200d,0x0051,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0052,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0053,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0054,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0055,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0056,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0057,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0058,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0059,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x005a,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x005b,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x005c,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x005d,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x005e,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x005f,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0060,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0070,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0071,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0072,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0073,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0074,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0075,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {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,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 }, {0x200d,0x00fa,"Philips US Imaging DD 045",VR::CS,VM::VM1,"ZLib/None",false }, {0x200d,0x00fb,"Philips US Imaging DD 045",VR::OB,VM::VM1,"Frames header array",false }, {0x200d,0x0000,"Philips US Imaging DD 066",VR::OB,VM::VM1,"Philips Confidential v.1",false }, {0x200d,0x0000,"Philips US Imaging DD 109",VR::US,VM::VM1,"?",false }, {0x200d,0x0001,"Philips US Imaging DD 109",VR::SQ,VM::VM1,"?",false }, {0x200d,0x0002,"Philips US Imaging DD 109",VR::ST,VM::VM1,"?",false }, {0x200d,0x0003,"Philips US Imaging DD 109",VR::CS,VM::VM1,"?",false }, {0x200d,0x0004,"Philips US Imaging DD 109",VR::SL,VM::VM4,"?",false }, {0x200d,0x0005,"Philips US Imaging DD 109",VR::UL,VM::VM3,"?",false }, {0x200d,0x0006,"Philips US Imaging DD 109",VR::UL,VM::VM3,"?",false }, {0x200d,0x0007,"Philips US Imaging DD 109",VR::CS,VM::VM1,"?",false }, {0x200d,0x0008,"Philips US Imaging DD 109",VR::CS,VM::VM1,"?",false }, {0x200d,0x0009,"Philips US Imaging DD 109",VR::OB,VM::VM1,"?",false }, {0x200d,0x000a,"Philips US Imaging DD 109",VR::UL,VM::VM1,"?",false }, {0x200d,0x000b,"Philips US Imaging DD 109",VR::OB,VM::VM1,"?",false }, {0x200d,0x000c,"Philips US Imaging DD 109",VR::UL,VM::VM1,"?",false }, {0x200d,0x000d,"Philips US Imaging DD 109",VR::SQ,VM::VM1,"?",false }, {0x200d,0x000e,"Philips US Imaging DD 109",VR::CS,VM::VM1,"?",false }, {0x200d,0x000f,"Philips US Imaging DD 109",VR::LO,VM::VM1,"?",false }, {0x200d,0x0010,"Philips US Imaging DD 109",VR::SL,VM::VM1,"?",false }, {0x200d,0x0011,"Philips US Imaging DD 109",VR::LO,VM::VM1,"?",false }, {0x200d,0x0012,"Philips US Imaging DD 109",VR::SL,VM::VM1,"?",false }, {0x200d,0x0013,"Philips US Imaging DD 109",VR::US,VM::VM1_n,"?",false }, {0x200d,0x0014,"Philips US Imaging DD 109",VR::CS,VM::VM1,"?",false }, {0x200d,0x0001,"Philips US Imaging DD 113",VR::LO,VM::VM1,"?",false }, {0x200d,0x0002,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x0003,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x0004,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x0005,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x0006,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x0007,"Philips US Imaging DD 113",VR::CS,VM::VM1,"?",false }, {0x200d,0x0008,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, // 16bits RLE {0x200d,0x0009,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x000a,"Philips US Imaging DD 113",VR::FD,VM::VM1_n,"?",false }, {0x200d,0x000b,"Philips US Imaging DD 113",VR::CS,VM::VM1,"?",false }, {0x200d,0x000c,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x000d,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x000e,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x000f,"Philips US Imaging DD 113",VR::DS,VM::VM1_n,"?",false }, {0x200d,0x0010,"Philips US Imaging DD 113",VR::DS,VM::VM1_n,"?",false }, {0x200d,0x0011,"Philips US Imaging DD 113",VR::SL,VM::VM1,"?",false }, {0x200d,0x0012,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x0013,"Philips US Imaging DD 113",VR::FL,VM::VM1_n,"?",false }, {0x200d,0x0014,"Philips US Imaging DD 113",VR::US_SS,VM::VM1_n,"?",false }, {0x200d,0x0015,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x0017,"Philips US Imaging DD 113",VR::FD,VM::VM1,"?",false }, {0x200d,0x0018,"Philips US Imaging DD 113",VR::FD,VM::VM1,"?",false }, {0x200d,0x0019,"Philips US Imaging DD 113",VR::FD,VM::VM1,"?",false }, {0x200d,0x001a,"Philips US Imaging DD 113",VR::FD,VM::VM1,"?",false }, {0x200d,0x001b,"Philips US Imaging DD 113",VR::FD,VM::VM1,"?",false }, {0x200d,0x001c,"Philips US Imaging DD 113",VR::FD,VM::VM1,"?",false }, {0x200d,0x001d,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x001e,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x001f,"Philips US Imaging DD 113",VR::FD,VM::VM1,"?",false }, {0x200d,0x0020,"Philips US Imaging DD 113",VR::FD,VM::VM1,"?",false }, {0x200d,0x0021,"Philips US Imaging DD 113",VR::FD,VM::VM1,"?",false }, {0x200d,0x0022,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x0024,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x0025,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x0026,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x0027,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x0028,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x0031,"Philips US Imaging DD 113",VR::UL,VM::VM1,"?",false }, {0x200d,0x0002,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Echo Vision Setting",false }, {0x200d,0x0003,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Color Vision Setting",false }, {0x200d,0x0004,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Transparency",false }, {0x200d,0x0006,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Vision Vol Brightness",false }, {0x200d,0x0008,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Low Threshold",false }, {0x200d,0x0009,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Image Layout",false }, {0x200d,0x000a,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Xres Filtering Enabled",false }, {0x200d,0x000b,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Echo Twod Chroma Map Enabled",false }, {0x200d,0x000c,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Box Outlined Enabled",false }, {0x200d,0x000d,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Smoothing Enabled",false }, {0x200d,0x000e,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Reference Graphic Enabled",false }, {0x200d,0x000f,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Map Inverted",false }, {0x200d,0x0010,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Color Stream Display Enabled",false }, {0x200d,0x0011,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Echo Stream Display Enabled",false }, {0x200d,0x0012,"Philips US Private 3D",VR::LO,VM::VM1,"Vdb Param Color 3d Estimate Scale(2)",false }, {0x200d,0x0013,"Philips US Private 3D",VR::LO,VM::VM1,"Vdb Param Color 3d Estimate Apex Position (1)",false }, {0x200d,0x0014,"Philips US Private 3D",VR::LO,VM::VM1,"Vdb Param Color 3d Estimate Color Offset",false }, {0x200d,0x0015,"Philips US Private 3D",VR::LO,VM::VM1,"Vdb Param Echo 3d Estimate Dimension(2)",false }, {0x200d,0x0016,"Philips US Private 3D",VR::SQ,VM::VM1,"Private Native Threed Data Sequence(1)",false }, {0x200d,0x0017,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Basic Vol Brightness",false }, {0x200d,0x0018,"Philips US Private 3D",VR::LO,VM::VM1,"Vdb Param Echo 3d Estimate Apex Position (2)",false }, {0x200d,0x001a,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Echo Smoothing",false }, {0x200d,0x001b,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Color Smoothing",false }, {0x200d,0x001e,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Num Completed Trim Planes",false }, {0x200d,0x001f,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Depth",false }, {0x200d,0x0020,"Philips US Private 3D",VR::SQ,VM::VM1,"Private Native Data Stream Array",false }, {0x200d,0x0021,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Wall Filter",false }, {0x200d,0x0023,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Baseline",false }, {0x200d,0x0024,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Gain",false }, {0x200d,0x0025,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Compress",false }, {0x200d,0x0026,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Light Brightness",false }, {0x200d,0x0027,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Elevation Scale Factor",false }, {0x200d,0x0028,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Zoom Factor",false }, {0x200d,0x0029,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Color Write Priority",false }, {0x200d,0x002a,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Rotation Angle X",false }, {0x200d,0x002b,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Rotation Angle Y",false }, {0x200d,0x002c,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Data Voi Center",false }, {0x200d,0x002d,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr View Translation",false }, {0x200d,0x002e,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Data Voi Min Point",false }, {0x200d,0x002f,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Data Voi Max Point",false }, {0x200d,0x0030,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Box Crop Min Point",false }, {0x200d,0x0031,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Box Crop Max Point",false }, {0x200d,0x0032,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Mpr Rotation Matrix",false }, {0x200d,0x0033,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Vol Rotation Matrix",false }, {0x200d,0x0034,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Trim Plane Equation",false }, {0x200d,0x0035,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Subpage Data Version",false }, {0x200d,0x0036,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Is Arbitrary Crop",false }, {0x200d,0x0037,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Arbitrary Crop Dist From Center",false }, {0x200d,0x0038,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Arbitrary Crop Rotation Matrix",false }, {0x200d,0x0039,"Philips US Private 3D",VR::FD,VM::VM1,"Threedpr Color Gain",false }, {0x200d,0x0040,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Color Wall Filter Index",false }, {0x200d,0x0041,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Cursor Enabled",false }, {0x200d,0x0042,"Philips US Private 3D",VR::IS,VM::VM1,"Threedpr Bondbox Graphic Enabled",false }, {0x2003,0x0000,"Philips X-ray Imaging DD 001",VR::CS,VM::VM1,"?",false }, {0x2003,0x0001,"Philips X-ray Imaging DD 001",VR::LO,VM::VM1,"?",false }, {0x2003,0x0002,"Philips X-ray Imaging DD 001",VR::FD,VM::VM3,"?",false }, {0x2003,0x0003,"Philips X-ray Imaging DD 001",VR::LO,VM::VM1,"?",false }, {0x2003,0x0004,"Philips X-ray Imaging DD 001",VR::SQ,VM::VM1,"Private enhanced Table Sequence",false }, {0x2003,0x0006,"Philips X-ray Imaging DD 001",VR::SL,VM::VM1,"?",false }, {0x2003,0x0009,"Philips X-ray Imaging DD 001",VR::SL,VM::VM1,"?",false }, {0x2003,0x0010,"Philips X-ray Imaging DD 001",VR::LO,VM::VM1,"?",false }, {0x2003,0x0011,"Philips X-ray Imaging DD 001",VR::SL,VM::VM1,"?",false }, {0x2003,0x0012,"Philips X-ray Imaging DD 001",VR::SL,VM::VM1,"?",false }, {0x2003,0x0013,"Philips X-ray Imaging DD 001",VR::SL,VM::VM1,"?",false }, {0x2003,0x0014,"Philips X-ray Imaging DD 001",VR::FD,VM::VM1,"?",false }, {0x2003,0x0015,"Philips X-ray Imaging DD 001",VR::FD,VM::VM1,"?",false }, {0x2003,0x0016,"Philips X-ray Imaging DD 001",VR::SL,VM::VM1,"?",false }, {0x2003,0x0017,"Philips X-ray Imaging DD 001",VR::SL,VM::VM1,"?",false }, {0x2003,0x0018,"Philips X-ray Imaging DD 001",VR::SL,VM::VM1,"?",false }, {0x2003,0x0019,"Philips X-ray Imaging DD 001",VR::SL,VM::VM1,"?",false }, {0x2003,0x0022,"Philips X-ray Imaging DD 001",VR::SL,VM::VM1,"?",false }, {0x2003,0x0024,"Philips X-ray Imaging DD 001",VR::FD,VM::VM4,"?",false }, {0x2003,0x0025,"Philips X-ray Imaging DD 001",VR::SL,VM::VM1,"?",false }, {0x2003,0x0026,"Philips X-ray Imaging DD 001",VR::SL,VM::VM1,"?",false }, {0x2003,0x0027,"Philips X-ray Imaging DD 001",VR::SH,VM::VM1,"?",false }, {0x2003,0x0028,"Philips X-ray Imaging DD 001",VR::SH,VM::VM1,"?",false }, {0x2003,0x0029,"Philips X-ray Imaging DD 001",VR::FD,VM::VM1,"?",false }, {0x2003,0x002a,"Philips X-ray Imaging DD 001",VR::LO,VM::VM1,"?",false }, {0x2003,0x002b,"Philips X-ray Imaging DD 001",VR::FD,VM::VM1,"?",false }, {0x2003,0x002c,"Philips X-ray Imaging DD 001",VR::SH,VM::VM1,"?",false }, {0x2003,0x002d,"Philips X-ray Imaging DD 001",VR::SL,VM::VM1_n,"?",false }, {0x2003,0x002e,"Philips X-ray Imaging DD 001",VR::SQ,VM::VM1,"?",false }, {0x2003,0x002f,"Philips X-ray Imaging DD 001",VR::CS,VM::VM1,"IsResolvePatientMixApplied",false }, {0x2003,0x0030,"Philips X-ray Imaging DD 001",VR::CS,VM::VM1,"?",false }, {0x2003,0x0031,"Philips X-ray Imaging DD 001",VR::CS,VM::VM1,"?",false }, {0x2003,0x0032,"Philips X-ray Imaging DD 001",VR::UI,VM::VM1,"?",false }, {0x7101,0x0000,"Picker MR Private Group",VR::OB,VM::VM1,"?Protocol Data 0 (weird gzip)?",false }, {0x7101,0x0001,"Picker MR Private Group",VR::SL,VM::VM1,"?Protocol Data 0 Length?",false }, {0x7101,0x0002,"Picker MR Private Group",VR::OB,VM::VM1,"?Protocol Data 2 (weird gzip)?",false }, {0x7101,0x0003,"Picker MR Private Group",VR::SL,VM::VM1,"?Protocol Data 2 Length?",false }, {0x7101,0x0004,"Picker MR Private Group",VR::SH,VM::VM1,"?Time?",false }, {0x7101,0x0005,"Picker MR Private Group",VR::SH,VM::VM2,"?ImageType?",false }, {0x7101,0x0006,"Picker MR Private Group",VR::SH,VM::VM4,"?MR Diffusion Info?",false }, {0x7101,0x0010,"Picker MR Private Group",VR::DS,VM::VM1,"?",false }, {0x7001,0x0001,"Picker NM Private Group",VR::UI,VM::VM1,"Private",false }, {0x7001,0x0002,"Picker NM Private Group",VR::OB,VM::VM1,"Private",false }, {0x7001,0x0003,"Picker NM Private Group",VR::OB,VM::VM1,"Private",false }, {0x7001,0x0004,"Picker NM Private Group",VR::OB,VM::VM1,"Private",false }, {0x7001,0x0005,"Picker NM Private Group",VR::OB,VM::VM1,"Private",false }, {0x7001,0x0006,"Picker NM Private Group",VR::OB,VM::VM1,"Private",false }, {0x7001,0x0007,"Picker NM Private Group",VR::OB,VM::VM1,"Private",false }, {0x7001,0x0008,"Picker NM Private Group",VR::OB,VM::VM1,"Private",false }, {0x7001,0x0009,"Picker NM Private Group",VR::OB,VM::VM1,"Private",false }, {0x7001,0x0010,"Picker NM Private Group",VR::SQ,VM::VM1,"Private",false }, {0x7001,0x0011,"Picker NM Private Group",VR::LO,VM::VM1,"Private",false }, {0x7001,0x0012,"Picker NM Private Group",VR::OB,VM::VM1,"Private",false }, {0x7001,0x0013,"Picker NM Private Group",VR::US,VM::VM1,"Private",false }, {0x7001,0x0014,"Picker NM Private Group",VR::OB,VM::VM1,"Private",false }, {0x7001,0x0015,"Picker NM Private Group",VR::OB,VM::VM1,"Private",false }, {0x7001,0x0016,"Picker NM Private Group",VR::OB,VM::VM1,"Private",false }, {0x7001,0x0017,"Picker NM Private Group",VR::LO,VM::VM1,"Contains a text string that includes some of the same information that appears on the Odyssey Clinical Index (image directory) for this Image.",false }, {0x7043,0x0000,"Picker NM Private Group",VR::SH,VM::VM1,"Private.",false }, {0x0009,0x0000,"QCA",VR::CS,VM::VM1,"Analysis Type",false }, {0x0009,0x0004,"QCA",VR::LO,VM::VM1,"Segment Name",false }, {0x0009,0x0012,"QCA",VR::DS,VM::VM1,"Pre Catheter size",false }, {0x0009,0x0013,"QCA",VR::DS,VM::VM1,"Pre Reference Diameter",false }, {0x0009,0x0014,"QCA",VR::DS,VM::VM1,"Pre Minimum Lumen Diameter",false }, {0x0009,0x0015,"QCA",VR::DS,VM::VM1,"Pre Average Diameter",false }, {0x0009,0x0016,"QCA",VR::DS,VM::VM1,"Pre Stenosis Length",false }, {0x0009,0x0017,"QCA",VR::DS,VM::VM1,"Pre Stenosis %",false }, {0x0009,0x0018,"QCA",VR::DS,VM::VM1,"Pre Geometric Area Reduction %",false }, {0x0009,0x0022,"QCA",VR::DS,VM::VM1,"Post Catheter Size",false }, {0x0009,0x0023,"QCA",VR::DS,VM::VM1,"Post Reference Diameter",false }, {0x0009,0x0024,"QCA",VR::DS,VM::VM1,"Post Minimum Lumen Diameter",false }, {0x0009,0x0025,"QCA",VR::DS,VM::VM1,"Post Average Diameter",false }, {0x0009,0x0026,"QCA",VR::DS,VM::VM1,"Post Stenosis Length",false }, {0x0009,0x0027,"QCA",VR::DS,VM::VM1,"Post Stenosis %",false }, {0x0009,0x0028,"QCA",VR::DS,VM::VM1,"Post Geometric Area Reduction %",false }, {0x0009,0x0000,"QCA_RESULTS",VR::CS,VM::VM1,"Analysis Views",false }, {0x0009,0x0010,"QCA_RESULTS",VR::LO,VM::VM1,"Segment",false }, {0x0009,0x0011,"QCA_RESULTS",VR::LO,VM::VM1,"Pre Catheter Name",false }, {0x0009,0x0012,"QCA_RESULTS",VR::DS,VM::VM1,"Pre Catheter Size",false }, {0x0009,0x0013,"QCA_RESULTS",VR::DS,VM::VM1,"Pre Reference Diameter",false }, {0x0009,0x0014,"QCA_RESULTS",VR::DS,VM::VM1,"Pre Minimum Lumen Diameter",false }, {0x0009,0x0015,"QCA_RESULTS",VR::DS,VM::VM1,"Pre Average Diameter",false }, {0x0009,0x0016,"QCA_RESULTS",VR::DS,VM::VM1,"Pre Stenosis Length",false }, {0x0009,0x0017,"QCA_RESULTS",VR::IS,VM::VM1,"Pre Stenosis %",false }, {0x0009,0x0018,"QCA_RESULTS",VR::IS,VM::VM1,"Pre Geometric Area Reduction %",false }, {0x0009,0x0021,"QCA_RESULTS",VR::LO,VM::VM1,"Post Catheter Name",false }, {0x0009,0x0022,"QCA_RESULTS",VR::DS,VM::VM1,"Post Catheter Size",false }, {0x0009,0x0023,"QCA_RESULTS",VR::DS,VM::VM1,"Post Reference Diameter",false }, {0x0009,0x0024,"QCA_RESULTS",VR::DS,VM::VM1,"Post Minimum Lumen Diameter",false }, {0x0009,0x0025,"QCA_RESULTS",VR::DS,VM::VM1,"Post Average Diameter",false }, {0x0009,0x0026,"QCA_RESULTS",VR::DS,VM::VM1,"Post Stenosis Length",false }, {0x0009,0x0027,"QCA_RESULTS",VR::IS,VM::VM1,"Post Stenosis %",false }, {0x0009,0x0028,"QCA_RESULTS",VR::IS,VM::VM1,"Post Geometric Area Reduction %",false }, {0x0009,0x0040,"QCA_RESULTS",VR::IS,VM::VM1,"Calibration Frame",false }, {0x0009,0x0041,"QCA_RESULTS",VR::IS,VM::VM1,"End Diastolic Frame",false }, {0x0009,0x0042,"QCA_RESULTS",VR::IS,VM::VM1,"End Systolic Frame",false }, {0x0009,0x0043,"QCA_RESULTS",VR::DS,VM::VM1,"End Diastolic Volume",false }, {0x0009,0x0044,"QCA_RESULTS",VR::DS,VM::VM1,"End Systolic Volume",false }, {0x0009,0x0045,"QCA_RESULTS",VR::DS,VM::VM1,"Stroke Volume",false }, {0x0009,0x0047,"QCA_RESULTS",VR::DS,VM::VM1,"Ejection Fraction",false }, {0x0009,0x0048,"QCA_RESULTS",VR::DS,VM::VM1,"Body Surface Area",false }, {0x0009,0x0049,"QCA_RESULTS",VR::SH,VM::VM1,"Artery Territory Region",false }, {0x0009,0x0050,"QCA_RESULTS",VR::IS,VM::VM1,"Number of Diseased Vessels",false }, {0x0009,0x0051,"QCA_RESULTS",VR::DS,VM::VM1,"Hypokinesis in Region",false }, {0x0009,0x0052,"QCA_RESULTS",VR::DS,VM::VM1,"Hyperkinesis in Opposite Region",false }, {0x0009,0x0053,"QCA_RESULTS",VR::IS,VM::VM1,"Percent Total LV Hypokinesis",false }, {0x0009,0x0055,"QCA_RESULTS",VR::DS,VM::VM1,"Calibration Factor",false }, {0x0009,0x0001,"QUASAR_INTERNAL_USE",VR::UL,VM::VM1_n,"Rate Vector",false }, {0x0009,0x0002,"QUASAR_INTERNAL_USE",VR::UL,VM::VM1_n,"Count Vector",false }, {0x0009,0x0003,"QUASAR_INTERNAL_USE",VR::UL,VM::VM1_n,"Time Vector",false }, {0x0009,0x0007,"QUASAR_INTERNAL_USE",VR::US,VM::VM1_n,"Angle Vector",false }, {0x0009,0x0008,"QUASAR_INTERNAL_USE",VR::US,VM::VM1,"Camera Shape",false }, {0x0009,0x0010,"QUASAR_INTERNAL_USE",VR::US,VM::VM1,"WholeBody Spots",false }, {0x0009,0x0011,"QUASAR_INTERNAL_USE",VR::US,VM::VM1,"Worklist Flag",false }, {0x0009,0x0012,"QUASAR_INTERNAL_USE",VR::LO,VM::VM1,"?",false }, {0x0009,0x0013,"QUASAR_INTERNAL_USE",VR::ST,VM::VM1,"Sequence Type",false }, {0x0009,0x0014,"QUASAR_INTERNAL_USE",VR::ST,VM::VM1,"Sequence Name",false }, {0x0009,0x0015,"QUASAR_INTERNAL_USE",VR::UL,VM::VM1,"Avr RR Time Vector",false }, {0x0009,0x0016,"QUASAR_INTERNAL_USE",VR::UL,VM::VM1,"Low Limit Vector",false }, {0x0009,0x0017,"QUASAR_INTERNAL_USE",VR::UL,VM::VM1,"High Limit Vector",false }, {0x0009,0x0018,"QUASAR_INTERNAL_USE",VR::UL,VM::VM1,"Begin Index Vector",false }, {0x0009,0x0019,"QUASAR_INTERNAL_USE",VR::UL,VM::VM1,"End Index Vector",false }, {0x0009,0x001a,"QUASAR_INTERNAL_USE",VR::UL,VM::VM1,"Raw Time Vector",false }, {0x0009,0x001b,"QUASAR_INTERNAL_USE",VR::LO,VM::VM1,"Image Type String",false }, {0x0009,0x001d,"QUASAR_INTERNAL_USE",VR::US,VM::VM1,"?",false }, {0x0009,0x001e,"QUASAR_INTERNAL_USE",VR::ST,VM::VM1,"?",false }, {0x0009,0x0022,"QUASAR_INTERNAL_USE",VR::FL,VM::VM1,"?",false }, {0x0009,0x0023,"QUASAR_INTERNAL_USE",VR::US,VM::VM1,"?",false }, {0x0009,0x0039,"QUASAR_INTERNAL_USE",VR::UI,VM::VM1,"?",false }, {0x0009,0x0040,"QUASAR_INTERNAL_USE",VR::DA,VM::VM1,"?",false }, {0x0009,0x0041,"QUASAR_INTERNAL_USE",VR::TM,VM::VM1,"?",false }, {0x0009,0x0042,"QUASAR_INTERNAL_USE",VR::LO,VM::VM1,"?",false }, {0x0009,0x0044,"QUASAR_INTERNAL_USE",VR::SH,VM::VM1,"?",false }, {0x0037,0x0010,"QUASAR_INTERNAL_USE",VR::SQ,VM::VM1,"?",false }, {0x0037,0x001b,"QUASAR_INTERNAL_USE",VR::LO,VM::VM1,"?",false }, {0x0037,0x0030,"QUASAR_INTERNAL_USE",VR::LO,VM::VM1,"?",false }, {0x0037,0x0040,"QUASAR_INTERNAL_USE",VR::LO,VM::VM1,"?",false }, {0x0037,0x0050,"QUASAR_INTERNAL_USE",VR::LO,VM::VM1,"?",false }, {0x0037,0x0060,"QUASAR_INTERNAL_USE",VR::LO,VM::VM1,"?",false }, {0x0037,0x0070,"QUASAR_INTERNAL_USE",VR::LO,VM::VM1,"?",false }, {0x0009,0x0040,"QVA",VR::IS,VM::VM1,"Calibration Frame",false }, {0x0009,0x0041,"QVA",VR::IS,VM::VM1,"End Diastolic Frame",false }, {0x0009,0x0042,"QVA",VR::IS,VM::VM1,"End Systolic Frame",false }, {0x0009,0x0043,"QVA",VR::DS,VM::VM1,"End Diastolic Volume",false }, {0x0009,0x0044,"QVA",VR::DS,VM::VM1,"End Systolic Volume",false }, {0x0009,0x0045,"QVA",VR::DS,VM::VM1,"Stroke Volume",false }, {0x0009,0x0046,"QVA",VR::DS,VM::VM1,"Cardiac Output",false }, {0x0009,0x0047,"QVA",VR::DS,VM::VM1,"Ejection Fraction",false }, {0x0009,0x0048,"QVA",VR::DS,VM::VM1,"Body Surface Area",false }, {0x0009,0x0049,"QVA",VR::SH,VM::VM1,"Artery Territory Region",false }, {0x0009,0x0050,"QVA",VR::IS,VM::VM1,"Number of Diseased Vessels",false }, {0x0009,0x0051,"QVA",VR::DS,VM::VM1,"Hypokinesis in Region",false }, {0x0009,0x0052,"QVA",VR::DS,VM::VM1,"Hyperkinesis in Region",false }, {0x0009,0x0053,"QVA",VR::IS,VM::VM1,"percent of chords with hyperkinesis <- 2 SD",false }, {0x0009,0x0054,"QVA",VR::IS,VM::VM1,"percent of chords with alkinesis/dyskinesis",false }, {0x0009,0x0055,"QVA",VR::DS,VM::VM1,"Calibration Factor",false }, {0x0039,0x0095,"REPORT_FROM_APP",VR::LO,VM::VM1,"?",false }, {0x0029,0x0024,"RadWorksMarconi",VR::US,VM::VM1," namespace gdcm { static const char * const SOPClassUIDToIODStrings[][2] = { {"1.2.840.10008.1.3.10" , "Basic Directory IOD Modules"}, // IOD defined in PS 3.3 {"1.2.840.10008.5.1.4.1.1.1" , "CR Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.1.1" , "Digital X Ray Image IOD Modules"}, // DX IOD (see B.5.1.1) {"1.2.840.10008.5.1.4.1.1.1.1.1" , "Digital X Ray Image IOD Modules"}, // DX IOD (see B.5.1.1) {"1.2.840.10008.5.1.4.1.1.1.2" , "Digital Mammography X Ray Image IOD Modules"}, // (see B.5.1.2) {"1.2.840.10008.5.1.4.1.1.1.2.1" , "Digital Mammography X Ray Image IOD Modules"}, // (see B.5.1.2) {"1.2.840.10008.5.1.4.1.1.1.3" , "Digital Intra Oral X Ray Image IOD Modules"}, // (see B.5.1.3) {"1.2.840.10008.5.1.4.1.1.1.3.1" , "Digital Intra Oral X Ray Image IOD Modules"}, // (see B.5.1.3) {"1.2.840.10008.5.1.4.1.1.2" , "CT Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.2.1" , "Enhanced CT Image IOD Modules"}, // (see B.5.1.7) {"1.2.840.10008.5.1.4.1.1.3.1" , "US Multi Frame Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.4" , "MR Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.4.1" , "Enhanced MR Image IOD Modules"}, // (see B.5.1.6) {"1.2.840.10008.5.1.4.1.1.4.2" , "MR Spectroscopy IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.4.3" , "Enhanced MR Color Image"}, {"1.2.840.10008.5.1.4.1.1.6.1" , "US Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.6.2" , "Enhanced US Volume"}, {"1.2.840.10008.5.1.4.1.1.7" , "SC Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.7.1" , "Multi Frame Single Bit SC Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.7.2" , "Multi Frame Grayscale Byte SC Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.7.3" , "Multi Frame Grayscale Word SC Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.7.4" , "Multi Frame True Color SC Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.9.1.1" , "12 Lead ECG IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.9.1.2" , "General ECG IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.9.1.3" , "Ambulatory ECG IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.9.2.1" , "Hemodynamic IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.9.3.1" , "Basic Cardiac EP IOD Modules"}, // Cardiac Electrophysiology Waveform {"1.2.840.10008.5.1.4.1.1.9.4.1" , "Basic Voice Audio IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.9.4.2" , "General Audio Waveform"}, {"1.2.840.10008.5.1.4.1.1.9.5.1" , "Arterial Pulse Waveform"}, {"1.2.840.10008.5.1.4.1.1.9.6.1" , "Respiratory Waveform"}, {"1.2.840.10008.5.1.4.1.1.11.1" , "Grayscale Softcopy Presentation State IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.11.2" , "Color Softcopy Presentation State"}, {"1.2.840.10008.5.1.4.1.1.11.3" , "Pseudo-Color Softcopy Presentation State"}, {"1.2.840.10008.5.1.4.1.1.11.4" , "Blending Softcopy Presentation State"}, {"1.2.840.10008.5.1.4.1.1.11.5" , "IOD defined in PS 3.3"}, {"1.2.840.10008.5.1.4.1.1.12.1" , "X Ray Angiographic Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.12.1.1" , "Enhanced X Ray Angiographic Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.12.2" , "XRF Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.12.2.1" , "Enhanced X Ray RF Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.13.1.1" , "X Ray 3D Angiographic Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.13.1.2" , "X-Ray 3D Craniofacial Image"}, {"1.2.840.10008.5.1.4.1.1.13.1.3" , "Breast Tomosynthesis Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.20" , "NM Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.66" , "Raw Data IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.66.1" , "Spatial Registration IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.66.2" , "Spatial Fiducials IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.66.3" , "Deformable Spatial Registration"}, {"1.2.840.10008.5.1.4.1.1.66.4" , "Segmentation IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.66.5" , "Surface Segmentation"}, {"1.2.840.10008.5.1.4.1.1.67" , "Real World Value Mapping"}, {"1.2.840.10008.5.1.4.1.1.77.1.1" , "VL Endoscopic Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.77.1.1.1" , "Video Endoscopic Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.77.1.2" , "VL Microscopic Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.77.1.2.1" , "Video Microscopic Image"}, {"1.2.840.10008.5.1.4.1.1.77.1.3" , "VL Slide-Coordinates Microscopic Image"}, {"1.2.840.10008.5.1.4.1.1.77.1.4" , "VL Photographic Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.77.1.4.1" , "Video Photographic Image"}, {"1.2.840.10008.5.1.4.1.1.77.1.5.1" , "Ophthalmic Photography 8 Bit Image"}, {"1.2.840.10008.5.1.4.1.1.77.1.5.2" , "Ophthalmic Photography 16 Bit Image"}, {"1.2.840.10008.5.1.4.1.1.77.1.5.3" , "Stereometric Relationship"}, {"1.2.840.10008.5.1.4.1.1.77.1.5.4" , "Ophthalmic Tomography Image"}, {"1.2.840.10008.5.1.4.1.1.78.1" , "Lensometry Measurements"}, {"1.2.840.10008.5.1.4.1.1.78.2" , "Autorefraction Measurements"}, {"1.2.840.10008.5.1.4.1.1.78.3" , "Keratometry Measurements"}, {"1.2.840.10008.5.1.4.1.1.78.4" , "Subjective Refraction Measurements"}, {"1.2.840.10008.5.1.4.1.1.78.5" , "Visual Acuity Measurements"}, {"1.2.840.10008.5.1.4.1.1.78.6" , "Spectacle Prescription Report"}, {"1.2.840.10008.5.1.4.1.1.79.1" , "Macular Grid Thickness and Volume Report"}, {"1.2.840.10008.5.1.4.1.1.88.11" , "Basic Text SR IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.88.22" , "Enhanced SR IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.88.33" , "Comprehensive SR IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.88.40" , "Procedure Log"}, {"1.2.840.10008.5.1.4.1.1.88.50" , "Mammography CAD SR IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.88.59" , "Key Object Selection Document IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.88.65" , "Chest CAD SR IOD"}, {"1.2.840.10008.5.1.4.1.1.88.67" , "X Ray Radiation Dose SR IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.88.69" , "Colon CAD SR IOD"}, {"1.2.840.10008.5.1.4.1.1.104.1" , "Encapsulated PDF IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.104.2" , "Encapsulated CDA IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.128" , "PET Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.130" , "Enhanced PET Image Storage"}, {"1.2.840.10008.5.1.4.1.1.131" , "Basic Structured Display IOD"}, {"1.2.840.10008.5.1.4.1.1.481.1" , "RT Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.481.2" , "RT Dose IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.481.3" , "RT Structure Set IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.481.4" , "RT Beams Treatment Record IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.481.5" , "RT Plan IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.481.6" , "RT Brachy Treatment Record IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.481.7" , "RT Treatment Summary Record IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.481.8" , "RT Ion Plan IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.481.9" , "RT Ion Beams Treatment Record IOD Modules"}, {"1.2.840.10008.5.1.4.38.1" , "Hanging Protocol IOD Modules"}, {"1.2.840.10008.5.1.4.39.1" , "Color Palette IOD"}, {"1.2.840.10008.5.1.4.1.1.2.2", "Legacy Converted Enhanced CT Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.4.4", "Legacy Converted Enhanced MR Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.128.1", "Legacy Converted Enhanced PET Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.13.1.4" , "Breast Projection X-Ray Image - For Presentation Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.13.1.5" , "Breast Projection X-Ray Image - For Processing Image IOD Modules"}, // Deprecated: {"1.2.840.10008.3.1.2.3.3" , "Modality Performed Procedure Step IOD Modules" }, {"1.2.840.10008.5.1.4.1.1.5" , "NM Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.6" , "US Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.3" , "US Multi Frame Image IOD Modules"}, {"1.2.840.10008.5.1.4.1.1.12.3" , ""}, // XRayAngiographicBiplaneImageStorage // private: { "1.3.12.2.1107.5.9.1" , "Siemens Non-image IOD Modules"}, // CSA Non-Image Storage { "1.2.392.200036.9125.1.1.2" , "Fuji Private CR Image IOD Modules"}, // { "1.2.392.200036.9125.1.1.4" , "Fuji Private Mammo CR Image IOD Modules"}, // { nullptr, nullptr } }; unsigned int SOPClassUIDToIOD::GetNumberOfSOPClassToIOD() { static const unsigned int n = sizeof( SOPClassUIDToIODStrings ) / sizeof( *SOPClassUIDToIODStrings ); assert( n > 0 ); return n - 1; } const char *SOPClassUIDToIOD::GetIOD(UIDs const & uid) { // std::ifstream is( ); // // char buf[BUFSIZ]; // XML_Parser parser = XML_ParserCreate(NULL); // int done; // //int depth = 0; // XML_SetUserData(parser, this); // XML_SetElementHandler(parser, startElement, endElement); // XML_SetCharacterDataHandler(parser, characterDataHandler); // int ret = 0; // do { // is.read(buf, sizeof(buf)); // size_t len = is.gcount(); // done = len < sizeof(buf); // if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) { // fprintf(stderr, // "%s at line %" XML_FMT_INT_MOD "u\n", // XML_ErrorString(XML_GetErrorCode(parser)), // XML_GetCurrentLineNumber(parser)); // ret = 1; // Mark as error // done = 1; // exit while // } // } while (!done); // XML_ParserFree(parser); // is.close(); //typedef const char* const (*SOPClassUIDToIODType)[2]; SOPClassUIDToIOD::SOPClassUIDToIODType *p = SOPClassUIDToIODStrings; const char *sopclassuid = uid.GetString(); // FIXME I think we can do binary search while( (*p)[0] && strcmp( (*p)[0] , sopclassuid ) != 0 ) { ++p; } return (*p)[1]; } SOPClassUIDToIOD::SOPClassUIDToIODType *SOPClassUIDToIOD::GetSOPClassUIDToIODs() { return SOPClassUIDToIODStrings; } SOPClassUIDToIOD::SOPClassUIDToIODType& SOPClassUIDToIOD::GetSOPClassUIDToIOD(unsigned int i) { if( i < SOPClassUIDToIOD::GetNumberOfSOPClassToIOD() ) return SOPClassUIDToIODStrings[i]; // else return the {0x0, 0x0} sentinel: assert( *SOPClassUIDToIODStrings[ SOPClassUIDToIOD::GetNumberOfSOPClassToIOD() ] == nullptr ); return SOPClassUIDToIODStrings[ SOPClassUIDToIOD::GetNumberOfSOPClassToIOD() ]; } const char *SOPClassUIDToIOD::GetSOPClassUIDFromIOD(const char *iod) { if(!iod) return nullptr; unsigned int i = 0; SOPClassUIDToIODType *sopclassuidtoiods = GetSOPClassUIDToIODs(); const char *p = sopclassuidtoiods[i][1]; while( p != nullptr ) { if( strcmp( iod, p ) == 0 ) { break; } ++i; p = sopclassuidtoiods[i][1]; } // \postcondition always valid (before sentinel) assert( i <= GetNumberOfSOPClassToIOD() ); return sopclassuidtoiods[i][0]; } const char *SOPClassUIDToIOD::GetIODFromSOPClassUID(const char *sopclassuid) { if(!sopclassuid) return nullptr; unsigned int i = 0; SOPClassUIDToIODType *sopclassuidtoiods = GetSOPClassUIDToIODs(); const char *p = sopclassuidtoiods[i][0]; while( p != nullptr ) { if( strcmp( sopclassuid, p ) == 0 ) { break; } ++i; p = sopclassuidtoiods[i][0]; } // \postcondition always valid (before sentinel) assert( i <= GetNumberOfSOPClassToIOD() ); return sopclassuidtoiods[i][1]; } } GDCM-3.0.10/Source/DataDictionary/gdcmSOPClassUIDToIOD.h000066400000000000000000000027421412732066400223120ustar00rootroot00000000000000/*========================================================================= 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 GDCMSOPCLASSUIDTOIOD_H #define GDCMSOPCLASSUIDTOIOD_H #include "gdcmUIDs.h" namespace gdcm { /** * \brief Class convert a class SOP Class UID into IOD * \details * Reference PS 3.4 Table B.5-1 STANDARD SOP CLASSES */ class GDCM_EXPORT SOPClassUIDToIOD { public: /// Return the associated IOD based on a SOP Class UID uid /// (there is a one-to-one mapping from SOP Class UID to matching IOD) static const char *GetIOD(UIDs const & uid); /// Return the number of SOP Class UID listed internally static unsigned int GetNumberOfSOPClassToIOD(); typedef const char* const (SOPClassUIDToIODType)[2]; static SOPClassUIDToIODType* GetSOPClassUIDToIODs(); static SOPClassUIDToIODType& GetSOPClassUIDToIOD(unsigned int i); static const char *GetSOPClassUIDFromIOD(const char *iod); static const char *GetIODFromSOPClassUID(const char *sopclassuid); }; } // end namespace gdcm #endif //GDCMSOPCLASSUIDTOIOD_H GDCM-3.0.10/Source/DataDictionary/gdcmTagKeywords.h000066400000000000000000007525701412732066400217400ustar00rootroot00000000000000// GENERATED FILE DO NOT EDIT // $ xsltproc TagKeywords.xsl Part6.xml > gdcmTagKeywords.h /*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2012 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 GDCMTAGKEYWORDS_H #define GDCMTAGKEYWORDS_H #include "gdcmAttribute.h" namespace gdcm { namespace Keywords { typedef gdcm::Attribute<0x0000, 0x0000> CommandGroupLength; typedef gdcm::Attribute<0x0000, 0x0002> AffectedSOPClassUID; typedef gdcm::Attribute<0x0000, 0x0003> RequestedSOPClassUID; typedef gdcm::Attribute<0x0000, 0x0100> CommandField; typedef gdcm::Attribute<0x0000, 0x0110> MessageID; typedef gdcm::Attribute<0x0000, 0x0120> MessageIDBeingRespondedTo; typedef gdcm::Attribute<0x0000, 0x0600> MoveDestination; typedef gdcm::Attribute<0x0000, 0x0700> Priority; typedef gdcm::Attribute<0x0000, 0x0800> CommandDataSetType; typedef gdcm::Attribute<0x0000, 0x0900> Status; typedef gdcm::Attribute<0x0000, 0x0901> OffendingElement; typedef gdcm::Attribute<0x0000, 0x0902> ErrorComment; typedef gdcm::Attribute<0x0000, 0x0903> ErrorID; typedef gdcm::Attribute<0x0000, 0x1000> AffectedSOPInstanceUID; typedef gdcm::Attribute<0x0000, 0x1001> RequestedSOPInstanceUID; typedef gdcm::Attribute<0x0000, 0x1002> EventTypeID; typedef gdcm::Attribute<0x0000, 0x1005> AttributeIdentifierList; typedef gdcm::Attribute<0x0000, 0x1008> ActionTypeID; typedef gdcm::Attribute<0x0000, 0x1020> NumberOfRemainingSuboperations; typedef gdcm::Attribute<0x0000, 0x1021> NumberOfCompletedSuboperations; typedef gdcm::Attribute<0x0000, 0x1022> NumberOfFailedSuboperations; typedef gdcm::Attribute<0x0000, 0x1023> NumberOfWarningSuboperations; typedef gdcm::Attribute<0x0000, 0x1030> MoveOriginatorApplicationEntityTitle; typedef gdcm::Attribute<0x0000, 0x1031> MoveOriginatorMessageID; typedef gdcm::Attribute<0x0000, 0x0001> CommandLengthToEnd; typedef gdcm::Attribute<0x0000, 0x0010> CommandRecognitionCode; typedef gdcm::Attribute<0x0000, 0x0200> Initiator; typedef gdcm::Attribute<0x0000, 0x0300> Receiver; typedef gdcm::Attribute<0x0000, 0x0400> FindLocation; typedef gdcm::Attribute<0x0000, 0x0850> NumberOfMatches; typedef gdcm::Attribute<0x0000, 0x0860> ResponseSequenceNumber; typedef gdcm::Attribute<0x0000, 0x4000> DialogReceiver; typedef gdcm::Attribute<0x0000, 0x4010> TerminalType; typedef gdcm::Attribute<0x0000, 0x5010> MessageSetID; typedef gdcm::Attribute<0x0000, 0x5020> EndMessageID; typedef gdcm::Attribute<0x0000, 0x5110> DisplayFormat; typedef gdcm::Attribute<0x0000, 0x5120> PagePositionID; typedef gdcm::Attribute<0x0000, 0x5130> TextFormatID; typedef gdcm::Attribute<0x0000, 0x5140> NormalReverse; typedef gdcm::Attribute<0x0000, 0x5150> AddGrayScale; typedef gdcm::Attribute<0x0000, 0x5160> Borders; typedef gdcm::Attribute<0x0000, 0x5170> Copies; typedef gdcm::Attribute<0x0000, 0x5180> CommandMagnificationType; typedef gdcm::Attribute<0x0000, 0x5190> Erase; typedef gdcm::Attribute<0x0000, 0x51a0> Print; typedef gdcm::Attribute<0x0000, 0x51b0> Overlays; typedef gdcm::Attribute<0x0008, 0x0001> LengthToEnd; typedef gdcm::Attribute<0x0008, 0x0005> SpecificCharacterSet; typedef gdcm::Attribute<0x0008, 0x0006> LanguageCodeSequence; typedef gdcm::Attribute<0x0008, 0x0008> ImageType; typedef gdcm::Attribute<0x0008, 0x0010> RecognitionCode; typedef gdcm::Attribute<0x0008, 0x0012> InstanceCreationDate; typedef gdcm::Attribute<0x0008, 0x0013> InstanceCreationTime; typedef gdcm::Attribute<0x0008, 0x0014> InstanceCreatorUID; typedef gdcm::Attribute<0x0008, 0x0016> SOPClassUID; typedef gdcm::Attribute<0x0008, 0x0018> SOPInstanceUID; typedef gdcm::Attribute<0x0008, 0x001a> RelatedGeneralSOPClassUID; typedef gdcm::Attribute<0x0008, 0x001b> OriginalSpecializedSOPClassUID; typedef gdcm::Attribute<0x0008, 0x0020> StudyDate; typedef gdcm::Attribute<0x0008, 0x0021> SeriesDate; typedef gdcm::Attribute<0x0008, 0x0022> AcquisitionDate; typedef gdcm::Attribute<0x0008, 0x0023> ContentDate; typedef gdcm::Attribute<0x0008, 0x0024> OverlayDate; typedef gdcm::Attribute<0x0008, 0x0025> CurveDate; typedef gdcm::Attribute<0x0008, 0x002a> AcquisitionDateTime; typedef gdcm::Attribute<0x0008, 0x0030> StudyTime; typedef gdcm::Attribute<0x0008, 0x0031> SeriesTime; typedef gdcm::Attribute<0x0008, 0x0032> AcquisitionTime; typedef gdcm::Attribute<0x0008, 0x0033> ContentTime; typedef gdcm::Attribute<0x0008, 0x0034> OverlayTime; typedef gdcm::Attribute<0x0008, 0x0035> CurveTime; typedef gdcm::Attribute<0x0008, 0x0040> DataSetType; typedef gdcm::Attribute<0x0008, 0x0041> DataSetSubtype; typedef gdcm::Attribute<0x0008, 0x0042> NuclearMedicineSeriesType; typedef gdcm::Attribute<0x0008, 0x0050> AccessionNumber; typedef gdcm::Attribute<0x0008, 0x0051> IssuerOfAccessionNumberSequence; typedef gdcm::Attribute<0x0008, 0x0052> QueryRetrieveLevel; typedef gdcm::Attribute<0x0008, 0x0054> RetrieveAETitle; typedef gdcm::Attribute<0x0008, 0x0056> InstanceAvailability; typedef gdcm::Attribute<0x0008, 0x0058> FailedSOPInstanceUIDList; typedef gdcm::Attribute<0x0008, 0x0060> Modality; typedef gdcm::Attribute<0x0008, 0x0061> ModalitiesInStudy; typedef gdcm::Attribute<0x0008, 0x0062> SOPClassesInStudy; typedef gdcm::Attribute<0x0008, 0x0064> ConversionType; typedef gdcm::Attribute<0x0008, 0x0068> PresentationIntentType; typedef gdcm::Attribute<0x0008, 0x0070> Manufacturer; typedef gdcm::Attribute<0x0008, 0x0080> InstitutionName; typedef gdcm::Attribute<0x0008, 0x0081> InstitutionAddress; typedef gdcm::Attribute<0x0008, 0x0082> InstitutionCodeSequence; typedef gdcm::Attribute<0x0008, 0x0090> ReferringPhysicianName; typedef gdcm::Attribute<0x0008, 0x0092> ReferringPhysicianAddress; typedef gdcm::Attribute<0x0008, 0x0094> ReferringPhysicianTelephoneNumbers; typedef gdcm::Attribute<0x0008, 0x0096> ReferringPhysicianIdentificationSequence; typedef gdcm::Attribute<0x0008, 0x0100> CodeValue; typedef gdcm::Attribute<0x0008, 0x0102> CodingSchemeDesignator; typedef gdcm::Attribute<0x0008, 0x0103> CodingSchemeVersion; typedef gdcm::Attribute<0x0008, 0x0104> CodeMeaning; typedef gdcm::Attribute<0x0008, 0x0105> MappingResource; typedef gdcm::Attribute<0x0008, 0x0106> ContextGroupVersion; typedef gdcm::Attribute<0x0008, 0x0107> ContextGroupLocalVersion; typedef gdcm::Attribute<0x0008, 0x010b> ContextGroupExtensionFlag; typedef gdcm::Attribute<0x0008, 0x010c> CodingSchemeUID; typedef gdcm::Attribute<0x0008, 0x010d> ContextGroupExtensionCreatorUID; typedef gdcm::Attribute<0x0008, 0x010f> ContextIdentifier; typedef gdcm::Attribute<0x0008, 0x0110> CodingSchemeIdentificationSequence; typedef gdcm::Attribute<0x0008, 0x0112> CodingSchemeRegistry; typedef gdcm::Attribute<0x0008, 0x0114> CodingSchemeExternalID; typedef gdcm::Attribute<0x0008, 0x0115> CodingSchemeName; typedef gdcm::Attribute<0x0008, 0x0116> CodingSchemeResponsibleOrganization; typedef gdcm::Attribute<0x0008, 0x0117> ContextUID; typedef gdcm::Attribute<0x0008, 0x0201> TimezoneOffsetFromUTC; typedef gdcm::Attribute<0x0008, 0x1000> NetworkID; typedef gdcm::Attribute<0x0008, 0x1010> StationName; typedef gdcm::Attribute<0x0008, 0x1030> StudyDescription; typedef gdcm::Attribute<0x0008, 0x1032> ProcedureCodeSequence; typedef gdcm::Attribute<0x0008, 0x103e> SeriesDescription; typedef gdcm::Attribute<0x0008, 0x103f> SeriesDescriptionCodeSequence; typedef gdcm::Attribute<0x0008, 0x1040> InstitutionalDepartmentName; typedef gdcm::Attribute<0x0008, 0x1048> PhysiciansOfRecord; typedef gdcm::Attribute<0x0008, 0x1049> PhysiciansOfRecordIdentificationSequence; typedef gdcm::Attribute<0x0008, 0x1050> PerformingPhysicianName; typedef gdcm::Attribute<0x0008, 0x1052> PerformingPhysicianIdentificationSequence; typedef gdcm::Attribute<0x0008, 0x1060> NameOfPhysiciansReadingStudy; typedef gdcm::Attribute<0x0008, 0x1062> PhysiciansReadingStudyIdentificationSequence; typedef gdcm::Attribute<0x0008, 0x1070> OperatorsName; typedef gdcm::Attribute<0x0008, 0x1072> OperatorIdentificationSequence; typedef gdcm::Attribute<0x0008, 0x1080> AdmittingDiagnosesDescription; typedef gdcm::Attribute<0x0008, 0x1084> AdmittingDiagnosesCodeSequence; typedef gdcm::Attribute<0x0008, 0x1090> ManufacturerModelName; typedef gdcm::Attribute<0x0008, 0x1100> ReferencedResultsSequence; typedef gdcm::Attribute<0x0008, 0x1110> ReferencedStudySequence; typedef gdcm::Attribute<0x0008, 0x1111> ReferencedPerformedProcedureStepSequence; typedef gdcm::Attribute<0x0008, 0x1115> ReferencedSeriesSequence; typedef gdcm::Attribute<0x0008, 0x1120> ReferencedPatientSequence; typedef gdcm::Attribute<0x0008, 0x1125> ReferencedVisitSequence; typedef gdcm::Attribute<0x0008, 0x1130> ReferencedOverlaySequence; typedef gdcm::Attribute<0x0008, 0x1134> ReferencedStereometricInstanceSequence; typedef gdcm::Attribute<0x0008, 0x113a> ReferencedWaveformSequence; typedef gdcm::Attribute<0x0008, 0x1140> ReferencedImageSequence; typedef gdcm::Attribute<0x0008, 0x1145> ReferencedCurveSequence; typedef gdcm::Attribute<0x0008, 0x114a> ReferencedInstanceSequence; typedef gdcm::Attribute<0x0008, 0x114b> ReferencedRealWorldValueMappingInstanceSequence; typedef gdcm::Attribute<0x0008, 0x1150> ReferencedSOPClassUID; typedef gdcm::Attribute<0x0008, 0x1155> ReferencedSOPInstanceUID; typedef gdcm::Attribute<0x0008, 0x115a> SOPClassesSupported; typedef gdcm::Attribute<0x0008, 0x1160> ReferencedFrameNumber; typedef gdcm::Attribute<0x0008, 0x1161> SimpleFrameList; typedef gdcm::Attribute<0x0008, 0x1162> CalculatedFrameList; typedef gdcm::Attribute<0x0008, 0x1163> TimeRange; typedef gdcm::Attribute<0x0008, 0x1164> FrameExtractionSequence; typedef gdcm::Attribute<0x0008, 0x1167> MultiFrameSourceSOPInstanceUID; typedef gdcm::Attribute<0x0008, 0x1195> TransactionUID; typedef gdcm::Attribute<0x0008, 0x1197> FailureReason; typedef gdcm::Attribute<0x0008, 0x1198> FailedSOPSequence; typedef gdcm::Attribute<0x0008, 0x1199> ReferencedSOPSequence; typedef gdcm::Attribute<0x0008, 0x1200> StudiesContainingOtherReferencedInstancesSequence; typedef gdcm::Attribute<0x0008, 0x1250> RelatedSeriesSequence; typedef gdcm::Attribute<0x0008, 0x2110> LossyImageCompressionRetired; typedef gdcm::Attribute<0x0008, 0x2111> DerivationDescription; typedef gdcm::Attribute<0x0008, 0x2112> SourceImageSequence; typedef gdcm::Attribute<0x0008, 0x2120> StageName; typedef gdcm::Attribute<0x0008, 0x2122> StageNumber; typedef gdcm::Attribute<0x0008, 0x2124> NumberOfStages; typedef gdcm::Attribute<0x0008, 0x2127> ViewName; typedef gdcm::Attribute<0x0008, 0x2128> ViewNumber; typedef gdcm::Attribute<0x0008, 0x2129> NumberOfEventTimers; typedef gdcm::Attribute<0x0008, 0x212a> NumberOfViewsInStage; typedef gdcm::Attribute<0x0008, 0x2130> EventElapsedTimes; typedef gdcm::Attribute<0x0008, 0x2132> EventTimerNames; typedef gdcm::Attribute<0x0008, 0x2133> EventTimerSequence; typedef gdcm::Attribute<0x0008, 0x2134> EventTimeOffset; typedef gdcm::Attribute<0x0008, 0x2135> EventCodeSequence; typedef gdcm::Attribute<0x0008, 0x2142> StartTrim; typedef gdcm::Attribute<0x0008, 0x2143> StopTrim; typedef gdcm::Attribute<0x0008, 0x2144> RecommendedDisplayFrameRate; typedef gdcm::Attribute<0x0008, 0x2200> TransducerPosition; typedef gdcm::Attribute<0x0008, 0x2204> TransducerOrientation; typedef gdcm::Attribute<0x0008, 0x2208> AnatomicStructure; typedef gdcm::Attribute<0x0008, 0x2218> AnatomicRegionSequence; typedef gdcm::Attribute<0x0008, 0x2220> AnatomicRegionModifierSequence; typedef gdcm::Attribute<0x0008, 0x2228> PrimaryAnatomicStructureSequence; typedef gdcm::Attribute<0x0008, 0x2229> AnatomicStructureSpaceOrRegionSequence; typedef gdcm::Attribute<0x0008, 0x2230> PrimaryAnatomicStructureModifierSequence; typedef gdcm::Attribute<0x0008, 0x2240> TransducerPositionSequence; typedef gdcm::Attribute<0x0008, 0x2242> TransducerPositionModifierSequence; typedef gdcm::Attribute<0x0008, 0x2244> TransducerOrientationSequence; typedef gdcm::Attribute<0x0008, 0x2246> TransducerOrientationModifierSequence; typedef gdcm::Attribute<0x0008, 0x2251> AnatomicStructureSpaceOrRegionCodeSequenceTrial; typedef gdcm::Attribute<0x0008, 0x2253> AnatomicPortalOfEntranceCodeSequenceTrial; typedef gdcm::Attribute<0x0008, 0x2255> AnatomicApproachDirectionCodeSequenceTrial; typedef gdcm::Attribute<0x0008, 0x2256> AnatomicPerspectiveDescriptionTrial; typedef gdcm::Attribute<0x0008, 0x2257> AnatomicPerspectiveCodeSequenceTrial; typedef gdcm::Attribute<0x0008, 0x2258> AnatomicLocationOfExaminingInstrumentDescriptionTrial; typedef gdcm::Attribute<0x0008, 0x2259> AnatomicLocationOfExaminingInstrumentCodeSequenceTrial; typedef gdcm::Attribute<0x0008, 0x225a> AnatomicStructureSpaceOrRegionModifierCodeSequenceTrial; typedef gdcm::Attribute<0x0008, 0x225c> OnAxisBackgroundAnatomicStructureCodeSequenceTrial; typedef gdcm::Attribute<0x0008, 0x3001> AlternateRepresentationSequence; typedef gdcm::Attribute<0x0008, 0x3010> IrradiationEventUID; typedef gdcm::Attribute<0x0008, 0x4000> IdentifyingComments; typedef gdcm::Attribute<0x0008, 0x9007> FrameType; typedef gdcm::Attribute<0x0008, 0x9092> ReferencedImageEvidenceSequence; typedef gdcm::Attribute<0x0008, 0x9121> ReferencedRawDataSequence; typedef gdcm::Attribute<0x0008, 0x9123> CreatorVersionUID; typedef gdcm::Attribute<0x0008, 0x9124> DerivationImageSequence; typedef gdcm::Attribute<0x0008, 0x9154> SourceImageEvidenceSequence; typedef gdcm::Attribute<0x0008, 0x9205> PixelPresentation; typedef gdcm::Attribute<0x0008, 0x9206> VolumetricProperties; typedef gdcm::Attribute<0x0008, 0x9207> VolumeBasedCalculationTechnique; typedef gdcm::Attribute<0x0008, 0x9208> ComplexImageComponent; typedef gdcm::Attribute<0x0008, 0x9209> AcquisitionContrast; typedef gdcm::Attribute<0x0008, 0x9215> DerivationCodeSequence; typedef gdcm::Attribute<0x0008, 0x9237> ReferencedPresentationStateSequence; typedef gdcm::Attribute<0x0008, 0x9410> ReferencedOtherPlaneSequence; typedef gdcm::Attribute<0x0008, 0x9458> FrameDisplaySequence; typedef gdcm::Attribute<0x0008, 0x9459> RecommendedDisplayFrameRateInFloat; typedef gdcm::Attribute<0x0008, 0x9460> SkipFrameRangeFlag; typedef gdcm::Attribute<0x0010, 0x0010> PatientName; typedef gdcm::Attribute<0x0010, 0x0020> PatientID; typedef gdcm::Attribute<0x0010, 0x0021> IssuerOfPatientID; typedef gdcm::Attribute<0x0010, 0x0022> TypeOfPatientID; typedef gdcm::Attribute<0x0010, 0x0024> IssuerOfPatientIDQualifiersSequence; typedef gdcm::Attribute<0x0010, 0x0030> PatientBirthDate; typedef gdcm::Attribute<0x0010, 0x0032> PatientBirthTime; typedef gdcm::Attribute<0x0010, 0x0040> PatientSex; typedef gdcm::Attribute<0x0010, 0x0050> PatientInsurancePlanCodeSequence; typedef gdcm::Attribute<0x0010, 0x0101> PatientPrimaryLanguageCodeSequence; typedef gdcm::Attribute<0x0010, 0x0102> PatientPrimaryLanguageModifierCodeSequence; typedef gdcm::Attribute<0x0010, 0x1000> OtherPatientIDs; typedef gdcm::Attribute<0x0010, 0x1001> OtherPatientNames; typedef gdcm::Attribute<0x0010, 0x1002> OtherPatientIDsSequence; typedef gdcm::Attribute<0x0010, 0x1005> PatientBirthName; typedef gdcm::Attribute<0x0010, 0x1010> PatientAge; typedef gdcm::Attribute<0x0010, 0x1020> PatientSize; typedef gdcm::Attribute<0x0010, 0x1021> PatientSizeCodeSequence; typedef gdcm::Attribute<0x0010, 0x1030> PatientWeight; typedef gdcm::Attribute<0x0010, 0x1040> PatientAddress; typedef gdcm::Attribute<0x0010, 0x1050> InsurancePlanIdentification; typedef gdcm::Attribute<0x0010, 0x1060> PatientMotherBirthName; typedef gdcm::Attribute<0x0010, 0x1080> MilitaryRank; typedef gdcm::Attribute<0x0010, 0x1081> BranchOfService; typedef gdcm::Attribute<0x0010, 0x1090> MedicalRecordLocator; typedef gdcm::Attribute<0x0010, 0x2000> MedicalAlerts; typedef gdcm::Attribute<0x0010, 0x2110> Allergies; typedef gdcm::Attribute<0x0010, 0x2150> CountryOfResidence; typedef gdcm::Attribute<0x0010, 0x2152> RegionOfResidence; typedef gdcm::Attribute<0x0010, 0x2154> PatientTelephoneNumbers; typedef gdcm::Attribute<0x0010, 0x2160> EthnicGroup; typedef gdcm::Attribute<0x0010, 0x2180> Occupation; typedef gdcm::Attribute<0x0010, 0x21a0> SmokingStatus; typedef gdcm::Attribute<0x0010, 0x21b0> AdditionalPatientHistory; typedef gdcm::Attribute<0x0010, 0x21c0> PregnancyStatus; typedef gdcm::Attribute<0x0010, 0x21d0> LastMenstrualDate; typedef gdcm::Attribute<0x0010, 0x21f0> PatientReligiousPreference; typedef gdcm::Attribute<0x0010, 0x2201> PatientSpeciesDescription; typedef gdcm::Attribute<0x0010, 0x2202> PatientSpeciesCodeSequence; typedef gdcm::Attribute<0x0010, 0x2203> PatientSexNeutered; typedef gdcm::Attribute<0x0010, 0x2210> AnatomicalOrientationType; typedef gdcm::Attribute<0x0010, 0x2292> PatientBreedDescription; typedef gdcm::Attribute<0x0010, 0x2293> PatientBreedCodeSequence; typedef gdcm::Attribute<0x0010, 0x2294> BreedRegistrationSequence; typedef gdcm::Attribute<0x0010, 0x2295> BreedRegistrationNumber; typedef gdcm::Attribute<0x0010, 0x2296> BreedRegistryCodeSequence; typedef gdcm::Attribute<0x0010, 0x2297> ResponsiblePerson; typedef gdcm::Attribute<0x0010, 0x2298> ResponsiblePersonRole; typedef gdcm::Attribute<0x0010, 0x2299> ResponsibleOrganization; typedef gdcm::Attribute<0x0010, 0x4000> PatientComments; typedef gdcm::Attribute<0x0010, 0x9431> ExaminedBodyThickness; typedef gdcm::Attribute<0x0012, 0x0010> ClinicalTrialSponsorName; typedef gdcm::Attribute<0x0012, 0x0020> ClinicalTrialProtocolID; typedef gdcm::Attribute<0x0012, 0x0021> ClinicalTrialProtocolName; typedef gdcm::Attribute<0x0012, 0x0030> ClinicalTrialSiteID; typedef gdcm::Attribute<0x0012, 0x0031> ClinicalTrialSiteName; typedef gdcm::Attribute<0x0012, 0x0040> ClinicalTrialSubjectID; typedef gdcm::Attribute<0x0012, 0x0042> ClinicalTrialSubjectReadingID; typedef gdcm::Attribute<0x0012, 0x0050> ClinicalTrialTimePointID; typedef gdcm::Attribute<0x0012, 0x0051> ClinicalTrialTimePointDescription; typedef gdcm::Attribute<0x0012, 0x0060> ClinicalTrialCoordinatingCenterName; typedef gdcm::Attribute<0x0012, 0x0062> PatientIdentityRemoved; typedef gdcm::Attribute<0x0012, 0x0063> DeidentificationMethod; typedef gdcm::Attribute<0x0012, 0x0064> DeidentificationMethodCodeSequence; typedef gdcm::Attribute<0x0012, 0x0071> ClinicalTrialSeriesID; typedef gdcm::Attribute<0x0012, 0x0072> ClinicalTrialSeriesDescription; typedef gdcm::Attribute<0x0012, 0x0081> ClinicalTrialProtocolEthicsCommitteeName; typedef gdcm::Attribute<0x0012, 0x0082> ClinicalTrialProtocolEthicsCommitteeApprovalNumber; typedef gdcm::Attribute<0x0012, 0x0083> ConsentForClinicalTrialUseSequence; typedef gdcm::Attribute<0x0012, 0x0084> DistributionType; typedef gdcm::Attribute<0x0012, 0x0085> ConsentForDistributionFlag; typedef gdcm::Attribute<0x0014, 0x0023> CADFileFormat; typedef gdcm::Attribute<0x0014, 0x0024> ComponentReferenceSystem; typedef gdcm::Attribute<0x0014, 0x0025> ComponentManufacturingProcedure; typedef gdcm::Attribute<0x0014, 0x0028> ComponentManufacturer; typedef gdcm::Attribute<0x0014, 0x0030> MaterialThickness; typedef gdcm::Attribute<0x0014, 0x0032> MaterialPipeDiameter; typedef gdcm::Attribute<0x0014, 0x0034> MaterialIsolationDiameter; typedef gdcm::Attribute<0x0014, 0x0042> MaterialGrade; typedef gdcm::Attribute<0x0014, 0x0044> MaterialPropertiesFileID; typedef gdcm::Attribute<0x0014, 0x0045> MaterialPropertiesFileFormat; typedef gdcm::Attribute<0x0014, 0x0046> MaterialNotes; typedef gdcm::Attribute<0x0014, 0x0050> ComponentShape; typedef gdcm::Attribute<0x0014, 0x0052> CurvatureType; typedef gdcm::Attribute<0x0014, 0x0054> OuterDiameter; typedef gdcm::Attribute<0x0014, 0x0056> InnerDiameter; typedef gdcm::Attribute<0x0014, 0x1010> ActualEnvironmentalConditions; typedef gdcm::Attribute<0x0014, 0x1020> ExpiryDate; typedef gdcm::Attribute<0x0014, 0x1040> EnvironmentalConditions; typedef gdcm::Attribute<0x0014, 0x2002> EvaluatorSequence; typedef gdcm::Attribute<0x0014, 0x2004> EvaluatorNumber; typedef gdcm::Attribute<0x0014, 0x2006> EvaluatorName; typedef gdcm::Attribute<0x0014, 0x2008> EvaluationAttempt; typedef gdcm::Attribute<0x0014, 0x2012> IndicationSequence; typedef gdcm::Attribute<0x0014, 0x2014> IndicationNumber; typedef gdcm::Attribute<0x0014, 0x2016> IndicationLabel; typedef gdcm::Attribute<0x0014, 0x2018> IndicationDescription; typedef gdcm::Attribute<0x0014, 0x201a> IndicationType; typedef gdcm::Attribute<0x0014, 0x201c> IndicationDisposition; typedef gdcm::Attribute<0x0014, 0x201e> IndicationROISequence; typedef gdcm::Attribute<0x0014, 0x2030> IndicationPhysicalPropertySequence; typedef gdcm::Attribute<0x0014, 0x2032> PropertyLabel; typedef gdcm::Attribute<0x0014, 0x2202> CoordinateSystemNumberOfAxes; typedef gdcm::Attribute<0x0014, 0x2204> CoordinateSystemAxesSequence; typedef gdcm::Attribute<0x0014, 0x2206> CoordinateSystemAxisDescription; typedef gdcm::Attribute<0x0014, 0x2208> CoordinateSystemDataSetMapping; typedef gdcm::Attribute<0x0014, 0x220a> CoordinateSystemAxisNumber; typedef gdcm::Attribute<0x0014, 0x220c> CoordinateSystemAxisType; typedef gdcm::Attribute<0x0014, 0x220e> CoordinateSystemAxisUnits; typedef gdcm::Attribute<0x0014, 0x2210> CoordinateSystemAxisValues; typedef gdcm::Attribute<0x0014, 0x2220> CoordinateSystemTransformSequence; typedef gdcm::Attribute<0x0014, 0x2222> TransformDescription; typedef gdcm::Attribute<0x0014, 0x2224> TransformNumberOfAxes; typedef gdcm::Attribute<0x0014, 0x2226> TransformOrderOfAxes; typedef gdcm::Attribute<0x0014, 0x2228> TransformedAxisUnits; typedef gdcm::Attribute<0x0014, 0x222a> CoordinateSystemTransformRotationAndScaleMatrix; typedef gdcm::Attribute<0x0014, 0x222c> CoordinateSystemTransformTranslationMatrix; typedef gdcm::Attribute<0x0014, 0x3011> InternalDetectorFrameTime; typedef gdcm::Attribute<0x0014, 0x3012> NumberOfFramesIntegrated; typedef gdcm::Attribute<0x0014, 0x3020> DetectorTemperatureSequence; typedef gdcm::Attribute<0x0014, 0x3022> SensorName; typedef gdcm::Attribute<0x0014, 0x3024> HorizontalOffsetOfSensor; typedef gdcm::Attribute<0x0014, 0x3026> VerticalOffsetOfSensor; typedef gdcm::Attribute<0x0014, 0x3028> SensorTemperature; typedef gdcm::Attribute<0x0014, 0x3040> DarkCurrentSequence; typedef gdcm::Attribute<0x0014, 0x3050> DarkCurrentCounts; typedef gdcm::Attribute<0x0014, 0x3060> GainCorrectionReferenceSequence; typedef gdcm::Attribute<0x0014, 0x3070> AirCounts; typedef gdcm::Attribute<0x0014, 0x3071> KVUsedInGainCalibration; typedef gdcm::Attribute<0x0014, 0x3072> MAUsedInGainCalibration; typedef gdcm::Attribute<0x0014, 0x3073> NumberOfFramesUsedForIntegration; typedef gdcm::Attribute<0x0014, 0x3074> FilterMaterialUsedInGainCalibration; typedef gdcm::Attribute<0x0014, 0x3075> FilterThicknessUsedInGainCalibration; typedef gdcm::Attribute<0x0014, 0x3076> DateOfGainCalibration; typedef gdcm::Attribute<0x0014, 0x3077> TimeOfGainCalibration; typedef gdcm::Attribute<0x0014, 0x3080> BadPixelImage; typedef gdcm::Attribute<0x0014, 0x3099> CalibrationNotes; typedef gdcm::Attribute<0x0014, 0x4002> PulserEquipmentSequence; typedef gdcm::Attribute<0x0014, 0x4004> PulserType; typedef gdcm::Attribute<0x0014, 0x4006> PulserNotes; typedef gdcm::Attribute<0x0014, 0x4008> ReceiverEquipmentSequence; typedef gdcm::Attribute<0x0014, 0x400a> AmplifierType; typedef gdcm::Attribute<0x0014, 0x400c> ReceiverNotes; typedef gdcm::Attribute<0x0014, 0x400e> PreAmplifierEquipmentSequence; typedef gdcm::Attribute<0x0014, 0x400f> PreAmplifierNotes; typedef gdcm::Attribute<0x0014, 0x4010> TransmitTransducerSequence; typedef gdcm::Attribute<0x0014, 0x4011> ReceiveTransducerSequence; typedef gdcm::Attribute<0x0014, 0x4012> NumberOfElements; typedef gdcm::Attribute<0x0014, 0x4013> ElementShape; typedef gdcm::Attribute<0x0014, 0x4014> ElementDimensionA; typedef gdcm::Attribute<0x0014, 0x4015> ElementDimensionB; typedef gdcm::Attribute<0x0014, 0x4016> ElementPitch; typedef gdcm::Attribute<0x0014, 0x4017> MeasuredBeamDimensionA; typedef gdcm::Attribute<0x0014, 0x4018> MeasuredBeamDimensionB; typedef gdcm::Attribute<0x0014, 0x4019> LocationOfMeasuredBeamDiameter; typedef gdcm::Attribute<0x0014, 0x401a> NominalFrequency; typedef gdcm::Attribute<0x0014, 0x401b> MeasuredCenterFrequency; typedef gdcm::Attribute<0x0014, 0x401c> MeasuredBandwidth; typedef gdcm::Attribute<0x0014, 0x4020> PulserSettingsSequence; typedef gdcm::Attribute<0x0014, 0x4022> PulseWidth; typedef gdcm::Attribute<0x0014, 0x4024> ExcitationFrequency; typedef gdcm::Attribute<0x0014, 0x4026> ModulationType; typedef gdcm::Attribute<0x0014, 0x4028> Damping; typedef gdcm::Attribute<0x0014, 0x4030> ReceiverSettingsSequence; typedef gdcm::Attribute<0x0014, 0x4031> AcquiredSoundpathLength; typedef gdcm::Attribute<0x0014, 0x4032> AcquisitionCompressionType; typedef gdcm::Attribute<0x0014, 0x4033> AcquisitionSampleSize; typedef gdcm::Attribute<0x0014, 0x4034> RectifierSmoothing; typedef gdcm::Attribute<0x0014, 0x4035> DACSequence; typedef gdcm::Attribute<0x0014, 0x4036> DACType; typedef gdcm::Attribute<0x0014, 0x4038> DACGainPoints; typedef gdcm::Attribute<0x0014, 0x403a> DACTimePoints; typedef gdcm::Attribute<0x0014, 0x403c> DACAmplitude; typedef gdcm::Attribute<0x0014, 0x4040> PreAmplifierSettingsSequence; typedef gdcm::Attribute<0x0014, 0x4050> TransmitTransducerSettingsSequence; typedef gdcm::Attribute<0x0014, 0x4051> ReceiveTransducerSettingsSequence; typedef gdcm::Attribute<0x0014, 0x4052> IncidentAngle; typedef gdcm::Attribute<0x0014, 0x4054> CouplingTechnique; typedef gdcm::Attribute<0x0014, 0x4056> CouplingMedium; typedef gdcm::Attribute<0x0014, 0x4057> CouplingVelocity; typedef gdcm::Attribute<0x0014, 0x4058> CrystalCenterLocationX; typedef gdcm::Attribute<0x0014, 0x4059> CrystalCenterLocationZ; typedef gdcm::Attribute<0x0014, 0x405a> SoundPathLength; typedef gdcm::Attribute<0x0014, 0x405c> DelayLawIdentifier; typedef gdcm::Attribute<0x0014, 0x4060> GateSettingsSequence; typedef gdcm::Attribute<0x0014, 0x4062> GateThreshold; typedef gdcm::Attribute<0x0014, 0x4064> VelocityOfSound; typedef gdcm::Attribute<0x0014, 0x4070> CalibrationSettingsSequence; typedef gdcm::Attribute<0x0014, 0x4072> CalibrationProcedure; typedef gdcm::Attribute<0x0014, 0x4074> ProcedureVersion; typedef gdcm::Attribute<0x0014, 0x4076> ProcedureCreationDate; typedef gdcm::Attribute<0x0014, 0x4078> ProcedureExpirationDate; typedef gdcm::Attribute<0x0014, 0x407a> ProcedureLastModifiedDate; typedef gdcm::Attribute<0x0014, 0x407c> CalibrationTime; typedef gdcm::Attribute<0x0014, 0x407e> CalibrationDate; typedef gdcm::Attribute<0x0014, 0x5002> LINACEnergy; typedef gdcm::Attribute<0x0014, 0x5004> LINACOutput; typedef gdcm::Attribute<0x0018, 0x0010> ContrastBolusAgent; typedef gdcm::Attribute<0x0018, 0x0012> ContrastBolusAgentSequence; typedef gdcm::Attribute<0x0018, 0x0014> ContrastBolusAdministrationRouteSequence; typedef gdcm::Attribute<0x0018, 0x0015> BodyPartExamined; typedef gdcm::Attribute<0x0018, 0x0020> ScanningSequence; typedef gdcm::Attribute<0x0018, 0x0021> SequenceVariant; typedef gdcm::Attribute<0x0018, 0x0022> ScanOptions; typedef gdcm::Attribute<0x0018, 0x0023> MRAcquisitionType; typedef gdcm::Attribute<0x0018, 0x0024> SequenceName; typedef gdcm::Attribute<0x0018, 0x0025> AngioFlag; typedef gdcm::Attribute<0x0018, 0x0026> InterventionDrugInformationSequence; typedef gdcm::Attribute<0x0018, 0x0027> InterventionDrugStopTime; typedef gdcm::Attribute<0x0018, 0x0028> InterventionDrugDose; typedef gdcm::Attribute<0x0018, 0x0029> InterventionDrugCodeSequence; typedef gdcm::Attribute<0x0018, 0x002a> AdditionalDrugSequence; typedef gdcm::Attribute<0x0018, 0x0030> Radionuclide; typedef gdcm::Attribute<0x0018, 0x0031> Radiopharmaceutical; typedef gdcm::Attribute<0x0018, 0x0032> EnergyWindowCenterline; typedef gdcm::Attribute<0x0018, 0x0033> EnergyWindowTotalWidth; typedef gdcm::Attribute<0x0018, 0x0034> InterventionDrugName; typedef gdcm::Attribute<0x0018, 0x0035> InterventionDrugStartTime; typedef gdcm::Attribute<0x0018, 0x0036> InterventionSequence; typedef gdcm::Attribute<0x0018, 0x0037> TherapyType; typedef gdcm::Attribute<0x0018, 0x0038> InterventionStatus; typedef gdcm::Attribute<0x0018, 0x0039> TherapyDescription; typedef gdcm::Attribute<0x0018, 0x003a> InterventionDescription; typedef gdcm::Attribute<0x0018, 0x0040> CineRate; typedef gdcm::Attribute<0x0018, 0x0042> InitialCineRunState; typedef gdcm::Attribute<0x0018, 0x0050> SliceThickness; typedef gdcm::Attribute<0x0018, 0x0060> KVP; typedef gdcm::Attribute<0x0018, 0x0070> CountsAccumulated; typedef gdcm::Attribute<0x0018, 0x0071> AcquisitionTerminationCondition; typedef gdcm::Attribute<0x0018, 0x0072> EffectiveDuration; typedef gdcm::Attribute<0x0018, 0x0073> AcquisitionStartCondition; typedef gdcm::Attribute<0x0018, 0x0074> AcquisitionStartConditionData; typedef gdcm::Attribute<0x0018, 0x0075> AcquisitionTerminationConditionData; typedef gdcm::Attribute<0x0018, 0x0080> RepetitionTime; typedef gdcm::Attribute<0x0018, 0x0081> EchoTime; typedef gdcm::Attribute<0x0018, 0x0082> InversionTime; typedef gdcm::Attribute<0x0018, 0x0083> NumberOfAverages; typedef gdcm::Attribute<0x0018, 0x0084> ImagingFrequency; typedef gdcm::Attribute<0x0018, 0x0085> ImagedNucleus; typedef gdcm::Attribute<0x0018, 0x0086> EchoNumbers; typedef gdcm::Attribute<0x0018, 0x0087> MagneticFieldStrength; typedef gdcm::Attribute<0x0018, 0x0088> SpacingBetweenSlices; typedef gdcm::Attribute<0x0018, 0x0089> NumberOfPhaseEncodingSteps; typedef gdcm::Attribute<0x0018, 0x0090> DataCollectionDiameter; typedef gdcm::Attribute<0x0018, 0x0091> EchoTrainLength; typedef gdcm::Attribute<0x0018, 0x0093> PercentSampling; typedef gdcm::Attribute<0x0018, 0x0094> PercentPhaseFieldOfView; typedef gdcm::Attribute<0x0018, 0x0095> PixelBandwidth; typedef gdcm::Attribute<0x0018, 0x1000> DeviceSerialNumber; typedef gdcm::Attribute<0x0018, 0x1002> DeviceUID; typedef gdcm::Attribute<0x0018, 0x1003> DeviceID; typedef gdcm::Attribute<0x0018, 0x1004> PlateID; typedef gdcm::Attribute<0x0018, 0x1005> GeneratorID; typedef gdcm::Attribute<0x0018, 0x1006> GridID; typedef gdcm::Attribute<0x0018, 0x1007> CassetteID; typedef gdcm::Attribute<0x0018, 0x1008> GantryID; typedef gdcm::Attribute<0x0018, 0x1010> SecondaryCaptureDeviceID; typedef gdcm::Attribute<0x0018, 0x1011> HardcopyCreationDeviceID; typedef gdcm::Attribute<0x0018, 0x1012> DateOfSecondaryCapture; typedef gdcm::Attribute<0x0018, 0x1014> TimeOfSecondaryCapture; typedef gdcm::Attribute<0x0018, 0x1016> SecondaryCaptureDeviceManufacturer; typedef gdcm::Attribute<0x0018, 0x1017> HardcopyDeviceManufacturer; typedef gdcm::Attribute<0x0018, 0x1018> SecondaryCaptureDeviceManufacturerModelName; typedef gdcm::Attribute<0x0018, 0x1019> SecondaryCaptureDeviceSoftwareVersions; typedef gdcm::Attribute<0x0018, 0x101a> HardcopyDeviceSoftwareVersion; typedef gdcm::Attribute<0x0018, 0x101b> HardcopyDeviceManufacturerModelName; typedef gdcm::Attribute<0x0018, 0x1020> SoftwareVersions; typedef gdcm::Attribute<0x0018, 0x1022> VideoImageFormatAcquired; typedef gdcm::Attribute<0x0018, 0x1023> DigitalImageFormatAcquired; typedef gdcm::Attribute<0x0018, 0x1030> ProtocolName; typedef gdcm::Attribute<0x0018, 0x1040> ContrastBolusRoute; typedef gdcm::Attribute<0x0018, 0x1041> ContrastBolusVolume; typedef gdcm::Attribute<0x0018, 0x1042> ContrastBolusStartTime; typedef gdcm::Attribute<0x0018, 0x1043> ContrastBolusStopTime; typedef gdcm::Attribute<0x0018, 0x1044> ContrastBolusTotalDose; typedef gdcm::Attribute<0x0018, 0x1045> SyringeCounts; typedef gdcm::Attribute<0x0018, 0x1046> ContrastFlowRate; typedef gdcm::Attribute<0x0018, 0x1047> ContrastFlowDuration; typedef gdcm::Attribute<0x0018, 0x1048> ContrastBolusIngredient; typedef gdcm::Attribute<0x0018, 0x1049> ContrastBolusIngredientConcentration; typedef gdcm::Attribute<0x0018, 0x1050> SpatialResolution; typedef gdcm::Attribute<0x0018, 0x1060> TriggerTime; typedef gdcm::Attribute<0x0018, 0x1061> TriggerSourceOrType; typedef gdcm::Attribute<0x0018, 0x1062> NominalInterval; typedef gdcm::Attribute<0x0018, 0x1063> FrameTime; typedef gdcm::Attribute<0x0018, 0x1064> CardiacFramingType; typedef gdcm::Attribute<0x0018, 0x1065> FrameTimeVector; typedef gdcm::Attribute<0x0018, 0x1066> FrameDelay; typedef gdcm::Attribute<0x0018, 0x1067> ImageTriggerDelay; typedef gdcm::Attribute<0x0018, 0x1068> MultiplexGroupTimeOffset; typedef gdcm::Attribute<0x0018, 0x1069> TriggerTimeOffset; typedef gdcm::Attribute<0x0018, 0x106a> SynchronizationTrigger; typedef gdcm::Attribute<0x0018, 0x106c> SynchronizationChannel; typedef gdcm::Attribute<0x0018, 0x106e> TriggerSamplePosition; typedef gdcm::Attribute<0x0018, 0x1070> RadiopharmaceuticalRoute; typedef gdcm::Attribute<0x0018, 0x1071> RadiopharmaceuticalVolume; typedef gdcm::Attribute<0x0018, 0x1072> RadiopharmaceuticalStartTime; typedef gdcm::Attribute<0x0018, 0x1073> RadiopharmaceuticalStopTime; typedef gdcm::Attribute<0x0018, 0x1074> RadionuclideTotalDose; typedef gdcm::Attribute<0x0018, 0x1075> RadionuclideHalfLife; typedef gdcm::Attribute<0x0018, 0x1076> RadionuclidePositronFraction; typedef gdcm::Attribute<0x0018, 0x1077> RadiopharmaceuticalSpecificActivity; typedef gdcm::Attribute<0x0018, 0x1078> RadiopharmaceuticalStartDateTime; typedef gdcm::Attribute<0x0018, 0x1079> RadiopharmaceuticalStopDateTime; typedef gdcm::Attribute<0x0018, 0x1080> BeatRejectionFlag; typedef gdcm::Attribute<0x0018, 0x1081> LowRRValue; typedef gdcm::Attribute<0x0018, 0x1082> HighRRValue; typedef gdcm::Attribute<0x0018, 0x1083> IntervalsAcquired; typedef gdcm::Attribute<0x0018, 0x1084> IntervalsRejected; typedef gdcm::Attribute<0x0018, 0x1085> PVCRejection; typedef gdcm::Attribute<0x0018, 0x1086> SkipBeats; typedef gdcm::Attribute<0x0018, 0x1088> HeartRate; typedef gdcm::Attribute<0x0018, 0x1090> CardiacNumberOfImages; typedef gdcm::Attribute<0x0018, 0x1094> TriggerWindow; typedef gdcm::Attribute<0x0018, 0x1100> ReconstructionDiameter; typedef gdcm::Attribute<0x0018, 0x1110> DistanceSourceToDetector; typedef gdcm::Attribute<0x0018, 0x1111> DistanceSourceToPatient; typedef gdcm::Attribute<0x0018, 0x1114> EstimatedRadiographicMagnificationFactor; typedef gdcm::Attribute<0x0018, 0x1120> GantryDetectorTilt; typedef gdcm::Attribute<0x0018, 0x1121> GantryDetectorSlew; typedef gdcm::Attribute<0x0018, 0x1130> TableHeight; typedef gdcm::Attribute<0x0018, 0x1131> TableTraverse; typedef gdcm::Attribute<0x0018, 0x1134> TableMotion; typedef gdcm::Attribute<0x0018, 0x1135> TableVerticalIncrement; typedef gdcm::Attribute<0x0018, 0x1136> TableLateralIncrement; typedef gdcm::Attribute<0x0018, 0x1137> TableLongitudinalIncrement; typedef gdcm::Attribute<0x0018, 0x1138> TableAngle; typedef gdcm::Attribute<0x0018, 0x113a> TableType; typedef gdcm::Attribute<0x0018, 0x1140> RotationDirection; typedef gdcm::Attribute<0x0018, 0x1141> AngularPosition; typedef gdcm::Attribute<0x0018, 0x1142> RadialPosition; typedef gdcm::Attribute<0x0018, 0x1143> ScanArc; typedef gdcm::Attribute<0x0018, 0x1144> AngularStep; typedef gdcm::Attribute<0x0018, 0x1145> CenterOfRotationOffset; typedef gdcm::Attribute<0x0018, 0x1146> RotationOffset; typedef gdcm::Attribute<0x0018, 0x1147> FieldOfViewShape; typedef gdcm::Attribute<0x0018, 0x1149> FieldOfViewDimensions; typedef gdcm::Attribute<0x0018, 0x1150> ExposureTime; typedef gdcm::Attribute<0x0018, 0x1151> XRayTubeCurrent; typedef gdcm::Attribute<0x0018, 0x1152> Exposure; typedef gdcm::Attribute<0x0018, 0x1153> ExposureInuAs; typedef gdcm::Attribute<0x0018, 0x1154> AveragePulseWidth; typedef gdcm::Attribute<0x0018, 0x1155> RadiationSetting; typedef gdcm::Attribute<0x0018, 0x1156> RectificationType; typedef gdcm::Attribute<0x0018, 0x115a> RadiationMode; typedef gdcm::Attribute<0x0018, 0x115e> ImageAndFluoroscopyAreaDoseProduct; typedef gdcm::Attribute<0x0018, 0x1160> FilterType; typedef gdcm::Attribute<0x0018, 0x1161> TypeOfFilters; typedef gdcm::Attribute<0x0018, 0x1162> IntensifierSize; typedef gdcm::Attribute<0x0018, 0x1164> ImagerPixelSpacing; typedef gdcm::Attribute<0x0018, 0x1166> Grid; typedef gdcm::Attribute<0x0018, 0x1170> GeneratorPower; typedef gdcm::Attribute<0x0018, 0x1180> CollimatorGridName; typedef gdcm::Attribute<0x0018, 0x1181> CollimatorType; typedef gdcm::Attribute<0x0018, 0x1182> FocalDistance; typedef gdcm::Attribute<0x0018, 0x1183> XFocusCenter; typedef gdcm::Attribute<0x0018, 0x1184> YFocusCenter; typedef gdcm::Attribute<0x0018, 0x1190> FocalSpots; typedef gdcm::Attribute<0x0018, 0x1191> AnodeTargetMaterial; typedef gdcm::Attribute<0x0018, 0x11a0> BodyPartThickness; typedef gdcm::Attribute<0x0018, 0x11a2> CompressionForce; typedef gdcm::Attribute<0x0018, 0x1200> DateOfLastCalibration; typedef gdcm::Attribute<0x0018, 0x1201> TimeOfLastCalibration; typedef gdcm::Attribute<0x0018, 0x1210> ConvolutionKernel; typedef gdcm::Attribute<0x0018, 0x1240> UpperLowerPixelValues; typedef gdcm::Attribute<0x0018, 0x1242> ActualFrameDuration; typedef gdcm::Attribute<0x0018, 0x1243> CountRate; typedef gdcm::Attribute<0x0018, 0x1244> PreferredPlaybackSequencing; typedef gdcm::Attribute<0x0018, 0x1250> ReceiveCoilName; typedef gdcm::Attribute<0x0018, 0x1251> TransmitCoilName; typedef gdcm::Attribute<0x0018, 0x1260> PlateType; typedef gdcm::Attribute<0x0018, 0x1261> PhosphorType; typedef gdcm::Attribute<0x0018, 0x1300> ScanVelocity; typedef gdcm::Attribute<0x0018, 0x1301> WholeBodyTechnique; typedef gdcm::Attribute<0x0018, 0x1302> ScanLength; typedef gdcm::Attribute<0x0018, 0x1310> AcquisitionMatrix; typedef gdcm::Attribute<0x0018, 0x1312> InPlanePhaseEncodingDirection; typedef gdcm::Attribute<0x0018, 0x1314> FlipAngle; typedef gdcm::Attribute<0x0018, 0x1315> VariableFlipAngleFlag; typedef gdcm::Attribute<0x0018, 0x1316> SAR; typedef gdcm::Attribute<0x0018, 0x1318> dBdt; typedef gdcm::Attribute<0x0018, 0x1400> AcquisitionDeviceProcessingDescription; typedef gdcm::Attribute<0x0018, 0x1401> AcquisitionDeviceProcessingCode; typedef gdcm::Attribute<0x0018, 0x1402> CassetteOrientation; typedef gdcm::Attribute<0x0018, 0x1403> CassetteSize; typedef gdcm::Attribute<0x0018, 0x1404> ExposuresOnPlate; typedef gdcm::Attribute<0x0018, 0x1405> RelativeXRayExposure; typedef gdcm::Attribute<0x0018, 0x1411> ExposureIndex; typedef gdcm::Attribute<0x0018, 0x1412> TargetExposureIndex; typedef gdcm::Attribute<0x0018, 0x1413> DeviationIndex; typedef gdcm::Attribute<0x0018, 0x1450> ColumnAngulation; typedef gdcm::Attribute<0x0018, 0x1460> TomoLayerHeight; typedef gdcm::Attribute<0x0018, 0x1470> TomoAngle; typedef gdcm::Attribute<0x0018, 0x1480> TomoTime; typedef gdcm::Attribute<0x0018, 0x1490> TomoType; typedef gdcm::Attribute<0x0018, 0x1491> TomoClass; typedef gdcm::Attribute<0x0018, 0x1495> NumberOfTomosynthesisSourceImages; typedef gdcm::Attribute<0x0018, 0x1500> PositionerMotion; typedef gdcm::Attribute<0x0018, 0x1508> PositionerType; typedef gdcm::Attribute<0x0018, 0x1510> PositionerPrimaryAngle; typedef gdcm::Attribute<0x0018, 0x1511> PositionerSecondaryAngle; typedef gdcm::Attribute<0x0018, 0x1520> PositionerPrimaryAngleIncrement; typedef gdcm::Attribute<0x0018, 0x1521> PositionerSecondaryAngleIncrement; typedef gdcm::Attribute<0x0018, 0x1530> DetectorPrimaryAngle; typedef gdcm::Attribute<0x0018, 0x1531> DetectorSecondaryAngle; typedef gdcm::Attribute<0x0018, 0x1600> ShutterShape; typedef gdcm::Attribute<0x0018, 0x1602> ShutterLeftVerticalEdge; typedef gdcm::Attribute<0x0018, 0x1604> ShutterRightVerticalEdge; typedef gdcm::Attribute<0x0018, 0x1606> ShutterUpperHorizontalEdge; typedef gdcm::Attribute<0x0018, 0x1608> ShutterLowerHorizontalEdge; typedef gdcm::Attribute<0x0018, 0x1610> CenterOfCircularShutter; typedef gdcm::Attribute<0x0018, 0x1612> RadiusOfCircularShutter; typedef gdcm::Attribute<0x0018, 0x1620> VerticesOfThePolygonalShutter; typedef gdcm::Attribute<0x0018, 0x1622> ShutterPresentationValue; typedef gdcm::Attribute<0x0018, 0x1623> ShutterOverlayGroup; typedef gdcm::Attribute<0x0018, 0x1624> ShutterPresentationColorCIELabValue; typedef gdcm::Attribute<0x0018, 0x1700> CollimatorShape; typedef gdcm::Attribute<0x0018, 0x1702> CollimatorLeftVerticalEdge; typedef gdcm::Attribute<0x0018, 0x1704> CollimatorRightVerticalEdge; typedef gdcm::Attribute<0x0018, 0x1706> CollimatorUpperHorizontalEdge; typedef gdcm::Attribute<0x0018, 0x1708> CollimatorLowerHorizontalEdge; typedef gdcm::Attribute<0x0018, 0x1710> CenterOfCircularCollimator; typedef gdcm::Attribute<0x0018, 0x1712> RadiusOfCircularCollimator; typedef gdcm::Attribute<0x0018, 0x1720> VerticesOfThePolygonalCollimator; typedef gdcm::Attribute<0x0018, 0x1800> AcquisitionTimeSynchronized; typedef gdcm::Attribute<0x0018, 0x1801> TimeSource; typedef gdcm::Attribute<0x0018, 0x1802> TimeDistributionProtocol; typedef gdcm::Attribute<0x0018, 0x1803> NTPSourceAddress; typedef gdcm::Attribute<0x0018, 0x2001> PageNumberVector; typedef gdcm::Attribute<0x0018, 0x2002> FrameLabelVector; typedef gdcm::Attribute<0x0018, 0x2003> FramePrimaryAngleVector; typedef gdcm::Attribute<0x0018, 0x2004> FrameSecondaryAngleVector; typedef gdcm::Attribute<0x0018, 0x2005> SliceLocationVector; typedef gdcm::Attribute<0x0018, 0x2006> DisplayWindowLabelVector; typedef gdcm::Attribute<0x0018, 0x2010> NominalScannedPixelSpacing; typedef gdcm::Attribute<0x0018, 0x2020> DigitizingDeviceTransportDirection; typedef gdcm::Attribute<0x0018, 0x2030> RotationOfScannedFilm; typedef gdcm::Attribute<0x0018, 0x3100> IVUSAcquisition; typedef gdcm::Attribute<0x0018, 0x3101> IVUSPullbackRate; typedef gdcm::Attribute<0x0018, 0x3102> IVUSGatedRate; typedef gdcm::Attribute<0x0018, 0x3103> IVUSPullbackStartFrameNumber; typedef gdcm::Attribute<0x0018, 0x3104> IVUSPullbackStopFrameNumber; typedef gdcm::Attribute<0x0018, 0x3105> LesionNumber; typedef gdcm::Attribute<0x0018, 0x4000> AcquisitionComments; typedef gdcm::Attribute<0x0018, 0x5000> OutputPower; typedef gdcm::Attribute<0x0018, 0x5010> TransducerData; typedef gdcm::Attribute<0x0018, 0x5012> FocusDepth; typedef gdcm::Attribute<0x0018, 0x5020> ProcessingFunction; typedef gdcm::Attribute<0x0018, 0x5021> PostprocessingFunction; typedef gdcm::Attribute<0x0018, 0x5022> MechanicalIndex; typedef gdcm::Attribute<0x0018, 0x5024> BoneThermalIndex; typedef gdcm::Attribute<0x0018, 0x5026> CranialThermalIndex; typedef gdcm::Attribute<0x0018, 0x5027> SoftTissueThermalIndex; typedef gdcm::Attribute<0x0018, 0x5028> SoftTissueFocusThermalIndex; typedef gdcm::Attribute<0x0018, 0x5029> SoftTissueSurfaceThermalIndex; typedef gdcm::Attribute<0x0018, 0x5030> DynamicRange; typedef gdcm::Attribute<0x0018, 0x5040> TotalGain; typedef gdcm::Attribute<0x0018, 0x5050> DepthOfScanField; typedef gdcm::Attribute<0x0018, 0x5100> PatientPosition; typedef gdcm::Attribute<0x0018, 0x5101> ViewPosition; typedef gdcm::Attribute<0x0018, 0x5104> ProjectionEponymousNameCodeSequence; typedef gdcm::Attribute<0x0018, 0x5210> ImageTransformationMatrix; typedef gdcm::Attribute<0x0018, 0x5212> ImageTranslationVector; typedef gdcm::Attribute<0x0018, 0x6000> Sensitivity; typedef gdcm::Attribute<0x0018, 0x6011> SequenceOfUltrasoundRegions; typedef gdcm::Attribute<0x0018, 0x6012> RegionSpatialFormat; typedef gdcm::Attribute<0x0018, 0x6014> RegionDataType; typedef gdcm::Attribute<0x0018, 0x6016> RegionFlags; typedef gdcm::Attribute<0x0018, 0x6018> RegionLocationMinX0; typedef gdcm::Attribute<0x0018, 0x601a> RegionLocationMinY0; typedef gdcm::Attribute<0x0018, 0x601c> RegionLocationMaxX1; typedef gdcm::Attribute<0x0018, 0x601e> RegionLocationMaxY1; typedef gdcm::Attribute<0x0018, 0x6020> ReferencePixelX0; typedef gdcm::Attribute<0x0018, 0x6022> ReferencePixelY0; typedef gdcm::Attribute<0x0018, 0x6024> PhysicalUnitsXDirection; typedef gdcm::Attribute<0x0018, 0x6026> PhysicalUnitsYDirection; typedef gdcm::Attribute<0x0018, 0x6028> ReferencePixelPhysicalValueX; typedef gdcm::Attribute<0x0018, 0x602a> ReferencePixelPhysicalValueY; typedef gdcm::Attribute<0x0018, 0x602c> PhysicalDeltaX; typedef gdcm::Attribute<0x0018, 0x602e> PhysicalDeltaY; typedef gdcm::Attribute<0x0018, 0x6030> TransducerFrequency; typedef gdcm::Attribute<0x0018, 0x6031> TransducerType; typedef gdcm::Attribute<0x0018, 0x6032> PulseRepetitionFrequency; typedef gdcm::Attribute<0x0018, 0x6034> DopplerCorrectionAngle; typedef gdcm::Attribute<0x0018, 0x6036> SteeringAngle; typedef gdcm::Attribute<0x0018, 0x6038> DopplerSampleVolumeXPositionRetired; typedef gdcm::Attribute<0x0018, 0x6039> DopplerSampleVolumeXPosition; typedef gdcm::Attribute<0x0018, 0x603a> DopplerSampleVolumeYPositionRetired; typedef gdcm::Attribute<0x0018, 0x603b> DopplerSampleVolumeYPosition; typedef gdcm::Attribute<0x0018, 0x603c> TMLinePositionX0Retired; typedef gdcm::Attribute<0x0018, 0x603d> TMLinePositionX0; typedef gdcm::Attribute<0x0018, 0x603e> TMLinePositionY0Retired; typedef gdcm::Attribute<0x0018, 0x603f> TMLinePositionY0; typedef gdcm::Attribute<0x0018, 0x6040> TMLinePositionX1Retired; typedef gdcm::Attribute<0x0018, 0x6041> TMLinePositionX1; typedef gdcm::Attribute<0x0018, 0x6042> TMLinePositionY1Retired; typedef gdcm::Attribute<0x0018, 0x6043> TMLinePositionY1; typedef gdcm::Attribute<0x0018, 0x6044> PixelComponentOrganization; typedef gdcm::Attribute<0x0018, 0x6046> PixelComponentMask; typedef gdcm::Attribute<0x0018, 0x6048> PixelComponentRangeStart; typedef gdcm::Attribute<0x0018, 0x604a> PixelComponentRangeStop; typedef gdcm::Attribute<0x0018, 0x604c> PixelComponentPhysicalUnits; typedef gdcm::Attribute<0x0018, 0x604e> PixelComponentDataType; typedef gdcm::Attribute<0x0018, 0x6050> NumberOfTableBreakPoints; typedef gdcm::Attribute<0x0018, 0x6052> TableOfXBreakPoints; typedef gdcm::Attribute<0x0018, 0x6054> TableOfYBreakPoints; typedef gdcm::Attribute<0x0018, 0x6056> NumberOfTableEntries; typedef gdcm::Attribute<0x0018, 0x6058> TableOfPixelValues; typedef gdcm::Attribute<0x0018, 0x605a> TableOfParameterValues; typedef gdcm::Attribute<0x0018, 0x6060> RWaveTimeVector; typedef gdcm::Attribute<0x0018, 0x7000> DetectorConditionsNominalFlag; typedef gdcm::Attribute<0x0018, 0x7001> DetectorTemperature; typedef gdcm::Attribute<0x0018, 0x7004> DetectorType; typedef gdcm::Attribute<0x0018, 0x7005> DetectorConfiguration; typedef gdcm::Attribute<0x0018, 0x7006> DetectorDescription; typedef gdcm::Attribute<0x0018, 0x7008> DetectorMode; typedef gdcm::Attribute<0x0018, 0x700a> DetectorID; typedef gdcm::Attribute<0x0018, 0x700c> DateOfLastDetectorCalibration; typedef gdcm::Attribute<0x0018, 0x700e> TimeOfLastDetectorCalibration; typedef gdcm::Attribute<0x0018, 0x7010> ExposuresOnDetectorSinceLastCalibration; typedef gdcm::Attribute<0x0018, 0x7011> ExposuresOnDetectorSinceManufactured; typedef gdcm::Attribute<0x0018, 0x7012> DetectorTimeSinceLastExposure; typedef gdcm::Attribute<0x0018, 0x7014> DetectorActiveTime; typedef gdcm::Attribute<0x0018, 0x7016> DetectorActivationOffsetFromExposure; typedef gdcm::Attribute<0x0018, 0x701a> DetectorBinning; typedef gdcm::Attribute<0x0018, 0x7020> DetectorElementPhysicalSize; typedef gdcm::Attribute<0x0018, 0x7022> DetectorElementSpacing; typedef gdcm::Attribute<0x0018, 0x7024> DetectorActiveShape; typedef gdcm::Attribute<0x0018, 0x7026> DetectorActiveDimensions; typedef gdcm::Attribute<0x0018, 0x7028> DetectorActiveOrigin; typedef gdcm::Attribute<0x0018, 0x702a> DetectorManufacturerName; typedef gdcm::Attribute<0x0018, 0x702b> DetectorManufacturerModelName; typedef gdcm::Attribute<0x0018, 0x7030> FieldOfViewOrigin; typedef gdcm::Attribute<0x0018, 0x7032> FieldOfViewRotation; typedef gdcm::Attribute<0x0018, 0x7034> FieldOfViewHorizontalFlip; typedef gdcm::Attribute<0x0018, 0x7036> PixelDataAreaOriginRelativeToFOV; typedef gdcm::Attribute<0x0018, 0x7038> PixelDataAreaRotationAngleRelativeToFOV; typedef gdcm::Attribute<0x0018, 0x7040> GridAbsorbingMaterial; typedef gdcm::Attribute<0x0018, 0x7041> GridSpacingMaterial; typedef gdcm::Attribute<0x0018, 0x7042> GridThickness; typedef gdcm::Attribute<0x0018, 0x7044> GridPitch; typedef gdcm::Attribute<0x0018, 0x7046> GridAspectRatio; typedef gdcm::Attribute<0x0018, 0x7048> GridPeriod; typedef gdcm::Attribute<0x0018, 0x704c> GridFocalDistance; typedef gdcm::Attribute<0x0018, 0x7050> FilterMaterial; typedef gdcm::Attribute<0x0018, 0x7052> FilterThicknessMinimum; typedef gdcm::Attribute<0x0018, 0x7054> FilterThicknessMaximum; typedef gdcm::Attribute<0x0018, 0x7056> FilterBeamPathLengthMinimum; typedef gdcm::Attribute<0x0018, 0x7058> FilterBeamPathLengthMaximum; typedef gdcm::Attribute<0x0018, 0x7060> ExposureControlMode; typedef gdcm::Attribute<0x0018, 0x7062> ExposureControlModeDescription; typedef gdcm::Attribute<0x0018, 0x7064> ExposureStatus; typedef gdcm::Attribute<0x0018, 0x7065> PhototimerSetting; typedef gdcm::Attribute<0x0018, 0x8150> ExposureTimeInuS; typedef gdcm::Attribute<0x0018, 0x8151> XRayTubeCurrentInuA; typedef gdcm::Attribute<0x0018, 0x9004> ContentQualification; typedef gdcm::Attribute<0x0018, 0x9005> PulseSequenceName; typedef gdcm::Attribute<0x0018, 0x9006> MRImagingModifierSequence; typedef gdcm::Attribute<0x0018, 0x9008> EchoPulseSequence; typedef gdcm::Attribute<0x0018, 0x9009> InversionRecovery; typedef gdcm::Attribute<0x0018, 0x9010> FlowCompensation; typedef gdcm::Attribute<0x0018, 0x9011> MultipleSpinEcho; typedef gdcm::Attribute<0x0018, 0x9012> MultiPlanarExcitation; typedef gdcm::Attribute<0x0018, 0x9014> PhaseContrast; typedef gdcm::Attribute<0x0018, 0x9015> TimeOfFlightContrast; typedef gdcm::Attribute<0x0018, 0x9016> Spoiling; typedef gdcm::Attribute<0x0018, 0x9017> SteadyStatePulseSequence; typedef gdcm::Attribute<0x0018, 0x9018> EchoPlanarPulseSequence; typedef gdcm::Attribute<0x0018, 0x9019> TagAngleFirstAxis; typedef gdcm::Attribute<0x0018, 0x9020> MagnetizationTransfer; typedef gdcm::Attribute<0x0018, 0x9021> T2Preparation; typedef gdcm::Attribute<0x0018, 0x9022> BloodSignalNulling; typedef gdcm::Attribute<0x0018, 0x9024> SaturationRecovery; typedef gdcm::Attribute<0x0018, 0x9025> SpectrallySelectedSuppression; typedef gdcm::Attribute<0x0018, 0x9026> SpectrallySelectedExcitation; typedef gdcm::Attribute<0x0018, 0x9027> SpatialPresaturation; typedef gdcm::Attribute<0x0018, 0x9028> Tagging; typedef gdcm::Attribute<0x0018, 0x9029> OversamplingPhase; typedef gdcm::Attribute<0x0018, 0x9030> TagSpacingFirstDimension; typedef gdcm::Attribute<0x0018, 0x9032> GeometryOfKSpaceTraversal; typedef gdcm::Attribute<0x0018, 0x9033> SegmentedKSpaceTraversal; typedef gdcm::Attribute<0x0018, 0x9034> RectilinearPhaseEncodeReordering; typedef gdcm::Attribute<0x0018, 0x9035> TagThickness; typedef gdcm::Attribute<0x0018, 0x9036> PartialFourierDirection; typedef gdcm::Attribute<0x0018, 0x9037> CardiacSynchronizationTechnique; typedef gdcm::Attribute<0x0018, 0x9041> ReceiveCoilManufacturerName; typedef gdcm::Attribute<0x0018, 0x9042> MRReceiveCoilSequence; typedef gdcm::Attribute<0x0018, 0x9043> ReceiveCoilType; typedef gdcm::Attribute<0x0018, 0x9044> QuadratureReceiveCoil; typedef gdcm::Attribute<0x0018, 0x9045> MultiCoilDefinitionSequence; typedef gdcm::Attribute<0x0018, 0x9046> MultiCoilConfiguration; typedef gdcm::Attribute<0x0018, 0x9047> MultiCoilElementName; typedef gdcm::Attribute<0x0018, 0x9048> MultiCoilElementUsed; typedef gdcm::Attribute<0x0018, 0x9049> MRTransmitCoilSequence; typedef gdcm::Attribute<0x0018, 0x9050> TransmitCoilManufacturerName; typedef gdcm::Attribute<0x0018, 0x9051> TransmitCoilType; typedef gdcm::Attribute<0x0018, 0x9052> SpectralWidth; typedef gdcm::Attribute<0x0018, 0x9053> ChemicalShiftReference; typedef gdcm::Attribute<0x0018, 0x9054> VolumeLocalizationTechnique; typedef gdcm::Attribute<0x0018, 0x9058> MRAcquisitionFrequencyEncodingSteps; typedef gdcm::Attribute<0x0018, 0x9059> Decoupling; typedef gdcm::Attribute<0x0018, 0x9060> DecoupledNucleus; typedef gdcm::Attribute<0x0018, 0x9061> DecouplingFrequency; typedef gdcm::Attribute<0x0018, 0x9062> DecouplingMethod; typedef gdcm::Attribute<0x0018, 0x9063> DecouplingChemicalShiftReference; typedef gdcm::Attribute<0x0018, 0x9064> KSpaceFiltering; typedef gdcm::Attribute<0x0018, 0x9065> TimeDomainFiltering; typedef gdcm::Attribute<0x0018, 0x9066> NumberOfZeroFills; typedef gdcm::Attribute<0x0018, 0x9067> BaselineCorrection; typedef gdcm::Attribute<0x0018, 0x9069> ParallelReductionFactorInPlane; typedef gdcm::Attribute<0x0018, 0x9070> CardiacRRIntervalSpecified; typedef gdcm::Attribute<0x0018, 0x9073> AcquisitionDuration; typedef gdcm::Attribute<0x0018, 0x9074> FrameAcquisitionDateTime; typedef gdcm::Attribute<0x0018, 0x9075> DiffusionDirectionality; typedef gdcm::Attribute<0x0018, 0x9076> DiffusionGradientDirectionSequence; typedef gdcm::Attribute<0x0018, 0x9077> ParallelAcquisition; typedef gdcm::Attribute<0x0018, 0x9078> ParallelAcquisitionTechnique; typedef gdcm::Attribute<0x0018, 0x9079> InversionTimes; typedef gdcm::Attribute<0x0018, 0x9080> MetaboliteMapDescription; typedef gdcm::Attribute<0x0018, 0x9081> PartialFourier; typedef gdcm::Attribute<0x0018, 0x9082> EffectiveEchoTime; typedef gdcm::Attribute<0x0018, 0x9083> MetaboliteMapCodeSequence; typedef gdcm::Attribute<0x0018, 0x9084> ChemicalShiftSequence; typedef gdcm::Attribute<0x0018, 0x9085> CardiacSignalSource; typedef gdcm::Attribute<0x0018, 0x9087> DiffusionBValue; typedef gdcm::Attribute<0x0018, 0x9089> DiffusionGradientOrientation; typedef gdcm::Attribute<0x0018, 0x9090> VelocityEncodingDirection; typedef gdcm::Attribute<0x0018, 0x9091> VelocityEncodingMinimumValue; typedef gdcm::Attribute<0x0018, 0x9092> VelocityEncodingAcquisitionSequence; typedef gdcm::Attribute<0x0018, 0x9093> NumberOfKSpaceTrajectories; typedef gdcm::Attribute<0x0018, 0x9094> CoverageOfKSpace; typedef gdcm::Attribute<0x0018, 0x9095> SpectroscopyAcquisitionPhaseRows; typedef gdcm::Attribute<0x0018, 0x9096> ParallelReductionFactorInPlaneRetired; typedef gdcm::Attribute<0x0018, 0x9098> TransmitterFrequency; typedef gdcm::Attribute<0x0018, 0x9100> ResonantNucleus; typedef gdcm::Attribute<0x0018, 0x9101> FrequencyCorrection; typedef gdcm::Attribute<0x0018, 0x9103> MRSpectroscopyFOVGeometrySequence; typedef gdcm::Attribute<0x0018, 0x9104> SlabThickness; typedef gdcm::Attribute<0x0018, 0x9105> SlabOrientation; typedef gdcm::Attribute<0x0018, 0x9106> MidSlabPosition; typedef gdcm::Attribute<0x0018, 0x9107> MRSpatialSaturationSequence; typedef gdcm::Attribute<0x0018, 0x9112> MRTimingAndRelatedParametersSequence; typedef gdcm::Attribute<0x0018, 0x9114> MREchoSequence; typedef gdcm::Attribute<0x0018, 0x9115> MRModifierSequence; typedef gdcm::Attribute<0x0018, 0x9117> MRDiffusionSequence; typedef gdcm::Attribute<0x0018, 0x9118> CardiacSynchronizationSequence; typedef gdcm::Attribute<0x0018, 0x9119> MRAveragesSequence; typedef gdcm::Attribute<0x0018, 0x9125> MRFOVGeometrySequence; typedef gdcm::Attribute<0x0018, 0x9126> VolumeLocalizationSequence; typedef gdcm::Attribute<0x0018, 0x9127> SpectroscopyAcquisitionDataColumns; typedef gdcm::Attribute<0x0018, 0x9147> DiffusionAnisotropyType; typedef gdcm::Attribute<0x0018, 0x9151> FrameReferenceDateTime; typedef gdcm::Attribute<0x0018, 0x9152> MRMetaboliteMapSequence; typedef gdcm::Attribute<0x0018, 0x9155> ParallelReductionFactorOutOfPlane; typedef gdcm::Attribute<0x0018, 0x9159> SpectroscopyAcquisitionOutOfPlanePhaseSteps; typedef gdcm::Attribute<0x0018, 0x9166> BulkMotionStatus; typedef gdcm::Attribute<0x0018, 0x9168> ParallelReductionFactorSecondInPlane; typedef gdcm::Attribute<0x0018, 0x9169> CardiacBeatRejectionTechnique; typedef gdcm::Attribute<0x0018, 0x9170> RespiratoryMotionCompensationTechnique; typedef gdcm::Attribute<0x0018, 0x9171> RespiratorySignalSource; typedef gdcm::Attribute<0x0018, 0x9172> BulkMotionCompensationTechnique; typedef gdcm::Attribute<0x0018, 0x9173> BulkMotionSignalSource; typedef gdcm::Attribute<0x0018, 0x9174> ApplicableSafetyStandardAgency; typedef gdcm::Attribute<0x0018, 0x9175> ApplicableSafetyStandardDescription; typedef gdcm::Attribute<0x0018, 0x9176> OperatingModeSequence; typedef gdcm::Attribute<0x0018, 0x9177> OperatingModeType; typedef gdcm::Attribute<0x0018, 0x9178> OperatingMode; typedef gdcm::Attribute<0x0018, 0x9179> SpecificAbsorptionRateDefinition; typedef gdcm::Attribute<0x0018, 0x9180> GradientOutputType; typedef gdcm::Attribute<0x0018, 0x9181> SpecificAbsorptionRateValue; typedef gdcm::Attribute<0x0018, 0x9182> GradientOutput; typedef gdcm::Attribute<0x0018, 0x9183> FlowCompensationDirection; typedef gdcm::Attribute<0x0018, 0x9184> TaggingDelay; typedef gdcm::Attribute<0x0018, 0x9185> RespiratoryMotionCompensationTechniqueDescription; typedef gdcm::Attribute<0x0018, 0x9186> RespiratorySignalSourceID; typedef gdcm::Attribute<0x0018, 0x9195> ChemicalShiftMinimumIntegrationLimitInHz; typedef gdcm::Attribute<0x0018, 0x9196> ChemicalShiftMaximumIntegrationLimitInHz; typedef gdcm::Attribute<0x0018, 0x9197> MRVelocityEncodingSequence; typedef gdcm::Attribute<0x0018, 0x9198> FirstOrderPhaseCorrection; typedef gdcm::Attribute<0x0018, 0x9199> WaterReferencedPhaseCorrection; typedef gdcm::Attribute<0x0018, 0x9200> MRSpectroscopyAcquisitionType; typedef gdcm::Attribute<0x0018, 0x9214> RespiratoryCyclePosition; typedef gdcm::Attribute<0x0018, 0x9217> VelocityEncodingMaximumValue; typedef gdcm::Attribute<0x0018, 0x9218> TagSpacingSecondDimension; typedef gdcm::Attribute<0x0018, 0x9219> TagAngleSecondAxis; typedef gdcm::Attribute<0x0018, 0x9220> FrameAcquisitionDuration; typedef gdcm::Attribute<0x0018, 0x9226> MRImageFrameTypeSequence; typedef gdcm::Attribute<0x0018, 0x9227> MRSpectroscopyFrameTypeSequence; typedef gdcm::Attribute<0x0018, 0x9231> MRAcquisitionPhaseEncodingStepsInPlane; typedef gdcm::Attribute<0x0018, 0x9232> MRAcquisitionPhaseEncodingStepsOutOfPlane; typedef gdcm::Attribute<0x0018, 0x9234> SpectroscopyAcquisitionPhaseColumns; typedef gdcm::Attribute<0x0018, 0x9236> CardiacCyclePosition; typedef gdcm::Attribute<0x0018, 0x9239> SpecificAbsorptionRateSequence; typedef gdcm::Attribute<0x0018, 0x9240> RFEchoTrainLength; typedef gdcm::Attribute<0x0018, 0x9241> GradientEchoTrainLength; typedef gdcm::Attribute<0x0018, 0x9250> ArterialSpinLabelingContrast; typedef gdcm::Attribute<0x0018, 0x9251> MRArterialSpinLabelingSequence; typedef gdcm::Attribute<0x0018, 0x9252> ASLTechniqueDescription; typedef gdcm::Attribute<0x0018, 0x9253> ASLSlabNumber; typedef gdcm::Attribute<0x0018, 0x9254> ASLSlabThickness; typedef gdcm::Attribute<0x0018, 0x9255> ASLSlabOrientation; typedef gdcm::Attribute<0x0018, 0x9256> ASLMidSlabPosition; typedef gdcm::Attribute<0x0018, 0x9257> ASLContext; typedef gdcm::Attribute<0x0018, 0x9258> ASLPulseTrainDuration; typedef gdcm::Attribute<0x0018, 0x9259> ASLCrusherFlag; typedef gdcm::Attribute<0x0018, 0x925a> ASLCrusherFlow; typedef gdcm::Attribute<0x0018, 0x925b> ASLCrusherDescription; typedef gdcm::Attribute<0x0018, 0x925c> ASLBolusCutoffFlag; typedef gdcm::Attribute<0x0018, 0x925d> ASLBolusCutoffTimingSequence; typedef gdcm::Attribute<0x0018, 0x925e> ASLBolusCutoffTechnique; typedef gdcm::Attribute<0x0018, 0x925f> ASLBolusCutoffDelayTime; typedef gdcm::Attribute<0x0018, 0x9260> ASLSlabSequence; typedef gdcm::Attribute<0x0018, 0x9295> ChemicalShiftMinimumIntegrationLimitInppm; typedef gdcm::Attribute<0x0018, 0x9296> ChemicalShiftMaximumIntegrationLimitInppm; typedef gdcm::Attribute<0x0018, 0x9301> CTAcquisitionTypeSequence; typedef gdcm::Attribute<0x0018, 0x9302> AcquisitionType; typedef gdcm::Attribute<0x0018, 0x9303> TubeAngle; typedef gdcm::Attribute<0x0018, 0x9304> CTAcquisitionDetailsSequence; typedef gdcm::Attribute<0x0018, 0x9305> RevolutionTime; typedef gdcm::Attribute<0x0018, 0x9306> SingleCollimationWidth; typedef gdcm::Attribute<0x0018, 0x9307> TotalCollimationWidth; typedef gdcm::Attribute<0x0018, 0x9308> CTTableDynamicsSequence; typedef gdcm::Attribute<0x0018, 0x9309> TableSpeed; typedef gdcm::Attribute<0x0018, 0x9310> TableFeedPerRotation; typedef gdcm::Attribute<0x0018, 0x9311> SpiralPitchFactor; typedef gdcm::Attribute<0x0018, 0x9312> CTGeometrySequence; typedef gdcm::Attribute<0x0018, 0x9313> DataCollectionCenterPatient; typedef gdcm::Attribute<0x0018, 0x9314> CTReconstructionSequence; typedef gdcm::Attribute<0x0018, 0x9315> ReconstructionAlgorithm; typedef gdcm::Attribute<0x0018, 0x9316> ConvolutionKernelGroup; typedef gdcm::Attribute<0x0018, 0x9317> ReconstructionFieldOfView; typedef gdcm::Attribute<0x0018, 0x9318> ReconstructionTargetCenterPatient; typedef gdcm::Attribute<0x0018, 0x9319> ReconstructionAngle; typedef gdcm::Attribute<0x0018, 0x9320> ImageFilter; typedef gdcm::Attribute<0x0018, 0x9321> CTExposureSequence; typedef gdcm::Attribute<0x0018, 0x9322> ReconstructionPixelSpacing; typedef gdcm::Attribute<0x0018, 0x9323> ExposureModulationType; typedef gdcm::Attribute<0x0018, 0x9324> EstimatedDoseSaving; typedef gdcm::Attribute<0x0018, 0x9325> CTXRayDetailsSequence; typedef gdcm::Attribute<0x0018, 0x9326> CTPositionSequence; typedef gdcm::Attribute<0x0018, 0x9327> TablePosition; typedef gdcm::Attribute<0x0018, 0x9328> ExposureTimeInms; typedef gdcm::Attribute<0x0018, 0x9329> CTImageFrameTypeSequence; typedef gdcm::Attribute<0x0018, 0x9330> XRayTubeCurrentInmA; typedef gdcm::Attribute<0x0018, 0x9332> ExposureInmAs; typedef gdcm::Attribute<0x0018, 0x9333> ConstantVolumeFlag; typedef gdcm::Attribute<0x0018, 0x9334> FluoroscopyFlag; typedef gdcm::Attribute<0x0018, 0x9335> DistanceSourceToDataCollectionCenter; typedef gdcm::Attribute<0x0018, 0x9337> ContrastBolusAgentNumber; typedef gdcm::Attribute<0x0018, 0x9338> ContrastBolusIngredientCodeSequence; typedef gdcm::Attribute<0x0018, 0x9340> ContrastAdministrationProfileSequence; typedef gdcm::Attribute<0x0018, 0x9341> ContrastBolusUsageSequence; typedef gdcm::Attribute<0x0018, 0x9342> ContrastBolusAgentAdministered; typedef gdcm::Attribute<0x0018, 0x9343> ContrastBolusAgentDetected; typedef gdcm::Attribute<0x0018, 0x9344> ContrastBolusAgentPhase; typedef gdcm::Attribute<0x0018, 0x9345> CTDIvol; typedef gdcm::Attribute<0x0018, 0x9346> CTDIPhantomTypeCodeSequence; typedef gdcm::Attribute<0x0018, 0x9351> CalciumScoringMassFactorPatient; typedef gdcm::Attribute<0x0018, 0x9352> CalciumScoringMassFactorDevice; typedef gdcm::Attribute<0x0018, 0x9353> EnergyWeightingFactor; typedef gdcm::Attribute<0x0018, 0x9360> CTAdditionalXRaySourceSequence; typedef gdcm::Attribute<0x0018, 0x9401> ProjectionPixelCalibrationSequence; typedef gdcm::Attribute<0x0018, 0x9402> DistanceSourceToIsocenter; typedef gdcm::Attribute<0x0018, 0x9403> DistanceObjectToTableTop; typedef gdcm::Attribute<0x0018, 0x9404> ObjectPixelSpacingInCenterOfBeam; typedef gdcm::Attribute<0x0018, 0x9405> PositionerPositionSequence; typedef gdcm::Attribute<0x0018, 0x9406> TablePositionSequence; typedef gdcm::Attribute<0x0018, 0x9407> CollimatorShapeSequence; typedef gdcm::Attribute<0x0018, 0x9410> PlanesInAcquisition; typedef gdcm::Attribute<0x0018, 0x9412> XAXRFFrameCharacteristicsSequence; typedef gdcm::Attribute<0x0018, 0x9417> FrameAcquisitionSequence; typedef gdcm::Attribute<0x0018, 0x9420> XRayReceptorType; typedef gdcm::Attribute<0x0018, 0x9423> AcquisitionProtocolName; typedef gdcm::Attribute<0x0018, 0x9424> AcquisitionProtocolDescription; typedef gdcm::Attribute<0x0018, 0x9425> ContrastBolusIngredientOpaque; typedef gdcm::Attribute<0x0018, 0x9426> DistanceReceptorPlaneToDetectorHousing; typedef gdcm::Attribute<0x0018, 0x9427> IntensifierActiveShape; typedef gdcm::Attribute<0x0018, 0x9428> IntensifierActiveDimensions; typedef gdcm::Attribute<0x0018, 0x9429> PhysicalDetectorSize; typedef gdcm::Attribute<0x0018, 0x9430> PositionOfIsocenterProjection; typedef gdcm::Attribute<0x0018, 0x9432> FieldOfViewSequence; typedef gdcm::Attribute<0x0018, 0x9433> FieldOfViewDescription; typedef gdcm::Attribute<0x0018, 0x9434> ExposureControlSensingRegionsSequence; typedef gdcm::Attribute<0x0018, 0x9435> ExposureControlSensingRegionShape; typedef gdcm::Attribute<0x0018, 0x9436> ExposureControlSensingRegionLeftVerticalEdge; typedef gdcm::Attribute<0x0018, 0x9437> ExposureControlSensingRegionRightVerticalEdge; typedef gdcm::Attribute<0x0018, 0x9438> ExposureControlSensingRegionUpperHorizontalEdge; typedef gdcm::Attribute<0x0018, 0x9439> ExposureControlSensingRegionLowerHorizontalEdge; typedef gdcm::Attribute<0x0018, 0x9440> CenterOfCircularExposureControlSensingRegion; typedef gdcm::Attribute<0x0018, 0x9441> RadiusOfCircularExposureControlSensingRegion; typedef gdcm::Attribute<0x0018, 0x9442> VerticesOfThePolygonalExposureControlSensingRegion; // 0x0018, 0x9445 SHALL NOT BE USED typedef gdcm::Attribute<0x0018, 0x9447> ColumnAngulationPatient; typedef gdcm::Attribute<0x0018, 0x9449> BeamAngle; typedef gdcm::Attribute<0x0018, 0x9451> FrameDetectorParametersSequence; typedef gdcm::Attribute<0x0018, 0x9452> CalculatedAnatomyThickness; typedef gdcm::Attribute<0x0018, 0x9455> CalibrationSequence; typedef gdcm::Attribute<0x0018, 0x9456> ObjectThicknessSequence; typedef gdcm::Attribute<0x0018, 0x9457> PlaneIdentification; typedef gdcm::Attribute<0x0018, 0x9461> FieldOfViewDimensionsInFloat; typedef gdcm::Attribute<0x0018, 0x9462> IsocenterReferenceSystemSequence; typedef gdcm::Attribute<0x0018, 0x9463> PositionerIsocenterPrimaryAngle; typedef gdcm::Attribute<0x0018, 0x9464> PositionerIsocenterSecondaryAngle; typedef gdcm::Attribute<0x0018, 0x9465> PositionerIsocenterDetectorRotationAngle; typedef gdcm::Attribute<0x0018, 0x9466> TableXPositionToIsocenter; typedef gdcm::Attribute<0x0018, 0x9467> TableYPositionToIsocenter; typedef gdcm::Attribute<0x0018, 0x9468> TableZPositionToIsocenter; typedef gdcm::Attribute<0x0018, 0x9469> TableHorizontalRotationAngle; typedef gdcm::Attribute<0x0018, 0x9470> TableHeadTiltAngle; typedef gdcm::Attribute<0x0018, 0x9471> TableCradleTiltAngle; typedef gdcm::Attribute<0x0018, 0x9472> FrameDisplayShutterSequence; typedef gdcm::Attribute<0x0018, 0x9473> AcquiredImageAreaDoseProduct; typedef gdcm::Attribute<0x0018, 0x9474> CArmPositionerTabletopRelationship; typedef gdcm::Attribute<0x0018, 0x9476> XRayGeometrySequence; typedef gdcm::Attribute<0x0018, 0x9477> IrradiationEventIdentificationSequence; typedef gdcm::Attribute<0x0018, 0x9504> XRay3DFrameTypeSequence; typedef gdcm::Attribute<0x0018, 0x9506> ContributingSourcesSequence; typedef gdcm::Attribute<0x0018, 0x9507> XRay3DAcquisitionSequence; typedef gdcm::Attribute<0x0018, 0x9508> PrimaryPositionerScanArc; typedef gdcm::Attribute<0x0018, 0x9509> SecondaryPositionerScanArc; typedef gdcm::Attribute<0x0018, 0x9510> PrimaryPositionerScanStartAngle; typedef gdcm::Attribute<0x0018, 0x9511> SecondaryPositionerScanStartAngle; typedef gdcm::Attribute<0x0018, 0x9514> PrimaryPositionerIncrement; typedef gdcm::Attribute<0x0018, 0x9515> SecondaryPositionerIncrement; typedef gdcm::Attribute<0x0018, 0x9516> StartAcquisitionDateTime; typedef gdcm::Attribute<0x0018, 0x9517> EndAcquisitionDateTime; typedef gdcm::Attribute<0x0018, 0x9524> ApplicationName; typedef gdcm::Attribute<0x0018, 0x9525> ApplicationVersion; typedef gdcm::Attribute<0x0018, 0x9526> ApplicationManufacturer; typedef gdcm::Attribute<0x0018, 0x9527> AlgorithmType; typedef gdcm::Attribute<0x0018, 0x9528> AlgorithmDescription; typedef gdcm::Attribute<0x0018, 0x9530> XRay3DReconstructionSequence; typedef gdcm::Attribute<0x0018, 0x9531> ReconstructionDescription; typedef gdcm::Attribute<0x0018, 0x9538> PerProjectionAcquisitionSequence; typedef gdcm::Attribute<0x0018, 0x9601> DiffusionBMatrixSequence; typedef gdcm::Attribute<0x0018, 0x9602> DiffusionBValueXX; typedef gdcm::Attribute<0x0018, 0x9603> DiffusionBValueXY; typedef gdcm::Attribute<0x0018, 0x9604> DiffusionBValueXZ; typedef gdcm::Attribute<0x0018, 0x9605> DiffusionBValueYY; typedef gdcm::Attribute<0x0018, 0x9606> DiffusionBValueYZ; typedef gdcm::Attribute<0x0018, 0x9607> DiffusionBValueZZ; typedef gdcm::Attribute<0x0018, 0x9701> DecayCorrectionDateTime; typedef gdcm::Attribute<0x0018, 0x9715> StartDensityThreshold; typedef gdcm::Attribute<0x0018, 0x9716> StartRelativeDensityDifferenceThreshold; typedef gdcm::Attribute<0x0018, 0x9717> StartCardiacTriggerCountThreshold; typedef gdcm::Attribute<0x0018, 0x9718> StartRespiratoryTriggerCountThreshold; typedef gdcm::Attribute<0x0018, 0x9719> TerminationCountsThreshold; typedef gdcm::Attribute<0x0018, 0x9720> TerminationDensityThreshold; typedef gdcm::Attribute<0x0018, 0x9721> TerminationRelativeDensityThreshold; typedef gdcm::Attribute<0x0018, 0x9722> TerminationTimeThreshold; typedef gdcm::Attribute<0x0018, 0x9723> TerminationCardiacTriggerCountThreshold; typedef gdcm::Attribute<0x0018, 0x9724> TerminationRespiratoryTriggerCountThreshold; typedef gdcm::Attribute<0x0018, 0x9725> DetectorGeometry; typedef gdcm::Attribute<0x0018, 0x9726> TransverseDetectorSeparation; typedef gdcm::Attribute<0x0018, 0x9727> AxialDetectorDimension; typedef gdcm::Attribute<0x0018, 0x9729> RadiopharmaceuticalAgentNumber; typedef gdcm::Attribute<0x0018, 0x9732> PETFrameAcquisitionSequence; typedef gdcm::Attribute<0x0018, 0x9733> PETDetectorMotionDetailsSequence; typedef gdcm::Attribute<0x0018, 0x9734> PETTableDynamicsSequence; typedef gdcm::Attribute<0x0018, 0x9735> PETPositionSequence; typedef gdcm::Attribute<0x0018, 0x9736> PETFrameCorrectionFactorsSequence; typedef gdcm::Attribute<0x0018, 0x9737> RadiopharmaceuticalUsageSequence; typedef gdcm::Attribute<0x0018, 0x9738> AttenuationCorrectionSource; typedef gdcm::Attribute<0x0018, 0x9739> NumberOfIterations; typedef gdcm::Attribute<0x0018, 0x9740> NumberOfSubsets; typedef gdcm::Attribute<0x0018, 0x9749> PETReconstructionSequence; typedef gdcm::Attribute<0x0018, 0x9751> PETFrameTypeSequence; typedef gdcm::Attribute<0x0018, 0x9755> TimeOfFlightInformationUsed; typedef gdcm::Attribute<0x0018, 0x9756> ReconstructionType; typedef gdcm::Attribute<0x0018, 0x9758> DecayCorrected; typedef gdcm::Attribute<0x0018, 0x9759> AttenuationCorrected; typedef gdcm::Attribute<0x0018, 0x9760> ScatterCorrected; typedef gdcm::Attribute<0x0018, 0x9761> DeadTimeCorrected; typedef gdcm::Attribute<0x0018, 0x9762> GantryMotionCorrected; typedef gdcm::Attribute<0x0018, 0x9763> PatientMotionCorrected; typedef gdcm::Attribute<0x0018, 0x9764> CountLossNormalizationCorrected; typedef gdcm::Attribute<0x0018, 0x9765> RandomsCorrected; typedef gdcm::Attribute<0x0018, 0x9766> NonUniformRadialSamplingCorrected; typedef gdcm::Attribute<0x0018, 0x9767> SensitivityCalibrated; typedef gdcm::Attribute<0x0018, 0x9768> DetectorNormalizationCorrection; typedef gdcm::Attribute<0x0018, 0x9769> IterativeReconstructionMethod; typedef gdcm::Attribute<0x0018, 0x9770> AttenuationCorrectionTemporalRelationship; typedef gdcm::Attribute<0x0018, 0x9771> PatientPhysiologicalStateSequence; typedef gdcm::Attribute<0x0018, 0x9772> PatientPhysiologicalStateCodeSequence; typedef gdcm::Attribute<0x0018, 0x9801> DepthsOfFocus; typedef gdcm::Attribute<0x0018, 0x9803> ExcludedIntervalsSequence; typedef gdcm::Attribute<0x0018, 0x9804> ExclusionStartDatetime; typedef gdcm::Attribute<0x0018, 0x9805> ExclusionDuration; typedef gdcm::Attribute<0x0018, 0x9806> USImageDescriptionSequence; typedef gdcm::Attribute<0x0018, 0x9807> ImageDataTypeSequence; typedef gdcm::Attribute<0x0018, 0x9808> DataType; typedef gdcm::Attribute<0x0018, 0x9809> TransducerScanPatternCodeSequence; typedef gdcm::Attribute<0x0018, 0x980b> AliasedDataType; typedef gdcm::Attribute<0x0018, 0x980c> PositionMeasuringDeviceUsed; typedef gdcm::Attribute<0x0018, 0x980d> TransducerGeometryCodeSequence; typedef gdcm::Attribute<0x0018, 0x980e> TransducerBeamSteeringCodeSequence; typedef gdcm::Attribute<0x0018, 0x980f> TransducerApplicationCodeSequence; typedef gdcm::Attribute<0x0018, 0xa001> ContributingEquipmentSequence; typedef gdcm::Attribute<0x0018, 0xa002> ContributionDateTime; typedef gdcm::Attribute<0x0018, 0xa003> ContributionDescription; typedef gdcm::Attribute<0x0020, 0x000d> StudyInstanceUID; typedef gdcm::Attribute<0x0020, 0x000e> SeriesInstanceUID; typedef gdcm::Attribute<0x0020, 0x0010> StudyID; typedef gdcm::Attribute<0x0020, 0x0011> SeriesNumber; typedef gdcm::Attribute<0x0020, 0x0012> AcquisitionNumber; typedef gdcm::Attribute<0x0020, 0x0013> InstanceNumber; typedef gdcm::Attribute<0x0020, 0x0014> IsotopeNumber; typedef gdcm::Attribute<0x0020, 0x0015> PhaseNumber; typedef gdcm::Attribute<0x0020, 0x0016> IntervalNumber; typedef gdcm::Attribute<0x0020, 0x0017> TimeSlotNumber; typedef gdcm::Attribute<0x0020, 0x0018> AngleNumber; typedef gdcm::Attribute<0x0020, 0x0019> ItemNumber; typedef gdcm::Attribute<0x0020, 0x0020> PatientOrientation; typedef gdcm::Attribute<0x0020, 0x0022> OverlayNumber; typedef gdcm::Attribute<0x0020, 0x0024> CurveNumber; typedef gdcm::Attribute<0x0020, 0x0026> LUTNumber; typedef gdcm::Attribute<0x0020, 0x0030> ImagePosition; typedef gdcm::Attribute<0x0020, 0x0032> ImagePositionPatient; typedef gdcm::Attribute<0x0020, 0x0035> ImageOrientation; typedef gdcm::Attribute<0x0020, 0x0037> ImageOrientationPatient; typedef gdcm::Attribute<0x0020, 0x0050> Location; typedef gdcm::Attribute<0x0020, 0x0052> FrameOfReferenceUID; typedef gdcm::Attribute<0x0020, 0x0060> Laterality; typedef gdcm::Attribute<0x0020, 0x0062> ImageLaterality; typedef gdcm::Attribute<0x0020, 0x0070> ImageGeometryType; typedef gdcm::Attribute<0x0020, 0x0080> MaskingImage; typedef gdcm::Attribute<0x0020, 0x00aa> ReportNumber; typedef gdcm::Attribute<0x0020, 0x0100> TemporalPositionIdentifier; typedef gdcm::Attribute<0x0020, 0x0105> NumberOfTemporalPositions; typedef gdcm::Attribute<0x0020, 0x0110> TemporalResolution; typedef gdcm::Attribute<0x0020, 0x0200> SynchronizationFrameOfReferenceUID; typedef gdcm::Attribute<0x0020, 0x0242> SOPInstanceUIDOfConcatenationSource; typedef gdcm::Attribute<0x0020, 0x1000> SeriesInStudy; typedef gdcm::Attribute<0x0020, 0x1001> AcquisitionsInSeries; typedef gdcm::Attribute<0x0020, 0x1002> ImagesInAcquisition; typedef gdcm::Attribute<0x0020, 0x1003> ImagesInSeries; typedef gdcm::Attribute<0x0020, 0x1004> AcquisitionsInStudy; typedef gdcm::Attribute<0x0020, 0x1005> ImagesInStudy; typedef gdcm::Attribute<0x0020, 0x1020> Reference; typedef gdcm::Attribute<0x0020, 0x1040> PositionReferenceIndicator; typedef gdcm::Attribute<0x0020, 0x1041> SliceLocation; typedef gdcm::Attribute<0x0020, 0x1070> OtherStudyNumbers; typedef gdcm::Attribute<0x0020, 0x1200> NumberOfPatientRelatedStudies; typedef gdcm::Attribute<0x0020, 0x1202> NumberOfPatientRelatedSeries; typedef gdcm::Attribute<0x0020, 0x1204> NumberOfPatientRelatedInstances; typedef gdcm::Attribute<0x0020, 0x1206> NumberOfStudyRelatedSeries; typedef gdcm::Attribute<0x0020, 0x1208> NumberOfStudyRelatedInstances; typedef gdcm::Attribute<0x0020, 0x1209> NumberOfSeriesRelatedInstances; typedef gdcm::Attribute<0x0020, 0x3100> SourceImageIDs; typedef gdcm::Attribute<0x0020, 0x3401> ModifyingDeviceID; typedef gdcm::Attribute<0x0020, 0x3402> ModifiedImageID; typedef gdcm::Attribute<0x0020, 0x3403> ModifiedImageDate; typedef gdcm::Attribute<0x0020, 0x3404> ModifyingDeviceManufacturer; typedef gdcm::Attribute<0x0020, 0x3405> ModifiedImageTime; typedef gdcm::Attribute<0x0020, 0x3406> ModifiedImageDescription; typedef gdcm::Attribute<0x0020, 0x4000> ImageComments; typedef gdcm::Attribute<0x0020, 0x5000> OriginalImageIdentification; typedef gdcm::Attribute<0x0020, 0x5002> OriginalImageIdentificationNomenclature; typedef gdcm::Attribute<0x0020, 0x9056> StackID; typedef gdcm::Attribute<0x0020, 0x9057> InStackPositionNumber; typedef gdcm::Attribute<0x0020, 0x9071> FrameAnatomySequence; typedef gdcm::Attribute<0x0020, 0x9072> FrameLaterality; typedef gdcm::Attribute<0x0020, 0x9111> FrameContentSequence; typedef gdcm::Attribute<0x0020, 0x9113> PlanePositionSequence; typedef gdcm::Attribute<0x0020, 0x9116> PlaneOrientationSequence; typedef gdcm::Attribute<0x0020, 0x9128> TemporalPositionIndex; typedef gdcm::Attribute<0x0020, 0x9153> NominalCardiacTriggerDelayTime; typedef gdcm::Attribute<0x0020, 0x9154> NominalCardiacTriggerTimePriorToRPeak; typedef gdcm::Attribute<0x0020, 0x9155> ActualCardiacTriggerTimePriorToRPeak; typedef gdcm::Attribute<0x0020, 0x9156> FrameAcquisitionNumber; typedef gdcm::Attribute<0x0020, 0x9157> DimensionIndexValues; typedef gdcm::Attribute<0x0020, 0x9158> FrameComments; typedef gdcm::Attribute<0x0020, 0x9161> ConcatenationUID; typedef gdcm::Attribute<0x0020, 0x9162> InConcatenationNumber; typedef gdcm::Attribute<0x0020, 0x9163> InConcatenationTotalNumber; typedef gdcm::Attribute<0x0020, 0x9164> DimensionOrganizationUID; typedef gdcm::Attribute<0x0020, 0x9165> DimensionIndexPointer; typedef gdcm::Attribute<0x0020, 0x9167> FunctionalGroupPointer; typedef gdcm::Attribute<0x0020, 0x9213> DimensionIndexPrivateCreator; typedef gdcm::Attribute<0x0020, 0x9221> DimensionOrganizationSequence; typedef gdcm::Attribute<0x0020, 0x9222> DimensionIndexSequence; typedef gdcm::Attribute<0x0020, 0x9228> ConcatenationFrameOffsetNumber; typedef gdcm::Attribute<0x0020, 0x9238> FunctionalGroupPrivateCreator; typedef gdcm::Attribute<0x0020, 0x9241> NominalPercentageOfCardiacPhase; typedef gdcm::Attribute<0x0020, 0x9245> NominalPercentageOfRespiratoryPhase; typedef gdcm::Attribute<0x0020, 0x9246> StartingRespiratoryAmplitude; typedef gdcm::Attribute<0x0020, 0x9247> StartingRespiratoryPhase; typedef gdcm::Attribute<0x0020, 0x9248> EndingRespiratoryAmplitude; typedef gdcm::Attribute<0x0020, 0x9249> EndingRespiratoryPhase; typedef gdcm::Attribute<0x0020, 0x9250> RespiratoryTriggerType; typedef gdcm::Attribute<0x0020, 0x9251> RRIntervalTimeNominal; typedef gdcm::Attribute<0x0020, 0x9252> ActualCardiacTriggerDelayTime; typedef gdcm::Attribute<0x0020, 0x9253> RespiratorySynchronizationSequence; typedef gdcm::Attribute<0x0020, 0x9254> RespiratoryIntervalTime; typedef gdcm::Attribute<0x0020, 0x9255> NominalRespiratoryTriggerDelayTime; typedef gdcm::Attribute<0x0020, 0x9256> RespiratoryTriggerDelayThreshold; typedef gdcm::Attribute<0x0020, 0x9257> ActualRespiratoryTriggerDelayTime; typedef gdcm::Attribute<0x0020, 0x9301> ImagePositionVolume; typedef gdcm::Attribute<0x0020, 0x9302> ImageOrientationVolume; typedef gdcm::Attribute<0x0020, 0x9307> UltrasoundAcquisitionGeometry; typedef gdcm::Attribute<0x0020, 0x9308> ApexPosition; typedef gdcm::Attribute<0x0020, 0x9309> VolumeToTransducerMappingMatrix; typedef gdcm::Attribute<0x0020, 0x930a> VolumeToTableMappingMatrix; typedef gdcm::Attribute<0x0020, 0x930c> PatientFrameOfReferenceSource; typedef gdcm::Attribute<0x0020, 0x930d> TemporalPositionTimeOffset; typedef gdcm::Attribute<0x0020, 0x930e> PlanePositionVolumeSequence; typedef gdcm::Attribute<0x0020, 0x930f> PlaneOrientationVolumeSequence; typedef gdcm::Attribute<0x0020, 0x9310> TemporalPositionSequence; typedef gdcm::Attribute<0x0020, 0x9311> DimensionOrganizationType; typedef gdcm::Attribute<0x0020, 0x9312> VolumeFrameOfReferenceUID; typedef gdcm::Attribute<0x0020, 0x9313> TableFrameOfReferenceUID; typedef gdcm::Attribute<0x0020, 0x9421> DimensionDescriptionLabel; typedef gdcm::Attribute<0x0020, 0x9450> PatientOrientationInFrameSequence; typedef gdcm::Attribute<0x0020, 0x9453> FrameLabel; typedef gdcm::Attribute<0x0020, 0x9518> AcquisitionIndex; typedef gdcm::Attribute<0x0020, 0x9529> ContributingSOPInstancesReferenceSequence; typedef gdcm::Attribute<0x0020, 0x9536> ReconstructionIndex; typedef gdcm::Attribute<0x0022, 0x0001> LightPathFilterPassThroughWavelength; typedef gdcm::Attribute<0x0022, 0x0002> LightPathFilterPassBand; typedef gdcm::Attribute<0x0022, 0x0003> ImagePathFilterPassThroughWavelength; typedef gdcm::Attribute<0x0022, 0x0004> ImagePathFilterPassBand; typedef gdcm::Attribute<0x0022, 0x0005> PatientEyeMovementCommanded; typedef gdcm::Attribute<0x0022, 0x0006> PatientEyeMovementCommandCodeSequence; typedef gdcm::Attribute<0x0022, 0x0007> SphericalLensPower; typedef gdcm::Attribute<0x0022, 0x0008> CylinderLensPower; typedef gdcm::Attribute<0x0022, 0x0009> CylinderAxis; typedef gdcm::Attribute<0x0022, 0x000a> EmmetropicMagnification; typedef gdcm::Attribute<0x0022, 0x000b> IntraOcularPressure; typedef gdcm::Attribute<0x0022, 0x000c> HorizontalFieldOfView; typedef gdcm::Attribute<0x0022, 0x000d> PupilDilated; typedef gdcm::Attribute<0x0022, 0x000e> DegreeOfDilation; typedef gdcm::Attribute<0x0022, 0x0010> StereoBaselineAngle; typedef gdcm::Attribute<0x0022, 0x0011> StereoBaselineDisplacement; typedef gdcm::Attribute<0x0022, 0x0012> StereoHorizontalPixelOffset; typedef gdcm::Attribute<0x0022, 0x0013> StereoVerticalPixelOffset; typedef gdcm::Attribute<0x0022, 0x0014> StereoRotation; typedef gdcm::Attribute<0x0022, 0x0015> AcquisitionDeviceTypeCodeSequence; typedef gdcm::Attribute<0x0022, 0x0016> IlluminationTypeCodeSequence; typedef gdcm::Attribute<0x0022, 0x0017> LightPathFilterTypeStackCodeSequence; typedef gdcm::Attribute<0x0022, 0x0018> ImagePathFilterTypeStackCodeSequence; typedef gdcm::Attribute<0x0022, 0x0019> LensesCodeSequence; typedef gdcm::Attribute<0x0022, 0x001a> ChannelDescriptionCodeSequence; typedef gdcm::Attribute<0x0022, 0x001b> RefractiveStateSequence; typedef gdcm::Attribute<0x0022, 0x001c> MydriaticAgentCodeSequence; typedef gdcm::Attribute<0x0022, 0x001d> RelativeImagePositionCodeSequence; typedef gdcm::Attribute<0x0022, 0x001e> CameraAngleOfView; typedef gdcm::Attribute<0x0022, 0x0020> StereoPairsSequence; typedef gdcm::Attribute<0x0022, 0x0021> LeftImageSequence; typedef gdcm::Attribute<0x0022, 0x0022> RightImageSequence; typedef gdcm::Attribute<0x0022, 0x0030> AxialLengthOfTheEye; typedef gdcm::Attribute<0x0022, 0x0031> OphthalmicFrameLocationSequence; typedef gdcm::Attribute<0x0022, 0x0032> ReferenceCoordinates; typedef gdcm::Attribute<0x0022, 0x0035> DepthSpatialResolution; typedef gdcm::Attribute<0x0022, 0x0036> MaximumDepthDistortion; typedef gdcm::Attribute<0x0022, 0x0037> AlongScanSpatialResolution; typedef gdcm::Attribute<0x0022, 0x0038> MaximumAlongScanDistortion; typedef gdcm::Attribute<0x0022, 0x0039> OphthalmicImageOrientation; typedef gdcm::Attribute<0x0022, 0x0041> DepthOfTransverseImage; typedef gdcm::Attribute<0x0022, 0x0042> MydriaticAgentConcentrationUnitsSequence; typedef gdcm::Attribute<0x0022, 0x0048> AcrossScanSpatialResolution; typedef gdcm::Attribute<0x0022, 0x0049> MaximumAcrossScanDistortion; typedef gdcm::Attribute<0x0022, 0x004e> MydriaticAgentConcentration; typedef gdcm::Attribute<0x0022, 0x0055> IlluminationWaveLength; typedef gdcm::Attribute<0x0022, 0x0056> IlluminationPower; typedef gdcm::Attribute<0x0022, 0x0057> IlluminationBandwidth; typedef gdcm::Attribute<0x0022, 0x0058> MydriaticAgentSequence; typedef gdcm::Attribute<0x0022, 0x1007> OphthalmicAxialMeasurementsRightEyeSequence; typedef gdcm::Attribute<0x0022, 0x1008> OphthalmicAxialMeasurementsLeftEyeSequence; typedef gdcm::Attribute<0x0022, 0x1009> OphthalmicAxialMeasurementsDeviceType; typedef gdcm::Attribute<0x0022, 0x1010> OphthalmicAxialLengthMeasurementsType; typedef gdcm::Attribute<0x0022, 0x1012> OphthalmicAxialLengthSequence; typedef gdcm::Attribute<0x0022, 0x1019> OphthalmicAxialLength; typedef gdcm::Attribute<0x0022, 0x1024> LensStatusCodeSequence; typedef gdcm::Attribute<0x0022, 0x1025> VitreousStatusCodeSequence; typedef gdcm::Attribute<0x0022, 0x1028> IOLFormulaCodeSequence; typedef gdcm::Attribute<0x0022, 0x1029> IOLFormulaDetail; typedef gdcm::Attribute<0x0022, 0x1033> KeratometerIndex; typedef gdcm::Attribute<0x0022, 0x1035> SourceOfOphthalmicAxialLengthCodeSequence; typedef gdcm::Attribute<0x0022, 0x1037> TargetRefraction; typedef gdcm::Attribute<0x0022, 0x1039> RefractiveProcedureOccurred; typedef gdcm::Attribute<0x0022, 0x1040> RefractiveSurgeryTypeCodeSequence; typedef gdcm::Attribute<0x0022, 0x1044> OphthalmicUltrasoundMethodCodeSequence; typedef gdcm::Attribute<0x0022, 0x1050> OphthalmicAxialLengthMeasurementsSequence; typedef gdcm::Attribute<0x0022, 0x1053> IOLPower; typedef gdcm::Attribute<0x0022, 0x1054> PredictedRefractiveError; typedef gdcm::Attribute<0x0022, 0x1059> OphthalmicAxialLengthVelocity; typedef gdcm::Attribute<0x0022, 0x1065> LensStatusDescription; typedef gdcm::Attribute<0x0022, 0x1066> VitreousStatusDescription; typedef gdcm::Attribute<0x0022, 0x1090> IOLPowerSequence; typedef gdcm::Attribute<0x0022, 0x1092> LensConstantSequence; typedef gdcm::Attribute<0x0022, 0x1093> IOLManufacturer; typedef gdcm::Attribute<0x0022, 0x1094> LensConstantDescription; typedef gdcm::Attribute<0x0022, 0x1095> ImplantName; typedef gdcm::Attribute<0x0022, 0x1096> KeratometryMeasurementTypeCodeSequence; typedef gdcm::Attribute<0x0022, 0x1097> ImplantPartNumber; typedef gdcm::Attribute<0x0022, 0x1100> ReferencedOphthalmicAxialMeasurementsSequence; typedef gdcm::Attribute<0x0022, 0x1101> OphthalmicAxialLengthMeasurementsSegmentNameCodeSequence; typedef gdcm::Attribute<0x0022, 0x1103> RefractiveErrorBeforeRefractiveSurgeryCodeSequence; typedef gdcm::Attribute<0x0022, 0x1121> IOLPowerForExactEmmetropia; typedef gdcm::Attribute<0x0022, 0x1122> IOLPowerForExactTargetRefraction; typedef gdcm::Attribute<0x0022, 0x1125> AnteriorChamberDepthDefinitionCodeSequence; typedef gdcm::Attribute<0x0022, 0x1127> LensThicknessSequence; typedef gdcm::Attribute<0x0022, 0x1128> AnteriorChamberDepthSequence; typedef gdcm::Attribute<0x0022, 0x1130> LensThickness; typedef gdcm::Attribute<0x0022, 0x1131> AnteriorChamberDepth; typedef gdcm::Attribute<0x0022, 0x1132> SourceOfLensThicknessDataCodeSequence; typedef gdcm::Attribute<0x0022, 0x1133> SourceOfAnteriorChamberDepthDataCodeSequence; typedef gdcm::Attribute<0x0022, 0x1134> SourceOfRefractiveMeasurementsSequence; typedef gdcm::Attribute<0x0022, 0x1135> SourceOfRefractiveMeasurementsCodeSequence; typedef gdcm::Attribute<0x0022, 0x1140> OphthalmicAxialLengthMeasurementModified; typedef gdcm::Attribute<0x0022, 0x1150> OphthalmicAxialLengthDataSourceCodeSequence; typedef gdcm::Attribute<0x0022, 0x1153> OphthalmicAxialLengthAcquisitionMethodCodeSequence; typedef gdcm::Attribute<0x0022, 0x1155> SignalToNoiseRatio; typedef gdcm::Attribute<0x0022, 0x1159> OphthalmicAxialLengthDataSourceDescription; typedef gdcm::Attribute<0x0022, 0x1210> OphthalmicAxialLengthMeasurementsTotalLengthSequence; typedef gdcm::Attribute<0x0022, 0x1211> OphthalmicAxialLengthMeasurementsSegmentalLengthSequence; typedef gdcm::Attribute<0x0022, 0x1212> OphthalmicAxialLengthMeasurementsLengthSummationSequence; typedef gdcm::Attribute<0x0022, 0x1220> UltrasoundOphthalmicAxialLengthMeasurementsSequence; typedef gdcm::Attribute<0x0022, 0x1225> OpticalOphthalmicAxialLengthMeasurementsSequence; typedef gdcm::Attribute<0x0022, 0x1230> UltrasoundSelectedOphthalmicAxialLengthSequence; typedef gdcm::Attribute<0x0022, 0x1250> OphthalmicAxialLengthSelectionMethodCodeSequence; typedef gdcm::Attribute<0x0022, 0x1255> OpticalSelectedOphthalmicAxialLengthSequence; typedef gdcm::Attribute<0x0022, 0x1257> SelectedSegmentalOphthalmicAxialLengthSequence; typedef gdcm::Attribute<0x0022, 0x1260> SelectedTotalOphthalmicAxialLengthSequence; typedef gdcm::Attribute<0x0022, 0x1262> OphthalmicAxialLengthQualityMetricSequence; typedef gdcm::Attribute<0x0022, 0x1273> OphthalmicAxialLengthQualityMetricTypeDescription; typedef gdcm::Attribute<0x0022, 0x1300> IntraocularLensCalculationsRightEyeSequence; typedef gdcm::Attribute<0x0022, 0x1310> IntraocularLensCalculationsLeftEyeSequence; typedef gdcm::Attribute<0x0022, 0x1330> ReferencedOphthalmicAxialLengthMeasurementQCImageSequence; typedef gdcm::Attribute<0x0024, 0x0010> VisualFieldHorizontalExtent; typedef gdcm::Attribute<0x0024, 0x0011> VisualFieldVerticalExtent; typedef gdcm::Attribute<0x0024, 0x0012> VisualFieldShape; typedef gdcm::Attribute<0x0024, 0x0016> ScreeningTestModeCodeSequence; typedef gdcm::Attribute<0x0024, 0x0018> MaximumStimulusLuminance; typedef gdcm::Attribute<0x0024, 0x0020> BackgroundLuminance; typedef gdcm::Attribute<0x0024, 0x0021> StimulusColorCodeSequence; typedef gdcm::Attribute<0x0024, 0x0024> BackgroundIlluminationColorCodeSequence; typedef gdcm::Attribute<0x0024, 0x0025> StimulusArea; typedef gdcm::Attribute<0x0024, 0x0028> StimulusPresentationTime; typedef gdcm::Attribute<0x0024, 0x0032> FixationSequence; typedef gdcm::Attribute<0x0024, 0x0033> FixationMonitoringCodeSequence; typedef gdcm::Attribute<0x0024, 0x0034> VisualFieldCatchTrialSequence; typedef gdcm::Attribute<0x0024, 0x0035> FixationCheckedQuantity; typedef gdcm::Attribute<0x0024, 0x0036> PatientNotProperlyFixatedQuantity; typedef gdcm::Attribute<0x0024, 0x0037> PresentedVisualStimuliDataFlag; typedef gdcm::Attribute<0x0024, 0x0038> NumberOfVisualStimuli; typedef gdcm::Attribute<0x0024, 0x0039> ExcessiveFixationLossesDataFlag; typedef gdcm::Attribute<0x0024, 0x0040> ExcessiveFixationLosses; typedef gdcm::Attribute<0x0024, 0x0042> StimuliRetestingQuantity; typedef gdcm::Attribute<0x0024, 0x0044> CommentsOnPatientPerformanceOfVisualField; typedef gdcm::Attribute<0x0024, 0x0045> FalseNegativesEstimateFlag; typedef gdcm::Attribute<0x0024, 0x0046> FalseNegativesEstimate; typedef gdcm::Attribute<0x0024, 0x0048> NegativeCatchTrialsQuantity; typedef gdcm::Attribute<0x0024, 0x0050> FalseNegativesQuantity; typedef gdcm::Attribute<0x0024, 0x0051> ExcessiveFalseNegativesDataFlag; typedef gdcm::Attribute<0x0024, 0x0052> ExcessiveFalseNegatives; typedef gdcm::Attribute<0x0024, 0x0053> FalsePositivesEstimateFlag; typedef gdcm::Attribute<0x0024, 0x0054> FalsePositivesEstimate; typedef gdcm::Attribute<0x0024, 0x0055> CatchTrialsDataFlag; typedef gdcm::Attribute<0x0024, 0x0056> PositiveCatchTrialsQuantity; typedef gdcm::Attribute<0x0024, 0x0057> TestPointNormalsDataFlag; typedef gdcm::Attribute<0x0024, 0x0058> TestPointNormalsSequence; typedef gdcm::Attribute<0x0024, 0x0059> GlobalDeviationProbabilityNormalsFlag; typedef gdcm::Attribute<0x0024, 0x0060> FalsePositivesQuantity; typedef gdcm::Attribute<0x0024, 0x0061> ExcessiveFalsePositivesDataFlag; typedef gdcm::Attribute<0x0024, 0x0062> ExcessiveFalsePositives; typedef gdcm::Attribute<0x0024, 0x0063> VisualFieldTestNormalsFlag; typedef gdcm::Attribute<0x0024, 0x0064> ResultsNormalsSequence; typedef gdcm::Attribute<0x0024, 0x0065> AgeCorrectedSensitivityDeviationAlgorithmSequence; typedef gdcm::Attribute<0x0024, 0x0066> GlobalDeviationFromNormal; typedef gdcm::Attribute<0x0024, 0x0067> GeneralizedDefectSensitivityDeviationAlgorithmSequence; typedef gdcm::Attribute<0x0024, 0x0068> LocalizedDeviationfromNormal; typedef gdcm::Attribute<0x0024, 0x0069> PatientReliabilityIndicator; typedef gdcm::Attribute<0x0024, 0x0070> VisualFieldMeanSensitivity; typedef gdcm::Attribute<0x0024, 0x0071> GlobalDeviationProbability; typedef gdcm::Attribute<0x0024, 0x0072> LocalDeviationProbabilityNormalsFlag; typedef gdcm::Attribute<0x0024, 0x0073> LocalizedDeviationProbability; typedef gdcm::Attribute<0x0024, 0x0074> ShortTermFluctuationCalculated; typedef gdcm::Attribute<0x0024, 0x0075> ShortTermFluctuation; typedef gdcm::Attribute<0x0024, 0x0076> ShortTermFluctuationProbabilityCalculated; typedef gdcm::Attribute<0x0024, 0x0077> ShortTermFluctuationProbability; typedef gdcm::Attribute<0x0024, 0x0078> CorrectedLocalizedDeviationFromNormalCalculated; typedef gdcm::Attribute<0x0024, 0x0079> CorrectedLocalizedDeviationFromNormal; typedef gdcm::Attribute<0x0024, 0x0080> CorrectedLocalizedDeviationFromNormalProbabilityCalculated; typedef gdcm::Attribute<0x0024, 0x0081> CorrectedLocalizedDeviationFromNormalProbability; typedef gdcm::Attribute<0x0024, 0x0083> GlobalDeviationProbabilitySequence; typedef gdcm::Attribute<0x0024, 0x0085> LocalizedDeviationProbabilitySequence; typedef gdcm::Attribute<0x0024, 0x0086> FovealSensitivityMeasured; typedef gdcm::Attribute<0x0024, 0x0087> FovealSensitivity; typedef gdcm::Attribute<0x0024, 0x0088> VisualFieldTestDuration; typedef gdcm::Attribute<0x0024, 0x0089> VisualFieldTestPointSequence; typedef gdcm::Attribute<0x0024, 0x0090> VisualFieldTestPointXCoordinate; typedef gdcm::Attribute<0x0024, 0x0091> VisualFieldTestPointYCoordinate; typedef gdcm::Attribute<0x0024, 0x0092> AgeCorrectedSensitivityDeviationValue; typedef gdcm::Attribute<0x0024, 0x0093> StimulusResults; typedef gdcm::Attribute<0x0024, 0x0094> SensitivityValue; typedef gdcm::Attribute<0x0024, 0x0095> RetestStimulusSeen; typedef gdcm::Attribute<0x0024, 0x0096> RetestSensitivityValue; typedef gdcm::Attribute<0x0024, 0x0097> VisualFieldTestPointNormalsSequence; typedef gdcm::Attribute<0x0024, 0x0098> QuantifiedDefect; typedef gdcm::Attribute<0x0024, 0x0100> AgeCorrectedSensitivityDeviationProbabilityValue; typedef gdcm::Attribute<0x0024, 0x0102> GeneralizedDefectCorrectedSensitivityDeviationFlag; typedef gdcm::Attribute<0x0024, 0x0103> GeneralizedDefectCorrectedSensitivityDeviationValue; typedef gdcm::Attribute<0x0024, 0x0104> GeneralizedDefectCorrectedSensitivityDeviationProbabilityValue; typedef gdcm::Attribute<0x0024, 0x0105> MinimumSensitivityValue; typedef gdcm::Attribute<0x0024, 0x0106> BlindSpotLocalized; typedef gdcm::Attribute<0x0024, 0x0107> BlindSpotXCoordinate; typedef gdcm::Attribute<0x0024, 0x0108> BlindSpotYCoordinate; typedef gdcm::Attribute<0x0024, 0x0110> VisualAcuityMeasurementSequence; typedef gdcm::Attribute<0x0024, 0x0112> RefractiveParametersUsedOnPatientSequence; typedef gdcm::Attribute<0x0024, 0x0113> MeasurementLaterality; typedef gdcm::Attribute<0x0024, 0x0114> OphthalmicPatientClinicalInformationLeftEyeSequence; typedef gdcm::Attribute<0x0024, 0x0115> OphthalmicPatientClinicalInformationRightEyeSequence; typedef gdcm::Attribute<0x0024, 0x0117> FovealPointNormativeDataFlag; typedef gdcm::Attribute<0x0024, 0x0118> FovealPointProbabilityValue; typedef gdcm::Attribute<0x0024, 0x0120> ScreeningBaselineMeasured; typedef gdcm::Attribute<0x0024, 0x0122> ScreeningBaselineMeasuredSequence; typedef gdcm::Attribute<0x0024, 0x0124> ScreeningBaselineType; typedef gdcm::Attribute<0x0024, 0x0126> ScreeningBaselineValue; typedef gdcm::Attribute<0x0024, 0x0202> AlgorithmSource; typedef gdcm::Attribute<0x0024, 0x0306> DataSetName; typedef gdcm::Attribute<0x0024, 0x0307> DataSetVersion; typedef gdcm::Attribute<0x0024, 0x0308> DataSetSource; typedef gdcm::Attribute<0x0024, 0x0309> DataSetDescription; typedef gdcm::Attribute<0x0024, 0x0317> VisualFieldTestReliabilityGlobalIndexSequence; typedef gdcm::Attribute<0x0024, 0x0320> VisualFieldGlobalResultsIndexSequence; typedef gdcm::Attribute<0x0024, 0x0325> DataObservationSequence; typedef gdcm::Attribute<0x0024, 0x0338> IndexNormalsFlag; typedef gdcm::Attribute<0x0024, 0x0341> IndexProbability; typedef gdcm::Attribute<0x0024, 0x0344> IndexProbabilitySequence; typedef gdcm::Attribute<0x0028, 0x0002> SamplesPerPixel; typedef gdcm::Attribute<0x0028, 0x0003> SamplesPerPixelUsed; typedef gdcm::Attribute<0x0028, 0x0004> PhotometricInterpretation; typedef gdcm::Attribute<0x0028, 0x0005> ImageDimensions; typedef gdcm::Attribute<0x0028, 0x0006> PlanarConfiguration; typedef gdcm::Attribute<0x0028, 0x0008> NumberOfFrames; typedef gdcm::Attribute<0x0028, 0x0009> FrameIncrementPointer; typedef gdcm::Attribute<0x0028, 0x000a> FrameDimensionPointer; typedef gdcm::Attribute<0x0028, 0x0010> Rows; typedef gdcm::Attribute<0x0028, 0x0011> Columns; typedef gdcm::Attribute<0x0028, 0x0012> Planes; typedef gdcm::Attribute<0x0028, 0x0014> UltrasoundColorDataPresent; // 0x0028, 0x0020 SHALL NOT BE USED typedef gdcm::Attribute<0x0028, 0x0030> PixelSpacing; typedef gdcm::Attribute<0x0028, 0x0031> ZoomFactor; typedef gdcm::Attribute<0x0028, 0x0032> ZoomCenter; typedef gdcm::Attribute<0x0028, 0x0034> PixelAspectRatio; typedef gdcm::Attribute<0x0028, 0x0040> ImageFormat; typedef gdcm::Attribute<0x0028, 0x0050> ManipulatedImage; typedef gdcm::Attribute<0x0028, 0x0051> CorrectedImage; typedef gdcm::Attribute<0x0028, 0x005f> CompressionRecognitionCode; typedef gdcm::Attribute<0x0028, 0x0060> CompressionCode; typedef gdcm::Attribute<0x0028, 0x0061> CompressionOriginator; typedef gdcm::Attribute<0x0028, 0x0062> CompressionLabel; typedef gdcm::Attribute<0x0028, 0x0063> CompressionDescription; typedef gdcm::Attribute<0x0028, 0x0065> CompressionSequence; typedef gdcm::Attribute<0x0028, 0x0066> CompressionStepPointers; typedef gdcm::Attribute<0x0028, 0x0068> RepeatInterval; typedef gdcm::Attribute<0x0028, 0x0069> BitsGrouped; typedef gdcm::Attribute<0x0028, 0x0070> PerimeterTable; typedef gdcm::Attribute<0x0028, 0x0071> PerimeterValue; typedef gdcm::Attribute<0x0028, 0x0080> PredictorRows; typedef gdcm::Attribute<0x0028, 0x0081> PredictorColumns; typedef gdcm::Attribute<0x0028, 0x0082> PredictorConstants; typedef gdcm::Attribute<0x0028, 0x0090> BlockedPixels; typedef gdcm::Attribute<0x0028, 0x0091> BlockRows; typedef gdcm::Attribute<0x0028, 0x0092> BlockColumns; typedef gdcm::Attribute<0x0028, 0x0093> RowOverlap; typedef gdcm::Attribute<0x0028, 0x0094> ColumnOverlap; typedef gdcm::Attribute<0x0028, 0x0100> BitsAllocated; typedef gdcm::Attribute<0x0028, 0x0101> BitsStored; typedef gdcm::Attribute<0x0028, 0x0102> HighBit; typedef gdcm::Attribute<0x0028, 0x0103> PixelRepresentation; typedef gdcm::Attribute<0x0028, 0x0104> SmallestValidPixelValue; typedef gdcm::Attribute<0x0028, 0x0105> LargestValidPixelValue; typedef gdcm::Attribute<0x0028, 0x0106> SmallestImagePixelValue; typedef gdcm::Attribute<0x0028, 0x0107> LargestImagePixelValue; typedef gdcm::Attribute<0x0028, 0x0108> SmallestPixelValueInSeries; typedef gdcm::Attribute<0x0028, 0x0109> LargestPixelValueInSeries; typedef gdcm::Attribute<0x0028, 0x0110> SmallestImagePixelValueInPlane; typedef gdcm::Attribute<0x0028, 0x0111> LargestImagePixelValueInPlane; typedef gdcm::Attribute<0x0028, 0x0120> PixelPaddingValue; typedef gdcm::Attribute<0x0028, 0x0121> PixelPaddingRangeLimit; typedef gdcm::Attribute<0x0028, 0x0200> ImageLocation; typedef gdcm::Attribute<0x0028, 0x0300> QualityControlImage; typedef gdcm::Attribute<0x0028, 0x0301> BurnedInAnnotation; typedef gdcm::Attribute<0x0028, 0x0302> RecognizableVisualFeatures; typedef gdcm::Attribute<0x0028, 0x0303> LongitudinalTemporalInformationModified; typedef gdcm::Attribute<0x0028, 0x0304> ReferencedColorPaletteInstanceUID; typedef gdcm::Attribute<0x0028, 0x0400> TransformLabel; typedef gdcm::Attribute<0x0028, 0x0401> TransformVersionNumber; typedef gdcm::Attribute<0x0028, 0x0402> NumberOfTransformSteps; typedef gdcm::Attribute<0x0028, 0x0403> SequenceOfCompressedData; typedef gdcm::Attribute<0x0028, 0x0404> DetailsOfCoefficients; typedef gdcm::Attribute<0x0028, 0x0400> RowsForNthOrderCoefficients; typedef gdcm::Attribute<0x0028, 0x0401> ColumnsForNthOrderCoefficients; typedef gdcm::Attribute<0x0028, 0x0402> CoefficientCoding; typedef gdcm::Attribute<0x0028, 0x0403> CoefficientCodingPointers; typedef gdcm::Attribute<0x0028, 0x0700> DCTLabel; typedef gdcm::Attribute<0x0028, 0x0701> DataBlockDescription; typedef gdcm::Attribute<0x0028, 0x0702> DataBlock; typedef gdcm::Attribute<0x0028, 0x0710> NormalizationFactorFormat; typedef gdcm::Attribute<0x0028, 0x0720> ZonalMapNumberFormat; typedef gdcm::Attribute<0x0028, 0x0721> ZonalMapLocation; typedef gdcm::Attribute<0x0028, 0x0722> ZonalMapFormat; typedef gdcm::Attribute<0x0028, 0x0730> AdaptiveMapFormat; typedef gdcm::Attribute<0x0028, 0x0740> CodeNumberFormat; typedef gdcm::Attribute<0x0028, 0x0800> CodeLabel; typedef gdcm::Attribute<0x0028, 0x0802> NumberOfTables; typedef gdcm::Attribute<0x0028, 0x0803> CodeTableLocation; typedef gdcm::Attribute<0x0028, 0x0804> BitsForCodeWord; typedef gdcm::Attribute<0x0028, 0x0808> ImageDataLocation; typedef gdcm::Attribute<0x0028, 0x0a02> PixelSpacingCalibrationType; typedef gdcm::Attribute<0x0028, 0x0a04> PixelSpacingCalibrationDescription; typedef gdcm::Attribute<0x0028, 0x1040> PixelIntensityRelationship; typedef gdcm::Attribute<0x0028, 0x1041> PixelIntensityRelationshipSign; typedef gdcm::Attribute<0x0028, 0x1050> WindowCenter; typedef gdcm::Attribute<0x0028, 0x1051> WindowWidth; typedef gdcm::Attribute<0x0028, 0x1052> RescaleIntercept; typedef gdcm::Attribute<0x0028, 0x1053> RescaleSlope; typedef gdcm::Attribute<0x0028, 0x1054> RescaleType; typedef gdcm::Attribute<0x0028, 0x1055> WindowCenterWidthExplanation; typedef gdcm::Attribute<0x0028, 0x1056> VOILUTFunction; typedef gdcm::Attribute<0x0028, 0x1080> GrayScale; typedef gdcm::Attribute<0x0028, 0x1090> RecommendedViewingMode; typedef gdcm::Attribute<0x0028, 0x1100> GrayLookupTableDescriptor; typedef gdcm::Attribute<0x0028, 0x1101> RedPaletteColorLookupTableDescriptor; typedef gdcm::Attribute<0x0028, 0x1102> GreenPaletteColorLookupTableDescriptor; typedef gdcm::Attribute<0x0028, 0x1103> BluePaletteColorLookupTableDescriptor; typedef gdcm::Attribute<0x0028, 0x1104> AlphaPaletteColorLookupTableDescriptor; typedef gdcm::Attribute<0x0028, 0x1111> LargeRedPaletteColorLookupTableDescriptor; typedef gdcm::Attribute<0x0028, 0x1112> LargeGreenPaletteColorLookupTableDescriptor; typedef gdcm::Attribute<0x0028, 0x1113> LargeBluePaletteColorLookupTableDescriptor; typedef gdcm::Attribute<0x0028, 0x1199> PaletteColorLookupTableUID; typedef gdcm::Attribute<0x0028, 0x1200> GrayLookupTableData; typedef gdcm::Attribute<0x0028, 0x1201> RedPaletteColorLookupTableData; typedef gdcm::Attribute<0x0028, 0x1202> GreenPaletteColorLookupTableData; typedef gdcm::Attribute<0x0028, 0x1203> BluePaletteColorLookupTableData; typedef gdcm::Attribute<0x0028, 0x1204> AlphaPaletteColorLookupTableData; typedef gdcm::Attribute<0x0028, 0x1211> LargeRedPaletteColorLookupTableData; typedef gdcm::Attribute<0x0028, 0x1212> LargeGreenPaletteColorLookupTableData; typedef gdcm::Attribute<0x0028, 0x1213> LargeBluePaletteColorLookupTableData; typedef gdcm::Attribute<0x0028, 0x1214> LargePaletteColorLookupTableUID; typedef gdcm::Attribute<0x0028, 0x1221> SegmentedRedPaletteColorLookupTableData; typedef gdcm::Attribute<0x0028, 0x1222> SegmentedGreenPaletteColorLookupTableData; typedef gdcm::Attribute<0x0028, 0x1223> SegmentedBluePaletteColorLookupTableData; typedef gdcm::Attribute<0x0028, 0x1300> BreastImplantPresent; typedef gdcm::Attribute<0x0028, 0x1350> PartialView; typedef gdcm::Attribute<0x0028, 0x1351> PartialViewDescription; typedef gdcm::Attribute<0x0028, 0x1352> PartialViewCodeSequence; typedef gdcm::Attribute<0x0028, 0x135a> SpatialLocationsPreserved; typedef gdcm::Attribute<0x0028, 0x1401> DataFrameAssignmentSequence; typedef gdcm::Attribute<0x0028, 0x1402> DataPathAssignment; typedef gdcm::Attribute<0x0028, 0x1403> BitsMappedToColorLookupTable; typedef gdcm::Attribute<0x0028, 0x1404> BlendingLUT1Sequence; typedef gdcm::Attribute<0x0028, 0x1405> BlendingLUT1TransferFunction; typedef gdcm::Attribute<0x0028, 0x1406> BlendingWeightConstant; typedef gdcm::Attribute<0x0028, 0x1407> BlendingLookupTableDescriptor; typedef gdcm::Attribute<0x0028, 0x1408> BlendingLookupTableData; typedef gdcm::Attribute<0x0028, 0x140b> EnhancedPaletteColorLookupTableSequence; typedef gdcm::Attribute<0x0028, 0x140c> BlendingLUT2Sequence; typedef gdcm::Attribute<0x0028, 0x140d> BlendingLUT2TransferFunction; typedef gdcm::Attribute<0x0028, 0x140e> DataPathID; typedef gdcm::Attribute<0x0028, 0x140f> RGBLUTTransferFunction; typedef gdcm::Attribute<0x0028, 0x1410> AlphaLUTTransferFunction; typedef gdcm::Attribute<0x0028, 0x2000> ICCProfile; typedef gdcm::Attribute<0x0028, 0x2110> LossyImageCompression; typedef gdcm::Attribute<0x0028, 0x2112> LossyImageCompressionRatio; typedef gdcm::Attribute<0x0028, 0x2114> LossyImageCompressionMethod; typedef gdcm::Attribute<0x0028, 0x3000> ModalityLUTSequence; typedef gdcm::Attribute<0x0028, 0x3002> LUTDescriptor; typedef gdcm::Attribute<0x0028, 0x3003> LUTExplanation; typedef gdcm::Attribute<0x0028, 0x3004> ModalityLUTType; typedef gdcm::Attribute<0x0028, 0x3006> LUTData; typedef gdcm::Attribute<0x0028, 0x3010> VOILUTSequence; typedef gdcm::Attribute<0x0028, 0x3110> SoftcopyVOILUTSequence; typedef gdcm::Attribute<0x0028, 0x4000> ImagePresentationComments; typedef gdcm::Attribute<0x0028, 0x5000> BiPlaneAcquisitionSequence; typedef gdcm::Attribute<0x0028, 0x6010> RepresentativeFrameNumber; typedef gdcm::Attribute<0x0028, 0x6020> FrameNumbersOfInterest; typedef gdcm::Attribute<0x0028, 0x6022> FrameOfInterestDescription; typedef gdcm::Attribute<0x0028, 0x6023> FrameOfInterestType; typedef gdcm::Attribute<0x0028, 0x6030> MaskPointers; typedef gdcm::Attribute<0x0028, 0x6040> RWavePointer; typedef gdcm::Attribute<0x0028, 0x6100> MaskSubtractionSequence; typedef gdcm::Attribute<0x0028, 0x6101> MaskOperation; typedef gdcm::Attribute<0x0028, 0x6102> ApplicableFrameRange; typedef gdcm::Attribute<0x0028, 0x6110> MaskFrameNumbers; typedef gdcm::Attribute<0x0028, 0x6112> ContrastFrameAveraging; typedef gdcm::Attribute<0x0028, 0x6114> MaskSubPixelShift; typedef gdcm::Attribute<0x0028, 0x6120> TIDOffset; typedef gdcm::Attribute<0x0028, 0x6190> MaskOperationExplanation; typedef gdcm::Attribute<0x0028, 0x7fe0> PixelDataProviderURL; typedef gdcm::Attribute<0x0028, 0x9001> DataPointRows; typedef gdcm::Attribute<0x0028, 0x9002> DataPointColumns; typedef gdcm::Attribute<0x0028, 0x9003> SignalDomainColumns; typedef gdcm::Attribute<0x0028, 0x9099> LargestMonochromePixelValue; typedef gdcm::Attribute<0x0028, 0x9108> DataRepresentation; typedef gdcm::Attribute<0x0028, 0x9110> PixelMeasuresSequence; typedef gdcm::Attribute<0x0028, 0x9132> FrameVOILUTSequence; typedef gdcm::Attribute<0x0028, 0x9145> PixelValueTransformationSequence; typedef gdcm::Attribute<0x0028, 0x9235> SignalDomainRows; typedef gdcm::Attribute<0x0028, 0x9411> DisplayFilterPercentage; typedef gdcm::Attribute<0x0028, 0x9415> FramePixelShiftSequence; typedef gdcm::Attribute<0x0028, 0x9416> SubtractionItemID; typedef gdcm::Attribute<0x0028, 0x9422> PixelIntensityRelationshipLUTSequence; typedef gdcm::Attribute<0x0028, 0x9443> FramePixelDataPropertiesSequence; typedef gdcm::Attribute<0x0028, 0x9444> GeometricalProperties; typedef gdcm::Attribute<0x0028, 0x9445> GeometricMaximumDistortion; typedef gdcm::Attribute<0x0028, 0x9446> ImageProcessingApplied; typedef gdcm::Attribute<0x0028, 0x9454> MaskSelectionMode; typedef gdcm::Attribute<0x0028, 0x9474> LUTFunction; typedef gdcm::Attribute<0x0028, 0x9478> MaskVisibilityPercentage; typedef gdcm::Attribute<0x0028, 0x9501> PixelShiftSequence; typedef gdcm::Attribute<0x0028, 0x9502> RegionPixelShiftSequence; typedef gdcm::Attribute<0x0028, 0x9503> VerticesOfTheRegion; typedef gdcm::Attribute<0x0028, 0x9505> MultiFramePresentationSequence; typedef gdcm::Attribute<0x0028, 0x9506> PixelShiftFrameRange; typedef gdcm::Attribute<0x0028, 0x9507> LUTFrameRange; typedef gdcm::Attribute<0x0028, 0x9520> ImageToEquipmentMappingMatrix; typedef gdcm::Attribute<0x0028, 0x9537> EquipmentCoordinateSystemIdentification; typedef gdcm::Attribute<0x0032, 0x000a> StudyStatusID; typedef gdcm::Attribute<0x0032, 0x000c> StudyPriorityID; typedef gdcm::Attribute<0x0032, 0x0012> StudyIDIssuer; typedef gdcm::Attribute<0x0032, 0x0032> StudyVerifiedDate; typedef gdcm::Attribute<0x0032, 0x0033> StudyVerifiedTime; typedef gdcm::Attribute<0x0032, 0x0034> StudyReadDate; typedef gdcm::Attribute<0x0032, 0x0035> StudyReadTime; typedef gdcm::Attribute<0x0032, 0x1000> ScheduledStudyStartDate; typedef gdcm::Attribute<0x0032, 0x1001> ScheduledStudyStartTime; typedef gdcm::Attribute<0x0032, 0x1010> ScheduledStudyStopDate; typedef gdcm::Attribute<0x0032, 0x1011> ScheduledStudyStopTime; typedef gdcm::Attribute<0x0032, 0x1020> ScheduledStudyLocation; typedef gdcm::Attribute<0x0032, 0x1021> ScheduledStudyLocationAETitle; typedef gdcm::Attribute<0x0032, 0x1030> ReasonForStudy; typedef gdcm::Attribute<0x0032, 0x1031> RequestingPhysicianIdentificationSequence; typedef gdcm::Attribute<0x0032, 0x1032> RequestingPhysician; typedef gdcm::Attribute<0x0032, 0x1033> RequestingService; typedef gdcm::Attribute<0x0032, 0x1034> RequestingServiceCodeSequence; typedef gdcm::Attribute<0x0032, 0x1040> StudyArrivalDate; typedef gdcm::Attribute<0x0032, 0x1041> StudyArrivalTime; typedef gdcm::Attribute<0x0032, 0x1050> StudyCompletionDate; typedef gdcm::Attribute<0x0032, 0x1051> StudyCompletionTime; typedef gdcm::Attribute<0x0032, 0x1055> StudyComponentStatusID; typedef gdcm::Attribute<0x0032, 0x1060> RequestedProcedureDescription; typedef gdcm::Attribute<0x0032, 0x1064> RequestedProcedureCodeSequence; typedef gdcm::Attribute<0x0032, 0x1070> RequestedContrastAgent; typedef gdcm::Attribute<0x0032, 0x4000> StudyComments; typedef gdcm::Attribute<0x0038, 0x0004> ReferencedPatientAliasSequence; typedef gdcm::Attribute<0x0038, 0x0008> VisitStatusID; typedef gdcm::Attribute<0x0038, 0x0010> AdmissionID; typedef gdcm::Attribute<0x0038, 0x0011> IssuerOfAdmissionID; typedef gdcm::Attribute<0x0038, 0x0014> IssuerOfAdmissionIDSequence; typedef gdcm::Attribute<0x0038, 0x0016> RouteOfAdmissions; typedef gdcm::Attribute<0x0038, 0x001a> ScheduledAdmissionDate; typedef gdcm::Attribute<0x0038, 0x001b> ScheduledAdmissionTime; typedef gdcm::Attribute<0x0038, 0x001c> ScheduledDischargeDate; typedef gdcm::Attribute<0x0038, 0x001d> ScheduledDischargeTime; typedef gdcm::Attribute<0x0038, 0x001e> ScheduledPatientInstitutionResidence; typedef gdcm::Attribute<0x0038, 0x0020> AdmittingDate; typedef gdcm::Attribute<0x0038, 0x0021> AdmittingTime; typedef gdcm::Attribute<0x0038, 0x0030> DischargeDate; typedef gdcm::Attribute<0x0038, 0x0032> DischargeTime; typedef gdcm::Attribute<0x0038, 0x0040> DischargeDiagnosisDescription; typedef gdcm::Attribute<0x0038, 0x0044> DischargeDiagnosisCodeSequence; typedef gdcm::Attribute<0x0038, 0x0050> SpecialNeeds; typedef gdcm::Attribute<0x0038, 0x0060> ServiceEpisodeID; typedef gdcm::Attribute<0x0038, 0x0061> IssuerOfServiceEpisodeID; typedef gdcm::Attribute<0x0038, 0x0062> ServiceEpisodeDescription; typedef gdcm::Attribute<0x0038, 0x0064> IssuerOfServiceEpisodeIDSequence; typedef gdcm::Attribute<0x0038, 0x0100> PertinentDocumentsSequence; typedef gdcm::Attribute<0x0038, 0x0300> CurrentPatientLocation; typedef gdcm::Attribute<0x0038, 0x0400> PatientInstitutionResidence; typedef gdcm::Attribute<0x0038, 0x0500> PatientState; typedef gdcm::Attribute<0x0038, 0x0502> PatientClinicalTrialParticipationSequence; typedef gdcm::Attribute<0x0038, 0x4000> VisitComments; typedef gdcm::Attribute<0x003a, 0x0004> WaveformOriginality; typedef gdcm::Attribute<0x003a, 0x0005> NumberOfWaveformChannels; typedef gdcm::Attribute<0x003a, 0x0010> NumberOfWaveformSamples; typedef gdcm::Attribute<0x003a, 0x001a> SamplingFrequency; typedef gdcm::Attribute<0x003a, 0x0020> MultiplexGroupLabel; typedef gdcm::Attribute<0x003a, 0x0200> ChannelDefinitionSequence; typedef gdcm::Attribute<0x003a, 0x0202> WaveformChannelNumber; typedef gdcm::Attribute<0x003a, 0x0203> ChannelLabel; typedef gdcm::Attribute<0x003a, 0x0205> ChannelStatus; typedef gdcm::Attribute<0x003a, 0x0208> ChannelSourceSequence; typedef gdcm::Attribute<0x003a, 0x0209> ChannelSourceModifiersSequence; typedef gdcm::Attribute<0x003a, 0x020a> SourceWaveformSequence; typedef gdcm::Attribute<0x003a, 0x020c> ChannelDerivationDescription; typedef gdcm::Attribute<0x003a, 0x0210> ChannelSensitivity; typedef gdcm::Attribute<0x003a, 0x0211> ChannelSensitivityUnitsSequence; typedef gdcm::Attribute<0x003a, 0x0212> ChannelSensitivityCorrectionFactor; typedef gdcm::Attribute<0x003a, 0x0213> ChannelBaseline; typedef gdcm::Attribute<0x003a, 0x0214> ChannelTimeSkew; typedef gdcm::Attribute<0x003a, 0x0215> ChannelSampleSkew; typedef gdcm::Attribute<0x003a, 0x0218> ChannelOffset; typedef gdcm::Attribute<0x003a, 0x021a> WaveformBitsStored; typedef gdcm::Attribute<0x003a, 0x0220> FilterLowFrequency; typedef gdcm::Attribute<0x003a, 0x0221> FilterHighFrequency; typedef gdcm::Attribute<0x003a, 0x0222> NotchFilterFrequency; typedef gdcm::Attribute<0x003a, 0x0223> NotchFilterBandwidth; typedef gdcm::Attribute<0x003a, 0x0230> WaveformDataDisplayScale; typedef gdcm::Attribute<0x003a, 0x0231> WaveformDisplayBackgroundCIELabValue; typedef gdcm::Attribute<0x003a, 0x0240> WaveformPresentationGroupSequence; typedef gdcm::Attribute<0x003a, 0x0241> PresentationGroupNumber; typedef gdcm::Attribute<0x003a, 0x0242> ChannelDisplaySequence; typedef gdcm::Attribute<0x003a, 0x0244> ChannelRecommendedDisplayCIELabValue; typedef gdcm::Attribute<0x003a, 0x0245> ChannelPosition; typedef gdcm::Attribute<0x003a, 0x0246> DisplayShadingFlag; typedef gdcm::Attribute<0x003a, 0x0247> FractionalChannelDisplayScale; typedef gdcm::Attribute<0x003a, 0x0248> AbsoluteChannelDisplayScale; typedef gdcm::Attribute<0x003a, 0x0300> MultiplexedAudioChannelsDescriptionCodeSequence; typedef gdcm::Attribute<0x003a, 0x0301> ChannelIdentificationCode; typedef gdcm::Attribute<0x003a, 0x0302> ChannelMode; typedef gdcm::Attribute<0x0040, 0x0001> ScheduledStationAETitle; typedef gdcm::Attribute<0x0040, 0x0002> ScheduledProcedureStepStartDate; typedef gdcm::Attribute<0x0040, 0x0003> ScheduledProcedureStepStartTime; typedef gdcm::Attribute<0x0040, 0x0004> ScheduledProcedureStepEndDate; typedef gdcm::Attribute<0x0040, 0x0005> ScheduledProcedureStepEndTime; typedef gdcm::Attribute<0x0040, 0x0006> ScheduledPerformingPhysicianName; typedef gdcm::Attribute<0x0040, 0x0007> ScheduledProcedureStepDescription; typedef gdcm::Attribute<0x0040, 0x0008> ScheduledProtocolCodeSequence; typedef gdcm::Attribute<0x0040, 0x0009> ScheduledProcedureStepID; typedef gdcm::Attribute<0x0040, 0x000a> StageCodeSequence; typedef gdcm::Attribute<0x0040, 0x000b> ScheduledPerformingPhysicianIdentificationSequence; typedef gdcm::Attribute<0x0040, 0x0010> ScheduledStationName; typedef gdcm::Attribute<0x0040, 0x0011> ScheduledProcedureStepLocation; typedef gdcm::Attribute<0x0040, 0x0012> PreMedication; typedef gdcm::Attribute<0x0040, 0x0020> ScheduledProcedureStepStatus; typedef gdcm::Attribute<0x0040, 0x0026> OrderPlacerIdentifierSequence; typedef gdcm::Attribute<0x0040, 0x0027> OrderFillerIdentifierSequence; typedef gdcm::Attribute<0x0040, 0x0031> LocalNamespaceEntityID; typedef gdcm::Attribute<0x0040, 0x0032> UniversalEntityID; typedef gdcm::Attribute<0x0040, 0x0033> UniversalEntityIDType; typedef gdcm::Attribute<0x0040, 0x0035> IdentifierTypeCode; typedef gdcm::Attribute<0x0040, 0x0036> AssigningFacilitySequence; typedef gdcm::Attribute<0x0040, 0x0039> AssigningJurisdictionCodeSequence; typedef gdcm::Attribute<0x0040, 0x003a> AssigningAgencyOrDepartmentCodeSequence; typedef gdcm::Attribute<0x0040, 0x0100> ScheduledProcedureStepSequence; typedef gdcm::Attribute<0x0040, 0x0220> ReferencedNonImageCompositeSOPInstanceSequence; typedef gdcm::Attribute<0x0040, 0x0241> PerformedStationAETitle; typedef gdcm::Attribute<0x0040, 0x0242> PerformedStationName; typedef gdcm::Attribute<0x0040, 0x0243> PerformedLocation; typedef gdcm::Attribute<0x0040, 0x0244> PerformedProcedureStepStartDate; typedef gdcm::Attribute<0x0040, 0x0245> PerformedProcedureStepStartTime; typedef gdcm::Attribute<0x0040, 0x0250> PerformedProcedureStepEndDate; typedef gdcm::Attribute<0x0040, 0x0251> PerformedProcedureStepEndTime; typedef gdcm::Attribute<0x0040, 0x0252> PerformedProcedureStepStatus; typedef gdcm::Attribute<0x0040, 0x0253> PerformedProcedureStepID; typedef gdcm::Attribute<0x0040, 0x0254> PerformedProcedureStepDescription; typedef gdcm::Attribute<0x0040, 0x0255> PerformedProcedureTypeDescription; typedef gdcm::Attribute<0x0040, 0x0260> PerformedProtocolCodeSequence; typedef gdcm::Attribute<0x0040, 0x0261> PerformedProtocolType; typedef gdcm::Attribute<0x0040, 0x0270> ScheduledStepAttributesSequence; typedef gdcm::Attribute<0x0040, 0x0275> RequestAttributesSequence; typedef gdcm::Attribute<0x0040, 0x0280> CommentsOnThePerformedProcedureStep; typedef gdcm::Attribute<0x0040, 0x0281> PerformedProcedureStepDiscontinuationReasonCodeSequence; typedef gdcm::Attribute<0x0040, 0x0293> QuantitySequence; typedef gdcm::Attribute<0x0040, 0x0294> Quantity; typedef gdcm::Attribute<0x0040, 0x0295> MeasuringUnitsSequence; typedef gdcm::Attribute<0x0040, 0x0296> BillingItemSequence; typedef gdcm::Attribute<0x0040, 0x0300> TotalTimeOfFluoroscopy; typedef gdcm::Attribute<0x0040, 0x0301> TotalNumberOfExposures; typedef gdcm::Attribute<0x0040, 0x0302> EntranceDose; typedef gdcm::Attribute<0x0040, 0x0303> ExposedArea; typedef gdcm::Attribute<0x0040, 0x0306> DistanceSourceToEntrance; typedef gdcm::Attribute<0x0040, 0x0307> DistanceSourceToSupport; typedef gdcm::Attribute<0x0040, 0x030e> ExposureDoseSequence; typedef gdcm::Attribute<0x0040, 0x0310> CommentsOnRadiationDose; typedef gdcm::Attribute<0x0040, 0x0312> XRayOutput; typedef gdcm::Attribute<0x0040, 0x0314> HalfValueLayer; typedef gdcm::Attribute<0x0040, 0x0316> OrganDose; typedef gdcm::Attribute<0x0040, 0x0318> OrganExposed; typedef gdcm::Attribute<0x0040, 0x0320> BillingProcedureStepSequence; typedef gdcm::Attribute<0x0040, 0x0321> FilmConsumptionSequence; typedef gdcm::Attribute<0x0040, 0x0324> BillingSuppliesAndDevicesSequence; typedef gdcm::Attribute<0x0040, 0x0330> ReferencedProcedureStepSequence; typedef gdcm::Attribute<0x0040, 0x0340> PerformedSeriesSequence; typedef gdcm::Attribute<0x0040, 0x0400> CommentsOnTheScheduledProcedureStep; typedef gdcm::Attribute<0x0040, 0x0440> ProtocolContextSequence; typedef gdcm::Attribute<0x0040, 0x0441> ContentItemModifierSequence; typedef gdcm::Attribute<0x0040, 0x0500> ScheduledSpecimenSequence; typedef gdcm::Attribute<0x0040, 0x050a> SpecimenAccessionNumber; typedef gdcm::Attribute<0x0040, 0x0512> ContainerIdentifier; typedef gdcm::Attribute<0x0040, 0x0513> IssuerOfTheContainerIdentifierSequence; typedef gdcm::Attribute<0x0040, 0x0515> AlternateContainerIdentifierSequence; typedef gdcm::Attribute<0x0040, 0x0518> ContainerTypeCodeSequence; typedef gdcm::Attribute<0x0040, 0x051a> ContainerDescription; typedef gdcm::Attribute<0x0040, 0x0520> ContainerComponentSequence; typedef gdcm::Attribute<0x0040, 0x0550> SpecimenSequence; typedef gdcm::Attribute<0x0040, 0x0551> SpecimenIdentifier; typedef gdcm::Attribute<0x0040, 0x0552> SpecimenDescriptionSequenceTrial; typedef gdcm::Attribute<0x0040, 0x0553> SpecimenDescriptionTrial; typedef gdcm::Attribute<0x0040, 0x0554> SpecimenUID; typedef gdcm::Attribute<0x0040, 0x0555> AcquisitionContextSequence; typedef gdcm::Attribute<0x0040, 0x0556> AcquisitionContextDescription; typedef gdcm::Attribute<0x0040, 0x059a> SpecimenTypeCodeSequence; typedef gdcm::Attribute<0x0040, 0x0560> SpecimenDescriptionSequence; typedef gdcm::Attribute<0x0040, 0x0562> IssuerOfTheSpecimenIdentifierSequence; typedef gdcm::Attribute<0x0040, 0x0600> SpecimenShortDescription; typedef gdcm::Attribute<0x0040, 0x0602> SpecimenDetailedDescription; typedef gdcm::Attribute<0x0040, 0x0610> SpecimenPreparationSequence; typedef gdcm::Attribute<0x0040, 0x0612> SpecimenPreparationStepContentItemSequence; typedef gdcm::Attribute<0x0040, 0x0620> SpecimenLocalizationContentItemSequence; typedef gdcm::Attribute<0x0040, 0x06fa> SlideIdentifier; typedef gdcm::Attribute<0x0040, 0x071a> ImageCenterPointCoordinatesSequence; typedef gdcm::Attribute<0x0040, 0x072a> XOffsetInSlideCoordinateSystem; typedef gdcm::Attribute<0x0040, 0x073a> YOffsetInSlideCoordinateSystem; typedef gdcm::Attribute<0x0040, 0x074a> ZOffsetInSlideCoordinateSystem; typedef gdcm::Attribute<0x0040, 0x08d8> PixelSpacingSequence; typedef gdcm::Attribute<0x0040, 0x08da> CoordinateSystemAxisCodeSequence; typedef gdcm::Attribute<0x0040, 0x08ea> MeasurementUnitsCodeSequence; typedef gdcm::Attribute<0x0040, 0x09f8> VitalStainCodeSequenceTrial; typedef gdcm::Attribute<0x0040, 0x1001> RequestedProcedureID; typedef gdcm::Attribute<0x0040, 0x1002> ReasonForTheRequestedProcedure; typedef gdcm::Attribute<0x0040, 0x1003> RequestedProcedurePriority; typedef gdcm::Attribute<0x0040, 0x1004> PatientTransportArrangements; typedef gdcm::Attribute<0x0040, 0x1005> RequestedProcedureLocation; typedef gdcm::Attribute<0x0040, 0x1006> PlacerOrderNumberProcedure; typedef gdcm::Attribute<0x0040, 0x1007> FillerOrderNumberProcedure; typedef gdcm::Attribute<0x0040, 0x1008> ConfidentialityCode; typedef gdcm::Attribute<0x0040, 0x1009> ReportingPriority; typedef gdcm::Attribute<0x0040, 0x100a> ReasonForRequestedProcedureCodeSequence; typedef gdcm::Attribute<0x0040, 0x1010> NamesOfIntendedRecipientsOfResults; typedef gdcm::Attribute<0x0040, 0x1011> IntendedRecipientsOfResultsIdentificationSequence; typedef gdcm::Attribute<0x0040, 0x1012> ReasonForPerformedProcedureCodeSequence; typedef gdcm::Attribute<0x0040, 0x1060> RequestedProcedureDescriptionTrial; typedef gdcm::Attribute<0x0040, 0x1101> PersonIdentificationCodeSequence; typedef gdcm::Attribute<0x0040, 0x1102> PersonAddress; typedef gdcm::Attribute<0x0040, 0x1103> PersonTelephoneNumbers; typedef gdcm::Attribute<0x0040, 0x1400> RequestedProcedureComments; typedef gdcm::Attribute<0x0040, 0x2001> ReasonForTheImagingServiceRequest; typedef gdcm::Attribute<0x0040, 0x2004> IssueDateOfImagingServiceRequest; typedef gdcm::Attribute<0x0040, 0x2005> IssueTimeOfImagingServiceRequest; typedef gdcm::Attribute<0x0040, 0x2006> PlacerOrderNumberImagingServiceRequestRetired; typedef gdcm::Attribute<0x0040, 0x2007> FillerOrderNumberImagingServiceRequestRetired; typedef gdcm::Attribute<0x0040, 0x2008> OrderEnteredBy; typedef gdcm::Attribute<0x0040, 0x2009> OrderEntererLocation; typedef gdcm::Attribute<0x0040, 0x2010> OrderCallbackPhoneNumber; typedef gdcm::Attribute<0x0040, 0x2016> PlacerOrderNumberImagingServiceRequest; typedef gdcm::Attribute<0x0040, 0x2017> FillerOrderNumberImagingServiceRequest; typedef gdcm::Attribute<0x0040, 0x2400> ImagingServiceRequestComments; typedef gdcm::Attribute<0x0040, 0x3001> ConfidentialityConstraintOnPatientDataDescription; typedef gdcm::Attribute<0x0040, 0x4001> GeneralPurposeScheduledProcedureStepStatus; typedef gdcm::Attribute<0x0040, 0x4002> GeneralPurposePerformedProcedureStepStatus; typedef gdcm::Attribute<0x0040, 0x4003> GeneralPurposeScheduledProcedureStepPriority; typedef gdcm::Attribute<0x0040, 0x4004> ScheduledProcessingApplicationsCodeSequence; typedef gdcm::Attribute<0x0040, 0x4005> ScheduledProcedureStepStartDateTime; typedef gdcm::Attribute<0x0040, 0x4006> MultipleCopiesFlag; typedef gdcm::Attribute<0x0040, 0x4007> PerformedProcessingApplicationsCodeSequence; typedef gdcm::Attribute<0x0040, 0x4009> HumanPerformerCodeSequence; typedef gdcm::Attribute<0x0040, 0x4010> ScheduledProcedureStepModificationDateTime; typedef gdcm::Attribute<0x0040, 0x4011> ExpectedCompletionDateTime; typedef gdcm::Attribute<0x0040, 0x4015> ResultingGeneralPurposePerformedProcedureStepsSequence; typedef gdcm::Attribute<0x0040, 0x4016> ReferencedGeneralPurposeScheduledProcedureStepSequence; typedef gdcm::Attribute<0x0040, 0x4018> ScheduledWorkitemCodeSequence; typedef gdcm::Attribute<0x0040, 0x4019> PerformedWorkitemCodeSequence; typedef gdcm::Attribute<0x0040, 0x4020> InputAvailabilityFlag; typedef gdcm::Attribute<0x0040, 0x4021> InputInformationSequence; typedef gdcm::Attribute<0x0040, 0x4022> RelevantInformationSequence; typedef gdcm::Attribute<0x0040, 0x4023> ReferencedGeneralPurposeScheduledProcedureStepTransactionUID; typedef gdcm::Attribute<0x0040, 0x4025> ScheduledStationNameCodeSequence; typedef gdcm::Attribute<0x0040, 0x4026> ScheduledStationClassCodeSequence; typedef gdcm::Attribute<0x0040, 0x4027> ScheduledStationGeographicLocationCodeSequence; typedef gdcm::Attribute<0x0040, 0x4028> PerformedStationNameCodeSequence; typedef gdcm::Attribute<0x0040, 0x4029> PerformedStationClassCodeSequence; typedef gdcm::Attribute<0x0040, 0x4030> PerformedStationGeographicLocationCodeSequence; typedef gdcm::Attribute<0x0040, 0x4031> RequestedSubsequentWorkitemCodeSequence; typedef gdcm::Attribute<0x0040, 0x4032> NonDICOMOutputCodeSequence; typedef gdcm::Attribute<0x0040, 0x4033> OutputInformationSequence; typedef gdcm::Attribute<0x0040, 0x4034> ScheduledHumanPerformersSequence; typedef gdcm::Attribute<0x0040, 0x4035> ActualHumanPerformersSequence; typedef gdcm::Attribute<0x0040, 0x4036> HumanPerformerOrganization; typedef gdcm::Attribute<0x0040, 0x4037> HumanPerformerName; typedef gdcm::Attribute<0x0040, 0x4040> RawDataHandling; typedef gdcm::Attribute<0x0040, 0x4041> InputReadinessState; typedef gdcm::Attribute<0x0040, 0x4050> PerformedProcedureStepStartDateTime; typedef gdcm::Attribute<0x0040, 0x4051> PerformedProcedureStepEndDateTime; typedef gdcm::Attribute<0x0040, 0x4052> ProcedureStepCancellationDateTime; typedef gdcm::Attribute<0x0040, 0x8302> EntranceDoseInmGy; typedef gdcm::Attribute<0x0040, 0x9094> ReferencedImageRealWorldValueMappingSequence; typedef gdcm::Attribute<0x0040, 0x9096> RealWorldValueMappingSequence; typedef gdcm::Attribute<0x0040, 0x9098> PixelValueMappingCodeSequence; typedef gdcm::Attribute<0x0040, 0x9210> LUTLabel; typedef gdcm::Attribute<0x0040, 0x9211> RealWorldValueLastValueMapped; typedef gdcm::Attribute<0x0040, 0x9212> RealWorldValueLUTData; typedef gdcm::Attribute<0x0040, 0x9216> RealWorldValueFirstValueMapped; typedef gdcm::Attribute<0x0040, 0x9224> RealWorldValueIntercept; typedef gdcm::Attribute<0x0040, 0x9225> RealWorldValueSlope; typedef gdcm::Attribute<0x0040, 0xa007> FindingsFlagTrial; typedef gdcm::Attribute<0x0040, 0xa010> RelationshipType; typedef gdcm::Attribute<0x0040, 0xa020> FindingsSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa021> FindingsGroupUIDTrial; typedef gdcm::Attribute<0x0040, 0xa022> ReferencedFindingsGroupUIDTrial; typedef gdcm::Attribute<0x0040, 0xa023> FindingsGroupRecordingDateTrial; typedef gdcm::Attribute<0x0040, 0xa024> FindingsGroupRecordingTimeTrial; typedef gdcm::Attribute<0x0040, 0xa026> FindingsSourceCategoryCodeSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa027> VerifyingOrganization; typedef gdcm::Attribute<0x0040, 0xa028> DocumentingOrganizationIdentifierCodeSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa030> VerificationDateTime; typedef gdcm::Attribute<0x0040, 0xa032> ObservationDateTime; typedef gdcm::Attribute<0x0040, 0xa040> ValueType; typedef gdcm::Attribute<0x0040, 0xa043> ConceptNameCodeSequence; typedef gdcm::Attribute<0x0040, 0xa047> MeasurementPrecisionDescriptionTrial; typedef gdcm::Attribute<0x0040, 0xa050> ContinuityOfContent; typedef gdcm::Attribute<0x0040, 0xa057> UrgencyOrPriorityAlertsTrial; typedef gdcm::Attribute<0x0040, 0xa060> SequencingIndicatorTrial; typedef gdcm::Attribute<0x0040, 0xa066> DocumentIdentifierCodeSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa067> DocumentAuthorTrial; typedef gdcm::Attribute<0x0040, 0xa068> DocumentAuthorIdentifierCodeSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa070> IdentifierCodeSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa073> VerifyingObserverSequence; typedef gdcm::Attribute<0x0040, 0xa074> ObjectBinaryIdentifierTrial; typedef gdcm::Attribute<0x0040, 0xa075> VerifyingObserverName; typedef gdcm::Attribute<0x0040, 0xa076> DocumentingObserverIdentifierCodeSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa078> AuthorObserverSequence; typedef gdcm::Attribute<0x0040, 0xa07a> ParticipantSequence; typedef gdcm::Attribute<0x0040, 0xa07c> CustodialOrganizationSequence; typedef gdcm::Attribute<0x0040, 0xa080> ParticipationType; typedef gdcm::Attribute<0x0040, 0xa082> ParticipationDateTime; typedef gdcm::Attribute<0x0040, 0xa084> ObserverType; typedef gdcm::Attribute<0x0040, 0xa085> ProcedureIdentifierCodeSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa088> VerifyingObserverIdentificationCodeSequence; typedef gdcm::Attribute<0x0040, 0xa089> ObjectDirectoryBinaryIdentifierTrial; typedef gdcm::Attribute<0x0040, 0xa090> EquivalentCDADocumentSequence; typedef gdcm::Attribute<0x0040, 0xa0b0> ReferencedWaveformChannels; typedef gdcm::Attribute<0x0040, 0xa110> DateOfDocumentOrVerbalTransactionTrial; typedef gdcm::Attribute<0x0040, 0xa112> TimeOfDocumentCreationOrVerbalTransactionTrial; typedef gdcm::Attribute<0x0040, 0xa120> DateTime; typedef gdcm::Attribute<0x0040, 0xa121> Date; typedef gdcm::Attribute<0x0040, 0xa122> Time; typedef gdcm::Attribute<0x0040, 0xa123> PersonName; typedef gdcm::Attribute<0x0040, 0xa124> UID; typedef gdcm::Attribute<0x0040, 0xa125> ReportStatusIDTrial; typedef gdcm::Attribute<0x0040, 0xa130> TemporalRangeType; typedef gdcm::Attribute<0x0040, 0xa132> ReferencedSamplePositions; typedef gdcm::Attribute<0x0040, 0xa136> ReferencedFrameNumbers; typedef gdcm::Attribute<0x0040, 0xa138> ReferencedTimeOffsets; typedef gdcm::Attribute<0x0040, 0xa13a> ReferencedDateTime; typedef gdcm::Attribute<0x0040, 0xa160> TextValue; typedef gdcm::Attribute<0x0040, 0xa167> ObservationCategoryCodeSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa168> ConceptCodeSequence; typedef gdcm::Attribute<0x0040, 0xa16a> BibliographicCitationTrial; typedef gdcm::Attribute<0x0040, 0xa170> PurposeOfReferenceCodeSequence; typedef gdcm::Attribute<0x0040, 0xa171> ObservationUIDTrial; typedef gdcm::Attribute<0x0040, 0xa172> ReferencedObservationUIDTrial; typedef gdcm::Attribute<0x0040, 0xa173> ReferencedObservationClassTrial; typedef gdcm::Attribute<0x0040, 0xa174> ReferencedObjectObservationClassTrial; typedef gdcm::Attribute<0x0040, 0xa180> AnnotationGroupNumber; typedef gdcm::Attribute<0x0040, 0xa192> ObservationDateTrial; typedef gdcm::Attribute<0x0040, 0xa193> ObservationTimeTrial; typedef gdcm::Attribute<0x0040, 0xa194> MeasurementAutomationTrial; typedef gdcm::Attribute<0x0040, 0xa195> ModifierCodeSequence; typedef gdcm::Attribute<0x0040, 0xa224> IdentificationDescriptionTrial; typedef gdcm::Attribute<0x0040, 0xa290> CoordinatesSetGeometricTypeTrial; typedef gdcm::Attribute<0x0040, 0xa296> AlgorithmCodeSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa297> AlgorithmDescriptionTrial; typedef gdcm::Attribute<0x0040, 0xa29a> PixelCoordinatesSetTrial; typedef gdcm::Attribute<0x0040, 0xa300> MeasuredValueSequence; typedef gdcm::Attribute<0x0040, 0xa301> NumericValueQualifierCodeSequence; typedef gdcm::Attribute<0x0040, 0xa307> CurrentObserverTrial; typedef gdcm::Attribute<0x0040, 0xa30a> NumericValue; typedef gdcm::Attribute<0x0040, 0xa313> ReferencedAccessionSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa33a> ReportStatusCommentTrial; typedef gdcm::Attribute<0x0040, 0xa340> ProcedureContextSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa352> VerbalSourceTrial; typedef gdcm::Attribute<0x0040, 0xa353> AddressTrial; typedef gdcm::Attribute<0x0040, 0xa354> TelephoneNumberTrial; typedef gdcm::Attribute<0x0040, 0xa358> VerbalSourceIdentifierCodeSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa360> PredecessorDocumentsSequence; typedef gdcm::Attribute<0x0040, 0xa370> ReferencedRequestSequence; typedef gdcm::Attribute<0x0040, 0xa372> PerformedProcedureCodeSequence; typedef gdcm::Attribute<0x0040, 0xa375> CurrentRequestedProcedureEvidenceSequence; typedef gdcm::Attribute<0x0040, 0xa380> ReportDetailSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa385> PertinentOtherEvidenceSequence; typedef gdcm::Attribute<0x0040, 0xa390> HL7StructuredDocumentReferenceSequence; typedef gdcm::Attribute<0x0040, 0xa402> ObservationSubjectUIDTrial; typedef gdcm::Attribute<0x0040, 0xa403> ObservationSubjectClassTrial; typedef gdcm::Attribute<0x0040, 0xa404> ObservationSubjectTypeCodeSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa491> CompletionFlag; typedef gdcm::Attribute<0x0040, 0xa492> CompletionFlagDescription; typedef gdcm::Attribute<0x0040, 0xa493> VerificationFlag; typedef gdcm::Attribute<0x0040, 0xa494> ArchiveRequested; typedef gdcm::Attribute<0x0040, 0xa496> PreliminaryFlag; typedef gdcm::Attribute<0x0040, 0xa504> ContentTemplateSequence; typedef gdcm::Attribute<0x0040, 0xa525> IdenticalDocumentsSequence; typedef gdcm::Attribute<0x0040, 0xa600> ObservationSubjectContextFlagTrial; typedef gdcm::Attribute<0x0040, 0xa601> ObserverContextFlagTrial; typedef gdcm::Attribute<0x0040, 0xa603> ProcedureContextFlagTrial; typedef gdcm::Attribute<0x0040, 0xa730> ContentSequence; typedef gdcm::Attribute<0x0040, 0xa731> RelationshipSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa732> RelationshipTypeCodeSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa744> LanguageCodeSequenceTrial; typedef gdcm::Attribute<0x0040, 0xa992> UniformResourceLocatorTrial; typedef gdcm::Attribute<0x0040, 0xb020> WaveformAnnotationSequence; typedef gdcm::Attribute<0x0040, 0xdb00> TemplateIdentifier; typedef gdcm::Attribute<0x0040, 0xdb06> TemplateVersion; typedef gdcm::Attribute<0x0040, 0xdb07> TemplateLocalVersion; typedef gdcm::Attribute<0x0040, 0xdb0b> TemplateExtensionFlag; typedef gdcm::Attribute<0x0040, 0xdb0c> TemplateExtensionOrganizationUID; typedef gdcm::Attribute<0x0040, 0xdb0d> TemplateExtensionCreatorUID; typedef gdcm::Attribute<0x0040, 0xdb73> ReferencedContentItemIdentifier; typedef gdcm::Attribute<0x0040, 0xe001> HL7InstanceIdentifier; typedef gdcm::Attribute<0x0040, 0xe004> HL7DocumentEffectiveTime; typedef gdcm::Attribute<0x0040, 0xe006> HL7DocumentTypeCodeSequence; typedef gdcm::Attribute<0x0040, 0xe008> DocumentClassCodeSequence; typedef gdcm::Attribute<0x0040, 0xe010> RetrieveURI; typedef gdcm::Attribute<0x0040, 0xe011> RetrieveLocationUID; typedef gdcm::Attribute<0x0040, 0xe020> TypeOfInstances; typedef gdcm::Attribute<0x0040, 0xe021> DICOMRetrievalSequence; typedef gdcm::Attribute<0x0040, 0xe022> DICOMMediaRetrievalSequence; typedef gdcm::Attribute<0x0040, 0xe023> WADORetrievalSequence; typedef gdcm::Attribute<0x0040, 0xe024> XDSRetrievalSequence; typedef gdcm::Attribute<0x0040, 0xe030> RepositoryUniqueID; typedef gdcm::Attribute<0x0040, 0xe031> HomeCommunityID; typedef gdcm::Attribute<0x0042, 0x0010> DocumentTitle; typedef gdcm::Attribute<0x0042, 0x0011> EncapsulatedDocument; typedef gdcm::Attribute<0x0042, 0x0012> MIMETypeOfEncapsulatedDocument; typedef gdcm::Attribute<0x0042, 0x0013> SourceInstanceSequence; typedef gdcm::Attribute<0x0042, 0x0014> ListOfMIMETypes; typedef gdcm::Attribute<0x0044, 0x0001> ProductPackageIdentifier; typedef gdcm::Attribute<0x0044, 0x0002> SubstanceAdministrationApproval; typedef gdcm::Attribute<0x0044, 0x0003> ApprovalStatusFurtherDescription; typedef gdcm::Attribute<0x0044, 0x0004> ApprovalStatusDateTime; typedef gdcm::Attribute<0x0044, 0x0007> ProductTypeCodeSequence; typedef gdcm::Attribute<0x0044, 0x0008> ProductName; typedef gdcm::Attribute<0x0044, 0x0009> ProductDescription; typedef gdcm::Attribute<0x0044, 0x000a> ProductLotIdentifier; typedef gdcm::Attribute<0x0044, 0x000b> ProductExpirationDateTime; typedef gdcm::Attribute<0x0044, 0x0010> SubstanceAdministrationDateTime; typedef gdcm::Attribute<0x0044, 0x0011> SubstanceAdministrationNotes; typedef gdcm::Attribute<0x0044, 0x0012> SubstanceAdministrationDeviceID; typedef gdcm::Attribute<0x0044, 0x0013> ProductParameterSequence; typedef gdcm::Attribute<0x0044, 0x0019> SubstanceAdministrationParameterSequence; typedef gdcm::Attribute<0x0046, 0x0012> LensDescription; typedef gdcm::Attribute<0x0046, 0x0014> RightLensSequence; typedef gdcm::Attribute<0x0046, 0x0015> LeftLensSequence; typedef gdcm::Attribute<0x0046, 0x0016> UnspecifiedLateralityLensSequence; typedef gdcm::Attribute<0x0046, 0x0018> CylinderSequence; typedef gdcm::Attribute<0x0046, 0x0028> PrismSequence; typedef gdcm::Attribute<0x0046, 0x0030> HorizontalPrismPower; typedef gdcm::Attribute<0x0046, 0x0032> HorizontalPrismBase; typedef gdcm::Attribute<0x0046, 0x0034> VerticalPrismPower; typedef gdcm::Attribute<0x0046, 0x0036> VerticalPrismBase; typedef gdcm::Attribute<0x0046, 0x0038> LensSegmentType; typedef gdcm::Attribute<0x0046, 0x0040> OpticalTransmittance; typedef gdcm::Attribute<0x0046, 0x0042> ChannelWidth; typedef gdcm::Attribute<0x0046, 0x0044> PupilSize; typedef gdcm::Attribute<0x0046, 0x0046> CornealSize; typedef gdcm::Attribute<0x0046, 0x0050> AutorefractionRightEyeSequence; typedef gdcm::Attribute<0x0046, 0x0052> AutorefractionLeftEyeSequence; typedef gdcm::Attribute<0x0046, 0x0060> DistancePupillaryDistance; typedef gdcm::Attribute<0x0046, 0x0062> NearPupillaryDistance; typedef gdcm::Attribute<0x0046, 0x0063> IntermediatePupillaryDistance; typedef gdcm::Attribute<0x0046, 0x0064> OtherPupillaryDistance; typedef gdcm::Attribute<0x0046, 0x0070> KeratometryRightEyeSequence; typedef gdcm::Attribute<0x0046, 0x0071> KeratometryLeftEyeSequence; typedef gdcm::Attribute<0x0046, 0x0074> SteepKeratometricAxisSequence; typedef gdcm::Attribute<0x0046, 0x0075> RadiusOfCurvature; typedef gdcm::Attribute<0x0046, 0x0076> KeratometricPower; typedef gdcm::Attribute<0x0046, 0x0077> KeratometricAxis; typedef gdcm::Attribute<0x0046, 0x0080> FlatKeratometricAxisSequence; typedef gdcm::Attribute<0x0046, 0x0092> BackgroundColor; typedef gdcm::Attribute<0x0046, 0x0094> Optotype; typedef gdcm::Attribute<0x0046, 0x0095> OptotypePresentation; typedef gdcm::Attribute<0x0046, 0x0097> SubjectiveRefractionRightEyeSequence; typedef gdcm::Attribute<0x0046, 0x0098> SubjectiveRefractionLeftEyeSequence; typedef gdcm::Attribute<0x0046, 0x0100> AddNearSequence; typedef gdcm::Attribute<0x0046, 0x0101> AddIntermediateSequence; typedef gdcm::Attribute<0x0046, 0x0102> AddOtherSequence; typedef gdcm::Attribute<0x0046, 0x0104> AddPower; typedef gdcm::Attribute<0x0046, 0x0106> ViewingDistance; typedef gdcm::Attribute<0x0046, 0x0121> VisualAcuityTypeCodeSequence; typedef gdcm::Attribute<0x0046, 0x0122> VisualAcuityRightEyeSequence; typedef gdcm::Attribute<0x0046, 0x0123> VisualAcuityLeftEyeSequence; typedef gdcm::Attribute<0x0046, 0x0124> VisualAcuityBothEyesOpenSequence; typedef gdcm::Attribute<0x0046, 0x0125> ViewingDistanceType; typedef gdcm::Attribute<0x0046, 0x0135> VisualAcuityModifiers; typedef gdcm::Attribute<0x0046, 0x0137> DecimalVisualAcuity; typedef gdcm::Attribute<0x0046, 0x0139> OptotypeDetailedDefinition; typedef gdcm::Attribute<0x0046, 0x0145> ReferencedRefractiveMeasurementsSequence; typedef gdcm::Attribute<0x0046, 0x0146> SpherePower; typedef gdcm::Attribute<0x0046, 0x0147> CylinderPower; typedef gdcm::Attribute<0x0048, 0x0001> ImagedVolumeWidth; typedef gdcm::Attribute<0x0048, 0x0002> ImagedVolumeHeight; typedef gdcm::Attribute<0x0048, 0x0003> ImagedVolumeDepth; typedef gdcm::Attribute<0x0048, 0x0006> TotalPixelMatrixColumns; typedef gdcm::Attribute<0x0048, 0x0007> TotalPixelMatrixRows; typedef gdcm::Attribute<0x0048, 0x0008> TotalPixelMatrixOriginSequence; typedef gdcm::Attribute<0x0048, 0x0010> SpecimenLabelInImage; typedef gdcm::Attribute<0x0048, 0x0011> FocusMethod; typedef gdcm::Attribute<0x0048, 0x0012> ExtendedDepthOfField; typedef gdcm::Attribute<0x0048, 0x0013> NumberOfFocalPlanes; typedef gdcm::Attribute<0x0048, 0x0014> DistanceBetweenFocalPlanes; typedef gdcm::Attribute<0x0048, 0x0015> RecommendedAbsentPixelCIELabValue; typedef gdcm::Attribute<0x0048, 0x0100> IlluminatorTypeCodeSequence; typedef gdcm::Attribute<0x0048, 0x0102> ImageOrientationSlide; typedef gdcm::Attribute<0x0048, 0x0105> OpticalPathSequence; typedef gdcm::Attribute<0x0048, 0x0106> OpticalPathIdentifier; typedef gdcm::Attribute<0x0048, 0x0107> OpticalPathDescription; typedef gdcm::Attribute<0x0048, 0x0108> IlluminationColorCodeSequence; typedef gdcm::Attribute<0x0048, 0x0110> SpecimenReferenceSequence; typedef gdcm::Attribute<0x0048, 0x0111> CondenserLensPower; typedef gdcm::Attribute<0x0048, 0x0112> ObjectiveLensPower; typedef gdcm::Attribute<0x0048, 0x0113> ObjectiveLensNumericalAperture; typedef gdcm::Attribute<0x0048, 0x0120> PaletteColorLookupTableSequence; typedef gdcm::Attribute<0x0048, 0x0200> ReferencedImageNavigationSequence; typedef gdcm::Attribute<0x0048, 0x0201> TopLeftHandCornerOfLocalizerArea; typedef gdcm::Attribute<0x0048, 0x0202> BottomRightHandCornerOfLocalizerArea; typedef gdcm::Attribute<0x0048, 0x0207> OpticalPathIdentificationSequence; typedef gdcm::Attribute<0x0048, 0x021a> PlanePositionSlideSequence; typedef gdcm::Attribute<0x0048, 0x021e> ColumnPositionInTotalImagePixelMatrix; typedef gdcm::Attribute<0x0048, 0x021f> RowPositionInTotalImagePixelMatrix; typedef gdcm::Attribute<0x0048, 0x0301> PixelOriginInterpretation; typedef gdcm::Attribute<0x0050, 0x0004> CalibrationImage; typedef gdcm::Attribute<0x0050, 0x0010> DeviceSequence; typedef gdcm::Attribute<0x0050, 0x0012> ContainerComponentTypeCodeSequence; typedef gdcm::Attribute<0x0050, 0x0013> ContainerComponentThickness; typedef gdcm::Attribute<0x0050, 0x0014> DeviceLength; typedef gdcm::Attribute<0x0050, 0x0015> ContainerComponentWidth; typedef gdcm::Attribute<0x0050, 0x0016> DeviceDiameter; typedef gdcm::Attribute<0x0050, 0x0017> DeviceDiameterUnits; typedef gdcm::Attribute<0x0050, 0x0018> DeviceVolume; typedef gdcm::Attribute<0x0050, 0x0019> InterMarkerDistance; typedef gdcm::Attribute<0x0050, 0x001a> ContainerComponentMaterial; typedef gdcm::Attribute<0x0050, 0x001b> ContainerComponentID; typedef gdcm::Attribute<0x0050, 0x001c> ContainerComponentLength; typedef gdcm::Attribute<0x0050, 0x001d> ContainerComponentDiameter; typedef gdcm::Attribute<0x0050, 0x001e> ContainerComponentDescription; typedef gdcm::Attribute<0x0050, 0x0020> DeviceDescription; typedef gdcm::Attribute<0x0052, 0x0001> ContrastBolusIngredientPercentByVolume; typedef gdcm::Attribute<0x0052, 0x0002> OCTFocalDistance; typedef gdcm::Attribute<0x0052, 0x0003> BeamSpotSize; typedef gdcm::Attribute<0x0052, 0x0004> EffectiveRefractiveIndex; typedef gdcm::Attribute<0x0052, 0x0006> OCTAcquisitionDomain; typedef gdcm::Attribute<0x0052, 0x0007> OCTOpticalCenterWavelength; typedef gdcm::Attribute<0x0052, 0x0008> AxialResolution; typedef gdcm::Attribute<0x0052, 0x0009> RangingDepth; typedef gdcm::Attribute<0x0052, 0x0011> ALineRate; typedef gdcm::Attribute<0x0052, 0x0012> ALinesPerFrame; typedef gdcm::Attribute<0x0052, 0x0013> CatheterRotationalRate; typedef gdcm::Attribute<0x0052, 0x0014> ALinePixelSpacing; typedef gdcm::Attribute<0x0052, 0x0016> ModeOfPercutaneousAccessSequence; typedef gdcm::Attribute<0x0052, 0x0025> IntravascularOCTFrameTypeSequence; typedef gdcm::Attribute<0x0052, 0x0026> OCTZOffsetApplied; typedef gdcm::Attribute<0x0052, 0x0027> IntravascularFrameContentSequence; typedef gdcm::Attribute<0x0052, 0x0028> IntravascularLongitudinalDistance; typedef gdcm::Attribute<0x0052, 0x0029> IntravascularOCTFrameContentSequence; typedef gdcm::Attribute<0x0052, 0x0030> OCTZOffsetCorrection; typedef gdcm::Attribute<0x0052, 0x0031> CatheterDirectionOfRotation; typedef gdcm::Attribute<0x0052, 0x0033> SeamLineLocation; typedef gdcm::Attribute<0x0052, 0x0034> FirstALineLocation; typedef gdcm::Attribute<0x0052, 0x0036> SeamLineIndex; typedef gdcm::Attribute<0x0052, 0x0038> NumberOfPaddedAlines; typedef gdcm::Attribute<0x0052, 0x0039> InterpolationType; typedef gdcm::Attribute<0x0052, 0x003a> RefractiveIndexApplied; typedef gdcm::Attribute<0x0054, 0x0010> EnergyWindowVector; typedef gdcm::Attribute<0x0054, 0x0011> NumberOfEnergyWindows; typedef gdcm::Attribute<0x0054, 0x0012> EnergyWindowInformationSequence; typedef gdcm::Attribute<0x0054, 0x0013> EnergyWindowRangeSequence; typedef gdcm::Attribute<0x0054, 0x0014> EnergyWindowLowerLimit; typedef gdcm::Attribute<0x0054, 0x0015> EnergyWindowUpperLimit; typedef gdcm::Attribute<0x0054, 0x0016> RadiopharmaceuticalInformationSequence; typedef gdcm::Attribute<0x0054, 0x0017> ResidualSyringeCounts; typedef gdcm::Attribute<0x0054, 0x0018> EnergyWindowName; typedef gdcm::Attribute<0x0054, 0x0020> DetectorVector; typedef gdcm::Attribute<0x0054, 0x0021> NumberOfDetectors; typedef gdcm::Attribute<0x0054, 0x0022> DetectorInformationSequence; typedef gdcm::Attribute<0x0054, 0x0030> PhaseVector; typedef gdcm::Attribute<0x0054, 0x0031> NumberOfPhases; typedef gdcm::Attribute<0x0054, 0x0032> PhaseInformationSequence; typedef gdcm::Attribute<0x0054, 0x0033> NumberOfFramesInPhase; typedef gdcm::Attribute<0x0054, 0x0036> PhaseDelay; typedef gdcm::Attribute<0x0054, 0x0038> PauseBetweenFrames; typedef gdcm::Attribute<0x0054, 0x0039> PhaseDescription; typedef gdcm::Attribute<0x0054, 0x0050> RotationVector; typedef gdcm::Attribute<0x0054, 0x0051> NumberOfRotations; typedef gdcm::Attribute<0x0054, 0x0052> RotationInformationSequence; typedef gdcm::Attribute<0x0054, 0x0053> NumberOfFramesInRotation; typedef gdcm::Attribute<0x0054, 0x0060> RRIntervalVector; typedef gdcm::Attribute<0x0054, 0x0061> NumberOfRRIntervals; typedef gdcm::Attribute<0x0054, 0x0062> GatedInformationSequence; typedef gdcm::Attribute<0x0054, 0x0063> DataInformationSequence; typedef gdcm::Attribute<0x0054, 0x0070> TimeSlotVector; typedef gdcm::Attribute<0x0054, 0x0071> NumberOfTimeSlots; typedef gdcm::Attribute<0x0054, 0x0072> TimeSlotInformationSequence; typedef gdcm::Attribute<0x0054, 0x0073> TimeSlotTime; typedef gdcm::Attribute<0x0054, 0x0080> SliceVector; typedef gdcm::Attribute<0x0054, 0x0081> NumberOfSlices; typedef gdcm::Attribute<0x0054, 0x0090> AngularViewVector; typedef gdcm::Attribute<0x0054, 0x0100> TimeSliceVector; typedef gdcm::Attribute<0x0054, 0x0101> NumberOfTimeSlices; typedef gdcm::Attribute<0x0054, 0x0200> StartAngle; typedef gdcm::Attribute<0x0054, 0x0202> TypeOfDetectorMotion; typedef gdcm::Attribute<0x0054, 0x0210> TriggerVector; typedef gdcm::Attribute<0x0054, 0x0211> NumberOfTriggersInPhase; typedef gdcm::Attribute<0x0054, 0x0220> ViewCodeSequence; typedef gdcm::Attribute<0x0054, 0x0222> ViewModifierCodeSequence; typedef gdcm::Attribute<0x0054, 0x0300> RadionuclideCodeSequence; typedef gdcm::Attribute<0x0054, 0x0302> AdministrationRouteCodeSequence; typedef gdcm::Attribute<0x0054, 0x0304> RadiopharmaceuticalCodeSequence; typedef gdcm::Attribute<0x0054, 0x0306> CalibrationDataSequence; typedef gdcm::Attribute<0x0054, 0x0308> EnergyWindowNumber; typedef gdcm::Attribute<0x0054, 0x0400> ImageID; typedef gdcm::Attribute<0x0054, 0x0410> PatientOrientationCodeSequence; typedef gdcm::Attribute<0x0054, 0x0412> PatientOrientationModifierCodeSequence; typedef gdcm::Attribute<0x0054, 0x0414> PatientGantryRelationshipCodeSequence; typedef gdcm::Attribute<0x0054, 0x0500> SliceProgressionDirection; typedef gdcm::Attribute<0x0054, 0x1000> SeriesType; typedef gdcm::Attribute<0x0054, 0x1001> Units; typedef gdcm::Attribute<0x0054, 0x1002> CountsSource; typedef gdcm::Attribute<0x0054, 0x1004> ReprojectionMethod; typedef gdcm::Attribute<0x0054, 0x1006> SUVType; typedef gdcm::Attribute<0x0054, 0x1100> RandomsCorrectionMethod; typedef gdcm::Attribute<0x0054, 0x1101> AttenuationCorrectionMethod; typedef gdcm::Attribute<0x0054, 0x1102> DecayCorrection; typedef gdcm::Attribute<0x0054, 0x1103> ReconstructionMethod; typedef gdcm::Attribute<0x0054, 0x1104> DetectorLinesOfResponseUsed; typedef gdcm::Attribute<0x0054, 0x1105> ScatterCorrectionMethod; typedef gdcm::Attribute<0x0054, 0x1200> AxialAcceptance; typedef gdcm::Attribute<0x0054, 0x1201> AxialMash; typedef gdcm::Attribute<0x0054, 0x1202> TransverseMash; typedef gdcm::Attribute<0x0054, 0x1203> DetectorElementSize; typedef gdcm::Attribute<0x0054, 0x1210> CoincidenceWindowWidth; typedef gdcm::Attribute<0x0054, 0x1220> SecondaryCountsType; typedef gdcm::Attribute<0x0054, 0x1300> FrameReferenceTime; typedef gdcm::Attribute<0x0054, 0x1310> PrimaryPromptsCountsAccumulated; typedef gdcm::Attribute<0x0054, 0x1311> SecondaryCountsAccumulated; typedef gdcm::Attribute<0x0054, 0x1320> SliceSensitivityFactor; typedef gdcm::Attribute<0x0054, 0x1321> DecayFactor; typedef gdcm::Attribute<0x0054, 0x1322> DoseCalibrationFactor; typedef gdcm::Attribute<0x0054, 0x1323> ScatterFractionFactor; typedef gdcm::Attribute<0x0054, 0x1324> DeadTimeFactor; typedef gdcm::Attribute<0x0054, 0x1330> ImageIndex; typedef gdcm::Attribute<0x0054, 0x1400> CountsIncluded; typedef gdcm::Attribute<0x0054, 0x1401> DeadTimeCorrectionFlag; typedef gdcm::Attribute<0x0060, 0x3000> HistogramSequence; typedef gdcm::Attribute<0x0060, 0x3002> HistogramNumberOfBins; typedef gdcm::Attribute<0x0060, 0x3004> HistogramFirstBinValue; typedef gdcm::Attribute<0x0060, 0x3006> HistogramLastBinValue; typedef gdcm::Attribute<0x0060, 0x3008> HistogramBinWidth; typedef gdcm::Attribute<0x0060, 0x3010> HistogramExplanation; typedef gdcm::Attribute<0x0060, 0x3020> HistogramData; typedef gdcm::Attribute<0x0062, 0x0001> SegmentationType; typedef gdcm::Attribute<0x0062, 0x0002> SegmentSequence; typedef gdcm::Attribute<0x0062, 0x0003> SegmentedPropertyCategoryCodeSequence; typedef gdcm::Attribute<0x0062, 0x0004> SegmentNumber; typedef gdcm::Attribute<0x0062, 0x0005> SegmentLabel; typedef gdcm::Attribute<0x0062, 0x0006> SegmentDescription; typedef gdcm::Attribute<0x0062, 0x0008> SegmentAlgorithmType; typedef gdcm::Attribute<0x0062, 0x0009> SegmentAlgorithmName; typedef gdcm::Attribute<0x0062, 0x000a> SegmentIdentificationSequence; typedef gdcm::Attribute<0x0062, 0x000b> ReferencedSegmentNumber; typedef gdcm::Attribute<0x0062, 0x000c> RecommendedDisplayGrayscaleValue; typedef gdcm::Attribute<0x0062, 0x000d> RecommendedDisplayCIELabValue; typedef gdcm::Attribute<0x0062, 0x000e> MaximumFractionalValue; typedef gdcm::Attribute<0x0062, 0x000f> SegmentedPropertyTypeCodeSequence; typedef gdcm::Attribute<0x0062, 0x0010> SegmentationFractionalType; typedef gdcm::Attribute<0x0064, 0x0002> DeformableRegistrationSequence; typedef gdcm::Attribute<0x0064, 0x0003> SourceFrameOfReferenceUID; typedef gdcm::Attribute<0x0064, 0x0005> DeformableRegistrationGridSequence; typedef gdcm::Attribute<0x0064, 0x0007> GridDimensions; typedef gdcm::Attribute<0x0064, 0x0008> GridResolution; typedef gdcm::Attribute<0x0064, 0x0009> VectorGridData; typedef gdcm::Attribute<0x0064, 0x000f> PreDeformationMatrixRegistrationSequence; typedef gdcm::Attribute<0x0064, 0x0010> PostDeformationMatrixRegistrationSequence; typedef gdcm::Attribute<0x0066, 0x0001> NumberOfSurfaces; typedef gdcm::Attribute<0x0066, 0x0002> SurfaceSequence; typedef gdcm::Attribute<0x0066, 0x0003> SurfaceNumber; typedef gdcm::Attribute<0x0066, 0x0004> SurfaceComments; typedef gdcm::Attribute<0x0066, 0x0009> SurfaceProcessing; typedef gdcm::Attribute<0x0066, 0x000a> SurfaceProcessingRatio; typedef gdcm::Attribute<0x0066, 0x000b> SurfaceProcessingDescription; typedef gdcm::Attribute<0x0066, 0x000c> RecommendedPresentationOpacity; typedef gdcm::Attribute<0x0066, 0x000d> RecommendedPresentationType; typedef gdcm::Attribute<0x0066, 0x000e> FiniteVolume; typedef gdcm::Attribute<0x0066, 0x0010> Manifold; typedef gdcm::Attribute<0x0066, 0x0011> SurfacePointsSequence; typedef gdcm::Attribute<0x0066, 0x0012> SurfacePointsNormalsSequence; typedef gdcm::Attribute<0x0066, 0x0013> SurfaceMeshPrimitivesSequence; typedef gdcm::Attribute<0x0066, 0x0015> NumberOfSurfacePoints; typedef gdcm::Attribute<0x0066, 0x0016> PointCoordinatesData; typedef gdcm::Attribute<0x0066, 0x0017> PointPositionAccuracy; typedef gdcm::Attribute<0x0066, 0x0018> MeanPointDistance; typedef gdcm::Attribute<0x0066, 0x0019> MaximumPointDistance; typedef gdcm::Attribute<0x0066, 0x001a> PointsBoundingBoxCoordinates; typedef gdcm::Attribute<0x0066, 0x001b> AxisOfRotation; typedef gdcm::Attribute<0x0066, 0x001c> CenterOfRotation; typedef gdcm::Attribute<0x0066, 0x001e> NumberOfVectors; typedef gdcm::Attribute<0x0066, 0x001f> VectorDimensionality; typedef gdcm::Attribute<0x0066, 0x0020> VectorAccuracy; typedef gdcm::Attribute<0x0066, 0x0021> VectorCoordinateData; typedef gdcm::Attribute<0x0066, 0x0023> TrianglePointIndexList; typedef gdcm::Attribute<0x0066, 0x0024> EdgePointIndexList; typedef gdcm::Attribute<0x0066, 0x0025> VertexPointIndexList; typedef gdcm::Attribute<0x0066, 0x0026> TriangleStripSequence; typedef gdcm::Attribute<0x0066, 0x0027> TriangleFanSequence; typedef gdcm::Attribute<0x0066, 0x0028> LineSequence; typedef gdcm::Attribute<0x0066, 0x0029> PrimitivePointIndexList; typedef gdcm::Attribute<0x0066, 0x002a> SurfaceCount; typedef gdcm::Attribute<0x0066, 0x002b> ReferencedSurfaceSequence; typedef gdcm::Attribute<0x0066, 0x002c> ReferencedSurfaceNumber; typedef gdcm::Attribute<0x0066, 0x002d> SegmentSurfaceGenerationAlgorithmIdentificationSequence; typedef gdcm::Attribute<0x0066, 0x002e> SegmentSurfaceSourceInstanceSequence; typedef gdcm::Attribute<0x0066, 0x002f> AlgorithmFamilyCodeSequence; typedef gdcm::Attribute<0x0066, 0x0030> AlgorithmNameCodeSequence; typedef gdcm::Attribute<0x0066, 0x0031> AlgorithmVersion; typedef gdcm::Attribute<0x0066, 0x0032> AlgorithmParameters; typedef gdcm::Attribute<0x0066, 0x0034> FacetSequence; typedef gdcm::Attribute<0x0066, 0x0035> SurfaceProcessingAlgorithmIdentificationSequence; typedef gdcm::Attribute<0x0066, 0x0036> AlgorithmName; typedef gdcm::Attribute<0x0068, 0x6210> ImplantSize; typedef gdcm::Attribute<0x0068, 0x6221> ImplantTemplateVersion; typedef gdcm::Attribute<0x0068, 0x6222> ReplacedImplantTemplateSequence; typedef gdcm::Attribute<0x0068, 0x6223> ImplantType; typedef gdcm::Attribute<0x0068, 0x6224> DerivationImplantTemplateSequence; typedef gdcm::Attribute<0x0068, 0x6225> OriginalImplantTemplateSequence; typedef gdcm::Attribute<0x0068, 0x6226> EffectiveDateTime; typedef gdcm::Attribute<0x0068, 0x6230> ImplantTargetAnatomySequence; typedef gdcm::Attribute<0x0068, 0x6260> InformationFromManufacturerSequence; typedef gdcm::Attribute<0x0068, 0x6265> NotificationFromManufacturerSequence; typedef gdcm::Attribute<0x0068, 0x6270> InformationIssueDateTime; typedef gdcm::Attribute<0x0068, 0x6280> InformationSummary; typedef gdcm::Attribute<0x0068, 0x62a0> ImplantRegulatoryDisapprovalCodeSequence; typedef gdcm::Attribute<0x0068, 0x62a5> OverallTemplateSpatialTolerance; typedef gdcm::Attribute<0x0068, 0x62c0> HPGLDocumentSequence; typedef gdcm::Attribute<0x0068, 0x62d0> HPGLDocumentID; typedef gdcm::Attribute<0x0068, 0x62d5> HPGLDocumentLabel; typedef gdcm::Attribute<0x0068, 0x62e0> ViewOrientationCodeSequence; typedef gdcm::Attribute<0x0068, 0x62f0> ViewOrientationModifier; typedef gdcm::Attribute<0x0068, 0x62f2> HPGLDocumentScaling; typedef gdcm::Attribute<0x0068, 0x6300> HPGLDocument; typedef gdcm::Attribute<0x0068, 0x6310> HPGLContourPenNumber; typedef gdcm::Attribute<0x0068, 0x6320> HPGLPenSequence; typedef gdcm::Attribute<0x0068, 0x6330> HPGLPenNumber; typedef gdcm::Attribute<0x0068, 0x6340> HPGLPenLabel; typedef gdcm::Attribute<0x0068, 0x6345> HPGLPenDescription; typedef gdcm::Attribute<0x0068, 0x6346> RecommendedRotationPoint; typedef gdcm::Attribute<0x0068, 0x6347> BoundingRectangle; typedef gdcm::Attribute<0x0068, 0x6350> ImplantTemplate3DModelSurfaceNumber; typedef gdcm::Attribute<0x0068, 0x6360> SurfaceModelDescriptionSequence; typedef gdcm::Attribute<0x0068, 0x6380> SurfaceModelLabel; typedef gdcm::Attribute<0x0068, 0x6390> SurfaceModelScalingFactor; typedef gdcm::Attribute<0x0068, 0x63a0> MaterialsCodeSequence; typedef gdcm::Attribute<0x0068, 0x63a4> CoatingMaterialsCodeSequence; typedef gdcm::Attribute<0x0068, 0x63a8> ImplantTypeCodeSequence; typedef gdcm::Attribute<0x0068, 0x63ac> FixationMethodCodeSequence; typedef gdcm::Attribute<0x0068, 0x63b0> MatingFeatureSetsSequence; typedef gdcm::Attribute<0x0068, 0x63c0> MatingFeatureSetID; typedef gdcm::Attribute<0x0068, 0x63d0> MatingFeatureSetLabel; typedef gdcm::Attribute<0x0068, 0x63e0> MatingFeatureSequence; typedef gdcm::Attribute<0x0068, 0x63f0> MatingFeatureID; typedef gdcm::Attribute<0x0068, 0x6400> MatingFeatureDegreeOfFreedomSequence; typedef gdcm::Attribute<0x0068, 0x6410> DegreeOfFreedomID; typedef gdcm::Attribute<0x0068, 0x6420> DegreeOfFreedomType; typedef gdcm::Attribute<0x0068, 0x6430> TwoDMatingFeatureCoordinatesSequence; typedef gdcm::Attribute<0x0068, 0x6440> ReferencedHPGLDocumentID; typedef gdcm::Attribute<0x0068, 0x6450> TwoDMatingPoint; typedef gdcm::Attribute<0x0068, 0x6460> TwoDMatingAxes; typedef gdcm::Attribute<0x0068, 0x6470> TwoDDegreeOfFreedomSequence; typedef gdcm::Attribute<0x0068, 0x6490> ThreeDDegreeOfFreedomAxis; typedef gdcm::Attribute<0x0068, 0x64a0> RangeOfFreedom; typedef gdcm::Attribute<0x0068, 0x64c0> ThreeDMatingPoint; typedef gdcm::Attribute<0x0068, 0x64d0> ThreeDMatingAxes; typedef gdcm::Attribute<0x0068, 0x64f0> TwoDDegreeOfFreedomAxis; typedef gdcm::Attribute<0x0068, 0x6500> PlanningLandmarkPointSequence; typedef gdcm::Attribute<0x0068, 0x6510> PlanningLandmarkLineSequence; typedef gdcm::Attribute<0x0068, 0x6520> PlanningLandmarkPlaneSequence; typedef gdcm::Attribute<0x0068, 0x6530> PlanningLandmarkID; typedef gdcm::Attribute<0x0068, 0x6540> PlanningLandmarkDescription; typedef gdcm::Attribute<0x0068, 0x6545> PlanningLandmarkIdentificationCodeSequence; typedef gdcm::Attribute<0x0068, 0x6550> TwoDPointCoordinatesSequence; typedef gdcm::Attribute<0x0068, 0x6560> TwoDPointCoordinates; typedef gdcm::Attribute<0x0068, 0x6590> ThreeDPointCoordinates; typedef gdcm::Attribute<0x0068, 0x65a0> TwoDLineCoordinatesSequence; typedef gdcm::Attribute<0x0068, 0x65b0> TwoDLineCoordinates; typedef gdcm::Attribute<0x0068, 0x65d0> ThreeDLineCoordinates; typedef gdcm::Attribute<0x0068, 0x65e0> TwoDPlaneCoordinatesSequence; typedef gdcm::Attribute<0x0068, 0x65f0> TwoDPlaneIntersection; typedef gdcm::Attribute<0x0068, 0x6610> ThreeDPlaneOrigin; typedef gdcm::Attribute<0x0068, 0x6620> ThreeDPlaneNormal; typedef gdcm::Attribute<0x0070, 0x0001> GraphicAnnotationSequence; typedef gdcm::Attribute<0x0070, 0x0002> GraphicLayer; typedef gdcm::Attribute<0x0070, 0x0003> BoundingBoxAnnotationUnits; typedef gdcm::Attribute<0x0070, 0x0004> AnchorPointAnnotationUnits; typedef gdcm::Attribute<0x0070, 0x0005> GraphicAnnotationUnits; typedef gdcm::Attribute<0x0070, 0x0006> UnformattedTextValue; typedef gdcm::Attribute<0x0070, 0x0008> TextObjectSequence; typedef gdcm::Attribute<0x0070, 0x0009> GraphicObjectSequence; typedef gdcm::Attribute<0x0070, 0x0010> BoundingBoxTopLeftHandCorner; typedef gdcm::Attribute<0x0070, 0x0011> BoundingBoxBottomRightHandCorner; typedef gdcm::Attribute<0x0070, 0x0012> BoundingBoxTextHorizontalJustification; typedef gdcm::Attribute<0x0070, 0x0014> AnchorPoint; typedef gdcm::Attribute<0x0070, 0x0015> AnchorPointVisibility; typedef gdcm::Attribute<0x0070, 0x0020> GraphicDimensions; typedef gdcm::Attribute<0x0070, 0x0021> NumberOfGraphicPoints; typedef gdcm::Attribute<0x0070, 0x0022> GraphicData; typedef gdcm::Attribute<0x0070, 0x0023> GraphicType; typedef gdcm::Attribute<0x0070, 0x0024> GraphicFilled; typedef gdcm::Attribute<0x0070, 0x0040> ImageRotationRetired; typedef gdcm::Attribute<0x0070, 0x0041> ImageHorizontalFlip; typedef gdcm::Attribute<0x0070, 0x0042> ImageRotation; typedef gdcm::Attribute<0x0070, 0x0050> DisplayedAreaTopLeftHandCornerTrial; typedef gdcm::Attribute<0x0070, 0x0051> DisplayedAreaBottomRightHandCornerTrial; typedef gdcm::Attribute<0x0070, 0x0052> DisplayedAreaTopLeftHandCorner; typedef gdcm::Attribute<0x0070, 0x0053> DisplayedAreaBottomRightHandCorner; typedef gdcm::Attribute<0x0070, 0x005a> DisplayedAreaSelectionSequence; typedef gdcm::Attribute<0x0070, 0x0060> GraphicLayerSequence; typedef gdcm::Attribute<0x0070, 0x0062> GraphicLayerOrder; typedef gdcm::Attribute<0x0070, 0x0066> GraphicLayerRecommendedDisplayGrayscaleValue; typedef gdcm::Attribute<0x0070, 0x0067> GraphicLayerRecommendedDisplayRGBValue; typedef gdcm::Attribute<0x0070, 0x0068> GraphicLayerDescription; typedef gdcm::Attribute<0x0070, 0x0080> ContentLabel; typedef gdcm::Attribute<0x0070, 0x0081> ContentDescription; typedef gdcm::Attribute<0x0070, 0x0082> PresentationCreationDate; typedef gdcm::Attribute<0x0070, 0x0083> PresentationCreationTime; typedef gdcm::Attribute<0x0070, 0x0084> ContentCreatorName; typedef gdcm::Attribute<0x0070, 0x0086> ContentCreatorIdentificationCodeSequence; typedef gdcm::Attribute<0x0070, 0x0087> AlternateContentDescriptionSequence; typedef gdcm::Attribute<0x0070, 0x0100> PresentationSizeMode; typedef gdcm::Attribute<0x0070, 0x0101> PresentationPixelSpacing; typedef gdcm::Attribute<0x0070, 0x0102> PresentationPixelAspectRatio; typedef gdcm::Attribute<0x0070, 0x0103> PresentationPixelMagnificationRatio; typedef gdcm::Attribute<0x0070, 0x0207> GraphicGroupLabel; typedef gdcm::Attribute<0x0070, 0x0208> GraphicGroupDescription; typedef gdcm::Attribute<0x0070, 0x0209> CompoundGraphicSequence; typedef gdcm::Attribute<0x0070, 0x0226> CompoundGraphicInstanceID; typedef gdcm::Attribute<0x0070, 0x0227> FontName; typedef gdcm::Attribute<0x0070, 0x0228> FontNameType; typedef gdcm::Attribute<0x0070, 0x0229> CSSFontName; typedef gdcm::Attribute<0x0070, 0x0230> RotationAngle; typedef gdcm::Attribute<0x0070, 0x0231> TextStyleSequence; typedef gdcm::Attribute<0x0070, 0x0232> LineStyleSequence; typedef gdcm::Attribute<0x0070, 0x0233> FillStyleSequence; typedef gdcm::Attribute<0x0070, 0x0234> GraphicGroupSequence; typedef gdcm::Attribute<0x0070, 0x0241> TextColorCIELabValue; typedef gdcm::Attribute<0x0070, 0x0242> HorizontalAlignment; typedef gdcm::Attribute<0x0070, 0x0243> VerticalAlignment; typedef gdcm::Attribute<0x0070, 0x0244> ShadowStyle; typedef gdcm::Attribute<0x0070, 0x0245> ShadowOffsetX; typedef gdcm::Attribute<0x0070, 0x0246> ShadowOffsetY; typedef gdcm::Attribute<0x0070, 0x0247> ShadowColorCIELabValue; typedef gdcm::Attribute<0x0070, 0x0248> Underlined; typedef gdcm::Attribute<0x0070, 0x0249> Bold; typedef gdcm::Attribute<0x0070, 0x0250> Italic; typedef gdcm::Attribute<0x0070, 0x0251> PatternOnColorCIELabValue; typedef gdcm::Attribute<0x0070, 0x0252> PatternOffColorCIELabValue; typedef gdcm::Attribute<0x0070, 0x0253> LineThickness; typedef gdcm::Attribute<0x0070, 0x0254> LineDashingStyle; typedef gdcm::Attribute<0x0070, 0x0255> LinePattern; typedef gdcm::Attribute<0x0070, 0x0256> FillPattern; typedef gdcm::Attribute<0x0070, 0x0257> FillMode; typedef gdcm::Attribute<0x0070, 0x0258> ShadowOpacity; typedef gdcm::Attribute<0x0070, 0x0261> GapLength; typedef gdcm::Attribute<0x0070, 0x0262> DiameterOfVisibility; typedef gdcm::Attribute<0x0070, 0x0273> RotationPoint; typedef gdcm::Attribute<0x0070, 0x0274> TickAlignment; typedef gdcm::Attribute<0x0070, 0x0278> ShowTickLabel; typedef gdcm::Attribute<0x0070, 0x0279> TickLabelAlignment; typedef gdcm::Attribute<0x0070, 0x0282> CompoundGraphicUnits; typedef gdcm::Attribute<0x0070, 0x0284> PatternOnOpacity; typedef gdcm::Attribute<0x0070, 0x0285> PatternOffOpacity; typedef gdcm::Attribute<0x0070, 0x0287> MajorTicksSequence; typedef gdcm::Attribute<0x0070, 0x0288> TickPosition; typedef gdcm::Attribute<0x0070, 0x0289> TickLabel; typedef gdcm::Attribute<0x0070, 0x0294> CompoundGraphicType; typedef gdcm::Attribute<0x0070, 0x0295> GraphicGroupID; typedef gdcm::Attribute<0x0070, 0x0306> ShapeType; typedef gdcm::Attribute<0x0070, 0x0308> RegistrationSequence; typedef gdcm::Attribute<0x0070, 0x0309> MatrixRegistrationSequence; typedef gdcm::Attribute<0x0070, 0x030a> MatrixSequence; typedef gdcm::Attribute<0x0070, 0x030c> FrameOfReferenceTransformationMatrixType; typedef gdcm::Attribute<0x0070, 0x030d> RegistrationTypeCodeSequence; typedef gdcm::Attribute<0x0070, 0x030f> FiducialDescription; typedef gdcm::Attribute<0x0070, 0x0310> FiducialIdentifier; typedef gdcm::Attribute<0x0070, 0x0311> FiducialIdentifierCodeSequence; typedef gdcm::Attribute<0x0070, 0x0312> ContourUncertaintyRadius; typedef gdcm::Attribute<0x0070, 0x0314> UsedFiducialsSequence; typedef gdcm::Attribute<0x0070, 0x0318> GraphicCoordinatesDataSequence; typedef gdcm::Attribute<0x0070, 0x031a> FiducialUID; typedef gdcm::Attribute<0x0070, 0x031c> FiducialSetSequence; typedef gdcm::Attribute<0x0070, 0x031e> FiducialSequence; typedef gdcm::Attribute<0x0070, 0x0401> GraphicLayerRecommendedDisplayCIELabValue; typedef gdcm::Attribute<0x0070, 0x0402> BlendingSequence; typedef gdcm::Attribute<0x0070, 0x0403> RelativeOpacity; typedef gdcm::Attribute<0x0070, 0x0404> ReferencedSpatialRegistrationSequence; typedef gdcm::Attribute<0x0070, 0x0405> BlendingPosition; typedef gdcm::Attribute<0x0072, 0x0002> HangingProtocolName; typedef gdcm::Attribute<0x0072, 0x0004> HangingProtocolDescription; typedef gdcm::Attribute<0x0072, 0x0006> HangingProtocolLevel; typedef gdcm::Attribute<0x0072, 0x0008> HangingProtocolCreator; typedef gdcm::Attribute<0x0072, 0x000a> HangingProtocolCreationDateTime; typedef gdcm::Attribute<0x0072, 0x000c> HangingProtocolDefinitionSequence; typedef gdcm::Attribute<0x0072, 0x000e> HangingProtocolUserIdentificationCodeSequence; typedef gdcm::Attribute<0x0072, 0x0010> HangingProtocolUserGroupName; typedef gdcm::Attribute<0x0072, 0x0012> SourceHangingProtocolSequence; typedef gdcm::Attribute<0x0072, 0x0014> NumberOfPriorsReferenced; typedef gdcm::Attribute<0x0072, 0x0020> ImageSetsSequence; typedef gdcm::Attribute<0x0072, 0x0022> ImageSetSelectorSequence; typedef gdcm::Attribute<0x0072, 0x0024> ImageSetSelectorUsageFlag; typedef gdcm::Attribute<0x0072, 0x0026> SelectorAttribute; typedef gdcm::Attribute<0x0072, 0x0028> SelectorValueNumber; typedef gdcm::Attribute<0x0072, 0x0030> TimeBasedImageSetsSequence; typedef gdcm::Attribute<0x0072, 0x0032> ImageSetNumber; typedef gdcm::Attribute<0x0072, 0x0034> ImageSetSelectorCategory; typedef gdcm::Attribute<0x0072, 0x0038> RelativeTime; typedef gdcm::Attribute<0x0072, 0x003a> RelativeTimeUnits; typedef gdcm::Attribute<0x0072, 0x003c> AbstractPriorValue; typedef gdcm::Attribute<0x0072, 0x003e> AbstractPriorCodeSequence; typedef gdcm::Attribute<0x0072, 0x0040> ImageSetLabel; typedef gdcm::Attribute<0x0072, 0x0050> SelectorAttributeVR; typedef gdcm::Attribute<0x0072, 0x0052> SelectorSequencePointer; typedef gdcm::Attribute<0x0072, 0x0054> SelectorSequencePointerPrivateCreator; typedef gdcm::Attribute<0x0072, 0x0056> SelectorAttributePrivateCreator; typedef gdcm::Attribute<0x0072, 0x0060> SelectorATValue; typedef gdcm::Attribute<0x0072, 0x0062> SelectorCSValue; typedef gdcm::Attribute<0x0072, 0x0064> SelectorISValue; typedef gdcm::Attribute<0x0072, 0x0066> SelectorLOValue; typedef gdcm::Attribute<0x0072, 0x0068> SelectorLTValue; typedef gdcm::Attribute<0x0072, 0x006a> SelectorPNValue; typedef gdcm::Attribute<0x0072, 0x006c> SelectorSHValue; typedef gdcm::Attribute<0x0072, 0x006e> SelectorSTValue; typedef gdcm::Attribute<0x0072, 0x0070> SelectorUTValue; typedef gdcm::Attribute<0x0072, 0x0072> SelectorDSValue; typedef gdcm::Attribute<0x0072, 0x0074> SelectorFDValue; typedef gdcm::Attribute<0x0072, 0x0076> SelectorFLValue; typedef gdcm::Attribute<0x0072, 0x0078> SelectorULValue; typedef gdcm::Attribute<0x0072, 0x007a> SelectorUSValue; typedef gdcm::Attribute<0x0072, 0x007c> SelectorSLValue; typedef gdcm::Attribute<0x0072, 0x007e> SelectorSSValue; typedef gdcm::Attribute<0x0072, 0x0080> SelectorCodeSequenceValue; typedef gdcm::Attribute<0x0072, 0x0100> NumberOfScreens; typedef gdcm::Attribute<0x0072, 0x0102> NominalScreenDefinitionSequence; typedef gdcm::Attribute<0x0072, 0x0104> NumberOfVerticalPixels; typedef gdcm::Attribute<0x0072, 0x0106> NumberOfHorizontalPixels; typedef gdcm::Attribute<0x0072, 0x0108> DisplayEnvironmentSpatialPosition; typedef gdcm::Attribute<0x0072, 0x010a> ScreenMinimumGrayscaleBitDepth; typedef gdcm::Attribute<0x0072, 0x010c> ScreenMinimumColorBitDepth; typedef gdcm::Attribute<0x0072, 0x010e> ApplicationMaximumRepaintTime; typedef gdcm::Attribute<0x0072, 0x0200> DisplaySetsSequence; typedef gdcm::Attribute<0x0072, 0x0202> DisplaySetNumber; typedef gdcm::Attribute<0x0072, 0x0203> DisplaySetLabel; typedef gdcm::Attribute<0x0072, 0x0204> DisplaySetPresentationGroup; typedef gdcm::Attribute<0x0072, 0x0206> DisplaySetPresentationGroupDescription; typedef gdcm::Attribute<0x0072, 0x0208> PartialDataDisplayHandling; typedef gdcm::Attribute<0x0072, 0x0210> SynchronizedScrollingSequence; typedef gdcm::Attribute<0x0072, 0x0212> DisplaySetScrollingGroup; typedef gdcm::Attribute<0x0072, 0x0214> NavigationIndicatorSequence; typedef gdcm::Attribute<0x0072, 0x0216> NavigationDisplaySet; typedef gdcm::Attribute<0x0072, 0x0218> ReferenceDisplaySets; typedef gdcm::Attribute<0x0072, 0x0300> ImageBoxesSequence; typedef gdcm::Attribute<0x0072, 0x0302> ImageBoxNumber; typedef gdcm::Attribute<0x0072, 0x0304> ImageBoxLayoutType; typedef gdcm::Attribute<0x0072, 0x0306> ImageBoxTileHorizontalDimension; typedef gdcm::Attribute<0x0072, 0x0308> ImageBoxTileVerticalDimension; typedef gdcm::Attribute<0x0072, 0x0310> ImageBoxScrollDirection; typedef gdcm::Attribute<0x0072, 0x0312> ImageBoxSmallScrollType; typedef gdcm::Attribute<0x0072, 0x0314> ImageBoxSmallScrollAmount; typedef gdcm::Attribute<0x0072, 0x0316> ImageBoxLargeScrollType; typedef gdcm::Attribute<0x0072, 0x0318> ImageBoxLargeScrollAmount; typedef gdcm::Attribute<0x0072, 0x0320> ImageBoxOverlapPriority; typedef gdcm::Attribute<0x0072, 0x0330> CineRelativeToRealTime; typedef gdcm::Attribute<0x0072, 0x0400> FilterOperationsSequence; typedef gdcm::Attribute<0x0072, 0x0402> FilterByCategory; typedef gdcm::Attribute<0x0072, 0x0404> FilterByAttributePresence; typedef gdcm::Attribute<0x0072, 0x0406> FilterByOperator; typedef gdcm::Attribute<0x0072, 0x0420> StructuredDisplayBackgroundCIELabValue; typedef gdcm::Attribute<0x0072, 0x0421> EmptyImageBoxCIELabValue; typedef gdcm::Attribute<0x0072, 0x0422> StructuredDisplayImageBoxSequence; typedef gdcm::Attribute<0x0072, 0x0424> StructuredDisplayTextBoxSequence; typedef gdcm::Attribute<0x0072, 0x0427> ReferencedFirstFrameSequence; typedef gdcm::Attribute<0x0072, 0x0430> ImageBoxSynchronizationSequence; typedef gdcm::Attribute<0x0072, 0x0432> SynchronizedImageBoxList; typedef gdcm::Attribute<0x0072, 0x0434> TypeOfSynchronization; typedef gdcm::Attribute<0x0072, 0x0500> BlendingOperationType; typedef gdcm::Attribute<0x0072, 0x0510> ReformattingOperationType; typedef gdcm::Attribute<0x0072, 0x0512> ReformattingThickness; typedef gdcm::Attribute<0x0072, 0x0514> ReformattingInterval; typedef gdcm::Attribute<0x0072, 0x0516> ReformattingOperationInitialViewDirection; typedef gdcm::Attribute<0x0072, 0x0520> ThreeDRenderingType; typedef gdcm::Attribute<0x0072, 0x0600> SortingOperationsSequence; typedef gdcm::Attribute<0x0072, 0x0602> SortByCategory; typedef gdcm::Attribute<0x0072, 0x0604> SortingDirection; typedef gdcm::Attribute<0x0072, 0x0700> DisplaySetPatientOrientation; typedef gdcm::Attribute<0x0072, 0x0702> VOIType; typedef gdcm::Attribute<0x0072, 0x0704> PseudoColorType; typedef gdcm::Attribute<0x0072, 0x0705> PseudoColorPaletteInstanceReferenceSequence; typedef gdcm::Attribute<0x0072, 0x0706> ShowGrayscaleInverted; typedef gdcm::Attribute<0x0072, 0x0710> ShowImageTrueSizeFlag; typedef gdcm::Attribute<0x0072, 0x0712> ShowGraphicAnnotationFlag; typedef gdcm::Attribute<0x0072, 0x0714> ShowPatientDemographicsFlag; typedef gdcm::Attribute<0x0072, 0x0716> ShowAcquisitionTechniquesFlag; typedef gdcm::Attribute<0x0072, 0x0717> DisplaySetHorizontalJustification; typedef gdcm::Attribute<0x0072, 0x0718> DisplaySetVerticalJustification; typedef gdcm::Attribute<0x0074, 0x0120> ContinuationStartMeterset; typedef gdcm::Attribute<0x0074, 0x0121> ContinuationEndMeterset; typedef gdcm::Attribute<0x0074, 0x1000> ProcedureStepState; typedef gdcm::Attribute<0x0074, 0x1002> ProcedureStepProgressInformationSequence; typedef gdcm::Attribute<0x0074, 0x1004> ProcedureStepProgress; typedef gdcm::Attribute<0x0074, 0x1006> ProcedureStepProgressDescription; typedef gdcm::Attribute<0x0074, 0x1008> ProcedureStepCommunicationsURISequence; typedef gdcm::Attribute<0x0074, 0x100a> ContactURI; typedef gdcm::Attribute<0x0074, 0x100c> ContactDisplayName; typedef gdcm::Attribute<0x0074, 0x100e> ProcedureStepDiscontinuationReasonCodeSequence; typedef gdcm::Attribute<0x0074, 0x1020> BeamTaskSequence; typedef gdcm::Attribute<0x0074, 0x1022> BeamTaskType; typedef gdcm::Attribute<0x0074, 0x1024> BeamOrderIndexTrial; typedef gdcm::Attribute<0x0074, 0x1026> TableTopVerticalAdjustedPosition; typedef gdcm::Attribute<0x0074, 0x1027> TableTopLongitudinalAdjustedPosition; typedef gdcm::Attribute<0x0074, 0x1028> TableTopLateralAdjustedPosition; typedef gdcm::Attribute<0x0074, 0x102a> PatientSupportAdjustedAngle; typedef gdcm::Attribute<0x0074, 0x102b> TableTopEccentricAdjustedAngle; typedef gdcm::Attribute<0x0074, 0x102c> TableTopPitchAdjustedAngle; typedef gdcm::Attribute<0x0074, 0x102d> TableTopRollAdjustedAngle; typedef gdcm::Attribute<0x0074, 0x1030> DeliveryVerificationImageSequence; typedef gdcm::Attribute<0x0074, 0x1032> VerificationImageTiming; typedef gdcm::Attribute<0x0074, 0x1034> DoubleExposureFlag; typedef gdcm::Attribute<0x0074, 0x1036> DoubleExposureOrdering; typedef gdcm::Attribute<0x0074, 0x1038> DoubleExposureMetersetTrial; typedef gdcm::Attribute<0x0074, 0x103a> DoubleExposureFieldDeltaTrial; typedef gdcm::Attribute<0x0074, 0x1040> RelatedReferenceRTImageSequence; typedef gdcm::Attribute<0x0074, 0x1042> GeneralMachineVerificationSequence; typedef gdcm::Attribute<0x0074, 0x1044> ConventionalMachineVerificationSequence; typedef gdcm::Attribute<0x0074, 0x1046> IonMachineVerificationSequence; typedef gdcm::Attribute<0x0074, 0x1048> FailedAttributesSequence; typedef gdcm::Attribute<0x0074, 0x104a> OverriddenAttributesSequence; typedef gdcm::Attribute<0x0074, 0x104c> ConventionalControlPointVerificationSequence; typedef gdcm::Attribute<0x0074, 0x104e> IonControlPointVerificationSequence; typedef gdcm::Attribute<0x0074, 0x1050> AttributeOccurrenceSequence; typedef gdcm::Attribute<0x0074, 0x1052> AttributeOccurrencePointer; typedef gdcm::Attribute<0x0074, 0x1054> AttributeItemSelector; typedef gdcm::Attribute<0x0074, 0x1056> AttributeOccurrencePrivateCreator; typedef gdcm::Attribute<0x0074, 0x1057> SelectorSequencePointerItems; typedef gdcm::Attribute<0x0074, 0x1200> ScheduledProcedureStepPriority; typedef gdcm::Attribute<0x0074, 0x1202> WorklistLabel; typedef gdcm::Attribute<0x0074, 0x1204> ProcedureStepLabel; typedef gdcm::Attribute<0x0074, 0x1210> ScheduledProcessingParametersSequence; typedef gdcm::Attribute<0x0074, 0x1212> PerformedProcessingParametersSequence; typedef gdcm::Attribute<0x0074, 0x1216> UnifiedProcedureStepPerformedProcedureSequence; typedef gdcm::Attribute<0x0074, 0x1220> RelatedProcedureStepSequence; typedef gdcm::Attribute<0x0074, 0x1222> ProcedureStepRelationshipType; typedef gdcm::Attribute<0x0074, 0x1224> ReplacedProcedureStepSequence; typedef gdcm::Attribute<0x0074, 0x1230> DeletionLock; typedef gdcm::Attribute<0x0074, 0x1234> ReceivingAE; typedef gdcm::Attribute<0x0074, 0x1236> RequestingAE; typedef gdcm::Attribute<0x0074, 0x1238> ReasonForCancellation; typedef gdcm::Attribute<0x0074, 0x1242> SCPStatus; typedef gdcm::Attribute<0x0074, 0x1244> SubscriptionListStatus; typedef gdcm::Attribute<0x0074, 0x1246> UnifiedProcedureStepListStatus; typedef gdcm::Attribute<0x0074, 0x1324> BeamOrderIndex; typedef gdcm::Attribute<0x0074, 0x1338> DoubleExposureMeterset; typedef gdcm::Attribute<0x0074, 0x133a> DoubleExposureFieldDelta; typedef gdcm::Attribute<0x0076, 0x0001> ImplantAssemblyTemplateName; typedef gdcm::Attribute<0x0076, 0x0003> ImplantAssemblyTemplateIssuer; typedef gdcm::Attribute<0x0076, 0x0006> ImplantAssemblyTemplateVersion; typedef gdcm::Attribute<0x0076, 0x0008> ReplacedImplantAssemblyTemplateSequence; typedef gdcm::Attribute<0x0076, 0x000a> ImplantAssemblyTemplateType; typedef gdcm::Attribute<0x0076, 0x000c> OriginalImplantAssemblyTemplateSequence; typedef gdcm::Attribute<0x0076, 0x000e> DerivationImplantAssemblyTemplateSequence; typedef gdcm::Attribute<0x0076, 0x0010> ImplantAssemblyTemplateTargetAnatomySequence; typedef gdcm::Attribute<0x0076, 0x0020> ProcedureTypeCodeSequence; typedef gdcm::Attribute<0x0076, 0x0030> SurgicalTechnique; typedef gdcm::Attribute<0x0076, 0x0032> ComponentTypesSequence; typedef gdcm::Attribute<0x0076, 0x0034> ComponentTypeCodeSequence; typedef gdcm::Attribute<0x0076, 0x0036> ExclusiveComponentType; typedef gdcm::Attribute<0x0076, 0x0038> MandatoryComponentType; typedef gdcm::Attribute<0x0076, 0x0040> ComponentSequence; typedef gdcm::Attribute<0x0076, 0x0055> ComponentID; typedef gdcm::Attribute<0x0076, 0x0060> ComponentAssemblySequence; typedef gdcm::Attribute<0x0076, 0x0070> Component1ReferencedID; typedef gdcm::Attribute<0x0076, 0x0080> Component1ReferencedMatingFeatureSetID; typedef gdcm::Attribute<0x0076, 0x0090> Component1ReferencedMatingFeatureID; typedef gdcm::Attribute<0x0076, 0x00a0> Component2ReferencedID; typedef gdcm::Attribute<0x0076, 0x00b0> Component2ReferencedMatingFeatureSetID; typedef gdcm::Attribute<0x0076, 0x00c0> Component2ReferencedMatingFeatureID; typedef gdcm::Attribute<0x0078, 0x0001> ImplantTemplateGroupName; typedef gdcm::Attribute<0x0078, 0x0010> ImplantTemplateGroupDescription; typedef gdcm::Attribute<0x0078, 0x0020> ImplantTemplateGroupIssuer; typedef gdcm::Attribute<0x0078, 0x0024> ImplantTemplateGroupVersion; typedef gdcm::Attribute<0x0078, 0x0026> ReplacedImplantTemplateGroupSequence; typedef gdcm::Attribute<0x0078, 0x0028> ImplantTemplateGroupTargetAnatomySequence; typedef gdcm::Attribute<0x0078, 0x002a> ImplantTemplateGroupMembersSequence; typedef gdcm::Attribute<0x0078, 0x002e> ImplantTemplateGroupMemberID; typedef gdcm::Attribute<0x0078, 0x0050> ThreeDImplantTemplateGroupMemberMatchingPoint; typedef gdcm::Attribute<0x0078, 0x0060> ThreeDImplantTemplateGroupMemberMatchingAxes; typedef gdcm::Attribute<0x0078, 0x0070> ImplantTemplateGroupMemberMatching2DCoordinatesSequence; typedef gdcm::Attribute<0x0078, 0x0090> TwoDImplantTemplateGroupMemberMatchingPoint; typedef gdcm::Attribute<0x0078, 0x00a0> TwoDImplantTemplateGroupMemberMatchingAxes; typedef gdcm::Attribute<0x0078, 0x00b0> ImplantTemplateGroupVariationDimensionSequence; typedef gdcm::Attribute<0x0078, 0x00b2> ImplantTemplateGroupVariationDimensionName; typedef gdcm::Attribute<0x0078, 0x00b4> ImplantTemplateGroupVariationDimensionRankSequence; typedef gdcm::Attribute<0x0078, 0x00b6> ReferencedImplantTemplateGroupMemberID; typedef gdcm::Attribute<0x0078, 0x00b8> ImplantTemplateGroupVariationDimensionRank; typedef gdcm::Attribute<0x0088, 0x0130> StorageMediaFileSetID; typedef gdcm::Attribute<0x0088, 0x0140> StorageMediaFileSetUID; typedef gdcm::Attribute<0x0088, 0x0200> IconImageSequence; typedef gdcm::Attribute<0x0088, 0x0904> TopicTitle; typedef gdcm::Attribute<0x0088, 0x0906> TopicSubject; typedef gdcm::Attribute<0x0088, 0x0910> TopicAuthor; typedef gdcm::Attribute<0x0088, 0x0912> TopicKeywords; typedef gdcm::Attribute<0x0100, 0x0410> SOPInstanceStatus; typedef gdcm::Attribute<0x0100, 0x0420> SOPAuthorizationDateTime; typedef gdcm::Attribute<0x0100, 0x0424> SOPAuthorizationComment; typedef gdcm::Attribute<0x0100, 0x0426> AuthorizationEquipmentCertificationNumber; typedef gdcm::Attribute<0x0400, 0x0005> MACIDNumber; typedef gdcm::Attribute<0x0400, 0x0010> MACCalculationTransferSyntaxUID; typedef gdcm::Attribute<0x0400, 0x0015> MACAlgorithm; typedef gdcm::Attribute<0x0400, 0x0020> DataElementsSigned; typedef gdcm::Attribute<0x0400, 0x0100> DigitalSignatureUID; typedef gdcm::Attribute<0x0400, 0x0105> DigitalSignatureDateTime; typedef gdcm::Attribute<0x0400, 0x0110> CertificateType; typedef gdcm::Attribute<0x0400, 0x0115> CertificateOfSigner; typedef gdcm::Attribute<0x0400, 0x0120> Signature; typedef gdcm::Attribute<0x0400, 0x0305> CertifiedTimestampType; typedef gdcm::Attribute<0x0400, 0x0310> CertifiedTimestamp; typedef gdcm::Attribute<0x0400, 0x0401> DigitalSignaturePurposeCodeSequence; typedef gdcm::Attribute<0x0400, 0x0402> ReferencedDigitalSignatureSequence; typedef gdcm::Attribute<0x0400, 0x0403> ReferencedSOPInstanceMACSequence; typedef gdcm::Attribute<0x0400, 0x0404> MAC; typedef gdcm::Attribute<0x0400, 0x0500> EncryptedAttributesSequence; typedef gdcm::Attribute<0x0400, 0x0510> EncryptedContentTransferSyntaxUID; typedef gdcm::Attribute<0x0400, 0x0520> EncryptedContent; typedef gdcm::Attribute<0x0400, 0x0550> ModifiedAttributesSequence; typedef gdcm::Attribute<0x0400, 0x0561> OriginalAttributesSequence; typedef gdcm::Attribute<0x0400, 0x0562> AttributeModificationDateTime; typedef gdcm::Attribute<0x0400, 0x0563> ModifyingSystem; typedef gdcm::Attribute<0x0400, 0x0564> SourceOfPreviousValues; typedef gdcm::Attribute<0x0400, 0x0565> ReasonForTheAttributeModification; typedef gdcm::Attribute<0x1000, 0x0000> EscapeTriplet; typedef gdcm::Attribute<0x1000, 0x0001> RunLengthTriplet; typedef gdcm::Attribute<0x1000, 0x0002> HuffmanTableSize; typedef gdcm::Attribute<0x1000, 0x0003> HuffmanTableTriplet; typedef gdcm::Attribute<0x1000, 0x0004> ShiftTableSize; typedef gdcm::Attribute<0x1000, 0x0005> ShiftTableTriplet; typedef gdcm::Attribute<0x1010, 0x0000> ZonalMap; typedef gdcm::Attribute<0x2000, 0x0010> NumberOfCopies; typedef gdcm::Attribute<0x2000, 0x001e> PrinterConfigurationSequence; typedef gdcm::Attribute<0x2000, 0x0020> PrintPriority; typedef gdcm::Attribute<0x2000, 0x0030> MediumType; typedef gdcm::Attribute<0x2000, 0x0040> FilmDestination; typedef gdcm::Attribute<0x2000, 0x0050> FilmSessionLabel; typedef gdcm::Attribute<0x2000, 0x0060> MemoryAllocation; typedef gdcm::Attribute<0x2000, 0x0061> MaximumMemoryAllocation; typedef gdcm::Attribute<0x2000, 0x0062> ColorImagePrintingFlag; typedef gdcm::Attribute<0x2000, 0x0063> CollationFlag; typedef gdcm::Attribute<0x2000, 0x0065> AnnotationFlag; typedef gdcm::Attribute<0x2000, 0x0067> ImageOverlayFlag; typedef gdcm::Attribute<0x2000, 0x0069> PresentationLUTFlag; typedef gdcm::Attribute<0x2000, 0x006a> ImageBoxPresentationLUTFlag; typedef gdcm::Attribute<0x2000, 0x00a0> MemoryBitDepth; typedef gdcm::Attribute<0x2000, 0x00a1> PrintingBitDepth; typedef gdcm::Attribute<0x2000, 0x00a2> MediaInstalledSequence; typedef gdcm::Attribute<0x2000, 0x00a4> OtherMediaAvailableSequence; typedef gdcm::Attribute<0x2000, 0x00a8> SupportedImageDisplayFormatsSequence; typedef gdcm::Attribute<0x2000, 0x0500> ReferencedFilmBoxSequence; typedef gdcm::Attribute<0x2000, 0x0510> ReferencedStoredPrintSequence; typedef gdcm::Attribute<0x2010, 0x0010> ImageDisplayFormat; typedef gdcm::Attribute<0x2010, 0x0030> AnnotationDisplayFormatID; typedef gdcm::Attribute<0x2010, 0x0040> FilmOrientation; typedef gdcm::Attribute<0x2010, 0x0050> FilmSizeID; typedef gdcm::Attribute<0x2010, 0x0052> PrinterResolutionID; typedef gdcm::Attribute<0x2010, 0x0054> DefaultPrinterResolutionID; typedef gdcm::Attribute<0x2010, 0x0060> MagnificationType; typedef gdcm::Attribute<0x2010, 0x0080> SmoothingType; typedef gdcm::Attribute<0x2010, 0x00a6> DefaultMagnificationType; typedef gdcm::Attribute<0x2010, 0x00a7> OtherMagnificationTypesAvailable; typedef gdcm::Attribute<0x2010, 0x00a8> DefaultSmoothingType; typedef gdcm::Attribute<0x2010, 0x00a9> OtherSmoothingTypesAvailable; typedef gdcm::Attribute<0x2010, 0x0100> BorderDensity; typedef gdcm::Attribute<0x2010, 0x0110> EmptyImageDensity; typedef gdcm::Attribute<0x2010, 0x0120> MinDensity; typedef gdcm::Attribute<0x2010, 0x0130> MaxDensity; typedef gdcm::Attribute<0x2010, 0x0140> Trim; typedef gdcm::Attribute<0x2010, 0x0150> ConfigurationInformation; typedef gdcm::Attribute<0x2010, 0x0152> ConfigurationInformationDescription; typedef gdcm::Attribute<0x2010, 0x0154> MaximumCollatedFilms; typedef gdcm::Attribute<0x2010, 0x015e> Illumination; typedef gdcm::Attribute<0x2010, 0x0160> ReflectedAmbientLight; typedef gdcm::Attribute<0x2010, 0x0376> PrinterPixelSpacing; typedef gdcm::Attribute<0x2010, 0x0500> ReferencedFilmSessionSequence; typedef gdcm::Attribute<0x2010, 0x0510> ReferencedImageBoxSequence; typedef gdcm::Attribute<0x2010, 0x0520> ReferencedBasicAnnotationBoxSequence; typedef gdcm::Attribute<0x2020, 0x0010> ImageBoxPosition; typedef gdcm::Attribute<0x2020, 0x0020> Polarity; typedef gdcm::Attribute<0x2020, 0x0030> RequestedImageSize; typedef gdcm::Attribute<0x2020, 0x0040> RequestedDecimateCropBehavior; typedef gdcm::Attribute<0x2020, 0x0050> RequestedResolutionID; typedef gdcm::Attribute<0x2020, 0x00a0> RequestedImageSizeFlag; typedef gdcm::Attribute<0x2020, 0x00a2> DecimateCropResult; typedef gdcm::Attribute<0x2020, 0x0110> BasicGrayscaleImageSequence; typedef gdcm::Attribute<0x2020, 0x0111> BasicColorImageSequence; typedef gdcm::Attribute<0x2020, 0x0130> ReferencedImageOverlayBoxSequence; typedef gdcm::Attribute<0x2020, 0x0140> ReferencedVOILUTBoxSequence; typedef gdcm::Attribute<0x2030, 0x0010> AnnotationPosition; typedef gdcm::Attribute<0x2030, 0x0020> TextString; typedef gdcm::Attribute<0x2040, 0x0010> ReferencedOverlayPlaneSequence; typedef gdcm::Attribute<0x2040, 0x0011> ReferencedOverlayPlaneGroups; typedef gdcm::Attribute<0x2040, 0x0020> OverlayPixelDataSequence; typedef gdcm::Attribute<0x2040, 0x0060> OverlayMagnificationType; typedef gdcm::Attribute<0x2040, 0x0070> OverlaySmoothingType; typedef gdcm::Attribute<0x2040, 0x0072> OverlayOrImageMagnification; typedef gdcm::Attribute<0x2040, 0x0074> MagnifyToNumberOfColumns; typedef gdcm::Attribute<0x2040, 0x0080> OverlayForegroundDensity; typedef gdcm::Attribute<0x2040, 0x0082> OverlayBackgroundDensity; typedef gdcm::Attribute<0x2040, 0x0090> OverlayMode; typedef gdcm::Attribute<0x2040, 0x0100> ThresholdDensity; typedef gdcm::Attribute<0x2040, 0x0500> ReferencedImageBoxSequenceRetired; typedef gdcm::Attribute<0x2050, 0x0010> PresentationLUTSequence; typedef gdcm::Attribute<0x2050, 0x0020> PresentationLUTShape; typedef gdcm::Attribute<0x2050, 0x0500> ReferencedPresentationLUTSequence; typedef gdcm::Attribute<0x2100, 0x0010> PrintJobID; typedef gdcm::Attribute<0x2100, 0x0020> ExecutionStatus; typedef gdcm::Attribute<0x2100, 0x0030> ExecutionStatusInfo; typedef gdcm::Attribute<0x2100, 0x0040> CreationDate; typedef gdcm::Attribute<0x2100, 0x0050> CreationTime; typedef gdcm::Attribute<0x2100, 0x0070> Originator; typedef gdcm::Attribute<0x2100, 0x0140> DestinationAE; typedef gdcm::Attribute<0x2100, 0x0160> OwnerID; typedef gdcm::Attribute<0x2100, 0x0170> NumberOfFilms; typedef gdcm::Attribute<0x2100, 0x0500> ReferencedPrintJobSequencePullStoredPrint; typedef gdcm::Attribute<0x2110, 0x0010> PrinterStatus; typedef gdcm::Attribute<0x2110, 0x0020> PrinterStatusInfo; typedef gdcm::Attribute<0x2110, 0x0030> PrinterName; typedef gdcm::Attribute<0x2110, 0x0099> PrintQueueID; typedef gdcm::Attribute<0x2120, 0x0010> QueueStatus; typedef gdcm::Attribute<0x2120, 0x0050> PrintJobDescriptionSequence; typedef gdcm::Attribute<0x2120, 0x0070> ReferencedPrintJobSequence; typedef gdcm::Attribute<0x2130, 0x0010> PrintManagementCapabilitiesSequence; typedef gdcm::Attribute<0x2130, 0x0015> PrinterCharacteristicsSequence; typedef gdcm::Attribute<0x2130, 0x0030> FilmBoxContentSequence; typedef gdcm::Attribute<0x2130, 0x0040> ImageBoxContentSequence; typedef gdcm::Attribute<0x2130, 0x0050> AnnotationContentSequence; typedef gdcm::Attribute<0x2130, 0x0060> ImageOverlayBoxContentSequence; typedef gdcm::Attribute<0x2130, 0x0080> PresentationLUTContentSequence; typedef gdcm::Attribute<0x2130, 0x00a0> ProposedStudySequence; typedef gdcm::Attribute<0x2130, 0x00c0> OriginalImageSequence; typedef gdcm::Attribute<0x2200, 0x0001> LabelUsingInformationExtractedFromInstances; typedef gdcm::Attribute<0x2200, 0x0002> LabelText; typedef gdcm::Attribute<0x2200, 0x0003> LabelStyleSelection; typedef gdcm::Attribute<0x2200, 0x0004> MediaDisposition; typedef gdcm::Attribute<0x2200, 0x0005> BarcodeValue; typedef gdcm::Attribute<0x2200, 0x0006> BarcodeSymbology; typedef gdcm::Attribute<0x2200, 0x0007> AllowMediaSplitting; typedef gdcm::Attribute<0x2200, 0x0008> IncludeNonDICOMObjects; typedef gdcm::Attribute<0x2200, 0x0009> IncludeDisplayApplication; typedef gdcm::Attribute<0x2200, 0x000a> PreserveCompositeInstancesAfterMediaCreation; typedef gdcm::Attribute<0x2200, 0x000b> TotalNumberOfPiecesOfMediaCreated; typedef gdcm::Attribute<0x2200, 0x000c> RequestedMediaApplicationProfile; typedef gdcm::Attribute<0x2200, 0x000d> ReferencedStorageMediaSequence; typedef gdcm::Attribute<0x2200, 0x000e> FailureAttributes; typedef gdcm::Attribute<0x2200, 0x000f> AllowLossyCompression; typedef gdcm::Attribute<0x2200, 0x0020> RequestPriority; typedef gdcm::Attribute<0x3002, 0x0002> RTImageLabel; typedef gdcm::Attribute<0x3002, 0x0003> RTImageName; typedef gdcm::Attribute<0x3002, 0x0004> RTImageDescription; typedef gdcm::Attribute<0x3002, 0x000a> ReportedValuesOrigin; typedef gdcm::Attribute<0x3002, 0x000c> RTImagePlane; typedef gdcm::Attribute<0x3002, 0x000d> XRayImageReceptorTranslation; typedef gdcm::Attribute<0x3002, 0x000e> XRayImageReceptorAngle; typedef gdcm::Attribute<0x3002, 0x0010> RTImageOrientation; typedef gdcm::Attribute<0x3002, 0x0011> ImagePlanePixelSpacing; typedef gdcm::Attribute<0x3002, 0x0012> RTImagePosition; typedef gdcm::Attribute<0x3002, 0x0020> RadiationMachineName; typedef gdcm::Attribute<0x3002, 0x0022> RadiationMachineSAD; typedef gdcm::Attribute<0x3002, 0x0024> RadiationMachineSSD; typedef gdcm::Attribute<0x3002, 0x0026> RTImageSID; typedef gdcm::Attribute<0x3002, 0x0028> SourceToReferenceObjectDistance; typedef gdcm::Attribute<0x3002, 0x0029> FractionNumber; typedef gdcm::Attribute<0x3002, 0x0030> ExposureSequence; typedef gdcm::Attribute<0x3002, 0x0032> MetersetExposure; typedef gdcm::Attribute<0x3002, 0x0034> DiaphragmPosition; typedef gdcm::Attribute<0x3002, 0x0040> FluenceMapSequence; typedef gdcm::Attribute<0x3002, 0x0041> FluenceDataSource; typedef gdcm::Attribute<0x3002, 0x0042> FluenceDataScale; typedef gdcm::Attribute<0x3002, 0x0050> PrimaryFluenceModeSequence; typedef gdcm::Attribute<0x3002, 0x0051> FluenceMode; typedef gdcm::Attribute<0x3002, 0x0052> FluenceModeID; typedef gdcm::Attribute<0x3004, 0x0001> DVHType; typedef gdcm::Attribute<0x3004, 0x0002> DoseUnits; typedef gdcm::Attribute<0x3004, 0x0004> DoseType; typedef gdcm::Attribute<0x3004, 0x0006> DoseComment; typedef gdcm::Attribute<0x3004, 0x0008> NormalizationPoint; typedef gdcm::Attribute<0x3004, 0x000a> DoseSummationType; typedef gdcm::Attribute<0x3004, 0x000c> GridFrameOffsetVector; typedef gdcm::Attribute<0x3004, 0x000e> DoseGridScaling; typedef gdcm::Attribute<0x3004, 0x0010> RTDoseROISequence; typedef gdcm::Attribute<0x3004, 0x0012> DoseValue; typedef gdcm::Attribute<0x3004, 0x0014> TissueHeterogeneityCorrection; typedef gdcm::Attribute<0x3004, 0x0040> DVHNormalizationPoint; typedef gdcm::Attribute<0x3004, 0x0042> DVHNormalizationDoseValue; typedef gdcm::Attribute<0x3004, 0x0050> DVHSequence; typedef gdcm::Attribute<0x3004, 0x0052> DVHDoseScaling; typedef gdcm::Attribute<0x3004, 0x0054> DVHVolumeUnits; typedef gdcm::Attribute<0x3004, 0x0056> DVHNumberOfBins; typedef gdcm::Attribute<0x3004, 0x0058> DVHData; typedef gdcm::Attribute<0x3004, 0x0060> DVHReferencedROISequence; typedef gdcm::Attribute<0x3004, 0x0062> DVHROIContributionType; typedef gdcm::Attribute<0x3004, 0x0070> DVHMinimumDose; typedef gdcm::Attribute<0x3004, 0x0072> DVHMaximumDose; typedef gdcm::Attribute<0x3004, 0x0074> DVHMeanDose; typedef gdcm::Attribute<0x3006, 0x0002> StructureSetLabel; typedef gdcm::Attribute<0x3006, 0x0004> StructureSetName; typedef gdcm::Attribute<0x3006, 0x0006> StructureSetDescription; typedef gdcm::Attribute<0x3006, 0x0008> StructureSetDate; typedef gdcm::Attribute<0x3006, 0x0009> StructureSetTime; typedef gdcm::Attribute<0x3006, 0x0010> ReferencedFrameOfReferenceSequence; typedef gdcm::Attribute<0x3006, 0x0012> RTReferencedStudySequence; typedef gdcm::Attribute<0x3006, 0x0014> RTReferencedSeriesSequence; typedef gdcm::Attribute<0x3006, 0x0016> ContourImageSequence; typedef gdcm::Attribute<0x3006, 0x0020> StructureSetROISequence; typedef gdcm::Attribute<0x3006, 0x0022> ROINumber; typedef gdcm::Attribute<0x3006, 0x0024> ReferencedFrameOfReferenceUID; typedef gdcm::Attribute<0x3006, 0x0026> ROIName; typedef gdcm::Attribute<0x3006, 0x0028> ROIDescription; typedef gdcm::Attribute<0x3006, 0x002a> ROIDisplayColor; typedef gdcm::Attribute<0x3006, 0x002c> ROIVolume; typedef gdcm::Attribute<0x3006, 0x0030> RTRelatedROISequence; typedef gdcm::Attribute<0x3006, 0x0033> RTROIRelationship; typedef gdcm::Attribute<0x3006, 0x0036> ROIGenerationAlgorithm; typedef gdcm::Attribute<0x3006, 0x0038> ROIGenerationDescription; typedef gdcm::Attribute<0x3006, 0x0039> ROIContourSequence; typedef gdcm::Attribute<0x3006, 0x0040> ContourSequence; typedef gdcm::Attribute<0x3006, 0x0042> ContourGeometricType; typedef gdcm::Attribute<0x3006, 0x0044> ContourSlabThickness; typedef gdcm::Attribute<0x3006, 0x0045> ContourOffsetVector; typedef gdcm::Attribute<0x3006, 0x0046> NumberOfContourPoints; typedef gdcm::Attribute<0x3006, 0x0048> ContourNumber; typedef gdcm::Attribute<0x3006, 0x0049> AttachedContours; typedef gdcm::Attribute<0x3006, 0x0050> ContourData; typedef gdcm::Attribute<0x3006, 0x0080> RTROIObservationsSequence; typedef gdcm::Attribute<0x3006, 0x0082> ObservationNumber; typedef gdcm::Attribute<0x3006, 0x0084> ReferencedROINumber; typedef gdcm::Attribute<0x3006, 0x0085> ROIObservationLabel; typedef gdcm::Attribute<0x3006, 0x0086> RTROIIdentificationCodeSequence; typedef gdcm::Attribute<0x3006, 0x0088> ROIObservationDescription; typedef gdcm::Attribute<0x3006, 0x00a0> RelatedRTROIObservationsSequence; typedef gdcm::Attribute<0x3006, 0x00a4> RTROIInterpretedType; typedef gdcm::Attribute<0x3006, 0x00a6> ROIInterpreter; typedef gdcm::Attribute<0x3006, 0x00b0> ROIPhysicalPropertiesSequence; typedef gdcm::Attribute<0x3006, 0x00b2> ROIPhysicalProperty; typedef gdcm::Attribute<0x3006, 0x00b4> ROIPhysicalPropertyValue; typedef gdcm::Attribute<0x3006, 0x00b6> ROIElementalCompositionSequence; typedef gdcm::Attribute<0x3006, 0x00b7> ROIElementalCompositionAtomicNumber; typedef gdcm::Attribute<0x3006, 0x00b8> ROIElementalCompositionAtomicMassFraction; typedef gdcm::Attribute<0x3006, 0x00c0> FrameOfReferenceRelationshipSequence; typedef gdcm::Attribute<0x3006, 0x00c2> RelatedFrameOfReferenceUID; typedef gdcm::Attribute<0x3006, 0x00c4> FrameOfReferenceTransformationType; typedef gdcm::Attribute<0x3006, 0x00c6> FrameOfReferenceTransformationMatrix; typedef gdcm::Attribute<0x3006, 0x00c8> FrameOfReferenceTransformationComment; typedef gdcm::Attribute<0x3008, 0x0010> MeasuredDoseReferenceSequence; typedef gdcm::Attribute<0x3008, 0x0012> MeasuredDoseDescription; typedef gdcm::Attribute<0x3008, 0x0014> MeasuredDoseType; typedef gdcm::Attribute<0x3008, 0x0016> MeasuredDoseValue; typedef gdcm::Attribute<0x3008, 0x0020> TreatmentSessionBeamSequence; typedef gdcm::Attribute<0x3008, 0x0021> TreatmentSessionIonBeamSequence; typedef gdcm::Attribute<0x3008, 0x0022> CurrentFractionNumber; typedef gdcm::Attribute<0x3008, 0x0024> TreatmentControlPointDate; typedef gdcm::Attribute<0x3008, 0x0025> TreatmentControlPointTime; typedef gdcm::Attribute<0x3008, 0x002a> TreatmentTerminationStatus; typedef gdcm::Attribute<0x3008, 0x002b> TreatmentTerminationCode; typedef gdcm::Attribute<0x3008, 0x002c> TreatmentVerificationStatus; typedef gdcm::Attribute<0x3008, 0x0030> ReferencedTreatmentRecordSequence; typedef gdcm::Attribute<0x3008, 0x0032> SpecifiedPrimaryMeterset; typedef gdcm::Attribute<0x3008, 0x0033> SpecifiedSecondaryMeterset; typedef gdcm::Attribute<0x3008, 0x0036> DeliveredPrimaryMeterset; typedef gdcm::Attribute<0x3008, 0x0037> DeliveredSecondaryMeterset; typedef gdcm::Attribute<0x3008, 0x003a> SpecifiedTreatmentTime; typedef gdcm::Attribute<0x3008, 0x003b> DeliveredTreatmentTime; typedef gdcm::Attribute<0x3008, 0x0040> ControlPointDeliverySequence; typedef gdcm::Attribute<0x3008, 0x0041> IonControlPointDeliverySequence; typedef gdcm::Attribute<0x3008, 0x0042> SpecifiedMeterset; typedef gdcm::Attribute<0x3008, 0x0044> DeliveredMeterset; typedef gdcm::Attribute<0x3008, 0x0045> MetersetRateSet; typedef gdcm::Attribute<0x3008, 0x0046> MetersetRateDelivered; typedef gdcm::Attribute<0x3008, 0x0047> ScanSpotMetersetsDelivered; typedef gdcm::Attribute<0x3008, 0x0048> DoseRateDelivered; typedef gdcm::Attribute<0x3008, 0x0050> TreatmentSummaryCalculatedDoseReferenceSequence; typedef gdcm::Attribute<0x3008, 0x0052> CumulativeDoseToDoseReference; typedef gdcm::Attribute<0x3008, 0x0054> FirstTreatmentDate; typedef gdcm::Attribute<0x3008, 0x0056> MostRecentTreatmentDate; typedef gdcm::Attribute<0x3008, 0x005a> NumberOfFractionsDelivered; typedef gdcm::Attribute<0x3008, 0x0060> OverrideSequence; typedef gdcm::Attribute<0x3008, 0x0061> ParameterSequencePointer; typedef gdcm::Attribute<0x3008, 0x0062> OverrideParameterPointer; typedef gdcm::Attribute<0x3008, 0x0063> ParameterItemIndex; typedef gdcm::Attribute<0x3008, 0x0064> MeasuredDoseReferenceNumber; typedef gdcm::Attribute<0x3008, 0x0065> ParameterPointer; typedef gdcm::Attribute<0x3008, 0x0066> OverrideReason; typedef gdcm::Attribute<0x3008, 0x0068> CorrectedParameterSequence; typedef gdcm::Attribute<0x3008, 0x006a> CorrectionValue; typedef gdcm::Attribute<0x3008, 0x0070> CalculatedDoseReferenceSequence; typedef gdcm::Attribute<0x3008, 0x0072> CalculatedDoseReferenceNumber; typedef gdcm::Attribute<0x3008, 0x0074> CalculatedDoseReferenceDescription; typedef gdcm::Attribute<0x3008, 0x0076> CalculatedDoseReferenceDoseValue; typedef gdcm::Attribute<0x3008, 0x0078> StartMeterset; typedef gdcm::Attribute<0x3008, 0x007a> EndMeterset; typedef gdcm::Attribute<0x3008, 0x0080> ReferencedMeasuredDoseReferenceSequence; typedef gdcm::Attribute<0x3008, 0x0082> ReferencedMeasuredDoseReferenceNumber; typedef gdcm::Attribute<0x3008, 0x0090> ReferencedCalculatedDoseReferenceSequence; typedef gdcm::Attribute<0x3008, 0x0092> ReferencedCalculatedDoseReferenceNumber; typedef gdcm::Attribute<0x3008, 0x00a0> BeamLimitingDeviceLeafPairsSequence; typedef gdcm::Attribute<0x3008, 0x00b0> RecordedWedgeSequence; typedef gdcm::Attribute<0x3008, 0x00c0> RecordedCompensatorSequence; typedef gdcm::Attribute<0x3008, 0x00d0> RecordedBlockSequence; typedef gdcm::Attribute<0x3008, 0x00e0> TreatmentSummaryMeasuredDoseReferenceSequence; typedef gdcm::Attribute<0x3008, 0x00f0> RecordedSnoutSequence; typedef gdcm::Attribute<0x3008, 0x00f2> RecordedRangeShifterSequence; typedef gdcm::Attribute<0x3008, 0x00f4> RecordedLateralSpreadingDeviceSequence; typedef gdcm::Attribute<0x3008, 0x00f6> RecordedRangeModulatorSequence; typedef gdcm::Attribute<0x3008, 0x0100> RecordedSourceSequence; typedef gdcm::Attribute<0x3008, 0x0105> SourceSerialNumber; typedef gdcm::Attribute<0x3008, 0x0110> TreatmentSessionApplicationSetupSequence; typedef gdcm::Attribute<0x3008, 0x0116> ApplicationSetupCheck; typedef gdcm::Attribute<0x3008, 0x0120> RecordedBrachyAccessoryDeviceSequence; typedef gdcm::Attribute<0x3008, 0x0122> ReferencedBrachyAccessoryDeviceNumber; typedef gdcm::Attribute<0x3008, 0x0130> RecordedChannelSequence; typedef gdcm::Attribute<0x3008, 0x0132> SpecifiedChannelTotalTime; typedef gdcm::Attribute<0x3008, 0x0134> DeliveredChannelTotalTime; typedef gdcm::Attribute<0x3008, 0x0136> SpecifiedNumberOfPulses; typedef gdcm::Attribute<0x3008, 0x0138> DeliveredNumberOfPulses; typedef gdcm::Attribute<0x3008, 0x013a> SpecifiedPulseRepetitionInterval; typedef gdcm::Attribute<0x3008, 0x013c> DeliveredPulseRepetitionInterval; typedef gdcm::Attribute<0x3008, 0x0140> RecordedSourceApplicatorSequence; typedef gdcm::Attribute<0x3008, 0x0142> ReferencedSourceApplicatorNumber; typedef gdcm::Attribute<0x3008, 0x0150> RecordedChannelShieldSequence; typedef gdcm::Attribute<0x3008, 0x0152> ReferencedChannelShieldNumber; typedef gdcm::Attribute<0x3008, 0x0160> BrachyControlPointDeliveredSequence; typedef gdcm::Attribute<0x3008, 0x0162> SafePositionExitDate; typedef gdcm::Attribute<0x3008, 0x0164> SafePositionExitTime; typedef gdcm::Attribute<0x3008, 0x0166> SafePositionReturnDate; typedef gdcm::Attribute<0x3008, 0x0168> SafePositionReturnTime; typedef gdcm::Attribute<0x3008, 0x0200> CurrentTreatmentStatus; typedef gdcm::Attribute<0x3008, 0x0202> TreatmentStatusComment; typedef gdcm::Attribute<0x3008, 0x0220> FractionGroupSummarySequence; typedef gdcm::Attribute<0x3008, 0x0223> ReferencedFractionNumber; typedef gdcm::Attribute<0x3008, 0x0224> FractionGroupType; typedef gdcm::Attribute<0x3008, 0x0230> BeamStopperPosition; typedef gdcm::Attribute<0x3008, 0x0240> FractionStatusSummarySequence; typedef gdcm::Attribute<0x3008, 0x0250> TreatmentDate; typedef gdcm::Attribute<0x3008, 0x0251> TreatmentTime; typedef gdcm::Attribute<0x300a, 0x0002> RTPlanLabel; typedef gdcm::Attribute<0x300a, 0x0003> RTPlanName; typedef gdcm::Attribute<0x300a, 0x0004> RTPlanDescription; typedef gdcm::Attribute<0x300a, 0x0006> RTPlanDate; typedef gdcm::Attribute<0x300a, 0x0007> RTPlanTime; typedef gdcm::Attribute<0x300a, 0x0009> TreatmentProtocols; typedef gdcm::Attribute<0x300a, 0x000a> PlanIntent; typedef gdcm::Attribute<0x300a, 0x000b> TreatmentSites; typedef gdcm::Attribute<0x300a, 0x000c> RTPlanGeometry; typedef gdcm::Attribute<0x300a, 0x000e> PrescriptionDescription; typedef gdcm::Attribute<0x300a, 0x0010> DoseReferenceSequence; typedef gdcm::Attribute<0x300a, 0x0012> DoseReferenceNumber; typedef gdcm::Attribute<0x300a, 0x0013> DoseReferenceUID; typedef gdcm::Attribute<0x300a, 0x0014> DoseReferenceStructureType; typedef gdcm::Attribute<0x300a, 0x0015> NominalBeamEnergyUnit; typedef gdcm::Attribute<0x300a, 0x0016> DoseReferenceDescription; typedef gdcm::Attribute<0x300a, 0x0018> DoseReferencePointCoordinates; typedef gdcm::Attribute<0x300a, 0x001a> NominalPriorDose; typedef gdcm::Attribute<0x300a, 0x0020> DoseReferenceType; typedef gdcm::Attribute<0x300a, 0x0021> ConstraintWeight; typedef gdcm::Attribute<0x300a, 0x0022> DeliveryWarningDose; typedef gdcm::Attribute<0x300a, 0x0023> DeliveryMaximumDose; typedef gdcm::Attribute<0x300a, 0x0025> TargetMinimumDose; typedef gdcm::Attribute<0x300a, 0x0026> TargetPrescriptionDose; typedef gdcm::Attribute<0x300a, 0x0027> TargetMaximumDose; typedef gdcm::Attribute<0x300a, 0x0028> TargetUnderdoseVolumeFraction; typedef gdcm::Attribute<0x300a, 0x002a> OrganAtRiskFullVolumeDose; typedef gdcm::Attribute<0x300a, 0x002b> OrganAtRiskLimitDose; typedef gdcm::Attribute<0x300a, 0x002c> OrganAtRiskMaximumDose; typedef gdcm::Attribute<0x300a, 0x002d> OrganAtRiskOverdoseVolumeFraction; typedef gdcm::Attribute<0x300a, 0x0040> ToleranceTableSequence; typedef gdcm::Attribute<0x300a, 0x0042> ToleranceTableNumber; typedef gdcm::Attribute<0x300a, 0x0043> ToleranceTableLabel; typedef gdcm::Attribute<0x300a, 0x0044> GantryAngleTolerance; typedef gdcm::Attribute<0x300a, 0x0046> BeamLimitingDeviceAngleTolerance; typedef gdcm::Attribute<0x300a, 0x0048> BeamLimitingDeviceToleranceSequence; typedef gdcm::Attribute<0x300a, 0x004a> BeamLimitingDevicePositionTolerance; typedef gdcm::Attribute<0x300a, 0x004b> SnoutPositionTolerance; typedef gdcm::Attribute<0x300a, 0x004c> PatientSupportAngleTolerance; typedef gdcm::Attribute<0x300a, 0x004e> TableTopEccentricAngleTolerance; typedef gdcm::Attribute<0x300a, 0x004f> TableTopPitchAngleTolerance; typedef gdcm::Attribute<0x300a, 0x0050> TableTopRollAngleTolerance; typedef gdcm::Attribute<0x300a, 0x0051> TableTopVerticalPositionTolerance; typedef gdcm::Attribute<0x300a, 0x0052> TableTopLongitudinalPositionTolerance; typedef gdcm::Attribute<0x300a, 0x0053> TableTopLateralPositionTolerance; typedef gdcm::Attribute<0x300a, 0x0055> RTPlanRelationship; typedef gdcm::Attribute<0x300a, 0x0070> FractionGroupSequence; typedef gdcm::Attribute<0x300a, 0x0071> FractionGroupNumber; typedef gdcm::Attribute<0x300a, 0x0072> FractionGroupDescription; typedef gdcm::Attribute<0x300a, 0x0078> NumberOfFractionsPlanned; typedef gdcm::Attribute<0x300a, 0x0079> NumberOfFractionPatternDigitsPerDay; typedef gdcm::Attribute<0x300a, 0x007a> RepeatFractionCycleLength; typedef gdcm::Attribute<0x300a, 0x007b> FractionPattern; typedef gdcm::Attribute<0x300a, 0x0080> NumberOfBeams; typedef gdcm::Attribute<0x300a, 0x0082> BeamDoseSpecificationPoint; typedef gdcm::Attribute<0x300a, 0x0084> BeamDose; typedef gdcm::Attribute<0x300a, 0x0086> BeamMeterset; typedef gdcm::Attribute<0x300a, 0x0088> BeamDosePointDepth; typedef gdcm::Attribute<0x300a, 0x0089> BeamDosePointEquivalentDepth; typedef gdcm::Attribute<0x300a, 0x008a> BeamDosePointSSD; typedef gdcm::Attribute<0x300a, 0x00a0> NumberOfBrachyApplicationSetups; typedef gdcm::Attribute<0x300a, 0x00a2> BrachyApplicationSetupDoseSpecificationPoint; typedef gdcm::Attribute<0x300a, 0x00a4> BrachyApplicationSetupDose; typedef gdcm::Attribute<0x300a, 0x00b0> BeamSequence; typedef gdcm::Attribute<0x300a, 0x00b2> TreatmentMachineName; typedef gdcm::Attribute<0x300a, 0x00b3> PrimaryDosimeterUnit; typedef gdcm::Attribute<0x300a, 0x00b4> SourceAxisDistance; typedef gdcm::Attribute<0x300a, 0x00b6> BeamLimitingDeviceSequence; typedef gdcm::Attribute<0x300a, 0x00b8> RTBeamLimitingDeviceType; typedef gdcm::Attribute<0x300a, 0x00ba> SourceToBeamLimitingDeviceDistance; typedef gdcm::Attribute<0x300a, 0x00bb> IsocenterToBeamLimitingDeviceDistance; typedef gdcm::Attribute<0x300a, 0x00bc> NumberOfLeafJawPairs; typedef gdcm::Attribute<0x300a, 0x00be> LeafPositionBoundaries; typedef gdcm::Attribute<0x300a, 0x00c0> BeamNumber; typedef gdcm::Attribute<0x300a, 0x00c2> BeamName; typedef gdcm::Attribute<0x300a, 0x00c3> BeamDescription; typedef gdcm::Attribute<0x300a, 0x00c4> BeamType; typedef gdcm::Attribute<0x300a, 0x00c6> RadiationType; typedef gdcm::Attribute<0x300a, 0x00c7> HighDoseTechniqueType; typedef gdcm::Attribute<0x300a, 0x00c8> ReferenceImageNumber; typedef gdcm::Attribute<0x300a, 0x00ca> PlannedVerificationImageSequence; typedef gdcm::Attribute<0x300a, 0x00cc> ImagingDeviceSpecificAcquisitionParameters; typedef gdcm::Attribute<0x300a, 0x00ce> TreatmentDeliveryType; typedef gdcm::Attribute<0x300a, 0x00d0> NumberOfWedges; typedef gdcm::Attribute<0x300a, 0x00d1> WedgeSequence; typedef gdcm::Attribute<0x300a, 0x00d2> WedgeNumber; typedef gdcm::Attribute<0x300a, 0x00d3> WedgeType; typedef gdcm::Attribute<0x300a, 0x00d4> WedgeID; typedef gdcm::Attribute<0x300a, 0x00d5> WedgeAngle; typedef gdcm::Attribute<0x300a, 0x00d6> WedgeFactor; typedef gdcm::Attribute<0x300a, 0x00d7> TotalWedgeTrayWaterEquivalentThickness; typedef gdcm::Attribute<0x300a, 0x00d8> WedgeOrientation; typedef gdcm::Attribute<0x300a, 0x00d9> IsocenterToWedgeTrayDistance; typedef gdcm::Attribute<0x300a, 0x00da> SourceToWedgeTrayDistance; typedef gdcm::Attribute<0x300a, 0x00db> WedgeThinEdgePosition; typedef gdcm::Attribute<0x300a, 0x00dc> BolusID; typedef gdcm::Attribute<0x300a, 0x00dd> BolusDescription; typedef gdcm::Attribute<0x300a, 0x00e0> NumberOfCompensators; typedef gdcm::Attribute<0x300a, 0x00e1> MaterialID; typedef gdcm::Attribute<0x300a, 0x00e2> TotalCompensatorTrayFactor; typedef gdcm::Attribute<0x300a, 0x00e3> CompensatorSequence; typedef gdcm::Attribute<0x300a, 0x00e4> CompensatorNumber; typedef gdcm::Attribute<0x300a, 0x00e5> CompensatorID; typedef gdcm::Attribute<0x300a, 0x00e6> SourceToCompensatorTrayDistance; typedef gdcm::Attribute<0x300a, 0x00e7> CompensatorRows; typedef gdcm::Attribute<0x300a, 0x00e8> CompensatorColumns; typedef gdcm::Attribute<0x300a, 0x00e9> CompensatorPixelSpacing; typedef gdcm::Attribute<0x300a, 0x00ea> CompensatorPosition; typedef gdcm::Attribute<0x300a, 0x00eb> CompensatorTransmissionData; typedef gdcm::Attribute<0x300a, 0x00ec> CompensatorThicknessData; typedef gdcm::Attribute<0x300a, 0x00ed> NumberOfBoli; typedef gdcm::Attribute<0x300a, 0x00ee> CompensatorType; typedef gdcm::Attribute<0x300a, 0x00f0> NumberOfBlocks; typedef gdcm::Attribute<0x300a, 0x00f2> TotalBlockTrayFactor; typedef gdcm::Attribute<0x300a, 0x00f3> TotalBlockTrayWaterEquivalentThickness; typedef gdcm::Attribute<0x300a, 0x00f4> BlockSequence; typedef gdcm::Attribute<0x300a, 0x00f5> BlockTrayID; typedef gdcm::Attribute<0x300a, 0x00f6> SourceToBlockTrayDistance; typedef gdcm::Attribute<0x300a, 0x00f7> IsocenterToBlockTrayDistance; typedef gdcm::Attribute<0x300a, 0x00f8> BlockType; typedef gdcm::Attribute<0x300a, 0x00f9> AccessoryCode; typedef gdcm::Attribute<0x300a, 0x00fa> BlockDivergence; typedef gdcm::Attribute<0x300a, 0x00fb> BlockMountingPosition; typedef gdcm::Attribute<0x300a, 0x00fc> BlockNumber; typedef gdcm::Attribute<0x300a, 0x00fe> BlockName; typedef gdcm::Attribute<0x300a, 0x0100> BlockThickness; typedef gdcm::Attribute<0x300a, 0x0102> BlockTransmission; typedef gdcm::Attribute<0x300a, 0x0104> BlockNumberOfPoints; typedef gdcm::Attribute<0x300a, 0x0106> BlockData; typedef gdcm::Attribute<0x300a, 0x0107> ApplicatorSequence; typedef gdcm::Attribute<0x300a, 0x0108> ApplicatorID; typedef gdcm::Attribute<0x300a, 0x0109> ApplicatorType; typedef gdcm::Attribute<0x300a, 0x010a> ApplicatorDescription; typedef gdcm::Attribute<0x300a, 0x010c> CumulativeDoseReferenceCoefficient; typedef gdcm::Attribute<0x300a, 0x010e> FinalCumulativeMetersetWeight; typedef gdcm::Attribute<0x300a, 0x0110> NumberOfControlPoints; typedef gdcm::Attribute<0x300a, 0x0111> ControlPointSequence; typedef gdcm::Attribute<0x300a, 0x0112> ControlPointIndex; typedef gdcm::Attribute<0x300a, 0x0114> NominalBeamEnergy; typedef gdcm::Attribute<0x300a, 0x0115> DoseRateSet; typedef gdcm::Attribute<0x300a, 0x0116> WedgePositionSequence; typedef gdcm::Attribute<0x300a, 0x0118> WedgePosition; typedef gdcm::Attribute<0x300a, 0x011a> BeamLimitingDevicePositionSequence; typedef gdcm::Attribute<0x300a, 0x011c> LeafJawPositions; typedef gdcm::Attribute<0x300a, 0x011e> GantryAngle; typedef gdcm::Attribute<0x300a, 0x011f> GantryRotationDirection; typedef gdcm::Attribute<0x300a, 0x0120> BeamLimitingDeviceAngle; typedef gdcm::Attribute<0x300a, 0x0121> BeamLimitingDeviceRotationDirection; typedef gdcm::Attribute<0x300a, 0x0122> PatientSupportAngle; typedef gdcm::Attribute<0x300a, 0x0123> PatientSupportRotationDirection; typedef gdcm::Attribute<0x300a, 0x0124> TableTopEccentricAxisDistance; typedef gdcm::Attribute<0x300a, 0x0125> TableTopEccentricAngle; typedef gdcm::Attribute<0x300a, 0x0126> TableTopEccentricRotationDirection; typedef gdcm::Attribute<0x300a, 0x0128> TableTopVerticalPosition; typedef gdcm::Attribute<0x300a, 0x0129> TableTopLongitudinalPosition; typedef gdcm::Attribute<0x300a, 0x012a> TableTopLateralPosition; typedef gdcm::Attribute<0x300a, 0x012c> IsocenterPosition; typedef gdcm::Attribute<0x300a, 0x012e> SurfaceEntryPoint; typedef gdcm::Attribute<0x300a, 0x0130> SourceToSurfaceDistance; typedef gdcm::Attribute<0x300a, 0x0134> CumulativeMetersetWeight; typedef gdcm::Attribute<0x300a, 0x0140> TableTopPitchAngle; typedef gdcm::Attribute<0x300a, 0x0142> TableTopPitchRotationDirection; typedef gdcm::Attribute<0x300a, 0x0144> TableTopRollAngle; typedef gdcm::Attribute<0x300a, 0x0146> TableTopRollRotationDirection; typedef gdcm::Attribute<0x300a, 0x0148> HeadFixationAngle; typedef gdcm::Attribute<0x300a, 0x014a> GantryPitchAngle; typedef gdcm::Attribute<0x300a, 0x014c> GantryPitchRotationDirection; typedef gdcm::Attribute<0x300a, 0x014e> GantryPitchAngleTolerance; typedef gdcm::Attribute<0x300a, 0x0180> PatientSetupSequence; typedef gdcm::Attribute<0x300a, 0x0182> PatientSetupNumber; typedef gdcm::Attribute<0x300a, 0x0183> PatientSetupLabel; typedef gdcm::Attribute<0x300a, 0x0184> PatientAdditionalPosition; typedef gdcm::Attribute<0x300a, 0x0190> FixationDeviceSequence; typedef gdcm::Attribute<0x300a, 0x0192> FixationDeviceType; typedef gdcm::Attribute<0x300a, 0x0194> FixationDeviceLabel; typedef gdcm::Attribute<0x300a, 0x0196> FixationDeviceDescription; typedef gdcm::Attribute<0x300a, 0x0198> FixationDevicePosition; typedef gdcm::Attribute<0x300a, 0x0199> FixationDevicePitchAngle; typedef gdcm::Attribute<0x300a, 0x019a> FixationDeviceRollAngle; typedef gdcm::Attribute<0x300a, 0x01a0> ShieldingDeviceSequence; typedef gdcm::Attribute<0x300a, 0x01a2> ShieldingDeviceType; typedef gdcm::Attribute<0x300a, 0x01a4> ShieldingDeviceLabel; typedef gdcm::Attribute<0x300a, 0x01a6> ShieldingDeviceDescription; typedef gdcm::Attribute<0x300a, 0x01a8> ShieldingDevicePosition; typedef gdcm::Attribute<0x300a, 0x01b0> SetupTechnique; typedef gdcm::Attribute<0x300a, 0x01b2> SetupTechniqueDescription; typedef gdcm::Attribute<0x300a, 0x01b4> SetupDeviceSequence; typedef gdcm::Attribute<0x300a, 0x01b6> SetupDeviceType; typedef gdcm::Attribute<0x300a, 0x01b8> SetupDeviceLabel; typedef gdcm::Attribute<0x300a, 0x01ba> SetupDeviceDescription; typedef gdcm::Attribute<0x300a, 0x01bc> SetupDeviceParameter; typedef gdcm::Attribute<0x300a, 0x01d0> SetupReferenceDescription; typedef gdcm::Attribute<0x300a, 0x01d2> TableTopVerticalSetupDisplacement; typedef gdcm::Attribute<0x300a, 0x01d4> TableTopLongitudinalSetupDisplacement; typedef gdcm::Attribute<0x300a, 0x01d6> TableTopLateralSetupDisplacement; typedef gdcm::Attribute<0x300a, 0x0200> BrachyTreatmentTechnique; typedef gdcm::Attribute<0x300a, 0x0202> BrachyTreatmentType; typedef gdcm::Attribute<0x300a, 0x0206> TreatmentMachineSequence; typedef gdcm::Attribute<0x300a, 0x0210> SourceSequence; typedef gdcm::Attribute<0x300a, 0x0212> SourceNumber; typedef gdcm::Attribute<0x300a, 0x0214> SourceType; typedef gdcm::Attribute<0x300a, 0x0216> SourceManufacturer; typedef gdcm::Attribute<0x300a, 0x0218> ActiveSourceDiameter; typedef gdcm::Attribute<0x300a, 0x021a> ActiveSourceLength; typedef gdcm::Attribute<0x300a, 0x0222> SourceEncapsulationNominalThickness; typedef gdcm::Attribute<0x300a, 0x0224> SourceEncapsulationNominalTransmission; typedef gdcm::Attribute<0x300a, 0x0226> SourceIsotopeName; typedef gdcm::Attribute<0x300a, 0x0228> SourceIsotopeHalfLife; typedef gdcm::Attribute<0x300a, 0x0229> SourceStrengthUnits; typedef gdcm::Attribute<0x300a, 0x022a> ReferenceAirKermaRate; typedef gdcm::Attribute<0x300a, 0x022b> SourceStrength; typedef gdcm::Attribute<0x300a, 0x022c> SourceStrengthReferenceDate; typedef gdcm::Attribute<0x300a, 0x022e> SourceStrengthReferenceTime; typedef gdcm::Attribute<0x300a, 0x0230> ApplicationSetupSequence; typedef gdcm::Attribute<0x300a, 0x0232> ApplicationSetupType; typedef gdcm::Attribute<0x300a, 0x0234> ApplicationSetupNumber; typedef gdcm::Attribute<0x300a, 0x0236> ApplicationSetupName; typedef gdcm::Attribute<0x300a, 0x0238> ApplicationSetupManufacturer; typedef gdcm::Attribute<0x300a, 0x0240> TemplateNumber; typedef gdcm::Attribute<0x300a, 0x0242> TemplateType; typedef gdcm::Attribute<0x300a, 0x0244> TemplateName; typedef gdcm::Attribute<0x300a, 0x0250> TotalReferenceAirKerma; typedef gdcm::Attribute<0x300a, 0x0260> BrachyAccessoryDeviceSequence; typedef gdcm::Attribute<0x300a, 0x0262> BrachyAccessoryDeviceNumber; typedef gdcm::Attribute<0x300a, 0x0263> BrachyAccessoryDeviceID; typedef gdcm::Attribute<0x300a, 0x0264> BrachyAccessoryDeviceType; typedef gdcm::Attribute<0x300a, 0x0266> BrachyAccessoryDeviceName; typedef gdcm::Attribute<0x300a, 0x026a> BrachyAccessoryDeviceNominalThickness; typedef gdcm::Attribute<0x300a, 0x026c> BrachyAccessoryDeviceNominalTransmission; typedef gdcm::Attribute<0x300a, 0x0280> ChannelSequence; typedef gdcm::Attribute<0x300a, 0x0282> ChannelNumber; typedef gdcm::Attribute<0x300a, 0x0284> ChannelLength; typedef gdcm::Attribute<0x300a, 0x0286> ChannelTotalTime; typedef gdcm::Attribute<0x300a, 0x0288> SourceMovementType; typedef gdcm::Attribute<0x300a, 0x028a> NumberOfPulses; typedef gdcm::Attribute<0x300a, 0x028c> PulseRepetitionInterval; typedef gdcm::Attribute<0x300a, 0x0290> SourceApplicatorNumber; typedef gdcm::Attribute<0x300a, 0x0291> SourceApplicatorID; typedef gdcm::Attribute<0x300a, 0x0292> SourceApplicatorType; typedef gdcm::Attribute<0x300a, 0x0294> SourceApplicatorName; typedef gdcm::Attribute<0x300a, 0x0296> SourceApplicatorLength; typedef gdcm::Attribute<0x300a, 0x0298> SourceApplicatorManufacturer; typedef gdcm::Attribute<0x300a, 0x029c> SourceApplicatorWallNominalThickness; typedef gdcm::Attribute<0x300a, 0x029e> SourceApplicatorWallNominalTransmission; typedef gdcm::Attribute<0x300a, 0x02a0> SourceApplicatorStepSize; typedef gdcm::Attribute<0x300a, 0x02a2> TransferTubeNumber; typedef gdcm::Attribute<0x300a, 0x02a4> TransferTubeLength; typedef gdcm::Attribute<0x300a, 0x02b0> ChannelShieldSequence; typedef gdcm::Attribute<0x300a, 0x02b2> ChannelShieldNumber; typedef gdcm::Attribute<0x300a, 0x02b3> ChannelShieldID; typedef gdcm::Attribute<0x300a, 0x02b4> ChannelShieldName; typedef gdcm::Attribute<0x300a, 0x02b8> ChannelShieldNominalThickness; typedef gdcm::Attribute<0x300a, 0x02ba> ChannelShieldNominalTransmission; typedef gdcm::Attribute<0x300a, 0x02c8> FinalCumulativeTimeWeight; typedef gdcm::Attribute<0x300a, 0x02d0> BrachyControlPointSequence; typedef gdcm::Attribute<0x300a, 0x02d2> ControlPointRelativePosition; typedef gdcm::Attribute<0x300a, 0x02d4> ControlPoint3DPosition; typedef gdcm::Attribute<0x300a, 0x02d6> CumulativeTimeWeight; typedef gdcm::Attribute<0x300a, 0x02e0> CompensatorDivergence; typedef gdcm::Attribute<0x300a, 0x02e1> CompensatorMountingPosition; typedef gdcm::Attribute<0x300a, 0x02e2> SourceToCompensatorDistance; typedef gdcm::Attribute<0x300a, 0x02e3> TotalCompensatorTrayWaterEquivalentThickness; typedef gdcm::Attribute<0x300a, 0x02e4> IsocenterToCompensatorTrayDistance; typedef gdcm::Attribute<0x300a, 0x02e5> CompensatorColumnOffset; typedef gdcm::Attribute<0x300a, 0x02e6> IsocenterToCompensatorDistances; typedef gdcm::Attribute<0x300a, 0x02e7> CompensatorRelativeStoppingPowerRatio; typedef gdcm::Attribute<0x300a, 0x02e8> CompensatorMillingToolDiameter; typedef gdcm::Attribute<0x300a, 0x02ea> IonRangeCompensatorSequence; typedef gdcm::Attribute<0x300a, 0x02eb> CompensatorDescription; typedef gdcm::Attribute<0x300a, 0x0302> RadiationMassNumber; typedef gdcm::Attribute<0x300a, 0x0304> RadiationAtomicNumber; typedef gdcm::Attribute<0x300a, 0x0306> RadiationChargeState; typedef gdcm::Attribute<0x300a, 0x0308> ScanMode; typedef gdcm::Attribute<0x300a, 0x030a> VirtualSourceAxisDistances; typedef gdcm::Attribute<0x300a, 0x030c> SnoutSequence; typedef gdcm::Attribute<0x300a, 0x030d> SnoutPosition; typedef gdcm::Attribute<0x300a, 0x030f> SnoutID; typedef gdcm::Attribute<0x300a, 0x0312> NumberOfRangeShifters; typedef gdcm::Attribute<0x300a, 0x0314> RangeShifterSequence; typedef gdcm::Attribute<0x300a, 0x0316> RangeShifterNumber; typedef gdcm::Attribute<0x300a, 0x0318> RangeShifterID; typedef gdcm::Attribute<0x300a, 0x0320> RangeShifterType; typedef gdcm::Attribute<0x300a, 0x0322> RangeShifterDescription; typedef gdcm::Attribute<0x300a, 0x0330> NumberOfLateralSpreadingDevices; typedef gdcm::Attribute<0x300a, 0x0332> LateralSpreadingDeviceSequence; typedef gdcm::Attribute<0x300a, 0x0334> LateralSpreadingDeviceNumber; typedef gdcm::Attribute<0x300a, 0x0336> LateralSpreadingDeviceID; typedef gdcm::Attribute<0x300a, 0x0338> LateralSpreadingDeviceType; typedef gdcm::Attribute<0x300a, 0x033a> LateralSpreadingDeviceDescription; typedef gdcm::Attribute<0x300a, 0x033c> LateralSpreadingDeviceWaterEquivalentThickness; typedef gdcm::Attribute<0x300a, 0x0340> NumberOfRangeModulators; typedef gdcm::Attribute<0x300a, 0x0342> RangeModulatorSequence; typedef gdcm::Attribute<0x300a, 0x0344> RangeModulatorNumber; typedef gdcm::Attribute<0x300a, 0x0346> RangeModulatorID; typedef gdcm::Attribute<0x300a, 0x0348> RangeModulatorType; typedef gdcm::Attribute<0x300a, 0x034a> RangeModulatorDescription; typedef gdcm::Attribute<0x300a, 0x034c> BeamCurrentModulationID; typedef gdcm::Attribute<0x300a, 0x0350> PatientSupportType; typedef gdcm::Attribute<0x300a, 0x0352> PatientSupportID; typedef gdcm::Attribute<0x300a, 0x0354> PatientSupportAccessoryCode; typedef gdcm::Attribute<0x300a, 0x0356> FixationLightAzimuthalAngle; typedef gdcm::Attribute<0x300a, 0x0358> FixationLightPolarAngle; typedef gdcm::Attribute<0x300a, 0x035a> MetersetRate; typedef gdcm::Attribute<0x300a, 0x0360> RangeShifterSettingsSequence; typedef gdcm::Attribute<0x300a, 0x0362> RangeShifterSetting; typedef gdcm::Attribute<0x300a, 0x0364> IsocenterToRangeShifterDistance; typedef gdcm::Attribute<0x300a, 0x0366> RangeShifterWaterEquivalentThickness; typedef gdcm::Attribute<0x300a, 0x0370> LateralSpreadingDeviceSettingsSequence; typedef gdcm::Attribute<0x300a, 0x0372> LateralSpreadingDeviceSetting; typedef gdcm::Attribute<0x300a, 0x0374> IsocenterToLateralSpreadingDeviceDistance; typedef gdcm::Attribute<0x300a, 0x0380> RangeModulatorSettingsSequence; typedef gdcm::Attribute<0x300a, 0x0382> RangeModulatorGatingStartValue; typedef gdcm::Attribute<0x300a, 0x0384> RangeModulatorGatingStopValue; typedef gdcm::Attribute<0x300a, 0x0386> RangeModulatorGatingStartWaterEquivalentThickness; typedef gdcm::Attribute<0x300a, 0x0388> RangeModulatorGatingStopWaterEquivalentThickness; typedef gdcm::Attribute<0x300a, 0x038a> IsocenterToRangeModulatorDistance; typedef gdcm::Attribute<0x300a, 0x0390> ScanSpotTuneID; typedef gdcm::Attribute<0x300a, 0x0392> NumberOfScanSpotPositions; typedef gdcm::Attribute<0x300a, 0x0394> ScanSpotPositionMap; typedef gdcm::Attribute<0x300a, 0x0396> ScanSpotMetersetWeights; typedef gdcm::Attribute<0x300a, 0x0398> ScanningSpotSize; typedef gdcm::Attribute<0x300a, 0x039a> NumberOfPaintings; typedef gdcm::Attribute<0x300a, 0x03a0> IonToleranceTableSequence; typedef gdcm::Attribute<0x300a, 0x03a2> IonBeamSequence; typedef gdcm::Attribute<0x300a, 0x03a4> IonBeamLimitingDeviceSequence; typedef gdcm::Attribute<0x300a, 0x03a6> IonBlockSequence; typedef gdcm::Attribute<0x300a, 0x03a8> IonControlPointSequence; typedef gdcm::Attribute<0x300a, 0x03aa> IonWedgeSequence; typedef gdcm::Attribute<0x300a, 0x03ac> IonWedgePositionSequence; typedef gdcm::Attribute<0x300a, 0x0401> ReferencedSetupImageSequence; typedef gdcm::Attribute<0x300a, 0x0402> SetupImageComment; typedef gdcm::Attribute<0x300a, 0x0410> MotionSynchronizationSequence; typedef gdcm::Attribute<0x300a, 0x0412> ControlPointOrientation; typedef gdcm::Attribute<0x300a, 0x0420> GeneralAccessorySequence; typedef gdcm::Attribute<0x300a, 0x0421> GeneralAccessoryID; typedef gdcm::Attribute<0x300a, 0x0422> GeneralAccessoryDescription; typedef gdcm::Attribute<0x300a, 0x0423> GeneralAccessoryType; typedef gdcm::Attribute<0x300a, 0x0424> GeneralAccessoryNumber; typedef gdcm::Attribute<0x300a, 0x0431> ApplicatorGeometrySequence; typedef gdcm::Attribute<0x300a, 0x0432> ApplicatorApertureShape; typedef gdcm::Attribute<0x300a, 0x0433> ApplicatorOpening; typedef gdcm::Attribute<0x300a, 0x0434> ApplicatorOpeningX; typedef gdcm::Attribute<0x300a, 0x0435> ApplicatorOpeningY; typedef gdcm::Attribute<0x300a, 0x0436> SourceToApplicatorMountingPositionDistance; typedef gdcm::Attribute<0x300c, 0x0002> ReferencedRTPlanSequence; typedef gdcm::Attribute<0x300c, 0x0004> ReferencedBeamSequence; typedef gdcm::Attribute<0x300c, 0x0006> ReferencedBeamNumber; typedef gdcm::Attribute<0x300c, 0x0007> ReferencedReferenceImageNumber; typedef gdcm::Attribute<0x300c, 0x0008> StartCumulativeMetersetWeight; typedef gdcm::Attribute<0x300c, 0x0009> EndCumulativeMetersetWeight; typedef gdcm::Attribute<0x300c, 0x000a> ReferencedBrachyApplicationSetupSequence; typedef gdcm::Attribute<0x300c, 0x000c> ReferencedBrachyApplicationSetupNumber; typedef gdcm::Attribute<0x300c, 0x000e> ReferencedSourceNumber; typedef gdcm::Attribute<0x300c, 0x0020> ReferencedFractionGroupSequence; typedef gdcm::Attribute<0x300c, 0x0022> ReferencedFractionGroupNumber; typedef gdcm::Attribute<0x300c, 0x0040> ReferencedVerificationImageSequence; typedef gdcm::Attribute<0x300c, 0x0042> ReferencedReferenceImageSequence; typedef gdcm::Attribute<0x300c, 0x0050> ReferencedDoseReferenceSequence; typedef gdcm::Attribute<0x300c, 0x0051> ReferencedDoseReferenceNumber; typedef gdcm::Attribute<0x300c, 0x0055> BrachyReferencedDoseReferenceSequence; typedef gdcm::Attribute<0x300c, 0x0060> ReferencedStructureSetSequence; typedef gdcm::Attribute<0x300c, 0x006a> ReferencedPatientSetupNumber; typedef gdcm::Attribute<0x300c, 0x0080> ReferencedDoseSequence; typedef gdcm::Attribute<0x300c, 0x00a0> ReferencedToleranceTableNumber; typedef gdcm::Attribute<0x300c, 0x00b0> ReferencedBolusSequence; typedef gdcm::Attribute<0x300c, 0x00c0> ReferencedWedgeNumber; typedef gdcm::Attribute<0x300c, 0x00d0> ReferencedCompensatorNumber; typedef gdcm::Attribute<0x300c, 0x00e0> ReferencedBlockNumber; typedef gdcm::Attribute<0x300c, 0x00f0> ReferencedControlPointIndex; typedef gdcm::Attribute<0x300c, 0x00f2> ReferencedControlPointSequence; typedef gdcm::Attribute<0x300c, 0x00f4> ReferencedStartControlPointIndex; typedef gdcm::Attribute<0x300c, 0x00f6> ReferencedStopControlPointIndex; typedef gdcm::Attribute<0x300c, 0x0100> ReferencedRangeShifterNumber; typedef gdcm::Attribute<0x300c, 0x0102> ReferencedLateralSpreadingDeviceNumber; typedef gdcm::Attribute<0x300c, 0x0104> ReferencedRangeModulatorNumber; typedef gdcm::Attribute<0x300e, 0x0002> ApprovalStatus; typedef gdcm::Attribute<0x300e, 0x0004> ReviewDate; typedef gdcm::Attribute<0x300e, 0x0005> ReviewTime; typedef gdcm::Attribute<0x300e, 0x0008> ReviewerName; typedef gdcm::Attribute<0x4000, 0x0010> Arbitrary; typedef gdcm::Attribute<0x4000, 0x4000> TextComments; typedef gdcm::Attribute<0x4008, 0x0040> ResultsID; typedef gdcm::Attribute<0x4008, 0x0042> ResultsIDIssuer; typedef gdcm::Attribute<0x4008, 0x0050> ReferencedInterpretationSequence; typedef gdcm::Attribute<0x4008, 0x00ff> ReportProductionStatusTrial; typedef gdcm::Attribute<0x4008, 0x0100> InterpretationRecordedDate; typedef gdcm::Attribute<0x4008, 0x0101> InterpretationRecordedTime; typedef gdcm::Attribute<0x4008, 0x0102> InterpretationRecorder; typedef gdcm::Attribute<0x4008, 0x0103> ReferenceToRecordedSound; typedef gdcm::Attribute<0x4008, 0x0108> InterpretationTranscriptionDate; typedef gdcm::Attribute<0x4008, 0x0109> InterpretationTranscriptionTime; typedef gdcm::Attribute<0x4008, 0x010a> InterpretationTranscriber; typedef gdcm::Attribute<0x4008, 0x010b> InterpretationText; typedef gdcm::Attribute<0x4008, 0x010c> InterpretationAuthor; typedef gdcm::Attribute<0x4008, 0x0111> InterpretationApproverSequence; typedef gdcm::Attribute<0x4008, 0x0112> InterpretationApprovalDate; typedef gdcm::Attribute<0x4008, 0x0113> InterpretationApprovalTime; typedef gdcm::Attribute<0x4008, 0x0114> PhysicianApprovingInterpretation; typedef gdcm::Attribute<0x4008, 0x0115> InterpretationDiagnosisDescription; typedef gdcm::Attribute<0x4008, 0x0117> InterpretationDiagnosisCodeSequence; typedef gdcm::Attribute<0x4008, 0x0118> ResultsDistributionListSequence; typedef gdcm::Attribute<0x4008, 0x0119> DistributionName; typedef gdcm::Attribute<0x4008, 0x011a> DistributionAddress; typedef gdcm::Attribute<0x4008, 0x0200> InterpretationID; typedef gdcm::Attribute<0x4008, 0x0202> InterpretationIDIssuer; typedef gdcm::Attribute<0x4008, 0x0210> InterpretationTypeID; typedef gdcm::Attribute<0x4008, 0x0212> InterpretationStatusID; typedef gdcm::Attribute<0x4008, 0x0300> Impressions; typedef gdcm::Attribute<0x4008, 0x4000> ResultsComments; typedef gdcm::Attribute<0x4010, 0x0001> LowEnergyDetectors; typedef gdcm::Attribute<0x4010, 0x0002> HighEnergyDetectors; typedef gdcm::Attribute<0x4010, 0x0004> DetectorGeometrySequence; typedef gdcm::Attribute<0x4010, 0x1001> ThreatROIVoxelSequence; typedef gdcm::Attribute<0x4010, 0x1004> ThreatROIBase; typedef gdcm::Attribute<0x4010, 0x1005> ThreatROIExtents; typedef gdcm::Attribute<0x4010, 0x1006> ThreatROIBitmap; typedef gdcm::Attribute<0x4010, 0x1007> RouteSegmentID; typedef gdcm::Attribute<0x4010, 0x1008> GantryType; typedef gdcm::Attribute<0x4010, 0x1009> OOIOwnerType; typedef gdcm::Attribute<0x4010, 0x100a> RouteSegmentSequence; typedef gdcm::Attribute<0x4010, 0x1010> PotentialThreatObjectID; typedef gdcm::Attribute<0x4010, 0x1011> ThreatSequence; typedef gdcm::Attribute<0x4010, 0x1012> ThreatCategory; typedef gdcm::Attribute<0x4010, 0x1013> ThreatCategoryDescription; typedef gdcm::Attribute<0x4010, 0x1014> ATDAbilityAssessment; typedef gdcm::Attribute<0x4010, 0x1015> ATDAssessmentFlag; typedef gdcm::Attribute<0x4010, 0x1016> ATDAssessmentProbability; typedef gdcm::Attribute<0x4010, 0x1017> Mass; typedef gdcm::Attribute<0x4010, 0x1018> Density; typedef gdcm::Attribute<0x4010, 0x1019> ZEffective; typedef gdcm::Attribute<0x4010, 0x101a> BoardingPassID; typedef gdcm::Attribute<0x4010, 0x101b> CenterOfMass; typedef gdcm::Attribute<0x4010, 0x101c> CenterOfPTO; typedef gdcm::Attribute<0x4010, 0x101d> BoundingPolygon; typedef gdcm::Attribute<0x4010, 0x101e> RouteSegmentStartLocationID; typedef gdcm::Attribute<0x4010, 0x101f> RouteSegmentEndLocationID; typedef gdcm::Attribute<0x4010, 0x1020> RouteSegmentLocationIDType; typedef gdcm::Attribute<0x4010, 0x1021> AbortReason; typedef gdcm::Attribute<0x4010, 0x1023> VolumeOfPTO; typedef gdcm::Attribute<0x4010, 0x1024> AbortFlag; typedef gdcm::Attribute<0x4010, 0x1025> RouteSegmentStartTime; typedef gdcm::Attribute<0x4010, 0x1026> RouteSegmentEndTime; typedef gdcm::Attribute<0x4010, 0x1027> TDRType; typedef gdcm::Attribute<0x4010, 0x1028> InternationalRouteSegment; typedef gdcm::Attribute<0x4010, 0x1029> ThreatDetectionAlgorithmandVersion; typedef gdcm::Attribute<0x4010, 0x102a> AssignedLocation; typedef gdcm::Attribute<0x4010, 0x102b> AlarmDecisionTime; typedef gdcm::Attribute<0x4010, 0x1031> AlarmDecision; typedef gdcm::Attribute<0x4010, 0x1033> NumberOfTotalObjects; typedef gdcm::Attribute<0x4010, 0x1034> NumberOfAlarmObjects; typedef gdcm::Attribute<0x4010, 0x1037> PTORepresentationSequence; typedef gdcm::Attribute<0x4010, 0x1038> ATDAssessmentSequence; typedef gdcm::Attribute<0x4010, 0x1039> TIPType; typedef gdcm::Attribute<0x4010, 0x103a> DICOSVersion; typedef gdcm::Attribute<0x4010, 0x1041> OOIOwnerCreationTime; typedef gdcm::Attribute<0x4010, 0x1042> OOIType; typedef gdcm::Attribute<0x4010, 0x1043> OOISize; typedef gdcm::Attribute<0x4010, 0x1044> AcquisitionStatus; typedef gdcm::Attribute<0x4010, 0x1045> BasisMaterialsCodeSequence; typedef gdcm::Attribute<0x4010, 0x1046> PhantomType; typedef gdcm::Attribute<0x4010, 0x1047> OOIOwnerSequence; typedef gdcm::Attribute<0x4010, 0x1048> ScanType; typedef gdcm::Attribute<0x4010, 0x1051> ItineraryID; typedef gdcm::Attribute<0x4010, 0x1052> ItineraryIDType; typedef gdcm::Attribute<0x4010, 0x1053> ItineraryIDAssigningAuthority; typedef gdcm::Attribute<0x4010, 0x1054> RouteID; typedef gdcm::Attribute<0x4010, 0x1055> RouteIDAssigningAuthority; typedef gdcm::Attribute<0x4010, 0x1056> InboundArrivalType; typedef gdcm::Attribute<0x4010, 0x1058> CarrierID; typedef gdcm::Attribute<0x4010, 0x1059> CarrierIDAssigningAuthority; typedef gdcm::Attribute<0x4010, 0x1060> SourceOrientation; typedef gdcm::Attribute<0x4010, 0x1061> SourcePosition; typedef gdcm::Attribute<0x4010, 0x1062> BeltHeight; typedef gdcm::Attribute<0x4010, 0x1064> AlgorithmRoutingCodeSequence; typedef gdcm::Attribute<0x4010, 0x1067> TransportClassification; typedef gdcm::Attribute<0x4010, 0x1068> OOITypeDescriptor; typedef gdcm::Attribute<0x4010, 0x1069> TotalProcessingTime; typedef gdcm::Attribute<0x4010, 0x106c> DetectorCalibrationData; typedef gdcm::Attribute<0x4ffe, 0x0001> MACParametersSequence; typedef gdcm::Attribute<0x5000, 0x0005> CurveDimensions; typedef gdcm::Attribute<0x5000, 0x0010> NumberOfPoints; typedef gdcm::Attribute<0x5000, 0x0020> TypeOfData; typedef gdcm::Attribute<0x5000, 0x0022> CurveDescription; typedef gdcm::Attribute<0x5000, 0x0030> AxisUnits; typedef gdcm::Attribute<0x5000, 0x0040> AxisLabels; typedef gdcm::Attribute<0x5000, 0x0103> DataValueRepresentation; typedef gdcm::Attribute<0x5000, 0x0104> MinimumCoordinateValue; typedef gdcm::Attribute<0x5000, 0x0105> MaximumCoordinateValue; typedef gdcm::Attribute<0x5000, 0x0106> CurveRange; typedef gdcm::Attribute<0x5000, 0x0110> CurveDataDescriptor; typedef gdcm::Attribute<0x5000, 0x0112> CoordinateStartValue; typedef gdcm::Attribute<0x5000, 0x0114> CoordinateStepValue; typedef gdcm::Attribute<0x5000, 0x1001> CurveActivationLayer; typedef gdcm::Attribute<0x5000, 0x2000> AudioType; typedef gdcm::Attribute<0x5000, 0x2002> AudioSampleFormat; typedef gdcm::Attribute<0x5000, 0x2004> NumberOfChannels; typedef gdcm::Attribute<0x5000, 0x2006> NumberOfSamples; typedef gdcm::Attribute<0x5000, 0x2008> SampleRate; typedef gdcm::Attribute<0x5000, 0x200a> TotalTime; typedef gdcm::Attribute<0x5000, 0x200c> AudioSampleData; typedef gdcm::Attribute<0x5000, 0x200e> AudioComments; typedef gdcm::Attribute<0x5000, 0x2500> CurveLabel; typedef gdcm::Attribute<0x5000, 0x2600> CurveReferencedOverlaySequence; typedef gdcm::Attribute<0x5000, 0x2610> CurveReferencedOverlayGroup; typedef gdcm::Attribute<0x5000, 0x3000> CurveData; typedef gdcm::Attribute<0x5200, 0x9229> SharedFunctionalGroupsSequence; typedef gdcm::Attribute<0x5200, 0x9230> PerFrameFunctionalGroupsSequence; typedef gdcm::Attribute<0x5400, 0x0100> WaveformSequence; typedef gdcm::Attribute<0x5400, 0x0110> ChannelMinimumValue; typedef gdcm::Attribute<0x5400, 0x0112> ChannelMaximumValue; typedef gdcm::Attribute<0x5400, 0x1004> WaveformBitsAllocated; typedef gdcm::Attribute<0x5400, 0x1006> WaveformSampleInterpretation; typedef gdcm::Attribute<0x5400, 0x100a> WaveformPaddingValue; typedef gdcm::Attribute<0x5400, 0x1010> WaveformData; typedef gdcm::Attribute<0x5600, 0x0010> FirstOrderPhaseCorrectionAngle; typedef gdcm::Attribute<0x5600, 0x0020> SpectroscopyData; typedef gdcm::Attribute<0x6000, 0x0010> OverlayRows; typedef gdcm::Attribute<0x6000, 0x0011> OverlayColumns; typedef gdcm::Attribute<0x6000, 0x0012> OverlayPlanes; typedef gdcm::Attribute<0x6000, 0x0015> NumberOfFramesInOverlay; typedef gdcm::Attribute<0x6000, 0x0022> OverlayDescription; typedef gdcm::Attribute<0x6000, 0x0040> OverlayType; typedef gdcm::Attribute<0x6000, 0x0045> OverlaySubtype; typedef gdcm::Attribute<0x6000, 0x0050> OverlayOrigin; typedef gdcm::Attribute<0x6000, 0x0051> ImageFrameOrigin; typedef gdcm::Attribute<0x6000, 0x0052> OverlayPlaneOrigin; typedef gdcm::Attribute<0x6000, 0x0060> OverlayCompressionCode; typedef gdcm::Attribute<0x6000, 0x0061> OverlayCompressionOriginator; typedef gdcm::Attribute<0x6000, 0x0062> OverlayCompressionLabel; typedef gdcm::Attribute<0x6000, 0x0063> OverlayCompressionDescription; typedef gdcm::Attribute<0x6000, 0x0066> OverlayCompressionStepPointers; typedef gdcm::Attribute<0x6000, 0x0068> OverlayRepeatInterval; typedef gdcm::Attribute<0x6000, 0x0069> OverlayBitsGrouped; typedef gdcm::Attribute<0x6000, 0x0100> OverlayBitsAllocated; typedef gdcm::Attribute<0x6000, 0x0102> OverlayBitPosition; typedef gdcm::Attribute<0x6000, 0x0110> OverlayFormat; typedef gdcm::Attribute<0x6000, 0x0200> OverlayLocation; typedef gdcm::Attribute<0x6000, 0x0800> OverlayCodeLabel; typedef gdcm::Attribute<0x6000, 0x0802> OverlayNumberOfTables; typedef gdcm::Attribute<0x6000, 0x0803> OverlayCodeTableLocation; typedef gdcm::Attribute<0x6000, 0x0804> OverlayBitsForCodeWord; typedef gdcm::Attribute<0x6000, 0x1001> OverlayActivationLayer; typedef gdcm::Attribute<0x6000, 0x1100> OverlayDescriptorGray; typedef gdcm::Attribute<0x6000, 0x1101> OverlayDescriptorRed; typedef gdcm::Attribute<0x6000, 0x1102> OverlayDescriptorGreen; typedef gdcm::Attribute<0x6000, 0x1103> OverlayDescriptorBlue; typedef gdcm::Attribute<0x6000, 0x1200> OverlaysGray; typedef gdcm::Attribute<0x6000, 0x1201> OverlaysRed; typedef gdcm::Attribute<0x6000, 0x1202> OverlaysGreen; typedef gdcm::Attribute<0x6000, 0x1203> OverlaysBlue; typedef gdcm::Attribute<0x6000, 0x1301> ROIArea; typedef gdcm::Attribute<0x6000, 0x1302> ROIMean; typedef gdcm::Attribute<0x6000, 0x1303> ROIStandardDeviation; typedef gdcm::Attribute<0x6000, 0x1500> OverlayLabel; typedef gdcm::Attribute<0x6000, 0x3000> OverlayData; typedef gdcm::Attribute<0x6000, 0x4000> OverlayComments; typedef gdcm::Attribute<0x7fe0, 0x0010> PixelData; typedef gdcm::Attribute<0x7fe0, 0x0020> CoefficientsSDVN; typedef gdcm::Attribute<0x7fe0, 0x0030> CoefficientsSDHN; typedef gdcm::Attribute<0x7fe0, 0x0040> CoefficientsSDDN; typedef gdcm::Attribute<0x7f00, 0x0010> VariablePixelData; typedef gdcm::Attribute<0x7f00, 0x0011> VariableNextDataGroup; typedef gdcm::Attribute<0x7f00, 0x0020> VariableCoefficientsSDVN; typedef gdcm::Attribute<0x7f00, 0x0030> VariableCoefficientsSDHN; typedef gdcm::Attribute<0x7f00, 0x0040> VariableCoefficientsSDDN; typedef gdcm::Attribute<0xfffa, 0xfffa> DigitalSignaturesSequence; typedef gdcm::Attribute<0xfffc, 0xfffc> DataSetTrailingPadding; typedef gdcm::Attribute<0xfffe, 0xe000> Item; typedef gdcm::Attribute<0xfffe, 0xe00d> ItemDelimitationItem; typedef gdcm::Attribute<0xfffe, 0xe0dd> SequenceDelimitationItem; typedef gdcm::Attribute<0x0002, 0x0000> FileMetaInformationGroupLength; typedef gdcm::Attribute<0x0002, 0x0001> FileMetaInformationVersion; typedef gdcm::Attribute<0x0002, 0x0002> MediaStorageSOPClassUID; typedef gdcm::Attribute<0x0002, 0x0003> MediaStorageSOPInstanceUID; typedef gdcm::Attribute<0x0002, 0x0010> TransferSyntaxUID; typedef gdcm::Attribute<0x0002, 0x0012> ImplementationClassUID; typedef gdcm::Attribute<0x0002, 0x0013> ImplementationVersionName; typedef gdcm::Attribute<0x0002, 0x0016> SourceApplicationEntityTitle; typedef gdcm::Attribute<0x0002, 0x0100> PrivateInformationCreatorUID; typedef gdcm::Attribute<0x0002, 0x0102> PrivateInformation; typedef gdcm::Attribute<0x0004, 0x1130> FileSetID; typedef gdcm::Attribute<0x0004, 0x1141> FileSetDescriptorFileID; typedef gdcm::Attribute<0x0004, 0x1142> SpecificCharacterSetOfFileSetDescriptorFile; typedef gdcm::Attribute<0x0004, 0x1200> OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity; typedef gdcm::Attribute<0x0004, 0x1202> OffsetOfTheLastDirectoryRecordOfTheRootDirectoryEntity; typedef gdcm::Attribute<0x0004, 0x1212> FileSetConsistencyFlag; typedef gdcm::Attribute<0x0004, 0x1220> DirectoryRecordSequence; typedef gdcm::Attribute<0x0004, 0x1400> OffsetOfTheNextDirectoryRecord; typedef gdcm::Attribute<0x0004, 0x1410> RecordInUseFlag; typedef gdcm::Attribute<0x0004, 0x1420> OffsetOfReferencedLowerLevelDirectoryEntity; typedef gdcm::Attribute<0x0004, 0x1430> DirectoryRecordType; typedef gdcm::Attribute<0x0004, 0x1432> PrivateRecordUID; typedef gdcm::Attribute<0x0004, 0x1500> ReferencedFileID; typedef gdcm::Attribute<0x0004, 0x1504> MRDRDirectoryRecordOffset; typedef gdcm::Attribute<0x0004, 0x1510> ReferencedSOPClassUIDInFile; typedef gdcm::Attribute<0x0004, 0x1511> ReferencedSOPInstanceUIDInFile; typedef gdcm::Attribute<0x0004, 0x1512> ReferencedTransferSyntaxUIDInFile; typedef gdcm::Attribute<0x0004, 0x151a> ReferencedRelatedGeneralSOPClassUIDInFile; typedef gdcm::Attribute<0x0004, 0x1600> NumberOfReferences; } } #endif GDCM-3.0.10/Source/DataDictionary/gdcmTagToType.h000066400000000000000000040017441412732066400213470ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc TagToType.xsl Part6.xml > gdcmTagToType.h /*========================================================================= 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 GDCMTAGTOTYPE_H #define GDCMTAGTOTYPE_H #include "gdcmVR.h" #include "gdcmVM.h" #include "gdcmStaticAssert.h" namespace gdcm { // default template: the compiler should only pick it up when the element is private: template struct TagToType { //GDCM_STATIC_ASSERT( group % 2 ); enum : long long { VRType = VR::VRALL }; enum { VMType = VM::VM1_n }; }; // template for group length: template struct TagToType { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0000> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0001> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0002> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0003> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0010> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0100> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0110> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0120> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0200> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0300> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0400> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0600> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0700> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0800> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0850> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0860> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0900> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0901> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0000,0x0902> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x0903> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x1000> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x1001> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x1002> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x1005> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0000,0x1008> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x1020> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x1021> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x1022> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x1023> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x1030> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x1031> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x4000> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x4010> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x5010> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x5020> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x5110> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x5120> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x5130> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x5140> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x5150> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x5160> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x5170> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x5180> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x5190> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x51a0> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0000,0x51b0> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0002,0x0000> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0002,0x0001> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0002,0x0002> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0002,0x0003> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0002,0x0010> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0002,0x0012> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0002,0x0013> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0002,0x0016> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0002,0x0017> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0002,0x0018> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0002,0x0100> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0002,0x0102> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x1130> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x1141> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_8 }; static const char* GetVMString() { return "1-8"; } }; template <> struct TagToType<0x0004,0x1142> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x1200> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x1202> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x1212> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x1220> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x1400> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x1410> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x1420> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x1430> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x1432> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x1500> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_8 }; static const char* GetVMString() { return "1-8"; } }; template <> struct TagToType<0x0004,0x1504> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x1510> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x1511> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x1512> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0004,0x151a> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0004,0x1600> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0001> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0005> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x0006> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0008> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM2_n }; static const char* GetVMString() { return "2-n"; } }; template <> struct TagToType<0x0008,0x0010> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0012> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0013> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0014> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0015> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0016> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0018> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x001a> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x001b> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0020> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0021> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0022> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0023> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0024> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0025> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x002a> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0030> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0031> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0032> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0033> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0034> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0035> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0040> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0041> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0042> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0050> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0051> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0052> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0053> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0054> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x0055> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0056> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0058> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x0060> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0061> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x0062> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x0064> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0068> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0070> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0080> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0081> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0082> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0090> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0092> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0094> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x0096> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x009c> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x009d> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0100> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0101> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0102> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0103> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0104> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0105> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0106> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0107> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0108> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x010b> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x010c> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x010d> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x010f> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0110> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0112> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0114> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0115> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0116> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0117> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0118> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0119> { static const char* GetVRString() { return "UC"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UC }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0120> { static const char* GetVRString() { return "UR"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UR }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0121> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0122> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0123> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0124> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0201> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0220> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0221> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0222> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0300> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0301> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0302> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0303> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0304> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x0305> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0306> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x0307> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0308> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0309> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1_3 }; static const char* GetVMString() { return "1-3"; } }; template <> struct TagToType<0x0008,0x030a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x030b> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0008,0x030c> { static const char* GetVRString() { return "UC"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UC }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x030d> { static const char* GetVRString() { return "UC"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UC }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x030e> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x030f> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x0310> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1000> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1010> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1030> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1032> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x103e> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x103f> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1040> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1048> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x1049> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1050> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x1052> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1060> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x1062> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1070> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x1072> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1080> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x1084> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1090> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1100> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1110> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1111> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1115> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1120> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1125> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1130> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1134> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x113a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1140> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1145> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x114a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x114b> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1150> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1155> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x115a> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x1160> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x1161> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x1162> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM3_3n }; static const char* GetVMString() { return "3-3n"; } }; template <> struct TagToType<0x0008,0x1163> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0008,0x1164> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1167> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1190> { static const char* GetVRString() { return "UR"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UR }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1195> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1196> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1197> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1198> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1199> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x119a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1200> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x1250> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2110> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2111> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2112> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2120> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2122> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2124> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2127> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2128> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2129> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x212a> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2130> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x2132> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x2133> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2134> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2135> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2142> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2143> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2144> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2200> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2204> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2208> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2218> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2220> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2228> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2229> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2230> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2240> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2242> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2244> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2246> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2251> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2253> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2255> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2256> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2257> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2258> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x2259> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x225a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x225c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x3001> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x3010> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0008,0x3011> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x3012> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x4000> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9007> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM4 }; static const char* GetVMString() { return "4"; } }; template <> struct TagToType<0x0008,0x9092> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9121> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9123> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9124> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9154> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9205> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9206> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9207> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9208> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9209> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9215> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9237> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9410> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9458> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9459> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0008,0x9460> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0010> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0020> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0021> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0022> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0024> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0026> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0027> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0028> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0010,0x0030> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0032> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0033> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0034> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0035> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0040> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0050> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0101> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0102> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0200> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0201> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0212> { static const char* GetVRString() { return "UC"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UC }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0213> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0214> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0215> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0216> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0217> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0218> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x0219> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x1000> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0010,0x1001> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0010,0x1002> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x1005> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x1010> { static const char* GetVRString() { return "AS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x1020> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x1021> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x1022> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x1023> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x1024> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x1030> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x1040> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x1050> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0010,0x1060> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x1080> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x1081> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x1090> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x1100> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2000> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0010,0x2110> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0010,0x2150> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2152> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2154> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0010,0x2155> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2160> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2180> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x21a0> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x21b0> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x21c0> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x21d0> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x21f0> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2201> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2202> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2203> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2210> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2292> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2293> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2294> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2295> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2296> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2297> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2298> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x2299> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x4000> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0010,0x9431> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0010> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0020> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0021> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0030> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0031> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0040> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0042> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0050> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0051> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0060> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0062> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0063> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0012,0x0064> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0071> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0072> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0081> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0082> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0083> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0084> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0085> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0086> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0012,0x0087> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0023> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0024> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0025> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0028> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0030> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0014,0x0032> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0014,0x0034> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0014,0x0042> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0044> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0045> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0046> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0050> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0052> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0054> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0056> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0100> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0014,0x0101> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0102> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0103> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0104> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0105> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0106> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x0107> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0014,0x0108> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0014,0x1010> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x1020> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x1040> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2002> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2004> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2006> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2008> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2012> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2014> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2016> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2018> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x201a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0014,0x201c> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x201e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2030> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2032> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2202> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2204> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2206> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2208> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x220a> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x220c> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x220e> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2210> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2220> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2222> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2224> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x2226> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0014,0x2228> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x222a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0014,0x222c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0014,0x3011> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3012> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3020> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3022> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3024> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3026> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3028> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3040> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3060> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3071> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3072> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3073> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3074> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3075> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3076> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3077> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3080> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x3099> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4002> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4004> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4006> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4008> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x400a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x400c> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x400e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x400f> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4010> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4011> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4012> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4013> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4014> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4015> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4016> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4017> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4018> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4019> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x401a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x401b> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x401c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x401d> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4020> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4022> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4024> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4026> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4028> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4030> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4031> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4032> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4033> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4034> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4035> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4036> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4038> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0014,0x403a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0014,0x403c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0014,0x4040> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4050> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4051> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4052> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4054> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4056> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4057> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4058> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4059> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x405a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x405c> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4060> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4062> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4064> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4070> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4072> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4074> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4076> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4078> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x407a> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x407c> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0014,0x407e> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0014,0x4080> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4081> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4082> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4083> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4084> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4085> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4086> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4087> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4088> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4089> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x408b> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x408c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x408d> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x408e> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4091> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x4092> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x409a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x409b> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x409c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x409d> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x409f> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x40a0> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x40a1> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x40a2> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5002> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5004> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5100> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5101> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5102> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5103> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5104> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5105> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5106> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5107> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5108> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5109> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x510a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x510b> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x510c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x510d> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x510e> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x510f> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5110> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5111> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5112> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5113> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5114> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5115> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5116> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5117> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5118> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x5119> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x511a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x511b> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x511c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x511d> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x511e> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0014,0x511f> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0010> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0012> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0013> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0014> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0015> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x0021> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x0022> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x0023> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0024> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0025> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0026> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0027> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0028> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0029> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x002a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0030> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x0031> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0032> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0033> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x0034> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0035> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0036> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0037> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0038> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0039> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x003a> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0040> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0042> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0050> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0060> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0061> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0070> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0071> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0072> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0073> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0074> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0075> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0080> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0081> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0082> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0083> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0084> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0085> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0086> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x0087> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0088> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0089> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0090> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0091> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0093> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0094> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x0095> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1000> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1002> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1003> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1004> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1005> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1006> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1007> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1008> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1009> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x100a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1010> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1011> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1012> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1014> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1016> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1017> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1018> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1019> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x101a> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x101b> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1020> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1022> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1023> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1030> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1040> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1041> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1042> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1043> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1044> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1045> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1046> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1047> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1048> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1049> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1050> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1060> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1061> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1062> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1063> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1064> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1065> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1066> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1067> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1068> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1069> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x106a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x106c> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x106e> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1070> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1071> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1072> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1073> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1074> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1075> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1076> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1077> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1078> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1079> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1080> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1081> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1082> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1083> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1084> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1085> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1086> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1088> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1090> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1094> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1100> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1110> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1111> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1114> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1120> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1121> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1130> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1131> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1134> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1135> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1136> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1137> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1138> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x113a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1140> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1141> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1142> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1143> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1144> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1145> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1146> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1147> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1149> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x1150> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1151> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1152> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1153> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1154> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1155> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1156> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x115a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x115e> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1160> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1161> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1162> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1164> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x1166> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1170> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1180> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1181> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1182> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x1183> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x1184> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x1190> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1191> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x11a0> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x11a2> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x11a4> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1200> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1201> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1202> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1210> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1240> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1242> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1243> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1244> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1250> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1251> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1260> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1261> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1271> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1272> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1300> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1301> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1302> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1310> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM4 }; static const char* GetVMString() { return "4"; } }; template <> struct TagToType<0x0018,0x1312> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1314> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1315> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1316> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1318> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1320> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1400> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1401> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1402> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1403> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1404> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1405> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1411> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1412> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1413> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1450> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1460> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1470> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1480> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1490> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1491> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1495> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1500> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1508> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1510> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1511> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1520> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1521> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x1530> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1531> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1600> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_3 }; static const char* GetVMString() { return "1-3"; } }; template <> struct TagToType<0x0018,0x1602> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1604> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1606> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1608> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1610> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x1612> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1620> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM2_2n }; static const char* GetVMString() { return "2-2n"; } }; template <> struct TagToType<0x0018,0x1622> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1623> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1624> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0018,0x1700> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_3 }; static const char* GetVMString() { return "1-3"; } }; template <> struct TagToType<0x0018,0x1702> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1704> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1706> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1708> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1710> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x1712> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1720> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM2_2n }; static const char* GetVMString() { return "2-2n"; } }; template <> struct TagToType<0x0018,0x1800> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1801> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1802> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x1803> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x2001> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x2002> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x2003> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x2004> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x2005> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x2006> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x2010> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x2020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x2030> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x2041> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x2042> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x2043> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x2044> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0018,0x2045> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x2046> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x3100> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x3101> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x3102> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x3103> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x3104> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x3105> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x4000> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5000> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x5010> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x5012> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5020> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5021> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5022> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5024> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5026> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5027> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5028> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5029> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5030> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5040> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5050> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5100> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5101> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5104> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x5210> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM6 }; static const char* GetVMString() { return "6"; } }; template <> struct TagToType<0x0018,0x5212> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0018,0x6000> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6011> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6012> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6014> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6016> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6018> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x601a> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x601c> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x601e> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6020> { static const char* GetVRString() { return "SL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6022> { static const char* GetVRString() { return "SL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6024> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6026> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6028> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x602a> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x602c> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x602e> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6030> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6031> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6032> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6034> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6036> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6038> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6039> { static const char* GetVRString() { return "SL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x603a> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x603b> { static const char* GetVRString() { return "SL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x603c> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x603d> { static const char* GetVRString() { return "SL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x603e> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x603f> { static const char* GetVRString() { return "SL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6040> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6041> { static const char* GetVRString() { return "SL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6042> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6043> { static const char* GetVRString() { return "SL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6044> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6046> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6048> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x604a> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x604c> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x604e> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6050> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6052> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x6054> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x6056> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x6058> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x605a> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x6060> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x7000> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7001> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7004> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7005> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7006> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7008> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x700a> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x700c> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x700e> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7010> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7011> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7012> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7014> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7016> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x701a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x7020> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x7022> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x7024> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7026> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x7028> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x702a> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x702b> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7030> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x7032> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7034> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7036> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x7038> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7040> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7041> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7042> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7044> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7046> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x7048> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x704c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7050> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x7052> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x7054> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x7056> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x7058> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x7060> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7062> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7064> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x7065> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x8150> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x8151> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9004> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9005> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9006> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9008> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9009> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9010> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9011> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9012> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9014> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9015> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9016> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9017> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9018> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9019> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9021> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9022> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9024> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9025> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9026> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9027> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9028> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9029> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9030> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9032> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9033> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9034> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9035> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9036> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9037> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9041> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9042> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9043> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9044> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9045> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9046> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9047> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9048> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9049> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9050> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9051> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9052> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x9053> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x9054> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9058> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9059> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9060> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x9061> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x9062> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9063> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x9064> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9065> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x9066> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x9067> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9069> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9070> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9073> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9074> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9075> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9076> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9077> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9078> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9079> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x9080> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9081> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9082> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9083> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9084> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9085> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9087> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9089> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0018,0x9090> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0018,0x9091> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9092> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9093> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9094> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9095> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9096> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9098> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x9100> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x9101> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9103> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9104> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9105> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0018,0x9106> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0018,0x9107> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9112> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9114> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9115> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9117> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9118> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9119> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9125> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9126> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9127> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9147> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9151> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9152> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9155> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9159> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9166> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9168> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9169> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9170> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9171> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9172> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9173> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9174> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9175> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9176> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9177> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9178> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9179> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9180> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9181> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9182> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9183> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9184> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9185> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9186> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9195> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9196> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9197> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9198> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9199> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9200> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9214> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9217> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9218> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9219> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9220> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9226> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9227> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9231> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9232> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9234> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9236> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9239> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9240> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9241> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9250> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9251> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9252> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9253> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9254> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9255> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0018,0x9256> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0018,0x9257> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9258> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9259> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x925a> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x925b> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x925c> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x925d> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x925e> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x925f> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9260> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9295> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9296> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9297> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9298> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9301> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9302> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9303> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9304> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9305> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9306> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9307> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9308> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9309> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9310> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9311> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9312> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9313> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0018,0x9314> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9315> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9316> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9317> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x9318> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0018,0x9319> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9320> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9321> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9322> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x9323> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x9324> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9325> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9326> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9327> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9328> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9329> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9330> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9332> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9333> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9334> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9335> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9337> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9338> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9340> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9341> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9342> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9343> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9344> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9345> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9346> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9351> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9352> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0018,0x9353> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9360> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9401> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9402> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9403> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9404> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x9405> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9406> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9407> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9410> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9412> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9417> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9420> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9423> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9424> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9425> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9426> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9427> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9428> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x9429> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x9430> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x9432> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9433> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9434> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9435> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9436> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9437> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9438> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9439> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9440> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0018,0x9441> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9442> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM2_n }; static const char* GetVMString() { return "2-n"; } }; template <> struct TagToType<0x0018,0x9447> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9449> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9451> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9452> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9455> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9456> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9457> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9461> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0018,0x9462> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9463> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9464> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9465> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9466> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9467> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9468> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9469> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9470> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9471> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9472> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9473> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9474> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9476> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9477> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9504> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9506> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9507> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9508> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9509> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9510> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9511> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9514> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9515> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9516> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9517> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9518> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9519> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9524> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9525> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9526> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9527> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9528> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9530> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9531> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9538> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9541> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9542> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9543> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9544> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9545> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9546> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9547> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9548> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9549> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9550> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9551> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9552> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9553> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9554> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9555> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9556> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9557> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0018,0x9558> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM6 }; static const char* GetVMString() { return "6"; } }; template <> struct TagToType<0x0018,0x9559> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9601> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9602> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9603> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9604> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9605> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9606> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9607> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9621> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9622> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9623> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9624> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9701> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9715> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9716> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9717> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9718> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9719> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9720> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9721> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9722> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9723> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9724> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9725> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9726> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9727> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9729> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9732> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9733> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9734> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9735> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9736> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9737> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9738> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9739> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9740> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9749> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9751> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9755> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9756> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9758> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9759> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9760> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9761> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9762> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9763> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9764> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9765> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9766> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9767> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9768> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9769> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9770> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9771> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9772> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9801> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x9803> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9804> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9805> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9806> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9807> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9808> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9809> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x980b> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x980c> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x980d> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x980e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x980f> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9900> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9901> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9902> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9903> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9904> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9905> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9906> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9907> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9908> { static const char* GetVRString() { return "UC"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UC }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x9909> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x990a> { static const char* GetVRString() { return "UC"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UC }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x990b> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x990c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x990d> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x990e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x990f> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9910> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9911> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9912> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9913> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9914> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9915> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9916> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9917> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9918> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9919> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x991a> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x991b> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x991c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x991d> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x991e> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x991f> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9920> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9921> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9922> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9923> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9924> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9930> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9931> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9932> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9933> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9934> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9935> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9936> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9937> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9938> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x9939> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x993a> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0018,0x993b> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x993c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x993d> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x993e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9941> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9942> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9943> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9944> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9945> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9946> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0x9947> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0xa001> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0xa002> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0018,0xa003> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x000d> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x000e> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0010> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0011> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0012> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0013> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0014> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0015> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0016> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0017> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0018> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0019> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0020,0x0022> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0024> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0026> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0030> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0020,0x0032> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0020,0x0035> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM6 }; static const char* GetVMString() { return "6"; } }; template <> struct TagToType<0x0020,0x0037> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM6 }; static const char* GetVMString() { return "6"; } }; template <> struct TagToType<0x0020,0x0050> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0052> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0060> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0062> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0070> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0080> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0020,0x00aa> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0100> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0105> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0110> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0200> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x0242> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x1000> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x1001> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x1002> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x1003> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x1004> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x1005> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x1020> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0020,0x103f> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x1040> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x1041> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x1070> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0020,0x1200> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x1202> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x1204> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x1206> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x1208> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x1209> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x3401> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x3402> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x3403> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x3404> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x3405> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x3406> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x4000> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x5000> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0020,0x5002> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0020,0x9056> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9057> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9071> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9072> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9111> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9113> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9116> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9128> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9153> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9154> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9155> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9156> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9157> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0020,0x9158> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9161> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9162> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9163> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9164> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9165> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9167> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9170> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9171> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9172> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9213> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9221> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9222> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9228> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9238> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9241> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9245> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9246> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9247> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9248> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9249> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9250> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9251> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9252> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9253> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9254> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9255> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9256> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9257> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9301> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0020,0x9302> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM6 }; static const char* GetVMString() { return "6"; } }; template <> struct TagToType<0x0020,0x9307> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9308> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0020,0x9309> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM16 }; static const char* GetVMString() { return "16"; } }; template <> struct TagToType<0x0020,0x930a> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM16 }; static const char* GetVMString() { return "16"; } }; template <> struct TagToType<0x0020,0x930b> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x930c> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x930d> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x930e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x930f> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9310> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9311> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9312> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9313> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9421> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9450> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9453> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9518> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0020,0x9529> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0020,0x9536> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0001> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0002> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0022,0x0003> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0004> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0022,0x0005> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0006> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0007> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0008> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0009> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x000a> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x000b> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x000c> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x000d> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x000e> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0010> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0011> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0012> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0013> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0014> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0015> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0016> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0017> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0018> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0019> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x001a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x001b> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x001c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x001d> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x001e> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0020> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0021> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0022> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0028> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0030> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0031> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0032> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2_2n }; static const char* GetVMString() { return "2-2n"; } }; template <> struct TagToType<0x0022,0x0035> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0036> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0037> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0038> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0039> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0041> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0042> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0048> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0049> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x004e> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0055> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0056> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0057> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x0058> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1007> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1008> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1009> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1010> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1012> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1019> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1024> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1025> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1028> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1029> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1033> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1035> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1037> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1039> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1040> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1044> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1050> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1053> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1054> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1059> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1065> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1066> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1090> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1092> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1093> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1094> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1095> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1096> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1097> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1100> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1101> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1103> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1121> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1122> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1125> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1127> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1128> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1130> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1131> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1132> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1133> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1134> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1135> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1140> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1150> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1153> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1155> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1159> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1210> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1211> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1212> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1220> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1225> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1230> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1250> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1255> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1257> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1260> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1262> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1265> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1273> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1300> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1310> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1330> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1415> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1420> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1423> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1436> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1443> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1445> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1450> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1454> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1458> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1460> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1463> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0022,0x1465> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1466> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1467> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0022,0x1468> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0022,0x1470> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1472> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1512> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1513> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1515> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1517> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1518> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1525> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1526> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1527> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1528> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1529> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1530> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0022,0x1531> { static const char* GetVRString() { return "OF"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OF }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0010> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0011> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0012> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0016> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0018> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0020> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0021> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0024> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0025> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0028> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0032> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0033> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0034> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0035> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0036> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0037> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0038> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0039> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0040> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0042> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0044> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0045> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0046> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0048> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0050> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0051> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0052> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0053> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0054> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0055> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0056> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0057> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0058> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0059> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0060> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0061> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0062> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0063> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0064> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0065> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0066> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0067> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0068> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0069> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0070> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0071> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0072> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0073> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0074> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0075> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0076> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0077> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0078> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0079> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0080> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0081> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0083> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0085> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0086> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0087> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0088> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0089> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0090> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0091> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0092> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0093> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0094> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0095> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0096> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0097> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0098> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0100> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0102> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0103> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0104> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0105> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0106> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0107> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0108> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0110> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0112> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0113> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0114> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0115> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0117> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0118> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0120> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0122> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0124> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0126> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0202> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0306> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0307> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0308> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0309> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0317> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0320> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0325> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0338> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0341> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0024,0x0344> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0002> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0003> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0004> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0005> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0006> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0008> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0009> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x000a> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x0010> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0011> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0012> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0014> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0030> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0028,0x0031> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0028,0x0032> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0028,0x0034> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0028,0x0040> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0050> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x0051> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x005f> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0060> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0061> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0062> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0063> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0065> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x0066> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x0068> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0069> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0070> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x0080> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0081> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0082> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x0090> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0091> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0092> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0093> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0094> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0100> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0101> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0102> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0103> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0122> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0123> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0124> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0125> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0200> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0300> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0301> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0302> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0303> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0304> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0400> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0401> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0402> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0403> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x0404> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x0700> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0701> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x0702> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x0710> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0720> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0721> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x0722> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0730> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0740> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0a02> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x0a04> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1040> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1041> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1050> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x1051> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x1052> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1053> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1054> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1055> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x1056> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1080> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1090> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1104> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0028,0x1199> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1201> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1202> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1203> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1204> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1211> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1212> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1213> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1214> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1221> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1222> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1223> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1224> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1230> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1231> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1232> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1300> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1350> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1351> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1352> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x135a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1401> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1402> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1403> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1404> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1405> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1406> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1407> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0028,0x1408> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x140b> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x140c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x140d> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x140e> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x140f> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x1410> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x2000> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x2002> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x2110> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x2112> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x2114> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x3000> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x3003> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x3004> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x3010> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x3110> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x4000> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x5000> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x6010> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x6020> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x6022> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x6023> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x6030> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x6040> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x6100> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x6101> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x6102> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM2_2n }; static const char* GetVMString() { return "2-2n"; } }; template <> struct TagToType<0x0028,0x6110> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x6112> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x6114> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0028,0x6120> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x6190> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7000> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7001> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7002> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7003> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7004> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7005> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7006> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7007> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7008> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7009> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x700a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x700b> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x700c> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x700d> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x700e> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x700f> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7010> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7011> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7012> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7013> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x7014> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7015> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7016> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7017> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7018> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0028,0x7019> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x701a> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x701b> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x701c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x701d> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x701e> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x701f> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7020> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7021> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7022> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7023> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7024> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7025> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7026> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x7027> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7028> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7029> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x702a> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x702b> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x702c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x702d> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x702e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x7fe0> { static const char* GetVRString() { return "UR"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UR }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9001> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9002> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9003> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9099> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9108> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9110> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9132> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9145> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9235> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9411> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9415> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9416> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9422> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9443> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9444> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9445> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9446> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0028,0x9454> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9474> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9478> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9501> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9502> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9503> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM2_2n }; static const char* GetVMString() { return "2-2n"; } }; template <> struct TagToType<0x0028,0x9505> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0028,0x9506> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM2_2n }; static const char* GetVMString() { return "2-2n"; } }; template <> struct TagToType<0x0028,0x9507> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM2_2n }; static const char* GetVMString() { return "2-2n"; } }; template <> struct TagToType<0x0028,0x9520> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM16 }; static const char* GetVMString() { return "16"; } }; template <> struct TagToType<0x0028,0x9537> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x000a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x000c> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x0012> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x0032> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x0033> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x0034> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x0035> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1000> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1001> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1010> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1011> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1020> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1021> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0032,0x1030> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1031> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1032> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1033> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1034> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1040> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1041> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1050> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1051> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1055> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1060> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1064> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x1070> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0032,0x4000> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0004> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0008> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0010> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0011> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0014> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0016> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x001a> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x001b> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x001c> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x001d> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x001e> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0020> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0021> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0030> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0032> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0040> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0044> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0050> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0060> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0061> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0062> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0064> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0100> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0101> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0102> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0300> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0400> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0500> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x0502> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0038,0x4000> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0004> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0005> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0010> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x001a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0020> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0200> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0202> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0203> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0205> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x003a,0x0208> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0209> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x020a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x020c> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0210> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0211> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0212> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0213> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0214> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0215> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0218> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x021a> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0220> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0221> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0222> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0223> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0230> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0231> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x003a,0x0240> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0241> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0242> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0244> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x003a,0x0245> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0246> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0247> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0248> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0300> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0301> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x003a,0x0302> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0001> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0040,0x0002> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0003> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0004> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0005> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0006> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0007> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0008> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0009> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x000a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x000b> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0010> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0040,0x0011> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0012> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0026> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0027> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0031> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0032> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0033> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0035> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0036> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0039> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x003a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0100> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0220> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0241> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0242> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0243> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0244> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0245> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0250> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0251> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0252> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0253> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0254> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0255> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0260> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0261> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0270> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0275> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0280> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0281> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0293> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0294> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0295> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0296> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0300> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0301> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0302> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0303> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_2 }; static const char* GetVMString() { return "1-2"; } }; template <> struct TagToType<0x0040,0x0306> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0307> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x030e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0310> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0312> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0314> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0316> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0318> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0320> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0321> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0324> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0330> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0340> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0400> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0440> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0441> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0500> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x050a> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0512> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0513> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0515> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0518> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x051a> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0520> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0550> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0551> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0552> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0553> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0554> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0555> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0556> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0560> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0562> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x059a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0600> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0602> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0610> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0612> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x0620> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x06fa> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x071a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x072a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x073a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x074a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x08d8> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x08da> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x08ea> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x09f8> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1001> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1002> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1003> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1004> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1005> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1006> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1007> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1008> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1009> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x100a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1010> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0040,0x1011> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1012> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1060> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1101> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1102> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1103> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0040,0x1104> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x1400> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x2001> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x2004> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x2005> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x2006> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x2007> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x2008> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x2009> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x2010> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x2011> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x2016> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x2017> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x2400> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x3001> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4001> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4002> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4003> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4004> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4005> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4006> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4007> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4009> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4010> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4011> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4015> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4016> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4018> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4019> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4021> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4022> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4023> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4025> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4026> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4027> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4028> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4029> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4030> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4031> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4032> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4033> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4034> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4035> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4036> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4037> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4040> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4041> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4050> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4051> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4052> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4070> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4071> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4072> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4073> { static const char* GetVRString() { return "UR"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UR }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x4074> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x8302> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x9092> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x9094> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x9096> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x9098> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x9210> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x9212> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0040,0x9213> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x9214> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x9220> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x9224> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0x9225> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa007> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa010> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa020> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa021> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa022> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa023> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa024> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa026> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa027> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa028> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa030> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa032> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa040> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa043> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa047> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa050> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa057> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0040,0xa060> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa066> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa067> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa068> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa070> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa073> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa074> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa075> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa076> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa078> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa07a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa07c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa080> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa082> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa084> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa085> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa088> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa089> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa090> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa0b0> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM2_2n }; static const char* GetVMString() { return "2-2n"; } }; template <> struct TagToType<0x0040,0xa110> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa112> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa120> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa121> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa122> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa123> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa124> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa125> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0040,0xa130> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa132> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0040,0xa136> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0040,0xa138> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0040,0xa13a> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0040,0xa160> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa161> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0040,0xa162> { static const char* GetVRString() { return "SL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0040,0xa163> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0040,0xa167> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa168> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa16a> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa170> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa171> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa172> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa173> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa174> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa180> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa192> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa193> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa194> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa195> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa224> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa290> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa296> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa297> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa29a> { static const char* GetVRString() { return "SL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SL }; enum { VMType = VM::VM2_2n }; static const char* GetVMString() { return "2-2n"; } }; template <> struct TagToType<0x0040,0xa300> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa301> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa307> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa30a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0040,0xa313> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa33a> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa340> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa352> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa353> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa354> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa358> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa360> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa370> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa372> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa375> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa380> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa385> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa390> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa402> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa403> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa404> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa491> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa492> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa493> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa494> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa496> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa504> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa525> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa600> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa601> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa603> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa730> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa731> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa732> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa744> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xa992> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xb020> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xdb00> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xdb06> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xdb07> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xdb0b> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xdb0c> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xdb0d> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xdb73> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0040,0xe001> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xe004> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xe006> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xe008> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xe010> { static const char* GetVRString() { return "UR"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UR }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xe011> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xe020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xe021> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xe022> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xe023> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xe024> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xe025> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xe030> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0040,0xe031> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0042,0x0010> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0042,0x0011> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0042,0x0012> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0042,0x0013> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0042,0x0014> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0044,0x0001> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0044,0x0002> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0044,0x0003> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0044,0x0004> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0044,0x0007> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0044,0x0008> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0044,0x0009> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0044,0x000a> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0044,0x000b> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0044,0x0010> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0044,0x0011> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0044,0x0012> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0044,0x0013> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0044,0x0019> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0012> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0014> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0015> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0016> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0018> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0028> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0030> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0032> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0034> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0036> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0038> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0040> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0042> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0044> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0046> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0050> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0052> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0060> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0062> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0063> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0064> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0070> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0071> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0074> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0075> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0076> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0077> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0080> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0092> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0094> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0095> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0097> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0098> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0100> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0101> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0102> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0104> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0106> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0121> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0122> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0123> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0124> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0125> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0135> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0046,0x0137> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0139> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0145> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0146> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0147> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0201> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0202> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0046,0x0203> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0204> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0205> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0207> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0208> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM2_2n }; static const char* GetVMString() { return "2-2n"; } }; template <> struct TagToType<0x0046,0x0210> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0211> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0212> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0213> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0046,0x0215> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0218> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0220> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0224> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0227> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0230> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0232> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0234> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0236> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0238> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0242> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0244> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0247> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0046,0x0248> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0249> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0250> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0251> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0252> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0046,0x0253> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0001> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0002> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0003> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0006> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0007> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0008> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0010> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0011> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0012> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0013> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0014> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0015> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0048,0x0100> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0102> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM6 }; static const char* GetVMString() { return "6"; } }; template <> struct TagToType<0x0048,0x0105> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0106> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0107> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0108> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0110> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0111> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0112> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0113> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0120> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0200> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0201> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0048,0x0202> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0048,0x0207> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x021a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x021e> { static const char* GetVRString() { return "SL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x021f> { static const char* GetVRString() { return "SL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0048,0x0301> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x0004> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x0010> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x0012> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x0013> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x0014> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x0015> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x0016> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x0017> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x0018> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x0019> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x001a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x001b> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x001c> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x001d> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x001e> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0050,0x0020> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0001> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0002> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0003> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0004> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0006> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0007> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0008> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0009> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0011> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0012> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0013> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0014> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0016> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0025> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0026> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0027> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0028> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0029> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0030> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0031> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0033> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0034> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0036> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0038> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x0039> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0052,0x003a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0010> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0054,0x0011> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0012> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0013> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0014> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0015> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0016> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0017> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0018> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0020> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0054,0x0021> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0022> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0030> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0054,0x0031> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0032> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0033> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0036> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0038> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0039> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0050> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0054,0x0051> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0052> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0053> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0060> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0054,0x0061> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0062> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0063> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0070> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0054,0x0071> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0072> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0073> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0080> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0054,0x0081> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0090> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0054,0x0100> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0054,0x0101> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0200> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0202> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0210> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0054,0x0211> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0220> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0222> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0300> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0302> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0304> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0306> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0308> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0400> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0410> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0412> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0414> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0500> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x0501> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1000> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0054,0x1001> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1002> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1004> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1006> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1100> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1101> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1102> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1103> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1104> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1105> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1200> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1201> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0054,0x1202> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1203> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0054,0x1210> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1220> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0054,0x1300> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1310> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1311> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0054,0x1320> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1321> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1322> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1323> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1324> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1330> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0054,0x1400> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0054,0x1401> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0060,0x3000> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0060,0x3002> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0060,0x3008> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0060,0x3010> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0060,0x3020> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0062,0x0001> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x0002> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x0003> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x0004> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x0005> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x0006> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x0007> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x0008> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x0009> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x000a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x000b> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0062,0x000c> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x000d> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0062,0x000e> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x000f> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x0010> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x0011> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x0012> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x0020> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0062,0x0021> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0064,0x0002> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0064,0x0003> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0064,0x0005> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0064,0x0007> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0064,0x0008> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0064,0x0009> { static const char* GetVRString() { return "OF"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OF }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0064,0x000f> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0064,0x0010> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0001> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0002> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0003> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0004> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0009> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x000a> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x000b> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x000c> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x000d> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x000e> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0010> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0011> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0012> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0013> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0015> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0016> { static const char* GetVRString() { return "OF"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OF }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0017> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0066,0x0018> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0019> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x001a> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM6 }; static const char* GetVMString() { return "6"; } }; template <> struct TagToType<0x0066,0x001b> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0066,0x001c> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0066,0x001e> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x001f> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0020> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0066,0x0021> { static const char* GetVRString() { return "OF"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OF }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0023> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0024> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0025> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0026> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0027> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0028> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0029> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x002a> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x002b> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x002c> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x002d> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x002e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x002f> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0030> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0031> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0032> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0034> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0035> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0036> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0037> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0038> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0040> { static const char* GetVRString() { return "OL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0041> { static const char* GetVRString() { return "OL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0042> { static const char* GetVRString() { return "OL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0043> { static const char* GetVRString() { return "OL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0101> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0102> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0103> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0104> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0105> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0106> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0107> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0108> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0121> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0124> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0125> { static const char* GetVRString() { return "OF"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OF }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0129> { static const char* GetVRString() { return "OL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0130> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0132> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0133> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0066,0x0134> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6210> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6221> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6222> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6223> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6224> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6225> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6226> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6230> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6260> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6265> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6270> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6280> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x62a0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x62a5> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x62c0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x62d0> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x62d5> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x62e0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x62f0> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM9 }; static const char* GetVMString() { return "9"; } }; template <> struct TagToType<0x0068,0x62f2> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6300> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6310> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6320> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6330> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6340> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6345> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6346> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0068,0x6347> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM4 }; static const char* GetVMString() { return "4"; } }; template <> struct TagToType<0x0068,0x6350> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0068,0x6360> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6380> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6390> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x63a0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x63a4> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x63a8> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x63ac> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x63b0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x63c0> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x63d0> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x63e0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x63f0> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6400> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6410> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6420> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6430> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6440> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6450> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0068,0x6460> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM4 }; static const char* GetVMString() { return "4"; } }; template <> struct TagToType<0x0068,0x6470> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6490> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0068,0x64a0> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0068,0x64c0> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0068,0x64d0> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM9 }; static const char* GetVMString() { return "9"; } }; template <> struct TagToType<0x0068,0x64f0> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0068,0x6500> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6510> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6520> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6530> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6540> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6545> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6550> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x6560> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0068,0x6590> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0068,0x65a0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x65b0> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM4 }; static const char* GetVMString() { return "4"; } }; template <> struct TagToType<0x0068,0x65d0> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM6 }; static const char* GetVMString() { return "6"; } }; template <> struct TagToType<0x0068,0x65e0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0068,0x65f0> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM4 }; static const char* GetVMString() { return "4"; } }; template <> struct TagToType<0x0068,0x6610> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0068,0x6620> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0070,0x0001> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0002> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0003> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0004> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0005> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0006> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0008> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0009> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0010> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0070,0x0011> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0070,0x0012> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0014> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0070,0x0015> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0020> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0021> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0022> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2_n }; static const char* GetVMString() { return "2-n"; } }; template <> struct TagToType<0x0070,0x0023> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0024> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0040> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0041> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0042> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0050> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0070,0x0051> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0070,0x0052> { static const char* GetVRString() { return "SL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0070,0x0053> { static const char* GetVRString() { return "SL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0070,0x005a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0060> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0062> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0066> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0067> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0070,0x0068> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0080> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0081> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0082> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0083> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0084> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0086> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0087> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0100> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0101> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0070,0x0102> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0070,0x0103> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0207> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0208> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0209> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0226> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0227> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0228> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0229> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0230> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0231> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0232> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0233> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0234> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0241> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0070,0x0242> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0243> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0244> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0245> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0246> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0247> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0070,0x0248> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0249> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0250> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0251> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0070,0x0252> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0070,0x0253> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0254> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0255> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0256> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0257> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0258> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0261> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0262> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0273> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0070,0x0274> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0278> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0279> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0282> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0284> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0285> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0287> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0288> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0289> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0294> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0295> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0306> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0308> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0309> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x030a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x030b> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM16 }; static const char* GetVMString() { return "16"; } }; template <> struct TagToType<0x0070,0x030c> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x030d> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x030f> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0310> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0311> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0312> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0314> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0318> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x031a> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x031c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x031e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x031f> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0401> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0070,0x0402> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0403> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0404> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x0405> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1101> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1102> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1103> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1104> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1201> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1202> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1203> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1204> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1205> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0070,0x1206> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1207> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1208> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1301> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1302> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1303> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM6 }; static const char* GetVMString() { return "6"; } }; template <> struct TagToType<0x0070,0x1304> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1305> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM4 }; static const char* GetVMString() { return "4"; } }; template <> struct TagToType<0x0070,0x1306> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0070,0x1309> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1501> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1502> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1503> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1505> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0070,0x1507> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0070,0x1508> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x150c> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x150d> { static const char* GetVRString() { return "OD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1511> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0070,0x1512> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1801> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1802> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1803> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1804> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1805> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1806> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1807> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0070,0x1808> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1901> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1903> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1904> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1905> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1907> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1a01> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1a03> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1a04> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0070,0x1a05> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0002> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0004> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0006> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0008> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x000a> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x000c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x000e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0010> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0012> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0014> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0020> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0022> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0024> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0026> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0028> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0030> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0032> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0034> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0038> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0072,0x003a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x003c> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0072,0x003e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0040> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0050> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0052> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0054> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0056> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x005e> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x005f> { static const char* GetVRString() { return "AS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0060> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0061> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0062> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0063> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0064> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0065> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0066> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0067> { static const char* GetVRString() { return "OF"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OF }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0068> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0069> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x006a> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x006b> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x006c> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x006d> { static const char* GetVRString() { return "UN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x006e> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x006f> { static const char* GetVRString() { return "UC"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UC }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0070> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0071> { static const char* GetVRString() { return "UR"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UR }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0072> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0073> { static const char* GetVRString() { return "OD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0074> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0075> { static const char* GetVRString() { return "OL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0076> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0078> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x007a> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x007c> { static const char* GetVRString() { return "SL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x007e> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x007f> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0080> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0100> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0102> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0104> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0106> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0108> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM4 }; static const char* GetVMString() { return "4"; } }; template <> struct TagToType<0x0072,0x010a> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x010c> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x010e> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0200> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0202> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0203> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0204> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0206> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0208> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0210> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0212> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM2_n }; static const char* GetVMString() { return "2-n"; } }; template <> struct TagToType<0x0072,0x0214> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0216> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0218> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0300> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0302> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0304> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0306> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0308> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0310> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0312> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0314> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0316> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0318> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0320> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0330> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0400> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0402> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0404> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0406> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0420> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0072,0x0421> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0072,0x0422> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0424> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0427> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0430> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0432> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM2_n }; static const char* GetVMString() { return "2-n"; } }; template <> struct TagToType<0x0072,0x0434> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0500> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0510> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0512> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0514> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0516> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0520> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0072,0x0600> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0602> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0604> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0700> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0072,0x0702> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0704> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0705> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0706> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0710> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0712> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0714> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0716> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0717> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0072,0x0718> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x0120> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x0121> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1000> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1002> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1004> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1006> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1008> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x100a> { static const char* GetVRString() { return "UR"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UR }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x100c> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x100e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1020> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1022> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1024> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1025> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1026> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1027> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1028> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x102a> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x102b> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x102c> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x102d> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1030> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1032> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1034> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1036> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1038> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x103a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM4 }; static const char* GetVMString() { return "4"; } }; template <> struct TagToType<0x0074,0x1040> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1042> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1044> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1046> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1048> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x104a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x104c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x104e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1050> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1052> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1054> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1056> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1057> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0074,0x1200> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1202> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1204> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1210> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1212> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1216> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1220> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1222> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1224> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1230> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1234> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1236> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1238> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1242> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1244> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1246> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1324> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1338> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x133a> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM4 }; static const char* GetVMString() { return "4"; } }; template <> struct TagToType<0x0074,0x1401> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1402> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1403> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1404> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1405> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1406> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1407> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1408> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x1409> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x140a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x140b> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x140c> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x140d> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0074,0x140e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0001> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0003> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0006> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0008> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x000a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x000c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x000e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0010> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0020> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0030> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0032> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0034> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0036> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0038> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0040> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0055> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0060> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0070> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0080> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x0090> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x00a0> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x00b0> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0076,0x00c0> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0078,0x0001> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0078,0x0010> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0078,0x0020> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0078,0x0024> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0078,0x0026> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0078,0x0028> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0078,0x002a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0078,0x002e> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0078,0x0050> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x0078,0x0060> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM9 }; static const char* GetVMString() { return "9"; } }; template <> struct TagToType<0x0078,0x0070> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0078,0x0090> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x0078,0x00a0> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM4 }; static const char* GetVMString() { return "4"; } }; template <> struct TagToType<0x0078,0x00b0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0078,0x00b2> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0078,0x00b4> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0078,0x00b6> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0078,0x00b8> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0080,0x0001> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0080,0x0002> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0080,0x0003> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0080,0x0004> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0080,0x0005> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0080,0x0006> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0080,0x0007> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM3_3n }; static const char* GetVMString() { return "3-3n"; } }; template <> struct TagToType<0x0080,0x0008> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0080,0x0009> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0080,0x0010> { static const char* GetVRString() { return "OF"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OF }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0080,0x0011> { static const char* GetVRString() { return "OF"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OF }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0080,0x0012> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0080,0x0013> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0001> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0003> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0004> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0005> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0006> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0007> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0008> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x000a> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x000c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0010> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0016> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0017> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0018> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0019> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0021> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0022> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0023> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0032> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0033> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0034> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0035> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0036> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0037> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0082,0x0038> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0088,0x0130> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0088,0x0140> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0088,0x0200> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0088,0x0904> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0088,0x0906> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0088,0x0910> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0088,0x0912> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_32 }; static const char* GetVMString() { return "1-32"; } }; template <> struct TagToType<0x0100,0x0410> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0100,0x0420> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0100,0x0424> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0100,0x0426> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0005> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0010> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0015> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0020> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x0400,0x0100> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0105> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0110> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0115> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0120> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0305> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0310> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0315> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0401> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0402> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0403> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0404> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0500> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0510> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0520> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0550> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0561> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0562> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0563> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0564> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x0400,0x0565> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x0010> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x001e> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x0020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x0030> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x0040> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x0050> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x0060> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x0061> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x0062> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x0063> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x0065> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x0067> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x0069> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x006a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x00a0> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x00a1> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x00a2> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x00a4> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x00a8> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x0500> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2000,0x0510> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0010> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0030> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0040> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0050> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0052> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0054> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0060> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0080> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x00a6> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x00a7> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x2010,0x00a8> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x00a9> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x2010,0x0100> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0110> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0120> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0130> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0140> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0150> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0152> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0154> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x015e> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0160> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0376> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x2010,0x0500> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0510> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2010,0x0520> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2020,0x0010> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2020,0x0020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2020,0x0030> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2020,0x0040> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2020,0x0050> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2020,0x00a0> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2020,0x00a2> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2020,0x0110> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2020,0x0111> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2020,0x0130> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2020,0x0140> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2030,0x0010> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2030,0x0020> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2040,0x0010> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2040,0x0011> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_99 }; static const char* GetVMString() { return "1-99"; } }; template <> struct TagToType<0x2040,0x0020> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2040,0x0060> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2040,0x0070> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2040,0x0072> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2040,0x0074> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2040,0x0080> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2040,0x0082> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2040,0x0090> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2040,0x0100> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2040,0x0500> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2050,0x0010> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2050,0x0020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2050,0x0500> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2100,0x0010> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2100,0x0020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2100,0x0030> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2100,0x0040> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2100,0x0050> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2100,0x0070> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2100,0x0140> { static const char* GetVRString() { return "AE"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AE }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2100,0x0160> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2100,0x0170> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2100,0x0500> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2110,0x0010> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2110,0x0020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2110,0x0030> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2110,0x0099> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2120,0x0010> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2120,0x0050> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2120,0x0070> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2130,0x0010> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2130,0x0015> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2130,0x0030> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2130,0x0040> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2130,0x0050> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2130,0x0060> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2130,0x0080> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2130,0x00a0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2130,0x00c0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2200,0x0001> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2200,0x0002> { static const char* GetVRString() { return "UT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2200,0x0003> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2200,0x0004> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2200,0x0005> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2200,0x0006> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2200,0x0007> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2200,0x0008> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2200,0x0009> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2200,0x000a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2200,0x000b> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2200,0x000c> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2200,0x000d> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2200,0x000e> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x2200,0x000f> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x2200,0x0020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0002> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0003> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0004> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x000a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x000c> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x000d> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x3002,0x000e> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0010> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM6 }; static const char* GetVMString() { return "6"; } }; template <> struct TagToType<0x3002,0x0011> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x3002,0x0012> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x3002,0x0020> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0022> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0024> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0026> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0028> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0029> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0030> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0032> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0034> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM4 }; static const char* GetVMString() { return "4"; } }; template <> struct TagToType<0x3002,0x0040> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0041> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0042> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0050> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0051> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3002,0x0052> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0001> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0002> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0004> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0005> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0006> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0008> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x3004,0x000a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x000c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2_n }; static const char* GetVMString() { return "2-n"; } }; template <> struct TagToType<0x3004,0x000e> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0010> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0012> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0014> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_3 }; static const char* GetVMString() { return "1-3"; } }; template <> struct TagToType<0x3004,0x0040> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x3004,0x0042> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0050> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0052> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0054> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0056> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0058> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2_2n }; static const char* GetVMString() { return "2-2n"; } }; template <> struct TagToType<0x3004,0x0060> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0062> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0070> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0072> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3004,0x0074> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0002> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0004> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0006> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0008> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0009> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0010> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0012> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0014> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0016> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0018> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0020> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0022> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0024> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0026> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0028> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x002a> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x3006,0x002c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0030> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0033> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0036> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0038> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0039> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0040> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0042> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0044> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0045> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x3006,0x0046> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0048> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0049> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x3006,0x0050> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM3_3n }; static const char* GetVMString() { return "3-3n"; } }; template <> struct TagToType<0x3006,0x0080> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0082> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0084> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0085> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0086> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x0088> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x00a0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x00a4> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x00a6> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x00b0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x00b2> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x00b4> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x00b6> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x00b7> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x00b8> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x00b9> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x00c0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x00c2> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x00c4> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3006,0x00c6> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM16 }; static const char* GetVMString() { return "16"; } }; template <> struct TagToType<0x3006,0x00c8> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0010> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0012> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0014> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0016> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0020> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0021> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0022> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0024> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0025> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x002a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x002b> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x002c> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0030> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0032> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0033> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0036> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0037> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x003a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x003b> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0040> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0041> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0042> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0044> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0045> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0046> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0047> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x3008,0x0048> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0050> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0052> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0054> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0056> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x005a> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0060> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0061> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0062> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0063> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0064> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0065> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0066> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0067> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0068> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x006a> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0070> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0072> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0074> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0076> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0078> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x007a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0080> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0082> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0090> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0092> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x00a0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x00b0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x00c0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x00d0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x00e0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x00f0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x00f2> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x00f4> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x00f6> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0100> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0105> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0110> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0116> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0120> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0122> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0130> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0132> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0134> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0136> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0138> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x013a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x013c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0140> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0142> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0150> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0152> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0160> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0162> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0164> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0166> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0168> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0171> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0172> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0173> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0200> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0202> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0220> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0223> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0224> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0230> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0240> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0250> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x3008,0x0251> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0002> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0003> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0004> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0006> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0007> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0009> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x300a,0x000a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x000b> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x300a,0x000c> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x000e> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0010> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0012> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0013> { static const char* GetVRString() { return "UI"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UI }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0014> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0015> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0016> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0018> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x300a,0x001a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0021> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0022> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0023> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0025> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0026> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0027> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0028> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x002a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x002b> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x002c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x002d> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0040> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0042> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0043> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0044> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0046> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0048> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x004a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x004b> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x004c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x004e> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x004f> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0050> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0051> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0052> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0053> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0055> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0070> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0071> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0072> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0078> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0079> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x007a> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x007b> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0080> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0082> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x300a,0x0084> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0086> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0088> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0089> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x008a> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x008b> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x008c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x008d> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x008e> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x008f> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0090> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0091> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0092> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00a0> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00a2> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x300a,0x00a4> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00b0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00b2> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00b3> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00b4> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00b6> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00b8> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00ba> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00bb> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00bc> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00be> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM3_n }; static const char* GetVMString() { return "3-n"; } }; template <> struct TagToType<0x300a,0x00c0> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00c2> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00c3> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00c4> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00c5> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00c6> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00c7> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00c8> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00ca> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00cc> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x300a,0x00ce> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00d0> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00d1> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00d2> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00d3> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00d4> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00d5> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00d6> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00d7> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00d8> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00d9> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00da> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00db> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00dc> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00dd> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00de> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00e0> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00e1> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00e2> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00e3> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00e4> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00e5> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00e6> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00e7> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00e8> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00e9> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x300a,0x00ea> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x300a,0x00eb> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x300a,0x00ec> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x300a,0x00ed> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00ee> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00ef> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00f0> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00f2> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00f3> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00f4> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00f5> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00f6> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00f7> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00f8> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00f9> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00fa> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00fb> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00fc> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x00fe> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0100> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0102> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0104> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0106> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2_2n }; static const char* GetVMString() { return "2-2n"; } }; template <> struct TagToType<0x300a,0x0107> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0108> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0109> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x010a> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x010c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x010e> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0110> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0111> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0112> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0114> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0115> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0116> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0118> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x011a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x011c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM2_2n }; static const char* GetVMString() { return "2-2n"; } }; template <> struct TagToType<0x300a,0x011e> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x011f> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0120> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0121> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0122> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0123> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0124> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0125> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0126> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0128> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0129> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x012a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x012c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x300a,0x012e> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x300a,0x0130> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0131> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0132> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0133> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x300a,0x0134> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0140> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0142> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0144> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0146> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0148> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x014a> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x014c> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x014e> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0150> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0151> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0152> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0153> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0154> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0155> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0180> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0182> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0183> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0184> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0190> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0192> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0194> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0196> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0198> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0199> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x019a> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01a0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01a2> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01a4> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01a6> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01a8> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01b0> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01b2> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01b4> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01b6> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01b8> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01ba> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01bc> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01d0> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01d2> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01d4> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x01d6> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0200> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0202> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0206> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0210> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0212> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0214> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0216> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0218> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x021a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x021b> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x021c> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0222> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0224> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0226> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0228> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0229> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x022a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x022b> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x022c> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x022e> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0230> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0232> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0234> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0236> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0238> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0240> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0242> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0244> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0250> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0260> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0262> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0263> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0264> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0266> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x026a> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x026c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0280> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0282> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0284> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0286> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0288> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x028a> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x028c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0290> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0291> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0292> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0294> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0296> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0298> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x029c> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x029e> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02a0> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02a2> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02a4> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02b0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02b2> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02b3> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02b4> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02b8> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02ba> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02c8> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02d0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02d2> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02d4> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x300a,0x02d6> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02e0> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02e1> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02e2> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x300a,0x02e3> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02e4> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02e5> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02e6> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x300a,0x02e7> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02e8> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02ea> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x02eb> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0302> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0304> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0306> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0308> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0309> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x030a> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x300a,0x030c> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x030d> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x030f> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0312> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0314> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0316> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0318> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0320> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0322> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0330> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0332> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0334> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0336> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0338> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x033a> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x033c> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0340> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0342> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0344> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0346> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0348> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x034a> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x034c> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0350> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0352> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0354> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0355> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0356> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0358> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x035a> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0360> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0362> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0364> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0366> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0370> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0372> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0374> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0380> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0382> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0384> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0386> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0388> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x038a> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x038f> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x300a,0x0390> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0391> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x300a,0x0392> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0393> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0394> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x300a,0x0395> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0396> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x300a,0x0398> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x300a,0x039a> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x03a0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x03a2> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x03a4> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x03a6> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x03a8> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x03aa> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x03ac> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0401> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0402> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0410> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0412> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x300a,0x0420> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0421> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0422> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0423> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0424> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0425> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0431> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0432> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0433> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0434> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0435> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0436> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0440> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0441> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0442> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0443> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0450> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0451> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0452> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0453> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0501> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0502> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0503> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x300a,0x0504> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x300a,0x0505> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0506> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0507> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0508> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0509> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x300a,0x0510> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x300a,0x0511> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300a,0x0512> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0002> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0004> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0006> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0007> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0008> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0009> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x000a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x000c> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x000e> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0020> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0022> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0040> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0042> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0050> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0051> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0055> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0060> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x006a> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0080> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x00a0> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x00b0> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x00c0> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x00d0> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x00e0> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x00f0> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x00f2> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x00f4> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x00f6> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0100> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0102> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0104> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0111> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0112> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300c,0x0113> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300e,0x0002> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300e,0x0004> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300e,0x0005> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x300e,0x0008> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4000,0x0010> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4000,0x4000> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0040> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0042> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0050> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x00ff> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0100> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0101> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0102> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0103> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0108> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0109> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x010a> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x010b> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x010c> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0111> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0112> { static const char* GetVRString() { return "DA"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DA }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0113> { static const char* GetVRString() { return "TM"; } typedef VRToType::Type Type; enum : long long { VRType = VR::TM }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0114> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0115> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0117> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0118> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0119> { static const char* GetVRString() { return "PN"; } typedef VRToType::Type Type; enum : long long { VRType = VR::PN }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x011a> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0200> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0202> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0210> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0212> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x0300> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4008,0x4000> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x0001> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x0002> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x0004> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1001> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1004> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x4010,0x1005> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x4010,0x1006> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1007> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1008> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1009> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x100a> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1010> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1011> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1012> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1013> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1014> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1015> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1016> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1017> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1018> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1019> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x101a> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x101b> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x4010,0x101c> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x4010,0x101d> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM6_n }; static const char* GetVMString() { return "6-n"; } }; template <> struct TagToType<0x4010,0x101e> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x101f> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1021> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x4010,0x1023> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1024> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1025> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1026> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1027> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1028> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1029> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x4010,0x102a> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x102b> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1031> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1033> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1034> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1037> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1038> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1039> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x103a> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1041> { static const char* GetVRString() { return "DT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1042> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1043> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x4010,0x1044> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1045> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1046> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1047> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1048> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1051> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1052> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1053> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1054> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1055> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1056> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1058> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1059> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1060> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x4010,0x1061> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x4010,0x1062> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1064> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1067> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1068> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1069> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x106c> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x106d> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x106e> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x106f> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1070> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1071> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1072> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1073> { static const char* GetVRString() { return "FD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1075> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1076> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1077> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1078> { static const char* GetVRString() { return "ST"; } typedef VRToType::Type Type; enum : long long { VRType = VR::ST }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x1079> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x107a> { static const char* GetVRString() { return "FL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::FL }; enum { VMType = VM::VM3 }; static const char* GetVMString() { return "3"; } }; template <> struct TagToType<0x4010,0x107b> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x107c> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x107d> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x4010,0x107e> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM6 }; static const char* GetVMString() { return "6"; } }; template <> struct TagToType<0x4ffe,0x0001> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x0005> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x0010> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x0020> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x0022> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x0030> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x5000,0x0040> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x5000,0x0103> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x0104> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x5000,0x0105> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x5000,0x0106> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x5000,0x0110> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x5000,0x0112> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x5000,0x0114> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x5000,0x1001> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x2000> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x2002> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x2004> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x2006> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x2008> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x200a> { static const char* GetVRString() { return "UL"; } typedef VRToType::Type Type; enum : long long { VRType = VR::UL }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x200e> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x2500> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x2600> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5000,0x2610> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5200,0x9229> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5200,0x9230> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5400,0x0100> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5400,0x1004> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5400,0x1006> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5600,0x0010> { static const char* GetVRString() { return "OF"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OF }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x5600,0x0020> { static const char* GetVRString() { return "OF"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OF }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0010> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0011> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0012> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0015> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0022> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0040> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0045> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0050> { static const char* GetVRString() { return "SS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SS }; enum { VMType = VM::VM2 }; static const char* GetVMString() { return "2"; } }; template <> struct TagToType<0x6000,0x0051> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0052> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0060> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0061> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0062> { static const char* GetVRString() { return "SH"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SH }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0063> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0066> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x6000,0x0068> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0069> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0100> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0102> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0110> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0200> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0800> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x6000,0x0802> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x0803> { static const char* GetVRString() { return "AT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::AT }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x6000,0x0804> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x1001> { static const char* GetVRString() { return "CS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::CS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x1100> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x1101> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x1102> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x1103> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x1200> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x6000,0x1201> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x6000,0x1202> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x6000,0x1203> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1_n }; static const char* GetVMString() { return "1-n"; } }; template <> struct TagToType<0x6000,0x1301> { static const char* GetVRString() { return "IS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::IS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x1302> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x1303> { static const char* GetVRString() { return "DS"; } typedef VRToType::Type Type; enum : long long { VRType = VR::DS }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x1500> { static const char* GetVRString() { return "LO"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LO }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x6000,0x4000> { static const char* GetVRString() { return "LT"; } typedef VRToType::Type Type; enum : long long { VRType = VR::LT }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x7fe0,0x0008> { static const char* GetVRString() { return "OF"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OF }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x7fe0,0x0009> { static const char* GetVRString() { return "OD"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OD }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x7fe0,0x0020> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x7fe0,0x0030> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x7fe0,0x0040> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x7f00,0x0011> { static const char* GetVRString() { return "US"; } typedef VRToType::Type Type; enum : long long { VRType = VR::US }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x7f00,0x0020> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x7f00,0x0030> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0x7f00,0x0040> { static const char* GetVRString() { return "OW"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OW }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0xfffa,0xfffa> { static const char* GetVRString() { return "SQ"; } typedef VRToType::Type Type; enum : long long { VRType = VR::SQ }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; template <> struct TagToType<0xfffc,0xfffc> { static const char* GetVRString() { return "OB"; } typedef VRToType::Type Type; enum : long long { VRType = VR::OB }; enum { VMType = VM::VM1 }; static const char* GetVMString() { return "1"; } }; } // end namespace gdcm #endif // GDCMTAGTOTYPE_H GDCM-3.0.10/Source/DataDictionary/gdcmUIDs.cxx000066400000000000000000001035361412732066400206440ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc UIDToC++.xsl Part6.xml > gdcmUIDs.cxx /*========================================================================= 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 "gdcmUIDs.h" #include // strcmp namespace gdcm { static const char * const TransferSyntaxStrings[][2] = { {nullptr,nullptr}, // Starts a 1, not 0 {"1.2.840.10008.1.1","Verification SOP Class"}, {"1.2.840.10008.1.2","Implicit VR Little Endian: Default Transfer Syntax for DICOM"}, {"1.2.840.10008.1.2.1","Explicit VR Little Endian"}, {"1.2.840.10008.1.2.1.99","Deflated Explicit VR Little Endian"}, {"1.2.840.10008.1.2.2","Explicit VR Big Endian"}, {"1.2.840.10008.1.2.4.50","JPEG Baseline (Process 1): Default Transfer Syntax for Lossy JPEG 8 Bit Image Compression"}, {"1.2.840.10008.1.2.4.51","JPEG Extended (Process 2 & 4): Default Transfer Syntax for Lossy JPEG 12 Bit Image Compression (Process 4 only)"}, {"1.2.840.10008.1.2.4.52","JPEG Extended (Process 3 & 5)"}, {"1.2.840.10008.1.2.4.53","JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8)"}, {"1.2.840.10008.1.2.4.54","JPEG Spectral Selection, Non-Hierarchical (Process 7 & 9)"}, {"1.2.840.10008.1.2.4.55","JPEG Full Progression, Non-Hierarchical (Process 10 & 12)"}, {"1.2.840.10008.1.2.4.56","JPEG Full Progression, Non-Hierarchical (Process 11 & 13)"}, {"1.2.840.10008.1.2.4.57","JPEG Lossless, Non-Hierarchical (Process 14)"}, {"1.2.840.10008.1.2.4.58","JPEG Lossless, Non-Hierarchical (Process 15)"}, {"1.2.840.10008.1.2.4.59","JPEG Extended, Hierarchical (Process 16 & 18)"}, {"1.2.840.10008.1.2.4.60","JPEG Extended, Hierarchical (Process 17 & 19)"}, {"1.2.840.10008.1.2.4.61","JPEG Spectral Selection, Hierarchical (Process 20 & 22)"}, {"1.2.840.10008.1.2.4.62","JPEG Spectral Selection, Hierarchical (Process 21 & 23)"}, {"1.2.840.10008.1.2.4.63","JPEG Full Progression, Hierarchical (Process 24 & 26)"}, {"1.2.840.10008.1.2.4.64","JPEG Full Progression, Hierarchical (Process 25 & 27)"}, {"1.2.840.10008.1.2.4.65","JPEG Lossless, Hierarchical (Process 28)"}, {"1.2.840.10008.1.2.4.66","JPEG Lossless, Hierarchical (Process 29)"}, {"1.2.840.10008.1.2.4.70","JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1]): Default Transfer Syntax for Lossless JPEG Image Compression"}, {"1.2.840.10008.1.2.4.80","JPEG-LS Lossless Image Compression"}, {"1.2.840.10008.1.2.4.81","JPEG-LS Lossy (Near-Lossless) Image Compression"}, {"1.2.840.10008.1.2.4.90","JPEG 2000 Image Compression (Lossless Only)"}, {"1.2.840.10008.1.2.4.91","JPEG 2000 Image Compression"}, {"1.2.840.10008.1.2.4.92","JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)"}, {"1.2.840.10008.1.2.4.93","JPEG 2000 Part 2 Multi-component Image Compression"}, {"1.2.840.10008.1.2.4.94","JPIP Referenced"}, {"1.2.840.10008.1.2.4.95","JPIP Referenced Deflate"}, {"1.2.840.10008.1.2.4.100","MPEG2 Main Profile @ Main Level"}, {"1.2.840.10008.1.2.5","RLE Lossless"}, {"1.2.840.10008.1.2.6.1","RFC 2557 MIME encapsulation"}, {"1.2.840.10008.1.2.6.2","XML Encoding"}, {"1.2.840.10008.1.3.10","Media Storage Directory Storage"}, {"1.2.840.10008.1.4.1.1","Talairach Brain Atlas Frame of Reference"}, {"1.2.840.10008.1.4.1.2","SPM2 T1 Frame of Reference"}, {"1.2.840.10008.1.4.1.3","SPM2 T2 Frame of Reference"}, {"1.2.840.10008.1.4.1.4","SPM2 PD Frame of Reference"}, {"1.2.840.10008.1.4.1.5","SPM2 EPI Frame of Reference"}, {"1.2.840.10008.1.4.1.6","SPM2 FIL T1 Frame of Reference"}, {"1.2.840.10008.1.4.1.7","SPM2 PET Frame of Reference"}, {"1.2.840.10008.1.4.1.8","SPM2 TRANSM Frame of Reference"}, {"1.2.840.10008.1.4.1.9","SPM2 SPECT Frame of Reference"}, {"1.2.840.10008.1.4.1.10","SPM2 GRAY Frame of Reference"}, {"1.2.840.10008.1.4.1.11","SPM2 WHITE Frame of Reference"}, {"1.2.840.10008.1.4.1.12","SPM2 CSF Frame of Reference"}, {"1.2.840.10008.1.4.1.13","SPM2 BRAINMASK Frame of Reference"}, {"1.2.840.10008.1.4.1.14","SPM2 AVG305T1 Frame of Reference"}, {"1.2.840.10008.1.4.1.15","SPM2 AVG152T1 Frame of Reference"}, {"1.2.840.10008.1.4.1.16","SPM2 AVG152T2 Frame of Reference"}, {"1.2.840.10008.1.4.1.17","SPM2 AVG152PD Frame of Reference"}, {"1.2.840.10008.1.4.1.18","SPM2 SINGLESUBJT1 Frame of Reference"}, {"1.2.840.10008.1.4.2.1","ICBM 452 T1 Frame of Reference"}, {"1.2.840.10008.1.4.2.2","ICBM Single Subject MRI Frame of Reference"}, {"1.2.840.10008.1.9","Basic Study Content Notification SOP Class"}, {"1.2.840.10008.1.20.1","Storage Commitment Push Model SOP Class"}, {"1.2.840.10008.1.20.1.1","Storage Commitment Push Model SOP Instance"}, {"1.2.840.10008.1.20.2","Storage Commitment Pull Model SOP Class"}, {"1.2.840.10008.1.20.2.1","Storage Commitment Pull Model SOP Instance"}, {"1.2.840.10008.1.40","Procedural Event Logging SOP Class"}, {"1.2.840.10008.1.40.1","Procedural Event Logging SOP Instance"}, {"1.2.840.10008.1.42","Substance Administration Logging SOP Class"}, {"1.2.840.10008.1.42.1","Substance Administration Logging SOP Instance"}, {"1.2.840.10008.2.6.1","DICOM UID Registry"}, {"1.2.840.10008.2.16.4","DICOM Controlled Terminology"}, {"1.2.840.10008.3.1.1.1","DICOM Application Context Name"}, {"1.2.840.10008.3.1.2.1.1","Detached Patient Management SOP Class"}, {"1.2.840.10008.3.1.2.1.4","Detached Patient Management Meta SOP Class"}, {"1.2.840.10008.3.1.2.2.1","Detached Visit Management SOP Class"}, {"1.2.840.10008.3.1.2.3.1","Detached Study Management SOP Class"}, {"1.2.840.10008.3.1.2.3.2","Study Component Management SOP Class"}, {"1.2.840.10008.3.1.2.3.3","Modality Performed Procedure Step SOP Class"}, {"1.2.840.10008.3.1.2.3.4","Modality Performed Procedure Step Retrieve SOP Class"}, {"1.2.840.10008.3.1.2.3.5","Modality Performed Procedure Step Notification SOP Class"}, {"1.2.840.10008.3.1.2.5.1","Detached Results Management SOP Class"}, {"1.2.840.10008.3.1.2.5.4","Detached Results Management Meta SOP Class"}, {"1.2.840.10008.3.1.2.5.5","Detached Study Management Meta SOP Class"}, {"1.2.840.10008.3.1.2.6.1","Detached Interpretation Management SOP Class"}, {"1.2.840.10008.4.2","Storage Service Class"}, {"1.2.840.10008.5.1.1.1","Basic Film Session SOP Class"}, {"1.2.840.10008.5.1.1.2","Basic Film Box SOP Class"}, {"1.2.840.10008.5.1.1.4","Basic Grayscale Image Box SOP Class"}, {"1.2.840.10008.5.1.1.4.1","Basic Color Image Box SOP Class"}, {"1.2.840.10008.5.1.1.4.2","Referenced Image Box SOP Class"}, {"1.2.840.10008.5.1.1.9","Basic Grayscale Print Management Meta SOP Class"}, {"1.2.840.10008.5.1.1.9.1","Referenced Grayscale Print Management Meta SOP Class"}, {"1.2.840.10008.5.1.1.14","Print Job SOP Class"}, {"1.2.840.10008.5.1.1.15","Basic Annotation Box SOP Class"}, {"1.2.840.10008.5.1.1.16","Printer SOP Class"}, {"1.2.840.10008.5.1.1.16.376","Printer Configuration Retrieval SOP Class"}, {"1.2.840.10008.5.1.1.17","Printer SOP Instance"}, {"1.2.840.10008.5.1.1.17.376","Printer Configuration Retrieval SOP Instance"}, {"1.2.840.10008.5.1.1.18","Basic Color Print Management Meta SOP Class"}, {"1.2.840.10008.5.1.1.18.1","Referenced Color Print Management Meta SOP Class"}, {"1.2.840.10008.5.1.1.22","VOI LUT Box SOP Class"}, {"1.2.840.10008.5.1.1.23","Presentation LUT SOP Class"}, {"1.2.840.10008.5.1.1.24","Image Overlay Box SOP Class"}, {"1.2.840.10008.5.1.1.24.1","Basic Print Image Overlay Box SOP Class"}, {"1.2.840.10008.5.1.1.25","Print Queue SOP Instance"}, {"1.2.840.10008.5.1.1.26","Print Queue Management SOP Class"}, {"1.2.840.10008.5.1.1.27","Stored Print Storage SOP Class"}, {"1.2.840.10008.5.1.1.29","Hardcopy Grayscale Image Storage SOP Class"}, {"1.2.840.10008.5.1.1.30","Hardcopy Color Image Storage SOP Class"}, {"1.2.840.10008.5.1.1.31","Pull Print Request SOP Class"}, {"1.2.840.10008.5.1.1.32","Pull Stored Print Management Meta SOP Class"}, {"1.2.840.10008.5.1.1.33","Media Creation Management SOP Class UID"}, {"1.2.840.10008.5.1.4.1.1.1","Computed Radiography Image Storage"}, {"1.2.840.10008.5.1.4.1.1.1.1","Digital X-Ray Image Storage - For Presentation"}, {"1.2.840.10008.5.1.4.1.1.1.1.1","Digital X-Ray Image Storage - For Processing"}, {"1.2.840.10008.5.1.4.1.1.1.2","Digital Mammography X-Ray Image Storage - For Presentation"}, {"1.2.840.10008.5.1.4.1.1.1.2.1","Digital Mammography X-Ray Image Storage - For Processing"}, {"1.2.840.10008.5.1.4.1.1.1.3","Digital Intra-oral X-Ray Image Storage - For Presentation"}, {"1.2.840.10008.5.1.4.1.1.1.3.1","Digital Intra-oral X-Ray Image Storage - For Processing"}, {"1.2.840.10008.5.1.4.1.1.2","CT Image Storage"}, {"1.2.840.10008.5.1.4.1.1.2.1","Enhanced CT Image Storage"}, {"1.2.840.10008.5.1.4.1.1.3","Ultrasound Multi-frame Image Storage"}, {"1.2.840.10008.5.1.4.1.1.3.1","Ultrasound Multi-frame Image Storage"}, {"1.2.840.10008.5.1.4.1.1.4","MR Image Storage"}, {"1.2.840.10008.5.1.4.1.1.4.1","Enhanced MR Image Storage"}, {"1.2.840.10008.5.1.4.1.1.4.2","MR Spectroscopy Storage"}, {"1.2.840.10008.5.1.4.1.1.5","Nuclear Medicine Image Storage"}, {"1.2.840.10008.5.1.4.1.1.6","Ultrasound Image Storage"}, {"1.2.840.10008.5.1.4.1.1.6.1","Ultrasound Image Storage"}, {"1.2.840.10008.5.1.4.1.1.7","Secondary Capture Image Storage"}, {"1.2.840.10008.5.1.4.1.1.7.1","Multi-frame Single Bit Secondary Capture Image Storage"}, {"1.2.840.10008.5.1.4.1.1.7.2","Multi-frame Grayscale Byte Secondary Capture Image Storage"}, {"1.2.840.10008.5.1.4.1.1.7.3","Multi-frame Grayscale Word Secondary Capture Image Storage"}, {"1.2.840.10008.5.1.4.1.1.7.4","Multi-frame True Color Secondary Capture Image Storage"}, {"1.2.840.10008.5.1.4.1.1.8","Standalone Overlay Storage"}, {"1.2.840.10008.5.1.4.1.1.9","Standalone Curve Storage"}, {"1.2.840.10008.5.1.4.1.1.9.1","Waveform Storage - Trial"}, {"1.2.840.10008.5.1.4.1.1.9.1.1","12-lead ECG Waveform Storage"}, {"1.2.840.10008.5.1.4.1.1.9.1.2","General ECG Waveform Storage"}, {"1.2.840.10008.5.1.4.1.1.9.1.3","Ambulatory ECG Waveform Storage"}, {"1.2.840.10008.5.1.4.1.1.9.2.1","Hemodynamic Waveform Storage"}, {"1.2.840.10008.5.1.4.1.1.9.3.1","Cardiac Electrophysiology Waveform Storage"}, {"1.2.840.10008.5.1.4.1.1.9.4.1","Basic Voice Audio Waveform Storage"}, {"1.2.840.10008.5.1.4.1.1.10","Standalone Modality LUT Storage"}, {"1.2.840.10008.5.1.4.1.1.11","Standalone VOI LUT Storage"}, {"1.2.840.10008.5.1.4.1.1.11.1","Grayscale Softcopy Presentation State Storage SOP Class"}, {"1.2.840.10008.5.1.4.1.1.11.2","Color Softcopy Presentation State Storage SOP Class"}, {"1.2.840.10008.5.1.4.1.1.11.3","Pseudo-Color Softcopy Presentation State Storage SOP Class"}, {"1.2.840.10008.5.1.4.1.1.11.4","Blending Softcopy Presentation State Storage SOP Class"}, {"1.2.840.10008.5.1.4.1.1.12.1","X-Ray Angiographic Image Storage"}, {"1.2.840.10008.5.1.4.1.1.12.1.1","Enhanced XA Image Storage"}, {"1.2.840.10008.5.1.4.1.1.12.2","X-Ray Radiofluoroscopic Image Storage"}, {"1.2.840.10008.5.1.4.1.1.12.2.1","Enhanced XRF Image Storage"}, {"1.2.840.10008.5.1.4.1.1.13.1.1","X-Ray 3D Angiographic Image Storage"}, {"1.2.840.10008.5.1.4.1.1.13.1.2","X-Ray 3D Craniofacial Image Storage"}, {"1.2.840.10008.5.1.4.1.1.12.3","X-Ray Angiographic Bi-Plane Image Storage"}, {"1.2.840.10008.5.1.4.1.1.20","Nuclear Medicine Image Storage"}, {"1.2.840.10008.5.1.4.1.1.66","Raw Data Storage"}, {"1.2.840.10008.5.1.4.1.1.66.1","Spatial Registration Storage"}, {"1.2.840.10008.5.1.4.1.1.66.2","Spatial Fiducials Storage"}, {"1.2.840.10008.5.1.4.1.1.66.3","Deformable Spatial Registration Storage"}, {"1.2.840.10008.5.1.4.1.1.66.4","Segmentation Storage"}, {"1.2.840.10008.5.1.4.1.1.67","Real World Value Mapping Storage"}, {"1.2.840.10008.5.1.4.1.1.77.1","VL Image Storage - Trial"}, {"1.2.840.10008.5.1.4.1.1.77.2","VL Multi-frame Image Storage - Trial"}, {"1.2.840.10008.5.1.4.1.1.77.1.1","VL Endoscopic Image Storage"}, {"1.2.840.10008.5.1.4.1.1.77.1.1.1","Video Endoscopic Image Storage"}, {"1.2.840.10008.5.1.4.1.1.77.1.2","VL Microscopic Image Storage"}, {"1.2.840.10008.5.1.4.1.1.77.1.2.1","Video Microscopic Image Storage"}, {"1.2.840.10008.5.1.4.1.1.77.1.3","VL Slide-Coordinates Microscopic Image Storage"}, {"1.2.840.10008.5.1.4.1.1.77.1.4","VL Photographic Image Storage"}, {"1.2.840.10008.5.1.4.1.1.77.1.4.1","Video Photographic Image Storage"}, {"1.2.840.10008.5.1.4.1.1.77.1.5.1","Ophthalmic Photography 8 Bit Image Storage"}, {"1.2.840.10008.5.1.4.1.1.77.1.5.2","Ophthalmic Photography 16 Bit Image Storage"}, {"1.2.840.10008.5.1.4.1.1.77.1.5.3","Stereometric Relationship Storage"}, {"1.2.840.10008.5.1.4.1.1.77.1.5.4","Ophthalmic Tomography Image Storage"}, {"1.2.840.10008.5.1.4.1.1.88.1","Text SR Storage - Trial"}, {"1.2.840.10008.5.1.4.1.1.88.2","Audio SR Storage - Trial"}, {"1.2.840.10008.5.1.4.1.1.88.3","Detail SR Storage - Trial"}, {"1.2.840.10008.5.1.4.1.1.88.4","Comprehensive SR Storage - Trial"}, {"1.2.840.10008.5.1.4.1.1.88.11","Basic Text SR Storage"}, {"1.2.840.10008.5.1.4.1.1.88.22","Enhanced SR Storage"}, {"1.2.840.10008.5.1.4.1.1.88.33","Comprehensive SR Storage"}, {"1.2.840.10008.5.1.4.1.1.88.40","Procedure Log Storage"}, {"1.2.840.10008.5.1.4.1.1.88.50","Mammography CAD SR Storage"}, {"1.2.840.10008.5.1.4.1.1.88.59","Key Object Selection Document Storage"}, {"1.2.840.10008.5.1.4.1.1.88.65","Chest CAD SR Storage"}, {"1.2.840.10008.5.1.4.1.1.88.67","X-Ray Radiation Dose SR Storage"}, {"1.2.840.10008.5.1.4.1.1.104.1","Encapsulated PDF Storage"}, {"1.2.840.10008.5.1.4.1.1.104.2","Encapsulated CDA Storage"}, {"1.2.840.10008.5.1.4.1.1.128","Positron Emission Tomography Image Storage"}, {"1.2.840.10008.5.1.4.1.1.129","Standalone PET Curve Storage"}, {"1.2.840.10008.5.1.4.1.1.481.1","RT Image Storage"}, {"1.2.840.10008.5.1.4.1.1.481.2","RT Dose Storage"}, {"1.2.840.10008.5.1.4.1.1.481.3","RT Structure Set Storage"}, {"1.2.840.10008.5.1.4.1.1.481.4","RT Beams Treatment Record Storage"}, {"1.2.840.10008.5.1.4.1.1.481.5","RT Plan Storage"}, {"1.2.840.10008.5.1.4.1.1.481.6","RT Brachy Treatment Record Storage"}, {"1.2.840.10008.5.1.4.1.1.481.7","RT Treatment Summary Record Storage"}, {"1.2.840.10008.5.1.4.1.1.481.8","RT Ion Plan Storage"}, {"1.2.840.10008.5.1.4.1.1.481.9","RT Ion Beams Treatment Record Storage"}, {"1.2.840.10008.5.1.4.1.2.1.1","Patient Root Query/Retrieve Information Model - FIND"}, {"1.2.840.10008.5.1.4.1.2.1.2","Patient Root Query/Retrieve Information Model - MOVE"}, {"1.2.840.10008.5.1.4.1.2.1.3","Patient Root Query/Retrieve Information Model - GET"}, {"1.2.840.10008.5.1.4.1.2.2.1","Study Root Query/Retrieve Information Model - FIND"}, {"1.2.840.10008.5.1.4.1.2.2.2","Study Root Query/Retrieve Information Model - MOVE"}, {"1.2.840.10008.5.1.4.1.2.2.3","Study Root Query/Retrieve Information Model - GET"}, {"1.2.840.10008.5.1.4.1.2.3.1","Patient/Study Only Query/Retrieve Information Model - FIND"}, {"1.2.840.10008.5.1.4.1.2.3.2","Patient/Study Only Query/Retrieve Information Model - MOVE"}, {"1.2.840.10008.5.1.4.1.2.3.3","Patient/Study Only Query/Retrieve Information Model - GET"}, {"1.2.840.10008.5.1.4.31","Modality Worklist Information Model - FIND"}, {"1.2.840.10008.5.1.4.32.1","General Purpose Worklist Information Model - FIND"}, {"1.2.840.10008.5.1.4.32.2","General Purpose Scheduled Procedure Step SOP Class"}, {"1.2.840.10008.5.1.4.32.3","General Purpose Performed Procedure Step SOP Class"}, {"1.2.840.10008.5.1.4.32","General Purpose Worklist Management Meta SOP Class"}, {"1.2.840.10008.5.1.4.33","Instance Availability Notification SOP Class"}, {"1.2.840.10008.5.1.4.34.1","RT Beams Delivery Instruction Storage (Supplement 74 Frozen Draft)"}, {"1.2.840.10008.5.1.4.34.2","RT Conventional Machine Verification (Supplement 74 Frozen Draft)"}, {"1.2.840.10008.5.1.4.34.3","RT Ion Machine Verification (Supplement 74 Frozen Draft)"}, {"1.2.840.10008.5.1.4.34.4","Unified Worklist and Procedure Step Service Class"}, {"1.2.840.10008.5.1.4.34.4.1","Unified Procedure Step - Push SOP Class"}, {"1.2.840.10008.5.1.4.34.4.2","Unified Procedure Step - Watch SOP Class"}, {"1.2.840.10008.5.1.4.34.4.3","Unified Procedure Step - Pull SOP Class"}, {"1.2.840.10008.5.1.4.34.4.4","Unified Procedure Step - Event SOP Class"}, {"1.2.840.10008.5.1.4.34.5","Unified Worklist and Procedure Step SOP Instance"}, {"1.2.840.10008.5.1.4.37.1","General Relevant Patient Information Query"}, {"1.2.840.10008.5.1.4.37.2","Breast Imaging Relevant Patient Information Query"}, {"1.2.840.10008.5.1.4.37.3","Cardiac Relevant Patient Information Query"}, {"1.2.840.10008.5.1.4.38.1","Hanging Protocol Storage"}, {"1.2.840.10008.5.1.4.38.2","Hanging Protocol Information Model - FIND"}, {"1.2.840.10008.5.1.4.38.3","Hanging Protocol Information Model - MOVE"}, {"1.2.840.10008.5.1.4.41","Product Characteristics Query SOP Class"}, {"1.2.840.10008.5.1.4.42","Substance Approval Query SOP Class"}, {"1.2.840.10008.15.0.3.1","dicomDeviceName"}, {"1.2.840.10008.15.0.3.2","dicomDescription"}, {"1.2.840.10008.15.0.3.3","dicomManufacturer"}, {"1.2.840.10008.15.0.3.4","dicomManufacturerModelName"}, {"1.2.840.10008.15.0.3.5","dicomSoftwareVersion"}, {"1.2.840.10008.15.0.3.6","dicomVendorData"}, {"1.2.840.10008.15.0.3.7","dicomAETitle"}, {"1.2.840.10008.15.0.3.8","dicomNetworkConnectionReference"}, {"1.2.840.10008.15.0.3.9","dicomApplicationCluster"}, {"1.2.840.10008.15.0.3.10","dicomAssociationInitiator"}, {"1.2.840.10008.15.0.3.11","dicomAssociationAcceptor"}, {"1.2.840.10008.15.0.3.12","dicomHostname"}, {"1.2.840.10008.15.0.3.13","dicomPort"}, {"1.2.840.10008.15.0.3.14","dicomSOPClass"}, {"1.2.840.10008.15.0.3.15","dicomTransferRole"}, {"1.2.840.10008.15.0.3.16","dicomTransferSyntax"}, {"1.2.840.10008.15.0.3.17","dicomPrimaryDeviceType"}, {"1.2.840.10008.15.0.3.18","dicomRelatedDeviceReference"}, {"1.2.840.10008.15.0.3.19","dicomPreferredCalledAETitle"}, {"1.2.840.10008.15.0.3.20","dicomTLSCyphersuite"}, {"1.2.840.10008.15.0.3.21","dicomAuthorizedNodeCertificateReference"}, {"1.2.840.10008.15.0.3.22","dicomThisNodeCertificateReference"}, {"1.2.840.10008.15.0.3.23","dicomInstalled"}, {"1.2.840.10008.15.0.3.24","dicomStationName"}, {"1.2.840.10008.15.0.3.25","dicomDeviceSerialNumber"}, {"1.2.840.10008.15.0.3.26","dicomInstitutionName"}, {"1.2.840.10008.15.0.3.27","dicomInstitutionAddress"}, {"1.2.840.10008.15.0.3.28","dicomInstitutionDepartmentName"}, {"1.2.840.10008.15.0.3.29","dicomIssuerOfPatientID"}, {"1.2.840.10008.15.0.3.30","dicomPreferredCallingAETitle"}, {"1.2.840.10008.15.0.3.31","dicomSupportedCharacterSet"}, {"1.2.840.10008.15.0.4.1","dicomConfigurationRoot"}, {"1.2.840.10008.15.0.4.2","dicomDevicesRoot"}, {"1.2.840.10008.15.0.4.3","dicomUniqueAETitlesRegistryRoot"}, {"1.2.840.10008.15.0.4.4","dicomDevice"}, {"1.2.840.10008.15.0.4.5","dicomNetworkAE"}, {"1.2.840.10008.15.0.4.6","dicomNetworkConnection"}, {"1.2.840.10008.15.0.4.7","dicomUniqueAETitle"}, {"1.2.840.10008.15.0.4.8","dicomTransferCapability"}, // {"1.2.840.10008.5.1.4.1.1.77.1.6","VL Whole Slide Microscopy Image Storage"}, {"1.2.840.10008.5.1.4.1.1.6.2", "Enhanced US Volume Storage" }, {"1.2.840.10008.5.1.4.1.1.66.5", "Surface Segmentation Storage"}, {"1.2.840.10008.5.1.4.1.1.13.1.3","Breast Tomosynthesis Image Storage"}, {"1.2.840.10008.5.1.4.1.1.2.2", "Legacy Converted Enhanced CT Image Storage"}, {"1.2.840.10008.5.1.4.1.1.4.4", "Legacy Converted Enhanced MR Image Storage"}, {"1.2.840.10008.5.1.4.1.1.128.1", "Legacy Converted Enhanced PET Image Storage"}, {"1.2.840.10008.1.2.4.101", "MPEG2 Main Profile @ High Level"}, {"1.2.840.10008.1.2.4.102", "MPEG-4 AVC/H.264 High Profile / Level 4.1"}, {"1.2.840.10008.1.2.4.103", "MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1"}, ////////////////////////////////////////////// // // 2019b // {"1.2.840.10008.1.5.2","PET Color Palette SOP Instance"}, {"1.2.840.10008.1.5.3","Hot Metal Blue Color Palette SOP Instance"}, {"1.2.840.10008.1.5.4","PET 20 Step Color Palette SOP Instance"}, {"1.2.840.10008.1.5.5","Spring Color Palette SOP Instance"}, {"1.2.840.10008.1.5.6","Summer Color Palette SOP Instance"}, {"1.2.840.10008.1.5.7","Fall Color Palette SOP Instance"}, {"1.2.840.10008.1.5.8","Winter Color Palette SOP Instance"}, {"1.2.840.10008.1.20","Papyrus 3 Implicit VR Little Endian"}, {"1.2.840.10008.2.16.5","Adult Mouse Anatomy Ontology"}, {"1.2.840.10008.2.16.6","Uberon Ontology"}, {"1.2.840.10008.2.16.7","Integrated Taxonomic Information System (ITIS) Taxonomic Serial Number (TSN)"}, {"1.2.840.10008.2.16.8","Mouse Genome Initiative (MGI)"}, {"1.2.840.10008.2.16.9","PubChem Compound CID"}, {"1.2.840.10008.2.16.10","ICD-11"}, {"1.2.840.10008.2.16.11","New York University Melanoma Clinical Cooperative Group"}, {"1.2.840.10008.2.16.12","Mayo Clinic Non-radiological Images Specific Body Structure Anatomical Surface Region Guide"}, {"1.2.840.10008.2.16.13","Image Biomarker Standardisation Initiative"}, {"1.2.840.10008.2.16.14","Radiomics Ontology"}, {"1.2.840.10008.5.1.1.40","Display System SOP Class"}, {"1.2.840.10008.5.1.1.40.1","Display System SOP Instance"}, {"1.2.840.10008.5.1.4.1.1.9.4.2","General Audio Waveform Storage"}, {"1.2.840.10008.5.1.4.1.1.9.5.1","Arterial Pulse Waveform Storage"}, {"1.2.840.10008.5.1.4.1.1.9.6.1","Respiratory Waveform Storage"}, {"1.2.840.10008.5.1.4.1.1.11.5","XA/XRF Grayscale Softcopy Presentation State Storage"}, {"1.2.840.10008.5.1.4.1.1.11.6","Grayscale Planar MPR Volumetric Presentation State Storage"}, {"1.2.840.10008.1.2.4.104","MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video"}, {"1.2.840.10008.1.2.4.105","MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video"}, {"1.2.840.10008.1.2.4.106","MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2"}, {"1.2.840.10008.1.2.4.107","HEVC/H.265 Main Profile / Level 5.1"}, {"1.2.840.10008.1.2.4.108","HEVC/H.265 Main 10 Profile / Level 5.1"}, {"1.2.840.10008.1.5.1","Hot Iron Color Palette SOP Instance"}, {"1.2.840.10008.5.1.4.1.1.11.7","Compositing Planar MPR Volumetric Presentation State Storage"}, {"1.2.840.10008.5.1.4.1.1.11.8","Advanced Blending Presentation State Storage"}, {"1.2.840.10008.5.1.4.1.1.11.9","Volume Rendering Volumetric Presentation State Storage"}, {"1.2.840.10008.5.1.4.1.1.11.10","Segmented Volume Rendering Volumetric Presentation State Storage"}, {"1.2.840.10008.5.1.4.1.1.11.11","Multiple Volume Rendering Volumetric Presentation State Storage"}, {"1.2.840.10008.5.1.4.1.1.12.77","NULL"}, {"1.2.840.10008.5.1.4.1.1.13.1.4","Breast Projection X-Ray Image Storage - For Presentation"}, {"1.2.840.10008.5.1.4.1.1.13.1.5","Breast Projection X-Ray Image Storage - For Processing"}, {"1.2.840.10008.5.1.4.1.1.14.1","Intravascular Optical Coherence Tomography Image Storage - For Presentation"}, {"1.2.840.10008.5.1.4.1.1.14.2","Intravascular Optical Coherence Tomography Image Storage - For Processing"}, {"1.2.840.10008.5.1.4.1.1.30","Parametric Map Storage"}, {"1.2.840.10008.5.1.4.1.1.40","NULL"}, {"1.2.840.10008.5.1.4.1.1.66.6","Tractography Results Storage"}, {"1.2.840.10008.5.1.4.1.1.68.1","Surface Scan Mesh Storage"}, {"1.2.840.10008.5.1.4.1.1.68.2","Surface Scan Point Cloud Storage"}, {"1.2.840.10008.5.1.4.1.1.77.1.5.5","Wide Field Ophthalmic Photography Stereographic Projection Image Storage"}, {"1.2.840.10008.5.1.4.1.1.77.1.5.6","Wide Field Ophthalmic Photography 3D Coordinates Image Storage"}, {"1.2.840.10008.5.1.4.1.1.77.1.5.7","Ophthalmic Optical Coherence Tomography En Face Image Storage"}, {"1.2.840.10008.5.1.4.1.1.77.1.5.8","Ophthalmic Optical Coherence Tomography B-scan Volume Analysis Storage"}, {"1.2.840.10008.5.1.4.1.1.78.1","Lensometry Measurements Storage"}, {"1.2.840.10008.5.1.4.1.1.78.2","Autorefraction Measurements Storage"}, {"1.2.840.10008.5.1.4.1.1.78.3","Keratometry Measurements Storage"}, {"1.2.840.10008.5.1.4.1.1.78.4","Subjective Refraction Measurements Storage"}, {"1.2.840.10008.5.1.4.1.1.78.5","Visual Acuity Measurements Storage"}, {"1.2.840.10008.5.1.4.1.1.78.6","Spectacle Prescription Report Storage"}, {"1.2.840.10008.5.1.4.1.1.78.7","Ophthalmic Axial Measurements Storage"}, {"1.2.840.10008.5.1.4.1.1.78.8","Intraocular Lens Calculations Storage"}, {"1.2.840.10008.5.1.4.1.1.79.1","Macular Grid Thickness and Volume Report Storage"}, {"1.2.840.10008.5.1.4.1.1.80.1","Ophthalmic Visual Field Static Perimetry Measurements Storage"}, {"1.2.840.10008.5.1.4.1.1.81.1","Ophthalmic Thickness Map Storage"}, {"1.2.840.10008.5.1.4.1.1.82.1","Corneal Topography Map Storage"}, {"1.2.840.10008.5.1.4.1.1.88.34","Comprehensive 3D SR Storage"}, {"1.2.840.10008.5.1.4.1.1.88.35","Extensible SR Storage"}, {"1.2.840.10008.5.1.4.1.1.88.68","Radiopharmaceutical Radiation Dose SR Storage"}, {"1.2.840.10008.5.1.4.1.1.88.69","Colon CAD SR Storage"}, {"1.2.840.10008.5.1.4.1.1.88.70","Implantation Plan SR Storage"}, {"1.2.840.10008.5.1.4.1.1.88.71","Acquisition Context SR Storage"}, {"1.2.840.10008.5.1.4.1.1.88.72","Simplified Adult Echo SR Storage"}, {"1.2.840.10008.5.1.4.1.1.88.73","Patient Radiation Dose SR Storage"}, {"1.2.840.10008.5.1.4.1.1.88.74","Planned Imaging Agent Administration SR Storage"}, {"1.2.840.10008.5.1.4.1.1.88.75","Performed Imaging Agent Administration SR Storage"}, {"1.2.840.10008.5.1.4.1.1.90.1","Content Assessment Results Storage"}, {"1.2.840.10008.5.1.4.1.1.104.3","Encapsulated STL Storage"}, {"1.2.840.10008.5.1.4.1.1.130","Enhanced PET Image Storage"}, {"1.2.840.10008.5.1.4.1.1.131","Basic Structured Display Storage"}, {"1.2.840.10008.5.1.4.1.1.200.1","CT Defined Procedure Protocol Storage"}, {"1.2.840.10008.5.1.4.1.1.200.2","CT Performed Procedure Protocol Storage"}, {"1.2.840.10008.5.1.4.1.1.200.3","Protocol Approval Storage"}, {"1.2.840.10008.5.1.4.1.1.200.4","Protocol Approval Information Model - FIND"}, {"1.2.840.10008.5.1.4.1.1.200.5","Protocol Approval Information Model - MOVE"}, {"1.2.840.10008.5.1.4.1.1.200.6","Protocol Approval Information Model - GET"}, {"1.2.840.10008.5.1.4.1.1.481.10","RT Physician Intent Storage"}, {"1.2.840.10008.5.1.4.1.1.481.11","RT Segment Annotation Storage"}, {"1.2.840.10008.5.1.4.1.1.501.1","DICOS CT Image Storage"}, {"1.2.840.10008.5.1.4.1.1.501.2.1","DICOS Digital X-Ray Image Storage - For Presentation"}, {"1.2.840.10008.5.1.4.1.1.501.2.2","DICOS Digital X-Ray Image Storage - For Processing"}, {"1.2.840.10008.5.1.4.1.1.501.3","DICOS Threat Detection Report Storage"}, {"1.2.840.10008.5.1.4.1.1.501.4","DICOS 2D AIT Storage"}, {"1.2.840.10008.5.1.4.1.1.501.5","DICOS 3D AIT Storage"}, {"1.2.840.10008.5.1.4.1.1.501.6","DICOS Quadrupole Resonance (QR) Storage"}, {"1.2.840.10008.5.1.4.1.1.601.1","Eddy Current Image Storage"}, {"1.2.840.10008.5.1.4.1.1.601.2","Eddy Current Multi-frame Image Storage"}, {"1.2.840.10008.5.1.4.1.2.4.2","Composite Instance Root Retrieve - MOVE"}, {"1.2.840.10008.5.1.4.1.2.4.3","Composite Instance Root Retrieve - GET"}, {"1.2.840.10008.5.1.4.1.2.5.3","Composite Instance Retrieve Without Bulk Data - GET"}, {"1.2.840.10008.5.1.4.20.1","Defined Procedure Protocol Information Model - FIND"}, {"1.2.840.10008.5.1.4.20.2","Defined Procedure Protocol Information Model - MOVE"}, {"1.2.840.10008.5.1.4.20.3","Defined Procedure Protocol Information Model - GET"}, {"1.2.840.10008.5.1.4.34.5.1","UPS Filtered Global Subscription SOP Instance"}, {"1.2.840.10008.5.1.4.34.6","Unified Worklist and Procedure Step Service Class (1)"}, {"1.2.840.10008.5.1.4.34.6.1","Unified Procedure Step - Push SOP Class (1)"}, {"1.2.840.10008.5.1.4.34.6.2","Unified Procedure Step - Watch SOP Class (1)"}, {"1.2.840.10008.5.1.4.34.6.3","Unified Procedure Step - Pull SOP Class (1)"}, {"1.2.840.10008.5.1.4.34.6.4","Unified Procedure Step - Event SOP Class (1)"}, {"1.2.840.10008.5.1.4.34.7","RT Beams Delivery Instruction Storage"}, {"1.2.840.10008.5.1.4.34.8","RT Conventional Machine Verification"}, {"1.2.840.10008.5.1.4.34.9","RT Ion Machine Verification"}, {"1.2.840.10008.5.1.4.34.10","RT Brachy Application Setup Delivery Instruction Storage"}, {"1.2.840.10008.5.1.4.38.4","Hanging Protocol Information Model - GET"}, {"1.2.840.10008.5.1.4.39.1","Color Palette Storage"}, {"1.2.840.10008.5.1.4.39.2","Color Palette Query/Retrieve Information Model - FIND"}, {"1.2.840.10008.5.1.4.39.3","Color Palette Query/Retrieve Information Model - MOVE"}, {"1.2.840.10008.5.1.4.39.4","Color Palette Query/Retrieve Information Model - GET"}, {"1.2.840.10008.5.1.4.43.1","Generic Implant Template Storage"}, {"1.2.840.10008.5.1.4.43.2","Generic Implant Template Information Model - FIND"}, {"1.2.840.10008.5.1.4.43.3","Generic Implant Template Information Model - MOVE"}, {"1.2.840.10008.5.1.4.43.4","Generic Implant Template Information Model - GET"}, {"1.2.840.10008.5.1.4.44.1","Implant Assembly Template Storage"}, {"1.2.840.10008.5.1.4.44.2","Implant Assembly Template Information Model - FIND"}, {"1.2.840.10008.5.1.4.44.3","Implant Assembly Template Information Model - MOVE"}, {"1.2.840.10008.5.1.4.44.4","Implant Assembly Template Information Model - GET"}, {"1.2.840.10008.5.1.4.45.1","Implant Template Group Storage"}, {"1.2.840.10008.5.1.4.45.2","Implant Template Group Information Model - FIND"}, {"1.2.840.10008.5.1.4.45.3","Implant Template Group Information Model - MOVE"}, {"1.2.840.10008.5.1.4.45.4","Implant Template Group Information Model - GET"}, {"1.2.840.10008.7.1.1","Native DICOM Model"}, {"1.2.840.10008.7.1.2","Abstract Multi-Dimensional Image Model"}, {"1.2.840.10008.8.1.1","DICOM Content Mapping Resource"}, {"1.2.840.10008.5.1.4.1.1.4.3","Enhanced MR Color Image Storage"}, {"1.2.840.10008.15.1.1","Universal Coordinated Time"}, // // // ////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // // Private UIDs // {"1.2.840.113619.4.2","General Electric Magnetic Resonance Image Storage"}, {"1.2.840.113619.4.3","General Electric Computed Tomography Image Storage"}, {"1.3.12.2.1107.5.9.1","CSA Non-Image Storage"}, // iis_fp_10282r2.pdf {"1.2.840.113619.4.26","GE Private 3D Model Storage" }, {"1.2.840.113619.4.30","GE Advance (PET) Raw Data Storage" }, {"2.16.840.1.113709.1.5.1","GEPACS_PRIVATE_IMS_INFO Storage" }, {"2.16.840.1.113709.1.2.2","COMPRESS_EXPRESS TRANSFER SYNTAX" }, {"1.2.840.113543.6.6.1.3.10002","Unregistered (?) Philips3D" }, {"1.2.392.200036.9116.7.8.1.1.1","Toshiba Private Data Storage" }, // business.fujifilm.co.uk/medical/downloads/DICOM_xg1.pdf {"1.2.392.200036.9125.1.1.2","Fuji Private CR Image Storage"}, // CREF4.09-80_iSite4.1DICOMConformance.pdf // Correction: 1.2.840113619.4.27 -> 1.2.840.113619.4.27 ... sigh // DICOM_Conformance_Statement_MR_R2.6.pdf {"1.2.840.113619.4.27","GE Nuclear Medicine private SOP Class"}, {"1.3.46.670589.11.0.0.12.1","Philips Private MR Spectrum Storage"}, {"1.3.46.670589.11.0.0.12.2","Philips Private MR Series Data Storage"}, {"1.3.46.670589.11.0.0.12.4","Philips Private MR Examcard Storage"}, {"1.3.46.670589.2.3.1.1" ,"Philips Private Specialized XA Image"}, {"1.3.46.670589.2.4.1.1" ,"Philips Private CX Image Storage"}, {"1.3.46.670589.2.5.1.1" ,"Philips iE33 private 3D Object Storage"}, {"1.3.46.670589.5.0.1" ,"Philips Private Volume Storage"}, {"1.3.46.670589.5.0.1.1" ,"Philips Private Volume Image Reference"}, {"1.3.46.670589.5.0.10" ,"Philips Private MR Synthetic Image Storage"}, {"1.3.46.670589.5.0.11" ,"Philips Private MR Cardio Analysis Storage"}, {"1.3.46.670589.5.0.11.1" ,"Philips Private MR Cardio Analysis Data"}, {"1.3.46.670589.5.0.12" ,"Philips Private CX Synthetic Image Storage"}, {"1.3.46.670589.5.0.13" ,"Philips Private Perfusion Image Reference"}, {"1.3.46.670589.5.0.14" ,"Philips Private Perfusion Analysis Data"}, {"1.3.46.670589.5.0.2" ,"Philips Private 3D Object Storage"}, {"1.3.46.670589.5.0.2.1" ,"Philips Private 3D Object 2 Storage"}, {"1.3.46.670589.5.0.3" ,"Philips Private Surface Storage"}, {"1.3.46.670589.5.0.3.1" ,"Philips Private Surface 2 Storage"}, {"1.3.46.670589.5.0.4" ,"Philips Private Composite Object Storage"}, {"1.3.46.670589.5.0.7" ,"Philips Private MR Cardio Profile"}, {"1.3.46.670589.5.0.8" ,"Philips Private MR Cardio"}, {"1.3.46.670589.5.0.9" ,"Philips Private CT Synthetic Image Storage"}, // PACS_conformance_statement_10.2P2.pdf {"1.2.752.24.3.7.6","Sectra Compression (Private Syntax)"}, {"1.2.752.24.3.7.7","Sectra Compression LS (Private Syntax)"}, {"1.2.840.113619.5.2","Implicit VR Big Endian DLX (G.E Private)"}, // DICOM_Conformance_Statement_GEMINI_R3.5_R3.6.pdf {"1.3.46.670589.33.1.4.1","CT-private-ELE"}, {"1.2.392.200036.9125.1.1.4","Fuji Private Mammo CR Image Storage"}, // // // ///////////////////////////////////////////////////////////////////////// { nullptr, nullptr } }; unsigned int UIDs::GetNumberOfTransferSyntaxStrings() { // Do not count NULL sentinels at end static const unsigned int size = sizeof(TransferSyntaxStrings)/sizeof(*TransferSyntaxStrings) - 2; return size; } const char * const * UIDs::GetTransferSyntaxString(unsigned int ts) { if( ts > 0 && ts <= UIDs::GetNumberOfTransferSyntaxStrings() ) return TransferSyntaxStrings[ts]; // else return the {0x0, 0x0} sentinel (begin or end) assert( *TransferSyntaxStrings[ UIDs::GetNumberOfTransferSyntaxStrings() + 1 ] == nullptr ); assert( *TransferSyntaxStrings[ 0 ] == nullptr ); return TransferSyntaxStrings[ UIDs::GetNumberOfTransferSyntaxStrings() + 1 ]; } const char* UIDs::GetUIDString(/*TSType*/ unsigned int ts) { return UIDs::GetTransferSyntaxString(ts)[0]; } const char* UIDs::GetUIDName(/*TSType*/ unsigned int ts) { return UIDs::GetTransferSyntaxString(ts)[1]; } UIDs::TransferSyntaxStringsType UIDs::GetTransferSyntaxStrings() { return TransferSyntaxStrings; } bool UIDs::SetFromUID(const char *str) { TSField = (TSType)0; if(!str) return false; //static const unsigned int size = sizeof(TransferSyntaxStrings) / sizeof(*TransferSyntaxStrings) - 1; TransferSyntaxStringsType uids = GetTransferSyntaxStrings(); int i = 1; // Start at 1, not 0 const char *p = uids[i][0]; while( p != nullptr ) { if( strcmp( p, str ) == 0 ) { break; } ++i; p = uids[i][0]; } //const char * found = uids[i][1]; if( p ) { TSField = TSType(i); assert( TSField != (TSType)0 ); return true; } assert( TSField == (TSType)0 ); return false; } const char *UIDs::GetString() const { return GetUIDString(TSField); } const char *UIDs::GetName() const { return GetUIDName(TSField); } } // end namespace gdcm GDCM-3.0.10/Source/DataDictionary/gdcmUIDs.h000066400000000000000000001722771412732066400203010ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc UIDToC++.xsl Part6.xml > gdcmUIDs.h /*========================================================================= 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 GDCMUIDS_H #define GDCMUIDS_H #include "gdcmTypes.h" namespace gdcm { /** * \brief all known uids */ class GDCM_EXPORT UIDs { public: typedef enum { uid_1_2_840_10008_1_1 = 1, // Verification SOP Class uid_1_2_840_10008_1_2 = 2, // Implicit VR Little Endian: Default Transfer Syntax for DICOM uid_1_2_840_10008_1_2_1 = 3, // Explicit VR Little Endian uid_1_2_840_10008_1_2_1_99 = 4, // Deflated Explicit VR Little Endian uid_1_2_840_10008_1_2_2 = 5, // Explicit VR Big Endian uid_1_2_840_10008_1_2_4_50 = 6, // JPEG Baseline (Process 1): Default Transfer Syntax for Lossy JPEG 8 Bit Image Compression uid_1_2_840_10008_1_2_4_51 = 7, // JPEG Extended (Process 2 & 4): Default Transfer Syntax for Lossy JPEG 12 Bit Image Compression (Process 4 only) uid_1_2_840_10008_1_2_4_52 = 8, // JPEG Extended (Process 3 & 5) uid_1_2_840_10008_1_2_4_53 = 9, // JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8) uid_1_2_840_10008_1_2_4_54 = 10, // JPEG Spectral Selection, Non-Hierarchical (Process 7 & 9) uid_1_2_840_10008_1_2_4_55 = 11, // JPEG Full Progression, Non-Hierarchical (Process 10 & 12) uid_1_2_840_10008_1_2_4_56 = 12, // JPEG Full Progression, Non-Hierarchical (Process 11 & 13) uid_1_2_840_10008_1_2_4_57 = 13, // JPEG Lossless, Non-Hierarchical (Process 14) uid_1_2_840_10008_1_2_4_58 = 14, // JPEG Lossless, Non-Hierarchical (Process 15) uid_1_2_840_10008_1_2_4_59 = 15, // JPEG Extended, Hierarchical (Process 16 & 18) uid_1_2_840_10008_1_2_4_60 = 16, // JPEG Extended, Hierarchical (Process 17 & 19) uid_1_2_840_10008_1_2_4_61 = 17, // JPEG Spectral Selection, Hierarchical (Process 20 & 22) uid_1_2_840_10008_1_2_4_62 = 18, // JPEG Spectral Selection, Hierarchical (Process 21 & 23) uid_1_2_840_10008_1_2_4_63 = 19, // JPEG Full Progression, Hierarchical (Process 24 & 26) uid_1_2_840_10008_1_2_4_64 = 20, // JPEG Full Progression, Hierarchical (Process 25 & 27) uid_1_2_840_10008_1_2_4_65 = 21, // JPEG Lossless, Hierarchical (Process 28) uid_1_2_840_10008_1_2_4_66 = 22, // JPEG Lossless, Hierarchical (Process 29) uid_1_2_840_10008_1_2_4_70 = 23, // JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1]): Default Transfer Syntax for Lossless JPEG Image Compression uid_1_2_840_10008_1_2_4_80 = 24, // JPEG-LS Lossless Image Compression uid_1_2_840_10008_1_2_4_81 = 25, // JPEG-LS Lossy (Near-Lossless) Image Compression uid_1_2_840_10008_1_2_4_90 = 26, // JPEG 2000 Image Compression (Lossless Only) uid_1_2_840_10008_1_2_4_91 = 27, // JPEG 2000 Image Compression uid_1_2_840_10008_1_2_4_92 = 28, // JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only) uid_1_2_840_10008_1_2_4_93 = 29, // JPEG 2000 Part 2 Multi-component Image Compression uid_1_2_840_10008_1_2_4_94 = 30, // JPIP Referenced uid_1_2_840_10008_1_2_4_95 = 31, // JPIP Referenced Deflate uid_1_2_840_10008_1_2_4_100 = 32, // MPEG2 Main Profile @ Main Level uid_1_2_840_10008_1_2_5 = 33, // RLE Lossless uid_1_2_840_10008_1_2_6_1 = 34, // RFC 2557 MIME encapsulation uid_1_2_840_10008_1_2_6_2 = 35, // XML Encoding uid_1_2_840_10008_1_3_10 = 36, // Media Storage Directory Storage uid_1_2_840_10008_1_4_1_1 = 37, // Talairach Brain Atlas Frame of Reference uid_1_2_840_10008_1_4_1_2 = 38, // SPM2 T1 Frame of Reference uid_1_2_840_10008_1_4_1_3 = 39, // SPM2 T2 Frame of Reference uid_1_2_840_10008_1_4_1_4 = 40, // SPM2 PD Frame of Reference uid_1_2_840_10008_1_4_1_5 = 41, // SPM2 EPI Frame of Reference uid_1_2_840_10008_1_4_1_6 = 42, // SPM2 FIL T1 Frame of Reference uid_1_2_840_10008_1_4_1_7 = 43, // SPM2 PET Frame of Reference uid_1_2_840_10008_1_4_1_8 = 44, // SPM2 TRANSM Frame of Reference uid_1_2_840_10008_1_4_1_9 = 45, // SPM2 SPECT Frame of Reference uid_1_2_840_10008_1_4_1_10 = 46, // SPM2 GRAY Frame of Reference uid_1_2_840_10008_1_4_1_11 = 47, // SPM2 WHITE Frame of Reference uid_1_2_840_10008_1_4_1_12 = 48, // SPM2 CSF Frame of Reference uid_1_2_840_10008_1_4_1_13 = 49, // SPM2 BRAINMASK Frame of Reference uid_1_2_840_10008_1_4_1_14 = 50, // SPM2 AVG305T1 Frame of Reference uid_1_2_840_10008_1_4_1_15 = 51, // SPM2 AVG152T1 Frame of Reference uid_1_2_840_10008_1_4_1_16 = 52, // SPM2 AVG152T2 Frame of Reference uid_1_2_840_10008_1_4_1_17 = 53, // SPM2 AVG152PD Frame of Reference uid_1_2_840_10008_1_4_1_18 = 54, // SPM2 SINGLESUBJT1 Frame of Reference uid_1_2_840_10008_1_4_2_1 = 55, // ICBM 452 T1 Frame of Reference uid_1_2_840_10008_1_4_2_2 = 56, // ICBM Single Subject MRI Frame of Reference uid_1_2_840_10008_1_9 = 57, // Basic Study Content Notification SOP Class uid_1_2_840_10008_1_20_1 = 58, // Storage Commitment Push Model SOP Class uid_1_2_840_10008_1_20_1_1 = 59, // Storage Commitment Push Model SOP Instance uid_1_2_840_10008_1_20_2 = 60, // Storage Commitment Pull Model SOP Class uid_1_2_840_10008_1_20_2_1 = 61, // Storage Commitment Pull Model SOP Instance uid_1_2_840_10008_1_40 = 62, // Procedural Event Logging SOP Class uid_1_2_840_10008_1_40_1 = 63, // Procedural Event Logging SOP Instance uid_1_2_840_10008_1_42 = 64, // Substance Administration Logging SOP Class uid_1_2_840_10008_1_42_1 = 65, // Substance Administration Logging SOP Instance uid_1_2_840_10008_2_6_1 = 66, // DICOM UID Registry uid_1_2_840_10008_2_16_4 = 67, // DICOM Controlled Terminology uid_1_2_840_10008_3_1_1_1 = 68, // DICOM Application Context Name uid_1_2_840_10008_3_1_2_1_1 = 69, // Detached Patient Management SOP Class uid_1_2_840_10008_3_1_2_1_4 = 70, // Detached Patient Management Meta SOP Class uid_1_2_840_10008_3_1_2_2_1 = 71, // Detached Visit Management SOP Class uid_1_2_840_10008_3_1_2_3_1 = 72, // Detached Study Management SOP Class uid_1_2_840_10008_3_1_2_3_2 = 73, // Study Component Management SOP Class uid_1_2_840_10008_3_1_2_3_3 = 74, // Modality Performed Procedure Step SOP Class uid_1_2_840_10008_3_1_2_3_4 = 75, // Modality Performed Procedure Step Retrieve SOP Class uid_1_2_840_10008_3_1_2_3_5 = 76, // Modality Performed Procedure Step Notification SOP Class uid_1_2_840_10008_3_1_2_5_1 = 77, // Detached Results Management SOP Class uid_1_2_840_10008_3_1_2_5_4 = 78, // Detached Results Management Meta SOP Class uid_1_2_840_10008_3_1_2_5_5 = 79, // Detached Study Management Meta SOP Class uid_1_2_840_10008_3_1_2_6_1 = 80, // Detached Interpretation Management SOP Class uid_1_2_840_10008_4_2 = 81, // Storage Service Class uid_1_2_840_10008_5_1_1_1 = 82, // Basic Film Session SOP Class uid_1_2_840_10008_5_1_1_2 = 83, // Basic Film Box SOP Class uid_1_2_840_10008_5_1_1_4 = 84, // Basic Grayscale Image Box SOP Class uid_1_2_840_10008_5_1_1_4_1 = 85, // Basic Color Image Box SOP Class uid_1_2_840_10008_5_1_1_4_2 = 86, // Referenced Image Box SOP Class uid_1_2_840_10008_5_1_1_9 = 87, // Basic Grayscale Print Management Meta SOP Class uid_1_2_840_10008_5_1_1_9_1 = 88, // Referenced Grayscale Print Management Meta SOP Class uid_1_2_840_10008_5_1_1_14 = 89, // Print Job SOP Class uid_1_2_840_10008_5_1_1_15 = 90, // Basic Annotation Box SOP Class uid_1_2_840_10008_5_1_1_16 = 91, // Printer SOP Class uid_1_2_840_10008_5_1_1_16_376 = 92, // Printer Configuration Retrieval SOP Class uid_1_2_840_10008_5_1_1_17 = 93, // Printer SOP Instance uid_1_2_840_10008_5_1_1_17_376 = 94, // Printer Configuration Retrieval SOP Instance uid_1_2_840_10008_5_1_1_18 = 95, // Basic Color Print Management Meta SOP Class uid_1_2_840_10008_5_1_1_18_1 = 96, // Referenced Color Print Management Meta SOP Class uid_1_2_840_10008_5_1_1_22 = 97, // VOI LUT Box SOP Class uid_1_2_840_10008_5_1_1_23 = 98, // Presentation LUT SOP Class uid_1_2_840_10008_5_1_1_24 = 99, // Image Overlay Box SOP Class uid_1_2_840_10008_5_1_1_24_1 = 100, // Basic Print Image Overlay Box SOP Class uid_1_2_840_10008_5_1_1_25 = 101, // Print Queue SOP Instance uid_1_2_840_10008_5_1_1_26 = 102, // Print Queue Management SOP Class uid_1_2_840_10008_5_1_1_27 = 103, // Stored Print Storage SOP Class uid_1_2_840_10008_5_1_1_29 = 104, // Hardcopy Grayscale Image Storage SOP Class uid_1_2_840_10008_5_1_1_30 = 105, // Hardcopy Color Image Storage SOP Class uid_1_2_840_10008_5_1_1_31 = 106, // Pull Print Request SOP Class uid_1_2_840_10008_5_1_1_32 = 107, // Pull Stored Print Management Meta SOP Class uid_1_2_840_10008_5_1_1_33 = 108, // Media Creation Management SOP Class UID uid_1_2_840_10008_5_1_4_1_1_1 = 109, // Computed Radiography Image Storage uid_1_2_840_10008_5_1_4_1_1_1_1 = 110, // Digital X-Ray Image Storage - For Presentation uid_1_2_840_10008_5_1_4_1_1_1_1_1 = 111, // Digital X-Ray Image Storage - For Processing uid_1_2_840_10008_5_1_4_1_1_1_2 = 112, // Digital Mammography X-Ray Image Storage - For Presentation uid_1_2_840_10008_5_1_4_1_1_1_2_1 = 113, // Digital Mammography X-Ray Image Storage - For Processing uid_1_2_840_10008_5_1_4_1_1_1_3 = 114, // Digital Intra-oral X-Ray Image Storage - For Presentation uid_1_2_840_10008_5_1_4_1_1_1_3_1 = 115, // Digital Intra-oral X-Ray Image Storage - For Processing uid_1_2_840_10008_5_1_4_1_1_2 = 116, // CT Image Storage uid_1_2_840_10008_5_1_4_1_1_2_1 = 117, // Enhanced CT Image Storage uid_1_2_840_10008_5_1_4_1_1_3 = 118, // Ultrasound Multi-frame Image Storage uid_1_2_840_10008_5_1_4_1_1_3_1 = 119, // Ultrasound Multi-frame Image Storage uid_1_2_840_10008_5_1_4_1_1_4 = 120, // MR Image Storage uid_1_2_840_10008_5_1_4_1_1_4_1 = 121, // Enhanced MR Image Storage uid_1_2_840_10008_5_1_4_1_1_4_2 = 122, // MR Spectroscopy Storage uid_1_2_840_10008_5_1_4_1_1_5 = 123, // Nuclear Medicine Image Storage uid_1_2_840_10008_5_1_4_1_1_6 = 124, // Ultrasound Image Storage uid_1_2_840_10008_5_1_4_1_1_6_1 = 125, // Ultrasound Image Storage uid_1_2_840_10008_5_1_4_1_1_7 = 126, // Secondary Capture Image Storage uid_1_2_840_10008_5_1_4_1_1_7_1 = 127, // Multi-frame Single Bit Secondary Capture Image Storage uid_1_2_840_10008_5_1_4_1_1_7_2 = 128, // Multi-frame Grayscale Byte Secondary Capture Image Storage uid_1_2_840_10008_5_1_4_1_1_7_3 = 129, // Multi-frame Grayscale Word Secondary Capture Image Storage uid_1_2_840_10008_5_1_4_1_1_7_4 = 130, // Multi-frame True Color Secondary Capture Image Storage uid_1_2_840_10008_5_1_4_1_1_8 = 131, // Standalone Overlay Storage uid_1_2_840_10008_5_1_4_1_1_9 = 132, // Standalone Curve Storage uid_1_2_840_10008_5_1_4_1_1_9_1 = 133, // Waveform Storage - Trial uid_1_2_840_10008_5_1_4_1_1_9_1_1 = 134, // 12-lead ECG Waveform Storage uid_1_2_840_10008_5_1_4_1_1_9_1_2 = 135, // General ECG Waveform Storage uid_1_2_840_10008_5_1_4_1_1_9_1_3 = 136, // Ambulatory ECG Waveform Storage uid_1_2_840_10008_5_1_4_1_1_9_2_1 = 137, // Hemodynamic Waveform Storage uid_1_2_840_10008_5_1_4_1_1_9_3_1 = 138, // Cardiac Electrophysiology Waveform Storage uid_1_2_840_10008_5_1_4_1_1_9_4_1 = 139, // Basic Voice Audio Waveform Storage uid_1_2_840_10008_5_1_4_1_1_10 = 140, // Standalone Modality LUT Storage uid_1_2_840_10008_5_1_4_1_1_11 = 141, // Standalone VOI LUT Storage uid_1_2_840_10008_5_1_4_1_1_11_1 = 142, // Grayscale Softcopy Presentation State Storage SOP Class uid_1_2_840_10008_5_1_4_1_1_11_2 = 143, // Color Softcopy Presentation State Storage SOP Class uid_1_2_840_10008_5_1_4_1_1_11_3 = 144, // Pseudo-Color Softcopy Presentation State Storage SOP Class uid_1_2_840_10008_5_1_4_1_1_11_4 = 145, // Blending Softcopy Presentation State Storage SOP Class uid_1_2_840_10008_5_1_4_1_1_12_1 = 146, // X-Ray Angiographic Image Storage uid_1_2_840_10008_5_1_4_1_1_12_1_1 = 147, // Enhanced XA Image Storage uid_1_2_840_10008_5_1_4_1_1_12_2 = 148, // X-Ray Radiofluoroscopic Image Storage uid_1_2_840_10008_5_1_4_1_1_12_2_1 = 149, // Enhanced XRF Image Storage uid_1_2_840_10008_5_1_4_1_1_13_1_1 = 150, // X-Ray 3D Angiographic Image Storage uid_1_2_840_10008_5_1_4_1_1_13_1_2 = 151, // X-Ray 3D Craniofacial Image Storage uid_1_2_840_10008_5_1_4_1_1_12_3 = 152, // X-Ray Angiographic Bi-Plane Image Storage uid_1_2_840_10008_5_1_4_1_1_20 = 153, // Nuclear Medicine Image Storage uid_1_2_840_10008_5_1_4_1_1_66 = 154, // Raw Data Storage uid_1_2_840_10008_5_1_4_1_1_66_1 = 155, // Spatial Registration Storage uid_1_2_840_10008_5_1_4_1_1_66_2 = 156, // Spatial Fiducials Storage uid_1_2_840_10008_5_1_4_1_1_66_3 = 157, // Deformable Spatial Registration Storage uid_1_2_840_10008_5_1_4_1_1_66_4 = 158, // Segmentation Storage uid_1_2_840_10008_5_1_4_1_1_67 = 159, // Real World Value Mapping Storage uid_1_2_840_10008_5_1_4_1_1_77_1 = 160, // VL Image Storage - Trial uid_1_2_840_10008_5_1_4_1_1_77_2 = 161, // VL Multi-frame Image Storage - Trial uid_1_2_840_10008_5_1_4_1_1_77_1_1 = 162, // VL Endoscopic Image Storage uid_1_2_840_10008_5_1_4_1_1_77_1_1_1 = 163, // Video Endoscopic Image Storage uid_1_2_840_10008_5_1_4_1_1_77_1_2 = 164, // VL Microscopic Image Storage uid_1_2_840_10008_5_1_4_1_1_77_1_2_1 = 165, // Video Microscopic Image Storage uid_1_2_840_10008_5_1_4_1_1_77_1_3 = 166, // VL Slide-Coordinates Microscopic Image Storage uid_1_2_840_10008_5_1_4_1_1_77_1_4 = 167, // VL Photographic Image Storage uid_1_2_840_10008_5_1_4_1_1_77_1_4_1 = 168, // Video Photographic Image Storage uid_1_2_840_10008_5_1_4_1_1_77_1_5_1 = 169, // Ophthalmic Photography 8 Bit Image Storage uid_1_2_840_10008_5_1_4_1_1_77_1_5_2 = 170, // Ophthalmic Photography 16 Bit Image Storage uid_1_2_840_10008_5_1_4_1_1_77_1_5_3 = 171, // Stereometric Relationship Storage uid_1_2_840_10008_5_1_4_1_1_77_1_5_4 = 172, // Ophthalmic Tomography Image Storage uid_1_2_840_10008_5_1_4_1_1_88_1 = 173, // Text SR Storage - Trial uid_1_2_840_10008_5_1_4_1_1_88_2 = 174, // Audio SR Storage - Trial uid_1_2_840_10008_5_1_4_1_1_88_3 = 175, // Detail SR Storage - Trial uid_1_2_840_10008_5_1_4_1_1_88_4 = 176, // Comprehensive SR Storage - Trial uid_1_2_840_10008_5_1_4_1_1_88_11 = 177, // Basic Text SR Storage uid_1_2_840_10008_5_1_4_1_1_88_22 = 178, // Enhanced SR Storage uid_1_2_840_10008_5_1_4_1_1_88_33 = 179, // Comprehensive SR Storage uid_1_2_840_10008_5_1_4_1_1_88_40 = 180, // Procedure Log Storage uid_1_2_840_10008_5_1_4_1_1_88_50 = 181, // Mammography CAD SR Storage uid_1_2_840_10008_5_1_4_1_1_88_59 = 182, // Key Object Selection Document Storage uid_1_2_840_10008_5_1_4_1_1_88_65 = 183, // Chest CAD SR Storage uid_1_2_840_10008_5_1_4_1_1_88_67 = 184, // X-Ray Radiation Dose SR Storage uid_1_2_840_10008_5_1_4_1_1_104_1 = 185, // Encapsulated PDF Storage uid_1_2_840_10008_5_1_4_1_1_104_2 = 186, // Encapsulated CDA Storage uid_1_2_840_10008_5_1_4_1_1_128 = 187, // Positron Emission Tomography Image Storage uid_1_2_840_10008_5_1_4_1_1_129 = 188, // Standalone PET Curve Storage uid_1_2_840_10008_5_1_4_1_1_481_1 = 189, // RT Image Storage uid_1_2_840_10008_5_1_4_1_1_481_2 = 190, // RT Dose Storage uid_1_2_840_10008_5_1_4_1_1_481_3 = 191, // RT Structure Set Storage uid_1_2_840_10008_5_1_4_1_1_481_4 = 192, // RT Beams Treatment Record Storage uid_1_2_840_10008_5_1_4_1_1_481_5 = 193, // RT Plan Storage uid_1_2_840_10008_5_1_4_1_1_481_6 = 194, // RT Brachy Treatment Record Storage uid_1_2_840_10008_5_1_4_1_1_481_7 = 195, // RT Treatment Summary Record Storage uid_1_2_840_10008_5_1_4_1_1_481_8 = 196, // RT Ion Plan Storage uid_1_2_840_10008_5_1_4_1_1_481_9 = 197, // RT Ion Beams Treatment Record Storage uid_1_2_840_10008_5_1_4_1_2_1_1 = 198, // Patient Root Query/Retrieve Information Model - FIND uid_1_2_840_10008_5_1_4_1_2_1_2 = 199, // Patient Root Query/Retrieve Information Model - MOVE uid_1_2_840_10008_5_1_4_1_2_1_3 = 200, // Patient Root Query/Retrieve Information Model - GET uid_1_2_840_10008_5_1_4_1_2_2_1 = 201, // Study Root Query/Retrieve Information Model - FIND uid_1_2_840_10008_5_1_4_1_2_2_2 = 202, // Study Root Query/Retrieve Information Model - MOVE uid_1_2_840_10008_5_1_4_1_2_2_3 = 203, // Study Root Query/Retrieve Information Model - GET uid_1_2_840_10008_5_1_4_1_2_3_1 = 204, // Patient/Study Only Query/Retrieve Information Model - FIND uid_1_2_840_10008_5_1_4_1_2_3_2 = 205, // Patient/Study Only Query/Retrieve Information Model - MOVE uid_1_2_840_10008_5_1_4_1_2_3_3 = 206, // Patient/Study Only Query/Retrieve Information Model - GET uid_1_2_840_10008_5_1_4_31 = 207, // Modality Worklist Information Model - FIND uid_1_2_840_10008_5_1_4_32_1 = 208, // General Purpose Worklist Information Model - FIND uid_1_2_840_10008_5_1_4_32_2 = 209, // General Purpose Scheduled Procedure Step SOP Class uid_1_2_840_10008_5_1_4_32_3 = 210, // General Purpose Performed Procedure Step SOP Class uid_1_2_840_10008_5_1_4_32 = 211, // General Purpose Worklist Management Meta SOP Class uid_1_2_840_10008_5_1_4_33 = 212, // Instance Availability Notification SOP Class uid_1_2_840_10008_5_1_4_34_1 = 213, // RT Beams Delivery Instruction Storage (Supplement 74 Frozen Draft) uid_1_2_840_10008_5_1_4_34_2 = 214, // RT Conventional Machine Verification (Supplement 74 Frozen Draft) uid_1_2_840_10008_5_1_4_34_3 = 215, // RT Ion Machine Verification (Supplement 74 Frozen Draft) uid_1_2_840_10008_5_1_4_34_4 = 216, // Unified Worklist and Procedure Step Service Class uid_1_2_840_10008_5_1_4_34_4_1 = 217, // Unified Procedure Step - Push SOP Class uid_1_2_840_10008_5_1_4_34_4_2 = 218, // Unified Procedure Step - Watch SOP Class uid_1_2_840_10008_5_1_4_34_4_3 = 219, // Unified Procedure Step - Pull SOP Class uid_1_2_840_10008_5_1_4_34_4_4 = 220, // Unified Procedure Step - Event SOP Class uid_1_2_840_10008_5_1_4_34_5 = 221, // Unified Worklist and Procedure Step SOP Instance uid_1_2_840_10008_5_1_4_37_1 = 222, // General Relevant Patient Information Query uid_1_2_840_10008_5_1_4_37_2 = 223, // Breast Imaging Relevant Patient Information Query uid_1_2_840_10008_5_1_4_37_3 = 224, // Cardiac Relevant Patient Information Query uid_1_2_840_10008_5_1_4_38_1 = 225, // Hanging Protocol Storage uid_1_2_840_10008_5_1_4_38_2 = 226, // Hanging Protocol Information Model - FIND uid_1_2_840_10008_5_1_4_38_3 = 227, // Hanging Protocol Information Model - MOVE uid_1_2_840_10008_5_1_4_41 = 228, // Product Characteristics Query SOP Class uid_1_2_840_10008_5_1_4_42 = 229, // Substance Approval Query SOP Class uid_1_2_840_10008_15_0_3_1 = 230, // dicomDeviceName uid_1_2_840_10008_15_0_3_2 = 231, // dicomDescription uid_1_2_840_10008_15_0_3_3 = 232, // dicomManufacturer uid_1_2_840_10008_15_0_3_4 = 233, // dicomManufacturerModelName uid_1_2_840_10008_15_0_3_5 = 234, // dicomSoftwareVersion uid_1_2_840_10008_15_0_3_6 = 235, // dicomVendorData uid_1_2_840_10008_15_0_3_7 = 236, // dicomAETitle uid_1_2_840_10008_15_0_3_8 = 237, // dicomNetworkConnectionReference uid_1_2_840_10008_15_0_3_9 = 238, // dicomApplicationCluster uid_1_2_840_10008_15_0_3_10 = 239, // dicomAssociationInitiator uid_1_2_840_10008_15_0_3_11 = 240, // dicomAssociationAcceptor uid_1_2_840_10008_15_0_3_12 = 241, // dicomHostname uid_1_2_840_10008_15_0_3_13 = 242, // dicomPort uid_1_2_840_10008_15_0_3_14 = 243, // dicomSOPClass uid_1_2_840_10008_15_0_3_15 = 244, // dicomTransferRole uid_1_2_840_10008_15_0_3_16 = 245, // dicomTransferSyntax uid_1_2_840_10008_15_0_3_17 = 246, // dicomPrimaryDeviceType uid_1_2_840_10008_15_0_3_18 = 247, // dicomRelatedDeviceReference uid_1_2_840_10008_15_0_3_19 = 248, // dicomPreferredCalledAETitle uid_1_2_840_10008_15_0_3_20 = 249, // dicomTLSCyphersuite uid_1_2_840_10008_15_0_3_21 = 250, // dicomAuthorizedNodeCertificateReference uid_1_2_840_10008_15_0_3_22 = 251, // dicomThisNodeCertificateReference uid_1_2_840_10008_15_0_3_23 = 252, // dicomInstalled uid_1_2_840_10008_15_0_3_24 = 253, // dicomStationName uid_1_2_840_10008_15_0_3_25 = 254, // dicomDeviceSerialNumber uid_1_2_840_10008_15_0_3_26 = 255, // dicomInstitutionName uid_1_2_840_10008_15_0_3_27 = 256, // dicomInstitutionAddress uid_1_2_840_10008_15_0_3_28 = 257, // dicomInstitutionDepartmentName uid_1_2_840_10008_15_0_3_29 = 258, // dicomIssuerOfPatientID uid_1_2_840_10008_15_0_3_30 = 259, // dicomPreferredCallingAETitle uid_1_2_840_10008_15_0_3_31 = 260, // dicomSupportedCharacterSet uid_1_2_840_10008_15_0_4_1 = 261, // dicomConfigurationRoot uid_1_2_840_10008_15_0_4_2 = 262, // dicomDevicesRoot uid_1_2_840_10008_15_0_4_3 = 263, // dicomUniqueAETitlesRegistryRoot uid_1_2_840_10008_15_0_4_4 = 264, // dicomDevice uid_1_2_840_10008_15_0_4_5 = 265, // dicomNetworkAE uid_1_2_840_10008_15_0_4_6 = 266, // dicomNetworkConnection uid_1_2_840_10008_15_0_4_7 = 267, // dicomUniqueAETitle uid_1_2_840_10008_15_0_4_8 = 268, // dicomTransferCapability // uid_1_2_840_10008_5_1_4_1_1_77_1_6 = 269, // VL Whole Slide Microscopy uid_1_2_840_10008_5_1_4_1_1_6_2 = 270, // Enhanced US Volume Storage uid_1_2_840_10008_5_1_4_1_1_66_5 = 271, // Surface Segmentation Storage uid_1_2_840_10008_5_1_4_1_1_13_1_3 = 272, // Breast Tomosynthesis Image Storage uid_1_2_840_10008_5_1_4_1_1_2_2 = 273, // Legacy Converted Enhanced CT uid_1_2_840_10008_5_1_4_1_1_4_4 = 274, // Legacy Converted Enhanced MR uid_1_2_840_10008_5_1_4_1_1_128_1 = 275, // Legacy Converted Enhanced PET uid_1_2_840_10008_1_2_4_101 = 276, // MPEG2 Main Profile High Level uid_1_2_840_10008_1_2_4_102 = 277, // MPEG-4 AVC/H.264 High Profile Lev. 4.1 uid_1_2_840_10008_1_2_4_103 = 278, // MPEG-4 AVC/H.264 BD-comp High Profile Lev. 4.1 ///////////////////////////////////////// // // 2019b // uid_1_2_840_10008_1_5_2 = 279, uid_1_2_840_10008_1_5_3 = 280, uid_1_2_840_10008_1_5_4 = 281, uid_1_2_840_10008_1_5_5 = 282, uid_1_2_840_10008_1_5_6 = 283, uid_1_2_840_10008_1_5_7 = 284, uid_1_2_840_10008_1_5_8 = 285, uid_1_2_840_10008_1_20 = 286, uid_1_2_840_10008_2_16_5 = 287, uid_1_2_840_10008_2_16_6 = 288, uid_1_2_840_10008_2_16_7 = 289, uid_1_2_840_10008_2_16_8 = 290, uid_1_2_840_10008_2_16_9 = 291, uid_1_2_840_10008_2_16_10 = 292, uid_1_2_840_10008_2_16_11 = 293, uid_1_2_840_10008_2_16_12 = 294, uid_1_2_840_10008_2_16_13 = 295, uid_1_2_840_10008_2_16_14 = 296, uid_1_2_840_10008_5_1_1_40 = 297, uid_1_2_840_10008_5_1_1_40_1 = 298, uid_1_2_840_10008_5_1_4_1_1_9_4_2 = 299, uid_1_2_840_10008_5_1_4_1_1_9_5_1 = 300, uid_1_2_840_10008_5_1_4_1_1_9_6_1 = 301, uid_1_2_840_10008_5_1_4_1_1_11_5 = 302, uid_1_2_840_10008_5_1_4_1_1_11_6 = 303, uid_1_2_840_10008_1_2_4_104 = 304, uid_1_2_840_10008_1_2_4_105 = 305, uid_1_2_840_10008_1_2_4_106 = 306, uid_1_2_840_10008_1_2_4_107 = 307, uid_1_2_840_10008_1_2_4_108 = 308, uid_1_2_840_10008_1_5_1 = 309, uid_1_2_840_10008_5_1_4_1_1_11_7 = 310, uid_1_2_840_10008_5_1_4_1_1_11_8 = 311, uid_1_2_840_10008_5_1_4_1_1_11_9 = 312, uid_1_2_840_10008_5_1_4_1_1_11_10 = 313, uid_1_2_840_10008_5_1_4_1_1_11_11 = 314, uid_1_2_840_10008_5_1_4_1_1_12_77 = 315, uid_1_2_840_10008_5_1_4_1_1_13_1_4 = 316, uid_1_2_840_10008_5_1_4_1_1_13_1_5 = 317, uid_1_2_840_10008_5_1_4_1_1_14_1 = 318, uid_1_2_840_10008_5_1_4_1_1_14_2 = 319, uid_1_2_840_10008_5_1_4_1_1_30 = 320, uid_1_2_840_10008_5_1_4_1_1_40 = 321, uid_1_2_840_10008_5_1_4_1_1_66_6 = 322, uid_1_2_840_10008_5_1_4_1_1_68_1 = 323, uid_1_2_840_10008_5_1_4_1_1_68_2 = 324, uid_1_2_840_10008_5_1_4_1_1_77_1_5_5 = 325, uid_1_2_840_10008_5_1_4_1_1_77_1_5_6 = 326, uid_1_2_840_10008_5_1_4_1_1_77_1_5_7 = 327, uid_1_2_840_10008_5_1_4_1_1_77_1_5_8 = 328, uid_1_2_840_10008_5_1_4_1_1_78_1 = 329, uid_1_2_840_10008_5_1_4_1_1_78_2 = 330, uid_1_2_840_10008_5_1_4_1_1_78_3 = 331, uid_1_2_840_10008_5_1_4_1_1_78_4 = 332, uid_1_2_840_10008_5_1_4_1_1_78_5 = 333, uid_1_2_840_10008_5_1_4_1_1_78_6 = 334, uid_1_2_840_10008_5_1_4_1_1_78_7 = 335, uid_1_2_840_10008_5_1_4_1_1_78_8 = 336, uid_1_2_840_10008_5_1_4_1_1_79_1 = 337, uid_1_2_840_10008_5_1_4_1_1_80_1 = 338, uid_1_2_840_10008_5_1_4_1_1_81_1 = 339, uid_1_2_840_10008_5_1_4_1_1_82_1 = 340, uid_1_2_840_10008_5_1_4_1_1_88_34 = 341, uid_1_2_840_10008_5_1_4_1_1_88_35 = 342, uid_1_2_840_10008_5_1_4_1_1_88_68 = 343, uid_1_2_840_10008_5_1_4_1_1_88_69 = 344, uid_1_2_840_10008_5_1_4_1_1_88_70 = 345, uid_1_2_840_10008_5_1_4_1_1_88_71 = 346, uid_1_2_840_10008_5_1_4_1_1_88_72 = 347, uid_1_2_840_10008_5_1_4_1_1_88_73 = 348, uid_1_2_840_10008_5_1_4_1_1_88_74 = 349, uid_1_2_840_10008_5_1_4_1_1_88_75 = 350, uid_1_2_840_10008_5_1_4_1_1_90_1 = 351, uid_1_2_840_10008_5_1_4_1_1_104_3 = 352, uid_1_2_840_10008_5_1_4_1_1_130 = 353, uid_1_2_840_10008_5_1_4_1_1_131 = 354, uid_1_2_840_10008_5_1_4_1_1_200_1 = 355, uid_1_2_840_10008_5_1_4_1_1_200_2 = 356, uid_1_2_840_10008_5_1_4_1_1_200_3 = 357, uid_1_2_840_10008_5_1_4_1_1_200_4 = 358, uid_1_2_840_10008_5_1_4_1_1_200_5 = 359, uid_1_2_840_10008_5_1_4_1_1_200_6 = 360, uid_1_2_840_10008_5_1_4_1_1_481_10 = 361, uid_1_2_840_10008_5_1_4_1_1_481_11 = 362, uid_1_2_840_10008_5_1_4_1_1_501_1 = 363, uid_1_2_840_10008_5_1_4_1_1_501_2_1 = 364, uid_1_2_840_10008_5_1_4_1_1_501_2_2 = 365, uid_1_2_840_10008_5_1_4_1_1_501_3 = 366, uid_1_2_840_10008_5_1_4_1_1_501_4 = 367, uid_1_2_840_10008_5_1_4_1_1_501_5 = 368, uid_1_2_840_10008_5_1_4_1_1_501_6 = 369, uid_1_2_840_10008_5_1_4_1_1_601_1 = 370, uid_1_2_840_10008_5_1_4_1_1_601_2 = 371, uid_1_2_840_10008_5_1_4_1_2_4_2 = 372, uid_1_2_840_10008_5_1_4_1_2_4_3 = 373, uid_1_2_840_10008_5_1_4_1_2_5_3 = 374, uid_1_2_840_10008_5_1_4_20_1 = 375, uid_1_2_840_10008_5_1_4_20_2 = 376, uid_1_2_840_10008_5_1_4_20_3 = 377, uid_1_2_840_10008_5_1_4_34_5_1 = 378, uid_1_2_840_10008_5_1_4_34_6 = 379, uid_1_2_840_10008_5_1_4_34_6_1 = 380, uid_1_2_840_10008_5_1_4_34_6_2 = 381, uid_1_2_840_10008_5_1_4_34_6_3 = 382, uid_1_2_840_10008_5_1_4_34_6_4 = 383, uid_1_2_840_10008_5_1_4_34_7 = 384, uid_1_2_840_10008_5_1_4_34_8 = 385, uid_1_2_840_10008_5_1_4_34_9 = 386, uid_1_2_840_10008_5_1_4_34_10 = 387, uid_1_2_840_10008_5_1_4_38_4 = 388, uid_1_2_840_10008_5_1_4_39_1 = 389, uid_1_2_840_10008_5_1_4_39_2 = 390, uid_1_2_840_10008_5_1_4_39_3 = 391, uid_1_2_840_10008_5_1_4_39_4 = 392, uid_1_2_840_10008_5_1_4_43_1 = 393, uid_1_2_840_10008_5_1_4_43_2 = 394, uid_1_2_840_10008_5_1_4_43_3 = 395, uid_1_2_840_10008_5_1_4_43_4 = 396, uid_1_2_840_10008_5_1_4_44_1 = 397, uid_1_2_840_10008_5_1_4_44_2 = 398, uid_1_2_840_10008_5_1_4_44_3 = 399, uid_1_2_840_10008_5_1_4_44_4 = 400, uid_1_2_840_10008_5_1_4_45_1 = 401, uid_1_2_840_10008_5_1_4_45_2 = 402, uid_1_2_840_10008_5_1_4_45_3 = 403, uid_1_2_840_10008_5_1_4_45_4 = 404, uid_1_2_840_10008_7_1_1 = 405, uid_1_2_840_10008_7_1_2 = 406, uid_1_2_840_10008_8_1_1 = 407, uid_1_2_840_10008_5_1_4_1_1_4_3 = 408, uid_1_2_840_10008_15_1_1 = 409 // // ///////////////////////////////////////// ///////////////////////////////////////// // // Optionally private UIDs // #if 0 uid_1_2_840_113619_4_2, uid_1_2_840_113619_4_3, uid_1_3_12_2_1107_5_9_1, uid_1_2_840_113619_4_26, uid_1_2_840_113619_4_30, uid_2_16_840_1_113709_1_5_1, uid_2_16_840_1_113709_1_2_2, uid_1_2_840_113543_6_6_1_3_10002, uid_1_2_392_200036_9116_7_8_1_1_1, uid_1_2_392_200036_9125_1_1_2, uid_1_2_840_113619_4_27, uid_1_3_46_670589_11_0_0_12_1, uid_1_3_46_670589_11_0_0_12_2, uid_1_3_46_670589_11_0_0_12_4, uid_1_3_46_670589_2_3_1_1, uid_1_3_46_670589_2_4_1_1, uid_1_3_46_670589_2_5_1_1, uid_1_3_46_670589_5_0_1, uid_1_3_46_670589_5_0_1_1, uid_1_3_46_670589_5_0_10, uid_1_3_46_670589_5_0_11, uid_1_3_46_670589_5_0_11_1, uid_1_3_46_670589_5_0_12, uid_1_3_46_670589_5_0_13, uid_1_3_46_670589_5_0_14, uid_1_3_46_670589_5_0_2, uid_1_3_46_670589_5_0_2_1, uid_1_3_46_670589_5_0_3, uid_1_3_46_670589_5_0_3_1, uid_1_3_46_670589_5_0_4, uid_1_3_46_670589_5_0_7, uid_1_3_46_670589_5_0_8, uid_1_3_46_670589_5_0_9, uid_1_2_752_24_3_7_6, uid_1_2_752_24_3_7_7, uid_1_2_840_113619_5_2, uid_1_3_46_670589_33_1_4_1 #endif // // ///////////////////////////////////////// } TSType; typedef enum { VerificationSOPClass = 1, // Verification SOP Class ImplicitVRLittleEndianDefaultTransferSyntaxforDICOM = 2, // Implicit VR Little Endian: Default Transfer Syntax for DICOM ExplicitVRLittleEndian = 3, // Explicit VR Little Endian DeflatedExplicitVRLittleEndian = 4, // Deflated Explicit VR Little Endian ExplicitVRBigEndian = 5, // Explicit VR Big Endian JPEGBaselineProcess1DefaultTransferSyntaxforLossyJPEG8BitImageCompression = 6, // JPEG Baseline (Process 1): Default Transfer Syntax for Lossy JPEG 8 Bit Image Compression JPEGExtendedProcess24DefaultTransferSyntaxforLossyJPEG12BitImageCompressionProcess4only = 7, // JPEG Extended (Process 2 & 4): Default Transfer Syntax for Lossy JPEG 12 Bit Image Compression (Process 4 only) JPEGExtendedProcess35Retired = 8, // JPEG Extended (Process 3 & 5) JPEGSpectralSelectionNonHierarchicalProcess68Retired = 9, // JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8) JPEGSpectralSelectionNonHierarchicalProcess79Retired = 10, // JPEG Spectral Selection, Non-Hierarchical (Process 7 & 9) JPEGFullProgressionNonHierarchicalProcess1012Retired = 11, // JPEG Full Progression, Non-Hierarchical (Process 10 & 12) JPEGFullProgressionNonHierarchicalProcess1113Retired = 12, // JPEG Full Progression, Non-Hierarchical (Process 11 & 13) JPEGLosslessNonHierarchicalProcess14 = 13, // JPEG Lossless, Non-Hierarchical (Process 14) JPEGLosslessNonHierarchicalProcess15Retired = 14, // JPEG Lossless, Non-Hierarchical (Process 15) JPEGExtendedHierarchicalProcess1618Retired = 15, // JPEG Extended, Hierarchical (Process 16 & 18) JPEGExtendedHierarchicalProcess1719Retired = 16, // JPEG Extended, Hierarchical (Process 17 & 19) JPEGSpectralSelectionHierarchicalProcess2022Retired = 17, // JPEG Spectral Selection, Hierarchical (Process 20 & 22) JPEGSpectralSelectionHierarchicalProcess2123Retired = 18, // JPEG Spectral Selection, Hierarchical (Process 21 & 23) JPEGFullProgressionHierarchicalProcess2426Retired = 19, // JPEG Full Progression, Hierarchical (Process 24 & 26) JPEGFullProgressionHierarchicalProcess2527Retired = 20, // JPEG Full Progression, Hierarchical (Process 25 & 27) JPEGLosslessHierarchicalProcess28Retired = 21, // JPEG Lossless, Hierarchical (Process 28) JPEGLosslessHierarchicalProcess29Retired = 22, // JPEG Lossless, Hierarchical (Process 29) JPEGLosslessNonHierarchicalFirstOrderPredictionProcess14SelectionValue1DefaultTransferSyntaxforLosslessJPEGImageCompression = 23, // JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1]): Default Transfer Syntax for Lossless JPEG Image Compression JPEGLSLosslessImageCompression = 24, // JPEG-LS Lossless Image Compression JPEGLSLossyNearLosslessImageCompression = 25, // JPEG-LS Lossy (Near-Lossless) Image Compression JPEG2000ImageCompressionLosslessOnly = 26, // JPEG 2000 Image Compression (Lossless Only) JPEG2000ImageCompression = 27, // JPEG 2000 Image Compression JPEG2000Part2MulticomponentImageCompressionLosslessOnly = 28, // JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only) JPEG2000Part2MulticomponentImageCompression = 29, // JPEG 2000 Part 2 Multi-component Image Compression JPIPReferenced = 30, // JPIP Referenced JPIPReferencedDeflate = 31, // JPIP Referenced Deflate MPEG2MainProfileMainLevel = 32, // MPEG2 Main Profile @ Main Level RLELossless = 33, // RLE Lossless RFC2557MIMEencapsulation = 34, // RFC 2557 MIME encapsulation XMLEncoding = 35, // XML Encoding MediaStorageDirectoryStorage = 36, // Media Storage Directory Storage TalairachBrainAtlasFrameofReference = 37, // Talairach Brain Atlas Frame of Reference SPM2T1FrameofReference = 38, // SPM2 T1 Frame of Reference SPM2T2FrameofReference = 39, // SPM2 T2 Frame of Reference SPM2PDFrameofReference = 40, // SPM2 PD Frame of Reference SPM2EPIFrameofReference = 41, // SPM2 EPI Frame of Reference SPM2FILT1FrameofReference = 42, // SPM2 FIL T1 Frame of Reference SPM2PETFrameofReference = 43, // SPM2 PET Frame of Reference SPM2TRANSMFrameofReference = 44, // SPM2 TRANSM Frame of Reference SPM2SPECTFrameofReference = 45, // SPM2 SPECT Frame of Reference SPM2GRAYFrameofReference = 46, // SPM2 GRAY Frame of Reference SPM2WHITEFrameofReference = 47, // SPM2 WHITE Frame of Reference SPM2CSFFrameofReference = 48, // SPM2 CSF Frame of Reference SPM2BRAINMASKFrameofReference = 49, // SPM2 BRAINMASK Frame of Reference SPM2AVG305T1FrameofReference = 50, // SPM2 AVG305T1 Frame of Reference SPM2AVG152T1FrameofReference = 51, // SPM2 AVG152T1 Frame of Reference SPM2AVG152T2FrameofReference = 52, // SPM2 AVG152T2 Frame of Reference SPM2AVG152PDFrameofReference = 53, // SPM2 AVG152PD Frame of Reference SPM2SINGLESUBJT1FrameofReference = 54, // SPM2 SINGLESUBJT1 Frame of Reference ICBM452T1FrameofReference = 55, // ICBM 452 T1 Frame of Reference ICBMSingleSubjectMRIFrameofReference = 56, // ICBM Single Subject MRI Frame of Reference BasicStudyContentNotificationSOPClassRetired = 57, // Basic Study Content Notification SOP Class StorageCommitmentPushModelSOPClass = 58, // Storage Commitment Push Model SOP Class StorageCommitmentPushModelSOPInstance = 59, // Storage Commitment Push Model SOP Instance StorageCommitmentPullModelSOPClassRetired = 60, // Storage Commitment Pull Model SOP Class StorageCommitmentPullModelSOPInstanceRetired = 61, // Storage Commitment Pull Model SOP Instance ProceduralEventLoggingSOPClass = 62, // Procedural Event Logging SOP Class ProceduralEventLoggingSOPInstance = 63, // Procedural Event Logging SOP Instance SubstanceAdministrationLoggingSOPClass = 64, // Substance Administration Logging SOP Class SubstanceAdministrationLoggingSOPInstance = 65, // Substance Administration Logging SOP Instance DICOMUIDRegistry = 66, // DICOM UID Registry DICOMControlledTerminology = 67, // DICOM Controlled Terminology DICOMApplicationContextName = 68, // DICOM Application Context Name DetachedPatientManagementSOPClassRetired = 69, // Detached Patient Management SOP Class DetachedPatientManagementMetaSOPClassRetired = 70, // Detached Patient Management Meta SOP Class DetachedVisitManagementSOPClassRetired = 71, // Detached Visit Management SOP Class DetachedStudyManagementSOPClassRetired = 72, // Detached Study Management SOP Class StudyComponentManagementSOPClassRetired = 73, // Study Component Management SOP Class ModalityPerformedProcedureStepSOPClass = 74, // Modality Performed Procedure Step SOP Class ModalityPerformedProcedureStepRetrieveSOPClass = 75, // Modality Performed Procedure Step Retrieve SOP Class ModalityPerformedProcedureStepNotificationSOPClass = 76, // Modality Performed Procedure Step Notification SOP Class DetachedResultsManagementSOPClassRetired = 77, // Detached Results Management SOP Class DetachedResultsManagementMetaSOPClassRetired = 78, // Detached Results Management Meta SOP Class DetachedStudyManagementMetaSOPClassRetired = 79, // Detached Study Management Meta SOP Class DetachedInterpretationManagementSOPClassRetired = 80, // Detached Interpretation Management SOP Class StorageServiceClass = 81, // Storage Service Class BasicFilmSessionSOPClass = 82, // Basic Film Session SOP Class BasicFilmBoxSOPClass = 83, // Basic Film Box SOP Class BasicGrayscaleImageBoxSOPClass = 84, // Basic Grayscale Image Box SOP Class BasicColorImageBoxSOPClass = 85, // Basic Color Image Box SOP Class ReferencedImageBoxSOPClassRetired = 86, // Referenced Image Box SOP Class BasicGrayscalePrintManagementMetaSOPClass = 87, // Basic Grayscale Print Management Meta SOP Class ReferencedGrayscalePrintManagementMetaSOPClassRetired = 88, // Referenced Grayscale Print Management Meta SOP Class PrintJobSOPClass = 89, // Print Job SOP Class BasicAnnotationBoxSOPClass = 90, // Basic Annotation Box SOP Class PrinterSOPClass = 91, // Printer SOP Class PrinterConfigurationRetrievalSOPClass = 92, // Printer Configuration Retrieval SOP Class PrinterSOPInstance = 93, // Printer SOP Instance PrinterConfigurationRetrievalSOPInstance = 94, // Printer Configuration Retrieval SOP Instance BasicColorPrintManagementMetaSOPClass = 95, // Basic Color Print Management Meta SOP Class ReferencedColorPrintManagementMetaSOPClassRetired = 96, // Referenced Color Print Management Meta SOP Class VOILUTBoxSOPClass = 97, // VOI LUT Box SOP Class PresentationLUTSOPClass = 98, // Presentation LUT SOP Class ImageOverlayBoxSOPClassRetired = 99, // Image Overlay Box SOP Class BasicPrintImageOverlayBoxSOPClassRetired = 100, // Basic Print Image Overlay Box SOP Class PrintQueueSOPInstanceRetired = 101, // Print Queue SOP Instance PrintQueueManagementSOPClassRetired = 102, // Print Queue Management SOP Class StoredPrintStorageSOPClassRetired = 103, // Stored Print Storage SOP Class HardcopyGrayscaleImageStorageSOPClassRetired = 104, // Hardcopy Grayscale Image Storage SOP Class HardcopyColorImageStorageSOPClassRetired = 105, // Hardcopy Color Image Storage SOP Class PullPrintRequestSOPClassRetired = 106, // Pull Print Request SOP Class PullStoredPrintManagementMetaSOPClassRetired = 107, // Pull Stored Print Management Meta SOP Class MediaCreationManagementSOPClassUID = 108, // Media Creation Management SOP Class UID ComputedRadiographyImageStorage = 109, // Computed Radiography Image Storage DigitalXRayImageStorageForPresentation = 110, // Digital X-Ray Image Storage - For Presentation DigitalXRayImageStorageForProcessing = 111, // Digital X-Ray Image Storage - For Processing DigitalMammographyXRayImageStorageForPresentation = 112, // Digital Mammography X-Ray Image Storage - For Presentation DigitalMammographyXRayImageStorageForProcessing = 113, // Digital Mammography X-Ray Image Storage - For Processing DigitalIntraoralXRayImageStorageForPresentation = 114, // Digital Intra-oral X-Ray Image Storage - For Presentation DigitalIntraoralXRayImageStorageForProcessing = 115, // Digital Intra-oral X-Ray Image Storage - For Processing CTImageStorage = 116, // CT Image Storage EnhancedCTImageStorage = 117, // Enhanced CT Image Storage UltrasoundMultiframeImageStorageRetired = 118, // Ultrasound Multi-frame Image Storage UltrasoundMultiframeImageStorage = 119, // Ultrasound Multi-frame Image Storage MRImageStorage = 120, // MR Image Storage EnhancedMRImageStorage = 121, // Enhanced MR Image Storage MRSpectroscopyStorage = 122, // MR Spectroscopy Storage NuclearMedicineImageStorageRetired = 123, // Nuclear Medicine Image Storage UltrasoundImageStorageRetired = 124, // Ultrasound Image Storage UltrasoundImageStorage = 125, // Ultrasound Image Storage SecondaryCaptureImageStorage = 126, // Secondary Capture Image Storage MultiframeSingleBitSecondaryCaptureImageStorage = 127, // Multi-frame Single Bit Secondary Capture Image Storage MultiframeGrayscaleByteSecondaryCaptureImageStorage = 128, // Multi-frame Grayscale Byte Secondary Capture Image Storage MultiframeGrayscaleWordSecondaryCaptureImageStorage = 129, // Multi-frame Grayscale Word Secondary Capture Image Storage MultiframeTrueColorSecondaryCaptureImageStorage = 130, // Multi-frame True Color Secondary Capture Image Storage StandaloneOverlayStorageRetired = 131, // Standalone Overlay Storage StandaloneCurveStorageRetired = 132, // Standalone Curve Storage WaveformStorageTrialRetired = 133, // Waveform Storage - Trial ECG12leadWaveformStorage = 134, // 12-lead ECG Waveform Storage GeneralECGWaveformStorage = 135, // General ECG Waveform Storage AmbulatoryECGWaveformStorage = 136, // Ambulatory ECG Waveform Storage HemodynamicWaveformStorage = 137, // Hemodynamic Waveform Storage CardiacElectrophysiologyWaveformStorage = 138, // Cardiac Electrophysiology Waveform Storage BasicVoiceAudioWaveformStorage = 139, // Basic Voice Audio Waveform Storage StandaloneModalityLUTStorageRetired = 140, // Standalone Modality LUT Storage StandaloneVOILUTStorageRetired = 141, // Standalone VOI LUT Storage GrayscaleSoftcopyPresentationStateStorageSOPClass = 142, // Grayscale Softcopy Presentation State Storage SOP Class ColorSoftcopyPresentationStateStorageSOPClass = 143, // Color Softcopy Presentation State Storage SOP Class PseudoColorSoftcopyPresentationStateStorageSOPClass = 144, // Pseudo-Color Softcopy Presentation State Storage SOP Class BlendingSoftcopyPresentationStateStorageSOPClass = 145, // Blending Softcopy Presentation State Storage SOP Class XRayAngiographicImageStorage = 146, // X-Ray Angiographic Image Storage EnhancedXAImageStorage = 147, // Enhanced XA Image Storage XRayRadiofluoroscopicImageStorage = 148, // X-Ray Radiofluoroscopic Image Storage EnhancedXRFImageStorage = 149, // Enhanced XRF Image Storage XRay3DAngiographicImageStorage = 150, // X-Ray 3D Angiographic Image Storage XRay3DCraniofacialImageStorage = 151, // X-Ray 3D Craniofacial Image Storage XRayAngiographicBiPlaneImageStorageRetired = 152, // X-Ray Angiographic Bi-Plane Image Storage NuclearMedicineImageStorage = 153, // Nuclear Medicine Image Storage RawDataStorage = 154, // Raw Data Storage SpatialRegistrationStorage = 155, // Spatial Registration Storage SpatialFiducialsStorage = 156, // Spatial Fiducials Storage DeformableSpatialRegistrationStorage = 157, // Deformable Spatial Registration Storage SegmentationStorage = 158, // Segmentation Storage RealWorldValueMappingStorage = 159, // Real World Value Mapping Storage VLImageStorageTrialRetired = 160, // VL Image Storage - Trial VLMultiframeImageStorageTrialRetired = 161, // VL Multi-frame Image Storage - Trial VLEndoscopicImageStorage = 162, // VL Endoscopic Image Storage VideoEndoscopicImageStorage = 163, // Video Endoscopic Image Storage VLMicroscopicImageStorage = 164, // VL Microscopic Image Storage VideoMicroscopicImageStorage = 165, // Video Microscopic Image Storage VLSlideCoordinatesMicroscopicImageStorage = 166, // VL Slide-Coordinates Microscopic Image Storage VLPhotographicImageStorage = 167, // VL Photographic Image Storage VideoPhotographicImageStorage = 168, // Video Photographic Image Storage OphthalmicPhotography8BitImageStorage = 169, // Ophthalmic Photography 8 Bit Image Storage OphthalmicPhotography16BitImageStorage = 170, // Ophthalmic Photography 16 Bit Image Storage StereometricRelationshipStorage = 171, // Stereometric Relationship Storage OphthalmicTomographyImageStorage = 172, // Ophthalmic Tomography Image Storage TextSRStorageTrialRetired = 173, // Text SR Storage - Trial AudioSRStorageTrialRetired = 174, // Audio SR Storage - Trial DetailSRStorageTrialRetired = 175, // Detail SR Storage - Trial ComprehensiveSRStorageTrialRetired = 176, // Comprehensive SR Storage - Trial BasicTextSRStorage = 177, // Basic Text SR Storage EnhancedSRStorage = 178, // Enhanced SR Storage ComprehensiveSRStorage = 179, // Comprehensive SR Storage ProcedureLogStorage = 180, // Procedure Log Storage MammographyCADSRStorage = 181, // Mammography CAD SR Storage KeyObjectSelectionDocumentStorage = 182, // Key Object Selection Document Storage ChestCADSRStorage = 183, // Chest CAD SR Storage XRayRadiationDoseSRStorage = 184, // X-Ray Radiation Dose SR Storage EncapsulatedPDFStorage = 185, // Encapsulated PDF Storage EncapsulatedCDAStorage = 186, // Encapsulated CDA Storage PositronEmissionTomographyImageStorage = 187, // Positron Emission Tomography Image Storage StandalonePETCurveStorageRetired = 188, // Standalone PET Curve Storage RTImageStorage = 189, // RT Image Storage RTDoseStorage = 190, // RT Dose Storage RTStructureSetStorage = 191, // RT Structure Set Storage RTBeamsTreatmentRecordStorage = 192, // RT Beams Treatment Record Storage RTPlanStorage = 193, // RT Plan Storage RTBrachyTreatmentRecordStorage = 194, // RT Brachy Treatment Record Storage RTTreatmentSummaryRecordStorage = 195, // RT Treatment Summary Record Storage RTIonPlanStorage = 196, // RT Ion Plan Storage RTIonBeamsTreatmentRecordStorage = 197, // RT Ion Beams Treatment Record Storage PatientRootQueryRetrieveInformationModelFIND = 198, // Patient Root Query/Retrieve Information Model - FIND PatientRootQueryRetrieveInformationModelMOVE = 199, // Patient Root Query/Retrieve Information Model - MOVE PatientRootQueryRetrieveInformationModelGET = 200, // Patient Root Query/Retrieve Information Model - GET StudyRootQueryRetrieveInformationModelFIND = 201, // Study Root Query/Retrieve Information Model - FIND StudyRootQueryRetrieveInformationModelMOVE = 202, // Study Root Query/Retrieve Information Model - MOVE StudyRootQueryRetrieveInformationModelGET = 203, // Study Root Query/Retrieve Information Model - GET PatientStudyOnlyQueryRetrieveInformationModelFINDRetired = 204, // Patient/Study Only Query/Retrieve Information Model - FIND PatientStudyOnlyQueryRetrieveInformationModelMOVERetired = 205, // Patient/Study Only Query/Retrieve Information Model - MOVE PatientStudyOnlyQueryRetrieveInformationModelGETRetired = 206, // Patient/Study Only Query/Retrieve Information Model - GET ModalityWorklistInformationModelFIND = 207, // Modality Worklist Information Model - FIND GeneralPurposeWorklistInformationModelFIND = 208, // General Purpose Worklist Information Model - FIND GeneralPurposeScheduledProcedureStepSOPClass = 209, // General Purpose Scheduled Procedure Step SOP Class GeneralPurposePerformedProcedureStepSOPClass = 210, // General Purpose Performed Procedure Step SOP Class GeneralPurposeWorklistManagementMetaSOPClass = 211, // General Purpose Worklist Management Meta SOP Class InstanceAvailabilityNotificationSOPClass = 212, // Instance Availability Notification SOP Class RTBeamsDeliveryInstructionStorageSupplement74FrozenDraft = 213, // RT Beams Delivery Instruction Storage (Supplement 74 Frozen Draft) RTConventionalMachineVerificationSupplement74FrozenDraft = 214, // RT Conventional Machine Verification (Supplement 74 Frozen Draft) RTIonMachineVerificationSupplement74FrozenDraft = 215, // RT Ion Machine Verification (Supplement 74 Frozen Draft) UnifiedWorklistandProcedureStepServiceClass = 216, // Unified Worklist and Procedure Step Service Class UnifiedProcedureStepPushSOPClass = 217, // Unified Procedure Step - Push SOP Class UnifiedProcedureStepWatchSOPClass = 218, // Unified Procedure Step - Watch SOP Class UnifiedProcedureStepPullSOPClass = 219, // Unified Procedure Step - Pull SOP Class UnifiedProcedureStepEventSOPClass = 220, // Unified Procedure Step - Event SOP Class UnifiedWorklistandProcedureStepSOPInstance = 221, // Unified Worklist and Procedure Step SOP Instance GeneralRelevantPatientInformationQuery = 222, // General Relevant Patient Information Query BreastImagingRelevantPatientInformationQuery = 223, // Breast Imaging Relevant Patient Information Query CardiacRelevantPatientInformationQuery = 224, // Cardiac Relevant Patient Information Query HangingProtocolStorage = 225, // Hanging Protocol Storage HangingProtocolInformationModelFIND = 226, // Hanging Protocol Information Model - FIND HangingProtocolInformationModelMOVE = 227, // Hanging Protocol Information Model - MOVE ProductCharacteristicsQuerySOPClass = 228, // Product Characteristics Query SOP Class SubstanceApprovalQuerySOPClass = 229, // Substance Approval Query SOP Class dicomDeviceName = 230, // dicomDeviceName dicomDescription = 231, // dicomDescription dicomManufacturer = 232, // dicomManufacturer dicomManufacturerModelName = 233, // dicomManufacturerModelName dicomSoftwareVersion = 234, // dicomSoftwareVersion dicomVendorData = 235, // dicomVendorData dicomAETitle = 236, // dicomAETitle dicomNetworkConnectionReference = 237, // dicomNetworkConnectionReference dicomApplicationCluster = 238, // dicomApplicationCluster dicomAssociationInitiator = 239, // dicomAssociationInitiator dicomAssociationAcceptor = 240, // dicomAssociationAcceptor dicomHostname = 241, // dicomHostname dicomPort = 242, // dicomPort dicomSOPClass = 243, // dicomSOPClass dicomTransferRole = 244, // dicomTransferRole dicomTransferSyntax = 245, // dicomTransferSyntax dicomPrimaryDeviceType = 246, // dicomPrimaryDeviceType dicomRelatedDeviceReference = 247, // dicomRelatedDeviceReference dicomPreferredCalledAETitle = 248, // dicomPreferredCalledAETitle dicomTLSCyphersuite = 249, // dicomTLSCyphersuite dicomAuthorizedNodeCertificateReference = 250, // dicomAuthorizedNodeCertificateReference dicomThisNodeCertificateReference = 251, // dicomThisNodeCertificateReference dicomInstalled = 252, // dicomInstalled dicomStationName = 253, // dicomStationName dicomDeviceSerialNumber = 254, // dicomDeviceSerialNumber dicomInstitutionName = 255, // dicomInstitutionName dicomInstitutionAddress = 256, // dicomInstitutionAddress dicomInstitutionDepartmentName = 257, // dicomInstitutionDepartmentName dicomIssuerOfPatientID = 258, // dicomIssuerOfPatientID dicomPreferredCallingAETitle = 259, // dicomPreferredCallingAETitle dicomSupportedCharacterSet = 260, // dicomSupportedCharacterSet dicomConfigurationRoot = 261, // dicomConfigurationRoot dicomDevicesRoot = 262, // dicomDevicesRoot dicomUniqueAETitlesRegistryRoot = 263, // dicomUniqueAETitlesRegistryRoot dicomDevice = 264, // dicomDevice dicomNetworkAE = 265, // dicomNetworkAE dicomNetworkConnection = 266, // dicomNetworkConnection dicomUniqueAETitle = 267, // dicomUniqueAETitle dicomTransferCapability = 268, // dicomTransferCapability // VLWholeSlideMicroscopyImageStorage = 269, EnhancedUSVolumeStorage = 270, SurfaceSegmentationStorage = 271, BreastTomosynthesisImageStorage = 272, LegacyConvertedEnhancedCTImageStorage = 273, LegacyConvertedEnhancedMRImageStorage = 274, LegacyConvertedEnhancedPETImageStorage = 275, MPEG2MainProfileHighLevel = 276, MPEG4AVCH_264HighProfileLevel4_1 = 277, MPEG4AVCH_264BDcompatibleHighProfileLevel4_1 = 278, ////////////////////////////////////////////// // // 2019b // PETColorPaletteSOPInstance = 279, HotMetalBlueColorPaletteSOPInstance = 280, PET20StepColorPaletteSOPInstance = 281, SpringColorPaletteSOPInstance = 282, SummerColorPaletteSOPInstance = 283, FallColorPaletteSOPInstance = 284, WinterColorPaletteSOPInstance = 285, Papyrus3ImplicitVRLittleEndian = 286, AdultMouseAnatomyOntology = 287, UberonOntology = 288, IntegratedTaxonomicInformationSystemITISTaxonomicSerialNumberTSN = 289, MouseGenomeInitiativeMGI = 290, PubChemCompoundCID = 291, ICD11 = 292, NewYorkUniversityMelanomaClinicalCooperativeGroup = 293, MayoClinicNonradiologicalImagesSBSAnatomicalSurfaceRegionGuide = 294, ImageBiomarkerStandardisationInitiative = 295, RadiomicsOntology = 296, DisplaySystemSOPClass = 297, DisplaySystemSOPInstance = 298, GeneralAudioWaveformStorage = 299, ArterialPulseWaveformStorage = 300, RespiratoryWaveformStorage = 301, XAXRFGrayscaleSoftcopyPresentationStateStorage = 302, GrayscalePlanarMPRVolumetricPresentationStateStorage = 303, MPEG4AVCH_264HighProfileLevel4_2For2DVideo = 304, MPEG4AVCH_264HighProfileLevel4_2For3DVideo = 305, MPEG4AVCH_264StereoHighProfileLevel4_2 = 306, HEVCH_265MainProfileLevel5_1 = 307, HEVCH_265Main10ProfileLevel5_1 = 308, HotIronColorPaletteSOPInstance = 309, CompositingPlanarMPRVolumetricPresentationStateStorage = 310, AdvancedBlendingPresentationStateStorage = 311, VolumeRenderingVolumetricPresentationStateStorage = 312, SegmentedVolumeRenderingVolumetricPresentationStateStorage = 313, MultipleVolumeRenderingVolumetricPresentationStateStorage = 314, Null0 = 315, BreastProjectionXRayImageStorageForPresentation = 316, BreastProjectionXRayImageStorageForProcessing = 317, IntravascularOpticalCoherenceTomographyImageStorageForPresentation = 318, IntravascularOpticalCoherenceTomographyImageStorageForProcessing = 319, ParametricMapStorage = 320, Null1 = 321, TractographyResultsStorage = 322, SurfaceScanMeshStorage = 323, SurfaceScanPointCloudStorage = 324, WideFieldOphthalmicPhotographyStereographicProjectionImageStorage = 325, WideFieldOphthalmicPhotography3DCoordinatesImageStorage = 326, OphthalmicOpticalCoherenceTomographyEnFaceImageStorage = 327, OphthalmicOpticalCoherenceTomographyBscanVolumeAnalysisStorage = 328, LensometryMeasurementsStorage = 329, AutorefractionMeasurementsStorage = 330, KeratometryMeasurementsStorage = 331, SubjectiveRefractionMeasurementsStorage = 332, VisualAcuityMeasurementsStorage = 333, SpectaclePrescriptionReportStorage = 334, OphthalmicAxialMeasurementsStorage = 335, IntraocularLensCalculationsStorage = 336, MacularGridThicknessandVolumeReportStorage = 337, OphthalmicVisualFieldStaticPerimetryMeasurementsStorage = 338, OphthalmicThicknessMapStorage = 339, CornealTopographyMapStorage = 340, Comprehensive3DSRStorage = 341, ExtensibleSRStorage = 342, RadiopharmaceuticalRadiationDoseSRStorage = 343, ColonCADSRStorage = 344, ImplantationPlanSRStorage = 345, AcquisitionContextSRStorage = 346, SimplifiedAdultEchoSRStorage = 347, PatientRadiationDoseSRStorage = 348, PlannedImagingAgentAdministrationSRStorage = 349, PerformedImagingAgentAdministrationSRStorage = 350, ContentAssessmentResultsStorage = 351, EncapsulatedSTLStorage = 352, EnhancedPETImageStorage = 353, BasicStructuredDisplayStorage = 354, CTDefinedProcedureProtocolStorage = 355, CTPerformedProcedureProtocolStorage = 356, ProtocolApprovalStorage = 357, ProtocolApprovalInformationModelFIND = 358, ProtocolApprovalInformationModelMOVE = 359, ProtocolApprovalInformationModelGET = 360, RTPhysicianIntentStorage = 361, RTSegmentAnnotationStorage = 362, DICOSCTImageStorage = 363, DICOSDigitalXRayImageStorageForPresentation = 364, DICOSDigitalXRayImageStorageForProcessing = 365, DICOSThreatDetectionReportStorage = 366, DICOS2DAITStorage = 367, DICOS3DAITStorage = 368, DICOSQuadrupoleResonanceQRStorage = 369, EddyCurrentImageStorage = 370, EddyCurrentMultiframeImageStorage = 371, CompositeInstanceRootRetrieveMOVE = 372, CompositeInstanceRootRetrieveGET = 373, CompositeInstanceRetrieveWithoutBulkDataGET = 374, DefinedProcedureProtocolInformationModelFIND = 375, DefinedProcedureProtocolInformationModelMOVE = 376, DefinedProcedureProtocolInformationModelGET = 377, UPSFilteredGlobalSubscriptionSOPInstance = 378, UnifiedWorklistandProcedureStepServiceClass1 = 379, UnifiedProcedureStepPushSOPClass1 = 380, UnifiedProcedureStepWatchSOPClass1 = 381, UnifiedProcedureStepPullSOPClass1 = 382, UnifiedProcedureStepEventSOPClass1 = 383, RTBeamsDeliveryInstructionStorage = 384, RTConventionalMachineVerification = 385, RTIonMachineVerification = 386, RTBrachyApplicationSetupDeliveryInstructionStorage = 387, HangingProtocolInformationModelGET = 388, ColorPaletteStorage = 389, ColorPaletteQueryRetrieveInformationModelFIND = 390, ColorPaletteQueryRetrieveInformationModelMOVE = 391, ColorPaletteQueryRetrieveInformationModelGET = 392, GenericImplantTemplateStorage = 393, GenericImplantTemplateInformationModelFIND = 394, GenericImplantTemplateInformationModelMOVE = 395, GenericImplantTemplateInformationModelGET = 396, ImplantAssemblyTemplateStorage = 397, ImplantAssemblyTemplateInformationModelFIND = 398, ImplantAssemblyTemplateInformationModelMOVE = 399, ImplantAssemblyTemplateInformationModelGET = 400, ImplantTemplateGroupStorage = 401, ImplantTemplateGroupInformationModelFIND = 402, ImplantTemplateGroupInformationModelMOVE = 403, ImplantTemplateGroupInformationModelGET = 404, NativeDICOMModel = 405, AbstractMultiDimensionalImageModel = 406, DICOMContentMappingResource = 407, EnhancedMRColorImageStorage = 408, UniversalCoordinatedTime = 409 // // ////////////////////////////////////////////// ////////////////////////////////////////////// // // Optionally private UIDs // #if 0 Private_1_2_840_113619_4_2, Private_1_2_840_113619_4_3, Private_1_3_12_2_1107_5_9_1, Private_1_2_840_113619_4_26, Private_1_2_840_113619_4_30, Private_2_16_840_1_113709_1_5_1, Private_2_16_840_1_113709_1_2_2, Private_1_2_840_113543_6_6_1_3_10002, Private_1_2_392_200036_9116_7_8_1_1_1, Private_1_2_392_200036_9125_1_1_2, Private_1_2_840_113619_4_27, Private_1_3_46_670589_11_0_0_12_1, Private_1_3_46_670589_11_0_0_12_2, Private_1_3_46_670589_11_0_0_12_4, Private_1_3_46_670589_2_3_1_1, Private_1_3_46_670589_2_4_1_1, Private_1_3_46_670589_2_5_1_1, Private_1_3_46_670589_5_0_1, Private_1_3_46_670589_5_0_1_1, Private_1_3_46_670589_5_0_10, Private_1_3_46_670589_5_0_11, Private_1_3_46_670589_5_0_11_1, Private_1_3_46_670589_5_0_12, Private_1_3_46_670589_5_0_13, Private_1_3_46_670589_5_0_14, Private_1_3_46_670589_5_0_2, Private_1_3_46_670589_5_0_2_1, Private_1_3_46_670589_5_0_3, Private_1_3_46_670589_5_0_3_1, Private_1_3_46_670589_5_0_4, Private_1_3_46_670589_5_0_7, Private_1_3_46_670589_5_0_8, Private_1_3_46_670589_5_0_9, Private_1_2_752_24_3_7_6, Private_1_2_752_24_3_7_7, Private_1_2_840_113619_5_2, Private_1_3_46_670589_33_1_4_1 #endif // // ////////////////////////////////////////////// } TSName; typedef const char* const (*TransferSyntaxStringsType)[2]; static TransferSyntaxStringsType GetTransferSyntaxStrings(); static const char * const *GetTransferSyntaxString(unsigned int ts); static unsigned int GetNumberOfTransferSyntaxStrings(); // TODO: Because I would like a dual signature for TSType and TSName, C++ won't let me do it... static const char* GetUIDString(/*TSType*/ unsigned int ts); static const char* GetUIDName(/*TSType*/ unsigned int ts); /// Initialize object from a string (a uid number) /// return false on error, and internal state is set to 0 bool SetFromUID(const char *str); /// When object is Initialize function return the well known name associated with uid /// return NULL when not initialized const char *GetName() const; /// When object is Initialize function return the uid /// return NULL when not initialized const char *GetString() const; operator TSType () const { return TSField; } private: TSType TSField; }; //----------------------------------------------------------------------------- inline std::ostream &operator<<(std::ostream &_os, const UIDs &uid) { _os << uid.GetString() << " -> " << uid.GetName(); return _os; } } // end namespace gdcm #endif //GDCMUIDS_H GDCM-3.0.10/Source/DataDictionary/gdcmconformancetests.xml000066400000000000000000000024301412732066400234020ustar00rootroot00000000000000 GDCM-3.0.10/Source/DataDictionary/getname.xsl000066400000000000000000000015521412732066400206240ustar00rootroot00000000000000 GDCM-3.0.10/Source/DataDictionary/getowner.xsl000066400000000000000000000017371412732066400210430ustar00rootroot00000000000000 {" "," "}, GDCM-3.0.10/Source/DataDictionary/getretired.xsl000066400000000000000000000022461412732066400213430ustar00rootroot00000000000000 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ , GDCM-3.0.10/Source/DataDictionary/order.xsl000066400000000000000000000023151412732066400203150ustar00rootroot00000000000000 GDCM-3.0.10/Source/DataDictionary/priv2html.xsl000066400000000000000000000075171412732066400211420ustar00rootroot00000000000000 DICOM DICTIONARY italic normal
Tag VR VM Description Version Owner Retired bla
( , ) (RET)
GDCM-3.0.10/Source/DataDictionary/privatedicts.xml000066400000000000000000035042511412732066400217060ustar00rootroot00000000000000 GDCM-3.0.10/Source/DataDictionary/redo.xsl000066400000000000000000000056631412732066400201440ustar00rootroot00000000000000 type="text/xsl" href="gdcm2html.xsl" to produce output use: $ xsltproc gdcm2html.xsl GDCM2.xml 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. GDCM-3.0.10/Source/DataDictionary/redo2.xsl000066400000000000000000000053101412732066400202130ustar00rootroot00000000000000 type="text/xsl" href="gdcm2html.xsl" to produce output use: $ xsltproc gdcm2html.xsl GDCM2.xml 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. GDCM-3.0.10/Source/DataDictionary/sort.xsl000066400000000000000000000013311412732066400201660ustar00rootroot00000000000000 GDCM-3.0.10/Source/DataDictionary/uppercase.xsl000066400000000000000000000033541412732066400211750ustar00rootroot00000000000000 GDCM-3.0.10/Source/DataDictionary/vital.xml000066400000000000000000000031011412732066400203050ustar00rootroot00000000000000 GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/000077500000000000000000000000001412732066400224475ustar00rootroot00000000000000GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/CMakeLists.txt000066400000000000000000000054361412732066400252170ustar00rootroot00000000000000# Define the srcs for Data Structure and Encoding Definitions # DSED # dual compilation (namespace gdcm_ns), all the following either directly # reference code using GDCM_SUPPORT_BROKEN_IMPLEMENTATION or indirectly set(DSED2_SRCS gdcmByteValue.cxx gdcmDataElement.cxx gdcmDataSet.cxx gdcmExplicitDataElement.cxx gdcmFile.cxx # FileMeta is class member gdcmFileMetaInformation.cxx # subclass of DataSet gdcmFragment.cxx gdcmImplicitDataElement.cxx gdcmItem.cxx gdcmMediaStorage.cxx # SetFromModality takes a DataSet gdcmPrivateTag.cxx gdcmReader.cxx gdcmSequenceOfFragments.cxx gdcmSequenceOfItems.cxx gdcmValue.cxx # friend decl ) # need to prepare duplicate files to help cmake handle setting compile # definitions (cmake cannot handle duplicate source file in same target). # this trick allows us to avoid a static compilation which may not be portable foreach(src ${DSED2_SRCS}) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${CMAKE_CURRENT_BINARY_DIR}/strict_${src} COPYONLY ) list(APPEND DSED3_SRCS ${CMAKE_CURRENT_BINARY_DIR}/strict_${src} ) set_property( SOURCE ${CMAKE_CURRENT_BINARY_DIR}/strict_${src} PROPERTY COMPILE_DEFINITIONS "GDCM_OVERRIDE_BROKEN_IMPLEMENTATION" "gdcm_ns=gdcmstrict" ) endforeach() # the following source code do not need a duplicate compilation to handle # GDCM_SUPPORT_BROKEN_IMPLEMENTATION set(DSED_SRCS ${DSED2_SRCS} gdcmReader.strict.cxx # hook to call gdcmstrict API gdcmTag.cxx gdcmTagToVR.cxx gdcmCodeString.cxx gdcmFileSet.cxx gdcmByteSwapFilter.cxx gdcmUNExplicitImplicitDataElement.cxx gdcmWriter.cxx #gdcmParser.cxx gdcmCSAHeader.cxx gdcmMrProtocol.cxx gdcmPDBHeader.cxx gdcmTransferSyntax.cxx gdcmVM.cxx gdcmVR.cxx gdcmPreamble.cxx gdcmParseException.cxx gdcmUNExplicitDataElement.cxx gdcmCP246ExplicitDataElement.cxx gdcmExplicitImplicitDataElement.cxx gdcmVR16ExplicitDataElement.cxx ) # Add the include paths include_directories( # Bin: "${GDCM_BINARY_DIR}/Source/Common" # src: "${GDCM_SOURCE_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/DataDictionary" "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition/" "${GDCM_SOURCE_DIR}/Utilities" ) if(NOT GDCM_USE_SYSTEM_ZLIB) include_directories( "${GDCM_BINARY_DIR}/Utilities/gdcmzlib" ) endif() add_library(gdcmDSED ${DSED_SRCS} ${DSED3_SRCS}) #target_compile_features(gdcmDSED PUBLIC cxx_strong_enums) target_link_libraries(gdcmDSED LINK_PUBLIC gdcmCommon) # zlib stuff are actually included (template) so we need to link them here. target_link_libraries(gdcmDSED LINK_PRIVATE ${GDCM_ZLIB_LIBRARIES}) set_target_properties(gdcmDSED PROPERTIES ${GDCM_LIBRARY_PROPERTIES}) # libs install_library(gdcmDSED) # PDB install_pdb(gdcmDSED) # include files install_includes("*.h" "*.txx") GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/README.txt000066400000000000000000000000671412732066400241500ustar00rootroot00000000000000DICOM Data Structure and Encoding Definitions Part 3.5 GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmAttribute.h000066400000000000000000001006541412732066400254240ustar00rootroot00000000000000/*========================================================================= 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 GDCMATTRIBUTE_H #define GDCMATTRIBUTE_H #include "gdcmTypes.h" #include "gdcmVR.h" #include "gdcmTagToType.h" #include "gdcmVM.h" #include "gdcmElement.h" #include "gdcmDataElement.h" #include "gdcmDataSet.h" #include "gdcmStaticAssert.h" #include #include #include namespace gdcm_ns { struct void_; // Declaration, also serve as forward declaration template class VRVLSize; // Implementation when VL is coded on 16 bits: template<> class VRVLSize<0> { public: static inline uint16_t Read(std::istream &_is) { uint16_t l; _is.read((char*)&l, 2); return l; } static inline void Write(std::ostream &os) { (void)os; } }; // Implementation when VL is coded on 32 bits: template<> class VRVLSize<1> { public: static inline uint32_t Read(std::istream &_is) { char dummy[2]; _is.read(dummy, 2); uint32_t l; _is.read((char*)&l, 4); return l; } static inline void Write(std::ostream &os) { (void)os; } }; /** * \brief Attribute class * This class use template metaprograming tricks to let the user know when the template * instantiation does not match the public dictionary. * * Typical example that compile is: * Attribute<0x0008,0x9007> a = {"ORIGINAL","PRIMARY","T1","NONE"}; * * Examples that will NOT compile are: * * Attribute<0x0018,0x1182, VR::IS, VM::VM1> fd1 = {}; // not enough parameters * Attribute<0x0018,0x1182, VR::IS, VM::VM2> fd2 = {0,1,2}; // too many initializers * Attribute<0x0018,0x1182, VR::IS, VM::VM3> fd3 = {0,1,2}; // VM3 is not valid * Attribute<0x0018,0x1182, VR::UL, VM::VM2> fd3 = {0,1}; // UL is not valid VR */ template::VRType, // can the user override this value ? int TVM = TagToType::VMType // can the user override this value ? /*typename SQAttribute = void_*/ > // if only I had variadic template... class Attribute { public: typedef typename VRToType::Type ArrayType; enum { VMType = VMToLength::Length }; ArrayType Internal[VMToLength::Length]; // Make sure that user specified VR/VM are compatible with the public dictionary: GDCM_STATIC_ASSERT( ((VR::VRType)TVR & (VR::VRType)(TagToType::VRType)) ); GDCM_STATIC_ASSERT( ((VM::VMType)TVM & (VM::VMType)(TagToType::VMType)) ); GDCM_STATIC_ASSERT( ((((VR::VRType)TVR & VR::VR_VM1) && ((VM::VMType)TVM == VM::VM1) ) || !((VR::VRType)TVR & VR::VR_VM1) ) ); static Tag GetTag() { return Tag(Group,Element); } static VR GetVR() { return (VR::VRType)TVR; } static VM GetVM() { return (VM::VMType)TVM; } // The following two methods do make sense only in case of public element, // when the template is intanciated with private element the VR/VM are simply // defaulted to allow everything (see gdcmTagToType.h default template for TagToType) static VR GetDictVR() { return (VR::VRType)(TagToType::VRType); } static VM GetDictVM() { return (VM::VMType)(TagToType::VMType); } // Some extra dummy checks: // Data Elements with a VR of SQ, OF, OW, OB or UN shall always have a Value Multiplicity of one. unsigned int GetNumberOfValues() const { return VMToLength::Length; } // Implementation of Print is common to all Mode (ASCII/Binary) // TODO: Can we print a \ when in ASCII...well I don't think so // it would mean we used a bad VM then, right ? void Print(std::ostream &os) const { os << GetTag() << " "; os << TagToType::GetVRString() << " "; os << TagToType::GetVMString() << " "; os << Internal[0]; // VM is at least guarantee to be one for(unsigned int i=1; i::Mode>::Write(Internal, GetNumberOfValues(),os); ret.SetVR( GetVR() ); assert( ret.GetVR() != VR::SQ ); if( (VR::VRType)VRToEncoding::Mode == VR::VRASCII ) { if( GetVR() != VR::UI ) { if( os.str().size() % 2 ) { os << " "; } } } VL::Type osStrSize = (VL::Type)os.str().size(); ret.SetByteValue( os.str().c_str(), osStrSize ); return ret; } void SetFromDataElement(DataElement const &de) { // This is kind of hackish but since I do not generate other element than the first one: 0x6000 I should be ok: assert( Tag(Group,Element) == de.GetTag() || Group == 0x6000 || Group == 0x5000 ); assert( GetVR() != VR::INVALID ); assert( GetVR().Compatible( de.GetVR() ) || de.GetVR() == VR::INVALID ); // In case of VR::INVALID cannot use the & operator if( de.IsEmpty() ) return; const ByteValue *bv = de.GetByteValue(); #ifdef GDCM_WORDS_BIGENDIAN if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ ) #else if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID ) #endif { SetByteValue(bv); } else { SetByteValueNoSwap(bv); } } void Set(DataSet const &ds) { SetFromDataElement( ds.GetDataElement( Tag(Group,Element) ) ); } void SetFromDataSet(DataSet const &ds) { if( ds.FindDataElement( Tag(Group,Element) ) && !ds.GetDataElement( Tag(Group,Element) ).IsEmpty() ) { SetFromDataElement( ds.GetDataElement( Tag(Group,Element) ) ); } } protected: void SetByteValueNoSwap(const ByteValue *bv) { if( !bv ) return; // That would be bad... assert( bv->GetPointer() && bv->GetLength() ); // [123]C element can be empty //if( VRToEncoding::Mode == VR::VRBINARY ) // { // // always do a copy ! // SetValues(bv->GetPointer(), bv->GetLength()); // } //else { std::stringstream ss; std::string s = std::string( bv->GetPointer(), bv->GetLength() ); ss.str( s ); EncodingImplementation::Mode>::ReadNoSwap(Internal, GetNumberOfValues(),ss); } } void SetByteValue(const ByteValue *bv) { if( !bv ) return; // That would be bad... assert( bv->GetPointer() && bv->GetLength() ); // [123]C element can be empty //if( VRToEncoding::Mode == VR::VRBINARY ) // { // // always do a copy ! // SetValues(bv->GetPointer(), bv->GetLength()); // } //else { std::stringstream ss; std::string s = std::string( bv->GetPointer(), bv->GetLength() ); ss.str( s ); EncodingImplementation::Mode>::Read(Internal, GetNumberOfValues(),ss); } } #if 0 // TODO FIXME the implicit way: // explicit: void Read(std::istream &_is) { const uint16_t cref[] = { Group, Element }; uint16_t c[2]; _is.read((char*)&c, sizeof(c)); assert( c[0] == cref[0] && c[1] == cref[1] ); char vr[2]; _is.read(vr, 2); // Check consistency ? const uint32_t lref = GetLength() * sizeof( typename VRToType::Type ); uint32_t l = VRVLSize< (TVR & VR::VL32) >::Read(_is); l /= sizeof( typename VRToType::Type ); return EncodingImplementation::Mode>::Read(Internal, l,_is); } void Write(std::ostream &_os) const { uint16_t c[] = { Group, Element }; _os.write((char*)&c, 4); uint32_t l = GetLength() * sizeof( typename VRToType::Type ); _os.write((char*)&l, 4); return EncodingImplementation::Mode>::Write(Internal, GetLength(),_os); } void Read(std::istream &_is) { uint16_t cref[] = { Group, Element }; uint16_t c[2]; _is.read((char*)&c, 4); const uint32_t lref = GetLength() * sizeof( typename VRToType::Type ); uint32_t l; _is.read((char*)&l, 4); l /= sizeof( typename VRToType::Type ); return EncodingImplementation::Mode>::Read(Internal, l,_is); } void Write(std::ostream &_os) const { uint16_t c[] = { Group, Element }; _os.write((char*)&c, 4); uint32_t l = GetLength() * sizeof( typename VRToType::Type ); _os.write((char*)&l, 4); return EncodingImplementation::Mode>::Write(Internal, GetLength(),_os); } #endif }; template class Attribute { public: typedef typename VRToType::Type ArrayType; enum { VMType = VMToLength::Length }; //ArrayType Internal[VMToLength::Length]; ArrayType Internal; GDCM_STATIC_ASSERT( VMToLength::Length == 1 ); // Make sure that user specified VR/VM are compatible with the public dictionary: GDCM_STATIC_ASSERT( ((VR::VRType)TVR & (VR::VRType)(TagToType::VRType)) ); GDCM_STATIC_ASSERT( ((VM::VMType)VM::VM1 & (VM::VMType)(TagToType::VMType)) ); GDCM_STATIC_ASSERT( ((((VR::VRType)TVR & VR::VR_VM1) && ((VM::VMType)VM::VM1 == VM::VM1) ) || !((VR::VRType)TVR & VR::VR_VM1) ) ); static Tag GetTag() { return Tag(Group,Element); } static VR GetVR() { return (VR::VRType)TVR; } static VM GetVM() { return (VM::VMType)VM::VM1; } // The following two methods do make sense only in case of public element, // when the template is intanciated with private element the VR/VM are simply // defaulted to allow everything (see gdcmTagToType.h default template for TagToType) static VR GetDictVR() { return (VR::VRType)(TagToType::VRType); } static VM GetDictVM() { return (VM::VMType)(TagToType::VMType); } // Some extra dummy checks: // Data Elements with a VR of SQ, OF, OW, OB or UN shall always have a Value Multiplicity of one. unsigned int GetNumberOfValues() const { return VMToLength::Length; } // Implementation of Print is common to all Mode (ASCII/Binary) // TODO: Can we print a \ when in ASCII...well I don't think so // it would mean we used a bad VM then, right ? void Print(std::ostream &os) const { os << GetTag() << " "; os << TagToType::GetVRString() << " "; os << TagToType::GetVMString() << " "; os << Internal; // VM is at least guarantee to be one } // copy: //ArrayType GetValue(unsigned int idx = 0) { // assert( idx < GetNumberOfValues() ); // return Internal[idx]; //} //ArrayType operator[] (unsigned int idx) { // return GetValue(idx); //} // FIXME: is this always a good idea ? // I do not think so, I prefer operator //operator ArrayType () const { return Internal[0]; } bool operator==(const Attribute &att) const { return std::equal(&Internal, &Internal+GetNumberOfValues(), att.GetValues()); } bool operator!=(const Attribute &att) const { return !std::equal(&Internal, &Internal+GetNumberOfValues(), att.GetValues()); } bool operator<(const Attribute &att) const { return std::lexicographical_compare(&Internal, &Internal+GetNumberOfValues(), att.GetValues(), att.GetValues() + att.GetNumberOfValues() ); } ArrayType &GetValue() { // assert( idx < GetNumberOfValues() ); return Internal; } // ArrayType & operator[] (unsigned int idx) { // return GetValue(idx); // } // const reference ArrayType const &GetValue() const { //assert( idx < GetNumberOfValues() ); return Internal; } //ArrayType const & operator[] () const { // return GetValue(); //} void SetValue(ArrayType v) { // assert( idx < GetNumberOfValues() ); Internal = v; } /* void SetValues(const ArrayType* array, unsigned int numel = VMType ) { assert( array && numel && numel == GetNumberOfValues() ); // std::copy is smarted than a memcpy, and will call memcpy when POD type std::copy(array, array+numel, Internal); } */ // FIXME Should we remove this function ? const ArrayType* GetValues() const { return &Internal; } // API to talk to the run-time layer: gdcm::DataElement DataElement GetAsDataElement() const { DataElement ret( Tag(Group,Element) ); std::ostringstream os; // os.imbue(std::locale::classic()); // This is not required AFAIK EncodingImplementation::Mode>::Write(&Internal, GetNumberOfValues(),os); ret.SetVR( GetVR() ); assert( ret.GetVR() != VR::SQ ); if( (VR::VRType)VRToEncoding::Mode == VR::VRASCII ) { if( GetVR() != VR::UI ) { if( os.str().size() % 2 ) { os << " "; } } } VL::Type osStrSize = (VL::Type)os.str().size(); ret.SetByteValue( os.str().c_str(), osStrSize ); return ret; } void SetFromDataElement(DataElement const &de) { // This is kind of hackish but since I do not generate other element than the first one: 0x6000 I should be ok: assert( Tag(Group,Element) == de.GetTag() || Group == 0x6000 || Group == 0x5000 ); assert( GetVR() != VR::INVALID ); assert( GetVR().Compatible( de.GetVR() ) || de.GetVR() == VR::INVALID ); // In case of VR::INVALID cannot use the & operator if( de.IsEmpty() ) return; const ByteValue *bv = de.GetByteValue(); #ifdef GDCM_WORDS_BIGENDIAN if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ ) #else if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID ) #endif { SetByteValue(bv); } else { SetByteValueNoSwap(bv); } } void Set(DataSet const &ds) { SetFromDataElement( ds.GetDataElement( Tag(Group,Element) ) ); } void SetFromDataSet(DataSet const &ds) { if( ds.FindDataElement( Tag(Group,Element) ) && !ds.GetDataElement( Tag(Group,Element) ).IsEmpty() ) { SetFromDataElement( ds.GetDataElement( Tag(Group,Element) ) ); } } protected: void SetByteValueNoSwap(const ByteValue *bv) { if( !bv ) return; // That would be bad... assert( bv->GetPointer() && bv->GetLength() ); // [123]C element can be empty //if( VRToEncoding::Mode == VR::VRBINARY ) // { // // always do a copy ! // SetValues(bv->GetPointer(), bv->GetLength()); // } //else { std::stringstream ss; std::string s = std::string( bv->GetPointer(), bv->GetLength() ); ss.str( s ); EncodingImplementation::Mode>::ReadNoSwap(&Internal, GetNumberOfValues(),ss); } } void SetByteValue(const ByteValue *bv) { if( !bv ) return; // That would be bad... assert( bv->GetPointer() && bv->GetLength() ); // [123]C element can be empty //if( VRToEncoding::Mode == VR::VRBINARY ) // { // // always do a copy ! // SetValues(bv->GetPointer(), bv->GetLength()); // } //else { std::stringstream ss; std::string s = std::string( bv->GetPointer(), bv->GetLength() ); ss.str( s ); EncodingImplementation::Mode>::Read(&Internal, GetNumberOfValues(),ss); } } #if 0 // TODO FIXME the implicit way: // explicit: void Read(std::istream &_is) { const uint16_t cref[] = { Group, Element }; uint16_t c[2]; _is.read((char*)&c, sizeof(c)); assert( c[0] == cref[0] && c[1] == cref[1] ); char vr[2]; _is.read(vr, 2); // Check consistency ? const uint32_t lref = GetLength() * sizeof( typename VRToType::Type ); uint32_t l = VRVLSize< (TVR & VR::VL32) >::Read(_is); l /= sizeof( typename VRToType::Type ); return EncodingImplementation::Mode>::Read(Internal, l,_is); } void Write(std::ostream &_os) const { uint16_t c[] = { Group, Element }; _os.write((char*)&c, 4); uint32_t l = GetLength() * sizeof( typename VRToType::Type ); _os.write((char*)&l, 4); return EncodingImplementation::Mode>::Write(Internal, GetLength(),_os); } void Read(std::istream &_is) { uint16_t cref[] = { Group, Element }; uint16_t c[2]; _is.read((char*)&c, 4); const uint32_t lref = GetLength() * sizeof( typename VRToType::Type ); uint32_t l; _is.read((char*)&l, 4); l /= sizeof( typename VRToType::Type ); return EncodingImplementation::Mode>::Read(Internal, l,_is); } void Write(std::ostream &_os) const { uint16_t c[] = { Group, Element }; _os.write((char*)&c, 4); uint32_t l = GetLength() * sizeof( typename VRToType::Type ); _os.write((char*)&l, 4); return EncodingImplementation::Mode>::Write(Internal, GetLength(),_os); } #endif }; // No need to repeat default template arg, since primary template // will be used to generate the default arguments template class Attribute { public: typedef typename VRToType::Type ArrayType; // Make sure that user specified VR/VM are compatible with the public dictionary: GDCM_STATIC_ASSERT( ((VR::VRType)TVR & (VR::VRType)(TagToType::VRType)) ); GDCM_STATIC_ASSERT( (VM::VM1_n & (VM::VMType)(TagToType::VMType)) ); GDCM_STATIC_ASSERT( ((((VR::VRType)TVR & VR::VR_VM1) && ((VM::VMType)TagToType::VMType == VM::VM1) ) || !((VR::VRType)TVR & VR::VR_VM1) ) ); static Tag GetTag() { return Tag(Group,Element); } static VR GetVR() { return (VR::VRType)TVR; } static VM GetVM() { return VM::VM1_n; } static VR GetDictVR() { return (VR::VRType)(TagToType::VRType); } static VM GetDictVM() { return GetVM(); } // This the way to prevent default initialization explicit Attribute() { Internal=nullptr; Length=0; Own = true; } ~Attribute() { if( Own ) { delete[] Internal; } Internal = nullptr; // paranoid } unsigned int GetNumberOfValues() const { return Length; } void SetNumberOfValues(unsigned int numel) { SetValues(nullptr, numel, true); } const ArrayType* GetValues() const { return Internal; } void Print(std::ostream &os) const { os << GetTag() << " "; os << GetVR() << " "; os << GetVM() << " "; os << Internal[0]; // VM is at least guarantee to be one for(unsigned int i=1; i(array); } // postcondition assert( numel == GetNumberOfValues() ); } DataElement GetAsDataElement() const { DataElement ret( GetTag() ); std::ostringstream os; if( Internal ) { EncodingImplementation::Mode>::Write(Internal, GetNumberOfValues(),os); if( (VR::VRType)VRToEncoding::Mode == VR::VRASCII ) { if( GetVR() != VR::UI ) { if( os.str().size() % 2 ) { os << " "; } } } } ret.SetVR( GetVR() ); assert( ret.GetVR() != VR::SQ ); VL::Type osStrSize = (VL::Type) os.str().size(); ret.SetByteValue( os.str().c_str(), osStrSize); return ret; } void SetFromDataElement(DataElement const &de) { // This is kind of hackish but since I do not generate other element than the first one: 0x6000 I should be ok: assert( GetTag() == de.GetTag() || GetTag().GetGroup() == 0x6000 || GetTag().GetGroup() == 0x5000 ); assert( GetVR().Compatible( de.GetVR() ) ); // In case of VR::INVALID cannot use the & operator assert( !de.IsEmpty() ); const ByteValue *bv = de.GetByteValue(); SetByteValue(bv); } void Set(DataSet const &ds) { SetFromDataElement( ds.GetDataElement( GetTag() ) ); } void SetFromDataSet(DataSet const &ds) { if( ds.FindDataElement( GetTag() ) && !ds.GetDataElement( GetTag() ).IsEmpty() ) { SetFromDataElement( ds.GetDataElement( GetTag() ) ); } } protected: void SetByteValue(const ByteValue *bv) { assert( bv ); // FIXME std::stringstream ss; std::string s = std::string( bv->GetPointer(), bv->GetLength() ); Length = bv->GetLength(); // HACK FIXME ss.str( s ); ArrayType *internal; ArrayType buffer[256]; if( bv->GetLength() < 256 ) { internal = buffer; } else { internal = new ArrayType[(VL::Type)bv->GetLength()]; // over allocation } EncodingImplementation::Mode>::ReadComputeLength(internal, Length, ss); SetValues( internal, Length, true ); if( !(bv->GetLength() < 256) ) { delete[] internal; } //EncodingImplementation::Mode>::Read(Internal, // GetNumberOfValues(),ss); } private: ArrayType *Internal; unsigned int Length; bool Own : 1; }; template class Attribute : public Attribute { public: VM GetVM() const { return VM::VM1_3; } }; template class Attribute : public Attribute { public: VM GetVM() const { return VM::VM1_8; } }; template class Attribute : public Attribute { public: VM GetVM() const { return VM::VM2_n; } }; template class Attribute : public Attribute { public: static VM GetVM() { return VM::VM2_2n; } }; template class Attribute : public Attribute { public: static VM GetVM() { return VM::VM3_n; } }; template class Attribute : public Attribute { public: static VM GetVM() { return VM::VM3_3n; } }; // For particular case for ASCII string // WARNING: This template explicitly instantiates a particular // EncodingImplementation THEREFORE it is required to be declared after the // EncodingImplementation is needs (doh!) #if 0 template class Attribute { public: Attribute(const char array[]) { unsigned int i = 0; const char sep = '\\'; std::string sarray = array; std::string::size_type pos1 = 0; std::string::size_type pos2 = sarray.find(sep, pos1+1); while(pos2 != std::string::npos) { Internal[i++] = sarray.substr(pos1, pos2-pos1); pos1 = pos2+1; pos2 = sarray.find(sep, pos1+1); } Internal[i] = sarray.substr(pos1, pos2-pos1); // Shouldn't we do the contrary, since we know how many separators // (and default behavior is to discard anything after the VM declared assert( GetLength()-1 == i ); } unsigned long GetLength() const { return VMToLength::Length; } // Implementation of Print is common to all Mode (ASCII/Binary) void Print(std::ostream &_os) const { _os << Internal[0]; // VM is at least guarantee to be one for(int i=1; i::Length; ++i) _os << "," << Internal[i]; } void Read(std::istream &_is) { EncodingImplementation::Read(Internal, GetLength(),_is); } void Write(std::ostream &_os) const { EncodingImplementation::Write(Internal, GetLength(),_os); } private: typename String Internal[VMToLength::Length]; }; template< int TVM> class Attribute : public StringAttribute { }; #endif #if 0 // Implementation for the undefined length (dynamically allocated array) template class Attribute { public: // This the way to prevent default initialization explicit Attribute() { Internal=0; Length=0; } ~Attribute() { delete[] Internal; Internal = 0; } // Length manipulation // SetLength should really be protected anyway...all operation // should go through SetArray unsigned long GetLength() const { return Length; } typedef typename VRToType::Type ArrayType; void SetLength(unsigned long len) { const unsigned int size = sizeof(ArrayType); if( len ) { if( len > Length ) { // perform realloc assert( (len / size) * size == len ); ArrayType *internal = new ArrayType[len / size]; memcpy(internal, Internal, Length * size); delete[] Internal; Internal = internal; } } Length = len / size; } // If save is set to zero user should not delete the pointer //void SetArray(const typename VRToType::Type *array, int len, bool save = false) void SetArray(const ArrayType *array, unsigned long len, bool save = false) { if( save ) { SetLength(len); // realloc memcpy(Internal, array, len/*/sizeof(ArrayType)*/); } else { // TODO rewrite this stupid code: Length = len; //Internal = array; assert(0); } } // Implementation of Print is common to all Mode (ASCII/Binary) void Print(std::ostream &_os) const { assert( Length ); assert( Internal ); _os << Internal[0]; // VM is at least guarantee to be one const unsigned long length = GetLength() < 25 ? GetLength() : 25; for(unsigned long i=1; i::Mode>::Read(Internal, GetLength(),_is); } void Write(std::ostream &_os) const { EncodingImplementation::Mode>::Write(Internal, GetLength(),_os); } Attribute(const Attribute&_val) { if( this != &_val) { *this = _val; } } Attribute &operator=(const Attribute &_val) { Length = 0; // SYITF Internal = 0; SetArray(_val.Internal, _val.Length, true); return *this; } private: typename VRToType::Type *Internal; unsigned long Length; // unsigned int ?? }; //template //class Attribute : public Attribute {}; // Partial specialization for derivatives of 1-n : 2-n, 3-n ... template class Attribute : public Attribute { public: typedef Attribute Parent; void SetLength(int len) { if( len <= 1 ) return; Parent::SetLength(len); } }; template class Attribute : public Attribute { public: typedef Attribute Parent; void SetLength(int len) { if( len % 2 ) return; Parent::SetLength(len); } }; template class Attribute : public Attribute { public: typedef Attribute Parent; void SetLength(int len) { if( len <= 2 ) return; Parent::SetLength(len); } }; template class Attribute : public Attribute { public: typedef Attribute Parent; void SetLength(int len) { if( len % 3 ) return; Parent::SetLength(len); } }; //template struct VRToLength; //template <> struct VRToLength //{ enum { Length = VM::VM1 }; } //template<> //class Attribute : public Attribute::Length > // only 0010 1010 AS 1 Patient's Age template<> class Attribute { public: char Internal[VMToLength::Length]; void Print(std::ostream &_os) const { _os << Internal; } }; template <> class Attribute : public Attribute {}; // Make it impossible to compile any other cases: template class Attribute; // Same for OW: template <> class Attribute : public Attribute {}; // Make it impossible to compile any other cases: template class Attribute; #endif #if 0 template<> class Attribute<0x7fe0,0x0010, VR::OW, VM::VM1> { public: char *Internal; unsigned long Length; // unsigned int ?? void Print(std::ostream &_os) const { _os << Internal[0]; } void SetBytes(char *bytes, unsigned long length) { Internal = bytes; Length = length; } void Read(std::istream &_is) { uint16_t c[2]; _is.read((char*)&c, 4); uint32_t l; _is.read((char*)&l, 4); Length = l; _is.read( Internal, Length ); } void Write(std::ostream &_os) const { uint16_t c[] = {0x7fe0, 0x0010}; _os.write((char*)&c, 4); _os.write((char*)&Length, 4); _os.write( Internal, Length ); } }; #endif /* // Removing Attribute for SQ for now... template class Attribute { public: SQA sqa; void Print(std::ostream &_os) const { _os << Tag(Group,Element); sqa.Print(_os << std::endl << '\t'); } void Write(std::ostream &_os) const { uint16_t c[] = {Group, Element}; _os.write((char*)&c, 4); uint32_t undef = 0xffffffff; _os.write((char*)&undef, 4); uint16_t item_beg[] = {0xfffe,0xe000}; _os.write((char*)&item_beg, 4); _os.write((char*)&undef, 4); sqa.Write(_os); uint16_t item_end[] = {0xfffe,0xe00d}; _os.write((char*)&item_end, 4); uint32_t zero = 0x0; _os.write((char*)&zero, 4); uint16_t seq_end[] = {0xfffe, 0xe0dd}; _os.write((char*)&seq_end, 4); _os.write((char*)&zero, 4); } }; */ /** * \example PatchFile.cxx * This is a C++ example on how to use gdcm::Attribute */ } // namespace gdcm_ns #endif //GDCMATTRIBUTE_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmBasicOffsetTable.h000066400000000000000000000064141412732066400266200ustar00rootroot00000000000000/*========================================================================= 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 GDCMBASICOFFSETTABLE_H #define GDCMBASICOFFSETTABLE_H #include "gdcmFragment.h" namespace gdcm_ns { /** * \brief Class to represent a BasicOffsetTable */ class GDCM_EXPORT BasicOffsetTable : public Fragment { //protected: // void SetTag(const Tag &t); public: BasicOffsetTable() : Fragment() {} friend std::ostream &operator<<(std::ostream &os, const BasicOffsetTable &val); /* VL GetLength() const { assert( !ValueLengthField.IsUndefined() ); assert( !ValueField || ValueField->GetLength() == ValueLengthField ); return TagField.GetLength() + ValueLengthField.GetLength() + ValueLengthField; } */ template 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"); return is; } //assert( TagField == itemStart ); if( TagField != itemStart ) { // Bug_Siemens_PrivateIconNoItem.dcm //gdcmDebugMacro( "Could be Bug_Siemens_PrivateIconNoItem.dcm" ); ParseException pe; pe.SetLastElement(*this); //throw "SIEMENS Icon thingy"; throw pe; } if( !ValueLengthField.Read(is) ) { assert(0 && "Should not happen"); return is; } // Self SmartPointer bv = new ByteValue; bv->SetLength(ValueLengthField); if( !bv->Read(is) ) { gdcmAssertAlwaysMacro(0 && "Should not happen"); return is; } ValueField = bv; return is; } /* template std::ostream &Write(std::ostream &os) const { const Tag itemStart(0xfffe, 0xe000); const Tag seqDelItem(0xfffe,0xe0dd); if( !TagField.Write(os) ) { assert(0 && "Should not happen"); return os; } assert( TagField == itemStart ); if( !ValueLengthField.Write(os) ) { assert(0 && "Should not happen"); return os; } if( ValueLengthField ) { // Self const ByteValue *bv = GetByteValue(); assert( bv ); assert( bv->GetLength() == ValueLengthField ); if( !bv->Write(os) ) { assert(0 && "Should not happen"); return os; } } return os; } */ }; //----------------------------------------------------------------------------- inline std::ostream &operator<<(std::ostream &os, const BasicOffsetTable &val) { os << " BasicOffsetTable Length=" << val.ValueLengthField << std::endl; if( val.ValueField ) { const ByteValue *bv = val.GetByteValue(); assert( bv ); os << *bv; } return os; } } // end namespace gdcm_ns #endif //GDCMBASICOFFSETTABLE_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmByteBuffer.h000066400000000000000000000047131412732066400255150ustar00rootroot00000000000000/*========================================================================= 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 GDCMBYTEBUFFER_H #define GDCMBYTEBUFFER_H #include "gdcmTypes.h" #include #include #include // memmove #error should not be used namespace gdcm { /** * \brief ByteBuffer * * \details Detailed description here * \note * looks like a std::streambuf or std::filebuf class with the get and * peek pointer */ class ByteBuffer { static const int InitBufferSize = 1024; public: ByteBuffer() : Start(0), End(0),Limit(0) {} char *Get(int len) { char *buffer = &Internal[0]; if (len > Limit - End) { // FIXME avoid integer overflow int neededSize = len + (End - Start); if (neededSize <= Limit - buffer) { memmove(buffer, Start, End - Start); End = buffer + (End - Start); Start = buffer; } else { char *newBuf; int bufferSize = Limit - Start; if ( bufferSize == 0 ) { bufferSize = InitBufferSize; } do { bufferSize *= 2; } while (bufferSize < neededSize); //newBuf = malloc(bufferSize); try { Internal.reserve(bufferSize); newBuf = &Internal[0]; } catch(...) { //errorCode = NoMemoryError; return 0; } Limit = newBuf + bufferSize; if (Start) { memcpy(newBuf, Start, End - Start); } End = newBuf + (End - Start); Start = /*buffer =*/ newBuf; } } assert( (int)Internal.capacity() >= len ); return End; } void UpdatePosition() {} void ShiftEnd(int len) { End += len; } const char *GetStart() const { return Start; } private: typedef std::vector CharVector; const char *Start; char *End; const char *Limit; CharVector Internal; }; } // end namespace gdcm #endif //GDCMBYTEBUFFER_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmByteSwapFilter.cxx000066400000000000000000000105331412732066400267340ustar00rootroot00000000000000/*========================================================================= 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 "gdcmByteSwapFilter.h" #include "gdcmElement.h" #include "gdcmByteValue.h" #include "gdcmSequenceOfFragments.h" #include "gdcmSequenceOfItems.h" #include "gdcmSwapper.h" namespace gdcm { //----------------------------------------------------------------------------- //ByteSwapFilter::ByteSwapFilter() //{ //} //----------------------------------------------------------------------------- ByteSwapFilter::~ByteSwapFilter() = default; bool ByteSwapFilter::ByteSwap() { for( DataSet::ConstIterator it = DS.Begin(); it != DS.End(); ++it) { const DataElement &de = *it; VR const & vr = de.GetVR(); //assert( vr & VR::VRASCII || vr & VR::VRBINARY ); ByteValue *bv = const_cast(de.GetByteValue()); gdcm::SmartPointer si = de.GetValueAsSQ(); if( de.IsEmpty() ) { } else if( bv && !si ) { assert( !si ); // ASCII do not need byte swap if( vr & VR::VRBINARY /*&& de.GetTag().IsPrivate()*/ ) { //assert( de.GetTag().IsPrivate() ); switch(vr) { case VR::AT: assert( 0 && "Should not happen" ); break; case VR::FL: // FIXME: Technically FL should not be byte-swapped... //std::cerr << "ByteSwap FL:" << de.GetTag() << std::endl; SwapperDoOp::SwapArray((uint32_t*)bv->GetVoidPointer(), bv->GetLength() / sizeof(uint32_t) ); break; case VR::FD: assert( 0 && "Should not happen" ); break; case VR::OB: // I think we are fine, unless this is one of those OB_OW thingy break; case VR::OF: assert( 0 && "Should not happen" ); break; case VR::OW: assert( 0 && "Should not happen" ); break; case VR::SL: SwapperDoOp::SwapArray((uint32_t*)bv->GetVoidPointer(), bv->GetLength() / sizeof(uint32_t) ); break; case VR::SQ: assert( 0 && "Should not happen" ); break; case VR::SS: SwapperDoOp::SwapArray((uint16_t*)bv->GetVoidPointer(), bv->GetLength() / sizeof(uint16_t) ); break; case VR::UL: SwapperDoOp::SwapArray((uint32_t*)bv->GetVoidPointer(), bv->GetLength() / sizeof(uint32_t) ); break; case VR::UN: assert( 0 && "Should not happen" ); break; case VR::US: SwapperDoOp::SwapArray((uint16_t*)bv->GetVoidPointer(), bv->GetLength() / sizeof(uint16_t) ); break; case VR::UT: assert( 0 && "Should not happen" ); break; default: assert( 0 && "Should not happen" ); } } } //else if( const SequenceOfItems *si = de.GetSequenceOfItems() ) else if( si ) { //if( de.GetTag().IsPrivate() ) { //std::cerr << "ByteSwap SQ:" << de.GetTag() << std::endl; SequenceOfItems::ConstIterator it2 = si->Begin(); for( ; it2 != si->End(); ++it2) { const Item &item = *it2; DataSet &ds = const_cast(item.GetNestedDataSet()); // FIXME ByteSwapFilter bsf(ds); bsf.ByteSwap(); } } } else if( const SequenceOfFragments *sf = de.GetSequenceOfFragments() ) { (void)sf; assert( 0 && "Should not happen" ); } else { assert( 0 && "error" ); } } if( ByteSwapTag ) { DataSet copy; DataSet::ConstIterator it = DS.Begin(); for( ; it != DS.End(); ++it) { DataElement de = *it; const Tag& tag = de.GetTag(); de.SetTag( Tag( SwapperDoOp::Swap( tag.GetGroup() ), SwapperDoOp::Swap( tag.GetElement() ) ) ); copy.Insert( de ); DS.Remove( de.GetTag() ); } DS = copy; } return true; } } GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmByteSwapFilter.h000066400000000000000000000022371412732066400263630ustar00rootroot00000000000000/*========================================================================= 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 GDCMBYTESWAPFILTER_H #define GDCMBYTESWAPFILTER_H #include "gdcmDataSet.h" namespace gdcm { /** * \brief ByteSwapFilter * \details In place byte-swapping of a dataset * FIXME: FL status ?? */ class GDCM_EXPORT ByteSwapFilter { public: ByteSwapFilter(DataSet& ds):DS(ds),ByteSwapTag(false) {} ~ByteSwapFilter(); ByteSwapFilter(const ByteSwapFilter &) = delete; ByteSwapFilter& operator=(const ByteSwapFilter &) = delete; bool ByteSwap(); void SetByteSwapTag(bool b) { ByteSwapTag = b; } private: DataSet &DS; bool ByteSwapTag; }; } // end namespace gdcm #endif //GDCMBYTESWAPFILTER_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmByteValue.cxx000066400000000000000000000210661412732066400257330ustar00rootroot00000000000000/*========================================================================= 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 "gdcmByteValue.h" #include // req C++11 #include // memcpy namespace gdcm_ns { void ByteValue::SetLength(VL vl) { VL l(vl); #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // CompressedLossy.dcm if( l.IsUndefined() ) throw Exception( "Impossible" ); if ( l.IsOdd() ) { gdcmDebugMacro( "BUGGY HEADER: Your dicom contain odd length value field." ); ++l; } #else gdcmAssertAlwaysMacro( !l.IsUndefined() && !l.IsOdd() ); #endif // I cannot use reserve for now. I need to implement: // STL - vector<> and istream // http://groups.google.com/group/comp.lang.c++/msg/37ec052ed8283e74 //#define SHORT_READ_HACK try { #ifdef SHORT_READ_HACK if( l <= 0xff ) #endif Internal.resize(l); //Internal.reserve(l); } catch(...) { //throw Exception("Impossible to allocate: " << l << " bytes." ); throw Exception("Impossible to allocate" ); } // Keep the exact length Length = vl; } void ByteValue::PrintASCII(std::ostream &os, VL maxlength ) const { VL length = std::min(maxlength, Length); // Special case for VR::UI, do not print the trailing \0 if( length && length == Length ) { if( Internal[length-1] == 0 ) { length = length - 1; } } // I cannot check IsPrintable some file contains \2 or \0 in a VR::LO element // See: acr_image_with_non_printable_in_0051_1010.acr //assert( IsPrintable(length) ); std::vector::const_iterator it = Internal.begin(); for(; it != Internal.begin()+length; ++it) { const char &c = *it; if ( !( isprint((unsigned char)c) || isspace((unsigned char)c) ) ) os << "."; else os << c; } } void ByteValue::PrintHex(std::ostream &os, VL maxlength ) const { VL length = std::min(maxlength, Length); // WARNING: Internal.end() != Internal.begin()+Length std::vector::const_iterator it = Internal.begin(); os << std::hex; for(; it != Internal.begin()+length; ++it) { //const char &c = *it; uint8_t v = *it; if( it != Internal.begin() ) os << "\\"; os << std::setw( 2 ) << std::setfill( '0' ) << (uint16_t)v; //++it; //os << std::setw( 1 ) << std::setfill( '0' ) << (int)*it; } os << std::dec; } bool ByteValue::GetBuffer(char *buffer, unsigned long length) const { // SIEMENS_GBS_III-16-ACR_NEMA_1.acr has a weird pixel length // so we need an inequality if( length <= Internal.size() ) { if(!Internal.empty()) memcpy(buffer, &Internal[0], length); return true; } gdcmDebugMacro( "Could not handle length= " << length ); return false; } void ByteValue::PrintPNXML(std::ostream &os) const { /* PersonName = element PersonName { Number, element SingleByte { NameComponents }?, element Ideographic { NameComponents }?, element Phonetic { NameComponents }? } NameComponents = element FamilyName {xsd:string}?, element GivenName {xsd:string}?, element MiddleName {xsd:string}?, element NamePrefix {xsd:string}?, element NameSuffix {xsd:string}? */ int count1 , count2; count1=count2=1; os << "\n" ; os << "\n " ; std::vector::const_iterator it = Internal.begin(); for(; it != (Internal.begin() + Length); ++it) { const char &c = *it; if ( c == '^' ) { if(count2==1) { os << "\n"; os << " "; count2++; } if(count2==2) { os << "\n"; os << " "; count2++; } else if(count2==3) { os << "\n"; os << " "; count2++; } else if(count2==4) { os << "\n"; os << " "; count2++; } else { //in the rare case there are more ^ characters assert("Name components exceeded"); } } else if ( c == '=' ) { if(count2==1) { os << "\n"; } if(count2==2) { os << "\n"; } else if(count2==3) { os << "\n"; } else if(count2==4) { os << "\n"; } else if(count2==5) { os << "\n"; } /*----------------------------------------------------------------*/ if(count1==1) { os << "\n"; os << " \n "; count1++; } else if(count1==2) { os << "\n"; os << " \n "; count1++; } else if(count1==3) { os << " \n \n"; count1++; } else { assert("Impossible - only 3 names allowed"); } count2=1; } else if ( !( isprint((unsigned char)c) ) ) os << "."; else if(c == '&') os << "&"; else if(c == '<') os << "<"; else if(c == '>') os << ">"; else if(c == '\'') os << "'"; else if(c == '\"') os << """; else os << c; } if(count2==1) { os << "\n"; } if(count2==2) { os << "\n"; } else if(count2==3) { os << "\n"; } else if(count2==4) { os << "\n"; } else if(count2==5) { os << "\n"; } if(count1==1) { os << "\n"; } else if(count1==2) { os << "\n"; } else if(count1==3) { os << "\n"; } os << ""; } void ByteValue::PrintASCIIXML(std::ostream &os) const { //VL length = std::min(maxlength, Length); // Special case for VR::UI, do not print the trailing \0 /*if(Length && Internal[Length-1] == 0 ) { Length = Length - 1; } */ // Check for non printable characters int count = 1; os << ""; std::vector::const_iterator it = Internal.begin(); for(; it != (Internal.begin() + Length); ++it) { const char &c = *it; if ( c == '\\' ) { count++; os << "\n"; os << ""; } else if ( !c ) { // \0 is found ... } else if(c == '&') os << "&"; else if(c == '<') os << "<"; else if(c == '>') os << ">"; else if(c == '\'') os << "'"; else if(c == '\"') os << """; else os << c; } os << "\n"; } void ByteValue::PrintHexXML(std::ostream &os ) const { //VL length = std::min(maxlength, Length); // WARNING: Internal.end() != Internal.begin()+Length std::vector::const_iterator it = Internal.begin(); os << std::hex; for(; it != Internal.begin() + Length; ++it) { //const char &c = *it; uint8_t v = *it; if( it != Internal.begin() ) os << "\\"; os << std::setw( 2 ) << std::setfill( '0' ) << (uint16_t)v; //++it; //os << std::setw( 1 ) << std::setfill( '0' ) << (int)*it; } os << std::dec; } void ByteValue::Append(ByteValue const & bv) { //Internal.resize( Length + bv.Length ); Internal.insert( Internal.end(), bv.Internal.begin(), bv.Internal.end()); Length += bv.Length; // post condition assert( Internal.size() % 2 == 0 && Internal.size() == Length ); } } // end namespace gdcm_ns GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmByteValue.h000066400000000000000000000156001412732066400253550ustar00rootroot00000000000000/*========================================================================= 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 GDCMBYTEVALUE_H #define GDCMBYTEVALUE_H #include "gdcmValue.h" #include "gdcmTrace.h" #include "gdcmVL.h" #include #include #include #include namespace gdcm_ns { #if !defined(SWIGPYTHON) && !defined(SWIGCSHARP) && !defined(SWIGJAVA) && !defined(SWIGPHP) using namespace gdcm; #endif /** * \brief Class to represent binary value (array of bytes) * \note */ class GDCM_EXPORT ByteValue : public Value { public: ByteValue(const char* array = nullptr, VL const &vl = 0): Internal(array, array+vl),Length(vl) { if( vl.IsOdd() ) { gdcmDebugMacro( "Odd length" ); Internal.resize(vl+1); Length++; } } /// \warning casting to uint32_t ByteValue(std::vector &v):Internal(v),Length((uint32_t)v.size()) {} //ByteValue(std::ostringstream const &os) { // (void)os; // assert(0); // TODO //} ~ByteValue() override { Internal.clear(); } // When 'dumping' dicom file we still have some information from // Either the VR: eg LO (private tag) void PrintASCII(std::ostream &os, VL maxlength ) const; void PrintHex(std::ostream &os, VL maxlength) const; // Either from Element Number (== 0x0000) void PrintGroupLength(std::ostream &os) { assert( Length == 2 ); (void)os; } bool IsEmpty() const { #if 0 if( Internal.empty() ) assert( Length == 0 ); return Internal.empty(); #else return Length == 0; #endif } VL GetLength() const override { return Length; } VL ComputeLength() const { return Length + Length % 2; } // Does a reallocation void SetLength(VL vl) override; operator const std::vector& () const { return Internal; } ByteValue &operator=(const ByteValue &val) { Internal = val.Internal; Length = val.Length; return *this; } bool operator==(const ByteValue &val) const { if( Length != val.Length ) return false; if( Internal == val.Internal ) return true; return false; } bool operator==(const Value &val) const override { const ByteValue &bv = dynamic_cast(val); return Length == bv.Length && Internal == bv.Internal; } void Append(ByteValue const & bv); void Clear() override { Internal.clear(); } // Use that only if you understand what you are doing const char *GetPointer() const { if(!Internal.empty()) return &Internal[0]; return nullptr; } // Use that only if you really understand what you are doing const void *GetVoidPointer() const { if(!Internal.empty()) return &Internal[0]; return nullptr; } void *GetVoidPointer() { if(!Internal.empty()) return &Internal[0]; return nullptr; } void Fill(char c) { //if( Internal.empty() ) return; std::vector::iterator it = Internal.begin(); for(; it != Internal.end(); ++it) *it = c; } bool GetBuffer(char *buffer, unsigned long length) const; bool WriteBuffer(std::ostream &os) const { if( Length ) { //assert( Internal.size() <= Length ); assert( !(Internal.size() % 2) ); os.write(&Internal[0], Internal.size() ); } return true; } template std::istream &Read(std::istream &is, bool readvalues = true) { // If Length is odd we have detected that in SetLength // and calling std::vector::resize make sure to allocate *AND* // initialize values to 0 so we are sure to have a \0 at the end // even in this case if(Length) { if( readvalues ) { is.read(&Internal[0], Length); assert( Internal.size() == Length || Internal.size() == Length + 1 ); TSwap::SwapArray((TType*)GetVoidPointer(), Internal.size() / sizeof(TType) ); } else { is.seekg(Length, std::ios::cur); } } return is; } template std::istream &Read(std::istream &is) { return Read(is); } template std::ostream const &Write(std::ostream &os) const { assert( !(Internal.size() % 2) ); if( !Internal.empty() ) { //os.write(&Internal[0], Internal.size()); std::vector copy = Internal; TSwap::SwapArray((TType*)(void*)©[0], Internal.size() / sizeof(TType) ); os.write(©[0], copy.size()); } return os; } template std::ostream const &Write(std::ostream &os) const { return Write(os); } /** * \brief Checks whether a 'ByteValue' is printable or not (in order * to avoid corrupting the terminal of invocation when printing) * I don't think this function is working since it does not handle * UNICODE or character set... */ bool IsPrintable(VL length) const { assert( length <= Length ); for(unsigned int i=0; i::size_type length = Length; if( Internal.back() == 0 ) --length; std::copy(Internal.begin(), Internal.begin()+length, std::ostream_iterator(os)); } else os << "Loaded:" << Internal.size(); } else { //os << "Not Loaded"; os << "(no value available)"; } } /* //Introduce check for invalid XML characters friend std::ostream& operator<<(std::ostream &os,const char c); */ void SetLengthOnly(VL vl) override { Length = vl; } private: std::vector Internal; // WARNING Length IS NOT Internal.size() some *featured* DICOM // implementation define odd length, we always load them as even number // of byte, so we need to keep the right Length VL Length; }; } // end namespace gdcm_ns #endif //GDCMBYTEVALUE_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmCP246ExplicitDataElement.cxx000066400000000000000000000035551412732066400304020ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCP246ExplicitDataElement.h" #include "gdcmSequenceOfItems.h" #include "gdcmSequenceOfFragments.h" namespace gdcm { //----------------------------------------------------------------------------- VL CP246ExplicitDataElement::GetLength() const { if( ValueLengthField.IsUndefined() ) { assert( ValueField->GetLength().IsUndefined() ); Value *p = ValueField; // If this is a SQ we need to compute it's proper length SequenceOfItems *sq = dynamic_cast(p); // TODO can factor the code: if( sq ) { return TagField.GetLength() + VRField.GetLength() + ValueLengthField.GetLength() + sq->ComputeLength(); } SequenceOfFragments *sf = dynamic_cast(p); if( sf ) { assert( VRField & VR::OB_OW ); return TagField.GetLength() + VRField.GetLength() + ValueLengthField.GetLength() + sf->ComputeLength(); } assert(0); return 0; } else { // Each time VR::GetLength() is 2 then Value Length is coded in 2 // 4 then Value Length is coded in 4 assert( !ValueField || ValueField->GetLength() == ValueLengthField ); return TagField.GetLength() + 2*VRField.GetLength() + ValueLengthField; } } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmCP246ExplicitDataElement.h000066400000000000000000000031331412732066400300170ustar00rootroot00000000000000/*========================================================================= 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 GDCMCP246EXPLICITDATAELEMENT_H #define GDCMCP246EXPLICITDATAELEMENT_H #include "gdcmDataElement.h" 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 */ class GDCM_EXPORT CP246ExplicitDataElement : public DataElement { public: VL GetLength() const; template std::istream &Read(std::istream &is); template std::istream &ReadPreValue(std::istream &is); template std::istream &ReadValue(std::istream &is, bool readvalues = true); template std::istream &ReadWithLength(std::istream &is, VL & length); // PURPOSELY do not provide an implementation for writing ! //template //const std::ostream &Write(std::ostream &os) const; }; } // end namespace gdcm #include "gdcmCP246ExplicitDataElement.txx" #endif //GDCMCP246EXPLICITDATAELEMENT_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmCP246ExplicitDataElement.txx000066400000000000000000000150171412732066400304170ustar00rootroot00000000000000/*========================================================================= 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 GDCMCP246EXPLICITDATAELEMENT_TXX #define GDCMCP246EXPLICITDATAELEMENT_TXX #include "gdcmSequenceOfItems.h" #include "gdcmSequenceOfFragments.h" #include "gdcmVL.h" #include "gdcmParseException.h" #include "gdcmImplicitDataElement.h" #include "gdcmValueIO.h" #include "gdcmSwapper.h" namespace gdcm { //----------------------------------------------------------------------------- template std::istream &CP246ExplicitDataElement::Read(std::istream &is) { ReadPreValue(is); return ReadValue(is); } //----------------------------------------------------------------------------- template std::istream &CP246ExplicitDataElement::ReadPreValue(std::istream &is) { TagField.Read(is); // See PS 3.5, Data Element Structure With Explicit VR // Read Tag if( !is ) { if( !is.eof() ) // FIXME This should not be needed { assert(0 && "Should not happen" ); } return is; } assert( TagField != Tag(0xfffe,0xe0dd) ); const Tag itemDelItem(0xfffe,0xe00d); if( TagField == itemDelItem ) { if( !ValueLengthField.Read(is) ) { assert(0 && "Should not happen"); return is; } if( ValueLengthField != 0 ) { gdcmDebugMacro( "Item Delimitation Item has a length different from 0" ); } // Set pointer to NULL to avoid user error ValueField = nullptr; return is; } // Read VR try { if( !VRField.Read(is) ) { assert(0 && "Should not happen" ); return is; } } catch( std::exception & ) { // gdcm-MR-PHILIPS-16-Multi-Seq.dcm // assert( TagField == Tag(0xfffe, 0xe000) ); // -> For some reason VR is written as {44,0} well I guess this is a VR... // Technically there is a second bug, dcmtk assume other things when reading this tag, // so I need to change this tag too, if I ever want dcmtk to read this file. oh well // 0019004_Baseline_IMG1.dcm // -> VR is garbage also... // assert( TagField == Tag(8348,0339) || TagField == Tag(b5e8,0338)) gdcmWarningMacro( "Assuming 16 bits VR for Tag=" << TagField << " in order to read a buggy DICOM file." ); VRField = VR::INVALID; } // Read Value Length if( VR::GetLength(VRField) == 4 ) { if( !ValueLengthField.Read(is) ) { assert(0 && "Should not happen"); return is; } } else { // 16bits only if( !ValueLengthField.template Read16(is) ) { //gdcmAssertAlwaysMacro(0 && "Should not happen"); // The following is occurs with gdcm 2.0.17 when two // seq del item marker are found // See UnexpectedSequenceDelimiterInFixedLengthSequence.dcm throw Exception("Should not happen CP246"); return is; } } return is; } //----------------------------------------------------------------------------- template std::istream &CP246ExplicitDataElement::ReadValue(std::istream &is, bool readvalues) { if( is.eof() ) return is; if( ValueLengthField == 0 ) { // Simple fast path ValueField = nullptr; return is; } //std::cerr << "exp cur tag=" << TagField << " VR=" << VRField << " VL=" << ValueLengthField << std::endl; // Read the Value //assert( ValueField == 0 ); if( VRField == VR::SQ ) { // Check whether or not this is an undefined length sequence assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new SequenceOfItems; } else if( ValueLengthField.IsUndefined() ) { if( VRField == VR::UN ) { // Support cp246 conforming file: // Enhanced_MR_Image_Storage_PixelSpacingNotIn_0028_0030.dcm (illegal) // vs // undefined_length_un_vr.dcm assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new SequenceOfItems; ValueField->SetLength(ValueLengthField); // perform realloc try { if( !ValueIO::Read(is,*ValueField,readvalues) ) // non cp246 { assert(0); } } catch( std::exception &) { // Must be one of those non-cp246 file... // but for some reason seekg back to previous offset + Read // as CP246Explicit does not work... ParseException pe; pe.SetLastElement(*this); throw pe; } return is; } else { // Ok this is Pixel Data fragmented... assert( TagField == Tag(0x7fe0,0x0010) ); assert( VRField & VR::OB_OW ); ValueField = new SequenceOfFragments; } } else { //assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new ByteValue; } // We have the length we should be able to read the value ValueField->SetLength(ValueLengthField); // perform realloc #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( TagField == Tag(0x2001,0xe05f) || TagField == Tag(0x2001,0xe100) || TagField == Tag(0x2005,0xe080) || TagField == Tag(0x2005,0xe083) || TagField == Tag(0x2005,0xe084) //TagField.IsPrivate() && VRField == VR::SQ //-> Does not work for 0029 //we really need to read item marker ) { gdcmWarningMacro( "ByteSwaping Private SQ: " << TagField ); assert( VRField == VR::SQ ); try { if( !ValueIO::Read(is,*ValueField,readvalues) ) { assert(0 && "Should not happen"); } } catch( std::exception & ) { ValueLengthField = ValueField->GetLength(); } return is; } #endif //if( !ValueField->Read(is) ) if( !ValueIO::Read(is,*ValueField,readvalues) ) { // Might be the famous UN 16bits ParseException pe; pe.SetLastElement( *this ); throw pe; return is; } return is; } template std::istream &CP246ExplicitDataElement::ReadWithLength(std::istream &is, VL & length) { (void)length; return Read(is); } } // end namespace gdcm #endif // GDCMCP246EXPLICITDATAELEMENT_TXX GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmCSAElement.h000066400000000000000000000107721412732066400254020ustar00rootroot00000000000000/*========================================================================= 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 GDCMCSAELEMENT_H #define GDCMCSAELEMENT_H #include "gdcmTag.h" #include "gdcmVM.h" #include "gdcmVR.h" #include "gdcmByteValue.h" #include "gdcmSmartPointer.h" namespace gdcm { /** * \brief Class to represent a CSA Element * \see CSAHeader */ class GDCM_EXPORT CSAElement { public: CSAElement(unsigned int kf = 0):KeyField(kf) {} friend std::ostream& operator<<(std::ostream &os, const CSAElement &val); /// Set/Get Key unsigned int GetKey() const { return KeyField; } void SetKey(unsigned int key) { KeyField = key; } /// Set/Get Name const char *GetName() const { return NameField.c_str(); } void SetName(const char *name) { NameField = name; } /// Set/Get VM const VM& GetVM() const { return ValueMultiplicityField; } void SetVM(const VM &vm) { ValueMultiplicityField = vm; } /// Set/Get VR VR const &GetVR() const { return VRField; } void SetVR(VR const &vr) { VRField = vr; } /// Set/Get SyngoDT unsigned int GetSyngoDT() const { return SyngoDTField; } void SetSyngoDT(unsigned int syngodt) { SyngoDTField = syngodt; } /// Set/Get NoOfItems unsigned int GetNoOfItems() const { return NoOfItemsField; } void SetNoOfItems(unsigned int items) { NoOfItemsField = items; } /// Set/Get Value (bytes array, SQ of items, SQ of fragments): Value const &GetValue() const { return *DataField; } Value &GetValue() { return *DataField; } void SetValue(Value const & vl) { //assert( DataField == 0 ); DataField = vl; } /// Check if CSA Element is empty bool IsEmpty() const { return DataField == nullptr; } /// Set void SetByteValue(const char *array, VL length) { ByteValue *bv = new ByteValue(array,length); SetValue( *bv ); } /// Return the Value of CSAElement as a ByteValue (if possible) /// \warning: You need to check for NULL return value const ByteValue* GetByteValue() const { // Get the raw pointer from the gdcm::SmartPointer const ByteValue *bv = dynamic_cast(DataField.GetPointer()); return bv; // Will return NULL if not ByteValue } CSAElement(const CSAElement &_val) { if( this != &_val) { *this = _val; } } bool operator<(const CSAElement &de) const { return GetKey() < de.GetKey(); } CSAElement &operator=(const CSAElement &de) = default; bool operator==(const CSAElement &de) const { return KeyField == de.KeyField && NameField == de.NameField && ValueMultiplicityField == de.ValueMultiplicityField && VRField == de.VRField && SyngoDTField == de.SyngoDTField //&& ValueField == de.ValueField; ; } protected: unsigned int KeyField; std::string NameField; VM ValueMultiplicityField; VR VRField; unsigned int SyngoDTField; unsigned int NoOfItemsField; typedef SmartPointer DataPtr; DataPtr DataField; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const CSAElement &val) { os << val.KeyField; os << " - '" << val.NameField; os << "' VM " << val.ValueMultiplicityField; os << ", VR " << val.VRField; os << ", SyngoDT " << val.SyngoDTField; os << ", NoOfItems " << val.NoOfItemsField; os << ", Data "; if( val.DataField ) { //val.DataField->Print( os << "'" ); const ByteValue * bv = dynamic_cast(&*val.DataField); assert( bv ); const char * p = bv->GetPointer(); std::string str(p, p + bv->GetLength() ); if( val.ValueMultiplicityField == VM::VM1 ) { os << "'" << str.c_str() << "'"; } else { std::istringstream is( str ); std::string s; bool sep = false; while( std::getline(is, s, '\\' ) ) { if( sep ) { os << '\\'; } sep = true; os << "'" << s.c_str() << "'"; } //bv->Print( os << "'" ); //os << "'"; } } return os; } } // end namespace gdcm #endif //GDCMCSAELEMENT_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.cxx000066400000000000000000001451241412732066400255540ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCSAHeader.h" #include "gdcmPrivateTag.h" #include "gdcmDataElement.h" #include "gdcmCSAElement.h" #include "gdcmDataSet.h" #include "gdcmExplicitDataElement.h" #include "gdcmSwapper.h" namespace gdcm { CSAElement CSAHeader::CSAEEnd = CSAElement((unsigned int)-1); const CSAElement& CSAHeader::GetCSAEEnd() const { return CSAEEnd; } /* * (0029,1110) OB 53\54\45\50\3b\0a... # 5342,1 MedCom OOG Info * -> MEDCOM Object Oriented Graphics (OOG) data. * I think this is the STEP-File, aka ISO standard (10303) * http://sourceforge.net/projects/stepmod * * $ ./bin/gdcmraw -i MR-SIEMENS-DICOM-WithOverlays.dcm -t 0029,1110 -o 0029_1110.raw * $ gvim 0029_1110.raw STEP; HEADER; FILE_IDENTIFICATION( '', 'Wed Nov 30 15:11:24 2005', ('meduser'), (''), '1.0', '1.0', 'Exchangeboard'); FILE_DESCRIPTION('STEP format'); IMP_LEVEL('1.0'); ENDSEC; DATA; @329 = CsaGraDoubleVec3DArray(0, ()); @331 = CsaGraDoubleVec3DArray(0, (69.0, 246.0, 0.0, 67.0, 245.0, 0.0, 66.0, 244.0, 0.0, 64.0, 244.0, 0.0, 62.0, 243.0, 0.0, 61.0, 243.0, 0.0, 59.0, 243.0, 0.0, 57.0, 243.0, 0.0, 56.0, 243.0, 0.0, 55.0, 243.0, 0.0, 53.0, 243.0, 0.0, 52.0, 243.0, 0.0, 51.0, 243.0, 0.0, 50.0, 243.0, 0.0, 49.0, 243.0, 0.0, 48.0, 243.0, 0.0, 48.0, 244.0, 0.0, 47.0, 244.0, 0.0, 46.0, 245.0, 0.0, 46.0, 247.0, 0.0, 46.0, 248.0, 0.0, 46.0, 249.0, 0.0, 46.0, 250.0, 0.0, 46.0, 251.0, 0.0, 46.0, 252.0, 0.0, 46.0, 253.0, 0.0, 46.0, 255.0, 0.0, 46.0, 257.0, 0.0, 47.0, 258.0, 0.0, 47.0, 259.0, 0.0, 48.0, 261.0, 0.0, 49.0, 261.0, 0.0, 50.0, 263.0, 0.0, 50.0, 264.0, 0.0, 51.0, 266.0, 0.0, 53.0, 267.0, 0.0, 54.0, 268.0, 0.0, 55.0, 270.0, 0.0, 56.0, 270.0, 0.0, 56.0, 271.0, 0.0, 57.0, 271.0, 0.0, 58.0, 271.0, 0.0, 59.0, 272.0, 0.0, 61.0, 272.0, 0.0, 62.0, 272.0, 0.0, 62.0, 273.0, 0.0, 63.0, 273.0, 0.0, 64.0, 273.0, 0.0, 65.0, 273.0, 0.0, 66.0, 273.0, 0.0, 67.0, 273.0, 0.0, 69.0, 273.0, 0.0, 69.0, 272.0, 0.0, 71.0, 271.0, 0.0, 72.0, 270.0, 0.0, 73.0, 269.0, 0.0, 73.0, 268.0, 0.0, 73.0, 267.0, 0.0, 74.0, 267.0, 0.0, 75.0, 266.0, 0.0, 75.0, 265.0, 0.0, 76.0, 265.0, 0.0, 77.0, 263.0, 0.0, 77.0, 261.0, 0.0, 78.0, 261.0, 0.0, 78.0, 259.0, 0.0, 78.0, 258.0, 0.0, 79.0, 257.0, 0.0, 79.0, 256.0, 0.0, 80.0, 256.0, 0.0, 80.0, 255.0, 0.0, 80.0, 254.0, 0.0, 80.0, 253.0, 0.0, 80.0, 252.0, 0.0, 80.0, 251.0, 0.0, 80.0, 250.0, 0.0, 79.0, 248.0, 0.0, 77.0, 247.0, 0.0, 77.0, 246.0, 0.0, 77.0, 245.0, 0.0, 77.0, 244.0, 0.0, 75.0, 244.0, 0.0, 75.0, 243.0, 0.0, 74.0, 242.0, 0.0, 73.0, 242.0, 0.0, 72.0, 241.0, 0.0, 71.0, 240.0, 0.0, 71.0, 239.0, 0.0, 70.0, 239.0, 0.0, 69.0, 239.0, 0.0, 68.0, 239.0, 0.0, 66.0, 239.0, 0.0, 64.0, 239.0, 0.0, 63.0, 239.0, 0.0, 64.0, 242.0, 0.0)); @333 = CsaImageOverlay(0, (), (), '', 0, 0, 0, $, (), (), (), (), (), (#332), 0, 0, (), '', '', (), '', (), 0, 0, $, 0, 0.0, 0.0, (), '', 0, 0, 'CAP_3D_MEANING', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, ); @332 = CsaGraphicPrimGroup(0, 0, 0, 0, 0.0, 0, #329, 1, 1, 0, 0, $, #333, $, $, $, (#330)); @335 = CsaUVString(0, (67, 111, 110, 116, 111, 117, 114, 77, 97, 110, 105, 112, 49, 54, 56, 49, 55, 100, 101, 48, 45, 97, 50, 48, 102, 45, 52, 50, 102, 99, 45, 97, 102, 102, 49, 45, 48, 55, 99, 49, 99, 51, 54, 48, 57, 102, 56, 102, 0)); @336 = CsaGraphicFrameApplContainer(0, (), 0); @334 = CsaGraVVIDictionary(0, (#335), (#336), (-1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), (-1)); @330 = CsaGraphicPolygon(0, 0, 0, 0, 0.0, 0, #331, 0, 1, 0, 0, #332, $, #334, $, $, 0, 63.0, 256.0, 0.0, 0, 0, 0, 0, 0, 65535, 1.0, 0.0, 1.0, 0.0, 0, 0.29899999999999999, 0.58699999999999997, 0.114, 0, 65535, 0.0, 0.0, 0.0, 0.0, 0, 0.29899999999999999, 0.58699999999999997, 0.114, 1, 0, '', 1, 0, 0, 0, 65535, 1.0, 1.0, 1.0, 0.0, 0, 0.29899999999999999, 0.58699999999999997, 0.114, 0, 65535, 0.0, 0.0, 0.0, 0.0, 0, 0.29899999999999999, 0.58699999999999997, 0.114, 2, $, $, 1); @337 = CsaGraDoubleVec3DArray(0, ()); @339 = CsaGraDoubleVec3DArray(0, (0.84375, 0.84375, 0.0)); @341 = CsaImageOverlay(0, (), (), '', 0, 0, 0, $, (), (), (), (), (), (#340), 0, 0, (), '', '', (), '', (), 0, 0, $, 0, 0.0, 0.0, (), '', 0, 0, 'CAP_3D_MEANING', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, ); @343 = CsaGraDoubleVec3DArray(0, (0.90234375, 0.29296875, 0.0)); @345 = CsaUVString(0, (68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 77, 97, 110, 105, 112, 35, 51, 95, 48, 98, 51, 57, 97, 54, 98, 53, 51, 45, 56, 53, 97, 50, 45, 52, 54, 102, 48, 45, 56, 99, 49, 52, 45, 97, 55, 102, 48, 51, 99, 100, 48, 53, 51, 56, 99, 0)); @346 = CsaGraphicFrameApplContainer(0, (), 0); @344 = CsaGraVVIDictionary(0, (#345), (#346), (-1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1), (-1)); @342 = CsaGraphicText(0, 0, 0, 0, 0.0, 0, #343, 4, 1, 1, 1, #340, $, #344, $, $, 0, 0.0, 0.0, 0.0, 0, 0, 0, 0, 65535, 1.0, 1.0, 1.0, 0.0, 0, 0.29899999999999999, 0.58699999999999997, 0.114, 0, 65535, 0.0, 0.0, 0.0, 0.0, 0, 0.29899999999999999, 0.58699999999999997, 0.114, (84, 114, 97, 0), 1, -1, 0, 100, -16, 0, 0, 0, 400, 0, 0, 0, 0, 3, 2, 1, 34, 77, 77, 105, 110, 99, 104, 111, 32, 102, 111, 114, 32, 83, 105, 101, 109, 101, 110, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2); @340 = CsaGraphicPrimGroup(0, 0, 0, 0, 0.0, 0, #337, 1, 1, 0, 0, $, #341, $, $, $, (#338, #342)); @348 = CsaUVString(0, (79, 114, 105, 101, 110, 116, 73, 110, 100, 105, 35, 51, 95, 48, 56, 54, 97, 100, 54, 52, 102, 50, 45, 50, 56, 49, 55, 45, 52, 102, 102, 50, 45, 57, 56, 52, 100, 45, 55, 49, 49, 101, 54, 55, 99, 52, 48, 53, 56, 57, 0)); @349 = CsaGraphicFrameApplContainer(0, (), 0); @347 = CsaGraVVIDictionary(0, (#348), (#349), (-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1), (-1)); @338 = CsaGraphicCube(0, 0, 0, 0, 0.0, 0, #339, 4, 1, 0, 0, #340, $, #347, $, $, 0, 0.84375, 0.84375, 0.0, 0, 0, 0, 0, 0, 65535, 1.0, 1.0, 0.0, 0.0, 0, 0.29899999999999999, 0.58699999999999997, 0.114, 0, 65535, 0.0, 0.0, 0.0, 0.0, 0, 0.29899999999999999, 0.58699999999999997, 0.114, 1, 0, '', 1, 0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.05859375); ENDSEC; ENDSTEP; 9 */ /* * http://www.enac.northwestern.edu/~tew/archives/2003/02/25/incomplete-dicom-headers/ * http://www.nmr.mgh.harvard.edu/~rudolph/software/vox2ras/download/vox2ras_rsolve.m * http://www.mail-archive.com/freesurfer@nmr.mgh.harvard.edu/msg03409.html * * Pretty good link: * http://www.mmrrcc.upenn.edu/CAMRIS/cfn/dicomhdr.html */ /* * SIEMENS-JPEG-CorruptFragClean.dcm (0029,xx10): * (0000,0005) FD (??) 337.625 # 8,? (1) * (0000,0006) FD (??) 4.665 # 8,? (1) * (0000,0007) SL (??) 955 # 4,? (1) * (0000,0008) SL (??) 200 # 4,? (1) * (0000,000c) FD (??) 4 # 8,? (1) * (0000,000d) SL (??) 2 # 4,? (1) * (0000,0013) SL (??) 337 # 4,? (1) * (0000,0014) SL (??) 0 # 4,? (1) * (0000,0016) SL (??) 50 # 4,? (1) * (0000,0018) SL (??) 672 # 4,? (1) * (0000,001d) LT (??) [N.E.C.K] # 8,? (1) * (0000,001e) FD (??) 160 # 8,? (1) * (0000,001f) FD (??) 0 # 8,? (1) * (0000,0020) FD (??) 3 # 8,? (1) * (0000,0021) SL (??) 1 # 4,? (1) * (0000,0022) SL (??) 11 # 4,? (1) * (0000,0025) SL (??) 8 # 4,? (1) * (0000,0027) FD (??) 60 # 8,? (1) * (0000,0028) SL (??) 292 # 4,? (1) * (0000,0029) SL (??) 0 # 4,? (1) * (0000,002c) SL (??) 200 # 4,? (1) * (0000,002d) SL (??) 0 # 4,? (1) * (0000,002e) SL (??) 0 # 4,? (1) * (0000,002f) FD (??) 1 # 8,? (1) * (ffff,ffff) CS (??) [END! ] # 10,? (1) */ /* Example of (29,10,SIEMENS CSA NON-IMAGE) / 0000,0a01 MlScanProtocol_Begin: 112 MlScanProtocolAttributes_Begin: 112 ActiveEntry: 0 AEC_SlopeObese: 0.33 AEC_SlopeSmall: 0.50 AutoReferenceLinesMode: MlAutoReferenceLinesModeOff BodySizeOld: MlAdult BreathHold: 99.000 BreathingDefault: 15.000 Cardiac: 1 CustomProtocol: 1 Ident: 21003100 Partial: 1 PatientID: "4.0.201300074" PatientName: "DQ" PatientPosition: MlPositionUndefined PreCond4Displ: 65535 ProtocolName: "PETCT_DailyQC" Region: MlPET Service: 0 StudyDescription: "PET^PETCT_DailyQC (Adult)" StudyID: "4.0.311400557" TotalmAs: 139 TotalNoOfScans: 1 CursorPos: 0 MlScanProtocolAttributes_End: 112 PROTOCOL_ENTRY_NO: 1 MlModeEntry_Begin: 112 MlModeEntryAttributes_Begin: 112 AutoRange: MlAutoRangeNone EntrySelected: 1 PatientPositionFoR: MlFaceUpHeadFirst Visible: 1 BodySize: MlAdult ModeEntryUID: 3 MlModeEntryAttributes_End: 112 MlModeScanNotNULL: MlModeScan_Begin: 112 CardioTriggerDelay: "" Comment1: "" Comment1Source: MlInherited Comment2: "" Comment2Source: MlInherited ReconMode: MlReconSliceMode SliceEffective: 5.00 SliceEffectiveTiltCorrected: 5 SlicesPerScan: 16 SpiralPrePostRotation: 1.057 AddScan: 0 AEC_Aref: 600 AEC_AttenuationDataAP: "" AEC_AttenuationDataLat: "" AEC_BeginPos: 68.000 AEC_CurrentDOMmax: 0 AEC_CurrentMean: 0 AEC_CurrentProfileAP: "" AEC_CurrentProfileLat: "" AEC_DoseProfile: "" AEC_EndPos: -127.000 AEC_MDS: "" AEC_PDS: "" AEC_PDSMean: 0 AEC_PositionExceed: 0 AEC_PowerExceed: 0 AEC_Range: -1.9697 AEC_TopoExceed: 0 AECDoseModulationType: MlAutomaticExposureControl AECReferenceMAs: 20 AngleType: MlTubePosLateral ApiId: -1 ASICCont1: 15 ASICCont2: 135 AssignmentTest: 0 AutoFeed: 0 AutoLoad: 0 AutoTilt: 0 AverageRawData: MlAverageRDOff BaseReconRangeBegin: 71.500 BaseReconRangeEnd: -184.500 BeginPos: 71.500 Biopsy: 0 BodyRegion: MlBodyRegionBody Breathing: 18.000 Capacitor: MlCapacitorNotused Cardio: 0 CardioAverage: MlCardioAverageLast3 CardioSyntheticTrigger: 0 Care: MlOff CareDoseType: MlCareDoseAEC CareVisionTableMode: MlTableMoveContinuous CareVisionTableStep: 2.5 Clustered: 0 ClusteredUsed: 0 Contrast: 0 CoolingTime: 0.000 CTDIw: 7.8 CTDIwEffective: 7.8 Current: 250 CurrentCorrection: 1.25 CurrentEffective: 250 CurrentPeak: 250 CurrentStd: 200 CustomMAs: 100 CycleTime: 0.000 CycleTimeMin: 0.000 CycleTimeUser: 0.000 DASCont1: 79 DASCont2: 0 DestinationRequestID: "ct48501---------------------20071113-071740-0021-1044D480-00000" DiscCheckSource: MlDiscCheckNone Displayed: 1 DLPEffective: 157.56 DoseModulationType: MlNoModulation ECGPulsing: MlOff EffectiveMAs: 100 EndPos: -130.500 FeedLastScan: 0.0 FeedScan: 0.0 Focus: MlSmallFocus FrameOfReferenceUID: "1.3.12.2.1107.5.1.4.48501.30000007111306074039000000021" FuseBolusModes: 0 GantryRotating: 1 HandCare: MlNone InterPosHori: 71.500 InterPosTilt: 0.0 IrsAcceptsMissingTables: 0 KeepFBAD: 0 Kind: MlSpiral mAs: 100 MasterAdjustOrTestNumber: 0 MasterAsymmetricStartAngle: 0 MasterCombActive: 0 MasterCompensatorActive: 1 MasterDataTransfer: 1 MasterDose: 1755 MasterDoseAmplification: 0 MasterDoseControl: 1 MasterDynamicFocusDeflection: 0 MasterFilament: 1 MasterFilamentCurrent: 7016 MasterFixedReadings: 0 MasterFocusAmplitude: 0 MasterFocusDelay: 0 MasterFocusOffset: -7 MasterGantryDisplay: 1 MasterGantryRotation: 1 MasterIgnoreTubeArcing: 1 MasterIntegrationMode: 4 MasterIntegrationTime: 431 MasterITControl: 0 MasterLateralPosition: 0 MasterLightMarkerInScanExecute: 0 MasterMoveAllowedInScanExecute: 0 MasterPhiControl: 1 MasterRotAnodeFrequency: 50 MasterRotAnodeFrequencyChanged: 1 MasterRotatingAnode: 1 MasterSyntheticTrigger: 0 MasterTestPattern: 0 MasterTubeCollimatorMovement: 1 MasterTubeCurrent: 199 MasterTubeVoltage: 120000 MasterUseNominalValues: 1 MasterUseStartAngle: 0 MasterXray: 1 MasterZControl: 1 MasterZControlDynamic: 0 MBH: 0 MultiScanTime: 1.000 NoOfClustersPerRange: 1 NoOfScans: 1 NoOfScansDone: 0 NoOfScansInLastCluster: 0 NoOfScansPerCluster: 1 NoOfSlicesAfterPrep: 16 NoOfSlicesDetector: 16 NoOfSlicesPrep: 16 OfflineReconstruction: 1 OrganCharacteristicOverride: MlOff OrganCharacteristics: MlOrgCharThorax Pitch: 20.0 PitchFactor: 1.2500000 PitchLowerLimit: 7.0 PitchUpperLimit: 8.0 Power: 30000 PreLoad: 0 ProcessSteps: 4294967295 ProspectiveDoseSaving: 0 RangeName: "CT" RangeStart: MlRangeStartConsole RawDataFile: "0001_RCT" RawDataLoid: "4.0.311407191" Readings: 15150 ReconRangeBeginPos: 51.500 ReconRangeBeginTime: 0.000 ReconRangeEndPos: -110.500 ReconRangeEndTime: 0.000 ReconRangeFirstImageTime: "0" ReconRangeLastImageTime: "0" RevolAngle: 360 RotKind: MlRotNormal RotNum: 13.029 RotTime: 0.500 RPP: MlRpp1 ScanLabel: "" ScanNumber: 1 ScanState: MlStateScanned ScanTime: 6.530 ScanTrigger: MlScanTriggerAuto SequenceGap: 0.0 SequenceReconRangeEndPos: 142.000 SequenceRotTime: 0.500 SequenceScanTime: 0.750 Serio: 0 SliceDetector: 0.75 SliceGain: 0.000 SlicePhysical: 0.75 SliceSelect: 128 SourceRequestID: "" SpecialMeas: MlSpecialMeasNone SpiralFeedRot: 15.0 SpiralLength: 162.0 SpiralReconRangeEndPos: -110.500 SpiralRotTime: 0.500 SpiralScanTime: 6.530 StartAngleNumber: 90.0 StartDelay: 4.000 StartDelayCalc: 2.000 StartDelayUser: 4.000 StaticRotTime: 0.500 StaticTime: 1.000 TableDirection: MlIn TableDirectionPatient: MlCraniocaudal TiltPos: 0.0 TopoLength: 0.0 TopoLengthList: 512.0 TopoLoid: "4.0.311400561" TopoReconRangeEndPos: 142.000 TopoScanTime: 0.000 TubeCollimator: 5100 TubeCollimatorClosed: 0 TubeNotify: 0 TubePosition: 0.0 UHR: MlOff UseAdjustAirCal: 0 UseAdjustBeamHard: 0 UseMasterGeneratorSettings: 0 VertPos: 106.0 VertPosValid: 1 Voltage: 120.000 MlModeScan_End: 112 First_MlModeRecon_Is_NULL: No_Of_Valid_Recons: 1 MlModeRecon_Begin: 112 CardioTriggerDelay: "" Comment1: "" Comment1Source: MlInherited Comment2: "" Comment2Source: MlInherited ReconMode: MlReconSliceMode SliceEffective: 5.00 SliceEffectiveTiltCorrected: 5 SlicesPerScan: 16 SpiralPrePostRotation: 1.057 AdaptFilter: 1 Algorithm: MlSlim AutoRecon: 0 AutoReferenceLinesActive: MlOff Balancing: 1 BalancingSteps: 5 BodyPartExamined: "CHEST" CardioBiPhase: 1 CardioListOfEditSyncs: "" CardioListOfTimeStamps: "" CardioMultiPhase: 0 CardioMultiPhaseTriggerDelay: "" CardioNoOfMultiPhase: 0 CardioNoOfTimeStampLists: "0" CardioReadyForRecon: 0 CareViewHead: MlLeft CenterX: 0 CenterY: 0 CrossSectionChanged: 0 CTScale: MlCTScaleStandard ExtendedFOV: 1 FilmImageInterval: 1 Filming: 0 FirstReconSlice: 0 FOV: 0 FoVHorLength: 700 FoVHorVec: 1.000;0.000;0.000 FoVVertLength: 700 FoVVertVec: 0.000;1.000;0.000 FuseModesP30: 1 ImaDisplay: 1 ImageMatrix: 512 ImageOrder: MlIO_Craniocaudal ImageReconType: MlPrimary ImaStore: 1 IRSReconTime: 6.999 Kernel: "B30f medium smooth" MCA: 0 Mirror: MlMirrorNone ModeReconJMUID: "" ModeReconUID: 4 MPPSDescription: "" MultiReconIncr: 1.000 NonLinearLookUpTable: 0 NoOfImages: 33 NoOfImagesEntryDone: 0 Obese: 1 OnlineReconPossible: 1 ORAFilter: 0 OrganFoV: 380 PFO: MlOff PostProcessingCommand: "NON" PostProcessingID: "Ml3DNone" ReconBeginPos: 0.000 ReconBeginTime: 0.000 ReconBeginVec: 0.000;0.000;51.500 ReconDirection: MlAxial ReconEndPos: 0.000 ReconEndTime: 0.000 ReconEndVec: 0.000;0.000;-110.500 ReconIncrementManualChange: MlUnchanged ReconKind: MlMetroRecon ReconLabel: "" ReconPriority: 0 ReconSelected: 1 ReconState: MlReconStateActive ReconStateJM: MlReconStateJMCreated ReconstructionVolumeBeginVec: 0.000;0.000;0.000 ReconstructionVolumeEndVec: 0.000;0.000;0.000 ReconTaskNumber: 1 ReconType: MlAxialRJ ReferenceSeriesLoid: "" Resolution: ResModeUltraFast SeriesDescription: "CT 5.0 eFoV " SeriesLoid: "" SeriesLoidKind: MlSeriesNew SpiralBaseFunction: MlSpiralBaseTrapezium06 SpiralPrePostLengthCorrection: 0.000 SpiralReconIncr: 5.000 ToBeReconBeginPos: 0.000 ToBeReconBeginTime: 0.000 ToBeReconBeginVec: 0.000;0.000;51.500 ToBeReconEndPos: 0.000 ToBeReconEndTime: 0.000 ToBeReconEndVec: 0.000;0.000;-110.500 TopoZoom: 1 Transfer: MlOff Transfer1: "" Transfer2: "" Transfer3: "" Ui3DViewCurrentPlanningVolumeLoid: "" Ui3DViewCutlineDirectionVec: 0.000;0.000;0.000 Ui3DViewFoVSegmentIndex: 0 Ui3DViewPanX: 0.000;0.000;0.000 Ui3DViewPanY: 0.000;0.000;0.000 Ui3DViewPivotVec: 0.000;0.000;0.000 Ui3DViewPVImageType: MlMPR Ui3DViewTopographicsSegmentIndex: 0 Ui3DViewTransformationVec1: 0.000;0.000;0.000 Ui3DViewTransformationVec2: 0.000;0.000;0.000 Ui3DViewWindowCenter1: 40.000;40.000;40.000 Ui3DViewWindowCenter2: 40.000;40.000;40.000 Ui3DViewWindowWidth1: 400.000;400.000;400.000 Ui3DViewWindowWidth2: 400.000;400.000;400.000 Ui3DViewZoomX: 1.000;1.000;1.000 Ui3DViewZoomY: 1.000;1.000;1.000 Viewing: MlOff ViewingDirection: MlIO_Craniocaudal Window[READ_ONLY]: "Mediastinum" Window.ResID: 33 Window1Center: 40 Window1Width: 400 Window2Center: -600 Window2Width: 1200 WindowImageLoid: "" MlModeRecon_End: 112 MlModeEntry_End: 112 MlScanProtocol_End: 112 */ struct DataSetFormatEntry { Tag t; VR vr; }; static DataSetFormatEntry DataSetFormatDict[] = { { Tag(0x0000,0x0004),VR::LT }, { Tag(0x0000,0x0005),VR::FD }, { Tag(0x0000,0x0006),VR::FD }, { Tag(0x0000,0x0007),VR::SL }, { Tag(0x0000,0x0008),VR::SL }, { Tag(0x0000,0x000c),VR::FD }, { Tag(0x0000,0x000d),VR::SL }, { Tag(0x0000,0x000e),VR::SL }, { Tag(0x0000,0x0012),VR::FD }, { Tag(0x0000,0x0013),VR::SL }, { Tag(0x0000,0x0014),VR::SL }, { Tag(0x0000,0x0016),VR::SL }, { Tag(0x0000,0x0018),VR::SL }, { Tag(0x0000,0x001a),VR::SL }, { Tag(0x0000,0x001d),VR::LT }, // Defined Terms: [A.B.D.O.M.E.N], [C.H.E.S.T], [E.X.T.R.E.M.I.T.Y], [H.E.A.D], [N.E.C.K], [P.E.L.V.I.S], [S.P.I.N.E] { Tag(0x0000,0x001e),VR::FD }, { Tag(0x0000,0x001f),VR::FD }, { Tag(0x0000,0x0020),VR::FD }, { Tag(0x0000,0x0021),VR::SL }, { Tag(0x0000,0x0022),VR::SL }, { Tag(0x0000,0x0025),VR::SL }, { Tag(0x0000,0x0026),VR::FD }, { Tag(0x0000,0x0027),VR::FD }, { Tag(0x0000,0x0028),VR::SL }, { Tag(0x0000,0x0029),VR::SL }, { Tag(0x0000,0x002b),VR::LT }, { Tag(0x0000,0x002c),VR::SL }, { Tag(0x0000,0x002d),VR::SL }, { Tag(0x0000,0x002e),VR::SL }, { Tag(0x0000,0x002f),VR::FD }, { Tag(0x0000,0x0030),VR::LT }, { Tag(0x0000,0x0033),VR::SL }, { Tag(0x0000,0x0035),VR::SL }, { Tag(0x0000,0x0036),VR::CS }, { Tag(0x0000,0x0037),VR::SL }, { Tag(0x0000,0x0038),VR::SL }, { Tag(0x0000,0x0039),VR::SL }, { Tag(0x0000,0x003a),VR::FD }, { Tag(0x0000,0x003b),VR::SL }, { Tag(0x0000,0x003c),VR::SL }, { Tag(0x0000,0x003d),VR::FD }, { Tag(0x0000,0x003e),VR::SL }, { Tag(0x0000,0x003f),VR::SL }, { Tag(0x0000,0x0101),VR::FD }, { Tag(0x0000,0x0102),VR::FD }, { Tag(0x0000,0x0103),VR::FD }, { Tag(0x0000,0x0105),VR::IS }, { Tag(0x0006,0x0006),VR::FD }, { Tag(0x0006,0x0007),VR::FD }, { Tag(0x0006,0x0008),VR::CS }, { Tag(0x0006,0x000a),VR::LT }, { Tag(0x0006,0x000b),VR::CS }, { Tag(0x0006,0x000c),VR::FD }, { Tag(0x0006,0x000e),VR::CS }, { Tag(0x0006,0x000f),VR::SL }, { Tag(0x0006,0x0024),VR::FD }, { Tag(0xffff,0xffff),VR::CS }, // ENDS! }; /* Apparently tag <-> vr has no relation ... it must be derived from something else (0000,0003) FD 500 # 8, 1 RequestedSOPClassUID (0000,0004) FD 1040 # 8, 1 Unknown Tag & Data (0000,0005) FD 570 # 8, 1 Unknown Tag & Data (0000,0008) LT [0] # 2, 1 Unknown Tag & Data (0000,0010) DT [20071113071752.765000] # 22, 1 ACR_NEMA_CommandRecognitionCode (0000,0020) SL 2 # 4, 1 Unknown Tag & Data (0000,0025) FD (no value available) # 0, 0 Unknown Tag & Data (0000,0026) FD 0.7 # 8, 1 Unknown Tag & Data (0000,0028) ?? (no value available) # 0, 1 Unknown Tag & Data (0000,0030) SL 30 # 4, 1 Unknown Tag & Data (0000,0040) LT [C] # 4, 1 Unknown Tag & Data (0000,0a01) ?? 4d\6c\53\63\61\6e\50\72\6f\74\6f\63\6f\6c\5f\42\65\67\69\6e\3a\09... # 8788, 1 Unknown Tag & Data (0000,fe10) CS [SCANPROT] # 10, 1 Unknown Tag & Data (ffff,ffff) CS [END!] # 10, 1 Unknown Tag & Data */ VR GetVRFromDataSetFormatDict( const Tag& t ) { static const unsigned int nentries = sizeof(DataSetFormatDict) / sizeof(*DataSetFormatDict); VR ret = VR::VR_END; //static const Tag tend = Tag(0xffff,0xffff); for( unsigned int i = 0; i < nentries; ++i) { const DataSetFormatEntry &entry = DataSetFormatDict[i]; if( entry.t == t ) { ret = entry.vr; break; } } return ret; } /* * http://www.healthcare.siemens.com/magnetom/phoenix-gallery/orthopedics/images/phoenix/29642762.ima Image shadow data (0029,xx10) 0 - 'EchoLinePosition' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '427 ' 1 - 'EchoColumnPosition' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '224 ' 2 - 'EchoPartitionPosition' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '8 ' 3 - 'UsedChannelMask' VM 1, VR UL, SyngoDT 9, NoOfItems 6, Data '63 ' 4 - 'Actual3DImaPartNumber' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 5 - 'ICE_Dims' VM 1, VR LO, SyngoDT 19, NoOfItems 6, Data 'X_1_1_1_1_1_1_1_1_1_1_1_41' 6 - 'B_value' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 7 - 'Filter1' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 8 - 'Filter2' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 9 - 'ProtocolSliceNumber' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '6 ' 10 - 'RealDwellTime' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '8600 ' 11 - 'PixelFile' VM 1, VR UN, SyngoDT 0, NoOfItems 0, Data 12 - 'PixelFileName' VM 1, VR UN, SyngoDT 0, NoOfItems 0, Data 13 - 'SliceMeasurementDuration' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '338142.50000000' 14 - 'SequenceMask' VM 1, VR UL, SyngoDT 9, NoOfItems 6, Data '134217728' 15 - 'AcquisitionMatrixText' VM 1, VR SH, SyngoDT 22, NoOfItems 6, Data '421*448s' 16 - 'MeasuredFourierLines' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '0 ' 17 - 'FlowEncodingDirection' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 18 - 'FlowVenc' VM 1, VR FD, SyngoDT 4, NoOfItems 0, Data 19 - 'PhaseEncodingDirectionPositive' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '1 ' 20 - 'NumberOfImagesInMosaic' VM 1, VR US, SyngoDT 10, NoOfItems 0, Data 21 - 'DiffusionGradientDirection' VM 3, VR FD, SyngoDT 4, NoOfItems 0, Data 22 - 'ImageGroup' VM 1, VR US, SyngoDT 10, NoOfItems 0, Data 23 - 'SliceNormalVector' VM 3, VR FD, SyngoDT 4, NoOfItems 0, Data 24 - 'DiffusionDirectionality' VM 1, VR CS, SyngoDT 16, NoOfItems 0, Data 25 - 'TimeAfterStart' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '0.00000000' 26 - 'FlipAngle' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 27 - 'SequenceName' VM 1, VR SH, SyngoDT 22, NoOfItems 0, Data 28 - 'RepetitionTime' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 29 - 'EchoTime' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 30 - 'NumberOfAverages' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 31 - 'VoxelThickness' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 32 - 'VoxelPhaseFOV' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 33 - 'VoxelReadoutFOV' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 34 - 'VoxelPositionSag' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 35 - 'VoxelPositionCor' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 36 - 'VoxelPositionTra' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 37 - 'VoxelNormalSag' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 38 - 'VoxelNormalCor' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 39 - 'VoxelNormalTra' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 40 - 'VoxelInPlaneRot' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 41 - 'ImagePositionPatient' VM 3, VR DS, SyngoDT 3, NoOfItems 0, Data 42 - 'ImageOrientationPatient' VM 6, VR DS, SyngoDT 3, NoOfItems 0, Data 43 - 'PixelSpacing' VM 2, VR DS, SyngoDT 3, NoOfItems 0, Data 44 - 'SliceLocation' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 45 - 'SliceThickness' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 46 - 'SpectrumTextRegionLabel' VM 1, VR SH, SyngoDT 22, NoOfItems 0, Data 47 - 'Comp_Algorithm' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 48 - 'Comp_Blended' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 49 - 'Comp_ManualAdjusted' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 50 - 'Comp_AutoParam' VM 1, VR LT, SyngoDT 20, NoOfItems 0, Data 51 - 'Comp_AdjustedParam' VM 1, VR LT, SyngoDT 20, NoOfItems 0, Data 52 - 'Comp_JobID' VM 1, VR LT, SyngoDT 20, NoOfItems 0, Data 53 - 'FMRIStimulInfo' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 54 - 'FlowEncodingDirectionString' VM 1, VR SH, SyngoDT 22, NoOfItems 0, Data 55 - 'RepetitionTimeEffective' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 56 - 'CsiImagePositionPatient' VM 3, VR DS, SyngoDT 3, NoOfItems 0, Data 57 - 'CsiImageOrientationPatient' VM 6, VR DS, SyngoDT 3, NoOfItems 0, Data 58 - 'CsiPixelSpacing' VM 2, VR DS, SyngoDT 3, NoOfItems 0, Data 59 - 'CsiSliceLocation' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 60 - 'CsiSliceThickness' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 61 - 'OriginalSeriesNumber' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 62 - 'OriginalImageNumber' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 63 - 'ImaAbsTablePosition' VM 3, VR SL, SyngoDT 7, NoOfItems 6, Data '0 '\'0 '\'-1952 ' 64 - 'NonPlanarImage' VM 1, VR US, SyngoDT 10, NoOfItems 6, Data '1 ' 65 - 'MoCoQMeasure' VM 1, VR US, SyngoDT 10, NoOfItems 0, Data 66 - 'LQAlgorithm' VM 1, VR SH, SyngoDT 22, NoOfItems 0, Data 67 - 'SlicePosition_PCS' VM 3, VR FD, SyngoDT 4, NoOfItems 6, Data '-47.43732992'\'-135.75159147'\'19.57638496' 68 - 'RBMoCoTrans' VM 3, VR FD, SyngoDT 4, NoOfItems 0, Data 69 - 'RBMoCoRot' VM 3, VR FD, SyngoDT 4, NoOfItems 0, Data 70 - 'MultistepIndex' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '0 ' 71 - 'ImaRelTablePosition' VM 3, VR IS, SyngoDT 6, NoOfItems 6, Data '0 '\'0 '\'39 ' 72 - 'ImaCoilString' VM 1, VR LO, SyngoDT 19, NoOfItems 6, Data 'T:BO1,2' 73 - 'RFSWDDataType' VM 1, VR SH, SyngoDT 22, NoOfItems 6, Data 'measured' 74 - 'GSWDDataType' VM 1, VR SH, SyngoDT 22, NoOfItems 6, Data 'measured' 75 - 'NormalizeManipulated' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 76 - 'ImaPATModeText' VM 1, VR LO, SyngoDT 19, NoOfItems 6, Data 'p2' 77 - 'B_matrix' VM 6, VR FD, SyngoDT 4, NoOfItems 0, Data 78 - 'BandwidthPerPixelPhaseEncode' VM 1, VR FD, SyngoDT 4, NoOfItems 0, Data 79 - 'FMRIStimulLevel' VM 1, VR FD, SyngoDT 4, NoOfItems 0, Data Series shadow data (0029,xx20) 0 - 'UsedPatientWeight' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '72 ' 1 - 'NumberOfPrescans' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '0 ' 2 - 'TransmitterCalibration' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '541.65400000' 3 - 'PhaseGradientAmplitude' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '0.00000000' 4 - 'ReadoutGradientAmplitude' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '0.00000000' 5 - 'SelectionGradientAmplitude' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '0.00000000' 6 - 'GradientDelayTime' VM 3, VR DS, SyngoDT 3, NoOfItems 6, Data '13.00000000'\'14.00000000'\'10.00000000' 7 - 'RfWatchdogMask' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '0 ' 8 - 'RfPowerErrorIndicator' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 9 - 'SarWholeBody' VM 3, VR DS, SyngoDT 3, NoOfItems 0, Data 10 - 'Sed' VM 3, VR DS, SyngoDT 3, NoOfItems 6, Data '1000000.00000000'\'725.84052985'\'725.71234997' 11 - 'SequenceFileOwner' VM 1, VR SH, SyngoDT 22, NoOfItems 6, Data 'SIEMENS' 12 - 'Stim_mon_mode' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '2 ' 13 - 'Operation_mode_flag' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '2 ' 14 - 'dBdt_max' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '0.00000000' 15 - 't_puls_max' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '0.00000000' 16 - 'dBdt_thresh' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '0.00000000' 17 - 'dBdt_limit' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '0.00000000' 18 - 'SW_korr_faktor' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '1.00000000' 19 - 'Stim_max_online' VM 3, VR DS, SyngoDT 3, NoOfItems 6, Data '2.14339137'\'17.54720879'\'0.45053142' 20 - 'Stim_max_ges_norm_online' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '0.63422704' 21 - 'Stim_lim' VM 3, VR DS, SyngoDT 3, NoOfItems 6, Data '45.73709869'\'27.64929962'\'31.94370079' 22 - 'Stim_faktor' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '1.00000000' 23 - 'CoilForGradient' VM 1, VR SH, SyngoDT 22, NoOfItems 6, Data 'void' 24 - 'CoilForGradient2' VM 1, VR SH, SyngoDT 22, NoOfItems 6, Data 'AS092' 25 - 'CoilTuningReflection' VM 2, VR DS, SyngoDT 3, NoOfItems 0, Data 26 - 'CoilId' VM 0, VR IS, SyngoDT 6, NoOfItems 12, Data '255 '\'83 '\'238 '\'238 '\'238 '\'238 '\'238 '\'177 '\'238 '\'178 '\'238 ' 27 - 'MiscSequenceParam' VM 38, VR IS, SyngoDT 6, NoOfItems 42, Data '0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 '\'1086 '\'0 '\'0 '\'0 '\'0 '\'0 '\'0 ' 28 - 'MrProtocolVersion' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '0 ' 29 - 'DataFileName' VM 1, VR LO, SyngoDT 19, NoOfItems 0, Data 30 - 'RepresentativeImage' VM 1, VR UI, SyngoDT 25, NoOfItems 0, Data 31 - 'PositivePCSDirections' VM 1, VR SH, SyngoDT 22, NoOfItems 6, Data '+LPH' 32 - 'RelTablePosition' VM 3, VR IS, SyngoDT 6, NoOfItems 6, Data '0 '\'0 '\'39 ' 33 - 'ReadoutOS' VM 1, VR FD, SyngoDT 4, NoOfItems 6, Data '2.00000000' 34 - 'LongModelName' VM 1, VR LO, SyngoDT 19, NoOfItems 6, Data 'TrioTim' 35 - 'SliceArrayConcatenations' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '1 ' 36 - 'SliceResolution' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '1.00000000' 37 - 'AbsTablePosition' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '-1952 ' 38 - 'AutoAlignMatrix' VM 16, VR FL, SyngoDT 5, NoOfItems 0, Data 39 - 'MeasurementIndex' VM 1, VR FL, SyngoDT 5, NoOfItems 0, Data 40 - 'CoilString' VM 1, VR LO, SyngoDT 19, NoOfItems 6, Data 'T:BO1,2' 41 - 'PATModeText' VM 1, VR LO, SyngoDT 19, NoOfItems 6, Data 'p2' 42 - 'PatReinPattern' VM 1, VR ST, SyngoDT 23, NoOfItems 6, Data '1;HFS;72.00;15.00;2;0;2;-794520928' 43 - 'ProtocolChangeHistory' VM 1, VR US, SyngoDT 10, NoOfItems 6, Data '0 ' 44 - 'Isocentered' VM 1, VR US, SyngoDT 10, NoOfItems 6, Data '1 ' 45 - 'MrPhoenixProtocol' VM 1, VR UN, SyngoDT 0, NoOfItems 6, Data ' <...> 46 - 'GradientMode' VM 1, VR SH, SyngoDT 22, NoOfItems 6, Data 'Fast' 47 - 'FlowCompensation' VM 1, VR SH, SyngoDT 22, NoOfItems 6, Data 'No' 48 - 'PostProcProtocol' VM 1, VR UT, SyngoDT 27, NoOfItems 0, Data 49 - 'RFSWDOperationMode' VM 1, VR SS, SyngoDT 8, NoOfItems 6, Data '+0 ' 50 - 'RFSWDMostCriticalAspect' VM 1, VR SH, SyngoDT 22, NoOfItems 6, Data 'Whole Body' 51 - 'SARMostCriticalAspect' VM 3, VR DS, SyngoDT 3, NoOfItems 6, Data '2.00000000'\'1.02534234'\'0.97963309' 52 - 'TablePositionOrigin' VM 3, VR SL, SyngoDT 7, NoOfItems 6, Data '0 '\'0 '\'-1991 ' 53 - 'MrProtocol' VM 1, VR UN, SyngoDT 0, NoOfItems 0, Data 54 - 'MrEvaProtocol' VM 1, VR UN, SyngoDT 0, NoOfItems 0, Data * * WARNING: I think this is context dependent so 0029,1010 and 0029,1110 are not supposed to mean the same thing, eg: (CSA image data) (0029,0010)siemens csa header Image shadow data (0029,xx10) 0 - 'ImageNumber' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 1 - 'ImageComments' VM 1, VR LT, SyngoDT 20, NoOfItems 0, Data 2 - 'ReferencedImageSequence' VM 0, VR UI, SyngoDT 25, NoOfItems 6, Data '1.2.840.10008.5.1.4.1.1.4'\'1.3.12.2.1107.5.2.30.25299.3.200803181402241188330606'\'1.2.840.10008.5.1.4.1.1.4'\'1.3.12.2.1107.5.2.30.25299.3.2008031814031374741230990'\'1.2.840.10008.5.1.4.1.1.4'\'1.3.12.2.1107.5.2.30.25299.3.200803181402241589130608' 3 - 'PatientOrientation' VM 1, VR CS, SyngoDT 16, NoOfItems 0, Data 4 - 'ScanningSequence' VM 0, VR CS, SyngoDT 16, NoOfItems 6, Data 'RM' 5 - 'SequenceName' VM 1, VR SH, SyngoDT 22, NoOfItems 6, Data 'tfi2d1_20' 6 - 'RepetitionTime' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '29.60000000' 7 - 'EchoTime' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '1.25000000' 8 - 'InversionTime' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 9 - 'NumberOfAverages' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '1.00000000' 10 - 'ImagingFrequency' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '63.61952800' 11 - 'ImagedNucleus' VM 1, VR SH, SyngoDT 22, NoOfItems 6, Data '1H' 12 - 'EchoNumbers' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '1 ' 13 - 'MagneticFieldStrength' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '1.50000000' 14 - 'NumberOfPhaseEncodingSteps' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '100 ' 15 - 'EchoTrainLength' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '1 ' 16 - 'PercentSampling' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '32.00000000' 17 - 'PercentPhaseFieldOfView' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '100.00000000' 18 - 'TriggerTime' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '82.50000000' 19 - 'ReceivingCoil' VM 1, VR SH, SyngoDT 22, NoOfItems 0, Data 20 - 'TransmittingCoil' VM 1, VR SH, SyngoDT 22, NoOfItems 6, Data 'Body' 21 - 'AcquisitionMatrix' VM 4, VR US, SyngoDT 10, NoOfItems 6, Data '256 '\'0 '\'0 '\'82 ' 22 - 'PhaseEncodingDirection' VM 1, VR CS, SyngoDT 16, NoOfItems 6, Data 'COL' 23 - 'FlipAngle' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '20.00000000' 24 - 'VariableFlipAngleFlag' VM 1, VR CS, SyngoDT 16, NoOfItems 6, Data 'N' 25 - 'SAR' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '0.21757985' 26 - 'dBdt' VM 3, VR DS, SyngoDT 3, NoOfItems 6, Data '0.00000000' 27 - 'SliceThickness' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '7.00000000' 28 - 'ImagePositionPatient' VM 3, VR DS, SyngoDT 3, NoOfItems 6, Data '117.38499069'\'-48.94067860'\'0.00000000' 29 - 'ImageOrientationPatient' VM 6, VR DS, SyngoDT 3, NoOfItems 6, Data '-1.00000000'\'0.00000000'\'0.00000000'\'0.00000000'\'1.00000000'\'0.00000000' 30 - 'SliceLocation' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '0.00000000' 31 - 'EchoLinePosition' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '50 ' 32 - 'EchoColumnPosition' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '128 ' 33 - 'EchoPartitionPosition' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '8 ' 34 - 'Actual3DImaPartNumber' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 35 - 'RealDwellTime' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '2300 ' 36 - 'ProtocolSliceNumber' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '0 ' 37 - 'DataFile' VM 1, VR UN, SyngoDT 0, NoOfItems 0, Data 38 - 'DataFileName' VM 1, VR UN, SyngoDT 0, NoOfItems 0, Data 39 - 'ICE_Dims' VM 1, VR LO, SyngoDT 19, NoOfItems 6, Data '1_1_2_1_4_1_1_1_1_1_1_1_259' 40 - 'PixelSpacing' VM 2, VR DS, SyngoDT 3, NoOfItems 6, Data '1.25000000'\'1.25000000' 41 - 'SourceImageSequence' VM 0, VR UI, SyngoDT 25, NoOfItems 0, Data 42 - 'PixelBandwidth' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '850.00000000' 43 - 'SliceMeasurementDuration' VM 1, VR DS, SyngoDT 3, NoOfItems 6, Data '4112.50000000' 44 - 'SequenceMask' VM 1, VR UL, SyngoDT 9, NoOfItems 6, Data '0 ' 45 - 'AcquisitionMatrixText' VM 1, VR SH, SyngoDT 22, NoOfItems 6, Data '82*256s' 46 - 'MeasuredFourierLines' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 47 - 'CsiGridshiftVector' VM 3, VR DS, SyngoDT 3, NoOfItems 0, Data 48 - 'MultistepIndex' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '0 ' 49 - 'SpectroscopyAcquisitionPhaseColumns' VM 1, VR UL, SyngoDT 9, NoOfItems 0, Data 50 - 'SpectroscopyAcquisitionPhaseRows' VM 1, VR UL, SyngoDT 9, NoOfItems 0, Data 51 - 'SpectroscopyAcquisitionOut-of-planePhaseSteps' VM 1, VR UL, SyngoDT 9, NoOfItems 0, Data 52 - 'SpectroscopyAcquisitionDataColumns' VM 1, VR UL, SyngoDT 9, NoOfItems 0, Data 53 - 'DataPointRows' VM 1, VR UL, SyngoDT 9, NoOfItems 0, Data 54 - 'DataPointColumns' VM 1, VR UL, SyngoDT 9, NoOfItems 0, Data 55 - 'DataRepresentation' VM 1, VR CS, SyngoDT 16, NoOfItems 0, Data 56 - 'SignalDomainColumns' VM 1, VR CS, SyngoDT 16, NoOfItems 0, Data 57 - 'Columns' VM 1, VR US, SyngoDT 10, NoOfItems 6, Data '256 ' 58 - 'Rows' VM 1, VR US, SyngoDT 10, NoOfItems 6, Data '100 ' 59 - 'NumberOfFrames' VM 1, VR IS, SyngoDT 6, NoOfItems 0, Data 60 - 'MixingTime' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 61 - 'k-spaceFiltering' VM 1, VR CS, SyngoDT 16, NoOfItems 0, Data 62 - 'HammingFilterWidth' VM 1, VR DS, SyngoDT 3, NoOfItems 0, Data 63 - 'TransmitterReferenceAmplitude' VM 1, VR FD, SyngoDT 4, NoOfItems 0, Data 64 - 'ResonantNucleus' VM 1, VR CS, SyngoDT 16, NoOfItems 0, Data 65 - 'VoiThickness' VM 1, VR FD, SyngoDT 4, NoOfItems 0, Data 66 - 'VoiPhaseFoV' VM 1, VR FD, SyngoDT 4, NoOfItems 0, Data 67 - 'VoiReadoutFoV' VM 1, VR FD, SyngoDT 4, NoOfItems 0, Data 68 - 'VoiOrientation' VM 3, VR FD, SyngoDT 4, NoOfItems 0, Data 69 - 'VoiPosition' VM 3, VR FD, SyngoDT 4, NoOfItems 0, Data 70 - 'VoiInPlaneRotation' VM 1, VR FD, SyngoDT 4, NoOfItems 0, Data 71 - 'RSatThickness' VM 0, VR FD, SyngoDT 4, NoOfItems 0, Data 72 - 'RSatOrientationSag' VM 0, VR FD, SyngoDT 4, NoOfItems 0, Data 73 - 'RSatOrientationCor' VM 0, VR FD, SyngoDT 4, NoOfItems 0, Data 74 - 'RSatOrientationTra' VM 0, VR FD, SyngoDT 4, NoOfItems 0, Data 75 - 'RSatPositionSag' VM 0, VR FD, SyngoDT 4, NoOfItems 0, Data 76 - 'RSatPositionCor' VM 0, VR FD, SyngoDT 4, NoOfItems 0, Data 77 - 'RSatPositionTra' VM 0, VR FD, SyngoDT 4, NoOfItems 0, Data 78 - 'SpacingBetweenSlices' VM 1, VR FD, SyngoDT 4, NoOfItems 0, Data 79 - 'DataSetInfo' VM 1, VR UN, SyngoDT 0, NoOfItems 0, Data 80 - 'ImaCoilString' VM 1, VR LO, SyngoDT 19, NoOfItems 6, Data 'BO1' 81 - 'BandwidthPerPixelPhaseEncode' VM 1, VR FD, SyngoDT 4, NoOfItems 0, Data */ struct equ { uint32_t syngodt; const char vr[2+1]; }; // Looks like there is mapping in between syngodt and vr... // O <=> UN // 3 <=> DS // 4 <=> FD // 5 <=> FL // 6 <=> IS // 9 <=> UL // 10 <=> US // 16 <=> CS // 19 <=> LO // 20 <=> LT // 22 <=> SH // 25 <=> UI static equ mapping[] = { { 0 , "UN" }, { 3 , "DS" }, { 4 , "FD" }, { 5 , "FL" }, { 6 , "IS" }, { 7 , "SL" }, { 8 , "SS" }, { 9 , "UL" }, { 10 , "US" }, { 16 , "CS" }, { 19 , "LO" }, { 20 , "LT" }, { 22 , "SH" }, { 23 , "ST" }, { 25 , "UI" }, { 27 , "UT" } }; bool check_mapping(uint32_t syngodt, const char *vr) { static const unsigned int max = sizeof(mapping) / sizeof(equ); const equ *p = mapping; assert( syngodt <= mapping[max-1].syngodt ); (void)max; while(p->syngodt < syngodt ) { //std::cout << "mapping:" << p->vr << std::endl; ++p; } assert( p->syngodt == syngodt ); // or else need to update mapping const char* lvr = p->vr; int check = strcmp(vr, lvr) == 0; assert( check ); (void)check; return true; } bool checkallzero(std::istream &is) { bool res = true; char c; while( is >> c ) { if( c != 0 ) { res = false; break; } } return res; } CSAHeader::CSAHeaderType CSAHeader::GetFormat() const { return InternalType; } // dcmInfo.exe print like this: // 67 - 'SlicePosition_PCS' VM 3, VR FD, SyngoDT 4, NoOfItems 6, Data '-185.77913332'\'-163.80459213'\'72.73944092' bool CSAHeader::LoadFromDataElement(DataElement const &de) { if( de.IsEmpty() ) return false; InternalCSADataSet.clear(); InternalDataSet.Clear(); gdcmDebugMacro( "Entering print" ); InternalType = UNKNOWN; // reset gdcm::Tag t1(0x0029,0x0010); gdcm::Tag t2(0x0029,0x0020); uint16_t v = (uint16_t)(de.GetTag().GetElement() << 8); uint16_t v2 = (uint16_t)(v >> 8); //if( de.GetTag().GetPrivateCreator() == t1 ) if( v2 == t1.GetElement() ) { //std::cout << "Image shadow data (0029,xx10)\n\n"; DataElementTag = t1; } //else if( de.GetTag().GetPrivateCreator() == t2 ) else if( v2 == t2.GetElement() ) { //std::cout << "Series shadow data (0029,xx20)\n\n"; DataElementTag = t2; } else { // std::cerr << "Unhandled tag: " << de.GetTag() << std::endl; DataElementTag = de.GetTag(); } gdcmDebugMacro( "found type" ); const ByteValue *bv = de.GetByteValue(); assert( bv ); const char *p = bv->GetPointer(); assert( p ); std::string s( bv->GetPointer(), bv->GetLength() ); std::stringstream ss; ss.str( s ); char signature[4+1]; signature[4] = 0; if( !ss.read(signature, 4) ) { gdcmErrorMacro( "Too short" ); return false; } // 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 ); ss.str( s ); ss.read(signature, 4); } //std::cout << signature << std::endl; // 1. NEW FORMAT // 2. OLD FORMAT // 3. Zero out // 4. DATASET FORMAT (Explicit Little Endian), with group=0x0 elements: if( strcmp( signature, "SV10" ) != 0 ) { if( checkallzero(ss) ) { //std::cout << "Zeroed out" << std::endl; InternalType = ZEROED_OUT; return true; } else if( strcmp(signature, "!INT" ) == 0 ) { InternalType = INTERFILE; InterfileData = p; return true; } // cannot use strcmp / strncmp in the following ... doh ! else if( memcmp(signature, "\0\0" , 2 ) == 0 || memcmp(signature, "\6\0" , 2 ) == 0 ) { // Most often start with an element (0000,xxxx) // And ends with element: // (ffff,ffff) CS 10 END! ss.seekg( 0, std::ios::beg ); // SIEMENS-JPEG-CorruptFragClean.dcm InternalType = DATASET_FORMAT; DataSet &ds = InternalDataSet; DataElement xde; try { while( xde.Read( ss ) ) { ds.InsertDataElement( xde ); // Cannot use Insert since Group = 0x0 (< 0x8) //VR refvr = GetVRFromDataSetFormatDict( xde.GetTag() ); //assert( xde.GetVR() == refvr ); } //std::cout << ds << std::endl; assert( ss.eof() ); } catch(std::exception &) { gdcmErrorMacro( "Something went wrong while decoding... please report" ); return false; } return true; } else { //assert(0); ss.seekg( 0, std::ios::beg ); // No magic number for this one: // SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm InternalType = NOMAGIC; } } if( strcmp( signature, "SV10" ) == 0 ) { // NEW FORMAT ! ss.read(signature, 4); assert( strcmp( signature, "\4\3\2\1" ) == 0 ); InternalType = SV10; } assert( InternalType != UNKNOWN ); gdcmDebugMacro( "Found Type: " << (int)InternalType ); uint32_t n; ss.read((char*)&n, sizeof(n)); SwapperNoOp::SwapArray(&n,1); uint32_t unused; ss.read((char*)&unused, sizeof(unused)); SwapperNoOp::SwapArray(&unused,1); if( unused != 77 ) { gdcmErrorMacro( "Must be a new format. Giving up" ); return false; } assert( unused == 77 ); // 'M' character... for(uint32_t i = 0; i < n; ++i) { CSAElement csael; //std::cout << i; csael.SetKey( i ); //std::cout << " - "; char name[64+1]; name[64] = 0; // security ss.read(name, 64); csael.SetName( name ); //std::cout << "'" << name << "' "; uint32_t vm; ss.read((char*)&vm, sizeof(vm)); SwapperNoOp::SwapArray(&vm,1); csael.SetVM( VM::GetVMTypeFromLength(vm,1) ); //assert( csael.GetVM() != VM::VM0 ); //std::cout << "VM " << vm << ", "; char vr[4]; ss.read(vr, 4); // In dataset without magic signature (OLD FORMAT) vr[3] is garbage... assert( /*vr[3] == 0 &&*/ vr[2] == 0 ); csael.SetVR( VR::GetVRTypeFromFile(vr) ); //std::cout << "VR " << vr << ", "; uint32_t syngodt; ss.read((char*)&syngodt, sizeof(syngodt)); SwapperNoOp::SwapArray(&syngodt,1); bool cm = check_mapping(syngodt, vr); if( !cm ) { gdcmErrorMacro( "SyngoDT is not handled, please submit bug report" ); return false; } csael.SetSyngoDT( syngodt ); //std::cout << "SyngoDT " << syngodt << ", "; uint32_t nitems; ss.read((char*)&nitems, sizeof(nitems)); SwapperNoOp::SwapArray(&nitems,1); csael.SetNoOfItems( nitems ); //std::cout << "NoOfItems " << nitems << ", "; uint32_t xx; ss.read((char*)&xx, sizeof(xx)); SwapperNoOp::SwapArray(&xx,1); //std::cout << "xx=" << xx<< std::endl; assert( xx == 77 || xx == 205 ); //std::cout << "Data "; std::ostringstream os; for( uint32_t j = 0; j < nitems; ++j) { uint32_t item_xx[4]; ss.read((char*)&item_xx, 4*sizeof(uint32_t)); SwapperNoOp::SwapArray(item_xx,4); assert( item_xx[2] == 77 || item_xx[2] == 205 ); uint32_t len = item_xx[1]; // 2nd element assert( item_xx[0] == item_xx[1] && item_xx[1] == item_xx[3] ); if( len ) { char *val = new char[len+1]; val[len] = 0; // security ss.read(val,len); // WARNING vr does not means anything AFAIK, // simply print the value as if it was IS/DS or LO (ASCII) if( j ) { //std::cout << '\\'; os << '\\'; } //std::cout << "'" << val << "'"; os << val; char dummy[4]; uint32_t dummy_len = (4 - len % 4) % 4; ss.read(dummy, dummy_len ); for(uint32_t d= 0; d < dummy_len; ++d) { // dummy[d] is zero in the NEW format //assert( dummy[d] == 0 ); //for the old format there appears to be some garbage: if( dummy[d] ) { //std::cout << "dummy=" << (int)dummy[d] << std::endl; } } delete[] val; } } std::string str = os.str(); if( !str.empty() ) csael.SetByteValue( &str[0], (uint32_t)str.size()); //std::cout << std::endl; InternalCSADataSet.insert( csael ); } return true; } void CSAHeader::Print(std::ostream &os) const { std::set::const_iterator it = InternalCSADataSet.begin(); gdcm::Tag t1(0x0029,0x0010); gdcm::Tag t2(0x0029,0x0020); if( DataElementTag == t1 ) { os << "Image shadow data (0029,xx10)\n\n"; } else if( DataElementTag == t2 ) { os << "Series shadow data (0029,xx20)\n\n"; } else { std::cerr << "Unhandled tag: " << DataElementTag << std::endl; } for(; it != InternalCSADataSet.end(); ++it) { std::cout << *it << std::endl; } } const CSAElement &CSAHeader::GetCSAElementByName(const char *name) { if( name ) { //int s = InternalCSADataSet.size(); std::set::const_iterator it = InternalCSADataSet.begin(); for(; it != InternalCSADataSet.end(); ++it) { const char *itname = it->GetName(); assert( itname ); if( strcmp(name, itname) == 0 ) { return *it; } } } return GetCSAEEnd(); } bool CSAHeader::FindCSAElementByName(const char *name) { if( name ) { std::set::const_iterator it = InternalCSADataSet.begin(); for(; it != InternalCSADataSet.end(); ++it) { const char *itname = it->GetName(); assert( itname ); if( strcmp(name, itname) == 0 ) { return true; } } } return false; } 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 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 const PrivateTag & CSAHeader::GetCSAImageHeaderInfoTag() { return t1; } const PrivateTag & CSAHeader::GetCSASeriesHeaderInfoTag() { return t2; } const PrivateTag & CSAHeader::GetCSADataInfo() { return t3; } bool CSAHeader::GetMrProtocol( const DataSet & ds, MrProtocol & mrProtocol ) { if(!ds.FindDataElement( t2 ) ) return false; if( !LoadFromDataElement( ds.GetDataElement( t2 ) ) ) return false; // 28 - 'MrProtocolVersion' VM 1, VR IS, SyngoDT 6, NoOfItems 6, Data '21710006' int mrprotocolversion = 0; static const char version[] = "MrProtocolVersion"; // This is not an error if we do not find the version: if( FindCSAElementByName( version ) ) { const CSAElement &csavers = GetCSAElementByName( version ); if( !csavers.IsEmpty() ) { const ByteValue* bv = csavers.GetByteValue(); std::string str( bv->GetPointer(), bv->GetLength() ); std::istringstream is(str); is >> mrprotocolversion; } } static const char * candidates[] = { "MrProtocol", "MrPhoenixProtocol" }; static const int n = sizeof candidates / sizeof * candidates; bool found = false; for( int i = 0; i < n; ++i ) { const char * candidate = candidates[i]; if( FindCSAElementByName( candidate ) ) { // assume the correct one is the one that is not empty, // ideally we should rely on the version... const gdcm::CSAElement &csael = GetCSAElementByName( candidate ); if( !csael.IsEmpty() ) { if( mrProtocol.Load(csael.GetByteValue(), candidate, mrprotocolversion) ) { found = true; } } } } return found; } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.h000066400000000000000000000113551412732066400251770ustar00rootroot00000000000000/*========================================================================= 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 GDCMCSAHEADER_H #define GDCMCSAHEADER_H #include "gdcmTypes.h" #include "gdcmDataSet.h" #include "gdcmCSAElement.h" #include "gdcmMrProtocol.h" namespace gdcm { /* * Everything done in this code is for the sole purpose of writing interoperable * software under Sect. 1201 (f) Reverse Engineering exception of the DMCA. * If you believe anything in this code violates any law or any of your rights, * please contact us (gdcm-developers@lists.sourceforge.net) so that we can * find a solution. */ //----------------------------------------------------------------------------- class DataElement; class PrivateTag; /** * \brief Class for CSAHeader * \details SIEMENS store private information in tag (0x0029,0x10,"SIEMENS CSA * HEADER") this class is meant for user wishing to access values stored within * this private attribute. * There are basically two main 'format' for this attribute : SV10/NOMAGIC and * DATASET_FORMAT SV10 and NOMAGIC are from a user prospective identical, see * CSAHeader.xml for possible name / value stored in this format. * DATASET_FORMAT is in fact simply just another DICOM dataset (implicit) with * -currently unknown- value. This can be only be printed for now. * * \warning * Everything you do with this code is at your own risk, since decoding process * was not written from specification documents. * * \warning the API of this class might change. * * \todo * MrEvaProtocol in 29,1020 contains ^M that would be nice to get rid of on UNIX system... * * \see PDBHeader * * External references: * 5.1.3.2.4.1 MEDCOM History Information * and 5.1.4.3 CSA Non-Image Module * in * http://tamsinfo.toshiba.com/docrequest/pdf/E.Soft_v2.0.pdf */ class GDCM_EXPORT CSAHeader { friend std::ostream& operator<<(std::ostream &_os, const CSAHeader &d); public : CSAHeader():InternalDataSet(),InternalType(UNKNOWN),InterfileData(nullptr) {}; ~CSAHeader() = default; /// Divers format of CSAHeader as found 'in the wild' typedef enum { UNKNOWN = 0, SV10, NOMAGIC, DATASET_FORMAT, INTERFILE, ZEROED_OUT } CSAHeaderType; /// Decode the CSAHeader from element 'de' bool LoadFromDataElement(DataElement const &de); /// Print the CSAHeader (use only if Format == SV10 or NOMAGIC) void Print(std::ostream &os) const; /// Return the DataSet output (use only if Format == DATASET_FORMAT ) const DataSet& GetDataSet() const { return InternalDataSet; } /// Return the string output (use only if Format == Interfile) const char * GetInterfile() const { return InterfileData; } /// return the format of the CSAHeader /// SV10 and NOMAGIC are equivalent. CSAHeaderType GetFormat() const; /// Return the private tag used by SIEMENS to store the CSA Image Header /// This is: PrivateTag(0x0029,0x0010,"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"); 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"); static const PrivateTag & GetCSADataInfo(); /// Return the CSAElement corresponding to name 'name' /// \warning Case Sensitive const CSAElement &GetCSAElementByName(const char *name); /// Return true if the CSA element matching 'name' is found or not /// \warning Case Sensitive bool FindCSAElementByName(const char *name); /// Retrieve the ASCII portion stored within the MrProtocol/MrPhoenixProtocol: bool GetMrProtocol( const DataSet & ds, MrProtocol & mrProtocol ); protected: const CSAElement& GetCSAEEnd() const; private: std::set InternalCSADataSet; DataSet InternalDataSet; CSAHeaderType InternalType; Tag DataElementTag; static CSAElement CSAEEnd; const char *InterfileData; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const CSAHeader &d) { d.Print( os ); return os; } } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMCSAHEADER_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmCodeString.cxx000066400000000000000000000021431412732066400260670ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCodeString.h" namespace gdcm { bool CodeString::IsValid() const { if( !Internal.IsValid() ) return false; // Implementation specific: /* * Uppercase characters, 0-9, the SPACE character, and underscore _, of the * Default Character Repertoire */ const_iterator it = Internal.begin(); for( ; it != Internal.end(); ++it ) { int c = *it; if( !isupper(c) && !isdigit(c) && c != ' ' && c != '_' ) { return false; } } return true; } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmCodeString.h000066400000000000000000000072611412732066400255220ustar00rootroot00000000000000/*========================================================================= 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 GDCMCODESTRING_H #define GDCMCODESTRING_H #include "gdcmString.h" namespace gdcm { /** * \brief CodeString * \details This is an implementation of DICOM VR: CS * The cstor will properly Trim so that operator== is correct. * * \note the cstor of CodeString will Trim the string on the fly so as * to remove the extra leading and ending spaces. However it will not * perform validation on the fly (CodeString obj can contains invalid * char such as lower cases). This design was chosen to be a little tolerant * to broken DICOM implementation, and thus allow user to compare lower * case CS from there input file without the need to first rewrite them * to get rid of invalid character (validation is a different operation from * searching, querying). * \warning when writing out DICOM file it is highly recommended to perform * the IsValid() call, at least to check that the length of the string match * the definition in the standard. */ // Note to myself: because note all wrapped language support exception // we could not support throwing an exception during object construction. class GDCM_EXPORT CodeString { friend std::ostream& operator<< (std::ostream& os, const CodeString& str); friend bool operator==(const CodeString &ref, const CodeString& cs); friend bool operator!=(const CodeString &ref, const CodeString& cs); typedef String<'\\',16> InternalClass; public: typedef InternalClass::value_type value_type; typedef InternalClass::pointer pointer; typedef InternalClass::reference reference; typedef InternalClass::const_reference const_reference; typedef InternalClass::size_type size_type; typedef InternalClass::difference_type difference_type; typedef InternalClass::iterator iterator; typedef InternalClass::const_iterator const_iterator; typedef InternalClass::reverse_iterator reverse_iterator; typedef InternalClass::const_reverse_iterator const_reverse_iterator; /// CodeString constructors. CodeString(): Internal() {} CodeString(const value_type* s): Internal(s) { Internal = Internal.Trim(); } CodeString(const value_type* s, size_type n): Internal(s, n) { Internal = Internal.Trim(); } CodeString(const InternalClass& s, size_type pos=0, size_type n=InternalClass::npos): Internal(s, pos, n) { Internal = Internal.Trim(); } /// Check if CodeString obj is correct.. bool IsValid() const; /// Return the full code string as std::string std::string GetAsString() const { return Internal; } /// Return the size of the string size_type Size() const { return Internal.size(); } protected: std::string TrimInternal() const { return Internal.Trim(); } private: String<'\\',16> Internal; }; inline std::ostream& operator<< (std::ostream& os, const CodeString& str) { os << str.Internal; return os; } inline bool operator==(const CodeString &ref, const CodeString& cs) { return ref.Internal == cs.Internal; } inline bool operator!=(const CodeString &ref, const CodeString& cs) { return ref.Internal != cs.Internal; } } // end namespace gdcm #endif //GDCMCODESTRING_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmDataElement.cxx000066400000000000000000000143131412732066400262130ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDataElement.h" #include "gdcmByteValue.h" #include "gdcmAttribute.h" #include "gdcmSequenceOfFragments.h" #include "gdcmSequenceOfItems.h" #include "gdcmImplicitDataElement.h" #include "gdcmTrace.h" namespace gdcm_ns { void DataElement::SetVLToUndefined() { assert( VRField == VR::SQ || VRField == VR::INVALID || (VRField == VR::UN /*&& IsUndefinedLength()*/ ) ); SequenceOfItems *sqi = dynamic_cast(ValueField.GetPointer()); if( sqi ) { sqi->SetLengthToUndefined(); assert( GetValueAsSQ()->IsUndefinedLength() ); } ValueLengthField.SetToUndefined(); } const SequenceOfFragments* DataElement::GetSequenceOfFragments() const { const SequenceOfFragments *sqf = dynamic_cast(ValueField.GetPointer()); return sqf; } SequenceOfFragments* DataElement::GetSequenceOfFragments() { SequenceOfFragments *sqf = dynamic_cast(ValueField.GetPointer()); return sqf; } /* * Two cases are handled: * - Simple ones: * Explicit file with VR::SQ (defined or undefined length) * Implicit file with undefined length (clearly a SQ) * - If not in the previous case then we are in the second case: complex one (hidden SQ) * Implicit file with defined length SQ * Explicit file with SQ declared as UN + undefined length */ SmartPointer DataElement::GetValueAsSQ() const { if( IsEmpty() /*|| GetByteValue()*/ || GetSequenceOfFragments() ) { return nullptr; } SequenceOfItems *sq = dynamic_cast(ValueField.GetPointer()); if( sq ) // all set ! { //assert( GetVR() == VR::SQ ); SmartPointer sqi = sq; return sqi; } const Tag itemStart(0xfffe, 0xe000); { { if( GetVR() == VR::INVALID ) { 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 &ex) { const Tag itemPMSStart(0xfeff, 0x00e0); const Tag itemPMSStart2(0x3f3f, 0x3f00); // same player ... //this to fix a broken dicom implementation //for philips medical systems std::stringstream ss; ss.str(s); Tag item; item.Read(ss); if( item == itemPMSStart ) { ss.seekg(-4,std::ios::cur); sqi->Read( ss, true ); gdcmWarningMacro(ex.what()); (void)ex; //to avoid unreferenced variable warning on release } else { delete sqi; sqi = nullptr; } } return sqi; } else if ( GetVR() == VR::UN ) // cp 246, IVRLE SQ { assert( GetVR() == VR::UN ); // cp 246, IVRLE SQ 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 ) { // Some people like to skew things up and write invalid SQ in VR:UN field // if conversion fails, simply keep the binary VR:UN stuff as-is // eg. AMIInvalidPrivateDefinedLengthSQasUN.dcm //const char *s = e.what(); // s -> gdcm::ImplicitDataElement -> Impossible (more) try { std::stringstream ss; ss.str(s); sqi->Read( ss, true ); gdcmWarningMacro(ex0.what()); (void)ex0; } catch ( Exception &ex1 ) { // Let's try again this time but without the byte swapping option: // eg. MEDILABInvalidCP246_EVRLESQasUN.dcm try { std::stringstream ss; ss.str(s); sqi->Read( ss, true ); gdcmWarningMacro(ex1.what()); (void)ex1; } catch ( Exception &ex2 ) { gdcmErrorMacro( "Could not read SQ. Giving up" ); gdcmErrorMacro(ex2.what()); (void)ex2; delete sqi; return nullptr; } } } return sqi; } else { assert( GetVR().IsVRFile() ); assert( GetByteValue() ); return nullptr; } } } // catch( ParseException &pex ) // { // gdcmDebugMacro( pex.what() ); // } // catch( Exception &ex ) // { // gdcmDebugMacro( ex.what() ); // } // catch( ... ) // { // gdcmWarningMacro( "Unknown exception" ); // } } void DataElement::SetValueFieldLength( VL vl, bool readvalues ) { if( readvalues ) ValueField->SetLength(vl); // perform realloc else ValueField->SetLengthOnly(vl); // do not perform realloc } } // end namespace gdcm_ns GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmDataElement.h000066400000000000000000000216441412732066400256450ustar00rootroot00000000000000/*========================================================================= 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 GDCMDATAELEMENT_H #define GDCMDATAELEMENT_H #include "gdcmTag.h" #include "gdcmVL.h" #include "gdcmVR.h" #include "gdcmByteValue.h" #include "gdcmSmartPointer.h" #include namespace gdcm_ns { // Data Element // Contains multiple fields: // -> Tag // -> Optional VR (Explicit Transfer Syntax) // -> ValueLength // -> Value // TODO: This class SHOULD be pure virtual. I don't want a user // to shoot himself in the foot. class SequenceOfItems; class SequenceOfFragments; /** * \brief Class to represent a Data Element * either Implicit or Explicit * * \details * DATA ELEMENT: * A unit of information as defined by a single entry in the data dictionary. * An encoded Information Object Definition (IOD) Attribute that is composed * of, at a minimum, three fields: a Data Element Tag, a Value Length, and a * Value Field. For some specific Transfer Syntaxes, a Data Element also * contains a VR Field where the Value Representation of that Data Element is * specified explicitly. * * Design: * \li A DataElement in GDCM always store VL (Value Length) on a 32 bits integer even when VL is 16 bits * \li A DataElement always store the VR even for Implicit TS, in which case VR is defaulted to VR::INVALID * \li For Item start/end (See 0xfffe tags), Value is NULL * * \see ExplicitDataElement ImplicitDataElement */ class GDCM_EXPORT DataElement { public: DataElement(const Tag& t = Tag(0), const VL& vl = 0, const VR &vr = VR::INVALID):TagField(t),ValueLengthField(vl),VRField(vr),ValueField(nullptr) {} //DataElement( Attribute const &att ); friend std::ostream& operator<<(std::ostream &_os, const DataElement &_val); /// Get Tag const Tag& GetTag() const { return TagField; } Tag& GetTag() { return TagField; } /// Set Tag /// Use with cautious (need to match Part 6) void SetTag(const Tag &t) { TagField = t; } /// Get VL const VL& GetVL() const { return ValueLengthField; } VL& GetVL() { return ValueLengthField; } /// Set VL /// Use with cautious (need to match Part 6), advanced user only /// \see SetByteValue void SetVL(const VL &vl) { ValueLengthField = vl; } void SetVLToUndefined(); /// Get VR /// do not set VR::SQ on bytevalue data element VR const &GetVR() const { return VRField; } /// Set VR /// Use with cautious (need to match Part 6), advanced user only /// \pre vr is a VR::VRALL (not a dual one such as OB_OW) void SetVR(VR const &vr) { if( vr.IsVRFile() ) VRField = vr; } /// Set/Get Value (bytes array, SQ of items, SQ of fragments): Value const &GetValue() const { gdcmAssertAlwaysMacro(ValueField); return *ValueField; } Value &GetValue() { gdcmAssertAlwaysMacro(ValueField); return *ValueField; } /// \warning you need to set the ValueLengthField explicitly void SetValue(Value const & vl) { //assert( ValueField == 0 ); ValueField = vl; ValueLengthField = vl.GetLength(); } /// Check if Data Element is empty bool IsEmpty() const { return ValueField == nullptr || (GetByteValue() && GetByteValue()->IsEmpty()); } /// Make Data Element empty (no Value) void Empty() { ValueField = nullptr; ValueLengthField = 0; } /// Clear Data Element (make Value empty and invalidate Tag & VR) void Clear() { TagField = 0; VRField = VR::INVALID; ValueField = nullptr; ValueLengthField = 0; } // Helper: /// Set the byte value /// \warning user need to read DICOM standard for an understanding of: /// * even padding /// * \0 vs space padding /// By default even padding is achieved using \0 regardless of the of VR void SetByteValue(const char *array, VL length) { ByteValue *bv = new ByteValue(array,length); SetValue( *bv ); } /// Return the Value of DataElement as a ByteValue (if possible) /// \warning: You need to check for NULL return value const ByteValue* GetByteValue() const { // Get the raw pointer from the gdcm::SmartPointer const ByteValue *bv = dynamic_cast(ValueField.GetPointer()); return bv; // Will return NULL if not ByteValue } /// Interpret the Value stored in the DataElement. This is more robust (but also more /// expensive) to call this function rather than the simplest form: GetSequenceOfItems() /// It also return NULL when the Value is NOT of type SequenceOfItems /// \warning in case GetSequenceOfItems() succeed the function return this value, otherwise /// it creates a new SequenceOfItems, you should handle that in your case, for instance: /// SmartPointer sqi = de.GetValueAsSQ(); SmartPointer GetValueAsSQ() const; /// Return the Value of DataElement as a Sequence Of Fragments (if possible) /// \warning: You need to check for NULL return value const SequenceOfFragments* GetSequenceOfFragments() const; SequenceOfFragments* GetSequenceOfFragments(); /// return if Value Length if of undefined length bool IsUndefinedLength() const { return ValueLengthField.IsUndefined(); } DataElement(const DataElement &_val) { if( this != &_val) { *this = _val; } } bool operator<(const DataElement &de) const { return GetTag() < de.GetTag(); } DataElement &operator=(const DataElement &) = default; bool operator==(const DataElement &de) const { bool b = TagField == de.TagField && ValueLengthField == de.ValueLengthField && VRField == de.VRField; if( !ValueField && !de.ValueField ) { return b; } if( ValueField && de.ValueField ) { return b && (*ValueField == *de.ValueField); } // ValueField != de.ValueField return false; } // The following functionalities are dependent on: // # The Transfer Syntax: Explicit or Implicit // # The Byte encoding: Little Endian / Big Endian /* * The following was inspired by a C++ idiom: Curiously Recurring Template Pattern * Ref: http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern * The typename TDE is typically a derived class *without* any data * while TSwap is a simple template parameter to achieve byteswapping (and allow factorization of * highly identical code) */ template VL GetLength() const { return static_cast(this)->GetLength(); } template std::istream &Read(std::istream &is) { return static_cast(this)->template Read(is); } template std::istream &ReadOrSkip(std::istream &is, std::set const &skiptags) { (void)skiptags; return static_cast(this)->template Read(is); } template std::istream &ReadPreValue(std::istream &is, std::set const &skiptags) { (void)skiptags; return static_cast(this)->template ReadPreValue(is); } template std::istream &ReadValue(std::istream &is, std::set const &skiptags) { (void)skiptags; return static_cast(this)->template ReadValue(is); } template std::istream &ReadValueWithLength(std::istream &is, VL & length, std::set const &skiptags) { (void)skiptags; return static_cast(this)->template ReadValueWithLength(is, length); } template std::istream &ReadWithLength(std::istream &is, VL &length) { return static_cast(this)->template ReadWithLength(is,length); } template const std::ostream &Write(std::ostream &os) const { return static_cast(this)->template Write(os); } protected: Tag TagField; // This is the value read from the file, might be different from the length of Value Field VL ValueLengthField; // Can be 0xFFFFFFFF // Value Representation VR VRField; typedef SmartPointer ValuePtr; ValuePtr ValueField; void SetValueFieldLength( VL vl, bool readvalues ); }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const DataElement &val) { os << val.TagField; os << "\t" << val.VRField; os << "\t" << val.ValueLengthField; if( val.ValueField ) { val.ValueField->Print( os << "\t" ); } return os; } inline bool operator!=(const DataElement& lhs, const DataElement& rhs) { return ! ( lhs == rhs ); } } // end namespace gdcm_ns #endif //GDCMDATAELEMENT_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmDataSet.cxx000066400000000000000000000113671412732066400253630ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDataSet.h" #include "gdcmPrivateTag.h" namespace gdcm_ns { DataElement DataSet::DEEnd = DataElement( Tag(0xffff,0xffff) ); const DataElement& DataSet::GetDEEnd() const { return DEEnd; } std::string DataSet::GetPrivateCreator(const Tag &t) const { if( t.IsPrivate() && !t.IsPrivateCreator() ) { Tag pc = t.GetPrivateCreator(); if( pc.GetElement() ) { const DataElement r(pc); ConstIterator it = DES.find(r); if( it == DES.end() ) { // FIXME, could this happen ? return ""; } const DataElement &de = *it; if( de.IsEmpty() ) return ""; const ByteValue *bv = de.GetByteValue(); assert( bv ); std::string owner = std::string(bv->GetPointer(),bv->GetLength()); // There should not be any trailing space character... // TODO: tmp.erase(tmp.find_last_not_of(' ') + 1); while( !owner.empty() && owner[owner.size()-1] == ' ' ) { // osirix/AbdominalCT/36382443 owner.erase(owner.size()-1,1); } assert( owner.size() == 0 || owner[owner.size()-1] != ' ' ); return owner; } } return ""; } Tag DataSet::ComputeDataElement(const PrivateTag & t) const { 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...) const DataElement r(start); ConstIterator it = DES.lower_bound(r); const char *refowner = t.GetOwner(); assert( refowner ); bool found = false; while( it != DES.end() && it->GetTag().GetGroup() == t.GetGroup() && it->GetTag().GetElement() < 0x100 ) { //assert( it->GetTag().GetOwner() ); const ByteValue * bv = it->GetByteValue(); if( bv ) { //if( strcmp( bv->GetPointer(), refowner ) == 0 ) 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 if( System::StrCaseCmp( tmp.c_str(), refowner ) == 0 ) { // found ! found = true; break; } } ++it; } 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 Tag copy = t; copy.SetPrivateCreator( it->GetTag() ); gdcmDebugMacro( "Compute found:" << copy ); return copy; } bool DataSet::FindDataElement(const PrivateTag &t) const { return FindDataElement( ComputeDataElement(t) ); } const DataElement& DataSet::GetDataElement(const PrivateTag &t) const { return GetDataElement( ComputeDataElement(t) ); } MediaStorage DataSet::GetMediaStorage() const { // Let's check 0008,0016: // D 0008|0016 [UI] [SOP Class UID] [1.2.840.10008.5.1.4.1.1.7 ] // ==> [Secondary Capture Image Storage] const Tag tsopclassuid(0x0008, 0x0016); if( !FindDataElement( tsopclassuid) ) { gdcmDebugMacro( "No SOP Class UID" ); return MediaStorage::MS_END; } const DataElement &de = GetDataElement(tsopclassuid); if( de.IsEmpty() ) { gdcmDebugMacro( "Empty SOP Class UID" ); return MediaStorage::MS_END; } std::string ts; { const ByteValue *bv = de.GetByteValue(); assert( bv ); if( bv->GetPointer() && bv->GetLength() ) { // Pad string with a \0 ts = std::string(bv->GetPointer(), bv->GetLength()); } } // Paranoid check: if last character of a VR=UI is space let's pretend this is a \0 if( !ts.empty() ) { char &last = ts[ts.size()-1]; if( last == ' ' ) { gdcmWarningMacro( "Media Storage Class UID: " << ts << " contained a trailing space character" ); last = '\0'; } } gdcmDebugMacro( "TS: " << ts ); MediaStorage ms = MediaStorage::GetMSType(ts.c_str()); if( ms == MediaStorage::MS_END ) { gdcmWarningMacro( "Media Storage Class UID: " << ts << " is unknown" ); } return ms; } } // end namespace gdcm_ns GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmDataSet.h000066400000000000000000000254051412732066400250060ustar00rootroot00000000000000/*========================================================================= 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 GDCMDATASET_H #define GDCMDATASET_H #include "gdcmDataElement.h" #include "gdcmTag.h" #include "gdcmVR.h" #include "gdcmElement.h" #include "gdcmMediaStorage.h" #include #include namespace gdcm_ns { class GDCM_EXPORT DataElementException : public std::exception {}; class PrivateTag; /** * \brief Class to represent a Data Set (which contains Data Elements) * \details A Data Set represents an instance of a real world Information Object * \note * DATA SET: * Exchanged information consisting of a structured set of Attribute values * directly or indirectly related to Information Objects. The value of each * Attribute in a Data Set is expressed as a Data Element. * A collection of Data Elements ordered by increasing Data Element Tag * number that is an encoding of the values of Attributes of a real world * object. * \note * Implementation note. If one do: * DataSet ds; * ds.SetLength(0); * ds.Read(is); * setting length to 0 actually means try to read is as if it was a root * DataSet. Other value are undefined (nested dataset with undefined length) * or defined length (different from 0) means nested dataset with defined * length. * * \warning * a DataSet does not have a Transfer Syntax type, only a File does. */ class GDCM_EXPORT DataSet { friend class CSAHeader; public: typedef std::set DataElementSet; typedef DataElementSet::const_iterator ConstIterator; typedef DataElementSet::iterator Iterator; typedef DataElementSet::size_type SizeType; //typedef typename DataElementSet::iterator iterator; ConstIterator Begin() const { return DES.begin(); } Iterator Begin() { return DES.begin(); } ConstIterator End() const { return DES.end(); } Iterator End() { return DES.end(); } const DataElementSet &GetDES() const { return DES; } DataElementSet &GetDES() { return DES; } void Clear() { DES.clear(); assert( DES.empty() ); } SizeType Size() const { return DES.size(); } void Print(std::ostream &os, std::string const &indent = "") const { // CT_Phillips_JPEG2K_Decompr_Problem.dcm has a SQ of length == 0 //int s = DES.size(); //assert( s ); //std::copy(DES.begin(), DES.end(), // std::ostream_iterator(os, "\n")); ConstIterator it = DES.begin(); for( ; it != DES.end(); ++it) { os << indent << *it << "\n"; } } template unsigned int ComputeGroupLength(Tag const &tag) const { assert( tag.GetElement() == 0x0 ); const DataElement r(tag); ConstIterator it = DES.find(r); unsigned int res = 0; for( ++it; it != DES.end() && it->GetTag().GetGroup() == tag.GetGroup(); ++it) { assert( it->GetTag().GetElement() != 0x0 ); assert( it->GetTag().GetGroup() == tag.GetGroup() ); res += it->GetLength(); } return res; } template VL GetLength() const { if( DES.empty() ) return 0; assert( !DES.empty() ); VL ll = 0; assert( ll == 0 ); ConstIterator it = DES.begin(); for( ; it != DES.end(); ++it) { assert( !(it->GetLength().IsUndefined()) ); if ( it->GetTag() != Tag(0xfffe,0xe00d) ) { ll += it->GetLength(); } } return ll; } /// Insert a DataElement in the DataSet. /// \warning: Tag need to be >= 0x8 to be considered valid data element void Insert(const DataElement& de) { // FIXME: there is a special case where a dataset can have value < 0x8, see: // $ gdcmdump --csa gdcmData/SIEMENS-JPEG-CorruptFrag.dcm if( de.GetTag().GetGroup() >= 0x0008 || de.GetTag().GetGroup() == 0x4 ) { // prevent user error: if( de.GetTag() == Tag(0xfffe,0xe00d) || de.GetTag() == Tag(0xfffe,0xe0dd) || de.GetTag() == Tag(0xfffe,0xe000) ) { } else { InsertDataElement( de ); } } else { gdcmErrorMacro( "Cannot add element with group < 0x0008 and != 0x4 in the dataset: " << de.GetTag() ); } } /// Replace a dataelement with another one void Replace(const DataElement& de) { ConstIterator it = DES.find(de); if( it != DES.end() ) { // detect loop: gdcmAssertAlwaysMacro( &*it != &de ); DES.erase(it); } DES.insert(de); } /// Only replace a DICOM attribute when it is missing or empty void ReplaceEmpty(const DataElement& de) { ConstIterator it = DES.find(de); if( it != DES.end() && it->IsEmpty() ) { // detect loop: gdcmAssertAlwaysMacro( &*it != &de ); DES.erase(it); } DES.insert(de); } /// Completely remove a dataelement from the dataset SizeType Remove(const Tag& tag) { DataElementSet::size_type count = DES.erase(tag); assert( count == 0 || count == 1 ); return count; } /// Return the DataElement with Tag 't' /// \warning: /// This only search at the 'root level' of the DataSet //DataElement& GetDataElement(const Tag &t) { // DataElement r(t); // Iterator it = DES.find(r); // if( it != DES.end() ) // return *it; // return GetDEEnd(); // } const DataElement& GetDataElement(const Tag &t) const { const DataElement r(t); ConstIterator it = DES.find(r); if( it != DES.end() ) return *it; return GetDEEnd(); } const DataElement& operator[] (const Tag &t) const { return GetDataElement(t); } const DataElement& operator() (uint16_t group, uint16_t element) const { return GetDataElement( Tag(group,element) ); } /// Return the private creator of the private tag 't': std::string GetPrivateCreator(const Tag &t) const; /// Look up if private tag 't' is present in the dataset: bool FindDataElement(const PrivateTag &t) const; /// Return the dataelement const DataElement& GetDataElement(const PrivateTag &t) const; // DUMB: this only search within the level of the current DataSet bool FindDataElement(const Tag &t) const { const DataElement r(t); //ConstIterator it = DES.find(r); if( DES.find(r) != DES.end() ) { return true; } return false; } // WARNING: // This only search at the same level as the DataSet is ! const DataElement& FindNextDataElement(const Tag &t) const { const DataElement r(t); ConstIterator it = DES.lower_bound(r); if( it != DES.end() ) return *it; return GetDEEnd(); } /// Returns if the dataset is 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); template std::istream &Read(std::istream &is); template std::istream &ReadUpToTag(std::istream &is, const Tag &t, std::set const & skiptags); template std::istream &ReadUpToTagWithLength(std::istream &is, const Tag &t, std::set const & skiptags, VL & length); template std::istream &ReadSelectedTags(std::istream &is, const std::set & tags, bool readvalues = true); template std::istream &ReadSelectedTagsWithLength(std::istream &is, const std::set & tags, VL & length, bool readvalues = true); template std::istream &ReadSelectedPrivateTags(std::istream &is, const std::set & tags, bool readvalues = true); template std::istream &ReadSelectedPrivateTagsWithLength(std::istream &is, const std::set & tags, VL & length, bool readvalues = true); template std::ostream const &Write(std::ostream &os) const; template std::istream &ReadWithLength(std::istream &is, VL &length); MediaStorage GetMediaStorage() const; protected: /* GetDEEnd is a Win32 only issue, one cannot use a dllexported * static member data in an inline function, otherwise symbol * will get reported as missing in any dll using the inlined function */ const DataElement& GetDEEnd() const; // This function is not safe, it does not check for the value of the tag // so depending whether we are getting called from a dataset or file meta header // the condition is different void InsertDataElement(const DataElement& de) { //if( de.GetTag() == Tag(0xfffe,0xe00d) ) return; //if( de.GetTag() == Tag(0xfffe,0xe0dd) ) return; #ifndef NDEBUG std::pair pr = DES.insert(de); if( pr.second == false ) { gdcmWarningMacro( "DataElement: " << de << " was already found, skipping duplicate entry.\n" "Original entry kept is: " << *pr.first ); } #else DES.insert(de); #endif assert( de.IsEmpty() || de.GetVL() == de.GetValue().GetLength() ); } protected: // Internal function, that will compute the actual Tag (if found) of // a requested Private Tag (XXXX,YY,"PRIVATE") Tag ComputeDataElement(const PrivateTag & t) const; private: DataElementSet DES; static DataElement DEEnd; friend std::ostream& operator<<(std::ostream &_os, const DataSet &); }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const DataSet &val) { val.Print(os); return os; } #if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPHP) /* * HACK: I need this temp class to be able to manipulate a std::set from python, * swig does not support wrapping of simple class like std::set... */ class SWIGDataSet { public: SWIGDataSet(DataSet &des):Internal(des),it(des.Begin()) {} const DataElement& GetCurrent() const { return *it; } void Start() { it = Internal.Begin(); } bool IsAtEnd() const { return it == Internal.End(); } void Next() { ++it; } private: DataSet & Internal; DataSet::ConstIterator it; }; #endif /* SWIG */ /** * \example SimplePrint.cs * This is a C# example on how to use gdcm::SWIGDataSet */ } // end namespace gdcm_ns #include "gdcmDataSet.txx" #endif //GDCMDATASET_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmDataSet.txx000066400000000000000000000417131412732066400254020ustar00rootroot00000000000000/*========================================================================= 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 GDCMDATASET_TXX #define GDCMDATASET_TXX #include "gdcmByteValue.h" #include "gdcmPrivateTag.h" #include "gdcmParseException.h" #include namespace gdcm_ns { template std::istream &DataSet::ReadNested(std::istream &is) { DataElement de; const Tag itemDelItem(0xfffe,0xe00d); assert( de.GetTag() != itemDelItem ); // precondition before while loop try { while( de.Read(is) && de.GetTag() != itemDelItem ) // Keep that order please ! { //std::cerr << "DEBUG Nested: " << de << std::endl; InsertDataElement( de ); } } catch(ParseException &pe) { if( pe.GetLastElement().GetTag() == Tag(0xfffe,0xe0dd) ) { // BogusItemStartItemEnd.dcm gdcmWarningMacro( "SQ End found but no Item end found" ); de.SetTag( itemDelItem ); is.seekg( -4, std::ios::cur ); } else { // MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm // Need to rethrow the exception...sigh throw pe; } } assert( de.GetTag() == itemDelItem ); return is; } template std::istream &DataSet::Read(std::istream &is) { DataElement de; while( !is.eof() && de.Read(is) ) { //std::cerr << "DEBUG:" << de << std::endl; InsertDataElement( de ); } return is; } template std::istream &DataSet::ReadUpToTag(std::istream &is, const Tag &t, const std::set & skiptags) { DataElement de; while( !is.eof() && de.template ReadPreValue(is, skiptags) ) { // If tag read was in skiptags then we should NOT add it: if( skiptags.count( de.GetTag() ) == 0 ) { de.template ReadValue(is, skiptags); InsertDataElement( de ); } else { assert( is.good() ); if( de.GetTag() != t ) is.seekg( de.GetVL(), std::ios::cur ); } // tag was found, we can exit the loop: if ( t <= de.GetTag() ) { assert( is.good() ); break; } } return is; } template std::istream &DataSet::ReadUpToTagWithLength(std::istream &is, const Tag &t, std::set const & skiptags, VL & length) { DataElement de; while( !is.eof() && de.template ReadPreValue(is, skiptags) ) { // If tag read was in skiptags then we should NOT add it: if( skiptags.count( de.GetTag() ) == 0 ) { de.template ReadValueWithLength(is, length, skiptags); InsertDataElement( de ); } else { assert( is.good() ); if( de.GetTag() != t ) is.seekg( de.GetVL(), std::ios::cur ); } // tag was found, we can exit the loop: if ( t <= de.GetTag() ) { assert( is.good() ); break; } } return is; } template std::istream &DataSet::ReadSelectedTags(std::istream &inputStream, const std::set & selectedTags, bool readvalues ) { if ( ! (selectedTags.empty() || inputStream.fail()) ) { const Tag maxTag = *(selectedTags.rbegin()); std::set tags = selectedTags; DataElement dataElem; while( !inputStream.eof() ) { static_cast(dataElem).template ReadPreValue(inputStream); const Tag& tag = dataElem.GetTag(); if ( inputStream.fail() || maxTag < tag ) { if( inputStream.good() ) { const int l = dataElem.GetVR().GetLength(); inputStream.seekg( - 4 - 2 * l, std::ios::cur ); } else { inputStream.clear(); inputStream.seekg( 0, std::ios::end ); } // Failed to read the tag, or the read tag exceeds the maximum. // As we assume ascending tag ordering, we can exit the loop. break; } static_cast(dataElem).template ReadValue(inputStream, readvalues); const std::set::iterator found = tags.find(tag); if ( found != tags.end() ) { InsertDataElement( dataElem ); tags.erase(found); if ( tags.empty() ) { // All selected tags were found, we can exit the loop: break; } } if ( ! (tag < maxTag ) ) { // The maximum tag was encountered, and as we assume // ascending tag ordering, we can exit the loop: break; } } } assert( inputStream.good() ); return inputStream; } template std::istream &DataSet::ReadSelectedPrivateTags(std::istream &inputStream, const std::set & selectedPTags, bool readvalues) { if ( ! (selectedPTags.empty() || inputStream.fail()) ) { assert( selectedPTags.size() == 1 ); const PrivateTag refPTag = *(selectedPTags.rbegin()); PrivateTag nextPTag = refPTag; nextPTag.SetElement( (uint16_t)(nextPTag.GetElement() + 0x1) ); assert( nextPTag.GetElement() & 0x00ff ); // no wrap please Tag maxTag; maxTag.SetPrivateCreator( nextPTag ); DataElement dataElem; while( !inputStream.eof() ) { static_cast(dataElem).template ReadPreValue(inputStream); const Tag& tag = dataElem.GetTag(); if ( inputStream.fail() || maxTag < tag ) { if( inputStream.good() ) { const int l = dataElem.GetVR().GetLength(); inputStream.seekg( - 4 - 2 * l, std::ios::cur ); } else { inputStream.clear(); inputStream.seekg( 0, std::ios::end ); } // Failed to read the tag, or the read tag exceeds the maximum. // As we assume ascending tag ordering, we can exit the loop. break; } static_cast(dataElem).template ReadValue(inputStream, readvalues); if ( inputStream.fail() ) { // Failed to read the value. break; } if( tag.GetPrivateCreator() == refPTag ) { DES.insert( dataElem ); } if ( ! (tag < maxTag ) ) { // The maximum group was encountered, and as we assume // ascending tag ordering, we can exit the loop: break; } } } return inputStream; } template std::istream &DataSet::ReadSelectedTagsWithLength(std::istream &inputStream, const std::set & selectedTags, VL & length, bool readvalues ) { (void)length; if ( ! selectedTags.empty() ) { const Tag maxTag = *(selectedTags.rbegin()); std::set tags = selectedTags; DataElement dataElem; while( !inputStream.eof() ) { static_cast(dataElem).template ReadPreValue(inputStream); const Tag tag = dataElem.GetTag(); if ( inputStream.fail() || maxTag < tag ) { if( inputStream.good() ) { const int l = dataElem.GetVR().GetLength(); inputStream.seekg( - 4 - 2 * l, std::ios::cur ); } else { inputStream.clear(); inputStream.seekg( 0, std::ios::end ); } // Failed to read the tag, or the read tag exceeds the maximum. // As we assume ascending tag ordering, we can exit the loop. break; } static_cast(dataElem).template ReadValue(inputStream, readvalues); if ( inputStream.fail() ) { // Failed to read the value. break; } const std::set::iterator found = tags.find(tag); if ( found != tags.end() ) { InsertDataElement( dataElem ); tags.erase(found); if ( tags.empty() ) { // All selected tags were found, we can exit the loop: break; } } if ( ! (tag < maxTag ) ) { // The maximum tag was encountered, and as we assume // ascending tag ordering, we can exit the loop: break; } } } return inputStream; } template std::istream &DataSet::ReadSelectedPrivateTagsWithLength(std::istream &inputStream, const std::set & selectedPTags, VL & length, bool readvalues ) { (void)length; if ( ! (selectedPTags.empty() || inputStream.fail()) ) { assert( selectedPTags.size() == 1 ); const PrivateTag refPTag = *(selectedPTags.rbegin()); PrivateTag nextPTag = refPTag; nextPTag.SetElement( (uint16_t)(nextPTag.GetElement() + 0x1) ); assert( nextPTag.GetElement() ); // no wrap please Tag maxTag; maxTag.SetPrivateCreator( nextPTag ); DataElement dataElem; while( !inputStream.eof() ) { static_cast(dataElem).template ReadPreValue(inputStream); const Tag& tag = dataElem.GetTag(); if ( inputStream.fail() || maxTag < tag ) { if( inputStream.good() ) { const int l = dataElem.GetVR().GetLength(); inputStream.seekg( - 4 - 2 * l, std::ios::cur ); } else { inputStream.clear(); inputStream.seekg( 0, std::ios::end ); } // Failed to read the tag, or the read tag exceeds the maximum. // As we assume ascending tag ordering, we can exit the loop. break; } static_cast(dataElem).template ReadValue(inputStream, readvalues); if ( inputStream.fail() ) { // Failed to read the value. break; } //const std::set::iterator found = selectedPTags.find(tag.GetGroup()); //if ( found != groups.end() ) if( tag.GetPrivateCreator() == refPTag ) { InsertDataElement( dataElem ); } if ( ! (tag < maxTag ) ) { // The maximum group was encountered, and as we assume // ascending tag ordering, we can exit the loop: break; } } } return inputStream; } template std::istream &DataSet::ReadWithLength(std::istream &is, VL &length) { DataElement de; VL l = 0; //std::cout << "ReadWithLength Length: " << length << std::endl; VL locallength = length; const std::streampos startpos = is.tellg(); try { while( l != locallength && de.ReadWithLength(is, locallength)) { //std::cout << "Nested: " << de << std::endl; #ifndef GDCM_SUPPORT_BROKEN_IMPLEMENTATION assert( de.GetTag() != Tag(0xfffe,0xe000) ); // We should not be reading the next item... #endif InsertDataElement( de ); const VL oflen = de.GetLength(); l += oflen; const std::streampos curpos = is.tellg(); //assert( (curpos - startpos) == l || (curpos - startpos) + 1 == l ); //std::cout << "l:" << l << std::endl; //assert( !de.GetVL().IsUndefined() ); //std::cerr << "DEBUG: " << de.GetTag() << " "<< de.GetLength() << // "," << de.GetVL() << "," << l << std::endl; // Bug_Philips_ItemTag_3F3F // (0x2005, 0x1080): for some reason computation of length fails... if( l == 70 && locallength == 63 ) { gdcmWarningMacro( "PMS: Super bad hack. Changing length" ); length = locallength = 140; } if( (curpos - startpos) + 1 == l ) { gdcmDebugMacro( "Papyrus odd padding detected" ); throw Exception( "Papyrus odd padding" ); } if( l > locallength ) { if( (curpos - startpos) == locallength ) { // this means that something went wrong somewhere, and upon recomputing the length // we found a discrepandy with own vendor made its layout. // update the length directly locallength = length = l; throw Exception( "Changed Length" ); } else { gdcmDebugMacro( "Out of Range SQ detected: " << l << " while max: " << locallength ); throw Exception( "Out of Range" ); } } } } catch(ParseException &pe) { if( pe.GetLastElement().GetTag() == Tag(0xfffe,0xe000) ) { // gdcm-MR-PHILIPS-16-Multi-Seq.dcm // Long story short, I think Philips engineer inserted 0xfffe,0x0000 instead of an item start element // assert( FindDataElement( Tag(0xfffe,0x0000) ) == false ); is.seekg(-6, std::ios::cur ); length = locallength = l; } else if( /*pe.GetLastElement().GetTag() == Tag(0xffd8,0xffe0) &&*/ de.GetTag() == Tag(0x7fe0,0x0010) && de.IsUndefinedLength() ) { // Bug_Siemens_PrivateIconNoItem.dcm // PET-GE-dicomwrite-PixelDataSQUN.dcm // PET-GE-dicomwrite-PixelDataSQUNv2.dcm // some bozo crafted an undefined length Pixel Data but is actually // defined length. Since inside SQ/Item it should be possible to // compute the proper length is.seekg(-16, std::ios::cur ); TDE pd; pd.template ReadPreValue(is); gdcmAssertAlwaysMacro( pd.GetTag() == Tag(0x7fe0,0x0010) ); gdcmAssertAlwaysMacro( pd.GetVR() == VR::OB ); gdcmAssertAlwaysMacro( pd.IsUndefinedLength() ); const VL pdlen = locallength - l - 12; pd.SetVL( pdlen ); pd.template ReadValue(is, true); InsertDataElement( pd ); length = locallength = l; } else { // Could be the famous : // gdcmDataExtra/gdcmBreakers/BuggedDicomWorksImage_Hopeless.dcm // let's just give up: gdcmErrorMacro( "Last Tag is : " << pe.GetLastElement().GetTag() ); throw Exception( "Unhandled" ); } } catch(Exception &pe) { if( strcmp( pe.GetDescription(), "Out of Range" ) == 0 ) { // BogugsItemAndSequenceLength.dcm // This is most likely the "Out of Range" one // Cautiously read until we find the next item starter and then stop. //std::cout << "Length read was:" << l << " should be at most:" << locallength ; while( de.Read(is) && de.GetTag() != Tag(0xfffe,0xe000) && de.GetTag().GetElement() != 0x0 ) { //std::cout << "Nested2: " << de << std::endl; InsertDataElement( de ); l += de.GetLength(); //std::cout << l << std::endl; } // seek back since we read the next item starter: int iteml = de.GetLength(); //assert( de.GetTag().GetElement() ); if( !de.GetTag().GetElement() ) { assert( iteml == 12 ); (void)iteml; is.seekg( -12, std::ios::cur ); } else { //assert( de.GetTag() == Tag(0xfffe,0xe000) ); is.seekg( -4, std::ios::cur ); } // let's fix the length now: length = locallength = l; gdcmWarningMacro( "Item length is wrong" ); throw Exception( "Changed Length" ); } else if( strcmp( pe.GetDescription(), "Papyrus odd padding" ) == 0 ) { is.get(); throw Exception( "Changed Length" ); } else { // re throw throw pe; } } // technically we could only do this assert if the dataset did not contains // duplicate data elements so only do a <= instead: //assert( l == locallength ); assert( l <= locallength ); return is; } template std::ostream const &DataSet::Write(std::ostream &os) const { typename DataSet::ConstIterator it = DES.begin(); for( ; it != DES.end(); ++it) { const DataElement & de = *it; //if( de.GetTag().GetGroup() >= 0x0008 || de.GetTag().GetGroup() == 0x0002 ) { de.Write(os); } } return os; } } // end namespace gdcm_ns #endif // GDCMDATASET_TXX GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmDataSetEvent.cxx000066400000000000000000000011741412732066400263600ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDataSetEvent.h" namespace gdcm { } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmDataSetEvent.h000066400000000000000000000027621412732066400260110ustar00rootroot00000000000000/*========================================================================= 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 GDCMDATASETEVENT_H #define GDCMDATASETEVENT_H #include "gdcmEvent.h" #include "gdcmDataSet.h" namespace gdcm { /** * \brief DataSetEvent * \details Special type of event triggered during the DataSet store/move process * * \see */ class DataSetEvent : public AnyEvent { public: typedef DataSetEvent Self; typedef AnyEvent Superclass; DataSetEvent(DataSet const *ds = nullptr):m_DataSet(ds) {} ~DataSetEvent() override = default; void operator=(const Self&) = delete; const DataSet *m_DataSet; const char * GetEventName() const override { return "DataSetEvent"; } bool CheckEvent(const ::gdcm::Event* e) const override { return (dynamic_cast(e) == nullptr ? false : true) ; } ::gdcm::Event* MakeObject() const override { return new Self; } DataSetEvent(const Self&s) : AnyEvent(s){}; DataSet const & GetDataSet() const { return *m_DataSet; } }; } // end namespace gdcm #endif //GDCMANONYMIZEEVENT_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmElement.h000066400000000000000000000614351412732066400250550ustar00rootroot00000000000000/*========================================================================= 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 GDCMELEMENT_H #define GDCMELEMENT_H #include "gdcmTypes.h" #include "gdcmVR.h" #include "gdcmTag.h" #include "gdcmVM.h" #include "gdcmByteValue.h" #include "gdcmDataElement.h" #include "gdcmSwapper.h" #include #include #include #include #include #include namespace gdcm_ns { // Forward declaration /** * \brief EncodingImplementation * * \note TODO */ template class EncodingImplementation; /** * \brief A class which is used to produce compile errors for an * invalid combination of template parameters. * * Invalid combinations have specialized declarations with no * definition. */ template class ElementDisableCombinations {}; template <> class ElementDisableCombinations {}; template <> class ElementDisableCombinations {}; // Make it impossible to compile these other cases template class ElementDisableCombinations; template class ElementDisableCombinations; /** * \brief Element class * * \note TODO */ template class Element { enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations ) }; public: typename VRToType::Type Internal[VMToLength::Length]; typedef typename VRToType::Type Type; static VR GetVR() { return (VR::VRType)TVR; } static VM GetVM() { return (VM::VMType)TVM; } unsigned long GetLength() const { return VMToLength::Length; } // Implementation of Print is common to all Mode (ASCII/Binary) // TODO: Can we print a \ when in ASCII...well I don't think so // it would mean we used a bad VM then, right? void Print(std::ostream &_os) const { _os << Internal[0]; // VM is at least guarantee to be one for(int i=1; i::Length; ++i) _os << "," << Internal[i]; } const typename VRToType::Type *GetValues() const { return Internal; } const typename VRToType::Type &GetValue(unsigned int idx = 0) const { assert( idx < VMToLength::Length ); return Internal[idx]; } typename VRToType::Type &GetValue(unsigned int idx = 0) { assert( idx < VMToLength::Length ); return Internal[idx]; } typename VRToType::Type operator[] (unsigned int idx) const { return GetValue(idx); } void SetValue(typename VRToType::Type v, unsigned int idx = 0) { assert( idx < VMToLength::Length ); Internal[idx] = v; } void SetFromDataElement(DataElement const &de) { const ByteValue *bv = de.GetByteValue(); if( !bv ) return; #ifdef GDCM_WORDS_BIGENDIAN if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ ) #else if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID ) #endif { Set(de.GetValue()); } else { SetNoSwap(de.GetValue()); } } DataElement GetAsDataElement() const { DataElement ret; std::ostringstream os; EncodingImplementation::Mode>::Write(Internal, GetLength(),os); ret.SetVR( (VR::VRType)TVR ); assert( ret.GetVR() != VR::SQ ); if( (VR::VRType)VRToEncoding::Mode == VR::VRASCII ) { if( GetVR() != VR::UI ) { if( os.str().size() % 2 ) { os << " "; } } } VL::Type osStrSize = (VL::Type)os.str().size(); ret.SetByteValue( os.str().c_str(), osStrSize ); return ret; } void Read(std::istream &_is) { return EncodingImplementation::Mode>::Read(Internal, GetLength(),_is); } void Write(std::ostream &_os) const { return EncodingImplementation::Mode>::Write(Internal, GetLength(),_os); } // FIXME: remove this function // this is only used in gdcm::SplitMosaicFilter / to pass value of a CSAElement void Set(Value const &v) { const ByteValue *bv = dynamic_cast(&v); if( bv ) { //memcpy(Internal, bv->GetPointer(), bv->GetLength()); std::stringstream ss; std::string s = std::string( bv->GetPointer(), bv->GetLength() ); ss.str( s ); EncodingImplementation::Mode>::Read(Internal, GetLength(),ss); } } protected: void SetNoSwap(Value const &v) { const ByteValue *bv = dynamic_cast(&v); assert( bv ); // That would be bad... //memcpy(Internal, bv->GetPointer(), bv->GetLength()); std::stringstream ss; std::string s = std::string( bv->GetPointer(), bv->GetLength() ); ss.str( s ); EncodingImplementation::Mode>::ReadNoSwap(Internal, GetLength(),ss); } }; struct ignore_char { ignore_char(char c): m_char(c) {} char m_char; }; ignore_char const backslash('\\'); inline std::istream& operator>> (std::istream& in, ignore_char const& ic) { if (!in.eof()) in.clear(in.rdstate() & ~std::ios_base::failbit); if (in.get() != ic.m_char) in.setstate(std::ios_base::failbit); return in; } // Implementation to perform formatted read and write template<> class EncodingImplementation { public: template // FIXME this should be VRToType::Type static inline void ReadComputeLength(T* data, unsigned int &length, std::istream &_is) { assert( data ); //assert( length ); // != 0 length = 0; assert( _is ); #if 0 char sep; while( _is >> data[length++] ) { // Get the separator in between the values assert( _is ); _is.get(sep); assert( sep == '\\' || sep == ' ' ); // FIXME: Bad use of assert if( sep == ' ' ) length--; // FIXME } #else while( _is >> std::ws >> data[length++] >> std::ws >> backslash ) { } #endif } template // FIXME this should be VRToType::Type static inline void Read(T* data, unsigned long length, std::istream &_is) { assert( data ); assert( length ); // != 0 assert( _is ); // FIXME BUG: what if >> operation fails ? // gdcmData/MR00010001.dcm / SpacingBetweenSlices _is >> std::ws >> data[0]; char sep; //std::cout << "GetLength: " << af->GetLength() << std::endl; for(unsigned long i=1; i> std::ws >> sep; //_is.get(sep); //assert( sep == '\\' ); // FIXME: Bad use of assert _is >> std::ws >> data[i]; } } template static inline void ReadNoSwap(T* data, unsigned long length, std::istream &_is) { Read(data,length,_is); } template static inline void Write(const T* data, unsigned long length, std::ostream &_os) { assert( data ); assert( length ); assert( _os ); _os << data[0]; for(unsigned long i=1; i std::string to_string ( Float data ) { std::stringstream in; // in.imbue(std::locale::classic()); // This is not required AFAIK int const digits = static_cast< int >( - std::log( std::numeric_limits::epsilon() ) / static_cast< Float >( std::log( 10.0 ) ) ); if ( in << std::dec << std::setprecision(/*2+*/digits) << data ) { return ( in.str() ); } else { throw "Impossible Conversion"; // should not happen ... } } #else // http://stackoverflow.com/questions/32631178/writing-ieee-754-1985-double-as-ascii-on-a-limited-16-bytes-string static inline void clean(char *mant) { char *ix = mant + strlen(mant) - 1; while(('0' == *ix) && (ix > mant)) { *ix-- = '\0'; } if ('.' == *ix) { *ix = '\0'; } } static int add1(char *buf, int n) { if (n < 0) return 1; if (buf[n] == '9') { buf[n] = '0'; return add1(buf, n-1); } else { buf[n] = (char)(buf[n] + 1); } return 0; } static int doround(char *buf, unsigned int n) { char c; if (n >= strlen(buf)) return 0; c = buf[n]; buf[n] = 0; if ((c >= '5') && (c <= '9')) return add1(buf, n-1); return 0; } static int roundat(char *buf, unsigned int i, int iexp) { if (doround(buf, i) != 0) { iexp += 1; switch(iexp) { case -2: strcpy(buf, ".01"); break; case -1: strcpy(buf, ".1"); break; case 0: strcpy(buf, "1."); break; case 1: strcpy(buf, "10"); break; case 2: strcpy(buf, "100"); break; default: sprintf(buf, "1e%d", iexp); } return 1; } return 0; } template < typename Float > static void x16printf(char *buf, int size, Float f) { char line[40]; char *mant = line + 1; int iexp, lexp, i; char exp[6]; if (f < 0) { f = -f; size -= 1; *buf++ = '-'; } sprintf(line, "%1.16e", f); if (line[0] == '-') { f = -f; size -= 1; *buf++ = '-'; sprintf(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); if ((iexp >= size) || (iexp < -3)) { i = roundat(mant, size - 1 -lexp, iexp); if(i == 1) { strcpy(buf, mant); return; } buf[0] = mant[0]; buf[1] = '.'; strncpy(buf + i + 2, mant + 1, size - 2 - lexp); buf[size-lexp] = 0; clean(buf); strcat(buf, exp); } else if (iexp >= size - 2) { roundat(mant, iexp + 1, iexp); strcpy(buf, mant); } else if (iexp >= 0) { i = roundat(mant, size - 1, iexp); if (i == 1) { strcpy(buf, mant); return; } strncpy(buf, mant, iexp + 1); buf[iexp + 1] = '.'; strncpy(buf + iexp + 2, mant + iexp + 1, size - iexp - 1); buf[size] = 0; clean(buf); } else { int j; i = roundat(mant, size + 1 + iexp, iexp); if (i == 1) { strcpy(buf, mant); return; } buf[0] = '.'; 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); } } #endif template<> inline void EncodingImplementation::Write(const double* data, unsigned long length, std::ostream &_os) { assert( data ); assert( length ); assert( _os ); #ifdef VRDS16ILLEGAL _os << to_string(data[0]); #else char buf[16+1]; x16printf(buf, 16, data[0]); _os << buf; #endif for(unsigned long i=1; i class EncodingImplementation { public: template // FIXME this should be VRToType::Type static inline void ReadComputeLength(T* data, unsigned int &length, std::istream &_is) { const unsigned int type_size = sizeof(T); assert( data ); // Can we read from pointer ? //assert( length ); length /= type_size; assert( _is ); // Is stream valid ? _is.read( reinterpret_cast(data+0), type_size); for(unsigned long i=1; i(data+i), type_size ); } } template static inline void ReadNoSwap(T* data, unsigned long length, std::istream &_is) { const unsigned int type_size = sizeof(T); assert( data ); // Can we read from pointer ? assert( length ); assert( _is ); // Is stream valid ? _is.read( reinterpret_cast(data+0), type_size); for(unsigned long i=1; i(data+i), type_size ); } //ByteSwap::SwapRangeFromSwapCodeIntoSystem(data, // _is.GetSwapCode(), length); //SwapperNoOp::SwapArray(data,length); } template static inline void Read(T* data, unsigned long length, std::istream &_is) { const unsigned int type_size = sizeof(T); assert( data ); // Can we read from pointer ? assert( length ); assert( _is ); // Is stream valid ? _is.read( reinterpret_cast(data+0), type_size); for(unsigned long i=1; i(data+i), type_size ); } //ByteSwap::SwapRangeFromSwapCodeIntoSystem(data, // _is.GetSwapCode(), length); SwapperNoOp::SwapArray(data,length); } template static inline void Write(const T* data, unsigned long length, std::ostream &_os) { const unsigned int type_size = sizeof(T); assert( data ); // Can we write into pointer ? assert( length ); assert( _os ); // Is stream valid ? //ByteSwap::SwapRangeFromSwapCodeIntoSystem((T*)data, // _os.GetSwapCode(), length); T swappedData = SwapperNoOp::Swap(data[0]); _os.write( reinterpret_cast(&swappedData), type_size); for(unsigned long i=1; i(&swappedData), type_size ); } //ByteSwap::SwapRangeFromSwapCodeIntoSystem((T*)data, // _os.GetSwapCode(), length); } }; // For particular case for ASCII string // WARNING: This template explicitly instantiates a particular // EncodingImplementation THEREFORE it is required to be declared after the // EncodingImplementation is needs (doh!) #if 0 template class Element { public: Element(const char array[]) { unsigned int i = 0; const char sep = '\\'; std::string sarray = array; std::string::size_type pos1 = 0; std::string::size_type pos2 = sarray.find(sep, pos1+1); while(pos2 != std::string::npos) { Internal[i++] = sarray.substr(pos1, pos2-pos1); pos1 = pos2+1; pos2 = sarray.find(sep, pos1+1); } Internal[i] = sarray.substr(pos1, pos2-pos1); // Shouldn't we do the contrary, since we know how many separators // (and default behavior is to discard anything after the VM declared assert( GetLength()-1 == i ); } unsigned long GetLength() const { return VMToLength::Length; } // Implementation of Print is common to all Mode (ASCII/Binary) void Print(std::ostream &_os) const { _os << Internal[0]; // VM is at least guarantee to be one for(int i=1; i::Length; ++i) _os << "," << Internal[i]; } void Read(std::istream &_is) { EncodingImplementation::Read(Internal, GetLength(),_is); } void Write(std::ostream &_os) const { EncodingImplementation::Write(Internal, GetLength(),_os); } private: typename String Internal[VMToLength::Length]; }; template< int TVM> class Element : public StringElement { enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations ) }; }; #endif // Implementation for the undefined length (dynamically allocated array) template class Element { enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations ) }; public: // This the way to prevent default initialization explicit Element() { Internal=nullptr; Length=0; Save = false; } ~Element() { if( Save ) { delete[] Internal; } Internal = nullptr; } static VR GetVR() { return (VR::VRType)TVR; } static VM GetVM() { return VM::VM1_n; } // Length manipulation // SetLength should really be protected anyway...all operation // should go through SetArray unsigned long GetLength() const { return Length; } typedef typename VRToType::Type Type; void SetLength(unsigned long len) { const unsigned int size = sizeof(Type); if( len ) { if( len > Length ) { // perform realloc assert( (len / size) * size == len ); Type *internal = new Type[len / size]; assert( Save == false ); Save = true; // ???? if( Internal ) { memcpy(internal, Internal, len); delete[] Internal; } Internal = internal; } } Length = len / size; } // If save is set to zero user should not delete the pointer //void SetArray(const typename VRToType::Type *array, int len, bool save = false) void SetArray(const Type *array, unsigned long len, bool save = false) { if( save ) { SetLength(len); // realloc memcpy(Internal, array, len/*/sizeof(Type)*/); assert( Save == false ); } else { // TODO rewrite this stupid code: assert( Length == 0 ); assert( Internal == nullptr ); assert( Save == false ); Length = len / sizeof(Type); //assert( (len / sizeof(Type)) * sizeof(Type) == len ); // MR00010001.dcm is a tough kid: 0019,105a is supposed to be VR::FL, VM::VM3 but // length is 14 bytes instead of 12 bytes. Simply consider value is total garbage. if( (len / sizeof(Type)) * sizeof(Type) != len ) { Internal = nullptr; Length = 0; } else Internal = const_cast(array); } Save = save; } void SetValue(typename VRToType::Type v, unsigned int idx = 0) { assert( idx < Length ); Internal[idx] = v; } const typename VRToType::Type &GetValue(unsigned int idx = 0) const { assert( idx < Length ); return Internal[idx]; } typename VRToType::Type &GetValue(unsigned int idx = 0) { //assert( idx < Length ); return Internal[idx]; } typename VRToType::Type operator[] (unsigned int idx) const { return GetValue(idx); } void Set(Value const &v) { const ByteValue *bv = dynamic_cast(&v); assert( bv ); // That would be bad... if( (VR::VRType)(VRToEncoding::Mode) == VR::VRBINARY ) { const Type* array = (const Type*)bv->GetVoidPointer(); if( array ) { assert( array ); // That would be bad... assert( Internal == nullptr ); SetArray(array, bv->GetLength() ); } } else { std::stringstream ss; std::string s = std::string( bv->GetPointer(), bv->GetLength() ); ss.str( s ); EncodingImplementation::Mode>::Read(Internal, GetLength(),ss); } } void SetFromDataElement(DataElement const &de) { const ByteValue *bv = de.GetByteValue(); if( !bv ) return; #ifdef GDCM_WORDS_BIGENDIAN if( de.GetVR() == VR::UN /*|| de.GetVR() == VR::INVALID*/ ) #else if( de.GetVR() == VR::UN || de.GetVR() == VR::INVALID ) #endif { Set(de.GetValue()); } else { SetNoSwap(de.GetValue()); } } // Need to be placed after definition of EncodingImplementation void WriteASCII(std::ostream &os) const { return EncodingImplementation::Write(Internal, GetLength(), os); } // Implementation of Print is common to all Mode (ASCII/Binary) void Print(std::ostream &_os) const { assert( Length ); assert( Internal ); _os << Internal[0]; // VM is at least guarantee to be one const unsigned long length = GetLength() < 25 ? GetLength() : 25; for(unsigned long i=1; i::Mode>::Read(Internal, GetLength(),_is); } //void ReadComputeLength(std::istream &_is) { // if( !Internal ) return; // EncodingImplementation::Mode>::ReadComputeLength(Internal, // Length,_is); // } void Write(std::ostream &_os) const { EncodingImplementation::Mode>::Write(Internal, GetLength(),_os); } DataElement GetAsDataElement() const { DataElement ret; ret.SetVR( (VR::VRType)TVR ); assert( ret.GetVR() != VR::SQ ); if( Internal ) { std::ostringstream os; EncodingImplementation::Mode>::Write(Internal, GetLength(),os); if( (VR::VRType)VRToEncoding::Mode == VR::VRASCII ) { if( GetVR() != VR::UI ) { if( os.str().size() % 2 ) { os << " "; } } } VL::Type osStrSize = (VL::Type)os.str().size(); ret.SetByteValue( os.str().c_str(), osStrSize ); } return ret; } Element(const Element&_val) { if( this != &_val) { *this = _val; } } Element &operator=(const Element &_val) { Length = 0; // SYITF Internal = 0; SetArray(_val.Internal, _val.Length, true); return *this; } protected: void SetNoSwap(Value const &v) { const ByteValue *bv = dynamic_cast(&v); assert( bv ); // That would be bad... if( (VR::VRType)(VRToEncoding::Mode) == VR::VRBINARY ) { const Type* array = (const Type*)bv->GetPointer(); if( array ) { assert( array ); // That would be bad... assert( Internal == nullptr ); SetArray(array, bv->GetLength() ); } } else { std::stringstream ss; std::string s = std::string( bv->GetPointer(), bv->GetLength() ); ss.str( s ); EncodingImplementation::Mode>::ReadNoSwap(Internal, GetLength(),ss); } } private: typename VRToType::Type *Internal; unsigned long Length; // unsigned int ?? bool Save; }; //template //class Element : public Element {}; // Partial specialization for derivatives of 1-n : 2-n, 3-n ... template class Element : public Element { public: typedef Element Parent; void SetLength(int len) { if( len != 1 && len != 2 ) return; Parent::SetLength(len); } }; template class Element : public Element { enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations ) }; public: typedef Element Parent; void SetLength(int len) { if( len <= 1 ) return; Parent::SetLength(len); } }; template class Element : public Element { enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations ) }; public: typedef Element Parent; void SetLength(int len) { if( len % 2 ) return; Parent::SetLength(len); } }; template class Element : public Element { enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations ) }; public: typedef Element Parent; void SetLength(int len) { if( len <= 2 ) return; Parent::SetLength(len); } }; template class Element : public Element { enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations ) }; public: typedef Element Parent; void SetLength(int len) { if( len % 3 ) return; Parent::SetLength(len); } }; template class Element : public Element { public: typedef Element Parent; void SetLength(int len) { if( len != 3 && len != 4 ) return; Parent::SetLength(len); } }; //template struct VRToLength; //template <> struct VRToLength //{ enum { Length = VM::VM1 }; } //template<> //class Element : public Element::Length > // only 0010 1010 AS 1 Patient's Age template<> class Element { enum { ElementDisableCombinationsCheck = sizeof ( ElementDisableCombinations ) }; public: char Internal[VMToLength::Length * sizeof( VRToType::Type )]; void Print(std::ostream &_os) const { _os << Internal; } unsigned long GetLength() const { return VMToLength::Length; } }; template <> class Element : public Element {}; // Same for OW: template <> class Element : public Element {}; } // namespace gdcm_ns #endif //GDCMELEMENT_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmExplicitDataElement.cxx000066400000000000000000000043771412732066400277260ustar00rootroot00000000000000/*========================================================================= 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 "gdcmExplicitDataElement.h" #include "gdcmSequenceOfItems.h" #include "gdcmSequenceOfFragments.h" namespace gdcm_ns { //----------------------------------------------------------------------------- VL ExplicitDataElement::GetLength() const { if( ValueLengthField.IsUndefined() ) { assert( ValueField->GetLength().IsUndefined() ); Value *p = ValueField; // If this is a SQ we need to compute it's proper length SequenceOfItems *sq = dynamic_cast(p); // TODO can factor the code: if( sq ) { const VL sqlen = sq->ComputeLength(); assert( sqlen % 2 == 0 ); return TagField.GetLength() + VRField.GetLength() + ValueLengthField.GetLength() + sqlen; } SequenceOfFragments *sf = dynamic_cast(p); if( sf ) { assert( VRField & VR::OB_OW ); // VR::INVALID is not possible AFAIK... const VL sflen = sf->ComputeLength(); assert( sflen % 2 == 0 ); return TagField.GetLength() + VRField.GetLength() + ValueLengthField.GetLength() + sflen; } assert(0); return 0; } else { // Each time VR::GetLength() is 2 then Value Length is coded in 2 // 4 then Value Length is coded in 4 assert( !ValueField || ValueField->GetLength() == ValueLengthField ); const bool vr16bitsimpossible = (VRField & VR::VL16) && (ValueLengthField > (uint32_t)VL::GetVL16Max()); if( vr16bitsimpossible || VRField == VR::INVALID ) return TagField.GetLength() + 2*VR::GetLength(VR::UN) + ValueLengthField; return TagField.GetLength() + 2*VRField.GetLength() + ValueLengthField; } } } // end namespace gdcm_ns GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmExplicitDataElement.h000066400000000000000000000025571412732066400273510ustar00rootroot00000000000000/*========================================================================= 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 GDCMEXPLICITDATAELEMENT_H #define GDCMEXPLICITDATAELEMENT_H #include "gdcmDataElement.h" namespace gdcm_ns { /** * \brief Class to read/write a DataElement as Explicit Data Element * \note bla */ class GDCM_EXPORT ExplicitDataElement : public DataElement { public: VL GetLength() const; template std::istream &Read(std::istream &is); template std::istream &ReadPreValue(std::istream &is); template std::istream &ReadValue(std::istream &is, bool readvalues = true); template std::istream &ReadWithLength(std::istream &is, VL & length); template const std::ostream &Write(std::ostream &os) const; }; } // end namespace gdcm_ns #include "gdcmExplicitDataElement.txx" #endif //GDCMEXPLICITDATAELEMENT_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmExplicitDataElement.txx000066400000000000000000000404511412732066400277400ustar00rootroot00000000000000/*========================================================================= 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 GDCMEXPLICITDATAELEMENT_TXX #define GDCMEXPLICITDATAELEMENT_TXX #include "gdcmSequenceOfItems.h" #include "gdcmSequenceOfFragments.h" #include "gdcmVL.h" #include "gdcmParseException.h" #include "gdcmImplicitDataElement.h" #include "gdcmValueIO.h" #include "gdcmSwapper.h" namespace gdcm_ns { //----------------------------------------------------------------------------- template std::istream &ExplicitDataElement::Read(std::istream &is) { ReadPreValue(is); return ReadValue(is); } template std::istream &ExplicitDataElement::ReadPreValue(std::istream &is) { TagField.Read(is); // See PS 3.5, Data Element Structure With Explicit VR // Read Tag if( !is ) { if( !is.eof() ) // FIXME This should not be needed { assert(0 && "Should not happen" ); } return is; } if( TagField == Tag(0xfffe,0xe0dd) ) { ParseException pe; pe.SetLastElement( *this ); throw pe; } //assert( TagField != Tag(0xfeff,0xdde0) ); const Tag itemDelItem(0xfffe,0xe00d); if( TagField == itemDelItem ) { if( !ValueLengthField.Read(is) ) { assert(0 && "Should not happen"); return is; } if( ValueLengthField ) { gdcmDebugMacro( "Item Delimitation Item has a length different from 0 and is: " << ValueLengthField ); } // Reset ValueLengthField to avoid user error ValueLengthField = 0; // Set pointer to NULL to avoid user error ValueField = nullptr; VRField = VR::INVALID; return is; } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( TagField == Tag(0x00ff, 0x4aa5) ) { //assert(0 && "Should not happen" ); // gdcmDataExtra/gdcmBreakers/DigitexAlpha_no_7FE0.dcm is.seekg( -4, std::ios::cur ); TagField = Tag(0x7fe0,0x0010); VRField = VR::OW; ValueField = new ByteValue; std::streampos s = is.tellg(); is.seekg( 0, std::ios::end); std::streampos e = is.tellg(); is.seekg( s, std::ios::beg ); ValueField->SetLength( (int32_t)(e - s) ); ValueLengthField = ValueField->GetLength(); bool failed = !ValueIO::Read(is,*ValueField,true); gdcmAssertAlwaysMacro( !failed ); return is; //throw Exception( "Unhandled" ); } #endif // Read VR try { if( !VRField.Read(is) ) { assert(0 && "Should not happen" ); return is; } } catch( Exception &ex ) { #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // gdcm-MR-PHILIPS-16-Multi-Seq.dcm // assert( TagField == Tag(0xfffe, 0xe000) ); // -> For some reason VR is written as {44,0} well I guess this is a VR... // Technically there is a second bug, dcmtk assume other things when reading this tag, // so I need to change this tag too, if I ever want dcmtk to read this file. oh well // 0019004_Baseline_IMG1.dcm // -> VR is garbage also... // assert( TagField == Tag(8348,0339) || TagField == Tag(b5e8,0338)) //gdcmWarningMacro( "Assuming 16 bits VR for Tag=" << // TagField << " in order to read a buggy DICOM file." ); //VRField = VR::INVALID; (void)ex; //compiler warning ParseException pe; pe.SetLastElement( *this ); throw pe; #else throw ex; #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */ } // Read Value Length if( VR::GetLength(VRField) == 4 ) { if( !ValueLengthField.Read(is) ) { assert(0 && "Should not happen"); return is; } } else { // 16bits only if( !ValueLengthField.template Read16(is) ) { assert(0 && "Should not happen"); return is; } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // HACK for SIEMENS Leonardo if( ValueLengthField == 0x0006 && VRField == VR::UL && TagField.GetGroup() == 0x0009 ) { gdcmWarningMacro( "Replacing VL=0x0006 with VL=0x0004, for Tag=" << TagField << " in order to read a buggy DICOM file." ); ValueLengthField = 0x0004; } #endif } //std::cerr << "exp cur tag=" << TagField << " VR=" << VRField << " VL=" << ValueLengthField << std::endl; // // I don't like the following 3 lines, what if 0000,0000 was indeed -wrongly- sent, we should be able to continue // chances is that 99% of times there is now way we can reach here, so safely throw an exception if( TagField == Tag(0x0000,0x0000) && ValueLengthField == 0 && VRField == VR::INVALID ) { ParseException pe; pe.SetLastElement( *this ); throw pe; } #ifdef ELSCINT1_01F7_1070 if( TagField == Tag(0x01f7,0x1070) ) { ValueLengthField = ValueLengthField - 7; } #endif return is; } template std::istream &ExplicitDataElement::ReadValue(std::istream &is, bool readvalues) { if( is.eof() ) return is; if( ValueLengthField == 0 ) { // Simple fast path ValueField = nullptr; return is; } // Read the Value //assert( ValueField == 0 ); if( VRField == VR::SQ ) { // Check whether or not this is an undefined length sequence assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new SequenceOfItems; } else if( ValueLengthField.IsUndefined() ) { if( TagField == Tag(0x7fe0,0x0010) ) { // Ok this is Pixel Data fragmented... assert( VRField & VR::OB_OW || VRField == VR::UN ); ValueField = new SequenceOfFragments; } else { // Support cp246 conforming file: // Enhanced_MR_Image_Storage_PixelSpacingNotIn_0028_0030.dcm (illegal) // vs // undefined_length_un_vr.dcm assert( TagField != Tag(0x7fe0,0x0010) ); assert( VRField == VR::UN ); ValueField = new SequenceOfItems; ValueField->SetLength(ValueLengthField); // perform realloc try { //if( !ValueIO::Read(is,*ValueField) ) // non cp246 if( !ValueIO::Read(is,*ValueField,readvalues) ) // cp246 compliant { assert(0); } } catch( std::exception &) { // Must be one of those non-cp246 file... // but for some reason seekg back to previous offset + Read // as Explicit does not work... ParseException pe; pe.SetLastElement(*this); throw pe; } return is; } } else { //assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new ByteValue; } // We have the length we should be able to read the value this->SetValueFieldLength( ValueLengthField, readvalues ); #if defined(GDCM_SUPPORT_BROKEN_IMPLEMENTATION) && 0 // PHILIPS_Intera-16-MONO2-Uncompress.dcm if( TagField == Tag(0x2001,0xe05f) || TagField == Tag(0x2001,0xe100) || TagField == Tag(0x2005,0xe080) || TagField == Tag(0x2005,0xe083) || TagField == Tag(0x2005,0xe084) || TagField == Tag(0x2005,0xe402) //TagField.IsPrivate() && VRField == VR::SQ //-> Does not work for 0029 //we really need to read item marker ) { gdcmWarningMacro( "ByteSwaping Private SQ: " << TagField ); assert( VRField == VR::SQ ); assert( TagField.IsPrivate() ); try { if( !ValueIO::Read(is,*ValueField,readvalues) ) { assert(0 && "Should not happen"); } Value* v = &*ValueField; SequenceOfItems *sq = dynamic_cast(v); assert( sq ); SequenceOfItems::Iterator it = sq->Begin(); for( ; it != sq->End(); ++it) { Item &item = *it; DataSet &ds = item.GetNestedDataSet(); ByteSwapFilter bsf(ds); bsf.ByteSwap(); } } catch( std::exception &ex ) { ValueLengthField = ValueField->GetLength(); } return is; } #endif bool failed; //assert( VRField != VR::UN ); if( VRField & VR::VRASCII ) { //assert( VRField.GetSize() == 1 ); failed = !ValueIO::Read(is,*ValueField,readvalues); } else { assert( VRField & VR::VRBINARY ); unsigned int vrsize = VRField.GetSize(); assert( vrsize == 1 || vrsize == 2 || vrsize == 4 || vrsize == 8 ); if(VRField==VR::AT) vrsize = 2; switch(vrsize) { case 1: failed = !ValueIO::Read(is,*ValueField,readvalues); break; case 2: failed = !ValueIO::Read(is,*ValueField,readvalues); break; case 4: failed = !ValueIO::Read(is,*ValueField,readvalues); break; case 8: failed = !ValueIO::Read(is,*ValueField,readvalues); break; default: failed = true; assert(0); } } if( failed ) { #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( TagField == Tag(0x7fe0,0x0010) ) { // BUG this should be moved to the ImageReader class, only this class // knows what 7fe0 actually is, and should tolerate partial Pixel Data // element... PMS-IncompletePixelData.dcm gdcmWarningMacro( "Incomplete Pixel Data found, use file at own risk" ); is.clear(); } else #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */ { // Might be the famous UN 16bits ParseException pe; pe.SetLastElement( *this ); throw pe; } return is; } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( SequenceOfItems *sqi = dynamic_cast(&GetValue()) ) { assert( ValueField->GetLength() == ValueLengthField ); // Recompute the total length: if( !ValueLengthField.IsUndefined() ) { // PhilipsInteraSeqTermInvLen.dcm // contains an extra seq del item marker, which we are not loading. Therefore the // total length needs to be recomputed when sqi is expressed in defined length VL dummy = sqi->template ComputeLength(); ValueLengthField = dummy; sqi->SetLength( dummy ); gdcmAssertAlwaysMacro( dummy == ValueLengthField ); } } else if( SequenceOfFragments *sqf = dynamic_cast(&GetValue()) ) { assert( ValueField->GetLength() == ValueLengthField ); assert( sqf->GetLength() == ValueLengthField ); (void)sqf; assert( ValueLengthField.IsUndefined() ); } #endif return is; } template std::istream &ExplicitDataElement::ReadWithLength(std::istream &is, VL & length) { (void)length; return Read(is); } //----------------------------------------------------------------------------- template const std::ostream &ExplicitDataElement::Write(std::ostream &os) const { if( TagField == Tag(0xfffe,0xe0dd) ) throw Exception( "Impossible" ); //if( TagField == Tag(0xfffe,0xe0dd) ) return os; if( !TagField.Write(os) ) { assert( 0 && "Should not happen" ); return os; } const Tag itemDelItem(0xfffe,0xe00d); if( TagField == itemDelItem ) { assert(0); assert( ValueField == nullptr ); #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( ValueLengthField != 0 ) { gdcmWarningMacro( "Item Delimitation Item had a length different from 0." ); VL zero = 0; zero.Write(os); return os; } #endif // else assert( ValueLengthField == 0 ); if( !ValueLengthField.Write(os) ) { assert( 0 && "Should not happen" ); return os; } return os; } bool vr16bitsimpossible = (VRField & VR::VL16) && (ValueLengthField > (uint32_t)VL::GetVL16Max()); if( VRField == VR::INVALID || vr16bitsimpossible ) { if ( TagField.IsPrivateCreator() ) { gdcmAssertAlwaysMacro( !vr16bitsimpossible ); VR lo = VR::LO; if( TagField.IsGroupLength() ) { lo = VR::UL; } lo.Write(os); ValueLengthField.Write16(os); } else { const VR un = VR::UN; un.Write(os); if( ValueField && dynamic_cast(&*ValueField) ) { VL vl = 0xFFFFFFFF; assert( vl.IsUndefined() ); vl.Write(os); } else ValueLengthField.Write(os); } } else { assert( VRField.IsVRFile() && VRField != VR::INVALID ); if( !VRField.Write(os) ) { assert( 0 && "Should not happen" ); return os; } if( VRField & VR::VL32 ) { if( !ValueLengthField.Write(os) ) { assert( 0 && "Should not happen" ); return os; } } else { // 16bits only if( !ValueLengthField.template Write16(os) ) { assert( 0 && "Should not happen" ); return os; } } } if( ValueLengthField ) { // Special case, check SQ if ( GetVR() == VR::SQ ) { gdcmAssertAlwaysMacro( dynamic_cast(&GetValue()) ); } //#ifndef NDEBUG // check consistency in Length: if( GetByteValue() ) { assert( ValueField->GetLength() == ValueLengthField ); } //else if( GetSequenceOfItems() ) else if( const SequenceOfItems *sqi = dynamic_cast(&GetValue()) ) { assert( ValueField->GetLength() == ValueLengthField ); // Recompute the total length: if( !ValueLengthField.IsUndefined() ) { VL dummy = sqi->template ComputeLength(); gdcmAssertAlwaysMacro( dummy == ValueLengthField ); } } else if( GetSequenceOfFragments() ) { assert( ValueField->GetLength() == ValueLengthField ); } //#endif // We have the length we should be able to write the value if( VRField == VR::UN && ValueLengthField.IsUndefined() ) { assert( TagField == Tag(0x7fe0,0x0010) || GetValueAsSQ() ); ValueIO::Write(os,*ValueField); } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION else if( VRField == VR::INVALID && dynamic_cast(&*ValueField) ) { // We have pretended so far that the Sequence was encoded as UN. Well the real // troubles is that we cannot store the length as explicit length, otherwise // we will loose the SQ, therefore change the length into undefined length // and add a seq del item: ValueIO::Write(os,*ValueField); if( !ValueLengthField.IsUndefined() ) { // eg. TestWriter with ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm // seq del item is not stored, write it ! const Tag seqDelItem(0xfffe,0xe0dd); seqDelItem.Write(os); VL zero = 0; zero.Write(os); } } #endif else { bool failed; if( VRField & VR::VRASCII || VRField == VR::INVALID ) { failed = !ValueIO::Write(os,*ValueField); } else { assert( VRField & VR::VRBINARY ); unsigned int vrsize = VRField.GetSize(); assert( vrsize == 1 || vrsize == 2 || vrsize == 4 || vrsize == 8 ); if(VRField == VR::AT) vrsize = 2; switch(vrsize) { case 1: failed = !ValueIO::Write(os,*ValueField); break; case 2: failed = !ValueIO::Write(os,*ValueField); break; case 4: failed = !ValueIO::Write(os,*ValueField); break; case 8: failed = !ValueIO::Write(os,*ValueField); break; default: failed = true; assert(0); } } if( failed ) { assert( 0 && "Should not happen" ); } } } return os; } } // end namespace gdcm_ns #endif // GDCMEXPLICITDATAELEMENT_TXX GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmExplicitImplicitDataElement.cxx000066400000000000000000000035761412732066400314210ustar00rootroot00000000000000/*========================================================================= 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 "gdcmExplicitImplicitDataElement.h" #include "gdcmSequenceOfItems.h" #include "gdcmSequenceOfFragments.h" namespace gdcm { //----------------------------------------------------------------------------- VL ExplicitImplicitDataElement::GetLength() const { if( ValueLengthField.IsUndefined() ) { assert( ValueField->GetLength().IsUndefined() ); Value *p = ValueField; // If this is a SQ we need to compute it's proper length SequenceOfItems *sq = dynamic_cast(p); // TODO can factor the code: if( sq ) { return TagField.GetLength() + VRField.GetLength() + ValueLengthField.GetLength() + sq->ComputeLength(); } SequenceOfFragments *sf = dynamic_cast(p); if( sf ) { assert( VRField & (VR::OB | VR::OW) ); return TagField.GetLength() + VRField.GetLength() + ValueLengthField.GetLength() + sf->ComputeLength(); } assert(0); return 0; } else { // Each time VR::GetLength() is 2 then Value Length is coded in 2 // 4 then Value Length is coded in 4 assert( !ValueField || ValueField->GetLength() == ValueLengthField ); return TagField.GetLength() + 2*VRField.GetLength() + ValueLengthField; } } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmExplicitImplicitDataElement.h000066400000000000000000000035001412732066400310310ustar00rootroot00000000000000/*========================================================================= 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 GDCMEXPLICITIMPLICITDATAELEMENT_H #define GDCMEXPLICITIMPLICITDATAELEMENT_H #include "gdcmDataElement.h" namespace gdcm { // Data Element (ExplicitImplicit) /** * \brief Class to read/write a DataElement as ExplicitImplicit Data Element * \note This only happen for some Philips images * Should I derive from ExplicitDataElement instead ? * This is the class that is the closest the GDCM1.x parser. At each element we try first * to read it as explicit, if this fails, then we try again as an implicit element. */ class GDCM_EXPORT ExplicitImplicitDataElement : public DataElement { public: VL GetLength() const; template std::istream &Read(std::istream &is); template std::istream &ReadPreValue(std::istream &is); template std::istream &ReadValue(std::istream &is, bool readvalues = true); template std::istream &ReadWithLength(std::istream &is, VL & length) { (void)length; return Read(is); } // PURPOSELY do not provide an implementation for writing ! //template //const std::ostream &Write(std::ostream &os) const; }; } // end namespace gdcm #include "gdcmExplicitImplicitDataElement.txx" #endif //GDCMEXPLICITIMPLICITDATAELEMENT_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmExplicitImplicitDataElement.txx000066400000000000000000000353231412732066400314350ustar00rootroot00000000000000/*========================================================================= 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 GDCMEXPLICITIMPLICITDATAELEMENT_TXX #define GDCMEXPLICITIMPLICITDATAELEMENT_TXX #include "gdcmExplicitImplicitDataElement.h" #include "gdcmSequenceOfItems.h" #include "gdcmSequenceOfFragments.h" #include "gdcmVL.h" #include "gdcmExplicitDataElement.h" #include "gdcmImplicitDataElement.h" #include "gdcmValueIO.h" #include "gdcmSwapper.h" namespace gdcm { //----------------------------------------------------------------------------- template std::istream &ExplicitImplicitDataElement::Read(std::istream &is) { ReadPreValue(is); return ReadValue(is); } template std::istream &ExplicitImplicitDataElement::ReadPreValue(std::istream &is) { TagField.Read(is); // See PS 3.5, Data Element Structure With Explicit VR // Read Tag if( !is ) { if( !is.eof() ) // FIXME This should not be needed { assert(0 && "Should not happen" ); } return is; } if( TagField == Tag(0xfffe,0xe0dd) ) { ParseException pe; pe.SetLastElement( *this ); throw pe; } //assert( TagField != Tag(0xfeff,0xdde0) ); const Tag itemDelItem(0xfffe,0xe00d); if( TagField == itemDelItem ) { //ParseException pe; //pe.SetLastElement( *this ); //throw pe; if( !ValueLengthField.Read(is) ) { assert(0 && "Should not happen"); return is; } if( ValueLengthField ) { gdcmDebugMacro( "Item Delimitation Item has a length different from 0 and is: " << ValueLengthField ); } // Set pointer to NULL to avoid user error ValueField = nullptr; VRField = VR::INVALID; return is; } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( TagField == Tag(0x00ff, 0x4aa5) ) { //assert(0 && "Should not happen" ); // gdcmDataExtra/gdcmBreakers/DigitexAlpha_no_7FE0.dcm is.seekg( -4, std::ios::cur ); TagField = Tag(0x7fe0,0x0010); VRField = VR::OW; ValueField = new ByteValue; std::streampos s = is.tellg(); is.seekg( 0, std::ios::end); std::streampos e = is.tellg(); is.seekg( s, std::ios::beg ); ValueField->SetLength( (int32_t)(e - s) ); ValueLengthField = ValueField->GetLength(); bool failed = !ValueIO::Read(is,*ValueField,true); gdcmAssertAlwaysMacro( !failed ); return is; //throw Exception( "Unhandled" ); } #endif // Read VR try { if( !VRField.Read(is) ) { assert(0 && "Should not happen" ); return is; } // Read Value Length if( VR::GetLength(VRField) == 4 ) { if( !ValueLengthField.Read(is) ) { assert(0 && "Should not happen"); return is; } } else { // 16bits only if( !ValueLengthField.template Read16(is) ) { assert(0 && "Should not happen"); return is; } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // HACK for SIEMENS Leonardo if( ValueLengthField == 0x0006 && VRField == VR::UL && TagField.GetGroup() == 0x0009 ) { gdcmWarningMacro( "Replacing VL=0x0006 with VL=0x0004, for Tag=" << TagField << " in order to read a buggy DICOM file." ); ValueLengthField = 0x0004; } #endif } } catch( Exception &ex ) { (void)ex; VRField = VR::INVALID; is.seekg( -2, std::ios::cur ); const Tag itemStartItem(0xfffe,0xe000); if( TagField == itemStartItem ) return is; //assert( TagField != Tag(0xfffe,0xe0dd) ); // Read Value Length if( !ValueLengthField.Read(is) ) { //assert(0 && "Should not happen"); throw Exception("Impossible"); return is; } //std::cerr << "imp cur tag=" << TagField << " VL=" << ValueLengthField << std::endl; if( ValueLengthField == 0 ) { // Simple fast path ValueField = nullptr; return is; } else if( ValueLengthField.IsUndefined() ) { //assert( de.GetVR() == VR::SQ ); // FIXME what if I am reading the pixel data... //assert( TagField != Tag(0x7fe0,0x0010) ); if( TagField != Tag(0x7fe0,0x0010) ) { ValueField = new SequenceOfItems; } else { gdcmErrorMacro( "Undefined value length is impossible in non-encapsulated Transfer Syntax" ); ValueField = new SequenceOfFragments; } //VRField = VR::SQ; } else { if( true /*ValueLengthField < 8 */ ) { ValueField = new ByteValue; } else { // In the following we read 4 more bytes in the Value field // to find out if this is a SQ or not // there is still work to do to handle the PMS featured SQ // where item Start is in fact 0xfeff, 0x00e0 ... sigh const Tag itemStart(0xfffe, 0xe000); #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION const Tag itemPMSStart(0xfeff, 0x00e0); const Tag itemPMSStart2(0x3f3f, 0x3f00); #endif Tag item; // TODO FIXME // This is pretty dumb to actually read to later on seekg back, why not `peek` directly ? item.Read(is); // Maybe this code can later be rewritten as I believe that seek back // is very slow... is.seekg(-4, std::ios::cur ); if( item == itemStart ) { assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new SequenceOfItems; } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION else if ( item == itemPMSStart ) { // MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm gdcmWarningMacro( "Illegal: Explicit SQ found in a file with " "TransferSyntax=Implicit for tag: " << TagField ); // TODO: We READ Explicit ok...but we store Implicit ! // Indeed when copying the VR will be saved... pretty cool eh ? ValueField = new SequenceOfItems; ValueField->SetLength(ValueLengthField); // perform realloc try { if( !ValueIO::Read(is,*ValueField,true) ) { assert(0 && "Should not happen"); } } catch( std::exception &ex2 ) { (void)ex2; ValueLengthField = ValueField->GetLength(); } return is; } else if ( item == itemPMSStart2 && false ) { gdcmWarningMacro( "Illegal: SQ start with " << itemPMSStart2 << " instead of " << itemStart << " for tag: " << TagField ); ValueField = new SequenceOfItems; ValueField->SetLength(ValueLengthField); // perform realloc if( !ValueIO::Read(is,*ValueField,true) ) { assert(0 && "Should not happen"); } return is; } #endif else { ValueField = new ByteValue; } } } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // THE WORST BUG EVER. From GE Workstation if( ValueLengthField == 13 ) { // Historically gdcm did not enforce proper length // thus Theralys started writing illegal DICOM images: const Tag theralys1(0x0008,0x0070); const Tag theralys2(0x0008,0x0080); if( TagField != theralys1 && TagField != theralys2 ) { gdcmWarningMacro( "GE,13: Replacing VL=0x000d with VL=0x000a, for Tag=" << TagField << " in order to read a buggy DICOM file." ); ValueLengthField = 10; } } #endif #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( ValueLengthField == 0x31f031c && TagField == Tag(0x031e,0x0324) ) { // TestImages/elbow.pap gdcmWarningMacro( "Replacing a VL. To be able to read a supposively" "broken Payrus file." ); ValueLengthField = 202; // 0xca } #endif // We have the length we should be able to read the value ValueField->SetLength(ValueLengthField); // perform realloc if( !ValueIO::Read(is,*ValueField,true) ) { // Special handling for PixelData tag: #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( TagField == Tag(0x7fe0,0x0010) ) { gdcmWarningMacro( "Incomplete Pixel Data found, use file at own risk" ); is.clear(); } else #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */ { throw Exception("Should not happen (imp)"); } return is; } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // dcmtk 3.5.4 is resilient to broken explicit SQ length and will properly recompute it // as long as each of the Item lengths are correct VL dummy = ValueField->GetLength(); if( ValueLengthField != dummy ) { gdcmWarningMacro( "ValueLengthField was bogus" ); assert(0); ValueLengthField = dummy; } #else assert( ValueLengthField == ValueField->GetLength() ); assert( VRField == VR::INVALID ); #endif return is; } //std::cerr << "exp cur tag=" << TagField << " VR=" << VRField << " VL=" << ValueLengthField << std::endl; // // I don't like the following 3 lines, what if 0000,0000 was indeed -wrongly- sent, we should be able to continue // chances is that 99% of times there is now way we can reach here, so safely throw an exception if( TagField == Tag(0x0000,0x0000) && ValueLengthField == 0 && VRField == VR::INVALID ) { ParseException pe; pe.SetLastElement( *this ); throw pe; } #ifdef ELSCINT1_01F7_1070 if( TagField == Tag(0x01f7,0x1070) ) { ValueLengthField = ValueLengthField - 7; } #endif return is; } template std::istream &ExplicitImplicitDataElement::ReadValue(std::istream &is, bool readvalues) { if( is.eof() ) return is; /* thechnically the following is bad it assumes that in the case of explicit/implicit dataset we are not handle the prevalue call properly for buggy implicit attribute */ if( VRField == VR::INVALID ) return is; if( ValueLengthField == 0 ) { // Simple fast path ValueField = nullptr; return is; } // Read the Value //assert( ValueField == 0 ); if( VRField == VR::SQ ) { // Check whether or not this is an undefined length sequence assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new SequenceOfItems; } else if( ValueLengthField.IsUndefined() ) { if( VRField == VR::UN ) { // Support cp246 conforming file: // Enhanced_MR_Image_Storage_PixelSpacingNotIn_0028_0030.dcm (illegal) // vs // undefined_length_un_vr.dcm assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new SequenceOfItems; ValueField->SetLength(ValueLengthField); // perform realloc try { //if( !ValueIO::Read(is,*ValueField) ) // non cp246 if( !ValueIO::Read(is,*ValueField,readvalues) ) // cp246 compliant { assert(0); } } catch( std::exception &) { // Must be one of those non-cp246 file... // but for some reason seekg back to previous offset + Read // as Explicit does not work... ParseException pe; pe.SetLastElement(*this); throw pe; } return is; } else { // Ok this is Pixel Data fragmented... assert( TagField == Tag(0x7fe0,0x0010) ); assert( VRField & VR::OB_OW ); ValueField = new SequenceOfFragments; } } else { //assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new ByteValue; } // We have the length we should be able to read the value this->SetValueFieldLength( ValueLengthField, readvalues ); #if defined(GDCM_SUPPORT_BROKEN_IMPLEMENTATION) && 0 // PHILIPS_Intera-16-MONO2-Uncompress.dcm if( TagField == Tag(0x2001,0xe05f) || TagField == Tag(0x2001,0xe100) || TagField == Tag(0x2005,0xe080) || TagField == Tag(0x2005,0xe083) || TagField == Tag(0x2005,0xe084) || TagField == Tag(0x2005,0xe402) //TagField.IsPrivate() && VRField == VR::SQ //-> Does not work for 0029 //we really need to read item marker ) { gdcmWarningMacro( "ByteSwaping Private SQ: " << TagField ); assert( VRField == VR::SQ ); assert( TagField.IsPrivate() ); try { if( !ValueIO::Read(is,*ValueField,readvalues) ) { assert(0 && "Should not happen"); } Value* v = &*ValueField; SequenceOfItems *sq = dynamic_cast(v); assert( sq ); SequenceOfItems::Iterator it = sq->Begin(); for( ; it != sq->End(); ++it) { Item &item = *it; DataSet &ds = item.GetNestedDataSet(); ByteSwapFilter bsf(ds); bsf.ByteSwap(); } } catch( std::exception &ex ) { ValueLengthField = ValueField->GetLength(); } return is; } #endif bool failed; //assert( VRField != VR::UN ); if( VRField & VR::VRASCII ) { //assert( VRField.GetSize() == 1 ); failed = !ValueIO::Read(is,*ValueField,readvalues); } else { assert( VRField & VR::VRBINARY ); unsigned int vrsize = VRField.GetSize(); assert( vrsize == 1 || vrsize == 2 || vrsize == 4 || vrsize == 8 ); if(VRField==VR::AT) vrsize = 2; switch(vrsize) { case 1: failed = !ValueIO::Read(is,*ValueField,readvalues); break; case 2: failed = !ValueIO::Read(is,*ValueField,readvalues); break; case 4: failed = !ValueIO::Read(is,*ValueField,readvalues); break; case 8: failed = !ValueIO::Read(is,*ValueField,readvalues); break; default: failed = true; assert(0); } } if( failed ) { #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( TagField == Tag(0x7fe0,0x0010) ) { // BUG this should be moved to the ImageReader class, only this class knows // what 7fe0 actually is, and should tolerate partial Pixel Data element... // PMS-IncompletePixelData.dcm gdcmWarningMacro( "Incomplete Pixel Data found, use file at own risk" ); is.clear(); } else #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */ { // Might be the famous UN 16bits ParseException pe; pe.SetLastElement( *this ); throw pe; } return is; } return is; } } // end namespace gdcm #endif // GDCMEXPLICITIMPLICITDATAELEMENT_TXX GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmFile.cxx000066400000000000000000000016471412732066400247150ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFile.h" namespace gdcm_ns { // Keep cstor and dstor here to keep API minimal (see dllexport issue with gdcmstrict::) File::File() = default; File::~File() = default; std::istream &File::Read(std::istream &is) { assert(0); return is; } std::ostream const &File::Write(std::ostream &os) const { assert(0); return os; } } // end namespace gdcm_ns GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmFile.h000066400000000000000000000041621412732066400243350ustar00rootroot00000000000000/*========================================================================= 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 GDCMFILE_H #define GDCMFILE_H #include "gdcmObject.h" #include "gdcmDataSet.h" #include "gdcmFileMetaInformation.h" namespace gdcm_ns { /** * \brief a DICOM File * \details See PS 3.10 File: A File is an ordered string of zero or more bytes, where * the first byte is at the beginning of the file and the last byte at the end * of the File. Files are identified by a unique File ID and may by written, * read and/or deleted. * * \see Reader Writer */ class GDCM_EXPORT File : public Object { public: File(); ~File() override; friend std::ostream &operator<<(std::ostream &os, const File &val); /// Read std::istream &Read(std::istream &is); /// Write std::ostream const &Write(std::ostream &os) const; /// Get File Meta Information const FileMetaInformation &GetHeader() const { return Header; } /// Get File Meta Information FileMetaInformation &GetHeader() { return Header; } /// Set File Meta Information void SetHeader( const FileMetaInformation &fmi ) { Header = fmi; } /// Get Data Set const DataSet &GetDataSet() const { return DS; } /// Get Data Set DataSet &GetDataSet() { return DS; } /// Set Data Set void SetDataSet( const DataSet &ds) { DS = ds; } private: FileMetaInformation Header; DataSet DS; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const File &val) { os << val.GetHeader() << std::endl; //os << val.GetDataSet() << std::endl; // FIXME assert(0); return os; } } // end namespace gdcm_ns #endif //GDCMFILE_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmFileMetaInformation.cxx000066400000000000000000000717711412732066400277370ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileMetaInformation.h" #include "gdcmAttribute.h" #include "gdcmVR.h" #include "gdcmExplicitDataElement.h" #include "gdcmImplicitDataElement.h" #include "gdcmByteValue.h" #include "gdcmSwapper.h" #include "gdcmException.h" #include "gdcmTagToType.h" //#include "gdcmUIDGenerator.h" #include "gdcmTag.h" namespace gdcm_ns { const char FileMetaInformation::GDCM_FILE_META_INFORMATION_VERSION[] = "\0\1"; const char FileMetaInformation::GDCM_IMPLEMENTATION_CLASS_UID[] = "1.2.826.0.1.3680043.2.1143.107.104.103.115." GDCM_VERSION; const char FileMetaInformation::GDCM_IMPLEMENTATION_VERSION_NAME[] = "GDCM " GDCM_VERSION; const char FileMetaInformation::GDCM_SOURCE_APPLICATION_ENTITY_TITLE[] = "GDCM"; // Default initialize those static std::string, with GDCM values: std::string FileMetaInformation::ImplementationClassUID = GetGDCMImplementationClassUID(); std::string FileMetaInformation::ImplementationVersionName = GetGDCMImplementationVersionName(); std::string FileMetaInformation::SourceApplicationEntityTitle = GetGDCMSourceApplicationEntityTitle(); const char * FileMetaInformation::GetFileMetaInformationVersion() { return GDCM_FILE_META_INFORMATION_VERSION; } const char * FileMetaInformation::GetGDCMImplementationClassUID() { return GDCM_IMPLEMENTATION_CLASS_UID; } const char * FileMetaInformation::GetGDCMImplementationVersionName() { return GDCM_IMPLEMENTATION_VERSION_NAME; } const char * FileMetaInformation::GetGDCMSourceApplicationEntityTitle() { return GDCM_SOURCE_APPLICATION_ENTITY_TITLE; } // Keep cstor and dstor here to keep API minimal (see dllexport issue with gdcmstrict::) FileMetaInformation::FileMetaInformation():DataSetTS(TransferSyntax::TS_END),MetaInformationTS(TransferSyntax::Unknown),DataSetMS(MediaStorage::MS_END) {} FileMetaInformation::~FileMetaInformation() = default; void FileMetaInformation::SetImplementationClassUID(const char * imp) { // TODO: it would be nice to make sure imp is actually a valid UID if( imp ) { ImplementationClassUID = imp; } } void FileMetaInformation::AppendImplementationClassUID(const char * imp) { if( imp ) { ImplementationClassUID = GetGDCMImplementationClassUID(); ImplementationClassUID += "."; ImplementationClassUID += imp; } } void FileMetaInformation::SetImplementationVersionName(const char * version) { if( version ) { // Simply override the value since we cannot have more than 16bytes... gdcmAssertAlwaysMacro( strlen(version) <= 16 ); //ImplementationVersionName = GetGDCMImplementationVersionName(); //ImplementationVersionName += "-"; //ImplementationVersionName += version; ImplementationVersionName = version; } } void FileMetaInformation::SetSourceApplicationEntityTitle(const char * title) { if( title ) { //SourceApplicationEntityTitle = GetGDCMSourceApplicationEntityTitle(); //SourceApplicationEntityTitle += "/"; AEComp ae( title ); SourceApplicationEntityTitle = ae.Truncate(); } } const char *FileMetaInformation::GetImplementationClassUID() { return ImplementationClassUID.c_str(); } const char *FileMetaInformation::GetImplementationVersionName() { return ImplementationVersionName.c_str(); } const char *FileMetaInformation::GetSourceApplicationEntityTitle() { return SourceApplicationEntityTitle.c_str(); } void FileMetaInformation::FillFromDataSet(DataSet const &ds) { // Example: CR-MONO1-10-chest.dcm is missing a file meta header: DataElement xde; // File Meta Information Version (0002,0001) -> computed if( !FindDataElement( Tag(0x0002, 0x0001) ) ) { xde.SetTag( Tag(0x0002, 0x0001) ); xde.SetVR( VR::OB ); const char *version = FileMetaInformation::GetFileMetaInformationVersion(); xde.SetByteValue( version, 2 /*strlen(version)*/ ); Insert( xde ); } else { const DataElement &de = GetDataElement( Tag(0x0002,0x0001) ); const ByteValue *bv = de.GetByteValue(); if( bv->GetLength() != 2 || memcmp( bv->GetPointer(), FileMetaInformation::GetFileMetaInformationVersion(), 2 ) != 0 ) { xde.SetTag( Tag(0x0002, 0x0001) ); xde.SetVR( VR::OB ); const char *version = FileMetaInformation::GetFileMetaInformationVersion(); xde.SetByteValue( version, 2 /*strlen(version)*/ ); Replace( xde ); } } // Media Storage SOP Class UID (0002,0002) -> see (0008,0016) if( !FindDataElement( Tag(0x0002, 0x0002) ) || GetDataElement( Tag(0x0002,0x0002) ).IsEmpty() ) { if( !ds.FindDataElement( Tag(0x0008, 0x0016) ) || ds.GetDataElement( Tag(0x0008,0x0016) ).IsEmpty() ) { MediaStorage ms; ms.SetFromModality(ds); const char *msstr = ms.GetString(); if( msstr ) { VL::Type strlenMsstr = (VL::Type) strlen(msstr); xde.SetByteValue( msstr, strlenMsstr ); xde.SetTag( Tag(0x0002, 0x0002) ); { xde.SetVR( VR::UI ); } Insert( xde ); } else { gdcmErrorMacro( "Could not find MediaStorage" ); } } else { const DataElement& msclass = ds.GetDataElement( Tag(0x0008, 0x0016) ); xde = msclass; xde.SetTag( Tag(0x0002, 0x0002) ); if( msclass.GetVR() == VR::UN || msclass.GetVR() == VR::INVALID ) { xde.SetVR( VR::UI ); } Insert( xde ); } } else // Ok there is a value in (0002,0002) let see if it match (0008,0016) { bool dicomdir = ds.FindDataElement( Tag(0x0004, 0x1220) ); // Directory Record Sequence (void)dicomdir; //if( !dicomdir ) { if( !ds.FindDataElement( Tag(0x0008, 0x0016) ) ) { // What should I do here ?? gdcmWarningMacro( "Missing SOPClassUID in DataSet but found in FileMeta" ); } else { const DataElement& sopclass = ds.GetDataElement( Tag(0x0008, 0x0016) ); DataElement mssopclass = GetDataElement( Tag(0x0002, 0x0002) ); assert( !mssopclass.IsEmpty() ); const ByteValue *bv = sopclass.GetByteValue(); if( bv ) { mssopclass.SetByteValue( bv->GetPointer(), bv->GetLength() ); } else { throw gdcm::Exception( "SOP Class is empty sorry" ); } Replace( mssopclass ); } } } // Media Storage SOP Instance UID (0002,0003) -> see (0008,0018) const DataElement &dummy = GetDataElement(Tag(0x0002,0x0003)); (void)dummy; if( !FindDataElement( Tag(0x0002, 0x0003) ) || GetDataElement( Tag(0x0002,0x0003) ).IsEmpty() ) { if( ds.FindDataElement( Tag(0x0008, 0x0018) ) ) { const DataElement& msinst = ds.GetDataElement( Tag(0x0008, 0x0018) ); if( msinst.IsEmpty() ) { // Ok there is nothing... //UIDGenerator uid; //const char *s = uid.Generate(); //xde.SetByteValue( s, strlen(s) ); // FIXME somebody before should make sure there is something... xde = msinst; } else { xde = msinst; } xde.SetTag( Tag(0x0002, 0x0003) ); if( msinst.GetVR() == VR::UN || msinst.GetVR() == VR::INVALID ) { xde.SetVR( VR::UI ); } Replace( xde ); } else { //assert(0); throw gdcm::Exception( "No 2,3 and 8,18 element sorry" ); } } else // Ok there is a value in (0002,0003) let see if it match (0008,0018) { bool dirrecsq = ds.FindDataElement( Tag(0x0004, 0x1220) ); // Directory Record Sequence MediaStorage ms; ms.SetFromHeader( *this ); bool dicomdir = (ms == MediaStorage::MediaStorageDirectoryStorage && dirrecsq); if( !dicomdir ) { if( !ds.FindDataElement( Tag(0x0008, 0x0018) ) || ds.GetDataElement( Tag(0x0008, 0x0018) ).IsEmpty() ) { throw gdcm::Exception( "No 8,18 element sorry" ); //assert(0); } const DataElement& sopinst = ds.GetDataElement( Tag(0x0008, 0x0018) ); //const DataElement & foo = GetDataElement( Tag(0x0002, 0x0003) ); assert( !GetDataElement( Tag(0x0002, 0x0003) ).IsEmpty() ); DataElement mssopinst = GetDataElement( Tag(0x0002, 0x0003) ); const ByteValue *bv = sopinst.GetByteValue(); assert( bv ); mssopinst.SetByteValue( bv->GetPointer(), bv->GetLength() ); Replace( mssopinst ); } } //assert( !GetDataElement( Tag(0x0002,0x0003) ).IsEmpty() ); // Transfer Syntax UID (0002,0010) -> ??? (computed at write time at most) if( FindDataElement( Tag(0x0002, 0x0010) ) && !GetDataElement( Tag(0x0002,0x0010) ).IsEmpty() ) { DataElement tsuid = GetDataElement( Tag(0x0002, 0x0010) ); const char * datasetts = DataSetTS.GetString(); const ByteValue * bv = tsuid.GetByteValue(); assert( bv ); std::string currentts( bv->GetPointer(), bv->GetPointer() + bv->GetLength() ); if( strlen(currentts.c_str()) != strlen(datasetts) || strcmp( currentts.c_str(), datasetts ) != 0 ) { xde = tsuid; VL::Type strlenDatasetts = (VL::Type) strlen(datasetts); xde.SetByteValue( datasetts, strlenDatasetts ); Replace( xde ); } if( tsuid.GetVR() != VR::UI ) { xde = tsuid; xde.SetVR( VR::UI ); Replace( xde ); } } else { // Very bad !! //throw Exception( "No (0002,0010) element found" ); // Construct it from DataSetTS if( DataSetTS == TransferSyntax::TS_END ) { throw gdcm::Exception( "No TransferSyntax specified." ); } const char* str = TransferSyntax::GetTSString(DataSetTS); VL::Type strlenStr = (VL::Type) strlen(str); xde.SetByteValue( str, strlenStr ); xde.SetVR( VR::UI ); xde.SetTag( Tag(0x0002,0x0010) ); Insert( xde ); } // Implementation Class UID (0002,0012) -> ?? if( !FindDataElement( Tag(0x0002, 0x0012) ) ) { xde.SetTag( Tag(0x0002, 0x0012) ); xde.SetVR( VR::UI ); //const char implementation[] = GDCM_IMPLEMENTATION_CLASS_UID; const char *implementation = FileMetaInformation::GetImplementationClassUID(); VL::Type strlenImplementation = (VL::Type) strlen(implementation); xde.SetByteValue( implementation, strlenImplementation ); Insert( xde ); } else { // TODO: Need to check Implementation UID is actually a valid UID... //const DataElement& impuid = GetDataElement( Tag(0x0002, 0x0012) ); //const ByteValue *bv = impuid.GetByteValue(); //assert( bv ); //std::string copy( bv->GetPointer(), bv->GetLength() ); //if( !UIDGenerator::IsValid( copy.c_str() ) ) // { //const char *implementation = FileMetaInformation::GetImplementationClassUID(); //impuid.SetByteValue( implementation, strlen(implementation) ); // } } // Implementation Version Name (0002,0013) -> ?? if( !FindDataElement( Tag(0x0002, 0x0013) ) ) { xde.SetTag( Tag(0x0002, 0x0013) ); xde.SetVR( VR::SH ); //const char version[] = GDCM_IMPLEMENTATION_VERSION_NAME; SHComp version = FileMetaInformation::GetImplementationVersionName(); VL::Type strlenVersion = (VL::Type)strlen(version); xde.SetByteValue( version, strlenVersion ); Insert( xde ); } // Source Application Entity Title (0002,0016) -> ?? if( !FindDataElement( Tag(0x0002, 0x0016) ) ) { xde.SetTag( Tag(0x0002, 0x0016) ); xde.SetVR( VR::AE ); //const char title[] = GDCM_SOURCE_APPLICATION_ENTITY_TITLE; const char *title = FileMetaInformation::GetSourceApplicationEntityTitle(); VL::Type strlenTitle = (VL::Type)strlen(title); xde.SetByteValue( title, strlenTitle ); Insert( xde ); } // Do this one last ! // (Meta) Group Length (0002,0000) -> computed Attribute<0x0002, 0x0000> filemetagrouplength; Remove( filemetagrouplength.GetTag() ); unsigned int glen = GetLength(); assert( (glen % 2) == 0 ); filemetagrouplength.SetValue( glen ); Insert( filemetagrouplength.GetAsDataElement() ); assert( !IsEmpty() ); } // FIXME // This code should clearly be rewritten with some template meta-programming to // enable reuse of code... // // \postcondition after the file meta information (well before the dataset...) template bool ReadExplicitDataElement(std::istream &is, ExplicitDataElement &de) { // Read Tag std::streampos start = is.tellg(); //std::cout << "Start: " << start << std::endl; Tag t; if( !t.template Read(is) ) { assert(0 && "Should not happen" ); return false; } //std::cout << "Tag: " << t << std::endl; if( t.GetGroup() != 0x0002 ) { //gdcmDebugMacro( "Done reading File Meta Information" ); std::streampos currentpos = is.tellg(); // old code was fseeking from the beginning of file // which seems to be quite different than fseeking in reverse from // the current position... ??? //is.seekg( start, std::ios::beg ); assert( (start - currentpos) <= 0); assert( (int)(start - currentpos) == -4 ); is.seekg( (start - currentpos), std::ios::cur ); return false; } // Read VR VR vr; if( !vr.Read(is) ) { is.seekg( start, std::ios::beg ); return false; } //std::cout << "VR : " << vr << std::endl; // Read Value Length VL vl; if( vr & VR::VL32 ) { if( !vl.template Read(is) ) { assert(0 && "Should not happen"); return false; } } else { // Value Length is stored on 16bits only vl.template Read16(is); } //gdcmDebugMacro( "VL : " << vl ); // Read the Value ByteValue *bv = nullptr; if( vr == VR::SQ ) { assert(0 && "Should not happen"); return false; } else if( vl.IsUndefined() ) { assert(0 && "Should not happen"); return false; } else { bv = new ByteValue; } // We have the length we should be able to read the value bv->SetLength(vl); // perform realloc if( !bv->template Read(is) ) { assert(0 && "Should not happen"); return false; } //std::cout << "Value : "; //bv->Print( std::cout ); //std::cout << std::endl; assert( bv->GetLength() == vl ); de.SetTag(t); de.SetVR(vr); de.SetVL(vl); // FIXME: There should be a way to set the Value to the NULL pointer... de.SetValue(*bv); // if( vl == 0 ) // { // assert( de.IsEmpty() ); // } return true; } template bool ReadImplicitDataElement(std::istream &is, ImplicitDataElement &de) { // See PS 3.5, 7.1.3 Data Element Structure With Implicit VR std::streampos start = is.tellg(); // Read Tag Tag t; if( !t.template Read(is) ) { assert(0 && "Should not happen"); return false; } //std::cout << "Tag: " << t << std::endl; if( t.GetGroup() != 0x0002 ) { gdcmDebugMacro( "Done reading File Meta Information" ); is.seekg( start, std::ios::beg ); return false; } // Read Value Length VL vl; if( !vl.template Read(is) ) { assert(0 && "Should not happen"); return false; } ByteValue *bv = nullptr; if( vl.IsUndefined() ) { assert(0 && "Should not happen"); return false; } else { bv = new ByteValue; } // We have the length we should be able to read the value bv->SetLength(vl); // perform realloc if( !bv->template Read(is) ) { assert(0 && "Should not happen"); return false; } de.SetTag(t); de.SetVL(vl); de.SetValue(*bv); return true; } /* * Except for the 128 bytes preamble and the 4 bytes prefix, the File Meta * Information shall be encoded using the Explicit VR Little Endian Transfer * Syntax (UID=1.2.840.10008.1.2.1) as defined in DICOM PS 3.5. * Values of each File Meta Element shall be padded when necessary to achieve * an even length as specified in PS 3.5 by their corresponding Value * Representation. For compatibility with future versions of this Standard, * any Tag (0002,xxxx) not defined in Table 7.1-1 shall be ignored. * Values of all Tags (0002,xxxx) are reserved for use by this Standard and * later versions of DICOM. * Note: PS 3.5 specifies that Elements with Tags (0001,xxxx), (0003,xxxx), * (0005,xxxx), and (0007,xxxx) shall not be used. */ /// \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... std::istream &FileMetaInformation::Read(std::istream &is) { //ExplicitAttribute<0x0002,0x0000> metagl; //metagl.Read(is); std::streampos start = is.tellg(); // TODO: Can now load data from std::ios::cur to std::ios::cur + metagl.GetValue() ExplicitDataElement xde; Tag gl; gl.Read(is); if( gl.GetGroup() != 0x2 ) throw Exception( "INVALID" ); if( gl.GetElement() != 0x0 ) throw Exception( "INVALID" ); VR vr; vr.Read(is); if( vr == VR::INVALID ) throw Exception( "INVALID" ); if( vr != VR::UL ) throw Exception( "INVALID" ); // TODO FIXME: I should not do seekg for valid file this is costly is.seekg(-6,std::ios::cur); // /opt/ibmcmp/vacpp/9.0/bin/xlC: 1501-230 (S) Internal compiler error; please contact your Service Representative //#if !defined(__xlC__) xde.Read(is); //#endif Insert( xde ); // See PS 3.5, Data Element Structure With Explicit VR try { // GDCM is a hack, so let's read all possible group 2 element, until the last one // and leave the group length value aside. while( ReadExplicitDataElement(is, xde ) ) { Insert( xde ); } } catch( std::exception & ex ) { (void)ex; // we've read a little bit too much. We are possibly in the case where an // implicit dataelement with group 2 (technically impossible) was found // (first dataelement). Let's start over again, but this time use group // length as the sentinel for the last group 2 element: is.seekg(start,std::ios::beg); // Group Length: ReadExplicitDataElement(is, xde ); Attribute<0x0002, 0x0000> filemetagrouplength; filemetagrouplength.SetFromDataElement( xde ); const unsigned int glen = filemetagrouplength.GetValue(); unsigned int cur_len = 0; while( cur_len < glen && ReadExplicitDataElement(is, xde ) ) { Insert( xde ); cur_len += xde.GetLength(); } } // Now is a good time to compute the transfer syntax: ComputeDataSetTransferSyntax(); // we are at the end of the meta file information and before the dataset return is; } std::istream &FileMetaInformation::ReadCompat(std::istream &is) { // \precondition assert( is.good() ); // First off save position in case we fail (no File Meta Information) // See PS 3.5, Data Element Structure With Explicit VR if( !IsEmpty() ) { throw Exception( "Serious bug" ); } Tag t; if( !t.Read(is) ) { throw Exception( "Cannot read very first tag" ); } if( t.GetGroup() == 0x0002 ) { // GE_DLX-8-MONO2-PrivateSyntax.dcm is in Implicit... return ReadCompatInternal(is); } else if( t.GetGroup() == 0x0008 ) // { char vr_str[3]; is.read(vr_str, 2); vr_str[2] = '\0'; VR::VRType vr = VR::GetVRType(vr_str); if( vr != VR::VR_END ) { // File start with a 0x0008 element but no FileMetaInfo and is Explicit DataSetTS = TransferSyntax::ExplicitVRLittleEndian; } else { // File start with a 0x0008 element but no FileMetaInfo and is Implicit DataSetTS = TransferSyntax::ImplicitVRLittleEndian; } is.seekg(-6, std::ios::cur); // Seek back } else if( t.GetGroup() == 0x0800 ) // Good ol' ACR NEMA { char vr_str[3]; is.read(vr_str, 2); vr_str[2] = '\0'; VR::VRType vr = VR::GetVRType(vr_str); if( vr != VR::VR_END ) { // File start with a 0x0008 element but no FileMetaInfo and is Explicit DataSetTS = TransferSyntax::ExplicitVRBigEndian; } else { // File start with a 0x0008 element but no FileMetaInfo and is Implicit DataSetTS = TransferSyntax::ImplicitVRBigEndianACRNEMA; } is.seekg(-6, std::ios::cur); // Seek back } else if( t.GetElement() == 0x0010 ) // Hum, is it a private creator ? { char vr_str[3]; is.read(vr_str, 2); vr_str[2] = '\0'; VR::VRType vr = VR::GetVRType(vr_str); if( vr != VR::VR_END ) { DataSetTS = TransferSyntax::ExplicitVRLittleEndian; } else { DataSetTS = TransferSyntax::ImplicitVRLittleEndian; } is.seekg(-6, std::ios::cur); // Seek back } else { //assert( t.GetElement() == 0x0 ); char vr_str[3]; VR::VRType vr = VR::VR_END; if( is.read(vr_str, 2) ) { vr_str[2] = '\0'; vr = VR::GetVRType(vr_str); } else { throw Exception( "Impossible: cannot read 2bytes for VR" ); } is.seekg(-6, std::ios::cur); // Seek back if( vr != VR::VR_END ) { // Ok we found a VR, this is 99% likely to be our safe bet if( t.GetGroup() > 0xff || t.GetElement() > 0xff ) DataSetTS = TransferSyntax::ExplicitVRBigEndian; else DataSetTS = TransferSyntax::ExplicitVRLittleEndian; } else { DataElement null( Tag(0x0,0x0), 0); ImplicitDataElement ide; ide.ReadPreValue(is); if( ide.GetTag() == null.GetTag() && ide.GetVL() == 4 ) { // This is insane, we are actually reading an attribute with tag (0,0) ! // something like IM-0001-0066.CommandTag00.dcm was crafted ide.ReadValue(is); ReadCompat(is); // this will read the next element assert( DataSetTS == TransferSyntax::ImplicitVRLittleEndian ); is.seekg(-12, std::ios::cur); // Seek back return is; } // else throw Exception( "Cannot find DICOM type. Giving up." ); } } return is; } #define ADDVRIMPLICIT( element ) \ case element: \ de.SetVR( (VR::VRType)TagToType<0x0002,element>::VRType ); \ break bool AddVRToDataElement(DataElement &de) { switch(de.GetTag().GetElement()) { ADDVRIMPLICIT(0x0000); ADDVRIMPLICIT(0x0001); ADDVRIMPLICIT(0x0002); ADDVRIMPLICIT(0x0003); ADDVRIMPLICIT(0x0010); ADDVRIMPLICIT(0x0012); ADDVRIMPLICIT(0x0013); ADDVRIMPLICIT(0x0016); ADDVRIMPLICIT(0x0100); ADDVRIMPLICIT(0x0102); default: return false; } return true; } template std::istream &FileMetaInformation::ReadCompatInternal(std::istream &is) { //assert( t.GetGroup() == 0x0002 ); // if( t.GetGroup() == 0x0002 ) { // Purposely not Re-use ReadVR since we can read VR_END char vr_str0[2]; is.read(vr_str0, 2); if( VR::IsValid(vr_str0) ) { MetaInformationTS = TransferSyntax::Explicit; // Hourah ! // Looks like an Explicit File Meta Information Header. is.seekg(-6, std::ios::cur); // Seek back //is.seekg(start, std::ios::beg); // Seek back //std::streampos dpos = is.tellg(); ExplicitDataElement xde; while( ReadExplicitDataElement(is, xde ) ) { //std::cout << xde << std::endl; if( xde.GetVR() == VR::UN ) { gdcmWarningMacro( "VR::UN found in file Meta header. " "VR::UN will be replaced with proper VR for tag: " << xde.GetTag() ); AddVRToDataElement(xde); } Insert( xde ); } // Now is a good time to find out the dataset transfer syntax ComputeDataSetTransferSyntax(); } else { MetaInformationTS = TransferSyntax::Implicit; gdcmWarningMacro( "File Meta Information is implicit. VR will be explicitly added" ); // Ok this might be an implicit encoded Meta File Information header... // GE_DLX-8-MONO2-PrivateSyntax.dcm is.seekg(-6, std::ios::cur); // Seek back ImplicitDataElement ide; while( ReadImplicitDataElement(is, ide ) ) { if( AddVRToDataElement(ide) ) { Insert(ide); } else { gdcmWarningMacro( "Unknown element found in Meta Header: " << ide.GetTag() ); } } // Now is a good time to find out the dataset transfer syntax try { ComputeDataSetTransferSyntax(); } catch( gdcm::Exception & ) { // We were able to read some of the Meta Header, but failed to compute the DataSetTS // technically GDCM is able to cope with any value here. But be kind and try to have a good guess: gdcmWarningMacro( "Meta Header is bogus. Guessing DataSet TS." ); Tag t; if( !t.Read(is) ) { throw Exception( "Cannot read very first tag" ); } char vr_str[3]; is.read(vr_str, 2); vr_str[2] = '\0'; VR::VRType vr = VR::GetVRType(vr_str); if( vr != VR::VR_END ) { DataSetTS = TransferSyntax::ExplicitVRLittleEndian; } else { DataSetTS = TransferSyntax::ImplicitVRLittleEndian; } is.seekg(-6, std::ios::cur); // Seek back } } } // else // { // gdcmDebugMacro( "No File Meta Information. Start with Tag: " << t ); // is.seekg(-4, std::ios::cur); // Seek back // } // we are at the end of the meta file information and before the dataset return is; } //void FileMetaInformation::SetTransferSyntaxType(TS const &ts) //{ // //assert( DS == 0 ); // //InternalTS = ts; //} // FIXME: If any boozoo ever write a SQ in the meta header // we are in bad shape... void FileMetaInformation::ComputeDataSetTransferSyntax() { const Tag t(0x0002,0x0010); const DataElement &de = GetDataElement(t); std::string ts; const ByteValue *bv = de.GetByteValue(); if( !bv ) { throw Exception( "Unknown Transfer syntax" ); } // Pad string with a \0 ts = std::string(bv->GetPointer(), bv->GetLength()); TransferSyntax tst(TransferSyntax::GetTSType(ts.c_str())); if( tst == TransferSyntax::TS_END ) { throw Exception( "Unknown Transfer syntax" ); } DataSetTS = tst; // postcondition DataSetTS.IsValid(); } void FileMetaInformation::SetDataSetTransferSyntax(const TransferSyntax &ts) { DataSetTS = ts; } std::string FileMetaInformation::GetMediaStorageAsString() const { // D 0002|0002 [UI] [Media Storage SOP Class UID] // [1.2.840.10008.5.1.4.1.1.12.1] // ==> [X-Ray Angiographic Image Storage] const Tag t(0x0002,0x0002); if( !FindDataElement( t ) ) { gdcmDebugMacro( "File Meta information is present but does not" " contains " << t ); return ""; } const DataElement &de = GetDataElement(t); std::string ts; { const ByteValue *bv = de.GetByteValue(); assert( bv ); if( bv->GetPointer() && bv->GetLength() ) { // Pad string with a \0 ts = std::string(bv->GetPointer(), bv->GetLength()); } } // Paranoid check: if last character of a VR=UI is space let's pretend this is a \0 if( !ts.empty() ) { char &last = ts[ts.size()-1]; if( last == ' ' ) { gdcmWarningMacro( "Media Storage Class UID: " << ts << " contained a trailing space character" ); last = '\0'; } } return ts; } MediaStorage FileMetaInformation::GetMediaStorage() const { const std::string &ts = GetMediaStorageAsString(); if( ts.empty() ) return MediaStorage::MS_END; MediaStorage ms = MediaStorage::GetMSType(ts.c_str()); if( ms == MediaStorage::MS_END ) { gdcmWarningMacro( "Media Storage Class UID: " << ts << " is unknown" ); } return ms; } void FileMetaInformation::Default() { } std::ostream &FileMetaInformation::Write(std::ostream &os) const { // if( !IsValid() ) // { // gdcmErrorMacro( "File is not valid" ); // return os; // } P.Write(os); // if( IsEmpty() ) // { // std::cerr << "IsEmpty" << std::endl; // FileMetaInformation fmi; // fmi.Default(); // //fmi.Write(os); // IOSerialize::Write(os,fmi); // } // else if( IsValid() ) { this->DataSet::Write(os); } // else // { // assert(0); // } #if 0 // At least make sure to have group length //if( !DS->FindDataElement( Tag(0x0002, 0x0000) ) ) { //if( DS->GetNegociatedType() == TransferSyntax::Explicit ) { ExplicitDataElement xde( Tag(0x0002, 0x0000), 4, VR::UL ); SmartPointer bv = new ByteValue; bv->SetLength( 4 ); uint32_t len = DS->GetLength(); Element el = reinterpret_cast< Element& > ( len ); std::stringstream ss; el.Write( ss ); bv->Read( ss ); xde.SetValue( *bv ); // This is the first element, so simply write the element and // then start writing the remaining of the File Meta Information xde.Write(os); } } #endif return os; } } // end namespace gdcm_ns GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmFileMetaInformation.h000066400000000000000000000117511412732066400273540ustar00rootroot00000000000000/*========================================================================= 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 GDCMFILEMETAINFORMATION_H #define GDCMFILEMETAINFORMATION_H #include "gdcmPreamble.h" #include "gdcmDataSet.h" #include "gdcmDataElement.h" #include "gdcmMediaStorage.h" #include "gdcmTransferSyntax.h" #include "gdcmExplicitDataElement.h" namespace gdcm_ns { /** * \brief Class to represent a File Meta Information * * \details FileMetaInformation is a Explicit Structured Set. Whenever the * file contains an ImplicitDataElement DataSet, a conversion will take place. * * Definition: * The File Meta Information includes identifying information on the * encapsulated Data Set. This header consists of a 128 byte File Preamble, * followed by a 4 byte DICOM prefix, followed by the File Meta Elements shown * in Table 7.1-1. This header shall be present in every DICOM file. * * \see Writer Reader */ class GDCM_EXPORT FileMetaInformation : public DataSet { public: // FIXME: TransferSyntax::TS_END -> TransferSyntax::ImplicitDataElement FileMetaInformation(); ~FileMetaInformation(); friend std::ostream &operator<<(std::ostream &_os, const FileMetaInformation &_val); bool IsValid() const { return true; } TransferSyntax::NegociatedType GetMetaInformationTS() const { return MetaInformationTS; } void SetDataSetTransferSyntax(const TransferSyntax &ts); const TransferSyntax &GetDataSetTransferSyntax() const { return DataSetTS; } MediaStorage GetMediaStorage() const; std::string GetMediaStorageAsString() const; // FIXME: no virtual function means: duplicate code... void Insert(const DataElement& de) { if( de.GetTag().GetGroup() == 0x0002 ) { InsertDataElement( de ); } else { gdcmErrorMacro( "Cannot add element with group != 0x0002 in the file meta header: " << de ); } } void Replace(const DataElement& de) { Remove(de.GetTag()); Insert(de); } /// Read std::istream &Read(std::istream &is); std::istream &ReadCompat(std::istream &is); /// Write std::ostream &Write(std::ostream &os) const; /// Construct a FileMetaInformation from an already existing DataSet: void FillFromDataSet(DataSet const &ds); /// Get Preamble const Preamble &GetPreamble() const { return P; } Preamble &GetPreamble() { return P; } void SetPreamble(const Preamble &p) { P = p; } /// Override the GDCM default values: static void SetImplementationClassUID(const char * imp); static void AppendImplementationClassUID(const char * imp); static const char *GetImplementationClassUID(); static void SetImplementationVersionName(const char * version); static const char *GetImplementationVersionName(); 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; } VL GetFullLength() const { return P.GetLength() + DataSet::GetLength(); } protected: void ComputeDataSetTransferSyntax(); // FIXME template std::istream &ReadCompatInternal(std::istream &is); void Default(); void ComputeDataSetMediaStorageSOPClass(); TransferSyntax DataSetTS; TransferSyntax::NegociatedType MetaInformationTS; MediaStorage::MSType DataSetMS; protected: static const char * GetFileMetaInformationVersion(); static const char * GetGDCMImplementationClassUID(); static const char * GetGDCMImplementationVersionName(); static const char * GetGDCMSourceApplicationEntityTitle(); private: Preamble P; //static stuff: static const char GDCM_FILE_META_INFORMATION_VERSION[]; static const char GDCM_IMPLEMENTATION_CLASS_UID[]; static const char GDCM_IMPLEMENTATION_VERSION_NAME[]; static const char GDCM_SOURCE_APPLICATION_ENTITY_TITLE[]; static std::string ImplementationClassUID; static std::string ImplementationVersionName; static std::string SourceApplicationEntityTitle; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const FileMetaInformation &val) { os << val.GetPreamble() << std::endl; val.Print( os ); return os; } } // end namespace gdcm_ns #endif //GDCMFILEMETAINFORMATION_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmFileSet.cxx000066400000000000000000000017651412732066400253720ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileSet.h" #include "gdcmSystem.h" namespace gdcm { bool FileSet::AddFile(const char *filename) { if( System::FileExists(filename) ) { Files.push_back( filename ); return true; } return false; } void FileSet::SetFiles(FilesType const &files) { FilesType::const_iterator it = files.begin(); for( ; it != files.end(); ++it ) { AddFile( it->c_str() ); } } } GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmFileSet.h000066400000000000000000000031761412732066400250150ustar00rootroot00000000000000/*========================================================================= 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 GDCMFILESET_H #define GDCMFILESET_H #include "gdcmFile.h" #include 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. */ class GDCM_EXPORT FileSet { friend std::ostream& operator<<(std::ostream &_os, const FileSet &d); public: FileSet():Files() {} typedef std::string FileType; typedef std::vector FilesType; /// \deprecated. Does nothing void AddFile(File const & ) {} /// Add a file 'filename' to the list of files. Return true on success, false in case filename could not /// be found on system. bool AddFile(const char *filename); void SetFiles(FilesType const &files); FilesType const &GetFiles() const { return Files; } private: FilesType Files; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const FileSet &f) { (void)f; // FIXME return os; } } // end namespace gdcm #endif //GDCMFILESET_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmFragment.cxx000066400000000000000000000022611412732066400255720ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFragment.h" namespace gdcm_ns { VL Fragment::GetLength() const { assert( !ValueLengthField.IsUndefined() ); assert( !ValueField || ValueField->GetLength() == ValueLengthField ); return TagField.GetLength() + ValueLengthField.GetLength() + ValueLengthField; } VL Fragment::ComputeLength() const { const ByteValue *bv = GetByteValue(); assert( bv ); assert( !ValueLengthField.IsUndefined() ); //assert( !ValueField || ValueField->GetLength() == ValueLengthField ); return TagField.GetLength() + ValueLengthField.GetLength() + bv->ComputeLength() /*ValueLengthField*/; } } // end namespace gdcm_ns GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmFragment.h000066400000000000000000000142021412732066400252150ustar00rootroot00000000000000/*========================================================================= 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 GDCMFRAGMENT_H #define GDCMFRAGMENT_H #include "gdcmDataElement.h" #include "gdcmByteValue.h" #include "gdcmSmartPointer.h" #include "gdcmParseException.h" namespace gdcm_ns { // Implementation detail: // I think Fragment should be a protected subclass of DataElement: // looking somewhat like this: /* class GDCM_EXPORT Fragment : protected DataElement { public: using DataElement::GetTag; using DataElement::GetVL; using DataElement::SetByteValue; using DataElement::GetByteValue; using DataElement::GetValue; */ // Instead I am only hiding the SetTag member... /** * \brief Class to represent a Fragment */ class GDCM_EXPORT Fragment : public DataElement { //protected: // void SetTag(const Tag &t); public: Fragment() : DataElement(Tag(0xfffe, 0xe000), 0) {} friend std::ostream &operator<<(std::ostream &os, const Fragment &val); VL GetLength() const; VL ComputeLength() const; template std::istream &Read(std::istream &is) { ReadPreValue(is); return ReadValue(is); } template std::istream &ReadPreValue(std::istream &is) { const Tag itemStart(0xfffe, 0xe000); const Tag seqDelItem(0xfffe,0xe0dd); TagField.Read(is); if( !is ) { // BogusItemStartItemEnd.dcm throw Exception( "Problem #1" ); return is; } if( !ValueLengthField.Read(is) ) { // GENESIS_SIGNA-JPEG-CorruptFrag.dcm // JPEG fragment is declared to have 61902, but in fact really is only 61901 // so we end up reading 0xddff,0x00e0, and VL = 0x0 (1 byte) throw Exception( "Problem #2" ); return is; } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( TagField != itemStart && TagField != seqDelItem ) { throw Exception( "Problem #3" ); } #endif return is; } 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); if( !bv->Read(is) ) { // Fragment is incomplete, but is a itemStart, let's try to push it anyway... gdcmWarningMacro( "Fragment could not be read" ); //bv->SetLength(is.gcount()); ValueField = bv; ParseException pe; pe.SetLastElement( *this ); throw pe; return is; } ValueField = bv; return is; } template std::istream &ReadBacktrack(std::istream &is) { const Tag itemStart(0xfffe, 0xe000); const Tag seqDelItem(0xfffe,0xe0dd); bool cont = true; const std::streampos start = is.tellg(); const int max = 10; int offset = 0; while( cont ) { TagField.Read(is); assert( is ); if( TagField != itemStart && TagField != seqDelItem ) { ++offset; is.seekg( (std::streampos)((size_t)start - offset) ); gdcmWarningMacro( "Fuzzy Search, backtrack: " << (start - is.tellg()) << " Offset: " << is.tellg() ); if( offset > max ) { gdcmErrorMacro( "Giving up" ); throw "Impossible to backtrack"; return is; } } else { cont = false; } } assert( TagField == itemStart || TagField == seqDelItem ); if( !ValueLengthField.Read(is) ) { return is; } // Self SmartPointer bv = new ByteValue; bv->SetLength(ValueLengthField); if( !bv->Read(is) ) { // Fragment is incomplete, but is a itemStart, let's try to push it anyway... gdcmWarningMacro( "Fragment could not be read" ); //bv->SetLength(is.gcount()); ValueField = bv; ParseException pe; pe.SetLastElement( *this ); throw pe; return is; } ValueField = bv; return is; } template std::ostream &Write(std::ostream &os) const { const Tag itemStart(0xfffe, 0xe000); const Tag seqDelItem(0xfffe,0xe0dd); if( !TagField.Write(os) ) { assert(0 && "Should not happen"); return os; } assert( TagField == itemStart || TagField == seqDelItem ); const ByteValue *bv = GetByteValue(); // VL // The following piece of code is hard to read in order to support such broken file as: // CompressedLossy.dcm if( IsEmpty() ) { //assert( bv ); VL zero = 0; if( !zero.Write(os) ) { assert(0 && "Should not happen"); return os; } } else { assert( ValueLengthField ); assert( !ValueLengthField.IsUndefined() ); const VL actuallen = bv->ComputeLength(); assert( actuallen == ValueLengthField || actuallen == ValueLengthField + 1 ); if( !actuallen.Write(os) ) { assert(0 && "Should not happen"); return os; } } // Value if( ValueLengthField && bv ) { // Self assert( bv ); assert( bv->GetLength() == ValueLengthField ); if( !bv->Write(os) ) { assert(0 && "Should not happen"); return os; } } return os; } }; //----------------------------------------------------------------------------- inline std::ostream &operator<<(std::ostream &os, const Fragment &val) { os << "Tag: " << val.TagField; os << "\tVL: " << val.ValueLengthField; if( val.ValueField ) { os << "\t" << *(val.ValueField); } return os; } } // end namespace gdcm_ns #endif //GDCMFRAGMENT_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmFragment.txx000066400000000000000000000013071412732066400256130ustar00rootroot00000000000000/*========================================================================= 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 GDCMFRAGMENT_TXX #define GDCMFRAGMENT_TXX #include "gdcmFragment.h" namespace gdcm { } // end namespace gdcm #endif // GDCMFRAGMENT_TXX GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmImplicitDataElement.cxx000066400000000000000000000037411412732066400277110ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImplicitDataElement.h" #include "gdcmByteValue.h" #include "gdcmSequenceOfItems.h" namespace gdcm_ns { VL ImplicitDataElement::GetLength() const { if( ValueLengthField.IsUndefined() ) { assert( ValueField->GetLength().IsUndefined() ); Value *p = ValueField; SequenceOfItems *sq = dynamic_cast(p); if( sq ) { return TagField.GetLength() + ValueLengthField.GetLength() + sq->ComputeLength(); } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION SequenceOfFragments *sf = dynamic_cast(p); if( sf ) { //assert( VRField & VR::OB_OW ); // VR::INVALID is not possible AFAIK... return TagField.GetLength() /*+ VRField.GetLength()*/ + ValueLengthField.GetLength() + sf->ComputeLength(); } #endif assert( !ValueLengthField.IsUndefined() ); return ValueLengthField; } //else if( const SequenceOfItems *sqi = GetSequenceOfItems() ) else if( const SequenceOfItems *sqi = dynamic_cast( ValueField.GetPointer() ) ) { // TestWrite2 return TagField.GetLength() + ValueLengthField.GetLength() + sqi->ComputeLength(); } else { assert( !ValueField || ValueField->GetLength() == ValueLengthField ); return TagField.GetLength() + ValueLengthField.GetLength() + ValueLengthField; } } } // end namespace gdcm_ns GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmImplicitDataElement.h000066400000000000000000000027671412732066400273450ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMPLICITDATAELEMENT_H #define GDCMIMPLICITDATAELEMENT_H #include "gdcmDataElement.h" namespace gdcm_ns { /** * \brief Class to represent an *Implicit VR* Data Element * \note bla */ class GDCM_EXPORT ImplicitDataElement : public DataElement { public: VL GetLength() const; template std::istream &Read(std::istream& is); template std::istream &ReadPreValue(std::istream& is); template std::istream &ReadValue(std::istream& is, bool readvalues = true); template std::istream &ReadWithLength(std::istream& is, VL & length, bool readvalues = true); template std::istream &ReadValueWithLength(std::istream& is, VL & length, bool readvalues = true); template const std::ostream &Write(std::ostream& os) const; }; } // end namespace gdcm_ns #include "gdcmImplicitDataElement.txx" #endif //GDCMIMPLICITDATAELEMENT_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmImplicitDataElement.txx000066400000000000000000000453561412732066400277420ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMPLICITDATAELEMENT_TXX #define GDCMIMPLICITDATAELEMENT_TXX #include "gdcmSequenceOfItems.h" #include "gdcmValueIO.h" #include "gdcmSwapper.h" #ifdef GDCM_WORDS_BIGENDIAN #include "gdcmTagToVR.h" #endif namespace gdcm_ns { //----------------------------------------------------------------------------- template std::istream &ImplicitDataElement::Read(std::istream &is) { ReadPreValue(is); return ReadValue(is); } template std::istream &ImplicitDataElement::ReadPreValue(std::istream& is) { TagField.Read(is); // See PS 3.5, 7.1.3 Data Element Structure With Implicit VR // Read Tag if( !is ) { if( !is.eof() ) // FIXME This should not be needed assert(0 && "Should not happen"); return is; } const Tag itemStartItem(0xfffe,0xe000); if( TagField == itemStartItem ) return is; //assert( TagField != Tag(0xfffe,0xe0dd) ); // Read Value Length if( !ValueLengthField.Read(is) ) { //assert(0 && "Should not happen"); throw Exception("Impossible ValueLengthField"); return is; } return is; } template std::istream &ImplicitDataElement::ReadValue(std::istream &is, bool readvalues) { if( is.eof() ) return is; const Tag itemStartItem(0xfffe,0xe000); assert( TagField != itemStartItem ); /* * technically this should not be needed, but what if an implementor, forgot * to set VL = 0, then we should make sure to exit early */ const Tag itemDelItem(0xfffe,0xe00d); if( TagField == itemDelItem ) { if( ValueLengthField != 0 ) { gdcmWarningMacro( "VL should be set to 0" ); } ValueField = nullptr; return is; } //std::cerr << "imp cur tag=" << TagField << " VL=" << ValueLengthField << std::endl; //if( ValueLengthField > length && !ValueLengthField.IsUndefined() ) // { // gdcmWarningMacro( "Cannot read more length than what is remaining in the file" ); // throw Exception( "Impossible" ); // } if( ValueLengthField == 0 ) { // Simple fast path ValueField = nullptr; return is; } else if( ValueLengthField.IsUndefined() ) { //assert( de.GetVR() == VR::SQ ); // FIXME what if I am reading the pixel data... //assert( TagField != Tag(0x7fe0,0x0010) ); if( TagField != Tag(0x7fe0,0x0010) ) { ValueField = new SequenceOfItems; } else { gdcmErrorMacro( "Undefined value length is impossible in non-encapsulated Transfer Syntax. Proceeding with caution" ); ValueField = new SequenceOfFragments; } //VRField = VR::SQ; } else { if( true /*ValueLengthField < 8 */ ) { ValueField = new ByteValue; } else { // In the following we read 4 more bytes in the Value field // to find out if this is a SQ or not // there is still work to do to handle the PMS featured SQ // where item Start is in fact 0xfeff, 0x00e0 ... sigh const Tag itemStart(0xfffe, 0xe000); #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION const Tag itemPMSStart(0xfeff, 0x00e0); const Tag itemPMSStart2(0x3f3f, 0x3f00); #endif Tag item; // TODO FIXME // This is pretty dumb to actually read to later on seekg back, why not `peek` directly ? item.Read(is); // Maybe this code can later be rewritten as I believe that seek back // is very slow... is.seekg(-4, std::ios::cur ); if( item == itemStart ) { assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new SequenceOfItems; } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION else if ( item == itemPMSStart ) { // MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm gdcmWarningMacro( "Illegal Tag for Item starter: " << TagField << " should be: " << itemStart ); // TODO: We READ Explicit ok...but we store Implicit ! // Indeed when copying the VR will be saved... pretty cool eh ? ValueField = new SequenceOfItems; ValueField->SetLength(ValueLengthField); // perform realloc std::streampos start = is.tellg(); try { if( !ValueIO::Read(is,*ValueField,readvalues) ) { assert(0 && "Should not happen"); } gdcmWarningMacro( "Illegal: Explicit SQ found in a file with " "TransferSyntax=Implicit for tag: " << TagField ); } catch( Exception & ) { // MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm std::streampos current = is.tellg(); std::streamoff diff = start - current; is.seekg( diff, std::ios::cur ); assert( diff == -14 ); ValueIO::Read(is,*ValueField,readvalues); } catch( std::exception & ) { ValueLengthField = ValueField->GetLength(); } return is; } else if ( item == itemPMSStart2 && false ) { gdcmWarningMacro( "Illegal: SQ start with " << itemPMSStart2 << " instead of " << itemStart << " for tag: " << TagField ); ValueField = new SequenceOfItems; ValueField->SetLength(ValueLengthField); // perform realloc if( !ValueIO::Read(is,*ValueField,readvalues) ) { assert(0 && "Should not happen"); } return is; } #endif else { ValueField = new ByteValue; } } } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // THE WORST BUG EVER. From GE Workstation if( ValueLengthField == 13 ) { // Historically gdcm did not enforce proper length // thus Theralys started writing illegal DICOM images: const Tag theralys1(0x0008,0x0070); const Tag theralys2(0x0008,0x0080); if( TagField != theralys1 && TagField != theralys2 ) { gdcmWarningMacro( "GE,13: Replacing VL=0x000d with VL=0x000a, for Tag=" << TagField << " in order to read a buggy DICOM file." ); ValueLengthField = 10; } } #endif #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( ValueLengthField == 0x31f031c && TagField == Tag(0x031e,0x0324) ) { // TestImages/elbow.pap gdcmWarningMacro( "Replacing a VL. To be able to read a supposively " "broken Payrus file." ); ValueLengthField = 202; // 0xca } #endif // We have the length we should be able to read the value this->SetValueFieldLength( ValueLengthField, readvalues ); bool failed; #ifdef GDCM_WORDS_BIGENDIAN VR vrfield = GetVRFromTag( TagField ); if( vrfield & VR::VRASCII || vrfield == VR::INVALID ) { //assert( VRField.GetSize() == 1 ); failed = !ValueIO::Read(is,*ValueField,readvalues); } else { assert( vrfield & VR::VRBINARY ); unsigned int vrsize = vrfield.GetSize(); assert( vrsize == 1 || vrsize == 2 || vrsize == 4 || vrsize == 8 ); if(vrfield==VR::AT) vrsize = 2; switch(vrsize) { case 1: failed = !ValueIO::Read(is,*ValueField,readvalues); break; case 2: failed = !ValueIO::Read(is,*ValueField,readvalues); break; case 4: failed = !ValueIO::Read(is,*ValueField,readvalues); break; case 8: failed = !ValueIO::Read(is,*ValueField,readvalues); break; default: failed = true; assert(0); } } #else failed = !ValueIO::Read(is,*ValueField,readvalues); #endif if( failed ) { // Special handling for PixelData tag: #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( TagField == Tag(0x7fe0,0x0010) ) { gdcmWarningMacro( "Incomplete Pixel Data found, use file at own risk" ); is.clear(); } else #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */ { throw Exception("Should not happen (imp)"); } return is; } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // dcmtk 3.5.4 is resilient to broken explicit SQ length and will properly // recompute it as long as each of the Item lengths are correct VL dummy = ValueField->GetLength(); if( ValueLengthField != dummy ) { gdcmWarningMacro( "ValueLengthField was bogus" ); assert(0); ValueLengthField = dummy; } #else assert( ValueLengthField == ValueField->GetLength() ); assert( VRField == VR::INVALID ); #endif return is; } //----------------------------------------------------------------------------- template std::istream &ImplicitDataElement::ReadWithLength(std::istream &is, VL & length, bool readvalues) { ReadPreValue(is); return ReadValueWithLength(is, length, readvalues); } template std::istream &ImplicitDataElement::ReadValueWithLength(std::istream& is, VL & length, bool readvalues) { if( is.eof() ) return is; const Tag itemStartItem(0xfffe,0xe000); if( TagField == itemStartItem ) return is; /* * technically this should not be needed, but what if an implementor, forgot * to set VL = 0, then we should make sure to exit early */ const Tag itemDelItem(0xfffe,0xe00d); if( TagField == itemDelItem ) { if( ValueLengthField != 0 ) { gdcmWarningMacro( "VL should be set to 0" ); } ValueField = nullptr; return is; } //std::cerr << "imp cur tag=" << TagField << " VL=" << ValueLengthField << std::endl; if( ValueLengthField > length && !ValueLengthField.IsUndefined() ) { gdcmWarningMacro( "Cannot read more length than what is remaining in the file" ); throw Exception( "Impossible (more)" ); } if( ValueLengthField == 0 ) { // Simple fast path ValueField = nullptr; return is; } else if( ValueLengthField.IsUndefined() ) { //assert( de.GetVR() == VR::SQ ); // FIXME what if I am reading the pixel data... //assert( TagField != Tag(0x7fe0,0x0010) ); if( TagField != Tag(0x7fe0,0x0010) ) { ValueField = new SequenceOfItems; } else { gdcmErrorMacro( "Undefined value length is impossible in non-encapsulated Transfer Syntax. Proceeding with caution" ); ValueField = new SequenceOfFragments; } //VRField = VR::SQ; } else { if( true /*ValueLengthField < 8*/ ) { ValueField = new ByteValue; } else { // In the following we read 4 more bytes in the Value field // to find out if this is a SQ or not // there is still work to do to handle the PMS featured SQ // where item Start is in fact 0xfeff, 0x00e0 ... sigh const Tag itemStart(0xfffe, 0xe000); #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION const Tag itemPMSStart(0xfeff, 0x00e0); const Tag itemPMSStart2(0x3f3f, 0x3f00); #endif Tag item; // TODO FIXME // This is pretty dumb to actually read to later on seekg back, why not `peek` directly ? item.Read(is); // Maybe this code can later be rewritten as I believe that seek back // is very slow... is.seekg(-4, std::ios::cur ); if( item == itemStart ) { assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new SequenceOfItems; } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION else if ( item == itemPMSStart ) { // MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm gdcmWarningMacro( "Illegal Tag for Item starter: " << TagField << " should be: " << itemStart ); // TODO: We READ Explicit ok...but we store Implicit ! // Indeed when copying the VR will be saved... pretty cool eh ? ValueField = new SequenceOfItems; ValueField->SetLength(ValueLengthField); // perform realloc std::streampos start = is.tellg(); try { if( !ValueIO::Read(is,*ValueField,readvalues) ) { assert(0 && "Should not happen"); } gdcmWarningMacro( "Illegal: Explicit SQ found in a file with " "TransferSyntax=Implicit for tag: " << TagField ); } catch( Exception &) { // MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm std::streampos current = is.tellg(); std::streamoff diff = start - current;//could be bad, if the specific implementation does not support negative streamoff values. is.seekg( diff, std::ios::cur ); assert( diff == -14 ); ValueIO::Read(is,*ValueField,readvalues); } catch( std::exception & ) { ValueLengthField = ValueField->GetLength(); } return is; } else if ( item == itemPMSStart2 ) { assert( 0 ); // FIXME: Sync Read/ReadWithLength gdcmWarningMacro( "Illegal: SQ start with " << itemPMSStart2 << " instead of " << itemStart << " for tag: " << TagField ); ValueField = new SequenceOfItems; ValueField->SetLength(ValueLengthField); // perform realloc if( !ValueIO::Read(is,*ValueField,readvalues) ) { assert(0 && "Should not happen"); } return is; } #endif else { ValueField = new ByteValue; } } } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // THE WORST BUG EVER. From GE Workstation if( ValueLengthField == 13 ) { // Historically gdcm did not enforce proper length // thus Theralys started writing illegal DICOM images: const Tag theralys1(0x0008,0x0070); const Tag theralys2(0x0008,0x0080); if( TagField != theralys1 && TagField != theralys2 ) { gdcmWarningMacro( "GE,13: Replacing VL=0x000d with VL=0x000a, for Tag=" << TagField << " in order to read a buggy DICOM file." ); ValueLengthField = 10; } } #endif #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( ValueLengthField == 0x31f031c && TagField == Tag(0x031e,0x0324) ) { // TestImages/elbow.pap gdcmWarningMacro( "Replacing a VL. To be able to read a supposively" "broken Payrus file." ); ValueLengthField = 202; // 0xca } #endif // We have the length we should be able to read the value ValueField->SetLength(ValueLengthField); // perform realloc bool failed; #ifdef GDCM_WORDS_BIGENDIAN VR vrfield = GetVRFromTag( TagField ); if( vrfield & VR::VRASCII || vrfield == VR::INVALID ) { //assert( VRField.GetSize() == 1 ); failed = !ValueIO::Read(is,*ValueField,readvalues); } else { assert( vrfield & VR::VRBINARY ); unsigned int vrsize = vrfield.GetSize(); assert( vrsize == 1 || vrsize == 2 || vrsize == 4 || vrsize == 8 ); if(vrfield==VR::AT) vrsize = 2; switch(vrsize) { case 1: failed = !ValueIO::Read(is,*ValueField,readvalues); break; case 2: failed = !ValueIO::Read(is,*ValueField,readvalues); break; case 4: failed = !ValueIO::Read(is,*ValueField,readvalues); break; case 8: failed = !ValueIO::Read(is,*ValueField,readvalues); break; default: failed = true; assert(0); } } #else failed = !ValueIO::Read(is,*ValueField,readvalues); #endif if( failed ) //if( !ValueIO::Read(is,*ValueField) ) { // Special handling for PixelData tag: #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( TagField == Tag(0x7fe0,0x0010) ) { gdcmWarningMacro( "Incomplete Pixel Data found, use file at own risk" ); is.clear(); } else #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */ { throw Exception("Should not happen (imp)"); } return is; } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // dcmtk 3.5.4 is resilient to broken explicit SQ length and will properly recompute it // as long as each of the Item lengths are correct VL dummy = ValueField->GetLength(); if( ValueLengthField != dummy ) { gdcmWarningMacro( "ValueLengthField was bogus" ); ValueLengthField = dummy; } #else assert( ValueLengthField == ValueField->GetLength() ); assert( VRField == VR::INVALID ); #endif return is; } //----------------------------------------------------------------------------- template const std::ostream &ImplicitDataElement::Write(std::ostream &os) const { // See PS 3.5, 7.1.3 Data Element Structure With Implicit VR // Write Tag if( !TagField.Write(os) ) { assert(0 && "Should not happen"); return os; } // Write Value Length // The following code should always work since we are in the case of IVRLE - CP246 // however broken file such as PET-GE-dicomwrite-PixelDataSQUNv2.dcm breaks this assumption right here: // see bug #502 const SequenceOfItems *sqi = dynamic_cast( ValueField.GetPointer() ); //GetSequenceOfItems(); if( sqi && !ValueLengthField.IsUndefined() ) { // Hum, we might have to recompute the length: // See TestWriter2, where an explicit SQ is converted to implicit SQ VL len = sqi->template ComputeLength(); //assert( len == ValueLengthField ); if( !len.Write(os) ) { assert(0 && "Should not happen"); return os; } } else // It should be safe to simply use the ValueLengthField as stored: { // Do not allow writing file such as: dcm4che_UndefinedValueLengthInImplicitTS.dcm if( TagField == Tag(0x7fe0,0x0010) && ValueLengthField.IsUndefined() ) throw Exception( "VL u/f Impossible" ); if( !ValueLengthField.Write(os) ) { assert(0 && "Should not happen"); return os; } } // Write Value if( ValueLengthField ) { assert( ValueField ); gdcmAssertAlwaysMacro( ValueLengthField == ValueField->GetLength() ); assert( TagField != Tag(0xfffe, 0xe00d) && TagField != Tag(0xfffe, 0xe0dd) ); if( !ValueIO::Write(os,*ValueField) ) { assert(0 && "Should not happen"); return os; } } return os; } } // end namespace gdcm_ns #endif // GDCMIMPLICITDATAELEMENT_TXX GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmItem.cxx000066400000000000000000000012161412732066400247240ustar00rootroot00000000000000/*========================================================================= 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 "gdcmItem.h" #include namespace gdcm_ns { } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmItem.h000066400000000000000000000232321412732066400243530ustar00rootroot00000000000000/*========================================================================= 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 GDCMITEM_H #define GDCMITEM_H #include "gdcmDataElement.h" #include "gdcmDataSet.h" #include "gdcmParseException.h" #include "gdcmSwapper.h" #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION #include "gdcmByteSwapFilter.h" #endif namespace gdcm_ns { class DataSet; /** * \brief Class to represent an Item * \details A component of the value of a Data Element that is of Value Representation * Sequence of Items. * An Item contains a Data Set . * See PS 3.5 7.5.1 Item Encoding Rules * Each Item of a Data Element of VR SQ shall be encoded as a DICOM Standard * Data Element with a specific Data Element Tag of Value (FFFE,E000). The Item * Tag is followed by a 4 byte Item Length field encoded in one of the * following two ways Explicit/ Implicit * \note * ITEM: A component of the Value of a Data Element that is of Value * Representation Sequence of Items. An Item contains a Data Set. */ class GDCM_EXPORT Item : public DataElement { public: Item() : DataElement(Tag(0xfffe, 0xe000), 0xFFFFFFFF), NestedDataSet() {} friend std::ostream& operator<< (std::ostream &os, const Item &val); void Clear() { this->DataElement::Clear(); NestedDataSet.Clear(); } template VL GetLength() const; void InsertDataElement(const DataElement & de) { NestedDataSet.Insert(de); // Update the length if( !IsUndefinedLength() ) { assert( 0 && "InsertDataElement" ); //ValueLengthField += de.GetLength(); } } const DataElement& GetDataElement(const Tag& t) const { return NestedDataSet.GetDataElement(t); } // Completely defines it with the nested dataset // destroy anything present void SetNestedDataSet(const DataSet& nested) { NestedDataSet = nested; } // Return a const ref to the Nested Data Set const DataSet &GetNestedDataSet() const { return NestedDataSet; } DataSet &GetNestedDataSet() { return NestedDataSet; } //Value const & GetValue() const { return *NestedDataSet; } Item(Item const &val):DataElement(val) { NestedDataSet = val.NestedDataSet; } template std::istream &Read(std::istream &is) { // Superclass { DataSet &nested = NestedDataSet; nested.Clear(); assert( nested.IsEmpty() ); } if( !TagField.Read(is) ) { throw Exception("Should not happen (item)"); return is; } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm if( TagField == Tag(0xfeff, 0x00e0) || TagField == Tag(0xfeff, 0xdde0) ) { gdcmWarningMacro( "ByteSwaping Private SQ: " << TagField ); // Invert previously read TagField since wrong endianness: TagField = Tag( SwapperDoOp::Swap( TagField.GetGroup() ), SwapperDoOp::Swap( TagField.GetElement() ) ); assert ( TagField == Tag(0xfffe, 0xe000) || TagField == Tag(0xfffe, 0xe0dd) ); if( !ValueLengthField.Read(is) ) { assert(0 && "Should not happen"); return is; } // Self // Some file written by GDCM 1.0 we write 0xFFFFFFFF instead of 0x0 if( TagField == Tag(0xfffe,0xe0dd) ) { if( ValueLengthField ) { gdcmErrorMacro( "ValueLengthField is not 0" ); } } //else if( ValueLengthField == 0 ) // { // //assert( TagField == Tag( 0xfffe, 0xe0dd) ); // if( TagField != Tag( 0xfffe, 0xe0dd) ) // { // gdcmErrorMacro( "SQ: " << TagField << " has a length of 0" ); // } // } else if( ValueLengthField.IsUndefined() ) { DataSet &nested = NestedDataSet; nested.Clear(); assert( nested.IsEmpty() ); std::streampos start = is.tellg(); try { nested.template ReadNested(is); ByteSwapFilter bsf(nested); bsf.ByteSwap(); } catch(ParseException &pe) { (void)pe; // MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm // You have to byteswap the length but not the tag...sigh gdcmWarningMacro( "Attempt to read nested Item without byteswapping the Value Length." ); start -= is.tellg(); assert( start < 0 ); is.seekg( start, std::ios::cur ); nested.Clear(); nested.template ReadNested(is); ByteSwapFilter bsf(nested); // Tag are read in big endian, need to byteswap them back... bsf.SetByteSwapTag(true); bsf.ByteSwap(); } catch(Exception &e) { // MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm throw e; } catch(...) { assert(0); } } else /* if( ValueLengthField.IsUndefined() ) */ { DataSet &nested = NestedDataSet; nested.Clear(); assert( nested.IsEmpty() ); nested.template ReadWithLength(is, ValueLengthField); ByteSwapFilter bsf(nested); bsf.ByteSwap(); } return is; } // http://groups.google.com/group/comp.protocols.dicom/msg/c07efcf5e759fc83 // Bug_Philips_ItemTag_3F3F.dcm if( TagField == Tag(0x3f3f, 0x3f00) ) { //TagField = Tag(0xfffe, 0xe000); } #endif if( TagField != Tag(0xfffe, 0xe000) && TagField != Tag(0xfffe, 0xe0dd) ) { gdcmDebugMacro( "Invalid Item, found tag: " << TagField); throw Exception( "Not a valid Item" ); } assert( TagField == Tag(0xfffe, 0xe000) || TagField == Tag(0xfffe, 0xe0dd) ); if( !ValueLengthField.Read(is) ) { assert(0 && "Should not happen"); return is; } // Self if( TagField == Tag(0xfffe,0xe0dd) ) { // Some file written by GDCM 1.0 were written with 0xFFFFFFFF instead of 0x0 if( ValueLengthField ) { gdcmDebugMacro( "ValueLengthField is not 0 but " << ValueLengthField ); } } else if( ValueLengthField.IsUndefined() ) { DataSet &nested = NestedDataSet; nested.Clear(); assert( nested.IsEmpty() ); nested.template ReadNested(is); } else /* if( ValueLengthField.IsUndefined() ) */ { assert( !ValueLengthField.IsUndefined() ); DataSet &nested = NestedDataSet; nested.Clear(); assert( nested.IsEmpty() ); nested.template ReadWithLength(is, ValueLengthField); } return is; } template const std::ostream &Write(std::ostream &os) const { #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( TagField == Tag(0x3f3f,0x3f00) && false ) { Tag t(0xfffe, 0xe000); t.Write(os); } else #endif { assert ( TagField == Tag(0xfffe, 0xe000) || TagField == Tag(0xfffe, 0xe0dd) ); // Not sure how this happen if( TagField == Tag(0xfffe, 0xe0dd) ) { gdcmWarningMacro( "SegDelItem found in defined length Sequence" ); assert( ValueLengthField == 0 ); assert( NestedDataSet.Size() == 0 ); } if( !TagField.Write(os) ) { assert(0 && "Should not happen"); return os; } } if( ValueLengthField.IsUndefined() ) { if( !ValueLengthField.Write(os) ) { assert(0 && "Should not happen"); return os; } } else { const VL dummy = NestedDataSet.GetLength(); assert( dummy % 2 == 0 ); //assert( ValueLengthField == dummy ); if( !dummy.Write(os) ) { assert(0 && "Should not happen"); return os; } } // Self NestedDataSet.Write(os); if( ValueLengthField.IsUndefined() ) { const Tag itemDelItem(0xfffe,0xe00d); itemDelItem.Write(os); VL zero = 0; zero.Write(os); } return os; } /* There are three special SQ related Data Elements that are not ruled by the VR encoding rules conveyed by the Transfer Syntax. They shall be encoded as Implicit VR. These special Data Elements are Item (FFFE,E000), Item Delimitation Item (FFFE,E00D), and Sequence Delimitation Item (FFFE,E0DD). However, the Data Set within the Value Field of the Data Element Item (FFFE,E000) shall be encoded according to the rules conveyed by the Transfer Syntax. */ bool FindDataElement(const Tag &t) const { return NestedDataSet.FindDataElement( t ); } private: /* NESTED DATA SET a Data Set contained within a Data Element of an other Data Set. * May be nested recursively. * Only Data Elements with VR = SQ may, themselves, contain Data Sets */ DataSet NestedDataSet; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& os, const Item &val) { os << val.TagField; os << "\t" << val.ValueLengthField << "\n"; val.NestedDataSet.Print( os, "\t" ); return os; } } // end namespace gdcm_ns #include "gdcmItem.txx" #endif //GDCMITEM_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmItem.txx000066400000000000000000000035101412732066400247440ustar00rootroot00000000000000/*========================================================================= 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 GDCMITEM_TXX #define GDCMITEM_TXX #include "gdcmItem.h" namespace gdcm_ns { template VL Item::GetLength() const { if( ValueLengthField.IsUndefined() ) { assert( !NestedDataSet.GetLength().IsUndefined() ); // Item Start 4 // Item Length 4 // DataSet ? // Item End Delimitation 4 // Item End Length 4 assert( NestedDataSet.GetLength() % 2 == 0 ); return TagField.GetLength() /* 4 */ + ValueLengthField.GetLength() /* 4 */ + NestedDataSet.GetLength() + 4 + 4; } else { // Item Start 4 // Item Length 4 // DataSet ? const VL nestedlen = NestedDataSet.GetLength(); // The following line is commented out, since we could be in the case where // we are computing the actual length of an implicit dataset, from an // initially read explicit dataset in which case the two length cannot // related to each other //gdcmAssertAlwaysMacro( ValueLengthField == nestedlen ); assert( nestedlen % 2 == 0 ); return TagField.GetLength() /* 4 */ + ValueLengthField.GetLength() /* 4 */ //+ ValueLengthField; + nestedlen; } } } // end namespace gdcm_ns #endif // GDCMITEM_TXX GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmLO.h000066400000000000000000000034721412732066400237730ustar00rootroot00000000000000/*========================================================================= 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 GDCMLO_H #define GDCMLO_H #include "gdcmString.h" namespace gdcm { /** * \brief LO * * \note TODO */ class /*GDCM_EXPORT*/ LO : public String<'\\',64> /* PLEASE do not export me */ { public: // typedef are not inherited: typedef String<'\\',64> Superclass; typedef Superclass::value_type value_type; typedef Superclass::pointer pointer; typedef Superclass::reference reference; typedef Superclass::const_reference const_reference; typedef Superclass::size_type size_type; typedef Superclass::difference_type difference_type; typedef Superclass::iterator iterator; typedef Superclass::const_iterator const_iterator; typedef Superclass::reverse_iterator reverse_iterator; typedef Superclass::const_reverse_iterator const_reverse_iterator; // LO constructors. LO(): Superclass() {} LO(const value_type* s): Superclass(s) {} LO(const value_type* s, size_type n): Superclass(s, n) {} LO(const Superclass& s, size_type pos=0, size_type n=npos): Superclass(s, pos, n) {} bool IsValid() const { if( !Superclass::IsValid() ) return false; // Implementation specific: return true; } }; } // end namespace gdcm #endif //GDCMLO_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmMediaStorage.cxx000066400000000000000000000546571412732066400264130ustar00rootroot00000000000000/*========================================================================= 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 "gdcmMediaStorage.h" #include "gdcmTag.h" #include "gdcmByteValue.h" #include "gdcmDataSet.h" #include "gdcmFileMetaInformation.h" #include "gdcmFile.h" #include "gdcmSequenceOfItems.h" #include "gdcmCodeString.h" namespace gdcm_ns { static const char *MSStrings[] = { "1.2.840.10008.1.3.10", "1.2.840.10008.5.1.4.1.1.1", "1.2.840.10008.5.1.4.1.1.1.1", "1.2.840.10008.5.1.4.1.1.1.1.1", "1.2.840.10008.5.1.4.1.1.1.2", "1.2.840.10008.5.1.4.1.1.1.2.1", "1.2.840.10008.5.1.4.1.1.1.3", "1.2.840.10008.5.1.4.1.1.1.3.1", "1.2.840.10008.5.1.4.1.1.2", "1.2.840.10008.5.1.4.1.1.2.1", "1.2.840.10008.5.1.4.1.1.6", "1.2.840.10008.5.1.4.1.1.6.1", // Ultrasound Image Storage "1.2.840.10008.5.1.4.1.1.3", "1.2.840.10008.5.1.4.1.1.3.1", "1.2.840.10008.5.1.4.1.1.4", "1.2.840.10008.5.1.4.1.1.4.1", "1.2.840.10008.5.1.4.1.1.4.2", "1.2.840.10008.5.1.4.1.1.5", // NuclearMedicineImageStorageRetired "1.2.840.10008.5.1.4.1.1.7", "1.2.840.10008.5.1.4.1.1.7.1", "1.2.840.10008.5.1.4.1.1.7.2", "1.2.840.10008.5.1.4.1.1.7.3", "1.2.840.10008.5.1.4.1.1.7.4", "1.2.840.10008.5.1.4.1.1.8", "1.2.840.10008.5.1.4.1.1.9", "1.2.840.10008.5.1.4.1.1.9.1.1", "1.2.840.10008.5.1.4.1.1.9.1.2", "1.2.840.10008.5.1.4.1.1.9.1.3", "1.2.840.10008.5.1.4.1.1.9.2.1", "1.2.840.10008.5.1.4.1.1.9.3.1", "1.2.840.10008.5.1.4.1.1.9.4.1", "1.2.840.10008.5.1.4.1.1.10", "1.2.840.10008.5.1.4.1.1.11", "1.2.840.10008.5.1.4.1.1.11.1", "1.2.840.10008.5.1.4.1.1.12.1", "1.2.840.10008.5.1.4.1.1.12.2", "1.2.840.10008.5.1.4.1.1.12.3", "1.2.840.10008.5.1.4.1.1.20", "1.2.840.10008.5.1.4.1.1.66", "1.2.840.10008.5.1.4.1.1.66.1", "1.2.840.10008.5.1.4.1.1.66.2", // See PETAt001_PT001.dcm "1.2.840.10008.5.1.4.1.1.128", // SYNGORTImage.dcm "1.2.840.10008.5.1.4.1.1.481.1", // eclipse_dose.dcm "1.2.840.10008.5.1.4.1.1.481.2", // exRT_Structure_Set_Storage.dcm "1.2.840.10008.5.1.4.1.1.481.3", // eclipse_plan.dcm "1.2.840.10008.5.1.4.1.1.481.5", // exCSA_Non-Image_Storage.dcm "1.3.12.2.1107.5.9.1", // 3DDCM011.dcm "1.2.840.113543.6.6.1.3.10002", // EnhancedSR "1.2.840.10008.5.1.4.1.1.88.22", // BasicTextSR: "1.2.840.10008.5.1.4.1.1.88.11", // HardcopyGrayscaleImageStorage "1.2.840.10008.5.1.1.29", // ComprehensiveSR "1.2.840.10008.5.1.4.1.1.88.33", // DetachedStudyManagementSOPClass, "1.2.840.10008.3.1.2.3.1", // EncapsulatedPDFStorage "1.2.840.10008.5.1.4.1.1.104.1", // EncapsulatedCDAStorage "1.2.840.10008.5.1.4.1.1.104.2", // StudyComponentManagementSOPClass "1.2.840.10008.3.1.2.3.2", // DetachedVisitManagementSOPClass "1.2.840.10008.3.1.2.2.1", // DetachedPatientManagementSOPClass "1.2.840.10008.3.1.2.1.1", // VideoEndoscopicImageStorage "1.2.840.10008.5.1.4.1.1.77.1.1.1", // GeneralElectricMagneticResonanceImageStorage "1.2.840.113619.4.2", // GEPrivate3DModelStorage "1.2.840.113619.4.26", // Toshiba Private Data Storage "1.2.392.200036.9116.7.8.1.1.1", // MammographyCADSR, "1.2.840.10008.5.1.4.1.1.88.50", // KeyObjectSelectionDocument "1.2.840.10008.5.1.4.1.1.88.59", // HangingProtocolStorage "1.2.840.10008.5.1.4.38.1", // Modality Performed Procedure Step SOP Class "1.2.840.10008.3.1.2.3.3", // Philips Private MR Synthetic Image Storage "1.3.46.670589.5.0.10", "1.2.840.10008.5.1.4.1.1.77.1.4", // "VL Photographic Image Storage", "1.2.840.10008.5.1.4.1.1.66.4", // Segmentation Storage "1.2.840.10008.5.1.4.1.1.481.8", // RT Ion Plan Storage "1.2.840.10008.5.1.4.1.1.13.1.1", // XRay3DAngiographicImageStorage, "1.2.840.10008.5.1.4.1.1.12.1.1", // Enhanced XA Image Storage "1.2.840.10008.5.1.4.1.1.481.9", // RTIonBeamsTreatmentRecordStorage "1.2.840.10008.5.1.4.1.1.66.5", // Surface Segmentation Storage "1.2.840.10008.5.1.4.1.1.77.1.6", // VLWholeSlideMicroscopyImageStorage "1.2.840.10008.5.1.4.1.1.481.7", // RTTreatmentSummaryRecordStorage "1.2.840.10008.5.1.4.1.1.6.2", // EnhancedUSVolumeStorage "1.2.840.10008.5.1.4.1.1.88.67", // XRayRadiationDoseSR "1.2.840.10008.5.1.4.1.1.77.1.1", // VLEndoscopicImageStorage "1.2.840.10008.5.1.4.1.1.13.1.3", // BreastTomosynthesisImageStorage "1.2.392.200036.9125.1.1.2", // FujiPrivateCRImageStorage "1.2.840.10008.5.1.4.1.1.77.1.5.1", // OphthalmicPhotography8BitImageStorage "1.2.840.10008.5.1.4.1.1.77.1.5.4", // OphthalmicTomographyImageStorage "1.2.840.10008.5.1.4.1.1.77.1.2", // VL Microscopic Image Storage "1.2.840.10008.5.1.4.1.1.130", // Enhanced PET Image Storage "1.2.840.10008.5.1.4.1.1.77.1.4.1", // Video Photographic Image Storage "1.2.840.10008.5.1.4.1.1.13.1.2", // XRay3DCraniofacialImageStorage "1.2.840.10008.5.1.4.1.1.14.1", // IVOCTForPresentation, "1.2.840.10008.5.1.4.1.1.14.2", // IVCOTForProcessing, "1.2.840.10008.5.1.4.1.1.2.2", // Legacy Converted Enhanced CT Image Storage "1.2.840.10008.5.1.4.1.1.4.4", // Legacy Converted Enhanced MR Image Storage "1.2.840.10008.5.1.4.1.1.128.1", // Legacy Converted Enhanced PET Image Storage "1.2.840.10008.5.1.4.1.1.13.1.4", // Breast Projection X-Ray Image Storage - For Presentation "1.2.840.10008.5.1.4.1.1.13.1.5", // Breast Projection X-Ray Image Storage - For Processing "1.2.840.10008.5.1.1.30", // HardcopyColorImageStorage "1.2.840.10008.5.1.4.1.1.4.3", // EnhancedMRColorImageStorage "1.2.392.200036.9125.1.1.4", // FujiPrivateMammoCRImageStorage (aka FUJI MAMMO CR Storage) "1.2.840.10008.5.1.4.1.1.77.1.5.2", // Ophthalmic Photography 16 Bit Image Storage "1.2.840.10008.5.1.4.1.1.77.1.2.1", // VideoMicroscopicImageStorage nullptr }; MediaStorage::MSType MediaStorage::GetMSType(const char *str) { if(!str) return MS_END; for(unsigned int i = 0; MSStrings[i] != nullptr; ++i) { if( strcmp(str, MSStrings[i]) == 0 ) { return (MSType)i; } } // Ouch ! We did not find anything, that's pretty bad, let's hope that // the toolkit which wrote the image is buggy and tolerate space padded binary // string CodeString codestring = str; std::string cs = codestring.GetAsString(); for(unsigned int i = 0; MSStrings[i] != nullptr; ++i) { if( strcmp(cs.c_str(), MSStrings[i]) == 0 ) { return (MSType)i; } } //assert(0); return MS_END; } const char* MediaStorage::GetMSString(MSType ms) { assert( ms <= MS_END ); return MSStrings[(int)ms]; } const char* MediaStorage::GetString() const { return GetMSString(MSField); } // FIXME // Currently the implementation is bogus it only define the TS which // are associated with an image so indeed the implementation of IsImage // is only the verification of TSType is != TS_END bool MediaStorage::IsImage(MSType ms) { if ( ms == MS_END // most frequent first // lexicographical order then... || ms == BasicVoiceAudioWaveformStorage || ms == CSANonImageStorage || ms == HemodynamicWaveformStorage || ms == MediaStorageDirectoryStorage || ms == RTPlanStorage || ms == GrayscaleSoftcopyPresentationStateStorageSOPClass || ms == CardiacElectrophysiologyWaveformStorage || ms == ToshibaPrivateDataStorage // not an image I think... || ms == EnhancedSR || ms == BasicTextSR || ms == ComprehensiveSR || ms == StudyComponentManagementSOPClass || ms == DetachedVisitManagementSOPClass || ms == DetachedStudyManagementSOPClass || ms == EncapsulatedPDFStorage || ms == EncapsulatedCDAStorage || ms == XRayRadiationDoseSR || ms == KeyObjectSelectionDocument || ms == HangingProtocolStorage || ms == MRSpectroscopyStorage || ms == ModalityPerformedProcedureStepSOPClass || ms == RawDataStorage || ms == RTIonPlanStorage || ms == LeadECGWaveformStorage || ms == GeneralECGWaveformStorage || ms == RTIonBeamsTreatmentRecordStorage || ms == RTStructureSetStorage || ms == MammographyCADSR || ms == SurfaceSegmentationStorage ) { return false; } return true; } struct MSModalityType { const char *Modality; const unsigned char Dimension; const bool Retired; }; static const MSModalityType MSModalityTypes[] = { {"00", 0, false},//MediaStorageDirectoryStorage, {"CR", 2, false},//ComputedRadiographyImageStorage, {"DX", 2, false},//DigitalXRayImageStorageForPresentation, {"DX", 2, false},//DigitalXRayImageStorageForProcessing, {" ", 2, false},//DigitalMammographyImageStorageForPresentation, {"MG", 2, false},//DigitalMammographyImageStorageForProcessing, {" ", 2, false},//DigitalIntraoralXrayImageStorageForPresentation, {" ", 2, false},//DigitalIntraoralXRayImageStorageForProcessing, {"CT", 2, false},//CTImageStorage, {"CT", 3, false},//EnhancedCTImageStorage, {"US", 2, true},//UltrasoundImageStorageRetired, {"US", 2, false},//UltrasoundImageStorage, {"US", 3, true},//UltrasoundMultiFrameImageStorageRetired, {"US", 3, false},//UltrasoundMultiFrameImageStorage, {"MR", 2, false},//MRImageStorage, {"MR", 3, false},//EnhancedMRImageStorage, {"MR", 2, false},//MRSpectroscopyStorage, {" ", 2, true},//NuclearMedicineImageStorageRetired, {"OT", 2, false},//SecondaryCaptureImageStorage, {"OT", 3, false},//MultiframeSingleBitSecondaryCaptureImageStorage, {"OT", 3, false},//MultiframeGrayscaleByteSecondaryCaptureImageStorage, {"OT", 3, false},//MultiframeGrayscaleWordSecondaryCaptureImageStorage, {"OT", 3, false},//MultiframeTrueColorSecondaryCaptureImageStorage, {" ", 2, false},//StandaloneOverlayStorage, {" ", 2, false},//StandaloneCurveStorage, {" ", 2, false},//LeadECGWaveformStorage, // 12- {" ", 2, false},//GeneralECGWaveformStorage, {" ", 2, false},//AmbulatoryECGWaveformStorage, {" ", 2, false},//HemodynamicWaveformStorage, {" ", 2, false},//CardiacElectrophysiologyWaveformStorage, {" ", 2, false},//BasicVoiceAudioWaveformStorage, {" ", 2, false},//StandaloneModalityLUTStorage, {" ", 2, false},//StandaloneVOILUTStorage, {" ", 2, false},//GrayscaleSoftcopyPresentationStateStorageSOPClass, {"XA", 3, false},//XRayAngiographicImageStorage, {"RF", 2, false},//XRayRadiofluoroscopingImageStorage, {" ", 2, false},//XRayAngiographicBiPlaneImageStorageRetired, {"NM", 3, false},//NuclearMedicineImageStorage, {" ", 2, false},//RawDataStorage, {" ", 2, false},//SpacialRegistrationStorage, {" ", 2, false},//SpacialFiducialsStorage, {"PT", 2, false},//PETImageStorage, {"RTIMAGE ", 2, false},//RTImageStorage, // FIXME {"RTDOSE", 3, false},//RTDoseStorage, {" ", 2, false},//RTStructureSetStorage, {" ", 2, false},//RTPlanStorage, {" ", 2, false},//CSANonImageStorage, {" ", 2, false},//Philips3D, {" ", 2, false},//EnhancedSR {" ", 2, false},//BasicTextSR {" ", 2, false},//HardcopyGrayscaleImageStorage {" ", 2, false},//ComprehensiveSR {" ", 2, false},//DetachedStudyManagementSOPClass {" ", 2, false},//EncapsulatedPDFStorage {" ", 2, false},//EncapsulatedCDAStorage {" ", 2, false},//StudyComponentManagementSOPClass {" ", 2, false},//DetachedVisitManagementSOPClass {" ", 2, false},//DetachedPatientManagementSOPClass {"ES", 3, false},//VideoEndoscopicImageStorage {" ", 2, false},//GeneralElectricMagneticResonanceImageStorage {" ", 2, false},//GEPrivate3DModelStorage {" ", 2, false},//ToshibaPrivateDataStorage {" ", 2, false},//MammographyCADSR {" ", 2, false},//KeyObjectSelectionDocument {" ", 2, false},//HangingProtocolStorage {" ", 2, false},//ModalityPerformedProcedureStepSOPClass {" ", 2, false},//PhilipsPrivateMRSyntheticImageStorage {"XC", 2, false},//VLPhotographicImageStorage {"SEG ", 3, false},// Segmentation Storage {" ", 2, false},// RT Ion Plan Storage {"XA", 3, false},// XRay3DAngiographicImageStorage, {"XA", 3, false},// Enhanced XA Image Storage {" ", 2, false},// RTIonBeamsTreatmentRecordStorage {"SEG", 3, false},// Surface Segmentation Storage {"SM", 3, false},// VLWholeSlideMicroscopyImageStorage {"RTRECORD", 2, false},//RTTreatmentSummaryRecordStorage {"US", 3, false},// EnhancedUSVolumeStorage {" ", 2, false},// XRayRadiationDoseSR {"ES", 2, false},// VLEndoscopicImageStorage {"MG", 3, false},// BreastTomosynthesisImageStorage {"CR", 2, false},// FujiPrivateCRImageStorage {"OP", 3, false},// OphthalmicPhotography8BitImageStorage {"OPT", 3, false},// OphthalmicTomographyImageStorage {"GM", 3, false},// VLMicroscopicImageStorage {"PT", 3, false},//EnhancedPETImageStorage, {"XC", 3, false},// VideoPhotographicImageStorage {"DX", 3, false},// XRay3DCraniofacialImageStorage {"IVOCT", 3, false},// IVOCTForPresentation, {"IVOCT", 3, false},// IVCOTForProcessing, {"CT", 3, false},// LegacyConvertedEnhancedCTImageStorage, {"MR", 3, false},// LegacyConvertedEnhancedMRImageStorage, {"PT", 3, false},// LegacyConvertedEnhancedPETImageStorage, {"MG", 3, false},// BreastProjectionXRayImageStorageForPresentation {"MG", 3, false},// BreastProjectionXRayImageStorageForProcessing {"HC", 2, false},// HardcopyGrayscaleImageStorage {"MR", 3, false},// EnhancedMRColorImageStorage {"MG", 2, false},// FujiPrivateMammoCRImageStorage {"OP", 3, false},// OphthalmicPhotography16BitImageStorage {"GM", 3, false},// VideoMicroscopicImageStorage {nullptr, 0, false} //MS_END }; unsigned int MediaStorage::GetNumberOfMSType() { const unsigned int n = MS_END; assert( n > 0 ); return n; } unsigned int MediaStorage::GetNumberOfMSString() { static const unsigned int n = sizeof( MSStrings ) / sizeof( *MSStrings ); assert( n > 0 ); return n - 1; } unsigned int MediaStorage::GetNumberOfModality() { static const unsigned int n = sizeof( MSModalityTypes ) / sizeof( *MSModalityTypes ); assert( n > 0 ); return n - 1; } const char *MediaStorage::GetModality() const { if (!MSModalityTypes[MSField].Modality) return nullptr; assert( MSModalityTypes[MSField].Modality[0] != ' ' ); // FIXME return MSModalityTypes[MSField].Modality; } unsigned int MediaStorage::GetModalityDimension() const { if (!MSModalityTypes[MSField].Modality) return 0; assert( MSModalityTypes[MSField].Dimension ); return MSModalityTypes[MSField].Dimension; } void MediaStorage::GuessFromModality(const char *modality, unsigned int dim ) { // no default value is set, it is up to the user to decide initial value if( !modality || !dim ) return; //if( strlen(modality) != 2 ) return; int i = 0; while( MSModalityTypes[i].Modality && (strcmp(modality, MSModalityTypes[i].Modality) != 0 || MSModalityTypes[i].Retired || MSModalityTypes[i].Dimension < dim )) { ++i; } if( MSModalityTypes[i].Modality ) { // Ok we found something... MSField = (MSType)i; } } std::string MediaStorage::GetFromDataSetOrHeader(DataSet const &ds, const Tag & tag) { if( ds.FindDataElement( tag ) ) { const ByteValue *sopclassuid = ds.GetDataElement( tag ).GetByteValue(); // Empty SOP Class UID: // lifetechmed/A0038329.DCM if( !sopclassuid || !sopclassuid->GetPointer() ) return std::string(); std::string sopclassuid_str( sopclassuid->GetPointer(), sopclassuid->GetLength() ); if( sopclassuid_str.find( ' ' ) != std::string::npos ) { gdcmWarningMacro( "UI contains a space character discarding" ); std::string::size_type pos = sopclassuid_str.find_last_of(' '); sopclassuid_str = sopclassuid_str.substr(0,pos); } return sopclassuid_str; } return std::string(); } bool MediaStorage::SetFromDataSetOrHeader(DataSet const &ds, const Tag & tag) { std::string ms_str = GetFromDataSetOrHeader(ds,tag); if( !ms_str.empty() ) { MediaStorage ms = MediaStorage::GetMSType(ms_str.c_str()); MSField = ms; if( ms == MS_END ) { // weird something was found, but we not find the MS anyway... gdcmWarningMacro( "Does not know what: " << ms_str << " is..." ); } return true; } return false; } std::string MediaStorage::GetFromHeader(FileMetaInformation const &fmi) { const Tag tmediastoragesopclassuid(0x0002, 0x0002); return GetFromDataSetOrHeader(fmi, tmediastoragesopclassuid); } bool MediaStorage::SetFromHeader(FileMetaInformation const &fmi) { const Tag tmediastoragesopclassuid(0x0002, 0x0002); return SetFromDataSetOrHeader(fmi, tmediastoragesopclassuid); } std::string MediaStorage::GetFromDataSet(DataSet const &ds) { const Tag tsopclassuid(0x0008, 0x0016); return GetFromDataSetOrHeader(ds, tsopclassuid); } bool MediaStorage::SetFromDataSet(DataSet const &ds) { const Tag tsopclassuid(0x0008, 0x0016); return SetFromDataSetOrHeader(ds, tsopclassuid); } void MediaStorage::SetFromSourceImageSequence(DataSet const &ds) { const Tag sourceImageSequenceTag(0x0008,0x2112); if( ds.FindDataElement( sourceImageSequenceTag ) ) { const DataElement &sourceImageSequencesq = ds.GetDataElement( sourceImageSequenceTag ); //const SequenceOfItems* sq = sourceImageSequencesq.GetSequenceOfItems(); SmartPointer sq = sourceImageSequencesq.GetValueAsSQ(); if( !sq ) return; SequenceOfItems::ConstIterator it = sq->Begin(); const DataSet &subds = it->GetNestedDataSet(); // (0008,1150) UI =MRImageStorage # 26, 1 ReferencedSOPClassUID const Tag referencedSOPClassUIDTag(0x0008,0x1150); if( subds.FindDataElement( referencedSOPClassUIDTag ) ) { const DataElement& de = subds.GetDataElement( referencedSOPClassUIDTag ); const ByteValue *sopclassuid = de.GetByteValue(); // LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm //assert( sopclassuid ); if( sopclassuid ) { std::string sopclassuid_str( sopclassuid->GetPointer(), sopclassuid->GetLength() ); if( sopclassuid_str.find( ' ' ) != std::string::npos ) { gdcmWarningMacro( "UI contains a space character discarding" ); std::string::size_type pos = sopclassuid_str.find_last_of(' '); sopclassuid_str = sopclassuid_str.substr(0,pos); } MediaStorage ms = MediaStorage::GetMSType(sopclassuid_str.c_str()); assert( ms != MS_END ); MSField = ms; } } } } bool MediaStorage::SetFromModality(DataSet const &ds) { // Ok let's try againg with little luck it contains a pixel data... // technically GDCM is called with a template DataSet before Pixel Data // is even set, so do not check for presence of this attribute at this point //if( ds.FindDataElement( Tag(0x7fe0,0x0010) ) ) { // Pixel Data found ! // Attempt to recover from the modality (0008,0060): if( ds.FindDataElement( Tag(0x0008,0x0060) ) ) { // gdcm-CR-DCMTK-16-NonSamplePerPix.dcm // Someone defined the Transfer Syntax but I have no clue what // it is. Since there is Pixel Data element, let's try to read // that as a buggy DICOM Image file... const ByteValue *bv = ds.GetDataElement( Tag(0x0008,0x0060) ).GetByteValue(); if( bv ) { std::string modality = std::string( bv->GetPointer(), bv->GetLength() ); GuessFromModality( modality.c_str() ); } } // We know there is a Pixel Data element, so make sure not to return without a default // to SC Object: if( MSField == MediaStorage::MS_END ) { gdcmWarningMacro( "Unknown/Unhandle MediaStorage, but Pixel Data element found" ); // BUG: Need to check Col*Row*Bit*NSample == PixelSize (uncompressed) MSField = MediaStorage::SecondaryCaptureImageStorage; return false; } return true; } //return false; } bool MediaStorage::SetFromFile(File const &file) { /* * DICOMDIR usually have group 0002 present, but no 0008,0016 (doh!) * So we first check in header, if found, assumed it is ok (we should * check that consistent with 0008,0016 ...) * A lot of DICOM image file are still missing the group header * this is why we check 0008,0016, and to preserve compat with ACR-NEMA * we also check Modality element to guess a fake Media Storage UID * file such as: * gdcmData/SIEMENS-MR-RGB-16Bits.dcm * are a pain to handle ... */ const FileMetaInformation &header = file.GetHeader(); std::string header_ms_str = GetFromHeader(header); const DataSet &ds = file.GetDataSet(); std::string ds_ms_str = GetFromDataSet(ds); // Easy case: if( !header_ms_str.empty() && !ds_ms_str.empty() && (header_ms_str == ds_ms_str) ) { return SetFromHeader( header ); } if( !ds_ms_str.empty() ) { // means either no header ms or different, take from dataset just in case return SetFromDataSet( ds ); } // Looks suspicious or DICOMDIR... if( !header_ms_str.empty() ) { return SetFromHeader( header ); } // old fall back if( !SetFromHeader( header ) ) { // try again but from dataset this time: gdcmDebugMacro( "No MediaStorage found in Header, looking up in DataSet" ); if( !SetFromDataSet( ds ) ) { // ACR-NEMA compat: gdcmDebugMacro( "No MediaStorage found neither in DataSet nor in FileMetaInformation, trying from Modality" ); // Attempt to read what's in Modality: if( !SetFromModality( ds ) ) { return false; } } } // BEGIN SPECIAL HANDLING FOR GDCM 1.2.x 'ReWrite'n files #if 0 else if( MSField == MediaStorage::SecondaryCaptureImageStorage ) { /* * BEGIN HACK: * Technically it should be enough to know that the image is a SecondaryCaptureImageStorage ... BUT GDCM 1.x * used to rewrite everything by default as SecondaryCaptureImageStorage so when you would look carefully * this DataSet would in fact contains *everything* from the MR Image Storage, therefore, we prefer to use * the Source Image Sequence to detect the *real* IOD...I am pretty sure this will bite us one day... */ MediaStorage ms2; ms2.SetFromSourceImageSequence(ds); if( MSField != ms2 && ms2 != MediaStorage::MS_END ) { assert( MediaStorage::IsImage( ms2 ) ); gdcmWarningMacro( "Object is declared as SecondaryCaptureImageStorage but according" " to Source Image Sequence it was derived from " << ms2 << ". Using it instead" ); MSField = ms2; } } #endif return true; } } // end namespace gdcm_ns GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmMediaStorage.h000066400000000000000000000173521412732066400260270ustar00rootroot00000000000000/*========================================================================= 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 GDCMMEDIASTORAGE_H #define GDCMMEDIASTORAGE_H #include "gdcmTransferSyntax.h" namespace gdcm { class Tag; } namespace gdcm_ns { #if !defined(SWIGPYTHON) && !defined(SWIGCSHARP) && !defined(SWIGJAVA) && !defined(SWIGPHP) using namespace gdcm; #endif class DataSet; class FileMetaInformation; class File; // WARNING: This class will be deprecated in the future. There is no reason to extend this class. // Please check the gdcm::UIDs class if adding new well known UID. /** * \brief MediaStorage * * \note * FIXME There should not be any notion of Image and/or PDF at that point * Only the codec can answer yes I support this Media Storage or not... * For instance an ImageCodec will answer yes to most of them * while a PDFCodec will answer only for the Encapsulated PDF * * \see UIDs */ class GDCM_EXPORT MediaStorage { public: typedef enum { MediaStorageDirectoryStorage = 0, ComputedRadiographyImageStorage, DigitalXRayImageStorageForPresentation, DigitalXRayImageStorageForProcessing, DigitalMammographyImageStorageForPresentation, DigitalMammographyImageStorageForProcessing, DigitalIntraoralXrayImageStorageForPresentation, DigitalIntraoralXRayImageStorageForProcessing, CTImageStorage, EnhancedCTImageStorage, UltrasoundImageStorageRetired, UltrasoundImageStorage, UltrasoundMultiFrameImageStorageRetired, UltrasoundMultiFrameImageStorage, MRImageStorage, EnhancedMRImageStorage, MRSpectroscopyStorage, NuclearMedicineImageStorageRetired, SecondaryCaptureImageStorage, MultiframeSingleBitSecondaryCaptureImageStorage, MultiframeGrayscaleByteSecondaryCaptureImageStorage, MultiframeGrayscaleWordSecondaryCaptureImageStorage, MultiframeTrueColorSecondaryCaptureImageStorage, StandaloneOverlayStorage, StandaloneCurveStorage, LeadECGWaveformStorage, // 12- GeneralECGWaveformStorage, AmbulatoryECGWaveformStorage, HemodynamicWaveformStorage, CardiacElectrophysiologyWaveformStorage, BasicVoiceAudioWaveformStorage, StandaloneModalityLUTStorage, StandaloneVOILUTStorage, GrayscaleSoftcopyPresentationStateStorageSOPClass, XRayAngiographicImageStorage, XRayRadiofluoroscopingImageStorage, XRayAngiographicBiPlaneImageStorageRetired, NuclearMedicineImageStorage, RawDataStorage, SpacialRegistrationStorage, // Spatial SpacialFiducialsStorage, // Spatial.. PETImageStorage, RTImageStorage, RTDoseStorage, RTStructureSetStorage, RTPlanStorage, CSANonImageStorage, Philips3D, EnhancedSR, BasicTextSR, HardcopyGrayscaleImageStorage, ComprehensiveSR, DetachedStudyManagementSOPClass, EncapsulatedPDFStorage, EncapsulatedCDAStorage, StudyComponentManagementSOPClass, DetachedVisitManagementSOPClass, DetachedPatientManagementSOPClass, VideoEndoscopicImageStorage, GeneralElectricMagneticResonanceImageStorage, GEPrivate3DModelStorage, ToshibaPrivateDataStorage, MammographyCADSR, KeyObjectSelectionDocument, HangingProtocolStorage, ModalityPerformedProcedureStepSOPClass, PhilipsPrivateMRSyntheticImageStorage, VLPhotographicImageStorage, SegmentationStorage, // "1.2.840.10008.5.1.4.1.1.66.4" RTIonPlanStorage, // 1.2.840.10008.5.1.4.1.1.481.8 XRay3DAngiographicImageStorage, // 1.2.840.10008.5.1.4.1.1.13.1.1 EnhancedXAImageStorage, RTIonBeamsTreatmentRecordStorage, // 1.2.840.10008.5.1.4.1.1.481.9 SurfaceSegmentationStorage, // "1.2.840.10008.5.1.4.1.1.66.5" VLWholeSlideMicroscopyImageStorage, // 1.2.840.10008.5.1.4.1.1.77.1.6 RTTreatmentSummaryRecordStorage, // 1.2.840.10008.5.1.4.1.1.481.7 EnhancedUSVolumeStorage, // 1.2.840.10008.5.1.4.1.1.6.2 XRayRadiationDoseSR, // 1.2.840.10008.5.1.4.1.1.88.67 VLEndoscopicImageStorage, // 1.2.840.10008.5.1.4.1.1.77.1.1 BreastTomosynthesisImageStorage, // 1.2.840.10008.5.1.4.1.1.13.1.3 FujiPrivateCRImageStorage, // 1.2.392.200036.9125.1.1.2 OphthalmicPhotography8BitImageStorage, // 1.2.840.10008.5.1.4.1.1.77.1.5.1 OphthalmicTomographyImageStorage, // 1.2.840.10008.5.1.4.1.1.77.1.5.4 VLMicroscopicImageStorage, EnhancedPETImageStorage, VideoPhotographicImageStorage, XRay3DCraniofacialImageStorage, IVOCTForPresentation, IVOCTForProcessing, LegacyConvertedEnhancedCTImageStorage, LegacyConvertedEnhancedMRImageStorage, LegacyConvertedEnhancedPETImageStorage, BreastProjectionXRayImageStorageForPresentation, BreastProjectionXRayImageStorageForProcessing, HardcopyColorImageStorage, EnhancedMRColorImageStorage, FujiPrivateMammoCRImageStorage, OphthalmicPhotography16BitImageStorage, VideoMicroscopicImageStorage, MS_END } MSType; // Media Storage Type typedef enum { NoObject = 0, // DICOMDIR Video, // Most common, include image, video and volume Waveform, // Isn't it simply a 1D video ? Audio, // ??? PDF, URI, // URL... Segmentation, // TODO ObjectEnd } ObjectType; /// Return the Media String associated. Will return NULL for MS_END static const char* GetMSString(MSType ts); /// Return the Media String of the object. const char* GetString() const; static MSType GetMSType(const char *str); MediaStorage(MSType type = MS_END):MSField(type) {} /// Returns whether DICOM has a Pixel Data element (7fe0,0010) /// \warning MRSpectroscopyStorage could be image but are not static bool IsImage(MSType ts); operator MSType () const { return MSField; } const char *GetModality() const; unsigned int GetModalityDimension() const; static unsigned int GetNumberOfMSType(); static unsigned int GetNumberOfMSString(); static unsigned int GetNumberOfModality(); /// Attempt to set the MediaStorage from a file: /// WARNING: When no MediaStorage & Modality are found BUT a PixelData element is found /// then MediaStorage is set to the default SecondaryCaptureImageStorage (return value is /// false in this case) bool SetFromFile(File const &file); /// Advanced user only (functions should be protected level...) /// Those function are lower level than SetFromFile bool SetFromDataSet(DataSet const &ds); // Will get the SOP Class UID bool SetFromHeader(FileMetaInformation const &fmi); // Will get the Media Storage SOP Class UID bool SetFromModality(DataSet const &ds); void GuessFromModality(const char *modality, unsigned int dimension = 2); friend std::ostream &operator<<(std::ostream &os, const MediaStorage &ms); bool IsUndefined() const { return MSField == MS_END; } protected: void SetFromSourceImageSequence(DataSet const &ds); private: bool SetFromDataSetOrHeader(DataSet const &ds, const Tag & tag); std::string GetFromDataSetOrHeader(DataSet const &ds, const Tag & tag); std::string GetFromHeader(FileMetaInformation const &fmi); std::string GetFromDataSet(DataSet const &ds); private: MSType MSField; }; //----------------------------------------------------------------------------- inline std::ostream &operator<<(std::ostream &_os, const MediaStorage &ms) { const char *msstring = MediaStorage::GetMSString(ms); _os << (msstring ? msstring : "INVALID MEDIA STORAGE"); return _os; } } // end namespace gdcm_ns #endif // GDCMMEDIASTORAGE_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmMrProtocol.cxx000066400000000000000000000134411412732066400261310ustar00rootroot00000000000000/*========================================================================= 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 "gdcmMrProtocol.h" #include #include namespace gdcm { struct MrProtocol::Element { }; using MyMapType = std::map; struct MrProtocol::Internals { MyMapType mymap; std::string csastr; int version; }; static inline bool starts_with(const std::string& s1, const std::string& s2) { return s2.size() <= s1.size() && s1.compare(0, s2.size(), s2) == 0; } MrProtocol::MrProtocol() { Pimpl = new MrProtocol::Internals; } bool MrProtocol::Load( const ByteValue * bv, const char * csastr, int version ) { if( bv ) { std::string str(bv->GetPointer(), bv->GetLength()); std::istringstream is(str); std::string s; Pimpl->version = version; if( csastr ) Pimpl->csastr = csastr; else Pimpl->csastr = ""; MyMapType &mymap = Pimpl->mymap; mymap.clear(); // Need to handle both: // ### ASCCONV BEGIN ### // as well as: // ### ASCCONV BEGIN object=MrProtDataImpl@MrProtocolData version=41310008 converter=%MEASCONST%/ConverterList/Prot_Converter.txt ### static const char begin[] = "### ASCCONV BEGIN "; static const char end[] = "### ASCCONV END ###"; bool hasstarted = false; while( std::getline(is, s ) ) { if( !hasstarted ) { hasstarted = starts_with(s, begin); if( hasstarted ) { if( version == -1 ) { // find version if not specified: static const char vers[] = "version="; std::string::size_type p = s.find(vers); if ( p != std::string::npos) { const char *v = s.c_str() + p + sizeof(vers) - 1; Pimpl->version = atoi(v); } } continue; // do not insert ASCCONV begin } } if( !hasstarted ) continue; if( starts_with(s, end) ) break; std::string::size_type pos = s.find( '=' ); if( pos != std::string::npos ) { std::string sub1 = s.substr(0, pos); sub1.erase( sub1.find_last_not_of(" \t") + 1); std::string sub2 = s.substr(pos+1); // skip the '=' char sub2.erase( 0, sub2.find_first_not_of(" \t")); mymap.insert( MyMapType::value_type(sub1, sub2) ); } else { // ### ASCCONV BEGIN ### // ### ASCCONV END ### } } } else { Pimpl->version = 0; Pimpl->csastr = ""; Pimpl->mymap.clear(); return false; } return true; } MrProtocol::~MrProtocol() { delete Pimpl; } int MrProtocol::GetVersion() const { return Pimpl->version; } static inline std::string trim(std::string str) { str.erase(0, str.find_first_not_of('"')); str.erase(str.find_last_not_of('"')+1); return str; } void MrProtocol::Print(std::ostream &os) const { { os << Pimpl->csastr << " / Version: " << Pimpl->version << std::endl; os << std::endl; MyMapType &mymap = Pimpl->mymap; for( MyMapType::const_iterator it = mymap.begin(); it != mymap.end(); ++it) { os << it->first << " : " << trim(std::string(it->second)) << std::endl; } } } const char * MrProtocol::GetMrProtocolByName(const char *name) const { if( name ) { MyMapType &mymap = Pimpl->mymap; MyMapType::const_iterator it = mymap.find ( name ); if( it == mymap.end() ) return nullptr; return it->second.c_str(); } return nullptr; } bool MrProtocol::FindMrProtocolByName(const char *name) const { if( name ) { MyMapType &mymap = Pimpl->mymap; MyMapType::const_iterator it = mymap.find ( name ); if( it != mymap.end() ) return true; } return false; } bool MrProtocol::GetSliceArray( MrProtocol::SliceArray & sa ) const { // Technically this is all boilerplate code, since we could infer the type // from the first few leters, eg: // us -> unsigned char // d -> double // ... sa.Slices.clear(); static const char saSize[] = "sSliceArray.lSize"; const char * sizestr = GetMrProtocolByName(saSize); if( sizestr == nullptr ) return false; const int size = atoi( sizestr ); sa.Slices.resize( size ); // sSliceArray.asSlice[*].sPosition.dSag // sSliceArray.asSlice[*].sPosition.dCor // sSliceArray.asSlice[*].sPosition.dTra char buf[512]; static const char templ1[] = "sSliceArray.asSlice[%d].sPosition.%s"; static const char templ2[] = "sSliceArray.asSlice[%d].sNormal.%s"; static const char *dir[3] = { "dSag", "dCor", "dTra"}; for( int i = 0; i < size; ++i ) { Slice & slice = sa.Slices[i]; { double v[3]; for( int j = 0; j < 3; ++j ) { sprintf( buf, templ1, i, dir[j] ); const char * valstr = GetMrProtocolByName(buf); // when not present this means 0.0 double val = 0.0; if( valstr ) val = atof( valstr ); v[j] = val; } Vector3 & pos = slice.Position; pos.dSag = v[0]; pos.dCor = v[1]; pos.dTra = v[2]; } { double v[3]; for( int j = 0; j < 3; ++j ) { sprintf( buf, templ2, i, dir[j] ); const char * valstr = GetMrProtocolByName(buf); // when not present this means 0.0 double val = 0.0; if( valstr ) val = atof( valstr ); v[j] = val; } Vector3 & pos = slice.Normal; pos.dSag = v[0]; pos.dCor = v[1]; pos.dTra = v[2]; } } return true; } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmMrProtocol.h000066400000000000000000000042621412732066400255570ustar00rootroot00000000000000/*========================================================================= 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 GDCMMRPROTOCOL_H #define GDCMMRPROTOCOL_H #include "gdcmTypes.h" #include "gdcmDataSet.h" namespace gdcm { class ByteValue; /* * Everything done in this code is for the sole purpose of writing interoperable * software under Sect. 1201 (f) Reverse Engineering exception of the DMCA. * If you believe anything in this code violates any law or any of your rights, * please contact us (gdcm-developers@lists.sourceforge.net) so that we can * find a solution. */ //----------------------------------------------------------------------------- class DataElement; /** * \brief Class for MrProtocol */ class GDCM_EXPORT MrProtocol { friend std::ostream& operator<<(std::ostream &_os, const MrProtocol &d); public : MrProtocol(); ~MrProtocol(); bool Load( const ByteValue * bv, const char * str, int version ); void Print(std::ostream &os) const; int GetVersion() const; const char * GetMrProtocolByName(const char *name) const; bool FindMrProtocolByName(const char *name) const; struct Vector3 { double dSag; double dCor; double dTra; }; struct Slice { Vector3 Normal; Vector3 Position; }; struct SliceArray { std::vector< Slice > Slices; }; bool GetSliceArray( MrProtocol::SliceArray & sa ) const; private: struct Element; struct Internals; Internals *Pimpl; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const MrProtocol &d) { d.Print( os ); return os; } } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMMRPROTOCOL_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmPDBElement.h000066400000000000000000000033121412732066400253710ustar00rootroot00000000000000/*========================================================================= 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 GDCMPDBELEMENT_H #define GDCMPDBELEMENT_H #include "gdcmTag.h" #include "gdcmVM.h" #include "gdcmVR.h" #include "gdcmByteValue.h" #include "gdcmSmartPointer.h" namespace gdcm { /** * \brief Class to represent a PDB Element * \see PDBHeader */ class GDCM_EXPORT PDBElement { public: PDBElement() = default; friend std::ostream& operator<<(std::ostream &os, const PDBElement &val); /// Set/Get Name const char *GetName() const { return NameField.c_str(); } void SetName(const char *name) { NameField = name; } /// Set/Get Value const char *GetValue() const { return ValueField.c_str(); } void SetValue(const char *value) { ValueField = value; } bool operator==(const PDBElement &de) const { return ValueField == de.ValueField && NameField == de.NameField; } protected: std::string NameField; std::string ValueField; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const PDBElement &val) { os << val.NameField; os << " \""; os << val.ValueField; os << "\""; return os; } } // end namespace gdcm #endif //GDCMPDBELEMENT_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmPDBHeader.cxx000066400000000000000000000200401412732066400255400ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPDBHeader.h" #include "gdcmPrivateTag.h" #include "gdcmDataElement.h" #include "gdcmDataSet.h" #include "gdcmExplicitDataElement.h" #include "gdcmSwapper.h" #include "gdcmDeflateStream.h" namespace gdcm { /* * In some GE MEDICAL SYSTEMS image one can find a Data Element: 0025,xx1b,GEMS_SERS_01 * which is documented as Protocol Data Block (compressed). * in fact this is a simple text format compressed using the gzip algorithm * * Typically one could do: * * $ gdcmraw -i input.dcm -o output.raw -t 0025,101b * * Skip the binary length (little endian encoding): * * $ dd bs=4 skip=1 if=output.raw of=foo.gz * * Check file type: * * $ file foo.gz * foo: gzip compressed data, was "Ex421Ser8Scan1", from Unix * * Gunzip ! * $ gunzip foo.gz * $ cat foo * * THANKS to: John Reiser (BitWagon.com) for hints * * For sample see: * GE_MR_0025xx1bProtocolDataBlock.dcm * ( <=> http://server.oersted.dtu.dk/personal/jw/jwpublic/courses/31540/mri/second_set/dicom/t2/b17.dcm) */ /* Typical output: * * ENTRY "Head First" * POSITION "Supine" * ANREF "NA" * COIL "HEAD" * PLANE "OBLIQUE" * SEDESCFLAG "1" * SEDESC "AX FSE T2" * IMODE "2D" * PSEQ "FSE-XL" * IOPT "FC, EDR, TRF, Fast" * PLUG "22" * FILTCHOICE "None" * BWRT "-1" * TRICKSIMG "1" * TAG_SPACE "7" * TAG_TYPE "None" * USERCV0 "0.00" * USERCV6 "0.00" * USERCV7 "0.00" * USERCV21 "0.00" * USERCV_MASK "2097344" * TE "102.0" * NECHO "1" * TR "5720.0" * NUMACQS "1" * ETL "17" * BPMMODE "0" * AUTOTRGTYPE "0" * PSDTRIG "0" * SLICEORDER "1" * VIEWORDER "1" * TRREST "0" * TRACTIVE "0" * SLICEASSET "1.00" * PHASEASSET "1.00" * SEPSERIES "0" * AUTOTRIGWIN "0" * FOV "24.0" * SLTHICK "2.0" * SPC "2.0" * GRXOPT "0" * SLOC1 "L11.8" * SLOC2 "P29.9" * SLOC3 "I50.0" * ELOC1 "L11.6" * ELOC2 "P29.4" * ELOC3 "S53.9" * NOSLC "27" * SL3PLANE "0" * SL3PLANE1 "0" * SL3PLANE2 "0" * SL3PLANE3 "0" * SPCPERPLANE1 "0.0" * SPCPERPLANE2 "0.0" * SPCPERPLANE3 "0.0" * MATRIXX "448" * MATRIXY "224" * SWAPPF "A/P" * NEX "4.00" * CONTRAST "No" * CONTAM "Yes " * TBLDELTA "0.00" * PHASEFOV "0.75" * RBW "31.25" * AUTOSHIM "Auto" * PHASECORR "Yes" * FLDIR "Freq" * NUMACCELFACTOR "1.00" * PAUSEDELMASKACQ "1" * NOTES ".pn/_3" * GRIP_NUMSLGROUPS "1" * GRIP_SLGROUP1 "-11.703952 -29.677423 1.949659 0.002380 0.004775 0.999985 0.999997 0.000175 -0.002380 0.000186 -0.999988 0.004775 27 0.000000 1 0 0" * GRIP_SATGROUP1 "0" * GRIP_SATGROUP2 "0" * GRIP_SATGROUP3 "0" * GRIP_SATGROUP4 "0" * GRIP_SATGROUP5 "0" * GRIP_SATGROUP6 "0" * GRIP_TRACKER "0" * GRIP_SPECTRO "0" * GRIP_NUMPSCVOL "0" * GRIP_PSCVOL1 "0" * GRIP_PSCVOL2 "0" * GRIP_PSCVOLFOV "0.000000" * GRIP_PSCVOLTHICK "0.000000" * AUTOSUBOPTIONS "0" * AUTOSCIC "0" * AUTOVOICE "0" * PRESETDELAY "0.0" * MASKPHASE "0" * MASKPAUSE "0" * TOTALNOSTATION "0" * STATION "0" */ PDBElement PDBHeader::PDBEEnd = PDBElement( ); const PDBElement& PDBHeader::GetPDBEEnd() const { return PDBEEnd; } int PDBHeader::readprotocoldatablock(const char *input, size_t inputlen, bool verbose) { (void)verbose; // First 4 bytes are the length (again) uint32_t len; // = *(const uint32_t*)input; memcpy(&len, input, sizeof len); SwapperNoOp::SwapArray(&len,1); //if( verbose ) // std::cout << len << "," << inputlen << std::endl; if( len + 4 + 1 == inputlen ) { //if( verbose ) // std::cout << "gzip stream was padded with an extra 0 \n"; } else if( len + 4 == inputlen ) { //if( verbose ) // std::cout << "gzip stream was not padded with an extra 0 \n"; } else { //std::cerr << "Found the Protocol Data Block but could not read length..." << std::endl; 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::istringstream is( str ); zlib_stream::zip_istream gzis( is ); // if (gzis.is_gzip()) // { // std::cout<<"crc check: "<<( gzis.check_crc() ? "ok" : "failed"); // std::cout << std::endl; // } std::string out; // We need to handle the old format and the new XML format here: // test: // static const char xmlstr[] = R"()"; bool isxml = false; while( std::getline(gzis, out) ) { if( !isxml && strncmp(out.c_str(), xmlstr, strlen(xmlstr)) == 0 ) { isxml = true; } if( isxml ) { xmltxt.append( out ); xmltxt.append( "\n" ); } else { PDBElement pdbel; std::istringstream is2( out ); std::string name, value; is2 >> name; std::getline(is2, value); pdbel.SetName( name.c_str() ); // remove the first space character and the first & last " character std::string value2( value.begin()+2, value.end()-1); pdbel.SetValue( value2.c_str() ); InternalPDBDataSet.push_back( pdbel ); } } //std::cout << out.size(); IsXML = isxml; return 0; } /* int DumpProtocolDataBlock(const std::string & filename, bool verbose) { gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); const gdcm::PrivateTag tprotocoldatablock(0x0025,0x1b,"GEMS_SERS_01"); if( !ds.FindDataElement( tprotocoldatablock) ) { std::cerr << "Could not find tag: " << tprotocoldatablock << std::endl; return 1; } const gdcm::DataElement& protocoldatablock= ds.GetDataElement( tprotocoldatablock); if ( protocoldatablock.IsEmpty() ) return 1; const gdcm::ByteValue * bv = protocoldatablock.GetByteValue(); std::cout << "Dumping: " << tprotocoldatablock << std::endl; int ret = readprotocoldatablock( bv->GetPointer(), bv->GetLength(), verbose ); return ret; } */ bool PDBHeader::LoadFromDataElement(DataElement const &protocoldatablock) { InternalPDBDataSet.clear(); if ( protocoldatablock.IsEmpty() ) return false; const gdcm::ByteValue * bv = protocoldatablock.GetByteValue(); //std::cout << "Dumping: " << tprotocoldatablock << std::endl; int ret = readprotocoldatablock( bv->GetPointer(), bv->GetLength(), false); if(ret) return false; return true; } void PDBHeader::Print(std::ostream &os) const { if( IsXML ) { os << xmltxt << std::endl; } else { std::vector::const_iterator it = InternalPDBDataSet.begin(); for(; it != InternalPDBDataSet.end(); ++it) { os << *it << std::endl; } } } const PDBElement &PDBHeader::GetPDBElementByName(const char *name) { if( !IsXML ) { std::vector::const_iterator it = InternalPDBDataSet.begin(); for(; it != InternalPDBDataSet.end(); ++it) { const char *itname = it->GetName(); if( strcmp(name, itname) == 0 ) { return *it; } } } return GetPDBEEnd(); } bool PDBHeader::FindPDBElementByName(const char *name) { if( !IsXML ) { std::vector::const_iterator it = InternalPDBDataSet.begin(); for(; it != InternalPDBDataSet.end(); ++it) { const char *itname = it->GetName(); if( strcmp(name, itname) == 0 ) { return true; } } } return false; } static const char pdbheader[] = "GEMS_SERS_01"; static const gdcm::PrivateTag t1(0x0025,0x001b,pdbheader); const PrivateTag & PDBHeader::GetPDBInfoTag() { return t1; } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmPDBHeader.h000066400000000000000000000056711412732066400252020ustar00rootroot00000000000000/*========================================================================= 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 GDCMPDBHEADER_H #define GDCMPDBHEADER_H #include "gdcmTypes.h" #include "gdcmDataSet.h" #include "gdcmPDBElement.h" namespace gdcm { /* * Everything done in this code is for the sole purpose of writing interoperable * software under Sect. 1201 (f) Reverse Engineering exception of the DMCA. * If you believe anything in this code violates any law or any of your rights, * please contact us (gdcm-developers@lists.sourceforge.net) so that we can * find a solution. */ //----------------------------------------------------------------------------- class DataElement; class PrivateTag; /** * \brief Class for PDBHeader * * \details GEMS MR Image have an Attribute (0025,1b,GEMS_SERS_01) which store the * Acquisition parameter of the MR Image. It is compressed and can therefore * not be used as is. This class de-encapsulated the Protocol Data Block and * allow users to query element by name. * * \warning * Everything you do with this code is at your own risk, since decoding process * was not written from specification documents. * * \warning: the API of this class might change. * * \see CSAHeader */ class GDCM_EXPORT PDBHeader { friend std::ostream& operator<<(std::ostream &_os, const PDBHeader &d); public : PDBHeader() = default; ~PDBHeader() = default; /// Load the PDB Header from a DataElement of a DataSet bool LoadFromDataElement(DataElement const &de); /// Print void Print(std::ostream &os) const; /// Return the Private Tag where the PDB header is stored within a DICOM DataSet static const PrivateTag & GetPDBInfoTag(); /// Lookup in the PDB header if a PDB element match the name 'name': /// \warning Case Sensitive const PDBElement &GetPDBElementByName(const char *name); /// Return true if the PDB element matching name is found or not bool FindPDBElementByName(const char *name); protected: const PDBElement& GetPDBEEnd() const; private: int readprotocoldatablock(const char *input, size_t inputlen, bool verbose); std::vector InternalPDBDataSet; static PDBElement PDBEEnd; bool IsXML; std::string xmltxt; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const PDBHeader &d) { d.Print( os ); return os; } } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMPDBHEADER_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmParseException.cxx000066400000000000000000000012021412732066400267520ustar00rootroot00000000000000/*========================================================================= 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 "gdcmParseException.h" namespace gdcm_ns { } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmParseException.h000066400000000000000000000045131412732066400264070ustar00rootroot00000000000000/*========================================================================= 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 GDCMPARSEEXCEPTION_H #define GDCMPARSEEXCEPTION_H #include "gdcmException.h" #include "gdcmDataElement.h" // Disable clang warning "dynamic exception specifications are deprecated". // We need to be C++03 and C++11 compatible, and if we remove the 'throw()' // specifier we'll get an error in C++03 by not matching the superclass. #if defined(__clang__) && defined(__has_warning) # if __has_warning("-Wdeprecated") # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wdeprecated" # endif #endif namespace gdcm_ns { /** * \brief ParseException Standard exception handling object. * */ class ParseException : public Exception { public: ParseException() = default; ~ParseException() throw() override {}; /** Assignment operator. */ ParseException &operator= ( const ParseException &orig ) { LastElement = orig.LastElement; return *this; } ParseException(const ParseException& orig):Exception(orig) { LastElement = orig.LastElement; } /** Equivalence operator. */ /* virtual bool operator==( const ParseException &orig ) { return true; }*/ /* // Multiple calls to what ?? const char* what() const throw() { static std::string strwhat; std::ostringstream oswhat; oswhat << File << ":" << Line << ":\n"; oswhat << Description; strwhat = oswhat.str(); return strwhat.c_str(); } */ void SetLastElement(DataElement& de) { LastElement = de; } const DataElement& GetLastElement() const { return LastElement; } private: // Store last parsed element before error: DataElement LastElement; }; } // end namespace gdcm_ns // Undo warning suppression. #if defined(__clang__) && defined(__has_warning) # if __has_warning("-Wdeprecated") # pragma clang diagnostic pop # endif #endif #endif GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmParser.cxx000066400000000000000000000043131412732066400252630ustar00rootroot00000000000000/*========================================================================= 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 "gdcmParser.h" namespace gdcm { static const char *ErrorStrings[] = { "FATAL", NULL }; bool Parser::Parse(const char *buffer, int len, bool isFinal) { if (len == 0) { if (!isFinal) { return true; } //PositionPtr = BufferPtr; //ErrorCode = processor(BufferPtr, ParseEndPtr = BufferEnd, 0); //if (ErrorCode == NoError) // return true; //EventEndPtr = EventPtr; //ProcessorPtr = ErrorProcessor; return false; } else { memcpy(GetBuffer(len), buffer, len); return ParseBuffer(len, isFinal); } } char *Parser::GetBuffer(int len) { return Buffer.Get(len); } Parser::ErrorType Parser::Process() { return Parser::NoError; } bool Parser::ParseBuffer(int len, bool isFinal) { const char *start = Buffer.GetStart(); const char *positionPtr = start; (void)positionPtr; Buffer.ShiftEnd(len); //bufferEnd += len; //parseEndByteIndex += len; ErrorCode = Process(); if (ErrorCode == Parser::NoError) { if (!isFinal) Buffer.UpdatePosition(); return 1; } //else { //eventEndPtr = eventPtr; //processor = errorProcessor; } return 0; } void Parser::SetUserData(void *userData) { (void)userData; } void * Parser::GetUserData() const { return UserData; } void Parser::SetElementHandler(StartElementHandler start, EndElementHandler end) { StartElement = start; EndElement = end; } unsigned long Parser::GetCurrentByteIndex() const { return 0; } Parser::ErrorType Parser::GetErrorCode() const { return ErrorCode; } const char *Parser::GetErrorString(ErrorType const &err) { return ErrorStrings[(int)err]; } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmParser.h000066400000000000000000000077521412732066400247220ustar00rootroot00000000000000/*========================================================================= 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 GDCMPARSER_H #define GDCMPARSER_H #include "gdcmTag.h" #error do not use #include "gdcmByteBuffer.h" #include // std::ifstream namespace gdcm { /** * \brief Parser ala XML_Parser from expat (SAX) * * \details Detailed description here * \note Simple API for DICOM */ class GDCM_EXPORT Parser /*: private IStream*/ { public: typedef enum { NoError, NoMemoryError, SyntaxError, NoElementsError, TagMismatchError, DuplicateAttributeError, JunkAfterDocElementError, UndefinedEntityError, UnexpectedStateError } ErrorType; Parser() : UserData(0),Buffer(),ErrorCode(NoError) {} ~Parser() {} // Parse some more of the document. The string s is a buffer containing // part (or perhaps all) of the document. The number of bytes of s that // are part of the document is indicated by len. This means that s // doesn't have to be null terminated. It also means that if len is // larger than the number of bytes in the block of memory that s points // at, then a memory fault is likely. The isFinal parameter informs the // parser that this is the last piece of the document. Frequently, the // last piece is empty (i.e. len is zero.) If a parse error occurred, // it returns 0. Otherwise it returns a non-zero value. bool Parse(const char* s, int len, bool isFinal); // Set handlers for start and end tags. Attributes are passed to the // start handler as a pointer to a vector of char pointers. Each // attribute seen in a start (or empty) tag occupies 2 consecutive places // in this vector: the attribute name followed by the attribute value. // These pairs are terminated by a null pointer. typedef void (*StartElementHandler) (void *userData, const Tag &tag, const char *atts[]); typedef void (*EndElementHandler) (void *userData, const Tag &name); void SetElementHandler(StartElementHandler start, EndElementHandler end); // Return what type of error has occurred. ErrorType GetErrorCode() const; // Return a string describing the error corresponding to code. // The code should be one of the enums that can be returned from // GetErrorCode. static const char *GetErrorString(ErrorType const &err); // Return the byte offset of the position. unsigned long GetCurrentByteIndex() const; // Miscellaneous functions // The functions in this section either obtain state information from // the parser or can be used to dynamically set parser options. // This sets the user data pointer that gets passed to handlers. void SetUserData(void *userData); // This returns the user data pointer that gets passed to handlers. void * GetUserData() const; protected: // This is just like Parse, except in this case expat provides the buffer. // By obtaining the buffer from expat with the GetBuffer function, // the application can avoid double copying of the input. bool ParseBuffer(int len, bool isFinal); // Obtain a buffer of size len to read a piece of the document into. // A NULL value is returned if expat can't allocate enough memory for // this buffer. This has to be called prior to every call to ParseBuffer. char *GetBuffer(int len); ErrorType Process(); private: std::ifstream Stream; void* UserData; ByteBuffer Buffer; ErrorType ErrorCode; StartElementHandler StartElement; EndElementHandler EndElement; }; } // end namespace gdcm #endif //GDCMPARSER_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmPreamble.cxx000066400000000000000000000040441412732066400255570ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPreamble.h" #include // memset namespace gdcm { Preamble::Preamble():Internal(nullptr) { Create(); } Preamble::~Preamble() { delete[] Internal; } std::istream &Preamble::Read(std::istream &is) { // \precondition: we are at beginning of Preamble gdcmAssertAlwaysMacro( !IsEmpty() /*&& is.tellg() == 0*/ ); if( is.read(Internal, 128+4) ) { if( Internal[128+0] == 'D' && Internal[128+1] == 'I' && Internal[128+2] == 'C' && Internal[128+3] == 'M') { return is; } } // else reset everything ! delete[] Internal; Internal = nullptr; throw Exception( "Not a DICOM V3 file (No Preamble)" ); // \postcondition we are after the Preamble (or at the beginning of file if none) } void Preamble::Valid() { if( !Internal ) Internal = new char[128+4]; memset( Internal, 0, 128 ); memcpy( Internal+128, "DICM", 4); } void Preamble::Create() { if( !Internal ) Internal = new char[128+4]; memset( Internal, 0, 128 ); memcpy( Internal+128, "DICM", 4); } void Preamble::Remove() { delete[] Internal; Internal = nullptr; // important } // \precondition we are at the beginning of file std::ostream const &Preamble::Write(std::ostream &os) const { // assert ( os.tellg()+0 == 0 ); if( Internal ) { os.write( Internal, 128+4); } // \postcondition a valid Preamble has been written to stream return os; } void Preamble::Clear() { } void Preamble::Print(std::ostream &) const { } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmPreamble.h000066400000000000000000000036271412732066400252120ustar00rootroot00000000000000/*========================================================================= 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 GDCMPREAMBLE_H #define GDCMPREAMBLE_H #include "gdcmTypes.h" #include "gdcmVL.h" namespace gdcm { /** * \brief DICOM Preamble (Part 10) */ class GDCM_EXPORT Preamble { public: Preamble(); ~Preamble(); friend std::ostream &operator<<(std::ostream &_os, const Preamble &_val); /// Clear void Clear(); /// Set Preamble to the default one void Valid(); void Create(); void Remove(); /// Read Preamble std::istream &Read(std::istream &is); /// Write Preamble std::ostream const &Write(std::ostream &os) const; /// Print Preamble void Print(std::ostream &os) const; /// Get internal pointer to preamble const char *GetInternal() const { return Internal; } /// Check if Preamble is empty bool IsEmpty() const { return !Internal; } /// Return size of Preamble VL GetLength() const { return 128 + 4; } Preamble(Preamble const &) { Create(); } Preamble& operator=(Preamble const &) { Create(); return *this; } protected: // bool IsValid() const { // is (IsValid == true) => Internal was read return true; } private: char *Internal; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const Preamble &val) { os << val.Internal; return os; } } // end namespace gdcm #endif //GDCMPREAMBLE_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmPrivateTag.cxx000066400000000000000000000055711412732066400261040ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPrivateTag.h" #include "gdcmTrace.h" #include "gdcmSystem.h" // FIXME #include // sscanf #include // numeric_limits namespace gdcm_ns { bool PrivateTag::ReadFromCommaSeparatedString(const char *str) { 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 || group > std::numeric_limits::max() || element > std::numeric_limits::max() /*|| strlen(owner.c_str()) == 0*/ ) // can't use owner.empty() { 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() ) { gdcmDebugMacro( ": " << str ); return false; } return true; } bool PrivateTag::operator<(const PrivateTag &_val) const { const Tag & t1 = *this; const Tag & t2 = _val; if( t1 == t2 ) { const char *s1 = Owner.c_str(); const char *s2 = _val.GetOwner(); assert( s1 ); assert( s2 ); if( *s1 ) assert( s1[strlen(s1)-1] != ' ' ); if( *s2 ) assert( s2[strlen(s2)-1] != ' ' ); bool res = strcmp(s1, s2) < 0; #ifdef DEBUG_DUPLICATE if( *s1 && *s2 && gdcm::System::StrCaseCmp(s1,s2) == 0 && strcmp(s1,s2) != 0 ) { // FIXME: // Typically this should only happen with the "Philips MR Imaging DD 001" vs "PHILIPS MR IMAGING DD 001" // or "Philips Imaging DD 001" vr "PHILIPS IMAGING DD 001" //assert( strcmp(Owner.c_str(), _val.GetOwner()) == 0 ); //return true; const bool res2 = gdcm::System::StrCaseCmp(s1,s2) < 0; res = res2; assert( 0 ); } #endif return res; } else return t1 < t2; } DataElement PrivateTag::GetAsDataElement() const { DataElement de; de.SetTag( *this ); de.SetVR( VR::LO ); std::string copy = Owner; if( copy.size() % 2 ) copy.push_back( ' ' ); de.SetByteValue( copy.c_str(), (uint32_t)copy.size() ); return de; } } // end namespace gdcm_ns GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmPrivateTag.h000066400000000000000000000050051412732066400255210ustar00rootroot00000000000000/*========================================================================= 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 GDCMPRIVATETAG_H #define GDCMPRIVATETAG_H #include "gdcmTag.h" #include "gdcmVR.h" #include "gdcmDataElement.h" #include #include #include #include #include // strlen #include // tolower namespace gdcm_ns { /** * \brief Class to represent a Private DICOM Data Element (Attribute) Tag (Group, Element, Owner) * \note private tag have element value in: [0x10,0xff], for instance 0x0009,0x0000 is NOT a private tag */ // TODO: We could save some space since we only store 8bits for element class GDCM_EXPORT PrivateTag : public Tag { friend std::ostream& operator<<(std::ostream &_os, const PrivateTag &_val); public: PrivateTag(uint16_t group = 0, uint16_t element = 0, const char *owner = ""):Tag(group,element),Owner(owner ? LOComp::Trim(owner) : "") { // truncate the high bits SetElement( (uint8_t)element ); } PrivateTag( Tag const & t, const char *owner = ""):Tag(t),Owner(owner ? LOComp::Trim(owner) : "") { // truncate the high bits SetElement( (uint8_t)t.GetElement()); } const char *GetOwner() const { return Owner.c_str(); } void SetOwner(const char *owner) { if(owner) Owner = LOComp::Trim(owner); } bool operator<(const PrivateTag &_val) const; /// Read PrivateTag from a string. Element number will be truncated /// to 8bits. Eg: "1234,5678,GDCM" is private tag: (1234,78,"GDCM") bool ReadFromCommaSeparatedString(const char *str); DataElement GetAsDataElement() const; private: // SIEMENS MED, GEMS_PETD_01 ... std::string Owner; }; inline std::ostream& operator<<(std::ostream &os, const PrivateTag &val) { //assert( !val.Owner.empty() ); os.setf( std::ios::right ); os << std::hex << '(' << std::setw( 4 ) << std::setfill( '0' ) << val[0] << ',' << std::setw( 2 ) << std::setfill( '0' ) << val[1] << ','; os << val.Owner; os << ')' << std::setfill( ' ' ) << std::dec; return os; } } // end namespace gdcm_ns #endif //GDCMPRIVATETAG_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmReader.cxx000066400000000000000000000610321412732066400252320ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmTrace.h" #include "gdcmVR.h" #include "gdcmFileMetaInformation.h" #include "gdcmSwapper.h" #include "gdcmDeflateStream.h" #include "gdcmSystem.h" #include "gdcmExplicitDataElement.h" #include "gdcmImplicitDataElement.h" #ifdef _MSC_VER #include // MultiByteToWideChar #endif #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION #include "gdcmUNExplicitDataElement.h" #include "gdcmCP246ExplicitDataElement.h" #include "gdcmExplicitImplicitDataElement.h" #include "gdcmUNExplicitImplicitDataElement.h" #include "gdcmVR16ExplicitDataElement.h" #endif namespace gdcm_ns { Reader::Reader():F(new File) { Stream = nullptr; Ifstream = nullptr; } Reader::~Reader() { if (Ifstream) { Ifstream->close(); delete Ifstream; Ifstream = nullptr; Stream = nullptr; } } /// \brief tells us if "DICM" is found as position 128 /// (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 /// Meta Information Header bool Reader::ReadPreamble() { return true; } /// \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 bool Reader::ReadMetaInformation() { return true; } bool Reader::ReadDataSet() { return true; } TransferSyntax Reader::GuessTransferSyntax() { // Don't call this function if you have a meta file info //assert( Header->GetTransferSyntaxType() == TransferSyntax::TS_END ); std::streampos start = Stream->tellg(); SwapCode sc = SwapCode::Unknown; TransferSyntax::NegociatedType nts = TransferSyntax::Unknown; TransferSyntax ts (TransferSyntax::TS_END); Tag t; t.Read(*Stream); if( ! (t.GetGroup() % 2) ) { switch( t.GetGroup() ) { case 0x0008: sc = SwapCode::LittleEndian; break; case 0x0800: sc = SwapCode::BigEndian; break; default: assert(0); } // Purposely not Re-use ReadVR since we can read VR_END char vr_str[3]; Stream->read(vr_str, 2); vr_str[2] = '\0'; // Cannot use GetVRTypeFromFile since is assert ... VR::VRType vr = VR::GetVRType(vr_str); if( vr != VR::VR_END ) { nts = TransferSyntax::Explicit; } else { assert( !(VR::IsSwap(vr_str))); Stream->seekg(-2, std::ios::cur); // Seek back if( t.GetElement() == 0x0000 ) { VL gl; // group length gl.Read(*Stream); switch(gl) { case 0x00000004 : sc = SwapCode::LittleEndian; // 1234 break; case 0x04000000 : sc = SwapCode::BigEndian; // 4321 break; case 0x00040000 : sc = SwapCode::BadLittleEndian; // 3412 gdcmWarningMacro( "Bad Little Endian" ); break; case 0x00000400 : sc = SwapCode::BadBigEndian; // 2143 gdcmWarningMacro( "Bad Big Endian" ); break; default: assert(0); } } nts = TransferSyntax::Implicit; } } else { gdcmWarningMacro( "Start with a private tag creator" ); assert( t.GetGroup() > 0x0002 ); switch( t.GetElement() ) { case 0x0010: sc = SwapCode::LittleEndian; break; default: assert(0); } // Purposely not Re-use ReadVR since we can read VR_END char vr_str[3]; Stream->read(vr_str, 2); vr_str[2] = '\0'; // Cannot use GetVRTypeFromFile since is assert ... VR::VRType vr = VR::GetVRType(vr_str); if( vr != VR::VR_END ) { nts = TransferSyntax::Explicit; } else { nts = TransferSyntax::Implicit; // We are reading a private creator (0x0010) so it's LO, it's // difficult to come up with something to check, maybe that // VL < 256 ... gdcmWarningMacro( "Very dangerous assertion needs some work" ); } } assert( nts != TransferSyntax::Unknown ); assert( sc != SwapCode::Unknown ); if( nts == TransferSyntax::Implicit ) { if( sc == SwapCode::BigEndian ) { ts = TransferSyntax::ImplicitVRBigEndianACRNEMA; } else if ( sc == SwapCode::LittleEndian ) { ts = TransferSyntax::ImplicitVRLittleEndian; } else { assert(0); } } else { assert(0); } Stream->seekg( start, std::ios::beg ); assert( ts != TransferSyntax::TS_END ); return ts; } namespace details { class DefaultCaller { private: DataSet & m_dataSet; public: DefaultCaller(DataSet &ds): m_dataSet(ds){} template void ReadCommon(std::istream & is) const { m_dataSet.template Read(is); } template void ReadCommonWithLength(std::istream & is, VL & length) const { m_dataSet.template ReadWithLength(is,length); // manually set eofbit: // https://groups.google.com/forum/?fromgroups#!topic/comp.lang.c++/yTW4ESh1IL8 is.setstate( std::ios::eofbit ); } static void Check(bool b, std::istream &stream) { (void)stream; if( b ) assert( stream.eof() ); } }; class ReadUpToTagCaller { private: DataSet & m_dataSet; const Tag & m_tag; std::set const & m_skipTags; public: ReadUpToTagCaller(DataSet &ds,const Tag & tag, std::set const & skiptags) : m_dataSet(ds),m_tag(tag),m_skipTags(skiptags) { } template void ReadCommon(std::istream & is) const { m_dataSet.template ReadUpToTag(is,m_tag,m_skipTags); } template void ReadCommonWithLength(std::istream & is, VL & length) const { m_dataSet.template ReadUpToTagWithLength(is,m_tag,m_skipTags,length); } static void Check(bool , std::istream &) {} }; class ReadSelectedTagsCaller { private: DataSet & m_dataSet; std::set const & m_tags; bool m_readvalues; public: ReadSelectedTagsCaller(DataSet &ds, std::set const & tags, const bool readvalues) : m_dataSet(ds),m_tags(tags),m_readvalues(readvalues) { } template void ReadCommon(std::istream & is) const { m_dataSet.template ReadSelectedTags(is,m_tags,m_readvalues); } template void ReadCommonWithLength(std::istream & is, VL & length) const { m_dataSet.template ReadSelectedTagsWithLength(is,m_tags,length,m_readvalues); } static void Check(bool , std::istream &) {} }; class ReadSelectedPrivateTagsCaller { private: DataSet & m_dataSet; std::set const & m_groups; bool m_readvalues; public: ReadSelectedPrivateTagsCaller(DataSet &ds, std::set const & groups, const bool readvalues) : m_dataSet(ds),m_groups(groups),m_readvalues(readvalues) { } template void ReadCommon(std::istream & is) const { m_dataSet.template ReadSelectedPrivateTags(is,m_groups,m_readvalues); } template void ReadCommonWithLength(std::istream & is, VL & length) const { m_dataSet.template ReadSelectedPrivateTagsWithLength(is,m_groups,length,m_readvalues); } static void Check(bool , std::istream &) {} }; } bool Reader::Read() { details::DefaultCaller caller(F->GetDataSet()); return InternalReadCommon(caller); } bool Reader::ReadUpToTag(const Tag & tag, std::set const & skiptags) { details::ReadUpToTagCaller caller(F->GetDataSet(),tag,skiptags); return InternalReadCommon(caller); } bool Reader::ReadSelectedTags( std::set const & selectedTags, bool readvalues ) { details::ReadSelectedTagsCaller caller(F->GetDataSet(), selectedTags,readvalues); return InternalReadCommon(caller); } bool Reader::ReadSelectedPrivateTags( std::set const & selectedPTags, bool readvalues ) { details::ReadSelectedPrivateTagsCaller caller(F->GetDataSet(), selectedPTags,readvalues); return InternalReadCommon(caller); } template bool Reader::InternalReadCommon(const T_Caller &caller) { if( !Stream || !*Stream ) { gdcmErrorMacro( "No File" ); return false; } bool success = true; try { std::istream &is = *Stream; bool haspreamble = true; try { F->GetHeader().GetPreamble().Read( is ); } catch( std::exception & ) { // return to beginning of file, hopefully this file is simply missing preamble is.clear(); is.seekg(0, std::ios::beg); haspreamble = false; } catch( ... ) { assert(0); } bool hasmetaheader = false; try { if( haspreamble ) { try { F->GetHeader().Read( is ); hasmetaheader = true; assert( !F->GetHeader().IsEmpty() ); } catch( std::exception &ex ) { (void)ex; //to avoid unreferenced variable warning on release gdcmWarningMacro(ex.what()); // Weird implicit meta header: is.seekg(128+4, std::ios::beg ); assert( is.good() ); try { F->GetHeader().ReadCompat(is); } catch( std::exception &ex2 ) { (void)ex2; //to avoid unreferenced variable warning on release // Ok I get it now... there is absolutely no meta header, giving up //hasmetaheader = false; gdcmErrorMacro(ex2.what()); } } } else { F->GetHeader().ReadCompat(is); } } catch( std::exception & ) { // Same player play again: is.seekg(0, std::ios::beg ); hasmetaheader = false; } catch( ... ) { // Ooops.. assert(0); } if( F->GetHeader().IsEmpty() ) { hasmetaheader = false; gdcmDebugMacro( "no file meta info found" ); } const TransferSyntax &ts = F->GetHeader().GetDataSetTransferSyntax(); if( !ts.IsValid() ) { throw Exception( "Meta Header issue" ); } // Special case where the dataset was compressed using the deflate // algorithm if( ts == TransferSyntax::DeflatedExplicitVRLittleEndian ) { zlib_stream::zip_istream gzis( is ); // FIXME: we also know in this case that we are dealing with Explicit: assert( ts.GetNegociatedType() == TransferSyntax::Explicit ); //F->GetDataSet().ReadUpToTag(gzis,tag, skiptags); caller.template ReadCommon(gzis); // I need the following hack to read: srwithgraphdeflated.dcm //is.clear(); // well not anymore, see special handling of trailing \0 in: // basic_unzip_streambuf::fill_input_buffer(void) return is.good(); } try { if( ts.GetSwapCode() == SwapCode::BigEndian ) { //US-RGB-8-epicard.dcm is big endian if( ts.GetNegociatedType() == TransferSyntax::Implicit ) { // There is no such thing as Implicit Big Endian... oh well // LIBIDO-16-ACR_NEMA-Volume.dcm //F->GetDataSet().ReadUpToTag(is,tag, skiptags); //caller.template ReadCommon(is); gdcmErrorMacro( "VirtualBigEndianNotHandled" ); throw "Virtual Big Endian Implicit is not defined by DICOM"; } else { //F->GetDataSet().ReadUpToTag(is,tag, skiptags); caller.template ReadCommon(is); } } else // LittleEndian { if( ts.GetNegociatedType() == TransferSyntax::Implicit ) { if( hasmetaheader && haspreamble ) { //F->GetDataSet().ReadUpToTag(is,tag, skiptags); caller.template ReadCommon(is); } else { std::streampos start = is.tellg(); is.seekg( 0, std::ios::end); std::streampos end = is.tellg(); assert( !is.eof() ); assert( is.good() ); std::streamoff theOffset = end-start; assert (theOffset > 0 || (uint32_t)theOffset < std::numeric_limits::max()); VL l = (uint32_t)(theOffset); is.seekg( start, std::ios::beg ); assert( is.good() ); assert( !is.eof() ); caller.template ReadCommonWithLength(is,l); } } else { caller.template ReadCommon(is); } } } // Only catch parse exception at this point catch( ParseException &ex ) { #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( ex.GetLastElement().GetVR() == VR::UN && ex.GetLastElement().IsUndefinedLength() ) { // non CP 246 // P.Read( is ); is.clear(); if( haspreamble ) { is.seekg(128+4, std::ios::beg); } else { is.seekg(0, std::ios::beg); } if( hasmetaheader ) { // FIXME: we are reading twice the same meta-header, we succedeed the first time... // We should be able to seek to proper place instead of re-reading FileMetaInformation header; header.Read(is); } // GDCM 1.X gdcmWarningMacro( "Attempt to read non CP 246" ); F->GetDataSet().Clear(); // remove garbage from 1st attempt... //F->GetDataSet().ReadUpToTag(is,tag, skiptags); caller.template ReadCommon(is); } else if( ex.GetLastElement().GetVR() == VR::UN ) { // P.Read( is ); is.clear(); if( haspreamble ) { is.seekg(128+4, std::ios::beg); } else { is.seekg(0, std::ios::beg); } if( hasmetaheader ) { // FIXME: we are reading twice the same meta-header, we succedeed the first time... // We should be able to seek to proper place instead of re-reading FileMetaInformation header; header.Read(is); } // GDCM 1.X gdcmWarningMacro( "Attempt to read GDCM 1.X wrongly encoded"); F->GetDataSet().Clear(); // remove garbage from 1st attempt... //F->GetDataSet().ReadUpToTag(is,tag, skiptags); caller.template ReadCommon(is); // This file can only be rewritten as implicit... } else if ( ex.GetLastElement().GetTag() == Tag(0xfeff,0x00e0) ) { // Famous philips where some private sequence were byteswapped ! // eg. PHILIPS_Intera-16-MONO2-Uncompress.dcm // P.Read( is ); is.clear(); if( haspreamble ) { is.seekg(128+4, std::ios::beg); } else { is.seekg(0, std::ios::beg); } if( hasmetaheader ) { // FIXME: we are reading twice the same meta-header, we succedeed the first time... // We should be able to seek to proper place instead of re-reading FileMetaInformation header; header.Read(is); } // gdcmWarningMacro( "Attempt to read Philips with ByteSwap private sequence wrongly encoded"); F->GetDataSet().Clear(); // remove garbage from 1st attempt... assert(0); // TODO FIXME } else if( ex.GetLastElement().GetVR() == VR::INVALID ) { if( ts.GetNegociatedType() == TransferSyntax::Explicit ) { try { gdcmWarningMacro( "Attempt to read file with VR16bits" ); // We could not read the VR in an explicit dataset // seek back tag + vr: is.seekg( -6, std::ios::cur ); VR16ExplicitDataElement ide; ide.template Read( is ); // If we are here it means we succeeded in reading the implicit data element: F->GetDataSet().Insert( ide ); //F->GetDataSet().template Read(is); caller.template ReadCommon(is); // This file can only be rewritten as implicit... } catch ( Exception & ) { try { // Ouch ! the file is neither: // 1. An Explicit encoded // 2. I could not reread it using the VR16Explicit reader, last option is // that the file is explicit/implicit is.clear(); if( haspreamble ) { is.seekg(128+4, std::ios::beg); } else { is.seekg(0, std::ios::beg); } if( hasmetaheader ) { // FIXME: we are reading twice the same meta-header, we succedeed the first time... // We should be able to seek to proper place instead of re-reading FileMetaInformation header; header.Read(is); } // Explicit/Implicit // gdcmData/c_vf1001.dcm falls into that category, while in fact the fmi could simply // be inverted and all would be perfect... gdcmWarningMacro( "Attempt to read file with explicit/implicit" ); F->GetDataSet().Clear(); // remove garbage from 1st attempt... //F->GetDataSet().template Read(is); caller.template ReadCommon(is); } catch ( Exception &ex2 ) { (void)ex2; // Mon Jan 24 10:59:25 CET 2011 // MM: UNExplicitImplicitDataElement does not seems to be used anymore to read // gdcmData/TheralysGDCM120Bug.dcm, instead the code path goes into // ExplicitImplicitDataElement class instead. // Simply rethrow the exception for now. throw; } } } } else { gdcmWarningMacro( "Attempt to read the file as mixture of explicit/implicit"); // Let's try again with an ExplicitImplicitDataElement: if( ts.GetSwapCode() == SwapCode::LittleEndian && ts.GetNegociatedType() == TransferSyntax::Explicit ) { // P.Read( is ); if( haspreamble ) { is.seekg(128+4, std::ios::beg); } else { is.seekg(0, std::ios::beg); } if( hasmetaheader ) { // FIXME: we are reading twice the same meta-header, we succedeed the first time... // We should be able to seek to proper place instead of re-reading FileMetaInformation header; header.ReadCompat(is); } // Philips F->GetDataSet().Clear(); // remove garbage from 1st attempt... //F->GetDataSet().ReadUpToTag(is,tag, skiptags); caller.template ReadCommon(is); // This file can only be rewritten as implicit... } else { gdcmDebugMacro( "No way this is DICOM" ); success = false; } } #else gdcmDebugMacro( ex.what() ); (void)ex; success = false; #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */ } catch( Exception &ex ) { (void)ex; //to avoid unreferenced variable warning on release gdcmDebugMacro( ex.what() ); success = false; } catch( ... ) { gdcmWarningMacro( "Unknown exception" ); success = false; } //if( success ) assert( Stream->eof() ); caller.Check(success, *Stream ); } catch( Exception &ex ) { (void)ex; //to avoid unreferenced variable warning on release gdcmDebugMacro( ex.what() ); success = false; } catch( ... ) { gdcmWarningMacro( "Unknown exception" ); success = false; } // FIXME : call this function twice... if (Ifstream && Ifstream->is_open()) { //Ifstream->close(); //delete Ifstream; //Ifstream = NULL; //Stream = NULL; } return success; } static inline bool isasciiupper( char c ) { return c >= 'A' && c <= 'Z'; } // This function re-implements code from: // http://www.dclunie.com/medical-image-faq/html/part2.html#DICOMTransferSyntaxDetermination // The above code does not work well for random file. It implicitly assumes we // are trying to read a DICOM file in the first place, while our goal is indeed // to detect whether or not the file can be assimilated as DICOM. So we // extended it. Of course this function only returns a 'maybe DICOM', since we // are not guaranteed that the stream is not truncated, but this is outside the // scope of this function. bool Reader::CanRead() const { // fastpath std::istream &is = *Stream; if( is.bad() ) return false; if( is.tellg() != std::streampos(0) ) return false; { is.seekg( 128, std::ios::beg ); // we ignore return value as we test is.good() char b[4]; if (is.good() && is.read(b,4) && strncmp(b,"DICM",4) == 0) { is.seekg(0, std::ios::beg); return true; } } // Start overhead for backward compatibility bool bigendian = false; bool explicitvr = false; is.clear(); is.seekg(0, std::ios::beg); char b[8]; if (is.good() && is.read(b,8)) { // examine probable group number ... assume <= 0x00ff if (b[0] < b[1]) bigendian=true; else if (b[0] == 0 && b[1] == 0) { // blech ... group number is zero // no point in looking at element number // as it will probably be zero too (group length) // try the 32 bit value length of implicit vr if (b[4] < b[7]) bigendian=true; } // else littleendian if (isasciiupper(b[4]) && isasciiupper(b[5])) explicitvr=true; } SwapCode sc = SwapCode::Unknown; TransferSyntax::NegociatedType nts = TransferSyntax::Unknown; std::stringstream ss( std::string(b, 8) ); Tag t; if (bigendian) { t.Read(ss); //assert( t.GetGroup() != 0x2 ); if( t.GetGroup() <= 0xff ) sc = SwapCode::BigEndian; } else { t.Read(ss); //assert( t.GetGroup() != 0x2 ); if( t.GetGroup() <= 0xff ) sc = SwapCode::LittleEndian; } VL vl; VR::VRType vr = VR::VR_END; if (explicitvr) { char vr_str[3]; vr_str[0] = b[4]; vr_str[1] = b[5]; vr_str[2] = '\0'; vr = VR::GetVRType(vr_str); if( vr != VR::VR_END ) nts = TransferSyntax::Explicit; } else { if( bigendian ) vl.Read( ss ); else vl.Read( ss ); if( vl < 0xff ) nts = TransferSyntax::Implicit; } // reset in all other cases: is.clear(); is.seekg(0, std::ios::beg); // Implicit Little Endian if( nts == TransferSyntax::Implicit && sc == SwapCode::LittleEndian ) return true; if( nts == TransferSyntax::Implicit && sc == SwapCode::BigEndian ) return false; if( nts == TransferSyntax::Explicit && sc == SwapCode::LittleEndian ) return true; if( nts == TransferSyntax::Explicit && sc == SwapCode::BigEndian ) return true; return false; } void Reader::SetFileName(const char *utf8path) { if(Ifstream) delete Ifstream; Ifstream = new std::ifstream(); if (utf8path && *utf8path) { #ifdef _MSC_VER const std::wstring uncpath = System::ConvertToUNC(utf8path); Ifstream->open(uncpath.c_str(), std::ios::binary); #else Ifstream->open( utf8path, std::ios::binary); #endif } if( Ifstream->is_open() ) { Stream = Ifstream; assert( Stream && *Stream ); } else { delete Ifstream; Ifstream = nullptr; Stream = nullptr; } } size_t Reader::GetStreamCurrentPosition() const { return static_cast(GetStreamPtr()->tellg()); } } // end namespace gdcm_ns GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmReader.h000066400000000000000000000111441412732066400246560ustar00rootroot00000000000000/*========================================================================= 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 GDCMREADER_H #define GDCMREADER_H #include "gdcmFile.h" #include namespace gdcm_ns { class StreamImageReader; /** * \brief Reader ala DOM (Document Object Model) * * \details This class is a non-validating reader, it will only performs well- * formedness check only, and to some extent catch known error (non * well-formed document). * * Detailed description here * * A DataSet DOES NOT contains group 0x0002 (see FileMetaInformation) * * This is really a DataSet reader. This will not make sure the dataset conform * to any IOD at all. This is a completely different step. The reasoning was * that user could control the IOD there lib would handle and thus we would not * be able to read a DataSet if the IOD was not found Instead we separate the * reading from the validation. * * \note * From GDCM1.x. Users will realize that one feature is missing * from this DOM implementation. In GDCM 1.x user used to be able to * control the size of the Value to be read. By default it was 0xfff. * The main author of GDCM2 thought this was too dangerous and harmful and * therefore this feature did not make it into GDCM2 * * \warning * GDCM will not produce warning for unorder (non-alphabetical order). * * \see Writer FileMetaInformation DataSet File */ class GDCM_EXPORT Reader { public: Reader(); virtual ~Reader(); /// Main function to read a file virtual bool Read(); // Execute() /// Set the filename to open. This will create a std::ifstream internally /// See SetStream if you are dealing with different std::istream object void SetFileName(const char *filename_native); /// Set the open-ed stream directly void SetStream(std::istream &input_stream) { Stream = &input_stream; } /// Set/Get File const File &GetFile() const { return *F; } /// Set/Get File File &GetFile() { return *F; } /// Set/Get File void SetFile(File& file) { F = &file; } /// Will read only up to Tag \param tag and skipping any tag specified in /// \param skiptags bool ReadUpToTag(const Tag & tag, std::set const & skiptags = std::set() ); /// Will only read the specified selected tags. bool ReadSelectedTags(std::set const & tags, bool readvalues = true); /// Will only read the specified selected private tags. bool ReadSelectedPrivateTags(std::set const & ptags, bool readvalues = true); /// Test whether this is a DICOM file /// \warning need to call either SetFileName or SetStream first bool CanRead() const; /// For wrapped language. return type is compatible with System::FileSize return type /// Use native std::streampos / std::streamoff directly from the stream from C++ size_t GetStreamCurrentPosition() const; protected: bool ReadPreamble(); bool ReadMetaInformation(); bool ReadDataSet(); SmartPointer F; friend class StreamImageReader; //need to be friended to be able to grab the GetStreamPtr //this function is added for the StreamImageReader, which needs to read //up to the pixel data and then stops right before reading the pixel data. //it's used to get that position, so that reading can continue //apace once the read function is called. //so, this function gets the stream directly, and then allows for position information //from the tellg function, and allows for stream/pointer manip in order //to read the pixel data. Note, of course, that reading pixel elements //will still have to be subject to endianness swaps, if necessary. std::istream* GetStreamPtr() const { return Stream; } private: template bool InternalReadCommon(const T_Caller &caller); TransferSyntax GuessTransferSyntax(); std::istream *Stream; std::ifstream *Ifstream; // prevent copy/move to avoid 2 ifstream leak Reader(const Reader &) = delete; Reader &operator=(const Reader &) = delete; Reader(const Reader &&) = delete; Reader &operator=(const Reader &&) = delete; }; /** * \example TestReader.cxx * \example TestReader.py * This is a C++ example on how to use gdcm::Reader */ } // end namespace gdcm_ns #endif //GDCMREADER_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmReader.strict.cxx000066400000000000000000000027401412732066400265420ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // do the magic: #define GDCM_FORCE_EXPORT #define GDCM_OVERRIDE_BROKEN_IMPLEMENTATION #undef gdcm_ns #define gdcm_ns gdcmstrict #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION #error misconfiguration #endif #include "gdcmReader.h" namespace gdcm { // make it public: GDCM_EXPORT bool StrictReadUpToTag( const char * filename, Tag const & last, std::set const & skiptags ) { gdcmstrict::Reader reader; 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" ); } return read; } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfFragments.cxx000066400000000000000000000076331412732066400277430ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSequenceOfFragments.h" #include "gdcmImplicitDataElement.h" #include "gdcmByteValue.h" namespace gdcm_ns { void SequenceOfFragments::Clear() { Table.SetByteValue( "", 0 ); Fragments.clear(); } SequenceOfFragments::SizeType SequenceOfFragments::GetNumberOfFragments() const { // Do not count the last fragment //assert( SequenceLengthField.IsUndefined() ); return Fragments.size(); } void SequenceOfFragments::AddFragment(Fragment const &item) { Fragments.push_back(item); } VL SequenceOfFragments::ComputeLength() const { VL length = 0; // First the table length += Table.GetLength(); // Then all the fragments FragmentVector::const_iterator it = Fragments.begin(); for(;it != Fragments.end(); ++it) { const VL fraglen = it->ComputeLength(); assert( fraglen % 2 == 0 ); length += fraglen; } assert( SequenceLengthField.IsUndefined() ); length += 8; // seq end delimiter (tag + vl) return length; } unsigned long SequenceOfFragments::ComputeByteLength() const { unsigned long r = 0; FragmentVector::const_iterator it = Fragments.begin(); for(;it != Fragments.end(); ++it) { assert( !it->GetVL().IsUndefined() ); r += it->GetVL(); } return r; } bool SequenceOfFragments::GetFragBuffer(unsigned int fragNb, char *buffer, unsigned long &length) const { FragmentVector::const_iterator it = Fragments.begin(); { const Fragment &frag = *(it+fragNb); const ByteValue &bv = dynamic_cast(frag.GetValue()); const VL len = frag.GetVL(); bv.GetBuffer(buffer, len); length = len; } return true; } const Fragment& SequenceOfFragments::GetFragment(SizeType num) const { assert( num < Fragments.size() ); FragmentVector::const_iterator it = Fragments.begin(); const Fragment &frag = *(it+num); return frag; } bool SequenceOfFragments::GetBuffer(char *buffer, unsigned long length) const { FragmentVector::const_iterator it = Fragments.begin(); unsigned long total = 0; for(;it != Fragments.end(); ++it) { const Fragment &frag = *it; const ByteValue &bv = dynamic_cast(frag.GetValue()); const VL len = frag.GetVL(); bv.GetBuffer(buffer, len); buffer += len; total += len; } if( total != length ) { //std::cerr << " DEBUG: " << total << " " << length << std::endl; assert(0); return false; } return true; } bool SequenceOfFragments::WriteBuffer(std::ostream &os) const { FragmentVector::const_iterator it = Fragments.begin(); unsigned long total = 0; for(;it != Fragments.end(); ++it) { const Fragment &frag = *it; const ByteValue *bv = frag.GetByteValue(); assert( bv ); const VL len = frag.GetVL(); bv->WriteBuffer(os); total += len; } //if( total != length ) // { // //std::cerr << " DEBUG: " << total << " " << length << std::endl; // assert(0); // return false; // } return true; } bool SequenceOfFragments::FillFragmentWithJPEG( Fragment & frag, std::istream & is ) { std::vector jfif; unsigned char byte; // begin /simple/ JPEG parser: while( is.read( (char*)&byte, 1 ) ) { jfif.push_back( byte ); if( byte == 0xd9 && jfif[ jfif.size() - 2 ] == 0xff ) break; } const uint32_t len = static_cast(jfif.size()); frag.SetByteValue( (char*)&jfif[0], len ); return true; } } // end namespace gdcm_ns GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfFragments.h000066400000000000000000000261761412732066400273730ustar00rootroot00000000000000/*========================================================================= 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 GDCMSEQUENCEOFFRAGMENTS_H #define GDCMSEQUENCEOFFRAGMENTS_H #include "gdcmValue.h" #include "gdcmVL.h" #include "gdcmFragment.h" #include "gdcmBasicOffsetTable.h" namespace gdcm_ns { // FIXME gdcmSequenceOfItems and gdcmSequenceOfFragments // should be rethink (duplicate code) /** * \brief Class to represent a Sequence Of Fragments * \todo I do not enforce that Sequence of Fragments ends with a SQ end del */ class GDCM_EXPORT SequenceOfFragments : public Value { public: // Typdefs: typedef std::vector FragmentVector; typedef FragmentVector::size_type SizeType; typedef FragmentVector::iterator Iterator; typedef FragmentVector::const_iterator ConstIterator; Iterator Begin() { return Fragments.begin(); } Iterator End() { return Fragments.end(); } ConstIterator Begin() const { return Fragments.begin(); } ConstIterator End() const { return Fragments.end(); } /// \brief constructor (UndefinedLength by default) SequenceOfFragments():Table(),SequenceLengthField(0xFFFFFFFF) { } /// \brief Returns the SQ length, as read from disk VL GetLength() const override { return SequenceLengthField; } /// \brief Sets the actual SQ length void SetLength(VL length) override { SequenceLengthField = length; } /// \brief Clear void Clear() override; /// \brief Appends a Fragment to the already added ones void AddFragment(Fragment const &item); // Compute the length of all fragments (and framents only!). // Basically the size of the PixelData as stored (in bytes). unsigned long ComputeByteLength() const; // Compute the length of fragments (in bytes)+ length of tag... // to be used for computation of Group Length VL ComputeLength() const; // Get the buffer bool GetBuffer(char *buffer, unsigned long length) const; bool GetFragBuffer(unsigned int fragNb, char *buffer, unsigned long &length) const; SizeType GetNumberOfFragments() const; const Fragment& GetFragment(SizeType num) const; // Write the buffer of each fragment (call WriteBuffer on all Fragments, which are // ByteValue). No Table information is written. bool WriteBuffer(std::ostream &os) const; const BasicOffsetTable &GetTable() const { return Table; } BasicOffsetTable &GetTable() { return Table; } template std::istream& Read(std::istream &is, bool readvalues = true) { assert( SequenceLengthField.IsUndefined() ); ReadPreValue(is); return ReadValue(is, readvalues); } template std::istream& ReadPreValue(std::istream &is) { // First item is the basic offset table: #if 0 try { Table.Read(is); gdcmDebugMacro( "Table: " << Table ); } catch(...) { // throw "SIEMENS Icon thingy"; // Bug_Siemens_PrivateIconNoItem.dcm // First thing first let's rewind is.seekg(-4, std::ios::cur); // FF D8 <=> Start of Image (SOI) marker // FF E0 <=> APP0 Reserved for Application Use if ( Table.GetTag() == Tag(0xd8ff,0xe0ff) ) { Table = BasicOffsetTable(); // clear up stuff //Table.SetByteValue( "", 0 ); Fragment frag; if( FillFragmentWithJPEG( frag, is ) ) { Fragments.push_back( frag ); } return is; } else { throw "Catch me if you can"; //assert(0); } } #else Table.Read(is); gdcmDebugMacro( "Table: " << Table ); #endif return is; } template std::istream& ReadValue(std::istream &is, bool /*readvalues*/) { const Tag seqDelItem(0xfffe,0xe0dd); // not used for now... Fragment frag; try { while( frag.Read(is) && frag.GetTag() != seqDelItem ) { //gdcmDebugMacro( "Frag: " << frag ); Fragments.push_back( frag ); } assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 ); } catch(Exception &ex) { (void)ex; #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // that's ok ! In all cases the whole file was read, because // Fragment::Read only fail on eof() reached 1. // SIEMENS-JPEG-CorruptFrag.dcm is more difficult to deal with, we have a // partial fragment, read we decide to add it anyway to the stack of // fragments (eof was reached so we need to clear error bit) if( frag.GetTag() == Tag(0xfffe,0xe000) ) { gdcmWarningMacro( "Pixel Data Fragment could be corrupted. Use file at own risk" ); Fragments.push_back( frag ); is.clear(); // clear the error bit } // 2. GENESIS_SIGNA-JPEG-CorruptFrag.dcm else if ( frag.GetTag() == Tag(0xddff,0x00e0) ) { assert( Fragments.size() == 1 ); const ByteValue *bv = Fragments[0].GetByteValue(); assert( (unsigned char)bv->GetPointer()[ bv->GetLength() - 1 ] == 0xfe ); // Yes this is an extra copy, this is a bug anyway, go fix YOUR code Fragments[0].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 ); gdcmWarningMacro( "JPEG Fragment length was declared with an extra byte" " at the end: stripped !" ); is.clear(); // clear the error bit } // 3. LEICA/WSI else if ( (frag.GetTag().GetGroup() == 0x00ff) && ((frag.GetTag().GetElement() & 0x00ff) == 0xe0) ) { // Looks like there is a mess with offset and odd byte array // We are going first to backtrack one byte back, and then use a // ReadBacktrack function which in turn may backtrack up to 10 bytes // backward. This appears to be working on a set of DICOM/WSI files from // LEICA gdcmWarningMacro( "Trying to fix the even-but-odd value length bug #1" ); assert( Fragments.size() ); const size_t lastf = Fragments.size() - 1; const ByteValue *bv = Fragments[ lastf ].GetByteValue(); const char *a = bv->GetPointer(); gdcmAssertAlwaysMacro( (unsigned char)a[ bv->GetLength() - 1 ] == 0xfe ); Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 ); is.seekg( -9, std::ios::cur ); assert( is.good() ); while( frag.ReadBacktrack(is) && frag.GetTag() != seqDelItem ) { gdcmDebugMacro( "Frag: " << frag ); Fragments.push_back( frag ); } assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 ); } // 4. LEICA/WSI (bis) else if ( frag.GetTag().GetGroup() == 0xe000 ) { // Looks like there is a mess with offset and odd byte array // We are going first to backtrack one byte back, and then use a // ReadBacktrack function which in turn may backtrack up to 10 bytes // backward. This appears to be working on a set of DICOM/WSI files from // LEICA gdcmWarningMacro( "Trying to fix the even-but-odd value length bug #2" ); assert( Fragments.size() ); const size_t lastf = Fragments.size() - 1; const ByteValue *bv = Fragments[ lastf ].GetByteValue(); const char *a = bv->GetPointer(); gdcmAssertAlwaysMacro( (unsigned char)a[ bv->GetLength() - 2 ] == 0xfe ); Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 2 ); is.seekg( -10, std::ios::cur ); assert( is.good() ); while( frag.ReadBacktrack(is) && frag.GetTag() != seqDelItem ) { gdcmDebugMacro( "Frag: " << frag ); Fragments.push_back( frag ); } assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 ); } // 5. LEICA/WSI (ter) else if ( (frag.GetTag().GetGroup() & 0x00ff) == 0x00e0 && (frag.GetTag().GetElement() & 0xff00) == 0x0000 ) { // Looks like there is a mess with offset and odd byte array // We are going first to backtrack one byte back, and then use a // ReadBacktrack function which in turn may backtrack up to 10 bytes // backward. This appears to be working on a set of DICOM/WSI files from // LEICA gdcmWarningMacro( "Trying to fix the even-but-odd value length bug #3" ); assert( Fragments.size() ); const size_t lastf = Fragments.size() - 1; const ByteValue *bv = Fragments[ lastf ].GetByteValue(); const char *a = bv->GetPointer(); gdcmAssertAlwaysMacro( (unsigned char)a[ bv->GetLength() - 3 ] == 0xfe ); Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 3 ); is.seekg( -11, std::ios::cur ); assert( is.good() ); while( frag.ReadBacktrack(is) && frag.GetTag() != seqDelItem ) { gdcmDebugMacro( "Frag: " << frag ); Fragments.push_back( frag ); } assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 ); } else { // 3. gdcm-JPEG-LossLess3a.dcm: easy case, an extra tag was found // instead of terminator (eof is the next char) gdcmWarningMacro( "Reading failed at Tag:" << frag.GetTag() << " Index #" << Fragments.size() << " Offset " << is.tellg() << ". Use file at own risk." << ex.what() ); } #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */ } return is; } template std::ostream const &Write(std::ostream &os) const { if( !Table.Write(os) ) { assert(0 && "Should not happen"); return os; } for(ConstIterator it = Begin();it != End(); ++it) { it->Write(os); } // seq del item is not stored, write it ! const Tag seqDelItem(0xfffe,0xe0dd); seqDelItem.Write(os); VL zero = 0; zero.Write(os); return os; } //#if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA) // For now leave it there, this does not make sense in the C++ layer // Create a new object static SmartPointer New() { return new SequenceOfFragments(); } //#endif protected: public: void Print(std::ostream &os) const override { os << "SQ L= " << SequenceLengthField << "\n"; os << "Table:" << Table << "\n"; for(ConstIterator it = Begin();it != End(); ++it) { os << " " << *it << "\n"; } assert( SequenceLengthField.IsUndefined() ); { const Tag seqDelItem(0xfffe,0xe0dd); VL zero = 0; os << seqDelItem; os << "\t" << zero; } } bool operator==(const Value &val) const override { const SequenceOfFragments &sqf = dynamic_cast(val); return Table == sqf.Table && SequenceLengthField == sqf.SequenceLengthField && Fragments == sqf.Fragments; } private: BasicOffsetTable Table; VL SequenceLengthField; /// \brief Vector of Sequence Fragments FragmentVector Fragments; private: bool FillFragmentWithJPEG( Fragment & frag, std::istream & is ); }; /** * \example DecompressJPEGFile.cs * This is a C# example on how to use gdcm::SequenceOfFragments */ } // end namespace gdcm_ns #endif //GDCMSEQUENCEOFFRAGMENTS_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfFragments.txx000066400000000000000000000013641412732066400277570ustar00rootroot00000000000000/*========================================================================= 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 GDCMSEQUENCEOFFRAGMENTS_TXX #define GDCMSEQUENCEOFFRAGMENTS_TXX #include "gdcmSequenceOfFragments.h" namespace gdcm { } // end namespace gdcm #endif // GDCMSEQUENCEOFFRAGMENTS_TXX GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfItems.cxx000066400000000000000000000037241412732066400270730ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSequenceOfItems.h" namespace gdcm_ns { void SequenceOfItems::AddItem(Item const &item) { Items.push_back( item ); if( !SequenceLengthField.IsUndefined() ) { assert(0); // TODO } } Item & SequenceOfItems::AddNewUndefinedLengthItem() { Item itemToAdd ; itemToAdd.SetVLToUndefined(); this->AddItem( itemToAdd ); return GetItem( this->GetNumberOfItems() ); } void SequenceOfItems::Clear() { Items.clear(); assert( SequenceLengthField.IsUndefined() ); } bool SequenceOfItems::RemoveItemByIndex( const SizeType position ) { if( position < 1 || position > Items.size() ) { return false; } Items.erase (Items.begin() + position - 1); return true; } Item &SequenceOfItems::GetItem(SizeType position) { if( position < 1 || position > Items.size() ) { throw Exception( "Out of Range" ); } return Items[position-1]; } const Item &SequenceOfItems::GetItem(SizeType position) const { if( position < 1 || position > Items.size() ) { throw Exception( "Out of Range" ); } return Items[position-1]; } void SequenceOfItems::SetLengthToUndefined() { SequenceLengthField = 0xFFFFFFFF; } bool SequenceOfItems::FindDataElement(const Tag &t) const { ConstIterator it = Begin(); bool found = false; for(; it != End() && !found; ++it) { const Item & item = *it; found = item.FindDataElement( t ); } return found; } } // end namespace gdcm_ns GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfItems.h000066400000000000000000000206351412732066400265200ustar00rootroot00000000000000/*========================================================================= 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 GDCMSEQUENCEOFITEMS_H #define GDCMSEQUENCEOFITEMS_H #include "gdcmValue.h" #include "gdcmItem.h" #include #include // strcmp namespace gdcm_ns { /** * \brief Class to represent a Sequence Of Items * \details (value representation : SQ) * - a Value Representation for Data Elements that contains a sequence of Data Sets. * - Sequence of Item allows for Nested Data Sets * * See PS 3.5, 7.4.6 Data Element Type Within a Sequence * \note * SEQUENCE OF ITEMS (VALUE REPRESENTATION SQ) * A Value Representation for Data Elements that contain a sequence of * Data Sets. Sequence of Items allows for Nested Data Sets. */ class GDCM_EXPORT SequenceOfItems : public Value { public: // Typdefs: typedef std::vector< Item > ItemVector; typedef ItemVector::size_type SizeType; typedef ItemVector::iterator Iterator; typedef ItemVector::const_iterator ConstIterator; Iterator Begin() { return Items.begin(); } Iterator End() { return Items.end(); } ConstIterator Begin() const { return Items.begin(); } ConstIterator End() const { return Items.end(); } /// \brief constructor (UndefinedLength by default) SequenceOfItems():SequenceLengthField(0xFFFFFFFF) { } //SequenceOfItems(VL const &vl = 0xFFFFFFFF):SequenceLengthField(vl),NType(type) { } /// \brief Returns the SQ length, as read from disk VL GetLength() const override { return SequenceLengthField; } /// \brief Sets the actual SQ length void SetLength(VL length) override { SequenceLengthField = length; } /// \brief Properly set the Sequence of Item to be undefined length void SetLengthToUndefined(); /// return if Value Length if of undefined length bool IsUndefinedLength() const { return SequenceLengthField.IsUndefined(); } template VL ComputeLength() const; /// remove all items within the sequence void Clear() override; /// \brief Appends an Item to the already added ones void AddItem(Item const &item); /// \brief Appends an Item to the already added ones Item & AddNewUndefinedLengthItem(); /// Remove an Item as specified by its index, if index > size, false is returned /// Index starts at 1 not 0 bool RemoveItemByIndex( const SizeType index ); bool IsEmpty() const { return Items.empty(); }; SizeType GetNumberOfItems() const { return Items.size(); } void SetNumberOfItems(SizeType n) { Items.resize(n); } /* WARNING: first item is #1 (see DICOM standard) * Each Item shall be implicitly assigned an ordinal position starting with the value 1 for the * first Item in the Sequence, and incremented by 1 with each subsequent Item. The last Item in the * Sequence shall have an ordinal position equal to the number of Items in the Sequence. */ const Item &GetItem(SizeType position) const; Item &GetItem(SizeType position); SequenceOfItems &operator=(const SequenceOfItems &val) { SequenceLengthField = val.SequenceLengthField; Items = val.Items; return *this; } template std::istream &Read(std::istream &is, bool readvalues = true) { (void)readvalues; const Tag seqDelItem(0xfffe,0xe0dd); if( SequenceLengthField.IsUndefined() ) { Item item; while( item.Read(is) && item.GetTag() != seqDelItem ) { //gdcmDebugMacro( "Item: " << item ); assert( item.GetTag() != seqDelItem ); Items.push_back( item ); item.Clear(); } //assert( item.GetTag() == seqDelItem && item.GetVL() == 0 ); } else { Item item; VL l = 0; //is.seekg( SequenceLengthField, std::ios::cur ); return is; while( l != SequenceLengthField ) { try { item.Read(is); } catch( Exception &ex ) { if( strcmp( ex.GetDescription(), "Changed Length" ) == 0 ) { VL newlength = l + item.template GetLength(); if( newlength > SequenceLengthField ) { // BogugsItemAndSequenceLength.dcm gdcmWarningMacro( "SQ length is wrong" ); SequenceLengthField = newlength; } } else { throw ex; } } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( item.GetTag() == seqDelItem ) { gdcmWarningMacro( "SegDelItem 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 // this way. Indeed by not adding this item we are changing the size of this sqi } else // Not a seq del item marker #endif { // By design we never load them. If we were to load those attribute // as normal item it would become very complex to convert a sequence // from defined length to undefined length with the risk to write two // seq del marker Items.push_back( item ); } l += item.template GetLength(); if( l > SequenceLengthField ) { gdcmDebugMacro( "Found: Length of Item larger than expected" ); throw "Length of Item larger than expected"; } assert( l <= SequenceLengthField ); //std::cerr << "sqi debug len: " << is.tellg() << " " << l << " " << SequenceLengthField << std::endl; #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm // (0x2005, 0x1080): for some reason computation of length fails... if( SequenceLengthField == 778 && l == 774 ) { gdcmWarningMacro( "PMS: Super bad hack" ); SequenceLengthField = l; throw Exception( "Wrong Length" ); //l = SequenceLengthField; } // Bug_Philips_ItemTag_3F3F // (0x2005, 0x1080): Because we do not handle fully the bug at the item // level we need to check here too else if ( SequenceLengthField == 444 && l == 3*71 ) { // This one is a double bug. Item length is wrong and impact SQ length gdcmWarningMacro( "PMS: Super bad hack" ); l = SequenceLengthField; } #endif } assert( l == SequenceLengthField ); } return is; } template std::ostream const &Write(std::ostream &os) const { typename ItemVector::const_iterator it = Items.begin(); for(;it != Items.end(); ++it) { it->Write(os); } if( SequenceLengthField.IsUndefined() ) { // seq del item is not stored, write it ! const Tag seqDelItem(0xfffe,0xe0dd); seqDelItem.Write(os); VL zero = 0; zero.Write(os); } return os; } //protected: void Print(std::ostream &os) const override { os << "\t(" << SequenceLengthField << ")\n"; ItemVector::const_iterator it = Items.begin(); for(;it != Items.end(); ++it) { os << " " << *it; } if( SequenceLengthField.IsUndefined() ) { const Tag seqDelItem(0xfffe,0xe0dd); VL zero = 0; os << seqDelItem; os << "\t" << zero; } } static SmartPointer New() { return new SequenceOfItems; } bool FindDataElement(const Tag &t) const; bool operator==(const Value &val) const override { const SequenceOfItems &sqi = dynamic_cast(val); return SequenceLengthField == sqi.SequenceLengthField && Items == sqi.Items; } private: public: /// \brief Total length of the Sequence (or 0xffffffff) if undefined VL SequenceLengthField; /// \brief Vector of Sequence Items ItemVector Items; }; } // end namespace gdcm_ns #include "gdcmSequenceOfItems.txx" #endif //GDCMSEQUENCEOFITEMS_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfItems.txx000066400000000000000000000023431412732066400271100ustar00rootroot00000000000000/*========================================================================= 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 GDCMSEQUENCEOFITEMS_TXX #define GDCMSEQUENCEOFITEMS_TXX namespace gdcm_ns { template VL SequenceOfItems::ComputeLength() const { typename ItemVector::const_iterator it = Items.begin(); VL length = 0; for(;it != Items.end(); ++it) { length += it->template GetLength(); } if( SequenceLengthField.IsUndefined() ) { length += 8; // item end delimiter (tag + vl) } // For defined length SQ, make sure computation is correct (compare // to original length) //assert( SequenceLengthField.IsUndefined() // || length == SequenceLengthField ); return length; } } // end namespace gdcm_ns #endif // GDCMSEQUENCEOFITEMS_TXX GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmTag.cxx000066400000000000000000000053741412732066400245520ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTag.h" #include "gdcmTrace.h" #include // sscanf namespace gdcm { bool Tag::ReadFromCommaSeparatedString(const char *str) { unsigned int group = 0, element = 0; if( !str || sscanf(str, "%04x,%04x", &group , &element) != 2 ) { gdcmDebugMacro( "Problem reading Tag: " << str ); return false; } SetGroup( (uint16_t)group ); SetElement( (uint16_t)element ); return true; } bool Tag::ReadFromContinuousString(const char *str) { unsigned int group = 0, element = 0; if( !str || sscanf(str, "%04x%04x", &group , &element) != 2 ) { gdcmDebugMacro( "Problem reading Tag: " << str ); return false; } SetGroup( (uint16_t)group ); SetElement( (uint16_t)element ); return true; } bool Tag::ReadFromPipeSeparatedString(const char *str) { unsigned int group = 0, element = 0; if( !str || sscanf(str, "%04x|%04x", &group , &element) != 2 ) { gdcmDebugMacro( "Problem reading Tag: " << str ); return false; } SetGroup( (uint16_t)group ); SetElement( (uint16_t)element ); return true; } std::string Tag::PrintAsContinuousString() const { std::ostringstream os; const Tag &val = *this; os.setf( std::ios::right); os << std::hex << std::setw( 4 ) << std::setfill( '0' ) << val[0] << std::setw( 4 ) << std::setfill( '0' ) << val[1] << std::setfill( ' ' ) << std::dec; return os.str(); } std::string Tag::PrintAsContinuousUpperCaseString() const { std::ostringstream os; const Tag &val = *this; os.setf( std::ios::right); os << std::uppercase << std::hex << std::setw( 4 ) << std::setfill( '0' ) << val[0] << std::setw( 4 ) << std::setfill( '0' ) << val[1] << std::setfill( ' ' ) << std::dec; return os.str(); } std::string Tag::PrintAsPipeSeparatedString() const { std::ostringstream _os; const Tag &_val = *this; _os.setf( std::ios::right); _os << std::hex << std::setw( 4 ) << std::setfill( '0' ) << _val[0] << '|' << std::setw( 4 ) << std::setfill( '0' ) << _val[1] << std::setfill( ' ' ) << std::dec; return _os.str(); } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmTag.h000066400000000000000000000233531412732066400241740ustar00rootroot00000000000000/*========================================================================= 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 GDCMTAG_H #define GDCMTAG_H #include "gdcmTypes.h" #include #include namespace gdcm { /** * \brief Class to represent a DICOM Data Element (Attribute) Tag (Group, Element). * \details Basically an uint32_t which can also be expressed as two uint16_t (group and * element) * \note * DATA ELEMENT TAG: * A unique identifier for a Data Element composed of an ordered pair of * numbers (a Group Number followed by an Element Number). GROUP NUMBER: The * first number in the ordered pair of numbers that makes up a Data Element * Tag. * ELEMENT NUMBER: The second number in the ordered pair of numbers that * makes up a Data Element Tag. */ class GDCM_EXPORT Tag { public: /// \brief Constructor with 2*uint16_t Tag(uint16_t group, uint16_t element) { ElementTag.tags[0] = group; ElementTag.tags[1] = element; } /// \brief Constructor with 1*uint32_t /// Prefer the cstor that takes two uint16_t Tag(uint32_t tag = 0) { SetElementTag(tag); } friend std::ostream& operator<<(std::ostream &_os, const Tag &_val); friend std::istream& operator>>(std::istream &_is, Tag &_val); /// \brief Returns the 'Group number' of the given Tag uint16_t GetGroup() const { return ElementTag.tags[0]; } /// \brief Returns the 'Element number' of the given Tag uint16_t GetElement() const { return ElementTag.tags[1]; } /// \brief Sets the 'Group number' of the given Tag void SetGroup(uint16_t group) { ElementTag.tags[0] = group; } /// \brief Sets the 'Element number' of the given Tag void SetElement(uint16_t element) { ElementTag.tags[1] = element; } /// \brief Sets the 'Group number' & 'Element number' of the given Tag void SetElementTag(uint16_t group, uint16_t element) { ElementTag.tags[0] = group; ElementTag.tags[1] = element; } /// \brief Returns the full tag value of the given Tag uint32_t GetElementTag() const { #ifndef GDCM_WORDS_BIGENDIAN return (ElementTag.tag<<16) | (ElementTag.tag>>16); #else return ElementTag.tag; #endif } /// \brief Sets the full tag value of the given Tag void SetElementTag(uint32_t tag) { #ifndef GDCM_WORDS_BIGENDIAN tag = ( (tag<<16) | (tag>>16) ); #endif ElementTag.tag = tag; } /// Returns the Group or Element of the given Tag, depending on id (0/1) const uint16_t &operator[](const unsigned int &_id) const { assert(_id<2); return ElementTag.tags[_id]; } /// Returns the Group or Element of the given Tag, depending on id (0/1) uint16_t &operator[](const unsigned int &_id) { assert(_id<2); return ElementTag.tags[_id]; } Tag &operator=(const Tag &_val) { ElementTag.tag = _val.ElementTag.tag; return *this; } bool operator==(const Tag &_val) const { return ElementTag.tag == _val.ElementTag.tag; } bool operator!=(const Tag &_val) const { return ElementTag.tag != _val.ElementTag.tag; } /// DICOM Standard expects the Data Element to be sorted by Tags /// All other comparison can be constructed from this one and operator == // FIXME FIXME FIXME TODO // the following is pretty dumb. Since we have control over who is group // and who is element, we should reverse them in little endian and big endian case // since what we really want is fast comparison and not guarantee that group is in #0 // ... bool operator<(const Tag &_val) const { #ifndef GDCM_WORDS_BIGENDIAN if( ElementTag.tags[0] < _val.ElementTag.tags[0] ) return true; if( ElementTag.tags[0] == _val.ElementTag.tags[0] && ElementTag.tags[1] < _val.ElementTag.tags[1] ) return true; return false; #else // Plain comparison is enough! return ( ElementTag.tag < _val.ElementTag.tag ); #endif } bool operator<=(const Tag &t2) const { const Tag &t1 = *this; return t1 == t2 || t1 < t2; } Tag(const Tag &_val) { ElementTag.tag = _val.ElementTag.tag; } /// return the length of tag (read: size on disk) uint32_t GetLength() const { return 4; } /// STANDARD DATA ELEMENT: A Data Element defined in the DICOM Standard, /// and therefore listed in the DICOM Data Element Dictionary in PS 3.6. /// Is the Tag from the Public dict...well the implementation is buggy /// it does not prove the element is indeed in the dict... bool IsPublic() const { return !(ElementTag.tags[0] % 2); } /// PRIVATE DATA ELEMENT: Additional Data Element, defined by an /// implementor, to communicate information that is not contained in /// Standard Data Elements. Private Data elements have odd Group Numbers. bool IsPrivate() const { return !IsPublic(); } //----------------------------------------------------------------------------- /// Read a tag from binary representation template std::istream &Read(std::istream &is) { if( is.read(ElementTag.bytes, 4) ) TSwap::SwapArray(ElementTag.tags, 2); return is; } /// Write a tag in binary rep template const std::ostream &Write(std::ostream &os) const { uint16_t copy[2]; copy[0]= ElementTag.tags[0]; copy[1]= ElementTag.tags[1]; TSwap::SwapArray(copy, 2); return os.write((char*)(©), 4); } /// Return the Private Creator Data Element tag of a private data element Tag GetPrivateCreator() const { // See PS 3.5 - 7.8.1 PRIVATE DATA ELEMENT TAGS // eg: 0x0123,0x1425 -> 0x0123,0x0014 if( IsPrivate() && !IsPrivateCreator() ) { Tag r = *this; r.SetElement( (uint16_t)(GetElement() >> 8) ); return r; } if( IsPrivateCreator() ) return *this; return Tag(0x0,0x0); } /// Set private creator: void SetPrivateCreator(Tag const &t) { // See PS 3.5 - 7.8.1 PRIVATE DATA ELEMENT TAGS // eg: 0x0123,0x0045 -> 0x0123,0x4567 assert( t.IsPrivate() /*&& t.IsPrivateCreator()*/ ); const uint16_t element = (uint16_t)(t.GetElement() << 8); const uint16_t base = (uint16_t)(GetElement() << 8); SetElement( (uint16_t)((base >> 8) + element) ); SetGroup( t.GetGroup() ); } /// Returns if tag is a Private Creator (xxxx,00yy), where xxxx is odd number /// and yy in [0x10,0xFF] bool IsPrivateCreator() const { return IsPrivate() && (GetElement() <= 0xFF && GetElement() >= 0x10); } /// return if the tag is considered to be an illegal tag bool IsIllegal() const { // DICOM reserved those groups: return GetGroup() == 0x0001 || GetGroup() == 0x0003 || GetGroup() == 0x0005 || GetGroup() == 0x0007 // This is a very special case, in private group, one cannot use element [0x01,0x09] ... // || (IsPrivate() && !IsPrivateCreator() && !IsGroupLength()); || (IsPrivate() && GetElement() > 0x0 && GetElement() < 0x10 ); } /// return whether the tag correspond to a group length tag: bool IsGroupLength() const { return GetElement() == 0x0; } /// e.g 6002,3000 belong to groupXX: 6000,3000 bool IsGroupXX(const Tag &t) const { if( t.GetElement() == GetElement() ) { if( t.IsPrivate() ) return false; uint16_t group = (uint16_t)((GetGroup() >> 8 ) << 8); return group == t.GetGroup(); } return false; } /// Read from a comma separated string. /// This is a highly user oriented function, the string should be formatted as: /// 1234,5678 to specify the tag (0x1234,0x5678) /// The notation comes from the DICOM standard, and is handy to use from a /// command line program bool ReadFromCommaSeparatedString(const char *str); /// Read From XML formatted tag value eg. tag = "12345678" /// It comes in useful when reading tag values from XML file(in NativeDICOMModel) bool ReadFromContinuousString(const char *str); /// Print tag value with no separating comma: eg. tag = "12345678" /// It comes in useful when reading tag values from XML file(in NativeDICOMModel) std::string PrintAsContinuousString() const; /// Same as PrintAsContinuousString, but hexadecimal [a-f] are printed using upper case std::string PrintAsContinuousUpperCaseString() const; /// Read from a pipe separated string (GDCM 1.x compat only). Do not use in newer code /// \see ReadFromCommaSeparatedString bool ReadFromPipeSeparatedString(const char *str); /// Print as a pipe separated string (GDCM 1.x compat only). Do not use in newer code /// \see ReadFromPipeSeparatedString std::string PrintAsPipeSeparatedString() const; private: union { uint32_t tag; uint16_t tags[2]; char bytes[4]; } ElementTag; }; //----------------------------------------------------------------------------- inline std::istream& operator>>(std::istream &_is, Tag &_val) { char c; _is >> c; uint16_t a, b; _is >> std::hex >> a; //_is >> std::hex >> _val[0]; //_is >> std::hex >> _val.ElementTag.tags[0]; _is >> c; //_is >> _val[1]; //_is >> std::hex >> _val.ElementTag.tags[1]; _is >> std::hex >> b; _is >> c; _val.SetGroup( a ); _val.SetElement( b ); return _is; } inline std::ostream& operator<<(std::ostream &_os, const Tag &_val) { _os.setf( std::ios::right); _os << std::hex << '(' << std::setw( 4 ) << std::setfill( '0' ) << _val[0] << ',' << std::setw( 4 ) << std::setfill( '0' ) << _val[1] << ')' << std::setfill( ' ' ) << std::dec; return _os; } } // end namespace gdcm #endif //GDCMTAG_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmTagToVR.cxx000066400000000000000000003351061412732066400253240ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc TagToVR.xsl Part6.xml > gdcmTagToVR.cxx /*========================================================================= 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 "gdcmVR.h" #include "gdcmVM.h" #include "gdcmStaticAssert.h" namespace gdcm { VR::VRType GetVRFromTag( Tag const & t ) { if( t.IsGroupLength() ) return VR::UL; uint32_t tag = t.GetElementTag(); switch( tag ) { case 0x00000000:return VR::UL; case 0x00000001:return VR::UL; case 0x00000002:return VR::UI; case 0x00000003:return VR::UI; case 0x00000010:return VR::SH; case 0x00000100:return VR::US; case 0x00000110:return VR::US; case 0x00000120:return VR::US; case 0x00000200:return VR::AE; case 0x00000300:return VR::AE; case 0x00000400:return VR::AE; case 0x00000600:return VR::AE; case 0x00000700:return VR::US; case 0x00000800:return VR::US; case 0x00000850:return VR::US; case 0x00000860:return VR::US; case 0x00000900:return VR::US; case 0x00000901:return VR::AT; case 0x00000902:return VR::LO; case 0x00000903:return VR::US; case 0x00001000:return VR::UI; case 0x00001001:return VR::UI; case 0x00001002:return VR::US; case 0x00001005:return VR::AT; case 0x00001008:return VR::US; case 0x00001020:return VR::US; case 0x00001021:return VR::US; case 0x00001022:return VR::US; case 0x00001023:return VR::US; case 0x00001030:return VR::AE; case 0x00001031:return VR::US; case 0x00004000:return VR::LT; case 0x00004010:return VR::LT; case 0x00005010:return VR::SH; case 0x00005020:return VR::SH; case 0x00005110:return VR::LT; case 0x00005120:return VR::LT; case 0x00005130:return VR::CS; case 0x00005140:return VR::CS; case 0x00005150:return VR::CS; case 0x00005160:return VR::CS; case 0x00005170:return VR::IS; case 0x00005180:return VR::CS; case 0x00005190:return VR::CS; case 0x000051a0:return VR::CS; case 0x000051b0:return VR::US; case 0x00020000:return VR::UL; case 0x00020001:return VR::OB; case 0x00020002:return VR::UI; case 0x00020003:return VR::UI; case 0x00020010:return VR::UI; case 0x00020012:return VR::UI; case 0x00020013:return VR::SH; case 0x00020016:return VR::AE; case 0x00020100:return VR::UI; case 0x00020102:return VR::OB; case 0x00041130:return VR::CS; case 0x00041141:return VR::CS; case 0x00041142:return VR::CS; case 0x00041200:return VR::UL; case 0x00041202:return VR::UL; case 0x00041212:return VR::US; case 0x00041220:return VR::SQ; case 0x00041400:return VR::UL; case 0x00041410:return VR::US; case 0x00041420:return VR::UL; case 0x00041430:return VR::CS; case 0x00041432:return VR::UI; case 0x00041500:return VR::CS; case 0x00041504:return VR::UL; case 0x00041510:return VR::UI; case 0x00041511:return VR::UI; case 0x00041512:return VR::UI; case 0x0004151a:return VR::UI; case 0x00041600:return VR::UL; case 0x00080001:return VR::UL; case 0x00080005:return VR::CS; case 0x00080006:return VR::SQ; case 0x00080008:return VR::CS; case 0x00080010:return VR::SH; case 0x00080012:return VR::DA; case 0x00080013:return VR::TM; case 0x00080014:return VR::UI; case 0x00080016:return VR::UI; case 0x00080018:return VR::UI; case 0x0008001a:return VR::UI; case 0x0008001b:return VR::UI; case 0x00080020:return VR::DA; case 0x00080021:return VR::DA; case 0x00080022:return VR::DA; case 0x00080023:return VR::DA; case 0x00080024:return VR::DA; case 0x00080025:return VR::DA; case 0x0008002a:return VR::DT; case 0x00080030:return VR::TM; case 0x00080031:return VR::TM; case 0x00080032:return VR::TM; case 0x00080033:return VR::TM; case 0x00080034:return VR::TM; case 0x00080035:return VR::TM; case 0x00080040:return VR::US; case 0x00080041:return VR::LO; case 0x00080042:return VR::CS; case 0x00080050:return VR::SH; case 0x00080051:return VR::SQ; case 0x00080052:return VR::CS; case 0x00080054:return VR::AE; case 0x00080056:return VR::CS; case 0x00080058:return VR::UI; case 0x00080060:return VR::CS; case 0x00080061:return VR::CS; case 0x00080062:return VR::UI; case 0x00080064:return VR::CS; case 0x00080068:return VR::CS; case 0x00080070:return VR::LO; case 0x00080080:return VR::LO; case 0x00080081:return VR::ST; case 0x00080082:return VR::SQ; case 0x00080090:return VR::PN; case 0x00080092:return VR::ST; case 0x00080094:return VR::SH; case 0x00080096:return VR::SQ; case 0x00080100:return VR::SH; case 0x00080102:return VR::SH; case 0x00080103:return VR::SH; case 0x00080104:return VR::LO; case 0x00080105:return VR::CS; case 0x00080106:return VR::DT; case 0x00080107:return VR::DT; case 0x0008010b:return VR::CS; case 0x0008010c:return VR::UI; case 0x0008010d:return VR::UI; case 0x0008010f:return VR::CS; case 0x00080110:return VR::SQ; case 0x00080112:return VR::LO; case 0x00080114:return VR::ST; case 0x00080115:return VR::ST; case 0x00080116:return VR::ST; case 0x00080117:return VR::UI; case 0x00080201:return VR::SH; case 0x00081000:return VR::AE; case 0x00081010:return VR::SH; case 0x00081030:return VR::LO; case 0x00081032:return VR::SQ; case 0x0008103e:return VR::LO; case 0x0008103f:return VR::SQ; case 0x00081040:return VR::LO; case 0x00081048:return VR::PN; case 0x00081049:return VR::SQ; case 0x00081050:return VR::PN; case 0x00081052:return VR::SQ; case 0x00081060:return VR::PN; case 0x00081062:return VR::SQ; case 0x00081070:return VR::PN; case 0x00081072:return VR::SQ; case 0x00081080:return VR::LO; case 0x00081084:return VR::SQ; case 0x00081090:return VR::LO; case 0x00081100:return VR::SQ; case 0x00081110:return VR::SQ; case 0x00081111:return VR::SQ; case 0x00081115:return VR::SQ; case 0x00081120:return VR::SQ; case 0x00081125:return VR::SQ; case 0x00081130:return VR::SQ; case 0x00081134:return VR::SQ; case 0x0008113a:return VR::SQ; case 0x00081140:return VR::SQ; case 0x00081145:return VR::SQ; case 0x0008114a:return VR::SQ; case 0x0008114b:return VR::SQ; case 0x00081150:return VR::UI; case 0x00081155:return VR::UI; case 0x0008115a:return VR::UI; case 0x00081160:return VR::IS; case 0x00081161:return VR::UL; case 0x00081162:return VR::UL; case 0x00081163:return VR::FD; case 0x00081164:return VR::SQ; case 0x00081167:return VR::UI; case 0x00081195:return VR::UI; case 0x00081197:return VR::US; case 0x00081198:return VR::SQ; case 0x00081199:return VR::SQ; case 0x00081200:return VR::SQ; case 0x00081250:return VR::SQ; case 0x00082110:return VR::CS; case 0x00082111:return VR::ST; case 0x00082112:return VR::SQ; case 0x00082120:return VR::SH; case 0x00082122:return VR::IS; case 0x00082124:return VR::IS; case 0x00082127:return VR::SH; case 0x00082128:return VR::IS; case 0x00082129:return VR::IS; case 0x0008212a:return VR::IS; case 0x00082130:return VR::DS; case 0x00082132:return VR::LO; case 0x00082133:return VR::SQ; case 0x00082134:return VR::FD; case 0x00082135:return VR::SQ; case 0x00082142:return VR::IS; case 0x00082143:return VR::IS; case 0x00082144:return VR::IS; case 0x00082200:return VR::CS; case 0x00082204:return VR::CS; case 0x00082208:return VR::CS; case 0x00082218:return VR::SQ; case 0x00082220:return VR::SQ; case 0x00082228:return VR::SQ; case 0x00082229:return VR::SQ; case 0x00082230:return VR::SQ; case 0x00082240:return VR::SQ; case 0x00082242:return VR::SQ; case 0x00082244:return VR::SQ; case 0x00082246:return VR::SQ; case 0x00082251:return VR::SQ; case 0x00082253:return VR::SQ; case 0x00082255:return VR::SQ; case 0x00082256:return VR::ST; case 0x00082257:return VR::SQ; case 0x00082258:return VR::ST; case 0x00082259:return VR::SQ; case 0x0008225a:return VR::SQ; case 0x0008225c:return VR::SQ; case 0x00083001:return VR::SQ; case 0x00083010:return VR::UI; case 0x00084000:return VR::LT; case 0x00089007:return VR::CS; case 0x00089092:return VR::SQ; case 0x00089121:return VR::SQ; case 0x00089123:return VR::UI; case 0x00089124:return VR::SQ; case 0x00089154:return VR::SQ; case 0x00089205:return VR::CS; case 0x00089206:return VR::CS; case 0x00089207:return VR::CS; case 0x00089208:return VR::CS; case 0x00089209:return VR::CS; case 0x00089215:return VR::SQ; case 0x00089237:return VR::SQ; case 0x00089410:return VR::SQ; case 0x00089458:return VR::SQ; case 0x00089459:return VR::FL; case 0x00089460:return VR::CS; case 0x00100010:return VR::PN; case 0x00100020:return VR::LO; case 0x00100021:return VR::LO; case 0x00100022:return VR::CS; case 0x00100024:return VR::SQ; case 0x00100030:return VR::DA; case 0x00100032:return VR::TM; case 0x00100040:return VR::CS; case 0x00100050:return VR::SQ; case 0x00100101:return VR::SQ; case 0x00100102:return VR::SQ; case 0x00101000:return VR::LO; case 0x00101001:return VR::PN; case 0x00101002:return VR::SQ; case 0x00101005:return VR::PN; case 0x00101010:return VR::AS; case 0x00101020:return VR::DS; case 0x00101021:return VR::SQ; case 0x00101030:return VR::DS; case 0x00101040:return VR::LO; case 0x00101050:return VR::LO; case 0x00101060:return VR::PN; case 0x00101080:return VR::LO; case 0x00101081:return VR::LO; case 0x00101090:return VR::LO; case 0x00102000:return VR::LO; case 0x00102110:return VR::LO; case 0x00102150:return VR::LO; case 0x00102152:return VR::LO; case 0x00102154:return VR::SH; case 0x00102160:return VR::SH; case 0x00102180:return VR::SH; case 0x001021a0:return VR::CS; case 0x001021b0:return VR::LT; case 0x001021c0:return VR::US; case 0x001021d0:return VR::DA; case 0x001021f0:return VR::LO; case 0x00102201:return VR::LO; case 0x00102202:return VR::SQ; case 0x00102203:return VR::CS; case 0x00102210:return VR::CS; case 0x00102292:return VR::LO; case 0x00102293:return VR::SQ; case 0x00102294:return VR::SQ; case 0x00102295:return VR::LO; case 0x00102296:return VR::SQ; case 0x00102297:return VR::PN; case 0x00102298:return VR::CS; case 0x00102299:return VR::LO; case 0x00104000:return VR::LT; case 0x00109431:return VR::FL; case 0x00120010:return VR::LO; case 0x00120020:return VR::LO; case 0x00120021:return VR::LO; case 0x00120030:return VR::LO; case 0x00120031:return VR::LO; case 0x00120040:return VR::LO; case 0x00120042:return VR::LO; case 0x00120050:return VR::LO; case 0x00120051:return VR::ST; case 0x00120060:return VR::LO; case 0x00120062:return VR::CS; case 0x00120063:return VR::LO; case 0x00120064:return VR::SQ; case 0x00120071:return VR::LO; case 0x00120072:return VR::LO; case 0x00120081:return VR::LO; case 0x00120082:return VR::LO; case 0x00120083:return VR::SQ; case 0x00120084:return VR::CS; case 0x00120085:return VR::CS; case 0x00140023:return VR::ST; case 0x00140024:return VR::ST; case 0x00140025:return VR::ST; case 0x00140028:return VR::ST; case 0x00140030:return VR::DS; case 0x00140032:return VR::DS; case 0x00140034:return VR::DS; case 0x00140042:return VR::ST; case 0x00140044:return VR::ST; case 0x00140045:return VR::ST; case 0x00140046:return VR::LT; case 0x00140050:return VR::CS; case 0x00140052:return VR::CS; case 0x00140054:return VR::DS; case 0x00140056:return VR::DS; case 0x00141010:return VR::ST; case 0x00141020:return VR::DA; case 0x00141040:return VR::ST; case 0x00142002:return VR::SQ; case 0x00142004:return VR::IS; case 0x00142006:return VR::PN; case 0x00142008:return VR::IS; case 0x00142012:return VR::SQ; case 0x00142014:return VR::IS; case 0x00142016:return VR::SH; case 0x00142018:return VR::ST; case 0x0014201a:return VR::CS; case 0x0014201c:return VR::CS; case 0x0014201e:return VR::SQ; case 0x00142030:return VR::SQ; case 0x00142032:return VR::SH; case 0x00142202:return VR::IS; case 0x00142204:return VR::SQ; case 0x00142206:return VR::ST; case 0x00142208:return VR::CS; case 0x0014220a:return VR::IS; case 0x0014220c:return VR::CS; case 0x0014220e:return VR::CS; case 0x00142210:return VR::OB; case 0x00142220:return VR::SQ; case 0x00142222:return VR::ST; case 0x00142224:return VR::IS; case 0x00142226:return VR::IS; case 0x00142228:return VR::CS; case 0x0014222a:return VR::DS; case 0x0014222c:return VR::DS; case 0x00143011:return VR::DS; case 0x00143012:return VR::DS; case 0x00143020:return VR::SQ; case 0x00143022:return VR::ST; case 0x00143024:return VR::DS; case 0x00143026:return VR::DS; case 0x00143028:return VR::DS; case 0x00143040:return VR::SQ; case 0x00143060:return VR::SQ; case 0x00143071:return VR::DS; case 0x00143072:return VR::DS; case 0x00143073:return VR::DS; case 0x00143074:return VR::LO; case 0x00143075:return VR::DS; case 0x00143076:return VR::DA; case 0x00143077:return VR::TM; case 0x00143080:return VR::OB; case 0x00143099:return VR::LT; case 0x00144002:return VR::SQ; case 0x00144004:return VR::CS; case 0x00144006:return VR::LT; case 0x00144008:return VR::SQ; case 0x0014400a:return VR::CS; case 0x0014400c:return VR::LT; case 0x0014400e:return VR::SQ; case 0x0014400f:return VR::LT; case 0x00144010:return VR::SQ; case 0x00144011:return VR::SQ; case 0x00144012:return VR::US; case 0x00144013:return VR::CS; case 0x00144014:return VR::DS; case 0x00144015:return VR::DS; case 0x00144016:return VR::DS; case 0x00144017:return VR::DS; case 0x00144018:return VR::DS; case 0x00144019:return VR::DS; case 0x0014401a:return VR::DS; case 0x0014401b:return VR::DS; case 0x0014401c:return VR::DS; case 0x00144020:return VR::SQ; case 0x00144022:return VR::DS; case 0x00144024:return VR::DS; case 0x00144026:return VR::CS; case 0x00144028:return VR::DS; case 0x00144030:return VR::SQ; case 0x00144031:return VR::DS; case 0x00144032:return VR::CS; case 0x00144033:return VR::IS; case 0x00144034:return VR::DS; case 0x00144035:return VR::SQ; case 0x00144036:return VR::CS; case 0x00144038:return VR::DS; case 0x0014403a:return VR::DS; case 0x0014403c:return VR::DS; case 0x00144040:return VR::SQ; case 0x00144050:return VR::SQ; case 0x00144051:return VR::SQ; case 0x00144052:return VR::DS; case 0x00144054:return VR::ST; case 0x00144056:return VR::ST; case 0x00144057:return VR::DS; case 0x00144058:return VR::DS; case 0x00144059:return VR::DS; case 0x0014405a:return VR::DS; case 0x0014405c:return VR::ST; case 0x00144060:return VR::SQ; case 0x00144062:return VR::DS; case 0x00144064:return VR::DS; case 0x00144070:return VR::SQ; case 0x00144072:return VR::ST; case 0x00144074:return VR::SH; case 0x00144076:return VR::DA; case 0x00144078:return VR::DA; case 0x0014407a:return VR::DA; case 0x0014407c:return VR::TM; case 0x0014407e:return VR::DA; case 0x00145002:return VR::IS; case 0x00145004:return VR::IS; case 0x00180010:return VR::LO; case 0x00180012:return VR::SQ; case 0x00180014:return VR::SQ; case 0x00180015:return VR::CS; case 0x00180020:return VR::CS; case 0x00180021:return VR::CS; case 0x00180022:return VR::CS; case 0x00180023:return VR::CS; case 0x00180024:return VR::SH; case 0x00180025:return VR::CS; case 0x00180026:return VR::SQ; case 0x00180027:return VR::TM; case 0x00180028:return VR::DS; case 0x00180029:return VR::SQ; case 0x0018002a:return VR::SQ; case 0x00180030:return VR::LO; case 0x00180031:return VR::LO; case 0x00180032:return VR::DS; case 0x00180033:return VR::DS; case 0x00180034:return VR::LO; case 0x00180035:return VR::TM; case 0x00180036:return VR::SQ; case 0x00180037:return VR::CS; case 0x00180038:return VR::CS; case 0x00180039:return VR::CS; case 0x0018003a:return VR::ST; case 0x00180040:return VR::IS; case 0x00180042:return VR::CS; case 0x00180050:return VR::DS; case 0x00180060:return VR::DS; case 0x00180070:return VR::IS; case 0x00180071:return VR::CS; case 0x00180072:return VR::DS; case 0x00180073:return VR::CS; case 0x00180074:return VR::IS; case 0x00180075:return VR::IS; case 0x00180080:return VR::DS; case 0x00180081:return VR::DS; case 0x00180082:return VR::DS; case 0x00180083:return VR::DS; case 0x00180084:return VR::DS; case 0x00180085:return VR::SH; case 0x00180086:return VR::IS; case 0x00180087:return VR::DS; case 0x00180088:return VR::DS; case 0x00180089:return VR::IS; case 0x00180090:return VR::DS; case 0x00180091:return VR::IS; case 0x00180093:return VR::DS; case 0x00180094:return VR::DS; case 0x00180095:return VR::DS; case 0x00181000:return VR::LO; case 0x00181002:return VR::UI; case 0x00181003:return VR::LO; case 0x00181004:return VR::LO; case 0x00181005:return VR::LO; case 0x00181006:return VR::LO; case 0x00181007:return VR::LO; case 0x00181008:return VR::LO; case 0x00181010:return VR::LO; case 0x00181011:return VR::LO; case 0x00181012:return VR::DA; case 0x00181014:return VR::TM; case 0x00181016:return VR::LO; case 0x00181017:return VR::LO; case 0x00181018:return VR::LO; case 0x00181019:return VR::LO; case 0x0018101a:return VR::LO; case 0x0018101b:return VR::LO; case 0x00181020:return VR::LO; case 0x00181022:return VR::SH; case 0x00181023:return VR::LO; case 0x00181030:return VR::LO; case 0x00181040:return VR::LO; case 0x00181041:return VR::DS; case 0x00181042:return VR::TM; case 0x00181043:return VR::TM; case 0x00181044:return VR::DS; case 0x00181045:return VR::IS; case 0x00181046:return VR::DS; case 0x00181047:return VR::DS; case 0x00181048:return VR::CS; case 0x00181049:return VR::DS; case 0x00181050:return VR::DS; case 0x00181060:return VR::DS; case 0x00181061:return VR::LO; case 0x00181062:return VR::IS; case 0x00181063:return VR::DS; case 0x00181064:return VR::LO; case 0x00181065:return VR::DS; case 0x00181066:return VR::DS; case 0x00181067:return VR::DS; case 0x00181068:return VR::DS; case 0x00181069:return VR::DS; case 0x0018106a:return VR::CS; case 0x0018106c:return VR::US; case 0x0018106e:return VR::UL; case 0x00181070:return VR::LO; case 0x00181071:return VR::DS; case 0x00181072:return VR::TM; case 0x00181073:return VR::TM; case 0x00181074:return VR::DS; case 0x00181075:return VR::DS; case 0x00181076:return VR::DS; case 0x00181077:return VR::DS; case 0x00181078:return VR::DT; case 0x00181079:return VR::DT; case 0x00181080:return VR::CS; case 0x00181081:return VR::IS; case 0x00181082:return VR::IS; case 0x00181083:return VR::IS; case 0x00181084:return VR::IS; case 0x00181085:return VR::LO; case 0x00181086:return VR::IS; case 0x00181088:return VR::IS; case 0x00181090:return VR::IS; case 0x00181094:return VR::IS; case 0x00181100:return VR::DS; case 0x00181110:return VR::DS; case 0x00181111:return VR::DS; case 0x00181114:return VR::DS; case 0x00181120:return VR::DS; case 0x00181121:return VR::DS; case 0x00181130:return VR::DS; case 0x00181131:return VR::DS; case 0x00181134:return VR::CS; case 0x00181135:return VR::DS; case 0x00181136:return VR::DS; case 0x00181137:return VR::DS; case 0x00181138:return VR::DS; case 0x0018113a:return VR::CS; case 0x00181140:return VR::CS; case 0x00181141:return VR::DS; case 0x00181142:return VR::DS; case 0x00181143:return VR::DS; case 0x00181144:return VR::DS; case 0x00181145:return VR::DS; case 0x00181146:return VR::DS; case 0x00181147:return VR::CS; case 0x00181149:return VR::IS; case 0x00181150:return VR::IS; case 0x00181151:return VR::IS; case 0x00181152:return VR::IS; case 0x00181153:return VR::IS; case 0x00181154:return VR::DS; case 0x00181155:return VR::CS; case 0x00181156:return VR::CS; case 0x0018115a:return VR::CS; case 0x0018115e:return VR::DS; case 0x00181160:return VR::SH; case 0x00181161:return VR::LO; case 0x00181162:return VR::DS; case 0x00181164:return VR::DS; case 0x00181166:return VR::CS; case 0x00181170:return VR::IS; case 0x00181180:return VR::SH; case 0x00181181:return VR::CS; case 0x00181182:return VR::IS; case 0x00181183:return VR::DS; case 0x00181184:return VR::DS; case 0x00181190:return VR::DS; case 0x00181191:return VR::CS; case 0x001811a0:return VR::DS; case 0x001811a2:return VR::DS; case 0x00181200:return VR::DA; case 0x00181201:return VR::TM; case 0x00181210:return VR::SH; case 0x00181240:return VR::IS; case 0x00181242:return VR::IS; case 0x00181243:return VR::IS; case 0x00181244:return VR::US; case 0x00181250:return VR::SH; case 0x00181251:return VR::SH; case 0x00181260:return VR::SH; case 0x00181261:return VR::LO; case 0x00181300:return VR::DS; case 0x00181301:return VR::CS; case 0x00181302:return VR::IS; case 0x00181310:return VR::US; case 0x00181312:return VR::CS; case 0x00181314:return VR::DS; case 0x00181315:return VR::CS; case 0x00181316:return VR::DS; case 0x00181318:return VR::DS; case 0x00181400:return VR::LO; case 0x00181401:return VR::LO; case 0x00181402:return VR::CS; case 0x00181403:return VR::CS; case 0x00181404:return VR::US; case 0x00181405:return VR::IS; case 0x00181411:return VR::DS; case 0x00181412:return VR::DS; case 0x00181413:return VR::DS; case 0x00181450:return VR::DS; case 0x00181460:return VR::DS; case 0x00181470:return VR::DS; case 0x00181480:return VR::DS; case 0x00181490:return VR::CS; case 0x00181491:return VR::CS; case 0x00181495:return VR::IS; case 0x00181500:return VR::CS; case 0x00181508:return VR::CS; case 0x00181510:return VR::DS; case 0x00181511:return VR::DS; case 0x00181520:return VR::DS; case 0x00181521:return VR::DS; case 0x00181530:return VR::DS; case 0x00181531:return VR::DS; case 0x00181600:return VR::CS; case 0x00181602:return VR::IS; case 0x00181604:return VR::IS; case 0x00181606:return VR::IS; case 0x00181608:return VR::IS; case 0x00181610:return VR::IS; case 0x00181612:return VR::IS; case 0x00181620:return VR::IS; case 0x00181622:return VR::US; case 0x00181623:return VR::US; case 0x00181624:return VR::US; case 0x00181700:return VR::CS; case 0x00181702:return VR::IS; case 0x00181704:return VR::IS; case 0x00181706:return VR::IS; case 0x00181708:return VR::IS; case 0x00181710:return VR::IS; case 0x00181712:return VR::IS; case 0x00181720:return VR::IS; case 0x00181800:return VR::CS; case 0x00181801:return VR::SH; case 0x00181802:return VR::CS; case 0x00181803:return VR::LO; case 0x00182001:return VR::IS; case 0x00182002:return VR::SH; case 0x00182003:return VR::DS; case 0x00182004:return VR::DS; case 0x00182005:return VR::DS; case 0x00182006:return VR::SH; case 0x00182010:return VR::DS; case 0x00182020:return VR::CS; case 0x00182030:return VR::DS; case 0x00183100:return VR::CS; case 0x00183101:return VR::DS; case 0x00183102:return VR::DS; case 0x00183103:return VR::IS; case 0x00183104:return VR::IS; case 0x00183105:return VR::IS; case 0x00184000:return VR::LT; case 0x00185000:return VR::SH; case 0x00185010:return VR::LO; case 0x00185012:return VR::DS; case 0x00185020:return VR::LO; case 0x00185021:return VR::LO; case 0x00185022:return VR::DS; case 0x00185024:return VR::DS; case 0x00185026:return VR::DS; case 0x00185027:return VR::DS; case 0x00185028:return VR::DS; case 0x00185029:return VR::DS; case 0x00185030:return VR::DS; case 0x00185040:return VR::DS; case 0x00185050:return VR::IS; case 0x00185100:return VR::CS; case 0x00185101:return VR::CS; case 0x00185104:return VR::SQ; case 0x00185210:return VR::DS; case 0x00185212:return VR::DS; case 0x00186000:return VR::DS; case 0x00186011:return VR::SQ; case 0x00186012:return VR::US; case 0x00186014:return VR::US; case 0x00186016:return VR::UL; case 0x00186018:return VR::UL; case 0x0018601a:return VR::UL; case 0x0018601c:return VR::UL; case 0x0018601e:return VR::UL; case 0x00186020:return VR::SL; case 0x00186022:return VR::SL; case 0x00186024:return VR::US; case 0x00186026:return VR::US; case 0x00186028:return VR::FD; case 0x0018602a:return VR::FD; case 0x0018602c:return VR::FD; case 0x0018602e:return VR::FD; case 0x00186030:return VR::UL; case 0x00186031:return VR::CS; case 0x00186032:return VR::UL; case 0x00186034:return VR::FD; case 0x00186036:return VR::FD; case 0x00186038:return VR::UL; case 0x00186039:return VR::SL; case 0x0018603a:return VR::UL; case 0x0018603b:return VR::SL; case 0x0018603c:return VR::UL; case 0x0018603d:return VR::SL; case 0x0018603e:return VR::UL; case 0x0018603f:return VR::SL; case 0x00186040:return VR::UL; case 0x00186041:return VR::SL; case 0x00186042:return VR::UL; case 0x00186043:return VR::SL; case 0x00186044:return VR::US; case 0x00186046:return VR::UL; case 0x00186048:return VR::UL; case 0x0018604a:return VR::UL; case 0x0018604c:return VR::US; case 0x0018604e:return VR::US; case 0x00186050:return VR::UL; case 0x00186052:return VR::UL; case 0x00186054:return VR::FD; case 0x00186056:return VR::UL; case 0x00186058:return VR::UL; case 0x0018605a:return VR::FL; case 0x00186060:return VR::FL; case 0x00187000:return VR::CS; case 0x00187001:return VR::DS; case 0x00187004:return VR::CS; case 0x00187005:return VR::CS; case 0x00187006:return VR::LT; case 0x00187008:return VR::LT; case 0x0018700a:return VR::SH; case 0x0018700c:return VR::DA; case 0x0018700e:return VR::TM; case 0x00187010:return VR::IS; case 0x00187011:return VR::IS; case 0x00187012:return VR::DS; case 0x00187014:return VR::DS; case 0x00187016:return VR::DS; case 0x0018701a:return VR::DS; case 0x00187020:return VR::DS; case 0x00187022:return VR::DS; case 0x00187024:return VR::CS; case 0x00187026:return VR::DS; case 0x00187028:return VR::DS; case 0x0018702a:return VR::LO; case 0x0018702b:return VR::LO; case 0x00187030:return VR::DS; case 0x00187032:return VR::DS; case 0x00187034:return VR::CS; case 0x00187036:return VR::FL; case 0x00187038:return VR::FL; case 0x00187040:return VR::LT; case 0x00187041:return VR::LT; case 0x00187042:return VR::DS; case 0x00187044:return VR::DS; case 0x00187046:return VR::IS; case 0x00187048:return VR::DS; case 0x0018704c:return VR::DS; case 0x00187050:return VR::CS; case 0x00187052:return VR::DS; case 0x00187054:return VR::DS; case 0x00187056:return VR::FL; case 0x00187058:return VR::FL; case 0x00187060:return VR::CS; case 0x00187062:return VR::LT; case 0x00187064:return VR::CS; case 0x00187065:return VR::DS; case 0x00188150:return VR::DS; case 0x00188151:return VR::DS; case 0x00189004:return VR::CS; case 0x00189005:return VR::SH; case 0x00189006:return VR::SQ; case 0x00189008:return VR::CS; case 0x00189009:return VR::CS; case 0x00189010:return VR::CS; case 0x00189011:return VR::CS; case 0x00189012:return VR::CS; case 0x00189014:return VR::CS; case 0x00189015:return VR::CS; case 0x00189016:return VR::CS; case 0x00189017:return VR::CS; case 0x00189018:return VR::CS; case 0x00189019:return VR::FD; case 0x00189020:return VR::CS; case 0x00189021:return VR::CS; case 0x00189022:return VR::CS; case 0x00189024:return VR::CS; case 0x00189025:return VR::CS; case 0x00189026:return VR::CS; case 0x00189027:return VR::CS; case 0x00189028:return VR::CS; case 0x00189029:return VR::CS; case 0x00189030:return VR::FD; case 0x00189032:return VR::CS; case 0x00189033:return VR::CS; case 0x00189034:return VR::CS; case 0x00189035:return VR::FD; case 0x00189036:return VR::CS; case 0x00189037:return VR::CS; case 0x00189041:return VR::LO; case 0x00189042:return VR::SQ; case 0x00189043:return VR::CS; case 0x00189044:return VR::CS; case 0x00189045:return VR::SQ; case 0x00189046:return VR::LO; case 0x00189047:return VR::SH; case 0x00189048:return VR::CS; case 0x00189049:return VR::SQ; case 0x00189050:return VR::LO; case 0x00189051:return VR::CS; case 0x00189052:return VR::FD; case 0x00189053:return VR::FD; case 0x00189054:return VR::CS; case 0x00189058:return VR::US; case 0x00189059:return VR::CS; case 0x00189060:return VR::CS; case 0x00189061:return VR::FD; case 0x00189062:return VR::CS; case 0x00189063:return VR::FD; case 0x00189064:return VR::CS; case 0x00189065:return VR::CS; case 0x00189066:return VR::US; case 0x00189067:return VR::CS; case 0x00189069:return VR::FD; case 0x00189070:return VR::FD; case 0x00189073:return VR::FD; case 0x00189074:return VR::DT; case 0x00189075:return VR::CS; case 0x00189076:return VR::SQ; case 0x00189077:return VR::CS; case 0x00189078:return VR::CS; case 0x00189079:return VR::FD; case 0x00189080:return VR::ST; case 0x00189081:return VR::CS; case 0x00189082:return VR::FD; case 0x00189083:return VR::SQ; case 0x00189084:return VR::SQ; case 0x00189085:return VR::CS; case 0x00189087:return VR::FD; case 0x00189089:return VR::FD; case 0x00189090:return VR::FD; case 0x00189091:return VR::FD; case 0x00189092:return VR::SQ; case 0x00189093:return VR::US; case 0x00189094:return VR::CS; case 0x00189095:return VR::UL; case 0x00189096:return VR::FD; case 0x00189098:return VR::FD; case 0x00189100:return VR::CS; case 0x00189101:return VR::CS; case 0x00189103:return VR::SQ; case 0x00189104:return VR::FD; case 0x00189105:return VR::FD; case 0x00189106:return VR::FD; case 0x00189107:return VR::SQ; case 0x00189112:return VR::SQ; case 0x00189114:return VR::SQ; case 0x00189115:return VR::SQ; case 0x00189117:return VR::SQ; case 0x00189118:return VR::SQ; case 0x00189119:return VR::SQ; case 0x00189125:return VR::SQ; case 0x00189126:return VR::SQ; case 0x00189127:return VR::UL; case 0x00189147:return VR::CS; case 0x00189151:return VR::DT; case 0x00189152:return VR::SQ; case 0x00189155:return VR::FD; case 0x00189159:return VR::UL; case 0x00189166:return VR::CS; case 0x00189168:return VR::FD; case 0x00189169:return VR::CS; case 0x00189170:return VR::CS; case 0x00189171:return VR::CS; case 0x00189172:return VR::CS; case 0x00189173:return VR::CS; case 0x00189174:return VR::CS; case 0x00189175:return VR::LO; case 0x00189176:return VR::SQ; case 0x00189177:return VR::CS; case 0x00189178:return VR::CS; case 0x00189179:return VR::CS; case 0x00189180:return VR::CS; case 0x00189181:return VR::FD; case 0x00189182:return VR::FD; case 0x00189183:return VR::CS; case 0x00189184:return VR::FD; case 0x00189185:return VR::ST; case 0x00189186:return VR::SH; case 0x00189195:return VR::FD; case 0x00189196:return VR::FD; case 0x00189197:return VR::SQ; case 0x00189198:return VR::CS; case 0x00189199:return VR::CS; case 0x00189200:return VR::CS; case 0x00189214:return VR::CS; case 0x00189217:return VR::FD; case 0x00189218:return VR::FD; case 0x00189219:return VR::SS; case 0x00189220:return VR::FD; case 0x00189226:return VR::SQ; case 0x00189227:return VR::SQ; case 0x00189231:return VR::US; case 0x00189232:return VR::US; case 0x00189234:return VR::UL; case 0x00189236:return VR::CS; case 0x00189239:return VR::SQ; case 0x00189240:return VR::US; case 0x00189241:return VR::US; case 0x00189250:return VR::CS; case 0x00189251:return VR::SQ; case 0x00189252:return VR::LO; case 0x00189253:return VR::US; case 0x00189254:return VR::FD; case 0x00189255:return VR::FD; case 0x00189256:return VR::FD; case 0x00189257:return VR::CS; case 0x00189258:return VR::UL; case 0x00189259:return VR::CS; case 0x0018925a:return VR::FD; case 0x0018925b:return VR::LO; case 0x0018925c:return VR::CS; case 0x0018925d:return VR::SQ; case 0x0018925e:return VR::LO; case 0x0018925f:return VR::UL; case 0x00189260:return VR::SQ; case 0x00189295:return VR::FD; case 0x00189296:return VR::FD; case 0x00189301:return VR::SQ; case 0x00189302:return VR::CS; case 0x00189303:return VR::FD; case 0x00189304:return VR::SQ; case 0x00189305:return VR::FD; case 0x00189306:return VR::FD; case 0x00189307:return VR::FD; case 0x00189308:return VR::SQ; case 0x00189309:return VR::FD; case 0x00189310:return VR::FD; case 0x00189311:return VR::FD; case 0x00189312:return VR::SQ; case 0x00189313:return VR::FD; case 0x00189314:return VR::SQ; case 0x00189315:return VR::CS; case 0x00189316:return VR::CS; case 0x00189317:return VR::FD; case 0x00189318:return VR::FD; case 0x00189319:return VR::FD; case 0x00189320:return VR::SH; case 0x00189321:return VR::SQ; case 0x00189322:return VR::FD; case 0x00189323:return VR::CS; case 0x00189324:return VR::FD; case 0x00189325:return VR::SQ; case 0x00189326:return VR::SQ; case 0x00189327:return VR::FD; case 0x00189328:return VR::FD; case 0x00189329:return VR::SQ; case 0x00189330:return VR::FD; case 0x00189332:return VR::FD; case 0x00189333:return VR::CS; case 0x00189334:return VR::CS; case 0x00189335:return VR::FD; case 0x00189337:return VR::US; case 0x00189338:return VR::SQ; case 0x00189340:return VR::SQ; case 0x00189341:return VR::SQ; case 0x00189342:return VR::CS; case 0x00189343:return VR::CS; case 0x00189344:return VR::CS; case 0x00189345:return VR::FD; case 0x00189346:return VR::SQ; case 0x00189351:return VR::FL; case 0x00189352:return VR::FL; case 0x00189353:return VR::FL; case 0x00189360:return VR::SQ; case 0x00189401:return VR::SQ; case 0x00189402:return VR::FL; case 0x00189403:return VR::FL; case 0x00189404:return VR::FL; case 0x00189405:return VR::SQ; case 0x00189406:return VR::SQ; case 0x00189407:return VR::SQ; case 0x00189410:return VR::CS; case 0x00189412:return VR::SQ; case 0x00189417:return VR::SQ; case 0x00189420:return VR::CS; case 0x00189423:return VR::LO; case 0x00189424:return VR::LT; case 0x00189425:return VR::CS; case 0x00189426:return VR::FL; case 0x00189427:return VR::CS; case 0x00189428:return VR::FL; case 0x00189429:return VR::FL; case 0x00189430:return VR::FL; case 0x00189432:return VR::SQ; case 0x00189433:return VR::LO; case 0x00189434:return VR::SQ; case 0x00189435:return VR::CS; case 0x00189436:return VR::SS; case 0x00189437:return VR::SS; case 0x00189438:return VR::SS; case 0x00189439:return VR::SS; case 0x00189440:return VR::SS; case 0x00189441:return VR::US; case 0x00189442:return VR::SS; case 0x00189447:return VR::FL; case 0x00189449:return VR::FL; case 0x00189451:return VR::SQ; case 0x00189452:return VR::FL; case 0x00189455:return VR::SQ; case 0x00189456:return VR::SQ; case 0x00189457:return VR::CS; case 0x00189461:return VR::FL; case 0x00189462:return VR::SQ; case 0x00189463:return VR::FL; case 0x00189464:return VR::FL; case 0x00189465:return VR::FL; case 0x00189466:return VR::FL; case 0x00189467:return VR::FL; case 0x00189468:return VR::FL; case 0x00189469:return VR::FL; case 0x00189470:return VR::FL; case 0x00189471:return VR::FL; case 0x00189472:return VR::SQ; case 0x00189473:return VR::FL; case 0x00189474:return VR::CS; case 0x00189476:return VR::SQ; case 0x00189477:return VR::SQ; case 0x00189504:return VR::SQ; case 0x00189506:return VR::SQ; case 0x00189507:return VR::SQ; case 0x00189508:return VR::FL; case 0x00189509:return VR::FL; case 0x00189510:return VR::FL; case 0x00189511:return VR::FL; case 0x00189514:return VR::FL; case 0x00189515:return VR::FL; case 0x00189516:return VR::DT; case 0x00189517:return VR::DT; case 0x00189524:return VR::LO; case 0x00189525:return VR::LO; case 0x00189526:return VR::LO; case 0x00189527:return VR::CS; case 0x00189528:return VR::LO; case 0x00189530:return VR::SQ; case 0x00189531:return VR::LO; case 0x00189538:return VR::SQ; case 0x00189601:return VR::SQ; case 0x00189602:return VR::FD; case 0x00189603:return VR::FD; case 0x00189604:return VR::FD; case 0x00189605:return VR::FD; case 0x00189606:return VR::FD; case 0x00189607:return VR::FD; case 0x00189701:return VR::DT; case 0x00189715:return VR::FD; case 0x00189716:return VR::FD; case 0x00189717:return VR::FD; case 0x00189718:return VR::FD; case 0x00189719:return VR::FD; case 0x00189720:return VR::FD; case 0x00189721:return VR::FD; case 0x00189722:return VR::FD; case 0x00189723:return VR::FD; case 0x00189724:return VR::FD; case 0x00189725:return VR::CS; case 0x00189726:return VR::FD; case 0x00189727:return VR::FD; case 0x00189729:return VR::US; case 0x00189732:return VR::SQ; case 0x00189733:return VR::SQ; case 0x00189734:return VR::SQ; case 0x00189735:return VR::SQ; case 0x00189736:return VR::SQ; case 0x00189737:return VR::SQ; case 0x00189738:return VR::CS; case 0x00189739:return VR::US; case 0x00189740:return VR::US; case 0x00189749:return VR::SQ; case 0x00189751:return VR::SQ; case 0x00189755:return VR::CS; case 0x00189756:return VR::CS; case 0x00189758:return VR::CS; case 0x00189759:return VR::CS; case 0x00189760:return VR::CS; case 0x00189761:return VR::CS; case 0x00189762:return VR::CS; case 0x00189763:return VR::CS; case 0x00189764:return VR::CS; case 0x00189765:return VR::CS; case 0x00189766:return VR::CS; case 0x00189767:return VR::CS; case 0x00189768:return VR::CS; case 0x00189769:return VR::CS; case 0x00189770:return VR::CS; case 0x00189771:return VR::SQ; case 0x00189772:return VR::SQ; case 0x00189801:return VR::FD; case 0x00189803:return VR::SQ; case 0x00189804:return VR::DT; case 0x00189805:return VR::FD; case 0x00189806:return VR::SQ; case 0x00189807:return VR::SQ; case 0x00189808:return VR::CS; case 0x00189809:return VR::SQ; case 0x0018980b:return VR::CS; case 0x0018980c:return VR::CS; case 0x0018980d:return VR::SQ; case 0x0018980e:return VR::SQ; case 0x0018980f:return VR::SQ; case 0x0018a001:return VR::SQ; case 0x0018a002:return VR::DT; case 0x0018a003:return VR::ST; case 0x0020000d:return VR::UI; case 0x0020000e:return VR::UI; case 0x00200010:return VR::SH; case 0x00200011:return VR::IS; case 0x00200012:return VR::IS; case 0x00200013:return VR::IS; case 0x00200014:return VR::IS; case 0x00200015:return VR::IS; case 0x00200016:return VR::IS; case 0x00200017:return VR::IS; case 0x00200018:return VR::IS; case 0x00200019:return VR::IS; case 0x00200020:return VR::CS; case 0x00200022:return VR::IS; case 0x00200024:return VR::IS; case 0x00200026:return VR::IS; case 0x00200030:return VR::DS; case 0x00200032:return VR::DS; case 0x00200035:return VR::DS; case 0x00200037:return VR::DS; case 0x00200050:return VR::DS; case 0x00200052:return VR::UI; case 0x00200060:return VR::CS; case 0x00200062:return VR::CS; case 0x00200070:return VR::LO; case 0x00200080:return VR::CS; case 0x002000aa:return VR::IS; case 0x00200100:return VR::IS; case 0x00200105:return VR::IS; case 0x00200110:return VR::DS; case 0x00200200:return VR::UI; case 0x00200242:return VR::UI; case 0x00201000:return VR::IS; case 0x00201001:return VR::IS; case 0x00201002:return VR::IS; case 0x00201003:return VR::IS; case 0x00201004:return VR::IS; case 0x00201005:return VR::IS; case 0x00201020:return VR::LO; case 0x00201040:return VR::LO; case 0x00201041:return VR::DS; case 0x00201070:return VR::IS; case 0x00201200:return VR::IS; case 0x00201202:return VR::IS; case 0x00201204:return VR::IS; case 0x00201206:return VR::IS; case 0x00201208:return VR::IS; case 0x00201209:return VR::IS; case 0x00203401:return VR::CS; case 0x00203402:return VR::CS; case 0x00203403:return VR::DA; case 0x00203404:return VR::LO; case 0x00203405:return VR::TM; case 0x00203406:return VR::LO; case 0x00204000:return VR::LT; case 0x00205000:return VR::AT; case 0x00205002:return VR::LO; case 0x00209056:return VR::SH; case 0x00209057:return VR::UL; case 0x00209071:return VR::SQ; case 0x00209072:return VR::CS; case 0x00209111:return VR::SQ; case 0x00209113:return VR::SQ; case 0x00209116:return VR::SQ; case 0x00209128:return VR::UL; case 0x00209153:return VR::FD; case 0x00209154:return VR::FL; case 0x00209155:return VR::FL; case 0x00209156:return VR::US; case 0x00209157:return VR::UL; case 0x00209158:return VR::LT; case 0x00209161:return VR::UI; case 0x00209162:return VR::US; case 0x00209163:return VR::US; case 0x00209164:return VR::UI; case 0x00209165:return VR::AT; case 0x00209167:return VR::AT; case 0x00209213:return VR::LO; case 0x00209221:return VR::SQ; case 0x00209222:return VR::SQ; case 0x00209228:return VR::UL; case 0x00209238:return VR::LO; case 0x00209241:return VR::FL; case 0x00209245:return VR::FL; case 0x00209246:return VR::FL; case 0x00209247:return VR::CS; case 0x00209248:return VR::FL; case 0x00209249:return VR::CS; case 0x00209250:return VR::CS; case 0x00209251:return VR::FD; case 0x00209252:return VR::FD; case 0x00209253:return VR::SQ; case 0x00209254:return VR::FD; case 0x00209255:return VR::FD; case 0x00209256:return VR::FD; case 0x00209257:return VR::FD; case 0x00209301:return VR::FD; case 0x00209302:return VR::FD; case 0x00209307:return VR::CS; case 0x00209308:return VR::FD; case 0x00209309:return VR::FD; case 0x0020930a:return VR::FD; case 0x0020930c:return VR::CS; case 0x0020930d:return VR::FD; case 0x0020930e:return VR::SQ; case 0x0020930f:return VR::SQ; case 0x00209310:return VR::SQ; case 0x00209311:return VR::CS; case 0x00209312:return VR::UI; case 0x00209313:return VR::UI; case 0x00209421:return VR::LO; case 0x00209450:return VR::SQ; case 0x00209453:return VR::LO; case 0x00209518:return VR::US; case 0x00209529:return VR::SQ; case 0x00209536:return VR::US; case 0x00220001:return VR::US; case 0x00220002:return VR::US; case 0x00220003:return VR::US; case 0x00220004:return VR::US; case 0x00220005:return VR::CS; case 0x00220006:return VR::SQ; case 0x00220007:return VR::FL; case 0x00220008:return VR::FL; case 0x00220009:return VR::FL; case 0x0022000a:return VR::FL; case 0x0022000b:return VR::FL; case 0x0022000c:return VR::FL; case 0x0022000d:return VR::CS; case 0x0022000e:return VR::FL; case 0x00220010:return VR::FL; case 0x00220011:return VR::FL; case 0x00220012:return VR::FL; case 0x00220013:return VR::FL; case 0x00220014:return VR::FL; case 0x00220015:return VR::SQ; case 0x00220016:return VR::SQ; case 0x00220017:return VR::SQ; case 0x00220018:return VR::SQ; case 0x00220019:return VR::SQ; case 0x0022001a:return VR::SQ; case 0x0022001b:return VR::SQ; case 0x0022001c:return VR::SQ; case 0x0022001d:return VR::SQ; case 0x0022001e:return VR::FL; case 0x00220020:return VR::SQ; case 0x00220021:return VR::SQ; case 0x00220022:return VR::SQ; case 0x00220030:return VR::FL; case 0x00220031:return VR::SQ; case 0x00220032:return VR::FL; case 0x00220035:return VR::FL; case 0x00220036:return VR::FL; case 0x00220037:return VR::FL; case 0x00220038:return VR::FL; case 0x00220039:return VR::CS; case 0x00220041:return VR::FL; case 0x00220042:return VR::SQ; case 0x00220048:return VR::FL; case 0x00220049:return VR::FL; case 0x0022004e:return VR::DS; case 0x00220055:return VR::FL; case 0x00220056:return VR::FL; case 0x00220057:return VR::FL; case 0x00220058:return VR::SQ; case 0x00221007:return VR::SQ; case 0x00221008:return VR::SQ; case 0x00221009:return VR::CS; case 0x00221010:return VR::CS; case 0x00221012:return VR::SQ; case 0x00221019:return VR::FL; case 0x00221024:return VR::SQ; case 0x00221025:return VR::SQ; case 0x00221028:return VR::SQ; case 0x00221029:return VR::LO; case 0x00221033:return VR::FL; case 0x00221035:return VR::SQ; case 0x00221037:return VR::FL; case 0x00221039:return VR::CS; case 0x00221040:return VR::SQ; case 0x00221044:return VR::SQ; case 0x00221050:return VR::SQ; case 0x00221053:return VR::FL; case 0x00221054:return VR::FL; case 0x00221059:return VR::FL; case 0x00221065:return VR::LO; case 0x00221066:return VR::LO; case 0x00221090:return VR::SQ; case 0x00221092:return VR::SQ; case 0x00221093:return VR::LO; case 0x00221094:return VR::LO; case 0x00221095:return VR::LO; case 0x00221096:return VR::SQ; case 0x00221097:return VR::LO; case 0x00221100:return VR::SQ; case 0x00221101:return VR::SQ; case 0x00221103:return VR::SQ; case 0x00221121:return VR::FL; case 0x00221122:return VR::FL; case 0x00221125:return VR::SQ; case 0x00221127:return VR::SQ; case 0x00221128:return VR::SQ; case 0x00221130:return VR::FL; case 0x00221131:return VR::FL; case 0x00221132:return VR::SQ; case 0x00221133:return VR::SQ; case 0x00221134:return VR::SQ; case 0x00221135:return VR::SQ; case 0x00221140:return VR::CS; case 0x00221150:return VR::SQ; case 0x00221153:return VR::SQ; case 0x00221155:return VR::FL; case 0x00221159:return VR::LO; case 0x00221210:return VR::SQ; case 0x00221211:return VR::SQ; case 0x00221212:return VR::SQ; case 0x00221220:return VR::SQ; case 0x00221225:return VR::SQ; case 0x00221230:return VR::SQ; case 0x00221250:return VR::SQ; case 0x00221255:return VR::SQ; case 0x00221257:return VR::SQ; case 0x00221260:return VR::SQ; case 0x00221262:return VR::SQ; case 0x00221273:return VR::LO; case 0x00221300:return VR::SQ; case 0x00221310:return VR::SQ; case 0x00221330:return VR::SQ; case 0x00240010:return VR::FL; case 0x00240011:return VR::FL; case 0x00240012:return VR::CS; case 0x00240016:return VR::SQ; case 0x00240018:return VR::FL; case 0x00240020:return VR::FL; case 0x00240021:return VR::SQ; case 0x00240024:return VR::SQ; case 0x00240025:return VR::FL; case 0x00240028:return VR::FL; case 0x00240032:return VR::SQ; case 0x00240033:return VR::SQ; case 0x00240034:return VR::SQ; case 0x00240035:return VR::US; case 0x00240036:return VR::US; case 0x00240037:return VR::CS; case 0x00240038:return VR::US; case 0x00240039:return VR::CS; case 0x00240040:return VR::CS; case 0x00240042:return VR::US; case 0x00240044:return VR::LT; case 0x00240045:return VR::CS; case 0x00240046:return VR::FL; case 0x00240048:return VR::US; case 0x00240050:return VR::US; case 0x00240051:return VR::CS; case 0x00240052:return VR::CS; case 0x00240053:return VR::CS; case 0x00240054:return VR::FL; case 0x00240055:return VR::CS; case 0x00240056:return VR::US; case 0x00240057:return VR::CS; case 0x00240058:return VR::SQ; case 0x00240059:return VR::CS; case 0x00240060:return VR::US; case 0x00240061:return VR::CS; case 0x00240062:return VR::CS; case 0x00240063:return VR::CS; case 0x00240064:return VR::SQ; case 0x00240065:return VR::SQ; case 0x00240066:return VR::FL; case 0x00240067:return VR::SQ; case 0x00240068:return VR::FL; case 0x00240069:return VR::LO; case 0x00240070:return VR::FL; case 0x00240071:return VR::FL; case 0x00240072:return VR::CS; case 0x00240073:return VR::FL; case 0x00240074:return VR::CS; case 0x00240075:return VR::FL; case 0x00240076:return VR::CS; case 0x00240077:return VR::FL; case 0x00240078:return VR::CS; case 0x00240079:return VR::FL; case 0x00240080:return VR::CS; case 0x00240081:return VR::FL; case 0x00240083:return VR::SQ; case 0x00240085:return VR::SQ; case 0x00240086:return VR::CS; case 0x00240087:return VR::FL; case 0x00240088:return VR::FL; case 0x00240089:return VR::SQ; case 0x00240090:return VR::FL; case 0x00240091:return VR::FL; case 0x00240092:return VR::FL; case 0x00240093:return VR::CS; case 0x00240094:return VR::FL; case 0x00240095:return VR::CS; case 0x00240096:return VR::FL; case 0x00240097:return VR::SQ; case 0x00240098:return VR::FL; case 0x00240100:return VR::FL; case 0x00240102:return VR::CS; case 0x00240103:return VR::FL; case 0x00240104:return VR::FL; case 0x00240105:return VR::FL; case 0x00240106:return VR::CS; case 0x00240107:return VR::FL; case 0x00240108:return VR::FL; case 0x00240110:return VR::SQ; case 0x00240112:return VR::SQ; case 0x00240113:return VR::CS; case 0x00240114:return VR::SQ; case 0x00240115:return VR::SQ; case 0x00240117:return VR::CS; case 0x00240118:return VR::FL; case 0x00240120:return VR::CS; case 0x00240122:return VR::SQ; case 0x00240124:return VR::CS; case 0x00240126:return VR::FL; case 0x00240202:return VR::LO; case 0x00240306:return VR::LO; case 0x00240307:return VR::LO; case 0x00240308:return VR::LO; case 0x00240309:return VR::LO; case 0x00240317:return VR::SQ; case 0x00240320:return VR::SQ; case 0x00240325:return VR::SQ; case 0x00240338:return VR::CS; case 0x00240341:return VR::FL; case 0x00240344:return VR::SQ; case 0x00280002:return VR::US; case 0x00280003:return VR::US; case 0x00280004:return VR::CS; case 0x00280005:return VR::US; case 0x00280006:return VR::US; case 0x00280008:return VR::IS; case 0x00280009:return VR::AT; case 0x0028000a:return VR::AT; case 0x00280010:return VR::US; case 0x00280011:return VR::US; case 0x00280012:return VR::US; case 0x00280014:return VR::US; case 0x00280030:return VR::DS; case 0x00280031:return VR::DS; case 0x00280032:return VR::DS; case 0x00280034:return VR::IS; case 0x00280040:return VR::CS; case 0x00280050:return VR::LO; case 0x00280051:return VR::CS; case 0x0028005f:return VR::LO; case 0x00280060:return VR::CS; case 0x00280061:return VR::SH; case 0x00280062:return VR::LO; case 0x00280063:return VR::SH; case 0x00280065:return VR::CS; case 0x00280066:return VR::AT; case 0x00280068:return VR::US; case 0x00280069:return VR::US; case 0x00280070:return VR::US; case 0x00280071:return VR::US_SS; case 0x00280080:return VR::US; case 0x00280081:return VR::US; case 0x00280082:return VR::US; case 0x00280090:return VR::CS; case 0x00280091:return VR::US; case 0x00280092:return VR::US; case 0x00280093:return VR::US; case 0x00280094:return VR::US; case 0x00280100:return VR::US; case 0x00280101:return VR::US; case 0x00280102:return VR::US; case 0x00280103:return VR::US; case 0x00280104:return VR::US_SS; case 0x00280105:return VR::US_SS; case 0x00280106:return VR::US_SS; case 0x00280107:return VR::US_SS; case 0x00280108:return VR::US_SS; case 0x00280109:return VR::US_SS; case 0x00280110:return VR::US_SS; case 0x00280111:return VR::US_SS; case 0x00280120:return VR::US_SS; case 0x00280121:return VR::US_SS; case 0x00280200:return VR::US; case 0x00280300:return VR::CS; case 0x00280301:return VR::CS; case 0x00280302:return VR::CS; case 0x00280303:return VR::CS; case 0x00280304:return VR::UI; case 0x00280400:return VR::LO; case 0x00280401:return VR::LO; case 0x00280402:return VR::US; case 0x00280403:return VR::LO; case 0x00280404:return VR::AT; case 0x00280700:return VR::LO; case 0x00280701:return VR::CS; case 0x00280702:return VR::AT; case 0x00280710:return VR::US; case 0x00280720:return VR::US; case 0x00280721:return VR::AT; case 0x00280722:return VR::US; case 0x00280730:return VR::US; case 0x00280740:return VR::US; case 0x00280a02:return VR::CS; case 0x00280a04:return VR::LO; case 0x00281040:return VR::CS; case 0x00281041:return VR::SS; case 0x00281050:return VR::DS; case 0x00281051:return VR::DS; case 0x00281052:return VR::DS; case 0x00281053:return VR::DS; case 0x00281054:return VR::LO; case 0x00281055:return VR::LO; case 0x00281056:return VR::CS; case 0x00281080:return VR::CS; case 0x00281090:return VR::CS; case 0x00281100:return VR::US_SS; case 0x00281101:return VR::US_SS; case 0x00281102:return VR::US_SS; case 0x00281103:return VR::US_SS; case 0x00281104:return VR::US; case 0x00281111:return VR::US_SS; case 0x00281112:return VR::US_SS; case 0x00281113:return VR::US_SS; case 0x00281199:return VR::UI; case 0x00281201:return VR::OW; case 0x00281202:return VR::OW; case 0x00281203:return VR::OW; case 0x00281204:return VR::OW; case 0x00281211:return VR::OW; case 0x00281212:return VR::OW; case 0x00281213:return VR::OW; case 0x00281214:return VR::UI; case 0x00281221:return VR::OW; case 0x00281222:return VR::OW; case 0x00281223:return VR::OW; case 0x00281300:return VR::CS; case 0x00281350:return VR::CS; case 0x00281351:return VR::ST; case 0x00281352:return VR::SQ; case 0x0028135a:return VR::CS; case 0x00281401:return VR::SQ; case 0x00281402:return VR::CS; case 0x00281403:return VR::US; case 0x00281404:return VR::SQ; case 0x00281405:return VR::CS; case 0x00281406:return VR::FD; case 0x00281407:return VR::US; case 0x00281408:return VR::OW; case 0x0028140b:return VR::SQ; case 0x0028140c:return VR::SQ; case 0x0028140d:return VR::CS; case 0x0028140e:return VR::CS; case 0x0028140f:return VR::CS; case 0x00281410:return VR::CS; case 0x00282000:return VR::OB; case 0x00282110:return VR::CS; case 0x00282112:return VR::DS; case 0x00282114:return VR::CS; case 0x00283000:return VR::SQ; case 0x00283002:return VR::US_SS; case 0x00283003:return VR::LO; case 0x00283004:return VR::LO; case 0x00283010:return VR::SQ; case 0x00283110:return VR::SQ; case 0x00284000:return VR::LT; case 0x00285000:return VR::SQ; case 0x00286010:return VR::US; case 0x00286020:return VR::US; case 0x00286022:return VR::LO; case 0x00286023:return VR::CS; case 0x00286030:return VR::US; case 0x00286040:return VR::US; case 0x00286100:return VR::SQ; case 0x00286101:return VR::CS; case 0x00286102:return VR::US; case 0x00286110:return VR::US; case 0x00286112:return VR::US; case 0x00286114:return VR::FL; case 0x00286120:return VR::SS; case 0x00286190:return VR::ST; case 0x00287fe0:return VR::UT; case 0x00289001:return VR::UL; case 0x00289002:return VR::UL; case 0x00289003:return VR::CS; case 0x00289099:return VR::US; case 0x00289108:return VR::CS; case 0x00289110:return VR::SQ; case 0x00289132:return VR::SQ; case 0x00289145:return VR::SQ; case 0x00289235:return VR::CS; case 0x00289411:return VR::FL; case 0x00289415:return VR::SQ; case 0x00289416:return VR::US; case 0x00289422:return VR::SQ; case 0x00289443:return VR::SQ; case 0x00289444:return VR::CS; case 0x00289445:return VR::FL; case 0x00289446:return VR::CS; case 0x00289454:return VR::CS; case 0x00289474:return VR::CS; case 0x00289478:return VR::FL; case 0x00289501:return VR::SQ; case 0x00289502:return VR::SQ; case 0x00289503:return VR::SS; case 0x00289505:return VR::SQ; case 0x00289506:return VR::US; case 0x00289507:return VR::US; case 0x00289520:return VR::DS; case 0x00289537:return VR::CS; case 0x0032000a:return VR::CS; case 0x0032000c:return VR::CS; case 0x00320012:return VR::LO; case 0x00320032:return VR::DA; case 0x00320033:return VR::TM; case 0x00320034:return VR::DA; case 0x00320035:return VR::TM; case 0x00321000:return VR::DA; case 0x00321001:return VR::TM; case 0x00321010:return VR::DA; case 0x00321011:return VR::TM; case 0x00321020:return VR::LO; case 0x00321021:return VR::AE; case 0x00321030:return VR::LO; case 0x00321031:return VR::SQ; case 0x00321032:return VR::PN; case 0x00321033:return VR::LO; case 0x00321034:return VR::SQ; case 0x00321040:return VR::DA; case 0x00321041:return VR::TM; case 0x00321050:return VR::DA; case 0x00321051:return VR::TM; case 0x00321055:return VR::CS; case 0x00321060:return VR::LO; case 0x00321064:return VR::SQ; case 0x00321070:return VR::LO; case 0x00324000:return VR::LT; case 0x00380004:return VR::SQ; case 0x00380008:return VR::CS; case 0x00380010:return VR::LO; case 0x00380011:return VR::LO; case 0x00380014:return VR::SQ; case 0x00380016:return VR::LO; case 0x0038001a:return VR::DA; case 0x0038001b:return VR::TM; case 0x0038001c:return VR::DA; case 0x0038001d:return VR::TM; case 0x0038001e:return VR::LO; case 0x00380020:return VR::DA; case 0x00380021:return VR::TM; case 0x00380030:return VR::DA; case 0x00380032:return VR::TM; case 0x00380040:return VR::LO; case 0x00380044:return VR::SQ; case 0x00380050:return VR::LO; case 0x00380060:return VR::LO; case 0x00380061:return VR::LO; case 0x00380062:return VR::LO; case 0x00380064:return VR::SQ; case 0x00380100:return VR::SQ; case 0x00380300:return VR::LO; case 0x00380400:return VR::LO; case 0x00380500:return VR::LO; case 0x00380502:return VR::SQ; case 0x00384000:return VR::LT; case 0x003a0004:return VR::CS; case 0x003a0005:return VR::US; case 0x003a0010:return VR::UL; case 0x003a001a:return VR::DS; case 0x003a0020:return VR::SH; case 0x003a0200:return VR::SQ; case 0x003a0202:return VR::IS; case 0x003a0203:return VR::SH; case 0x003a0205:return VR::CS; case 0x003a0208:return VR::SQ; case 0x003a0209:return VR::SQ; case 0x003a020a:return VR::SQ; case 0x003a020c:return VR::LO; case 0x003a0210:return VR::DS; case 0x003a0211:return VR::SQ; case 0x003a0212:return VR::DS; case 0x003a0213:return VR::DS; case 0x003a0214:return VR::DS; case 0x003a0215:return VR::DS; case 0x003a0218:return VR::DS; case 0x003a021a:return VR::US; case 0x003a0220:return VR::DS; case 0x003a0221:return VR::DS; case 0x003a0222:return VR::DS; case 0x003a0223:return VR::DS; case 0x003a0230:return VR::FL; case 0x003a0231:return VR::US; case 0x003a0240:return VR::SQ; case 0x003a0241:return VR::US; case 0x003a0242:return VR::SQ; case 0x003a0244:return VR::US; case 0x003a0245:return VR::FL; case 0x003a0246:return VR::CS; case 0x003a0247:return VR::FL; case 0x003a0248:return VR::FL; case 0x003a0300:return VR::SQ; case 0x003a0301:return VR::IS; case 0x003a0302:return VR::CS; case 0x00400001:return VR::AE; case 0x00400002:return VR::DA; case 0x00400003:return VR::TM; case 0x00400004:return VR::DA; case 0x00400005:return VR::TM; case 0x00400006:return VR::PN; case 0x00400007:return VR::LO; case 0x00400008:return VR::SQ; case 0x00400009:return VR::SH; case 0x0040000a:return VR::SQ; case 0x0040000b:return VR::SQ; case 0x00400010:return VR::SH; case 0x00400011:return VR::SH; case 0x00400012:return VR::LO; case 0x00400020:return VR::CS; case 0x00400026:return VR::SQ; case 0x00400027:return VR::SQ; case 0x00400031:return VR::UT; case 0x00400032:return VR::UT; case 0x00400033:return VR::CS; case 0x00400035:return VR::CS; case 0x00400036:return VR::SQ; case 0x00400039:return VR::SQ; case 0x0040003a:return VR::SQ; case 0x00400100:return VR::SQ; case 0x00400220:return VR::SQ; case 0x00400241:return VR::AE; case 0x00400242:return VR::SH; case 0x00400243:return VR::SH; case 0x00400244:return VR::DA; case 0x00400245:return VR::TM; case 0x00400250:return VR::DA; case 0x00400251:return VR::TM; case 0x00400252:return VR::CS; case 0x00400253:return VR::SH; case 0x00400254:return VR::LO; case 0x00400255:return VR::LO; case 0x00400260:return VR::SQ; case 0x00400261:return VR::CS; case 0x00400270:return VR::SQ; case 0x00400275:return VR::SQ; case 0x00400280:return VR::ST; case 0x00400281:return VR::SQ; case 0x00400293:return VR::SQ; case 0x00400294:return VR::DS; case 0x00400295:return VR::SQ; case 0x00400296:return VR::SQ; case 0x00400300:return VR::US; case 0x00400301:return VR::US; case 0x00400302:return VR::US; case 0x00400303:return VR::US; case 0x00400306:return VR::DS; case 0x00400307:return VR::DS; case 0x0040030e:return VR::SQ; case 0x00400310:return VR::ST; case 0x00400312:return VR::DS; case 0x00400314:return VR::DS; case 0x00400316:return VR::DS; case 0x00400318:return VR::CS; case 0x00400320:return VR::SQ; case 0x00400321:return VR::SQ; case 0x00400324:return VR::SQ; case 0x00400330:return VR::SQ; case 0x00400340:return VR::SQ; case 0x00400400:return VR::LT; case 0x00400440:return VR::SQ; case 0x00400441:return VR::SQ; case 0x00400500:return VR::SQ; case 0x0040050a:return VR::LO; case 0x00400512:return VR::LO; case 0x00400513:return VR::SQ; case 0x00400515:return VR::SQ; case 0x00400518:return VR::SQ; case 0x0040051a:return VR::LO; case 0x00400520:return VR::SQ; case 0x00400550:return VR::SQ; case 0x00400551:return VR::LO; case 0x00400552:return VR::SQ; case 0x00400553:return VR::ST; case 0x00400554:return VR::UI; case 0x00400555:return VR::SQ; case 0x00400556:return VR::ST; case 0x0040059a:return VR::SQ; case 0x00400560:return VR::SQ; case 0x00400562:return VR::SQ; case 0x00400600:return VR::LO; case 0x00400602:return VR::UT; case 0x00400610:return VR::SQ; case 0x00400612:return VR::SQ; case 0x00400620:return VR::SQ; case 0x004006fa:return VR::LO; case 0x0040071a:return VR::SQ; case 0x0040072a:return VR::DS; case 0x0040073a:return VR::DS; case 0x0040074a:return VR::DS; case 0x004008d8:return VR::SQ; case 0x004008da:return VR::SQ; case 0x004008ea:return VR::SQ; case 0x004009f8:return VR::SQ; case 0x00401001:return VR::SH; case 0x00401002:return VR::LO; case 0x00401003:return VR::SH; case 0x00401004:return VR::LO; case 0x00401005:return VR::LO; case 0x00401006:return VR::SH; case 0x00401007:return VR::SH; case 0x00401008:return VR::LO; case 0x00401009:return VR::SH; case 0x0040100a:return VR::SQ; case 0x00401010:return VR::PN; case 0x00401011:return VR::SQ; case 0x00401012:return VR::SQ; case 0x00401060:return VR::LO; case 0x00401101:return VR::SQ; case 0x00401102:return VR::ST; case 0x00401103:return VR::LO; case 0x00401400:return VR::LT; case 0x00402001:return VR::LO; case 0x00402004:return VR::DA; case 0x00402005:return VR::TM; case 0x00402006:return VR::SH; case 0x00402007:return VR::SH; case 0x00402008:return VR::PN; case 0x00402009:return VR::SH; case 0x00402010:return VR::SH; case 0x00402016:return VR::LO; case 0x00402017:return VR::LO; case 0x00402400:return VR::LT; case 0x00403001:return VR::LO; case 0x00404001:return VR::CS; case 0x00404002:return VR::CS; case 0x00404003:return VR::CS; case 0x00404004:return VR::SQ; case 0x00404005:return VR::DT; case 0x00404006:return VR::CS; case 0x00404007:return VR::SQ; case 0x00404009:return VR::SQ; case 0x00404010:return VR::DT; case 0x00404011:return VR::DT; case 0x00404015:return VR::SQ; case 0x00404016:return VR::SQ; case 0x00404018:return VR::SQ; case 0x00404019:return VR::SQ; case 0x00404020:return VR::CS; case 0x00404021:return VR::SQ; case 0x00404022:return VR::SQ; case 0x00404023:return VR::UI; case 0x00404025:return VR::SQ; case 0x00404026:return VR::SQ; case 0x00404027:return VR::SQ; case 0x00404028:return VR::SQ; case 0x00404029:return VR::SQ; case 0x00404030:return VR::SQ; case 0x00404031:return VR::SQ; case 0x00404032:return VR::SQ; case 0x00404033:return VR::SQ; case 0x00404034:return VR::SQ; case 0x00404035:return VR::SQ; case 0x00404036:return VR::LO; case 0x00404037:return VR::PN; case 0x00404040:return VR::CS; case 0x00404041:return VR::CS; case 0x00404050:return VR::DT; case 0x00404051:return VR::DT; case 0x00404052:return VR::DT; case 0x00408302:return VR::DS; case 0x00409094:return VR::SQ; case 0x00409096:return VR::SQ; case 0x00409098:return VR::SQ; case 0x00409210:return VR::SH; case 0x00409211:return VR::US_SS; case 0x00409212:return VR::FD; case 0x00409216:return VR::US_SS; case 0x00409224:return VR::FD; case 0x00409225:return VR::FD; case 0x0040a007:return VR::CS; case 0x0040a010:return VR::CS; case 0x0040a020:return VR::SQ; case 0x0040a021:return VR::UI; case 0x0040a022:return VR::UI; case 0x0040a023:return VR::DA; case 0x0040a024:return VR::TM; case 0x0040a026:return VR::SQ; case 0x0040a027:return VR::LO; case 0x0040a028:return VR::SQ; case 0x0040a030:return VR::DT; case 0x0040a032:return VR::DT; case 0x0040a040:return VR::CS; case 0x0040a043:return VR::SQ; case 0x0040a047:return VR::LO; case 0x0040a050:return VR::CS; case 0x0040a057:return VR::CS; case 0x0040a060:return VR::LO; case 0x0040a066:return VR::SQ; case 0x0040a067:return VR::PN; case 0x0040a068:return VR::SQ; case 0x0040a070:return VR::SQ; case 0x0040a073:return VR::SQ; case 0x0040a074:return VR::OB; case 0x0040a075:return VR::PN; case 0x0040a076:return VR::SQ; case 0x0040a078:return VR::SQ; case 0x0040a07a:return VR::SQ; case 0x0040a07c:return VR::SQ; case 0x0040a080:return VR::CS; case 0x0040a082:return VR::DT; case 0x0040a084:return VR::CS; case 0x0040a085:return VR::SQ; case 0x0040a088:return VR::SQ; case 0x0040a089:return VR::OB; case 0x0040a090:return VR::SQ; case 0x0040a0b0:return VR::US; case 0x0040a110:return VR::DA; case 0x0040a112:return VR::TM; case 0x0040a120:return VR::DT; case 0x0040a121:return VR::DA; case 0x0040a122:return VR::TM; case 0x0040a123:return VR::PN; case 0x0040a124:return VR::UI; case 0x0040a125:return VR::CS; case 0x0040a130:return VR::CS; case 0x0040a132:return VR::UL; case 0x0040a136:return VR::US; case 0x0040a138:return VR::DS; case 0x0040a13a:return VR::DT; case 0x0040a160:return VR::UT; case 0x0040a167:return VR::SQ; case 0x0040a168:return VR::SQ; case 0x0040a16a:return VR::ST; case 0x0040a170:return VR::SQ; case 0x0040a171:return VR::UI; case 0x0040a172:return VR::UI; case 0x0040a173:return VR::CS; case 0x0040a174:return VR::CS; case 0x0040a180:return VR::US; case 0x0040a192:return VR::DA; case 0x0040a193:return VR::TM; case 0x0040a194:return VR::CS; case 0x0040a195:return VR::SQ; case 0x0040a224:return VR::ST; case 0x0040a290:return VR::CS; case 0x0040a296:return VR::SQ; case 0x0040a297:return VR::ST; case 0x0040a29a:return VR::SL; case 0x0040a300:return VR::SQ; case 0x0040a301:return VR::SQ; case 0x0040a307:return VR::PN; case 0x0040a30a:return VR::DS; case 0x0040a313:return VR::SQ; case 0x0040a33a:return VR::ST; case 0x0040a340:return VR::SQ; case 0x0040a352:return VR::PN; case 0x0040a353:return VR::ST; case 0x0040a354:return VR::LO; case 0x0040a358:return VR::SQ; case 0x0040a360:return VR::SQ; case 0x0040a370:return VR::SQ; case 0x0040a372:return VR::SQ; case 0x0040a375:return VR::SQ; case 0x0040a380:return VR::SQ; case 0x0040a385:return VR::SQ; case 0x0040a390:return VR::SQ; case 0x0040a402:return VR::UI; case 0x0040a403:return VR::CS; case 0x0040a404:return VR::SQ; case 0x0040a491:return VR::CS; case 0x0040a492:return VR::LO; case 0x0040a493:return VR::CS; case 0x0040a494:return VR::CS; case 0x0040a496:return VR::CS; case 0x0040a504:return VR::SQ; case 0x0040a525:return VR::SQ; case 0x0040a600:return VR::CS; case 0x0040a601:return VR::CS; case 0x0040a603:return VR::CS; case 0x0040a730:return VR::SQ; case 0x0040a731:return VR::SQ; case 0x0040a732:return VR::SQ; case 0x0040a744:return VR::SQ; case 0x0040a992:return VR::ST; case 0x0040b020:return VR::SQ; case 0x0040db00:return VR::CS; case 0x0040db06:return VR::DT; case 0x0040db07:return VR::DT; case 0x0040db0b:return VR::CS; case 0x0040db0c:return VR::UI; case 0x0040db0d:return VR::UI; case 0x0040db73:return VR::UL; case 0x0040e001:return VR::ST; case 0x0040e004:return VR::DT; case 0x0040e006:return VR::SQ; case 0x0040e008:return VR::SQ; case 0x0040e010:return VR::UT; case 0x0040e011:return VR::UI; case 0x0040e020:return VR::CS; case 0x0040e021:return VR::SQ; case 0x0040e022:return VR::SQ; case 0x0040e023:return VR::SQ; case 0x0040e024:return VR::SQ; case 0x0040e030:return VR::UI; case 0x0040e031:return VR::UI; case 0x00420010:return VR::ST; case 0x00420011:return VR::OB; case 0x00420012:return VR::LO; case 0x00420013:return VR::SQ; case 0x00420014:return VR::LO; case 0x00440001:return VR::ST; case 0x00440002:return VR::CS; case 0x00440003:return VR::LT; case 0x00440004:return VR::DT; case 0x00440007:return VR::SQ; case 0x00440008:return VR::LO; case 0x00440009:return VR::LT; case 0x0044000a:return VR::LO; case 0x0044000b:return VR::DT; case 0x00440010:return VR::DT; case 0x00440011:return VR::LO; case 0x00440012:return VR::LO; case 0x00440013:return VR::SQ; case 0x00440019:return VR::SQ; case 0x00460012:return VR::LO; case 0x00460014:return VR::SQ; case 0x00460015:return VR::SQ; case 0x00460016:return VR::SQ; case 0x00460018:return VR::SQ; case 0x00460028:return VR::SQ; case 0x00460030:return VR::FD; case 0x00460032:return VR::CS; case 0x00460034:return VR::FD; case 0x00460036:return VR::CS; case 0x00460038:return VR::CS; case 0x00460040:return VR::FD; case 0x00460042:return VR::FD; case 0x00460044:return VR::FD; case 0x00460046:return VR::FD; case 0x00460050:return VR::SQ; case 0x00460052:return VR::SQ; case 0x00460060:return VR::FD; case 0x00460062:return VR::FD; case 0x00460063:return VR::FD; case 0x00460064:return VR::FD; case 0x00460070:return VR::SQ; case 0x00460071:return VR::SQ; case 0x00460074:return VR::SQ; case 0x00460075:return VR::FD; case 0x00460076:return VR::FD; case 0x00460077:return VR::FD; case 0x00460080:return VR::SQ; case 0x00460092:return VR::CS; case 0x00460094:return VR::CS; case 0x00460095:return VR::CS; case 0x00460097:return VR::SQ; case 0x00460098:return VR::SQ; case 0x00460100:return VR::SQ; case 0x00460101:return VR::SQ; case 0x00460102:return VR::SQ; case 0x00460104:return VR::FD; case 0x00460106:return VR::FD; case 0x00460121:return VR::SQ; case 0x00460122:return VR::SQ; case 0x00460123:return VR::SQ; case 0x00460124:return VR::SQ; case 0x00460125:return VR::CS; case 0x00460135:return VR::SS; case 0x00460137:return VR::FD; case 0x00460139:return VR::LO; case 0x00460145:return VR::SQ; case 0x00460146:return VR::FD; case 0x00460147:return VR::FD; case 0x00480001:return VR::FL; case 0x00480002:return VR::FL; case 0x00480003:return VR::FL; case 0x00480006:return VR::UL; case 0x00480007:return VR::UL; case 0x00480008:return VR::SQ; case 0x00480010:return VR::CS; case 0x00480011:return VR::CS; case 0x00480012:return VR::CS; case 0x00480013:return VR::US; case 0x00480014:return VR::FL; case 0x00480015:return VR::US; case 0x00480100:return VR::SQ; case 0x00480102:return VR::DS; case 0x00480105:return VR::SQ; case 0x00480106:return VR::SH; case 0x00480107:return VR::ST; case 0x00480108:return VR::SQ; case 0x00480110:return VR::SQ; case 0x00480111:return VR::DS; case 0x00480112:return VR::DS; case 0x00480113:return VR::DS; case 0x00480120:return VR::SQ; case 0x00480200:return VR::SQ; case 0x00480201:return VR::US; case 0x00480202:return VR::US; case 0x00480207:return VR::SQ; case 0x0048021a:return VR::SQ; case 0x0048021e:return VR::SL; case 0x0048021f:return VR::SL; case 0x00480301:return VR::CS; case 0x00500004:return VR::CS; case 0x00500010:return VR::SQ; case 0x00500012:return VR::SQ; case 0x00500013:return VR::FD; case 0x00500014:return VR::DS; case 0x00500015:return VR::FD; case 0x00500016:return VR::DS; case 0x00500017:return VR::CS; case 0x00500018:return VR::DS; case 0x00500019:return VR::DS; case 0x0050001a:return VR::CS; case 0x0050001b:return VR::LO; case 0x0050001c:return VR::FD; case 0x0050001d:return VR::FD; case 0x0050001e:return VR::LO; case 0x00500020:return VR::LO; case 0x00520001:return VR::FL; case 0x00520002:return VR::FD; case 0x00520003:return VR::FD; case 0x00520004:return VR::FD; case 0x00520006:return VR::CS; case 0x00520007:return VR::FD; case 0x00520008:return VR::FD; case 0x00520009:return VR::FD; case 0x00520011:return VR::FD; case 0x00520012:return VR::US; case 0x00520013:return VR::FD; case 0x00520014:return VR::FD; case 0x00520016:return VR::SQ; case 0x00520025:return VR::SQ; case 0x00520026:return VR::CS; case 0x00520027:return VR::SQ; case 0x00520028:return VR::FD; case 0x00520029:return VR::SQ; case 0x00520030:return VR::SS; case 0x00520031:return VR::CS; case 0x00520033:return VR::FD; case 0x00520034:return VR::FD; case 0x00520036:return VR::US; case 0x00520038:return VR::US; case 0x00520039:return VR::CS; case 0x0052003a:return VR::CS; case 0x00540010:return VR::US; case 0x00540011:return VR::US; case 0x00540012:return VR::SQ; case 0x00540013:return VR::SQ; case 0x00540014:return VR::DS; case 0x00540015:return VR::DS; case 0x00540016:return VR::SQ; case 0x00540017:return VR::IS; case 0x00540018:return VR::SH; case 0x00540020:return VR::US; case 0x00540021:return VR::US; case 0x00540022:return VR::SQ; case 0x00540030:return VR::US; case 0x00540031:return VR::US; case 0x00540032:return VR::SQ; case 0x00540033:return VR::US; case 0x00540036:return VR::IS; case 0x00540038:return VR::IS; case 0x00540039:return VR::CS; case 0x00540050:return VR::US; case 0x00540051:return VR::US; case 0x00540052:return VR::SQ; case 0x00540053:return VR::US; case 0x00540060:return VR::US; case 0x00540061:return VR::US; case 0x00540062:return VR::SQ; case 0x00540063:return VR::SQ; case 0x00540070:return VR::US; case 0x00540071:return VR::US; case 0x00540072:return VR::SQ; case 0x00540073:return VR::DS; case 0x00540080:return VR::US; case 0x00540081:return VR::US; case 0x00540090:return VR::US; case 0x00540100:return VR::US; case 0x00540101:return VR::US; case 0x00540200:return VR::DS; case 0x00540202:return VR::CS; case 0x00540210:return VR::IS; case 0x00540211:return VR::US; case 0x00540220:return VR::SQ; case 0x00540222:return VR::SQ; case 0x00540300:return VR::SQ; case 0x00540302:return VR::SQ; case 0x00540304:return VR::SQ; case 0x00540306:return VR::SQ; case 0x00540308:return VR::US; case 0x00540400:return VR::SH; case 0x00540410:return VR::SQ; case 0x00540412:return VR::SQ; case 0x00540414:return VR::SQ; case 0x00540500:return VR::CS; case 0x00541000:return VR::CS; case 0x00541001:return VR::CS; case 0x00541002:return VR::CS; case 0x00541004:return VR::CS; case 0x00541006:return VR::CS; case 0x00541100:return VR::CS; case 0x00541101:return VR::LO; case 0x00541102:return VR::CS; case 0x00541103:return VR::LO; case 0x00541104:return VR::LO; case 0x00541105:return VR::LO; case 0x00541200:return VR::DS; case 0x00541201:return VR::IS; case 0x00541202:return VR::IS; case 0x00541203:return VR::DS; case 0x00541210:return VR::DS; case 0x00541220:return VR::CS; case 0x00541300:return VR::DS; case 0x00541310:return VR::IS; case 0x00541311:return VR::IS; case 0x00541320:return VR::DS; case 0x00541321:return VR::DS; case 0x00541322:return VR::DS; case 0x00541323:return VR::DS; case 0x00541324:return VR::DS; case 0x00541330:return VR::US; case 0x00541400:return VR::CS; case 0x00541401:return VR::CS; case 0x00603000:return VR::SQ; case 0x00603002:return VR::US; case 0x00603004:return VR::US_SS; case 0x00603006:return VR::US_SS; case 0x00603008:return VR::US; case 0x00603010:return VR::LO; case 0x00603020:return VR::UL; case 0x00620001:return VR::CS; case 0x00620002:return VR::SQ; case 0x00620003:return VR::SQ; case 0x00620004:return VR::US; case 0x00620005:return VR::LO; case 0x00620006:return VR::ST; case 0x00620008:return VR::CS; case 0x00620009:return VR::LO; case 0x0062000a:return VR::SQ; case 0x0062000b:return VR::US; case 0x0062000c:return VR::US; case 0x0062000d:return VR::US; case 0x0062000e:return VR::US; case 0x0062000f:return VR::SQ; case 0x00620010:return VR::CS; case 0x00640002:return VR::SQ; case 0x00640003:return VR::UI; case 0x00640005:return VR::SQ; case 0x00640007:return VR::UL; case 0x00640008:return VR::FD; case 0x00640009:return VR::OF; case 0x0064000f:return VR::SQ; case 0x00640010:return VR::SQ; case 0x00660001:return VR::UL; case 0x00660002:return VR::SQ; case 0x00660003:return VR::UL; case 0x00660004:return VR::LT; case 0x00660009:return VR::CS; case 0x0066000a:return VR::FL; case 0x0066000b:return VR::LO; case 0x0066000c:return VR::FL; case 0x0066000d:return VR::CS; case 0x0066000e:return VR::CS; case 0x00660010:return VR::CS; case 0x00660011:return VR::SQ; case 0x00660012:return VR::SQ; case 0x00660013:return VR::SQ; case 0x00660015:return VR::UL; case 0x00660016:return VR::OF; case 0x00660017:return VR::FL; case 0x00660018:return VR::FL; case 0x00660019:return VR::FL; case 0x0066001a:return VR::FL; case 0x0066001b:return VR::FL; case 0x0066001c:return VR::FL; case 0x0066001e:return VR::UL; case 0x0066001f:return VR::US; case 0x00660020:return VR::FL; case 0x00660021:return VR::OF; case 0x00660023:return VR::OW; case 0x00660024:return VR::OW; case 0x00660025:return VR::OW; case 0x00660026:return VR::SQ; case 0x00660027:return VR::SQ; case 0x00660028:return VR::SQ; case 0x00660029:return VR::OW; case 0x0066002a:return VR::UL; case 0x0066002b:return VR::SQ; case 0x0066002c:return VR::UL; case 0x0066002d:return VR::SQ; case 0x0066002e:return VR::SQ; case 0x0066002f:return VR::SQ; case 0x00660030:return VR::SQ; case 0x00660031:return VR::LO; case 0x00660032:return VR::LT; case 0x00660034:return VR::SQ; case 0x00660035:return VR::SQ; case 0x00660036:return VR::LO; case 0x00686210:return VR::LO; case 0x00686221:return VR::LO; case 0x00686222:return VR::SQ; case 0x00686223:return VR::CS; case 0x00686224:return VR::SQ; case 0x00686225:return VR::SQ; case 0x00686226:return VR::DT; case 0x00686230:return VR::SQ; case 0x00686260:return VR::SQ; case 0x00686265:return VR::SQ; case 0x00686270:return VR::DT; case 0x00686280:return VR::ST; case 0x006862a0:return VR::SQ; case 0x006862a5:return VR::FD; case 0x006862c0:return VR::SQ; case 0x006862d0:return VR::US; case 0x006862d5:return VR::LO; case 0x006862e0:return VR::SQ; case 0x006862f0:return VR::FD; case 0x006862f2:return VR::FD; case 0x00686300:return VR::OB; case 0x00686310:return VR::US; case 0x00686320:return VR::SQ; case 0x00686330:return VR::US; case 0x00686340:return VR::LO; case 0x00686345:return VR::ST; case 0x00686346:return VR::FD; case 0x00686347:return VR::FD; case 0x00686350:return VR::US; case 0x00686360:return VR::SQ; case 0x00686380:return VR::LO; case 0x00686390:return VR::FD; case 0x006863a0:return VR::SQ; case 0x006863a4:return VR::SQ; case 0x006863a8:return VR::SQ; case 0x006863ac:return VR::SQ; case 0x006863b0:return VR::SQ; case 0x006863c0:return VR::US; case 0x006863d0:return VR::LO; case 0x006863e0:return VR::SQ; case 0x006863f0:return VR::US; case 0x00686400:return VR::SQ; case 0x00686410:return VR::US; case 0x00686420:return VR::CS; case 0x00686430:return VR::SQ; case 0x00686440:return VR::US; case 0x00686450:return VR::FD; case 0x00686460:return VR::FD; case 0x00686470:return VR::SQ; case 0x00686490:return VR::FD; case 0x006864a0:return VR::FD; case 0x006864c0:return VR::FD; case 0x006864d0:return VR::FD; case 0x006864f0:return VR::FD; case 0x00686500:return VR::SQ; case 0x00686510:return VR::SQ; case 0x00686520:return VR::SQ; case 0x00686530:return VR::US; case 0x00686540:return VR::LO; case 0x00686545:return VR::SQ; case 0x00686550:return VR::SQ; case 0x00686560:return VR::FD; case 0x00686590:return VR::FD; case 0x006865a0:return VR::SQ; case 0x006865b0:return VR::FD; case 0x006865d0:return VR::FD; case 0x006865e0:return VR::SQ; case 0x006865f0:return VR::FD; case 0x00686610:return VR::FD; case 0x00686620:return VR::FD; case 0x00700001:return VR::SQ; case 0x00700002:return VR::CS; case 0x00700003:return VR::CS; case 0x00700004:return VR::CS; case 0x00700005:return VR::CS; case 0x00700006:return VR::ST; case 0x00700008:return VR::SQ; case 0x00700009:return VR::SQ; case 0x00700010:return VR::FL; case 0x00700011:return VR::FL; case 0x00700012:return VR::CS; case 0x00700014:return VR::FL; case 0x00700015:return VR::CS; case 0x00700020:return VR::US; case 0x00700021:return VR::US; case 0x00700022:return VR::FL; case 0x00700023:return VR::CS; case 0x00700024:return VR::CS; case 0x00700040:return VR::IS; case 0x00700041:return VR::CS; case 0x00700042:return VR::US; case 0x00700050:return VR::US; case 0x00700051:return VR::US; case 0x00700052:return VR::SL; case 0x00700053:return VR::SL; case 0x0070005a:return VR::SQ; case 0x00700060:return VR::SQ; case 0x00700062:return VR::IS; case 0x00700066:return VR::US; case 0x00700067:return VR::US; case 0x00700068:return VR::LO; case 0x00700080:return VR::CS; case 0x00700081:return VR::LO; case 0x00700082:return VR::DA; case 0x00700083:return VR::TM; case 0x00700084:return VR::PN; case 0x00700086:return VR::SQ; case 0x00700087:return VR::SQ; case 0x00700100:return VR::CS; case 0x00700101:return VR::DS; case 0x00700102:return VR::IS; case 0x00700103:return VR::FL; case 0x00700207:return VR::LO; case 0x00700208:return VR::ST; case 0x00700209:return VR::SQ; case 0x00700226:return VR::UL; case 0x00700227:return VR::LO; case 0x00700228:return VR::CS; case 0x00700229:return VR::LO; case 0x00700230:return VR::FD; case 0x00700231:return VR::SQ; case 0x00700232:return VR::SQ; case 0x00700233:return VR::SQ; case 0x00700234:return VR::SQ; case 0x00700241:return VR::US; case 0x00700242:return VR::CS; case 0x00700243:return VR::CS; case 0x00700244:return VR::CS; case 0x00700245:return VR::FL; case 0x00700246:return VR::FL; case 0x00700247:return VR::US; case 0x00700248:return VR::CS; case 0x00700249:return VR::CS; case 0x00700250:return VR::CS; case 0x00700251:return VR::US; case 0x00700252:return VR::US; case 0x00700253:return VR::FL; case 0x00700254:return VR::CS; case 0x00700255:return VR::UL; case 0x00700256:return VR::OB; case 0x00700257:return VR::CS; case 0x00700258:return VR::FL; case 0x00700261:return VR::FL; case 0x00700262:return VR::FL; case 0x00700273:return VR::FL; case 0x00700274:return VR::CS; case 0x00700278:return VR::CS; case 0x00700279:return VR::CS; case 0x00700282:return VR::CS; case 0x00700284:return VR::FL; case 0x00700285:return VR::FL; case 0x00700287:return VR::SQ; case 0x00700288:return VR::FL; case 0x00700289:return VR::SH; case 0x00700294:return VR::CS; case 0x00700295:return VR::UL; case 0x00700306:return VR::CS; case 0x00700308:return VR::SQ; case 0x00700309:return VR::SQ; case 0x0070030a:return VR::SQ; case 0x0070030c:return VR::CS; case 0x0070030d:return VR::SQ; case 0x0070030f:return VR::ST; case 0x00700310:return VR::SH; case 0x00700311:return VR::SQ; case 0x00700312:return VR::FD; case 0x00700314:return VR::SQ; case 0x00700318:return VR::SQ; case 0x0070031a:return VR::UI; case 0x0070031c:return VR::SQ; case 0x0070031e:return VR::SQ; case 0x00700401:return VR::US; case 0x00700402:return VR::SQ; case 0x00700403:return VR::FL; case 0x00700404:return VR::SQ; case 0x00700405:return VR::CS; case 0x00720002:return VR::SH; case 0x00720004:return VR::LO; case 0x00720006:return VR::CS; case 0x00720008:return VR::LO; case 0x0072000a:return VR::DT; case 0x0072000c:return VR::SQ; case 0x0072000e:return VR::SQ; case 0x00720010:return VR::LO; case 0x00720012:return VR::SQ; case 0x00720014:return VR::US; case 0x00720020:return VR::SQ; case 0x00720022:return VR::SQ; case 0x00720024:return VR::CS; case 0x00720026:return VR::AT; case 0x00720028:return VR::US; case 0x00720030:return VR::SQ; case 0x00720032:return VR::US; case 0x00720034:return VR::CS; case 0x00720038:return VR::US; case 0x0072003a:return VR::CS; case 0x0072003c:return VR::SS; case 0x0072003e:return VR::SQ; case 0x00720040:return VR::LO; case 0x00720050:return VR::CS; case 0x00720052:return VR::AT; case 0x00720054:return VR::LO; case 0x00720056:return VR::LO; case 0x00720060:return VR::AT; case 0x00720062:return VR::CS; case 0x00720064:return VR::IS; case 0x00720066:return VR::LO; case 0x00720068:return VR::LT; case 0x0072006a:return VR::PN; case 0x0072006c:return VR::SH; case 0x0072006e:return VR::ST; case 0x00720070:return VR::UT; case 0x00720072:return VR::DS; case 0x00720074:return VR::FD; case 0x00720076:return VR::FL; case 0x00720078:return VR::UL; case 0x0072007a:return VR::US; case 0x0072007c:return VR::SL; case 0x0072007e:return VR::SS; case 0x00720080:return VR::SQ; case 0x00720100:return VR::US; case 0x00720102:return VR::SQ; case 0x00720104:return VR::US; case 0x00720106:return VR::US; case 0x00720108:return VR::FD; case 0x0072010a:return VR::US; case 0x0072010c:return VR::US; case 0x0072010e:return VR::US; case 0x00720200:return VR::SQ; case 0x00720202:return VR::US; case 0x00720203:return VR::LO; case 0x00720204:return VR::US; case 0x00720206:return VR::LO; case 0x00720208:return VR::CS; case 0x00720210:return VR::SQ; case 0x00720212:return VR::US; case 0x00720214:return VR::SQ; case 0x00720216:return VR::US; case 0x00720218:return VR::US; case 0x00720300:return VR::SQ; case 0x00720302:return VR::US; case 0x00720304:return VR::CS; case 0x00720306:return VR::US; case 0x00720308:return VR::US; case 0x00720310:return VR::CS; case 0x00720312:return VR::CS; case 0x00720314:return VR::US; case 0x00720316:return VR::CS; case 0x00720318:return VR::US; case 0x00720320:return VR::US; case 0x00720330:return VR::FD; case 0x00720400:return VR::SQ; case 0x00720402:return VR::CS; case 0x00720404:return VR::CS; case 0x00720406:return VR::CS; case 0x00720420:return VR::US; case 0x00720421:return VR::US; case 0x00720422:return VR::SQ; case 0x00720424:return VR::SQ; case 0x00720427:return VR::SQ; case 0x00720430:return VR::SQ; case 0x00720432:return VR::US; case 0x00720434:return VR::CS; case 0x00720500:return VR::CS; case 0x00720510:return VR::CS; case 0x00720512:return VR::FD; case 0x00720514:return VR::FD; case 0x00720516:return VR::CS; case 0x00720520:return VR::CS; case 0x00720600:return VR::SQ; case 0x00720602:return VR::CS; case 0x00720604:return VR::CS; case 0x00720700:return VR::CS; case 0x00720702:return VR::CS; case 0x00720704:return VR::CS; case 0x00720705:return VR::SQ; case 0x00720706:return VR::CS; case 0x00720710:return VR::CS; case 0x00720712:return VR::CS; case 0x00720714:return VR::CS; case 0x00720716:return VR::CS; case 0x00720717:return VR::CS; case 0x00720718:return VR::CS; case 0x00740120:return VR::FD; case 0x00740121:return VR::FD; case 0x00741000:return VR::CS; case 0x00741002:return VR::SQ; case 0x00741004:return VR::DS; case 0x00741006:return VR::ST; case 0x00741008:return VR::SQ; case 0x0074100a:return VR::ST; case 0x0074100c:return VR::LO; case 0x0074100e:return VR::SQ; case 0x00741020:return VR::SQ; case 0x00741022:return VR::CS; case 0x00741024:return VR::IS; case 0x00741026:return VR::FD; case 0x00741027:return VR::FD; case 0x00741028:return VR::FD; case 0x0074102a:return VR::FD; case 0x0074102b:return VR::FD; case 0x0074102c:return VR::FD; case 0x0074102d:return VR::FD; case 0x00741030:return VR::SQ; case 0x00741032:return VR::CS; case 0x00741034:return VR::CS; case 0x00741036:return VR::CS; case 0x00741038:return VR::DS; case 0x0074103a:return VR::DS; case 0x00741040:return VR::SQ; case 0x00741042:return VR::SQ; case 0x00741044:return VR::SQ; case 0x00741046:return VR::SQ; case 0x00741048:return VR::SQ; case 0x0074104a:return VR::SQ; case 0x0074104c:return VR::SQ; case 0x0074104e:return VR::SQ; case 0x00741050:return VR::SQ; case 0x00741052:return VR::AT; case 0x00741054:return VR::UL; case 0x00741056:return VR::LO; case 0x00741057:return VR::IS; case 0x00741200:return VR::CS; case 0x00741202:return VR::LO; case 0x00741204:return VR::LO; case 0x00741210:return VR::SQ; case 0x00741212:return VR::SQ; case 0x00741216:return VR::SQ; case 0x00741220:return VR::SQ; case 0x00741222:return VR::LO; case 0x00741224:return VR::SQ; case 0x00741230:return VR::LO; case 0x00741234:return VR::AE; case 0x00741236:return VR::AE; case 0x00741238:return VR::LT; case 0x00741242:return VR::CS; case 0x00741244:return VR::CS; case 0x00741246:return VR::CS; case 0x00741324:return VR::UL; case 0x00741338:return VR::FD; case 0x0074133a:return VR::FD; case 0x00760001:return VR::LO; case 0x00760003:return VR::LO; case 0x00760006:return VR::LO; case 0x00760008:return VR::SQ; case 0x0076000a:return VR::CS; case 0x0076000c:return VR::SQ; case 0x0076000e:return VR::SQ; case 0x00760010:return VR::SQ; case 0x00760020:return VR::SQ; case 0x00760030:return VR::LO; case 0x00760032:return VR::SQ; case 0x00760034:return VR::CS; case 0x00760036:return VR::CS; case 0x00760038:return VR::CS; case 0x00760040:return VR::SQ; case 0x00760055:return VR::US; case 0x00760060:return VR::SQ; case 0x00760070:return VR::US; case 0x00760080:return VR::US; case 0x00760090:return VR::US; case 0x007600a0:return VR::US; case 0x007600b0:return VR::US; case 0x007600c0:return VR::US; case 0x00780001:return VR::LO; case 0x00780010:return VR::ST; case 0x00780020:return VR::LO; case 0x00780024:return VR::LO; case 0x00780026:return VR::SQ; case 0x00780028:return VR::SQ; case 0x0078002a:return VR::SQ; case 0x0078002e:return VR::US; case 0x00780050:return VR::FD; case 0x00780060:return VR::FD; case 0x00780070:return VR::SQ; case 0x00780090:return VR::FD; case 0x007800a0:return VR::FD; case 0x007800b0:return VR::SQ; case 0x007800b2:return VR::LO; case 0x007800b4:return VR::SQ; case 0x007800b6:return VR::US; case 0x007800b8:return VR::US; case 0x00880130:return VR::SH; case 0x00880140:return VR::UI; case 0x00880200:return VR::SQ; case 0x00880904:return VR::LO; case 0x00880906:return VR::ST; case 0x00880910:return VR::LO; case 0x00880912:return VR::LO; case 0x01000410:return VR::CS; case 0x01000420:return VR::DT; case 0x01000424:return VR::LT; case 0x01000426:return VR::LO; case 0x04000005:return VR::US; case 0x04000010:return VR::UI; case 0x04000015:return VR::CS; case 0x04000020:return VR::AT; case 0x04000100:return VR::UI; case 0x04000105:return VR::DT; case 0x04000110:return VR::CS; case 0x04000115:return VR::OB; case 0x04000120:return VR::OB; case 0x04000305:return VR::CS; case 0x04000310:return VR::OB; case 0x04000401:return VR::SQ; case 0x04000402:return VR::SQ; case 0x04000403:return VR::SQ; case 0x04000404:return VR::OB; case 0x04000500:return VR::SQ; case 0x04000510:return VR::UI; case 0x04000520:return VR::OB; case 0x04000550:return VR::SQ; case 0x04000561:return VR::SQ; case 0x04000562:return VR::DT; case 0x04000563:return VR::LO; case 0x04000564:return VR::LO; case 0x04000565:return VR::CS; case 0x20000010:return VR::IS; case 0x2000001e:return VR::SQ; case 0x20000020:return VR::CS; case 0x20000030:return VR::CS; case 0x20000040:return VR::CS; case 0x20000050:return VR::LO; case 0x20000060:return VR::IS; case 0x20000061:return VR::IS; case 0x20000062:return VR::CS; case 0x20000063:return VR::CS; case 0x20000065:return VR::CS; case 0x20000067:return VR::CS; case 0x20000069:return VR::CS; case 0x2000006a:return VR::CS; case 0x200000a0:return VR::US; case 0x200000a1:return VR::US; case 0x200000a2:return VR::SQ; case 0x200000a4:return VR::SQ; case 0x200000a8:return VR::SQ; case 0x20000500:return VR::SQ; case 0x20000510:return VR::SQ; case 0x20100010:return VR::ST; case 0x20100030:return VR::CS; case 0x20100040:return VR::CS; case 0x20100050:return VR::CS; case 0x20100052:return VR::CS; case 0x20100054:return VR::CS; case 0x20100060:return VR::CS; case 0x20100080:return VR::CS; case 0x201000a6:return VR::CS; case 0x201000a7:return VR::CS; case 0x201000a8:return VR::CS; case 0x201000a9:return VR::CS; case 0x20100100:return VR::CS; case 0x20100110:return VR::CS; case 0x20100120:return VR::US; case 0x20100130:return VR::US; case 0x20100140:return VR::CS; case 0x20100150:return VR::ST; case 0x20100152:return VR::LT; case 0x20100154:return VR::IS; case 0x2010015e:return VR::US; case 0x20100160:return VR::US; case 0x20100376:return VR::DS; case 0x20100500:return VR::SQ; case 0x20100510:return VR::SQ; case 0x20100520:return VR::SQ; case 0x20200010:return VR::US; case 0x20200020:return VR::CS; case 0x20200030:return VR::DS; case 0x20200040:return VR::CS; case 0x20200050:return VR::CS; case 0x202000a0:return VR::CS; case 0x202000a2:return VR::CS; case 0x20200110:return VR::SQ; case 0x20200111:return VR::SQ; case 0x20200130:return VR::SQ; case 0x20200140:return VR::SQ; case 0x20300010:return VR::US; case 0x20300020:return VR::LO; case 0x20400010:return VR::SQ; case 0x20400011:return VR::US; case 0x20400020:return VR::SQ; case 0x20400060:return VR::CS; case 0x20400070:return VR::CS; case 0x20400072:return VR::CS; case 0x20400074:return VR::US; case 0x20400080:return VR::CS; case 0x20400082:return VR::CS; case 0x20400090:return VR::CS; case 0x20400100:return VR::CS; case 0x20400500:return VR::SQ; case 0x20500010:return VR::SQ; case 0x20500020:return VR::CS; case 0x20500500:return VR::SQ; case 0x21000010:return VR::SH; case 0x21000020:return VR::CS; case 0x21000030:return VR::CS; case 0x21000040:return VR::DA; case 0x21000050:return VR::TM; case 0x21000070:return VR::AE; case 0x21000140:return VR::AE; case 0x21000160:return VR::SH; case 0x21000170:return VR::IS; case 0x21000500:return VR::SQ; case 0x21100010:return VR::CS; case 0x21100020:return VR::CS; case 0x21100030:return VR::LO; case 0x21100099:return VR::SH; case 0x21200010:return VR::CS; case 0x21200050:return VR::SQ; case 0x21200070:return VR::SQ; case 0x21300010:return VR::SQ; case 0x21300015:return VR::SQ; case 0x21300030:return VR::SQ; case 0x21300040:return VR::SQ; case 0x21300050:return VR::SQ; case 0x21300060:return VR::SQ; case 0x21300080:return VR::SQ; case 0x213000a0:return VR::SQ; case 0x213000c0:return VR::SQ; case 0x22000001:return VR::CS; case 0x22000002:return VR::UT; case 0x22000003:return VR::CS; case 0x22000004:return VR::LT; case 0x22000005:return VR::LT; case 0x22000006:return VR::CS; case 0x22000007:return VR::CS; case 0x22000008:return VR::CS; case 0x22000009:return VR::CS; case 0x2200000a:return VR::CS; case 0x2200000b:return VR::US; case 0x2200000c:return VR::LO; case 0x2200000d:return VR::SQ; case 0x2200000e:return VR::AT; case 0x2200000f:return VR::CS; case 0x22000020:return VR::CS; case 0x30020002:return VR::SH; case 0x30020003:return VR::LO; case 0x30020004:return VR::ST; case 0x3002000a:return VR::CS; case 0x3002000c:return VR::CS; case 0x3002000d:return VR::DS; case 0x3002000e:return VR::DS; case 0x30020010:return VR::DS; case 0x30020011:return VR::DS; case 0x30020012:return VR::DS; case 0x30020020:return VR::SH; case 0x30020022:return VR::DS; case 0x30020024:return VR::DS; case 0x30020026:return VR::DS; case 0x30020028:return VR::DS; case 0x30020029:return VR::IS; case 0x30020030:return VR::SQ; case 0x30020032:return VR::DS; case 0x30020034:return VR::DS; case 0x30020040:return VR::SQ; case 0x30020041:return VR::CS; case 0x30020042:return VR::DS; case 0x30020050:return VR::SQ; case 0x30020051:return VR::CS; case 0x30020052:return VR::SH; case 0x30040001:return VR::CS; case 0x30040002:return VR::CS; case 0x30040004:return VR::CS; case 0x30040006:return VR::LO; case 0x30040008:return VR::DS; case 0x3004000a:return VR::CS; case 0x3004000c:return VR::DS; case 0x3004000e:return VR::DS; case 0x30040010:return VR::SQ; case 0x30040012:return VR::DS; case 0x30040014:return VR::CS; case 0x30040040:return VR::DS; case 0x30040042:return VR::DS; case 0x30040050:return VR::SQ; case 0x30040052:return VR::DS; case 0x30040054:return VR::CS; case 0x30040056:return VR::IS; case 0x30040058:return VR::DS; case 0x30040060:return VR::SQ; case 0x30040062:return VR::CS; case 0x30040070:return VR::DS; case 0x30040072:return VR::DS; case 0x30040074:return VR::DS; case 0x30060002:return VR::SH; case 0x30060004:return VR::LO; case 0x30060006:return VR::ST; case 0x30060008:return VR::DA; case 0x30060009:return VR::TM; case 0x30060010:return VR::SQ; case 0x30060012:return VR::SQ; case 0x30060014:return VR::SQ; case 0x30060016:return VR::SQ; case 0x30060020:return VR::SQ; case 0x30060022:return VR::IS; case 0x30060024:return VR::UI; case 0x30060026:return VR::LO; case 0x30060028:return VR::ST; case 0x3006002a:return VR::IS; case 0x3006002c:return VR::DS; case 0x30060030:return VR::SQ; case 0x30060033:return VR::CS; case 0x30060036:return VR::CS; case 0x30060038:return VR::LO; case 0x30060039:return VR::SQ; case 0x30060040:return VR::SQ; case 0x30060042:return VR::CS; case 0x30060044:return VR::DS; case 0x30060045:return VR::DS; case 0x30060046:return VR::IS; case 0x30060048:return VR::IS; case 0x30060049:return VR::IS; case 0x30060050:return VR::DS; case 0x30060080:return VR::SQ; case 0x30060082:return VR::IS; case 0x30060084:return VR::IS; case 0x30060085:return VR::SH; case 0x30060086:return VR::SQ; case 0x30060088:return VR::ST; case 0x300600a0:return VR::SQ; case 0x300600a4:return VR::CS; case 0x300600a6:return VR::PN; case 0x300600b0:return VR::SQ; case 0x300600b2:return VR::CS; case 0x300600b4:return VR::DS; case 0x300600b6:return VR::SQ; case 0x300600b7:return VR::US; case 0x300600b8:return VR::FL; case 0x300600c0:return VR::SQ; case 0x300600c2:return VR::UI; case 0x300600c4:return VR::CS; case 0x300600c6:return VR::DS; case 0x300600c8:return VR::LO; case 0x30080010:return VR::SQ; case 0x30080012:return VR::ST; case 0x30080014:return VR::CS; case 0x30080016:return VR::DS; case 0x30080020:return VR::SQ; case 0x30080021:return VR::SQ; case 0x30080022:return VR::IS; case 0x30080024:return VR::DA; case 0x30080025:return VR::TM; case 0x3008002a:return VR::CS; case 0x3008002b:return VR::SH; case 0x3008002c:return VR::CS; case 0x30080030:return VR::SQ; case 0x30080032:return VR::DS; case 0x30080033:return VR::DS; case 0x30080036:return VR::DS; case 0x30080037:return VR::DS; case 0x3008003a:return VR::DS; case 0x3008003b:return VR::DS; case 0x30080040:return VR::SQ; case 0x30080041:return VR::SQ; case 0x30080042:return VR::DS; case 0x30080044:return VR::DS; case 0x30080045:return VR::FL; case 0x30080046:return VR::FL; case 0x30080047:return VR::FL; case 0x30080048:return VR::DS; case 0x30080050:return VR::SQ; case 0x30080052:return VR::DS; case 0x30080054:return VR::DA; case 0x30080056:return VR::DA; case 0x3008005a:return VR::IS; case 0x30080060:return VR::SQ; case 0x30080061:return VR::AT; case 0x30080062:return VR::AT; case 0x30080063:return VR::IS; case 0x30080064:return VR::IS; case 0x30080065:return VR::AT; case 0x30080066:return VR::ST; case 0x30080068:return VR::SQ; case 0x3008006a:return VR::FL; case 0x30080070:return VR::SQ; case 0x30080072:return VR::IS; case 0x30080074:return VR::ST; case 0x30080076:return VR::DS; case 0x30080078:return VR::DS; case 0x3008007a:return VR::DS; case 0x30080080:return VR::SQ; case 0x30080082:return VR::IS; case 0x30080090:return VR::SQ; case 0x30080092:return VR::IS; case 0x300800a0:return VR::SQ; case 0x300800b0:return VR::SQ; case 0x300800c0:return VR::SQ; case 0x300800d0:return VR::SQ; case 0x300800e0:return VR::SQ; case 0x300800f0:return VR::SQ; case 0x300800f2:return VR::SQ; case 0x300800f4:return VR::SQ; case 0x300800f6:return VR::SQ; case 0x30080100:return VR::SQ; case 0x30080105:return VR::LO; case 0x30080110:return VR::SQ; case 0x30080116:return VR::CS; case 0x30080120:return VR::SQ; case 0x30080122:return VR::IS; case 0x30080130:return VR::SQ; case 0x30080132:return VR::DS; case 0x30080134:return VR::DS; case 0x30080136:return VR::IS; case 0x30080138:return VR::IS; case 0x3008013a:return VR::DS; case 0x3008013c:return VR::DS; case 0x30080140:return VR::SQ; case 0x30080142:return VR::IS; case 0x30080150:return VR::SQ; case 0x30080152:return VR::IS; case 0x30080160:return VR::SQ; case 0x30080162:return VR::DA; case 0x30080164:return VR::TM; case 0x30080166:return VR::DA; case 0x30080168:return VR::TM; case 0x30080200:return VR::CS; case 0x30080202:return VR::ST; case 0x30080220:return VR::SQ; case 0x30080223:return VR::IS; case 0x30080224:return VR::CS; case 0x30080230:return VR::CS; case 0x30080240:return VR::SQ; case 0x30080250:return VR::DA; case 0x30080251:return VR::TM; case 0x300a0002:return VR::SH; case 0x300a0003:return VR::LO; case 0x300a0004:return VR::ST; case 0x300a0006:return VR::DA; case 0x300a0007:return VR::TM; case 0x300a0009:return VR::LO; case 0x300a000a:return VR::CS; case 0x300a000b:return VR::LO; case 0x300a000c:return VR::CS; case 0x300a000e:return VR::ST; case 0x300a0010:return VR::SQ; case 0x300a0012:return VR::IS; case 0x300a0013:return VR::UI; case 0x300a0014:return VR::CS; case 0x300a0015:return VR::CS; case 0x300a0016:return VR::LO; case 0x300a0018:return VR::DS; case 0x300a001a:return VR::DS; case 0x300a0020:return VR::CS; case 0x300a0021:return VR::DS; case 0x300a0022:return VR::DS; case 0x300a0023:return VR::DS; case 0x300a0025:return VR::DS; case 0x300a0026:return VR::DS; case 0x300a0027:return VR::DS; case 0x300a0028:return VR::DS; case 0x300a002a:return VR::DS; case 0x300a002b:return VR::DS; case 0x300a002c:return VR::DS; case 0x300a002d:return VR::DS; case 0x300a0040:return VR::SQ; case 0x300a0042:return VR::IS; case 0x300a0043:return VR::SH; case 0x300a0044:return VR::DS; case 0x300a0046:return VR::DS; case 0x300a0048:return VR::SQ; case 0x300a004a:return VR::DS; case 0x300a004b:return VR::FL; case 0x300a004c:return VR::DS; case 0x300a004e:return VR::DS; case 0x300a004f:return VR::FL; case 0x300a0050:return VR::FL; case 0x300a0051:return VR::DS; case 0x300a0052:return VR::DS; case 0x300a0053:return VR::DS; case 0x300a0055:return VR::CS; case 0x300a0070:return VR::SQ; case 0x300a0071:return VR::IS; case 0x300a0072:return VR::LO; case 0x300a0078:return VR::IS; case 0x300a0079:return VR::IS; case 0x300a007a:return VR::IS; case 0x300a007b:return VR::LT; case 0x300a0080:return VR::IS; case 0x300a0082:return VR::DS; case 0x300a0084:return VR::DS; case 0x300a0086:return VR::DS; case 0x300a0088:return VR::FL; case 0x300a0089:return VR::FL; case 0x300a008a:return VR::FL; case 0x300a00a0:return VR::IS; case 0x300a00a2:return VR::DS; case 0x300a00a4:return VR::DS; case 0x300a00b0:return VR::SQ; case 0x300a00b2:return VR::SH; case 0x300a00b3:return VR::CS; case 0x300a00b4:return VR::DS; case 0x300a00b6:return VR::SQ; case 0x300a00b8:return VR::CS; case 0x300a00ba:return VR::DS; case 0x300a00bb:return VR::FL; case 0x300a00bc:return VR::IS; case 0x300a00be:return VR::DS; case 0x300a00c0:return VR::IS; case 0x300a00c2:return VR::LO; case 0x300a00c3:return VR::ST; case 0x300a00c4:return VR::CS; case 0x300a00c6:return VR::CS; case 0x300a00c7:return VR::CS; case 0x300a00c8:return VR::IS; case 0x300a00ca:return VR::SQ; case 0x300a00cc:return VR::LO; case 0x300a00ce:return VR::CS; case 0x300a00d0:return VR::IS; case 0x300a00d1:return VR::SQ; case 0x300a00d2:return VR::IS; case 0x300a00d3:return VR::CS; case 0x300a00d4:return VR::SH; case 0x300a00d5:return VR::IS; case 0x300a00d6:return VR::DS; case 0x300a00d7:return VR::FL; case 0x300a00d8:return VR::DS; case 0x300a00d9:return VR::FL; case 0x300a00da:return VR::DS; case 0x300a00db:return VR::FL; case 0x300a00dc:return VR::SH; case 0x300a00dd:return VR::ST; case 0x300a00e0:return VR::IS; case 0x300a00e1:return VR::SH; case 0x300a00e2:return VR::DS; case 0x300a00e3:return VR::SQ; case 0x300a00e4:return VR::IS; case 0x300a00e5:return VR::SH; case 0x300a00e6:return VR::DS; case 0x300a00e7:return VR::IS; case 0x300a00e8:return VR::IS; case 0x300a00e9:return VR::DS; case 0x300a00ea:return VR::DS; case 0x300a00eb:return VR::DS; case 0x300a00ec:return VR::DS; case 0x300a00ed:return VR::IS; case 0x300a00ee:return VR::CS; case 0x300a00f0:return VR::IS; case 0x300a00f2:return VR::DS; case 0x300a00f3:return VR::FL; case 0x300a00f4:return VR::SQ; case 0x300a00f5:return VR::SH; case 0x300a00f6:return VR::DS; case 0x300a00f7:return VR::FL; case 0x300a00f8:return VR::CS; case 0x300a00f9:return VR::LO; case 0x300a00fa:return VR::CS; case 0x300a00fb:return VR::CS; case 0x300a00fc:return VR::IS; case 0x300a00fe:return VR::LO; case 0x300a0100:return VR::DS; case 0x300a0102:return VR::DS; case 0x300a0104:return VR::IS; case 0x300a0106:return VR::DS; case 0x300a0107:return VR::SQ; case 0x300a0108:return VR::SH; case 0x300a0109:return VR::CS; case 0x300a010a:return VR::LO; case 0x300a010c:return VR::DS; case 0x300a010e:return VR::DS; case 0x300a0110:return VR::IS; case 0x300a0111:return VR::SQ; case 0x300a0112:return VR::IS; case 0x300a0114:return VR::DS; case 0x300a0115:return VR::DS; case 0x300a0116:return VR::SQ; case 0x300a0118:return VR::CS; case 0x300a011a:return VR::SQ; case 0x300a011c:return VR::DS; case 0x300a011e:return VR::DS; case 0x300a011f:return VR::CS; case 0x300a0120:return VR::DS; case 0x300a0121:return VR::CS; case 0x300a0122:return VR::DS; case 0x300a0123:return VR::CS; case 0x300a0124:return VR::DS; case 0x300a0125:return VR::DS; case 0x300a0126:return VR::CS; case 0x300a0128:return VR::DS; case 0x300a0129:return VR::DS; case 0x300a012a:return VR::DS; case 0x300a012c:return VR::DS; case 0x300a012e:return VR::DS; case 0x300a0130:return VR::DS; case 0x300a0134:return VR::DS; case 0x300a0140:return VR::FL; case 0x300a0142:return VR::CS; case 0x300a0144:return VR::FL; case 0x300a0146:return VR::CS; case 0x300a0148:return VR::FL; case 0x300a014a:return VR::FL; case 0x300a014c:return VR::CS; case 0x300a014e:return VR::FL; case 0x300a0180:return VR::SQ; case 0x300a0182:return VR::IS; case 0x300a0183:return VR::LO; case 0x300a0184:return VR::LO; case 0x300a0190:return VR::SQ; case 0x300a0192:return VR::CS; case 0x300a0194:return VR::SH; case 0x300a0196:return VR::ST; case 0x300a0198:return VR::SH; case 0x300a0199:return VR::FL; case 0x300a019a:return VR::FL; case 0x300a01a0:return VR::SQ; case 0x300a01a2:return VR::CS; case 0x300a01a4:return VR::SH; case 0x300a01a6:return VR::ST; case 0x300a01a8:return VR::SH; case 0x300a01b0:return VR::CS; case 0x300a01b2:return VR::ST; case 0x300a01b4:return VR::SQ; case 0x300a01b6:return VR::CS; case 0x300a01b8:return VR::SH; case 0x300a01ba:return VR::ST; case 0x300a01bc:return VR::DS; case 0x300a01d0:return VR::ST; case 0x300a01d2:return VR::DS; case 0x300a01d4:return VR::DS; case 0x300a01d6:return VR::DS; case 0x300a0200:return VR::CS; case 0x300a0202:return VR::CS; case 0x300a0206:return VR::SQ; case 0x300a0210:return VR::SQ; case 0x300a0212:return VR::IS; case 0x300a0214:return VR::CS; case 0x300a0216:return VR::LO; case 0x300a0218:return VR::DS; case 0x300a021a:return VR::DS; case 0x300a0222:return VR::DS; case 0x300a0224:return VR::DS; case 0x300a0226:return VR::LO; case 0x300a0228:return VR::DS; case 0x300a0229:return VR::CS; case 0x300a022a:return VR::DS; case 0x300a022b:return VR::DS; case 0x300a022c:return VR::DA; case 0x300a022e:return VR::TM; case 0x300a0230:return VR::SQ; case 0x300a0232:return VR::CS; case 0x300a0234:return VR::IS; case 0x300a0236:return VR::LO; case 0x300a0238:return VR::LO; case 0x300a0240:return VR::IS; case 0x300a0242:return VR::SH; case 0x300a0244:return VR::LO; case 0x300a0250:return VR::DS; case 0x300a0260:return VR::SQ; case 0x300a0262:return VR::IS; case 0x300a0263:return VR::SH; case 0x300a0264:return VR::CS; case 0x300a0266:return VR::LO; case 0x300a026a:return VR::DS; case 0x300a026c:return VR::DS; case 0x300a0280:return VR::SQ; case 0x300a0282:return VR::IS; case 0x300a0284:return VR::DS; case 0x300a0286:return VR::DS; case 0x300a0288:return VR::CS; case 0x300a028a:return VR::IS; case 0x300a028c:return VR::DS; case 0x300a0290:return VR::IS; case 0x300a0291:return VR::SH; case 0x300a0292:return VR::CS; case 0x300a0294:return VR::LO; case 0x300a0296:return VR::DS; case 0x300a0298:return VR::LO; case 0x300a029c:return VR::DS; case 0x300a029e:return VR::DS; case 0x300a02a0:return VR::DS; case 0x300a02a2:return VR::IS; case 0x300a02a4:return VR::DS; case 0x300a02b0:return VR::SQ; case 0x300a02b2:return VR::IS; case 0x300a02b3:return VR::SH; case 0x300a02b4:return VR::LO; case 0x300a02b8:return VR::DS; case 0x300a02ba:return VR::DS; case 0x300a02c8:return VR::DS; case 0x300a02d0:return VR::SQ; case 0x300a02d2:return VR::DS; case 0x300a02d4:return VR::DS; case 0x300a02d6:return VR::DS; case 0x300a02e0:return VR::CS; case 0x300a02e1:return VR::CS; case 0x300a02e2:return VR::DS; case 0x300a02e3:return VR::FL; case 0x300a02e4:return VR::FL; case 0x300a02e5:return VR::FL; case 0x300a02e6:return VR::FL; case 0x300a02e7:return VR::FL; case 0x300a02e8:return VR::FL; case 0x300a02ea:return VR::SQ; case 0x300a02eb:return VR::LT; case 0x300a0302:return VR::IS; case 0x300a0304:return VR::IS; case 0x300a0306:return VR::SS; case 0x300a0308:return VR::CS; case 0x300a030a:return VR::FL; case 0x300a030c:return VR::SQ; case 0x300a030d:return VR::FL; case 0x300a030f:return VR::SH; case 0x300a0312:return VR::IS; case 0x300a0314:return VR::SQ; case 0x300a0316:return VR::IS; case 0x300a0318:return VR::SH; case 0x300a0320:return VR::CS; case 0x300a0322:return VR::LO; case 0x300a0330:return VR::IS; case 0x300a0332:return VR::SQ; case 0x300a0334:return VR::IS; case 0x300a0336:return VR::SH; case 0x300a0338:return VR::CS; case 0x300a033a:return VR::LO; case 0x300a033c:return VR::FL; case 0x300a0340:return VR::IS; case 0x300a0342:return VR::SQ; case 0x300a0344:return VR::IS; case 0x300a0346:return VR::SH; case 0x300a0348:return VR::CS; case 0x300a034a:return VR::LO; case 0x300a034c:return VR::SH; case 0x300a0350:return VR::CS; case 0x300a0352:return VR::SH; case 0x300a0354:return VR::LO; case 0x300a0356:return VR::FL; case 0x300a0358:return VR::FL; case 0x300a035a:return VR::FL; case 0x300a0360:return VR::SQ; case 0x300a0362:return VR::LO; case 0x300a0364:return VR::FL; case 0x300a0366:return VR::FL; case 0x300a0370:return VR::SQ; case 0x300a0372:return VR::LO; case 0x300a0374:return VR::FL; case 0x300a0380:return VR::SQ; case 0x300a0382:return VR::FL; case 0x300a0384:return VR::FL; case 0x300a0386:return VR::FL; case 0x300a0388:return VR::FL; case 0x300a038a:return VR::FL; case 0x300a0390:return VR::SH; case 0x300a0392:return VR::IS; case 0x300a0394:return VR::FL; case 0x300a0396:return VR::FL; case 0x300a0398:return VR::FL; case 0x300a039a:return VR::IS; case 0x300a03a0:return VR::SQ; case 0x300a03a2:return VR::SQ; case 0x300a03a4:return VR::SQ; case 0x300a03a6:return VR::SQ; case 0x300a03a8:return VR::SQ; case 0x300a03aa:return VR::SQ; case 0x300a03ac:return VR::SQ; case 0x300a0401:return VR::SQ; case 0x300a0402:return VR::ST; case 0x300a0410:return VR::SQ; case 0x300a0412:return VR::FL; case 0x300a0420:return VR::SQ; case 0x300a0421:return VR::SH; case 0x300a0422:return VR::ST; case 0x300a0423:return VR::CS; case 0x300a0424:return VR::IS; case 0x300a0431:return VR::SQ; case 0x300a0432:return VR::CS; case 0x300a0433:return VR::FL; case 0x300a0434:return VR::FL; case 0x300a0435:return VR::FL; case 0x300a0436:return VR::FL; case 0x300c0002:return VR::SQ; case 0x300c0004:return VR::SQ; case 0x300c0006:return VR::IS; case 0x300c0007:return VR::IS; case 0x300c0008:return VR::DS; case 0x300c0009:return VR::DS; case 0x300c000a:return VR::SQ; case 0x300c000c:return VR::IS; case 0x300c000e:return VR::IS; case 0x300c0020:return VR::SQ; case 0x300c0022:return VR::IS; case 0x300c0040:return VR::SQ; case 0x300c0042:return VR::SQ; case 0x300c0050:return VR::SQ; case 0x300c0051:return VR::IS; case 0x300c0055:return VR::SQ; case 0x300c0060:return VR::SQ; case 0x300c006a:return VR::IS; case 0x300c0080:return VR::SQ; case 0x300c00a0:return VR::IS; case 0x300c00b0:return VR::SQ; case 0x300c00c0:return VR::IS; case 0x300c00d0:return VR::IS; case 0x300c00e0:return VR::IS; case 0x300c00f0:return VR::IS; case 0x300c00f2:return VR::SQ; case 0x300c00f4:return VR::IS; case 0x300c00f6:return VR::IS; case 0x300c0100:return VR::IS; case 0x300c0102:return VR::IS; case 0x300c0104:return VR::IS; case 0x300e0002:return VR::CS; case 0x300e0004:return VR::DA; case 0x300e0005:return VR::TM; case 0x300e0008:return VR::PN; case 0x40000010:return VR::LT; case 0x40004000:return VR::LT; case 0x40080040:return VR::SH; case 0x40080042:return VR::LO; case 0x40080050:return VR::SQ; case 0x400800ff:return VR::CS; case 0x40080100:return VR::DA; case 0x40080101:return VR::TM; case 0x40080102:return VR::PN; case 0x40080103:return VR::LO; case 0x40080108:return VR::DA; case 0x40080109:return VR::TM; case 0x4008010a:return VR::PN; case 0x4008010b:return VR::ST; case 0x4008010c:return VR::PN; case 0x40080111:return VR::SQ; case 0x40080112:return VR::DA; case 0x40080113:return VR::TM; case 0x40080114:return VR::PN; case 0x40080115:return VR::LT; case 0x40080117:return VR::SQ; case 0x40080118:return VR::SQ; case 0x40080119:return VR::PN; case 0x4008011a:return VR::LO; case 0x40080200:return VR::SH; case 0x40080202:return VR::LO; case 0x40080210:return VR::CS; case 0x40080212:return VR::CS; case 0x40080300:return VR::ST; case 0x40084000:return VR::ST; case 0x40100001:return VR::CS; case 0x40100002:return VR::CS; case 0x40100004:return VR::SQ; case 0x40101001:return VR::SQ; case 0x40101004:return VR::FL; case 0x40101005:return VR::FL; case 0x40101006:return VR::OB; case 0x40101007:return VR::SH; case 0x40101008:return VR::CS; case 0x40101009:return VR::CS; case 0x4010100a:return VR::SQ; case 0x40101010:return VR::US; case 0x40101011:return VR::SQ; case 0x40101012:return VR::CS; case 0x40101013:return VR::LT; case 0x40101014:return VR::CS; case 0x40101015:return VR::CS; case 0x40101016:return VR::FL; case 0x40101017:return VR::FL; case 0x40101018:return VR::FL; case 0x40101019:return VR::FL; case 0x4010101a:return VR::SH; case 0x4010101b:return VR::FL; case 0x4010101c:return VR::FL; case 0x4010101d:return VR::FL; case 0x4010101e:return VR::SH; case 0x4010101f:return VR::SH; case 0x40101020:return VR::CS; case 0x40101021:return VR::CS; case 0x40101023:return VR::FL; case 0x40101024:return VR::CS; case 0x40101025:return VR::DT; case 0x40101026:return VR::DT; case 0x40101027:return VR::CS; case 0x40101028:return VR::CS; case 0x40101029:return VR::LO; case 0x4010102a:return VR::SH; case 0x4010102b:return VR::DT; case 0x40101031:return VR::CS; case 0x40101033:return VR::US; case 0x40101034:return VR::US; case 0x40101037:return VR::SQ; case 0x40101038:return VR::SQ; case 0x40101039:return VR::CS; case 0x4010103a:return VR::CS; case 0x40101041:return VR::DT; case 0x40101042:return VR::CS; case 0x40101043:return VR::FL; case 0x40101044:return VR::CS; case 0x40101045:return VR::SQ; case 0x40101046:return VR::CS; case 0x40101047:return VR::SQ; case 0x40101048:return VR::CS; case 0x40101051:return VR::LO; case 0x40101052:return VR::SH; case 0x40101053:return VR::LO; case 0x40101054:return VR::SH; case 0x40101055:return VR::SH; case 0x40101056:return VR::CS; case 0x40101058:return VR::SH; case 0x40101059:return VR::CS; case 0x40101060:return VR::FL; case 0x40101061:return VR::FL; case 0x40101062:return VR::FL; case 0x40101064:return VR::SQ; case 0x40101067:return VR::CS; case 0x40101068:return VR::LT; case 0x40101069:return VR::FL; case 0x4010106c:return VR::OB; case 0x4ffe0001:return VR::SQ; case 0x50000005:return VR::US; case 0x50000010:return VR::US; case 0x50000020:return VR::CS; case 0x50000022:return VR::LO; case 0x50000030:return VR::SH; case 0x50000040:return VR::SH; case 0x50000103:return VR::US; case 0x50000104:return VR::US; case 0x50000105:return VR::US; case 0x50000106:return VR::SH; case 0x50000110:return VR::US; case 0x50000112:return VR::US; case 0x50000114:return VR::US; case 0x50001001:return VR::CS; case 0x50002000:return VR::US; case 0x50002002:return VR::US; case 0x50002004:return VR::US; case 0x50002006:return VR::UL; case 0x50002008:return VR::UL; case 0x5000200a:return VR::UL; case 0x5000200e:return VR::LT; case 0x50002500:return VR::LO; case 0x50002600:return VR::SQ; case 0x50002610:return VR::US; case 0x52009229:return VR::SQ; case 0x52009230:return VR::SQ; case 0x54000100:return VR::SQ; case 0x54001004:return VR::US; case 0x54001006:return VR::CS; case 0x56000010:return VR::OF; case 0x56000020:return VR::OF; case 0x60000010:return VR::US; case 0x60000011:return VR::US; case 0x60000012:return VR::US; case 0x60000015:return VR::IS; case 0x60000022:return VR::LO; case 0x60000040:return VR::CS; case 0x60000045:return VR::LO; case 0x60000050:return VR::SS; case 0x60000051:return VR::US; case 0x60000052:return VR::US; case 0x60000060:return VR::CS; case 0x60000061:return VR::SH; case 0x60000062:return VR::SH; case 0x60000063:return VR::CS; case 0x60000066:return VR::AT; case 0x60000068:return VR::US; case 0x60000069:return VR::US; case 0x60000100:return VR::US; case 0x60000102:return VR::US; case 0x60000110:return VR::CS; case 0x60000200:return VR::US; case 0x60000800:return VR::CS; case 0x60000802:return VR::US; case 0x60000803:return VR::AT; case 0x60000804:return VR::US; case 0x60001001:return VR::CS; case 0x60001100:return VR::US; case 0x60001101:return VR::US; case 0x60001102:return VR::US; case 0x60001103:return VR::US; case 0x60001200:return VR::US; case 0x60001201:return VR::US; case 0x60001202:return VR::US; case 0x60001203:return VR::US; case 0x60001301:return VR::IS; case 0x60001302:return VR::DS; case 0x60001303:return VR::DS; case 0x60001500:return VR::LO; case 0x60004000:return VR::LT; case 0x7fe00020:return VR::OW; case 0x7fe00030:return VR::OW; case 0x7fe00040:return VR::OW; case 0x7f000011:return VR::US; case 0x7f000020:return VR::OW; case 0x7f000030:return VR::OW; case 0x7f000040:return VR::OW; case 0xfffafffa:return VR::SQ; case 0xfffcfffc:return VR::OB; default: return VR::INVALID; } } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmTagToVR.h000066400000000000000000000013361412732066400247440ustar00rootroot00000000000000/*========================================================================= 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 GDCMTAGTOVR_H #define GDCMTAGTOVR_H #include "gdcmVR.h" namespace gdcm { class Tag; VR::VRType GetVRFromTag( Tag const & tag ); } #endif // GDCMTAGTOVR_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmTransferSyntax.cxx000066400000000000000000000207231412732066400270250ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTransferSyntax.h" #include "gdcmTrace.h" #include #include #include #include namespace gdcm { //#include "gdcmUIDs.cxx" static const char *TSStrings[] = { // Implicit VR Little Endian "1.2.840.10008.1.2", // Implicit VR Big Endian DLX (G.E Private) "1.2.840.113619.5.2", // Explicit VR Little Endian "1.2.840.10008.1.2.1", // Deflated Explicit VR Little Endian "1.2.840.10008.1.2.1.99", // Explicit VR Big Endian "1.2.840.10008.1.2.2", // JPEG Baseline (Process 1) "1.2.840.10008.1.2.4.50", // JPEG Extended (Process 2 & 4) "1.2.840.10008.1.2.4.51", // JPEG Extended (Process 3 & 5) "1.2.840.10008.1.2.4.52", // JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8) "1.2.840.10008.1.2.4.53", // JPEG Full Progression, Non-Hierarchical (Process 10 & 12) "1.2.840.10008.1.2.4.55", // JPEG Lossless, Non-Hierarchical (Process 14) "1.2.840.10008.1.2.4.57", // JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14, // [Selection Value 1]) "1.2.840.10008.1.2.4.70", // JPEG-LS Lossless Image Compression "1.2.840.10008.1.2.4.80", // JPEG-LS Lossy (Near-Lossless) Image Compression "1.2.840.10008.1.2.4.81", // JPEG 2000 Lossless "1.2.840.10008.1.2.4.90", // JPEG 2000 "1.2.840.10008.1.2.4.91", // JPEG 2000 Part 2 Lossless "1.2.840.10008.1.2.4.92", // JPEG 2000 Part 2 "1.2.840.10008.1.2.4.93", // RLE Lossless "1.2.840.10008.1.2.5", // MPEG2 Main Profile @ Main Level "1.2.840.10008.1.2.4.100", // Old ACR NEMA, fake a TS "ImplicitVRBigEndianACRNEMA", // Weird Papyrus "1.2.840.10008.1.20", // CT_private_ELE, "1.3.46.670589.33.1.4.1", // JPIP Referenced "1.2.840.10008.1.2.4.94", // MPEG2 Main Profile @ High Level "1.2.840.10008.1.2.4.101", // MPEG-4 AVC/H.264 High Profile / Level 4.1 "1.2.840.10008.1.2.4.102", // MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1 "1.2.840.10008.1.2.4.103", // Unknown "Unknown Transfer Syntax", // Pretty sure we never use this case... nullptr // Compilers have no obligation to finish by NULL, do it ourself }; 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; if( notspace != str.size() ) { gdcmDebugMacro( "BUGGY HEADER: TS contains " << str.size()-notspace << " whitespace character(s)" ); str.erase(notspace); } int i = 0; while(TSStrings[i] != nullptr) //while(TransferSyntaxStrings[i] != 0) { if( str == TSStrings[i] ) //if( str == TransferSyntaxStrings[i] ) return (TSType)i; ++i; } return TS_END; } const char* TransferSyntax::GetTSString(TSType ts) { assert( ts <= TS_END ); return TSStrings[(int)ts]; //return TransferSyntaxStrings[(int)ts]; } bool TransferSyntax::IsImplicit(TSType ts) const { assert( ts != TS_END ); return ts == ImplicitVRLittleEndian || ts == ImplicitVRBigEndianACRNEMA || ts == ImplicitVRBigEndianPrivateGE #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION || ts == WeirdPapryus #endif ; } bool TransferSyntax::IsImplicit() const { if ( TSField == TS_END ) return false; return TSField == ImplicitVRLittleEndian || TSField == ImplicitVRBigEndianACRNEMA || TSField == ImplicitVRBigEndianPrivateGE #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION || TSField == WeirdPapryus #endif ; } bool TransferSyntax::IsExplicit() const { if ( TSField == TS_END ) return false; // important ! return !IsImplicit(); } bool TransferSyntax::IsLossy() const { if ( TSField == JPEGBaselineProcess1 || TSField == JPEGExtendedProcess2_4 || TSField == JPEGExtendedProcess3_5 || TSField == JPEGSpectralSelectionProcess6_8 || TSField == JPEGFullProgressionProcess10_12 || TSField == JPEGLSNearLossless || TSField == JPEG2000 || TSField == JPEG2000Part2 || TSField == JPIPReferenced || TSField == MPEG2MainProfile || TSField == MPEG2MainProfileHighLevel || TSField == MPEG4AVCH264HighProfileLevel4_1 || TSField == MPEG4AVCH264BDcompatibleHighProfileLevel4_1 ) { return true; } return false; } // This function really test the kind of compression algorithm and the matching // transfer syntax. If you use the JPEG compression algorithm (ITU-T T.81, // ISO/IEC IS 10918-1), You will not be able to declare a lossy compress pixel // data using JPEGLosslessProcess14_1 For the same reason using J2K (ITU-T // T.800, ISO/IEC IS 15444-1), you should not be allowed to stored an // irreversible wavelet compressed pixel data in a file declared with transfer // syntax JPEG2000Lossless. // Same goes for JPEG-LS (ITU-T T.87, ISO/IEC IS 14495-1), and to some extent // RLE which does not even allow lossy compression... bool TransferSyntax::CanStoreLossy() const { if ( TSField == JPEGLosslessProcess14 || TSField == JPEGLosslessProcess14_1 || TSField == JPEGLSLossless || TSField == JPEG2000Lossless || TSField == JPEG2000Part2Lossless || TSField == RLELossless ) { return false; } return true; } bool TransferSyntax::IsLossless() const { if ( TSField == JPEGBaselineProcess1 || TSField == JPEGExtendedProcess2_4 || TSField == JPEGExtendedProcess3_5 || TSField == JPEGSpectralSelectionProcess6_8 || TSField == JPEGFullProgressionProcess10_12 || // TSField == JPEGLSNearLossless || -> can be lossy & lossless // TSField == JPEG2000 || -> can be lossy & lossless // TSField == JPEG2000Part2 || -> can be lossy & lossless // TSField == JPIPReferenced || -> can be lossy & lossless TSField == MPEG2MainProfile || TSField == MPEG2MainProfileHighLevel || TSField == MPEG4AVCH264HighProfileLevel4_1 || TSField == MPEG4AVCH264BDcompatibleHighProfileLevel4_1 ) { return false; } return true; } // By implementation those two functions form a partition bool TransferSyntax::IsExplicit(TSType ts) const { assert( ts != TS_END ); return !IsImplicit(ts); } TransferSyntax::NegociatedType TransferSyntax::GetNegociatedType() const { if( TSField == TS_END ) { return TransferSyntax::Unknown; } else if( IsImplicit(TSField) ) { return TransferSyntax::Implicit; } return TransferSyntax::Explicit; } bool TransferSyntax::IsLittleEndian(TSType ts) const { assert( ts != TS_END ); return !IsBigEndian(ts); } bool TransferSyntax::IsBigEndian(TSType ts) const { assert( ts != TS_END ); return ts == ExplicitVRBigEndian // || ts == ImplicitVRBigEndianPrivateGE // Indeed this is LittleEndian || ts == ImplicitVRBigEndianACRNEMA; } SwapCode TransferSyntax::GetSwapCode() const { assert( TSField != TS_END ); if( IsBigEndian( TSField ) ) { return SwapCode::BigEndian; } assert( IsLittleEndian( TSField ) ); return SwapCode::LittleEndian; } bool TransferSyntax::IsEncoded() const { return TSField == DeflatedExplicitVRLittleEndian; } bool TransferSyntax::IsEncapsulated() const { bool ret = false; switch( TSField ) { //case ImplicitVRLittleEndian: //case ImplicitVRBigEndianPrivateGE: //case ExplicitVRLittleEndian: //case DeflatedExplicitVRLittleEndian: //case ExplicitVRBigEndian: case JPEGBaselineProcess1: case JPEGExtendedProcess2_4: case JPEGExtendedProcess3_5: case JPEGSpectralSelectionProcess6_8: case JPEGFullProgressionProcess10_12: case JPEGLosslessProcess14: case JPEGLosslessProcess14_1: case JPEGLSLossless: case JPEGLSNearLossless: case JPEG2000Lossless: case JPEG2000: case JPEG2000Part2Lossless: case JPEG2000Part2: case JPIPReferenced: case RLELossless: case MPEG2MainProfile: case MPEG2MainProfileHighLevel: case MPEG4AVCH264HighProfileLevel4_1: case MPEG4AVCH264BDcompatibleHighProfileLevel4_1: //case ImplicitVRBigEndianACRNEMA: //case WeirdPapryus: ret = true; break; default: ; } return ret; } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmTransferSyntax.h000066400000000000000000000105341412732066400264510ustar00rootroot00000000000000/*========================================================================= 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 GDCMTRANSFERSYNTAX_H #define GDCMTRANSFERSYNTAX_H #include "gdcmSwapCode.h" namespace gdcm { /** * \brief Class to manipulate Transfer Syntax * \note * TRANSFER SYNTAX (Standard and Private): A set of encoding rules that allow * Application Entities to unambiguously negotiate the encoding techniques * (e.g., Data Element structure, byte ordering, compression) they are able to * support, thereby allowing these Application Entities to communicate. * * \todo: The implementation is completely retarded -> see gdcm::UIDs for a replacement * We need: IsSupported * We need preprocess of raw/xml file * We need GetFullName() * * Need a notion of Private Syntax. As defined in PS 3.5. Section 9.2 * * \see UIDs */ class GDCM_EXPORT TransferSyntax { public: typedef enum { Unknown = 0, Explicit, Implicit } NegociatedType; #if 0 //NOT FLEXIBLE, since forces user to update lib every time new module //comes out... // TODO typedef enum { NoSpacing = 0, PixelSpacing, ImagerPixelSpacing, PixelAspectRatio } ImageSpacingType; ImageSpacingType GetImageSpacing(); #endif typedef enum { ImplicitVRLittleEndian = 0, ImplicitVRBigEndianPrivateGE, ExplicitVRLittleEndian, DeflatedExplicitVRLittleEndian, ExplicitVRBigEndian, JPEGBaselineProcess1, JPEGExtendedProcess2_4, JPEGExtendedProcess3_5, JPEGSpectralSelectionProcess6_8, JPEGFullProgressionProcess10_12, JPEGLosslessProcess14, JPEGLosslessProcess14_1, JPEGLSLossless, JPEGLSNearLossless, JPEG2000Lossless, JPEG2000, JPEG2000Part2Lossless, JPEG2000Part2, RLELossless, MPEG2MainProfile, ImplicitVRBigEndianACRNEMA, WeirdPapryus, CT_private_ELE, JPIPReferenced, MPEG2MainProfileHighLevel, MPEG4AVCH264HighProfileLevel4_1, MPEG4AVCH264BDcompatibleHighProfileLevel4_1, TS_END } TSType; // Return the string as written in the official DICOM dict from // a custom enum type static const char* GetTSString(TSType ts); static TSType GetTSType(const char *str); NegociatedType GetNegociatedType() const; /// \deprecated Return the SwapCode associated with the Transfer Syntax. Be careful with /// the special GE private syntax the DataSet is written in little endian but /// the Pixel Data is in Big Endian. SwapCode GetSwapCode() const; bool IsValid() const { return TSField != TS_END; } operator TSType () const { return TSField; } // FIXME: ImplicitVRLittleEndian used to be the default, but nowadays // this is rather the ExplicitVRLittleEndian instead...should be change the default ? TransferSyntax(TSType type = ImplicitVRLittleEndian):TSField(type) {} // return if dataset is encoded or not (Deflate Explicit VR) bool IsEncoded() const; bool IsImplicit() const; bool IsExplicit() const; bool IsEncapsulated() const; /** Return true if the transfer syntax algorithm is a lossy algorithm */ bool IsLossy() const; /** Return true if the transfer syntax algorithm is a lossless algorithm */ bool IsLossless() const; /** return true if TransFer Syntax Allow storing of Lossy Pixel Data */ bool CanStoreLossy() const; const char *GetString() const { return TransferSyntax::GetTSString(TSField); } friend std::ostream &operator<<(std::ostream &os, const TransferSyntax &ts); private: // DO NOT EXPOSE the following. Internal details of TransferSyntax bool IsImplicit(TSType ts) const; bool IsExplicit(TSType ts) const; bool IsLittleEndian(TSType ts) const; bool IsBigEndian(TSType ts) const; TSType TSField; }; //----------------------------------------------------------------------------- inline std::ostream &operator<<(std::ostream &_os, const TransferSyntax &ts) { _os << TransferSyntax::GetTSString(ts); return _os; } } // end namespace gdcm #endif //GDCMTRANSFERSYNTAX_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmUNExplicitDataElement.cxx000066400000000000000000000035541412732066400301650ustar00rootroot00000000000000/*========================================================================= 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 "gdcmUNExplicitDataElement.h" #include "gdcmSequenceOfItems.h" #include "gdcmSequenceOfFragments.h" namespace gdcm { //----------------------------------------------------------------------------- VL UNExplicitDataElement::GetLength() const { if( ValueLengthField.IsUndefined() ) { assert( ValueField->GetLength().IsUndefined() ); Value *p = ValueField; // If this is a SQ we need to compute it's proper length SequenceOfItems *sq = dynamic_cast(p); // TODO can factor the code: if( sq ) { return TagField.GetLength() + VRField.GetLength() + ValueLengthField.GetLength() + sq->ComputeLength(); } SequenceOfFragments *sf = dynamic_cast(p); if( sf ) { assert( VRField & (VR::OB | VR::OW) ); return TagField.GetLength() + VRField.GetLength() + ValueLengthField.GetLength() + sf->ComputeLength(); } assert(0); return 0; } else { // Each time VR::GetLength() is 2 then Value Length is coded in 2 // 4 then Value Length is coded in 4 assert( !ValueField || ValueField->GetLength() == ValueLengthField ); return TagField.GetLength() + 2*VRField.GetLength() + ValueLengthField; } } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmUNExplicitDataElement.h000066400000000000000000000027241412732066400276100ustar00rootroot00000000000000/*========================================================================= 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 GDCMUNEXPLICITDATAELEMENT_H #define GDCMUNEXPLICITDATAELEMENT_H #include "gdcmDataElement.h" namespace gdcm { // Data Element (UNExplicit) /** * \brief Class to read/write a DataElement as UNExplicit Data Element * \note bla */ class GDCM_EXPORT UNExplicitDataElement : public DataElement { public: VL GetLength() const; template std::istream &Read(std::istream &is); template std::istream &ReadPreValue(std::istream &is); template std::istream &ReadValue(std::istream &is, bool readvalues = true); template std::istream &ReadWithLength(std::istream &is, VL & length); // PURPOSELY do not provide an implementation for writing ! //template //const std::ostream &Write(std::ostream &os) const; }; } // end namespace gdcm #include "gdcmUNExplicitDataElement.txx" #endif //GDCMUNEXPLICITDATAELEMENT_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmUNExplicitDataElement.txx000066400000000000000000000143011412732066400301760ustar00rootroot00000000000000/*========================================================================= 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 GDCMUNEXPLICITDATAELEMENT_TXX #define GDCMUNEXPLICITDATAELEMENT_TXX #include "gdcmSequenceOfItems.h" #include "gdcmSequenceOfFragments.h" #include "gdcmVL.h" #include "gdcmParseException.h" #include "gdcmValueIO.h" #include "gdcmSwapper.h" namespace gdcm { //----------------------------------------------------------------------------- template std::istream &UNExplicitDataElement::Read(std::istream &is) { ReadPreValue(is); return ReadValue(is); } template std::istream &UNExplicitDataElement::ReadPreValue(std::istream &is) { TagField.Read(is); // See PS 3.5, Data Element Structure With UNExplicit VR // Read Tag if( !is ) { if( !is.eof() ) // FIXME This should not be needed { assert(0 && "Should not happen" ); } return is; } if( TagField == Tag(0xfffe,0xe0dd) ) { ParseException pe; pe.SetLastElement( *this ); throw pe; } assert( TagField != Tag(0xfffe,0xe0dd) ); const Tag itemDelItem(0xfffe,0xe00d); if( TagField == itemDelItem ) { if( !ValueLengthField.Read(is) ) { assert(0 && "Should not happen"); return is; } if( ValueLengthField != 0 ) { gdcmDebugMacro( "Item Delimitation Item has a length different from 0" ); } // Set pointer to NULL to avoid user error ValueField = nullptr; VRField = VR::INVALID; return is; } // Read VR try { if( !VRField.Read(is) ) { assert(0 && "Should not happen" ); return is; } } catch( Exception &ex ) { #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // gdcm-MR-PHILIPS-16-Multi-Seq.dcm // assert( TagField == Tag(0xfffe, 0xe000) ); // -> For some reason VR is written as {44,0} well I guess this is a VR... // Technically there is a second bug, dcmtk assume other things when reading this tag, // so I need to change this tag too, if I ever want dcmtk to read this file. oh well // 0019004_Baseline_IMG1.dcm // -> VR is garbage also... // assert( TagField == Tag(8348,0339) || TagField == Tag(b5e8,0338)) //gdcmWarningMacro( "Assuming 16 bits VR for Tag=" << // TagField << " in order to read a buggy DICOM file." ); //VRField = VR::INVALID; (void)ex; ParseException pe; pe.SetLastElement( *this ); throw pe; #else throw ex; #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */ } if( VRField == VR::UN ) { // backtrack ... is.seekg(-2, std::ios::cur); } // Read Value Length if( VR::GetLength(VRField) == 4 && VRField != VR::UN ) { if( !ValueLengthField.Read(is) ) { assert(0 && "Should not happen"); return is; } } else { // 16bits only if( !ValueLengthField.template Read16(is) ) { assert(0 && "Should not happen"); return is; } } return is; } template std::istream &UNExplicitDataElement::ReadValue(std::istream &is, bool readvalues) { if( is.eof() ) return is; if( ValueLengthField == 0 ) { // Simple fast path ValueField = nullptr; return is; } //std::cerr << "exp cur tag=" << TagField << " VR=" << VRField << " VL=" << ValueLengthField << std::endl; // Read the Value //assert( ValueField == 0 ); if( VRField == VR::SQ ) { // Check whether or not this is an undefined length sequence assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new SequenceOfItems; } else if( ValueLengthField.IsUndefined() ) { if( VRField == VR::UN ) { // Support cp246 conforming file: // Enhanced_MR_Image_Storage_PixelSpacingNotIn_0028_0030.dcm (illegal) // vs // undefined_length_un_vr.dcm assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new SequenceOfItems; ValueField->SetLength(ValueLengthField); // perform realloc try { //if( !ValueIO::Read(is,*ValueField) ) // non cp246 if( !ValueIO::Read(is,*ValueField,readvalues) ) // cp246 compliant { assert(0); } } catch( std::exception &) { // Must be one of those non-cp246 file... // but for some reason seekg back to previous offset + Read // as UNExplicit does not work... throw Exception( "CP 246" ); } return is; } else { // Ok this is Pixel Data fragmented... assert( TagField == Tag(0x7fe0,0x0010) ); assert( VRField & VR::OB_OW ); ValueField = new SequenceOfFragments; } } else { //assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new ByteValue; } // We have the length we should be able to read the value ValueField->SetLength(ValueLengthField); // perform realloc if( TagField == Tag(0x2001,0xe05f) || TagField == Tag(0x2001,0xe100) || TagField == Tag(0x2005,0xe080) || TagField == Tag(0x2005,0xe083) || TagField == Tag(0x2005,0xe084) || TagField == Tag(0x2005,0xe402) //TagField.IsPrivate() && VRField == VR::SQ //-> Does not work for 0029 //we really need to read item marker ) { assert(0); // Could we possibly be so unlucky to have this mixture of bugs... } if( !ValueIO::Read(is,*ValueField,readvalues) ) { ParseException pe; pe.SetLastElement( *this ); throw pe; return is; } return is; } template std::istream &UNExplicitDataElement::ReadWithLength(std::istream &is, VL & length) { (void)length; return Read(is); } } // end namespace gdcm #endif // GDCMUNEXPLICITDATAELEMENT_TXX GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmUNExplicitImplicitDataElement.cxx000066400000000000000000000036041412732066400316540ustar00rootroot00000000000000/*========================================================================= 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 "gdcmUNExplicitImplicitDataElement.h" #include "gdcmSequenceOfItems.h" #include "gdcmSequenceOfFragments.h" namespace gdcm { //----------------------------------------------------------------------------- VL UNExplicitImplicitDataElement::GetLength() const { if( ValueLengthField.IsUndefined() ) { assert( ValueField->GetLength().IsUndefined() ); Value *p = ValueField; // If this is a SQ we need to compute it's proper length SequenceOfItems *sq = dynamic_cast(p); // TODO can factor the code: if( sq ) { return TagField.GetLength() + VRField.GetLength() + ValueLengthField.GetLength() + sq->ComputeLength(); } SequenceOfFragments *sf = dynamic_cast(p); if( sf ) { assert( VRField & (VR::OB | VR::OW) ); return TagField.GetLength() + VRField.GetLength() + ValueLengthField.GetLength() + sf->ComputeLength(); } assert(0); return 0; } else { // Each time VR::GetLength() is 2 then Value Length is coded in 2 // 4 then Value Length is coded in 4 assert( !ValueField || ValueField->GetLength() == ValueLengthField ); return TagField.GetLength() + 2*VRField.GetLength() + ValueLengthField; } } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmUNExplicitImplicitDataElement.h000066400000000000000000000034621412732066400313030ustar00rootroot00000000000000/*========================================================================= 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 GDCMUNEXPLICITIMPLICITDATAELEMENT_H #define GDCMUNEXPLICITIMPLICITDATAELEMENT_H #include "gdcmDataElement.h" namespace gdcm { // Data Element (ExplicitImplicit) /** * \brief Class to read/write a DataElement as ExplicitImplicit Data Element * \details This class gather two known bugs: * 1. GDCM 1.2.0 would rewrite VR=UN Value Length on 2 bytes instead of 4 bytes * 2. GDCM 1.2.0 would also rewrite DataElement as Implicit when the VR would not be known * this would only happen in some very rare cases. * gdcm 2.X design could handle bug #1 or #2 exclusively, this class can now handle * file which have both issues. * See: gdcmData/TheralysGDCM120Bug.dcm */ class GDCM_EXPORT UNExplicitImplicitDataElement : public DataElement { public: VL GetLength() const; template std::istream &Read(std::istream &is); template std::istream &ReadPreValue(std::istream &is); template std::istream &ReadValue(std::istream &is); // PURPOSELY do not provide an implementation for writing ! //template //const std::ostream &Write(std::ostream &os) const; }; } // end namespace gdcm #include "gdcmUNExplicitImplicitDataElement.txx" #endif //GDCMUNEXPLICITIMPLICITDATAELEMENT_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmUNExplicitImplicitDataElement.txx000066400000000000000000000041311412732066400316710ustar00rootroot00000000000000/*========================================================================= 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 GDCMUNEXPLICITIMPLICITDATAELEMENT_TXX #define GDCMUNEXPLICITIMPLICITDATAELEMENT_TXX #include "gdcmSequenceOfItems.h" #include "gdcmSequenceOfFragments.h" #include "gdcmVL.h" #include "gdcmUNExplicitDataElement.h" #include "gdcmImplicitDataElement.h" #include "gdcmValueIO.h" #include "gdcmSwapper.h" namespace gdcm { //----------------------------------------------------------------------------- template std::istream &UNExplicitImplicitDataElement::Read(std::istream &is) { ReadPreValue(is); return ReadValue(is); } template std::istream &UNExplicitImplicitDataElement::ReadPreValue(std::istream &is) { assert(0); //DataElement &de = *this;//unused de, fires a warning on macos //de.template ReadPreValue( is ); return is; } template std::istream &UNExplicitImplicitDataElement::ReadValue(std::istream &is) { if( is.eof() ) return is; DataElement &de = *this; try { //de.template ReadValue( is ); } catch(ParseException &ex) { de.SetVR( VR::INVALID ); // EXTREMELY IMPORTANT ! if( ex.GetLastElement().GetTag() == Tag(0xfffe,0xe0dd) ) { // We have never read the 2 bytes for the VR, since exception raised earlier is.seekg( -4, std::ios::cur ); } else { is.seekg( -6, std::ios::cur ); } //de.template ReadValue( is ); } return is; } } // end namespace gdcm #endif // GDCMUNEXPLICITIMPLICITDATAELEMENT_TXX GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmVL.h000066400000000000000000000063501412732066400240000ustar00rootroot00000000000000/*========================================================================= 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 GDCMVL_H #define GDCMVL_H #include "gdcmTypes.h" #include namespace gdcm { /** * \brief Value Length * \warning this is a 4bytes value ! Do not try to use it for 2bytes value * length */ class GDCM_EXPORT VL { public: typedef uint32_t Type; VL(uint32_t vl = 0) : ValueLength(vl) { } // FIXME: ugly static uint32_t GetVL32Max() { return 0xFFFFFFFF; } static uint16_t GetVL16Max() { return 0xFFFF; } bool IsUndefined() const { return ValueLength == 0xFFFFFFFF; } void SetToUndefined() { ValueLength = 0xFFFFFFFF; } /// Return whether or not the VL is odd or not. bool IsOdd() const { return !IsUndefined() && ValueLength % 2; } /// += operator VL& operator+=(VL const &vl) { ValueLength += vl.ValueLength; return *this; } VL& operator++() { ++ValueLength; return *this; } VL operator++(int) { uint32_t tmp(ValueLength); ++ValueLength; return tmp; } operator uint32_t () const { return ValueLength; } VL GetLength() const { // VL cannot know it's length...well in implicit yes... // TODO: need to check we cannot call this function from an Explicit element return 4; } friend std::ostream& operator<<(std::ostream& os, const VL& vl); // PURPOSELY not implemented (could not differentiate 16bits vs 32bits VL) //friend std::istream& operator>>(std::istream& is, VL& n); template std::istream &Read(std::istream &is) { is.read((char*)(&ValueLength), sizeof(uint32_t)); TSwap::SwapArray(&ValueLength,1); return is; } template std::istream &Read16(std::istream &is) { uint16_t copy; is.read((char*)(©), sizeof(uint16_t)); TSwap::SwapArray(©,1); ValueLength = copy; assert( ValueLength <= 65535 /*UINT16_MAX*/ ); // ?? doh ! return is; } template const std::ostream &Write(std::ostream &os) const { uint32_t copy = ValueLength; if( IsOdd() ) { ++copy; } TSwap::SwapArray(©,1); return os.write((char*)(©), sizeof(uint32_t)); } template const std::ostream &Write16(std::ostream &os) const { assert( ValueLength <= 65535 /*UINT16_MAX*/ ); uint16_t copy = (uint16_t)ValueLength; if( IsOdd() ) { ++copy; } TSwap::SwapArray(©,1); return os.write((char*)(©), sizeof(uint16_t)); } private: uint32_t ValueLength; }; //---------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& os, const VL& val) { os << /*std::hex <<*/ val.ValueLength; return os; } } // end namespace gdcm #endif //GDCMVL_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmVM.cxx000066400000000000000000000204401412732066400243500ustar00rootroot00000000000000/*========================================================================= 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 "gdcmVM.h" #include #include // abort #include // strcmp namespace gdcm { static const char *VMStrings[] = { "INVALID", "1", "2", "3", "4", "5", "6", "8", "9", "10", "12", "16", "18", "24", "28", "32", "35", "99", "256", "1-2", "1-3", "1-4", "1-5", "1-8", "1-32", "1-99", "1-n", "2-2n", "2-n", "3-4", "3-3n", "3-n", "4-4n", "6-6n", "7-7n", "30-30n", "47-47n", nullptr }; unsigned int VM::GetLength() const { unsigned int len; switch(VMField) { case VM::VM1: len = VMToLength::Length; break; case VM::VM2: len = VMToLength::Length; break; case VM::VM3: len = VMToLength::Length; break; case VM::VM4: len = VMToLength::Length; break; case VM::VM5: len = VMToLength::Length; break; case VM::VM6: len = VMToLength::Length; break; case VM::VM8: len = VMToLength::Length; break; case VM::VM9: len = VMToLength::Length; break; case VM::VM10: len = VMToLength::Length; break; case VM::VM12: len = VMToLength::Length; break; case VM::VM16: len = VMToLength::Length; break; case VM::VM18: len = VMToLength::Length; break; case VM::VM24: len = VMToLength::Length; break; case VM::VM28: len = VMToLength::Length; break; case VM::VM32: len = VMToLength::Length; break; case VM::VM35: len = VMToLength::Length; break; case VM::VM99: len = VMToLength::Length; break; case VM::VM256: len = VMToLength::Length; break; case VM::VM0: case VM::VM1_2: case VM::VM1_3: case VM::VM1_4: case VM::VM1_5: case VM::VM1_8: case VM::VM1_32: case VM::VM1_99: case VM::VM1_n: case VM::VM2_2n: case VM::VM2_n: case VM::VM3_4: case VM::VM3_3n: case VM::VM3_n: case VM::VM4_4n: case VM::VM6_6n: case VM::VM7_7n: return 0; default: len = 0; assert(0); } assert( len ); return len; } unsigned int VM::GetIndex(VMType vm) { assert( vm <= VM_END ); unsigned int l; switch(vm) { case VM0: l = 0; break; case VM1_2: l = 19; break; case VM1_3: l = 20; break; case VM1_4: l = 21; break; case VM1_5: l = 22; break; case VM1_8: l = 23; break; case VM1_32: l = 24; break; case VM1_99: l = 25; break; case VM1_n: l = 26; break; case VM2_2n: l = 27; break; case VM2_n: l = 28; break; case VM3_4: l = 29; break; case VM3_3n: l = 30; break; case VM3_n: l = 31; break; case VM4_4n: l = 32; break; case VM6_6n: l = 33; break; case VM7_7n: l = 34; break; case VM30_30n: l = 35; break; case VM47_47n: l = 36; break; case VM_END: l = 37; break; default: { unsigned int a = (unsigned int)vm; for (l = 0; a > 1; ++l) a >>= 1; l++; } } return l; } const char *VM::GetVMString(VMType vm) { unsigned int idx = GetIndex(vm); assert( idx < sizeof(VMStrings) / sizeof(VMStrings[0]) ); //assert( idx ); return VMStrings[idx]; } VM::VMType VM::GetVMType(const char *vm) { if(!vm) return VM::VM_END; if(!*vm) return VM::VM0; // ?? for (int i = 0; VMStrings[i] != nullptr; i++) { //if (strncmp(VMStrings[i],vm,strlen(VMStrings[i])) == 0) if (strcmp(VMStrings[i],vm) == 0) { return (VM::VMType)(i); } } return VM::VM_END; } // FIXME IsValid will only work for VM defined in public dict... bool VM::IsValid(int vm1, VMType vm2) { bool r = false; assert( vm1 >= 0 ); // Still need to check Part 3 // If you update the VMType, you need to update this code. Hopefully a compiler is // able to tell when a case is missing switch(vm2) { case VM1: r = vm1 == 1; break; case VM2: r = vm1 == 2; break; case VM3: r = vm1 == 3; break; case VM4: r = vm1 == 4; break; case VM5: r = vm1 == 5; break; case VM6: r = vm1 == 6; break; case VM8: r = vm1 == 8; break; case VM16: r = vm1 == 16; break; case VM24: r = vm1 == 24; break; case VM1_2: r = (vm1 == 1 || vm1 == 2); break; case VM1_3: r = (vm1 >= 1 && vm1 <= 3); break; case VM1_8: r = (vm1 >= 1 && vm1 <= 8); break; case VM1_32: r = (vm1 >= 1 && vm1 <= 32); break; case VM1_99: r = (vm1 >= 1 && vm1 <= 99); break; case VM1_n: r = (vm1 >= 1); break; case VM2_2n: r = (vm1 >= 2 && !(vm1%2) ); break; case VM2_n: r = (vm1 >= 2); break; case VM3_3n: r = (vm1 >= 3 && !(vm1%3) ); break; case VM3_n: r = (vm1 >= 3); break; default: assert(0); // should not happen } return r; } // TODO write some ugly macro to expand the template //int VM::GetLength() //{ //} // This function should not be used in production code. // Indeed this only return a 'guess' at the VM (ie. a lower bound) VM::VMType VM::GetVMTypeFromLength(size_t length, unsigned int size) { // Check first of length is a indeed a multiple of size and that length is != 0 if ( !length || length % size ) return VM::VM0; const unsigned int ratio = (unsigned int)(length / size); //std::cerr << "RATIO=" << ratio << std::endl; switch( ratio ) { case 1: return VM::VM1; case 2: return VM::VM2; case 3: return VM::VM3; case 4: return VM::VM4; case 5: return VM::VM5; case 6: return VM::VM6; case 8: return VM::VM8; case 9: return VM::VM9; case 16: return VM::VM16; case 24: return VM::VM24; case 32: return VM::VM32; default: return VM::VM1_n; } } size_t VM::GetNumberOfElementsFromArray(const char *array, size_t length) { size_t c=0; if( !length || !array ) return 0; const char *parray = array; const char *end = array + length; bool valuefound = false; for(; parray != end; ++parray) { if( *parray == ' ' ) { // space char do not count } else if( *parray == '\\' ) { if( valuefound ) { ++c; valuefound = false; // reset counter } } else { valuefound = true; } } if( valuefound ) ++c; return c; } bool VM::Compatible(VM const &vm) const { // make sure that vm is a numeric value //assert( vm.VMField <= VM256 ); if ( VMField == VM::VM0 ) return false; // nothing was found in the dict if ( vm == VM::VM0 ) return true; // the user was not able to compute the vm from the empty bytevalue // let's start with the easy case: if ( VMField == vm.VMField ) return true; bool r; switch(VMField) { case VM1_2: r = vm.VMField >= VM::VM1 && vm.VMField <= VM::VM2; break; case VM1_3: r = vm.VMField >= VM::VM1 && vm.VMField <= VM::VM3; break; case VM1_8: r = vm.VMField >= VM::VM1 && vm.VMField <= VM::VM8; break; case VM1_32: r = vm.VMField >= VM::VM1 && vm.VMField <= VM::VM32; break; case VM1_99: r = vm.VMField >= VM::VM1 && vm.VMField <= VM::VM99; break; case VM1_n: r = vm.VMField >= VM::VM1; break; case VM2_2n: { if( vm == VM1_n ) r = true; // FIXME else r = vm.VMField >= VM::VM2 && !(vm.GetLength() % 2); } break; case VM2_n: r = vm.VMField >= VM::VM2; break; case VM3_4: r = vm.VMField == VM::VM3 || vm.VMField == VM::VM4; break; case VM3_3n: r = vm.VMField >= VM::VM3 && !(vm.GetLength() % 3); break; case VM3_n: r = vm.VMField >= VM::VM3; break; default: r = VMField == vm.VMField; } if( r ) { assert( VMField & vm.VMField ); } return r; } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmVM.h000066400000000000000000000120101412732066400237670ustar00rootroot00000000000000/*========================================================================= 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 GDCMVM_H #define GDCMVM_H #include "gdcmTypes.h" #include namespace gdcm { /** * \brief Value Multiplicity * Looking at the DICOMV3 dict only there is very few cases: * 1 * 2 * 3 * 4 * 5 * 6 * 8 * 16 * 24 * 1-2 * 1-3 * 1-8 * 1-32 * 1-99 * 1-n * 2-2n * 2-n * 3-3n * 3-n * * Some private dict define some more: * 4-4n * 1-4 * 1-5 * 256 * 9 * 3-4 * * even more: * * 7-7n * 10 * 18 * 12 * 35 * 47_47n * 30_30n * 28 * * 6-6n */ class GDCM_EXPORT VM { public: typedef enum { VM0 = 0, // aka the invalid VM VM1 = 1, VM2 = 2, VM3 = 4, VM4 = 8, VM5 = 16, VM6 = 32, VM8 = 64, VM9 = 128, VM10 = 256, VM12 = 512, //1024, VM16 = 1024, //2048, VM18 = 2048, //4096, VM24 = 4096, //8192, VM28 = 8192, //16384, VM32 = 16384, //32768, VM35 = 32768, //65536, VM99 = 65536, //131072, VM256 = 131072, //262144, VM1_2 = VM1 | VM2, VM1_3 = VM1 | VM2 | VM3, VM1_4 = VM1 | VM2 | VM3 | VM4, VM1_5 = VM1 | VM2 | VM3 | VM4 | VM5, VM1_8 = VM1 | VM2 | VM3 | VM4 | VM5 | VM6 | VM8, // The following need some work: VM1_32 = VM1 | VM2 | VM3 | VM4 | VM5 | VM6 | VM8 | VM9 | VM16 | VM24 | VM32, VM1_99 = VM1 | VM2 | VM3 | VM4 | VM5 | VM6 | VM8 | VM9 | VM16 | VM24 | VM32 | VM99, VM1_n = VM1 | VM2 | VM3 | VM4 | VM5 | VM6 | VM8 | VM9 | VM16 | VM24 | VM32 | VM99 | VM256, VM2_2n = VM2 | VM4 | VM6 | VM8 | VM16 | VM24 | VM32 | VM256, VM2_n = VM2 | VM3 | VM4 | VM5 | VM6 | VM8 | VM9 | VM16 | VM24 | VM32 | VM99 | VM256, VM3_4 = VM3 | VM4, VM3_3n = VM3 | VM6 | VM9 | VM24 | VM99 | VM256, VM3_n = VM3 | VM4 | VM5 | VM6 | VM8 | VM9 | VM16 | VM24 | VM32 | VM99 | VM256, VM4_4n = VM4 | VM16 | VM24 | VM32 | VM256, VM6_6n = VM6 | VM12 | VM18 | VM24 , VM6_n = VM6 | VM8 | VM9 | VM16 | VM24 | VM32 | VM99 | VM256, VM7_7n, VM30_30n, VM47_47n, VM_END = VM1_n + 1 // Custom tag to count number of entry } VMType; /// Return the string as written in the official DICOM dict from /// a custom enum type static const char* GetVMString(VMType vm); static VMType GetVMType(const char *vm); /// Check if vm1 is valid compare to vm2, i.e vm1 is element of vm2 /// vm1 is typically deduce from counting in a ValueField static bool IsValid(int vm1, VMType vm2); //bool IsValid() { return VMField != VM0 && VMField < VM_END; } /// WARNING: Implementation deficiency /// The Compatible function is poorly implemented, the reference vm should be coming from /// the dictionary, while the passed in value is the value guess from the file. bool Compatible(VM const &vm) const; /// static VMType GetVMTypeFromLength(size_t length, unsigned int size); static size_t GetNumberOfElementsFromArray(const char *array, size_t length); VM(VMType type = VM0):VMField(type) {} operator VMType () const { return VMField; } unsigned int GetLength() const; friend std::ostream &operator<<(std::ostream &os, const VM &vm); protected: static unsigned int GetIndex(VMType vm); private: VMType VMField; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& _os, const VM &_val) { assert( VM::GetVMString(_val) ); _os << VM::GetVMString(_val); return _os; } //template struct LengthToVM; //template <> struct LengthToVM<1> //{ enum { TVM = VM::VM1 }; }; template struct VMToLength; #define TYPETOLENGTH(type,length) \ template<> struct VMToLength \ { enum { Length = length }; }; // TODO: Could be generated from XML file //TYPETOLENGTH(VM0,1) TYPETOLENGTH(VM1,1) TYPETOLENGTH(VM2,2) TYPETOLENGTH(VM3,3) TYPETOLENGTH(VM4,4) TYPETOLENGTH(VM5,5) TYPETOLENGTH(VM6,6) TYPETOLENGTH(VM8,8) TYPETOLENGTH(VM9,9) TYPETOLENGTH(VM10,10) TYPETOLENGTH(VM12,12) TYPETOLENGTH(VM16,16) TYPETOLENGTH(VM18,18) TYPETOLENGTH(VM24,24) TYPETOLENGTH(VM28,28) TYPETOLENGTH(VM32,32) TYPETOLENGTH(VM35,35) TYPETOLENGTH(VM99,99) TYPETOLENGTH(VM256,256) //TYPETOLENGTH(VM1_2,2) //TYPETOLENGTH(VM1_3,3) //TYPETOLENGTH(VM1_8,8) //TYPETOLENGTH(VM1_32,32) //TYPETOLENGTH(VM1_99,99) //TYPETOLENGTH(VM1_n, //TYPETOLENGTH(VM2_2n, //TYPETOLENGTH(VM2_n, //TYPETOLENGTH(VM3_3n, //TYPETOLENGTH(VM3_n, } // end namespace gdcm #endif //GDCMVM_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmVR.cxx000066400000000000000000000315761412732066400243710ustar00rootroot00000000000000/*========================================================================= 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 "gdcmVR.h" #include // for std::lower_bound #include #include namespace gdcm { static const char *VRStrings[] = { "??", // 0 "AE", // 1 "AS", // 2 "AT", // 3 "CS", // 4 "DA", // 5 "DS", // 6 "DT", // 7 "FD", // 8 "FL", // 9 "IS", // 10 "LO", // 11 "LT", // 12 "OB", // 13 "OF", // 14 "OW", // 15 "PN", // 16 "SH", // 17 "SL", // 18 "SQ", // 19 "SS", // 20 "ST", // 21 "TM", // 22 "UI", // 23 "UL", // 24 "UN", // 25 "US", // 26 "UT", // 27 "OD", // 28 "OL", // 29 "UC", // 30 "UR", // 31 "OV", // 32 "SV", // 33 "UV", // 34 "OB or OW", // 35 "US or SS", // 36 "US or SS or OW", //37 "US or OW", //38 nullptr }; static VR::VRType VRValue[] = { VR::INVALID , VR::AE , VR::AS , VR::AT , VR::CS , VR::DA , VR::DS , VR::DT , VR::FD , VR::FL , VR::IS , VR::LO , VR::LT , VR::OB , VR::OF , VR::OW , VR::PN , VR::SH , VR::SL , VR::SQ , VR::SS , VR::ST , VR::TM , VR::UI , VR::UL , VR::UN , VR::US , VR::UT , VR::OD , VR::OL , VR::UC , VR::UR , VR::OV , VR::SV , VR::UV , }; bool VR::IsVRFile() const { switch(VRField) { case VR::INVALID: case VR::AE: case VR::AS: case VR::AT: case VR::CS: case VR::DA: case VR::DS: case VR::DT: case VR::FD: case VR::FL: case VR::IS: case VR::LO: case VR::LT: case VR::OB: case VR::OD: case VR::OF: case VR::OL: case VR::OV: case VR::OW: case VR::PN: case VR::SH: case VR::SL: case VR::SQ: case VR::SS: case VR::ST: case VR::SV: case VR::TM: case VR::UC: case VR::UI: case VR::UL: case VR::UN: case VR::UR: case VR::US: case VR::UT: case VR::UV: return true; default: return false; } } unsigned int VR::GetSizeof() const { unsigned int size; // Question: Should I move all ASCII type VR down to the bottom ? switch(VRField) { case VR::AE: size = sizeof(VRToType::Type); break; case VR::AS: size = sizeof(VRToType::Type); break; case VR::AT: size = sizeof(VRToType::Type); break; case VR::CS: size = sizeof(VRToType::Type); break; case VR::DA: size = sizeof(VRToType::Type); break; case VR::DS: size = sizeof(VRToType::Type); break; case VR::DT: size = sizeof(VRToType::Type); break; case VR::FD: size = sizeof(VRToType::Type); break; case VR::FL: size = sizeof(VRToType::Type); break; case VR::IS: size = sizeof(VRToType::Type); break; case VR::LO: size = sizeof(VRToType::Type); break; case VR::LT: size = sizeof(VRToType::Type); break; case VR::OB: size = sizeof(VRToType::Type); break; case VR::OD: size = sizeof(VRToType::Type); break; case VR::OF: size = sizeof(VRToType::Type); break; case VR::OL: size = sizeof(VRToType::Type); break; case VR::OV: size = sizeof(VRToType::Type); break; case VR::OW: size = sizeof(VRToType::Type); break; case VR::PN: size = sizeof(VRToType::Type); break; case VR::SH: size = sizeof(VRToType::Type); break; case VR::SL: size = sizeof(VRToType::Type); break; case VR::SQ: size = sizeof(VRToType::Type); break; case VR::SS: size = sizeof(VRToType::Type); break; case VR::ST: size = sizeof(VRToType::Type); break; case VR::SV: size = sizeof(VRToType::Type); break; case VR::TM: size = sizeof(VRToType::Type); break; case VR::UC: size = sizeof(VRToType::Type); break; case VR::UI: size = sizeof(VRToType::Type); break; case VR::UL: size = sizeof(VRToType::Type); break; case VR::UN: size = sizeof(VRToType::Type); break; case VR::UR: size = sizeof(VRToType::Type); break; case VR::US: size = sizeof(VRToType::Type); break; case VR::UT: size = sizeof(VRToType::Type); break; case VR::UV: size = sizeof(VRToType::Type); break; case VR::US_SS: size = sizeof(VRToType::Type); // why not ? break; default: size = 0; } assert( size ); return size; } unsigned int VR::GetIndex(VRType vr) { if( vr == VR::VL32 ) return 0; unsigned int l = 0; assert( vr <= VR_END ); switch(vr) { case INVALID: break; case OB_OW: l = 35; break; case US_SS: l = 36; break; case US_SS_OW: l = 37; break; case US_OW: l = 38; break; case VR_END: l = 39; break; default: { long long a = (long long)vr; for (; a > 1; ++l) a >>= 1LL; l++; } break; } return l; } const char *VR::GetVRString(VRType vr) { const unsigned int idx = GetIndex(vr); return VRStrings[idx]; } const char *VR::GetVRStringFromFile(VRType vr) { #if 1 static const int N = sizeof(VRValue) / sizeof(VRType); assert( N == 35 ); static VRType *start = VRValue; static VRType *end = VRValue+N; const VRType *p = std::lower_bound(start, end, vr); assert( *p == vr ); assert( (p - start) == (long long)GetIndex(vr) ); return VRStrings[p-start]; #else const unsigned int idx = GetIndex(vr); return VRStrings[idx]; #endif } class MySort { public: bool operator() (const char *a, const char *b) { if( a[0] == b[0] ) return a[1] < b[1]; return a[0] < b[0]; } }; // Optimized version for transforming a read VR from DICOM file // into a VRType (does not support OB_OW for instance) VR::VRType VR::GetVRTypeFromFile(const char *vr) { /* * You need to compile with -DNDEBUG * Running TestReader on gdcmData, leads to 2.2% improvement */ #if 0 static const int N = sizeof(VRValue) / sizeof(VRType); assert( N == 35 ); static const char **start = VRStrings+1; static const char **end = VRStrings+N; //std::cerr << "VR=" << vr << std::endl; const char **p = std::lower_bound(start, end, vr, MySort()); if( (*p)[0] != vr[0] || (*p)[1] != vr[1] ) { // https://groups.google.com/d/msg/comp.protocols.dicom/0ata_3lpjF4/xlkjOKRGBwAJ // http://dicom.nema.org/medical/dicom/current/output/chtml/part05/chapter_E.html if( vr[0] >= ' ' && vr[0] <= '~' && vr[1] >= ' ' && vr[1] <= '~' ) // FIXME Control Char LF/FF/CR TAB and ESC should be accepted { // newly added VR ? // we are not capable of preserving the original VR. this is accepted behavior return VR::UN; } return VR::INVALID; } assert( (*p)[0] == vr[0] && (*p)[1] == vr[1] ); VRType r = VRValue[p-start+1]; assert( r == (VR::VRType)(1 << (p-start)) ); #else // old version not optimized VRType r = VR::VR_END; for (int i = 1; VRStrings[i] != nullptr; i++) { const char *ref = VRStrings[i]; // Use lazy evaluation instead of strncmp if (ref[0] == vr[0] && ref[1] == vr[1] ) { r = (VR::VRType)(1LL << (i-1)); break; } } if( r == VR::VR_END ) { // https://groups.google.com/d/msg/comp.protocols.dicom/0ata_3lpjF4/xlkjOKRGBwAJ // http://dicom.nema.org/medical/dicom/current/output/chtml/part05/chapter_E.html if( vr[0] >= ' ' && vr[0] <= '~' && vr[1] >= ' ' && vr[1] <= '~' ) // FIXME Control Char LF/FF/CR TAB and ESC should be accepted { // newly added VR ? // we are not capable of preserving the original VR. this is accepted behavior return VR::UN; } return VR::INVALID; } #endif // postcondition assert( r != VR::INVALID && r != VR::OB_OW && r != VR::US_SS && r != VR::US_SS_OW && r != VR::US_OW && r != VR::VR_END ); return r; } VR::VRType VR::GetVRType(const char *vr) { VRType r = VR::VR_END; if(!vr) return r; for (int i = 0; VRStrings[i] != nullptr; i++) //if (strncmp(VRStrings[i],vr, strlen(VRStrings[i])) == 0) if (strcmp(VRStrings[i],vr) == 0) { switch(i) { case 0: r = INVALID; break; case 35: r = OB_OW; break; case 36: r = US_SS; break; case 37: r = US_SS_OW; break; case 38: r = US_OW; break; case 39: r = VR_END; assert(0); break; default: assert( vr[2] == 0 ); r = (VR::VRType)(1LL << (i-1)); } break; // found one value, we can exit the for loop } return r; } bool VR::IsValid(const char *vr) { for (int i = 1; VRStrings[i] != nullptr; i++) { const char *ref = VRStrings[i]; // Use lazy evaluation instead of strncmp if (ref[0] == vr[0] && ref[1] == vr[1] ) { assert( i < 35 ); // FIXME return true; } } return false; } bool VR::IsValid(const char *vr1, VRType vr2) { assert( strlen(vr1) == 2 ); VR::VRType vr = GetVRType(vr1); return ((vr & vr2) != 0 ? true : false); } bool VR::IsSwap(const char *vr) { assert( vr[2] == '\0' ); char vr_swap[3]; vr_swap[0] = vr[1]; vr_swap[1] = vr[0]; vr_swap[2] = '\0'; assert( GetVRType(vr_swap) != SS ); return GetVRType(vr_swap) != VR_END; } #define VRTemplateCase(type, rep) \ case VR::type: \ return (VR::VRType)VRToEncoding::Mode \ == VR::rep; #define VRTemplate(rep) \ VRTemplateCase(AE,rep) \ VRTemplateCase(AS,rep) \ VRTemplateCase(AT,rep) \ VRTemplateCase(CS,rep) \ VRTemplateCase(DA,rep) \ VRTemplateCase(DS,rep) \ VRTemplateCase(DT,rep) \ VRTemplateCase(FD,rep) \ VRTemplateCase(FL,rep) \ VRTemplateCase(IS,rep) \ VRTemplateCase(LO,rep) \ VRTemplateCase(LT,rep) \ VRTemplateCase(OB,rep) \ VRTemplateCase(OD,rep) \ VRTemplateCase(OF,rep) \ VRTemplateCase(OL,rep) \ VRTemplateCase(OV,rep) \ VRTemplateCase(OW,rep) \ VRTemplateCase(PN,rep) \ VRTemplateCase(SH,rep) \ VRTemplateCase(SL,rep) \ VRTemplateCase(SQ,rep) \ VRTemplateCase(SS,rep) \ VRTemplateCase(ST,rep) \ VRTemplateCase(SV,rep) \ VRTemplateCase(TM,rep) \ VRTemplateCase(UC,rep) \ VRTemplateCase(UI,rep) \ VRTemplateCase(UL,rep) \ VRTemplateCase(UN,rep) \ VRTemplateCase(UR,rep) \ VRTemplateCase(US,rep) \ VRTemplateCase(UT,rep) \ VRTemplateCase(UV,rep) bool VR::IsASCII(VRType vr) { //assert( vr != VR::INVALID ); switch(vr) { VRTemplate(VRASCII) default: // 1.3.12.2.1107.5.1.4.54035.30000005100516290423400005768-no-phi.dcm has a VR=RT //assert(0); return false; } } bool VR::IsASCII2(VRType vr) { assert( vr != VR::INVALID ); return vr == AE || vr == AS || vr == CS || vr == DA || vr == DS || vr == DT || vr == IS || vr == LO || vr == LT || vr == PN || vr == SH || vr == ST || vr == TM || vr == UI; } bool VR::IsBinary(VRType vr) { //assert( vr != VR::INVALID ); switch(vr) { VRTemplate(VRBINARY) // TODO FIXME FIXME: case US_SS_OW: return true; case US_SS: return true; case OB_OW: return true; default: // 1.3.12.2.1107.5.1.4.54035.30000005100516290423400005768-no-phi.dcm has a VR=RT //assert(0); return false; } } bool VR::IsBinary2(VRType vr) { //assert( vr != OF ); return vr == OB || vr == OW || vr == OB_OW || vr == UN || vr == SQ ; } bool VR::CanDisplay(VRType vr) { return vr == AE || vr == AS || vr == AT || vr == CS || vr == DA || vr == DS || vr == FL || vr == FD || vr == IS || vr == LO || vr == LT || vr == PN || vr == SH || vr == SL || vr == SS || vr == ST || vr == TM || vr == UI || vr == UL || vr == US || vr == UT; } bool VR::Compatible(VR const &vr) const { //if( VRField == VR::INVALID && vr.VRField == VR::INVALID ) return true; if( vr.VRField == VR::INVALID ) return true; else if( vr.VRField == VR::UN ) return true; else return ((VRField & vr.VRField) > 0 ? true : false); } bool VR::IsDual() const { switch(VRField) { case OB_OW : case US_SS : case US_SS_OW : case US_OW : return true; default: return false; } } } // end of namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmVR.h000066400000000000000000000255161412732066400240130ustar00rootroot00000000000000/*========================================================================= 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 GDCMVR_H #define GDCMVR_H #include "gdcmTag.h" #include "gdcmTrace.h" #include "gdcmString.h" #include #include #include //these defines are here to ensure compilation on sunos gcc #if defined (CS) # undef CS #endif #if defined (DS) # undef DS #endif #if defined (SS) # undef SS #endif namespace gdcm { /** * \brief VR class * \details This is adapted from DICOM standard * The biggest difference is the INVALID VR * and the composite one that differ from standard (more like an addition) * This allow us to represent all the possible case express in the DICOMV3 dict * \note * VALUE REPRESENTATION (VR) * Specifies the data type and format of the Value(s) contained in the * Value Field of a Data Element. * VALUE REPRESENTATION FIELD: * The field where the Value Representation of a Data Element is * stored in the encoding of a Data Element structure with explicit VR. */ class GDCM_EXPORT VR { public: enum VRType : long long { // Warning: Do not write if ( vr & VR::INVALID ) but if ( vr == VR::INVALID ) INVALID = 0, // For Item/(Seq) Item Delimitation Item AE = 1, AS = 2, AT = 4, CS = 8, DA = 16, DS = 32, DT = 64, FD = 128, FL = 256, IS = 512, LO = 1024, LT = 2048, OB = 4096, OD = 134217728, // 2^27 OF = 8192, OL = 268435456, // 2^28 OV = 2147483648, // 2^31 OW = 16384, PN = 32768, SH = 65536, SL = 131072, SQ = 262144, SS = 524288, ST = 1048576, SV = 4294967296, // 2^32 TM = 2097152, UC = 536870912, // 2^29 UI = 4194304, UL = 8388608, UN = 16777216, UR = 1073741824, // 2^30 US = 33554432, UT = 67108864, UV = 8589934592, // 2^33 OB_OW = OB | OW, US_SS = US | SS, US_SS_OW = US | SS | OW, US_OW = US | OW, // The following do not have a VRString equivalent (ie cannot be found in PS 3.6) VL16 = AE | AS | AT | CS | DA | DS | DT | FD | FL | IS | LO | LT | PN | SH | SL | SS | ST | TM | UI | UL | US, // if( VR & VL16 ) => VR has its VL coded over 16bits VL32 = OB | OW | OD | OF | OL | OV | SQ | SV | UC | UN | UR | UT | UV, // if( VR & VL32 ) => VR has its VL coded over 32bits VRASCII = AE | AS | CS | DA | DS | DT | IS | LO | LT | PN | SH | ST | TM | UC | UI | UR | UT, VRBINARY = AT | FL | FD | OB | OD | OF | OL | OV | OW | SL | SQ | SS | SV | UL | UN | US | UV, // FIXME: UN ? // PS 3.5: // Data Elements with a VR of SQ, OD, OF, OL, OW, OB or UN shall always have a Value Multiplicity of one. // GDCM is adding a couple more: AS, LT, ST, UT VR_VM1 = AS | LT | ST | UT | SQ | OF | OL | OV | OD | OW | OB | UN, // All those VR have a VM1 VRALL = VRASCII | VRBINARY, VR_END = UV+1 // Invalid VR, need to be max(VRType)+1 }; static const char *GetVRString(VRType vr); // This function will only look at the very first two chars nothing else static VRType GetVRTypeFromFile(const char *vr); // You need to make sure end of string is \0 static VRType GetVRType(const char *vr); static const char *GetVRStringFromFile(VRType vr); static bool IsValid(const char *vr); // Check if vr1 is valid against vr2, // Typically vr1 is read from the file and vr2 is taken from the dict static bool IsValid(const char *vr1, VRType vr2); //static bool IsValid(const VRType &vr1, const VRType &vr2); // Find out if the string read is byte swapped static bool IsSwap(const char *vr); // Size read on disk // FIXME: int ? int GetLength() const { return VR::GetLength(VRField); } unsigned int GetSizeof() const; static uint32_t GetLength(VRType vr) { //if( vr == VR::INVALID ) return 4; if( vr & VL32 ) { return 4; } else return 2; } // Some use of template metaprograming with ugly macro static bool IsBinary(VRType vr); static bool IsASCII(VRType vr); // TODO: REMOVE ME static bool CanDisplay(VRType vr); // TODO: REMOVE ME static bool IsBinary2(VRType vr); // TODO: REMOVE ME static bool IsASCII2(VRType vr); VR(VRType vr = INVALID):VRField(vr) { } //VR(VR const &vr):VRField(vr.VRField) { } std::istream &Read(std::istream &is) { char vr[2]; is.read(vr, 2); VRField = GetVRTypeFromFile(vr); assert( VRField != VR::VR_END ); if( VRField == VR::INVALID ) { // \0\2 Data/TheralysGDCM120Bug.dcm // \0\0 Data/MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm // \0\4 Data/BugGDCM2_UndefItemWrongVL.dcm // \44\0 Data/gdcm-MR-PHILIPS-16-Multi-Seq.dcm // \0\20 Data/ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm // \0\3 Data/DMCPACS_ExplicitImplicit_BogusIOP.dcm // \0\4 Data/THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm // \0\4 Data/PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm // \0\4 Data/GE_DLX-8-MONO2-PrivateSyntax.dcm throw Exception( "INVALID VR" ); } if( VRField & VL32 ) { #if 0 // For some reason this seems slower on my linux box... is.seekg(2, std::ios::cur ); #else char dum[2]; is.read(dum, 2); if( !(dum[0] == 0 && dum[1] == 0 )) { // JDDICOM_Sample4.dcm gdcmDebugMacro( "32bits VR contains non zero bytes. Skipped" ); } #endif } return is; } const std::ostream &Write(std::ostream &os) const { VRType vrfield = VRField; gdcmAssertAlwaysMacro( !IsDual() ); if( vrfield == VR::INVALID ) { //vrfield = VR::UN; } const char *vr = GetVRString(vrfield); //assert( strlen( vr ) == 2 ); assert( vr[0] && vr[1] && vr[2] == 0 ); os.write(vr, 2); // See PS 3.5, Data Element Structure With Explicit VR if( vrfield & VL32 ) { const char dum[2] = {0, 0}; os.write(dum,2); } return os; } friend std::ostream &operator<<(std::ostream &os, const VR &vr); operator VRType () const { return VRField; } unsigned int GetSize() const; bool Compatible(VR const &vr) const; bool IsVRFile() const; bool IsDual() const; private: // Internal function that map a VRType to an index in the VRStrings table static unsigned int GetIndex(VRType vr); VRType VRField; }; //----------------------------------------------------------------------------- inline std::ostream &operator<<(std::ostream &_os, const VR &val) { //_os << VR::GetVRStringFromFile(val.VRField); _os << VR::GetVRString(val.VRField); return _os; } // Apparently SWIG is not happy with something, somewhere below... #ifndef SWIG // Tells whether VR Type is ASCII or Binary template struct VRToEncoding; // Convert from VR Type to real underlying type template struct VRToType; #define TYPETOENCODING(type,rep, rtype) \ template<> struct VRToEncoding \ { enum:long long { Mode = VR::rep }; }; \ template<> struct VRToType \ { typedef rtype Type; }; // Do not use me struct UI { char Internal[64+1]; friend std::ostream& operator<<(std::ostream &_os, const UI &_val); }; inline std::ostream& operator<<(std::ostream &_os, const UI &_val) { _os << _val.Internal; return _os; } typedef String<'\\',16> AEComp; typedef String<'\\',64> ASComp; typedef String<'\\',16> CSComp; typedef String<'\\',64> DAComp; typedef String<'\\',64> DTComp; typedef String<'\\',64> LOComp; typedef String<'\\',64> LTComp; typedef String<'\\',64> PNComp; typedef String<'\\',64> SHComp; typedef String<'\\',64> STComp; typedef String<'\\',4294967294> UCComp; typedef String<'\\',4294967294> URComp; typedef String<'\\',16> TMComp; typedef String<'\\',64,0> UIComp; typedef String<'\\',64> UTComp; // TODO: Could be generated from XML file TYPETOENCODING(AE,VRASCII ,AEComp) TYPETOENCODING(AS,VRASCII ,ASComp) TYPETOENCODING(AT,VRBINARY,Tag) TYPETOENCODING(CS,VRASCII ,CSComp) TYPETOENCODING(DA,VRASCII ,DAComp) TYPETOENCODING(DS,VRASCII ,double) TYPETOENCODING(DT,VRASCII ,DTComp) TYPETOENCODING(FL,VRBINARY,float) TYPETOENCODING(FD,VRBINARY,double) TYPETOENCODING(IS,VRASCII ,int32_t) TYPETOENCODING(LO,VRASCII ,LOComp) TYPETOENCODING(LT,VRASCII ,LTComp) TYPETOENCODING(OB,VRBINARY,uint8_t) TYPETOENCODING(OD,VRBINARY,double) TYPETOENCODING(OF,VRBINARY,float) TYPETOENCODING(OL,VRBINARY,uint32_t) TYPETOENCODING(OV,VRBINARY,uint64_t) TYPETOENCODING(OW,VRBINARY,uint16_t) TYPETOENCODING(PN,VRASCII ,PNComp) TYPETOENCODING(SH,VRASCII ,SHComp) TYPETOENCODING(SL,VRBINARY,int32_t) TYPETOENCODING(SQ,VRBINARY,unsigned char) // FIXME TYPETOENCODING(SS,VRBINARY,int16_t) TYPETOENCODING(ST,VRASCII ,STComp) TYPETOENCODING(SV,VRBINARY,int64_t) TYPETOENCODING(TM,VRASCII ,TMComp) TYPETOENCODING(UC,VRASCII ,UCComp) TYPETOENCODING(UI,VRASCII ,UIComp) TYPETOENCODING(UL,VRBINARY,uint32_t) TYPETOENCODING(UN,VRBINARY,uint8_t) // FIXME ? TYPETOENCODING(UR,VRASCII,URComp) TYPETOENCODING(US,VRBINARY,uint16_t) TYPETOENCODING(UT,VRASCII ,UTComp) TYPETOENCODING(UV,VRBINARY,uint64_t) #define VRTypeTemplateCase(type) \ case VR::type: \ return sizeof ( VRToType::Type ); inline unsigned int VR::GetSize() const { switch(VRField) { VRTypeTemplateCase(AE) VRTypeTemplateCase(AS) VRTypeTemplateCase(AT) VRTypeTemplateCase(CS) VRTypeTemplateCase(DA) VRTypeTemplateCase(DS) VRTypeTemplateCase(DT) VRTypeTemplateCase(FL) VRTypeTemplateCase(FD) VRTypeTemplateCase(IS) VRTypeTemplateCase(LO) VRTypeTemplateCase(LT) VRTypeTemplateCase(OB) VRTypeTemplateCase(OD) VRTypeTemplateCase(OF) VRTypeTemplateCase(OL) VRTypeTemplateCase(OV) VRTypeTemplateCase(OW) VRTypeTemplateCase(PN) VRTypeTemplateCase(SH) VRTypeTemplateCase(SL) VRTypeTemplateCase(SQ) VRTypeTemplateCase(SS) VRTypeTemplateCase(ST) VRTypeTemplateCase(SV) VRTypeTemplateCase(TM) VRTypeTemplateCase(UC) VRTypeTemplateCase(UI) VRTypeTemplateCase(UL) VRTypeTemplateCase(UN) VRTypeTemplateCase(UR) VRTypeTemplateCase(US) VRTypeTemplateCase(UT) VRTypeTemplateCase(UV) case VR::US_SS: return 2; case VR::INVALID: case VR::OB_OW: case VR::US_SS_OW: case VR::US_OW: case VR::VL16: case VR::VL32: case VR::VRASCII: case VR::VRBINARY: case VR::VR_VM1: case VR::VRALL: case VR::VR_END: default: assert( 0 && "should not" ); } return 0; } #endif // SWIG } // end namespace gdcm #endif //GDCMVR_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmVR16ExplicitDataElement.cxx000066400000000000000000000035621412732066400303400ustar00rootroot00000000000000/*========================================================================= 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 "gdcmVR16ExplicitDataElement.h" #include "gdcmSequenceOfItems.h" #include "gdcmSequenceOfFragments.h" namespace gdcm { //----------------------------------------------------------------------------- VL VR16ExplicitDataElement::GetLength() const { if( ValueLengthField.IsUndefined() ) { assert( ValueField->GetLength().IsUndefined() ); Value *p = ValueField; // If this is a SQ we need to compute it's proper length SequenceOfItems *sq = dynamic_cast(p); // TODO can factor the code: if( sq ) { return TagField.GetLength() + VRField.GetLength() + ValueLengthField.GetLength() + sq->ComputeLength(); } SequenceOfFragments *sf = dynamic_cast(p); if( sf ) { assert( VRField & (VR::OB | VR::OW) ); return TagField.GetLength() + VRField.GetLength() + ValueLengthField.GetLength() + sf->ComputeLength(); } assert(0); return 0; } else { // Each time VR::GetLength() is 2 then Value Length is coded in 2 // 4 then Value Length is coded in 4 assert( !ValueField || ValueField->GetLength() == ValueLengthField ); return TagField.GetLength() + 2*VRField.GetLength() + ValueLengthField; } } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmVR16ExplicitDataElement.h000066400000000000000000000031061412732066400277570ustar00rootroot00000000000000/*========================================================================= 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 GDCMVR16EXPLICITDATAELEMENT_H #define GDCMVR16EXPLICITDATAELEMENT_H #include "gdcmDataElement.h" namespace gdcm { // Data Element (Explicit) /** * \brief Class to read/write a DataElement as Explicit Data Element * \note This class support 16 bits when finding an unknown VR: * For instance: * Siemens_CT_Sensation64_has_VR_RT.dcm */ class GDCM_EXPORT VR16ExplicitDataElement : public DataElement { public: VL GetLength() const; template std::istream &Read(std::istream &is); template std::istream &ReadPreValue(std::istream &is); template std::istream &ReadValue(std::istream &is, bool readvalues = true); template std::istream &ReadWithLength(std::istream &is, VL & length); // PURPOSELY do not provide an implementation for writing ! //template //const std::ostream &Write(std::ostream &os) const; }; } // end namespace gdcm #include "gdcmVR16ExplicitDataElement.txx" #endif //GDCMVR16EXPLICITDATAELEMENT_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmVR16ExplicitDataElement.txx000066400000000000000000000215461412732066400303630ustar00rootroot00000000000000/*========================================================================= 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 GDCMVR16EXPLICITDATAELEMENT_TXX #define GDCMVR16EXPLICITDATAELEMENT_TXX #include "gdcmSequenceOfItems.h" #include "gdcmSequenceOfFragments.h" #include "gdcmVL.h" #include "gdcmParseException.h" #include "gdcmImplicitDataElement.h" #include "gdcmValueIO.h" #include "gdcmSwapper.h" namespace gdcm { //----------------------------------------------------------------------------- template std::istream &VR16ExplicitDataElement::Read(std::istream &is) { ReadPreValue(is); return ReadValue(is); } template std::istream &VR16ExplicitDataElement::ReadPreValue(std::istream &is) { TagField.Read(is); // See PS 3.5, Data Element Structure With Explicit VR // Read Tag if( !is ) { if( !is.eof() ) // FIXME This should not be needed { assert(0 && "Should not happen" ); } return is; } assert( TagField != Tag(0xfffe,0xe0dd) ); //assert( TagField != Tag(0xfeff,0xdde0) ); const Tag itemDelItem(0xfffe,0xe00d); const Tag itemStartItem(0xfffe,0x0000); assert( TagField != itemStartItem ); if( TagField == itemDelItem ) { if( !ValueLengthField.Read(is) ) { assert(0 && "Should not happen"); return is; } if( ValueLengthField ) { gdcmWarningMacro( "Item Delimitation Item has a length different from 0 and is: " << ValueLengthField ); } // Set pointer to NULL to avoid user error ValueField = nullptr; return is; } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( TagField == Tag(0x00ff, 0x4aa5) ) { assert(0 && "Should not happen" ); // char c; // is.read(&c, 1); // std::cerr << "Debug: " << c << std::endl; } #endif // Read VR // FIXME // Special hack for KONICA_VROX.dcm where in fact the VR=OX, in Pixel Data element // in which case we need to assume a 32bits VR...for now this is a big phat hack ! bool OX_hack = false; try { if( !VRField.Read(is) ) { assert(0 && "Should not happen" ); return is; } } catch( Exception & ) { VRField = VR::INVALID; // gdcm-MR-PHILIPS-16-Multi-Seq.dcm if( TagField == Tag(0xfffe, 0xe000) ) { gdcmWarningMacro( "Found item delimiter in item" ); ParseException pe; pe.SetLastElement( *this ); throw pe; } // -> For some reason VR is written as {44,0} well I guess this is a VR... // Technically there is a second bug, dcmtk assume other things when reading this tag, // so I need to change this tag too, if I ever want dcmtk to read this file. oh well // 0019004_Baseline_IMG1.dcm // -> VR is garbage also... // assert( TagField == Tag(8348,0339) || TagField == Tag(b5e8,0338)) if( TagField == Tag(0x7fe0,0x0010) ) { OX_hack = true; VRField = VR::UN; // make it a fake 32bits for now... char dummy[2]; is.read(dummy,2); assert( dummy[0] == 0 && dummy[1] == 0 ); gdcmWarningMacro( "Assuming 32 bits VR for Tag=" << TagField << " in order to read a buggy DICOM file." ); } else { gdcmWarningMacro( "Assuming 16 bits VR for Tag=" << TagField << " in order to read a buggy DICOM file." ); } } // Read Value Length if( VR::GetLength(VRField) == 4 ) { if( !ValueLengthField.Read(is) ) { assert(0 && "Should not happen"); return is; } if( OX_hack ) { VRField = VR::INVALID; // revert to a pseudo unknown VR... } } else { assert( OX_hack == false ); // 16bits only if( !ValueLengthField.template Read16(is) ) { assert(0 && "Should not happen"); return is; } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // HACK for SIEMENS Leonardo if( ValueLengthField == 0x0006 && VRField == VR::UL && TagField.GetGroup() == 0x0009 ) { gdcmWarningMacro( "Replacing VL=0x0006 with VL=0x0004, for Tag=" << TagField << " in order to read a buggy DICOM file." ); ValueLengthField = 0x0004; } #endif } //std::cerr << "exp cur tag=" << TagField << " VR=" << VRField << " VL=" << ValueLengthField << std::endl; // // I don't like the following 3 lines, what if 0000,0000 was indeed -wrongly- sent, we should be able to continue // chances is that 99% of times there is now way we can reach here, so safely throw an exception if( TagField == Tag(0x0000,0x0000) && ValueLengthField == 0 && VRField == VR::INVALID ) { // This handles DMCPACS_ExplicitImplicit_BogusIOP.dcm ParseException pe; pe.SetLastElement( *this ); throw pe; } return is; } template std::istream &VR16ExplicitDataElement::ReadValue(std::istream &is, bool readvalues ) { if( is.eof() ) return is; if( ValueLengthField == 0 ) { // Simple fast path ValueField = nullptr; return is; } // Read the Value //assert( ValueField == 0 ); if( VRField == VR::SQ ) { // Check whether or not this is an undefined length sequence assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new SequenceOfItems; } else if( ValueLengthField.IsUndefined() ) { if( VRField == VR::UN ) { // Support cp246 conforming file: // Enhanced_MR_Image_Storage_PixelSpacingNotIn_0028_0030.dcm (illegal) // vs // undefined_length_un_vr.dcm assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new SequenceOfItems; ValueField->SetLength(ValueLengthField); // perform realloc try { //if( !ValueIO::Read(is,*ValueField) ) // non cp246 if( !ValueIO::Read(is,*ValueField,readvalues) ) // cp246 compliant { assert(0); } } catch( std::exception &) { // Must be one of those non-cp246 file... // but for some reason seekg back to previous offset + Read // as Explicit does not work... ParseException pe; pe.SetLastElement(*this); throw pe; } return is; } else { if( TagField != Tag(0x7fe0,0x0010) ) { // gdcmSampleData/ForSeriesTesting/Perfusion/DICOMDIR ParseException pe; pe.SetLastElement(*this); throw pe; } // Ok this is Pixel Data fragmented... assert( TagField == Tag(0x7fe0,0x0010) ); assert( VRField & VR::OB_OW ); ValueField = new SequenceOfFragments; } } else { //assert( TagField != Tag(0x7fe0,0x0010) ); ValueField = new ByteValue; } // We have the length we should be able to read the value ValueField->SetLength(ValueLengthField); // perform realloc #if defined(GDCM_SUPPORT_BROKEN_IMPLEMENTATION) && 0 // PHILIPS_Intera-16-MONO2-Uncompress.dcm if( TagField == Tag(0x2001,0xe05f) || TagField == Tag(0x2001,0xe100) || TagField == Tag(0x2005,0xe080) || TagField == Tag(0x2005,0xe083) || TagField == Tag(0x2005,0xe084) || TagField == Tag(0x2005,0xe402) //TagField.IsPrivate() && VRField == VR::SQ //-> Does not work for 0029 //we really need to read item marker ) { gdcmWarningMacro( "ByteSwaping Private SQ: " << TagField ); assert( VRField == VR::SQ ); assert( TagField.IsPrivate() ); try { if( !ValueIO::Read(is,*ValueField,readvalues) ) { assert(0 && "Should not happen"); } Value* v = &*ValueField; SequenceOfItems *sq = dynamic_cast(v); assert( sq ); SequenceOfItems::Iterator it = sq->Begin(); for( ; it != sq->End(); ++it) { Item &item = *it; DataSet &ds = item.GetNestedDataSet(); ByteSwapFilter bsf(ds); bsf.ByteSwap(); } } catch( std::exception &ex ) { ValueLengthField = ValueField->GetLength(); } return is; } #endif if( !ValueIO::Read(is,*ValueField,readvalues) ) { // Might be the famous UN 16bits ParseException pe; pe.SetLastElement( *this ); throw pe; return is; } return is; } template std::istream &VR16ExplicitDataElement::ReadWithLength(std::istream &is, VL & length) { (void)length; return Read(is); } } // end namespace gdcm #endif // GDCMVR16EXPLICITDATAELEMENT_TXX GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmValue.cxx000066400000000000000000000013071412732066400251030ustar00rootroot00000000000000/*========================================================================= 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 "gdcmValue.h" #include "gdcmVL.h" namespace gdcm_ns { void Value::SetLengthOnly(VL l) { SetLength( l ); } } // end namespace gdcm_ns GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmValue.h000066400000000000000000000025631412732066400245350ustar00rootroot00000000000000/*========================================================================= 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 GDCMVALUE_H #define GDCMVALUE_H #include "gdcmObject.h" namespace gdcm { class VL; } namespace gdcm_ns { #if !defined(SWIGPYTHON) && !defined(SWIGCSHARP) && !defined(SWIGJAVA) && !defined(SWIGPHP) using namespace gdcm; #endif /** * \brief Class to represent the value of a Data Element. * \note * VALUE: A component of a Value Field. A Value Field may consist of one * or more of these components. */ class GDCM_EXPORT Value : public Object { public: Value() = default; ~Value() override = default; virtual VL GetLength() const = 0; virtual void SetLength(VL l) = 0; virtual void Clear() = 0; virtual bool operator==(const Value &val) const = 0; protected: friend class DataElement; virtual void SetLengthOnly(VL l); }; } // end namespace gdcm_ns #include "gdcmValue.txx" #endif //GDCMVALUE_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmValue.txx000066400000000000000000000012511412732066400251220ustar00rootroot00000000000000/*========================================================================= 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 GDCMVALUE_TXX #define GDCMVALUE_TXX namespace gdcm_ns { } // end namespace gdcm_ns #endif // GDCMVALUE_TXX GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmValueIO.h000066400000000000000000000020141412732066400247540ustar00rootroot00000000000000/*========================================================================= 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 GDCMVALUEIO_H #define GDCMVALUEIO_H #include "gdcmTypes.h" namespace gdcm_ns { /** * \brief Class to dispatch template calls */ template class /*GDCM_EXPORT*/ ValueIO { public: static std::istream &Read(std::istream &is, Value& v, bool readvalues); static const std::ostream &Write(std::ostream &os, const Value& v); }; } // end namespace gdcm_ns #include "gdcmValueIO.txx" #endif //GDCMVALUEIO_H GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmValueIO.txx000066400000000000000000000044041412732066400253550ustar00rootroot00000000000000/*========================================================================= 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 GDCMVALUEIO_TXX #define GDCMVALUEIO_TXX #include "gdcmValueIO.h" #include "gdcmExplicitDataElement.h" #include "gdcmImplicitDataElement.h" #include "gdcmSequenceOfFragments.h" #include "gdcmSequenceOfItems.h" #include "gdcmByteValue.h" namespace gdcm_ns { template std::istream &ValueIO::Read(std::istream &is, Value& _v, bool readvalues) { Value* v = &_v; if( ByteValue *bv = dynamic_cast(v) ) { bv->template Read(is,readvalues); } else if( SequenceOfItems *si = dynamic_cast(v) ) { si->template Read(is,readvalues); } else if( SequenceOfFragments *sf = dynamic_cast(v) ) { sf->template Read(is,readvalues); } else { assert( 0 && "error" ); } return is; } template const std::ostream &ValueIO::Write(std::ostream &os, const Value& _v) { const Value* v = &_v; if( const ByteValue *bv = dynamic_cast(v) ) { bv->template Write(os); } else if( const SequenceOfItems *si = dynamic_cast(v) ) { //VL dummy = si->ComputeLength(); //assert( /*dummy.IsUndefined() ||*/ dummy == si->GetLength() ); si->template Write(os); } else if( const SequenceOfFragments *sf = dynamic_cast(v) ) { sf->template Write(os); } else { assert( 0 && "error" ); } return os; } } // end namespace gdcm_ns #endif // GDCMVALUEIO_TXX GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmWriter.cxx000066400000000000000000000110761412732066400253070ustar00rootroot00000000000000/*========================================================================= 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 "gdcmWriter.h" #include "gdcmFileMetaInformation.h" #include "gdcmDataSet.h" #include "gdcmTrace.h" #include "gdcmSwapper.h" #include "gdcmDataSet.h" #include "gdcmExplicitDataElement.h" #include "gdcmImplicitDataElement.h" #include "gdcmValue.h" #include "gdcmValue.h" #include "gdcmItem.h" #include "gdcmSequenceOfItems.h" #include "gdcmParseException.h" #include "gdcmDeflateStream.h" namespace gdcm { Writer::Writer():Stream(nullptr),Ofstream(nullptr),F(new File),CheckFileMetaInformation(true),WriteDataSetOnly(false) { } Writer::~Writer() { if (Ofstream) { delete Ofstream; Ofstream = nullptr; Stream = nullptr; } } bool Writer::Write() { if( !Stream || !*Stream ) { gdcmErrorMacro( "No Filename" ); return false; } std::ostream &os = *Stream; FileMetaInformation &Header = F->GetHeader(); DataSet &DS = F->GetDataSet(); if( DS.IsEmpty() ) { gdcmErrorMacro( "DS empty" ); return false; } // Should I check that 0002,0002 / 0008,0016 and 0002,0003 / 0008,0018 match ? if( !WriteDataSetOnly ) { if( CheckFileMetaInformation ) { FileMetaInformation duplicate( Header ); try { duplicate.FillFromDataSet( DS ); } catch(gdcm::Exception &ex) { (void)ex; //to avoid unreferenced variable warning on release gdcmErrorMacro( "Could not recreate the File Meta Header, please report:" << ex.what() ); return false; } duplicate.Write(os); } else { Header.Write(os); } } const TransferSyntax &ts = Header.GetDataSetTransferSyntax(); if( !ts.IsValid() ) { gdcmErrorMacro( "Invalid Transfer Syntax" ); return false; } if( ts == TransferSyntax::DeflatedExplicitVRLittleEndian ) { //gzostream gzos(os.rdbuf()); try { zlib_stream::zip_ostream gzos( os ); assert( ts.GetNegociatedType() == TransferSyntax::Explicit ); DS.Write(gzos); //gzos.flush(); } catch (...){ return false; } return !os.fail(); } try { if( ts.GetSwapCode() == SwapCode::BigEndian ) { //US-RGB-8-epicard.dcm is big endian if( ts.GetNegociatedType() == TransferSyntax::Implicit ) { // There is no such thing as Implicit Big Endian... oh well // LIBIDO-16-ACR_NEMA-Volume.dcm DS.Write(os); } else { assert( ts.GetNegociatedType() == TransferSyntax::Explicit ); DS.Write(os); } } else // LittleEndian { if( ts.GetNegociatedType() == TransferSyntax::Implicit ) { DS.Write(os); } else { assert( ts.GetNegociatedType() == TransferSyntax::Explicit ); DS.Write(os); } } } catch(std::exception &ex) { (void)ex; //to avoid unreferenced variable warning on release gdcmErrorMacro( ex.what() ); return false; } catch(...) { gdcmErrorMacro( "what the hell" ); return false; } os.flush(); if (Ofstream) { Ofstream->close(); } return !os.fail(); } void Writer::SetFileName(const char *utf8path) { //std::cerr << "Stream: " << filename << std::endl; //std::cerr << "Ofstream: " << Ofstream << std::endl; if (Ofstream) { if (Ofstream->is_open()) { Ofstream->close(); } delete Ofstream; } Ofstream = new std::ofstream(); if (utf8path && *utf8path) { #ifdef _MSC_VER const std::wstring uncpath = System::ConvertToUNC(utf8path); Ofstream->open(uncpath.c_str(), std::ios::out | std::ios::binary); #else Ofstream->open(utf8path, std::ios::out | std::ios::binary); #endif assert(Ofstream->is_open()); assert(!Ofstream->fail()); } //std::cerr << Stream.is_open() << std::endl; Stream = Ofstream; } } // end namespace gdcm GDCM-3.0.10/Source/DataStructureAndEncodingDefinition/gdcmWriter.h000066400000000000000000000060401412732066400247270ustar00rootroot00000000000000/*========================================================================= 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 GDCMWRITER_H #define GDCMWRITER_H #include "gdcmFile.h" namespace gdcm { class FileMetaInformation; /** * \brief Writer ala DOM (Document Object Model) * \details This class is a non-validating writer, it will only performs well- * formedness check only. * * \details Detailed description here * To avoid GDCM being yet another broken DICOM lib we try to * be user level and avoid writing illegal stuff (odd length, * non-zero value for Item start/end length ...) * Therefore you cannot (well unless you are really smart) write * DICOM with even length tag. * All the checks are consider basics: * - Correct Meta Information Header (see gdcm::FileMetaInformation) * - Zero value for Item Length (0xfffe, 0xe00d/0xe0dd) * - Even length for any elements * - Alphabetical order for elements (guaranteed by design of internals) * - 32bits VR will be rewritten with 00 * * \warning * gdcm::Writer cannot write a DataSet if no SOP Instance UID (0008,0018) is found, * unless a DICOMDIR is being written out * * \see Reader DataSet File */ class GDCM_EXPORT Writer { public: Writer(); virtual ~Writer(); /// Main function to tell the writer to write virtual bool Write(); // Execute() /// Set the filename of DICOM file to write: void SetFileName(const char *filename_native); /// Set user ostream buffer void SetStream(std::ostream &output_stream) { Stream = &output_stream; } /// Set/Get the DICOM file (DataSet + Header) void SetFile(const File& f) { F = f; } File &GetFile() { return *F; } /// Undocumented function, do not use (= leave default) void SetCheckFileMetaInformation(bool b) { CheckFileMetaInformation = b; } void CheckFileMetaInformationOff() { CheckFileMetaInformation = false; } void CheckFileMetaInformationOn() { CheckFileMetaInformation = true; } protected: void SetWriteDataSetOnly(bool b) { WriteDataSetOnly = b; } protected: friend class StreamImageWriter; //this function is added for the StreamImageWriter, which needs to write //up to the pixel data and then stops right before writing the pixel data. //after that, for the raw codec at least, zeros are written for the length of the data std::ostream* GetStreamPtr() const { return Stream; } protected: std::ostream *Stream; std::ofstream *Ofstream; bool GetCheckFileMetaInformation() const { return CheckFileMetaInformation; } private: SmartPointer F; bool CheckFileMetaInformation; bool WriteDataSetOnly; }; } // end namespace gdcm #endif //GDCMWRITER_H GDCM-3.0.10/Source/InformationObjectDefinition/000077500000000000000000000000001412732066400211775ustar00rootroot00000000000000GDCM-3.0.10/Source/InformationObjectDefinition/CMakeLists.txt000066400000000000000000000041511412732066400237400ustar00rootroot00000000000000# Define the srcs for the Information Object Definition # IOD set(IOD_SRCS gdcmModule.cxx gdcmMacro.cxx gdcmModules.cxx gdcmMacros.cxx gdcmNestedModuleEntries.cxx gdcmIODEntry.cxx gdcmTableReader.cxx gdcmTable.cxx gdcmSeries.cxx gdcmDefs.cxx gdcmDefinedTerms.cxx gdcmEnumeratedValues.cxx gdcmStudy.cxx gdcmPatient.cxx gdcmType.cxx gdcmUsage.cxx gdcmIOD.cxx #gdcmXMLDictReader.cxx #gdcmXMLPrivateDictReader.cxx ) # expat stuff if(NOT BUILD_SHARED_LIBS) set_source_files_properties(gdcmTableReader.cxx PROPERTIES COMPILE_FLAGS -DXML_STATIC ) endif() # Add the include paths include_directories( "${GDCM_SOURCE_DIR}/Source/Common" "${GDCM_BINARY_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition" "${GDCM_SOURCE_DIR}/Source/DataDictionary" "${GDCM_SOURCE_DIR}/Utilities" "${GDCM_BINARY_DIR}/Utilities/gdcmexpat" # expat_mangle.h ) if(GDCM_USE_SYSTEM_EXPAT) include_directories( ${EXPAT_INCLUDE_DIRS} ) endif() add_library(gdcmIOD ${IOD_SRCS}) target_link_libraries(gdcmIOD LINK_PUBLIC gdcmDSED gdcmCommon) target_link_libraries(gdcmIOD LINK_PRIVATE ${GDCM_EXPAT_LIBRARIES}) set_target_properties(gdcmIOD PROPERTIES ${GDCM_LIBRARY_PROPERTIES}) # libs install_library(gdcmIOD) # PDB install_pdb(gdcmIOD) # include files install_includes("*.h" "*.txx") #----------------------------------------------------------------------------- # Install Part3.xml / Part4.xml install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/Part3.xml ${CMAKE_CURRENT_SOURCE_DIR}/Part4.xml DESTINATION ${GDCM_INSTALL_DATA_DIR}/XML COMPONENT Libraries ) #----------------------------------------------------------------------------- file(GLOB GDCM_XML_TABLES_GLOB "${CMAKE_CURRENT_SOURCE_DIR}/*.xml" ) set(GDCM_XML_TABLES) foreach(filename ${GDCM_XML_TABLES_GLOB}) set(GDCM_XML_TABLES "${GDCM_XML_TABLES}\n\"${filename}\",") endforeach() # Populate GDCM_DATA_IMAGES: configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/gdcmTables.h.in" "${CMAKE_CURRENT_BINARY_DIR}/gdcmTables.h" ) GDCM-3.0.10/Source/InformationObjectDefinition/ParseAttributes.py000077500000000000000000000444241412732066400247050ustar00rootroot00000000000000#!/usr/bin/env python # vim: set fileencoding=iso-8859-1 """ $ pdftotext -layout -nopgbrk -f 303 -l 305 07_03pu.pdf page303.txt $ python ParseAttributes.py page273-1000.txt out.txt > log2 $ grep ADD log2 | grep -v "Notes:" | grep -v "Note:" | grep -v "C.8" | grep -v "C.7" """ import re,os """ """ class Attribute: # Cstor def __init__(self): self._Name = '' self._Tag = '(0000,0000)' self._Type = '' self._Description= '' def SetInit(self,s): # Should be something like: # Blue Palette Color Lookup Table (0028,1103) 1C Specifies the format of the Blue Palette patt = re.compile("^(.*)(\\([0-9A-Fx]+,[0-9A-F]+\\))\s+([1-3C]+)\s+(.*)\s*$") m = patt.match(s) if not m: print s assert 0 self._Name = m.group(1).strip() self._Tag = m.group(2).strip() self._Type = m.group(3).strip() self._Description = m.group(4).strip() def SetName(self,s): self._Name = s def AppendName(self,s): self._Name += " " self._Name += s.strip() def SetTag(self,s): self._Tag = s def SetType(self,s): self._Type = s def SetDescription(self,s): self._Description = s def AppendDescription(self,s): self._Description += " " self._Description += s.strip() def GetAsXML(self): description = self._Description.replace('"','"') description = description.replace('&','&') return "" def Print(self): print self.GetAsXML() class Part3Parser: # Cstor def __init__(self): self._InputFilename = '' self._OutputFilename = '' self._Buffer = '' self._CurrentAttribute = Attribute() self._IsInTable = False self._Shift = 0 def SetInputFileName(self,s): self._InputFilename = s def SetOutputFileName(self,s): self._OutputFilename = s def IsComment(self,s): if len(s) == 0: return True patt1 = re.compile("^\s+- Standard -\s*$") patt2 = re.compile("^\s*PS 3.3 - 2007\s*") patt3 = re.compile("^\s*Page\s+[0-9]+\s*$") patt4 = re.compile("^\s*Notes:$") m1 = patt1.match(s) m2 = patt2.match(s) m3 = patt3.match(s) m4 = patt4.match(s) if(m1 or m2 or m3 or m4): print "Comment:", s return True if self.IsTableDescription(s): return True return False def IsStartTable(self,s): #patt = re.compile("^\s+Table C[0-9a-z\.-]+.*\s+$") patt = re.compile("^\s+Table\s+C.[0-9A-Za-z-.]+\s*$") m = patt.match(s) assert self._IsInTable != True self._IsInTable = False if s.strip() == 'Table C.7-23' or s.strip() == 'Table C.7-24' \ or s.strip() == 'Table C.7.6.10-1' \ or s.strip() == 'Table C.7-25' \ or s.strip() == 'Table C.7-26' \ or s.strip() == 'Table C.7-27' \ or s.strip() == 'Table C.8-8' \ or s.strip() == 'Table C.8-19' \ or s.strip() == 'Table C.8-20' \ or s.strip() == 'Table C.8-21' \ or s.strip() == 'Table C.8-22' \ or s.strip() == 'Table C.8-23' \ or s.strip() == 'Table C.8-80' \ or s.strip() == 'Table C.8-83' \ or s.strip() == 'Table C.8-84' \ or s.strip() == 'Table C.8-85' \ or s.strip() == 'Table C.8-86' \ or s.strip() == 'Table C.8-108' \ or s.strip() == 'Table C.8-109' \ or s.strip() == 'Table C.8-110' \ or s.strip() == 'Table C.8-111' \ or s.strip() == 'Table C.8-112' \ or s.strip() == 'Table C.8-115' \ or s.strip() == 'Table C.8-116' \ or s.strip() == 'Table C.8-127' \ or s.strip() == 'Table C.8-128' \ or s.strip() == 'Table C.8-129' \ or s.strip() == 'Table C.8-130' \ or s.strip() == 'Table C.8-131' \ or s.strip() == 'Table C.8-132' \ or s.strip() == 'Table C.8-133' \ or s.strip() == 'Table C.8-134' \ or s.strip() == 'Table C.8.19.2-2' \ or s.strip() == 'Table C.10-10' \ or s.strip() == 'Table C.11-4' \ or s.strip() == 'Table C.12-2' \ or s.strip() == 'Table C.12-3' \ or s.strip() == 'Table C.12-4' \ or s.strip() == 'Table C.12-5' \ or s.strip() == 'Table C.12-7' \ or s.strip() == 'Table C.13-1' \ or s.strip() == 'Table C.13-2' \ or s.strip() == 'Table C.13-3' \ or s.strip() == 'Table C.13-4' \ or s.strip() == 'Table C.13-5' \ or s.strip() == 'Table C.13-7' \ or s.strip() == 'Table C.13-8' \ or s.strip() == 'Table C.13-9' \ or s.strip() == 'Table C.13-13' \ or s.strip() == 'Table C.14-1' \ or s.strip() == 'Table C.17.3-7' \ or s.strip() == 'Table C.17.3-8' \ or s.strip() == 'Table C.22.1-1': # C.11-4, C.13-*, C.22.1-1: Does not even comes with column type !!! # C.12-7 is difficult to parse # C.7.6.16-1 is insane... # TODO: Last line of C.19-1... return False if(m): print "Start", s self._IsInTable = True return True # grrrrr: Table C.8-37 - RT SERIES MODULE ATTRIBUTES patt = re.compile("^\s+Table\s+C.[0-9A-Za-z-]+\s*[-]*\s*([A-Z/\s-]+)\s*$") #patt = re.compile("^\s+Table\s+C.[0-9A-Za-z-]+[-\s]+([A-Z/\s-]+)\s*$") m = patt.match(s) if(m): print "Start", s self._IsInTable = True return True print "IsTable failed with:", s return False def IsEndTable(self,s): assert self._IsInTable == True assert not self.IsComment(s) self._IsInTable = False return True def IsTableName(self,s): patt = re.compile("^\s*[A-Z/\s-]+ATTRIBUTES\s*$") #MACRO/MODULE m = patt.match(s) if(m): print "Table Name", s return True patt = re.compile("^\s+[A-Za-z\s]+Attributes\s*$") #MACRO/MODULE m = patt.match(s) if(m): print "Table Name", s return True # PALETTE COLOR LOOKUP MODULE patt = re.compile("^\s+[A-Z\s]+MODULE\s*$") #MACRO/MODULE m = patt.match(s) if(m): print "Table Name", s return True # MR IMAGE AND SPECTROSCOPY INSTANCE MACRO patt = re.compile("^\s+[A-Z\s]+MACRO\s*$") #MACRO/MODULE m = patt.match(s) if(m): print "Table Name", s return True # Enhanced XA/XRF Image Module Table patt = re.compile("^\s+[A-Z/a-z\s]+Module Table\s*$") m = patt.match(s) if(m): print "Table Name", s return True # Presentation LUT Module #patt = re.compile("^\s+Presentation LUT Module\s*$") #m = patt.match(s) #if(m): # print "Table Name", s # return True print "TableName failed with:", s return False def IsTableName2(self,s): # grrrrr: Table C.8-37 - RT SERIES MODULE ATTRIBUTES # Table C.8-39--RT DOSE MODULE ATTRIBUTES patt = re.compile("^\s+Table\s+C.[0-9A-Za-z-]+\s*[-]*\s*([A-Z/\s-]+)\s*$") m = patt.match(s) # The previous regex would think : Table C.7-17A # is correct...I don't know how to fix the regex, so discard result if # len(m.group(1)) <= 1 if(m and len(m.group(1)) > 1): print "Table Name:", m.group(1) assert self.IsTableName( m.group(1) ) return True print "TableName2 failed with:", s return False def IsTableDescription(self,s): patt = re.compile("^\s*Attribute Name\s+Tag\s+Type\s+Attribute Description\s*$") m = patt.match(s) if(m): print "Table Description:", s return True # Around page 574 patt = re.compile("^\s*Attribute [Nn]ame\s+Tag\s+Type\s+Description\s*$") m = patt.match(s) if(m): print "Table Description:", s return True return False def IsFirstLineAttribute(self,s): # Line should look like: # Bits Stored ... (0028,0101) ... 1 ... Number of bits stored for each pixel patt = re.compile("^\s*(.*)\\([0-9A-Fx]+,[0-9A-F]+\\)\s+([1-3C]+).*\s*$") #MACRO/MODULE m = patt.match(s) if(m): s1 = m.group(1).strip() if s1 == '': return False #print "First Line Attribute:", s1, s return True #print "No:", s return False def IsIncludeTable(self,s): # Need to support : "Include `Image Pixel Macro' Table C.7-11b" #assert self._Shift == 0 #print "Include:", s #patt = re.compile("^>*Include `(.*)' Table [A-Z0-9a-z-.]+$") #m = patt.match(s) #if m: # return True #patt = re.compile("^>*Include [`|'](.*)' Table [A-Z0-9a-z-.]+\s+Defined Context ID is.*$") #m = patt.match(s) #return m #print "FALLBACK" patt = re.compile("^>*\s*Include [`'\"]*([A-Za-z/ -]*)['\"]* \\(*Table [A-Z0-9a-z-.]+\\)*.*$") m = patt.match(s) #if not m: # print "FAIL", s return m def IsNextLineAttribute(self,s): if self._Shift == 0: print "IsNextLineAttribute failed with", s return False if len(s) <= self._Shift: print "IsNextLineAttribute failed with", s return False blank = s[0:self._Shift] blank = blank.strip() #print "BLANK:", blank if blank == '': self._CurrentAttribute.AppendDescription( s ) return True # The following is really ugly ... need to be fixed if blank == 'Descriptor' or blank == 'Data' or blank == 'Center Name' \ or blank == 'Description' \ or blank == 'Sequence' \ or blank == 'Distance' \ or blank == 'Index' \ or blank == 'Reordering' \ or blank == 'Time' \ or blank == 'Device Number' \ or blank == 'Justification' \ or blank == 'Shape' \ or blank == 'Relationship' \ or blank == 'in Float' \ or blank == 'Displacement' \ or blank == 'Technique Description' \ or blank == 'Left Vertical Edge' \ or blank == 'State Sequence' \ or blank == 'In-plane' \ or blank == 'Certification Number' \ or blank == 'Right Vertical Edge' \ or blank == 'Accumulated' \ or blank == 'Equivalent Thickness' \ or blank == 'Distances' \ or blank == 'Definition' \ or blank == 'Upper Horizontal Edge' \ or blank == 'Modification' \ or blank == 'Power Ratio' \ or blank == 'Lower Horizontal Edge' \ or blank == 'Device Distance' \ or blank == 'Sensing Region' \ or blank == 'Control Sensing Region' \ or blank == 'Water Equivalent Thickness' \ or blank == 'Columns' \ or blank == 'Rows' \ or blank == 'Ratio' \ or blank == 'Display Grayscale Value' \ or blank == 'Display CIELab Value' \ or blank == 'UID' \ or blank == 'Units' \ or blank == 'Pointer' \ or blank == 'Value' \ or blank == 'Annotation' \ or blank == 'Pointer Private Creator' \ or blank == 'Creator' \ or blank == 'Value Mapping Sequence' \ or blank == 'Performed Procedure' \ or blank == 'MAC Sequence' \ or blank == 'Class UID' \ or blank == 'Instance UID' \ or blank == 'Syntax UID' \ or blank == 'Used' \ or blank == 'Identifier' \ or blank == 'Datetime' \ or blank == 'plane Phase Steps' \ or blank == '(Patient)' \ or blank == 'Collection Center' \ or blank == 'Technique' \ or blank == 'Interpretation' \ or blank == 'Representation' \ or blank == 'Configuration' \ or blank == 'Compression' \ or blank == 'Reference Code' \ or blank == 'Encoding Steps' \ or blank == 'Steps in-plane' \ or blank == 'Steps out-of-plane' \ or blank == 'Type' \ or blank == 'Explanation' \ or blank == 'Mapped' \ or blank == 'Calibration' \ or blank == 'Manufactured' \ or blank == 'Thickness' \ or blank == 'Reference Sequence' \ or blank == 'Reference Number' \ or blank == 'Transmission' \ or blank == 'Matrix' \ or blank == 'Comment' \ or blank == 'Setup Sequence' \ or blank == 'Setup Number' \ or blank == 'Fraction' \ or blank == 'Tolerance' \ or blank == 'Number' \ or blank == 'Day' \ or blank == 'Parameters' \ or blank == 'Coefficient' \ or blank == 'Specification Point' \ or blank == 'Identification Sequence' \ or blank == 'Reference UID' \ or blank == 'Synchronized' \ or blank == 'Description Code Sequence' \ or blank == 'Concentration' \ or blank == 'Procedure Step' \ or blank == 'Manufacturer' \ or blank == 'Lookup Table Data' \ or blank == 'Version' \ or blank == 'Images' \ or blank == 'Wavelength' \ or blank == 'Code Sequence' \ or blank == 'Housing' \ or blank == 'Exposure' \ or blank == 'Beam' \ or blank == 'Angle' \ or blank == 'Rotation Angle' \ or blank == 'Corner' \ or blank == 'Factor' \ or blank == 'Product' \ or blank == "Manufacturer's Model Name" \ or blank == 'Qualifier Code' \ or blank == 'Mapping Instance Sequence' \ or blank == 'Channels' \ or blank == 'Samples' \ or blank == 'Transformation Comment' \ or blank == 'Pixels' \ or blank == 'Correction Factor' \ or blank == 'Group' \ or blank == 'Amount' \ or blank == 'Priority' \ or blank == 'Group Name' \ or blank == 'Frame Rate' \ or blank == 'Presence' \ or blank == 'Sequencing' \ or blank == 'Orientation' \ or blank == 'Inverted' \ or blank == 'Numbers' \ or blank == 'Flag' \ or blank == 'Annotation Flag' \ or blank == 'Demographics Flag' \ or blank == 'Techniques Flag' \ or blank == 'Group Description' \ or blank == 'Handling' \ or blank == 'Initial View Direction' \ or blank == 'Identification Code Sequence' \ or blank == 'Identification Code' \ or blank == 'Category' \ or blank == 'Spatial Position' \ or blank == 'Creation Datetime' \ or blank == 'Grayscale Bit Depth' \ or blank == 'Bit Depth' \ or blank == 'Repaint Time' \ or blank == 'Definition Sequence' \ or blank == 'Procedure Code' \ or blank == 'Referenced' \ or blank == 'Reference' \ or blank == 'Usage Flag' \ or blank == 'Horizontal Dimension' \ or blank == 'Dimension' \ or blank == 'Direction' \ or blank == 'Registration Sequence' \ or blank == 'Transformation Matrix' \ or blank == 'Transformation Matrix Type' \ or blank == 'Step Sequence': self._CurrentAttribute.AppendName( blank ) self._CurrentAttribute.AppendDescription( s[self._Shift:] ) return True else: print "ADD KEYWORD:", blank return False def FindShiftValue(self,s): # Line should look like: # Bits Stored ... (0028,0101) ... 1 ... Number of bits stored for each pixel patt = re.compile("^[A-Za-z0-9µ /()'>-]+\s+\\([0-9A-Fx]+,[0-9A-F]+\\)\s+[1-3][C]*\s+(.*)$") m = patt.match(s) if(m): # worse case happen around page 448 with `Required` # worse case happen around page 475 with `LOG`... self._Shift = s.find( m.group(1) ) - 17 return self._Shift print "OUCH:", s return 0 def Open(self): #self._Infile = file(self._InputFilename, 'r') #for line in self._Infile.readlines(): # line = line[:-1] # remove '\n' # if( self.IsStartTable(line) ): # print line.next() cmd_input = open(self._InputFilename,'r') outfile = open(self._OutputFilename, 'w') # To support some weird output from pdftotext outfile.write( '' ) outfile.write( '' ) for line_ori in cmd_input: #while line.startswith('%') : # skip comment lines #print "!!!",line #line= cmd_input.next() line = line_ori[:-1] if( self.IsStartTable(line) ): table_name_found = self.IsTableName2(line) line2 = line # Okay table is on next line: if ( not table_name_found ): line2 = cmd_input.next()[:-1] table_name_found = self.IsTableName(line2) # Either way we need to find the table name assert table_name_found if( table_name_found ): line3 = cmd_input.next()[:-1] if( self.IsTableDescription(line3) ): # Ok we found a table outfile.write( "" ) buffer = '' self._CurrentAttribute = Attribute() self._Shift = 0 for subline_ori in cmd_input: subline = subline_ori[:-1] if( self.IsIncludeTable(subline)): # BUG DO NOT SUPPORT MULTI_LINE INCLUDE #print "Include Table:", subline if( subline != '' ): outfile.write( "" ) outfile.write( '\n' ) elif( self.IsFirstLineAttribute(subline)): #print "Previous Buffer was: ", buffer if( buffer != '' ): outfile.write( self._CurrentAttribute.GetAsXML() ) outfile.write( '\n' ) self._CurrentAttribute.SetInit(subline) self.FindShiftValue(subline) assert self._Shift != 0 buffer = subline else: if( not self.IsComment(subline) ): #print "Found Comment: ", subline if( self.IsNextLineAttribute(subline) ): buffer += ' ' + subline.strip() else: print "Wotsit:", subline self._Shift = 0 self._IsInTable = False if( buffer != '' ): outfile.write( self._CurrentAttribute.GetAsXML() ) outfile.write( '\n' ) outfile.write( '
' ) break #print "Working on: ", subline if not subline_ori: break else: print "Problem with:", line, line2 #line = cmd_input.next() if not line_ori: break cmd_input.close() outfile.write( '
' ) self.Write() def Write(self): print "Write" # Main function to call for parsing def Parse(self): self.Open() if __name__ == "__main__": argc = len(os.sys.argv ) if ( argc < 3 ): print "Sorry, wrong list of args" os.sys.exit(1) #error inputfilename = os.sys.argv[1] outputfilename = os.sys.argv[2] tempfile = "/tmp/mytemp2" dp = Part3Parser() dp.SetInputFileName( inputfilename ) dp.SetOutputFileName( tempfile ) dp.Parse() GDCM-3.0.10/Source/InformationObjectDefinition/Part3.xml000066400000000000000000107224061412732066400227260ustar00rootroot00000000000000 See Section 8.1. See Section 8.2. See Section 8.2. Required if the value of Coding Scheme Designator (0008,0102) is not sufficient to identify the Code Value (0008,0100) unambiguously. See Section 8.3. See Section 8.6. See Section 8.4. Required if Context Identifier (0008,010F) is present. See Section 8.5. Required if Context Identifier (0008,010F) is present. Indicates whether the Code Value/Coding Scheme/Code Meaning is selected from a private extension of the Context Group identified in Context Identifier (0008,010F). See Section 8.7 of this Part. Enumerated Values: "Y", "N" See Section 8.7. Required if the value of Context Group Extension Flag (0008,010B) is "Y". . Identifies the person or organization who created an extension to the Context Group. See Section 8.7. Required if the value of Context Group Extension Flag (0008,010B) is "Y". A coded entry which identifies a person. The Code Meaning attribute, though it will be encoded with a VR of LO, may be encoded according to the rules of the PN VR (e.g. caret ‘^' delimiters shall separate name components), except that a single component (i.e. the whole name unseparated by caret delimiters) is not permitted. Name component groups for use with multi-byte character sets are permitted, as long as they fit within the 64 characters (the length of the LO VR). One or more Items may be permitted in this Sequence. Person's mailing address Person's telephone number(s) Institution or organization to which the identified individual is responsible or accountable. Required if Institution Code Sequence (0008,0082) is not present. Mailing address of the institution or organization to which the identified individual is responsible or accountable. Institution or organization to which the identified individual is responsible or accountable. Required if Institution Name (0008,0080) is not present. Only a single Item shall be permitted in this Sequence. The type of the value encoded in this name-value Item. Defined Terms: DATETIME DATE TIME PNAME UIDREF TEXT CODE NUMERIC Coded concept name of this name-value Item. Only a single Item shall be permitted in this Sequence. DateTime value for this name-value Item. Required if Value Type (0040,A040) is DATETIME. Date value for this name-value Item. Required if Value Type (0040,A040) is DATE. Time value for this name-value Item. Required if Value Type (0040,A040) is TIME. Person name value for this name-value Item. Required if Value Type (0040,A040) is PNAME. UID value for this name-value Item. Required if Value Type (0040,A040) is UIDREF. Text value for this name-value Item. Required if Value Type (0040,A040) is TEXT. Coded concept value of this name-value Item. Only a single Item shall be permitted in this Sequence. Required if Value Type (0040,A040) is CODE. Numeric value for this name-value Item. Required if Value Type (0040,A040) is NUMERIC. Units of measurement for a numeric value in this name-value Item. Only a single Item shall be permitted in this Sequence. Required if Value Type (0040,A040) is NUMERIC. Identifies the frame numbers within the Referenced SOP Instance to which the reference applies. The first frame shall be denoted as frame number 1. Note: This Attribute may be multi-valued. Required if the Referenced SOP Instance is a multi-frame image and the reference does not apply to all frames, and Referenced Segment Number (0062,000B) is not present. Identifies the Segment Number to which the reference applies. Required if the Referenced SOP Instance is a Segmentation and the reference does not apply to all segments and Referenced Frame Number (0008,1160) is not present. Sequence of Items each of which includes the Attributes of one Series. One or more Items shall be present. Unique identifier of the Series containing the referenced Instances. Sequence of Items each providing a reference to an Instance that is part of the Series defined by Series Instance UID (0020,000E) in the enclosing Item. One or more Items shall be present. Sequence that identifies the anatomic region of interest in this Instance (i.e. external anatomy, surface anatomy, or general region of the body). Only a single Item shall be permitted in this sequence. Sequence of Items that modifies the anatomic region of interest of this Instance One or more Items may be included in this Sequence. Sequence that identifies the anatomic region of interest in this Instance (i.e. external anatomy, surface anatomy, or general region of the body). Zero or one Item may be present in this Sequence. Sequence of Items that modifies the anatomic region of interest of this Instance One or more Items may be included in this Sequence. Sequence that identifies the anatomic region of interest in this Instance (i.e. external anatomy, surface anatomy, or general region of the body). Only a single Item shall be permitted in this sequence. Sequence of Items that modifies the anatomic region of interest of this Instance One or more Items may be included in this Sequence. Sequence of Items that identifies the primary anatomic structure(s) of interest in this Instance. One or more Items may be included in this Sequence. Sequence of Items that modifies the primary anatomic structure of interest in this Instance. One or more Items may be included in this Sequence. Identifier that identifies the Requested Procedure in the Imaging Service Request. Required if procedure was scheduled. May be present otherwise. Note: The condition is to allow the contents of this macro to be present (e.g., to convey the reason for the procedure, such as whether a mammogram is for screening or diagnostic purposes) even when the procedure was not formally scheduled and a value for this identifier is unknown, rather than making up a dummy value. An identifier of the Imaging Service Request for this Requested Procedure. The unique identifier for the Study provided for this Requested Procedure. Uniquely identifies the Study SOP Instances associated with this SOP Instance. One or more items may be included. Institution-generated administrative description or classification of Requested Procedure. A sequence that conveys the Procedure Type of the requested procedure. The Requested Procedure Code Sequence shall contain only a single item. Reason for requesting this procedure. Coded Reason for requesting this procedure. One or more sequence items may be present. Identifier that identifies the Scheduled Procedure Step. Required if procedure was scheduled. Note: The condition is to allow the contents of this macro to be present (e.g., to convey the reason for the procedure, such as whether a mammogram is for screening or diagnostic purposes) even when the procedure step was not formally scheduled and a value for this identifier is unknown, rather than making up a dummy value. Institution-generated description or classification of the Scheduled Procedure Step to be performed. Sequence describing the Scheduled Protocol following a specific coding scheme. This sequence contains one or more Items. Sequence that specifies the context for the Scheduled Protocol Code Sequence Item. One or more items may be included in this sequence. Sequence that specifies modifiers for a Protocol Context Content Item. One or more items may be included in this sequence. See Section C.4.10.1.
The Protocol Context Sequence (0040,0440) allows the specification of parameters that further qualify the scheduled protocol, provided through a set of generic name/value pairs of context Content Items. Note: This allows the specification of clinical, acquisition, or procedural qualifiers for the scheduled protocol, such as a specific body part, imaging technique, or parameters of a preparatory event (e.g., radionuclide injection). Specific uses of this Sequence may be documented in a Template defined in accordance with PS3.16.
Physical distance in the patient between the center of each pixel, specified by a numeric pair - adjacent row spacing (delimiter) adjacent column spacing in mm. See 10.7.1.1 and 10.7.1.3. Required if the image has been calibrated. May be present otherwise. The type of correction for the effect of geometric magnification or calibration against an object of known size, if any. See 10.7.1.2. A free text description of the type of correction or calibration performed. Notes: 1. In the case of correction, the text might include description of the assumptions made about the body part and geometry and depth within the patient. 2. in the case of calibration, the text might include a description of the fiducial and where it is located (e.g., "XYZ device applied to the skin over the greater trochanter"). 3. Though it is not required, the Device Module may be used to describe the specific characteristics and size of the calibration device. Required if Pixel Spacing Calibration Type (0028,0A02) is present. Uniquely identifies the referenced SOP Class. Uniquely identifies the referenced SOP Instance. A number that identifies this SOP Instance. A label that is used to identify this SOP Instance. A description of the content of the SOP Instance. Name of operator (such as a technologist or physician) creating the content of the SOP Instance. Identification of the person who created the real world value mapping. Only a single item shall be present in this sequence. A sequence that identifies the contributing SOP Instances. Required if this SOP Instance is created from other DICOM SOP Instances. Note: The attribute is absent in the case where the sources used to create this SOP Instance are not SOP Instances, e.g., a volume that was directly generated by an acquisition system. One or more Items may be present. Unique identifier for the Study of the Contributing SOP Instances. Sequence of Items each of which includes the Attributes of one Series. One or more Items may be present. Unique identifier of the Series containing the referenced Instances. A number that identifies this Series. Sequence of Items each providing a reference to an Instance that is part of the Series defined by Series Instance UID (0020,000E) in the enclosing Item. One or more Items may be present. A number that identifies this instance. Manufacturer of the equipment that produced the sources. Manufacturer's model name of the equipment that produced the sources. Required if present and consistent in the contributing SOP Instances. Manufacturer's serial number of the equipment that produced the sources. Required if present and consistent in the contributing SOP Instances. Manufacturer's designation of software version of the equipment that produced the sources. Required if present and consistent in the contributing SOP Instances. The time the acquisition of data that resulted in sources started. The value shall be the start date and time of the first contributing SOP Instance of the group specified by the Contributing SOP Instances Reference Sequence (0020,9529). Required if present and consistent in the contributing SOP Instances. Note: The Acquisition DateTime may be created by combining the values of Acquisition Date (0008,0022) and Acquisition Time (0008,0032) attributes in the contributing SOP Instances. User defined name identifying the machine that produced the sources. Required if present and consistent in the contributing SOP Instances. Name(s) of the operator(s) supporting the Series. Required if present and consistent in the contributing SOP Instances. Identification of the operator(s) supporting the Series. One or more items shall be included in this sequence. If more than one Item, the number and order shall correspond to the value of Operators' Name (0008,1070), if present. Required if present and consistent in the contributing SOP Instances. User-defined description of the conditions under which the Series was performed. Required if present and consistent in the contributing SOP Instances. Note: This attribute conveys series-specific protocol identification and may or may not be identical to the one presented in the Performed Protocol Code Sequence (0040,0260). Sequence describing the Protocol performed for the Procedure Step creating the sources. One or more Items may be included in this Sequence. Required if present and consistent in the contributing SOP Instances. User defined name of the protocol used to acquire this image. Required if present and consistent in the contributing SOP Instances. Number of rows in the images. Number of columns in the images. Number of bits stored for each pixel sample. Each sample shall have the same number of bits stored. See PS 3.5 for further explanation. Specifies whether the Source Images have undergone lossy compression. Enumerated Values: 00 = Image has NOT been subjected to lossy compression. 01 = Image has been subjected to lossy compression. See C.7.6.1.1.5 for further explanation. Required if it is known whether or not Lossy Compression has been performed on the Images. Note: In some SOP Class definitions the Lossy Image Compression attribute is optional.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
See C.7.6.1.1.5 for further explanation. Required if Lossy Image Compression (0028,2110) equals 01.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
A label for the lossy compression method(s) that have been applied to the source images. See C.7.6.1.1.5 for further explanation. May be multi-valued if successive lossy compression steps have been applied; the value order shall correspond to the values of Lossy Image Compression Ratio (0028,2112). Note: For historical reasons, the lossy compression method may also be described in Derivation Description (0008,2111). Required if Lossy Image Compression (0028,2110) equals 01.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
Sequence that describes the orientation of the patient with respect to gravity. See C.8.11.5.1.2 for further explanation. Only a single Item shall be permitted in this Sequence.
This Attribute is not related to Patient Orientation (0020,0020) and conveys a different concept entirely.
Patient orientation modifier. Required if needed to fully specify the orientation of the patient with respect to gravity. Only a single Item shall be permitted in this Sequence. Sequence that describes the orientation of the patient with respect to the head of the table. See Section C.8.4.6.1.3 for further explanation. Only a single Item shall be permitted in this Sequence.
Patient Gantry Relationship Code Sequence (0054,0414) is used to describe the patient direction within the gantry, such as head-first or feet-first. When imaging the extremities, these directions are related to normal anatomic position. Example: In normal anatomic position, the fingers point towards the feet.
User or equipment generated identifier of that part of a Procedure that has been carried out within this step. Date on which the Performed Procedure Step started. Time on which the Performed Procedure Step started. Institution-generated description or classification of the Procedure Step that was performed. Sequence describing the Protocol performed for this Procedure Step. One or more Items may be included in this Sequence. Sequence that specifies the context for the Performed Protocol Code Sequence Item. One or more items may be included in this sequence. Sequence that specifies modifiers for a Protocol Context Content Item. One or more items may be included in this sequence. See Section C.4.10.1.
The Protocol Context Sequence (0040,0440) allows the specification of parameters that further qualify the scheduled protocol, provided through a set of generic name/value pairs of context Content Items. Note: This allows the specification of clinical, acquisition, or procedural qualifiers for the scheduled protocol, such as a specific body part, imaging technique, or parameters of a preparatory event (e.g., radionuclide injection). Specific uses of this Sequence may be documented in a Template defined in accordance with PS3.16.
User-defined comments on the Performed Procedure Step.
Uniquely identifies the Study SOP Instances associated with the Patient SOP Instance. One or more Items may be included in this Sequence. Uniquely identifies the Visit SOP Instances associated with this Patient SOP Instance. One or more Items may be included in this Sequence. Uniquely identifies any Patient SOP Instances that also describe this patient. These SOP Instances are aliases. Zero or more Items may be included in this Sequence. Patient's full name Primary hospital identification number or code for the patient. Identifier of the Assigning Authority (system, organization, agency, or department) that issued the Patient ID. Note: Issuer of Patient ID (0010,0021) is equivalent to HL7 v2 PID-3 component 4. Other identification numbers or codes used to identify the patient. A sequence of identification numbers or codes used to identify the patient, which may or may not be human readable, and may or may not have been obtained from an implanted or attached device such as an RFID or barcode. An identification number or code used to identify the patient Identifier of the Assigning Authority that issued the Patient ID. The type of identifier in this item. Defined Terms: TEXT RFID BARCODE Note: The identifier is coded as a string regardless of the type, not as a binary value. Other names used to identify the patient. Patient's birth name. Birth name of patient's mother. An identifier used to find the patient's existing medical record (e.g. film jacket). Age of the Patient. Occupation of the Patient. Special indication to the modality operator about confidentiality of patient information (e.g., that he should not use the patients name where other patients are present). Date of birth of the named patient Time of birth of the named patient Sex of the named patient. Enumerated Values: M = male F = female O = other A sequence that conveys the patient's insurance plan. Zero or more Items may be included in this Sequence. The languages that can be used to communicate with the patient. Zero or more Items may be included in the sequence. The sequence items are ordered by preference (most preferred language to least preferred language). A modifier for a Patient's Primary Language. Can be used to specify a national language variant. Exactly one Item may be included in the sequence. Patient's height or length in meters Weight of the patient in kilograms Legal address of the named patient Military rank of patient Branch of the military. The country allegiance may also be included (e.g. U.S. Army). Country in which patient currently resides Region within patient's country of residence Telephone numbers at which the patient can be reached Ethnic group or race of patient The religious preference of the patient User-defined comments about the patient Name of person with medical decision making authority for the patient. Relationship of Responsible Person to the patient. Defined Terms: OWNER Name of organization with medical decision making authority for the patient. The species of the patient. The species of the patient. The breed of the patient. The breed of the patient. Information identifying an animal within a breed registry. Identification number of a veterinary patient within the registry. Identification of the organization with which an animal is registered. Conditions to which medical staff should be alerted (e.g. contagious condition, drug allergies, etc.) Description of prior reaction to contrast agents, or other patient allergies or adverse reactions. Indicates whether patient smokes. Enumerated Values: YES NO UNKNOWN Additional information about the patient's medical history Describes pregnancy state of patient. Enumerated Values: 0001 = not pregnant 0002 = possibly pregnant 0003 = definitely pregnant 0004 = unknown Date of onset of last menstrual period Whether or not a procedure has been performed in an effort to render the patient sterile. Enumerated value: ALTERED = Altered/Neutered UNALTERED = Unaltered/intact Medical and social needs (e.g. wheelchair, oxygen, translator, etc.) Description of patient state (comatose, disoriented, vision impaired, etc.) List of Documents (e.g., SR, or CDA) that contain information considered pertinent for the patient medical condition. Zero or more Items may be included in this sequence. Describes the purpose for which the document reference is made. Zero or more Items may be present. Title of the referenced document. Sequence of identifiers for clinical trials in which the patient participates. Zero or more Items may be included in this sequence. The name of the clinical trial sponsor, responsible for conducting the clinical trial and for defining the Clinical Trial Protocol. Identifier for the noted protocol, used by the Clinical Trial Sponsor to uniquely identify the investigational protocol. The name or title of the clinical trial protocol. The identifier, issued by the Clinical Trial Sponsor, of the site responsible for submitting clinical trial data. Name of the site responsible for submitting clinical trial data. The assigned identifier for the patient as a clinical trial subject. Identifies the patient as a clinical trial subject for blinded evaluations. Uniquely identifies the Study SOP Instances associated with the Visit SOP Instance. One or more Items may be included in this Sequence. Uniquely identifies the Patient SOP Instance that relates to the Visit SOP Instance. Only a single Item shall be permitted in this Sequence. Institution where the equipment is located Mailing Address of the institution where the equipment is located A sequence that conveys the healthcare facility identification. Only a single Item shall be permitted in this Sequence. Identification number of the visit as assigned by the healthcare provider Name of healthcare provider which issued the Admission ID Identifier of the Service Episode as assigned by the healthcare provider Name of healthcare provider that issued the Service Episode ID Description of the type of service episode. Identifies the state of the visit. Defined Terms: CREATED = Created but not yet scheduled SCHEDULED = Scheduled but not yet admitted ADMITTED = Patient admitted to institution DISCHARGED = Patient Discharged Describes the current known location of the patient Primary location where patient resides (ward, floor, room, etc. or outpatient) User-defined comments about the visit Patient's primary referring physician for this visit Referring physician's address Referring physician's telephone numbers Identification of the patient's referring physician. Only a single item shall be permitted in this sequence. Description of admitting diagnosis (diagnoses). A sequence that conveys the admitting diagnosis (diagnoses). One or more Items may be included in this Sequence. Mode of admission: emergency, normal Date patient visit began Time patient visit began One or more Scheduled Procedure Steps for one Requested Procedure. The AE title of the modality on which the Scheduled Procedure Step is scheduled to be performed. An institution defined name for the modality on which the Scheduled Procedure Step is scheduled to be performed. The location at which the Procedure Step is scheduled to be performed. Date on which the Scheduled Procedure Step is scheduled to start. Time at which the Scheduled Procedure Step is scheduled to start. Date on which the Scheduled Procedure Step is scheduled to end. Time at which the Scheduled Procedure Step is scheduled to end. Name of the physician scheduled to administer the Scheduled Procedure Step. Identification of the physician scheduled to administer the Scheduled Procedure Step. Only a single item shall be permitted in this sequence. Institution-generated description or classification of the Scheduled Procedure Step to be performed. Note: The purpose of this attribute is to store a description or classification that is used at a local level (e.g., a hospital or a managed care network), and this description need not comply to an accepted standard. Sequence describing the Scheduled Protocol following a specified coding scheme. This sequence contains one or more Items. Sequence that specifies the context for the Scheduled Protocol Code Sequence Item. One or more items may be included in this sequence. See Section C.4.10.1.
The Protocol Context Sequence (0040,0440) allows the specification of parameters that further qualify the scheduled protocol, provided through a set of generic name/value pairs of context Content Items. Note: This allows the specification of clinical, acquisition, or procedural qualifiers for the scheduled protocol, such as a specific body part, imaging technique, or parameters of a preparatory event (e.g., radionuclide injection). Specific uses of this Sequence may be documented in a Template defined in accordance with PS3.16.
Sequence that specifies modifiers for a Protocol Context Content Item. One or more items may be included in this sequence. See Section C.4.10.1.
The Protocol Context Sequence (0040,0440) allows the specification of parameters that further qualify the scheduled protocol, provided through a set of generic name/value pairs of context Content Items. Note: This allows the specification of clinical, acquisition, or procedural qualifiers for the scheduled protocol, such as a specific body part, imaging technique, or parameters of a preparatory event (e.g., radionuclide injection). Specific uses of this Sequence may be documented in a Template defined in accordance with PS3.16.
Identifier that identifies the Scheduled Procedure Step. A real world condition that may affect the selection of of the Scheduled Procedure Step. Defined Terms: SCHEDULED - Procedure Step scheduled ARRIVED - patient is available for the Scheduled Procedure Step READY - all patient and other necessary preparation for this step has been completed STARTED - at least one Performed Procedure Step has been created that references this Scheduled Procedure Step User-defined comments on the Scheduled Procedure Step. Note: The Comments attribute is intended to transmit non-structured information, which can be displayed to the operator of the Modality. Source equipment for the image. See Section C.7.3.1.1.1 for Defined Terms.
Defined Terms for the Modality (0008,0060) are: Retired Defined Terms for the Modality (0008,0060) are: Note: 1. The XA modality incorporates the retired modality DS. 2. The RF modality incorporates the retired modalities CF, DF, VF. 3. The modality listed in the Modality Data Element (0008,0060) may not match the name of the IOD in which it appears. For example, a SOP instance from XA IOD may list the RF modality when an RF implementation produces an XA object. 4. The MR modality incorporates the retired modalities MA and MS.
Contrast agent requested for use in the Scheduled Procedure Step. Medication to be administered at the beginning of the Scheduled Procedure Step, e.g. Nuclear Medicine radiopharmaceutical.
Identifier that identifies the Requested Procedure in the Imaging Service Request. Reason for requesting this imaging procedure. Note: This reason is more specific to the requested procedure than the reason mentioned in the imaging service request (0040,2001). User-defined comments on the Requested Procedure. Coded Reason for requesting this procedure. One or more sequence items may be present. A sequence that conveys the Requested Procedure of one Procedure Type. Unique identifier to be used to identify the Study Date the Study started, if any previous procedure steps within the same study have already been performed. Time the Study started, if any previous procedure steps within the same study have already been performed. Uniquely identifies the Study SOP Instances associated with this SOP Instance. Institution-generated administrative description or classification of Requested Procedure Requested Procedure Type Urgency. Defined Terms: STAT, HIGH, ROUTINE, MEDIUM, LOW Mode of transportation of the patient to the location of examination. Physical location at which the Requested Procedure is to be performed. Confidentiality Constraints on the Requested Procedure by the party filling the order. Requested Reporting Priority. Defined Terms: HIGH, ROUTINE, MEDIUM, LOW Names of the physicians, who are intended recipients of results. Identification of the physicians who are intended recipients of results. One or more items shall be included in this sequence. If more than one Item, the number and order shall correspond to the value of Names of Intended Recipients of Results (0040,1010), if present. User-defined comments on the Imaging Service Request. Note: The Comments attribute is intended to transmit non-structured information, which can be displayed to the operator of the equipment (e.g. Modality). Name of the physician who requested the Imaging Service Request. Identification of the physician who requested the Imaging Service Request. Only a single item shall be permitted in this sequence. Name of the patient's referring physician for this Imaging Service Request. Identification of the patient's referring physician. Only a single item shall be permitted in this sequence. Institutional department where the request initiated. A departmental IS generated number that identifies the order for the Imaging Service Request. Date on which the Imaging Service Request was issued by the requester. Time at which the Imaging Service Request was issued by the requester. The order number assigned to the Imaging Service Request by the party placing the order. The order number assigned to the Imaging Service Request by the party filling the order. The person who entered the Imaging Service Request into an Information System. The location at which the Imaging Service Request was entered. Telephone Number at which additional information can be retrieved. Identification number of the visit as assigned by the healthcare provider Name of healthcare provider that issued the Admission ID Patient's full legal name. Primary hospital identification number or code for the patient. Identifier of the Assigning Authority that issued the Patient ID. Date of birth of the named patient Sex of the named Patient. Enumerated Values: M = male F = female O = other Uniquely identifies the Patient SOP Instance. Identifier of the Service Episode as assigned by the healthcare provider Name of healthcare provider that issued the Service Episode ID Description of the type of service episode. Sequence containing attributes that are related to the scheduling of the Procedure Step. The Sequence may have one or more Items. Unique identifier for the Study. Uniquely identifies the Study SOP Instance associated with this Scheduled Procedure Step. This Sequence shall have only one Item. A departmental IS generated number that identifies the order for the Study. The order number assigned to the Imaging Service Request by the party placing the order. The order number assigned to the Imaging Service Request by the party filling the order. Identifier of the related Requested Procedure. Institution-generated administrative description or classification of Requested Procedure. A sequence that conveys the Procedure Type of the requested procedure. The Requested Procedure Code Sequence shall contain only a single item. Identifier of the related Scheduled Procedure Step. Institution-generated description or classification of the Scheduled Procedure Step to be performed. Sequence describing the Scheduled Protocol following a specific coding scheme. This sequence contains one or more Items. Sequence that specifies the context for the Scheduled Protocol Code Sequence Item. One or more items may be included in this sequence. See Section C.4.10.1.
The Protocol Context Sequence (0040,0440) allows the specification of parameters that further qualify the scheduled protocol, provided through a set of generic name/value pairs of context Content Items. Note: This allows the specification of clinical, acquisition, or procedural qualifiers for the scheduled protocol, such as a specific body part, imaging technique, or parameters of a preparatory event (e.g., radionuclide injection). Specific uses of this Sequence may be documented in a Template defined in accordance with PS3.16.
Sequence that specifies modifiers for a Protocol Context Content Item. One or more items may be included in this sequence. See Section C.4.10.1.
The Protocol Context Sequence (0040,0440) allows the specification of parameters that further qualify the scheduled protocol, provided through a set of generic name/value pairs of context Content Items. Note: This allows the specification of clinical, acquisition, or procedural qualifiers for the scheduled protocol, such as a specific body part, imaging technique, or parameters of a preparatory event (e.g., radionuclide injection). Specific uses of this Sequence may be documented in a Template defined in accordance with PS3.16.
AE title of the modality on which the Performed Procedure Step was performed. An institution defined name for the modality on which the Performed Procedure Step was performed. Description of the location at which the Performed Procedure Step was performed. Date on which the Performed Procedure Step started. Note: This value may be used to determine the earliest date to use as the Study Date (0008,0020) in composite instances and in updated Modality Scheduled Procedure Steps in order to allow Study level attributes to have consistent values if additional Procedure Steps are performed. Time at which the Performed Procedure Step started. Note: This value may be used to determine the earliest time to use as the Study Time (0008,0030) in composite instances and in updated Modality Scheduled Procedure Steps in order to allow Study level attributes to have consistent values if additional Procedure Steps are performed. User or equipment generated identifier of that part of a Procedure that has been carried out within this step. Date on which the Performed Procedure Step ended. Time at which the Performed Procedure Step ended. Contains the state of the Performed Procedure Step. Enumerated Values: IN PROGRESS = Started but not complete DISCONTINUED = Canceled or unsuccessfully terminated COMPLETED = Successfully completed Institution-generated description or classification of the Procedure Step that was performed. User-defined comments on the Performed Procedure Step. A description of the type of procedure performed. A sequence that conveys the (single) type of procedure performed. The reason the Performed Procedure Step Status (0040,0252) was set to DISCONTINUED. Type of equipment that originally acquired the data used to create the images associated with this Modality Performed Procedure Step. See C.7.3.1.1.1 for Defined Terms. Note: A Modality value in the created SOP Instances may be different from the MPPS Modality value. For example, multiple series may have been created during the MPPS (images, waveforms, softcopy presentation states and/or structured reports) with SOP Instances in different series having different modality values.
Defined Terms for the Modality (0008,0060) are: Retired Defined Terms for the Modality (0008,0060) are: Note: 1. The XA modality incorporates the retired modality DS. 2. The RF modality incorporates the retired modalities CF, DF, VF. 3. The modality listed in the Modality Data Element (0008,0060) may not match the name of the IOD in which it appears. For example, a SOP instance from XA IOD may list the RF modality when an RF implementation produces an XA object. 4. The MR modality incorporates the retired modalities MA and MS.
User or equipment generated Study Identifier. Sequence describing the Protocol performed for this Procedure Step. This sequence may have zero or more Items. Sequence that specifies the context for the Performed Protocol Code Sequence Item. One or more items may be included in this sequence. See Section C.4.10.1.
The Protocol Context Sequence (0040,0440) allows the specification of parameters that further qualify the scheduled protocol, provided through a set of generic name/value pairs of context Content Items. Note: This allows the specification of clinical, acquisition, or procedural qualifiers for the scheduled protocol, such as a specific body part, imaging technique, or parameters of a preparatory event (e.g., radionuclide injection). Specific uses of this Sequence may be documented in a Template defined in accordance with PS3.16.
Sequence that specifies modifiers for a Protocol Context Content Item. One or more items may be included in this sequence. See Section C.4.10.1.
The Protocol Context Sequence (0040,0440) allows the specification of parameters that further qualify the scheduled protocol, provided through a set of generic name/value pairs of context Content Items. Note: This allows the specification of clinical, acquisition, or procedural qualifiers for the scheduled protocol, such as a specific body part, imaging technique, or parameters of a preparatory event (e.g., radionuclide injection). Specific uses of this Sequence may be documented in a Template defined in accordance with PS3.16.
Attributes of the Series that comprise this Modality Performed Procedure Step. The Sequence may have zero or more Items. Name of the physician(s) administering this Series. Identification of the physician(s) administering the Series. One or more items shall be included in this sequence. If more than one Item, the number and order shall correspond to the value of Performing Physician's Name (0008,1050), if present. Name(s) of the operator(s) who supporting this Series. Identification of the operator(s) supporting the Series. One or more items shall be included in this sequence. If more than one Item, the number and order shall correspond to the value of Operators' Name (0008,1070), if present. User-defined description of the conditions under which the Series was performed. Note: This attribute conveys series-specific protocol identification and may or may not be identical to the one presented in the Performed Protocol Code Sequence (0040,0260). Unique Identifier of the Series. User provided description of the Series Title of the DICOM Application Entity where the Images and other Composite SOP Instances in this Series may be retrieved on the network. Note: The duration for which this location remains valid is unspecified. The instances in this series are expected to be archived in the long term archive. Defined Terms: NO, YES A Sequence that provides reference to Composite SOP Instances created during the acquisition of the procedure step. The sequence may have zero or more Items. Note: The use of Referenced Image Sequence is historical, and in this context it allows the reference of any Composite SOP Instance. Uniquely identifies instances, other than images, of any SOP Class that conforms to the DICOM Composite IOD Information Model, such as Waveforms, Presentation States or Structured Reports, created during the acquisition of the procedure step, and that are not referenced in Referenced Image Sequence (0008,1140). The sequence may have zero or more Items.
Anatomic structure, space or region that has been exposed to ionizing radiation. The sequence may have zero or one Items. Total duration of X-Ray exposure during fluoroscopy in seconds (pedal time) during this Performed Procedure Step. Total number of exposures made during this Performed Procedure Step. The number includes non-digital and digital exposures. Distance in mm from the source to detector center. Note: This value is traditionally referred to as Source Image Receptor Distance (SID). Distance in mm from the source to the surface of the patient closest to the source during this Performed Procedure Step. Note: This may be an estimated value based on assumptions about the patient's body size and habitus. Average entrance dose value measured in dGy at the surface of the patient during this Performed Procedure Step. Note: This may be an estimated value based on assumptions about the patient's body size and habitus. Average entrance dose value measured in mGy at the surface of the patient during this Performed Procedure Step. Note: This may be an estimated value based on assumptions about the patient's body size and habitus. Typical dimension of the exposed area at the detector plane. If Rectangular: row dimension followed by column; if Round: diameter. Measured in mm. Notes: 1. This may be an estimated value based on assumptions about the patient's body size and habitus. 2. This attribute is used in the X-Ray Acquisition Dose Module with units in cm (see Section C 8.7.8 Table C.8-33). Total area-dose-product to which the patient was exposed, accumulated over the complete Performed Procedure Step and measured in dGy*cm*cm, including fluoroscopy. Notes: 1. The sum of the area dose product of all images of a Series or a Study may not result in the total area dose product to which the patient was exposed. 2. This may be an estimated value based on assumptions about the patient's body size and habitus. User-defined comments on any special conditions related to radiation dose encountered during this Performed Procedure Step. Exposure Dose Sequence will contain Total Number of Exposures (0040,0301) items plus an item for each fluoroscopy episode not already counted as an exposure. Specifies X-Ray radiation mode. Enumerated Values: CONTINUOUS PULSED Peak kilo voltage output of the x-ray generator used. An average in the case of fluoroscopy (continuous radiation mode). X-Ray Tube Current in µA. An average in the case of fluoroscopy (continuous radiation mode). Time of x-ray exposure or fluoroscopy in msec. Type of filter(s) inserted into the X-Ray beam (e.g. wedges). See C.8.7.10 and C.8.15.3.9 (for enhanced CT) for Defined Terms.
This Module describes the attributes related to the filtration of X-Rays during the acquisition of an X-Ray image. Table C.8-35 X-RAY FILTRATION MODULE ATTRIBUTES
The X-Ray absorbing material used in the filter. May be multi-valued. See C.8.7.10 and C.8.15.3.9 (for enhanced CT) for Defined Terms.
This Module describes the attributes related to the filtration of X-Rays during the acquisition of an X-Ray image. Table C.8-35 X-RAY FILTRATION MODULE ATTRIBUTES
User-defined comments on any special conditions related to radiation dose encountered during during the episode described by this Exposure Dose Sequence Item.
Contains billing codes for the Procedure Type performed within the Procedure Step. The sequence may have zero or more Items. Information about the film consumption for this Performed Procedure Step. The sequence may have zero or more Items. Number of films actually printed. Type(s) of medium on which images were printed. For Defined Terms see Table C.13-1. Size(s) of film on which images were printed. For Defined Terms see Table C.13-3. Chemicals, supplies and devices for billing used in the Performed Procedure Step. The sequence may have one or more Items. Code values of chemicals, supplies or devices required for billing. The sequence may have zero or one Items. Sequence containing the quantity of used chemicals or devices. The sequence may have zero or one Items. Numerical quantity value. Unit of measurement. The sequence may have zero or one Items. Patient's full legal name. Primary hospital identification number or code for the patient. Identifier of the Assigning Authority that issued the Patient ID. Date of birth of the named patient. Sex of the named Patient. Enumerated Values: M = male F = female O = other The list of Requested Procedures the Procedure Step shall contribute to. One or more Items may be included in the sequence. Unique identifier for the Study. Uniquely identifies the Study SOP Instance that represents the Requested Procedure. Zero or one Item may be included in this sequence. Uniquely identifies the SOP Class. Uniquely identifies the SOP Instance. A departmental IS generated number that identifies the Imaging Service Request. A sequence that conveys the Procedure Type of the Requested Procedure. Zero or one Item may be included in this sequence. The order number assigned to the Imaging Service Request by the party placing the order. The order number assigned to the Imaging Service Request by the party filling the order. Identifier that identifies the Requested Procedure in the Imaging Service Request. Institution-generated description or classification of the Requested Procedure. Reason for requesting this procedure. Coded reason for requesting this procedure. User-defined comments on the Requested Procedure. Confidentiality Constraints on the Requested Procedure by the party filling the order. Names of the physicians, who are intended recipients of results. User-defined comments on the Imaging Service Request. Physician who requested the Imaging Service Request. Institutional department where the request initiated. Date on which the Imaging Service Request was issued by the requester. Time at which the Imaging Service Request was issued by the requester. Patient's primary physician for this Imaging Service Request. A status that informs the operator and the worklist management system about the progress of the scheduled General Purpose procedure step. Enumerated Values are: SCHEDULED, IN PROGRESS, SUSPENDED, COMPLETED, DISCONTINUED. See PS 3.4 for a detailed description of the meaning and usage of these values. Scheduled Procedure Step priority. Enumerated Values are: HIGH: used to indicate an urgent or emergent work item, equivalent to a STAT request. MEDIUM: used to indicate a work item that has a priority less than HIGH and higher than LOW. It can be used to further stratify work items. LOW: used to indicate a routine or non-urgent work item. Identifier that identifies the Scheduled General Purpose Procedure Step. Date and time when the General Purpose Scheduled Procedure Step was last modified or first created (whichever is most recent). Note: This attribute should be implicitly updated by the worklist management system whenever any modification is made to attributes of a General Purpose Scheduled Procedure Step. In particular, note that creation of General Purpose Performed Procedure Steps by a performing device can modify attributes of a related General Purpose Scheduled Procedure Step (e.g. the contents of Resulting General Purpose Performed Procedure Steps Sequence (0040,4015)). The list of processing application instances and/or application types on which the General Purpose Procedure Step is scheduled. Zero or more Items may be included in this sequence. Identifying name within the enterprise of the equipment for which the General Purpose Scheduled Procedure Step is scheduled. The name conveyed in the Code Value (0008,0100) may be the same as the AE Title, but does not have to be. Zero or more Items may be included in this sequence. Class of the equipment for which the General Purpose Scheduled Procedure Step is scheduled. Zero or more Items may be included in this sequence. Geographic location of the equipment for which the General Purpose Scheduled Procedure Step is scheduled. Zero or more Items may be included in this sequence. The list of human performers that are scheduled to be involved or responsible for performing the Workitem in the General Purpose Scheduled Procedure Step. Zero or more Items may be included in this sequence. Human performer that is involved or responsible for performing the Workitem. Only a single Item shall be permitted in this sequence. Name of the human performer. Organization to which the human performer is accountable for the activities in the Workitem. Date and time on which the General Purpose Scheduled Procedure Step is scheduled to start. Date on which the Procedure Step is expected to be completed. A sequence that conveys the code for the Workitem. Only a single Item shall be permitted in this sequence. User-defined comments on the Scheduled Procedure Step. List of any Modality or General Purpose Performed Procedure Steps, that may be used to perform the procedure step. This sequence may contain references to performed procedure steps resulting from previous contributions to the performance of the procedure step (e.g. an image processing procedure step interrupted, and completed later). Zero or more Items may be included in this sequence. Flag that indicates the availability of Composite SOP Instances in the Attribute "Input Information Sequence" (0040,4021) of the General Purpose Scheduled Procedure Step. Enumerated values are: PARTIAL COMPLETE The value PARTIAL denotes that the list of Composite SOP Instances may not yet be complete, and additional ones may be added at a later time. The value COMPLETE denotes that all Composite SOP Instances are available and listed. Note: It may happen that the list of Composite SOP Instances is empty when the value of the Input Availability Flag is COMPLETE. In such a case a Workitem has been scheduled that does not require input information. List of Composite SOP Instances that forms the input information needed to perform the scheduled procedure step. See also Input Availability Flag (0040,4020). The same Composite SOP Instance shall not be included in both the Input Information Sequence (0040,4021) and the Relevant Information Sequence (0040,4022). Zero or more Items may be included in this sequence. List of Composite SOP Instances that refers to relevant information that is considered pertinent for the performance of the scheduled procedure step. The same Composite SOP Instance shall not be included in both the Input Information Sequence (0040,4021) and the Relevant Information Sequence (0040,4022). Zero or more Items may be included in this sequence. Unique Study identification that shall be used for the created Composite SOP Instances resulting from this General Purpose Scheduled Procedure Step. Note: In most cases this will be the same Study Instance UID as for the instances in the Input Information Sequence (0040,4021). Date the Study started, if any previous procedure steps within the same study have already been performed. Note: This value should be the same as that in the instances in the Input Information Sequence (0040,4021). Time the Study started, if any previous procedure steps within the same study have already been performed. Note: This value should be the same as that in the instances in the Input Information Sequence (0040,4021). This flag indicates that multiple copies have to be made of a Composite SOP Instance that supports the notion of multiple copies. This includes the SR SOP Class. If set the Study Instance UIDs in the Referenced Request Sequence (0040,A370) shall be used for the created multiple copies. Enumerated Values: Y = Yes N = No List of all General Purpose Performed Procedure Steps that result from the performance of the procedure step. Zero or more Items may be included in this sequence. Note: Initially this list will be empty. New entries will be added when General Purpose Performed Procedure Steps are created by performing devices that are related to this Scheduled Procedure Step. E.g, this sequence may contain the partial results in case a General Purpose Scheduled Procedure Step is discontinued. The list of current human performers that are actually involved or responsible for performing the Workitem. Zero or more Items may be included in this sequence. Note: Initially this list will be empty. A list of entries may be created at the status transition of the General Purpose Scheduled Procedure Step Status (0040,4001) to "IN PROGRESS" Human performer that is involved or responsible for performing the Workitem. Only a single Item shall be permitted in this sequence. Name of the human performer. Organization to which the human performer is accountable for the activities in the Workitem. Patient's full legal name. Primary hospital identification number or code for the patient. Identifier of the Assigning Authority that issued the Patient ID. Date of birth of the named patient. Sex of the named Patient. Enumerated Values: M = male F = female O = other The list of Requested Procedures the Procedure Step shall contribute to. Zero or more Items may be included in the sequence. Unique identifier for the Study. Uniquely identifies the Study SOP Instance associated with this Scheduled Procedure Step. Only a single Item shall be permitted in this sequence. A departmental IS generated number that identifies the order for the Study. A sequence that conveys the Procedure Type of the Requested Procedure. Zero or one Item may be included in this sequence. The order number assigned to the Imaging Service Request by the party placing the order. The order number assigned to the Imaging Service Request by the party filling the order. Identifier of the related Requested Procedure. Institution-generated administrative description or classification of Requested Procedure. Uniquely identifies the General Purpose Scheduled Procedure Step SOP Instance associated with this General Purpose Performed Procedure Step. Zero or more Items may be included in this sequence. Transaction UID (0008,1195) used in the N-ACTION transaction that requested the transition to the IN PROGRESS state for the referenced General Purpose Scheduled Procedure Step. Identification number of the visit as assigned by the healthcare provider Name of healthcare provider that issued the Admission ID Identifier of the Service Episode as assigned by the healthcare provider Name of healthcare provider that issued the Service Episode ID Description of the type of service episode. The list of human performers that were actually involved in or responsible for performing this General Purpose Performed Procedure Step. Zero or more Items may be included in this sequence. Human performer that is actually involved or responsible for performing the General Purpose Performed Procedure Step. Only a single Item shall be permitted in this sequence. Name of the human performer. Organization to which the human performer is accountable for the activities in the General Purpose Performed Procedure Step. Name within the enterprise of the equipment that created the General Purpose Performed Procedure Step. This name may be the same as the AE Title, but does not have to be. Zero or one Item may be included in this sequence. Class of the equipment that created the General Purpose Performed Procedure Step. Zero or one Item may be included in this sequence. Geographic location of the equipment that created General Purpose Performed Procedure Step. Zero or one Item may be included in this sequence. The list of processing application instances and/or application types on which the General Purpose Performed Procedure Step is executed. Zero or more Items may be included in this sequence. Date on which the General Purpose Performed Procedure Step started. Note: This value may be used to determine the earliest date to use as the Study Date (0008,0020) in composite instances and in updated General Purpose Scheduled Procedure Steps in order to allow Study level attributes to have consistent values if additional Procedure Steps are performed. Time at which the General Purpose Performed Procedure Step started. Note: This value may be used to determine the earliest time to use as the Study Time (0008,0030) in composite instances and in updated General Purpose Scheduled Procedure Steps in order to allow Study level attributes to have consistent values if additional Procedure Steps are performed. User or equipment generated identifier of that part of a Procedure that has been carried out within this procedure step. Date on which the General Purpose Performed Procedure Step ended. Time at which the General Purpose Performed Procedure Step ended. Contains the state of the Performed Procedure Step. Enumerated Values: IN PROGRESS = Started but not complete DISCONTINUED = Canceled or unsuccessfully terminated COMPLETED = Successfully completed Institution-generated description or classification of the Procedure Step that was performed. User-defined comments on the Performed Procedure Step. This attribute shall not be used as a substitute for the code meaning in the Performed Workitem Code Sequence (0040,4019). A sequence that conveys the (single) type of procedure performed. Only a single Item shall be permitted in this sequence. A Sequence that provides reference to one or more Composite SOP instances, that identify the Structured Reports or other results created. Zero or more Items may be included in this sequence. Unique identifier for the Study Sequence of Items where each Item includes the Attributes of a Series containing referenced Composite Object(s). One or more Items may be included in this sequence The instances in this series are expected to be archived in the long term archive. Defined Terms: NO, YES A Sequence that provides suggested next Workitems, based on the produced results. Note: This Attribute may also be used in case a step has been done incorrectly and should be redone. Zero or more Items may be included in this sequence A Sequence that describes any non-DICOM output produced as results. Zero or more Items may be included in this sequence. Uniquely identifies the Performed Procedure Step SOP Instance to which this availability notification instance is related, if any. The Sequence shall have zero or one Item. Notes: 1. This may refer to a different PPS than that encoded in the composite instances themselves. 2. It is typically used for notification about instances created as a consequence of some scheduled activity. A sequence that conveys the (single) type of procedure performed. Only a single Item shall be permitted in this sequence. Unique identifier for the Study of which all the Instances referenced in this notification are part. Sequence of Items where each Item includes references to Instances within the same Series. One or more Items shall be included in this Sequence. Unique identifier of the Series of which all the Instances referenced in this Item are part. Sequence of Items where each Item includes a reference to a single Instance within this Series. One or more Items shall be included in this Sequence. The availability of the referenced Instance. See Section C.4.23.1.1
The Enumerated Values for Instance Availability (0008,0056) are:
Title of the DICOM Application Entity from which the referenced Instance may or may not be retrievable, i.e. the scope for which Instance Availability (0008,0056) applies. See Section C.4.23.1.1.
The Enumerated Values for Instance Availability (0008,0056) are:
The user or implementation specific human readable identifier that identifies the offline storage media on which the instance resides. Uniquely identifies the offline storage media on which the instance resides.
Patient's full name. Primary hospital identification number or code for the patient. Identifier of the Assigning Authority that issued the Patient ID. Birth date of the patient. Sex of the named patient. Enumerated Values: M = male F = female O = other A sequence that provides reference to a Patient SOP Class/Instance pair. Only a single Item shall be permitted in this Sequence. Birth time of the Patient. Other identification numbers or codes used to identify the patient. A sequence of identification numbers or codes used to identify the patient, which may or may not be human readable, and may or may not have been obtained from an implanted or attached device such as an RFID or barcode. If present, shall contain one or more items. An identification number or code used to identify the patient. Identifier of the Assigning Authority that issued the Patient ID. The type of identifier in this item. Defined Terms: TEXT RFID BARCODE Note: The identifier is coded as a string regardless of the type, not as a binary value. Other names used to identify the patient. Ethnic group or race of the patient. User-defined additional information about the patient. The species of the patient. Required if the patient is an animal and if Patient Species Code Sequence (0010,2202) is not present. May be present otherwise. The species of the patient. One Item shall be present. Required if the patient is an animal and if Patient Species Description (0010,2201) is not present. May be present otherwise. The breed of the patient. Required if the patient is an animal and if Patient Breed Code Sequence (0010,2293) is empty. May be present otherwise. The breed of the patient. Zero or more Items shall be present. Required if the patient is an animal. Information identifying an animal within a breed registry. Zero or more Items shall be present. Required if the patient is an animal. Identification number of an animal within the registry. Identification of the organization with which an animal is registered. One Item shall be present. Name of person with medical decision making authority for the patient. Required if the patient is an animal. May be present otherwise. Relationship of Responsible Person to the patient. Defined Terms: OWNER Required if Responsible Person is present and has a value. Name of organization with medical decision making authority for the patient. Required if patient is an animal. May be present otherwise. The true identity of the patient has been removed from the Attributes and the Pixel Data Enumerated Values: YES NO A description or label of the mechanism or method use to remove the patient's identity. May be multi-valued if successive de-identification steps have been performed. Note: This may be used to describe the extent or thoroughness of the de-identification, for example whether or not the de-identification is for a "Limited Data Set" (as per HIPAA Privacy Rule). Required if Patient Identity Removed (0012,0062) is present and has a value of YES and De-identification Method Code Sequence (0012,0064) is not present. A code describing the mechanism or method use to remove the patient's identity. One or more Items shall be present. Multiple items are used if successive de-identification steps have been performed Required if Patient Identity Removed (0012,0062) is present and has a value of YES and De-identification Method (0012,0063) is not present. A departmental Information System identifier that identifies the Accession. See Section C.7.1.2.1.1 for further explanation.
Specimen Accession Number (0040,050A) is the primary identifier of the Specimen. Note: Specimen Accession Number (0040,050A) identifies tissue or fluid obtained from a Patient in a Specimen-harvest procedure. This Attribute was created to differentiate Accession Numbers, as used in Anatomic Pathology to identify specimens, from other uses of the term “Accession Number” in Information Systems. The Specimen Accession Number (0040,050A) is typically unique within the scope of the institution in which the Accession is performed. An Accession may contain multiple Specimens. Typically, an Accession contains the Specimens obtained in one Specimen-harvest procedure and submitted by one Requesting Physician. However, multiple Specimen-harvest procedures may be involved.
Detailed description of one or more specimens. Zero or more Items may be included in this Sequence. A departmental information system identifier for the Specimen. See Section C.7.1.2.1.2 for further explanation.
Specimen Identifier (0040,0551) may be used to convey a slide number, a block number, or other secondary identifier of the Specimen. Note: The Specimen Identifier (0040,0551) is typically unique within the scope of the institution in which the related Accession is performed. However, a value of Specimen Identifier (0040,0551) does not always exist. For example, it is common practice in some Anatomic Pathology departments to use a Specimen Identifier (0040,0551) to identify specimen-containers or blocks only if multiple containers or blocks are submitted for a single Accession. Therefore, Specimen Identifier (0040,0551) is modeled as a Type 2 Attribute.
Specimen Type. Only a single Item shall be permitted in this Sequence. Required if Specimen Identifier (0040,0551) is sent with a value. Identifier of the Slide. Required if the Specimen is a Slide.
The name of the clinical trial sponsor. See C.7.1.3.1.1.
The Clinical Trial Sponsor Name (0012,0010) identifies the entity responsible for conducting the clinical trial and for defining the Clinical Trial Protocol ID (0012,0020).
Identifier for the noted protocol. See C.7.1.3.1.2.
The Clinical Trial Protocol ID (0012,0020) is the number or character sequence used by the Clinical Trial Sponsor to uniquely identify the investigational protocol in which the subject has been enrolled.
The name of the clinical trial protocol. See C.7.1.3.1.3.
The Clinical Trial Protocol Name (0012,0021) contains the title of the investigational protocol in which the subject has been enrolled. Note: It is recommended that the phase of the clinical trial be noted in the Clinical Trial Protocol Name, if applicable.
The identifier of the site responsible for submitting clinical trial data. See C.7.1.3.1.4.
The Clinical Trial Site ID (0012,0030) is the identification number or character string (issued by the entity identified by the Clinical Trial Sponsor Name (0012,0010)) used to identify the site responsible for submitting clinical trial data.
Name of the site responsible for submitting clinical trial data. See C.7.1.3.1.5
The Clinical Trial Site Name (0012,0031) is a character string used to identify the site responsible for submitting clinical trial data.
The assigned identifier for the clinical trial subject. See C.7.1.3.1.6. Shall be present if Clinical Trial Subject Reading ID (0012,0042) is absent. May be present otherwise.
The Clinical Trial Subject ID (0012,0040) identifies the subject within the investigational protocol specified by Clinical Trial Protocol ID (0012,0020).
Identifies the subject for blinded evaluations. Shall be present if Clinical Trial Subject ID (0012,0040) is absent. May be present otherwise. See C.7.1.3.1.7.
The Clinical Trial Subject Reading ID (0012,0042) identifies the subject in the context of blinded evaluations.
Unique identifier for the Study. Date the Study started. Time the Study started. Name of the patient's referring physician Identification of the patient's referring physician. Only a single item shall be permitted in this sequence. User or equipment generated Study identifier. A RIS generated number that identifies the order for the Study. Institution-generated description or classification of the Study (component) performed. Names of the physician(s) who are responsible for overall patient care at time of Study (see Section C.7.3.1 for Performing Physician) Identification of the physician(s) who are responsible for overall patient care at time of Study. One or more items shall be included in this sequence. If more than one Item, the number and order shall correspond to the value of Physician(s) of Record (0008,1048), if present. Names of the physician(s) reading the Study. Identification of the physician(s) reading the Study. One or more items shall be included in this sequence. If more than one Item, the number and order shall correspond to the value of Name of Physician(s) Reading Study (0008,1060), if present. A sequence that provides reference to a Study SOP Class/Instance pair. The sequence may have zero or more Items. A Sequence that conveys the type of procedure performed. One or more Items may be included in this Sequence. Description of the admitting diagnosis (diagnoses) A sequence that conveys the admitting diagnosis (diagnoses). One or more Items may be included in this Sequence. Age of the Patient. Length or size of the Patient, in meters. Weight of the Patient, in kilograms. Occupation of the Patient. Additional information about the Patient's medical history. Identification number of the visit as assigned by the healthcare provider Name of healthcare provider that issued the Admission ID Identifier of the Service Episode as assigned by the healthcare provider Name of healthcare provider that issued the Service Episode ID Description of the type of service episode. Whether or not a procedure has been performed in an effort to render the patient sterile. Enumerated value: ALTERED = Altered/Neutered UNALTERED = Unaltered/intact Note: If this Attribute is present but has no value then the status is unknown. Required if patient is an animal. May be present otherwise. An identifier specifying the one or more studies that are grouped together as a clinical time point or submission in a clinical trial. See C.7.2.3.1.1.
The Clinical Trial Time Point ID (0012,0050) attribute identifies an imaging study within the context of an investigational protocol. This attribute is used to define a set of studies that are grouped together as a clinical time point or data submission in a clinical trial. The Clinical Trial Time Point Description (0012,0051) attribute can be used to give a description of the Clinical Trial Time Point to which the set of studies belongs.
A description of a set of one or more studies that are grouped together to represent a clinical time point or submission in a clinical trial. See C.7.2.3.1.1.
The Clinical Trial Time Point ID (0012,0050) attribute identifies an imaging study within the context of an investigational protocol. This attribute is used to define a set of studies that are grouped together as a clinical time point or data submission in a clinical trial. The Clinical Trial Time Point Description (0012,0051) attribute can be used to give a description of the Clinical Trial Time Point to which the set of studies belongs.
Type of equipment that originally acquired the data used to create the images in this Series. See C.7.3.1.1.1 for Defined Terms.
Defined Terms for the Modality (0008,0060) are: Retired Defined Terms for the Modality (0008,0060) are: Note: 1. The XA modality incorporates the retired modality DS. 2. The RF modality incorporates the retired modalities CF, DF, VF. 3. The modality listed in the Modality Data Element (0008,0060) may not match the name of the IOD in which it appears. For example, a SOP instance from XA IOD may list the RF modality when an RF implementation produces an XA object. 4. The MR modality incorporates the retired modalities MA and MS.
Unique identifier of the Series. A number that identifies this Series. Laterality of (paired) body part examined. Required if the body part examined is a paired structure and Image Laterality (0020,0062) or Frame Laterality (0020,9072) are not sent. Enumerated Values: R = right L = left Note: Some IODs support Image Laterality (0020,0062) at the Image level or Frame Laterality(0020,9072) at the Frame level in the Frame Anatomy functional group macro, which can provide a more comprehensive mechanism for specifying the laterality of the body part(s) being examined. Date the Series started. Time the Series started. Name of the physician(s) administering the Series. Identification of the physician(s) administering the Series. One or more items shall be included in this sequence. If more than one Item, the number and order shall correspond to the value of Performing Physicians' Name (0008,1050), if present. User-defined description of the conditions under which the Series was performed. Note: This attribute conveys series-specific protocol identification and may or may not be identical to the one presented in the Performed Protocol Code Sequence (0040,0260). User provided description of the Series Name(s) of the operator(s) supporting the Series. Identification of the operator(s) supporting the Series. One or more items shall be included in this sequence. If more than one Item, the number and order shall correspond to the value of Operators' Name (0008,1070), if present. Uniquely identifies the Performed Procedure Step SOP Instance to which the Series is related (e.g. a Modality or General-Purpose Performed Procedure Step SOP Instance). The Sequence shall have zero or one Item. Identification of Series significantly related to this Series. Zero or more Items may be present. Notes: 1. For example, for a combined CT and PET acquisition, the CT images and PET images would be in separate series that could cross-reference each other with multiple purpose of reference codes meaning same anatomy, simultaneously acquired and same indication. 2. The related series may have different Frames of Reference and hence require some sort of registration before spatial coordinates can be directly compared. 3. This attribute is not intended for conveying localizer reference information, for which Referenced Image Sequence (0008,1140) should be used. Instance UID of Study to which the related Series belongs Instance UID of Related Series Describes the purpose for which the reference is made. Zero or more Items may be present. When absent, implies that the reason for the reference is unknown. Text description of the part of the body examined. See PS 3.16 Annex on Correspondence of Anatomic Region Codes and Body Part Examined for Defined Terms Note: Some IODs support the Anatomic Region Sequence (0008,2218), which can provide a more comprehensive mechanism for specifying the body part being examined. Patient position descriptor relative to the equipment. Required for CT and MR images; shall not be present if Patient Orientation Code Sequence (0054,0410) is present; may be present otherwise. See C.7.3.1.1.2 for Defined Terms and further explanation.
Patient Position (0018,5100) specifies the position of the patient relative to the imaging equipment space. This attribute is intended for annotation purposes only. It does not provide an exact mathematical relationship of the patient to the imaging equipment. When facing the front of the imaging equipment, Head First is defined as the patient’s head being positioned toward the front of the imaging equipment. Feet First is defined as the patient’s feet being positioned toward the front of the imaging equipment. Prone is defined as the patient’s face being positioned in a downward (gravity) direction. Supine is defined as the patient’s face being in an upward direction. Decubitus Right is defined as the patient’s right side being in a downward direction. Decubitus Left is defined as the patient’s left side being in a downward direction. The Defined Terms are:
The minimum value of all images in this Series. The maximum value of all images in this Series. Sequence that contains attributes from the Imaging Service Request. The sequence may have one or more Items.
The name of the institution that is responsible for coordinating the medical imaging data for the clinical trial. See C.7.3.2.1.1.
The Clinical Trial Coordinating Center Name (0012,0060) identifies the institution responsible for coordinating the collection of images and associated data for subjects enrolled in the clinical trial.
An identifier of the series in the context of a clinical trial. See C.7.3.2.1.2.
The Clinical Trial Series ID (0012,0071) and Clinical Trial Series Description (0012,0072) attributes can be used to identify and describe a Series within the context of a clinical trial without requiring the replacement of the values in the Series Number (0020,0011) and Series Description (0008,103E) attributes in the General Series Module, whose manufacturer or user provided values may be relevant and important to retain.
A description of the series in the context of a clinical trial. See C.7.3.2.1.2.
The Clinical Trial Series ID (0012,0071) and Clinical Trial Series Description (0012,0072) attributes can be used to identify and describe a Series within the context of a clinical trial without requiring the replacement of the values in the Series Number (0020,0011) and Series Description (0008,103E) attributes in the General Series Module, whose manufacturer or user provided values may be relevant and important to retain.
A number that identifies this Series. Notes: 1. The value of this attribute should be unique for all series in a study created on the same equipment. 2. Because series can be created on more than one equipment, it can not be guaranteed that the value of Series Number (0020,0011) is unique in a study. Uniquely identifies the Performed Procedure Step SOP Instance to which the Series is related (e.g. a Modality or General-Purpose Performed Procedure Step SOP Instance). Only a single Item is permitted in this sequence. Required if the Modality Performed Procedure Step SOP Class or General Purpose Performed Procedure Step SOP Class is supported. Uniquely identifies the frame of reference for a Series. See C.7.4.1.1.1 for further explanation.
The Frame of Reference UID (0020,0052) shall be used to uniquely identify a frame of reference for a series. Each series shall have a single Frame of Reference UID. However, multiple Series within a Study may share a Frame of Reference UID. All images in a Series that share the same Frame of Reference UID shall be spatially related to each other. Notes: 1. Previous versions of this Standard defined a Data Element "Location", which has been retired. Frame of Reference UID provides a completely unambiguous identification of the image location reference used to indicate position. 2. A common Frame of Reference UID may be used to spatially relate localizer images with a set of transverse images. However, in some cases (eg. multiple localizer images being related to a single set of transverse images) a common Frame of Reference UID may not be sufficient. The Referenced Image Sequence (0008,1140) provides an unambiguous method for relating localizer images.
Part of the patient's anatomy used as a reference, such as the iliac crest, orbital-medial, sternal notch, symphysis pubis, xiphoid, lower coastal margin, external auditory meatus. See C.7.4.1.1.2 for further explanation.
The Position Reference Indicator (0020,1040) specifies the part of the patient’s anatomy that was used as an anatomical reference point associated with a specific Frame of Reference UID. The Position Reference Indicator may or may not coincide with the origin of the fixed frame of reference related to the Frame of Reference UID. The Position Reference Indicator shall be used only for annotation purposes and is not intended to be used as a mathematical spatial reference. Note: The Position Reference Indicator may be sent zero length when it has no meaning, for example, when the Frame of Reference Module is required to relate mammographic images of the breast acquired without releasing breast compression, but where there is no meaningful anatomical reference point as such.
UID of common synchronization environment. See C.7.4.2.1.1.
A set of equipment may share a common acquisition synchronization environment, which is identified by a Synchronization Frame of Reference UID. All SOP Instances that share the same Synchronization Frame of Reference UID shall be temporally related to each other. If a Synchronization Frame of Reference UID is present, all SOP Instances in the Series must share the same Frame of Reference. The UTC Synchronization UID, 1.2.840.10008.15.1.1, may be used when the equipment is synchronized to the international standard UTC. In this case the quality of synchronization may be determined by means of the Time Distribution Protocol (0018,1802) and NTP Source Address (0018,1803). Notes: 1. The Synchronization Frame of Reference UID defines an equipment synchronization environment, and does not need to be changed for each unrelated acquisition. SOP Instances may therefore share a Synchronization Frame of Reference UID, but be clinically unrelated (e.g., apply to different patients). 2. When a synchronization environment is recalibrated, a new UID must be issued. 3. The method of distributing the Synchronization Frame of Reference UID to multiple devices is not specified.
Data acquisition synchronization with external equipment Enumerated Values: SOURCE - this equipment provides synchronization channel or trigger to other equipment EXTERNAL - this equipment receives synchronization channel or trigger from other equipment PASSTHRU - this equipment receives synchronization channel or trigger and forwards it NO TRIGGER - data acquisition not synchronized by common channel or trigger Specifies equipment ID of trigger source and/or type of trigger Identifier of waveform channel that records the synchronization channel or trigger, see C.7.4.2.1.3. Required if synchronization channel or trigger is encoded in a waveform in this SOP Instance Acquisition DateTime (0008,002A) synchronized with external time reference. Enumerated Values: Y, N See C.7.4.2.1.4
The Acquisition Time Synchronized (0018,1800) attribute specifies whether the Acquisition DateTime (0008,002A) attribute of the Waveform Identification Module or the General Image Module represents an accurate synchronized timestamp for the acquisition of the waveform and/or image data. For triggered multi-frame images, the Acquisition DateTime applies to the trigger for the first image frame (see attribute Image Trigger Delay (0018.1067) in the Cine Module). Note: The degree of precision of the Acquisition DateTime and its accuracy relative to the external clock are not specified, but need to be appropriate for the clinical application. For IODs that include the SR Document Content Module, the Acquisition Time Synchronized (0018,1800) attribute specifies whether the Observation DateTime (0040,A032) attribute of Items in the Content Sequence (0040,A730) of the SR Document Content Module represents an accurate synchronized timestamp for the Item.
ID of equipment or system providing time reference Method of time distribution used to synchronize this equipment. Defined Terms: NTP - Network Time Protocol IRIG - InterRange Instrumentation Group GPS - Global Positioning System SNTP - Simple Network Time Protocol IP Address of NTP time source. IPv4 addresses shall be in dotted decimal (e.g. 192.168.1.1). The IPv6 addresses shall be in colon separated hexadecimal (e.g. 12:34:56:78:9a:bc:de:f0). Note: Identity of this value in two instances acquired contemporaneously implies a common time base. The NTP Source Address may not persist over time.
Manufacturer of the equipment that produced the composite instances. Institution where the equipment that produced the composite instances is located. Mailing address of the institution where the equipment that produced the composite instances is located. User defined name identifying the machine that produced the composite instances. Department in the institution where the equipment that produced the composite instances is located. Manufacturer's model name of the equipment that produced the composite instances. Manufacturer's serial number of the equipment that produced the composite instances. Note: This identifier corresponds to the device that actually created the images, such as a CR plate reader or a CT console, and may not be sufficient to identify all of the equipment in the imaging chain, such as the generator or gantry or plate. Manufacturer's designation of software version of the equipment that produced the composite instances. Identifier of the gantry or positioner. The inherent limiting resolution in mm of the acquisition equipment for high contrast objects for the data gathering and reconstruction technique chosen. If variable across the images of the series, the value at the image center. Date when the image acquisition device calibration was last changed in any way. Multiple entries may be used for additional calibrations at other times. See C.7.5.1.1.1 for further explanation.
Date of Last Calibration (0018,1200) and Time of Last Calibration (0018,1201) are used to convey the date and time of calibration. The Attribute Date of Last Calibration (0018,1200) may be supported alone, however, Time of Last Calibration (0018,1201) Attribute has no meaning unless Attribute Date of Last Calibration (0018,1200) is also supported. The order for each Attribute shall be from the oldest date/time to the most recent date/time. When the Attributes are both supported they shall be provided as pairs.
Time when the image acquisition device calibration was last changed in any way. Multiple entries may be used. See C.7.5.1.1.1 for further explanation.
Date of Last Calibration (0018,1200) and Time of Last Calibration (0018,1201) are used to convey the date and time of calibration. The Attribute Date of Last Calibration (0018,1200) may be supported alone, however, Time of Last Calibration (0018,1201) Attribute has no meaning unless Attribute Date of Last Calibration (0018,1200) is also supported. The order for each Attribute shall be from the oldest date/time to the most recent date/time. When the Attributes are both supported they shall be provided as pairs.
Single pixel value or one limit (inclusive) of a range of pixel values used in animage to pad to rectangular format or to signal background that may be suppressed. See C.7.5.1.1.2 for further explanation. Required if Pixel Padding Range Limit (0028,0121) is present. May be present otherwise. Note: The Value Representation of this Attribute is determined by the value of Pixel Representation (0028,0103).
Pixel Padding Value (0028,0120) is used to pad grayscale images (those with a Photometric Interpretation of MONOCHROME1 or MONOCHROME2)to rectangular format. The native format of some images is not rectangular. It is common for devices with this format to pad the images to the rectangular format required by the DICOM Standard with a specific pixel value that is not contained in the native image. Further, when resampling, such as after spatial registration, padding may need to be used to fill previously non-existent pixels. Pixel Padding Value (0028,0120) and Pixel Padding Range Limit (0028,0121) are also used to identify pixels to be excluded from the normal grayscale rendering pipeline for other reasons, such as suppression of background air. Pixel Padding Range Limit (0028,0121) is defined in the Image Pixel Module. Notes: 1. The “native image” is that which is being padded to the required rectangular format, e.g., the area within the circular reconstruction perimeter of a CT image, or the subset of the rectangular area that contains useful image information. 2. The pixel padding value is explicitly described in order to prevent display applications from taking it into account when determining the dynamic range of an image, since the Pixel Padding Value will be outside the range between the minimum and maximum values of the pixels in the native image 3. No pixels in the native image will have a value equal to Pixel Padding Value. Pixel Padding Value (0028,0120) specifies either a single value of this padding value, or when combined with Pixel Padding Range Limit (0028,0121), a range of values (inclusive) that are padding. The values of Pixel Padding Value (0028,0120) and Pixel Padding Range Limit (0028,0121) shall be valid values within the constraints defined by Bits Allocated (0028,0100), Bits Stored (0028,0101), and High Bit (0028,0102). Pixel Padding Value (0028,0120) and Pixel Padding Range Limit (0028,0121) shall not be present when padding is performed but the pixel value used for padding does occur in the native image. If Photometric Interpretation (0028,0004) is MONOCHROME2, Pixel Padding Value (0028,0120) shall be less than (closer to or equal to the minimum possible pixel value) or equal to Pixel Padding Range Limit (0028,0121). If Photometric Interpretation (0028,0004) is MONOCHROME1, Pixel Padding Value (0028,0120) shall be greater than (closer to or equal to the maximum possible pixel value) or equal to Pixel Padding Range Limit (0028,0121). Notes: 1. When the relationship between pixel value and X-Ray Intensity is unknown, it is recommended that the following values be used to pad with black when the image is unsigned: 0 if Photometric Interpretation (0028,0004) is MONOCHROME2. 2BitsStored - 1 if Photometric Interpretation (0028,0004) is MONOCHROME1. and when the image is signed: -2BitsStored-1 if Photometric Interpretation (0028,0004) is MONOCHROME2. 2BitsStored-1 - 1 if Photometric Interpretation (0028,0004) is MONOCHROME1. 2. For projection radiography, when the relationship between pixel value and X-Ray Intensity is known (for example as defined by Pixel Intensity Relationship (0028,1040) and Pixel Intensity relationship Sign (0028,1041)), it is recommended that a pixel value equivalent to, or rendered similarly to, air (least X-Ray absorbance) be used for padding. However, if such a value may occur in the native image, the Pixel Padding Value (0028,0120) Attribute itself should not be sent. E.g., for an XRF image obtained with an image intensifier, if air is black then a padded perimeter, if any, should also appear black. Typically though, if unpadded, this area would be collimated with a circular collimator, in which case the pixels would appear natively as white (greatest X-Ray absorbance) and a circular shutter would be necessary to neutralize them as black. Whether collimated areas are detected and treated as padded, or neutralized with shutters is at the discretion of the application. See also the Display Shutter Module C.7.6.11. 3. The conditional requirement for the Pixel Padding Value Range Limit (0028,0121) in the Image Pixel Module means that it shall not be present unless Pixel Padding Value (0028,0120) is also present. 4. The range of values to be suppressed between Pixel Padding Value (0028,0120) and Pixel Padding Value Range Limit (0028,0121) is specified as being inclusive, that is the values themselves as well as all values between are suppressed. 5. When Pixel Padding Value Range Limit (0028,0121) is present, but not supported by a rendering application, the constraint that Pixel Padding Value (0028,0120) is closest to the “blackest” value, which is typically the most frequently occurring background pixel, will most often result in an acceptable display, permitting “backward compatibility” in the majority of cases. When modifying equipment changes the pixel padding value in the image, it shall change the values of Pixel Padding Value (0028,0120) and Pixel Padding Range Limit (0028,0121), if present. If modifying equipment changes the pixel padding values in the image to values present in the native image, the attribute Pixel Padding Value (0028,0120) and Pixel Padding Range Limit (0028,0121) shall be removed. Notes: 1. For example, if a CT image containing signed values from -1024 to 3191 and a Pixel Padding Value of -2000 and a Rescale Intercept of 0 is converted to an unsigned image with a Rescale Intercept of -1024 by adding 1024 to all pixels and clipping all more negative pixels to 0, then the padding pixels will be indistinguishable from some of the modified native image pixels, and hence Pixel Padding Value (0028,0120) needs to be removed. 2. If the modification involves lossy compression, which may result in changes to the pixel values, then the application of Pixel Padding Value and Pixel Padding Range Limit may result in a different appearance, and hence these attributes may need different values also.
Manufacturer of the equipment that produced the composite instances. Manufacturer's model name of the equipment that produced the composite instances. Manufacturer's serial number of the equipment that produced the composite instances. Manufacturer's designation of software version of the equipment that produced the composite instances. A number that identifies this image. Note: This Attribute was named Image Number in earlier versions of this Standard. Patient direction of the rows and columns of the image. Required if image does not require Image Orientation (Patient) (0020,0037) and Image Position (Patient) (0020,0032). See C.7.6.1.1.1 for further explanation. Note: IOD's may have attributes other than Patient Orientation, Image Orientation, or Image Position (Patient) to describe orientation in which case this attribute will be zero length.
The Patient Orientation (0020,0020) relative to the image plane shall be specified by two values that designate the anatomical direction of the positive row axis (left to right) and the positive column axis (top to bottom). The first entry is the direction of the rows, given by the direction of the last pixel in the first row from the first pixel in that row. The second entry is the direction of the columns, given by the direction of the last pixel in the first column from the first pixel in that column. Anatomical direction shall be designated by the capital letters: A (anterior), P (posterior), R (right), L (left), H (head), F (foot). Each value of the orientation attribute shall contain at least one of these characters. If refinements in the orientation descriptions are to be specified, then they shall be designated by one or two additional letters in each value. Within each value, the letters shall be ordered with the principal orientation designated in the first character.
The date the image pixel data creation started. Required if image is part of a series in which the images are temporally related. Note: This Attribute was formerly known as Image Date. The time the image pixel data creation started. Required if image is part of a series in which the images are temporally related. Image identification characteristics. See C.7.6.1.1.2 for Defined Terms and further explanation.
The Image Type (0008,0008) Attribute identifies important image identification characteristics. These characteristics are: a. Pixel Data Characteristics 1. is the image an ORIGINAL Image; an image whose pixel values are based on original or source data 2. is the image a DERIVED Image; an image whose pixel values have been derived in some manner from the pixel value of one or more other images b. Patient Examination Characteristics 1. is the image a PRIMARY Image; an image created as a direct result of the Patient examination 2. is the image a SECONDARY Image; an image created after the initial Patient examination c. Modality Specific Characteristics d. Implementation specific identifiers; other implementation specific identifiers shall be documented in an implementation's conformance statement. The Image Type attribute is multi-valued and shall be provided in the following manner: a. Value 1 shall identify the Pixel Data Characteristics; Enumerated Values for the Pixel Data Characteristics are: ORIGINAL identifies an Original Image DERIVED identifies a Derived Image b. Value 2 shall identify the Patient Examination Characteristics; Enumerated Values for the Patient Examination Characteristics are: PRIMARY identifies a Primary Image SECONDARY identifies a Secondary Image c. Value 3 shall identify any Image IOD specific specialization (optional) d. Other Values which are implementation specific (optional) Any of the optional values (value 3 and beyond) may be sent either with a value or zero-length, independent of other optional values, unless otherwise specified by a specialization of this attribute in an IOD. If the pixel data of the derived Image is different from the pixel data of the source images and this difference is expected to affect professional interpretation of the image, the Derived Image shall have a UID different than all the source images.
A number identifying the single continuous gathering of data over a period of time that resulted in this image. The date the acquisition of data that resulted in this image started The time the acquisition of data that resulted in this image started The date and time that the acquisition of data that resulted in this image started. Note: The synchronization of this time with an external clock is specified in the Synchronization Module in Acquisition Time Synchronized (0018,1800). A sequence that references other images significantly related to this image (e.g. post-localizer CT image or Mammographic biopsy or partial view images). One or more Items may be included in this sequence. Describes the purpose for which the reference is made. Only a single Item shall be permitted in this sequence. A text description of how this image was derived. See C.7.6.1.1.3 for further explanation.
If an Image is identified to be a derived image (see C.7.6.1.1.2 Image Type), Derivation Description (0008,2111) and Derivation Code Sequence (0008,9215) describe the way in which the image was derived. They may be used whether or not the Source Image Sequence (0008,2112) is provided. They may also be used in cases when the Derived Image pixel data is not significantly changed from one of the source images and the SOP Instance UID of the Derived Image is the same as the one used for the source image. Notes: 1. Examples of Derived Images that would normally be expected to affect professional interpretation and would thus have a new UID include: a. images resulting from image processing of another image (e.g. unsharp masking), b. a multiplanar reformatted CT image, c. a DSA image derived by subtracting pixel values of one image from another. d. an image that has been decompressed after having been compressed with a lossy compression algorithm. To ensure that the user has the necessary information about the lossy compression, the approximate compression ratio may be included in Derivation Description (0008,2111). An example of a Derived Image that would normally not be expected to affect professional interpretation and thus would not require a new UID is an image that has been padded with additional rows and columns for more display purposes. 2. An image may be lossy compressed, e.g., for long term archive purposes, and its SOP Instance UID changed. PS3.4 provides a mechanism by which a query for the original image Instance may return a reference to the UID of the lossy compressed version of the image using the Alternate Representation Sequence (0008,3001). This allows an application processing a SOP Instance that references the original image UID, e.g., a Structured Report, to obtain a reference to an accessible version of the image even if the original SOP Instance is no longer available.
A coded description of how this image was derived. See C.7.6.1.1.3 for further explanation. One or more Items may be included in this Sequence. More than one Item indicates that successive derivation steps have been applied.
If an Image is identified to be a derived image (see C.7.6.1.1.2 Image Type), Derivation Description (0008,2111) and Derivation Code Sequence (0008,9215) describe the way in which the image was derived. They may be used whether or not the Source Image Sequence (0008,2112) is provided. They may also be used in cases when the Derived Image pixel data is not significantly changed from one of the source images and the SOP Instance UID of the Derived Image is the same as the one used for the source image. Notes: 1. Examples of Derived Images that would normally be expected to affect professional interpretation and would thus have a new UID include: a. images resulting from image processing of another image (e.g. unsharp masking), b. a multiplanar reformatted CT image, c. a DSA image derived by subtracting pixel values of one image from another. d. an image that has been decompressed after having been compressed with a lossy compression algorithm. To ensure that the user has the necessary information about the lossy compression, the approximate compression ratio may be included in Derivation Description (0008,2111). An example of a Derived Image that would normally not be expected to affect professional interpretation and thus would not require a new UID is an image that has been padded with additional rows and columns for more display purposes. 2. An image may be lossy compressed, e.g., for long term archive purposes, and its SOP Instance UID changed. PS3.4 provides a mechanism by which a query for the original image Instance may return a reference to the UID of the lossy compressed version of the image using the Alternate Representation Sequence (0008,3001). This allows an application processing a SOP Instance that references the original image UID, e.g., a Structured Report, to obtain a reference to an accessible version of the image even if the original SOP Instance is no longer available.
A Sequence that identifies the set of Image SOP Class/Instance pairs of the Images that were used to derive this Image. Zero or more Items may be included in this Sequence. See C.7.6.1.1.4 for further explanation.
If an Image is identified to be a Derived image (see C.7.6.1.1.2 Image Type), Source Image Sequence (0008,2112) is an optional list of Referenced SOP Class UID (0008,1150)/ Referenced SOP Instance UID (0008,1150) pairs that identify the source images used to create the Derived image. It may be used whether or not there is a description of the way the image was derived in Derivation Description (0008,2111) or Derivation Code Sequence (0008,9215). Note: Multiple Items may be present within Source Image Sequence (0008,2112), in which case either: a) those images were combined to make the derived image (e.g. multiple source images to make an MPR or MIP), or b) each of the items represents a step in the successive derivation of an image (e.g. when an image has had successive lossy compression steps applied to it), c) some combination of the above. The Purpose of Reference Code Sequence (0040,A170) and the Attributes within the referenced images themselves may be used to determine the history of the derivation, which is not otherwise explicitly specified.
Describes the purpose for which the reference is made, that is what role the source image or frame(s) played in the derivation of this image. Only a single Item shall be permitted in this sequence. The extent to which the spatial locations of all pixels are preserved during the processing of the source image that resulted in the current image Enumerated Values: YES NO REORIENTED_ONLY - A projection radiograph that has been flipped, and/or rotated by a multiple of 90 degrees Notes: 1. This applies not only to images with a known relationship to a 3D space, but also to projection images. For example, a projection radiograph such as a mammogram that is processed by a point image processing operation such as contrast enhancement, or a smoothing or edge enhancing convolution, would have a value of YES for this attribute. A projection radiograph that had been magnified or warped geometrically would have a value of NO for this attribute. A projection radiograph that has been flipped, and/or rotated by a multiple of 90 degrees, such that transformation of pixel locations is possible by comparison of the values of Patient Orientation (0020,0020) would have a value of REORIENTED_ONLY. This attribute is typically of importance in relating images with Presentation Intent Type (0008,0068) values of FOR PROCESSING and FOR PRESENTATION. 2. When the value of this attribute is NO, it is not possible to locate on the current image any pixel coordinates that are referenced relative to the source image, such as for example, might be required for rendering CAD findings derived from a referenced FOR PROCESSING image on the current FOR PRESENTATION image. The Patient Orientation values of the source image. Required if the value of Spatial Locations Preserved (0028,135A) is REORIENTED_ONLY. A sequence which provides reference to a set of non-image SOP Class/Instance pairs significantly related to this Image, including waveforms that may or may not be temporally synchronized with this image . One or more Items may be included in this sequence. Code describing the purpose of the reference to the Instance(s). Only a single Item shall be permitted in this sequence. Number of images that resulted from this acquisition of data User-defined comments about the image Indicates whether or not this image is a quality control or phantom image. Enumerated Values: YES NO If this Attribute is absent, then the image may or may not be a quality control or phantom image. The phantom device in the image can be described using the Device Module. See C.7.6.12
Table C.7-18 describes the Attributes of devices or calibration objects (e.g., catheters, markers, baskets) that are associated with a study and/or image. Table C.7-18 DEVICE MODULE ATTRIBUTES
Indicates whether or not image contains sufficient burned in annotation to identify the patient and date the image was acquired. Enumerated Values: YES NO If this Attribute is absent, then the image may or may not contain burned in annotation. Specifies whether an Image has undergone lossy compression. Enumerated Values: 00 = Image has NOT been subjected to lossy compression. 01 = Image has been subjected to lossy compression. See C.7.6.1.1.5
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
Describes the approximate lossy compression ratio(s) that have been applied to this image. See C.7.6.1.1.5 for further explanation. May be multivalued if successive lossy compression steps have been applied. Notes: 1. For example, a compression ratio of 30:1 would be described in this Attribute with a single value of 30. 2. For historical reasons, the lossy compression ratio may also be described in Derivation Description (0008,2111).
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
A label for the lossy compression method(s) that have been applied to this image. See C.7.6.1.1.5 for further explanation. May be multivalued if successive lossy compression steps have been applied; the value order shall correspond to the values of Lossy Image Compression Ratio (0028,2112). Note: For historical reasons, the lossy compression method may also be described in Derivation Description (0008,2111).
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
This icon image is representative of the Image. Only a single Item shall be permitted in this Sequence. When present, specifies an identity transformation for the Presentation LUT such that the output of all grayscale transformations, if any, are defined to be in P-Values. Enumerated Values are: IDENTITY - output is in P-Values - shall be used if Photometric Interpretation (0028,0004) is MONOCHROME2 or any color photometric interpretation. INVERSE - output after inversion is in P-Values - shall be used if Photometric Interpretation (0028,0004) is MONOCHROME1. When this attribute is used with a color photometric interpretation then the luminance component is in P-Values. Unique identification of the irradiation event(s) associated with the acquisition of this image. See C.7.6.1.1.7.
An irradiation event is the occurrence of radiation being applied to a patient in single continuous time-frame between the start (release) and the stop (cease) of the irradiation. Any on-off switching of the irradiation source during the event shall not be treated as separate events, rather the event includes the time between start and stop of irradiation as triggered by the user. E.g., a pulsed fluoro X-Ray acquisition shall be treated as a single irradiation event.
Physical distance in the patient between the center of each pixel, specified by a numeric pair - adjacent row spacing (delimiter) adjacent column spacing in mm. See 10.7.1.3 for further explanation. The direction cosines of the first row and the first column with respect to the patient. See C.7.6.2.1.1 for further explanation.
The Image Position (0020,0032) specifies the x, y, and z coordinates of the upper left hand corner of the image; it is the center of the first voxel transmitted. Image Orientation (0020,0037) specifies the direction cosines of the first row and the first column with respect to the patient. These Attributes shall be provide as a pair. Row value for the x, y, and z axes respectively followed by the Column value for the x, y, and z axes respectively. The direction of the axes is defined fully by the patient’s orientation. The x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient. The patient based coordinate system is a right handed system, i.e. the vector cross product of a unit vector along the positive x-axis and a unit vector along the positive y-axis is equal to a unit vector along the positive z-axis. Note If a patient lies parallel to the ground, face-up on the table, with his feet-to-head direction same as the front-to-back direction of the imaging equipment, the direction of the axes of this patient based coordinate system and the equipment based coordinate system in previous versions of this Standard will coincide. The Image Plane Attributes, in conjunction with the Pixel Spacing Attribute, describe the position and orientation of the image slices relative to the patient-based coordinate system. In each image frame the Image Position (Patient) (0020,0032) specifies the origin of the image with respect to the patient-based coordinate system. RCS and the Image Orientation (Patient) (0020,0037) attribute values specify the orientation of the image frame rows and columns. The mapping of pixel location to the RCS is calculated as follows: size 12{ left [ matrix { P rSub { size 8{x} } {} ## P rSub { size 8{y} } {} ## P rSub { size 8{z} } {} ## 1 } right ]= left [ matrix { X rSub { size 8{x} } Δi {} # Y rSub { size 8{x} } Δj {} # 0 {} # S rSub { size 8{x} } {} ## X rSub { size 8{y} } Δi {} # Y rSub { size 8{y} } Δj {} # 0 {} # S rSub { size 8{y} } {} ## X rSub { size 8{z} } Δi {} # Y rSub { size 8{z} } Δj {} # 0 {} # S rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { i {} ## j {} ## 0 {} ## 1 } right ]} {} = M Where: Pxyz The coordinates of the voxel (i,j) in the frame’s image plane in units of mm. Sxyz The three values of the Image Position (Patient) (0020,0032) attributes. It is the location in mm from the origin of the RCS. Xxyz The values from the row (X) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. Yxyz The values from the column (Y) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. i Column index to the image plane. The first column is index zero. i Column pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. j Row index to the image plane. The first row index is zero. j Row pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. Additional constraints apply: 1) The row and column direction cosine vectors shall be orthogonal, i.e. their dot product shall be zero. 2) The row and column direction cosine vectors shall be normal, i.e. the dot product of each direction cosine vector with itself shall be unity.
The x, y, and z coordinates of the upper left hand corner (center of the first voxel transmitted) of the image, in mm. See C.7.6.2.1.1 for further explanation.
The Image Position (0020,0032) specifies the x, y, and z coordinates of the upper left hand corner of the image; it is the center of the first voxel transmitted. Image Orientation (0020,0037) specifies the direction cosines of the first row and the first column with respect to the patient. These Attributes shall be provide as a pair. Row value for the x, y, and z axes respectively followed by the Column value for the x, y, and z axes respectively. The direction of the axes is defined fully by the patient’s orientation. The x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient. The patient based coordinate system is a right handed system, i.e. the vector cross product of a unit vector along the positive x-axis and a unit vector along the positive y-axis is equal to a unit vector along the positive z-axis. Note If a patient lies parallel to the ground, face-up on the table, with his feet-to-head direction same as the front-to-back direction of the imaging equipment, the direction of the axes of this patient based coordinate system and the equipment based coordinate system in previous versions of this Standard will coincide. The Image Plane Attributes, in conjunction with the Pixel Spacing Attribute, describe the position and orientation of the image slices relative to the patient-based coordinate system. In each image frame the Image Position (Patient) (0020,0032) specifies the origin of the image with respect to the patient-based coordinate system. RCS and the Image Orientation (Patient) (0020,0037) attribute values specify the orientation of the image frame rows and columns. The mapping of pixel location to the RCS is calculated as follows: size 12{ left [ matrix { P rSub { size 8{x} } {} ## P rSub { size 8{y} } {} ## P rSub { size 8{z} } {} ## 1 } right ]= left [ matrix { X rSub { size 8{x} } Δi {} # Y rSub { size 8{x} } Δj {} # 0 {} # S rSub { size 8{x} } {} ## X rSub { size 8{y} } Δi {} # Y rSub { size 8{y} } Δj {} # 0 {} # S rSub { size 8{y} } {} ## X rSub { size 8{z} } Δi {} # Y rSub { size 8{z} } Δj {} # 0 {} # S rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { i {} ## j {} ## 0 {} ## 1 } right ]} {} = M Where: Pxyz The coordinates of the voxel (i,j) in the frame’s image plane in units of mm. Sxyz The three values of the Image Position (Patient) (0020,0032) attributes. It is the location in mm from the origin of the RCS. Xxyz The values from the row (X) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. Yxyz The values from the column (Y) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. i Column index to the image plane. The first column is index zero. i Column pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. j Row index to the image plane. The first row index is zero. j Row pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. Additional constraints apply: 1) The row and column direction cosine vectors shall be orthogonal, i.e. their dot product shall be zero. 2) The row and column direction cosine vectors shall be normal, i.e. the dot product of each direction cosine vector with itself shall be unity.
Nominal slice thickness, in mm. Relative position of the image plane expressed in mm. C.7.6.2.1.2 for further explanation.
A URL of a provider service that supplies the pixel data of the Image. Required if the image is to be transferred in one of the following presentation contexts identified by Transfer Syntax UID: 1.2.840.10008.1.2.4.94 (DICOM JPIP Referenced Transfer Syntax) 1.2.840.10008.1.2.4.95 (DICOM JPIP Referenced Deflate Transfer Syntax) Pixel value that represents one limit (inclusive) of a range of padding values used together with Pixel Padding Value (0028,0120) as defined in the General Equipment Module. See C.7.5.1.1.2 for further explanation. Required if pixel padding is to be defined as a range rather than a single value. Notes: 1. The Value Representation of this Attribute is determined by the value of Pixel Representation (0028,0103). 2. Pixel Padding Value (0028,0120) is also required when this Attribute is present.
Pixel Padding Value (0028,0120) is used to pad grayscale images (those with a Photometric Interpretation of MONOCHROME1 or MONOCHROME2)to rectangular format. The native format of some images is not rectangular. It is common for devices with this format to pad the images to the rectangular format required by the DICOM Standard with a specific pixel value that is not contained in the native image. Further, when resampling, such as after spatial registration, padding may need to be used to fill previously non-existent pixels. Pixel Padding Value (0028,0120) and Pixel Padding Range Limit (0028,0121) are also used to identify pixels to be excluded from the normal grayscale rendering pipeline for other reasons, such as suppression of background air. Pixel Padding Range Limit (0028,0121) is defined in the Image Pixel Module. Notes: 1. The “native image” is that which is being padded to the required rectangular format, e.g., the area within the circular reconstruction perimeter of a CT image, or the subset of the rectangular area that contains useful image information. 2. The pixel padding value is explicitly described in order to prevent display applications from taking it into account when determining the dynamic range of an image, since the Pixel Padding Value will be outside the range between the minimum and maximum values of the pixels in the native image 3. No pixels in the native image will have a value equal to Pixel Padding Value. Pixel Padding Value (0028,0120) specifies either a single value of this padding value, or when combined with Pixel Padding Range Limit (0028,0121), a range of values (inclusive) that are padding. The values of Pixel Padding Value (0028,0120) and Pixel Padding Range Limit (0028,0121) shall be valid values within the constraints defined by Bits Allocated (0028,0100), Bits Stored (0028,0101), and High Bit (0028,0102). Pixel Padding Value (0028,0120) and Pixel Padding Range Limit (0028,0121) shall not be present when padding is performed but the pixel value used for padding does occur in the native image. If Photometric Interpretation (0028,0004) is MONOCHROME2, Pixel Padding Value (0028,0120) shall be less than (closer to or equal to the minimum possible pixel value) or equal to Pixel Padding Range Limit (0028,0121). If Photometric Interpretation (0028,0004) is MONOCHROME1, Pixel Padding Value (0028,0120) shall be greater than (closer to or equal to the maximum possible pixel value) or equal to Pixel Padding Range Limit (0028,0121). Notes: 1. When the relationship between pixel value and X-Ray Intensity is unknown, it is recommended that the following values be used to pad with black when the image is unsigned: 0 if Photometric Interpretation (0028,0004) is MONOCHROME2. 2BitsStored - 1 if Photometric Interpretation (0028,0004) is MONOCHROME1. and when the image is signed: -2BitsStored-1 if Photometric Interpretation (0028,0004) is MONOCHROME2. 2BitsStored-1 - 1 if Photometric Interpretation (0028,0004) is MONOCHROME1. 2. For projection radiography, when the relationship between pixel value and X-Ray Intensity is known (for example as defined by Pixel Intensity Relationship (0028,1040) and Pixel Intensity relationship Sign (0028,1041)), it is recommended that a pixel value equivalent to, or rendered similarly to, air (least X-Ray absorbance) be used for padding. However, if such a value may occur in the native image, the Pixel Padding Value (0028,0120) Attribute itself should not be sent. E.g., for an XRF image obtained with an image intensifier, if air is black then a padded perimeter, if any, should also appear black. Typically though, if unpadded, this area would be collimated with a circular collimator, in which case the pixels would appear natively as white (greatest X-Ray absorbance) and a circular shutter would be necessary to neutralize them as black. Whether collimated areas are detected and treated as padded, or neutralized with shutters is at the discretion of the application. See also the Display Shutter Module C.7.6.11. 3. The conditional requirement for the Pixel Padding Value Range Limit (0028,0121) in the Image Pixel Module means that it shall not be present unless Pixel Padding Value (0028,0120) is also present. 4. The range of values to be suppressed between Pixel Padding Value (0028,0120) and Pixel Padding Value Range Limit (0028,0121) is specified as being inclusive, that is the values themselves as well as all values between are suppressed. 5. When Pixel Padding Value Range Limit (0028,0121) is present, but not supported by a rendering application, the constraint that Pixel Padding Value (0028,0120) is closest to the “blackest” value, which is typically the most frequently occurring background pixel, will most often result in an acceptable display, permitting “backward compatibility” in the majority of cases. When modifying equipment changes the pixel padding value in the image, it shall change the values of Pixel Padding Value (0028,0120) and Pixel Padding Range Limit (0028,0121), if present. If modifying equipment changes the pixel padding values in the image to values present in the native image, the attribute Pixel Padding Value (0028,0120) and Pixel Padding Range Limit (0028,0121) shall be removed. Notes: 1. For example, if a CT image containing signed values from -1024 to 3191 and a Pixel Padding Value of -2000 and a Rescale Intercept of 0 is converted to an unsigned image with a Rescale Intercept of -1024 by adding 1024 to all pixels and clipping all more negative pixels to 0, then the padding pixels will be indistinguishable from some of the modified native image pixels, and hence Pixel Padding Value (0028,0120) needs to be removed. 2. If the modification involves lossy compression, which may result in changes to the pixel values, then the application of Pixel Padding Value and Pixel Padding Range Limit may result in a different appearance, and hence these attributes may need different values also.
Number of samples (planes) in this image. See C.7.6.3.1.1 for further explanation.
Samples per Pixel (0028,0002) is the number of separate planes in this image. One, three, and four image planes are defined. Other numbers of image planes are allowed, but their meaning is not defined by this Standard. For monochrome (gray scale) and palette color images, the number of planes is 1. For RGB and other three vector color models, the value of this attribute is 3. For four vector color models, the value of this attribute is 4. All image planes shall have the same number of Rows (0028,0010), Columns (0028,0011), Bits Allocated (0028,0100), Bits Stored (0028,0101), High Bit (0028,0102), Pixel Representation (0028,0103), and Pixel Aspect Ratio (0028,0034). The data in each pixel may be represented as a “Composite Pixel Code”. If Samples Per Pixel is one, the Composite Pixel Code is just the “n” bit pixel sample, where “n” = Bits Allocated. If Samples Per Pixel is greater than one, Composite Pixel Code is a “k” bit concatenation of samples, where “k” = Bits Allocated multiplied by Samples Per Pixel, and with the sample representing the vector color designated first in the Photometric Interpretation name comprising the most significant bits of the Composite Pixel Code, followed in order by the samples representing the next vector colors, with the sample representing the vector color designated last in the Photometric Interpretation name comprising the least significant bits of the Composite Pixel Code. For example, for Photometric Interpretation = “RGB”, the most significant “Bits Allocated” bits contain the Red sample, the next “Bits Allocated” bits contain the Green sample, and the least significant “Bits Allocated” bits contain the Blue sample.
Specifies the intended interpretation of the pixel data. See C.7.6.3.1.2 for further explanation.
The value of Photometric Interpretation (0028,0004) specifies the intended interpretation of the image pixel data. See PS 3.5 for restrictions imposed by compressed Transfer Syntaxes. The following values are defined. Other values are permitted but the meaning is not defined by this Standard. MONOCHROME1 = Pixel data represent a single monochrome image plane. The minimum sample value is intended to be displayed as white after any VOI gray scale transformations have been performed. See PS 3.4. This value may be used only when Samples per Pixel (0028,0002) has a value of 1. MONOCHROME2 = Pixel data represent a single monochrome image plane. The minimum sample value is intended to be displayed as black after any VOI gray scale transformations have been performed. See PS 3.4. This value may be used only when Samples per Pixel (0028,0002) has a value of 1. PALETTE COLOR = Pixel data describe a color image with a single sample per pixel (single image plane). The pixel value is used as an index into each of the Red, Blue, and Green Palette Color Lookup Tables (0028,1101-1103&1201-1203). This value may be used only when Samples per Pixel (0028,0002) has a value of 1. When the Photometric Interpretation is Palette Color; Red, Blue, and Green Palette Color Lookup Tables shall be present. RGB = Pixel data represent a color image described by red, green, and blue image planes. The minimum sample value for each color plane represents minimum intensity of the color. This value may be used only when Samples per Pixel (0028,0002) has a value of 3. HSV = Retired. ARGB = Retired. CMYK = Retired. YBR_FULL = Pixel data represent a color image described by one luminance (Y) and two chrominance planes (CB and CR). This photometric interpretation may be used only when Samples per Pixel (0028,0002) has a value of 3. Black is represented by Y equal to zero. The absence of color is represented by both CB and CR values equal to half full scale. Note: In the case where the Bits Allocated (0028,0100) has value of 8 half full scale is 128. In the case where Bits Allocated (0028,0100) has a value of 8 then the following equations convert between RGB and YCBCR Photometric Interpretation. Y = + .2990R + .5870G + .1140B CB = - .1687R - .3313G + .5000B + 128 CR = + .5000R - .4187G - .0813B + 128 Note: The above is based on CCIR Recommendation 601-2 dated 1990. YBR_FULL_422 = The same as YBR_FULL except that the CB and CR values are sampled horizontally at half the Y rate and as a result there are half as many CB and CR values as Y values. This Photometric Interpretation is only allowed with Planar Configuration (0028,0006) equal to 0. Two Y values shall be stored followed by one CB and one CR value. The CB and CR values shall be sampled at the location of the first of the two Y values. For each Row of Pixels, the first CB and CR samples shall be at the location of the first Y sample. The next CB and CR samples shall be at the location of the third Y sample etc. Note: This subsampling is often referred to as cosited sampling. YBR_PARTIAL_422 = The same as YBR_FULL_422 except that: 1. black corresponds to Y = 16; 2. Y is restricted to 220 levels (i.e. the maximum value is 235); 3. CB and CR each has a minimum value of 16; 4. CB and CR are restricted to 225 levels (i.e. the maximum value is 240); 5. lack of color is represented by CB and CR equal to 128. In the case where Bits Allocated (0028,0100) has value of 8 then the following equations convert between RGB and YBR_PARTIAL_422 Photometric Interpretation Y = + .2568R + .5041G + .0979B + 16 CB = - .1482R - .2910G + .4392B + 128 CR = + .4392R - .3678G - .0714B + 128 Note: The above is based on CCIR Recommendation 601-2 dated 1990. YBR_PARTIAL_420 = The same as YBR_PARTIAL_422 except that the CB and CR values are sampled horizontally and vertically at half the Y rate and as a result there are four times less CB and CR values than Y values, versus twice less for YBR_PARTIAL_422. This Photometric Interpretation is only allowed with Planar Configuration (0028,0006) equal to 0. The CB and CR values shall be sampled at the location of the first of the two Y values. For the first Row of Pixels (etc.), the first CB and CR samples shall be at the location of the first Y sample. The next CB and CR samples shall be at the location of the third Y sample etc. The next Rows of Pixels containing CB and CR samples (at the same locations than for the first Row) will be the third etc. YBR_ICT = Irreversible Color Transformation: Pixel data represent a color image described by one luminance (Y) and two chrominance planes (CB and CR). This photometric interpretation may be used only when Samples per Pixel (0028,0002) has a value of 3. Black is represented by Y equal to zero. The absence of color is represented by both CB and CR values equal to zero. Regardless of the value of Bits Allocated (0028,0100), the following equations convert between RGB and YCBCR Photometric Interpretation. Y = + .29900R + .58700G + .11400B CB = - .16875R - .33126G + .50000B CR = + .50000R - .41869G - .08131B Notes: 1. The above is based on ISO/IEC 15444-1 (JPEG 2000). 2. In a JPEG 2000 bitstream, DC level shifting (used if the untransformed components are unsigned) is applied before forward color transformation, and the transformed components may be signed (unlike in JPEG ISO/IEC 10918-1). 3. In JPEG 2000, spatial down-sampling of the chrominance components, if performed, is signaled in the JPEG 2000 bitstream. YBR_RCT = Reversible Color Transformation: Pixel data represent a color image described by one luminance (Y) and two chrominance planes (CB and CR). This photometric interpretation may be used only when Samples per Pixel (0028,0002) has a value of 3. Black is represented by Y equal to zero. The absence of color is represented by both CB and CR values equal to zero. Regardless of the value of Bits Allocated (0028,0100), the following equations convert between RGB and YBR_RCT Photometric Interpretation. Y = R + 2G +B) / 4 (Note:  mean floor) CB = B - G CR = R - G The following equations convert between YBR_RCT and RGB Photometric Interpretation. G = Y –  (CR + CB) / 4 R = CR + G B = CB + G Notes: 1. The above is based on ISO/IEC 15444-1 (JPEG 2000). 2. In a JPEG 2000 bitstream, DC level shifting (used if the untransformed components are unsigned) is applied before forward color transformation, and the transformed components may be signed (unlike in JPEG ISO/IEC 10918-1). 3. This photometric interpretation is a reversible approximation to the YUV transformation used in PAL and SECAM.
Number of rows in the image. Number of columns in the image Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated. See PS 3.5 for further explanation. Number of bits stored for each pixel sample. Each sample shall have the same number of bits stored. See PS 3.5 for further explanation. Most significant bit for pixel sample data. Each sample shall have the same high bit. See PS 3.5 for further explanation. Data representation of the pixel samples. Each sample shall have the same pixel representation. Enumerated Values: 0000H = unsigned integer. 0001H = 2's complement A data stream of the pixel samples that comprise the Image. See C.7.6.3.1.4 for further explanation. Required if Pixel Data Provider URL (0028,7FE0) is not present.
Pixel Data (7FE0,0010) for this image. The order of pixels sent for each image plane is left to right, top to bottom, i.e., the upper left pixel (labeled 1,1) is sent first followed by the remainder of row 1, followed by the first pixel of row 2 (labeled 2,1) then the remainder of row 2 and so on. For multi-plane images see Planar Configuration (0028,0006) in this Section.
Indicates whether the pixel data are sent color-by-plane or color-by-pixel. Required if Samples per Pixel (0028,0002) has a value greater than 1. See C.7.6.3.1.3 for further explanation.
Planar Configuration (0028,0006) indicates whether the color pixel data are sent color-by-plane or color-by-pixel. This Attribute shall be present if Samples per Pixel (0028,0002) has a value greater than 1. It shall not be present otherwise. Enumerated Values: 0 = The sample values for the first pixel are followed by the sample values for the second pixel, etc. For RGB images, this means the order of the pixel values sent shall be R1, G1, B1, R2, G2, B2, ..., etc. 1 = Each color plane shall be sent contiguously. For RGB images, this means the order of the pixel values sent is R1, R2, R3, ..., G1, G2, G3, ..., B1, B2, B3, etc. Note: Planar Configuration (0028,0006) is not meaningful when a compression transfer syntax is used that involves reorganization of sample components in the compressed bit stream. In such cases, since the Attribute is required to be sent, then an appropriate value to use may be specified in the description of the Transfer Syntax in PS 3.5, though in all likelihood the value of the Attribute will be ignored by the receiving implementation.
Ratio of the vertical size and horizontal size of the pixels in the image specified by a pair of integer values where the first value is the vertical pixel size, and the second value is the horizontal pixel size. Required if the aspect ratio values do not have a ratio of 1:1 and the physical pixel spacing is not specified by Pixel Spacing (0028,0030), or Imager Pixel Spacing (0018,1164) or Nominal Scanned Pixel Spacing (0018,2010), either for the entire Image or per-frame in a Functional Group Macro. See C.7.6.3.1.7.
The pixel aspect ratio is the ratio of the vertical size and horizontal size of the pixels in the image specified by a pair of integer values where the first value is the vertical pixel size, and the second value is the horizontal pixel size. To illustrate, consider the following example pixel size: Pixel Aspect Ratio = Vertical Size \ Horizontal Size = 0.30 mm \0.25 mm. Thus the Pixel Aspect Ratio could be represented as the multivalued integer string "6\5", "60\50", or any equivalent integer ratio.
The minimum actual pixel value encountered in this image. The maximum actual pixel value encountered in this image. Specifies the format of the Red Palette Color Lookup Table Data (0028,1201) Required if Photometric Interpretation (0028,0004) has a value of PALETTE COLOR or Pixel Presentation (0008,9205) at the image level equals COLOR or MIXED. See C.7.6.3.1.5 for further explanation.
The three values of Palette Color Lookup Table Descriptor (0028,1101-1103) describe the format of the Lookup Table Data in the corresponding Data Element (0028,1201-1203) or (0028,1221-1223). The first value is the number of entries in the lookup table. When the number of table entries is equal to 216 then this value shall be 0. The first value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The second value is the first stored pixel value mapped. This pixel value is mapped to the first entry in the Lookup Table Data. All image pixel values less than the first value mapped are also mapped to the first entry in the Lookup Table Data if the Photometric Interpretation is PALETTE COLOR. Note: In the case of the Supplemental Palette Color LUT, the stored pixel values less than the second descriptor value are grayscale values. An image pixel value one greater than the first value mapped is mapped to the second entry in the Lookup Table Data. Subsequent image pixel values are mapped to the subsequent entries in the Lookup Table Data up to an image pixel value equal to number of entries + first value mapped – 1, which is mapped to the last entry in the Lookup Table Data. Image pixel values greater than or equal to number of entries + first value mapped are also mapped to the last entry in the Lookup Table Data. The second value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The third value specifies the number of bits for each entry in the Lookup Table Data. It shall take the value of 8 or 16. The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where in both cases the high bit is equal to bits allocated-1. The third value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. Note: Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits; this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry. The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16. When the Palette Color Lookup Table Descriptor (0028,1101-1103) are used as part of the Palette Color Lookup Table Module or the Supplemental Palette Color Lookup Table Module, the third value shall be equal to 16. Notes: 1. A value of 16 indicates the Lookup Table Data will range from (0,0,0) minimum intensity to (65535,65535,65535) maximum intensity. 2. Since the Palette Color Lookup Table Descriptor (0028,1101-1103) Attributes are multi-valued, in an Explicit VR Transfer Syntax, only one value representation (US or SS) may be specified, even though the first and third values are always by definition interpreted as unsigned. The explicit VR actually used is dictated by the VR needed to represent the second value, which will be consistent with Pixel Representation (0028,0103).
Specifies the format of the Green Palette Color Lookup Table Data (0028,1202) Required if Photometric Interpretation (0028,0004) has a value of PALETTE COLOR or Pixel Presentation (0008,9205) at the image level equals COLOR or MIXED. See C.7.6.3.1.5 for further explanation.
The three values of Palette Color Lookup Table Descriptor (0028,1101-1103) describe the format of the Lookup Table Data in the corresponding Data Element (0028,1201-1203) or (0028,1221-1223). The first value is the number of entries in the lookup table. When the number of table entries is equal to 216 then this value shall be 0. The first value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The second value is the first stored pixel value mapped. This pixel value is mapped to the first entry in the Lookup Table Data. All image pixel values less than the first value mapped are also mapped to the first entry in the Lookup Table Data if the Photometric Interpretation is PALETTE COLOR. Note: In the case of the Supplemental Palette Color LUT, the stored pixel values less than the second descriptor value are grayscale values. An image pixel value one greater than the first value mapped is mapped to the second entry in the Lookup Table Data. Subsequent image pixel values are mapped to the subsequent entries in the Lookup Table Data up to an image pixel value equal to number of entries + first value mapped – 1, which is mapped to the last entry in the Lookup Table Data. Image pixel values greater than or equal to number of entries + first value mapped are also mapped to the last entry in the Lookup Table Data. The second value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The third value specifies the number of bits for each entry in the Lookup Table Data. It shall take the value of 8 or 16. The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where in both cases the high bit is equal to bits allocated-1. The third value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. Note: Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits; this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry. The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16. When the Palette Color Lookup Table Descriptor (0028,1101-1103) are used as part of the Palette Color Lookup Table Module or the Supplemental Palette Color Lookup Table Module, the third value shall be equal to 16. Notes: 1. A value of 16 indicates the Lookup Table Data will range from (0,0,0) minimum intensity to (65535,65535,65535) maximum intensity. 2. Since the Palette Color Lookup Table Descriptor (0028,1101-1103) Attributes are multi-valued, in an Explicit VR Transfer Syntax, only one value representation (US or SS) may be specified, even though the first and third values are always by definition interpreted as unsigned. The explicit VR actually used is dictated by the VR needed to represent the second value, which will be consistent with Pixel Representation (0028,0103).
Specifies the format of the Blue Palette Color Lookup Table Data (0028,1203) Required if Photometric Interpretation (0028,0004) has a value of PALETTE COLOR or Pixel Presentation (0008,9205) at the image level equals COLOR or MIXED. See C.7.6.3.1.5 for further explanation.
The three values of Palette Color Lookup Table Descriptor (0028,1101-1103) describe the format of the Lookup Table Data in the corresponding Data Element (0028,1201-1203) or (0028,1221-1223). The first value is the number of entries in the lookup table. When the number of table entries is equal to 216 then this value shall be 0. The first value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The second value is the first stored pixel value mapped. This pixel value is mapped to the first entry in the Lookup Table Data. All image pixel values less than the first value mapped are also mapped to the first entry in the Lookup Table Data if the Photometric Interpretation is PALETTE COLOR. Note: In the case of the Supplemental Palette Color LUT, the stored pixel values less than the second descriptor value are grayscale values. An image pixel value one greater than the first value mapped is mapped to the second entry in the Lookup Table Data. Subsequent image pixel values are mapped to the subsequent entries in the Lookup Table Data up to an image pixel value equal to number of entries + first value mapped – 1, which is mapped to the last entry in the Lookup Table Data. Image pixel values greater than or equal to number of entries + first value mapped are also mapped to the last entry in the Lookup Table Data. The second value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The third value specifies the number of bits for each entry in the Lookup Table Data. It shall take the value of 8 or 16. The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where in both cases the high bit is equal to bits allocated-1. The third value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. Note: Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits; this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry. The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16. When the Palette Color Lookup Table Descriptor (0028,1101-1103) are used as part of the Palette Color Lookup Table Module or the Supplemental Palette Color Lookup Table Module, the third value shall be equal to 16. Notes: 1. A value of 16 indicates the Lookup Table Data will range from (0,0,0) minimum intensity to (65535,65535,65535) maximum intensity. 2. Since the Palette Color Lookup Table Descriptor (0028,1101-1103) Attributes are multi-valued, in an Explicit VR Transfer Syntax, only one value representation (US or SS) may be specified, even though the first and third values are always by definition interpreted as unsigned. The explicit VR actually used is dictated by the VR needed to represent the second value, which will be consistent with Pixel Representation (0028,0103).
Red Palette Color Lookup Table Data. Required if Photometric Interpretation (0028,0004) has a value of PALETTE COLOR or Pixel Presentation (0008,9205) at the image level equals COLOR or MIXED. See C.7.6.3.1.6 for further explanation.
Palette Color Lookup Table Data (0028,1201-1203) contain the lookup table data corresponding to the Lookup Table Descriptor (0028,1101-1103). Palette color values must always be scaled across the full range of available intensities. This is indicated by the fact that there are no bits stored and high bit values for palette color data. Note: For example, if there are 16 bits per entry specified and only 8 bits of value are truly used then the 8 bit intensities from 0 to 255 must be scaled to the corresponding 16 bit intensities from 0 to 65535. To do this for 8 bit values, simply replicate the value in both the most and least significant bytes. These lookup tables shall be used only when there is a single sample per pixel (single image plane) in the image. These lookup tables are required when the value of Photometric Interpretation (0028,0004) is Palette Color. The semantics of these lookup tables is not defined otherwise.
Green Palette Color Lookup Table Data. Required if Photometric Interpretation (0028,0004) has a value of PALETTE COLOR or Pixel Presentation (0008,9205) at the image level equals COLOR or MIXED. See C.7.6.3.1.6 for further explanation.
Palette Color Lookup Table Data (0028,1201-1203) contain the lookup table data corresponding to the Lookup Table Descriptor (0028,1101-1103). Palette color values must always be scaled across the full range of available intensities. This is indicated by the fact that there are no bits stored and high bit values for palette color data. Note: For example, if there are 16 bits per entry specified and only 8 bits of value are truly used then the 8 bit intensities from 0 to 255 must be scaled to the corresponding 16 bit intensities from 0 to 65535. To do this for 8 bit values, simply replicate the value in both the most and least significant bytes. These lookup tables shall be used only when there is a single sample per pixel (single image plane) in the image. These lookup tables are required when the value of Photometric Interpretation (0028,0004) is Palette Color. The semantics of these lookup tables is not defined otherwise.
Blue Palette Color Lookup Table Data. Required if Photometric Interpretation (0028,0004) has a value of PALETTE COLOR or Pixel Presentation (0008,9205) at the image level equals COLOR or MIXED. See C.7.6.3.1.6 for further explanation.
Palette Color Lookup Table Data (0028,1201-1203) contain the lookup table data corresponding to the Lookup Table Descriptor (0028,1101-1103). Palette color values must always be scaled across the full range of available intensities. This is indicated by the fact that there are no bits stored and high bit values for palette color data. Note: For example, if there are 16 bits per entry specified and only 8 bits of value are truly used then the 8 bit intensities from 0 to 255 must be scaled to the corresponding 16 bit intensities from 0 to 65535. To do this for 8 bit values, simply replicate the value in both the most and least significant bytes. These lookup tables shall be used only when there is a single sample per pixel (single image plane) in the image. These lookup tables are required when the value of Photometric Interpretation (0028,0004) is Palette Color. The semantics of these lookup tables is not defined otherwise.
An ICC Profile encoding the transformation of device-dependent color stored pixel values into PCS-Values. See Section C.11.15.1.1.1. When present, defines the color space of color Pixel Data (7FE0,0010) values, and the output of Palette Color Lookup Table Data (0028,1201-1203). Note: The profile applies only to the Pixel Data (7FE0,0010) attribute at the same level of the dataset and not to any icons nested within sequences, which may or may not have their own ICC profile specified.
Contrast or bolus agent Sequence that identifies the contrast agent. One or more Items may be present. Administration route of contrast agent Sequence that identifies the route of administration of contrast agent. Only a single Item shall be permitted in this sequence. Sequence that identifies any additional drug that is administered with the contrast agent bolus. One or more Items may be present. Volume injected in milliliters of diluted contrast agent Time of start of injection Time of end of contrast injection Total amount in milliliters of the undiluted contrast agent Rate(s) of injection(s) in milliliters/sec Duration(s) of injection(s) in seconds. Each Contrast Flow Duration value shall correspond to a value of Contrast Flow Rate (0018,1046). Active ingredient of agent. Defined Terms: IODINE GADOLINIUM CARBON DIOXIDE BARIUM Milligrams of active ingredient per milliliter of (diluted) agent Sequence that identifies one or more contrast agents administered prior to or during the acquisition. Shall contain one or more Items. Identifying number, unique within this SOP Instance, of the agent administered. Used to reference this particular agent from the Contrast/Bolus Functional Group Macro. The number shall be 1 for the first Item and increase by 1 for each subsequent Item. Sequence that identifies the route of administration of contrast agent. Shall contain exactly one Item. Active ingredient of agent. Zero or more Items may be included in the Sequence. Total volume administered in milliliters of diluted contrast agent. Milligrams of active ingredient per milliliter of agent. Absorption of the ingredient greater than the absorption of water (tissue). Enumerated Values: YES NO See Section C.7.6.4b.1.
Table C.7-12 specifies the Attributes that describe the contrast /bolus used in the acquisition of the Image. Table C.7-12 CONTRAST/BOLUS MODULE ATTRIBUTES Note: 1. Flow duration is an alternate method of specifying stop time 2. Flow rate allows for stepped injections by being capable of multiple values (1,N) instances. 3. For a 100 ml injection of 76% Diatrizoate and meglumine/sodium, diluted 1:1, the Contrast/Bolus Agent would be “76% Diatrizoate” as text the Contrast/Bolus Volume would be 100 ml, the Contrast/Bolus Total Dose would be 50 ml, the Contrast/Bolus Ingredient would be “IODINE”, the Contrast/Bolus Ingredient Concentration would be 370mg/ml.
Sequence that describes one or more phases of contrast administered. If present, shall contain one or more Items. Volume administered during this phase in milliliters of diluted contrast agent. Time of start of administration. Time of end of administration. Rate of administration in milliliters/sec. Only a single value shall be present. Duration of injection in seconds. Only a single value shall be present.
Describes the preferred playback sequencing for a multi-frame image. Enumerated Values: 0 = Looping (1,2...n,1,2,...n,1,2,....n,...) 1 = Sweeping (1,2,...n,n-1,...2,1,2,...n,...) Nominal time (in msec) per individual frame. See C.7.6.5.1.1 for further explanation. Required if Frame Increment Pointer (0028,0009) points to Frame Time.
Frame Time (0018,1063) is the nominal time (in milliseconds) between individual frames of a Multi-frame image. If the Frame Increment Pointer points to this Attribute, Frame Time shall be used in the following manner to calculate 'the relative time' for each frame: Frame 'Relative Time' (n) = Frame Delay + Frame Time * (n-1) where: n = number of frame within the Multi-frame image and the first frame number is one Note: When there is only one frame present, Frame Time (0018,1063) may have either a value of 0, or a nominal value that would apply if there were multiple frames.
An array that contains the real time increments (in msec) between frames for a Multi-frame image. See C.7.6.5.1.2 for further explanation. Required if Frame Increment Pointer (0028,0009) points to Frame Time Vector. Note: Frame Time Vector arrays may not be properly encoded if Explicit-VR transfer syntax is used and the VL of this attribute exceeds 65534 bytes.
Frame Time Vector (0018,1065) is an array that contains the time increments (in milliseconds) between the nth frame and the previous frame for a Multi-frame image. The first frame always has a time increment of 0. If the Frame Increment Pointer points to this Attribute, the Frame Time Vector shall be used in the following manner to calculate 'relative time' T(n) for frame n: where ti is the ith Frame Time Vector component.
The frame number of the first frame of the Multi-frame image to be displayed. The Frame Number of the last frame of a Multi-frame image to be displayed. Recommended rate at which the frames of a Multi-frame image should be displayed in frames/second. Number of frames per second. Time (in msec) from Content Time (0008,0033) to the start of the first frame in a Multi-frame image. Delay time in milliseconds from trigger (e.g., X-Ray on pulse) to the first frame of a Multi-frame image. Total time in seconds that data was actually taken for the entire Multi-frame image. Elapsed time of data acquisition in msec per each frame. Description of any multiplexed audio channels. See Section C.7.6.5.1.3. Required if the Transfer Syntax used to encode the multi-frame image contains multiplexed (interleaved) audio channels, such as is possible with MPEG2. Zero or more items may be present in this sequence.
During a video acquisition, audio may be used for voice commentary of what is being observed, as well as to record sound-based physiological information such as Doppler audio. Some Transfer Syntaxes allow for the multiplexing of interleaved audio with video data, and the Attributes of the Cine Module support this encoding paradigm. They are not intended to describe audio acquired simultaneously when it is encoded in other SOP Instances or within Attributes other than Pixel Data (7FE0,0010) of the same SOP Instance. Synchronization between audio and video is assumed to be encoded at the Transfer Syntax level (i.e. within the encoded bit stream). Note: If no audio was recorded, the Multiplexed Audio Channels Description Code Sequence (003A,0300) will be present and contain no sequence items.
A reference to the audio channel as identified within Transfer Syntax encoded bit stream (1 for the main channel, 2 for the second channel and 3 to 9 to the complementary channels). A coded descriptor qualifying the mode of the channel: Enumerated Values: MONO = 1 signal STEREO = 2 simultaneously acquired (left and right) signals A coded descriptor of the audio channel source. Only a single Item shall be permitted in this sequence.
Number of frames in a Multi-frame Image. See C.7.6.6.1.1 for further explanation.
A Multi-frame Image is defined as a Image whose pixel data consists of a sequential set of individual Image Pixel frames. A Multi-frame Image is transmitted as a single contiguous stream of pixels. Frame headers do not exist within the data stream. Each individual frame shall be defined (and thus can be identified) by the Attributes in the Image Pixel Module (see C.7.6.3). All Image IE Attributes shall be related to the first frame in the Multi-frame image. The total number of frames contained within a Multi-frame Image is conveyed in the Number of Frames (0028,0008). The frames within a Multi-frame Image shall be conveyed as a logical sequence. The information that determines the sequential order of the frames shall be identified by the Data Element Tag or tags conveyed by the Frame Increment Pointer (0028,0009). Each specific Image IOD that supports the Multi-frame Module specializes the Frame Increment Pointer (0028,0009) to identify the Attributes that may be used as sequences. Even if only a single frame is present, Frame Increment Pointer (0028,0009) is still required to be present and have at least one value, each of which shall point to an attribute that is also present in the dataset and has a value. Note: For example, in single-frame instance of an IOD that is required to or may contain the Cine Module, it may be appropriate for Frame Time (0018,1063) to be present with a value of 0, and be the only target of Frame Increment Pointer (0028,0009).
Contains the Data Element Tag of the attribute that is used as the frame increment in Multi-frame pixel data. See C.7.6.6.1.1 for further explanation.
A Multi-frame Image is defined as a Image whose pixel data consists of a sequential set of individual Image Pixel frames. A Multi-frame Image is transmitted as a single contiguous stream of pixels. Frame headers do not exist within the data stream. Each individual frame shall be defined (and thus can be identified) by the Attributes in the Image Pixel Module (see C.7.6.3). All Image IE Attributes shall be related to the first frame in the Multi-frame image. The total number of frames contained within a Multi-frame Image is conveyed in the Number of Frames (0028,0008). The frames within a Multi-frame Image shall be conveyed as a logical sequence. The information that determines the sequential order of the frames shall be identified by the Data Element Tag or tags conveyed by the Frame Increment Pointer (0028,0009). Each specific Image IOD that supports the Multi-frame Module specializes the Frame Increment Pointer (0028,0009) to identify the Attributes that may be used as sequences. Even if only a single frame is present, Frame Increment Pointer (0028,0009) is still required to be present and have at least one value, each of which shall point to an attribute that is also present in the dataset and has a value. Note: For example, in single-frame instance of an IOD that is required to or may contain the Cine Module, it may be appropriate for Frame Time (0018,1063) to be present with a value of 0, and be the only target of Frame Increment Pointer (0028,0009).
The frame number selected for use as a pictorial representation (e.g. icon) of the Multi-frame Image Frame number(s) selected as frames of interest. A frame number may appear more than once. Description of each one of the Frame(s) of Interest selected in (0028,6020). If multiple Frames of Interest are selected and this Attribute is used, it shall contain the same number of values as are in Frame Numbers of Interest (0028,6020). A defined term for each one of the Frame(s) of Interest (0028,6020) that identifies the significance of the frame. If multiple Frames of Interest are selected and this Attribute is used, it shall contain the same number of values as are in Frame Numbers of Interest (0028,6020). Defined Terms are: HIGHMI = a frame acquired at the time of the high power pulse that destroys acoustic contrast RWAVE = the frame closest to the R-Wave TRIGGER = a trigger frame, for example a set delay from the R Wave ENDSYSTOLE = the frame closest to end of systole, at the end of the T-wave Defines a sequence that describes mask subtraction operations for a Multi-frame Image. One or more items may be included in this sequence. Defined Term identifying the type of mask operation to be performed. See C.7.6.10.1 for further explanation.
Identification of the Subtraction Item used to associate a certain Mask Sub-Pixel Shift (0028,6114) in the Frame Pixel Shift Functional Group. See C.7.6.16.2.14.1. Required if SOP Class UID (0008,0016) equals "1.2.840.10008.5.1.4.1.1.12.1.1" or "1.2.840.10008.5.1.4.1.1.12.2.1". May be present otherwise.
Subtraction Item ID (0028,9416) specifies the ID of a subtraction operation to which the Mask Sub-pixel Shift (0028,6114) is associated. The Subtraction Item ID is also present in the Mask Subtraction Sequence (0028,6100) to allow this association. When used as per-frame macro, the Subtraction Item ID (0028,9416) allows to specify different values of Mask Sub-pixel Shift (0028,6114) individually frame by frame, and relate them to a single item of the Mask Subtraction Sequence (0028,6100). Note: There is no restriction in the number of Subtraction Item ID’s associated to each contrast frame. The same contrast frame may be present in several items of the Mask Subtraction Sequence, each item having a different value of Subtraction Item ID. When used as shared macro, the Subtraction Item ID (0028,9416) allows to specify one or more values of Mask Sub-pixel Shift that will be applied to all the frames of the Multi-frame image. Note: Example of usage of Subtraction Item ID in a per-frame macro, see Figure C.7.6.16-8: In this example of Multi-Frame Image with 3 frames, one Mask Frame (i.e., Frame 1) is applied to the next two frames of the Multi-Frame image (i.e., Frames 2 and 3). Therefore, there is only one item in the Mask Subtraction Sequence, containing its own Subtraction Item ID value (i.e., 100). The Frame Pixel Shift Macro allows to define a Mask Sub-Pixel Shift different for each contrast frame. First Frame Subtracted: Subtraction of Frame 1 (Mask) to Frame 2, with Sub-Pixel Shift 1.3\2.4 Second Frame Subtracted: Subtraction of Frame 1 (Mask) to Frame 3, with Sub-Pixel Shift 1.9\3.0 Figure C.7.6.16-8 Example of usage of Subtraction Item ID in a per-frame Macro
Each pair of numbers in this multi-valued attribute specify a beginning and ending frame number inclusive of a range where this particular mask operation is valid. Discontinuous ranges are represented by multiple pairs of numbers. Frames in a Multi-frame Image are specified by sequentially increasing number values beginning with 1. If this Attribute is missing in this particular sequence item, then the mask operation is applicable throughout the entire Multi-frame Image, subject to certain limits as described in C.7.6.10.1.1. Required if Mask Operation (0028,6101) equals REV_TID. May be present otherwise. Specifies the frame numbers of the pixel data used to generate this mask. Frames in a Multi-frame Image are specified by sequentially increasing number values beginning with 1. Required if the Mask Operation (0028,6101) is AVG_SUB. Specifies the number of contrast frames to average together before performing the mask operation. If the Attribute is missing, no averaging is performed. A pair of floating point numbers specifying the fractional vertical [adjacent row spacing] and horizontal [adjacent column spacing] pixel shift applied to the mask before subtracting it from the contrast frame. See Section C.7.6.10.1.2. Note: When the Frame Pixel Shift Functional Group is present the values of the Mask Pixel Shift attribute of that Functional Group prevails over the values specified in this module.
A pair of floating point numbers specifying the fractional vertical [adjacent row spacing] and horizontal [adjacent column spacing] pixel shift applied to the mask before subtracting it from the contrast frame. The row offset results in a shift of the pixels along the column axis. The column offset results in a shift of the pixels along the row axis. A positive row offset is a shift toward the pixels of the lower row of the pixel plane. A positive column offset is a shift toward the pixels of the left hand side column of the pixel plane.
If Mask Operation is TID, specifies the offset to be subtracted from the current frame number in order to locate the mask frame in TID mode. If Mask Operation is REV_TID, specifies the initial offset to be subtracted from the first contrast frame number. See section C.7.6.10.1.1. If zero length, TID Offset defaults to 1. Required if Mask Operation (0028,6101) is TID or REV_TID. Free form explanation of this particular mask operation. Specifies the method of selection of the mask operations of this item. Defined Terms: SYSTEM USER Specifies the recommended viewing protocol(s). Defined terms: SUB = for subtraction with mask images; NAT = native viewing of image as sent. Note: If an implementation does not recognize the defined term for Recommended Viewing Mode (0028,1090) , reverting to native display mode is recommended. Shape(s) of the shutter defined for display. Enumerated Values: RECTANGULAR CIRCULAR POLYGONAL This multi-valued Attribute shall contain at most one of each Enumerated Value. Required if Shutter Shape (0018,1600) is RECTANGULAR. Location of the left edge of the rectangular shutter with respect to pixels in the image given as column. Required if Shutter Shape (0018,1600) is RECTANGULAR. Location of the right edge of the rectangular shutter with respect to pixels in the image given as column. Required if Shutter Shape (0018,1600) is RECTANGULAR. Location of the upper edge of the rectangular shutter with respect to pixels in the image given as row. Required if Shutter Shape (0018,1600) is RECTANGULAR. Location of the lower edge of the rectangular shutter with respect to pixels in the image given as row. Required if Shutter Shape (0018,1600) is CIRCULAR. Location of the center of the circular shutter with respect to pixels in the image given as row and column. Required if Shutter Shape (0018,1600) is CIRCULAR. Radius of the circular shutter with respect to pixels in the image given as a number of pixels along the row direction. Required if Shutter Shape (0018,1600) is POLYGONAL. Multiple Values where the first set of two values are: row of the origin vertex column of the origin vertex Two or more pairs of values follow and are the row and column coordinates of the other vertices of the polygon shutter. Polygon shutters are implicitly closed from the last vertex to the origin vertex and all edges shall be non-intersecting except at the vertices. A single gray unsigned value used to replace those parts of the image occluded by the shutter, when rendered on a monochrome display. The units are specified in P-Values, from a minimum of 0000H (black) up to a maximum of FFFFH (white). Note: The maximum P-Value for this Attribute may be different from the maximum P-Value from the output of the Presentation LUT, which may be less than 16 bits in depth. A color triplet value used to replace those parts of the image occluded by the shutter, when rendered on a color display. The units are specified in PCS-Values, and the value is encoded as CIELab. See C.10.7.1.1.
Attributes such as Graphic Layer Recommended Display CIELab Value (0070,0401) consist of three unsigned short values:
Introduces sequence of items describing devices used that may be visible in the image. One or more Items may be included in this Sequence. Manufacturer of the device Manufacturer's model name of the device Manufacturer's serial number of the device User-supplied identifier for the device Length in mm of device. See C.7.6.12.1.1.
Depending on the type of device specified by the Code Value (0008,0100) in an item of the Device Sequence (0050,0010), various device size attributes (e.g., Device Length (0050,0014), Device Diameter (0050,0016), Device Volume (0050,0018), Inter Marker Distance (0050,0019)) may be required to fully characterize the device.
Unit diameter of device. See C.7.6.12.1.1.
Depending on the type of device specified by the Code Value (0008,0100) in an item of the Device Sequence (0050,0010), various device size attributes (e.g., Device Length (0050,0014), Device Diameter (0050,0016), Device Volume (0050,0018), Inter Marker Distance (0050,0019)) may be required to fully characterize the device.
Required if Device Diameter (0050,0016) is present. Defined terms: FR = French GA = Gauge IN = Inch MM = Millimeter Volume of device in ml. See C.7.6.12.1.1.
Depending on the type of device specified by the Code Value (0008,0100) in an item of the Device Sequence (0050,0010), various device size attributes (e.g., Device Length (0050,0014), Device Diameter (0050,0016), Device Volume (0050,0018), Inter Marker Distance (0050,0019)) may be required to fully characterize the device.
Distance in mm between markers on calibrated device. See C.7.6.12.1.1.
Depending on the type of device specified by the Code Value (0008,0100) in an item of the Device Sequence (0050,0010), various device size attributes (e.g., Device Length (0050,0014), Device Diameter (0050,0016), Device Volume (0050,0018), Inter Marker Distance (0050,0019)) may be required to fully characterize the device.
Further description in free form text describing the device.
Introduces sequence of items describing interventional therapies or procedures. One or more Items may be included in this Sequence. Temporal relation of SOP Instance to intervention Enumerated Values: PRE INTERMEDIATE POST NONE Sequence that identifies the interventional drug. Only one item shall be included in this Sequence. Time of administration of the interventional drug. Time of completion of administration of the intervention drug. Sequence that identifies the Administration Route. This sequence shall contain exactly one item. Further description in free form text describing the therapy or other intervention. A sequence of Items that describes the conditions present during the acquisition of the data of the SOP Instance. Zero or more items may be included in this sequence. The type of the value encoded in this Item. Defined Terms: TEXT NUMERIC CODE DATE TIME PNAME See Section 10.2. A concept that constrains the meaning of (i.e. defines the role of) the Observation Value. The "Name" component of a Name/Value pair. This sequence shall contain exactly one item. References one or more frames in a Multi-frame SOP Instance. The first frame shall be denoted as frame number one. Required if this SOP Instance is a Multi-frame SOP Instance and the values in this sequence item do not apply to all frames. This is the Value component of a Name/Value pair when the Concept implied by Concept Name Code Sequence (0040,A043) is a set of one or more numeric values. Required if the value that Concept Name Code Sequence (0040,A043) requires (implies) is a set of one or more integers or real numbers. Shall not be present otherwise. Units of measurement. Only a single Item shall be permitted in this Sequence. Required if Numeric Value (0040,A30A) is sent. Shall not be present otherwise. This is the Value component of a Name/Value pair when the Concept implied by Concept Name Code Sequence (0040,A043) is a date. Note: The purpose or role of the date value could be specified in Concept Name Code Sequence (0040,A043). Required if the value that Concept Name Code Sequence (0040,A043) requires (implies) is a date. Shall not be present otherwise. This is the Value component of a Name/Value pair when the Concept implied by Concept Name Code Sequence (0040,A043) is a time. Note: The purpose or role of the time value could be specified in Concept Name Code Sequence (0040,A043). Required if the value that Concept Name Code Sequence (0040,A043) requires (implies) is a time. Shall not be present otherwise. This is the Value component of a Name/Value pair when the Concept implied by Concept Name Code Sequence (0040,A043) is a Person Name. Note: The role of the person could be specified in Concept Name Code Sequence (0040,A043). Required if the value that Concept Name Code Sequence (0040,A043) irequires (implies) is a person name. Shall not be present otherwise. This is the Value component of a Name/Value pair when the Concept implied by Concept Name Code Sequence (0040,A043) is a Text Observation Value. Required if Date (0040,A121), Time (0040,A122), and Person Name (0040,A123) do not fully describe the concept specified by Concept Name Code Sequence (0040,A043). Shall not be present otherwise. This is the Value component of a Name/Value pair when the Concept implied by Concept Name Code Sequence (0040,A043) is a Coded Value. This sequence shall contain exactly one item. Required if Date (0040,A121), Time (0040,A122), Person Name (0040,A123), Text Value (0040,A160), and the pair of Numeric Value (0040,A30A) and Measurement Units Code Sequence (0040,08EA) are not present. Free-text description of the image-acquisition context. Shape of the shutter defined for display. Enumerated Values are: BITMAP This Attribute shall contain one Value. Specifies the Group (60xx) of an Overlay stored within the Presentation State IOD that contains the bitmap data, as defined in the Overlay Plane Module C.9.2. A single gray unsigned value used to replace those parts of the image occluded by the shutter, when rendered on a monochrome display. The units are specified in P-Values, from a minimum of 0000H (black) up to a maximum of FFFFH (white). Note: The maximum P-Value for this Attribute may be different from the maximum P-Value from the output of the Presentation LUT, which may be less than 16 bits in depth. A color triplet value used to replace those parts of the image occluded by the shutter, when rendered on a color display. The units are specified in PCS-Values, and the value is encoded as CIELab. See C.10.7.1.1.
Attributes such as Graphic Layer Recommended Display CIELab Value (0070,0401) consist of three unsigned short values:
Sequence that contains the Functional Group Macros that are shared for all frames in this SOP Instance and Concatenation. Note: The contents of this sequence are the same in all SOP Instances that comprise a Concatenation. Zero or one Item may be included in this sequence. See section C.7.6.16.1.1 for further explanation. Sequence that contains the Functional Group Macros corresponding to each frame of the Multi-frame Image. The first Item corresponds with the first frame, and so on. Each Item shall contain the same set of Functional Group Macros. This Sequence shall contain the same number of Items as the number of frames in the Multi-frame image. See Section C.7.6.16.1.2 for further explanation.
The Per-frame Functional Groups Sequence Attribute (5200,9230) consists of a Sequence of Items. Each Item describes the frame of the same rank in the multi-frame pixel data. The first Item describes frame 1, the second Item describes frame 2, etc. Frames are implicitly numbered starting from 1. See Figure C.7.6.16-1.
A number that identifies this instance. The value shall be the same for all SOP Instances of a Concatenation, and different for each separate Concatenation and for each SOP Instance not within a Concatenation in a series. The date the data creation was started. Note: For instance, this is the date the pixel data is created, not the date the data is acquired. The time the data creation was started. Note: For instance, this is the time the pixel data is created, not the time the data is acquired. Number of frames in a multi-frame image. See C.7.6.6.1.1 for further explanation.
A Multi-frame Image is defined as a Image whose pixel data consists of a sequential set of individual Image Pixel frames. A Multi-frame Image is transmitted as a single contiguous stream of pixels. Frame headers do not exist within the data stream. Each individual frame shall be defined (and thus can be identified) by the Attributes in the Image Pixel Module (see C.7.6.3). All Image IE Attributes shall be related to the first frame in the Multi-frame image. The total number of frames contained within a Multi-frame Image is conveyed in the Number of Frames (0028,0008). The frames within a Multi-frame Image shall be conveyed as a logical sequence. The information that determines the sequential order of the frames shall be identified by the Data Element Tag or tags conveyed by the Frame Increment Pointer (0028,0009). Each specific Image IOD that supports the Multi-frame Module specializes the Frame Increment Pointer (0028,0009) to identify the Attributes that may be used as sequences. Even if only a single frame is present, Frame Increment Pointer (0028,0009) is still required to be present and have at least one value, each of which shall point to an attribute that is also present in the dataset and has a value. Note: For example, in single-frame instance of an IOD that is required to or may contain the Cine Module, it may be appropriate for Frame Time (0018,1063) to be present with a value of 0, and be the only target of Frame Increment Pointer (0028,0009).
Offset of the first frame in a multi-frame image of a concatenation. Logical frame numbers in a concatenation can be used across all its SOP instances. This offset can be applied to the implicit frame number to find the logical frame number in a concatenation. The offset is numbered from zero; i.e., the instance of a concatenation that begins with the first frame of the concatenation has a Concatenation Frame Offset Number (0020,9228) of zero. Required if Concatenation UID (0020,9161) is present. The frame number selected for use as a pictorial representation (e.g. icon) of the multi-frame Image. Identifier of all SOP Instances that belong to the same concatenation. Required if a group of multi-frame image SOP Instances within a Series are part of a Concatenation. Identifier for one SOP Instance belonging to a concatenation. See C.7.6.16.2.2.4 for further specification. The first instance in a concatenation (that with the lowest Concatenation Frame Offset Number (0020,9228) value) shall have an In-concatenation Number (0020,9162) value of 1, and subsequent instances shall have values monotonically increasing by 1. Required if Concatenation UID (0020,9161) is present.
Due to implementation specific reasons (such as maximum object size) the information of a multi-frame image may be split into more than one SOP Instance. These SOP Instances form together a Concatenation. This is a group of SOP Instances within a Series that is uniquely identified by the Concatenation UID (0020,9161). The Dimension Index Sequence (0020,9222) for each SOP Instance with the same Concatenation UID (0020,9161) shall contain exactly the same tags and values. In a Concatenation the Dimension Index Sequence (0020,9222) items of the Shared Functional Groups (5200,9229) shall be identical and have the same values for all individual SOP Instances. The items of the Per-frame Functional Groups (5200,9230) shall be identical for all individual SOP Instances but the values may change per frame. For all other Attributes of all the Modules of the IOD, the same Attributes shall be present and the values shall be identical, with the exception of the following Attributes:
The number of SOP Instances sharing the same Concatenation UID.
Identifies the physical characteristics of the pixels of this frame. Only a single Item shall be permitted in this sequence. Physical distance in the patient between the centers of each pixel, specified by a numeric pair - adjacent row spacing (delimiter) adjacent column spacing in mm. See 10.7.1.3 for further explanation of the value order. Note: In the case of CT images with an Acquisition Type (0018,9302) of CONSTANT_ANGLE, the pixel spacing is that in a plane normal to the central ray of the diverging X-Ray beam as it passes through the data collection center. Required if Volumetric Properties (0008,9206) is other than DISTORTED or SAMPLED. May be present otherwise. Nominal reconstructed slice thickness, in mm. See C.7.6.2.1.1 and C.7.6.16.2.3.1 for further explanation. Required if Volumetric Properties (0008,9206) is VOLUME or SAMPLED. May be present otherwise.
The Image Position (0020,0032) specifies the x, y, and z coordinates of the upper left hand corner of the image; it is the center of the first voxel transmitted. Image Orientation (0020,0037) specifies the direction cosines of the first row and the first column with respect to the patient. These Attributes shall be provide as a pair. Row value for the x, y, and z axes respectively followed by the Column value for the x, y, and z axes respectively. The direction of the axes is defined fully by the patient’s orientation. The x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient. The patient based coordinate system is a right handed system, i.e. the vector cross product of a unit vector along the positive x-axis and a unit vector along the positive y-axis is equal to a unit vector along the positive z-axis. Note If a patient lies parallel to the ground, face-up on the table, with his feet-to-head direction same as the front-to-back direction of the imaging equipment, the direction of the axes of this patient based coordinate system and the equipment based coordinate system in previous versions of this Standard will coincide. The Image Plane Attributes, in conjunction with the Pixel Spacing Attribute, describe the position and orientation of the image slices relative to the patient-based coordinate system. In each image frame the Image Position (Patient) (0020,0032) specifies the origin of the image with respect to the patient-based coordinate system. RCS and the Image Orientation (Patient) (0020,0037) attribute values specify the orientation of the image frame rows and columns. The mapping of pixel location to the RCS is calculated as follows: size 12{ left [ matrix { P rSub { size 8{x} } {} ## P rSub { size 8{y} } {} ## P rSub { size 8{z} } {} ## 1 } right ]= left [ matrix { X rSub { size 8{x} } Δi {} # Y rSub { size 8{x} } Δj {} # 0 {} # S rSub { size 8{x} } {} ## X rSub { size 8{y} } Δi {} # Y rSub { size 8{y} } Δj {} # 0 {} # S rSub { size 8{y} } {} ## X rSub { size 8{z} } Δi {} # Y rSub { size 8{z} } Δj {} # 0 {} # S rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { i {} ## j {} ## 0 {} ## 1 } right ]} {} = M Where: Pxyz The coordinates of the voxel (i,j) in the frame’s image plane in units of mm. Sxyz The three values of the Image Position (Patient) (0020,0032) attributes. It is the location in mm from the origin of the RCS. Xxyz The values from the row (X) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. Yxyz The values from the column (Y) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. i Column index to the image plane. The first column is index zero. i Column pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. j Row index to the image plane. The first row index is zero. j Row pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. Additional constraints apply: 1) The row and column direction cosine vectors shall be orthogonal, i.e. their dot product shall be zero. 2) The row and column direction cosine vectors shall be normal, i.e. the dot product of each direction cosine vector with itself shall be unity.
Identifies general characteristics of this frame. Only a single Item shall be permitted in this sequence. A number identifying the single continuous gathering of data over a period of time that resulted in this frame. The point in time that is most representative of when data was acquired for this frame. See C.7.6.16.2.2.1 and C.7.6.16.2.2.2 for further explanation. Note: The synchronization of this time with an external clock is specified in the synchronization Module in Acquisition Time synchronized (0018,1800). Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise.
Figure C.7.6.16-2 shows the relationships among the various timing parameters used.
The date and time that the acquisition of data that resulted in this frame started. See C.7.6.16.2.2.1 for further explanation. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise.
Figure C.7.6.16-2 shows the relationships among the various timing parameters used.
The actual amount of time [in milliseconds] that was used to acquire data for this frame. See C.7.6.16.2.2.1 and C.7.6.16.2.2.3 for further explanation. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise.
Figure C.7.6.16-2 shows the relationships among the various timing parameters used.
Description of the position in the cardiac cycle that is most representative of this frame. Defined Terms: END_SYSTOLE END_DIASTOLE UNDETERMINED Description of the position in the respiratory cycle that is most representative of this frame. Defined Terms: START _RESPIR END_RESPIR UNDETERMINED Contains the values of the indices defined in the Dimension Index Sequence (0020,9222) for this multi-frame header frame. The number of values is equal to the number of Items of the Dimension Index Sequence and shall be applied in the same order. See section C.7.6.17.1 for a description. Required if the value of the Dimension Index Sequence (0020,9222) contains Items. Ordinal number (starting from 1) of the frame in the set of frames with different temporal positions. Identification of a group of frames, with different positions and/or orientations that belong together, within a dimension organization. See C.7.6.16.2.2.4 for further explanation
Due to implementation specific reasons (such as maximum object size) the information of a multi-frame image may be split into more than one SOP Instance. These SOP Instances form together a Concatenation. This is a group of SOP Instances within a Series that is uniquely identified by the Concatenation UID (0020,9161). The Dimension Index Sequence (0020,9222) for each SOP Instance with the same Concatenation UID (0020,9161) shall contain exactly the same tags and values. In a Concatenation the Dimension Index Sequence (0020,9222) items of the Shared Functional Groups (5200,9229) shall be identical and have the same values for all individual SOP Instances. The items of the Per-frame Functional Groups (5200,9230) shall be identical for all individual SOP Instances but the values may change per frame. For all other Attributes of all the Modules of the IOD, the same Attributes shall be present and the values shall be identical, with the exception of the following Attributes:
The ordinal number of a frame in a group of frames, with the same Stack ID Required if Stack ID (0020,9056) is present. See section C.7.6.16.2.2.4 for further explanation. User-defined comments about the frame. Label corresponding to a specific dimension index value. Selected from a set of dimension values defined by the application. This attribute may be referenced by the Dimension Index Pointer (0020,9165) attribute in the Multi-frame Dimension Module. See C.7.6.16.2.2.5 for further explanation.
The Frame Label attribute (0020,9453) can be used to label frames that need to be handled as a group in application. The Dimension Index Pointer (0020,9165) from the Dimension Module may point to this attribute if it is the base of a dimension.
Identifies the position of the plane of this frame. Only a single Item shall be permitted in this sequence. The x, y, and z coordinates of the upper left hand corner (center of the first voxel transmitted) of the frame, in mm. See C.7.6.2.1.1 and C.7.6.16.2.3.1 for further explanation. Note: In the case of CT images with an Acquisition Type (0018,9302) of CONSTANT_ANGLE the image plane is defined to pass through the data collection center and be normal to the central ray of the diverging X-Ray beam. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Volumetric Properties (0008,9206) of this frame is other than DISTORTED, may be present otherwise.
The Image Position (0020,0032) specifies the x, y, and z coordinates of the upper left hand corner of the image; it is the center of the first voxel transmitted. Image Orientation (0020,0037) specifies the direction cosines of the first row and the first column with respect to the patient. These Attributes shall be provide as a pair. Row value for the x, y, and z axes respectively followed by the Column value for the x, y, and z axes respectively. The direction of the axes is defined fully by the patient’s orientation. The x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient. The patient based coordinate system is a right handed system, i.e. the vector cross product of a unit vector along the positive x-axis and a unit vector along the positive y-axis is equal to a unit vector along the positive z-axis. Note If a patient lies parallel to the ground, face-up on the table, with his feet-to-head direction same as the front-to-back direction of the imaging equipment, the direction of the axes of this patient based coordinate system and the equipment based coordinate system in previous versions of this Standard will coincide. The Image Plane Attributes, in conjunction with the Pixel Spacing Attribute, describe the position and orientation of the image slices relative to the patient-based coordinate system. In each image frame the Image Position (Patient) (0020,0032) specifies the origin of the image with respect to the patient-based coordinate system. RCS and the Image Orientation (Patient) (0020,0037) attribute values specify the orientation of the image frame rows and columns. The mapping of pixel location to the RCS is calculated as follows: size 12{ left [ matrix { P rSub { size 8{x} } {} ## P rSub { size 8{y} } {} ## P rSub { size 8{z} } {} ## 1 } right ]= left [ matrix { X rSub { size 8{x} } Δi {} # Y rSub { size 8{x} } Δj {} # 0 {} # S rSub { size 8{x} } {} ## X rSub { size 8{y} } Δi {} # Y rSub { size 8{y} } Δj {} # 0 {} # S rSub { size 8{y} } {} ## X rSub { size 8{z} } Δi {} # Y rSub { size 8{z} } Δj {} # 0 {} # S rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { i {} ## j {} ## 0 {} ## 1 } right ]} {} = M Where: Pxyz The coordinates of the voxel (i,j) in the frame’s image plane in units of mm. Sxyz The three values of the Image Position (Patient) (0020,0032) attributes. It is the location in mm from the origin of the RCS. Xxyz The values from the row (X) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. Yxyz The values from the column (Y) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. i Column index to the image plane. The first column is index zero. i Column pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. j Row index to the image plane. The first row index is zero. j Row pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. Additional constraints apply: 1) The row and column direction cosine vectors shall be orthogonal, i.e. their dot product shall be zero. 2) The row and column direction cosine vectors shall be normal, i.e. the dot product of each direction cosine vector with itself shall be unity.
Identifies orientation of the plane of this frame. Only a single Item shall be permitted in this sequence. The direction cosines of the first row and the first column with respect to the patient. See C.7.6.2.1.1 and C.7.6.16.2.3.1 for further explanation. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Volumetric Properties (0008,9206) of this frame is other than DISTORTED. May be present otherwise.
The Image Position (0020,0032) specifies the x, y, and z coordinates of the upper left hand corner of the image; it is the center of the first voxel transmitted. Image Orientation (0020,0037) specifies the direction cosines of the first row and the first column with respect to the patient. These Attributes shall be provide as a pair. Row value for the x, y, and z axes respectively followed by the Column value for the x, y, and z axes respectively. The direction of the axes is defined fully by the patient’s orientation. The x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient. The patient based coordinate system is a right handed system, i.e. the vector cross product of a unit vector along the positive x-axis and a unit vector along the positive y-axis is equal to a unit vector along the positive z-axis. Note If a patient lies parallel to the ground, face-up on the table, with his feet-to-head direction same as the front-to-back direction of the imaging equipment, the direction of the axes of this patient based coordinate system and the equipment based coordinate system in previous versions of this Standard will coincide. The Image Plane Attributes, in conjunction with the Pixel Spacing Attribute, describe the position and orientation of the image slices relative to the patient-based coordinate system. In each image frame the Image Position (Patient) (0020,0032) specifies the origin of the image with respect to the patient-based coordinate system. RCS and the Image Orientation (Patient) (0020,0037) attribute values specify the orientation of the image frame rows and columns. The mapping of pixel location to the RCS is calculated as follows: size 12{ left [ matrix { P rSub { size 8{x} } {} ## P rSub { size 8{y} } {} ## P rSub { size 8{z} } {} ## 1 } right ]= left [ matrix { X rSub { size 8{x} } Δi {} # Y rSub { size 8{x} } Δj {} # 0 {} # S rSub { size 8{x} } {} ## X rSub { size 8{y} } Δi {} # Y rSub { size 8{y} } Δj {} # 0 {} # S rSub { size 8{y} } {} ## X rSub { size 8{z} } Δi {} # Y rSub { size 8{z} } Δj {} # 0 {} # S rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { i {} ## j {} ## 0 {} ## 1 } right ]} {} = M Where: Pxyz The coordinates of the voxel (i,j) in the frame’s image plane in units of mm. Sxyz The three values of the Image Position (Patient) (0020,0032) attributes. It is the location in mm from the origin of the RCS. Xxyz The values from the row (X) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. Yxyz The values from the column (Y) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. i Column index to the image plane. The first column is index zero. i Column pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. j Row index to the image plane. The first row index is zero. j Row pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. Additional constraints apply: 1) The row and column direction cosine vectors shall be orthogonal, i.e. their dot product shall be zero. 2) The row and column direction cosine vectors shall be normal, i.e. the dot product of each direction cosine vector with itself shall be unity.
A sequence that provides reference to a set of SOP Class/Instance pairs identifying images or other composite SOP Instances used to plan the acquisition or significant related images. See Section C.7.6.16.2.5.1 for further explanation. Zero or more Items may be included in this Sequence.
Referenced Image Sequence (0008,1140) shall be used to provide a reference to a set of SOP Class/Instance pairs identifying other data objects used to plan the acquisition of this image where the images shall share the same Frame of Reference UID (0020,0052). For each Item that contains such a reference, the value of the Purpose of Reference Code Sequence (0040,A170) shall be (”121311”, DCM, ”Localizer"). Applications can use the Referenced Image Sequence (0008,1140) in combination with data in Plane Position and Plane Orientation Macros to provide projections of the position of an image with respect to the referenced image. The Referenced Image Sequence (0008,1140) may also be present when references to other images (or frames within other images) are required for other reasons, as specified by Purpose of Reference Code Sequence (0040,A170). Note: An Image may contain references to itself (e.g. to other frames within itself).
Describes the purpose for which the reference is made. Only a single Item shall be permitted in this sequence. See C.7.6.16.2.5.1 for further explanation.
Referenced Image Sequence (0008,1140) shall be used to provide a reference to a set of SOP Class/Instance pairs identifying other data objects used to plan the acquisition of this image where the images shall share the same Frame of Reference UID (0020,0052). For each Item that contains such a reference, the value of the Purpose of Reference Code Sequence (0040,A170) shall be (”121311”, DCM, ”Localizer"). Applications can use the Referenced Image Sequence (0008,1140) in combination with data in Plane Position and Plane Orientation Macros to provide projections of the position of an image with respect to the referenced image. The Referenced Image Sequence (0008,1140) may also be present when references to other images (or frames within other images) are required for other reasons, as specified by Purpose of Reference Code Sequence (0040,A170). Note: An Image may contain references to itself (e.g. to other frames within itself).
A sequence that that provides reference to the set of SOP Class/Instance pairs of the Images or other composite SOP Instances which were used to derive this frame. Zero or more Items may be included in this Sequence. A text description of how this frame data was derived. See C.7.6.1.1.3 for further explanation.
If an Image is identified to be a derived image (see C.7.6.1.1.2 Image Type), Derivation Description (0008,2111) and Derivation Code Sequence (0008,9215) describe the way in which the image was derived. They may be used whether or not the Source Image Sequence (0008,2112) is provided. They may also be used in cases when the Derived Image pixel data is not significantly changed from one of the source images and the SOP Instance UID of the Derived Image is the same as the one used for the source image. Notes: 1. Examples of Derived Images that would normally be expected to affect professional interpretation and would thus have a new UID include: a. images resulting from image processing of another image (e.g. unsharp masking), b. a multiplanar reformatted CT image, c. a DSA image derived by subtracting pixel values of one image from another. d. an image that has been decompressed after having been compressed with a lossy compression algorithm. To ensure that the user has the necessary information about the lossy compression, the approximate compression ratio may be included in Derivation Description (0008,2111). An example of a Derived Image that would normally not be expected to affect professional interpretation and thus would not require a new UID is an image that has been padded with additional rows and columns for more display purposes. 2. An image may be lossy compressed, e.g., for long term archive purposes, and its SOP Instance UID changed. PS3.4 provides a mechanism by which a query for the original image Instance may return a reference to the UID of the lossy compressed version of the image using the Alternate Representation Sequence (0008,3001). This allows an application processing a SOP Instance that references the original image UID, e.g., a Structured Report, to obtain a reference to an accessible version of the image even if the original SOP Instance is no longer available.
A coded description of how this frame was derived. See C.7.6.1.1.3 for further explanation. One or more Items may be included in this Sequence. More than one Item indicates that successive derivation steps have been applied.
If an Image is identified to be a derived image (see C.7.6.1.1.2 Image Type), Derivation Description (0008,2111) and Derivation Code Sequence (0008,9215) describe the way in which the image was derived. They may be used whether or not the Source Image Sequence (0008,2112) is provided. They may also be used in cases when the Derived Image pixel data is not significantly changed from one of the source images and the SOP Instance UID of the Derived Image is the same as the one used for the source image. Notes: 1. Examples of Derived Images that would normally be expected to affect professional interpretation and would thus have a new UID include: a. images resulting from image processing of another image (e.g. unsharp masking), b. a multiplanar reformatted CT image, c. a DSA image derived by subtracting pixel values of one image from another. d. an image that has been decompressed after having been compressed with a lossy compression algorithm. To ensure that the user has the necessary information about the lossy compression, the approximate compression ratio may be included in Derivation Description (0008,2111). An example of a Derived Image that would normally not be expected to affect professional interpretation and thus would not require a new UID is an image that has been padded with additional rows and columns for more display purposes. 2. An image may be lossy compressed, e.g., for long term archive purposes, and its SOP Instance UID changed. PS3.4 provides a mechanism by which a query for the original image Instance may return a reference to the UID of the lossy compressed version of the image using the Alternate Representation Sequence (0008,3001). This allows an application processing a SOP Instance that references the original image UID, e.g., a Structured Report, to obtain a reference to an accessible version of the image even if the original SOP Instance is no longer available.
A Sequence which identifies the set of Image or other SOP Class/Instance pairs of the Instances which were used to derive this frame. Zero or more Items may be included in this Sequence. See C.7.6.1.1.4 for further explanation.
If an Image is identified to be a Derived image (see C.7.6.1.1.2 Image Type), Source Image Sequence (0008,2112) is an optional list of Referenced SOP Class UID (0008,1150)/ Referenced SOP Instance UID (0008,1150) pairs that identify the source images used to create the Derived image. It may be used whether or not there is a description of the way the image was derived in Derivation Description (0008,2111) or Derivation Code Sequence (0008,9215). Note: Multiple Items may be present within Source Image Sequence (0008,2112), in which case either: a) those images were combined to make the derived image (e.g. multiple source images to make an MPR or MIP), or b) each of the items represents a step in the successive derivation of an image (e.g. when an image has had successive lossy compression steps applied to it), c) some combination of the above. The Purpose of Reference Code Sequence (0040,A170) and the Attributes within the referenced images themselves may be used to determine the history of the derivation, which is not otherwise explicitly specified.
Describes the purpose for which the reference is made, that is what role the source image or frame played in the derivation of this image or frame. Only a single Item shall be permitted in this sequence.
Sequence that describes the frame specific cardiac synchronization parameters. Only a single Item shall be permitted in this sequence. The nominal time relative to the preceding R peak divided by the nominal R-R interval multiplied by 100. Required if used as a dimension index, may be present otherwise. The nominal time in ms from the time of the previous R-peak to the value of the Frame Reference DateTime (0018,9151). See C.7.6.16.2.7.1 for further explanation.
The Nominal Cardiac Trigger Delay Time (0020,9153) is the nominal trigger delay time in ms from the previous R-peak to the value of the Frame Reference DateTime (0018,9151). When frames are acquired with prospective gating, that is, the data acquisition actually begins in response to a timed delay from the R-peak, it may be that Actual Cardiac Trigger Delay Time (0020,9252) and the Nominal Cardiac Trigger Delay Time (0020,9153) have the same value. However, when frames are the result of retrospective gating, that is, the data is continuously acquired and then later compared with a simultaneously acquired ECG waveform and fitted into time slots corresponding to nominal phases of the cardiac cycle, then Nominal Cardiac Trigger Delay Time (0020,9153) and the Actual Cardiac Trigger Delay Time (0020,9252) may have different values. When multiple cardiac cycles are averaged together, then the Low R-R Value (0018,1081), and High R-R Value (0018,1082) are an average of the cardiac cycles that were accepted in the frame. Note: For cardiac gated acquisitions the choice of the Frame Reference DateTime (0018,9151) is influenced by the Nominal Cardiac Trigger Delay Time (0020,9153). For respiratory gated acquisitions the choice of the Frame Reference DateTime (0018,9151) is influenced by the Nominal Respiratory Trigger Delay Time (0020,9255). Figure C.7.6.16-5 depicts the usage.
The actual time in ms from the time of the previous R-peak to the value of the Frame Reference DateTime (0018,9151). See C.7.6.16.2.7.1 for further explanation. Required if Intervals Acquired (0018,1083) is present and has a value of 1. May be present otherwise.
The Nominal Cardiac Trigger Delay Time (0020,9153) is the nominal trigger delay time in ms from the previous R-peak to the value of the Frame Reference DateTime (0018,9151). When frames are acquired with prospective gating, that is, the data acquisition actually begins in response to a timed delay from the R-peak, it may be that Actual Cardiac Trigger Delay Time (0020,9252) and the Nominal Cardiac Trigger Delay Time (0020,9153) have the same value. However, when frames are the result of retrospective gating, that is, the data is continuously acquired and then later compared with a simultaneously acquired ECG waveform and fitted into time slots corresponding to nominal phases of the cardiac cycle, then Nominal Cardiac Trigger Delay Time (0020,9153) and the Actual Cardiac Trigger Delay Time (0020,9252) may have different values. When multiple cardiac cycles are averaged together, then the Low R-R Value (0018,1081), and High R-R Value (0018,1082) are an average of the cardiac cycles that were accepted in the frame. Note: For cardiac gated acquisitions the choice of the Frame Reference DateTime (0018,9151) is influenced by the Nominal Cardiac Trigger Delay Time (0020,9153). For respiratory gated acquisitions the choice of the Frame Reference DateTime (0018,9151) is influenced by the Nominal Respiratory Trigger Delay Time (0020,9255). Figure C.7.6.16-5 depicts the usage.
Number of R-R intervals acquired. Number of R-R intervals rejected. Average number of heart beats per minute for the collection period for this frame. This shall include all accepted beats as well as rejected beats. Note: During prolonged acquisitions the average heart rate may differ from the reciprocal of the nominal R-R interval. Nominal R-peak - R-peak interval time in ms for the cardiac cycle used for the acquisition of this frame. See C.7.6.16.2.7.1 for further explanation. Required if Cardiac Synchronization Technique (0018,9037) equals other than NONE or REALTIME. May be present otherwise.
The Nominal Cardiac Trigger Delay Time (0020,9153) is the nominal trigger delay time in ms from the previous R-peak to the value of the Frame Reference DateTime (0018,9151). When frames are acquired with prospective gating, that is, the data acquisition actually begins in response to a timed delay from the R-peak, it may be that Actual Cardiac Trigger Delay Time (0020,9252) and the Nominal Cardiac Trigger Delay Time (0020,9153) have the same value. However, when frames are the result of retrospective gating, that is, the data is continuously acquired and then later compared with a simultaneously acquired ECG waveform and fitted into time slots corresponding to nominal phases of the cardiac cycle, then Nominal Cardiac Trigger Delay Time (0020,9153) and the Actual Cardiac Trigger Delay Time (0020,9252) may have different values. When multiple cardiac cycles are averaged together, then the Low R-R Value (0018,1081), and High R-R Value (0018,1082) are an average of the cardiac cycles that were accepted in the frame. Note: For cardiac gated acquisitions the choice of the Frame Reference DateTime (0018,9151) is influenced by the Nominal Cardiac Trigger Delay Time (0020,9153). For respiratory gated acquisitions the choice of the Frame Reference DateTime (0018,9151) is influenced by the Nominal Respiratory Trigger Delay Time (0020,9255). Figure C.7.6.16-5 depicts the usage.
R-R interval low limit for beat rejection, in ms. R-R interval high limit for beat rejection, in ms.
Identifies anatomic characteristics of this frame. Only a single Item shall be permitted in this sequence. Laterality of (possibly paired) body parts (as described in Anatomic Region Sequence (0008,2218)) examined. Enumerated Values: R = right L = left U = unpaired B = both left and right Note: This Attribute is mandatory, in order to ensure that frames may be positioned correctly relative to one another for display. Shall be consistent with any laterality information contained in Primary Anatomic Structure Modifier Sequence (0008,2230), if present. Contains the attributes involved in the transformation of stored pixel values. Only a single Item shall be permitted in this sequence. The value b in relationship between stored values (SV) and the output units. Output units = m*SV + b. m in the equation specified by Rescale Intercept (0028,1052). Specifies the output units of Rescale Slope (0028,1053) and Rescale Intercept (0028,1052). See C.11.1.1.2 for further explanation. Enumerated Value: US = Unspecified if Modality (0008,0060) equals MR.
Specifies the units of the output of the Modality LUT or rescale operation. Defined Terms: OD = The number in the LUT represents thousands of optical density. That is, a value of 2140 represents an optical density of 2.140. HU = Hounsfield Units (CT) US = Unspecified Other values are permitted, but are not defined by the DICOM Standard.
Window Center and Width values applied to the frame. Only one item is permitted in this sequence. Window Center for display. See C.11.2.1.2 for further explanation.
Window Center (0028,1050) and Window Width (0028,1051) specify a linear conversion from stored pixel values (after any Modality LUT or Rescale Slope and Intercept specified in the IOD have been applied) to values to be displayed. Window Center contains the input value that is the center of the window. Window Width contains the width of the window. Note: The terms “window center” and “window width” are not consistently used in practice, nor were they defined in previous versions of the standard. The definitions here are presented for the purpose of defining consistent meanings for identity and threshold transformations while preserving the common practice of using integral values for center and width. Window Width (0028,1051) shall always be greater than or equal to 1. When Window Width (0028,1051) is greater than 1, these Attributes select the range of input values that are to be mapped to the full range of the displayed output. When Window Width (0028,1051) is equal to 1, they specify a threshold below which input values will be displayed as the minimum output value. Note: Whether the minimum output value is rendered as black or white may depend on the value of Photometric Interpretation (0028,0004) or the presence of a Presentation LUT Module. These Attributes are applied according to the following pseudo-code, where x is the input value, y is an output value with a range from ymin to ymax, c is Window Center (0028,1050) and w is Window Width (0028,1051): if (x <= c - 0.5 - (w-1)/2), then y = ymin else if (x > c - 0.5 + (w-1)/2), then y = ymax, else y = ((x - (c - 0.5)) / (w-1) + 0.5) * (ymax - ymin)+ ymin Notes: 1. For the purpose of this definition, a floating point calculation without integer truncation is assumed, though the manner of implementation may vary as long as the result is the same. 2. The pseudo-code function computes a continuous value over the output range without any discontinuity at the boundaries. The value of 0 for w is expressly forbidden, and the value of 1 for w does not cause division by zero, since the continuous segment of the function will never be reached for that case. 3. For example, for an output range 0 to 255: c=2048, w=4096 becomes: if (x <= 0) then y = 0 else if (x > 4095) then y = 255 else y = ((x - 2047.5) / 4095 + 0.5) * (255-0) + 0 c=2048, w=1 becomes: if (x <= 2047.5) then y = 0 else if (x > 2047.5) then y = 255 else /* not reached */ c=0, w=100 becomes: if (x <= -50) then y = 0 else if (x > 49) then y = 255 else y = ((x + 0.5) / 99 + 0.5) * (255-0) + 0 c=0, w=1 becomes: if (x <= -0.5) then y = 0 else if (x > -0.5) then y = 255 else /* not reached */ 4. A Window Center of 2n-1 and a Window Width of 2n selects the range of input values from 0 to 2n-1. This represents an identity VOI LUT transformation in the case where no Modality LUT is specified and the stored pixel data are n bit unsigned integers. 5. A Window Width of 1 is typically used to represent a "threshold" operation in which those integer input values less than the Window Center are represented as the minimum displayed value and those greater than or equal to the Window Center are represented as the maximum displayed value. A Window Width of 2 will have the same result for integral input values. 6. The application of Window Center (0028,1050) and Window Width (0028,1051) may select a signed input range. There is no implication that this signed input range is clipped to zero. 7. The selected input range may exceed the actual range of the input values, thus effectively “compressing” the contrast range of the displayed data into a narrower band of the available contrast range, and “flattening” the appearance. There are no limits to the maximum value of the window width, or to the minimum or maximum value of window level, both of which may exceed the actual or possible range of input values. 8. Input values "below" the window are displayed as the minimum output value and input values "above" the window are displayed as the maximum output value. This is the common usage of the window operation in medical imaging. There is no provision for an alternative approach in which all values "outside" the window are displayed as the minimum output value. 9. The output of the Window Center/Width or VOI LUT transformation is either implicitly scaled to the full range of the display device if there is no succeeding transformation defined, or implicitly scaled to the full input range of the succeeding transformation step (such as the Presentation LUT), if present. See C.11.6.1. 10. Fractional values of Window Center and Window Width are permitted (since the VR of these Attributes is Decimal String), and though they are not often encountered, applications should be prepared to accept them. These Attributes shall be used only for Images with Photometric Interpretation (0028,0004) values of MONOCHROME1 and MONOCHROME2. They have no meaning for other Images. 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 may be presented. If any VOI LUT Table is included by an Image, a Window Width and Window Center or the VOI LUT Table, but not both, may be applied to the Image for display. Inclusion of both indicates that multiple alternative views may be presented. If multiple items are present in VOI LUT Sequence (0028,3010), only one may be applied to the Image for display. Multiple items indicate that multiple alternative views may be presented. If the VOI LUT Module is defined in an IOD and if neither a VOI LUT Sequence nor a Window Width and Window Center are present, then the VOI LUT stage of the grayscale pipeline is defined to be an identity transformation. Notes: 1. This requirement is specified so that IODs that define a particular output space for the grayscale pipeline, such as P-Values, are not in an undefined state when no VOI LUT Sequence or Window Width and Window Center are present. 2. Despite the Type 3 requirement for VOI LUT Sequence and Window Center, implementations that render images are expected to implement and apply these transformations when they are present in the image, unless overridden by the user, a presentation state, or a hanging protocol, and to allow the user to select which transformation to apply when multiple transformations are present.
Window Width for display. See C.11.2.1.2 for further explanation.
Window Center (0028,1050) and Window Width (0028,1051) specify a linear conversion from stored pixel values (after any Modality LUT or Rescale Slope and Intercept specified in the IOD have been applied) to values to be displayed. Window Center contains the input value that is the center of the window. Window Width contains the width of the window. Note: The terms “window center” and “window width” are not consistently used in practice, nor were they defined in previous versions of the standard. The definitions here are presented for the purpose of defining consistent meanings for identity and threshold transformations while preserving the common practice of using integral values for center and width. Window Width (0028,1051) shall always be greater than or equal to 1. When Window Width (0028,1051) is greater than 1, these Attributes select the range of input values that are to be mapped to the full range of the displayed output. When Window Width (0028,1051) is equal to 1, they specify a threshold below which input values will be displayed as the minimum output value. Note: Whether the minimum output value is rendered as black or white may depend on the value of Photometric Interpretation (0028,0004) or the presence of a Presentation LUT Module. These Attributes are applied according to the following pseudo-code, where x is the input value, y is an output value with a range from ymin to ymax, c is Window Center (0028,1050) and w is Window Width (0028,1051): if (x <= c - 0.5 - (w-1)/2), then y = ymin else if (x > c - 0.5 + (w-1)/2), then y = ymax, else y = ((x - (c - 0.5)) / (w-1) + 0.5) * (ymax - ymin)+ ymin Notes: 1. For the purpose of this definition, a floating point calculation without integer truncation is assumed, though the manner of implementation may vary as long as the result is the same. 2. The pseudo-code function computes a continuous value over the output range without any discontinuity at the boundaries. The value of 0 for w is expressly forbidden, and the value of 1 for w does not cause division by zero, since the continuous segment of the function will never be reached for that case. 3. For example, for an output range 0 to 255: c=2048, w=4096 becomes: if (x <= 0) then y = 0 else if (x > 4095) then y = 255 else y = ((x - 2047.5) / 4095 + 0.5) * (255-0) + 0 c=2048, w=1 becomes: if (x <= 2047.5) then y = 0 else if (x > 2047.5) then y = 255 else /* not reached */ c=0, w=100 becomes: if (x <= -50) then y = 0 else if (x > 49) then y = 255 else y = ((x + 0.5) / 99 + 0.5) * (255-0) + 0 c=0, w=1 becomes: if (x <= -0.5) then y = 0 else if (x > -0.5) then y = 255 else /* not reached */ 4. A Window Center of 2n-1 and a Window Width of 2n selects the range of input values from 0 to 2n-1. This represents an identity VOI LUT transformation in the case where no Modality LUT is specified and the stored pixel data are n bit unsigned integers. 5. A Window Width of 1 is typically used to represent a "threshold" operation in which those integer input values less than the Window Center are represented as the minimum displayed value and those greater than or equal to the Window Center are represented as the maximum displayed value. A Window Width of 2 will have the same result for integral input values. 6. The application of Window Center (0028,1050) and Window Width (0028,1051) may select a signed input range. There is no implication that this signed input range is clipped to zero. 7. The selected input range may exceed the actual range of the input values, thus effectively “compressing” the contrast range of the displayed data into a narrower band of the available contrast range, and “flattening” the appearance. There are no limits to the maximum value of the window width, or to the minimum or maximum value of window level, both of which may exceed the actual or possible range of input values. 8. Input values "below" the window are displayed as the minimum output value and input values "above" the window are displayed as the maximum output value. This is the common usage of the window operation in medical imaging. There is no provision for an alternative approach in which all values "outside" the window are displayed as the minimum output value. 9. The output of the Window Center/Width or VOI LUT transformation is either implicitly scaled to the full range of the display device if there is no succeeding transformation defined, or implicitly scaled to the full input range of the succeeding transformation step (such as the Presentation LUT), if present. See C.11.6.1. 10. Fractional values of Window Center and Window Width are permitted (since the VR of these Attributes is Decimal String), and though they are not often encountered, applications should be prepared to accept them. These Attributes shall be used only for Images with Photometric Interpretation (0028,0004) values of MONOCHROME1 and MONOCHROME2. They have no meaning for other Images. 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 may be presented. If any VOI LUT Table is included by an Image, a Window Width and Window Center or the VOI LUT Table, but not both, may be applied to the Image for display. Inclusion of both indicates that multiple alternative views may be presented. If multiple items are present in VOI LUT Sequence (0028,3010), only one may be applied to the Image for display. Multiple items indicate that multiple alternative views may be presented. If the VOI LUT Module is defined in an IOD and if neither a VOI LUT Sequence nor a Window Width and Window Center are present, then the VOI LUT stage of the grayscale pipeline is defined to be an identity transformation. Notes: 1. This requirement is specified so that IODs that define a particular output space for the grayscale pipeline, such as P-Values, are not in an undefined state when no VOI LUT Sequence or Window Width and Window Center are present. 2. Despite the Type 3 requirement for VOI LUT Sequence and Window Center, implementations that render images are expected to implement and apply these transformations when they are present in the image, unless overridden by the user, a presentation state, or a hanging protocol, and to allow the user to select which transformation to apply when multiple transformations are present.
Explanation of the Window Center and Width. Defined Terms for CT: BRAIN SOFT_TISSUE LUNG BONE Describes a VOI LUT function to apply to the values of Window Center (0028,1050) and Window Width (0028,1051). See C.11.2.1.3 for further explanation. Defined terms: LINEAR SIGMOID When this attribute is not present, the interpretation of the values of Window Center (0028,1050) and Window Width (0028,1051) is linear as in C.11.2.1.2.
The VOI LUT Function (0028,1056) specifies a potentially non-linear conversion for the output of the (conceptual) Modality LUT values to the input of the (conceptual) Presentation LUT. The behavior for the value LINEAR is defined in C.11.2.1.2. For all other values, the VOI LUT Function (0028,1056) shall include a unique descriptor of the LUT function to be used. Each descriptor is associated with a bivariate function of Window Center (0028,1050) and Window Width (0028,1051). If the VOI LUT Function (0028,1056) is present with a value other than LINEAR, the values provided in Window Center (0028,1050) and Window Width (0028,1051) shall not be interpreted as a linear conversion of the (conceptual) Modality LUT values to the input to the (conceptual) Presentation LUT – but as parameters for the function defined by the VOI LUT Function descriptor in (0028,1056). When defined, each descriptor must provide the functional relationship between the output of the (conceptual) Modality LUT values to the input of the (conceptual) Presentation LUT.
The mapping of stored values to associated real world values. One or more Items may be included in this sequence. Specifies the first stored value mapped for the Real Word Value Intercept (0040,9224) and Real World Value Slope (0040,9225) or Real World Value LUT (0040,9212) of this Item. See C.7.6.16.2.11.1 for further explanation.
Specifies the last stored value mapped for the Real Word Value Intercept (0040,9224) and Real World Value Slope (0040,9225) or Real World Value LUT (0040,9212) of this Item. See C.7.6.16.2.11.1 for further explanation.
The Intercept value in relationship between stored values (SV) and the real world values. See section C.7.6.16.2.11.2 for further explanation. Required if Real World Value LUT Data (0040,9212) is not present. The Slope value in relationship between stored values (SV) and the real world values. See section C.7.6.16.2.11.2 for further explanation. Required if Real World Value LUT Data (0040,9212) is not present. LUT Data in this Sequence. Required if Real World Value Intercept (0040,9224) is not present. Free form text explanation of the meaning of the LUT. Label that is used to identify this transformation. Units of measurement. Only a single value shall be present. See C.7.6.16.2.11.1 for further explanation.
Contains the attributes describing the use of contrast for this frame. One or more Items shall be present in this sequence. Identifying number corresponding to the agent described in the Enhanced Contrast/Bolus Module. The number shall be 1 for the first Item and increase by 1 for each subsequent Item. The administration of the selected agent had begun by the time this frame was acquired. Enumerated Values: YES NO The selected agent was detected in the frame. Enumerated Values: YES NO May only be zero length if the acquisition device is not capable of detecting the presence of this contrast agent in the frame. Nominal phase of intravenous contrast administration. Defined terms: PRE_CONTRAST POST_CONTRAST IMMEDIATE DYNAMIC STEADY_STATE DELAYED ARTERIAL CAPILLARY VENOUS PORTAL_VENOUS Required if Contrast/Bolus Administration Route Sequence (0018,0014) for the Contrast/Bolus Agent Number (0018,9337) defined in the Contrast/Bolus Agent Sequence (0018,0012) is (G-D101, SRT, "Intravenous route") or (G-D101, SNM3, "Intravenous route"); may be present otherwise. Note: SRT is the preferred designator for SNOMED, but SNM3 is allowed for backward compatibility. See PS3.16. Defines a sequence of Pixel Intensity Relationship LUTs. One or more items shall be present in this sequence. At least one item with LUT Function (0028,9474) equals TO_LINEAR LUT shall be present if Pixel Intensity Relationship (0028,1040) equals LOG. Only a single item with LUT Function (0028,9474) equals TO_LINEAR LUT shall be present. Specifies the format of the LUT Data in this Sequence. See C.11.1.1 and C.7.6.16.2.13.1 for further explanation.
LUT Data in this Sequence. The transformation function this LUT applies to the stored pixel values. Defined Terms: TO_LOG TO_LINEAR Sequence containing the pixel shift for a number of masks for this frame. One or more items shall be present in this sequence. Identifier of the Subtraction Item in the Mask Subtraction Sequence (0028,6100) to which this pixel shift is associated. See C.7.6.16.2.14.1.
Subtraction Item ID (0028,9416) specifies the ID of a subtraction operation to which the Mask Sub-pixel Shift (0028,6114) is associated. The Subtraction Item ID is also present in the Mask Subtraction Sequence (0028,6100) to allow this association. When used as per-frame macro, the Subtraction Item ID (0028,9416) allows to specify different values of Mask Sub-pixel Shift (0028,6114) individually frame by frame, and relate them to a single item of the Mask Subtraction Sequence (0028,6100). Note: There is no restriction in the number of Subtraction Item ID’s associated to each contrast frame. The same contrast frame may be present in several items of the Mask Subtraction Sequence, each item having a different value of Subtraction Item ID. When used as shared macro, the Subtraction Item ID (0028,9416) allows to specify one or more values of Mask Sub-pixel Shift that will be applied to all the frames of the Multi-frame image. Note: Example of usage of Subtraction Item ID in a per-frame macro, see Figure C.7.6.16-8: In this example of Multi-Frame Image with 3 frames, one Mask Frame (i.e., Frame 1) is applied to the next two frames of the Multi-Frame image (i.e., Frames 2 and 3). Therefore, there is only one item in the Mask Subtraction Sequence, containing its own Subtraction Item ID value (i.e., 100). The Frame Pixel Shift Macro allows to define a Mask Sub-Pixel Shift different for each contrast frame. First Frame Subtracted: Subtraction of Frame 1 (Mask) to Frame 2, with Sub-Pixel Shift 1.3\2.4 Second Frame Subtracted: Subtraction of Frame 1 (Mask) to Frame 3, with Sub-Pixel Shift 1.9\3.0 Figure C.7.6.16-8 Example of usage of Subtraction Item ID in a per-frame Macro
A pair of floating point numbers specifying the fractional vertical [adjacent row spacing] and horizontal [adjacent column spacing] pixel shift applied to the mask before subtracting it from this contrast frame. Note: If no pixel shift has to be applied a pair of zero values should be specified. See Section C.7.6.10.1.2.
A pair of floating point numbers specifying the fractional vertical [adjacent row spacing] and horizontal [adjacent column spacing] pixel shift applied to the mask before subtracting it from the contrast frame. The row offset results in a shift of the pixels along the column axis. The column offset results in a shift of the pixels along the row axis. A positive row offset is a shift toward the pixels of the lower row of the pixel plane. A positive column offset is a shift toward the pixels of the left hand side column of the pixel plane.
Sequence containing the row and column directions for this frame in the patient. Only a single Item shall be permitted in this sequence. Patient direction of the rows and columns of this frame. See C.7.6.1.1.1 for further explanation.
The Patient Orientation (0020,0020) relative to the image plane shall be specified by two values that designate the anatomical direction of the positive row axis (left to right) and the positive column axis (top to bottom). The first entry is the direction of the rows, given by the direction of the last pixel in the first row from the first pixel in that row. The second entry is the direction of the columns, given by the direction of the last pixel in the first column from the first pixel in that column. Anatomical direction shall be designated by the capital letters: A (anterior), P (posterior), R (right), L (left), H (head), F (foot). Each value of the orientation attribute shall contain at least one of these characters. If refinements in the orientation descriptions are to be specified, then they shall be designated by one or two additional letters in each value. Within each value, the letters shall be ordered with the principal orientation designated in the first character.
Sequence containing the display shutter parameters for this frame. Only a single Item shall be permitted in this sequence. Sequence that describes the frame specific respiratory synchronization parameters. Only a single Item shall be permitted in this sequence. Measured interval time in ms from maximum respiration peak to the next peak for the respiratory cycle in which this frame occurs. See C.7.6.16.2.17.1 for further explanation. Required if Respiratory Motion Compensation Technique (0018,9170) equals other than NONE or REALTIME and Respiratory Trigger Type (0020,9250) is absent or has a value of TIME or BOTH.
For time based respiratory gating, the Nominal Respiratory Trigger Delay Time (0020,9255) is the prescribed trigger delay time in ms from the previous Respiratory-peak to the value of the Frame Reference DateTime (0018,9151). When frames are acquired with prospective gating, that is, the data acquisition actually begins in response to a timed delay from the Respiratory trigger, it may be that Actual Respiratory Trigger Delay Time (0020,9257) and the Nominal Respiratory Trigger Delay Time (0020,9255) have the same value. However, when frames are the result of retrospective gating, that is, the data is continuously acquired and then later compared with a simultaneously acquired respiratory waveform and fitted into bins corresponding to nominal phases of the respiratory cycle, then Nominal Respiratory Trigger Delay Time (0020,9255) and the Actual Respiratory Trigger Delay Time (0020,9257) may have different values. Figure C.7.6.16-9a and C.7.6.16-9b depict the usage. Figure C.7.6.16-9a Respiratory Timing Tags Figure C.7.6.16-9b Relationship of Respiratory Amplitude Attributes
The nominal time relative to the preceding respiratory inspiration maximum divided by the nominal respiratory interval multiplied by 100. Required if used as a dimension index, may be present otherwise. The nominal time in ms from the beginning of the respiratory interval to the value of the Frame Reference DateTime (0018,9151). See C.7.6.16.2.17.1 for further explanation.
For time based respiratory gating, the Nominal Respiratory Trigger Delay Time (0020,9255) is the prescribed trigger delay time in ms from the previous Respiratory-peak to the value of the Frame Reference DateTime (0018,9151). When frames are acquired with prospective gating, that is, the data acquisition actually begins in response to a timed delay from the Respiratory trigger, it may be that Actual Respiratory Trigger Delay Time (0020,9257) and the Nominal Respiratory Trigger Delay Time (0020,9255) have the same value. However, when frames are the result of retrospective gating, that is, the data is continuously acquired and then later compared with a simultaneously acquired respiratory waveform and fitted into bins corresponding to nominal phases of the respiratory cycle, then Nominal Respiratory Trigger Delay Time (0020,9255) and the Actual Respiratory Trigger Delay Time (0020,9257) may have different values. Figure C.7.6.16-9a and C.7.6.16-9b depict the usage. Figure C.7.6.16-9a Respiratory Timing Tags Figure C.7.6.16-9b Relationship of Respiratory Amplitude Attributes
The actual time in ms from the beginning of the respiratory interval to the value of the Frame Reference DateTime (0018,9151). See C.7.6.16.2.17.1 for further explanation. Required if Respiratory Trigger Type (0020,9250) is TIME or BOTH.
For time based respiratory gating, the Nominal Respiratory Trigger Delay Time (0020,9255) is the prescribed trigger delay time in ms from the previous Respiratory-peak to the value of the Frame Reference DateTime (0018,9151). When frames are acquired with prospective gating, that is, the data acquisition actually begins in response to a timed delay from the Respiratory trigger, it may be that Actual Respiratory Trigger Delay Time (0020,9257) and the Nominal Respiratory Trigger Delay Time (0020,9255) have the same value. However, when frames are the result of retrospective gating, that is, the data is continuously acquired and then later compared with a simultaneously acquired respiratory waveform and fitted into bins corresponding to nominal phases of the respiratory cycle, then Nominal Respiratory Trigger Delay Time (0020,9255) and the Actual Respiratory Trigger Delay Time (0020,9257) may have different values. Figure C.7.6.16-9a and C.7.6.16-9b depict the usage. Figure C.7.6.16-9a Respiratory Timing Tags Figure C.7.6.16-9b Relationship of Respiratory Amplitude Attributes
Nominal amplitude of the respiratory signal at which the acquisition of data for this frame begins, in percent of the nominal maximum value (which represents maximum inspiration). Required if Respiratory Trigger Type (0020,9250) is AMPLITUDE or BOTH. The phase of respiration at which the Starting Respiratory Amplitude (0020,9246) was measured. Enumerated Value: INSPIRATION MAXIMUM EXPIRATION MINIMUM Required if Starting Respiratory Amplitude (0020,9246) is present. Nominal amplitude of the respiratory signal at which the acquisition of data for this frame ends, in percent of the nominal maximum value (which represents maximum inspiration). Required if Respiratory Trigger Type (0020,9250) is AMPLITUDE or BOTH. The phase of respiration at which the Ending Respiratory Amplitude (0020,9248) was measured. Enumerated Value: INSPIRATION MAXIMUM EXPIRATION MINIMUM Required if Ending Respiratory Amplitude (0020,9248) is present.
Sequence containing the Irradiation Event Identification for this frame. Only a single Item shall be permitted in this sequence. Unique identification of the irradiation event(s) associated with the acquisition of this image. Sequence that lists the Dimension Organization UIDs referenced by the containing SOP Instance. See section C.7.6.17.2 for further explanation. Zero or more Items may be included in this Sequence. Uniquely identifies a set of dimensions referenced within the containing SOP Instance. See section C.7.6.17.2 for further explanation. Identifies the sequence containing the indices used to specify the dimension of the multi-frame object. Zero or more Items may be included in this sequence. Contains the Data Element Tag that is used to identify the Attribute connected with the index. See section C.7.6.17.1 for further explanation. Identification of the creator of a group of private data elements. Required if the Dimension Index Pointer (0020,9165) value is the Data Element Tag of a Private Attribute. Contains the Data Element Tag of the Functional Group Sequence that contains the Attribute that is referenced by the Dimension Index Pointer (0020,9165). See section C.7.6.17.1 for further explanation. Required if the value of the Dimension Index Pointer (0020,9165) is the Data Element Tag of an Attribute that is contained within a Functional Group Sequence. Identification of the creator of a group of private data elements. Required if the Functional Group Pointer 0020,9167) value is the Data Element Tag of a Private Attribute. Uniquely identifies a set of dimensions referenced within the containing SOP Instance. In particular the dimension described by this sequence item is associated with this Dimension Organization UID. See section C.7.6.17.2 for further explanation. Required if the value of the Dimension Organization Sequence (0020,9221) contains Items Free text description that explains the meaning of the dimension. Defines if a cardiac synchronization technique was applied during or after the acquisition. Enumerated Values: NONE REALTIME = total time for the acquisition is shorter than cardiac cycle, no gating is applied PROSPECTIVE = certain thresholds have been set for a gating window that defines the acceptance of measurement data during the acquisition RETROSPECTIVE = certain thresholds have been set for a gating window that defines the acceptance of measurement data after the acquisition PACED = there is a constant RR interval (e.g., Pacemaker), which makes thresholding not required Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Cardiac Signal Source. Defined Terms: ECG = electrocardiogram VCG = vector cardiogram PP = peripheral pulse MR = magnetic resonance, i.e. M-mode or cardiac navigator Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and Cardiac Synchronization Technique (0018,9037) equals other than NONE. Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and Cardiac Synchronization Technique (0018,9037) equals other than NONE. R-R interval in ms measured prior to or during the scan. Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and Cardiac Synchronization Technique (0018,9037) equals other than NONE. Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and Cardiac Synchronization Technique (0018,9037) equals other than NONE. Note: The Heart Rate (0018,1088) attribute is not used in this Module, since its value can be derived as 1/ Cardiac RR Interval Specified (0018,9070). Cardiac arrhythmia rejection technique. Defined Terms: NONE RR_INTERVAL = rejection based on deviation from average RR interval QRS_LOOP = rejection based on deviation from regular QRS loop PVC = rejection based on PVC criteria Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and Cardiac Synchronization Technique (0018,9037) equals PROSPECTIVE or RETROSPECTIVE. Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and Cardiac Synchronization Technique (0018,9037) equals PROSPECTIVE or RETROSPECTIVE. R-R interval low limit for beat rejection, in ms. Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and Cardiac Synchronization Technique (0018,9037) equals PROSPECTIVE or RETROSPECTIVE. Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and Cardiac Synchronization Technique (0018,9037) equals PROSPECTIVE or RETROSPECTIVE. R-R interval high limit for beat rejection, in ms. Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and Cardiac Synchronization Technique (0018,9037) equals PROSPECTIVE or RETROSPECTIVE. Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and Cardiac Synchronization Technique (0018,9037) equals PROSPECTIVE or RETROSPECTIVE. Number of R-R intervals acquired and used to create the image (not including the intervals rejected). Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and Cardiac Synchronization Technique (0018,9037) equals other than NONE. Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and Cardiac Synchronization Technique (0018,9037) equals other than NONE. Number of R-R intervals rejected. Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and Cardiac Synchronization Technique (0018,9037) equals other than NONE. Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and Cardiac Synchronization Technique (0018,9037) equals other than NONE. Number of beats prescribed to be skipped after each detected arrhythmia. Description of type of framing performed. Defined Terms: FORW = time forward from trigger BACK = time back before trigger PCNT = percentage of R-R forward from trigger See C.7.6.18.1.1.1. Required if type of framing is not time forward from trigger, may be present otherwise.
Cardiac Framing Type (0018,1064) is the mechanism used to select the data acquired to construct the frames within a specified cardiac timing interval.C.7.6.18.2 Respiratory Synchronization Module Table C7.6.18-2 specifies the attributes of the Respiratory Synchronization Module. Table C.7.6.18-2 RESPIRATORY SYNCHRONIZATION MODULE ATTRIBUTES
Applied technique to reduce respiratory motion artifacts. Defined Terms: NONE BREATH_HOLD REALTIME = image acquisition shorter than respiratory cycle GATING = Prospective gating TRACKING = prospective through-plane or in-plane motion tracking PHASE_ORDERING = prospective phase ordering PHASE_RESCANNING = prospective techniques, such as real-time averaging, diminishing variance and motion adaptive gating RETROSPECTIVE = retrospective gating CORRECTION = retrospective image correction Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Signal source from which respiratory motion is derived. Defined Terms: NONE BELT = includes various devices that detect or track expansion of the chest NASAL_PROBE CO2_SENSOR NAVIGATOR = MR navigator and organ edge detection MR_PHASE = phase (of center k-space line) ECG = baseline demodulation of the ECG Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and Respiratory Motion Compensation Technique (0018,9170) equals other than NONE. Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and Respiratory Motion Compensation Technique (0018,9170 equals other than NONE. Respiratory trigger threshold in percent of the chest expansion for the frame relative to the last Respiratory-Peak. See C.7.6.16.2.17.1 for further explanation. Required if Respiratory Motion Compensation Technique (0018,9170) equals other than NONE, REALTIME or BREATH_HOLD and if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise.
For time based respiratory gating, the Nominal Respiratory Trigger Delay Time (0020,9255) is the prescribed trigger delay time in ms from the previous Respiratory-peak to the value of the Frame Reference DateTime (0018,9151). When frames are acquired with prospective gating, that is, the data acquisition actually begins in response to a timed delay from the Respiratory trigger, it may be that Actual Respiratory Trigger Delay Time (0020,9257) and the Nominal Respiratory Trigger Delay Time (0020,9255) have the same value. However, when frames are the result of retrospective gating, that is, the data is continuously acquired and then later compared with a simultaneously acquired respiratory waveform and fitted into bins corresponding to nominal phases of the respiratory cycle, then Nominal Respiratory Trigger Delay Time (0020,9255) and the Actual Respiratory Trigger Delay Time (0020,9257) may have different values. Figure C.7.6.16-9a and C.7.6.16-9b depict the usage. Figure C.7.6.16-9a Respiratory Timing Tags Figure C.7.6.16-9b Relationship of Respiratory Amplitude Attributes
Characteristic of the respiratory signal used to the define the respiratory triggering. Defined Terms: TIME AMPLITUDE BOTH Required if the value is not TIME, may be present otherwise.
Applied technique to reduce bulk or other physiology motion artifacts. Defined Terms: NONE REALTIME = image acquisition shorter than motion cycle GATING = prospective gating TRACKING = prospective through and/or in‑plane motion tracking RETROSPECTIVE = retrospective gating CORRECTION = retrospective image correction Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Signal source to measure motion. Defined Terms: JOINT = joint motion detection NAVIGATOR = MR navigator and organ edge detection MR_PHASE = phase (of center k‑space line) Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and Bulk Motion Compensation Technique (0018,9172) equals other than NONE. Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and Bulk Motion Compensation Technique (0018,9172) equals other than NONE. Specifies the format of the Red Palette Color Lookup Table Data (0028,1201). See C.7.6.3.1.5 for further explanation.
The three values of Palette Color Lookup Table Descriptor (0028,1101-1103) describe the format of the Lookup Table Data in the corresponding Data Element (0028,1201-1203) or (0028,1221-1223). The first value is the number of entries in the lookup table. When the number of table entries is equal to 216 then this value shall be 0. The first value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The second value is the first stored pixel value mapped. This pixel value is mapped to the first entry in the Lookup Table Data. All image pixel values less than the first value mapped are also mapped to the first entry in the Lookup Table Data if the Photometric Interpretation is PALETTE COLOR. Note: In the case of the Supplemental Palette Color LUT, the stored pixel values less than the second descriptor value are grayscale values. An image pixel value one greater than the first value mapped is mapped to the second entry in the Lookup Table Data. Subsequent image pixel values are mapped to the subsequent entries in the Lookup Table Data up to an image pixel value equal to number of entries + first value mapped – 1, which is mapped to the last entry in the Lookup Table Data. Image pixel values greater than or equal to number of entries + first value mapped are also mapped to the last entry in the Lookup Table Data. The second value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The third value specifies the number of bits for each entry in the Lookup Table Data. It shall take the value of 8 or 16. The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where in both cases the high bit is equal to bits allocated-1. The third value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. Note: Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits; this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry. The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16. When the Palette Color Lookup Table Descriptor (0028,1101-1103) are used as part of the Palette Color Lookup Table Module or the Supplemental Palette Color Lookup Table Module, the third value shall be equal to 16. Notes: 1. A value of 16 indicates the Lookup Table Data will range from (0,0,0) minimum intensity to (65535,65535,65535) maximum intensity. 2. Since the Palette Color Lookup Table Descriptor (0028,1101-1103) Attributes are multi-valued, in an Explicit VR Transfer Syntax, only one value representation (US or SS) may be specified, even though the first and third values are always by definition interpreted as unsigned. The explicit VR actually used is dictated by the VR needed to represent the second value, which will be consistent with Pixel Representation (0028,0103).
Specifies the format of the Green Palette Color Lookup Table Data (0028,1202). See C.7.6.3.1.5 for further explanation.
The three values of Palette Color Lookup Table Descriptor (0028,1101-1103) describe the format of the Lookup Table Data in the corresponding Data Element (0028,1201-1203) or (0028,1221-1223). The first value is the number of entries in the lookup table. When the number of table entries is equal to 216 then this value shall be 0. The first value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The second value is the first stored pixel value mapped. This pixel value is mapped to the first entry in the Lookup Table Data. All image pixel values less than the first value mapped are also mapped to the first entry in the Lookup Table Data if the Photometric Interpretation is PALETTE COLOR. Note: In the case of the Supplemental Palette Color LUT, the stored pixel values less than the second descriptor value are grayscale values. An image pixel value one greater than the first value mapped is mapped to the second entry in the Lookup Table Data. Subsequent image pixel values are mapped to the subsequent entries in the Lookup Table Data up to an image pixel value equal to number of entries + first value mapped – 1, which is mapped to the last entry in the Lookup Table Data. Image pixel values greater than or equal to number of entries + first value mapped are also mapped to the last entry in the Lookup Table Data. The second value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The third value specifies the number of bits for each entry in the Lookup Table Data. It shall take the value of 8 or 16. The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where in both cases the high bit is equal to bits allocated-1. The third value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. Note: Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits; this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry. The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16. When the Palette Color Lookup Table Descriptor (0028,1101-1103) are used as part of the Palette Color Lookup Table Module or the Supplemental Palette Color Lookup Table Module, the third value shall be equal to 16. Notes: 1. A value of 16 indicates the Lookup Table Data will range from (0,0,0) minimum intensity to (65535,65535,65535) maximum intensity. 2. Since the Palette Color Lookup Table Descriptor (0028,1101-1103) Attributes are multi-valued, in an Explicit VR Transfer Syntax, only one value representation (US or SS) may be specified, even though the first and third values are always by definition interpreted as unsigned. The explicit VR actually used is dictated by the VR needed to represent the second value, which will be consistent with Pixel Representation (0028,0103).
Specifies the format of the Blue Palette Color Lookup table Data (0028,1203). See C.7.6.3.1.5 for further explanation.
The three values of Palette Color Lookup Table Descriptor (0028,1101-1103) describe the format of the Lookup Table Data in the corresponding Data Element (0028,1201-1203) or (0028,1221-1223). The first value is the number of entries in the lookup table. When the number of table entries is equal to 216 then this value shall be 0. The first value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The second value is the first stored pixel value mapped. This pixel value is mapped to the first entry in the Lookup Table Data. All image pixel values less than the first value mapped are also mapped to the first entry in the Lookup Table Data if the Photometric Interpretation is PALETTE COLOR. Note: In the case of the Supplemental Palette Color LUT, the stored pixel values less than the second descriptor value are grayscale values. An image pixel value one greater than the first value mapped is mapped to the second entry in the Lookup Table Data. Subsequent image pixel values are mapped to the subsequent entries in the Lookup Table Data up to an image pixel value equal to number of entries + first value mapped – 1, which is mapped to the last entry in the Lookup Table Data. Image pixel values greater than or equal to number of entries + first value mapped are also mapped to the last entry in the Lookup Table Data. The second value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The third value specifies the number of bits for each entry in the Lookup Table Data. It shall take the value of 8 or 16. The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where in both cases the high bit is equal to bits allocated-1. The third value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. Note: Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits; this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry. The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16. When the Palette Color Lookup Table Descriptor (0028,1101-1103) are used as part of the Palette Color Lookup Table Module or the Supplemental Palette Color Lookup Table Module, the third value shall be equal to 16. Notes: 1. A value of 16 indicates the Lookup Table Data will range from (0,0,0) minimum intensity to (65535,65535,65535) maximum intensity. 2. Since the Palette Color Lookup Table Descriptor (0028,1101-1103) Attributes are multi-valued, in an Explicit VR Transfer Syntax, only one value representation (US or SS) may be specified, even though the first and third values are always by definition interpreted as unsigned. The explicit VR actually used is dictated by the VR needed to represent the second value, which will be consistent with Pixel Representation (0028,0103).
Red Palette Color Lookup Table Data. See C.7.6.3.1.6 for further explanation.
Palette Color Lookup Table Data (0028,1201-1203) contain the lookup table data corresponding to the Lookup Table Descriptor (0028,1101-1103). Palette color values must always be scaled across the full range of available intensities. This is indicated by the fact that there are no bits stored and high bit values for palette color data. Note: For example, if there are 16 bits per entry specified and only 8 bits of value are truly used then the 8 bit intensities from 0 to 255 must be scaled to the corresponding 16 bit intensities from 0 to 65535. To do this for 8 bit values, simply replicate the value in both the most and least significant bytes. These lookup tables shall be used only when there is a single sample per pixel (single image plane) in the image. These lookup tables are required when the value of Photometric Interpretation (0028,0004) is Palette Color. The semantics of these lookup tables is not defined otherwise.
Green Palette Color Lookup Table Data. See C.7.6.3.1.6 for further explanation.
Palette Color Lookup Table Data (0028,1201-1203) contain the lookup table data corresponding to the Lookup Table Descriptor (0028,1101-1103). Palette color values must always be scaled across the full range of available intensities. This is indicated by the fact that there are no bits stored and high bit values for palette color data. Note: For example, if there are 16 bits per entry specified and only 8 bits of value are truly used then the 8 bit intensities from 0 to 255 must be scaled to the corresponding 16 bit intensities from 0 to 65535. To do this for 8 bit values, simply replicate the value in both the most and least significant bytes. These lookup tables shall be used only when there is a single sample per pixel (single image plane) in the image. These lookup tables are required when the value of Photometric Interpretation (0028,0004) is Palette Color. The semantics of these lookup tables is not defined otherwise.
Blue Palette Color Lookup Table Data. See C.7.6.3.1.6 for further explanation.
Palette Color Lookup Table Data (0028,1201-1203) contain the lookup table data corresponding to the Lookup Table Descriptor (0028,1101-1103). Palette color values must always be scaled across the full range of available intensities. This is indicated by the fact that there are no bits stored and high bit values for palette color data. Note: For example, if there are 16 bits per entry specified and only 8 bits of value are truly used then the 8 bit intensities from 0 to 255 must be scaled to the corresponding 16 bit intensities from 0 to 65535. To do this for 8 bit values, simply replicate the value in both the most and least significant bytes. These lookup tables shall be used only when there is a single sample per pixel (single image plane) in the image. These lookup tables are required when the value of Photometric Interpretation (0028,0004) is Palette Color. The semantics of these lookup tables is not defined otherwise.
A 4x4 homogeneous transformation matrix that maps patient coordinate space of the reconstructed image to the equipment defined original coordinate space. Matrix elements shall be listed in row-major order. See C.7.6.21.1.
The Image to Equipment Mapping Matrix (0028,9520) is used to describe the relationship between the Patient oriented coordinate system and a modality specific equipment coordinate system. This mapping can only be used with systems that have a well-defined equipment coordinate system (such as XA, etc.). The Image to Equipment Mapping Matrix AMB describes how to transform a point (Bx,By,Bz) with respect to the Patient coordinate system into (Ax,Ay,Az) with respect to the equipment coordinate system according to the equation below. size 12{ left [ matrix { "" lSup { size 8{A} } x {} ## "" lSup { size 8{A} } y {} ## "" lSup { size 8{A} } z {} ## 1 } right ]= left [ matrix { M rSub { size 8{"11"} } {} # M rSub { size 8{"12"} } {} # M rSub { size 8{"13"} } {} # T rSub { size 8{x} } {} ## M rSub { size 8{"21"} } {} # M rSub { size 8{"22"} } {} # M rSub { size 8{"23"} } {} # T rSub { size 8{y} } {} ## M rSub { size 8{"31"} } {} # M rSub { size 8{"32"} } {} # M rSub { size 8{"33"} } {} # T rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { "" lSup { size 8{B} } x {} ## "" lSup { size 8{B} } y {} ## "" lSup { size 8{B} } z {} ## 1 } right ]} {} The Image to Equipment Mapping Matrix is a rigid transformation that involves only translations and rotations. Mathematically, the matrix shall be orthonormal and can describe six degrees of freedom: three translations, and three rotations. Note: Both the Patient Coordinate System and the Equipment Coordinate System are expressed in millimeters.
Identification of the type of equipment coordinate system in which the projection images were acquired. See C.7.6.21.2. Defined Terms: ISOCENTER
The Equipment Coordinate System Identification (0028,9537) identifies the Reference Coordinate System to which the Image to Equipment Mapping Matrix (0028,9520) is related. The Defined Term ISOCENTER refers to a coordinate reference system where the origin corresponds with the center of rotation of the projections. Note: For X-Ray 3D Angiographic Images created from SOP Instances of the Enhanced XA SOP Class (1.2.840.10008.5.1.4.1.1.12.1.1) the isocenter coordinate system is used to describe the positioning of the table and positioner (see C.8.19.6.13), and will use only the Defined Term ISOCENTER.
Specifies the format of the Red Palette Color Lookup Table Data (0028,1201). See C.7.6.3.1.5 for further explanation.
The three values of Palette Color Lookup Table Descriptor (0028,1101-1103) describe the format of the Lookup Table Data in the corresponding Data Element (0028,1201-1203) or (0028,1221-1223). The first value is the number of entries in the lookup table. When the number of table entries is equal to 216 then this value shall be 0. The first value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The second value is the first stored pixel value mapped. This pixel value is mapped to the first entry in the Lookup Table Data. All image pixel values less than the first value mapped are also mapped to the first entry in the Lookup Table Data if the Photometric Interpretation is PALETTE COLOR. Note: In the case of the Supplemental Palette Color LUT, the stored pixel values less than the second descriptor value are grayscale values. An image pixel value one greater than the first value mapped is mapped to the second entry in the Lookup Table Data. Subsequent image pixel values are mapped to the subsequent entries in the Lookup Table Data up to an image pixel value equal to number of entries + first value mapped – 1, which is mapped to the last entry in the Lookup Table Data. Image pixel values greater than or equal to number of entries + first value mapped are also mapped to the last entry in the Lookup Table Data. The second value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The third value specifies the number of bits for each entry in the Lookup Table Data. It shall take the value of 8 or 16. The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where in both cases the high bit is equal to bits allocated-1. The third value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. Note: Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits; this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry. The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16. When the Palette Color Lookup Table Descriptor (0028,1101-1103) are used as part of the Palette Color Lookup Table Module or the Supplemental Palette Color Lookup Table Module, the third value shall be equal to 16. Notes: 1. A value of 16 indicates the Lookup Table Data will range from (0,0,0) minimum intensity to (65535,65535,65535) maximum intensity. 2. Since the Palette Color Lookup Table Descriptor (0028,1101-1103) Attributes are multi-valued, in an Explicit VR Transfer Syntax, only one value representation (US or SS) may be specified, even though the first and third values are always by definition interpreted as unsigned. The explicit VR actually used is dictated by the VR needed to represent the second value, which will be consistent with Pixel Representation (0028,0103).
Specifies the format of the Green Palette Color Lookup Table Data (0028,1202). See C.7.6.3.1.5 for further explanation.
The three values of Palette Color Lookup Table Descriptor (0028,1101-1103) describe the format of the Lookup Table Data in the corresponding Data Element (0028,1201-1203) or (0028,1221-1223). The first value is the number of entries in the lookup table. When the number of table entries is equal to 216 then this value shall be 0. The first value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The second value is the first stored pixel value mapped. This pixel value is mapped to the first entry in the Lookup Table Data. All image pixel values less than the first value mapped are also mapped to the first entry in the Lookup Table Data if the Photometric Interpretation is PALETTE COLOR. Note: In the case of the Supplemental Palette Color LUT, the stored pixel values less than the second descriptor value are grayscale values. An image pixel value one greater than the first value mapped is mapped to the second entry in the Lookup Table Data. Subsequent image pixel values are mapped to the subsequent entries in the Lookup Table Data up to an image pixel value equal to number of entries + first value mapped – 1, which is mapped to the last entry in the Lookup Table Data. Image pixel values greater than or equal to number of entries + first value mapped are also mapped to the last entry in the Lookup Table Data. The second value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The third value specifies the number of bits for each entry in the Lookup Table Data. It shall take the value of 8 or 16. The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where in both cases the high bit is equal to bits allocated-1. The third value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. Note: Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits; this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry. The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16. When the Palette Color Lookup Table Descriptor (0028,1101-1103) are used as part of the Palette Color Lookup Table Module or the Supplemental Palette Color Lookup Table Module, the third value shall be equal to 16. Notes: 1. A value of 16 indicates the Lookup Table Data will range from (0,0,0) minimum intensity to (65535,65535,65535) maximum intensity. 2. Since the Palette Color Lookup Table Descriptor (0028,1101-1103) Attributes are multi-valued, in an Explicit VR Transfer Syntax, only one value representation (US or SS) may be specified, even though the first and third values are always by definition interpreted as unsigned. The explicit VR actually used is dictated by the VR needed to represent the second value, which will be consistent with Pixel Representation (0028,0103).
Specifies the format of the Blue Palette Color Lookup table Data (0028,1203). See C.7.6.3.1.5 for further explanation.
The three values of Palette Color Lookup Table Descriptor (0028,1101-1103) describe the format of the Lookup Table Data in the corresponding Data Element (0028,1201-1203) or (0028,1221-1223). The first value is the number of entries in the lookup table. When the number of table entries is equal to 216 then this value shall be 0. The first value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The second value is the first stored pixel value mapped. This pixel value is mapped to the first entry in the Lookup Table Data. All image pixel values less than the first value mapped are also mapped to the first entry in the Lookup Table Data if the Photometric Interpretation is PALETTE COLOR. Note: In the case of the Supplemental Palette Color LUT, the stored pixel values less than the second descriptor value are grayscale values. An image pixel value one greater than the first value mapped is mapped to the second entry in the Lookup Table Data. Subsequent image pixel values are mapped to the subsequent entries in the Lookup Table Data up to an image pixel value equal to number of entries + first value mapped – 1, which is mapped to the last entry in the Lookup Table Data. Image pixel values greater than or equal to number of entries + first value mapped are also mapped to the last entry in the Lookup Table Data. The second value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. The third value specifies the number of bits for each entry in the Lookup Table Data. It shall take the value of 8 or 16. The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where in both cases the high bit is equal to bits allocated-1. The third value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors. Note: Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits; this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry. The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16. When the Palette Color Lookup Table Descriptor (0028,1101-1103) are used as part of the Palette Color Lookup Table Module or the Supplemental Palette Color Lookup Table Module, the third value shall be equal to 16. Notes: 1. A value of 16 indicates the Lookup Table Data will range from (0,0,0) minimum intensity to (65535,65535,65535) maximum intensity. 2. Since the Palette Color Lookup Table Descriptor (0028,1101-1103) Attributes are multi-valued, in an Explicit VR Transfer Syntax, only one value representation (US or SS) may be specified, even though the first and third values are always by definition interpreted as unsigned. The explicit VR actually used is dictated by the VR needed to represent the second value, which will be consistent with Pixel Representation (0028,0103).
Palette Color Lookup Table UID. See C.7.9.1 for further explanation.
This data element uniquely identifies a palette color lookup table set (red, green, blue). Note: This can be used to avoid reloading a palette if a system already has that palette loaded without examining all the data entries in the palette.
Red Palette Color Lookup Table Data. Required if segmented data is NOT used in an Image IOD, or if the IOD is a Presentation State IOD. See C.7.6.3.1.6 for further explanation.
Palette Color Lookup Table Data (0028,1201-1203) contain the lookup table data corresponding to the Lookup Table Descriptor (0028,1101-1103). Palette color values must always be scaled across the full range of available intensities. This is indicated by the fact that there are no bits stored and high bit values for palette color data. Note: For example, if there are 16 bits per entry specified and only 8 bits of value are truly used then the 8 bit intensities from 0 to 255 must be scaled to the corresponding 16 bit intensities from 0 to 65535. To do this for 8 bit values, simply replicate the value in both the most and least significant bytes. These lookup tables shall be used only when there is a single sample per pixel (single image plane) in the image. These lookup tables are required when the value of Photometric Interpretation (0028,0004) is Palette Color. The semantics of these lookup tables is not defined otherwise.
Green Palette Color Lookup Table Data. Required if segmented data is NOT used in an Image IOD, or if the IOD is a Presentation State IOD. See C.7.6.3.1.6 for further explanation.
Palette Color Lookup Table Data (0028,1201-1203) contain the lookup table data corresponding to the Lookup Table Descriptor (0028,1101-1103). Palette color values must always be scaled across the full range of available intensities. This is indicated by the fact that there are no bits stored and high bit values for palette color data. Note: For example, if there are 16 bits per entry specified and only 8 bits of value are truly used then the 8 bit intensities from 0 to 255 must be scaled to the corresponding 16 bit intensities from 0 to 65535. To do this for 8 bit values, simply replicate the value in both the most and least significant bytes. These lookup tables shall be used only when there is a single sample per pixel (single image plane) in the image. These lookup tables are required when the value of Photometric Interpretation (0028,0004) is Palette Color. The semantics of these lookup tables is not defined otherwise.
Blue Palette Color Lookup Table Data. Required if segmented data is NOT used in an Image IOD, or if the IOD is a Presentation State IOD. See C.7.6.3.1.6 for further explanation.
Palette Color Lookup Table Data (0028,1201-1203) contain the lookup table data corresponding to the Lookup Table Descriptor (0028,1101-1103). Palette color values must always be scaled across the full range of available intensities. This is indicated by the fact that there are no bits stored and high bit values for palette color data. Note: For example, if there are 16 bits per entry specified and only 8 bits of value are truly used then the 8 bit intensities from 0 to 255 must be scaled to the corresponding 16 bit intensities from 0 to 65535. To do this for 8 bit values, simply replicate the value in both the most and least significant bytes. These lookup tables shall be used only when there is a single sample per pixel (single image plane) in the image. These lookup tables are required when the value of Photometric Interpretation (0028,0004) is Palette Color. The semantics of these lookup tables is not defined otherwise.
Segmented Red Palette Color Lookup Table Data. Required segmented data is used in an Image IOD; shall not be present in a Presentation State IOD. See C.7.9.2 for further explanation.
The Segmented Palette Color Lookup Table Data (0028,1221-1223) is stored as a series of segments, see Table C.7-23. When the segments are expanded into the actual lookup table data, it shall have the number of table entries specified by the first value of the Palette Color Lookup Table Descriptors (0028,1101-1103), Number of Table Entries. These lookup tables shall be used only when segmented lookup table data use is desriable and there is a single sample per pixel (single image plane) in the image. Table C.7-23 COMPRESSED PALETTE COLOR LOOKUP TABLE DATA There are currently three types of segments: discrete, linear, and indirect. The segments type is identified by the opcodes in Table C.7-24: Table C.7-24 SEGMENT TYPES
Segmented Green Palette Color Lookup Table Data. Required if segmented data is used in an Image IOD; shall not be present in a Presentation State IOD. See C.7.9.2 for further explanation.
The Segmented Palette Color Lookup Table Data (0028,1221-1223) is stored as a series of segments, see Table C.7-23. When the segments are expanded into the actual lookup table data, it shall have the number of table entries specified by the first value of the Palette Color Lookup Table Descriptors (0028,1101-1103), Number of Table Entries. These lookup tables shall be used only when segmented lookup table data use is desriable and there is a single sample per pixel (single image plane) in the image. Table C.7-23 COMPRESSED PALETTE COLOR LOOKUP TABLE DATA There are currently three types of segments: discrete, linear, and indirect. The segments type is identified by the opcodes in Table C.7-24: Table C.7-24 SEGMENT TYPES
Segmented Blue Palette Color Lookup Table Data. Required if segmented data is used in an Image IOD; shall not be present in a Presentation State IOD. See C.7.9.2 for further explanation.
The Segmented Palette Color Lookup Table Data (0028,1221-1223) is stored as a series of segments, see Table C.7-23. When the segments are expanded into the actual lookup table data, it shall have the number of table entries specified by the first value of the Palette Color Lookup Table Descriptors (0028,1101-1103), Number of Table Entries. These lookup tables shall be used only when segmented lookup table data use is desriable and there is a single sample per pixel (single image plane) in the image. Table C.7-23 COMPRESSED PALETTE COLOR LOOKUP TABLE DATA There are currently three types of segments: discrete, linear, and indirect. The segments type is identified by the opcodes in Table C.7-24: Table C.7-24 SEGMENT TYPES
Text description of the part of the body examined. See PS 3.16 Annex on Correspondence of Anatomic Region Codes and Body Part Examined for Defined Terms Radiographic view associated with Patient Position (0018,5100). Defined Terms: AP = Anterior/Posterior PA = Posterior/Anterior LL = Left Lateral RL = Right Lateral RLD = Right Lateral Decubitus LLD = Left Lateral Decubitus RLO = Right Lateral Oblique LLO = Left Lateral Oblique Label for the type of filter inserted into the x-ray beam Label describing any grid inserted. Size of the focal spot in mm. For devices with variable focal spot or multiple focal spots, small dimension followed by large dimension. Label of the type of storage phosphor plates used in this series Label of type of phosphor on the plates Specifies the intended interpretation of the pixel data. Shall have one of the following Enumerated Values: MONOCHROME1 MONOCHROME2 Peak kilo voltage output of the x-ray generator used The ID or serial number of the sensing plate upon which the image was acquired Distance in mm from source to detector center. Note: This value is traditionally referred to as Source Image Receptor Distance (SID). Distance in mm from source to isocenter (center of field of view) . Note: This value is traditionally referred to as Source Object Distance (SOD). Time of x-ray exposure in msec X-Ray Tube Current in mA. The exposure expressed in mAs, for example calculated from Exposure Time and X-Ray Tube Current. The exposure expressed in µAs, for example calculated from Exposure Time and X-Ray Tube Current. Physical distance measured at the front plane of the Image Receptor housing between the center of each pixel. Specified by a numeric pair - row spacing value (delimiter) column spacing value - in mm. In the case of CR, the front plane is defined to be the external surface of the CR plate closest to the patient and radiation source. Power in kW to the x-ray generator. Describes device-specific processing associated with the image (e.g. Organ Description) Code representing the device-specific processing associated with the image (e.g. CR Organ Filtering code) Orientation of cassette, used to properly position the image for display. Enumerated Values: LANDSCAPE PORTRAIT Size of cassette. Defined Terms: 18CMX24CM 8INX10IN 24CMX30CM 10INX12IN 30CMX35CM 30CMX40CM 11INX14IN 35CMX35CM 14INX14IN 35CMX43CM 14INX17IN Total number of x-ray exposures that have been made on the plate identified in Plate ID (0018,1004) Relative x-ray exposure on the plate. Meaning of values is implementation specific. May be used to adjust the dynamic range of the plate digitizer (scanner). Read out sensitivity. Image identification characteristics. See C.8.2.1.1.1 for specialization.
For CT Images, Image Type (0008,0008) is specified to be Type 1 and uses one of the following Defined Terms for Value 3: AXIAL identifies a CT Axial Image LOCALIZER identifies a CT Localizer Image Note: Axial in this context means any cross-sectional image, and includes transverse, coronal, sagittal and oblique images.
Number of samples (planes) in this image. See C.8.2.1.1.2 for specialization.
For CT Images, Samples per Pixel (0028,0002) shall have an Enumerated Value of 1.
Specifies the intended interpretation of the pixel data. See C.8.2.1.1.3 for specialization.
For CT Images, Photometric Interpretation (0028,0004) shall have one of the following Enumerated Values: MONOCHROME1 MONOCHROME2 See C.7.6.3.1.1.2 for definition of these terms.
Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated. See C.8.2.1.1.4 for specialization.
For CT Images, Bits Allocated (0028,0100) shall have the Enumerated Value of 16.
Number of bits stored for each pixel sample. Each sample shall have the same number of bits stored. See C.8.2.1.1.5 for specialization.
For CT Images, Bits Stored (0028,0101) shall have the Enumerated Values of 12 to 16.
Most significant bit for pixel sample data. Each sample shall have the same high bit. See C.8.2.1.1.6 for specialization.
For CT Images, High Bit (0028,0102) shall have only the Enumerated Value of one less than the value sent in Bits Stored.
The value b in relationship between stored values (SV) and Hounsfield (HU). HU = m*SV+b m in the equation specified in Rescale Intercept (0028,1052). Peak kilo voltage output of the x-ray generator used A number identifying the single continuous gathering of data over a period of time which resulted in this image Parameters of scanning sequence. The diameter in mm of the region over which data were collected The x, y, and z coordinates (in the patient coordinate system) in mm of the center of the region in which data were collected. See C.8.15.3.6.1.
In Figure C.8-19 the relationship of the Geometric Attributes within the CT Geometry and CT Reconstruction functional groups is shown. The figure, viewed from the front of the gantry (where the table enters the gantry), is informative only and is not meant to represent a standardization of an equipment-based frame of reference. Figure C.8-19: Geometry of CT Acquisition System
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 this region. The x, y, and z coordinates (in the patient coordinate system) of the reconstruction center target point as used for reconstruction in mm. See C.8.15.3.6.1. Note: If the reconstructed image is not magnified or panned the value corresponds with the Data Collection Center (Patient) (0018,9313) attribute.
In Figure C.8-19 the relationship of the Geometric Attributes within the CT Geometry and CT Reconstruction functional groups is shown. The figure, viewed from the front of the gantry (where the table enters the gantry), is informative only and is not meant to represent a standardization of an equipment-based frame of reference. Figure C.8-19: Geometry of CT Acquisition System
Distance in mm from source to detector center. Note: This value is traditionally referred to as Source Image Receptor Distance (SID). Distance in mm from source to isocenter (center of field of view). Note: This value is traditionally referred to as Source Object Distance (SOD). Nominal angle of tilt in degrees of the scanning gantry. Not intended for mathematical computations. The distance in mm of the top of the patient table to the center of rotation; below the center is positive. Direction of rotation of the source when relevant, about nearest principal axis of equipment. Enumerated Values: CW = clockwise CC = counter clockwise Time of x-ray exposure in msec X-Ray Tube Current in mA. The exposure expressed in mAs, for example calculated from Exposure Time and X-Ray Tube Current. The exposure expressed in µAs, for example calculated from Exposure Time and X-Ray Tube Current. Label for the type of filter inserted into the x-ray beam. Power in kW to the x-ray generator. Size of the focal spot in mm. For devices with variable focal spot or multiple focal spots, small dimension followed by large dimension. A label describing the convolution kernel or algorithm used to reconstruct the data The time in seconds of a complete revolution of the source around the gantry orbit. The width of a single row of acquired data (in mm). Note: Adjacent physical detector rows may have been combined to form a single effective acquisition row. The width of the total collimation (in mm) over the area of active x-ray detection. Note: This will be equal the number of effective detector rows multiplied by single collimation width. The distance in mm that the table moves in one second during the gathering of data that resulted in this image. Motion of the table (in mm) during a complete revolution of the source around the gantry orbit. Ratio of the Table Feed per Rotation (0018,9310) to the Total Collimation Width (0018,9307). A label describing the type of exposure modulation used for the purpose of limiting the dose. Defined Terms: NONE A percent value of dose saving due to the use of Exposure Modulation Type (0018,9323). A negative percent value of dose savings reflects an increase of exposure. Computed Tomography Dose Index (CTDIvol), im mGy according to IEC 60601-2-44, Ed.2.1 (Clause 29.1.103.4), The Volume CTDIvol. It describes the average dose for this image for the selected CT conditions of operation. The type of phantom used for CTDI measurement according to IEC 60601-2-44. Only a single Item shall be permitted in this Sequence. The calibration factor for the calcium mass score. These factors incorporate the effects of See C.8.2.1.1.7.
The calibration factors for the Calcium Scoring Mass Factor Patient (0018,9351) and Calcium Scoring Mass Factor Device (0018,9352) attributes are defined by the International Consortium for Multi-Detector CT Evaluation of Coronary Calcium, see McCollough, C.H. “A multi-institutional, multi-manufacturer, international standard for the quantification of coronary artery calcium using cardiac CT”.
The calibration factors for the calcium mass score of the device. These factors incorporate the effects of This a multi-value attribute, the first value specifies the mass factor for a small patient size, the second value for a medium patient size and the third value for a large patient size. See C.8.2.1.1.7.
The calibration factors for the Calcium Scoring Mass Factor Patient (0018,9351) and Calcium Scoring Mass Factor Device (0018,9352) attributes are defined by the International Consortium for Multi-Detector CT Evaluation of Coronary Calcium, see McCollough, C.H. “A multi-institutional, multi-manufacturer, international standard for the quantification of coronary artery calcium using cardiac CT”.
Contains the attributes defining the data acquisition in a multiple X-Ray source system beyond the primary source. The primary X-Ray source is specified in other attributes of this module. One or more items may be present. Peak kilo voltage output of the X-Ray generator used. Nominal X-Ray tube current in milliamperes. The diameter in mm of the region over which data were collected. Used nominal size of the focal spot in mm. Type of filter(s) inserted into the X-Ray beam. The X-Ray absorbing material used in the filter.
Image identification characteristics. See C.8.3.1.1.1 for specialization.
For MR Images, Image Type (0008,0008) is specified to be Type 1 and use one of the following Defined Terms for Value 3:
Number of samples (planes) in this image. See C.8.3.1.1.2 for specialization.
For MR Images, Samples per Pixel (0028,0002) shall have an Enumerated Value of 1.
Specifies the intended interpretation of the pixel data. See C.8.3.1.1.3 for specialization.
For MR Images, Photometric Interpretation (0028,0004) shall have one of the following Enumerated Values: MONOCHROME1 MONOCHROME2 See C.7.6.3.1.2 for definition of these terms.
Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated. See C.8.3.1.1.4 for specialization.
For MR Images, Bits Allocated (0028,0100) shall have the Enumerated Value of 16.
Description of the type of data taken. Enumerated Values: SE = Spin Echo IR = Inversion Recovery GR = Gradient Recalled EP = Echo Planar RM = Research Mode Note: Multi-valued, but not all combinations are valid (e.g. SE/GR, etc.). Variant of the Scanning Sequence. Defined Terms: SK = segmented k-space MTC = magnetization transfer contrast SS = steady state TRSS = time reversed steady state SP = spoiled MP = MAG prepared OSP = oversampling phase NONE = no sequence variant Parameters of scanning sequence. Defined Terms: PER = Phase Encode Reordering RG = Respiratory Gating CG = Cardiac Gating PPG = Peripheral Pulse Gating FC = Flow Compensation PFF = Partial Fourier - Frequency PFP = Partial Fourier - Phase SP = Spatial Presaturation FS = Fat Saturation Identification of data encoding scheme. Enumerated Values: 2D = frequency x phase 3D = frequency x phase x phase The period of time in msec between the beginning of a pulse sequence and the beginning of the succeeding (essentially identical) pulse sequence. Required except when Scanning Sequence (0018,0020) is EP and Sequence Variant (0018,0021) is not SK. Time in ms between the middle of the excitation pulse and the peak of the echo produced (kx=0). 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 (i.e.-kx=0, ky=0). Number of lines in k-space acquired per excitation per image. 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 (0018,0020) has values of IR. Time, in msec, between peak of the R wave and the peak of the echo produced. In the case of segmented k-space, the TE(eff) is the time between the peak of the echo that is used to cover the center of k-space. Required for Scan Options (0018,0022) which include heart gating (e.g. CG, PPG, etc.) User defined name for the Scanning Sequence (0018,0020) and Sequence Variant (0018,0021) combination. Angio Image Indicator. Primary image for Angio processing. Enumerated Values: Y = Image is Angio N = Image is not Angio Number of times a given pulse sequence is repeated before any parameter is changed Precession frequency in MHz of the nucleus being addressed Nucleus that is resonant at the imaging frequency. Examples: 31P, 1H The echo number used in generating this image. In the case of segmented k-space, it is the effective Echo Number. Nominal field strength of MR magnet, in Tesla Spacing between slices, in mm. The spacing is measured from the center-to-center of each slice. Total number of lines in k-space in the 'y' direction collected during acquisition. Fraction of acquisition matrix lines acquired, expressed as a percent. Ratio of field of view dimension in phase direction to field of view dimension in frequency direction, expressed as a percent. Reciprocal of the total sampling period, in hertz per pixel. Average R-R interval used for the scans, in msec Beat length sorting has been applied. Enumerated Values: Y = yes N = No R-R interval low limit for beat rejection, in msec R-R interval high limit for beat rejection, in msec Number of R-R intervals acquired. Number of R-R intervals rejected. Description of type of PVC rejection criteria used. Number of beats skipped after a detected arrhythmia. Beats per minute. Number of images per cardiac cycle. Percent of R-R interval, based on Heart Rate (0018,1088), prescribed as a window for a valid/usable trigger. 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 this region. Receive coil used. Transmit coil used. Dimensions of the acquired frequency /phase data before reconstruction. Multi-valued: frequency rows\frequency columns\phase rows\phase columns. The axis of phase encoding with respect to the image. Enumerated Values: ROW = phase encoded in rows. COL = phase encoded in columns. Steady state angle in degrees to which the magnetic vector is flipped from the magnetic vector of the primary field. Calculated whole body Specific Absorption Rate in watts/kilogram. Flip angle variation applied during image acquisition. Enumerated Values: Y = yes N = no The rate of change of the gradient coil magnetic flux density with time (T/s). Temporal order of a dynamic or functional set of Images. Total number of temporal positions prescribed. Time delta between Images in a dynamic or functional set of Images.
Sequence that describes the orientation of the patient with respect to gravity. See C.8.4.6.1.1 for further explanation. Zero or one item shall be present in the sequence.
The Patient Orientation Code Sequence (0054,0410) is used to describe the orientation of the patient with respect to gravity, and is independent of the position in the gantry.
Patient Orientation Modifier. Required if needed to fully specify the orientation of the patient with respect to gravity. See C.8.4.6.1.2 for further explanation. Zero or one item shall be present in the sequence.
The Patient Orientation Modifier Code Sequence (0054,0412) is used to modify or enhance the orientation specified by Patient Orientation Code Sequence (0054,0410).
Sequence which describes the orientation of the patient with respect to the gantry. See Section C.8.4.6.1.3 for further explanation. Zero or one item shall be present in the sequence.
Patient Gantry Relationship Code Sequence (0054,0414) is used to describe the patient direction within the gantry, such as head-first or feet-first. When imaging the extremities, these directions are related to normal anatomic position. Example: In normal anatomic position, the fingers point towards the feet.
Number of samples (color planes) in this image. The value shall be 1. Specifies the intended interpretation of the pixel data. See C.8.4.7.1.1 for further explanation.
For NM Images, Photometric Interpretation (0028,0004) shall have one of the following Enumerated Values: MONOCHROME2 PALETTE COLOR See C.7.6.3.1.2 for definition of these terms.
Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated. Enumerated Values: 8, 16. Number of bits stored for each pixel sample. Each sample shall have the same number of bits stored. The value shall be the same as the value in Bits Allocated (0028,0100). Most significant bit for pixel sample data. Each sample shall have the same high bit. Shall be one less than the value in Bits Stored (0028,0101). Physical distance in the patient between the center of each pixel, specified by a numeric pair - adjacent row spacing (delimiter) adjacent column spacing, in mm. See 10.7.1.3 for further explanation of the value order.
Contains the Data Element Tags of one or more frame index vectors. See C.8.4.8.1.1 for further specialization.
By definition, NM Images are multi-dimensional Multi-frame Images. The value of the Frame Increment Pointer (0028,0009) contains the Tag for one or more frame indexing vectors. This determines the number of dimensions of frame indices in the image, and the order in which these indices vary from one frame to the next, with the last Tag indicating the most rapidly changing index. The Enumerated Values for the Frame Increment Pointer (0028,0009) are determined by the Image Type (0008,0008), Value 3, as shown in Table C.8-8. Table C.8-8 ENUMERATED VALUES FOR FRAME INCREMENT POINTER
An array which contains the energy window number for each frame. Required if the value of the Frame Increment Pointer (0028,0009) includes the Tag for Energy Window Vector (0054,0010). See C.8.4.8.1.2 for specialization.
Number of Energy Windows (0054,0011) is the number of distinct energy window groupings acquired in this image. See C.8.4.10.1. When Image Type (0008,0008), Value 3, is RECON TOMO or RECON GATED TOMO, then the Number of Energy Windows (0054,0011) shall be 1. Energy Window Vector (0054,0010) is an indexing vector. The value of the nth element of this vector is the energy window number for the nth frame in this image, and shall have a value from 1 to Number of Energy Windows (0054,0011).
Number of energy window groupings. See C.8.4.8.1.2 for specialization.
Number of Energy Windows (0054,0011) is the number of distinct energy window groupings acquired in this image. See C.8.4.10.1. When Image Type (0008,0008), Value 3, is RECON TOMO or RECON GATED TOMO, then the Number of Energy Windows (0054,0011) shall be 1. Energy Window Vector (0054,0010) is an indexing vector. The value of the nth element of this vector is the energy window number for the nth frame in this image, and shall have a value from 1 to Number of Energy Windows (0054,0011).
An array which contains the detector number for each frame. Required if the value of the Frame Increment Pointer (0028,0009) includes the Tag for Detector Vector (0054,0020). See C.8.4.8.1.3 for specialization.
Number of Detectors (0054,0021) is the number of separate detectors which differentiate the frames in this image. When Image Type (0008,0008), Value 3, is RECON TOMO or RECON GATED TOMO, then the Number of Detectors (0054,0021) shall be 1. Note: Number of Detectors (0054,0021) does not necessarily represent the actual number of detectors used during data acquisition. Example 1: In a TOMO acquisition in which frames from 2 or more detectors are interleaved to form one continuous set of frames, then no distinction is made between frames on the basis of which detector created them. In this case, the Number of Detectors (0054,0021) would be 1. Example 2: In a WHOLE BODY acquisition in which a single detector acquires anterior and posterior views in two separate passes, the Number of Detectors (0054,0021) would be 2. Detector Vector (0054,0020) is an indexing vector. The value of the nth element of this vector is the detector number of the nth frame in this image, and shall have a value from 1 to Number of Detectors (0054,0021).
Number of detectors. See C.8.4.8.1.3 for specialization.
Number of Detectors (0054,0021) is the number of separate detectors which differentiate the frames in this image. When Image Type (0008,0008), Value 3, is RECON TOMO or RECON GATED TOMO, then the Number of Detectors (0054,0021) shall be 1. Note: Number of Detectors (0054,0021) does not necessarily represent the actual number of detectors used during data acquisition. Example 1: In a TOMO acquisition in which frames from 2 or more detectors are interleaved to form one continuous set of frames, then no distinction is made between frames on the basis of which detector created them. In this case, the Number of Detectors (0054,0021) would be 1. Example 2: In a WHOLE BODY acquisition in which a single detector acquires anterior and posterior views in two separate passes, the Number of Detectors (0054,0021) would be 2. Detector Vector (0054,0020) is an indexing vector. The value of the nth element of this vector is the detector number of the nth frame in this image, and shall have a value from 1 to Number of Detectors (0054,0021).
An array which contains the phase number for each frame. Required if the value of the Frame Increment Pointer (0028,0009) includes the Tag for Phase Vector (0054,0030). See C.8.4.8.1.4 for specialization.
Number of Phases (0054,0031) is the number of dynamic phases, independent of the number of Detectors and Isotopes. See Section C.8.4.14 for definition of a phase. Phase Vector (0054,0030) is an indexing vector. The value of the nth element of this vector is the phase number of the nth frame in this image, and shall have a value from 1 to Number of Phases (0054,0031).
Number of phases. Required if the value of the Frame Increment Pointer (0028,0009) includes the Tag for Phase Vector (0054,0030). See C.8.4.8.1.4 for specialization.
Number of Phases (0054,0031) is the number of dynamic phases, independent of the number of Detectors and Isotopes. See Section C.8.4.14 for definition of a phase. Phase Vector (0054,0030) is an indexing vector. The value of the nth element of this vector is the phase number of the nth frame in this image, and shall have a value from 1 to Number of Phases (0054,0031).
An array which contains the rotation number for each frame. Required if the value of the Frame Increment Pointer (0028,0009) includes the Tag for Rotation Vector (0054,0050). See C.8.4.8.1.5 for specialization.
Number of Rotations (0054,0051) is the number of separate rotations. See Section C.8.4.12 for definition of a rotation. When Image Type (0008,0008), Value 3, is RECON TOMO, GATED TOMO or RECON GATED TOMO, then the Number of Rotations (0054,0051) shall be 1. Rotation Vector (0054,0050) is an indexing vector. The value of the nth element of this vector is the rotation number of the nth frame in this image, and shall have a value from 1 to Number of Rotations (0054,0051).
Number of rotations. Required if Image Type (0008,0008), Value 3 is TOMO, GATED TOMO, RECON TOMO, or RECON GATED TOMO. See C.8.4.8.1.5 for specialization.
Number of Rotations (0054,0051) is the number of separate rotations. See Section C.8.4.12 for definition of a rotation. When Image Type (0008,0008), Value 3, is RECON TOMO, GATED TOMO or RECON GATED TOMO, then the Number of Rotations (0054,0051) shall be 1. Rotation Vector (0054,0050) is an indexing vector. The value of the nth element of this vector is the rotation number of the nth frame in this image, and shall have a value from 1 to Number of Rotations (0054,0051).
An array which contains the R-R interval number for each frame. Required if the value of the Frame Increment Pointer (0028,0009) includes the Tag for R-R Interval Vector (0054,0060). See C.8.4.8.1.6 for specialization.
Number of R-R Intervals (0054,0061) is the number of ranges of heartbeat durations collected. A gated acquisition may employ one R-R Interval to collect data from normal beats, a second R-R Interval to collect data from ectopic beats, and possibly others. Each R-R Interval accepts beats whose duration is greater than its Low R-R Value (0018,1081) and shorter than its High R-R Value (0018,1082). Beats which do not fall within these ranges may be accepted by another R-R Interval, or may be rejected. The Number of R-R Intervals (0054,0061) is the total number of such ranges. R-R Interval Vector (0054,0060) is an indexing vector. The value of the nth element of this vector is the interval number of the nth frame in this image, and shall have a value from 1 to Number of R-R Intervals (0054,0061).
Number of R-R intervals. Required if the value of the Frame Increment Pointer (0028,0009) includes the Tag for R-R Interval Vector (0054,0060). See C.8.4.8.1.6 for specialization.
Number of R-R Intervals (0054,0061) is the number of ranges of heartbeat durations collected. A gated acquisition may employ one R-R Interval to collect data from normal beats, a second R-R Interval to collect data from ectopic beats, and possibly others. Each R-R Interval accepts beats whose duration is greater than its Low R-R Value (0018,1081) and shorter than its High R-R Value (0018,1082). Beats which do not fall within these ranges may be accepted by another R-R Interval, or may be rejected. The Number of R-R Intervals (0054,0061) is the total number of such ranges. R-R Interval Vector (0054,0060) is an indexing vector. The value of the nth element of this vector is the interval number of the nth frame in this image, and shall have a value from 1 to Number of R-R Intervals (0054,0061).
An array which contains the time slot number for each frame. Required if the value of the Frame Increment Pointer (0028,0009) includes the Tag for Time Slot Vector (0054,0070). See C.8.4.8.1.7 for specialization.
Number of Time Slots (0054,0071) is the number of frames into which each gating event is divided in a gated acquisition. For example, in a cardiac gated acquisition, data from a number of heartbeats are then combined by summing together the first frames from all beats into a summed first frame, all the second frames into a summed second frame, and so on. The result has the same number of frames as the Number of Time Slots in each beat. Time Slot Vector (0054,0070) is an indexing vector. The value of the nth element of this vector is the time slot number of the nth frame in this image, and shall have a value from 1 to Number of Time Slots (0054,0071).
Number of time slots. Required if the value of the Frame Increment Pointer (0028,0009) includes the Tag for Time Slot Vector (0054,0070). See C.8.4.8.1.7 for specialization.
Number of Time Slots (0054,0071) is the number of frames into which each gating event is divided in a gated acquisition. For example, in a cardiac gated acquisition, data from a number of heartbeats are then combined by summing together the first frames from all beats into a summed first frame, all the second frames into a summed second frame, and so on. The result has the same number of frames as the Number of Time Slots in each beat. Time Slot Vector (0054,0070) is an indexing vector. The value of the nth element of this vector is the time slot number of the nth frame in this image, and shall have a value from 1 to Number of Time Slots (0054,0071).
An array which contains the spatial slice number for each frame. Required if the value of the Frame Increment Pointer (0028,0009) includes the Tag for Slice Vector (0054,0080). See C.8.4.8.1.8 for specialization.
Number of Slices (0054,0081) is the number of slices in each separate volume. Note: For images with Image Type (0008,0008), Value 3, equal to RECON GATED TOMO this implies that Number of Slices (0054,0081) is the same for all R-R Intervals and Time Slots. Slice Vector (0054,0080) is an indexing vector. The value of the nth element of this vector is the slice number of the nth frame in this image, and shall have a value from 1 to Number of Slices (0054,0081).
Number of slices. Required if the value of the Frame Increment Pointer (0028,0009) includes the Tag for Slice Vector (0054,0080). See C.8.4.8.1.8 for specialization.
Number of Slices (0054,0081) is the number of slices in each separate volume. Note: For images with Image Type (0008,0008), Value 3, equal to RECON GATED TOMO this implies that Number of Slices (0054,0081) is the same for all R-R Intervals and Time Slots. Slice Vector (0054,0080) is an indexing vector. The value of the nth element of this vector is the slice number of the nth frame in this image, and shall have a value from 1 to Number of Slices (0054,0081).
An array which contains the angular view number for each frame. Required if the value of the Frame Increment Pointer (0028,0009) includes the Tag for Angular View Vector (0054,0090). See C.8.4.8.1.9 for specialization.
Angular View Vector (0054,0090) is an indexing vector. The value of the nth element of this vector is the angular view number of the nth frame in this image. If Image Type (0008,0008), Value 3, is TOMO or GATED TOMO, then the value shall be from 1 to Number of Frames in Rotation (0054,0053).
An array which contains the time slice number for each frame. Required if the value of the Frame Increment Pointer (0028,0009) includes the Tag for Time Slice Vector (0054,0100). See C.8.4.8.1.10 for specialization.
Time Slice Vector (0054,0100) is an indexing vector. The value of the nth element of this vector is the time slice number of the nth frame in this image, and shall have a value from 1 to Number of Frames in Phase (0054,0033).
Image identification characteristics. See C.8.4.9.1.1 for specialization.
For NM images, Image Type (0008,0008) Value 3 is specified to be Type 1 and use one of the following Enumerated Values: STATIC DYNAMIC GATED WHOLE BODY TOMO GATED TOMO RECON TOMO RECON GATED TOMO For NM images, Image Type (0008,0008) Value 4 is specified to use one of the following Enumerated Values: EMISSION TRANSMISSION Note: For NM images, Image Type (0008,0008) Value 1 will be ORIGINAL for all raw data and reconstructed images. DERIVED may be appropriate for some other results images. For NM images, Image Type (0008,0008) Value 2 will be PRIMARY.
User or equipment generated Image identifier. Specifies whether an Image has undergone lossy compression. Enumerated Values: 00 = Image has NOT been subjected to lossy compression. 01 = Image has been subjected to lossy compression. See C.7.6.1.1.5 Required if Lossy Compression has been performed on the Image.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
Sum of all gamma events for all frames in the image. See C.8.4.9.1.2 for specialization.
Counts Accumulated (0018,0070) is the total of all gamma events accumulated in all frames of this Image. This attribute applies to acquisition data, and often does not apply to processed images (DERIVED, SECONDARY).
Description of how the data collection was stopped. Defined Terms: CNTS = counts DENS = density MANU = manual OVFL = data overflow TIME = time TRIG = physiological trigger See C.8.4.9.1.3 for specialization.
Acquisition Termination Condition (0018,0071) is the method of acquisition termination which was actually applied to the data collection. The Defined Terms and definitions are: CNTS = preset count limit was reached DENS = preset count density was reached MANU = acquisition was terminated manually OVFL = acquisition was terminated automatically by pixel data overflow condition TIME = preset time limit was reached TRIG = preset number of physiological triggers was reached
The height of the patient table in mm. The range and values of this element are determined by the manufacturer. Should not be included if Image Type (0008,0008), Value 3, is TOMO, GATED TOMO, RECON TOMO or RECON GATED TOMO. Location of the patient table (or gantry relative to the table) in mm. The range and values of this element are determined by the manufacturer. Should not be included if Image Type (0008,0008), Value 3, is TOMO, GATED TOMO, RECON TOMO or RECON GATED TOMO. Elapsed time for data acquisition in msec. Required if Image Type (0008,0008) Value 3 is: WHOLE BODY or STATIC. See C.8.4.9.1.4 for specialization.
Actual Frame Duration (0018,1242) is defined as the elapsed time in msec for a single frame of an acquisition. For some types of multi-frame images, Actual Frame Duration (0018,1242) may have a more specialized meaning as defined in the appropriate IOD Module.
Maximum count rate achieved during the acquisition in counts/sec. Code or description of processing functions applied to the data. A value that indicates which, if any, corrections have been applied to the image. Corrections are applied to all frames in the image. Defined Terms: UNIF = flood corrected COR = center of rotation corrected NCO = non-circular orbit corrected DECY = decay corrected ATTN = attenuation corrected SCAT = scatter corrected DTIM = dead time corrected NRGY = energy corrected LIN = linearity corrected MOTN = motion corrected CLN = count loss normalization; Any type of normalization applied to correct for count loss in Time Slots. The type of scan performed. Used only if Image Type (0008,0008), Value 3, contains the value WHOLE BODY. Enumerated Values: 1PS = one pass 2PS = two pass PCN = patient contour following employed MSP = multiple static frames collected into a whole body frame. The speed of the camera motion over the body in mm/sec. Required if Image Type (0008,0008) Value 3 contains the value WHOLE BODY. Size of the imaged area in the direction of scanning motion, in mm. Required if Image Type (0008,0008) Value 3 contains the value WHOLE BODY. Text indicating trigger source. Defined Term: EKG
Sequence of Items that describe the energy window groups used. Zero or more Items may be included in this sequence. The number of items shall be equal to Number of Energy Windows (0054,0011). The first item corresponds to frames with value of 1 in the Energy Window Vector (0054,0010), the second item with value 2, etc. A user defined name which describes this Energy Window. Sequence of Items that describes this energy window group. One or more Items may be included in this Sequence. The lower limit of the energy window in KeV. See C.8.4.10.1.1 for further explanation.
Energy Window Lower Limit (0054,0014) is the acquisition energy window lower limit in KeV for acceptance of scintillation events into this Isotope.
The upper limit of the energy window in KeV. See C.8.4.10.1.2 for further explanation.
Energy Window Upper Limit (0054,0015) is the acquisition energy window upper limit in KeV for acceptance of scintillation events into this Isotope.
Sequence of Items that describe isotope information. Zero or more Items may be included in this sequence. Sequence that identifies the radionuclide. Zero or one item shall be present in the sequence. Route of injection. Sequence that identifies the administration route for the radiopharmaceutical. This sequence shall contain exactly one item. Volume of injection in cubic cm. Time of start of injection. See C.8.4.10.1.5 for further explanation.
Radiopharmaceutical Start Time (0018,1072) is the actual time of radiopharmaceutical administration to the patient for imaging purposes, using the same time base as for the Acquisition Start Time (0008,0032).
Time of end of injection. See C.8.4.10.1.6 for further explanation.
Radiopharmaceutical Stop Time (0018,1073) is the actual ending time of radiopharmaceutical administration to the patient for imaging purposes, using the same time base as for the Acquisition Start Time (0008,0032).
Total amount of radionuclide injected. See C.8.4.10.1.7 for further explanation.
Radionuclide Total Dose (0018,1074) is the radiopharmaceutical dose administered to the patient measured in MegaBecquerels (Mbq) at the Radiopharmaceutical Start Time.
Sequence that contains calibration data. One or more Items may be included in this Sequence. The Item number in the Energy Window Information Sequence to which the following calibration data relates. The Items are numbered starting from 1. Pre-injection syringe count rate in counts/sec. See C.8.4.10.1.8 for further explanation.
Syringe Counts (0018,1045) is the pre-injection syringe acquisition count rate measured in counts/sec, corrected to the Acquisition Start Time (0008,0032) if necessary.
Post-injection residue syringe count rate in counts/sec. See C.8.4.10.1.9 for further explanation.
Residual Syringe Counts (0054,0017) is the syringe acquisition count rate following patient injection, measured in counts/sec, corrected to the Acquisition Start Time (0008,0032) if necessary.
Name of the radiopharmaceutical. Sequence that identifies the radiopharmaceutical. This sequence shall contain exactly one item. Sequence of Items that describes the intervention drugs used. Zero or more Items may be included in this sequence. Name of intervention drug. Sequence that identifies the intervention drug name. Only a single Item shall be permitted in this Sequence. Sequence that identifies the administration route for the intervention drug. This sequence shall contain exactly one item. Time of administration of the intervention drug, using the same time base as for the Acquisition Start Time (0008,0032). Time of completion of administration of the intervention drug, using the same time base as for the Acquisition Start Time (0008,0032). Intervention drug dose, in mg.
Sequence of Items that describe the detectors used. Zero or more Items may be included in this sequence. The number of items shall be equal to Number of Detectors (0054,0021). The first item corresponds to frames with value of 1 in the Detector Vector (0054,0020), the second item with value 2, etc. Label describing the collimator used (LEAP, hires, etc.) Collimator type. Defined Terms: PARA = Parallel (default) PINH = Pinhole FANB = Fan-beam CONE = Cone-beam SLNT = Slant hole ASTG = Astigmatic DIVG = Diverging NONE = No collimator UNKN = Unknown Shape of the field of view of the Nuclear Medicine detector. Defined Terms: RECTANGLE ROUND HEXAGONAL Dimensions of the field of view, in mm. If Field of View Shape (0018,1147) is: RECTANGLE: row dimension followed by column. ROUND: diameter. HEXAGONAL: diameter of a circumscribed circle. Focal distance, in mm. A value of 0 means infinite distance for parallel collimation. See C.8.4.11.1.1 for further specialization.
Focal Distance (0018,1182) for NM Image data is the focal distance, in mm for converging or diverging collimators, measured from the front face of the detector to the focus. Positive values indicate converging and negative values indicate diverging collimators. A value of 0 means infinite distance for parallel collimation.
Center of focus along a row. See C.8.4.11.1.2 for further explanation.
X Focus Center (0018,1183) and Y Focus Center (0018,1184) for NM Image data is used to define the projection of the focus for a converging or diverging collimator within the un-zoomed Field of View. It is defined in mm for row and column relative to the center of the un-zoomed Field of View.
Center of focus along a column. See C.8.4.11.1.2 for further explanation.
X Focus Center (0018,1183) and Y Focus Center (0018,1184) for NM Image data is used to define the projection of the focus for a converging or diverging collimator within the un-zoomed Field of View. It is defined in mm for row and column relative to the center of the un-zoomed Field of View.
The amount of offset from (0,0) applied to each pixel in the image before application of the zoom factor, specified by a numeric pair: row value (delimiter) column value (in mm). See C.8.4.11.1.3 for further explanation.
Zoom Center (0028,0032) is the offset between the un-zoomed camera field of view and field of view, measured from the center of the un-zoomed camera field of view to the center the of the zoomed field of view. The offset is measured in mm in the un-zoomed camera FOV dimensions. Positive values are to the right and down from the un-zoomed center, as viewed from the image plane. When this attribute is not given, the Zoom Center is assumed to be 0\0.
The amount of magnification applied to each pixel in the image, specified by a numeric pair: row value (delimiter) column value. See C.8.4.11.1.4 for further explanation.
Zoom Factor (0028,0031) is the magnification factor that was used during the acquisition. When this attribute is not given, it is assumed to be 1.0\1.0. Note: Zoom Factor (0028,0031) is informational only. Pixel Spacing (0028,0030) already takes account of this and any other changes to pixel size.
Average center of rotation offset of Nuclear Medicine detector in mm. See C.8.4.11.1.5 for further explanation.
Center of Rotation Offset (0018,1145) is the average amount of offset in mm between the Detector Field of View center and the physical center of rotation of the gantry for circular orbital scans. Positive values indicate the physical center is to the right of the image plane center. If: 1) Image Type (0008,0008) Value 3 is TOMO or GATED TOMO, and 2) Corrected Image (0028,0051) does not include the value "COR", and 3) Center of Rotation Offset (0018,1145) is non-zero, then the receiver should assume that Center of Rotation correction has not already been done. If the Center of Rotation Offset is zero, no correction shall be applied.
Angle of tilt in degrees of the detector. See C.8.4.11.1.6 for further explanation.
Gantry/Detector Tilt (0018,1120) for NM Image data is the angle in degrees of the detector face relative to the patient's major (Head to Feet) axis (or the table supporting the patient). Positive tilt is towards the patient’s feet.
Distance in mm from transmission source to the detector face. Required if Image Type (0008,0008) Value 4 is TRANSMISSION, Value 3 is not TOMO,. Position of the detector about the patient for the start of the acquisition, in degrees. Zero degrees is referenced to the origin at the patient's back. Viewing from the patient's feet, angle increases in a counter-clockwise direction (detector normal rotating from the patient's back towards the patient's left side). Should not be included if Image Type (0008,0008), Value 3, is TOMO, GATED TOMO, RECON TOMO or RECON GATED TOMO. Radial distance of the detector from the center of rotation, in mm. Should not be included if Image Type (0008,0008), Value 3, is TOMO, GATED TOMO, RECON TOMO or RECON GATED TOMO. The direction cosines of the first row and the first column with respect to the patient. See C.7.6.2.1.1 for further explanation.
The Image Position (0020,0032) specifies the x, y, and z coordinates of the upper left hand corner of the image; it is the center of the first voxel transmitted. Image Orientation (0020,0037) specifies the direction cosines of the first row and the first column with respect to the patient. These Attributes shall be provide as a pair. Row value for the x, y, and z axes respectively followed by the Column value for the x, y, and z axes respectively. The direction of the axes is defined fully by the patient’s orientation. The x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient. The patient based coordinate system is a right handed system, i.e. the vector cross product of a unit vector along the positive x-axis and a unit vector along the positive y-axis is equal to a unit vector along the positive z-axis. Note If a patient lies parallel to the ground, face-up on the table, with his feet-to-head direction same as the front-to-back direction of the imaging equipment, the direction of the axes of this patient based coordinate system and the equipment based coordinate system in previous versions of this Standard will coincide. The Image Plane Attributes, in conjunction with the Pixel Spacing Attribute, describe the position and orientation of the image slices relative to the patient-based coordinate system. In each image frame the Image Position (Patient) (0020,0032) specifies the origin of the image with respect to the patient-based coordinate system. RCS and the Image Orientation (Patient) (0020,0037) attribute values specify the orientation of the image frame rows and columns. The mapping of pixel location to the RCS is calculated as follows: size 12{ left [ matrix { P rSub { size 8{x} } {} ## P rSub { size 8{y} } {} ## P rSub { size 8{z} } {} ## 1 } right ]= left [ matrix { X rSub { size 8{x} } Δi {} # Y rSub { size 8{x} } Δj {} # 0 {} # S rSub { size 8{x} } {} ## X rSub { size 8{y} } Δi {} # Y rSub { size 8{y} } Δj {} # 0 {} # S rSub { size 8{y} } {} ## X rSub { size 8{z} } Δi {} # Y rSub { size 8{z} } Δj {} # 0 {} # S rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { i {} ## j {} ## 0 {} ## 1 } right ]} {} = M Where: Pxyz The coordinates of the voxel (i,j) in the frame’s image plane in units of mm. Sxyz The three values of the Image Position (Patient) (0020,0032) attributes. It is the location in mm from the origin of the RCS. Xxyz The values from the row (X) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. Yxyz The values from the column (Y) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. i Column index to the image plane. The first column is index zero. i Column pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. j Row index to the image plane. The first row index is zero. j Row pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. Additional constraints apply: 1) The row and column direction cosine vectors shall be orthogonal, i.e. their dot product shall be zero. 2) The row and column direction cosine vectors shall be normal, i.e. the dot product of each direction cosine vector with itself shall be unity.
The x, y, and z coordinates of the upper left hand corner (center of the first voxel transmitted) of the image, in mm. See C.7.6.2.1.1 for further explanation.
The Image Position (0020,0032) specifies the x, y, and z coordinates of the upper left hand corner of the image; it is the center of the first voxel transmitted. Image Orientation (0020,0037) specifies the direction cosines of the first row and the first column with respect to the patient. These Attributes shall be provide as a pair. Row value for the x, y, and z axes respectively followed by the Column value for the x, y, and z axes respectively. The direction of the axes is defined fully by the patient’s orientation. The x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient. The patient based coordinate system is a right handed system, i.e. the vector cross product of a unit vector along the positive x-axis and a unit vector along the positive y-axis is equal to a unit vector along the positive z-axis. Note If a patient lies parallel to the ground, face-up on the table, with his feet-to-head direction same as the front-to-back direction of the imaging equipment, the direction of the axes of this patient based coordinate system and the equipment based coordinate system in previous versions of this Standard will coincide. The Image Plane Attributes, in conjunction with the Pixel Spacing Attribute, describe the position and orientation of the image slices relative to the patient-based coordinate system. In each image frame the Image Position (Patient) (0020,0032) specifies the origin of the image with respect to the patient-based coordinate system. RCS and the Image Orientation (Patient) (0020,0037) attribute values specify the orientation of the image frame rows and columns. The mapping of pixel location to the RCS is calculated as follows: P rSub { size 8{x} } {} ## P rSub { size 8{y} } {} ## P rSub { size 8{z} } {} ## 1 } right ]= left [ matrix { X rSub { size 8{x} } Δi {} # Y rSub { size 8{x} } Δj {} # 0 {} # S rSub { size 8{x} } {} ## X rSub { size 8{y} } Δi {} # Y rSub { size 8{y} } Δj {} # 0 {} # S rSub { size 8{y} } {} ## X rSub { size 8{z} } Δi {} # Y rSub { size 8{z} } Δj {} # 0 {} # S rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { i {} ## j {} ## 0 {} ## 1 } right ]} {} = M Where: Pxyz The coordinates of the voxel (i,j) in the frame’s image plane in units of mm. Sxyz The three values of the Image Position (Patient) (0020,0032) attributes. It is the location in mm from the origin of the RCS. Xxyz The values from the row (X) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. Yxyz The values from the column (Y) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. i Column index to the image plane. The first column is index zero. i Column pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. j Row index to the image plane. The first row index is zero. j Row pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. Additional constraints apply: 1) The row and column direction cosine vectors shall be orthogonal, i.e. their dot product shall be zero. 2) The row and column direction cosine vectors shall be normal, i.e. the dot product of each direction cosine vector with itself shall be unity.
Sequence that describes the projection of the anatomic region of interest on the image receptor. Only a single Item shall be permitted in this sequence. View Modifier. Required if needed to fully specify the View. Zero or one Items shall be permitted in this sequence.
Sequence of Items that describe TOMO rotational groups. A new rotation is defined whenever the direction of the detector motion changes, or the Table Traverse (0018,1131) changes. Zero or more Items may be included in this sequence. The number of items shall be equal to Number of Rotations (0054,0051). If Rotation Vector (0054,0050) is present, the first item corresponds to frames with value of 1 in the Rotation Vector (0054,0050), the second item with value 2, etc. Position of the detector about the patient for the start of this rotation, in degrees. Zero degrees is referenced to the origin at the patient's back. Viewing from the patient's feet, angle increases in a counter-clockwise direction (detector normal rotating from the patient's back towards the patient's left side). The angular scan arc step between views of the TOMO acquisition, in degrees. See C.8.4.12.1.1 for further explanation.
Angular Step (0018,1144) is the nominal frame-to-frame incremental angle for TOMO and GATED TOMO acquisition images, defined in degrees. The Angular Step (0018,1144) shall be a positive number. Summation of Angular Step values is not defined to give accurate Angular Position or Scan Arc values. The Angular Step is the effective angular spacing between resultant frames of the Multi-framed planar image data.
Direction of rotation of the detector about the patient. See Start Angle (0054,0200) for further explanation of direction. Enumerated Values: CW = clockwise (decreasing angle) CC = counter-clockwise (increasing angle). The effective angular range of the scan data in degrees. The value shall be positive. Nominal acquisition time per angular position, in msec. Radial distance of the detector from the center of rotation, in mm. It shall have a single value which is an average value for this rotation, or it shall have one value per angular view. Distance in mm from transmission source to the detector face. Required if Image Type (0008,0008) and Value 4, is TRANSMISSION. Number of angular views in this rotation. Location of the patient table (or gantry relative to the table) in mm.The range and values of this element are determined by the manufacturer. The distance in mm of the top of the patient table to the center of rotation. Table height below the center of rotation has a positive value. Describes the detector motion during acquisition. Enumerated Values: STEP AND SHOOT = Interrupted motion, acquire only while stationary. CONTINUOUS = Gantry motion and acquisition are simultaneous and continuous. ACQ DURING STEP = Interrupted motion, acquisition is continuous.
Heart beat duration sorting has been applied. Enumerated Values: Y = yes N = no Description of type of arrhythmic beat rejection criteria used. Number of beats skipped after a detected arrhythmia Average number of heart beats per minute for the collection period for these frames. This shall include all accepted beats as well as rejected beats. Sequence of Items that describe R-R intervals. Each gated interval is defined by an upper and lower range of heart beat durations. Required if the Frame Increment Pointer (0028,0009) contains the Tag for R-R Interval Vector (0054,0060). Zero or more Items may be included in this sequence. The number of items shall be equal to Number of R-R Intervals (0054,0061). The first item corresponds to frames with value of 1 in the R-R Interval Vector (0054,0060), the second item with value 2, etc. Time interval measured in msec from the start of the R-wave to the beginning of the data taking. Description of type of framing performed such as forward, backward, forward/backward by percentage. See C.7.6.18.1.1.1.
Cardiac Framing Type (0018,1064) is the mechanism used to select the data acquired to construct the frames within a specified cardiac timing interval.C.7.6.18.2 Respiratory Synchronization Module Table C7.6.18-2 specifies the attributes of the Respiratory Synchronization Module. Table C.7.6.18-2 RESPIRATORY SYNCHRONIZATION MODULE ATTRIBUTES
Sequence of Items that describe gating criteria. Zero or more Items may be included in this sequence. See C.8.4.13.1.1.
Data Information Sequence (0054,0063) shall contain a single sequence item which applies to the sum of all angular views, except when Image Type (0008,0008) Value 3 is GATED TOMO. In this case it shall have either a single item which applies to the sum of all angular views, or it shall have one item for each angular view.
Nominal time per individual frame in msec. Average duration of accepted beats, in msec. R-R interval lower limit for beat rejection, in msec R-R interval upper limit for beat rejection, in msec Number of heartbeats that fall within Low R-R Value (0018,1081) and High R-R Value (0018,1082), and were therefore accepted and contribute gamma events to this R-R Interval. Number of heartbeats that fall outside Low R-R (0018,1081) and High R-R Value (0018,1082), and do not contribute gamma events to this R-R Interval. However, they may contribute gamma events to other R-R Intervals. Sequence of Items that describe Time Slot Information. Required if the Frame Increment Pointer (0028,0009) contains the Tag for Time Slot Vector (0054,0070). Zero or more Items may be included in this sequence. The number of items shall be equal to Number of Time Slots (0054,0071). The first item corresponds to frames with value of 1 in the Time Slot Vector (0054,0070), the second item with value 2, etc. The total amount of time, in msec, that the acquisition accumulates gamma events into this frame. See C.8.4.13.1.2.
The Time Slot Time (0054,0073) records the effective imaging time of each Time Slot. For example, if some of the accepted beats are shorter than others then the last frames may not receive a contribution from the shorter beats. The Time Slot Time for a Time Slot is the total acquisition time for that Time Slot. It is approximately equal to the Frame Time (0018,1063) multiplied by the number of accepted beats contributing to the Time Slot.
Sequence of Items that describes each dynamic phase. Required if the Frame Increment Pointer (0028,0009) contains the Tag for Phase Vector (0054,0030). Zero or more Items may be included in this sequence. The number of items shall be equal to Number of Phases (0054,0031). The first item corresponds to frames with value of 1 in the Phase Vector (0054,0030), the second item with value 2, etc. Time paused between the last frame of the previous phase and the first frame of this phase, in msec. Nominal time of acquisition per individual frame, in msec. Time paused between each frame of this phase (in msec). Number of frames in this phase. An array of trigger times when gating information is acquired simultaneously with the dynamic image data. See Section C.8.4.14.1.1 for further explanation.
Trigger Vector (0054,0210) is an array containing a list of the inter-trigger interval times in milliseconds in the order in which they were acquired, with the first being measured from the start time of the first frame of the image data in the Phase. If this element is used, the start times are required to be the same so that a mathematical correlation can be made between trigger times and frame start times.
The number of entries in the Trigger Vector (0054,0210) for this phase. Required if Trigger Vector (0054,0210) is present. Description of this phase of the Dynamic image. Defined Terms: FLOW WASHOUT UPTAKE EMPTYING EXCRETION
Spacing between slices, in mm, measured from center-to-center of each slice along the normal to the first image. The sign of the Spacing Between Slices (0018,0088) determines the direction of stacking. The normal is determined by the cross product of the direction cosines of the first row and first column of the first frame, such that a positive spacing indicates slices are stacked behind the first slice and a negative spacing indicates slices are stacked in front of the first slice. See Image Orientation (0020,0037) in the NM Detector module. Diameter, in mm, of the region from within which the data was used in creating the reconstruction of the image. Data may exist outside this region and portions of the patient may exist outside this region. A label describing the convolution kernel or algorithm used to reconstruct the data. Nominal slice thickness, in mm. Relative position of the image plane expressed in mm. See C.7.6.2.1.2 for further explanation.
The Slice Location (0020,1041) is defined as the relative position of the image plane expressed in mm. This information is relative to an unspecified implementation specific reference point.
Describes the anatomical direction that slices are progressing as the slices are considered in order (as defined by the Slice Vector (0054,0080)). Meaningful only for cardiac images. When View Code Sequence (0054,0220) indicates a short axis view, then Enumerated Values are: APEX_TO_BASE BASE_TO_APEX
Defines a sequence of Ultrasound Regions. One or more Items may be included in this Sequence. The bounds of a rectangle specifying the location of the region, x0,y0,x1,y1. See C.8.5.5.1.14 for further explanation.
These attributes specify the location of the region, Region Location Min x0 (0018,6018), Region Location Min y0 (0018,601A), Region Location Max x1 (0018,601C), Region Location Max y1 (0018,601E) expressed as offsets to the pixel coordinates. The upper left corner of the entire image is x=0,y=0 and the lower right corner is x=image width - 1, and y=image length - 1. Thus, a region will be specified as within these bounds. Where x0,y0 is the coordinate of the upper left corner of the region and x1,y1 is the coordinate of the lower right corner of the region.
The bounds of a rectangle specifying the location of the region, x0,y0,x1,y1. See C.8.5.5.1.14 for further explanation.
These attributes specify the location of the region, Region Location Min x0 (0018,6018), Region Location Min y0 (0018,601A), Region Location Max x1 (0018,601C), Region Location Max y1 (0018,601E) expressed as offsets to the pixel coordinates. The upper left corner of the entire image is x=0,y=0 and the lower right corner is x=image width - 1, and y=image length - 1. Thus, a region will be specified as within these bounds. Where x0,y0 is the coordinate of the upper left corner of the region and x1,y1 is the coordinate of the lower right corner of the region.
The bounds of a rectangle specifying the location of the region, x0,y0,x1,y1. See C.8.5.5.1.14 for further explanation.
These attributes specify the location of the region, Region Location Min x0 (0018,6018), Region Location Min y0 (0018,601A), Region Location Max x1 (0018,601C), Region Location Max y1 (0018,601E) expressed as offsets to the pixel coordinates. The upper left corner of the entire image is x=0,y=0 and the lower right corner is x=image width - 1, and y=image length - 1. Thus, a region will be specified as within these bounds. Where x0,y0 is the coordinate of the upper left corner of the region and x1,y1 is the coordinate of the lower right corner of the region.
The bounds of a rectangle specifying the location of the region, x0,y0,x1,y1. See C.8.5.5.1.14 for further explanation.
These attributes specify the location of the region, Region Location Min x0 (0018,6018), Region Location Min y0 (0018,601A), Region Location Max x1 (0018,601C), Region Location Max y1 (0018,601E) expressed as offsets to the pixel coordinates. The upper left corner of the entire image is x=0,y=0 and the lower right corner is x=image width - 1, and y=image length - 1. Thus, a region will be specified as within these bounds. Where x0,y0 is the coordinate of the upper left corner of the region and x1,y1 is the coordinate of the lower right corner of the region.
The physical units of the dimensions of the region. See C.8.5.5.1.15 for Enumerated Values.
Physical Units X Direction (0018,6024) and Physical Units Y Direction (0018,6026) provide Enumerated Values indicating the physical units of the dimensions of the region.
The physical units of the dimensions of the region. See C.8.5.5.1.15 for Enumerated Values.
Physical Units X Direction (0018,6024) and Physical Units Y Direction (0018,6026) provide Enumerated Values indicating the physical units of the dimensions of the region.
The physical value increments per positive X pixel increment. The units are as specified in the Physical Units X Direction (0018,6024). See C.8.5.5.1.17 for further explanation.
The Physical Delta X (0018,602C) is the physical value increment per positive X pixel increment, which is left to right. The Physical Delta Y (0018,602E) is the physical value increment per positive Y pixel increment which is top to bottom. Note: When displaying Doppler data, ultrasound applications typically display the Doppler strip horizontally, with data sweeping (moving time origin) from left (oldest) to right (newest) or scrolling (static time origin) from right to left. The default display of positive velocity values normally indicates flow toward the transducer; negative velocity values indicate flow away from the transducer. In this case a negative Physical Delta Y is required to specify that the direction of positive velocities or frequencies is upward.
The physical value increments per positive Y pixel increment. The units are as specified in the Physical Units Y Direction (0018,6026). See C.8.5.5.1.17 for further explanation.
The Physical Delta X (0018,602C) is the physical value increment per positive X pixel increment, which is left to right. The Physical Delta Y (0018,602E) is the physical value increment per positive Y pixel increment which is top to bottom. Note: When displaying Doppler data, ultrasound applications typically display the Doppler strip horizontally, with data sweeping (moving time origin) from left (oldest) to right (newest) or scrolling (static time origin) from right to left. The default display of positive velocity values normally indicates flow toward the transducer; negative velocity values indicate flow away from the transducer. In this case a negative Physical Delta Y is required to specify that the direction of positive velocities or frequencies is upward.
This coordinate pair, x0,y0 defines the location of a virtual "reference" pixel. See C.8.5.5.1.16 for further explanation.
This coordinate pair, Reference Pixel x0 (0018,6020), Reference Pixel y0 (0018,6022) defines the location of a virtual "reference" pixel. This reference pixel location is used to tie the image's pixel coordinate system to the physical coordinate system. For example, the reference pixel could be defined where a depth of zero centimeters occurs in the 2D image, or it could define where the baseline (i.e.: zero frequency) resides in a spectral display. The reference pixel location is the relative offset from the Region Location Min x0 (0018,6018) and Region Location Min y0 (0018,601A), not the image origin. The location is not required to be within the region or even within the image boundary. For this reason, the Reference Pixel x0 and Reference Pixel y0values can be positive or negative. The reference pixel location varies depending on the type and spatial organization of the data within the region.
This coordinate pair, x0,y0 defines the location of a virtual "reference" pixel. See C.8.5.5.1.16 for further explanation.
This coordinate pair, Reference Pixel x0 (0018,6020), Reference Pixel y0 (0018,6022) defines the location of a virtual "reference" pixel. This reference pixel location is used to tie the image's pixel coordinate system to the physical coordinate system. For example, the reference pixel could be defined where a depth of zero centimeters occurs in the 2D image, or it could define where the baseline (i.e.: zero frequency) resides in a spectral display. The reference pixel location is the relative offset from the Region Location Min x0 (0018,6018) and Region Location Min y0 (0018,601A), not the image origin. The location is not required to be within the region or even within the image boundary. For this reason, the Reference Pixel x0 and Reference Pixel y0values can be positive or negative. The reference pixel location varies depending on the type and spatial organization of the data within the region.
The Physical Value at the reference pixel x location. The units are specified in the Physical Units field. The Physical Value at the reference pixel y location. The units are specified in the Physical Units field. The spatial organization of the data within the region. See C.8.5.5.1.1 for Enumerated Values.
Enumerated Values for Region Spatial Format (0018,6012) indicate the spatial organization of the data within the region.
The type of data within the region. See C.8.5.5.1.2 for Enumerated Values.
Enumerated Values for Region Data Type (0018,6014) indicate the type of data within the region.
Flags used for special handling of the region. See C.8.5.5.1.3 for Enumerated Values and further explanation.
Region Flags (0018,6016) specify characteristics of US Regions. Bit 0 of the Region Flags specifies the relative priority of the pixel component calibration specified by an US Region in the case where the US Region intersects with other US Regions. The calibration supplied by one or more of the regions may not be valid in the area that they intersect. Enumerated Values for Bit 0 (lsb): 1 = Region pixels are low priority 0 = Region pixels are high priority A high priority region overwrites data of a low priority region when they overlap, thus invalidating any pixel component calibration specified for a low priority region. pixel component calibration of overlapping regions of the same priority is indeterminate where they overlap. Figure C.8-6 shows an example of intersecting regions. Figure C.8-6 Intersecting Spatial Format Regions and Overlapping Measurement In this example, Region B is Color Flow while Region A is Tissue Echo. If Region B Color Flow values share the same bit planes as Region A Tissue Echo values, then it is indeterminate whether a pixel in this region is a Color Flow pixel or a Tissue Echo pixel. Since the pixels of the Color Flow region overwrite those of the Tissue Echo region, the Region Flag of the Tissue Echo region is assigned low priority and the Region Flag of the color region is assigned high priority. This means that if both the Tissue Echo and Color Flow regions define pixel component calibration that only the calibration specified by the Color Flow region can be applied to the pixel data value at Point X. The measurement in Figure C.8-6 is a line between Point Y and Point Z. Both points are in Region A so the distance between them can be calculated using the Region A scaling (assuming that Region A defines both the Physical Units X Direction and Y Direction as being cm). If the points are in Region B, and hence also in Region A, it is still possible to calculate the distance because the region scaling is identical in both regions. The lower priority of Region B only applies to its pixel component calibration, not its X and Y direction scaling. Enumerated Values for Bit 1 Scaling Protection: 1 = Protected 0 = Not Protected Ultrasound systems should set this to 1 if the image is scaled automatically by the ultrasound system. If the image is frame-grabbed and scaling is not available then it should be set to 0. If the region is protected, the region can not be manually rescaled. That is the data defined by the region calibration Module can not be overridden by a reader of that image. Enumerated Values for Bit 2 Doppler Scale Type: 1 = Frequency 0 = Velocity Valid for PW and CW regions only. Indicates which type of Doppler scale is used. Enumerated Values for Bit 3-4 Scrolling Region: 00 = Unspecified 01 = Scrolling 10 = Sweeping 11 = Sweeping then Scrolling Bit 5-31 Reserved for future use, shall be set to zero.
Describes how the components of a pixel can be described. Required if pixel component calibration exists for this region. See C.8.5.5.1.4 for Enumerated Values and further explanation.
Pixel Component Organization (0018,6044) provides an Enumerated Value describing how the components of a pixel can be described. The absence of this data element means that pixel component calibration does not exist for this region. Where: 0 = Bit aligned positions 1 = Ranges 2 = Table look up 3 = Code Sequence look up Other values reserved for future use. Pixel Component Organization defines the way in which the composite pixel values are mapped into real world values with physical units, as illustrated in Figure C.8-7. Figure C.8-7 Pixel Component Calibration An example of Component Calibration for an ultrasound image is shown in Figure C.8-8. Figure C.8-8 Pixel Component Calibration Example In this example, some pixels lie within two Regions. One Region specifies pixel component calibration for Doppler velocity values. The second Region specifies pixel component calibration for Doppler magnitude. A particular Pixel Data (7FE0,0010) value will thus map to a displayed value, a Doppler velocity and magnitude value. The example has a Palette Color Photometric Interpretation with 16 Bits Allocated and Bits Stored per sample. The Palette Color Lookup Tables also have 16 bits for each entry. The fact that the example has just one sample per pixel means that each composite pixel value is identical to the single Pixel Data value. An example Pixel Data value is shown in brackets along with the output values resulting from each step where it is processed. The Pixel Data value is mapped to red, green, and blue values from the supplied Palette Color Lookup Tables before being displayed. The display device supports 8 bits per sample and thus requires the scaling of the output values from the 16 bit per entry LUTs. The Doppler Velocity Region maps each pixel value in the Region to the Doppler velocity. The Pixel Component Organization (0018,6044) has a value of zero, indicating bit aligned positions with a bit mask. The Pixel Component Mask (0018,6046) specifies that the least significant 4 bits of the most significant byte convey the Doppler velocity of each pixel. The Pixel Component Physical Units (0018,604C) are cm/sec, and the Pixel Component Data Type (0018,604E) indicates color flow velocity. The Table of X Break Points (0018,6052) and Table of Y Break Points (0018,6054) map each masked composite pixel value to a Doppler velocity value in cm/sec. The Doppler Magnitude Region maps each pixel value in the Region to the Doppler magnitude. The Pixel Component Organization (0018,6044) has a value of zero, indicating bit aligned positions with a bit mask. The Pixel Component Mask (0018,6046) specifies that the most significant 4 bits of the most significant byte convey the Doppler magnitude of each pixel. The Pixel Component Physical Units (0018,604C) is set to dB, and the Pixel Component Data Type (0018,604E) indicates color flow magnitude. The Table of X Break Points (0018,6052) and Table of Y Break Points (0018,6054) map each masked composite pixel value to a Doppler magnitude value in dB.
This value is ANDed with the composite pixel code for each pixel within the region, then shifted right by the number of contiguous least significant zeros in the mask to obtain what will be referred to as the "Shifted Masked Composite Pixel Code" (SMCPC). Required if Pixel Component Organization = Bit aligned. See C.8.5.5.1.5 for further explanation.
Pixel Component Mask (0018,6046) is ANDed with the Composite Pixel Code (see Section C.7.6.3.1.1) for each pixel within the region, then shifted right by the number of contiguous least significant zeros in the mask to obtain what will be referred to as the "Shifted Masked Composite Pixel Code". The mask will most likely (but not necessarily) contain a block of contiguous ones, surrounded by leading and trailing zeros. The purpose of this mask is to keep only those bits within the composite pixel code that pertain to the region. It is to be used only when Pixel Organization is bit aligned positions.
Defines the start of the numeric range of values within the composite pixel where calibration is to be defined by the "pixel physical calibration table". To be used only when ranges are used to describe the portion of the composite pixel. Required if Pixel Component Organization = Ranges. Defines the stop of the numeric range of values within the composite pixel where calibration is to be defined by the "pixel physical calibration table". To be used only when ranges are used to describe the portion of the composite pixel. Required if Pixel Component Organization = Ranges. The physical units to be applied to the pixel component. Required if Pixel Component Organization exists. See C.8.5.5.1.6 for further explanation.
For Pixel Component Physical Units (0018,604C), the Enumerated Values describing the physical units to be applied to the pixel component are:
The type of data for the pixel component. Required if Pixel Component Organization exists. See C.8.5.5.1.7 for further explanation.
For Pixel Component Data Type (0018,604E), the Enumerated Values indicating the type of data for the pixel component are: 000AH Tissue Classification
The number of break point coordinate pairs used to describe a piece wise linear curve. Required if Pixel Component Organization equals 0 or 1. Otherwise not used. See C.8.5.5.1.8 for further explanation.
The Number of Table Break Points (0018,6050) gives the number of entries in each of two tables: the Table of X Break Points (0018,6052) and Table of Y Break Points (0018,6054). These tables are used to designate a curve mapping the value of a pixel component to its actual physical value, as described in Section C.8.5.5.1.9.
An array of X values used to create the piece wise linear curve. Required if Pixel Component Organization equals 0 or 1. Otherwise not used. See C.8.5.5.1.9 for further explanation.
Table of X Break Points (0018,6052) and Table of Y Break Points (0018,6054) are individual arrays of coordinates which interpreted together are used to create a piecewise linear curve. Each X value from the Table of X Break Points is matched with the corresponding Y value from the Table of Y Break Points yielding an (X,Y) coordinate. The set of (X,Y) coordinates describes a piecewise linear curve mapping the value of a pixel component to its actual physical value (in units defined in Pixel Component Physical Units data element (0018,604C) ). The X direction on the curve has no units, and represents actual pixel component values. If the Pixel Component Organization (0018,6044) is "Bit aligned positions", and the width of the Pixel Component Mask is n bits then the X coordinates are in the range 0 through 2n -1. If the Pixel Component Organization is Ranges, then the X coordinates are in the range 0 through 2 number of bits in the composite pixel - 1. Note: The X value is NOT relative to the Pixel Component Range Start (0018,6048). Not all possible X values in the range need be covered by the curve. For any pixel component value in the range of the curve described by this table, the corresponding Y value is the actual physical value for that pixel, in units specified in the Pixel Component Physical Units data element (0018,604C). If the pixel component value is NOT within the range of specified X values for the curve, then no pixel calibration is defined by this region. It may be possible for pixel calibration to be defined by other spatial regions intersecting this one.
An array of Y values used to create the piece wise linear curve. Required if Pixel Component Organization equals 0 or 1. Otherwise not used. See C.8.5.5.1.9 for further explanation.
Table of X Break Points (0018,6052) and Table of Y Break Points (0018,6054) are individual arrays of coordinates which interpreted together are used to create a piecewise linear curve. Each X value from the Table of X Break Points is matched with the corresponding Y value from the Table of Y Break Points yielding an (X,Y) coordinate. The set of (X,Y) coordinates describes a piecewise linear curve mapping the value of a pixel component to its actual physical value (in units defined in Pixel Component Physical Units data element (0018,604C) ). The X direction on the curve has no units, and represents actual pixel component values. If the Pixel Component Organization (0018,6044) is "Bit aligned positions", and the width of the Pixel Component Mask is n bits then the X coordinates are in the range 0 through 2n -1. If the Pixel Component Organization is Ranges, then the X coordinates are in the range 0 through 2 number of bits in the composite pixel - 1. Note: The X value is NOT relative to the Pixel Component Range Start (0018,6048). Not all possible X values in the range need be covered by the curve. For any pixel component value in the range of the curve described by this table, the corresponding Y value is the actual physical value for that pixel, in units specified in the Pixel Component Physical Units data element (0018,604C). If the pixel component value is NOT within the range of specified X values for the curve, then no pixel calibration is defined by this region. It may be possible for pixel calibration to be defined by other spatial regions intersecting this one.
The number of entries in the Table of Pixel Values. Required if the value of Pixel Component Organization (0018,6044) is 2 or 3. Otherwise not used. See C.8.5.5.1.11 for further explanation.
The Number of Table Entries (0018,6056) gives the number of entries in the Table of Pixel Values, the number of entries in the Table of Parameter Values (0018,605A), if present, and the number of items in the Pixel Value Mapping Code Sequence (0040,9098) , if present.
A table of Pixel Values used in conjunction with the Table of Parameter Values (0018,605A) or Pixel Value Mapping Code Sequence (0040,9098) to provide a mapping from Pixel Value to a real world value. Required if the Pixel Component Organization equals 2. Otherwise not used. See C.8.5.5.1.12 for further explanation.
The Table of Pixel Values (0018,6058) specifies the pixel values that are mapped to real world parameter values or coded concepts (tissue characterizations). The number of entries in the table is given by Number of Table Entries (0018,6056). A pixel is calibrated (mapped to a real-world value) by finding an entry in the Table of Pixel Values that matches its Composite Pixel Code (see Section C.7.6.3.1.1). The offset index of this entry is used as an index into the Parameter Value Table (0018,605A) or as a sequence item number in the Pixel Value Mapping Code Sequence (0040,9098) to select the real world value. The first Table of Pixel Values entry corresponds to sequence item 1. Note: If a Composite Pixel Code has no matching value in the Pixel Value Table then there is no unambiguous way to determine the corresponding Parameter Value. A method may exist to determine a valid Parameter Value but the specification of such a method is outside the scope of the DICOM standard. No assumption should be made that linear interpolation will produce a valid result.
A table of Parameter Values used in conjunction with the Table of Pixel Values (0018,6058) to provide a mapping from Pixel Value to Parameter Value. Required if the value of Pixel Component Organization (0018,6044) is 2. Otherwise not used. See C.8.5.5.1.13 for further explanation
The Table of Parameter Values (0018,605A) provides the real world values for pixel values identified in the Table of Pixel Values (0018,6058). The number of table entries is given by Number of Table Entries (0018,6056) and the physical units are given by Pixel Component Physical Units (0018,604C). Values may repeat when a parameter value is associated with more than one Composite Pixel Code value.
Sequence that, in conjunction with the Table of Pixel Values (0018,6058), provides a mapping from a Pixel Value to an associated Coded Concept. One or more Items shall be present; the number of Items shall be equal to the value of Number of Table Entries (0018,6056). Required if the value of Pixel Component Organization (0018,6044) is 3 (Code Sequence look up). See Sections C.8.5.6.1.18 for further explanation. The manufacturer defined description of center frequency of the interrogating ultrasound energy. The units are kilohertz. The ultrasound pulse repetition frequency, as defined by the manufacturer, used to collect data in the region. The units are in hertz. The Doppler correction angle. The units are degrees. The steering angle, as defined by the manufacturer, used for a steered 2D image. The units are degrees. The x displacement, in pixels, from the Reference pixel to the center of the Doppler sample volume. The y displacement, in pixels, from the Reference pixel to the center of the Doppler sample volume. The starting and ending coordinates pairs of the m-line. Where the X0,Y0 are the starting point and X1,Y1 are the end point of the tm-line. See C.8.5.5.1.10 for further explanation.
TM-Line Position X1 ,TM-Line Position Y1 The TM-Line Position X0 (0018,603D) and TM-Line Position Y0 (0018,603F) are the coordinates of the starting point and TM-Line Position X1 (0018,6041), TM-Line Position Y1 (0018,6043) are the coordinates of the end point of the TM-line. The coordinate is defined as the displacement, in pixels, from the Reference pixel. Typically used for M-mode line and CW Doppler.
The starting and ending coordinates pairs of the m-line. Where the X0,Y0 are the starting point and X1,Y1 are the end point of the tm-line. See C.8.5.5.1.10 for further explanation.
TM-Line Position X1 ,TM-Line Position Y1 The TM-Line Position X0 (0018,603D) and TM-Line Position Y0 (0018,603F) are the coordinates of the starting point and TM-Line Position X1 (0018,6041), TM-Line Position Y1 (0018,6043) are the coordinates of the end point of the TM-line. The coordinate is defined as the displacement, in pixels, from the Reference pixel. Typically used for M-mode line and CW Doppler.
The starting and ending coordinates pairs of the m-line. Where the X0,Y0 are the starting point and X1,Y1 are the end point of the tm-line. See C.8.5.5.1.10 for further explanation.
TM-Line Position X1 ,TM-Line Position Y1 The TM-Line Position X0 (0018,603D) and TM-Line Position Y0 (0018,603F) are the coordinates of the starting point and TM-Line Position X1 (0018,6041), TM-Line Position Y1 (0018,6043) are the coordinates of the end point of the TM-line. The coordinate is defined as the displacement, in pixels, from the Reference pixel. Typically used for M-mode line and CW Doppler.
The starting and ending coordinates pairs of the m-line. Where the X0,Y0 are the starting point and X1,Y1 are the end point of the tm-line. See C.8.5.5.1.10 for further explanation.
TM-Line Position X1 ,TM-Line Position Y1 The TM-Line Position X0 (0018,603D) and TM-Line Position Y0 (0018,603F) are the coordinates of the starting point and TM-Line Position X1 (0018,6041), TM-Line Position Y1 (0018,6043) are the coordinates of the end point of the TM-line. The coordinate is defined as the displacement, in pixels, from the Reference pixel. Typically used for M-mode line and CW Doppler.
Number of samples (planes) in this image. See C.8.5.6.1.12 for specialization
For US Images, Samples Per Pixel (0028,0002) is specified to use the following values for specific Photometric Interpretations: Table C.8-19 US SAMPLES PER PIXEL
Specifies the intended interpretation of the pixel data. See C.8.5.6.1.2 for specialization.
For US Images, Photometric Interpretation (0028,0004) is specified to use the following Defined Terms: Note: It is recommended that future implementations should not use ARGB photometric interpretation. See PS 3.5 for restrictions imposed by compressed Transfer Syntaxes.
Number of bits allocated for each pixel sample. See C.8.5.6.1.13 for specialization.
For US Images, Bits Allocated (0028,0100) is specified to use the following values for specific Photometric Interpretations: Table C.8-20 US BITS ALLOCATED
Number of bits stored for each pixel sample. See C.8.5.6.1.14 for specialization.
For US Images, Bits Stored (0028,0101) is specified to use the following values for specific Photometric Interpretations: Table C.8-21 US BITS STORED
Most significant bit for pixel sample data. See C.8.5.6.1.15 for specialization.
For US Images, High Bit (0028,0102) is specified to use the following values for specific Photometric Interpretations: Table C.8-22 US HIGH BIT
Indicates whether the pixel data are sent color-by-plane or color-by-pixel. Required if Samples per Pixel (0028,0002) has a value greater than 1. See C.8.5.6.1.16 for specialization.
For US Images, Planar Configuration (0028,0006) is specified to use the following values for specific Photometric Interpretations: Table C.8-23 US PLANAR CONFIGURATION
Data representation of pixel samples. See C.8.5.6.1.3 for specialization.
For US Images, Pixel Representation (0028,0103) is specified to use the following Enumerated Value: 0000H = unsigned integer
Contains the Data Element Tag of the attribute which is used as the frame increment in Multi-frame pixel data (see C.7.6.6). Required if Number of Frames is sent. See C.8.5.6.1.4 for specialization.
For US Multi-frame images, the Attribute Frame Increment Pointer (0028,0009) of the Multi-frame Module (see Section C.7.6.6) is specified by the following Defined Terms: 00181063 = sequencing by Frame Time (0018,1063) 00181065 = sequencing by Frame Time Vector (0018,1065)
Image identification characteristics. See C.8.5.6.1.1 for specialization.
For US Images, Image Type (0008,0008) is specified to be Type 2. The Defined Terms for Value 3 are: Value 4 is constructed as a modality bit map to allow for a description of multi-modality displays. In using this bit map, the sum of the values of the various modalities will unambiguously determine the constituent modalities. Notes: 1. All Values are hexadecimal encoded as a CS. See PS 3.5. 2. For example, Color Flow with CW spectral Doppler would have a value 4 = 0015. Note that no assumption should be made in Color Doppler or Color M-Mode regarding underlying B or M-Mode, respectively.
Specifies whether an Image has undergone lossy compression. Enumerated Values: 00 = Image has NOT been subjected to lossy compression. 01 = Image has been subjected to lossy compression. See C.7.6.1.1.5 Required if Lossy Compression has been performed on the Image.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
Number of Stages in this protocol. Required if image was acquired in a Staged protocol. Number of views in this Stage. Required if image was acquired in a Staged protocol. The time offset(s) of the reported R Wave peaks, each relative to the time of the start of the acquisition of the first frame in msec. Multi-valued, with one value per reported R Wave. This element indicates if any ultrasound color data is present in an image. Enumerated Values: 00 = Ultrasound color data not present in image 01 = Ultrasound color data is present in image. See C.8.5.6.10 A Stage is a particular time slice of a protocol in which a set of images are collected. The names can be free form text. Recommended text for Stress Echo stage names are: PRE-EXERCISE, POST-EXERCISE, PEAK-EXERCISE, RECOVERY, BASELINE, LOW DOSE, PEAK DOSE Sequence of items describing the performed Ultrasound Protocol Stage(s). One or more Items may be included in this Sequence. A number that identifies the Stage. Stage Number starts at one. A View is a particular combination of the position and orientation when a set of images are acquired. Images are acquired at the same View in different Stages for the purpose of comparison. A number that identifies the View. View Number starts at one. The number of event timers used at the time of acquisition of a Multi-frame image. An array of values associated with each event timer. Units in milliseconds. Name that identifies the event timer. Sequence that describes the view of the patient anatomy in this image. Only a single Item shall be permitted in this Sequence. See Section C.8.5.6.1.19.
The view of the patient anatomy may be described using coded terminology in the View Code Sequence (0054,0220). The view is typically specified by transducer position relative to the patient anatomy and/or transducer orientation, The view may be described by a single Code Sequence Item, or by combination of post-coordinated Code Sequence Items. The principal coded item is specified in View Code Sequence, and modifier terms in the View Modifier Code Sequence (0054,0222). The Baseline Context IDs for post-coordinated encoding of view are:
Sequence that provides modifiers for the view of the patient anatomy. Zero or more Items shall be permitted in this Sequence. See Section C.8.5.6.1.19.
The view of the patient anatomy may be described using coded terminology in the View Code Sequence (0054,0220). The view is typically specified by transducer position relative to the patient anatomy and/or transducer orientation, The view may be described by a single Code Sequence Item, or by combination of post-coordinated Code Sequence Items. The principal coded item is specified in View Code Sequence, and modifier terms in the View Modifier Code Sequence (0054,0222). The Baseline Context IDs for post-coordinated encoding of view are:
The date and time that the acquisition of data that resulted in this image started. Required if Modality (0008,0060) = IVUS May be present otherwise. Note: The synchronization of this time with an external clock is specified in the Synchronization Module in Acquisition Time Synchronized (0018,1800). Time interval measured in msec from the start of the R-wave to the beginning of data taking Average R-R interval used for these data, in msec Beat length sorting has been applied. Enumerated Values: Y = yes N = no R-R interval low limit for beat rejection, in msec R-R interval high limit for beat rejection, in msec Beats per minute. Defined Terms: MOTOR_PULLBACK MANUAL_PULLBACK SELECTIVE GATED_PULLBACK See C.8.5.6.1.21 Required if Modality (0008,0060) = IVUS
This attribute denotes which of the following defined terms describes the method used to acquire the IVUS Images. MOTOR_PULLBACK: The IVUS imaging catheter is positioned in the blood vessel under examination distal to the anatomical structures to be examined. Then the catheter is attached to a motorized mechanism capable of withdrawing the catheter through the vessel at a constant velocity specified by the attribute IVUS Pullback Rate (0018,3101) from the defined IVUS Pullback Start Frame Number (0018,3103) (see C.8.5.6.1.24) to the IVUS Pullback Stop Frame Number (0018,3104) (see C.8.5.6.1.25). MANUAL_PULLBACK: The IVUS imaging catheter is positioned in the blood vessel under examination distal to the anatomical structures to be examined. Then the catheter is manually withdrawn through the vessel region of interest. SELECTIVE: The IVUS imaging catheter is positioned in the blood vessel under examination near the anatomical structures to be examined. Then the catheter is manually withdrawn or advanced through the vessel region of interest. GATED_PULLBACK: The IVUS imaging catheter is positioned in the blood vessel under examination distal to the anatomical structures to be examined. Then the catheter is attached to a motorized mechanism capable of withdrawing the catheter through the vessel at a rate specified by the attribute IVUS Gated Rate (0018,3102), once per heart cycle, from the defined IVUS Pullback Start Frame Number (0018,3103) (see C.8.5.6.1.24) to the IVUS Pullback Stop Frame Number (0018,3104) (see C.8.5.6.1.25).
Required if IVUS Acquisition (0018,3100) value is MOTOR_PULLBACK. Specified in units of mm/sec. See C.8.5.6.1.22
The attribute IVUS Pullback Rate (0018,3101) is required when IVUS Acquisition (0018,3100) is MOTOR_PULLBACK and it specifies the velocity of withdrawal of the IVUS imaging catheter in millimeters per second.
Required if IVUS Acquisition (0018,3100) value is GATED_PULLBACK. Specified in units of mm/beat. See C.8.5.6.1.23
The attribute IVUS Gated Rate (0018,3102) is required when IVUS Acquisition (0018,3100) is GATED_PULLBACK and it specifies the velocity of withdrawal of the IVUS imaging catheter in millimeters per beat.
Required if IVUS Acquisition (0018,3100) value is MOTOR_PULLBACK or GATED_PULLBACK. See C.8.5.6.1.24
The IVUS Pullback Start Frame Number (0018,3103) specifies the frame number of a IVUS multi-frame acquisition upon which motorized or gated pullback begins.
Required if IVUS Acquisition (0018,3100) value is MOTOR_PULLBACK or GATED_PULLBACK. See C.8.5.6.1.25
The IVUS Pullback Stop Frame Number (0018,3104) specifies the frame number of a IVUS multi-frame acquisition upon which motorized or gated pullback ends.
Identifier(s) of the lesion(s) of interest imaged within the current SOP Instance. Each lesion shall have a unique numeric integer identifier within the study. See C.8.5.6.1.26.
Attribute Lesion Number identifies the lesion(s) of interest imaged within the current SOP Instance. Each lesion shall have a unique numeric integer identifier within the study. If during a study the same lesion is imaged more than once, the same Lesion Number should be used for both SOP Instances. Notes: 1.Lesion Number is not a DICOM UID. 2.An IVUS pullback may contain multiple values in Lesion Number.
Manufacturer defined character string description of ultrasound output level(s) used in generating a given image. Data may be expressed in dB, %, W/cm2, etc. Manufacturer defined code or description of ultrasound transducer used. Defined Terms: SECTOR_PHASED SECTOR_MECH SECTOR_ANNULAR LINEAR CURVED LINEAR SINGLE CRYSTAL SPLIT XTAL CWD IV_PHASED IV_ROT XTAL IV_ROT MIRROR ENDOCAV_PA ENDOCAV_MECH ENDOCAV_CLA ENDOCAV_AA ENDOCAV_LINEAR VECTOR_PHASED The depth, from the transducer face, of the manufacturer defined beam focus used for the image, in cm. Manufacturer defined description of processing of echo information. Data may include code or description of gain (initial, overall, TGC, dynamic range, etc.), preprocessing, postprocessing, Doppler processing parameters, e.g. cutoff filters, etc., as used in generating a given image. See C.8.5.6.1.8 for Description.
The thermal and/or mechanical indices, when made available by a manufacturer, are defined according to the Standard for Real-Time Display of Thermal and Mechanical Acoustic Output Indices on Diagnostic Ultrasound Equipment, a voluntary performance standard jointly published by AIUM and NEMA.
See C.8.5.6.1.8 for Description.
The thermal and/or mechanical indices, when made available by a manufacturer, are defined according to the Standard for Real-Time Display of Thermal and Mechanical Acoustic Output Indices on Diagnostic Ultrasound Equipment, a voluntary performance standard jointly published by AIUM and NEMA.
See C.8.5.6.1.8 for Description.
The thermal and/or mechanical indices, when made available by a manufacturer, are defined according to the Standard for Real-Time Display of Thermal and Mechanical Acoustic Output Indices on Diagnostic Ultrasound Equipment, a voluntary performance standard jointly published by AIUM and NEMA.
See C.8.5.6.1.8 for Description.
The thermal and/or mechanical indices, when made available by a manufacturer, are defined according to the Standard for Real-Time Display of Thermal and Mechanical Acoustic Output Indices on Diagnostic Ultrasound Equipment, a voluntary performance standard jointly published by AIUM and NEMA.
See C.8.5.6.1.8 for Description.
The thermal and/or mechanical indices, when made available by a manufacturer, are defined according to the Standard for Real-Time Display of Thermal and Mechanical Acoustic Output Indices on Diagnostic Ultrasound Equipment, a voluntary performance standard jointly published by AIUM and NEMA.
See C.8.5.6.1.8 for Description.
The thermal and/or mechanical indices, when made available by a manufacturer, are defined according to the Standard for Real-Time Display of Thermal and Mechanical Acoustic Output Indices on Diagnostic Ultrasound Equipment, a voluntary performance standard jointly published by AIUM and NEMA.
The depth, in mm, from the transducer face to the deepest point included in the displayed image- the field of view. Defined term which identifies the intended purpose of the ROI Overlay Type. See C.8.5.6.1.11 for specialization.
For US Images, Overlay Subtype (60xx,0045) shall use the following Defined Terms: ACTIVE 2D/BMODE IMAGE AREA = identification of the active area of a 2D/B-mode image.
Describes the kind of image conversion. Defined Terms : DV = Digitized Video DI = Digital Interface DF = Digitized Film WSD = Workstation SD = Scanned Document SI = Scanned Image DRW = Drawing SYN = Synthetic Image Source equipment for the image. This type definition shall override the definition in the General Series Module. See C.7.3.1.1.1 for Defined Terms.
Defined Terms for the Modality (0008,0060) are: Retired Defined Terms for the Modality (0008,0060) are: Note: 1. The XA modality incorporates the retired modality DS. 2. The RF modality incorporates the retired modalities CF, DF, VF. 3. The modality listed in the Modality Data Element (0008,0060) may not match the name of the IOD in which it appears. For example, a SOP instance from XA IOD may list the RF modality when an RF implementation produces an XA object. 4. The MR modality incorporates the retired modalities MA and MS.
User defined identification of the device that converted the image Manufacturer of the Secondary Capture Device Manufacturer's model number of the Secondary Capture Device Manufacturer's designation of software version of the Secondary Capture Device Original format of the captured video image (e.g. NTSC, PAL, Videomed-H) Additional information about digital interface used to acquire the image
The date the Secondary Capture Image was captured. The time the Secondary Capture Image was captured. Physical distance on the media being digitized or scanned between the center of each pixel, specified by a numeric pair - adjacent row spacing (delimiter) adjacent column spacing in mm. See 10.7.1.3 for further explanation of the value order. Shall be consistent with Pixel Aspect Ratio (0028,0034), if present. Indicates whether or not image contains sufficient burned in annotation to identify the patient and date the image was acquired. Enumerated Values: YES NO Specifies an identity transformation for the Presentation LUT, such that the output of all grayscale transformations defined in the IOD containing this Module are defined to be P-Values. Enumerated Values: IDENTITY - output is in P-Values. Required if Photometric Interpretation (0028,0004) is MONOCHROME2, and BitsStored (0028,0101) is greater than 1. Note: If the VOI LUT Module is required by the IOD but no VOI LUT Sequence (0028,3010) or Window Center (0028,1050) is present, then the VOI LUT stage is an identity transformation. Luminance of a hypothetical viewing device illuminating a piece of monochrome transmissive film, or for the case of reflective media, luminance obtainable from diffuse reflection of the illumination present. Expressed as L0, in candelas per square meter (cd/m2). Note: May be used together with Reflected Ambient Light (2010,0160) to recover Optical Density information from P-Values. See C.8.6.3.1.
Illumination (2010,015E) and Reflected Ambient Light (2010,0160) may be used to recover Optical Density information from P-Values. Monochrome media that is being digitized is often measured in Optical Density values. These values need to be converted to P-Values for storage and display. The P-Values used in an image correspond to the perception of a human observer viewing the film on a hypothetical viewing device (such as a light box), using the specified values of Illumination (2010,015E) and Reflected Ambient Light (2010,0160). The Grayscale Standard Display Function defined in PS 3.14 is used to convert Luminance to P-Values. In the case of scanned film, the Luminance is derived from Optical Density using the specified values of Illumination (2010,015E) and Reflected Ambient Light (2010,0160). An example of this derivation, as well as typical “default” values for these parameters, is specified in PS 3.14.
For scanned monochrome transmissive film viewed on a hypothetical viewing device, the luminance contribution due to reflected ambient light. Expressed as La, in candelas per square meter (cd/m2). Note: May be used together with Illumination (2010,015E) to recover Optical Density information from P-Values. See C.8.6.3.1.
Illumination (2010,015E) and Reflected Ambient Light (2010,0160) may be used to recover Optical Density information from P-Values. Monochrome media that is being digitized is often measured in Optical Density values. These values need to be converted to P-Values for storage and display. The P-Values used in an image correspond to the perception of a human observer viewing the film on a hypothetical viewing device (such as a light box), using the specified values of Illumination (2010,015E) and Reflected Ambient Light (2010,0160). The Grayscale Standard Display Function defined in PS 3.14 is used to convert Luminance to P-Values. In the case of scanned film, the Luminance is derived from Optical Density using the specified values of Illumination (2010,015E) and Reflected Ambient Light (2010,0160). An example of this derivation, as well as typical “default” values for these parameters, is specified in PS 3.14.
The value b in the relationship between stored values (SV) in Pixel Data (7FE0,0010) and the output units specified in Rescale Type (0028,1054). Output units = m*SV + b. Enumerated Value: 0 Required if Photometric Interpretation (0028,0004) is MONOCHROME2, and BitsStored () is greater than 1. Note: This specifies an identity Modality LUT transformation. m in the equation specified by Rescale Intercept (0028,1052). Enumerated Value: 1 Required if Photometric Interpretation (0028,0004) is MONOCHROME2, and BitsStored (0028,0101) is greater than 1. Note: This specifies an identity Modality LUT transformation. Specifies the output units of Rescale Slope (0028,1053) and Rescale Intercept (0028,1052). Enumerated Value: US = Unspecified Required if Photometric Interpretation (0028,0004) is MONOCHROME2, and BitsStored (0028,0101) is greater than 1. Note: This specifies an identity Modality LUT transformation. Contains the Data Element Tag of the attribute which is used as the frame increment in Multi-frame pixel data. See C.7.6.6.1.1 for further explanation. Shall be present if Number of Frames is greater than 1, overriding (specializing) the Type 1 requirement on this attribute in the Multi-frame Module.
A Multi-frame Image is defined as a Image whose pixel data consists of a sequential set of individual Image Pixel frames. A Multi-frame Image is transmitted as a single contiguous stream of pixels. Frame headers do not exist within the data stream. Each individual frame shall be defined (and thus can be identified) by the Attributes in the Image Pixel Module (see C.7.6.3). All Image IE Attributes shall be related to the first frame in the Multi-frame image. The total number of frames contained within a Multi-frame Image is conveyed in the Number of Frames (0028,0008). The frames within a Multi-frame Image shall be conveyed as a logical sequence. The information that determines the sequential order of the frames shall be identified by the Data Element Tag or tags conveyed by the Frame Increment Pointer (0028,0009). Each specific Image IOD that supports the Multi-frame Module specializes the Frame Increment Pointer (0028,0009) to identify the Attributes that may be used as sequences. Even if only a single frame is present, Frame Increment Pointer (0028,0009) is still required to be present and have at least one value, each of which shall point to an attribute that is also present in the dataset and has a value. Note: For example, in single-frame instance of an IOD that is required to or may contain the Cine Module, it may be appropriate for Frame Time (0018,1063) to be present with a value of 0, and be the only target of Frame Increment Pointer (0028,0009).
Physical distance on the media being digitized or scanned between the center of each pixel, specified by a numeric pair - adjacent row spacing (delimiter) adjacent column spacing in mm. See 10.7.1.3 for further explanation of the value order. Required if Conversion Type (0008,0064) is DF (Digitized Film). May also be present if Conversion Type (0008,0064) is SD (Scanned Document) or SI (Scanned Image). Shall be consistent with Pixel Aspect Ratio (0028,0034), if present. Enumerated Values: ROW COLUMN Angle of the edge of the film relative to the transport direction in degrees greater than or equal to -45 and less than or equal to +45.
An array which contains the real time increments (in msec) between frames for a Multi-frame image. See C.7.6.5.1.2 for further explanation. Required if Frame Increment Pointer (0028,0009) points to Frame Time Vector (0018,1065). Note: Frame Time Vector arrays may not be properly encoded if Explicit-VR transfer syntax is used and the VL of this attribute exceeds 65534 bytes.
Frame Time Vector (0018,1065) is an array that contains the time increments (in milliseconds) between the nth frame and the previous frame for a Multi-frame image. The first frame always has a time increment of 0. If the Frame Increment Pointer points to this Attribute, the Frame Time Vector shall be used in the following manner to calculate 'relative time' T(n) for frame n: where ti is the ith Frame Time Vector component.
An array which contains, for each of the image frames, the corresponding page numbers of the original document. Required if Frame Increment Pointer (0028,0009) points to Page Number Vector (0018,2001). An array which contains, for each of the image frames, a descriptive label. Required if Frame Increment Pointer (0028,0009) points to Frame Label Vector (0018,2002). An array which contains, for each of the image frames, the primary angle of rotation about an undefined axis, in degrees. May be used for annotative purposes for "cine loops" of 3D reprojected images Required if Frame Increment Pointer (0028,0009) points to Frame Primary Angle Vector (0018,2003). An array which contains, for each of the image frames, the secondary angle of rotation about an undefined axis that is orthogonal to that used for Frame Primary Angle Vector (0018,2003), in degrees. May be used for annotative purposes for "cine loops" of 3D reprojected images Required if Frame Increment Pointer (0028,0009) points to Frame Secondary Angle Vector (0018,2004). An array that contains, for each of the image frames, the relative position of the image plane expressed in mm, as defined for Slice Location (0020,1041). See C.7.6.2.1.2 for further explanation. Required if Frame Increment Pointer (0028,0009) points to Slice Location Vector (0018,2005).
The Slice Location (0020,1041) is defined as the relative position of the image plane expressed in mm. This information is relative to an unspecified implementation specific reference point.
An array which contains, for each of the image frames, a label or number of the display window of a graphical user interface from which the frame was captured. Required if Frame Increment Pointer (0028,0009) points to Display Window Label Vector (0018,2006).
Required if Multi-Frame Image. Contains the Data Element Tag of the attribute that is used as the Frame increment in Multi-frame image pixel data (See C.7.6.6). Specialized for X-Ray as Enumerated Value: 00181063H = Frame Time (0018,1063); 00181065H = Frame Time Vector (0018,1065).
Table C.7-14 specifies the Attributes of a Multi-frame pixel data Image. Table C.7-14 MULTI-FRAME MODULE ATTRIBUTES
Specifies whether an Image has undergone lossy compression. Enumerated Values: 00 = Image has NOT been subjected to lossy compression. 01 = Image has been subjected to lossy compression. See C.7.6.1.1.5 Required if Lossy Compression has been performed on the Image.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
Image identification characteristics. See C.8.7.1.1.1 for specialization.
The Image Type attribute identifies important image characteristics in a multiple valued data element. For X-Ray, Image Type is specialized as follows: a. Value 1 shall identify the Pixel Data Characteristics in accordance with Section C.7.6.1.1.2; Enumerated Values are: ORIGINAL and DERIVED; b. Value 2 shall identify the Patient Examination Characteristics in accordance with Section C.7.6.1.1.2; Enumerated Values are: PRIMARY and SECONDARY. Note: X-Ray images generally use PRIMARY value for images captured from patient exposure. c. Value 3 shall identify the image set in terms of the imaging planes. Enumerated Values are: d. Other Values are implementation specific (optional).
The relationship between the Pixel sample values and the X-Ray beam intensity. See Section C.8.7.1.1.2.
Pixel Intensity Relationship (0028,1040) shall identify the relationship of the pixel values to the X-Ray beam intensity. Defined terms are:
Number of samples (color planes) in this image shall have a value of 1. Specifies the intended interpretation of the pixel data. Only MONOCHROME2 may be used. Number of bits allocated for each pixel sample. See Section C.8.7.1.1.6.
For X-Ray Images, Bits Allocated (0028,0100) shall have the Enumerated Value of 8 or 16.
Number of bits stored for each pixel sample. See Section C.8.7.1.1.7.
For X-Ray Images, Bits Stored (0028,0101) shall have the Enumerated Values of 8, 10, 12, or 16.
Most significant bit for pixel sample data. See Section C.8.7.1.1.8.
For X-Ray Images, High Bit (0028,0102) shall have the Enumerated Value of one less than the value in Bit Stored.
Data representation of the pixel samples. Shall have the value: 0000H = Unsigned Integer. Parameters of scanning sequence. See Section C. 8.7.1.1.4. Marks the location(s) of the R Wave in the cardiac cycles by referencing frame numbers; frame numbers begin with 1. A sequence which provides reference to a set of Image SOP Class/Instance identifying other images significantly related to this image. Shall be present if Image Type (0008,0008) Value 3 is BIPLANE A or BIPLANE B. May be present otherwise. One or more items may be included in this sequence.. See Section C.8.7.1.1.13.
When Image Type (0008,0008) Value 3 is BIPLANE A or BIPLANE B, Referenced Image Sequence (0008,1140) shall be used to identify the corresponding SOP Instance of the Biplane acquisition. In this case, either:
Describes the purpose for which the reference is made. Only a single Item shall be permitted in this Sequence. A text description of how this image was derived. See C.8.7.1.1.5 for further explanation.
If an Image is identified to be a Derived image (see C.8.9.1.1.1 Image Type), Derivation Description (0008,2111) is an optional and implementation specific text description of the way the image was derived from an original image. As applied to X-Ray images, it may be used to describe derivation operations such as edge enhancement, temporal filtering, digital subtraction, or other linear and non-linear transformations.
Indicates any visual processing performed on the images prior to exchange. See Section C.8.7.1.1.3.
Acquisition Device Processing Description (0018,1400) provides some indication in human readable text of the digital processing on the images before exchange. Examples of this processing are: edge enhanced, subtracted, time filtered, gamma corrected, convolved (spatially filtered).
A multi-valued attribute that contains a descriptive label for each of the image frames. The number of values shall equal the number of frames. Contains the Data Element Tags of one or more attributes that vary or increment for the frames of a multi-frame image. See C.8.7.1.1.12. Shall not be present if it would contain only one value and that value would be Frame Time (0018,1063) or Frame Time Vector (0018,1065).
Frame Dimension Pointer (0028,000A) identifies attributes that vary or increment with each frame, and which are clinically significant for viewing or processing the image. This is intended for SOP Instances whose preferred clinical presentation is dependent on frame relationships other than simply time. Defined Terms for multiframe cine from the Cine Module (see C.7.6.5) are: 00181063H = Frame Time (0018,1063) 00181065H = Frame Time Vector (0018,1065) Defined Terms for rotational acquisition from the XA Positioner Module (see C.8.7.5) are: 00181520H = Positioner Primary Angle Increment (0018,1520) 00181521H = Positioner Secondary Angle Increment (0018,1521) Defined Terms for stepped acquisition from the X-Ray Table Module (see C.8.7.4) are: 00181135H = Table Vertical Increment (0018,1135) 00181137H = Table Longitudinal Increment (0018,1137) 00181136H = Table Lateral Increment (0018,1136) Defined Terms for an arbitrary labeled increment: 00182002H = Frame Label Vector (0018,2002) Notes: 1. Previous editions of the standard did not include the optional Frame Dimension Pointer (0028,000A), but instead depended entirely on the mandatory Frame Increment Pointer (0028,0009), and envisaged that only time and no other dimension would relate frames. Image creators that add the Frame Dimension Pointer (0028,000A) must anticipate that many implementations will ignore or discard this attribute when displaying or storing images and continue to assume that frames are temporally related. 2. Frame Time (0018,1063) or Frame Time Vector (0018,1065) will also be present and will contain appropriate values consistent with the times of acquisition of the frames.
Indicates whether a reference object (phantom) of known size is present in the image and was used for calibration. Enumerated Values: YES NO Device is identified using the Device module. See C.7.6.12.
Table C.7-18 describes the Attributes of devices or calibration objects (e.g., catheters, markers, baskets) that are associated with a study and/or image. Table C.7-18 DEVICE MODULE ATTRIBUTES
Peak kilo voltage output of the X-Ray generator used. Identify the general level of X-Ray dose exposure. Enumerated values are: SC = low dose exposure generally corresponding to fluoroscopic settings (e.g. preparation for diagnostic quality image acquisition); GR = high dose for diagnostic quality image acquisition (also called digital spot or cine); X-Ray Tube Current in mA. Required if Exposure (0018,1152) is not present. May be present otherwise. X-Ray Tube Current in µA. Duration of X-Ray exposure in msec. See 8.7.2.1.1. Required if Exposure (0018,1152) is not present. May be present otherwise. Duration of X-Ray exposure in µsec. The exposure expressed in mAs, for example calculated from Exposure Time and X-Ray Tube Current. Required if either Exposure Time (0018,1150) or X-Ray Tube Current (0018,1151) are not present. May be present otherwise. The exposure expressed in µAs, for example calculated from Exposure Time and X-Ray Tube Current. Identify the grid. Only a single value shall be present. Defined Terms are: IN = A Grid is positioned; NONE = No Grid is used. Average width of X-Ray pulse in msec. Specifies X-Ray radiation mode. Defined Terms: CONTINUOUS PULSED Type of filter(s) inserted into the X-Ray beam (e.g. wedges). Diameter of X-Ray intensifier in mm Shape of the Image Intensifier Field of View. See C.8.7.2.1.2. Defined Terms are: ROUND RECTANGLE
The Field of View Attribute describes the shape and dimensions of the Image Intensifier Field of View (zoom mode). This could be further restricted by the Collimator. See Section C.8.7.3.
Dimensions of the Image Intensifier Field of View in mm. If Rectangle, row dimension followed by column; if Round, diameter. Physical distance measured at the front plane of the Image Receptor housing between the center of each pixel specified by a numeric pair - row spacing value(delimiter) column spacing value in mm. See 10.7.1.3 for further explanation of the value order. The value of this attribute shall never be adjusted to account for correction for the effect of geometric magnification or calibration against an object of known size; Pixel Spacing (0028,0030) is specified for that purpose. Nominal focal spot size in mm used to acquire this image. X-Ray dose, measured in dGy*cm*cm, to which the patient was exposed for the acquisition of this image plus any non-digitally recorded fluoroscopy which may have been performed to prepare for the acquisition of this image. Note: The sum of the area dose product of all images of a Series or a Study may not result in the total area dose product to which the patient was exposed.
Shape(s) of the collimator. Enumerated Values: RECTANGULAR CIRCULAR POLYGONAL This multi-valued Attribute shall contain at most one of each Enumerated Value. Required if Collimator Shape (0018,1700) is RECTANGULAR. Location of the left edge of the rectangular collimator with respect to pixels in the image given as column. See C.8.7.3.1.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is RECTANGULAR. Location of the right edge of the rectangular collimator with respect to pixels in the image given as column. See C.8.7.3.1.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is RECTANGULAR. Location of the upper edge of the rectangular collimator with respect to pixels in the image given as row. See C.8.7.3.1.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is RECTANGULAR. Location of the lower edge of the rectangular collimator with respect to pixels in the image given as row. See C.8.7.3.1.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is CIRCULAR. Location of the center of the circular collimator with respect to pixels in the image given as row and column. See C.8.7.3.1.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is CIRCULAR. Radius of the circular collimator with respect to pixels in the image given as a number of pixels along the row direction. See C.8.7.3.1.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is POLYGONAL. Multiple Values where the first set of two values are: row of the origin vertex; column of the origin vertex. Two or more pairs of values follow and are the row and column coordinates of the other vertices of the polygon collimator. Polygon collimators are implicitly closed from the last vertex to the origin vertex and all edges shall be non-intersecting except at the vertices.
Defined terms: STATIC DYNAMIC Incremental change in Vertical position of the table relative to first frame of Multi-frame image given in mm. Required if Table Motion is DYNAMIC. Incremental change in Longitudinal position of the table relative to first frame of Multi-frame image in mm. Table motion towards +90°position of the primary angle of the positioner is positive. See C.8.7.4.1.2. Required if Table Motion is DYNAMIC.
The direction of the longitudinal movement is perpendicular to the primary axis of rotation of the positioner. A positive value of Table Longitudinal Increment (0018,1137) attributes indicates a movement towards the +90° position of the positioner, see figure C.8-9a. Figure C.8-9a Table Longitudinal Movement
Incremental change in Lateral position of the table relative to first frame of Multi-frame image given in mm. Table motion towards +90°position of the secondary angle of the positioner is positive. See C.8.7.4.1.3. Required if Table Motion is DYNAMIC.
The direction of the lateral movement is perpendicular to the secondary axis of rotation of the positioner. A positive value of Table Lateral Increment (0018,1136) attributes indicates a movement towards the +90° position of the positioner, see figure C.8-9b. Figure C.8-9b Table Lateral Movement Note: The terms “longitudinal” and “lateral” are relative to an operator standing tableside, and facing the patient. Thus lateral movement is to the left and right of the operator, and longitudinal movement is towards or away from the operator.
Angle of table plane in degrees relative to horizontal plane [Gravity plane]. Positive values indicate that the head of the table is upwards.
Distance in mm from source to isocenter (center of field of view). Note: This value is traditionally referred to as Source Object Distance (SOD). Distance in mm from source to detector center. Note: This value is traditionally referred to as Source Image Receptor Distance (SID). Ratio of Source Image Receptor Distance (SID) over Source Object Distance (SOD). Used to describe the activity of the imaging devices. Defined terms: DYNAMIC, STATIC. Required if Multi-frame data. See C.8.7.5.1.1.
Positioner Motion attribute is STATIC if the imaging table moves during a multi-frame acquisition, but the X-Ray positioner do not move. Note: If the positioner undergoes translation (non-rotational movement) during the acquisition, then that motion shall be described by an opposite table motion (See Section C.8.7.4).
Position of the X-Ray Image Intensifier about the patient from the RAO to LAO direction where movement from RAO to vertical is positive. See C.8.7.5.1.2.
The definitions of Positioner Angles shall be with respect to the patient as illustrated in Figures C.8-11 and C.8-12 Zero degree is referenced to the origin perpendicular to the patient's chest. The Positioner Primary Angle definition is like longitude (in the equatorial plan); the Positioner Secondary Angle definition is like latitude (in the sagittal plane). The Positioner Angle attributes apply to the first frame of a multi-frame image. The valid range of Primary Positioner Angle is -180 to +180 degrees and the Secondary Positioner Angle range is -90 to + 90 degrees. The Patient Plane is defined by the isocenter of the imaging device and slices through the patient such that it is perpendicular to the sagittal plane of the body. The Primary Axis of rotation is defined at the intersection of the Patient Plane and of the Sagittal Plane. The Positioner Primary Angle is defined in the transaxial plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest and + 90 degrees at the Patient left hand side (LAO) and -90 at the Patient right hand side (RAO). The valid range of Primary Positioner Angle is -180 to +180 degrees. The Secondary Axis is in the Patient Plane and is perpendicular to the Primary Axis at the isocenter. The Positioner Secondary Angle is defined in the Sagittal Plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest. +90 degrees corresponds to the cranial direction. The Secondary Positioner Angle range is -90 to + 90 degrees. At a 0 angle for both the Primary Angle (0018,1510) and Secondary Angle (0018,1511), the patient faces the Image Intensifier. The Positioner Primary Angle (0018,1510) and Secondary Angle (0018,1511) apply to the first frame of a multi-frame image. Figure C.8-11 Positioner Primary Angle Figure C.8-12 Positioner Secondary Angle
Position of the X-Ray Image Intensifier about the patient from the CAU to CRA direction where movement from CAU to vertical is positive. See C.8.7.5.1.2
The definitions of Positioner Angles shall be with respect to the patient as illustrated in Figures C.8-11 and C.8-12 Zero degree is referenced to the origin perpendicular to the patient's chest. The Positioner Primary Angle definition is like longitude (in the equatorial plan); the Positioner Secondary Angle definition is like latitude (in the sagittal plane). The Positioner Angle attributes apply to the first frame of a multi-frame image. The valid range of Primary Positioner Angle is -180 to +180 degrees and the Secondary Positioner Angle range is -90 to + 90 degrees. The Patient Plane is defined by the isocenter of the imaging device and slices through the patient such that it is perpendicular to the sagittal plane of the body. The Primary Axis of rotation is defined at the intersection of the Patient Plane and of the Sagittal Plane. The Positioner Primary Angle is defined in the transaxial plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest and + 90 degrees at the Patient left hand side (LAO) and -90 at the Patient right hand side (RAO). The valid range of Primary Positioner Angle is -180 to +180 degrees. The Secondary Axis is in the Patient Plane and is perpendicular to the Primary Axis at the isocenter. The Positioner Secondary Angle is defined in the Sagittal Plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest. +90 degrees corresponds to the cranial direction. The Secondary Positioner Angle range is -90 to + 90 degrees. At a 0 angle for both the Primary Angle (0018,1510) and Secondary Angle (0018,1511), the patient faces the Image Intensifier. The Positioner Primary Angle (0018,1510) and Secondary Angle (0018,1511) apply to the first frame of a multi-frame image. Figure C.8-11 Positioner Primary Angle Figure C.8-12 Positioner Secondary Angle
Incremental change in primary positioner angle for each frame. See C.8.7.5.1.3. Required if Positioner Motion is DYNAMIC.
If the positioner angles change during acquisition of a multi-frame image, the Positioner Angle Increment attributes describe the angular change per frame. If the change in positioner angle is nominally constant for each frame, these fields may contain a single value of the average angular change per frame. Alternatively, the fields may contain a vector of offsets from the (initial) Positioner Angle attributes, with one value for each frame in the multi-frame image. The number of values in the Positioner Angle Increment attributes must be one, or must be equal to the Number of Frames attribute (0028,0008) in the Multi-Frame Module (see Section C.7.6.6). Note: It is permissible to generate a vector of the absolute positioner angles in the Positioner Angle Increment attributes, and set the Positioner Primary and Secondary Angle attributes to value 0.
Incremental change in secondary positioner angle for each frame. See C.8.7.5.1.3. Required if Positioner Motion is DYNAMIC.
If the positioner angles change during acquisition of a multi-frame image, the Positioner Angle Increment attributes describe the angular change per frame. If the change in positioner angle is nominally constant for each frame, these fields may contain a single value of the average angular change per frame. Alternatively, the fields may contain a vector of offsets from the (initial) Positioner Angle attributes, with one value for each frame in the multi-frame image. The number of values in the Positioner Angle Increment attributes must be one, or must be equal to the Number of Frames attribute (0028,0008) in the Multi-Frame Module (see Section C.7.6.6). Note: It is permissible to generate a vector of the absolute positioner angles in the Positioner Angle Increment attributes, and set the Positioner Primary and Secondary Angle attributes to value 0.
Angle of the X-Ray beam in the row direction in degrees relative to the normal to the detector plane. Positive values indicate that the X-Ray beam is tilted towards higher numbered columns. Negative values indicate that the X-Ray beam is tilted towards lower numbered columns. See C.8.7.5.1.4.
Detector Angles are defined in a fashion similar to the positioner angles, except that the angle of the central x-ray beam vector is relative to the detector plane rather than the patient plane. The central x-ray beam vector is defined as the vector from the x-ray source through the isocenter to the detector plane. Zero degree is referenced to the normal to the detector plane pointing away from the x-ray source. The Detector Angle attributes apply to the first frame of a multi-frame image. The valid range of the Detector Angles is -90 to + 90 degrees. The Primary Axis of rotation is defined along the line in the column direction of the detector plane which intersects the central x-ray beam vector. The Detector Primary Angle is defined in the plane perpendicular to the Primary Axis of rotation at the point where the central x-ray beam vector intersects the detector plane, with zero degrees in the direction normal to the detector plane and -90 degrees at the left hand side of the image (i.e., toward column 1) and +90 at the right hand side of the image (i.e., toward the highest numbered column). The valid range of Primary Detector Angle is -90 to +90 degrees. The Secondary Axis is in the detector plane and is perpendicular to the Primary Axis at the intersection of the beam vector with the detector plane (i.e., it is along the row direction). The Detector Secondary Angle is defined in the plane perpendicular to the Secondary Axis at the point where the central x-ray beam vector intersects the detector plane, with zero degrees in the direction normal to the detector plane. +90 degrees corresponds to the direction toward the top of the image. The Secondary Detector Angle range is -90 to + 90 degrees.
Angle of the X-Ray beam in the column direction in degrees relative to the normal to the detector plane. Positive values indicate that the X-Ray beam is tilted towards lower numbered rows. Negative values indicate that the X-Ray beam is tilted towards higher numbered rows. See C.8.7.5.1.4.
Detector Angles are defined in a fashion similar to the positioner angles, except that the angle of the central x-ray beam vector is relative to the detector plane rather than the patient plane. The central x-ray beam vector is defined as the vector from the x-ray source through the isocenter to the detector plane. Zero degree is referenced to the normal to the detector plane pointing away from the x-ray source. The Detector Angle attributes apply to the first frame of a multi-frame image. The valid range of the Detector Angles is -90 to + 90 degrees. The Primary Axis of rotation is defined along the line in the column direction of the detector plane which intersects the central x-ray beam vector. The Detector Primary Angle is defined in the plane perpendicular to the Primary Axis of rotation at the point where the central x-ray beam vector intersects the detector plane, with zero degrees in the direction normal to the detector plane and -90 degrees at the left hand side of the image (i.e., toward column 1) and +90 at the right hand side of the image (i.e., toward the highest numbered column). The valid range of Primary Detector Angle is -90 to +90 degrees. The Secondary Axis is in the detector plane and is perpendicular to the Primary Axis at the intersection of the beam vector with the detector plane (i.e., it is along the row direction). The Detector Secondary Angle is defined in the plane perpendicular to the Secondary Axis at the point where the central x-ray beam vector intersects the detector plane, with zero degrees in the direction normal to the detector plane. +90 degrees corresponds to the direction toward the top of the image. The Secondary Detector Angle range is -90 to + 90 degrees.
Distance in mm from source to detector center. Note: This value is traditionally referred to as Source Image Receptor Distance (SID). Distance in mm from source to isocenter (center of field of view). Note: This value is traditionally referred to as Source Object Distance (SOD). Ratio of SID (Source Image Receptor Distance) over SOD (Source Object Distance). Angle of the X-Ray beam in degree relative to an orthogonal axis to the detector plane. Positive values indicate that the tilt is towards the head of the table. Note: The detector plane is assumed to be parallel to the table plane. Distance in mm between the table surface and the sharp image plane. Angle span in degrees of rotation of X-Ray Source during X-Ray acquisition. Time in seconds the source has taken to rotate the Tomo Angle during X-Ray acquisition. Type of tomography. Defined Terms: LINEAR SPIRAL POLYCYCLOIDAL CIRCULAR Form of tomography: Defined Terms: MOTION TOMOSYNTHESIS The number of source images used to construct this tomosynthetic image. Only meaningful if Tomo Class (0018,1491) is TOMOSYNTHESIS. These may be listed in Source Image Sequence (0008,2112) of the General Image Module. Peak kilo voltage output of the X-Ray generator used. X-Ray Tube Current in mA. X-Ray Tube Current in µA. Duration of X-Ray exposure in msec. Duration of X-Ray exposure in µsec. The exposure expressed in mAs, for example calculated from Exposure Time and X-Ray Tube Current. The exposure expressed in µAs, for example calculated from Exposure Time and X-Ray Tube Current. Distance in mm from source to detector center. Note: This value is traditionally referred to as Source Image Receptor Distance (SID). Distance in mm from source to the table, support or bucky side that is closest to the Imaging Subject, as measured along the central ray of the X-Ray beam. Note: 1. This definition is less useful in terms of estimating geometric magnification than a measurement to a defined point within the Imaging Subject, but accounts for what is realistically measurable in an automated fashion in a clinical setting. 2. This measurement does not take into account any air gap between the Imaging Subject and the "front" of the table or bucky. 3. If the detector is not mounted in a table or bucky, then the actual position relative to the patient is implementation or operator defined. 4. This value is traditionally referred to as Source Object Distance (SOD). X-Ray dose, measured in dGy*cm*cm, to which the patient was exposed for the acquisition of this image plus any non-digitally recorded fluoroscopy which may have been performed to prepare for the acquisition of this image. Notes: 1. The sum of the area dose product of all images of a Series or a Study may not result in the total area dose product to which the patient was exposed. 2. This may be an estimated value based on assumptions about the patient's body size and habitus. The average thickness in mm of the body part examined when compressed, if compression has been applied during exposure. Indication of the applied dose, in manufacturer specific units. Notes: 1. This value is intended to provide a single location where manufacturer specific information can be found for annotation on a display or film, that has meaning to a knowledgeable observer. 2. This may be a calculated or measured value. Examples are the detector entrance dose (KB), the CR sensitivity value (S), or the logarithmic median (lgM). Average entrance dose value measured in dGy at the surface of the patient during the acquisition of this image. Note: This may be an estimated value based on assumptions about the patient's body size and habitus. Average entrance dose value measured in mGy at the surface of the patient during the acquisition of this image. Note: This may be an estimated value based on assumptions about the patient's body size and habitus. Typical dimension of the exposed area at the detector plane. If Rectangular: row dimension followed by column; if Round: diameter. Measured in cm. Notes: 1. The exposed area should be consistent with values specified in the X-Ray Collimator Module, if present. 2. This may be an estimated value based on assumptions about the patient's body size and habitus. 3. This attribute is used in the Radiation Dose Module with units in mm (see Section C.4.16 Table C.4-16). Distance in mm from the source to the surface of the patient closest to the source during the acquisition of this image. Note: This may be an estimated value based on assumptions about the patient's body size and habitus. User-defined comments on any special conditions related to radiation dose encountered during the acquisition of this image. The X-Ray output at the patient entrance surface and kVp used to acquire the image, measured in mGy/mAs. Note: This value may be a calibrated value rather than measured during the exposure. The thickness of Aluminum in mm required to reduce the X-Ray Output (0040,0312) by a factor of two. Note: This value may be a calibrated value rather than measured during the exposure. Average organ dose value measured in dGy during the acquisition of this image. Note: This may be an estimated value. Organ to which Organ Dose (0040,0316) applies. Defined Terms: BREAST GONADS BONE MARROW FETUS LENS Note: The anatomic regions described by these terms are those that are particularly radiosensitive and for which it is conventional to obtain organ specific dose parameters. The primary material in the anode of the X-Ray source. Defined Terms: TUNGSTEN MOLYBDENUM RHODIUM The X-Ray absorbing material used in the filter. May be multi-valued. Defined Terms: MOLYBDENUM ALUMINUM COPPER RHODIUM NIOBIUM EUROPIUM LEAD The minimum thickness in mm of the X-Ray absorbing material used in the filters. May be multi-valued, with values corresponding to the respective values in Filter Material (0018,7050). The maximum thickness in mm of the X-Ray absorbing material used in the filters. May be multi-valued, with values corresponding to the respective values in Filter Material (0018,7050). Type of rectification used in the X-Ray generator. Defined Terms: SINGLE PHASE THREE PHASE CONST POTENTIAL Peak kilo voltage output of the X-Ray generator used. X-Ray Tube Current in mA. X-Ray Tube Current in µA. Duration of X-Ray exposure in msec. Duration of X-Ray exposure in µsec. The exposure expressed in mAs, for example calculated from Exposure Time and X-Ray Tube Current. The exposure expressed in µAs, for example calculated from Exposure Time and X-Ray Tube Current. Type of exposure control. Defined Terms: MANUAL AUTOMATIC Text description of the mechanism of exposure control. May describe the number and type of exposure sensors or position of the sensitive area of the imaging detector. Whether the exposure was normally completed or not. Defined Terms: NORMAL ABORTED Nominal percentage phototimer setting, where a more positive value indicates greater exposure and a more negative value indicates less exposure. Nominal focal spot size in mm used to acquire this image. The primary material in the anode of the X-Ray source. Defined Terms: TUNGSTEN MOLYBDENUM RHODIUM Type of rectification used in the X-Ray generator. Defined Terms: SINGLE PHASE THREE PHASE CONST POTENTIAL Identifier of the generator Type of filter(s) inserted into the X-Ray beam (e.g. wedges). Defined Terms: STRIP WEDGE BUTTERFLY MULTIPLE NONE The X-Ray absorbing material used in the filter. May be multi-valued. Defined Terms: MOLYBDENUM ALUMINUM COPPER RHODIUM NIOBIUM EUROPIUM LEAD The minimum thickness in mm of the X-Ray absorbing material used in the filters. May be multi-valued, with values corresponding to the respective values in Filter Material (0018,7050). The maximum thickness in mm of the X-Ray absorbing material used in the filters. May be multi-valued, with values corresponding to the respective values in Filter Material (0018,7050). Identifies the grid. May be multi-valued. Defined Terms are: FIXED FOCUSED RECIPROCATING PARALLEL CROSSED NONE The X-Ray absorbing material used in the grid. The spacing material used in the grid. The thickness in mm of the X-Ray absorbing material used in the grid. The pitch in mm of the X-Ray absorbing material used in the grid. Ratio of the vertical spacing and horizontal spacing of the X-Ray absorbing material used in the grid. Specified by a pair of integer values where the first value is the vertical size, and the second value is the horizontal size. Period in mSec of reciprocation cycle. Only meaningful if Grid (0018,1166) is RECIPROCATING. Focal distance in mm of a FOCUSED grid. Identifier of the grid Type of equipment that originally acquired the data. Enumerated Values: RTIMAGE = RT Image RTDOSE = RT Dose RTSTRUCT = RT Structure Set RTPLAN = RT Plan RTRECORD = RT Treatment Record See C.8.8.1.1.
The Enumerated Value for Modality (0008,0060) shall determined by the IOD: RTIMAGE if RT Image IOD, RTDOSE if RT Dose IOD, RTSTRUCT if RT Structure Set IOD, RTPLAN if RT Plan IOD or RT Ion Plan IOD, RTRECORD if RT Beams Treatment Record IOD, RT Ion Beams Treatment Record IOD, RT Brachy Treatment Record IOD, or RT Treatment Summary Record IOD. Note: DICOM specifies that a given series shall contain objects of only one Modality, and shall be created by a single device (described in the General Equipment Module). However, in general there may be many series defined for a given modality/device pair. Note that a radiotherapy series is generally created over an extended time interval (unlike in radiology, where all images in an image series are generally created together).
Unique identifier of the series. A number that identifies this series. User provided description of the series. Uniquely identifies the Performed Procedure Step SOP Instance to which the Series is related (e.g. a Modality or General-Purpose Performed Procedure Step SOP Instance). One or more items may be included in this sequence. Sequence that contains attributes from the Imaging Service Request. The sequence may have one or more Items.
Number of samples (planes) in this image. See C.8.8.2.6.1 for specialization.
For RT Images, Samples per Pixel (0028,0002) shall have the Enumerated Value of 0001H.
Specifies the intended interpretation of the pixel data. See C.8.8.2.6.2 for specialization.
For RT Images, Photometric Interpretation (0028,0004) shall have the Enumerated Value of MONOCHROME2.
Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated. See C.8.8.2.6.3 for specialization.
For RT Images, Bits Allocated (0028,0100) shall have an Enumerated Value of 8 or 16.
Number of bits stored for each pixel sample. Each sample shall have the same number of bits stored. See C.8.8.2.6.4 for specialization.
For RT Images, Bits Stored (0028,0101) shall have an Enumerated Value of: 8 when Bits Allocated (0028,0100) is 8 12-16 when Bits Allocated (0028,0100) is 16
Most significant bit for each pixel sample. Each sample shall have the same high bit. See C.8.8.2.6.5 for specialization.
For RT Images, High Bit (0028,0102) shall have the Enumerated Value of one less than the value sent in Bits Stored (0028,0101).
Data representation of the pixel samples. Each sample shall have the same pixel representation. See C.8.8.2.6.6 for specialization.
For RT Images, Pixel Representation (0028,0103) shall have the Enumerated Value of 0000H (unsigned integer).
The relationship between the Pixel sample values and the X-Ray beam intensity. Enumerated Values: LIN = Linearly proportional to X-Ray beam intensity LOG = Logarithmically proportional to X-Ray beam intensity See C.8.11.3.1.2 for further explanation.
Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041) describe how the stored pixel values in Pixel Data (7FE0,0010) are related to the X-Ray beam intensity incident on the detector. They do not define a transformation intended to be applied to the pixel data for presentation. Note: For example, if Pixel Intensity Relationship (0028,1040) is LIN and Pixel Intensity Relationship Sign (0028,1041) is -1, then lower values of Pixel Data (7FE0,0010) indicate higher X-Ray beam intensities corresponding to less radiographically dense regions projected on the image such as through air, and higher values of Pixel Data (7FE0,0010) indicate lower X-Ray beam intensities corresponding to more radiographically dense regions projected on the image such as through bone and radio-opaque contrast agents. The transformation to be applied to the pixel data for presentation is defined by the successive application of the conceptual Modality LUT, the VOI Attributes and the conceptual Presentation LUT. This shall result in the output of P-Values. Rescale Slope (0028,1053) and Rescale Intercept (0028,1052) define a linear subset of a conceptual Modality LUT transformation. For IODs that include this Module, these Attributes define an identity transformation. IODs that include the DX Image Module shall not include the Modality LUT Module. The Presentation LUT Shape (2050,0020) defines a subset of a conceptual Presentation LUT. For IODs that include this Module, this Attribute defines an identity transformation or inverse identity transformation. IODs that include the DX Image Module shall not include the Presentation LUT Module. Photometric Interpretation (0028,0004) indicates whether lower values that are the output of the VOI Attributes should be displayed as darker or lighter. Since the output of the equivalent of a conceptual Presentation LUT is in P-Values, which are defined in PS 3.14 such that lower values correspond to lower luminance levels, then the definition of the Presentation LUT Shape (2050,0020), otherwise intended to be an identity transformation, must take into account the effect of the value specified for Photometric Interpretation (0028,0004). Note: Regardless of the values of Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041), the grayscale transformations to be applied to the Pixel Data (7FE0,0010) are defined by the equivalent of the Modality LUT (Rescale Slope (0028,1053) and Rescale Intercept (0028,1052)), Value of Interest Attributes, Photometric Interpretation (0028,0004) and the equivalent of the Presentation LUT (Presentation LUT Shape (2050,0020)). However, the combination of the grayscale transformations and the description of the pixel intensity relationship, together define whether, for example, air is expected to be displayed as black or white.
The sign of the relationship between the Pixel sample values stored in Pixel Data (7FE0,0010) and the X-Ray beam intensity. Required if Pixel Intensity Relationship (0028,1040) is present. Enumerated Values; 1 = Lower pixel values correspond to less X-Ray beam intensity -1 = Higher pixel values correspond to less X-Ray beam intensity See C.8.11.3.1.2 for further explanation.
Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041) describe how the stored pixel values in Pixel Data (7FE0,0010) are related to the X-Ray beam intensity incident on the detector. They do not define a transformation intended to be applied to the pixel data for presentation. Note: For example, if Pixel Intensity Relationship (0028,1040) is LIN and Pixel Intensity Relationship Sign (0028,1041) is -1, then lower values of Pixel Data (7FE0,0010) indicate higher X-Ray beam intensities corresponding to less radiographically dense regions projected on the image such as through air, and higher values of Pixel Data (7FE0,0010) indicate lower X-Ray beam intensities corresponding to more radiographically dense regions projected on the image such as through bone and radio-opaque contrast agents. The transformation to be applied to the pixel data for presentation is defined by the successive application of the conceptual Modality LUT, the VOI Attributes and the conceptual Presentation LUT. This shall result in the output of P-Values. Rescale Slope (0028,1053) and Rescale Intercept (0028,1052) define a linear subset of a conceptual Modality LUT transformation. For IODs that include this Module, these Attributes define an identity transformation. IODs that include the DX Image Module shall not include the Modality LUT Module. The Presentation LUT Shape (2050,0020) defines a subset of a conceptual Presentation LUT. For IODs that include this Module, this Attribute defines an identity transformation or inverse identity transformation. IODs that include the DX Image Module shall not include the Presentation LUT Module. Photometric Interpretation (0028,0004) indicates whether lower values that are the output of the VOI Attributes should be displayed as darker or lighter. Since the output of the equivalent of a conceptual Presentation LUT is in P-Values, which are defined in PS 3.14 such that lower values correspond to lower luminance levels, then the definition of the Presentation LUT Shape (2050,0020), otherwise intended to be an identity transformation, must take into account the effect of the value specified for Photometric Interpretation (0028,0004). Note: Regardless of the values of Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041), the grayscale transformations to be applied to the Pixel Data (7FE0,0010) are defined by the equivalent of the Modality LUT (Rescale Slope (0028,1053) and Rescale Intercept (0028,1052)), Value of Interest Attributes, Photometric Interpretation (0028,0004) and the equivalent of the Presentation LUT (Presentation LUT Shape (2050,0020)). However, the combination of the grayscale transformations and the description of the pixel intensity relationship, together define whether, for example, air is expected to be displayed as black or white.
User-defined label for RT Image. User-defined name for RT Image. User-defined description of RT Image. Name of operator(s) acquiring or creating RT Image. Image identification characteristics (see Section C.7.6.1.1.2). RT Images shall use one of the following Defined Terms for Value 3: DRR = digitally reconstructed radiograph PORTAL = digital portal image or portal film image SIMULATOR = conventional simulator image RADIOGRAPH = radiographic image BLANK = image pixels set to background value FLUENCE = fluence map Describes the kind of image conversion. Defined Terms: DV = Digitized Video DI = Digital Interface DF = Digitized Film WSD = Workstation Describes the origin of the parameter values reported in the image. Required if Value 3 of Image Type (0008,0008) is SIMULATOR or PORTAL. Enumerated Values: OPERATOR = manually entered by operator PLAN = planned parameter values ACTUAL = electronically recorded Describes whether or not image plane is normal to beam axis. Enumerated Values: NORMAL = image plane normal to beam axis NON_NORMAL = image plane non-normal to beam axis Position in (x,y,z) coordinates of origin of IEC X-RAY IMAGE RECEPTOR System in the IEC GANTRY coordinate system (mm). See Note 2. X-Ray Image Receptor Angle i.e. orientation of IEC X-RAY IMAGE RECEPTOR coordinate system with respect to IEC GANTRY coordinate system (degrees). See C.8.8.2.2.
The X-Ray Image Receptor Angle (3002,000E) specifies the rotation of the image receptor device in the IEC X-RAY IMAGE RECEPTOR PLANE. A positive angle corresponds to a counter-clockwise rotation of the X-Ray Image Receptor as viewed from the radiation source in the IEC GANTRY coordinate system. The normal (non-rotated) value for this parameter is zero degrees.
The direction cosines of the first row and the first column with respect to the IEC X-RAY IMAGE RECEPTOR coordinate system. Required if RT Image Plane (3002,000C) is NON_NORMAL. May be present otherwise. Physical distance (in mm) between the center of each image pixel, specified by a numeric pair - adjacent row spacing (delimiter) adjacent column spacing. See C.8.8.2.3 and 10.7.1.3 for further explanation.
The Image Plane Pixel Spacing (3002,0011) attribute shall always be defined on the image plane, i.e. at the radiation machine source to image plane distance specified by RT Image SID (3002,0026). For images where the source-image distance is undefined or unknown (e.g. DRR images), RT Image SID (3002,0026) shall equal Radiation Machine SAD (3002,0022) and Image Plane Pixel Spacing (3002,0011) shall be defined on this common plane.
The x and y coordinates (in mm) of the upper left hand corner of the image, in the IEC X-RAY IMAGE RECEPTOR coordinate system. This is the center of the first pixel transmitted. See C.8.8.2.7.
When RT Image Plane (3002,000C) is NORMAL and RT Image Orientation (3002,0010) is not provided, the orientation is defined as follows: The image viewing direction goes from the radiation source to the image (i.e. in the sense of a beam’s eye view, or along the negative Zr direction of the IEC X-RAY IMAGE RECEPTOR coordinate system). The direction of rows goes along the positive Xr direction and the direction of the columns goes along the negative Yr direction of the IEC X-RAY IMAGE RECEPTOR coordinate system. Other interpretations shall be documented in an implementation's conformance statement.
User-defined name identifying radiation machine used in acquiring or computing image (i.e. name of conventional simulator, electron accelerator, X-Ray device, or machine modeled when calculating DRR). Measurement unit of machine dosimeter. Enumerated Values: MU = Monitor Unit MINUTE = minute Radiation source to Gantry rotation axis distance of radiation machine used in acquiring or computing image (mm). Source to patient surface distance (in mm) of radiation machine used in acquiring or computing image. Distance from radiation machine source to image plane (in mm) along radiation beam axis. See C.8.8.2.3.
The Image Plane Pixel Spacing (3002,0011) attribute shall always be defined on the image plane, i.e. at the radiation machine source to image plane distance specified by RT Image SID (3002,0026). For images where the source-image distance is undefined or unknown (e.g. DRR images), RT Image SID (3002,0026) shall equal Radiation Machine SAD (3002,0022) and Image Plane Pixel Spacing (3002,0011) shall be defined on this common plane.
Source to reference object distance (in mm), as used for magnification calculation of RADIOGRAPH and SIMULATOR images. Introduces sequence of one Class/Instance pair describing RT Plan associated with image. Only a single item shall be permitted in this sequence. Uniquely identifies the corresponding N-segment treatment beam specified by Beam Number (300A,00C0) within Beam Sequence in RT Beams Module within the RT Plan referenced in Referenced RT Plan Sequence (300C,0002). Identifier of Fraction Group within RT Plan referenced in Referenced RT Plan Sequence (300C,0002). Fraction Number of fraction during which image was acquired, within Fraction Group referenced by Referenced Fraction Group Number (300C,0022) within RT Plan referenced in Referenced RT Plan Sequence (300C,0002). Cumulative Meterset Weight within Beam referenced by Referenced Beam Number (300C,0006) at which image acquisition starts. Cumulative Meterset Weight within Beam referenced by Referenced Beam Number (300C,0006) at which image acquisition ends. Introduces sequence of Exposure parameter sets, corresponding to exposures used in generating the image. One or more items may be included in this sequence. See C.8.8.2.4.
The Exposure Sequence (3002,0030) allows specification of imaging parameters and aperture definitions for single exposure images (single item sequence) or multiple exposures (multiple item sequence). A multiple exposure image can be expressed as a multi-frame image containing either a single frame, or more than one frame. Referenced Frame Number (0008,1160) shall be specified for each Exposure Sequence item for multiple exposure images expressed using more than one frame.
Identifies corresponding image frame in multi-frame image. Required if there is more than one item in Exposure Sequence (3002,0030), and image is a multi-frame image. Peak kilo voltage output (kV) of X-Ray generator used to acquire image. Required if Value 3 of Image Type (0008,0008) is PORTAL, SIMULATOR or RADIOGRAPH. Imaging device X-Ray Tube Current (mA). Required if Value 3 of Image Type (0008,0008) is SIMULATOR or RADIOGRAPH. Time of X-Ray exposure (msec). Required if Value 3 of Image Type (0008,0008) is SIMULATOR or RADIOGRAPH. Treatment machine Meterset duration over which image has been acquired, specified in Monitor units (MU) or minutes as defined by Primary Dosimeter Unit (300A,00B3). Required if Value 3 of Image Type (0008,0008) is PORTAL. Positions of diaphragm jaw pairs (in mm) in IEC BEAM LIMITING DEVICE coordinate axis in the IEC order X1, X2, Y1, Y2. Introduces sequence of beam limiting device (collimator) jaw or leaf (element) positions for given exposure. One or more items may be included in this sequence. Type of beam limiting device (collimator). Enumerated Values: X = symmetric jaw pair in IEC X direction Y = symmetric jaw pair in IEC Y direction ASYMX = asymmetric jaw pair in IEC X direction ASYMY = asymmetric pair in IEC Y direction MLCX = multileaf (multi-element) jaw pair in IEC X direction MLCY = multileaf (multi-element) jaw pair in IEC Y direction Radiation source to beam limiting device (collimator) distance (mm). Number of leaf (element) or jaw pairs (equal to 1 for standard beam limiting device jaws). Boundaries (in mm) of beam limiting device (collimator) leaves (elements) in IEC BEAM LIMITING DEVICE coordinate axis appropriate to RT Beam Limiting Device Type (300A,00B8), i.e. X-axis for MLCY, Y-axis for MLCX. Contains N+1 values, where N is the Number of Leaf/Jaw Pairs (300A,00BC), starting from Leaf (Element) Pair 1. Required if RT Beam Limiting Device Type (300A,00B8) is MLCX or MLCY. Positions of beam limiting device (collimator) leaf or jaw (element) pairs (in mm) in IEC BEAM LIMITING DEVICE coordinate axis appropriate to RT Beam Limiting Device Type (300A,00B8), e.g. X-axis for MLCX, Y-axis for MLCY). Contains 2N values, where N is the Number of Leaf/Jaw Pairs (300A,00BC), in IEC leaf (element) subscript order 101, 102, ... 1N, 201, 202, ... 2N. Introduces sequence of Applicators associated with Beam. Only a single item shall be permitted in this sequence. User or machine supplied identifier for Applicator. Type of Applicator. Defined Terms: ELECTRON_SQUARE = square electron applicator ELECTRON_RECT = rectangular electron applicator ELECTRON_CIRC = circular electron applicator ELECTRON_SHORT = short electron applicator ELECTRON_OPEN = open (dummy) electron applicator INTRAOPERATIVE = intraoperative (custom) applicator STEREOTACTIC = stereotactic applicator User-defined description for Applicator. Number of shielding blocks associated with Beam. Introduces sequence of blocks associated with Beam. Required if Number of Blocks (300A,00F0) is non-zero. Zero or more items may be included in this sequence. User-supplied identifier for block tray. Radiation Source to attachment edge of block tray assembly (mm). Type of block. Enumerated Values: SHIELDING = blocking material is inside contour APERTURE = blocking material is outside contour Indicates presence or otherwise of geometrical divergence Enumerated Values: PRESENT = block edges are shaped for beam divergence ABSENT = block edges are not shaped for beam divergence Indicates on which side of the Block Tray the block is mounted. Enumerated Values: PATIENT_SIDE = the block is mounted on the side of the Block Tray which is towards the patient. SOURCE_SIDE = the block is mounted on the side of the Block Tray which is towards the radiation source. Identification Number of the Block. The value of Block Number (300A,00FC) shall be unique within the Beam in which it is created. User-defined name for block. User-supplied identifier for material used to manufacture Block. Physical thickness of block (in mm) parallel to radiation beam axis. Number of (x,y) pairs defining the block edge. A data stream of (x,y) pairs which comprise the block edge. The number of pairs shall be equal to Block Number of Points (300A,0104), and the vertices shall be interpreted as a closed polygon. Coordinates are projected onto the machine isocentric plane in the IEC BEAM LIMITING DEVICE coordinate system (mm). A Sequence of data describing the fluence map attributes for a radiotherapy beam. Only one item may be included in this sequence. Required if the third value of Image Type (0008,0008) is FLUENCE. Source of fluence data. Enumerated Values: CALCULATED = Calculated by a workstation MEASURED=Measured by exposure to a film or detector. The meterset corresponding with a fluence map cell value of 1.0 expressed in units specified by Primary Dosimeter Units (300A,00B3). This is the meterset value used for treatment, not the meterset used to expose the film as defined by Meterset Exposure (3002,0032). Treatment machine gantry angle, i.e. orientation of IEC GANTRY coordinate system with respect to IEC FIXED REFERENCE coordinate system (degrees). Gantry Pitch Angle. i.e. the rotation of the IEC GANTRY coordinate system about the X-axis of the IEC GANTRY coordinate system (degrees). See C.8.8.25.6.5.
The Gantry Pitch angle is not defined in IEC 61217. This angle is defined in the DICOM standard in a way compatible with the current notion of IEC by introducing it as rotation of the IEC GANTRY System as indicated below. The Gantry Pitch Angle is defined as the rotation of the coordinate axes Yg, Zg about axis Xg by an angle g; see Figure C.8.8.25-7. An increase in the value of angle g corresponds to the clockwise rotation as viewed from the isocenter along the positive Xg axis Figure C.8.8.25-7 Gantry Pitch Angle
Treatment machine beam limiting device (collimator) angle, i.e. orientation of IEC BEAM LIMITING DEVICE coordinate system with respect to IEC GANTRY coordinate system (degrees). Patient Support angle, i.e. orientation of IEC PATIENT SUPPORT coordinate system with respect to IEC FIXED REFERENCE coordinate system (degrees). Distance (positive) from the IEC PATIENT SUPPORT vertical axis to the IEC TABLE TOP ECCENTRIC vertical axis (mm). Table Top (non-isocentric) angle, i.e. orientation of IEC TABLE TOP ECCENTRIC coordinate system with respect to IEC PATIENT SUPPORT system (degrees). Table Top Pitch Angle, i.e. the rotation of the IEC TABLE TOP coordinate system about the X-axis of the IEC TABLE TOP coordinate system (degrees). See C.8.8.25.6.2.
Pitch and Roll Coordinate Systems of the Table Top are not defined in IEC 61217. These angles are defined in the DICOM standard in a way compatible with the current notion of IEC by introducing them as rotations of the IEC Table Top System as indicated below. The Table Top Pitch Angle is defined as the rotation of the coordinate axes Yt, Zt about axis Xt by an angle t; see Figure C.8.8.25-3. An increase in the value of angle t corresponds to the clockwise rotation of the Table Top as viewed from the Table Top coordinate system origin along the positive Xt axis. The Table Top Roll Angle is defined as the rotation of the coordinate axes Xt, Zt about axis Yt by an angle t; see Figure C.8.8.25-4. An increase in the value of angle t corresponds to the clockwise rotation of the Table Top as viewed from the Table Top coordinate system origin along the positive Yt axis. Figure C.8.8.25-3 Table Top Pitch Angle Figure C.8.8.25-4 Table Top Roll Angle
Table Top Roll Angle, i.e. the rotation of the IEC TABLE TOP coordinate system about the Y-axis of the IEC TABLE TOP coordinate system (degrees). See C.8.8.25.6.2.
Pitch and Roll Coordinate Systems of the Table Top are not defined in IEC 61217. These angles are defined in the DICOM standard in a way compatible with the current notion of IEC by introducing them as rotations of the IEC Table Top System as indicated below. The Table Top Pitch Angle is defined as the rotation of the coordinate axes Yt, Zt about axis Xt by an angle t; see Figure C.8.8.25-3. An increase in the value of angle t corresponds to the clockwise rotation of the Table Top as viewed from the Table Top coordinate system origin along the positive Xt axis. The Table Top Roll Angle is defined as the rotation of the coordinate axes Xt, Zt about axis Yt by an angle t; see Figure C.8.8.25-4. An increase in the value of angle t corresponds to the clockwise rotation of the Table Top as viewed from the Table Top coordinate system origin along the positive Yt axis. Figure C.8.8.25-3 Table Top Pitch Angle Figure C.8.8.25-4 Table Top Roll Angle
Table Top Vertical position in IEC TABLE TOP coordinate system (mm). Table Top Longitudinal position in IEC TABLE TOP coordinate system (mm). Table Top Lateral position in IEC TABLE TOP coordinate system (mm). Isocenter coordinates (x,y,z), in mm. Specifies the location of the machine isocenter in the patient-based coordinate system associated with the Frame of Reference. It allows transformation from the equipment-based IEC coordinate system to the patient-based coordinate system. Patient position descriptor relative to the patient support device. Required if Isocenter Position (300A,012C) is present. May be present otherwise. See Section C.8.8.12.1.2 for Defined Terms and further explanation. Note: The orientation of the patient relative to the patient support device is denoted in the same manner as in the RT Patient Setup module. It defines the relation of the patient-based DICOM coordinate system identified by the frame of reference module of the RT Image to the IEC coordinate system and together with the Isocenter Position (300A,012C) allows the RT Image to be placed into the patient frame of reference. It also allows a system using an RT Image to verify that the patient is setup in a similar position relative to the patient support device.
Defined Terms for Patient Position shall be those specified in Section C.7.3.1.1.2, plus the following: SITTING In the sitting position, the patient’s face is towards the front of the chair.
Number of samples (planes) in this image. See C.8.8.3.4.1 for specialization. Required if Pixel Data (7FE0,0010) is present.
For RT Doses, Samples per Pixel (0028,0002) shall have the Enumerated Value of 1.
Specifies the intended interpretation of the pixel data. See C.8.8.3.4.2 for specialization. Required if Pixel Data (7FE0,0010) is present.
For RT Doses, Photometric Interpretation (0028,0004) shall have the Enumerated Value of MONOCHROME2.
Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated. See C.8.8.3.4.3 for specialization. Required Pixel Data (7FE0,0010) is present.
For RT Doses, Bits Allocated (0028,0100) shall have an Enumerated Value of 16 or 32.
Number of bits stored for each pixel sample. Each sample shall have the same number of bits stored. See C.8.8.3.4.4 for specialization. Required if Pixel Data (7FE0,0010) is present.
For RT Doses, Bits Stored (0028,0101) shall have an Enumerated Value equal to Bits Allocated (0028,0100).
Most significant bit for each pixel sample. Each sample shall have the same high bit. See C.8.8.3.4.5 for specialization. Required if Pixel Data (7FE0,0010) is present.
For RT Doses, High Bit (0028,0102) shall have the Enumerated Value of one less than the value sent in Bits Stored (0028,0101).
Data representation of the pixel samples. Each sample shall have the same pixel representation. See C.8.8.3.4.6 for specialization. Required Pixel Data (7FE0,0010) is present.
For RT Doses, Pixel Representation (0028,0103) is specified to use the following Enumerated Values: 0001H = two’s complement integer, when Dose Type (3004,0004) = ERROR 0000H = unsigned integer, otherwise.
Units used to describe dose. Enumerated Values: GY = Gray RELATIVE = dose relative to implicit reference value Type of dose. Defined Terms: PHYSICAL = physical dose EFFECTIVE = physical dose after correction for biological effect using user-defined modeling technique ERROR = difference between desired and planned dose A number that identifies this object instance. User-defined comments for dose data. Coordinates (x, y, z) of normalization point in the patient based coordinate system described in C.7.6.2.1.1 (mm). See C.8.8.3.1.
The Normalization Point (3004,0008) aids in the interpretation and subsequent use of the transmitted data. If used, it shall be a point receiving dose contributions from all referenced components of the dose summation.
Type of dose summation. Defined Terms: PLAN = dose calculated for entire RT Plan FRACTION = dose calculated for a single Fraction Group within RT Plan BEAM = dose calculated for one or more Beams within RT Plan BRACHY = dose calculated for one or more Brachy Application Setups within RT Plan CONTROL_POINT = dose calculated for one or more Control Points within a Beam Introduces sequence of one Class/Instance pair describing RT Plan associated with dose. Required if Dose Summation Type (3004,000A) is PLAN, FRACTION, BEAM, BRACHY or CONTROL_POINT. Only a single item shall be permitted in this sequence. See Note 1. Introduces sequence of one Fraction Group containing beams or brachy application setups contributing to dose. Required if Dose Summation Type (3004,000A) is FRACTION, BEAM, BRACHY or CONTROL_POINT. Only a single item shall be permitted in this sequence. See Note 1. Uniquely identifies Fraction Group specified by Fraction Group Number (300A,0071) in Fraction Group Sequence of RT Fraction Scheme Module within RT Plan referenced in Referenced RT Plan Sequence (300C,0002). Introduces sequence of Beams in current Fraction Group contributing to dose. Required if Dose Summation Type (3004,000A) is BEAM or CONTROL_POINT. One or more items may be included in this sequence. Uniquely identifies Beam specified by Beam Number (300A,00C0) in Beam Sequence of RT Beams Module within RT Plan referenced in Referenced RT Plan Sequence (300C,0002). Sequence defining the Control Points in current Beam contributing to dose. Required if Dose Summation Type (3004,000A) is CONTROL_POINT. Only a single item shall be present in this sequence. Identifies Control Point specified by Control Point Index (300A,0112) within Beam referenced by Referenced Beam Number (300C,0006). This is the first of the two Control Points from which the Dose contribution to the Control Point can be calculated. Identifies Control Point specified by Control Point Index (300A,0112) within Beam referenced by Referenced Beam Number (300C,0006). This is the second of the two Control Points from which the Dose contribution to the Control Point can be calculated. The Control Point Index (300A,0112) referenced by Referenced Stop Control Point Index (300C,00F6) shall be the Control Point Index (300A,0112) immediately following the Control Point Index (300A,0112) referenced by Referenced Start Control Point Index (300C,00F4) within the Referenced Beam Number (300C,0006). Introduces sequence of Brachy Application Setups in current Fraction Group contributing to dose. Required if Dose Summation Type (3004,000A) is BRACHY. One or more items may be included in this sequence. Uniquely identifies Brachy Application Setup specified by Brachy Application Setup Number (300A,0234) in Brachy Application Setup Sequence (300A,0230) of RT Brachy Application Setups Module within RT Plan referenced in Referenced RT Plan Sequence (300C,0002). An array which contains the dose image plane offsets (in mm) of the dose image frames in a multi-frame dose. Required if multi-frame pixel data are present and Frame Increment Pointer (0028,0009) points to Grid Frame Offset Vector (3004,000C). See C.8.8.3.2.
Grid Frame Offset Vector (3004,000C) shall be provided if a dose distribution is sent as a multi-frame image. Values of the Grid Frame Offset Vector (3004,000C) shall vary monotonically and are to be interpreted as follows: a. If Grid Frame Offset Vector (3004,000C) is present and its first element is zero, this attribute contains an array of n elements indicating the plane location of the data in the right-handed image coordinate system, relative to the position of the first dose plane transmitted, i.e., the point at which the Image Position (Patient) (0020,0032) attribute is defined, with positive offsets in the direction of the cross product of the row and column directions. b. If Grid Frame Offset Vector (3004,000C) is present, its first element is equal to the third element of Image Position (Patient) (0020,0032), and Image Orientation (Patient) (0020,0037) has the value (1,0,0,0,1,0), then Grid Frame Offset Vector contains an array of n elements indicating the plane location (patient z coordinate) of the data in the patient coordinate system. In future implementations, use of option a) is strongly recommended. This attribute is conditional since the RT Dose module may be included even if pixel doses are not being transmitted, or the image may be a single-frame image. If the Multi-frame Module is present, Frame Increment Pointer (0028,0009) shall have the Enumerated Value of 3004000C (Grid Frame Offset Vector). Note: Option (a) can represent a rectangular-parallelepiped dose grid with any orientation with respect to the patient, while option (b) can only represent a rectangular-parallelepiped dose grid whose planes are in the transverse patient dimension and whose x- and y-axes are parallel to the patient x- and y-axes. Example: Figure C.8.8.3-1 shows an example of plane positions for a dose grid with transverse planes. Figure C.8.8.3-1 Dose Grid Frame Example For this example, Table C.8.39b gives the values of elements in the Grid Frame Offset Vector (3004,000C) for both relative (option (a)) and absolute (option (b)) interpretations, under the following conditions: 1. The value of Image Orientation (Patient) (0020,0037) is (1,0,0,0,1,0). I.e., the dose grid is transverse with x- and y-axes parallel to the patient x- and y-axes; 2. The value of Image Position (Patient) (0020,0032), i.e. the position of the first element of the dose grid, is (4, 5, 6); and 3. The spacing between adjacent dose grid planes is 2mm (uniform). Table C.8-39b. Values of Dose Grid Frame Offset Vector under Relative (a) and Absolute (b) Interpretations
Scaling factor that when multiplied by the dose grid data found in the Pixel Data (7FE0,0010) attribute of the Image Pixel Module, yields grid doses in the dose units as specified by Dose Units (3004,0002). Specifies a list of patient heterogeneity characteristics used for calculating dose. This Atttibute shall be multi-valued if beams used to compute the dose have differing correction techniques. Enumerated Values: IMAGE = image data ROI_OVERRIDE = one or more ROI densities override image or water values where they exist WATER = entire volume treated as water equivalent
Introduces sequence of one class/instance pair describing Structure Set containing structures which are used to calculate Dose-Volume Histograms (DVHs). Only a single item shall be permitted in this sequence. See C.8.8.4.1.
The Referenced Structure Set Sequence (300C,0060) is required for direct cross-reference of the dose bin data with the corresponding ROI(s) from which they were derived. ROIs referenced by the DVH Referenced ROI Sequence (3004,0050) shall only contain contours with a Contour Geometric Type (3006,0042) of POINT or CLOSED_PLANAR.
Coordinates (x, y, z) of common DVH normalization point in the patient based coordinate system described in C.7.6.2.1.1 (mm). Dose Value at DVH Normalization Point (3004,0040) used as reference for individual DVHs when Dose Units (3004,0002) is RELATIVE. Introduces sequence of DVHs. One or more items may be included in this sequence. Introduces sequence of referenced ROIs used to calculate DVH. One or more items may be included in this sequence. Uniquely identifies ROI used to calculate DVH specified by ROI Number (3006,0022) in Structure Set ROI Sequence (3006,0020) in Structure Set Module within RT Structure Set referenced by referenced RT Plan in Referenced RT Plan Sequence (300C,0002) in RT Dose Module. Specifies whether volume within ROI is included or excluded in DVH. See C.8.8.4.2. Enumerated Values: INCLUDED, EXCLUDED.
The volume used to calculate the DVH shall be the geometric union of ROIs where DVH ROI Contribution Type (3004,0062) is INCLUDED, minus the geometric union of ROIs where DVH ROI Contribution Type (3004,0062) is EXCLUDED.
Type of DVH. Enumerated Values: DIFFERENTIAL = differential dose-volume histogram CUMULATIVE = cumulative dose-volume histogram NATURAL = natural dose volume histogram Dose axis units. Enumerated Values: GY = Gray RELATIVE = dose relative to reference value specified in DVH Normalization Dose Value (3004,0042) Type of dose. Defined Terms: PHYSICAL = physical dose EFFECTIVE = physical dose after correction for biological effect using user-defined modeling technique ERROR = difference between desired and planned dose Scaling factor that when multiplied by the dose bin widths found in DVH Data (3004,0058), yields dose bin widths in the dose units as specified by Dose Units (3004,0002). Volume axis units. Defined Terms: CM3 = cubic centimeters PERCENT = percent PER_U= volume per u with u(dose)=dose-3/2. See C.8.8.4.3.
The unit PER_U is defined in: Anderson, LL: “A “natural” volume-dose histogram for brachytherapy”, Medical Physics 13(6) pp 898-903, 1986.
Number of bins n used to store DVH Data (3004,0058). A data stream describing the dose bin widths Dn and associated volumes Vn in DVH Volume Units (3004,0054) in the order D1V1, D2V2, ... DnVn. Note: DVH Data arrays may not be properly encoded if Explicit-VR transfer syntax is used and the VL of this attribute exceeds 65534 bytes. Minimum calculated dose to ROI(s) described by DVH Referenced ROI Sequence (3004,0060). Maximum calculated dose to ROI(s) described by DVH Referenced ROI Sequence (3004,0060). Mean calculated dose to ROI(s) described by DVH Referenced ROI Sequence (3004,0060).
User-defined label for Structure Set. User-defined name for Structure Set. User-defined description for Structure Set. A number that identifies this object instance. Date at which Structure Set was last modified. Time at which Structure Set was last modified. Introduces sequence of items describing Frames of Reference in which the ROIs are defined. One or more items may be included in this sequence. See C.8.8.5.1.
The Referenced Frame of Reference Sequence (3006,0010) describes a set of frames of reference in which some or all of the ROIs are expressed. Since the Referenced Frame of Reference UID (3006,0024) is required for each ROI, each frame of reference used to express the coordinates of an ROI shall be listed in the Referenced Frame of Reference Sequence (3006,0010) once and only once. Notes: 1.As an example, a set of ROIs defined using a single image series would list the image series in a single Referenced Frame of Reference Sequence (3006,0010) item, providing the UID for this referenced frame of reference (obtained from the source images), and listing all pertinent images in the Contour Image Sequence (3006,0016). 2. As an example, a set of ROIs containing ROIs referencing more than one frame of reference would list the referenced images in two or more different Referenced Frame of Reference Sequence (3006,0010) items, providing in each case the UID for this referenced frame of reference (obtained from the source images), and listing all pertinent images in the Contour Image Sequence (3006,0016). Each ROI would then reference the appropriate Frame of Reference UID (0020,0052).
Uniquely identifies Frame of Reference within Structure Set. Introduces sequence of transforms that relate other Frames of Reference to this Frame of Reference. One or more items may be included in this sequence. Frame of Reference Coordinate System to be transformed to the current Frame of Reference. Type of Transformation. Required if Frame of Reference Relationship Sequence (3006,00C0) is sent. Defined Terms: HOMOGENEOUS Four-by-four transformation Matrix from Related Frame of Reference to current Frame of Reference. Matrix elements shall be listed in row-major order. See C.8.8.5.2.
In a rigid body system, two coordinate systems can be related using a single 4 x 4 transformation matrix to describe any rotations and/or translations necessary to transform coordinates from the related coordinate system (frame of reference) to the primary system. The equation performing the transform from a point (X’,Y’,Z’) in the related coordinate system to a point (X,Y,Z) in the current coordinate system can be shown as follows, where for homogeneous transforms M41 = M42 = M43 = 0 and M44 = 1: X M11 M12 M13 M14 X’ Y = M21 M22 M23 M24 x Y’ Z M31 M32 M33 M34 Z’ 1 M41 M42 M43 M44 1
Comment regarding the transformation between the related and current Frames of Reference. Introduces sequence of Studies containing series to be referenced. One or more items may be included in this sequence. Introduces sequence of items describing series of images within the referenced study which are used in defining the Structure Set. One or more items may be included in this sequence. Unique identifier for the series containing the images. Introduces sequence of items describing images in a given series used in defining the Structure Set (typically CT or MR images). One or more items may be included in this sequence. Introduces sequence of ROIs for current Structure Set. One or more items may be included in this sequence. Identification number of the ROI. The value of ROI Number (3006,0022) shall be unique within the Structure Set in which it is created. Uniquely identifies Frame of Reference in which ROI is defined, specified by Frame of Reference UID (0020,0052) in Referenced Frame of Reference Sequence (3006,0010). User-defined name for ROI. User-defined description for ROI. Volume of ROI (cubic centimeters). Type of algorithm used to generate ROI. Defined Terms: AUTOMATIC = calculated ROI SEMIAUTOMATIC = ROI calculated with user assistance MANUAL = user-entered ROI User-defined description of technique used to generate ROI.
Introduces sequence of Contour Sequences defining ROIs. One or more items may be included in this sequence. Uniquely identifies the referenced ROI described in the Structure Set ROI Sequence (3006,0020). RGB triplet color representation for ROI, specified using the range 0-255. Introduces sequence of Contours defining ROI. One or more items may be included in this sequence. Identification number of the contour. The value of Contour Number (3006,0048) shall be unique within the Contour Sequence (3006,0040) in which it is defined. No semantics or ordering shall be inferred from this attribute. List of Contour Number (3006,0048) defining lower-numbered contour(s) to which the current contour is connected. Introduces sequence of images containing the contour. One or more items may be included in this sequence. Geometric type of contour. See C.8.8.6.1. Enumerated Values: POINT = single point OPEN_PLANAR = open contour containing coplanar points OPEN_NONPLANAR = open contour containing non-coplanar points CLOSED_PLANAR = closed contour (polygon) containing coplanar points
A contour can be one of the following geometric types: - A Contour Geometric Type (3006,0042) of POINT indicates that the contour is a single point, defining a specific location of significance. - A Contour Geometric Type (3006,0042) of OPEN_PLANAR indicates that the last vertex shall not be connected to the first point, and that all points in Contour Data (3006,0050) shall be coplanar. - A Contour Geometric Type (3006,0042) of OPEN_NONPLANAR indicates that the last vertex shall not be connected to the first point, and that the points in Contour Data (3006,0050) may be non-coplanar. Contours having a Geometric Type (3006,0042) of OPEN_NONPLANAR can be used to represent objects best described by a single, possibly non-coplanar curve, such as a brachytherapy applicator. - A Contour Geometric Type (3006,0042) of CLOSED_PLANAR indicates that the last point shall be connected to the first point, where the first point is not repeated in the Contour Data (3006,0050). All points in Contour Data (3006,0050) shall be coplanar.
Thickness of slab (in mm) represented by contour, where the Contour Data (3006,0050) defines a plane in the center of the slab, offset by the Contour Offset Vector (3006,0045) if it is present. See C.8.8.6.2.
A set of Contour slabs may define a multi-slab Volume of Interest. Contour Slab Thickness (3006,0044) shall specify the thickness of a slab, the central plane of which shall be defined by the set of points offset from Contour Data (3006,0050) by the value of Contour Offset Vector (3006,0045). One contour slab may contain one to many sets of Contour Data (3006,0050) that may define regions of one complex Volume of Interest. If no valid value of Contour Slab Thickness (3006,0044) is sent, then the offset value shall be (0,0,0) and the original Contour Data (3006,0050) shall define the central plane of the Contour slab.
Vector (x,y,z) in the the patient based coordinate system described in C.7.6.2.1.1 which is normal to plane of Contour Data (3006,0050), describing direction and magnitude of the offset (in mm) of each point of the central plane of a contour slab from the corresponding original point of Contour Data (3006,0050). See C.8.8.6.2.
A set of Contour slabs may define a multi-slab Volume of Interest. Contour Slab Thickness (3006,0044) shall specify the thickness of a slab, the central plane of which shall be defined by the set of points offset from Contour Data (3006,0050) by the value of Contour Offset Vector (3006,0045). One contour slab may contain one to many sets of Contour Data (3006,0050) that may define regions of one complex Volume of Interest. If no valid value of Contour Slab Thickness (3006,0044) is sent, then the offset value shall be (0,0,0) and the original Contour Data (3006,0050) shall define the central plane of the Contour slab.
Number of points (triplets) in Contour Data (3006,0050). Sequence of (x,y,z) triplets defining a contour in the patient based coordinate system described in C.7.6.2.1.1 (mm). See C.8.8.6.1 and C.8.8.6.3. Note: Contour Data may not be properly encoded if Explicit-VR transfer syntax is used and the VL of this attribute exceeds 65534 bytes.
A contour can be one of the following geometric types: - A Contour Geometric Type (3006,0042) of POINT indicates that the contour is a single point, defining a specific location of significance. - A Contour Geometric Type (3006,0042) of OPEN_PLANAR indicates that the last vertex shall not be connected to the first point, and that all points in Contour Data (3006,0050) shall be coplanar. - A Contour Geometric Type (3006,0042) of OPEN_NONPLANAR indicates that the last vertex shall not be connected to the first point, and that the points in Contour Data (3006,0050) may be non-coplanar. Contours having a Geometric Type (3006,0042) of OPEN_NONPLANAR can be used to represent objects best described by a single, possibly non-coplanar curve, such as a brachytherapy applicator. - A Contour Geometric Type (3006,0042) of CLOSED_PLANAR indicates that the last point shall be connected to the first point, where the first point is not repeated in the Contour Data (3006,0050). All points in Contour Data (3006,0050) shall be coplanar.
Introduces sequence of items specifying dose levels for isodose curves or dose points described in the ROI module. One or more items may be included in this sequence. See C.8.8.7.1.
ROIs referenced in the RT Dose ROI Module shall have a Contour Geometric Type (3006,0042) of POINT, OPEN_PLANAR or CLOSED_PLANAR.
Uniquely identifies the referenced ROI within the current RT Dose. See Note 1 and C.8.8.7.2. Units used for ROI Dose. Enumerated Values: GY = Gray RELATIVE = dose relative to implicit reference value Dose value for ROI, in units defined by Dose Units (3004,0002). See C.8.8.7.3.
Dose Value (3004,0012) shall be the dose value corresponding to the referenced isodose curve, named dose point, or unnamed dose point.
Introduces sequence of observations related to ROIs defined in the ROI Module. One or more items may be included in this sequence. Identification number of the Observation. The value of Observation Number (3006,0082) shall be unique within the RT ROI Observations Sequence (3006,0080). Uniquely identifies the referenced ROI described in the Structure Set ROI Sequence (3006,0020). User-defined label for ROI Observation. User-defined description for ROI Observation. Introduces sequence of significantly related ROIs, e.g. CTVs contained within a PTV. One or more items may be included in this sequence. Uniquely identifies the related ROI described in the Structure Set ROI Sequence (3006,0020). Relationship of referenced ROI with respect to referencing ROI. Defined Terms: SAME = ROIs represent the same entity ENCLOSED = referenced ROI completely encloses referencing ROI ENCLOSING = referencing ROI completely encloses referenced ROI Introduces sequence containing Code used to identify ROI. If this sequence is included, only one item shall be present. Baseline Context ID Number = 96. See Section 5.3 for further explanation. Introduces sequence of related ROI Observations. One or more items may be included in this sequence. Uniquely identifies a related ROI Observation. Type of ROI. See C.8.8.8.1. Defined Terms: EXTERNAL = external patient contour PTV = Planning Target Volume (as defined in ICRU50) CTV = Clinical Target Volume (as defined in ICRU50) GTV = Gross Tumor Volume (as defined in ICRU50) TREATED_VOLUME = Treated Volume (as defined in ICRU50) IRRAD_VOLUME = Irradiated Volume (as defined in ICRU50) BOLUS = patient bolus to be used for external beam therapy AVOIDANCE = region in which dose is to be minimized ORGAN = patient organ MARKER = patient marker or marker on a localizer REGISTRATION = registration ROI ISOCENTER = treatment isocenter to be used for external beam therapy CONTRAST_AGENT = volume into which a contrast agent has been injected CAVITY = patient anatomical cavity BRACHY_CHANNEL = brachytherapy channel BRACHY_ACCESSORY = brachytherapy accessory device BRACHY_SRC_APP = brachytherapy source applicator BRACHY_CHNL_SHLD = brachytherapy channel shield SUPPORT = external patient support device FIXATION = external patient fixation or immobilisation device DOSE_REGION = ROI to be used as a dose reference CONTROL = ROI to be used in control of dose optimization and calculation
RT ROI Interpreted Type (3006,00A4) shall describe the class of ROI (e.g. CTV, PTV). Individual instances of each class of structure (e.g. CTV1, CTV2) can be distinguished using ROI Observation Label (3006,0085).
Name of person performing the interpretation. User-supplied identifier for ROI material. Introduces sequence describing physical properties associated with current ROI interpretation. One or more items may be included in this sequence. Physical property specified by ROI Physical Property Value (3006,00B4). Defined Terms: REL_MASS_DENSITY = mass density relative to water REL_ELEC_DENSITY = electron density relative to water EFFECTIVE_Z = effective atomic number EFF_Z_PER_A = ratio of effective atomic number to mass (AMU-1) REL_STOP_RATIO = linear stopping power ratio relative to water ELEM_FRACTION = elemental composition of the material The elemental composition of the ROI and the atomic mass fraction of the elements in the ROI. Required if ROI Physical Property (3006,00B2) equals ELEM_FRACTION. One or more items may be included in this sequence. The atomic number of the element for which the ROI Elemental Composition Sequence (3006,00B6) is sent. The fractional weight of the element for which the ROI Elemental Composition Sequence (3006,00B6) is sent. The sum of all ROI Elemental Composition Atomic Mass Fractions (3006,00B8) sent in the ROI Elemental Composition Sequence (3006,00B6) shall equal 1.0 within acceptable limits of floating point precision. User-assigned value for physical property.
User-defined label for treatment plan. User-defined name for treatment plan. User-defined description of treatment plan. A number that identifies this object instance. Name of operator(s) creating treatment plan. Date treatment plan was last modified. Time treatment plan was last modified. Planned treatment protocols. Intent of this plan. Defined Terms: CURATIVE = curative therapy on patient PALLIATIVE = palliative therapy on patient PROPHYLACTIC = preventative therapy on patient VERIFICATION = verification of patient plan using phantom MACHINE_QA= Quality assurance of the delivery machine (independently of a specific patient) RESEARCH = Research project SERVICE = Machine repair or maintenance operation Planned treatment sites. Describes whether RT Plan is based on patient or treatment device geometry. See C.8.8.9.1. Defined Terms: PATIENT = RT Structure Set exists TREATMENT_DEVICE = RT Structure Set does not exist
An RT Plan Geometry (300A,000C) of PATIENT shall signify that an RT Structure Set has been defined upon which the plan geometry is based, and this RT Structure Set shall be specified in the Referenced Structure Set Sequence (300C,0060). An RT Plan Geometry (300A,000C) of TREATMENT_DEVICE shall indicate that no patient geometry is available, and that the RT Plan is being defined with respect to the IEC FIXED Coordinate System.
Introduces sequence of one Class/Instance pair describing instance of RT Structure Set on which the RT Plan is based. Only a single item shall be permitted in this sequence. Required if RT Plan Geometry (300A,000C) is PATIENT. Introduces sequence of related SOP Class/Instance pairs describing related instances of RT Dose (for grids and named/unnamed point doses). One or more items may be included in this sequence. See Note 1. Introduces sequence of related SOP Class/Instance pairs describing related instances of RT Plan. One or more items may be included in this sequence. Relationship of referenced plan with respect to current plan. Defined Terms: PRIOR = plan delivered prior to current treatment ALTERNATIVE = alternative plan prepared for current treatment PREDECESSOR = plan used in derivation of current plan VERIFIED_PLAN = plan which is verified using the current plan. This value shall only be used if Plan Intent (300A,000A) is present and has a value of VERIFICATION.
User-defined description of treatment prescription. Introduces sequence of Dose References. One or more items may be included in this sequence. Identification number of the Dose Reference. The value of Dose Reference Number (300A,0012) shall be unique within the RT Plan in which it is created. A unique identifier for a Dose Reference that can be used to link the same entity across multiple RT Plan objects. Structure type of Dose Reference. Defined Terms: POINT = dose reference point specified as ROI VOLUME = dose reference volume specified as ROI COORDINATES = point specified by Dose Reference Point Coordinates (300A,0018) SITE = dose reference clinical site User-defined description of Dose Reference. Uniquely identifies ROI representing the dose reference specified by ROI Number (3006,0022) in Structure Set ROI Sequence (3006,0020) in Structure Set Module within RT Structure Set in Referenced Structure Set Sequence (300C,0060) in RT General Plan Module. Required if Dose Reference Structure Type (300A,0014) is POINT or VOLUME. Coordinates (x,y,z) of Reference Point in the patient based coordinate system described in C.7.6.2.1.1 (mm). Required if Dose Reference Structure Type (300A,0014) is COORDINATES. Dose (in Gy) from prior treatment to this Dose Reference (e.g. from a previous course of treatment). Type of Dose Reference. Defined Terms: TARGET = treatment target (corresponding to GTV, PTV, or CTV in ICRU50) ORGAN_AT_RISK = Organ at Risk (as defined in ICRU50) Relative importance of satisfying constraint, where high values represent more important constraints. The dose (in Gy) which when reached or exceeded should cause some action to be taken. The maximum dose (in Gy) which can be delivered to the dose reference. Minimum permitted dose (in Gy) to Dose Reference if Dose Reference Type (300A,0020) is TARGET. Prescribed dose (in Gy) to Dose Reference if Dose Reference Type (300A,0020) is TARGET. Maximum permitted dose (in Gy) to Dose Reference if Dose Reference Type (300A,0020) is TARGET. Maximum permitted fraction (in percent) of Target to receive less than the Target Prescription Dose if Dose Reference Type (300A,0020) is TARGET and Dose Reference Structure Type (300A,0014) is VOLUME. See C.8.8.10.1.
If the Target Underdose Volume Fraction (300A,0028) is not present, it shall be interpreted as zero.
Maximum dose (in Gy) to entire Dose Reference if Dose Reference Type (300A,0020) is ORGAN_AT_RISK and Dose Reference Structure Type (300A,0014) is VOLUME. Maximum permitted dose (in Gy) to any part of Dose Reference if Dose Reference Type (300A,0020) is ORGAN_AT_RISK and Dose Reference Structure Type (300A,0014) is VOLUME. Maximum dose (in Gy) to non-overdosed part of Dose Reference if Dose Reference Type (300A,0020) is ORGAN_AT_RISK and Dose Reference Structure Type (300A,0014) is VOLUME. Maximum permitted fraction (in percent) of the Organ at Risk to receive more than the Organ at Risk Maximum Dose if Dose Reference Type (300A,0020) is ORGAN_AT_RISK and Dose Reference Structure Type (300A,0014) is VOLUME.
Introduces sequence of tolerance tables to be used for delivery of treatment plan. One or more items may be included in this sequence. See Note 1. Identification number of the Tolerance Table. The value of Tolerance Table Number (300A,0042) shall be unique within the RT Plan in which it is created. Required if Tolerance Table Sequence (300A,0040) is sent. User-defined label for Tolerance Table. Maximum permitted difference (in degrees) between planned and delivered Gantry Angle. Maximum permitted difference (in degrees) between planned and delivered Gantry Pitch Angle. Maximum permitted difference (in degrees) between planned and delivered Beam Limiting Device Angle. Introduces sequence of beam limiting device (collimator) tolerances. One or more items may be included in this sequence. Type of beam limiting device (collimator). Required if Beam Limiting Device Tolerance Sequence (300A,0048) is sent. Enumerated Values: X = symmetric jaw pair in IEC X direction Y = symmetric jaw pair in IEC Y direction ASYMX = asymmetric jaw pair in IEC X direction ASYMY = asymmetric pair in IEC Y direction MLCX = multileaf (multi-element) jaw pair in IEC X direction MLCY = multileaf (multi-element) jaw pair in IEC Y direction Maximum permitted difference (in mm) between planned and delivered leaf (element) or jaw positions for current beam limiting device (collimator). Required if Beam Limiting Device Tolerance Sequence (300A,0048) is sent. Maximum permitted difference (in degrees) between planned and delivered Patient Support Angle. Maximum permitted difference (in degrees) between planned and delivered Table Top Eccentric Angle. Maximum permitted difference (in degrees) between the planned and delivered Table Top Pitch Angle. Maximum permitted difference (in degrees) between the planned and delivered Table Top Roll Angle. Maximum permitted difference (in mm) between planned and delivered Table Top Vertical Position. Maximum permitted difference (in mm) between planned and delivered Table Top Longitudinal Position. Maximum permitted difference (in mm) between planned and delivered Table Top Lateral Position. Introduces sequence of patient setup data for current plan. One or more items may be included in this sequence. Identification number of the Patient Setup. The value of Patient Setup Number (300A,0182) shall be unique within the RT Plan in which it is created. The user-defined label for the patient setup. Patient position descriptor relative to the equipment. Required if Patient Additional Position (300A,0184) is not present. See Section C.8.8.12.1.2 for Defined Terms and further explanation.
Defined Terms for Patient Position shall be those specified in Section C.7.3.1.1.2, plus the following: SITTING In the sitting position, the patient’s face is towards the front of the chair.
User-defined additional description of patient position. Required if Patient Position (0018,5100) is not present. Introduces sequence of setup verification images for this patient setup. One or more items may be included in this sequence. See C.8.8.12.1.1
Images with modality SC or VL serve as visible light photos for visual setup control. Images with modality RTIMAGE serve as reference images on plan level. RT Images present in this sequence shall not be referenced in the Referenced Reference Image Sequence (300C,0042) of the RT Beams module.
Comment on the Setup Image. Introduces sequence of Fixation Devices used in Patient Setup. One or more items may be included in this sequence. Type of Fixation Device used during in Patient Setup. Required if Fixation Device Sequence (300A,0190) is sent. Defined Terms: BITEBLOCK HEADFRAME MASK MOLD CAST HEADREST BREAST_BOARD BODY_FRAME VACUUM_MOLD WHOLE_BODY_POD RECTAL_BALLOON User-defined label identifier for Fixation Device. Required if Fixation Device Sequence (300A,0190) is sent. User-defined description of Fixation Device. Position/Notch number of Fixation Device. The Fixation Device Pitch Angle, i.e. orientation of PITCHED FIXATION DEVICE coordinate system with respect to IEC PATIENT SUPPORT coordinate system (degrees). Pitching is the rotation around IEC PATIENT SUPPORT X-axis. The Fixation Device Roll Angle, i.e. orientation of ROLLED FIXATION DEVICE coordinate system with respect to IEC PITCHED FIXATION DEVICE coordinate system (degrees). Rolling is the rotation around IEC PATIENT SUPPORT Y-axis. An identifier for the accessory intended to be read by a device such as a bar-code reader. Introduces sequence of Shielding Devices used in Patient Setup. One or more items may be included in this sequence. Type of Shielding Device used in Patient Setup. Required if Shielding Device Sequence (300A,01A0) is sent. Defined Terms: GUM EYE GONAD User-defined label for Shielding Device. Required if Shielding Device Sequence (300A,01A0) is sent. User-defined description of Shielding Device. Position/Notch number of Shielding Device. An identifier for the accessory intended to be read by a device such as a bar-code reader. Setup Technique used in Patient Setup. Defined Terms: ISOCENTRIC FIXED_SSD TBI BREAST_BRIDGE SKIN_APPOSITION User-defined description of Setup Technique. Introduces sequence of devices used for patient alignment in Patient Setup. One or more items may be included in this sequence. Type of Setup Device used for Patient alignment. Required if Setup Device Sequence (300A,01B4) is sent. Defined Terms: LASER_POINTER DISTANCE_METER TABLE_HEIGHT MECHANICAL_PTR ARC User-defined label for Setup Device used for patient alignment. Required if Setup Device Sequence (300A,01B4) is sent. User-defined description for Setup Device used for patient alignment. Setup Parameter for Setup Device in appropriate IEC 61217 coordinate system. Units shall be mm for distances and degrees for angles. Required if Setup Device Sequence (300A,011B4) is sent. User-defined description of Setup Reference used for patient alignment. Vertical Displacement in IEC TABLE TOP coordinate system (in mm) relative to initial Setup Position, i.e. vertical offset between patient positioning performed using setup and treatment position. Longitudinal Displacement in IEC TABLE TOP coordinate system (in mm) relative to initial Setup Position, i.e. longitudinal offset between patient positioning performed using setup and treatment position. Lateral Displacement in IEC TABLE TOP coordinate system (in mm) relative to initial Setup Position, i.e. lateral offset between patient positioning performed using setup and treatment position. Introduces sequence of Motion Synchronization. One or more items may be included in this sequence. Technique applied to reduce respiratory motion artifacts. Defined Terms: NONE BREATH_HOLD REALTIME = image acquisition shorter than respiratory cycle GATING = Prospective gating TRACKING = prospective through-plane or in-plane motion tracking PHASE_ORDERING = prospective phase ordering PHASE_RESCANNING = prospective techniques, such as real-time averaging, diminishing variance and motion adaptive gating RETROSPECTIVE = retrospective gating CORRECTION = retrospective image correction UNKNOWN = technique not known Signal source from which respiratory motion is derived. Defined Terms: NONE BELT NASAL_PROBE CO2_SENSOR NAVIGATOR = MR navigator and organ edge detection MR_PHASE = phase (of center k-space line) ECG = baseline demodulation of the ECG SPIROMETER = Signal derived from flow sensor EXTERNAL_MARKER = Signal determined from external motion surrogate INTERNAL_MARKER = Signal determined from internal motion surrogate IMAGE = Signal derived from an image UNKNOWN = Signal source not known Description of respiratory motion compensation technique. Identifies the device providing the respiratory signal.
Introduces sequence of Fraction Groups in current Fraction Scheme. One or more items may be included in this sequence. Identification number of the Fraction Group. The value of Fraction Group Number (300A,0071) shall be unique within the RT Plan in which it is created. The user defined description for the fraction group. Introduces sequence of related SOP Class/Instance pairs describing related instances of RT Dose (for grids, isodose curves and named/unnamed point doses). One or more items may be included in this sequence. See Note 1. Introduces sequence of Dose References for the current Fraction Group. One or more items may be included in this sequence. Uniquely identifies Dose Reference specified by Dose Reference Number (300A,0012) within Dose Reference Sequence (300A,0010) in RT Prescription Module. Required if Referenced Dose Reference Sequence (300C,0050) is sent. Relative importance of satisfying constraint, where high values represent more important constraints. The dose (in Gy) which when reached or exceeded should cause some action to be taken. The maximum dose (in Gy) which can be delivered to the dose reference. Minimum permitted dose (in Gy) to Dose Reference if Dose Reference Type (300A,0020) of referenced Dose Reference is TARGET. Prescribed dose (in Gy) to Dose Reference if Dose Reference Type (300A,0020) of referenced Dose Reference is TARGET. Maximum permitted dose (in Gy) to Dose Reference if Dose Reference Type (300A,0020) of referenced Dose Reference is TARGET. Maximum permitted fraction (in percent) of Target to receive less than the Target Prescription Dose (300A,0027) if Dose Reference Type (300A,0020) of referenced Dose Reference is TARGET and Dose Reference Structure Type (300A,0014) of referenced Dose Reference is VOLUME. Maximum dose (in Gy) to entire Dose Reference if Dose Reference Type (300A,0020) of referenced Dose Reference is ORGAN_AT_RISK and Dose Reference Structure Type (300A,0014) of referenced Dose Reference is VOLUME. Maximum permitted dose (in Gy) to any part of Dose Reference if Dose Reference Type (300A,0020) of referenced Dose Reference is ORGAN_AT_RISK and Dose Reference Structure Type (300A,0014) of referenced Dose Reference is VOLUME. Maximum dose (in Gy) to non-overdosed part of Dose Reference if Dose Reference Type (300A,0020) of referenced Dose Reference is ORGAN_AT_RISK and Dose Reference Structure Type (300A,0014) of referenced Dose Reference is VOLUME. Maximum permitted fraction (in percent) of Organ at Risk to receive more than the Organ at Risk Maximum Dose if Dose Reference Type (300A,0020) of referenced Dose Reference is ORGAN_AT_RISK and Dose Reference Structure Type (300A,0014) of referenced Dose Reference is VOLUME. Total number of treatments (Fractions) prescribed for current Fraction Group. Number of digits in Fraction Pattern (300A,007B) used to represent one day. See Note 2. Number of weeks needed to describe treatment pattern. See Note 2. String of 0's (no treatment) and 1's (treatment) describing treatment pattern. Length of string is 7 x Number of Fraction Pattern Digits Per Day x Repeat Fraction Cycle Length. Pattern shall start on a Monday. See Note 2. Number of Beams in current Fraction Group. If Number of Beams is greater then zero, Number of Brachy Application Setups (300A,00A0) shall equal zero. Introduces sequence of treatment beams in current Fraction Group. Required if Number of Beams (300A,0080) is greater than zero. One or more items may be included in this sequence. Uniquely identifies Beam specified by Beam Number (300A,00C0) within Beam Sequence (300A,00B0) in RT Beams Module. Required if Referenced Beam Sequence (300C,0004) is sent. Coordinates (x,y,z) of point at which Beam Dose is specified in the patient based coordinate system described in C.7.6.2.1.1 (mm). See Note 3. Dose (in Gy) at Beam Dose Specification Point (300A,0082) due to current Beam. The depth (in mm) in the patient along a ray from the source to the dose point specified by the Beam Dose Specification Point (300A,0082). The radiological depth in mm (water-equivalent depth, taking tissue heterogeneity into account) in the patient along a ray from the source to the dose point specified by the Beam Dose Specification Point (300A,0082). Source to patient surface distance along a ray from the source to the dose point specified by the Beam Dose Specification Point (300A,0082). Machine setting to be delivered for current Beam, specified in Monitor Units (MU) or minutes as defined by Primary Dosimeter Unit (300A,00B3) (in RT Beams Module) for referenced Beam. See Note 4. Number of Brachy Application Setups in current Fraction Group. If Number of Brachy Application Setups is greater then zero, Number of Beams (300A,0080) shall equal zero. Introduces sequence of treatment Brachy Application Setups in current Fraction Group. Required if Number of Brachy Application Setups (300A,00A0) is greater than zero. One or more items may be included in this sequence. Uniquely identifies Brachy Application Setup specified by Brachy Application Setup Number (300A,0234) within Brachy Application Setup Sequence (300A,0230) in RT Brachy Application Setups Module. Required if Referenced Brachy Application Setup Sequence (300C,000A) is sent. Coordinates (x,y,z) of point in the patient based coordinate system described in C.7.6.2.1.1 at which Brachy Application Setup Dose (300A,00A4) is specified (mm). Dose (in Gy) at Brachy Application Setup Dose Specification Point (300A,00A2) due to current Brachy Application Setup. Introduces sequence of treatment beams for current RT Plan. One or more items may be included in this sequence. Identification number of the Beam. The value of Beam Number (300A,00C0) shall be unique within the RT Plan in which it is created. See Note 1. User-defined name for Beam. See Note 1. User-defined description for Beam. See Note 1. Motion characteristic of Beam. See Note 5. Enumerated Values: STATIC = All Control Point Sequence (300A,0111) attributes remain unchanged between consecutive pairs of control points with changing Cumulative Meterset Weight (300A,0134). DYNAMIC = One or more Control Point Sequence (300A,0111) attributes change between one or more consecutive pairs of control points with changing Cumulative Meterset Weight (300A,0134). Particle type of Beam. Defined Terms: PHOTON ELECTRON NEUTRON PROTON Type of high-dose treatment technique. Defined Terms: NORMAL = Standard treatment TBI = Total Body Irradiation HDR = High Dose Rate Required if treatment technique requires a dose that would normally require overriding of treatment machine safety controls. User-defined name identifying treatment machine to be used for beam delivery. See Note 2. Manufacturer of the equipment to be used for beam delivery. Institution where the equipment is located that is to be used for beam delivery. Mailing address of the institution where the equipment is located that is to be used for beam delivery. Department in the institution where the equipment is located that is to be used for beam delivery. Manufacturer's model name of the equipment that is to be used for beam delivery. Manufacturer's serial number of the equipment that is to be used for beam delivery. Measurement unit of machine dosimeter. See C.8.8.14.1. Enumerated Values: MU = Monitor Unit MINUTE = minute
The Meterset at a given Control Point is equal to the Beam Meterset (300A,0086) specified in the Referenced Beam Sequence (300C,0004) of the RT Fraction Scheme Module, multiplied by the Cumulative Meterset Weight (300A,0134) for the Control Point, divided by the Final Cumulative Meterset Weight (300A,010E). The Meterset is specified in units defined by Primary Dosimeter Unit (300A,00B3). If the calculation for Meterset results in a meterset value which is not an exact multiple of the primary meterset resolution, then the result shall be rounded to the nearest allowed meterset value (i.e. less than a half resolution unit shall be rounded down to the nearest resolution unit, and equal or greater than half a resolution unit shall be rounded up to the nearest resolution unit). Note also that if Final Cumulative Meterset Weight (300A,010E) is equal to 100, then Cumulative Meterset Weight (300A,0134) becomes equivalent to the percentage of Beam Meterset (300A,0086) delivered at each control point. If Final Cumulative Meterset Weight (300A,010E) is equal to Beam Meterset (300A,0086), then the Cumulative Meterset Weight (300A,0134) at each control point becomes equal to the cumulative Meterset delivered at that control point.
Uniquely identifies Tolerance Table specified by Tolerance Table Number (300A,0042) within Tolerance Table Sequence in RT Tolerance Tables Module. These tolerances are to be used for verification of treatment machine settings. Radiation source to Gantry rotation axis distance of the equipment that is to be used for beam delivery (mm). Introduces sequence of beam limiting device (collimator) jaw or leaf (element) sets. One or more items may be included in this sequence. Type of beam limiting device (collimator). Enumerated Values: X = symmetric jaw pair in IEC X direction Y = symmetric jaw pair in IEC Y direction ASYMX = asymmetric jaw pair in IEC X direction ASYMY = asymmetric pair in IEC Y direction MLCX = multileaf (multi-element) jaw pair in IEC X direction MLCY = multileaf (multi-element) jaw pair in IEC Y direction Radiation source to beam limiting device (collimator) distance of the equipment that is to be used for beam delivery (mm). Number of leaf (element) or jaw pairs (equal to 1 for standard beam limiting device jaws). Boundaries of beam limiting device (collimator) leaves (in mm) in IEC BEAM LIMITING DEVICE coordinate axis appropriate to RT Beam Limiting Device Type (300A,00B8), i.e. X-axis for MLCY, Y-axis for MLCX. Contains N+1 values, where N is the Number of Leaf/Jaw Pairs (300A,00BC), starting from Leaf (Element) Pair 1. Required if Beam Limiting Device Sequence (300A,00B6) is sent and RT Beam Limiting Device Type (300A,00B8) is MLCX or MLCY. See Note 3. Uniquely identifies Patient Setup to be used for current beam, specified by Patient Setup Number (300A,0182) within Patient Setup Sequence of RT Patient Setup Module. Introduces sequence of reference images used for validation of current beam. One or more items may be included in this sequence. Uniquely identifies Reference Image within Referenced Reference Image Sequence (300A,0042). Required if Referenced Reference Image Sequence (300A,0042) is sent. Cumulative Meterset Weight within current Beam at which image acquisition starts. Cumulative Meterset Weight within current Beam at which image acquisition ends. Introduces sequence of planned verification images to be acquired during current beam. One or more items may be included in this sequence. See C.8.8.14.2.
The Planned Verification Image Sequence (300A,00CA) contains attributes which describe the planned verification images to be acquired during current beam. The Start Cumulative Meterset Weight (300C,0008) specifies the Cumulative Meterset Weight at which image acquisition is to begin. If Meterset Exposure (3002,0032) is present in a sequence item and End Cumulative Meterset Weight (300C,0009) is not present then a single image shall be acquired using the meterset duration specified in Meterset Exposure (3002,0032). If End Cumulative Meterset Weight (300C,0009) is present in a sequence item and Meterset Exposure (3002,0032) is not present then a single image shall be acquired over the beam delivery from Start Cumulative Meterset Weight (300C,0008) to End Cumulative Meterset Weight (300C,0009). If both Meterset Exposure (3002,0032) and End Cumulative Meterset Weight (300C,0009) are present in a sequence item then images shall be acquired every Meterset Exposure (3002,0032) from Start Cumulative Meterset Weight (300C,0008) to End Cumulative Meterset Weight (300C,0009). No images shall extend past End Cumulative Meterset Weight (300C,0009).
Cumulative Meterset Weight within current Beam at which image acquisition will start. Meterset duration over which image is to be acquired, specified in Monitor units (MU) or minutes as defined by Primary Dosimeter Unit (300A,00B3). Cumulative Meterset Weight within current Beam at which image acquisition will end. Describes whether or not image plane is normal to beam axis. Enumerated Values: NORMAL = image plane normal to beam axis NON_NORMAL = image plane non-normal to beam axis X-Ray Image Receptor Angle i.e. orientation of IEC X-RAY IMAGE RECEPTOR coordinate system with respect to IEC GANTRY coordinate system (degrees). See C.8.8.14.3.
The X-Ray Image Receptor Angle (3002,000E) specifies the rotation of the image receptor device in the IEC X-RAY IMAGE RECEPTOR PLANE. A positive angle corresponds to a counter-clockwise rotation of the X-Ray Image Receptor as viewed from the radiation source in the IEC GANTRY coordinate system. The normal (non-rotated) value for this parameter is zero degrees.
The direction cosines of the first row and the first column with respect to the IEC X-RAY IMAGE RECEPTOR coordinate system. The x and y coordinates (in mm) of the upper left hand corner of the image, in the IEC X-RAY IMAGE RECEPTOR coordinate system. This is the center of the first pixel transmitted. Radiation machine source to image plane distance (mm). User-specified device-specific parameters that describe how the imager will acquire the image. Uniquely identifies Reference Image to which planned verification image is related, specified by Reference Image Number (300A,00C8) within Referenced Reference Image Sequence (300A,0042). Delivery Type of treatment. Defined Terms: TREATMENT = normal patient treatment OPEN_PORTFILM = portal image acquisition with open field TRMT_PORTFILM = portal image acquisition with treatment port CONTINUATION = continuation of interrupted treatment SETUP = no treatment beam is applied for this RT Beam. To be used for specifying the gantry, couch, and other machine positions where X-Ray set-up images or measurements are to be taken Introduces sequence of related SOP Class/Instance pairs describing related instances of RT Dose (for grids, isodose curves, and named/unnamed point doses). One or more items may be included in this sequence. Number of wedges associated with current Beam. Introduces sequence of treatment wedges. Required if Number of Wedges (300A,00D0) is non-zero. One or more items may be included in this sequence. Identification number of the Wedge. The value of Wedge Number (300A,00D2) shall be unique within the Beam in which it is created. Required if Wedge Sequence (300A,00D1) is sent. Type of wedge (if any) defined for Beam. Required if Wedge Sequence (300A,00D1) is sent. Defined Terms: STANDARD = standard (static) wedge DYNAMIC = moving beam limiting device (collimator) jaw simulating wedge MOTORIZED = single wedge which can be removed from beam remotely User-supplied identifier for Wedge. An identifier for the accessory intended to be read by a device such as a bar-code reader. Nominal wedge angle (degrees). Required if Wedge Sequence (300A,00D1) is sent. Nominal wedge factor under machine calibration conditions at the beam energy specified by the Nominal Beam Energy (300A,0114) of the first Control Point of the Control Point Sequence (300A,0111). Required if Wedge Sequence (300A,00D1) is sent. Orientation of wedge, i.e. orientation of IEC WEDGE FILTER coordinate system with respect to IEC BEAM LIMITING DEVICE coordinate system (degrees). Required if Wedge Sequence (300A,00D1) is sent. Radiation source to wedge tray attachment edge distance (in mm) for current wedge. Number of compensators associated with current Beam. Compensator Tray transmission factor (between 0 and 1), at the beam energy specified by the Nominal Beam Energy (300A,0114) of the first Control Point of the Control Point Sequence (300A,0111). Introduces sequence of treatment compensators. Required if Number of Compensators (300A,00E0) is non-zero. One or more items may be included in this sequence. User defined description for the compensator. Identification number of the Compensator. The value of Compensator Number (300A,00E4) shall be unique within the Beam in which it is created. Required if Number of Compensators (300A,00E0) is non-zero. Type of compensator (if any). Defined Terms: STANDARD = physical (static) compensator DYNAMIC = moving Beam Limiting Device (collimator) simulating physical compensator User-supplied identifier for material used to manufacture Compensator. Required if Number of Compensators (300A,00E0) is non-zero. User-supplied identifier for compensator. An identifier for the accessory intended to be read by a device such as a bar-code reader. Radiation source to compensator tray attachment edge distance (in mm) for current compensator. Required if Compensator Sequence (300A,00E3) is sent. Indicates presence or absence of geometrical divergence of the compensator. Enumerated Values: PRESENT = the compensator is shaped according to the beam geometrical divergence. ABSENT = the compensator is not shaped according to the beam geometrical divergence. Indicates on which side of the Compensator Tray the compensator is mounted. Enumerated Values: PATIENT_SIDE = the compensator is mounted on the side of the Compensator Tray which is towards the patient. SOURCE_SIDE = the compensator is mounted on the side of the Compensator Tray which is towards the radiation source. DOUBLE_SIDED = the compensator has a shaped (i.e. non-flat) surface on both sides of the Compensator Tray. Number of rows in the compensator. A row is defined to be in the X direction of the IEC Beam Limiting Device Coordinate system. Number of columns in the compensator. A column is defined to be in the Y direction of the IEC Beam Limiting Device Coordinate system. Physical distance (in mm) between the center of each pixel projected onto machine isocentric plane. Specified by a numeric pair - adjacent row spacing (delimiter) adjacent column spacing. See 10.7.1.3 for further explanation of the value order. Required if Compensator Sequence (300A,00E3) is sent. The x and y coordinates of the upper left hand corner (first pixel transmitted) of the compensator, projected onto the machine isocentric plane in the IEC BEAM LIMITING DEVICE coordinate system (mm). Required if Compensator Sequence (300A,00E3) is sent. A data stream of the pixel samples which comprise the compensator, expressed as broad-beam transmission values (between 0 and 1) along a ray line passing through the pixel, at the beam energy specified by the Nominal Beam Energy (300A,0114) of the first Control Point of the Control Point Sequence (300A,0111). The order of pixels sent is left to right, top to bottom, i.e., the upper left pixel is sent first followed by the remainder of the first row , followed by the first pixel of the 2nd row, then the remainder of the 2nd row and so on) when viewed from the radiation source. Required if Material ID (300A,00E1) is zero-length. May be present if Material ID (300A,00E1) is non-zero length. See C.8.8.14.10 and C.8.8.14.11. Note: Compensator Transmission Data may not be properly encoded if Explicit-VR transfer syntax is used and the VL of this attribute exceeds 65534 bytes.
The direction of the rows and columns in Compensator Transmission Data (300A,00EB) and Compensator Thickness Data (300A,00EC) is defined as follows: The direction of rows goes along the positive Xb direction and the direction of the columns does along the negative Yb direction of the IEC X-BEAM LIMITING DEVICE coordinate system. Other interpretations shall be documented in an implementation's conformance statement.
A data stream of the pixel samples which comprise the compensator, expressed as thicknesses (in mm). The order of pixels sent is left to right, top to bottom, i.e., the upper left pixel is sent first followed by the remainder of the first row , followed by the first pixel of the 2nd row, then the remainder of the 2nd row and so on) when viewed from the radiation source. Required if Material ID (300A,00E1) is non-zero length. May be present if Material ID (300A,00E1) is zero length. See C.8.8.14.9 and C.8.8.14.10 and C.8.8.14.11. Note: Compensator Thickness Data may not be properly encoded if Explicit-VR transfer syntax is used and the VL of this attribute exceeds 65534 bytes.
The values stored in Compensator Thickness Data (300A,00EC) and Source to Compensator Distance (300A,02E2) shall be parallel to the radiation beam axis if Compensator Divergence (300A,02E0) equals ABSENT, or divergent according to the beam geometrical divergence if Compensator Divergence (300A,02E0) equals PRESENT. If Compensator Divergence (300A,02E0) is not sent, then the parallel or divergent nature of the thicknesses is as if ABSENT was specified for Compensator Divergence (300A,02E0).
A data stream of the pixel samples which comprise the distance from the radiation source to the compensator surface closest to the radiation source (in mm). The order of pixels sent is left to right, top to bottom (upper left pixel, followed by the remainder of row 1, followed by the remainder of the columns). Required if Material ID (300A,00E1) is non-zero length, and Compensator Mounting Position (300A,02E1) is DOUBLE_SIDED. May be present if Material ID (300A,00E1) is zero length and Compensator Mounting Position (300A,02E1) is DOUBLE_SIDED. See C.8.8.14.9 and C.8.8.14.11.
The values stored in Compensator Thickness Data (300A,00EC) and Source to Compensator Distance (300A,02E2) shall be parallel to the radiation beam axis if Compensator Divergence (300A,02E0) equals ABSENT, or divergent according to the beam geometrical divergence if Compensator Divergence (300A,02E0) equals PRESENT. If Compensator Divergence (300A,02E0) is not sent, then the parallel or divergent nature of the thicknesses is as if ABSENT was specified for Compensator Divergence (300A,02E0).
Number of boli associated with current Beam. Introduces sequence of boli associated with Beam. Required if Number of Boli (300A,00ED) is non-zero. One or more items may be included in this sequence. Uniquely identifies ROI representing the Bolus specified by ROI Number (3006,0022) in Structure Set ROI Sequence (3006,0020) in Structure Set Module within RT Structure Set in Referenced Structure Set Sequence (300C,0060) in RT General Plan Module. Required if Referenced Bolus Sequence (300C,00B0) is sent. User-supplied identifier for the Bolus. User-defined description for the Bolus. An identifier for the accessory intended to be read by a device such as a bar-code reader. Number of shielding blocks associated with Beam. Total block tray transmission for all block trays (between 0 and 1) at the beam energy specified by the Nominal Beam Energy (300A,0114) of the first Control Point of the Control Point Sequence (300A,0111). Introduces sequence of blocks associated with Beam. Required if Number of Blocks (300A,00F0) is non-zero. One or more items may be included in this sequence. User-supplied identifier for block tray. An identifier for the accessory intended to be read by a device such as a bar-code reader. Radiation Source to attachment edge of block tray assembly (mm). Required if Block Sequence (300A,00F4) is sent. Type of block. Required if Block Sequence (300A,00F4) is sent. See C.8.8.14.4. Enumerated Values: SHIELDING = blocking material is inside contour APERTURE = blocking material is outside contour
All blocks with Block Type (300A,00F8) of APERTURE for a given beam shall have equal values of Block Transmission (300A,0102) and/or Block Thickness (300A,0100) if they are specified. The composite aperture shall be evaluated as the union of the individual apertures within a single Block. Shielding block transmission(s) shall be applied multiplicatively after the (composite) aperture has been evaluated.
Indicates presence or otherwise of geometrical divergence. Required if Block Sequence (300A,00F4) is sent. Enumerated Values: PRESENT = block edges are shaped for beam divergence ABSENT = block edges are not shaped for beam divergence Indicates on which side of the Block Tray the block is mounted. Enumerated Values: PATIENT_SIDE = the block is mounted on the side of the Block Tray which is towards the patient. SOURCE_SIDE = the block is mounted on the side of the Block Tray which is towards the radiation source. Identification number of the Block. The value of Block Number (300A,00FC) shall be unique within the Beam in which it is created. Required if Block Sequence (300A,00F4) is sent. User-defined name for block. User-supplied identifier for material used to manufacture Block. Required if Block Sequence (300A,00F4) is sent. Physical thickness of block (in mm) parallel to radiation beam axis. Required if Material ID (300A,00E1) is non-zero length. May be present if Material ID (300A,00E1) is zero length. See C.8.8.14.4 and C.8.8.14.11.
All blocks with Block Type (300A,00F8) of APERTURE for a given beam shall have equal values of Block Transmission (300A,0102) and/or Block Thickness (300A,0100) if they are specified. The composite aperture shall be evaluated as the union of the individual apertures within a single Block. Shielding block transmission(s) shall be applied multiplicatively after the (composite) aperture has been evaluated.
Transmission through the block (between 0 and 1) at the beam energy specified by the Nominal Beam Energy (300A,0114) of the first Control Point of the Control Point Sequence (300A,0111). Required if Material ID (300A,00E1) is zero length. May be present if Material ID (300A,00E1) is non-zero length. See C.8.8.14.4 and C.8.8.14.11.
All blocks with Block Type (300A,00F8) of APERTURE for a given beam shall have equal values of Block Transmission (300A,0102) and/or Block Thickness (300A,0100) if they are specified. The composite aperture shall be evaluated as the union of the individual apertures within a single Block. Shielding block transmission(s) shall be applied multiplicatively after the (composite) aperture has been evaluated.
Number of (x,y) pairs defining the block edge. Required if Block Sequence (300A,00F4) is sent. A data stream of (x,y) pairs which comprise the block edge. The number of pairs shall be equal to Block Number of Points (300A,0104), and the vertices shall be interpreted as a closed polygon. Coordinates are projected onto the machine isocentric plane in the IEC BEAM LIMITING DEVICE coordinate system (mm). Required if Block Sequence (300A,00F4) is sent. See Note 4. Introduces sequence of Applicators associated with Beam. Only a single item shall be permitted in this sequence. User or machine supplied identifier for Applicator. Required if Applicator Sequence (300A,0107) is sent. An identifier for the accessory intended to be read by a device such as a bar-code reader. Type of Applicator. Required if Applicator Sequence (300A,0107) is sent. Defined Terms: ELECTRON_SQUARE = square electron applicator ELECTRON_RECT = rectangular electron applicator ELECTRON_CIRC = circular electron applicator ELECTRON_SHORT = short electron applicator ELECTRON_OPEN = open (dummy) electron applicator INTRAOPERATIVE = intraoperative (custom) applicator STEREOTACTIC = stereotactic applicator User-defined description for Applicator. Introduces a Sequence of General Accessories associated with this Beam. One or more items may be included in this sequence. Identification Number of the General Accessory. The value shall be unique within the sequence. User or machine supplied identifier for General Accessory. User supplied description of General Accessory. Specifies the type of accessory. Defined Terms: GRATICULE = Accessory tray with a radio-opaque grid IMAGE_DETECTOR = Image acquisition device positioned in the beam line RETICLE = Accessory tray with radio-transparent markers or grid Machine-readable identifier for this accessory Value of Cumulative Meterset Weight (300A,0134) for final Control Point in Control Point Sequence (300A,0111). Required if Cumulative Meterset Weight is non-null in Control Points specified within Control Point Sequence (300A,0111). See C.8.8.14.1.
The Meterset at a given Control Point is equal to the Beam Meterset (300A,0086) specified in the Referenced Beam Sequence (300C,0004) of the RT Fraction Scheme Module, multiplied by the Cumulative Meterset Weight (300A,0134) for the Control Point, divided by the Final Cumulative Meterset Weight (300A,010E). The Meterset is specified in units defined by Primary Dosimeter Unit (300A,00B3). If the calculation for Meterset results in a meterset value which is not an exact multiple of the primary meterset resolution, then the result shall be rounded to the nearest allowed meterset value (i.e. less than a half resolution unit shall be rounded down to the nearest resolution unit, and equal or greater than half a resolution unit shall be rounded up to the nearest resolution unit). Note also that if Final Cumulative Meterset Weight (300A,010E) is equal to 100, then Cumulative Meterset Weight (300A,0134) becomes equivalent to the percentage of Beam Meterset (300A,0086) delivered at each control point. If Final Cumulative Meterset Weight (300A,010E) is equal to Beam Meterset (300A,0086), then the Cumulative Meterset Weight (300A,0134) at each control point becomes equal to the cumulative Meterset delivered at that control point.
Number of control points in Beam. Introduces sequence of machine configurations describing treatment beam. Two or more items may be included in this sequence. See C.8.8.14.5 and C.8.8.14.6.
The DICOM RT Beams Module uses a single beam model to handle static, arc, and dynamic delivery of external beam radiation by a medical accelerator or gamma beam therapy equipment (cobalt unit). All applicable parameters shall be specified at Control Point 0, with the exception of couch positions (see C.8.8.14.6). All parameters that change at any control point of a given beam shall be specified explicitly at all control points (including those preceding the change). No assumptions are made about the behavior of machine parameters between specified control points, and communicating devices shall agree on this behavior outside the current standard. Gantry Rotation Direction (300A,011F), Beam Limiting Device Rotation Direction (300A,0121), Patient Support Rotation Direction (300A,0123), and Table Top Eccentric Rotation Direction (300A,0126) are defined as applying to the segment following the control point, and changes to these parameters during treatment may be specified without use of a “non-irradiation” segment. All other Control Point Sequence attributes are defined only at the control point. To unambiguously encode changes in discrete-valued attributes such as Wedge Position (300A,0118) and Nominal Beam Energy (300A,0114), a non-irradiation segment where Cumulative Meterset Weight (300A,0134) does not change, shall be used. Some examples of beam specification using control points are as follows: a) Static delivery: Control Point 0: All applicable treatment parameters defined, Cumulative Meterset Weight = 0 Control Point 1: Cumulative Meterset Weight = 1, no other parameters defined b) Arc delivery: Control Point 0: All applicable treatment parameters defined, Cumulative Meterset Weight = 0, Gantry Rotation Direction = rotation direction, Gantry Angle = initial angle Control Point 1: Cumulative Meterset Weight = 1, Gantry Rotation Direction = NONE, Gantry Angle = final angle c) Dynamic delivery of two equally weighted segments: Control Point 0: All applicable treatment parameters defined, Cumulative Meterset Weight = 0 Control Point 1: All changing treatment parameters defined (including those which do not change at this control point), Cumulative Meterset Weight = 0.5 Control Point 2: All changing treatment parameters defined (including those which do not change at this control point), Cumulative Meterset Weight = 1 d) Dynamic Delivery of two unequally weighted segments with a step change in table angle: Control Point 0: All applicable treatment parameters defined, Patient Support Angle = initial angle, Patient Support Rotation Direction = NONE, Cumulative Meterset Weight = 0 Control Point 1: All changing parameters defined (including those that do not change at this control point), Cumulative Meterset Weight = 0.3, Patient Support Angle = initial angle, Patient Support Rotation Direction = rotation direction Control Point 2: All changing parameters defined (although none should change at this control point), Cumulative Meterset Weight = 0.3, Patient Support Angle = new angle, Patient Support Rotation Direction = NONE Control Point 3: All changing parameters defined (including those that do not change at this control point), Cumulative Meterset Weight = 1, Patient Support Angle = new angle, Patient Support Rotation Direction = NONE
Index of current Control Point, starting at 0 for first Control Point. Required if Control Point Sequence (300A,0111) is sent. Cumulative weight to current control point. Cumulative Meterset Weight for the first item in Control Point Sequence shall always be zero. Cumulative Meterset Weight for the final item in Control Point Sequence shall always be equal to Final Cumulative Meterset Weight. Required if Control Point Sequence (300A,0111) is sent. See C.8.8.14.1.
The Meterset at a given Control Point is equal to the Beam Meterset (300A,0086) specified in the Referenced Beam Sequence (300C,0004) of the RT Fraction Scheme Module, multiplied by the Cumulative Meterset Weight (300A,0134) for the Control Point, divided by the Final Cumulative Meterset Weight (300A,010E). The Meterset is specified in units defined by Primary Dosimeter Unit (300A,00B3). If the calculation for Meterset results in a meterset value which is not an exact multiple of the primary meterset resolution, then the result shall be rounded to the nearest allowed meterset value (i.e. less than a half resolution unit shall be rounded down to the nearest resolution unit, and equal or greater than half a resolution unit shall be rounded up to the nearest resolution unit). Note also that if Final Cumulative Meterset Weight (300A,010E) is equal to 100, then Cumulative Meterset Weight (300A,0134) becomes equivalent to the percentage of Beam Meterset (300A,0086) delivered at each control point. If Final Cumulative Meterset Weight (300A,010E) is equal to Beam Meterset (300A,0086), then the Cumulative Meterset Weight (300A,0134) at each control point becomes equal to the cumulative Meterset delivered at that control point.
Introduces a sequence of Dose References for current Beam. One or more items may be included in this sequence. Uniquely identifies Dose Reference specified by Dose Reference Number (300A,0012) in Dose Reference Sequence (300A,0010) in RT Prescription Module. Required if Referenced Dose Reference Sequence (300C,0050) is sent. Coefficient used to calculate cumulative dose contribution from this Beam to the referenced Dose Reference at the current Control Point. Required if Referenced Dose Reference Sequence (300C,0050) is sent. See C.8.8.14.7.
The Cumulative Dose Reference Coefficient (300A,010C) is the value by which Beam Dose (300A,0084) is multiplied to obtain the dose to the referenced dose reference site at the current control point (and after previous control points have been successfully administered). The Cumulative Dose Reference Coefficient (300A,010C) is by definition zero for the initial control point. The Cumulative Dose Reference Coefficient (300A,010C) of the final control point multiplied by Beam Dose (300A,0084) results in the final dose to the referenced dose reference site for the current beam. Dose calculation for dose reference sites other than points is not well defined.
Sequence describing related instances of RT Dose (for grids, isodose curves, and named/unnamed point doses). One or more items may be included in this sequence. Required if RT Dose is being sent, and Dose Summation Type (3004,000A) equals CONTROL_POINT. Nominal Beam Energy at control point (MV/MeV). Dose Rate to be set on treatment machine for segment beginning at current control point (e.g. MU/min). A Sequence of Items describing Wedge Positions for the current control point. Required for first item of Control Point Sequence if Number of Wedges (300A,00D0) is non-zero, and in subsequent control points if Wedge Position (300A,0118) changes during Beam. See C.8.8.14.5. The number of items in this sequence shall equal the value of Number of Wedges (300A,00D0).
The DICOM RT Beams Module uses a single beam model to handle static, arc, and dynamic delivery of external beam radiation by a medical accelerator or gamma beam therapy equipment (cobalt unit). All applicable parameters shall be specified at Control Point 0, with the exception of couch positions (see C.8.8.14.6). All parameters that change at any control point of a given beam shall be specified explicitly at all control points (including those preceding the change). No assumptions are made about the behavior of machine parameters between specified control points, and communicating devices shall agree on this behavior outside the current standard. Gantry Rotation Direction (300A,011F), Beam Limiting Device Rotation Direction (300A,0121), Patient Support Rotation Direction (300A,0123), and Table Top Eccentric Rotation Direction (300A,0126) are defined as applying to the segment following the control point, and changes to these parameters during treatment may be specified without use of a “non-irradiation” segment. All other Control Point Sequence attributes are defined only at the control point. To unambiguously encode changes in discrete-valued attributes such as Wedge Position (300A,0118) and Nominal Beam Energy (300A,0114), a non-irradiation segment where Cumulative Meterset Weight (300A,0134) does not change, shall be used. Some examples of beam specification using control points are as follows: a) Static delivery: Control Point 0: All applicable treatment parameters defined, Cumulative Meterset Weight = 0 Control Point 1: Cumulative Meterset Weight = 1, no other parameters defined b) Arc delivery: Control Point 0: All applicable treatment parameters defined, Cumulative Meterset Weight = 0, Gantry Rotation Direction = rotation direction, Gantry Angle = initial angle Control Point 1: Cumulative Meterset Weight = 1, Gantry Rotation Direction = NONE, Gantry Angle = final angle c) Dynamic delivery of two equally weighted segments: Control Point 0: All applicable treatment parameters defined, Cumulative Meterset Weight = 0 Control Point 1: All changing treatment parameters defined (including those which do not change at this control point), Cumulative Meterset Weight = 0.5 Control Point 2: All changing treatment parameters defined (including those which do not change at this control point), Cumulative Meterset Weight = 1 d) Dynamic Delivery of two unequally weighted segments with a step change in table angle: Control Point 0: All applicable treatment parameters defined, Patient Support Angle = initial angle, Patient Support Rotation Direction = NONE, Cumulative Meterset Weight = 0 Control Point 1: All changing parameters defined (including those that do not change at this control point), Cumulative Meterset Weight = 0.3, Patient Support Angle = initial angle, Patient Support Rotation Direction = rotation direction Control Point 2: All changing parameters defined (although none should change at this control point), Cumulative Meterset Weight = 0.3, Patient Support Angle = new angle, Patient Support Rotation Direction = NONE Control Point 3: All changing parameters defined (including those that do not change at this control point), Cumulative Meterset Weight = 1, Patient Support Angle = new angle, Patient Support Rotation Direction = NONE
Uniquely references Wedge described by Wedge Number (300A,00D2) in Wedge Sequence (300A,00D1). Required if Wedge Position Sequence (300A,0116) is sent. Position of Wedge at current Control Point. Required if Wedge Position Sequence (300A,0116) is sent. Enumerated Values: IN OUT Introduces sequence of beam limiting device (collimator) jaw or leaf (element) positions. Required for first item of Control Point Sequence, or if Beam Limiting Device changes during Beam. One or more items may be included in this sequence. Type of beam limiting device (collimator). The value of this attribute shall correspond to RT Beam Limiting Device Type (300A,00B8) defined in an item of Beam Limiting Device Sequence (300A,00B6). Required if Beam Limiting Device Position Sequence (300A,011A) is sent. Enumerated Values: X = symmetric jaw pair in IEC X direction Y = symmetric jaw pair in IEC Y direction ASYMX = asymmetric jaw pair in IEC X direction ASYMY = asymmetric pair in IEC Y direction MLCX = multileaf (multi-element) jaw pair in IEC X direction MLCY = multileaf (multi-element) jaw pair in IEC Y direction Positions of beam limiting device (collimator) leaf (element) or jaw pairs (in mm) in IEC BEAM LIMITING DEVICE coordinate axis appropriate to RT Beam Limiting Device Type (300A,00B8), e.g. X-axis for MLCX, Y-axis for MLCY. Contains 2N values, where N is the Number of Leaf/Jaw Pairs (300A,00BC) in Beam Limiting Device Sequence (300A,00B6). Values shall be listed in IEC leaf (element) subscript order 101, 102, ... 1N, 201, 202, ... 2N. Required if Beam Limiting Device Position Sequence (300A,011A) is sent. See Note 2. Gantry angle of radiation source, i.e. orientation of IEC GANTRY coordinate system with respect to IEC FIXED REFERENCE coordinate system (degrees). Required for first item of Control Point Sequence, or if Gantry Angle changes during Beam. Direction of Gantry Rotation when viewing gantry from isocenter, for segment following Control Point. Required for first item of Control Point Sequence, or if Gantry Rotation Direction changes during Beam. See C.8.8.14.8. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Gantry Pitch Angle. i.e. the rotation of the IEC GANTRY coordinate system about the X-axis of the IEC GANTRY coordinate system (degrees). If used, must be present for first item of Control Point Sequence, or if used and Gantry Pitch Rotation Angle changes during Beam, must be present. See C.8.8.25.6.5.
The Gantry Pitch angle is not defined in IEC 61217. This angle is defined in the DICOM standard in a way compatible with the current notion of IEC by introducing it as rotation of the IEC GANTRY System as indicated below. The Gantry Pitch Angle is defined as the rotation of the coordinate axes Yg, Zg about axis Xg by an angle g; see Figure C.8.8.25-7. An increase in the value of angle g corresponds to the clockwise rotation as viewed from the isocenter along the positive Xg axis Figure C.8.8.25-7 Gantry Pitch Angle
Direction of Gantry Pitch Angle when viewing along the positive X-axis of the IEC GANTRY coordinate system, for segment following Control Point. If used, must be present for first item of Control Point Sequence, or if used and Gantry Pitch Rotation Direction changes during Beam, must be present. See C.8.8.14.8 and C.8.8.25.6.5. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Beam Limiting Device angle, i.e. orientation of IEC BEAM LIMITING DEVICE coordinate system with respect to IEC GANTRY coordinate system (degrees). Required for first item of Control Point Sequence, or if Beam Limiting Device Angle changes during Beam. Direction of Beam Limiting Device Rotation when viewing beam limiting device (collimator) from radiation source, for segment following Control Point. Required for first item of Control Point Sequence, or if Beam Limiting Device Rotation Direction changes during Beam. See C.8.8.14.8. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Patient Support angle, i.e. orientation of IEC PATIENT SUPPORT (turntable) coordinate system with respect to IEC FIXED REFERENCE coordinate system (degrees). Required for first item of Control Point Sequence, or if Patient Support Angle changes during Beam. Direction of Patient Support Rotation when viewing table from above, for segment following Control Point. Required for first item of Control Point Sequence, or if Patient Support Rotation Direction changes during Beam. See C.8.8.14.8. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Distance (positive) from the IEC PATIENT SUPPORT vertical axis to the IEC TABLE TOP ECCENTRIC vertical axis (mm). Table Top (non-isocentric) angle, i.e. orientation of IEC TABLE TOP ECCENTRIC coordinate system with respect to IEC PATIENT SUPPORT coordinate system (degrees). Required for first item of Control Point Sequence, or if Table Top Eccentric Angle changes during Beam. Direction of Table Top Eccentric Rotation when viewing table from above, for segment following Control Point. Required for first item of Control Point Sequence, or if Table Top Eccentric Rotation Direction changes during Beam. See C.8.8.14.8. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Table Top Pitch Angle, i.e. the rotation of the IEC TABLE TOP coordinate system about the X-axis of the IEC TABLE TOP coordinate system (degrees). If required by treatment delivery device, shall be present for first item of Control Point Sequence. If required by treatment delivery device and if Table Top Pitch Angle changes during Beam, shall be present in all subsequent items of Control Point Sequence. See C.8.8.25.6.2.
Pitch and Roll Coordinate Systems of the Table Top are not defined in IEC 61217. These angles are defined in the DICOM standard in a way compatible with the current notion of IEC by introducing them as rotations of the IEC Table Top System as indicated below. The Table Top Pitch Angle is defined as the rotation of the coordinate axes Yt, Zt about axis Xt by an angle t; see Figure C.8.8.25-3. An increase in the value of angle t corresponds to the clockwise rotation of the Table Top as viewed from the Table Top coordinate system origin along the positive Xt axis. The Table Top Roll Angle is defined as the rotation of the coordinate axes Xt, Zt about axis Yt by an angle t; see Figure C.8.8.25-4. An increase in the value of angle t corresponds to the clockwise rotation of the Table Top as viewed from the Table Top coordinate system origin along the positive Yt axis. Figure C.8.8.25-3 Table Top Pitch Angle Figure C.8.8.25-4 Table Top Roll Angle
Direction of Table Top Pitch Rotation when viewing the table along the positive X-axis of the IEC TABLE TOP coordinate system, for segment following Control Point. If required by treatment delivery device, shall be present for first item of Control Point Sequence. If required by treatment delivery device and if Table Top Pitch Rotation Direction changes during Beam, shall be present in all subsequent items of Control Point Sequence. See C.8.8.14.8 and C.8.8.25.6.2. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Table Top Roll Angle, i.e. the rotation of the IEC TABLE TOP coordinate system about the IEC Y-axis of the IEC TABLE TOP coordinate system (degrees). If required by treatment delivery device, shall be present for first item of Control Point Sequence. If required by treatment delivery device and if Table Top Roll Angle changes during Beam, shall be present in all subsequent items of Control Point Sequence. See C.8.8.25.6.2.
Pitch and Roll Coordinate Systems of the Table Top are not defined in IEC 61217. These angles are defined in the DICOM standard in a way compatible with the current notion of IEC by introducing them as rotations of the IEC Table Top System as indicated below. The Table Top Pitch Angle is defined as the rotation of the coordinate axes Yt, Zt about axis Xt by an angle t; see Figure C.8.8.25-3. An increase in the value of angle t corresponds to the clockwise rotation of the Table Top as viewed from the Table Top coordinate system origin along the positive Xt axis. The Table Top Roll Angle is defined as the rotation of the coordinate axes Xt, Zt about axis Yt by an angle t; see Figure C.8.8.25-4. An increase in the value of angle t corresponds to the clockwise rotation of the Table Top as viewed from the Table Top coordinate system origin along the positive Yt axis. Figure C.8.8.25-3 Table Top Pitch Angle Figure C.8.8.25-4 Table Top Roll Angle
Direction of Table Top Roll Rotation when viewing the table along the positive Y-axis of the IEC TABLE TOP coordinate system, for segment following Control Point. If required by treatment delivery device, shall be present for first item of Control Point Sequence. If required by treatment delivery device and if Table Top Roll Rotation Direction changes during Beam, shall be present in all subsequent items of Control Point Sequence. See C.8.8.14.8 and C.8.8.25.6.2. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Table Top Vertical position in IEC TABLE TOP coordinate system (mm). Required for first item of Control Point Sequence, or if Table Top Vertical Position changes during Beam. See C.8.8.14.6.
All treatment machine parameters except couch translations are specified in absolute machine coordinates as defined by IEC 61217. For the Table Top Vertical Position (300A,0128), Table Top Longitudinal Position (300A,0129), and Table Top Lateral Position (300A,012A), if the first Control Point contains a value of non-zero length, all subsequent Control Point position values are absolute values in their respective coordinate system. If the first Control Point contains a zero-length value, all subsequent Control Point position values are specified relative to the (unknown) initial value.
Table Top Longitudinal position in IEC TABLE TOP coordinate system (mm). Required for first item of Control Point Sequence, or if Table Top Longitudinal Position changes during Beam. See C.8.8.14.6.
All treatment machine parameters except couch translations are specified in absolute machine coordinates as defined by IEC 61217. For the Table Top Vertical Position (300A,0128), Table Top Longitudinal Position (300A,0129), and Table Top Lateral Position (300A,012A), if the first Control Point contains a value of non-zero length, all subsequent Control Point position values are absolute values in their respective coordinate system. If the first Control Point contains a zero-length value, all subsequent Control Point position values are specified relative to the (unknown) initial value.
Table Top Lateral position in IEC TABLE TOP coordinate system (mm). Required for first item of Control Point Sequence, or if Table Top Lateral Position changes during Beam. See C.8.8.14.6.
All treatment machine parameters except couch translations are specified in absolute machine coordinates as defined by IEC 61217. For the Table Top Vertical Position (300A,0128), Table Top Longitudinal Position (300A,0129), and Table Top Lateral Position (300A,012A), if the first Control Point contains a value of non-zero length, all subsequent Control Point position values are absolute values in their respective coordinate system. If the first Control Point contains a zero-length value, all subsequent Control Point position values are specified relative to the (unknown) initial value.
Isocenter coordinates (x,y,z) in the patient based coordinate system described in C.7.6.2.1.1 (mm). Required for first item of Segment Control Point Sequence, or if Segment Isocenter Position changes during Beam. Patient surface entry point coordinates (x,y,z) in the patient based coordinate system described in C.7.6.2.1.1 (mm). Source to Patient Surface distance (mm).
Type of brachytherapy treatment technique. Enumerated Values: INTRALUMENARY INTRACAVITARY INTERSTITIAL CONTACT INTRAVASCULAR PERMANENT See C.8.8.15.1.
In permanent implant techniques the value for Channel Total Time (300A,0286) shall be mean life time of the isotope. The Brachy Control Point Sequence (300A,02D0) shall consist of two items: the first having Cumulative Time Weight (300A,02D6) = 0 and the second having Cumulative Time Weight (300A,02D6) = Final Cumulative Time Weight (300A,02C8).
Type of brachytherapy treatment. Defined Terms: MANUAL = manually positioned HDR = High dose rate MDR = Medium dose rate LDR = Low dose rate PDR = Pulsed dose rate Introduces single item sequence describing treatment machine to be used for treatment delivery. Only one item may be included in this sequence. User-defined name identifying treatment machine to be used for treatment delivery. Manufacturer of the equipment to be used for treatment delivery. Institution where the equipment is located that is to be used for treatment delivery. Mailing address of the institution where the equipment is located that is to be used for treatment delivery. Department in the institution where the equipment is located that is to be used for treatment delivery. Manufacturer's model name of the equipment that is to be used for treatment delivery. Manufacturer's serial number of the equipment that is to be used for treatment delivery. Introduces sequence of Sources to be used within Application Setups. One or more items may be included in this sequence. Identification number of the Source. The value of Source Number (300A,0212) shall be unique within the RT Plan in which it is created. Type of Source. Defined Terms: POINT LINE CYLINDER SPHERE Manufacturer of Source. Diameter of active Source (mm). Length of active Source (mm). User-supplied identifier for encapsulation material of active Source. Nominal thickness of wall of encapsulation (mm). See C.8.8.15.12.
If provided, Source Encapsulation Nominal Thickness (300A,0222), Brachy Accessory Device Nominal Thickness (300A,026A), Source Applicator Wall Nominal Thickness (300A,029C), and Channel Shield Nominal Thickness (300A,02B8) shall indicate that the related objects are of uniform thickness with the specified value. If this is not the case, these attributes shall not be provided. If provided, Source Encapsulation Nominal Transmission (300A,0224), Brachy Accessory Device Nominal Transmission (300A,026C), Source Applicator Wall Nominal Transmission (300A,029E), and Channel Shield Nominal Transmission (300A,02BA) shall indicate that the related objects are of uniform transmission with the specified value. If this is not the case, these attributes shall not be provided. No assumptions are made about the source characteristics beyond the parameters specified here.
Nominal transmission through wall of encapsulation (between 0 and 1). See C.8.8.15.12
If provided, Source Encapsulation Nominal Thickness (300A,0222), Brachy Accessory Device Nominal Thickness (300A,026A), Source Applicator Wall Nominal Thickness (300A,029C), and Channel Shield Nominal Thickness (300A,02B8) shall indicate that the related objects are of uniform thickness with the specified value. If this is not the case, these attributes shall not be provided. If provided, Source Encapsulation Nominal Transmission (300A,0224), Brachy Accessory Device Nominal Transmission (300A,026C), Source Applicator Wall Nominal Transmission (300A,029E), and Channel Shield Nominal Transmission (300A,02BA) shall indicate that the related objects are of uniform transmission with the specified value. If this is not the case, these attributes shall not be provided. No assumptions are made about the source characteristics beyond the parameters specified here.
Name of Isotope. Half-life of Isotope (days). Measurement unit of Source Strength. Required if the source is not a gamma-emitting (photon) source. May be present otherwise. Enumerated Values: AIR_KERMA_RATE = Air Kerma Rate if Source is Gamma emitting Isotope. DOSE_RATE_WATER = Dose Rate in Water if Source is Beta emitting Isotope. Air Kerma Rate in air of Isotope specified at Air Kerma Rate Reference Date (300A,022C) and Air Kerma Rate Reference Time (300A,022E) (in µGy h-1 at 1 m). Value shall be zero for non-gamma sources. Source Strength of Isotope at Source Strength Reference Date (300A,022C) and Source Strength Reference Time (300A,022E), in units specified in Source Strength Units (300A,0229). Required if the source is not a gamma-emitting (photon) source. See C.8.8.15.13.
For beta emitting isotopes, the Source Strength (300A,022B) shall be defined at reference point (r0,θ0), where r0 is the radial distance of 2 mm from the source longitudinal axis, and θ0 is the angle of 90 degrees between the source longitudinal axis and the line defined by the center of the source and the reference point. Refer to: • IEC 60601-2-17 (Medical electrical equipment – Particular requirements for the safety of automatically-controlled brachytherapy afterloading equipment), where the beta source strength is defined as: ABSORBED DOSE RATE [Gy s-1] in water at 2 mm along the perpendicular bisector from a RADIOACTIVE SOURCE emitting beta RADIATION. • Nath et. al.: Intravascular brachytherapy physics: Report of the AAPM Radiation Therapy Committee Task Group No. 60, Med. Phys 26 (2) Feb 1999, pp 119-152.
Reference date for Reference Air Kerma Rate (300A,022A) or Source Strength (300A,022B) of Isotope. Reference time for Air Kerma Rate (300A,022A) or Source Strength (300A,022B) of Isotope. Introduces sequence of Application Setups for current RT Plan. One or more items may be included in this sequence. Type of Application Setup. Defined Terms: FLETCHER_SUIT DELCLOS BLOEDORN JOSLIN_FLYNN CHANDIGARH MANCHESTER HENSCHKE NASOPHARYNGEAL OESOPHAGEAL ENDOBRONCHIAL SYED_NEBLETT ENDORECTAL PERINEAL Identification number of the Application Setup. The value of Application Setup Number (300A,0234) shall be unique within the RT Plan in which it is created. User-defined name for Application Setup. Manufacturer of Application Setup. Identification number of the Template. The value of Template Number (300A,0240) shall be unique within the Application Setup in which it is created. User-defined type for Template Device. User-defined name for Template Device. Introduces sequence of reference images used for validation of current Application Setup. One or more items may be included in this sequence. Total Reference Air Kerma for current Application Setup, i.e. the product of Air Kerma Rate of all Sources in all Channels with their respective Channel Times (µGy at 1 m). Value shall be zero for non-gamma sources. Introduces sequence of Brachy Accessory Devices associated with current Application Setup. One or more items may be included in this sequence. Identification number of the Brachy Accessory Device. The value of Brachy Accessory Device Number (300A,0262) shall be unique within the Application Setup in which it is created. Required if Brachy Accessory Device Sequence (300A,0260) is sent. User or machine supplied identifier for Brachy Accessory Device. Required if Brachy Accessory Device Sequence (300A,0260) is sent. Type of Brachy Accessory Device. Required if Brachy Accessory Device Sequence (300A,0260) is sent. Defined Terms: SHIELD DILATATION MOLD PLAQUE FLAB User-defined name for Brachy Accessory Device. User-supplied identifier for material of Brachy Accessory Device. See Note. Nominal thickness of Brachy Accessory Device (mm). See C.8.8.15.12.
If provided, Source Encapsulation Nominal Thickness (300A,0222), Brachy Accessory Device Nominal Thickness (300A,026A), Source Applicator Wall Nominal Thickness (300A,029C), and Channel Shield Nominal Thickness (300A,02B8) shall indicate that the related objects are of uniform thickness with the specified value. If this is not the case, these attributes shall not be provided. If provided, Source Encapsulation Nominal Transmission (300A,0224), Brachy Accessory Device Nominal Transmission (300A,026C), Source Applicator Wall Nominal Transmission (300A,029E), and Channel Shield Nominal Transmission (300A,02BA) shall indicate that the related objects are of uniform transmission with the specified value. If this is not the case, these attributes shall not be provided. No assumptions are made about the source characteristics beyond the parameters specified here.
Nominal Transmission through Brachy Accessory Device (between 0 and 1). See C.8.8.15.12.
If provided, Source Encapsulation Nominal Thickness (300A,0222), Brachy Accessory Device Nominal Thickness (300A,026A), Source Applicator Wall Nominal Thickness (300A,029C), and Channel Shield Nominal Thickness (300A,02B8) shall indicate that the related objects are of uniform thickness with the specified value. If this is not the case, these attributes shall not be provided. If provided, Source Encapsulation Nominal Transmission (300A,0224), Brachy Accessory Device Nominal Transmission (300A,026C), Source Applicator Wall Nominal Transmission (300A,029E), and Channel Shield Nominal Transmission (300A,02BA) shall indicate that the related objects are of uniform transmission with the specified value. If this is not the case, these attributes shall not be provided. No assumptions are made about the source characteristics beyond the parameters specified here.
Uniquely identifies ROI representing the Brachy Accessory specified by ROI Number (3006,0022) in Structure Set ROI Sequence (3006,0020) in Structure Set Module within RT Structure Set referenced by Referenced RT Structure Set Sequence (300C,0060) in RT General Plan Module. Required if Brachy Accessory Device Sequence (300A,0260) is sent. See C.8.8.15.2.
The Structure Set ROI shall be used in the Brachy Application Setups Module to describe the 3D coordinates of Accessory Devices, Applicators and Channel Shields, but not individual source positions (see C.8.8.15.9 and C.8.8.15.10).
Introduces sequence of Channels for current Application Setup. One or more items may be included in this sequence. Identification number of the Channel. The value of Channel Number (300A,0282) shall be unique within the Application Setup in which it is created. Length of Channel (mm). See C.8.8.15.3.
If specified, the Channel Length (300A,0284) shall be the sum of the Source Applicator Length (300A,0296) and Transfer Tube Length (300A,02A4).
Total amount of time between first and final Control Points of the Brachy Control Point Sequence (300A,02D0) for current Channel (sec). Channel Total Time calculation is based upon the Reference Air Kerma Rate (300A,022A) of the Referenced Source Number (300C,000E). Type of Source movement. See C.8.8.15.4. Defined Terms: STEPWISE FIXED OSCILLATING UNIDIRECTIONAL
In brachytherapy treatment techniques involving oscillating source movement (i.e. when Source Movement Type (300A,0288) is OSCILLATING), the Brachy Control Point Sequence (300A,02D0) shall consist of two items. The first Control Point shall have Cumulative Time Weight (300A,02D6) = 0, and Control Point Relative Position (300A,02D2) equal to one end point of the oscillation. The second Control Point shall have Cumulative Time Weight (300A,02D6) = Final Cumulative Time Weight (300A,02C8), and Control Point Relative Position (300A,02D2) equal to the other end point of the oscillation. Transit time shall not be modeled explicitly for oscillating techniques.
Number of Pulses per fraction for current Channel. Required if Brachy Treatment Type (300A,0202) is PDR. Pulse repetition interval (sec) for current Channel. Required if Brachy Treatment Type (300A,0202) is PDR. Identification number of the Source Applicator. The value of Source Applicator Number (300A,0290) shall be unique within the Channel in which it is created. User or machine supplied identifier for Source Applicator. Required if Source Applicator Number (300A,0290) is sent. Type of Source Applicator. Required if Source Applicator Number (300A,0290) is sent. Defined Terms: FLEXIBLE RIGID User-defined name for Source Applicator. Length of Source Applicator (mm), defined as the distance between the connector of the applicator and the distal-most position of the source. Required if Source Applicator Number (300A,0290) is sent. Manufacturer of Source Applicator. User-supplied identifier for material of Source Applicator wall. See Note. Nominal Thickness of Source Applicator wall (mm). See C.8.8.15.12.
If provided, Source Encapsulation Nominal Thickness (300A,0222), Brachy Accessory Device Nominal Thickness (300A,026A), Source Applicator Wall Nominal Thickness (300A,029C), and Channel Shield Nominal Thickness (300A,02B8) shall indicate that the related objects are of uniform thickness with the specified value. If this is not the case, these attributes shall not be provided. If provided, Source Encapsulation Nominal Transmission (300A,0224), Brachy Accessory Device Nominal Transmission (300A,026C), Source Applicator Wall Nominal Transmission (300A,029E), and Channel Shield Nominal Transmission (300A,02BA) shall indicate that the related objects are of uniform transmission with the specified value. If this is not the case, these attributes shall not be provided. No assumptions are made about the source characteristics beyond the parameters specified here.
Nominal Transmission through Source Applicator wall (between 0 and 1). See C.8.8.15.12.
If provided, Source Encapsulation Nominal Thickness (300A,0222), Brachy Accessory Device Nominal Thickness (300A,026A), Source Applicator Wall Nominal Thickness (300A,029C), and Channel Shield Nominal Thickness (300A,02B8) shall indicate that the related objects are of uniform thickness with the specified value. If this is not the case, these attributes shall not be provided. If provided, Source Encapsulation Nominal Transmission (300A,0224), Brachy Accessory Device Nominal Transmission (300A,026C), Source Applicator Wall Nominal Transmission (300A,029E), and Channel Shield Nominal Transmission (300A,02BA) shall indicate that the related objects are of uniform transmission with the specified value. If this is not the case, these attributes shall not be provided. No assumptions are made about the source characteristics beyond the parameters specified here.
Distance of path along channel (in mm) between adjacent (potential) dwell positions. Required if Source Movement Type (300A,0288) is STEPWISE. Uniquely identifies ROI representing the Source Applicator specified by ROI Number (3006,0022) in Structure Set ROI Sequence (3006,0020) in Structure Set Module within RT Structure Set referenced by Referenced RT Structure Set Sequence (300C,0060) in RT General Plan Module. Required if Source Applicator Number (300A,0290) is sent. See C.8.8.15.2.
The Structure Set ROI shall be used in the Brachy Application Setups Module to describe the 3D coordinates of Accessory Devices, Applicators and Channel Shields, but not individual source positions (see C.8.8.15.9 and C.8.8.15.10).
Identification number of the Transfer Tube. The value of Transfer Tube Number (300A,02A2) shall be unique within the Channel in which it is created. Length of Transfer Tube of current afterloading Channel (mm). Required if value Transfer Tube Number (300A,02A2) is non-null. Introduces sequence of Channel Shields associated with current Channel. One or more items may be included in this sequence. See C.8.8.15.5.
The effect of Channel Shields on dose contributions shall be specific to the Channel for which they are specified. There shall be no effect of these shields on the dose contributions from any other Channels.
Identification number of the Channel Shield. The value of Channel Shield Number (300A,02B2) shall be unique within the Channel in which it is created. Required if Channel Shield Sequence (300A,02B0) is sent. User or machine supplied identifier for Channel Shield. Required if Channel Shield Sequence (300A,02B0) is sent. User-defined name for Channel Shield. User-supplied identifier for material of Channel Shield. See Note. Nominal Thickness of Channel Shield (mm). See C.8.8.15.12.
If provided, Source Encapsulation Nominal Thickness (300A,0222), Brachy Accessory Device Nominal Thickness (300A,026A), Source Applicator Wall Nominal Thickness (300A,029C), and Channel Shield Nominal Thickness (300A,02B8) shall indicate that the related objects are of uniform thickness with the specified value. If this is not the case, these attributes shall not be provided. If provided, Source Encapsulation Nominal Transmission (300A,0224), Brachy Accessory Device Nominal Transmission (300A,026C), Source Applicator Wall Nominal Transmission (300A,029E), and Channel Shield Nominal Transmission (300A,02BA) shall indicate that the related objects are of uniform transmission with the specified value. If this is not the case, these attributes shall not be provided. No assumptions are made about the source characteristics beyond the parameters specified here.
Nominal Transmission of Channel Shield (between 0 and 1). See C.8.8.15.12.
If provided, Source Encapsulation Nominal Thickness (300A,0222), Brachy Accessory Device Nominal Thickness (300A,026A), Source Applicator Wall Nominal Thickness (300A,029C), and Channel Shield Nominal Thickness (300A,02B8) shall indicate that the related objects are of uniform thickness with the specified value. If this is not the case, these attributes shall not be provided. If provided, Source Encapsulation Nominal Transmission (300A,0224), Brachy Accessory Device Nominal Transmission (300A,026C), Source Applicator Wall Nominal Transmission (300A,029E), and Channel Shield Nominal Transmission (300A,02BA) shall indicate that the related objects are of uniform transmission with the specified value. If this is not the case, these attributes shall not be provided. No assumptions are made about the source characteristics beyond the parameters specified here.
Uniquely identifies ROI representing the Channel Shield specified by ROI Number (3006,0022) in Structure Set ROI Sequence (3006,0020) in Structure Set Module within RT Structure Set referenced by Referenced RT Structure Set Sequence (300C,0060) in RT General Plan Module. Required if Channel Shield Sequence (300A,02B0) is sent. See C.8.8.15.2.
The Structure Set ROI shall be used in the Brachy Application Setups Module to describe the 3D coordinates of Accessory Devices, Applicators and Channel Shields, but not individual source positions (see C.8.8.15.9 and C.8.8.15.10).
Uniquely identifies the referenced Source within the Source Sequence (300A,0210) for current Application Setup. Number of control points in Channel. For an N-segment Channel there will be 2N (stepwise movement) or N+1 (continuous movement) control points. Value of Cumulative Time Weight (300A,02D6) for final Control Point in Brachy Control Point Sequence (300A,02D0). Required if Cumulative Time Weight (300A,02D6) is non-null in Control Points specified within Brachy Control Point Sequence (300A,02D0). See C.8.8.15.6.
The treatment time at a given Control Point is equal to the Channel Total Time (300A,0286), multiplied by the Cumulative Time Weight (300A,02D6) for the Control Point, divided by the Final Cumulative Time Weight (300A,02C8). If the calculation for treatment time results in a time value which is not an exact multiple of the timer resolution, then the result shall be rounded to the nearest allowed timer value (i.e. less than a half resolution unit shall be rounded down to the nearest resolution unit, and equal or greater than half a resolution unit shall be rounded up to the nearest resolution unit). Note also that if Final Cumulative Time Weight (300A,02C8) is equal to 100, then Cumulative Time Weight (300A,02D6) becomes equivalent to the percentage of Channel Total Time (300A,0286) delivered at each control point. If Final Cumulative Time Weight (300A,02C8) is equal to Channel Total Time (300A,0286), then the Cumulative Time Weight (300A,02D6) at each control point becomes equal to the cumulative treatment time delivered at that control point. If Treatment Type (300A,0202) is PDR, then the Channel Total Time (3008,0286) shall specify the duration of a single pulse.
Introduces sequence of machine configurations describing this Channel. Two or more items may be included in this sequence. See C.8.8.15.7.
The Control Points shall be arranged such that the first Control Point for a particular Channel describes the first dwell position and the final Control Point for the Channel describes the final dwell position. If Brachy Treatment Type (300A,0202) is PDR, the Brachy Control Point Sequence (300A,02D0) shall specify the sequence of machine configurations for a single pulse. Similarly, if Source Movement Type (300A,0288) is OSCILLATING, the Brachy Control Point Sequence (300A,02D0) shall specify the sequence of machine configurations for a single period. Some examples of Brachytherapy specification using control points are as follows: a) Stepwise motion; Four equally weighted dwell positions; Step size = 10; Final Cumulative Time Weight = 100: Control Point 0: Control Point Relative Position = 30, Cumulative Time Weight = 0 Control Point 1: Control Point Relative Position = 30, Cumulative Time Weight = 25 Control Point 2: Control Point Relative Position = 20, Cumulative Time Weight = 25 Control Point 3: Control Point Relative Position = 20, Cumulative Time Weight = 50 Control Point 4: Control Point Relative Position = 10, Cumulative Time Weight = 50 Control Point 5: Control Point Relative Position = 10, Cumulative Time Weight = 75 Control Point 6: Control Point Relative Position = 0, Cumulative Time Weight = 75 Control Point 7: Control Point Relative Position = 0, Cumulative Time Weight = 100 b) Fixed (manually placed) sources; Final Cumulative Time Weight = 100: Control Point 0: Control Point Relative Position = 0, Control Point 3D Position = (x,y,z), Cumulative Time Weight = 0 Control Point 1: Control Point Relative Position = 0, Control Point 3D Position = (x,y,z), Cumulative Time Weight = 100 c) Oscillating movement; Final Cumulative Time Weight = 100: Control Point 0: Control Point Relative Position = 100, Cumulative Time Weight = 0 Control Point 1: Control Point Relative Position = 0, Cumulative Time Weight = 100 d) Unidirectional movement; Final Cumulative Time Weight = 100: Control Point 0: Control Point Relative Position = 0, Cumulative Time Weight = 0 Control Point 1: Control Point Relative Position = 100, Cumulative Time Weight = 100 e) Stepwise motion with consideration of source transit times between dwell positions; Three equally weighted dwell positions; Step size = 10; Final Cumulative Time Weight = 79: Control Point 0: Control Point Relative Position = 30, Cumulative Time Weight = 0 Control Point 1: Control Point Relative Position = 30, Cumulative Time Weight = 25 Control Point 2: Control Point Relative Position = 20, Cumulative Time Weight = 27 Control Point 3: Control Point Relative Position = 20, Cumulative Time Weight = 52 Control Point 4: Control Point Relative Position = 10, Cumulative Time Weight = 54 Control Point 5: Control Point Relative Position = 10, Cumulative Time Weight = 79 f) Stepwise motion with consideration of source transit times between dwell positions and to first and from last dwell position; Three equally weighted dwell positions; Step size = 10; Final Cumulative Time Weight = 383: Control Point 0: Control Point Relative Position = 1200, Cumulative Time Weight = 0 Control Point 1: Control Point Relative Position = 30, Cumulative Time Weight = 150 Control Point 2: Control Point Relative Position = 30, Cumulative Time Weight = 175 Control Point 3: Control Point Relative Position = 20, Cumulative Time Weight = 177 Control Point 4: Control Point Relative Position = 20, Cumulative Time Weight = 202 Control Point 5: Control Point Relative Position = 10, Cumulative Time Weight = 204 Control Point 6: Control Point Relative Position = 10, Cumulative Time Weight = 229 Control Point 7: Control Point Relative Position = 1200, Cumulative Time Weight = 383
Index of current Control Point, starting at 0 for first Control Point. Cumulative time weight to current Control Point (where the weighting is proportional to time values delivered). Cumulative Time Weight for first item in Brachy Control Point Sequence (300A,02D0) is always zero. See C.8.8.15.6 and C.8.8.15.8.
The treatment time at a given Control Point is equal to the Channel Total Time (300A,0286), multiplied by the Cumulative Time Weight (300A,02D6) for the Control Point, divided by the Final Cumulative Time Weight (300A,02C8). If the calculation for treatment time results in a time value which is not an exact multiple of the timer resolution, then the result shall be rounded to the nearest allowed timer value (i.e. less than a half resolution unit shall be rounded down to the nearest resolution unit, and equal or greater than half a resolution unit shall be rounded up to the nearest resolution unit). Note also that if Final Cumulative Time Weight (300A,02C8) is equal to 100, then Cumulative Time Weight (300A,02D6) becomes equivalent to the percentage of Channel Total Time (300A,0286) delivered at each control point. If Final Cumulative Time Weight (300A,02C8) is equal to Channel Total Time (300A,0286), then the Cumulative Time Weight (300A,02D6) at each control point becomes equal to the cumulative treatment time delivered at that control point. If Treatment Type (300A,0202) is PDR, then the Channel Total Time (3008,0286) shall specify the duration of a single pulse.
Distance between current Control Point Position and the distal-most possible Source position in current Channel (mm). See C.8.8.15.9.
Control Point Relative Position (300A,02D2) shall describe where a given source in a channel is located with respect to the end of the channel. This position shall correspond to the end of the afterloader applicator, not the “safe position”.
Coordinates (x, y, z) of Control Point in the patient based coordinate system described in C.7.6.2.1.1 (mm). See C.8.8.15.10.
Control Point 3D Position (300A,02D4) shall describe the absolute 3D coordinates of a source. This position shall correspond to the center of a source in an applicator during a remote or manually controlled afterloading treatment.
(x,y,z) component of the direction vector of the brachy source or seed at the Control Point 3D Position (300A,02D4). See C.8.8.15.14.
The Control Point Orientation (300A,0412) shall be used to define the orientation of an anisotropic brachytherapy source or seed for the purpose of calculating the effect of the anisotropy on the dose calculation. The Control Point Orientation (300A,0412) shall be given by the direction vector of the long axis of the Brachy source or seed in the insertion direction, in the DICOM Patient Coordinate System. The direction vector shall be oriented from the source center as defined by the Control Point 3D Position (300A,02D4) along the long axis of the source and in the insertion direction.
Introduces a sequence of Dose References for current Channel. One or more items may be included in this sequence. Uniquely identifies Dose Reference described in Dose Reference Sequence. (300A,0010) within RT Prescription Module of current RT Plan. Required if Brachy Referenced Dose Reference Sequence (300C,0055) is sent. Coefficient used to calculate cumulative dose contribution from this Source to the referenced Dose Reference at the current Control Point. Required if Brachy Referenced Dose Reference Sequence (300C,0055) is sent. See C.8.8.15.11.
The Cumulative Dose Reference Coefficient (300A,010C) is the value by which Brachy Application Setup Dose (300A,00A4) is multiplied to obtain the dose to the referenced dose reference site at the current control point (and after previous control points have been successfully administered). The Cumulative Dose Reference Coefficient (300A,010C) is by definition zero for the initial control point. The Cumulative Dose Reference Coefficient (300A,010C) of the final control point multiplied by Brachy Application Setup Dose (300A,00A4) results in the final dose to the referenced dose reference site for the current channel. Dose calculation for dose reference sites other than points is not well defined. If Treatment Type (300A,0202) is PDR, then the Cumulative Dose Reference Coefficient (3008,010C) shall specify the dose delivered to the dose reference during a single pulse. The total dose delivered to the dose reference shall then be expressed by Cumulative Dose Reference Coefficient (3008,010C) multiplied by Number of Pulses (300A,028A) multiplied by Brachy Application Setup Dose (300A,00A4).
Approval status at the time the SOP Instance was created. Enumerated Values: APPROVED = Reviewer recorded that object met an implied criterion UNAPPROVED = No review of object has been recorded REJECTED = Reviewer recorded that object failed to meet an implied criterion Date on which object was reviewed. Required if Approval Status (300E,0002) is APPROVED or REJECTED. Time at which object was reviewed. Required if Approval Status (300E,0002) is APPROVED or REJECTED. Name of person who reviewed object. Required if Approval Status (300E,0002) is APPROVED or REJECTED. Instance number identifying this particular instance of the object. Date when current fraction was delivered, or Date last fraction was delivered in case of RT Treatment Summary Record IOD. See Note. Time when current fraction was delivered (begun), or Time last fraction was delivered (begun) in case of RT Treatment Summary Record IOD. See Note. A sequence which provides reference to a RT Plan SOP Class/Instance pair. Only a single Item shall be permitted in this Sequence. A sequence which provides reference to RT Treatment Record SOP Class/Instance pairs to which the current RT Treatment Record is significantly related. The sequence may contain one or more items. Introduces sequence describing treatment machine used for treatment delivery. Only a single Item shall be permitted in this Sequence. User-defined name identifying treatment machine used for treatment delivery. Manufacturer of the equipment used for treatment delivery. Institution where the equipment is located that was used for treatment delivery. Mailing address of the institution where the equipment is located that was used for treatment delivery. Department in the institution where the equipment is located that was used for treatment delivery. Manufacturer's model name of the equipment used for treatment delivery. Manufacturer's serial number of the equipment used for treatment delivery. Introduces sequence of doses measured during treatment delivery, summed over entire session. The sequence may contain one or more items. Uniquely identifies Dose Reference specified by Dose Reference Number (300A,0012) in Dose Reference Sequence (300A,0010) in RT Prescription Module of referenced RT Plan. Required only if Measured Dose Reference Number (3008,0064) is not sent. It shall not be present otherwise. Unique identifier of measured dose point. Required only if Referenced Dose Reference Number (300C,0051) is not sent. It shall not be present otherwise. Units used to describe measured dose. Enumerated Values: GY = Gray RELATIVE = Dose relative to implicit reference value Measured Dose in units specified by Dose Units (3004,0002). Type of dose measurement. Defined Terms: DIODE = semiconductor diode TLD = thermoluminescent dosimeter ION_CHAMBER = ion chamber GEL = dose sensitive gel EPID = electronic portal imaging device FILM = dose sensitive film User-defined description of Dose Reference (e.g. "Exit dose", "Point A"). Introduces sequence of doses estimated for each treatment delivery. The sequence may contain one or more items. Uniquely identifies Dose Reference specified by Dose Reference Number (300A,0012) in Dose Reference Sequence (300A,0010) in RT Prescription Module of referenced RT Plan. Required only if Calculated Dose Reference Number (3008,0072) is not sent. It shall not be present otherwise. Unique identifier of dose reference point within RT Treatment Record IOD. Required only if Referenced Dose Reference Number (300C,0051) is not sent. It shall not be present otherwise. Calculated Dose (Gy). User-defined description of Calculated Dose Reference. Name of operator administering treatment session. Identifier of Fraction Group within referenced RT Plan. Total number of treatments (Fractions) planned for current Fraction Group. Measurement unit of machine dosimeter. Enumerated Values: MU = Monitor Unit MINUTE = minute Introduces sequence of Beams administered during treatment session. The sequence may contain one or more items. References Beam specified by Beam Number (300A,00C0) in Beam Sequence (300A,00B0) in RT Beams Module within referenced RT Plan. User-defined name for delivered Beam. User-defined description for delivered Beam. Motion characteristic of delivered Beam. Enumerated Values: STATIC = all beam parameters remain unchanged during delivery DYNAMIC = one or more beam parameters changes during delivery Particle type of delivered Beam. Defined Terms: PHOTON, ELECTRON, NEUTRON, PROTON. Type of high-dose treatment technique. Defined Terms: NORMAL = Standard treatment TBI = Total Body Irradiation HDR = High Dose Rate Required if treatment technique requires a dose that would normally require overriding of treatment machine safety controls. Introduces sequence of verification images obtained during delivery of current beam. The sequence may contain one or more items. Cumulative Meterset Weight within Beam referenced by Referenced Beam Number at which image acquisition starts. Cumulative Meterset Weight within Beam referenced by Referenced Beam Number at which image acquisition ends. Introduces sequence of doses measured during treatment delivery for current Beam. The sequence may contain one or more items. Uniquely references Dose Reference specified by Dose Reference Number (300A,0012) in Dose Reference Sequence (300A,0010) in RT Prescription Module of referenced RT Plan. Required if Referenced Measured Dose Reference Sequence (3008,0080) is sent and Referenced Measured Dose Reference Number (3008,0082) is not sent. It shall not be present otherwise. Uniquely references Measured Dose Reference specified by Measured Dose Reference Number (3008,0064) in Measured Dose Reference Sequence (3008,0010). Required if Referenced Measured Dose Reference Sequence (3008,0080) is sent and Referenced Dose Reference Number (300C,0051) is not sent. It shall not be present otherwise. Measured Dose in units specified by Dose Units (3004,0002) in sequence referenced by Measured Dose Reference Sequence (3008,0010) or Dose Reference Sequence (300A,0010) in RT Prescription Module of referenced RT Plan as defined above. Required if Referenced Measured Dose Reference Sequence (3008,0080) is sent. Introduces sequence of doses estimated for each treatment delivery. The sequence may contain one or more items. Uniquely identifies Dose Reference specified by Dose Reference Number (300A,0012) in Dose Reference Sequence (300A,0010) in RT Prescription Module of referenced RT Plan. Required if Referenced Calculated Dose Reference Sequence (3008,0090) is sent and Referenced Calculated Dose Reference Number (3008,0092) is not sent. Uniquely identifies Calculated Dose Reference specified by Calculated Dose Reference Number (3008,0072) within Calculated Dose Reference Sequence (3008,0070). Required if Referenced Calculated Dose Reference Sequence (3008,0090) is sent and Referenced Dose Reference Number (300C,0051) is not sent. Calculated Dose (Gy). Required if Referenced Calculated Dose Reference Sequence (3008,0090) is sent. Radiation source to gantry rotation axis distance of the equipment that was used for beam delivery (mm). Introduces sequence of beam limiting device (collimator) jaw or leaf (element) leaf pair values. The sequence may contain one or more items. Type of beam limiting device (collimator). Enumerated Values: X = symmetric jaw pair in IEC X direction Y = symmetric jaw pair in IEC Y direction ASYMX = asymmetric jaw pair in IEC X direction ASYMY = asymmetric pair in IEC Y direction MLCX = multileaf (multi-element) jaw pair in IEC X direction MLCY = multileaf (multi-element) jaw pair in IEC Y direction Number of leaf (element) or jaw pairs (equal to 1 for standard beam limiting device jaws). Uniquely identifies Patient Setup used within current beam, specified by Patient Setup Number (300A,0182) within Patient Setup Sequence (300A,0180) of RT Treatment Record. Number of wedges associated with current delivered Beam. Introduces sequence of treatment wedges present during delivered Beam. Required if Number of Wedges (300A,00D0) is non-zero. The sequence may contain one or more items. Identification number of the Wedge. The value of Wedge Number (300A,00D2) shall be unique within the wedge sequence. Type of wedge defined for delivered Beam. Required if Recorded Wedge Sequence (3008,00B0) is sent. Defined Terms: STANDARD = standard (static) wedge DYNAMIC = moving Beam Limiting Device (collimator) jaw simulating wedge MOTORIZED = single wedge which can be removed from beam remotely User-supplied identifier for wedge. An identifier for the accessory intended to be read by a device such as a bar-code reader. Nominal wedge angle delivered (degrees). Orientation of wedge, i.e. orientation of IEC WEDGE FILTER coordinate system with respect to IEC BEAM LIMITING DEVICE coordinate system (degrees). Number of compensators associated with current delivered Beam. Introduces sequence of treatment compensators associated with current Beam. The sequence may contain one or more items. Uniquely identifies compensator specified by Compensator Number (300A,00E4) within Beam referenced by Referenced Beam Number (300C,0006). Required if Recorded Compensator Sequence (3008,00C0) is sent. Type of compensator (if any). Required if Recorded Compensator Sequence (3008,00C0) is sent. Defined Terms: STANDARD = physical (static) compensator DYNAMIC = moving Beam Limiting Device (collimator) simulating compensator User-supplied identifier for compensator. An identifier for the accessory intended to be read by a device such as a bar-code reader. Number of boli used with current Beam. Introduces sequence of boli associated with Beam. The sequence may contain one or more items. Uniquely identifies ROI representing the bolus specified by ROI Number (3006,0022) in Structure Set ROI Sequence (3006,0020) in Structure Set Module within RT Structure Set IOD referenced by referenced RT Plan in Referenced RT Plan Sequence (300C,0002) in RT General Treatment Record Module. Required if Referenced Bolus Sequence (300C,00B0) is sent. User-supplied identifier for the Bolus. An identifier for the accessory intended to be read by a device such as a bar-code reader. Number of shielding blocks or Electron Inserts associated with Beam. Introduces sequence of blocks associated with current Beam. The sequence may contain one or more items. User-supplied identifier for block tray or Electron Insert. An identifier for the accessory intended to be read by a device such as a bar-code reader. Uniquely identifies block specified by Block Number (300A,00FC) within Beam referenced by Referenced Beam Number (300C,0006). User-defined name for block. Required if Recorded Block Sequence (3008,00D0) is sent. Introduces sequence of Applicators associated with Beam. Only a single item shall be permitted in this sequence. User or machine supplied identifier for Applicator. Required if Applicator Sequence (300A,0107) is sent. An identifier for the accessory intended to be read by a device such as a bar-code reader. Type of Applicator. Required if Applicator Sequence (300A,0107) is sent. Defined Terms: ELECTRON_SQUARE = square electron applicator ELECTRON_RECT = rectangular electron applicator ELECTRON_CIRC = circular electron applicator ELECTRON_SHORT = short electron applicator ELECTRON_OPEN = open (dummy) electron applicator INTRAOPERATIVE = intraoperative (custom) applicator STEREOTACTIC = stereotactic applicator User-defined description for Applicator. Introduces a Sequence of General Accessories associated with this Beam. One or more items may be included in this sequence. Identification Number of the General Accessory. The value shall be unique within the sequence. User or machine supplied identifier for General Accessory. User supplied description of General Accessory. Specifies the type of accessory. Defined Terms: GRATICULE = Accessory tray with a radio-opaque grid IMAGE_DETECTOR = Image acquisition device positioned in the beam line RETICLE = Accessory tray with radio-transparent markers or grid Machine-readable identifier for this accessory Fraction number for this beam administration. Delivery Type of treatment. Defined Terms: TREATMENT = normal patient treatment OPEN_PORTFILM = portal image acquisition with open field TRMT_PORTFILM = portal image acquisition with treatment port CONTINUATION = continuation of interrupted treatment SETUP = no treatment beam is applied for this RT Beam. To be used for specifying the gantry, couch, and other machine positions where X-Ray set-up images or measurements are to be taken Conditions under which treatment was terminated. Enumerated Values: NORMAL = treatment terminated normally OPERATOR = operator terminated treatment MACHINE = machine terminated treatment UNKNOWN = status at termination unknown Treatment machine termination code. This code is dependent upon the particular application and equipment. Conditions under which treatment was verified by a verification system. Enumerated Values: VERIFIED = treatment verified VERIFIED_OVR = treatment verified with at least one out-of-range value overridden NOT_VERIFIED = treatment verified manually Desired machine setting of primary meterset. Desired machine setting of secondary meterset. Machine setting actually delivered as recorded by primary meterset. Machine setting actually delivered as recorded by secondary meterset. Treatment Time set (sec). Treatment Time actually delivered (sec). Number of control points delivered. Introduces sequence of beam control points for current treatment beam. The sequence may contain one or more items. See C.8.8.21.1.
All treatment machine delivery parameters (including table angles and positions) in the RT Treatment Session Record Module shall be specified as absolute, not relative, values at the Control Point.
Uniquely identifies Control Point specified by Control Point Index (300A,0112) within Beam referenced by Referenced Beam Number (300C,0006). Date administration of treatment beam began. Time administration of treatment beam began. Desired machine setting for current control point. See C.8.8.21.2.
Specified Meterset (3008,0042) contains the MU as specified in the corresponding RT Plan at a given control point. Delivered Meterset (3008,0044) shall contain one of the following three values:
Machine setting actually delivered at current control point. See C.8.8.21.2.
Specified Meterset (3008,0042) contains the MU as specified in the corresponding RT Plan at a given control point. Delivered Meterset (3008,0044) shall contain one of the following three values:
Dose Rate set on treatment machine for segment beginning at current control point (meterset/min). Dose Rate actually delivered for segment beginning at current control point (meterset/min). Nominal Beam Energy at control point. Units used for Nominal Beam Energy (300A,0114). Required if Nominal Beam Energy (300A,0114) is sent. Defined Terms: MV = Megavolt MEV = Mega electron-Volt If Radiation Type (300A,00C6) is PHOTON, Nominal Beam Energy Unit (300A,0015) shall be MV. If Radiation Type (300A,00C6) is ELECTRON, Nominal Beam Energy Unit (300A,0015) shall be MEV. Introduces sequence of Wedge positions for current control point. The sequence may contain one or more items. Uniquely identifies wedge specified by Wedge Number (300A,00D2) within Beam referenced by Referenced Beam Number (300C,0006). Required if Wedge Position Sequence (300A,0116) is sent. Position of Wedge at current control point. Required if Wedge Position Sequence (300A,0116) is sent. Enumerated Values: IN, OUT. Introduces sequence of beam limiting device (collimator) jaw or leaf (element) positions. Required for Control Point 0 of Control Point Delivery Sequence (3008,0040) or if beam limiting device (collimator) changes during beam administration. The sequence may contain one or more items. Type of beam limiting device. The value of this attribute shall correspond to RT Beam Limiting Device Type (300A,00B8) defined in an element of Beam Limiting Device Leaf Pairs Sequence (3008,00A0). Required if Beam Limiting Device Position Sequence (300A,011A) is sent. Enumerated Values: X = symmetric jaw pair in IEC X direction Y = symmetric jaw pair in IEC Y direction ASYMX = asymmetric jaw pair in IEC X direction ASYMY = asymmetric pair in IEC Y direction MLCX = multileaf (multi-element) jaw pair in IEC X direction MLCY = multileaf (multi-element) jaw pair in IEC Y direction Positions of beam limiting device (collimator) leaf (element) or jaw pairs (mm) in IEC BEAM LIMITING DEVICE coordinate axis appropriate to RT Beam Limiting Device Type (300A,00B8), e.g. X-axis for MLCX, Y-axis for MLCY. Contains 2N values, where N is the Number of Leaf/Jaw Pairs (300A,00BC) defined in element of Beam Limiting Device Leaf Pairs Sequence (3008,00A0). Values shall be in IEC leaf subscript order 101, 102, … 1N, 201, 202 … 2N. Required if Beam Limiting Device Position Sequence (300A,011A) is sent. Treatment machine gantry angle, i.e. orientation of IEC GANTRY coordinate system with respect to IEC FIXED REFERENCE coordinate system (degrees). Required for Control Point 0 of Control Point Delivery Sequence (3008,0040) or if Gantry Angle changes during beam administration. Direction of Gantry Rotation when viewing gantry from isocenter, for segment beginning at current Control Point. Required for Control Point 0 of Control Point Delivery Sequence (3008,0040), or if Gantry Rotation Direction changes during beam administration. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation Gantry Pitch Angle. i.e. the rotation of the IEC GANTRY coordinate system about the X-axis of the IEC GANTRY coordinate system (degrees). If used, must be present for first item of Control Point Sequence, or if used and Gantry Pitch Rotation Angle changes during Beam, must be present. See C.8.8.25.6.5.
The Gantry Pitch angle is not defined in IEC 61217. This angle is defined in the DICOM standard in a way compatible with the current notion of IEC by introducing it as rotation of the IEC GANTRY System as indicated below. The Gantry Pitch Angle is defined as the rotation of the coordinate axes Yg, Zg about axis Xg by an angle g; see Figure C.8.8.25-7. An increase in the value of angle g corresponds to the clockwise rotation as viewed from the isocenter along the positive Xg axis Figure C.8.8.25-7 Gantry Pitch Angle
Direction of Gantry Pitch Angle when viewing along the positive X-axis of the IEC GANTRY coordinate system, for segment following Control Point. If used, must be present for first item of Control Point Sequence, or if used and Gantry Pitch Rotation Direction changes during Beam, must be present. See C.8.8.14.8 and C.8.8.25.6.5. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Position of Beam Stopper during beam administration. Enumerated Values: EXTENDED = Beam Stopper extended RETRACTED = Beam Stopper retracted UNKNOWN = Position unknown Beam Limiting Device (collimator) angle, i.e. orientation of IEC BEAM LIMITING DEVICE coordinate system with respect to IEC GANTRY coordinate system (degrees). Required for Control Point 0 of Control Point Delivery Sequence (3008,0040) or if beam limiting device (collimator) angle changes during beam delivery. Direction of Beam Limiting Device Rotation when viewing beam limiting device (collimator) from radiation source, for segment beginning at current Control Point. Required for Control Point 0 of Control Point Delivery Sequence (3008,0040) or if Beam Limiting Device Rotation Direction changes during beam administration. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation Patient Support angle, i.e. orientation of IEC PATIENT SUPPORT (turntable) coordinate system with respect to IEC FIXED REFERENCE coordinate system (degrees). Required for Control Point 0 of Control Point Delivery Sequence (3008,0040) or if Patient Support Angle changes during beam administration. Direction of Patient Support Rotation when viewing table from above, for segment beginning at current Control Point. Required for Control Point 0 of Control Point Delivery Sequence (3008,0040), or if Patient Support Rotation Direction changes during beam administration. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation Distance (positive) from the IEC PATIENT SUPPORT vertical axis to the IEC TABLE TOP ECCENTRIC vertical axis (mm). Table Top (non-isocentric) angle, i.e. orientation of IEC TABLE TOP ECCENTRIC coordinate system with respect to IEC PATIENT SUPPORT coordinate system (degrees). Required for Control Point 0 of Control Point Delivery Sequence (3008,0040) or if Table Top Eccentric Angle changes during beam administration. Direction of Table Top Eccentric Rotation when viewing table from above, for segment beginning at current Control Point. Required for Control Point 0 of Control Point Delivery Sequence (3008,0040) or if Table Top Eccentric Rotation Direction changes during beam administration. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation Table Top Pitch Angle, i.e. the rotation of the IEC TABLE TOP coordinate system about the X-axis of the IEC TABLE TOP coordinate system (degrees). If required by treatment delivery device, shall be present for first item of Control Point Sequence. If required by treatment delivery device and if Table Top Pitch Angle changes during Beam, shall be present in all subsequent items of Control Point Sequence. See C.8.8.25.6.2.
Pitch and Roll Coordinate Systems of the Table Top are not defined in IEC 61217. These angles are defined in the DICOM standard in a way compatible with the current notion of IEC by introducing them as rotations of the IEC Table Top System as indicated below. The Table Top Pitch Angle is defined as the rotation of the coordinate axes Yt, Zt about axis Xt by an angle t; see Figure C.8.8.25-3. An increase in the value of angle t corresponds to the clockwise rotation of the Table Top as viewed from the Table Top coordinate system origin along the positive Xt axis. The Table Top Roll Angle is defined as the rotation of the coordinate axes Xt, Zt about axis Yt by an angle t; see Figure C.8.8.25-4. An increase in the value of angle t corresponds to the clockwise rotation of the Table Top as viewed from the Table Top coordinate system origin along the positive Yt axis. Figure C.8.8.25-3 Table Top Pitch Angle Figure C.8.8.25-4 Table Top Roll Angle
Direction of Table Top Pitch Rotation when viewing the table along the positive X-axis of the IEC TABLE TOP coordinate system, for segment following Control Point. If required by treatment delivery device, shall be present for first item of Control Point Sequence. If required by treatment delivery device and if Table Top Pitch Rotation Direction changes during Beam, shall be present in all subsequent items of Control Point Sequence. See C.8.8.14.8 and C.8.8.25.6.2. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Table Top Roll Angle, i.e. the rotation of the IEC TABLE TOP coordinate system about the IEC Y-axis of the IEC TABLE TOP coordinate system (degrees). If required by treatment delivery device, shall be present for first item of Control Point Sequence. If required by treatment delivery device and if Table Top Roll Angle changes during Beam, shall be present in all subsequent items of Control Point Sequence. See C.8.8.25.6.2.
Pitch and Roll Coordinate Systems of the Table Top are not defined in IEC 61217. These angles are defined in the DICOM standard in a way compatible with the current notion of IEC by introducing them as rotations of the IEC Table Top System as indicated below. The Table Top Pitch Angle is defined as the rotation of the coordinate axes Yt, Zt about axis Xt by an angle t; see Figure C.8.8.25-3. An increase in the value of angle t corresponds to the clockwise rotation of the Table Top as viewed from the Table Top coordinate system origin along the positive Xt axis. The Table Top Roll Angle is defined as the rotation of the coordinate axes Xt, Zt about axis Yt by an angle t; see Figure C.8.8.25-4. An increase in the value of angle t corresponds to the clockwise rotation of the Table Top as viewed from the Table Top coordinate system origin along the positive Yt axis. Figure C.8.8.25-3 Table Top Pitch Angle Figure C.8.8.25-4 Table Top Roll Angle
Direction of Table Top Roll Rotation when viewing the table along the positive Y-axis of the IEC TABLE TOP coordinate system, for segment following Control Point. If required by treatment delivery device, shall be present for first item of Control Point Sequence. If required by treatment delivery device and if Table Top Roll Rotation Direction changes during Beam, shall be present in all subsequent items of Control Point Sequence. See C.8.8.14.8 and C.8.8.25.6.2. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Table Top Vertical position in IEC TABLE TOP coordinate system (mm). This value is interpreted as an absolute, rather than relative, Table setting. Required for Control Point 0 of Control Point Delivery Sequence (3008,0040) or if Table Top Vertical Position changes during beam administration. Table Top Longitudinal position in IEC TABLE TOP coordinate system (mm). This value is interpreted as an absolute, rather than relative, Table setting. Required for Control Point 0 of Control Point Delivery Sequence (3008,0040) or if Table Top Longitudinal Position changes during beam administration. Table Top Lateral position in IEC TABLE TOP coordinate system (mm). This value is interpreted as an absolute, rather than relative, Table setting. Required for Control Point 0 of Control Point Delivery Sequence (3008,0040) or if Table Top Lateral Position changes during beam administration. Introduces a sequence of items describing any corrections made to any attributes prior to delivery of the next control point. The sequence may contain one or more items. Contains the Data Element Tag of the parent sequence containing the attribute that was corrected. The value is limited in scope to the Treatment Session Beam Sequence (3008,0020) and all nested sequences therein. Contains the sequence item index (starting at 1) of the corrected attribute within its parent sequence. Contains the Data Element Tag of the attribute that was corrected. The value applied to the attribute that was referenced by the Parameter Sequence Pointer (3008,0061), Parameter Item Index (3008,0063) and Parameter Pointer (3008,0065). Introduces sequence of parameters that were overridden during the administration of the beam segment immediately prior to the current control point. The sequence may contain one or more items. Contains the Data Element Tag of the attribute that was overridden. Required if Override Sequence (3008,0060) is sent. Contains the Data Element Tag of the parent sequence containing the attribute that was overridden. The value is limited in scope to the Treatment Session Beam Sequence (3008,0020) and all nested sequences therein. Contains the sequence item index (monotonically increasing from 1) of the overridden attributes within its parent sequence. The value is limited in scope to the Treatment Session Beam Sequence (3008,0020) and all nested sequences therein. Name of operator who authorized override. Required if Override Sequence (3008,0060) is sent. User-defined description of reason for override of parameter specified by Override Parameter Pointer (3008,0062).
Name of operator administering treatment session. Identifier of Fraction Group within referenced RT Plan. Total number of treatments (Fractions) planned for current Fraction Group. Type of brachytherapy treatment technique. Enumerated Values: INTRALUMENARY, INTRACAVITARY, INTERSTITIAL, CONTACT, INTRAVASCULAR, PERMANENT. See RT Plan IOD. Type of brachytherapy treatment. Defined Terms: MANUAL = manually positioned HDR = High dose rate MDR = Medium dose rate LDR = Low dose rate PDR = Pulsed dose rate Introduces sequence of Sources to be used within Application Setups. The sequence may contain one or more items. Identification number of the Source. The value of Source Number (300A,0212) shall be unique within the Recorded Source Sequence (3008,0100) in which it is created. Type of Source. Defined Terms: POINT, LINE, CYLINDER, SPHERE. Manufacturer of source. Serial Number of source. User-defined name of Isotope. Half-life of Isotope (days). Measurement unit of Source Strength. Required if the source is not a gamma-emitting (photon) source. May be present otherwise. Enumerated Values: AIR_KERMA_RATE = Air Kerma Rate if Source is Gamma emitting Isotope. DOSE_RATE_WATER = Dose Rate in Water if Source is Beta emitting Isotope. Air Kerma Rate in air of Isotope specified at Air Kerma Rate Reference Date (300A,022C) and Air Kerma Rate Reference Time (300A,022E) (in µGy h-1 at 1 m). Value shall be zero for non-gamma sources. Source Strength of Isotope at Source Strength Reference Date (300A,022C) and Source Strength Reference Time (300A,022E), in units specified in Source Strength Units (300A,0229). Required if the source is not a gamma-emitting (photon) source. See C.8.8.15.13.
For beta emitting isotopes, the Source Strength (300A,022B) shall be defined at reference point (r0,θ0), where r0 is the radial distance of 2 mm from the source longitudinal axis, and θ0 is the angle of 90 degrees between the source longitudinal axis and the line defined by the center of the source and the reference point. Refer to: • IEC 60601-2-17 (Medical electrical equipment – Particular requirements for the safety of automatically-controlled brachytherapy afterloading equipment), where the beta source strength is defined as: ABSORBED DOSE RATE [Gy s-1] in water at 2 mm along the perpendicular bisector from a RADIOACTIVE SOURCE emitting beta RADIATION. • Nath et. al.: Intravascular brachytherapy physics: Report of the AAPM Radiation Therapy Committee Task Group No. 60, Med. Phys 26 (2) Feb 1999, pp 119-152.
Reference date for Reference Air Kerma Rate (300A,022A) or Source Strength (300A,022B) of Isotope. Reference time for Air Kerma Rate (300A,022A) or Source Strength (300A,022B) of Isotope. Introduces sequence of Application Setups for RT Treatment Record for current RT Plan. The sequence may contain one or more items. Type of Application Setup. Defined Terms: FLETCHER_SUIT, DELCLOS, BLOEDORN, JOSLIN_FLYNN, CHANDIGARH, MANCHESTER, HENSCHKE, NASOPHARYNGEAL, OESOPHAGEAL, ENDOBRONCHIAL, SYED_NEBLETT, ENDORECTAL, PERINEAL. References application setup specified by Application Setup Number (300A,0234) in Application Setup Sequence (300A,0230) in RT Brachy Applications Module within referenced RT Plan. User-defined name for Application Setup. Manufacturer of Application Setup. Identification number of the Template. User-defined type for Template Device. User-defined name for Template Device. Results of check-wire travel through all channels of current Application Setup. Enumerated Values: PASSED = Passed check FAILED = Failed check UNKNOWN = Unknown status Introduces sequence of verification images obtained during delivery of current beam. The sequence may contain one or more items. See Note. Total Reference Air Kerma for current Application Setup, i.e. the sum of the products of the Air Kerma Rates of each Source in each Channel with its respective Channel Time (µGy at 1 m). Value shall be zero for non-gamma sources. Introduces sequence of doses measured during treatment delivery, summed over entire session. The sequence may contain one or more items. Uniquely references Dose Reference specified by Dose Reference Number (300A,0012) in Dose Reference Sequence (300A,0010) in RT Prescription Module of referenced RT Plan. Required if Referenced Measured Dose Reference Sequence (3008,0080) is sent and Referenced Measured Dose Reference Number (3008,0082) is not sent. It shall not be present otherwise. Uniquely references Measured Dose Reference specified by Measured Dose Reference Number (3008,0064) in Measured Dose Reference Sequence (3008,0010). Required if Referenced Measured Dose Reference Sequence (3008,0080) is sent and Referenced Dose Reference Number (300C,0051) is not sent. It shall not be present otherwise. Measured Dose in units specified by Dose Units (3004,0002) in sequence referenced by Measured Dose Reference Sequence (3008,0010) or Dose Reference Sequence (300A,0010) in RT Prescription Module of referenced RT Plan as defined above. Required if Referenced Measured Dose Reference Sequence (3008,0080) is sent. Introduces sequence of doses estimated for each treatment delivery. The sequence may contain one or more items. Uniquely identifies Dose Reference specified by Dose Reference Number (300A,0012) in Dose Reference Sequence (300A,0010) in RT Prescription Module of referenced RT Plan. Required if Referenced Calculated Dose Reference Sequence (3008,0090) is sent and Referenced Calculated Dose Reference Number (3008,0092) is not sent. It shall not be present otherwise. Uniquely identifies Calculated Dose Reference specified by Calculated Dose Reference Number (3008,0072) within Calculated Dose Reference Sequence (3008,0070). Required if Referenced Calculated Dose Reference Sequence (3008,0090) is sent and Referenced Dose Reference Number (300C,0051) is not sent. It shall not be present otherwise. Calculated Dose (Gy). Required if Referenced Calculated Dose Reference Sequence (3008,0090) is sent. Fraction number for this application setup. Delivery Type of treatment. Defined Terms: TREATMENT = normal patient treatment CONTINUATION = continuation of interrupted treatment Conditions under which treatment was terminated. Enumerated Values: NORMAL = treatment terminated normally OPERATOR = operator terminated treatment MACHINE = machine terminated treatment for other than NORMAL condition UNKNOWN = status at termination unknown Treatment machine termination code. This code is dependent upon the particular application and equipment. Conditions under which treatment was verified by a verification system. Enumerated Values: VERIFIED = treatment verified VERIFIED_OVR = treatment verified with at least one out-of-range value overridden NOT_VERIFIED = treatment verified manually Introduces sequence of Brachy Accessory Devices associated with current Application Setup. The sequence may contain one or more items. Identification number of the Brachy Accessory Device. The value of Brachy Accessory Device Number (300A,0262) shall be unique within the Application Setup in which it is created. Required if Recorded Brachy Accessory Device Sequence (3008,0120) is sent. User or machine supplied identifier for Brachy Accessory Device. Required if Recorded Brachy Accessory Device Sequence (3008,0120) is sent. Type of Brachy Accessory Device. Required if Recorded Brachy Accessory Device Sequence (3008,0120) is sent. Defined Terms: SHIELD, DILATATION, MOLD, PLAQUE, FLAB. User-defined name for Brachy Accessory Device. Introduces sequence of Channels for current Application Setup. The sequence may contain one or more items. Identification number of the Channel. The value of Channel Number (300A,0282) shall be unique within the Application Setup in which it is created. Length of Channel (mm). See RT Plan IOD. Total amount of time specified between Control Point 0 and final Control Point of the Brachy Control Point Sequence (300A,02D0) for current Channel (sec). Total amount of time actually delivered between Control Point 0 and final Control Point of the Brachy Control Point Sequence (300A,02D0) for current Channel (sec). Type of Source movement. Defined Terms: STEPWISE, FIXED, OSCILLATING, UNIDIRECTIONAL. Number of Pulses specified per fraction for current Channel. Required if Brachy Treatment Type (300A,0202) is PDR. See C.8.8.22.1.
In Brachytherapy treatment techniques where Brachy Treatment Type (300A,0202) is PDR, the Brachy Control Point Sequence (300A,02D0) shall consist of 2N items, where N = Delivered Number of Pulses (3008,0138). Each control point pair shall specify the start and end of a single pulse.
Number of Pulses actually delivered per fraction for current Channel. Required if Brachy Treatment Type (300A,0202) is PDR. See C.8.8.22.1.
In Brachytherapy treatment techniques where Brachy Treatment Type (300A,0202) is PDR, the Brachy Control Point Sequence (300A,02D0) shall consist of 2N items, where N = Delivered Number of Pulses (3008,0138). Each control point pair shall specify the start and end of a single pulse.
Pulse repetition interval (sec) specified for current Channel. Required if Brachy Treatment Type (300A,0202) is PDR. See C.8.8.22.1
In Brachytherapy treatment techniques where Brachy Treatment Type (300A,0202) is PDR, the Brachy Control Point Sequence (300A,02D0) shall consist of 2N items, where N = Delivered Number of Pulses (3008,0138). Each control point pair shall specify the start and end of a single pulse.
Pulse repetition interval (sec) actually delivered for current Channel. Required if Brachy Treatment Type (300A,0202) is PDR. See C.8.8.22.1.
In Brachytherapy treatment techniques where Brachy Treatment Type (300A,0202) is PDR, the Brachy Control Point Sequence (300A,02D0) shall consist of 2N items, where N = Delivered Number of Pulses (3008,0138). Each control point pair shall specify the start and end of a single pulse.
Introduces sequence of doses measured during treatment delivery, summed over entire session. The sequence may contain one or more items. Uniquely references Dose Reference specified by Dose Reference Number (300A,0012) in Dose Reference Sequence (300A,0010) in RT Prescription Module of referenced RT Plan. Required if Referenced Measured Dose Reference Sequence (3008,0080) is sent and Referenced Measured Dose Reference Number (3008,0082) is not sent. It shall not be present otherwise. References Measured Dose Reference specified by Measured Dose Reference Number (3008,0064) in Measured Dose Reference Sequence (3008,0010). Required if Referenced Measured Dose Reference Sequence (3008,0080) is sent and Referenced Dose Reference Number (300C,0051) is not sent. It shall not be present otherwise. Measured Dose. Required if Referenced Measured Dose Reference Sequence (3008,0080) is sent. Introduces sequence of doses estimated for each treatment delivery. The sequence may contain one or more items. Uniquely identifies Dose Reference specified by Dose Reference Number (300A,0012) in Dose Reference Sequence (300A,0010) in RT Prescription Module of referenced RT Plan. Required if Referenced Calculated Dose Reference Sequence (3008,0090) is sent and Referenced Calculated Dose Reference Number (3008,0092) is not sent. It shall not be present otherwise. Uniquely identifies Calculated Dose Reference specified by Calculated Dose Reference Number (3008,0072) within Calculated Dose Reference Sequence (3008,0070). Required if Referenced Calculated Dose Reference Sequence (3008,0090) is sent and Referenced Dose Reference Number (300C,0051) is not sent. It shall not be present otherwise. Calculated Dose (Gy). Required if Referenced Calculated Dose Reference Sequence (3008,0090) is sent. Introduces sequence of recorded Source Applicators. The sequence may contain one or more items. Identification number of the Source Applicator. The value of Source Applicator Number (300A,0290) shall be unique within the Channel in which it is created. User or machine supplied identifier for Source Applicator. Required if Recorded Source Applicator Sequence (3008,0140) is sent. Type of Source Applicator. Required if Recorded Source Applicator Sequence (3008,0140) is sent. Enumerated Values: FLEXIBLE, RIGID. User-defined name for Source Applicator. Length of Source Applicator (mm), defined as the distance between the connector of the applicator and the distal-most position of the source. Required if Recorded Source Applicator Sequence (3008,0140) is sent. Manufacturer of Source Applicator. Distance of path along channel (mm) between adjacent (potential) dwell positions. Required if Source Movement Type (300A,0288) is STEPWISE. Identification number of the Transfer Tube. The value of Transfer Tube Number (300A,02A2) shall be unique within the Channel in which it is created. Length of Transfer Tube of current afterloading Channel (mm). Required if value Transfer Tube Number (300A,02A2) is not zero length. Introduces sequence of Channel Shields associated with current Channel. The sequence may contain one or more items. See RT Plan IOD for description of Channel Shields. Identification number of the Channel Shield. The value of Channel Shield Number (300A,02B2) shall be unique within the Channel in which it is created. Required if Recorded Channel Shield Sequence (3008,0150) is sent. User or machine supplied identifier for Channel Shield. Required if Recorded Channel Shield Sequence (3008,0150) is sent. User-defined name for Channel Shield. Uniquely identifies the referenced Source within the Recorded Source Sequence (3008,0100) for current Application Setup. Date on which the source(s) exited the safe. Required if Recorded Channel Sequence (3008,0130) is sent and Brachy Treatment Type (300A,0202) is not MANUAL. Time on which the source(s) exited the safe. Required if Recorded Channel Sequence (3008,0130) is sent and Brachy Treatment Type (300A,0202) is not MANUAL. Date on which the source(s) returned to the safe. Required if Recorded Channel Sequence (3008,0130) is sent and Brachy Treatment Type (300A,0202) is not MANUAL. Time on which the source(s) returned to the safe. Required if Recorded Channel Sequence (3008,0130) is sent and Brachy Treatment Type (300A,0202) is not MANUAL. Number of control points in Channel. For an N-segment Channel there will be 2N (stepwise movement) or N+1 (continuous movement) control points. Introduces sequence of machine configurations describing this Channel. The sequence may contain two or more items. See RT Plan IOD and C.8.8.22.1 for description of Brachy Control Point Delivered Sequence. Index of current Control Point, starting at 0 for first Control Point. Date when current Control Point occurred. Time when current Control Point occurred. Distance between current Control Point Position and the distal-most possible Source position in current Channel (mm). See RT Plan IOD. Introduces sequence of parameters which were overridden during the administration of the treatment immediately prior to the current control point. The sequence may contain one or more items. Contains the Data Element Tag of the attribute which was overridden. Required if Override Sequence (3008,0060) is sent. Name of operator who authorized override. Required if Override Sequence (3008,0060) is sent. User-defined description of reason for override of parameter specified by Override Parameter Pointer (3008,0062).
Status of the Treatment at the time the Treatment Summary was created. Enumerated Values: NOT_STARTED, ON_TREATMENT, ON_BREAK, SUSPENDED, STOPPED, COMPLETED. See C.8.8.23.1.
The definition of the enumerated values for Current Treatment Status (3008,0200) are defined as follows: NOT_STARTED Patient has not yet begun treatment. ON_TREATMENT Patient is currently undergoing treatment. ON_BREAK Patient is currently not undergoing treatment, but a resumption date is known. SUSPENDED Patient is currently not undergoing treatment, but resumption of treatment is planned at an unknown date. STOPPED Patient has stopped treatment without completing the planned course. COMPLETED Patient completed the planned course of treatment. A change in the Current Treatment Status (or any other field) in a RT Treatment Summary Record Object shall define a new instance of the RT Treatment Summary Record IOD.
Comment on current treatment status. Date of delivery of the first treatment. Date of delivery of the most recent administration. Introduces sequence describing current state of planned vs. delivered fraction groups. The sequence may contain one or more items. References Fraction Group Number (300A,0071) in Fraction Group Sequence (300A,0070) in the referenced RT Plan. Indicates type of fraction group. Required if Fraction Group Summary Sequence (3008,0220) is sent. Enumerated Values: EXTERNAL_BEAM, BRACHY. Number of fractions planned for this fraction group. Required if Fraction Group Summary Sequence (3008,0220) is sent. Number of fractions delivered as of Treatment Summary Report. Required if Fraction Group Summary Sequence (3008,0220) is sent. Introduces sequence describing status of fractions in Fraction Group. The sequence may contain one or more items. Identifies fraction. Required if Fraction Status Summary Sequence (3008,0240) is sent. Date when fraction was delivered. Required if Fraction Status Summary Sequence (3008,0240) is sent. Time when fraction was delivered. Required if Fraction Status Summary Sequence (3008,0240) is sent. Conditions under which treatment was terminated. Required if Fraction Status Summary Sequence (3008,0240) is sent. Enumerated Values: NORMAL = treatment terminated normally OPERATOR = operator terminated treatment MACHINE = machine terminated treatment for other than NORMAL condition UNKNOWN = status at termination unknown Introduces sequence of references to Measured Dose References. The sequence may contain one or more items. Uniquely identifies Dose Reference specified by Dose Reference Number (300A,0012) in Dose Reference Sequence (300A,0010) in RT Prescription Module of referenced RT Plan referenced in Referenced RT Plan Sequence (300C,0002) of RT General Treatment Record Module. User-defined description of Dose Reference. Cumulative Dose delivered to Dose Reference (Gy). Required if Treatment Summary Dose Reference Sequence (3008,00E0) is sent. Introduces sequence of references to Calculated Dose References. The sequence may contain one or more items. Uniquely identifies Dose Reference specified by Dose Reference Number (300A,0012) in Dose Reference Sequence (300A,0010) in RT Prescription Module of referenced RT Plan referenced in Referenced RT Plan Sequence (300C,0002) of RT General Treatment Record Module. User-defined description of Dose Reference. Cumulative Dose delivered to Dose Reference (Gy). Required if Treatment Summary Dose Reference Sequence (3008,0050) is sent.
Introduces sequence of ion tolerance tables to be used for delivery of treatment plan. One or more items shall be included in this sequence. See Note 1. Identification number of the Tolerance Table. The value of Tolerance Table Number (300A,0042) shall be unique within the RT Ion Plan in which it is created. User-defined label for Tolerance Table. Maximum permitted difference (in degrees) between planned and delivered Gantry Angle. Maximum permitted difference (in degrees) between planned and delivered Beam Limiting Device Angle. Introduces sequence of beam limiting device (collimator) tolerances. One or more items may be included in this sequence. Type of beam limiting device (collimator). Enumerated Values: X = symmetric jaw pair in IEC X direction Y = symmetric jaw pair in IEC Y direction ASYMX = asymmetric jaw pair in IEC X direction ASYMY = asymmetric pair in IEC Y direction MLCX = multileaf (multi-element) jaw pair in IEC X direction MLCY = multileaf (multi-element) jaw pair in IEC Y direction Maximum permitted difference (in mm) between planned and delivered leaf (element) or jaw positions for current beam limiting device (collimator). Maximum permitted difference (in degrees) between planned and delivered Patient Support Angle. Maximum permitted difference (in mm) between planned and delivered Table Top Vertical Position. Maximum permitted difference (in mm) between planned and delivered Table Top Longitudinal Position. Maximum permitted difference (in mm) between planned and delivered Table Top Lateral Position. Maximum permitted difference (in degrees) between planned and delivered Table Top Pitch Angle. Maximum permitted difference (in degrees) between planned and delivered Table Top Roll Angle. Maximum permitted difference (in mm) between planned and delivered Snout Position. Introduces sequence of setup and/or treatment beams for current RT Ion Plan. One or more items shall be included in this sequence. Identification number of the Beam. The value of Beam Number (300A,00C0) shall be unique within the RT Ion Plan in which it is created. See section C.8.8.25.1. User-defined name for Beam. See section C.8.8.25.1. User-defined description for Beam. See section C.8.8.25.1. Motion characteristic of Beam. Enumerated Values: STATIC = all beam parameters remain unchanged during delivery DYNAMIC = one or more beam parameters changes during delivery Particle type of Beam. Defined Terms: PHOTON PROTON ION Mass number of radiation. Required if Radiation Type (300A,00C6) is ION Atomic number of radiation. Required if Radiation Type (300A,00C6) is ION Charge state of radiation. Required if Radiation Type (300A,00C6) is ION The method of beam scanning to be used during treatment. Defined Terms: NONE = No beam scanning is performed. UNIFORM = The beam is scanned between control points to create a uniform lateral fluence distribution across the field. MODULATED = The beam is scanned between control points to create a modulated lateral fluence distribution across the field. User-defined name identifying treatment machine to be used for beam delivery. See section C.8.8.25.2. Manufacturer of the equipment to be used for beam delivery. Institution where the equipment is located that is to be used for beam delivery. Mailing address of the institution where the equipment is located that is to be used for beam delivery. Department in the institution where the equipment is located that is to be used for beam delivery. Manufacturer's model name of the equipment that is to be used for beam delivery. Manufacturer's serial number of the equipment that is to be used for beam delivery. Measurement unit of machine dosimeter. Enumerated Values: MU = Monitor Unit NP = number of particles Uniquely identifies Tolerance Table specified by Tolerance Table Number (300A,0042) within Tolerance Table Sequence in RT Ion Tolerance Tables Module. These tolerances are to be used for verification of treatment machine settings. Distance (in mm) from virtual source position to gantry rotation axis or nominal isocenter position (fixed beam-lines) of the equipment to be used for beam delivery. Specified by a numeric pair - the VSAD in the IEC Gantry X direction followed by the VSAD in the IEC Gantry Y direction. The VSAD is commonly used for designing apertures in contrast to the effective source-axis-distance (ESAD) that is commonly used with the inverse square law for calculating the dose decrease with distance. See section C.8.8.25.4. Introduces sequence of beam limiting device (collimator) jaw or leaf (element) sets. One or more items may be included in this sequence. Type of beam limiting device (collimator). Enumerated Values: X = symmetric jaw pair in IEC X direction Y = symmetric jaw pair in IEC Y direction ASYMX = asymmetric jaw pair in IEC X direction ASYMY = asymmetric pair in IEC Y direction MLCX = multileaf (multi-element) jaw pair in IEC X direction MLCY = multileaf (multi-element) jaw pair in IEC Y direction Isocenter to beam limiting device (collimator) distance (in mm) of the equipment that is to be used for beam delivery. See section C.8.8.25.4. Number of leaf (element) or jaw pairs (equal to 1 for standard beam limiting device jaws). Boundaries of beam limiting device (collimator) leaves (in mm) in IEC BEAM LIMITING DEVICE coordinate axis appropriate to RT Beam Limiting Device Type (300A,00B8), i.e. X-axis for MLCY, Y-axis for MLCX. Contains N+1 values, where N is the Number of Leaf/Jaw Pairs (300A,00BC), starting from Leaf (Element) Pair 1. Required if RT Beam Limiting Device Type (300A,00B8) is MLCX or MLCY. See section C.8.8.25.3. Uniquely identifies Patient Setup to be used for current beam, specified by Patient Setup Number (300A,0182) within Patient Setup Sequence of RT Patient Setup Module. Introduces sequence of reference images used for validation of current beam. One or more items may be included in this sequence. Uniquely identifies Reference Image within Referenced Reference Image Sequence (300C,0042). Delivery Type of treatment. Defined Terms: TREATMENT = normal patient treatment OPEN_PORTFILM = portal image acquisition with open field (the source of radiation is specified by Radiation Type (300A,00C6)) TRMT_PORTFILM = portal image acquisition with treatment port (the source of radiation is specified by Radiation Type (300A,00C6)) CONTINUATION = continuation of interrupted treatment SETUP = no treatment beam is applied for this RT Beam. To be used for specifying the gantry, couch, and other machine positions where X-Ray set-up images or measurements shall be taken. Introduces sequence of related SOP Class/Instance pairs describing related instances of RT Dose (for grids, isodose curves, and named/unnamed point doses). One or more items may be included in this sequence. Number of wedges associated with current beam. Shift of the wedge tray induced on the range of the ion beam as measured in water (in mm). Introduces sequence of treatment wedges. Required if Number of Wedges (300A,00D0) is non-zero. The number of items shall be identical to the value of Number of Wedges (300A,00D0). Identification number of the Wedges. The value of Wedge Number (300A,00D2) shall be unique within the Beam in which it was created. Typer of wedge (if any) defined for Beam. Defined Terms: STANDARD = standard (static) wedge MOTORIZED = single wedge that can be removed from beam remotely. PARTIAL_STANDARD = wedge does not extend across the whole field and is operated manually. PARTIAL_MOTORIZ = wedge does not extend across the whole field and can be removed from beam remotely. User-supplied identifier for Wedge. An accessory identifier to be read by a device such as a bar code reader. Nominal wedge angle (degrees). Orientation of wedge, i.e. orientation of IEC WEDGE FILTER coordinate system with respect to the IEC BEAM LIMITING DEVICE coordinate systems (degrees). Isocenter to downstream edge of wedge tray (mm). See section C.8.8.25.4 Number of compensators associated with current Beam. Water-Equivalent thickness of the compensator tray (in mm) parallel to radiation beam axis. Introduces sequence of compensators. Required if Number of Compensators (300A,00E0) is non-zero. The number of items shall be identical to the value of Number of Compensators (300A,00E0). User defined description for the compensator. Identification number of the Compensator. The value of Compensator Number (300A,00E4) shall be unique within the Beam in which it is created. User-supplied identifier for material used to manufacture Compensator. User-supplied identifier for the compensator. An accessory identifier to be read by a device such as a bar code reader. Isocenter to compensator tray attachment edge distance (in mm) for current range compensator. Required if Compensator Mounting Position (300A,02E1) is not DOUBLE_SIDED. See section C.8.8.25.4 Indicates presence or absence of geometrical divergence of the range compensator. Enumerated Values: PRESENT = the range compensator is shaped according to the beam geometrical divergence. ABSENT = the range compensator is not shaped according to the beam geometrical divergence. Indicates on which side of the Compensator Tray the compensator is mounted. Enumerated Values: PATIENT_SIDE = the Compensator is mounted on the side of the Compensator Tray that is towards the patient. SOURCE_SIDE = the Compensator is mounted on the side of the Compensator Tray that is towards the radiation source. DOUBLE_SIDED = the Compensator has a shaped (i.e. non-flat) surface on both sides of the Compensator Tray. Number of rows in the range compensator. A row is defined to be in the X direction of the IEC Beam Limiting Device Coordinate system. Number of columns in the range compensator. A column is defined to be in the Y direction of the IEC Beam Limiting Device Coordinate system. Physical distance (in mm) between the center of each pixel projected onto machine isocentric plane. Specified by a numeric pair - adjacent row spacing followed by adjacent column spacing. See 10.7.1.3 for further explanation of the value order. The x and y coordinates of the upper left hand corner (first pixel transmitted) of the range compensator, projected onto the machine isocentric plane in the IEC BEAM LIMITING DEVICE coordinate system (mm). The offset distance (in mm) applied to the x coordinate of the Compensator Position (300A,00EA) for even numbered rows. Required if the compensator pattern is hexogonal. A data stream of the pixel samples that comprise the range compensator, expressed as physical thickness (in mm), either parallel to radiation beam axis if Compensator Divergence (300A,02E0) equals ABSENT, or divergent according to the beam geometrical divergence if Compensator Divergence (300A,02E0) equals PRESENT. The order of pixels sent is left to right, top to bottom (upper left pixel, followed by the remainder of row 1, followed by the remainder of the rows). A data stream of the pixel samples that comprise the distance from the isocenter to the compensator surface closest to the radiation source (in mm). The order of pixels sent is left to right, top to bottom (upper left pixel, followed by the remainder of row 1, followed by the remainder of the rows). Required if Material ID (300A,00E1) is non-zero length, and Compensator Mounting Position (300A,02E1) is DOUBLE_SIDED. See sections C.8.8.14.9 and C.8.8.25.4 Compensator Linear Stopping Power Ratio, relative to water, at the beam energy specified by the Nominal Beam Energy (300A,0114) of the first Control Point of the Ion Control Point Sequence (300A,03A8). The diameter (in mm) of the milling tool to be used to create the compensator. The diameter is expressed as the actual physical size and not a projected size at isocenter. Number of boli associated with current Beam. Introduces sequence of boli associated with Beam. Required if Number of Boli (300A,00ED) is non-zero. The number of items shall be identical to the value of Number of Boli (300A,00ED). Uniquely identifies ROI representing the Bolus specified by ROI Number (3006,0022) in Structure Set ROI Sequence (3006,0020) in Structure Set Module within RT Structure Set in Referenced Structure Set Sequence (300C,0060) in RT General Plan Module. An accessory identifier to be read by a device such as a bar code reader. Number of shielding blocks associated with Beam. Water-Equivalent thickness of the block tray (in mm) parallel to radiation beam axis. Introduces sequence of blocks associated with Beam. Required if Number of Blocks (300A,00F0) is non-zero. The number of items shall be identical to the value of Number of Blocks (300A,00F0). User-supplied identifier for block tray. An accessory identifier to be read by a device such as a bar code reader. Isocenter to downstream edge of block tray (mm). See section C.8.8.25.4 Type of block. See section C.8.8.14.4. Enumerated Values: SHIELDING = blocking material is inside contour APERTURE = blocking material is outside contour Indicates presence or otherwise of geometrical divergence. Enumerated Values: PRESENT = block edges are shaped for beam divergence ABSENT = block edges are not shaped for beam divergence Indicates on which side of the Block Tray the block is mounted. Enumerated Values; PATIENT_SIDE = the block is mounted on the side of the Block Tray that is towards the patient. SOURCE_SIDE = the block is mounted on the side of the Block Tray that is towards the radiation source. Identification number of the Block. The value of Block Number (300A,00FC) shall be unique within the Beam in which it is created. User-defined name for block. User-supplied identifier for material used to manufacture Block. Physical thickness of block (in mm) parallel to radiation beam axis. See section C.8.8.14.4. Number of (x,y) pairs defining the block edge. A data stream of (x,y) pairs that comprise the block edge. The number of pairs shall be equal to Block Number of Points (300A,0104), and the vertices shall be interpreted as a closed polygon. Coordinates are projected onto the machine isocentric plane in the IEC BEAM LIMITING DEVICE coordinate system (mm). Introduces sequence of Snouts associated with Beam. Only a single item shall be permitted in this sequence. User or machine supplied identifier for Snout. An accessory identifier to be read by a device such as a bar code reader. Introduces sequence of Applicators associated with Beam. Only a single item shall be permitted in this sequence. User or machine supplied identifier for Applicator. See section C.8.8.14.12 An accessory identifier to be read by a device such as a bar code reader. Type of applicator. Defined Terms: ION_SQUARE = square ion applicator ION_RECT = rectangluar ion applicator ION_CIRC = circular ion applicator ION_SHORT = short ion applicator ION_OPEN = open (dummy) ion applicator INTEROPERATIVE = interoperative (custom) applicator STEREOTACTIC = stereotactic applicator User-defined description for Applicator. Introduces a Sequence of General Accessories associated with this Beam. One or more items may be included in this sequence. Identification Number of the General Accessory. The value shall be unique within the sequence. User or machine supplied identifier for General Accessory. User supplied description of General Accessory. Specifies the type of accessory. Defined Terms: GRATICULE = Accessory tray with a radio-opaque grid IMAGE_DETECTOR = Image acquisition device positioned in the beam line RETICLE = Accessory tray with radio-transparent markers or grid Machine-readable identifier for this accessory Number of range shifters associated with current beam. Introduces sequence of range shifters associated with Beam. Required if Number of Range Shifters (300A,0312) is non-zero. The number of items shall be identical to the value of Number of Range Shifters (300A,0312). Identification number of the Range Shifter. The value of Range Shifter Number (300A,0316) shall be unique within the Beam in which it is created. User or machine supplied identifier for Range Shifter. An accessory identifier to be read by a device such as a bar code reader. Type of Range Shifter. Defined Terms: ANALOG = Device is variable thickness and is composed of opposing sliding wedges, water column or similar mechanism. BINARY = Device is composed of different thickness materials that can be moved in or out of the beam in various stepped combinations. User defined description of Range Shifter. Number of lateral spreading devices associated with current beam. Introduces sequence of lateral spreading devices associated with Beam. Required if Number of Lateral Spreading Devices (300A,0330) is non-zero. The number of items shall be identical to the value of Number of Lateral Spreading Devices (300A,0330). Identification number of the Lateral Spreading Device. The value of Lateral Spreading Device Number (300A,0334) shall be unique within the Beam in which it is created. User or machine supplied identifier for Lateral Spreading Device. An accessory identifier to be read by a device such as a bar code reader. Type of Lateral Spreading Device. Defined Terms: SCATTERER = metal placed into the beam path to scatter charged particles laterally. MAGNET = nozzle configuration of magnet devices to expand beam laterally. User-defined description for lateral spreading device. Number of range modulators associated with current beam. Introduces sequence of range modulators associated with Beam. Required if Number of Range Modulators (300A,0340) is non-zero. The number of items shall be identical to the value of Number of Range Modulators (300A,0340). Identification number of the Range Modulator. The value of Range Modulator Number (300A,0344) shall be unique within the Beam in which it is created. User or machine supplied identifier for Range Modulator. An accessory identifier to be read by a device such as a bar code reader. Type of Range Modulator. Defined Terms: FIXED = fixed modulation width and weights using ridge filter or constant speed wheel with constant beam current WHL_FIXEDWEIGHTS = selected wheel/track (Range Modulator ID) is spinning at constant speed. Modulation width is adjusted by switching constant beam current on and off at wheel steps indicated by Range Modulator Gating Values. WHL_MODWEIGHTS = selected wheel/track (Range Modulator ID) is spinning at constant speed. Weight per wheel step is adjusted by modulating beam current according to selected Beam Current Modulation ID (300A,034C). Only one item in the Range Modulator Sequence (300A,0342) can have a Range Modulator Type (300A,0348) of WHL_MODWEIGHTS. User-defined description of Range Modulator. User-supplied identifier for the beam current modulation pattern. Required if Range Modulator Type (300A,0348) is WHL_MODWEIGHTS Azimuthal angle (degrees) of the fixation light coordinate around IEC BEAM LIMITING DEVICE Y-axis. Used for eye treatments. See section C.8.8.25.6.4. Polar angle (degrees) of the fixation light coordinate. Used for eye treatments. See section C.8.8.25.6.4. Value of Cumulative Meterset Weight (300A,0134) for final Control Point in Ion Control Point Sequence (300A,03A8). Required if Cumulative Meterset Weight is non-null in Control Points specified within Ion Control Point Sequence. See section C.8.8.14.1. Number of control points in Beam. Value shall be greater than or equal to 2. Introduces sequence of machine configurations describing Ion treatment beam. The number of items shall be identical to the value of Number of Control Points (300A,0110). See C.8.8.25.7.
The control point sequence for RT Ion Beams is defined using the same rule set as in the RT Beams module (see Section C.8.8.14.5 Control Point Sequence). Specifically, the following rules apply:
Index of current Control Point, starting at 0 for first Control Point. Cumulative weight to current control point. Cumulative Meterset Weight for the first item in Control Point Sequence shall always be zero. Cumulative Meterset Weight for the final item in Ion Control Point Sequence shall always be equal to Final Cumulative Meterset Weight. Introduces a sequence of Dose References for current Beam. One or more items may be included in this sequence. Uniquely identifies Dose Reference specified by Dose Reference Number (300A,0012) in Dose Reference Sequence (300A,0010) in RT Prescription Module. Coefficient used to calculate cumulative dose contribution from this Beam to the referenced Dose Reference at the current Control Point. Nominal Beam Energy at control point in MeV per nucleon. Defined at nozzle entrance before all Beam Modifiers. Required for first item of Control Point Sequence, or if Nominal Beam Energy changes during Beam, and KVp (0018,0060) is not present. Peak kilo voltage output of the setup X-Ray generator to be used. Required for first item of Control Point Sequence, or if KVp changes during setup, and Nominal Beam Energy (300A,0114) is not present. Specifies the speed of delivery of the specified dose in units specified by Primary Dosimeter Unit (300A,00B3) per minute. Introduces sequence of Wedge positions for current control point. Required for first item of Ion Control Point Sequence if Number of Wedges (300A,00D0) is non-zero, and in subsequent control points if Wedge Position (300A,0118) or Wedge Thin Edge Position (300A,00DB) changes during beam. The number of items shall be identical to the value of Number of Wedges (300A,00D0). Uniquely references Wedge described by Wedge Number (300A,00D2) in Wedge Sequence (300A,00D1). Position of Wedge at current Control Point. Enumerated Values: IN OUT Closest distance from the central axis of the beam along a wedge axis to the thin edge as projected to the machine isocentric plane (mm). Value is positive is the wedge does not cover the central axis, negative if it does. Required if Wedge Type (300A,00D3) of the wedge referenced by Referenced Wedge Number (300C,00C0) is PARTIAL_STANDARD or PARTIAL_MOTORIZ. See section C.8.8.25.6.4. Introduces sequence of Range Shifter settings for the current control point. One or more items shall be included in this sequence. Required for first item of Control Point Sequence if Number of Range Shifters (300A,0312) is non-zero, or if Range Shifter Setting (300A,0362) changes during Beam. Uniquely references Range Shifter described by Range Shifter Number (300A,0316) in Range Shifter Sequence (300A,0314). Machine specific setting attribute for the range shifter. The specific encoding of this value should be documented in a Conformance Statement. See section C.8.8.25.5. Isocenter to downstream edge of range shifter (mm) at current control point. See section C.8.8.25.4 Water equivalent thickness (in mm) of the range shifter at the central axis for the beam energy incident upon the device. Introduces sequence of Lateral Spreading Device settings for the current control point. One or more items shall be included in this sequence. Required for first item of Control Point Sequence if Number of Lateral Spreading Devices (300A,0330) is non-zero, or if Lateral Spreading Device Setting (300A,0372) changes during Beam. Uniquely references Lateral Spreading Device described by Lateral Spreading Device Number (300A,0334) in Lateral Spreading Device Sequence (300A,0332). Machine specific setting attribute for the lateral spreading device. The specific encoding of this value should be documented in a Conformance Statement. See section C.8.8.25.5. Isocenter to downstream edge of Lateral Spreading Device (mm) at current control point. See section C.8.8.25.4 Water equivalent thickness (in mm) of the lateral spreading device at the central axis for the beam energy incident upon the device. Introduces sequence of Range Modulator Settings for current control point. One or more items shall be included in this sequence. Required for first item of Control Point Sequence if Number of Range Modulators (300A,0340) is non-zero, or if Range Modulator Setting changes during Beam. Uniquely references Range Modulator described by Range Modulator Number (300A,0344) in Range Modulator Sequence (300A,0342). Start position defines the range modulator position at which the beam is switched on. Required if Range Modulator Type (300A,0348) of the range modulator referenced by Referenced Range Modulator Number (300C,0104) is WHL_MODWEIGHTS or WHL_FIXEDWEIGHTS Stop position defines the range modulator position at which the beam is switched off. Required if Range Modulator Type (300A,0348) of the range modulator referenced by Referenced Range Modulator Number (300C,0104) is WHL_MODWEIGHTS or WHL_FIXEDWEIGHTS If Range Modulator Type (300A,0348) is WHL_MODWEIGHTS or WHL_FIXEDWEIGHTS: Water equivalent thickness (in mm) of the range modulator at the position specified by Range Modulator Gating Start Value (300A,0382). If Range Modulator Type (300A,0348) is FIXED: Minimum water equivalent thickness (in mm) of the range modulator. If Range Modulator Type (300A,0348) is WHL_MODWEIGHTS or WHL_FIXEDWEIGHTS: Water equivalent thickness (in mm) of the range modulator at the position specified by Range Modulator Gating Stop Value (300A,0384). If Range Modulator Type (300A,0348) is FIXED: Maximum water equivalent thickness (in mm) of the range modulator. Isocenter to downstream edge of range modulator (mm) at current control point. See section C.8.8.25.4 Gantry angle of radiation source, i.e. orientation of IEC GANTRY coordinate system with respect to IEC FIXED REFERENCE coordinate system (degrees). Required for first item of Control Point Sequence, or if Gantry Angle changes during Beam. Direction of Gantry Rotation when viewing gantry from isocenter, for segment following Control Point. Required for first item of Control Point Sequence, or if Gantry Rotation Direction changes during Beam. See section C.8.8.14.8. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation Gantry Pitch Angle of the radiation source, i.e. the rotation of the IEC GANTRY coordinate system about the X-axis of the IEC GANTRY coordinate system (degrees). Required for first item of Control Point Sequence, or if Gantry Pitch Rotation Angle changes during Beam. See C.8.8.25.6.5.
The Gantry Pitch angle is not defined in IEC 61217. This angle is defined in the DICOM standard in a way compatible with the current notion of IEC by introducing it as rotation of the IEC GANTRY System as indicated below. The Gantry Pitch Angle is defined as the rotation of the coordinate axes Yg, Zg about axis Xg by an angle g; see Figure C.8.8.25-7. An increase in the value of angle g corresponds to the clockwise rotation as viewed from the isocenter along the positive Xg axis Figure C.8.8.25-7 Gantry Pitch Angle
Direction of Gantry Pitch Angle when viewing along the positive X-axis of the IEC GANTRY coordinate system, for segment following Control Point. Required for first item of Control Point Sequence, or if Gantry Pitch Rotation Direction changes during Beam. See C.8.8.14.8 and C.8.8.25.6.5. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Beam Limiting Device angle, i.e. orientation of IEC BEAM LIMITING DEVICE coordinate system with respect to IEC GANTRY coordinate system (degrees). Required for first item of Control Point Sequence, or if Beam Limiting Device Angle changes during Beam. Direction of Beam Limiting Device Rotation when viewing beam limiting device (collimator) from radiation source, for segment following Control Point. Required for first item of Control Point Sequence, or if Beam Limiting Device Rotation Direction changes during Beam. See section C.8.8.14.8. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation User-supplied or machine code identifier for machine configuration to produce beam spot. This may be the nominal spot size or some other machine specific value. Required if Scan Mode (300A,0308) is MODULATED. Number of spot positions used to specify scanning pattern for current segment beginning at control point. Required if Scan Mode (300A,0308) is MODULATED. The x and y coordinates of the scan spots are defined as projected onto the machine isocentric plane in the IEC GANTRY coordinate system (mm). Required if Scan Mode (300A,0308) is MODULATED. Contains 2N values where N is the Number of Scan Spot Positions (300A,0392). A data set of meterset weights corresponding to scan spot positions. The order of weights matches the positions in Scan Spot Positions (300A,0394). The sum contained in all meterset weights shall match the difference of the cumulative meterset weight of the current control point to the following control point. Required if Scan Mode (300A,0308) is MODULATED. The Scanning Spot Size as calculated using the Full Width Half Maximum (FWHM). Specified by a numeric pair - the size measured in air at isocenter in IEC GANTRY X direction followed by the size in the IEC GANTRY Y direction (mm). The number of times the scan pattern given by Scan Spot Position Map (300A,0394) and Scan Spot Meterset Weights (300A,0396) shall be applied at the current control point. To obtain the meterset weight per painting, the values in the Scan Spot Meterset Weights (300A,0396) should be divided by the value of this attribute. Required if Scan Mode (300A,0308) is MODULATED. Patient Support angle, i.e. orientation of IEC PATIENT SUPPORT (turntable) coordinate system with respect to IEC FIXED REFERENCE coordinate system (degrees). Required for first item of Control Point Sequence, or if Patient Support Angle changes during Beam. Direction of Patient Support Rotation when viewing table from above, for segment following Control Point. Required for first item of Control Point Sequence, or if Patient Support Rotation Direction changes during Beam. See section C.8.8.14.8. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation Table Top Pitch Angle, i.e. the rotation of the IEC TABLE TOP coordinate system about the X-axis of the IEC TABLE TOP coordinate system (degrees). Required for first item of Control Point Sequence, or if Table Top Pitch Angle changes during Beam. See section C.8.8.25.6.2. Direction of Table Top Pitch Rotation when viewing the table along the positive X-axis of the IEC TABLE TOP coordinate system, for segment following Control Point. Required for first item of Control Point Sequence, or if Table Top Pitch Rotation Direction changes during Beam. See C.8.8.14.8 and C.8.8.25.6.2. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Table Top Roll Angle, i.e. the rotation of the IEC TABLE TOP coordinate system about the Y-axis of the IEC TABLE TOP coordinate system (degrees). Required for first item of Control Point Sequence, or if Table Top Roll Angle changes during Beam. See section C.8.8.25.6.2. Direction of Table Top Roll Rotation when viewing the table along the positive Y-axis of the IEC TABLE TOP coordinate system, for segment following Control Point. Required for first item of Control Point Sequence, or if Table Top Roll Rotation Direction changes during Beam. See C.8.8.14.8 and C.8.8.25.6.2. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation.
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Angle (in degrees) of the head fixation for eye treatments with respect to the Table Top Pitch Angle (300A,0140) coordinate system. Positive head fixation angle is the same direction as positive Table Top pitch. See section C.8.8.25.6.4. Table Top Vertical position in IEC TABLE TOP coordinate system (mm). Required for first item of Control Point Sequence, or if Table Top Vertical Position changes during Beam. See section C.8.8.14.6. Table Top Longitudinal position in IEC TABLE TOP coordinate system (mm). Required for first item of Control Point Sequence, or if Table Top Longitudinal Position changes during Beam. See section C.8.8.14.6. Table Top Lateral position in IEC TABLE TOP coordinate system (mm). Required for first item of Control Point Sequence, or if Table Top Lateral Position changes during Beam. See section C.8.8.14.6. Axial position of the snout (in mm) measured from isocenter to the downstream side of the snout (without consideration of variable length elements such as blocks, MLC and/or compensators). Required for first item in Control Point Sequence, or if Snout Position changes during Beam. Isocenter coordinates (x,y,z) in the patient based coordinate system described in C.7.6.2.1.1 (mm). Required for first item of Segment Control Point Sequence, or if Segment Isocenter Position changes during Beam. Patient surface entry point coordinates (x,y,z), along the central axis of the beam, in the patient based coordinate system described in C.7.6.2.1.1 (mm).
Name of operator administering treatment session. Identifier of fraction group within referenced RT Ion Plan. Total number of treatments (fractions) planned for current fraction group. Measurement unit of the machine dosimeter. Enumerated Values: MU = Monitor Units NP = Number of Particles Introduces sequence of setup and/or treatment beams administered during treatment session. One or more items shall be included in this sequence. References Beam specified by Beam Number (300A,00C0) in Ion Beam Sequence (300A,03A2) in RT Ion Beams Module within the referenced RT Ion Plan. User-defined name for Beam. See section C.8.8.25.1. User-defined description for Beam. See section C.8.8.25.1. Motion characteristic of Beam. Enumerated Values: STATIC = all beam parameters remain unchanged during delivery DYNAMIC = one or more beam parameters changes during delivery Particle type of Beam. Defined Terms: PHOTON PROTON ION Mass number of radiation. Required if Radiation Type (300A,00C6) is ION Atomic number of radiation. Required if Radiation Type (300A,00C6) is ION Charge state of radiation. Required if Radiation Type (300A,00C6) is ION The method of beam scanning used during treatment. Defined Terms: NONE = No beam scanning is performed. UNIFORM = The beam is scanned between control points to create a uniform lateral fluence distribution across the field. MODULATED = The beam is scanned between control points to create a modulated lateral fluence distribution across the field. Uniquely identifies Ion Tolerance Table specified by Tolerance Table Number (300A,0042) within Ion Tolerance Table Sequence in RT Ion Tolerance Tables Module. These tolerances are to be used for verification of treatment machine settings. Introduces sequence of beam limiting device (collimator) jaw or leaf (element) sets. One or more items may be included in this sequence. Type of beam limiting device (collimator). Enumerated Values: X = symmetric jaw pair in IEC X direction Y = symmetric jaw pair in IEC Y direction ASYMX = asymmetric jaw pair in IEC X direction ASYMY = asymmetric pair in IEC Y direction MLCX = multileaf (multi-element) jaw pair in IEC X direction MLCY = multileaf (multi-element) jaw pair in IEC Y direction Number of leaf (element) or jaw pairs (equal to 1 for standard beam limiting device jaws). Uniquely identifies Ion Patient Setup to be used for current beam, specified by Patient Setup Number (300A,0182) within Patient Setup Sequence of RT Patient Setup Module. Introduces sequence of verification images obtained during delivery of current beam. One or more items may be included in this sequence. See C.8.8.14.2.
The Planned Verification Image Sequence (300A,00CA) contains attributes which describe the planned verification images to be acquired during current beam. The Start Cumulative Meterset Weight (300C,0008) specifies the Cumulative Meterset Weight at which image acquisition is to begin. If Meterset Exposure (3002,0032) is present in a sequence item and End Cumulative Meterset Weight (300C,0009) is not present then a single image shall be acquired using the meterset duration specified in Meterset Exposure (3002,0032). If End Cumulative Meterset Weight (300C,0009) is present in a sequence item and Meterset Exposure (3002,0032) is not present then a single image shall be acquired over the beam delivery from Start Cumulative Meterset Weight (300C,0008) to End Cumulative Meterset Weight (300C,0009). If both Meterset Exposure (3002,0032) and End Cumulative Meterset Weight (300C,0009) are present in a sequence item then images shall be acquired every Meterset Exposure (3002,0032) from Start Cumulative Meterset Weight (300C,0008) to End Cumulative Meterset Weight (300C,0009). No images shall extend past End Cumulative Meterset Weight (300C,0009).
Introduces sequence of doses measured during treatment delivery for current Beam. The sequence may contain one or more items. Uniquely references Dose Reference specified by Dose Reference Number (300A,0012) in Dose Reference Sequence (300A,0010) in RT Prescription Module of referenced RT Ion Plan. Required if Referenced Measured Dose Reference Number (3008,0082) is not sent. Uniquely references Measured Dose Reference specified by Measured Dose Reference Number (3008,0064) in Measured Dose Reference Sequence (3008,0010). Required if Referenced Dose Reference Number (300C,0051) is not sent. Measured Dose in units specified by Dose Units (3004,0002) in sequence referenced by Measured Dose Reference Sequence (3008,0010) or Dose Reference Sequence (300A,0010) in RT Prescription Module of Referenced RT Ion Plan as defined above. Introduces sequence of doses estimated for each treatment delivery. The sequence may contain one or more items. Uniquely identifies Dose Reference specified by Dose Reference Number (300A,0012) in Dose Reference Sequence (300A,0010) in RT Prescription Module of referenced RT Ion Plan. Required if Referenced Calculated Dose Reference Number (3008,0092) is not sent. Uniquely identifies Calculated Dose Reference specified by Calculated Dose Reference Number (3008,0072) within Calculated Dose Reference Sequence (3008,0070). Required if Referenced Dose Reference Number (300C,0051) is not sent. Calculated Dose (Gy). Number of wedges associated with current beam. Introduces sequence of treatment wedges. Required if Number of Wedges (300A,00D0) is non-zero. One or more items may be included in this sequence. The number of items shall be identical to the value of Number of Wedges (300A,00D0). Identification number of the Wedges. The value of Wedge Number (300A,00D2) shall be unique within the Beam in which it was created. Type of wedge (if any) defined for Beam. Defined Terms: STANDARD = standard (static) wedge MOTORIZED = single wedge that can be removed from beam remotely. PARTIAL_STANDARD = wedge does not extend across the whole field and is operated manually. PARTIAL_MOTORIZ = wedge does not extend across the whole field and can be removed from beam remotely. User-supplied identifier for Wedge. An accessory identifier to be read by a device such as a bar code reader. Nominal wedge angle (degrees). Orientation of wedge, i.e. orientation of IEC WEDGE FILTER coordinate system with respect to the IEC BEAM LIMITING DEVICE coordinate systems (degrees). Number of range compensators associated with current Beam. Introduces sequence of treatment compensators. Required if Number of Compensators (300A,00E0) is non-zero. One or more items may be included in this sequence. The number of items shall be identical to the value of Number of Compensators (300A,00E0). Uniquely identifies compensator specified by Compensator Number (300A,00E4) within Beam referenced by Referenced Beam Number (300C,0006). User-supplied identifier for compensator. An accessory identifier to be read by a device such as a bar code reader. Number of boli associated with current Beam. Introduces sequence of boli associated with Beam. Required if Number of Boli (300A,00ED) is non-zero. One or more items may be included in this sequence. The number of items shall be identical to the value of Number of Boli (300A,00ED). Uniquely identifies ROI representing the Bolus specified by ROI Number (3006,0022) in Structure Set ROI Sequence (3006,0020) in Structure Set Module within RT Structure Set in Referenced Structure Set Sequence (300C,0060) in RT General Plan Module. An accessory identifier to be read by a device such as a bar code reader. Number of shielding blocks associated with Beam. Introduces sequence of blocks associated with Beam. Required if Number of Blocks (300A,00F0) is non-zero. One or more items may be included in this sequence. The number of items shall be identical to the value of Number of Blocks (300A,00F0). User-supplied identifier for block tray. An accessory identifier to be read by a device such as a bar code reader. Uniquely identifies block specified by Block Number (300A,00FC) within Beam referenced by Referenced Beam Number (300C,0006). User-defined name for block. Introduces sequence of Snouts associated with Beam. Required if Snout Sequence (300A,030C) is included in the RT Ion Plan referenced within the Referenced RT Plan Sequence (300C,0002). Only a single item shall be permitted in this sequence. User or machine supplied identifier for Snout. An accessory identifier to be read by a device such as a bar code reader. Introduces sequence of Applicators associated with Beam. Required if Applicator Sequence (300A,0107) is included in the RT Ion Plan referenced within the Referenced RT Plan Sequence (300C,0002). Only a single item shall be permitted in this sequence. User or machine supplied identifier for Applicator. See C.8.8.14.12 An accessory identifier to be read by a device such as a bar code reader. Type of applicator. Defined Terms: ION_SQUARE = square ion applicator ION_RECT = rectangluar ion applicator ION_CIRC = circular ion applicator ION_SHORT = short ion applicator ION_OPEN = open (dummy) ion applicator INTEROPERATIVE = interoperative (custom) applicator STEREOTACTIC = stereotactic applicator User-defined description for Applicator. Introduces a Sequence of General Accessories associated with this Beam. One or more items may be included in this sequence. Identification Number of the General Accessory. The value shall be unique within the sequence. User or machine supplied identifier for General Accessory. User supplied description of General Accessory. Specifies the type of accessory. Defined Terms: GRATICULE = Accessory tray with a radio-opaque grid IMAGE_DETECTOR = Image acquisition device positioned in the beam line RETICLE = Accessory tray with radio-transparent markers or grid Machine-readable identifier for this accessory Number of range shifters associated with current beam. Introduces sequence of range shifters recorded with Beam. Required if Number of Range Shifters (300A,0312) is non-zero. One or more items may be included in this sequence. The number of items shall be identical to the value of Number of Range Shifters (300A,0312). Uniquely identifies range shifter specified by Range Shifter Number (300A,0316) within Beam referenced by Referenced Beam Number (300C,0006). User or machine supplied identifier for Range Modulator. An accessory identifier to be read by a device such as a bar code reader. Number of lateral spreading devices associated with current beam. Introduces sequence of lateral spreading devices associated with Beam. Required if Number of Lateral Spreading Devices (300A,0330) is non-zero. One or more items may be included in this sequence. The number of items shall be identical to the value of Number of Lateral Spreading Devices (300A,0330). Uniquely identifies lateral spreading device specified by Lateral Spreading Device Number (300A,0334) within Beam referenced by Referenced Beam Number (300C,0006). User or machine supplied identifier for Lateral Spreading Device. An accessory identifier to be read by a device such as a bar code reader. Number of range modulators associated with current beam. Introduces sequence of range modulators associated with Beam. Required if Number of Range Modulators (300A,0340) is non-zero. One or more items may be included in this sequence. The number of items shall be identical to the value of Number of Range Modulators (300A,0340). Uniquely identifies range modulator specified by Range Modulator Number (300A,0344) within Beam referenced by Referenced Beam Number (300C,0006). User or machine supplied identifier for Range Modulator. An accessory identifier to be read by a device such as a bar code reader. Type of Range Modulator. Defined Terms: FIXED = fixed modulation width and weights using ridge filter or constant speed wheel with constant beam current WHL_FIXEDWEIGHTS = selected wheel/track (Range Modulator ID) is spinning at constant speed. Modulation width is adjusted by switching constant beam current on and off at wheel steps indicated by Range Modulator Interrupt Values WHL_MODWEIGHTS = selected wheel/track (Range Modulator ID) is spinning at constant speed. Weight per wheel step is adjusted by modulating beam current according to selected Beam Current Modulation ID (300A,034C) Only one item in the Recorded Range Modulator Sequence (3008,00F6) can have a Range Modulator Type (300A,0348) of WHL_MODWEIGHTS. User-supplied identifier for the beam current modulation pattern. Required if Range Modulator Type (300A,0348) is WHL_MODWEIGHTS Azimuthal angle (degrees) of the fixation light coordinate around IEC PATIENT SUPPORT Y-axis. Used for eye treatments. See section C.8.8.25.6.4. Polar angle (degrees) of the fixation light coordinate. Used for eye treatments. See section C.8.8.25.6.4. Fraction number for this beam administration. Delivery Type of treatment. Defined Terms: TREATMENT = normal patient treatment OPEN_PORTFILM = portal image acquisition with open field (the source of radiation is specified by Radiation Type (300A,00C6)) TRMT_PORTFILM = portal image acquisition with treatment port (the source of radiation is specified by Radiation Type (300A,00C6)) CONTINUATION = continuation of interrupted treatment SETUP = no treatment beam was applied for this RT Beam. To be used for specifying the gantry, couch, and other machine positions where X-Ray set-up images or measurements were taken. Conditions under which treatment was terminated. Enumerated Values: NORMAL = treatment terminated normally OPERATOR = operator terminated treatment MACHINE = machine terminated treatment UNKNOWN = status at termination unknown Treatment machine termination code. This code is dependent upon the particular application and equipment. Conditions under which treatment was verified by a verification system. Enumerated Values: VERIFIED = treatment verified VERIFIED_OVR = treatment verified with at least one out-of-range value overridden NOT_VERIFIED = treatment verified manually Desired machine setting of primary meterset in units specified by Primary Dosimeter Unit (300A,00B3). Desired machine setting of secondary meterset. Machine setting actually delivered as recorded by primary meterset in units specified by Primary Dosimeter Unit (300A,00B3). Machine setting actually delivered as recorded by secondary meterset. Treatment Time set (sec). Treatment Time actually delivered (sec). Number of control points in Beam. Introduces sequence of beam control points for current ion treatment beam. One or more items may be included in this sequence. The number of items shall be identical to the value of Number of Control Points (300A,0110). See section C.8.8.21.1. Uniquely identifies Control Point specified by Control Point Index (300A,0112) within the Beam referenced by Referenced Beam Number (300C,0006). Date administration of treatment beam began. Time administration of treatment beam began. Desired machine setting for current control point in units specified by Primary Dosimeter Unit (300A,00B3). Machine setting actually delivered at current control point in units specified by Primary Dosimeter Unit (300A,00B3). The specified speed of delivery of the specified dose in units specified by Primary Dosimeter Unit (300A,00B3) per minute. The delivered speed of delivery of the specified dose in units specified by Primary Dosimeter Unit (300A,00B3) per minute. Nominal Beam Energy at control point in MeV per nucleon. Defined at nozzle entrance before all Beam Modifiers. Required for Control Point 0 of Ion Control Point Delivery Sequence (3008,0041) or if Nominal Beam Energy (300A,0114) changes during beam administration, and KVp (0018,0060) is not present. Peak kilo voltage output of the setup X-Ray generator used. Required for Control Point 0 of Ion Control Point Delivery Sequence (3008,0041), or if KVp changes during setup, and Nominal Beam Energy (300A,0114) is not present. Introduces sequence of Wedge positions for current control point. Required for first item of Ion Control Point Sequence if Number of Wedges (300A,00D0) is non-zero, and in subsequent control points if Wedge Position (300A,0118) or Wedge Thin Edge Position (300A,00DB) changes during beam. One or more items may be included in this sequence. The number of items shall be identical to the value of Number of Wedges (300A,00D0). Uniquely references Wedge described by Wedge Number (300A,00D2) in Wedge Sequence (300A,00D1). Position of Wedge at current control point. Enumerated Values: IN, OUT. Closest distance from the central axis of the beam along a wedge axis to the thin edge as projected to the machine isocentric plane (mm). Value is positive is the wedge does not cover the central axis, negative if it does. Required if Wedge Type (300A,00D3) of the wedge referenced by Referenced Wedge Number (300C,00C0) is PARTIAL_STANDARD or PARTIAL_MOTORIZ. See section C.8.8.25.6.4. Introduces sequence of Range Shifter settings for the current control point. One or more items may be included in this sequence. Required for Control Point 0 of Ion Control Point Delivery Sequence (3008,0041) or if Range Shifter Setting (300A,0362) changes during beam administration, and Number of Range Shifters (300A,0312) is non-zero. Uniquely references Range Shifter described by Range Shifter Number (300A,0316) in Range Shifter Sequence (300A,0314). Machine specific setting attribute for the range shifter. The specific encoding of this value should be documented in a Conformance Statement. See section C.8.8.25.5. Introduces sequence of Lateral Spreading Device settings for the current control point. One or more items may be included in this sequence. Required for Control Point 0 of Ion Control Point Delivery Sequence (3008,0041) or if Lateral Spreading Device Setting (300A,0372) changes during beam administration, and Number of Lateral Spreading Devices (300A,0330) is non-zero. Uniquely references Lateral Spreading Device described by Lateral Spreading Device Number (300A,0334) in Lateral Spreading Device Sequence (300A,0332). Machine specific setting attribute for the lateral spreading device. The specific encoding of this value should be documented in a Conformance Statement. See section C.8.8.25.5. Introduces sequence of Range Modulator Settings for current control point. One or more items may be included in this sequence.Required for Control Point 0 of Ion Control Point Delivery Sequence (3008,0041), or if Range Modulator Settings change during beam administration, and Number of Range Modulators (300A,0340) is non-zero. Uniquely references Range Modulator described by Range Modulator Number (300A,0344) in Range Modulator Sequence (300A,0342). Start position defines the range modulator position at which the beam is switched on. Required if Range Modulator Type (300A,0348) of the range modulator referenced by Referenced Range Modulator Number (300C,0104) is WHL_MODWEIGHTS or WHL_FIXEDWEIGHTS Stop position defines the range modulator position at which the beam is switched off. Required if Range Modulator Type (300A,0348) of the range modulator referenced by Referenced Range Modulator Number (300C,0104) is WHL_MODWEIGHTS or WHL_FIXEDWEIGHTS Treatment machine gantry angle, i.e. orientation of IEC GANTRY coordinate system with respect to IEC FIXED REFERENCE coordinate system (degrees). Required for Control Point 0 of Ion Control Point Delivery Sequence (3008,0041) or if Gantry Angle changes during beam administration. Direction of Gantry Rotation when viewing gantry from isocenter, for segment beginning at current Control Point. Required for Control Point 0 of Ion Control Point Delivery Sequence (3008,0041), or if Gantry Rotation Direction changes during beam administration. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation Gantry Pitch Angle. i.e. the rotation of the IEC GANTRY coordinate system about the X-axis of the IEC GANTRY coordinate system (degrees). Required for first item of Control Point Sequence, or if Gantry PitchRotation Angle changes during Beam. See C.8.8.25.6.5.
The Gantry Pitch angle is not defined in IEC 61217. This angle is defined in the DICOM standard in a way compatible with the current notion of IEC by introducing it as rotation of the IEC GANTRY System as indicated below. The Gantry Pitch Angle is defined as the rotation of the coordinate axes Yg, Zg about axis Xg by an angle g; see Figure C.8.8.25-7. An increase in the value of angle g corresponds to the clockwise rotation as viewed from the isocenter along the positive Xg axis Figure C.8.8.25-7 Gantry Pitch Angle
Direction of Gantry PitchAngle when viewing along the positive X-axis of the IEC GANTRY coordinate system, for segment following Control Point. Required for first item of Control Point Sequence, or if Gantry PitchRotation Direction changes during Beam. See C.8.8.14.8 and C.8.8.25.6.5. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Beam Limiting Device (collimator) angle, i.e. orientation of IEC BEAM LIMITING DEVICE coordinate system with respect to IEC GANTRY coordinate system (degrees). Required for Control Point 0 of Ion Control Point Delivery Sequence (3008,0041) or if beam limiting device (collimator) angle changes during beam administration. Direction of Beam Limiting Device Rotation when viewing beam limiting device (collimator) from radiation source, for segment beginning at current Control Point. Required for Control Point 0 of Ion Control Point Delivery Sequence (3008,0041) or if Beam Limiting Device Rotation Direction changes during beam administration. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation User-supplied or machine code identifier for machine configuration to produce beam spot. This may be the nominal spot size or some other machine specific value. Required if Scan Mode (300A,0308) is MODULATED. Number of spot positions used to specify scanning pattern for current segment beginning at control point. Required if Scan Mode (300A,0308) is MODULATED. The x and y coordinates of the scan spots are defined as projected onto the machine isocentric plane in the IEC GANTRY coordinate system (mm). Required if Scan Mode (300A,0308) is MODULATED. Contains 2N values were N is the Number of Scan Spot Positions (300A,0392). A data set of metersets delivered to the scan spot positions. The order of metersets matches the positions in Scan Spot Position Map (300A,0394). The sum contained in all metersets shall match the difference of the Delivered Meterset of the current control point to the following control point. Required if Scan Mode (300A,0308) is MODULATED. The Scanning Spot Size as calculated using the Full Width Half Maximum (FWHM). Specified by a numeric pair - the size measured in air at isocenter in IEC GANTRY X direction followed by the size in the IEC GANTRY Y direction (mm). The intended number of times the scan pattern given by Scan Spot Position Map (300A,0394) and Scan Spot Meterset Weights (300A,0396) in the Referenced RT Plan was to be applied at the current control point. Note: The actual number of paintings is not known or recorded. The Scan Spot Metersets Delivered (3008,0047) contains the sum of all complete and partial repaints. Required if Scan Mode (300A,0308) is MODULATED. Patient Support angle, i.e. orientation of IEC PATIENT SUPPORT (turntable) coordinate system with respect to IEC FIXED REFERENCE coordinate system (degrees). Required for Control Point 0 of Ion Control Point Delivery Sequence (3008,0041) or if Patient Support Angle changes during beam administration. Direction of Patient Support Rotation when viewing table from above, for segment beginning at current Control Point. Required for Control Point 0 of Ion Control Point Delivery Sequence (3008,0041), or if Patient Support Rotation Direction changes during beam administration. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation Table Top Pitch Angle, i.e. the rotation of the IEC TABLE TOP coordinate system about the X-axis of the IEC TABLE TOP coordinate system (degrees). Required for first item of Control Point Sequence, or if Table Top Pitch Angle changes during Beam. See section C.8.8.25.6.2. Direction of Table Top Pitch Rotation when viewing the table along the positive X-axis of the IEC TABLE TOP coordinate system, for segment following Control Point. Required for first item of Control Point Sequence, or if Table Top Pitch Rotation Direction changes during Beam. See C.8.8.14.8 and C.8.8.25.6.2. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Table Top Roll Angle, i.e. the rotation of the IEC TABLE TOP coordinate system about the Y-axis of the IEC TABLE TOP coordinate system (degrees). Required for first item of Control Point Sequence, or if Table Top Roll Angle changes during Beam. See section C.8.8.25.6.2. Direction of Table Top Roll Rotation when viewing the table along the positive Y-axis of the IEC TABLE TOP coordinate system, for segment following Control Point. Required for first item of Control Point Sequence, or if Table Top Roll Rotation Direction changes during Beam. See C.8.8.14.8 and C.8.8.25.6.2. Enumerated Values: CW = clockwise CC = counter-clockwise NONE = no rotation
For the machine rotation angles Gantry Angle (300A,011E), Beam Limiting Device Angle (300A,0120), Patient Support Angle (300A,0122) , and Table Top Eccentric Angle (300A,0125), rotation direction is specified as clockwise (CW), counter-clockwise (CC), or NONE. The maximum permitted rotation between two Control Points is 360 degrees. Examples: a) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = NONE: No movement. b) Gantry Angle moves from 5 degrees to 5 degrees, Gantry Rotation Direction = CW: Full clockwise rotation (360 degrees). c) Table Angle moves from 170 degrees to 160 degrees, Table Rotation Direction = CC: Counter-clockwise rotation by 350 degrees (note direction of increasing table angle as defined by IEC 61217).
Angle (in degrees) of the head fixation for eye treatments with respect to the Table Top Pitch Angle (300A,0140) coordinate system. Positive head fixation angle is the same direction as positive Table Top Pitch. See section C.8.8.25.6.4. Table Top Vertical position in IEC TABLE TOP coordinate system (mm). This value is interpreted as an absolute, rather than relative, Table setting. Required for Control Point 0 of Ion Control Point Delivery Sequence (3008,0041) or if Table Top Vertical Position changes during beam administration. Table Top Longitudinal position in IEC TABLE TOP coordinate system (mm). This value is interpreted as an absolute, rather than relative, Table setting. Required for Control Point 0 of Ion Control Point Delivery Sequence (3008,0041) or if Table Top Longitudinal Position changes during beam administration. Table Top Lateral position in IEC TABLE TOP coordinate system (mm). This value is interpreted as an absolute, rather than relative, Table setting. Required for Control Point 0 of Ion Control Point Delivery Sequence (3008,0041) or if Table Top Lateral Position changes during beam administration. Axial position of the snout (in mm) measured from isocenter to the downstream side of the snout (without consideration of variable length elements such as blocks, MLC and/or compensators). Required for Control Point 0 of Ion Control Point Delivery Sequence (3008,0041) or if Snout Position changes during beam administration. Introduces a sequence of items describing corrections made to any attributes prior to delivery of the next control point. The sequence may contain one or more items. Contains the Data Element Tag of the parent sequence containing the attribute that was corrected. The value is limited in scope to the Treatment Session Ion Beam Sequence (3008,0021) and all nested sequences therein. Contains the ones-based sequence item index of the corrected attribute within its parent sequence as indicated by Parameter Sequence Pointer (3008,0061). Contains the Data Element Tag of the attribute that was corrected. The value that was added the value referenced by the Parameter Sequence Pointer (3008,0061), Parameter Item Index (3008,0063) and Parameter Pointer (3008,0065). Introduces sequence of parameters that were overridden during the administration of the beam segment immediately prior to the current control point. The sequence may contain one or more items. Contains the Data Element Tag of the parent sequence containing the attribute that was overridden. The value is limited in scope to the Treatment Session Ion Beam Sequence (3008,0021) and all nested sequences therein. Contains the Data Element Tag of the attribute that was overridden. Contains the ones-based sequence item index of the overridden attributes within it's parent sequence. The value is limited in scope to the Treatment Session Ion Beam Sequence (3008,0021) and all nested sequences therein. Name of operator who authorized override. User-defined description of reason for override of parameter specified by Override Parameter Pointer (3008,0062).
Introduces sequence of beam limiting device (collimator) jaw or leaf (element) positions. Required if Ion Beam Limiting Device Sequence (300A,03A4) is included and for first item of Control Point Sequence, or if Beam Limiting Device changes during Beam. One or more items shall be included in this sequence. Type of beam limiting device (collimator). The value of this attribute shall correspond to RT Beam Limiting Device Type (300A,00B8) defined in an item of Ion Beam Limiting Device Sequence (300A,03A4). Enumerated Values: X = symmetric jaw pair in IEC X direction Y = symmetric jaw pair in IEC Y direction ASYMX = asymmetric jaw pair in IEC X direction ASYMY = asymmetric pair in IEC Y direction MLCX = multileaf (multi-element) jaw pair in IEC X direction MLCY = multileaf (multi-element) jaw pair in IEC Y direction Positions of beam limiting device (collimator) leaf (element) or jaw pairs (in mm) in IEC BEAM LIMITING DEVICE coordinate axis appropriate to RT Beam Limiting Device Type (300A,00B8), e.g. X-axis for MLCX, Y-axis for MLCY. Contains 2N values, where N is the Number of Leaf/Jaw Pairs (300A,00BC) in Ion Beam Limiting Device Sequence (300A,03A4). Values shall be listed in IEC leaf (element) subscript order 101, 102, ... 1N, 201, 202, ... 2N. See section C.8.8.25.3. Defined terms: TABLE = Treatment delivery system table CHAIR = Treatment delivery system chair See section C.8.8.25.6.3. User-specified identifier for manufacturer specific patient support devices. A Patient Support accessory identifier to be read by a device such as a bar code reader. Date the Series started. See C.8.9.1.1.2 for specialization.
For PET Series, Series Date (0008,0021) and Series Time (0008,0031) are specified to be Type 1. The Series Date (0008,0021) and Series Time (0008,0031) are used as the reference time for all PET Image attributes that are temporally related, including activity measurements. The Series Date (0008,0021) and Series Time (0008,0031) are not tied to any real-world event (e.g. acquisition start, radiopharmaceutical administration) and their real-world meaning are implementation dependent.
Time the Series started. See C.8.9.1.1.2 for specialization.
For PET Series, Series Date (0008,0021) and Series Time (0008,0031) are specified to be Type 1. The Series Date (0008,0021) and Series Time (0008,0031) are used as the reference time for all PET Image attributes that are temporally related, including activity measurements. The Series Date (0008,0021) and Series Time (0008,0031) are not tied to any real-world event (e.g. acquisition start, radiopharmaceutical administration) and their real-world meaning are implementation dependent.
Pixel value units. See C.8.9.1.1.3 for explanation. Defined terms: CNTS, NONE, CM2, PCNT, CPS, BQML, MGMINML, UMOLMINML, MLMING, MLG, 1CM, UMOLML, PROPCNTS, PROPCPS, MLMINML, MLML, GML, STDDEV
The units of the pixel values obtained after conversion from the stored pixel values (SV) (Pixel Data (7FE0,0010)) to pixel value units (U), as defined by Rescale Intercept (0028,1052) and Rescale Slope (0028,1053). Defined Terms: CNTS = counts NONE = unitless CM2 = centimeter**2 PCNT = percent CPS = counts/second BQML = Becquerels/milliliter MGMINML = milligram/minute/milliliter UMOLMINML = micromole/minute/milliliter MLMING = milliliter/minute/gram MLG = milliliter/gram 1CM = 1/centimeter UMOLML = micromole/milliliter PROPCNTS = proportional to counts PROPCPS = proportional to counts/sec MLMINML = milliliter/minute/milliliter MLML = milliliter/milliliter GML = grams/milliliter STDDEV = standard deviations
The primary source of counts. The primary source leads to the underlying image Units (0054,1001), as opposed to secondary sources which are used during reconstruction correction. Enumerated Values: EMISSION TRANSMISSION A multi-valued indicator of the type of Series. See C.8.9.1.1.4 for explanation. Value 1 Enumerated Values: STATIC DYNAMIC GATED WHOLE BODY Value 2 Enumerated Values: IMAGE REPROJECTION
The Series Type (0054,1000), Value 1 is used to identify the spatial location and temporal nature of the images within a PET Series. The Enumerated Values and their definitions are: STATIC = a group of images at varying spatial locations at the same time DYNAMIC = a group of images at a set of spatial locations (e.g. slices) at varying time slices, with all spatial locations acquired at all time slices GATED = a group of images at the same spatial location, same starting and ending time, but acquired in different time slots of (possibly) different R-R intervals WHOLE BODY = same as STATIC, except covering multiple transverse fields of view (and therefore acquired at a different time). Notes: 1. Using this definition and the comments in C.8.9.1.1.1, here are some examples of PET series and the encoding of Series Type (0054,1000) Value 1. Static acquisition: a group of n transverse images at varying superior<->inferior locations, all acquired between the same starting and ending time. Series Type = STATIC. Dynamic acquisition: a group of n*m transverse images at n superior<->inferior locations, acquired with m different starting and ending times. Series Type = DYNAMIC. Gated acquisition: a group of n*m*p transverse images at n superior<->inferior locations, all acquired between the same starting and ending time, acquired in m different R-R Intervals (as determined by Low R-R Value (0018,1081) and High R-R Value (0018,1082)), and acquired in p time slots of a given R-R Interval (as determined by Trigger Time (0054,1000) ). Series Type = GATED. Whole body acquisition: a group of n transverse images at varying superior<->inferior locations covering a significant fraction of the entire body. Series Type = WHOLE BODY. Multiple transverse fields of view: a group of n transverse images at varying superior<->inferior locations. Series Type = WHOLE BODY. Interleaved: group of 2*n transverse images acquired at overlapped AFOVs to increase transverse sampling. Series Type = WHOLE BODY. Sagittal (Coronal, Oblique): sagittal (coronal, oblique) re-sliced images derived by reformatting transverse images. The Series Type is STATIC, DYNAMIC, GATED, or WHOLE BODY depending on source Series Type. Arithmetic: images derived by an arithmetic operation on operand images. The Series Type is STATIC, DYNAMIC, GATED, or WHOLE BODY depending on source Series Type. Metabolic: images derived by a metabolic model. The Series Type is STATIC, DYNAMIC, GATED, or WHOLE BODY depending on source Series Type. 2. Using this definition, here are some images that are not stored in the same PET Series: Two images from the same scan that were reconstructed differently. Emission and transmission images for the same Patient and Study, even if acquired simultaneously (because emission and transmission images have different reconstruction processing). Two images of same patient, one after NH3 injection and one after FDG injection. Two images: an original image created from reconstructed scan data and its derived image based on a metabolic model. The Series Type (0054,1000), Value 2 is used to identify the volumetric meaning of the images within a PET Series. The Enumerated Values and their definitions are: IMAGE = a tomographic image slice REPROJECTION = a projection image derived from forward projection through slices of tomographic images, using the algorithm defined in Reprojection Method (0054,1004).
Method for projecting volumetric data onto planar projection. Required if Series Type (0054,1000), Value 2 is REPROJECTION. Defined terms: SUM MAX PIXEL The maximum number of R-R Intervals that may exist in this Series. Required if Series Type (0054,1000), Value 1 is GATED. The maximum number of Time Slots that may exist in this Series. Required if Series Type (0054,1000), Value 1 is GATED. The maximum number of Time Slices that may exist in this Series. Required if Series Type (0054,1000), Value 1 is DYNAMIC. The maximum number of Slices that may exist in this Series. A value that indicates which, if any, corrections have been applied to the images in this series. Defined terms: DECY=decay corrected ATTN=attenuation corrected SCAT=scatter corrected DTIM=dead time corrected MOTN=gantry motion corrected (e.g. wobble, clamshell) PMOT=patient motion corrected CLN=count loss normalization (correction for count loss in gated Time Slots). RAN=randoms corrected RADL=non-uniform radial sampling corrected DCAL=sensitivity calibrated using dose calibrator NORM=detector normalization Type of randoms correction processing. Defined terms: NONE = no randoms correction DLYD = delayed event subtraction SING = singles estimation A textual description of the attenuation correction processing. e.g. measured vs. calculated, transmission source type (ring, line, point), assumed patient geometry (polygon, ellipse, segmented, attenuation coefficient, skull thickness), post-injection transmission, smoothing. A textual description of the scatter correction processing. e.g. convolution-subtraction, dual energy window, model-based, use of attenuation data. The real-world event to which images in this Series were decay corrected. See C.8.9.1.1.5 for explanation. Defined terms: NONE = no decay correction START= acquisition start time ADMIN = radiopharmaceutical administration time
The Decay Correction (0054,1102) is the real-world event to which images in this Series were decay corrected. If decay correction is applied, all images in the Series shall be decay corrected to the same time. The Defined Terms and definitions are: NONE = no decay correction START= acquisition start time, Acquisition Time (0008,0032) ADMIN = radiopharmaceutical administration time, Radiopharmaceutical Start Time (0018,1072) The time to which images have been decay corrected can be derived from Decay Factor (0054,1321), Frame Reference Time (0054,1300), Radionuclide Half Life (0018,1075), Series Date (0008,0021), and Series Time (0008,0031).
Diameter, in mm, of the region within which the data was used in creating the reconstruction of the image. Data may exist outside this region and portions of the patient may exist outside this region. Textual description of the convolution kernel(s) used to reconstruct the data (e.g. name, cutoff, radial/axial/angular, mathematical form, DC handling) Textual description of reconstruction processing, e.g. 2D filtered backprojection, 2D iterative, 3D PROMIS, 3D FAVOR, 3D iterative. Textual description of which detector lines of response were used, mashed, or otherwise processed during tomographic reconstruction. Description of how the data collection was started. Defined terms: DENS = density (counts/sec) RDD = relative density difference (change in counts/sec) MANU = manual TIME = time AUTO = automatic, when ready TRIG = physiological trigger See C.8.9.1.1.6 for explanation.
Acquisition Start Condition (0018,0073) is the method of starting acquisition data collection. The Defined Terms and definitions are: DENS = preset count density (counts/sec) was reached RDD = preset relative count density difference (change in counts/sec) was reached MANU = acquisition was started manually TIME = preset time limit was reached AUTO = start automatically, when ready TRIG = preset number of physiological triggers was reached
Count density, change in count density, or physiological triggers causing data collection to start. Description of how the data collection for the series was stopped. Defined terms: CNTS = counts DENS = density (counts/sec) RDD = relative density difference (change in counts/sec) MANU = manual OVFL = data overflow TIME = time TRIG = physiological trigger See C.8.4.9.1.3 for explanation.
Acquisition Termination Condition (0018,0071) is the method of acquisition termination which was actually applied to the data collection. The Defined Terms and definitions are: CNTS = preset count limit was reached DENS = preset count density was reached MANU = acquisition was terminated manually OVFL = acquisition was terminated automatically by pixel data overflow condition TIME = preset time limit was reached TRIG = preset number of physiological triggers was reached
Number of counts, count density, change in count density, or physiological triggers causing the termination. Shape of the field of view of the PET camera. Defined Terms: CYLINDRICAL RING HEXAGONAL MULTIPLE PLANAR Dimensions of the field of view, in mm. Transverse detector diameter followed by axial width. Angle of tilt in degrees of the gantry. See C.8.9.1.1.7 for explanation.
Gantry/Detector Tilt (0018,1120) for PET Image data is the angle in degrees of the gantry relative to the patient’s major (Head to Feet) axis (or the table supporting the patient). Positive tilt is moving the top of the gantry towards the patient’s feet.
Angle of slew in degrees of the gantry. Positive slew is moving the gantry on the patient's left toward the patient's superior, when the patient is supine. Describes the detector motion during acquisition. Defined Terms: NONE = stationary gantry STEP AND SHOOT = Interrupted motion, acquire only while stationary CONTINUOUS = Gantry motion and acquisition are simultaneous and continuous WOBBLE = wobble motion CLAMSHELL = clamshell motion Collimator Type. Defined Terms: NONE = no collimator RING = transverse septa Label describing the collimator used. Maximum axial angle accepted, in degrees. Number of adjacent axial lines of response mashed together. See C.8.9.1.1.8 for explanation.
Axial Mash (0054,1201) is multi-valued and is defined as the number of unique axial Lines of Response (LOR) that were mashed together (center of the axial field of view only). Value 1 is the number of LORs mashed for an odd slice. Value 2 is the number of LORs mashed for an even slice. For discrete crystal scanners, each unique LOR corresponds to a pair of crystals. For continuous detectors whose bin size is variable, the number of LORs mashed is determined by the actual bin size divided by the Detector Element Size (0054,1203), Value 2. The value of Axial Mash (0054,1201) is the same regardless of whether the mashing was done during acquisition or reconstruction. Note: As an example on a discrete crystal scanner, if a ring difference of -2,0,+2 are binned as an odd slice and a ring difference of -1,+1 are binned as an even slice, then the Axial Mash (0054,1201) is equal to 3\2 .
Number of adjacent transverse lines of response mashed together. See C.8.9.1.1.9 for explanation.
Transverse Mash (0054,1202) is defined as the number of unique transverse Lines of Response (LOR) that were mashed together. For discrete crystal scanners, each unique LOR corresponds to a pair of crystals. For continuous detectors whose bin size is variable, the number of LORs mashed is determined by the actual bin size divided by the Detector Element Size (0054,1203), Value 1. The value of Transverse Mash (0054,1202) is the same regardless of whether the mashing was done during acquisition or reconstruction.
Size of an individual detector element, in mm. Transverse dimension followed by axial dimension. For a discrete crystal, this is the crystal size. For a continuous detector, this is the pixel bin size. The width of the coincidence timing window, in nsec. The maximum time difference accepted between two single events. Sequence of Items that describes the energy windows used for this Series. This sequence may contain zero or more items. See C.8.9.1.1.10 for explanation.
Multiple energy windows are allowed in order to allow coincidence events based on additional Energy Windows (e.g. Compton events scattered in the detector). All energy windows are assumed to contribute to all images in the PET Series.
The lower limit of the energy window, in KeV. The upper limit of the energy window, in KeV. Array defining the type of additional counts accumulated during acquisition. Defined terms: DLYD=delayed events SCAT=scattered events in secondary window SING=singles DTIM=events lost due to deadtime
Sequence of Items that describe isotope information. Zero or more Items may be included in this sequence. Sequence that identifies the radionuclide. Zero or one item shall be present in the sequence. Route of administration. Sequence that identifies the administration route of the radiopharmaceutical. This sequence shall contain exactly one item. Volume of administered radiopharmaceutical in cubic cm. Time of start of administration. The actual time of radiopharmaceutical administration to the patient for imaging purposes, using the same time base as Series Time (0008,0031). The use of this Attribute is deprecated in favor of Radiopharmaceutical Start DateTime (0018,1078). Note: The use of a time alone can cause confusion when the procedure spans midnight. Date and time of start of administration. The actual date and time of radiopharmaceutical administration to the patient for imaging purposes, using the same time base as Series Time (0008,0031). Time of end of administration. The actual ending time of radiopharmaceutical administration to the patient for imaging purposes, using the same time base as Series Time (0008,0031). The use of this Attribute is deprecated in favor of Radiopharmaceutical Stop DateTime (0018,1079). Note: The use of a time alone can cause confusion when the procedure spans midnight. Date and time of end of administration. The actual ending date and time of radiopharmaceutical administration to the patient for imaging purposes, using the same time base as Series Time (0008,0031). The radiopharmaceutical dose administered to the patient measured in Becquerels (Bq) at the Radiopharmaceutical Start Time (0018,1072). Note: In other IODs, such as the NM IOD, this same attribute is specified in MegaBecquerels (MBq). The radionuclide half life, in seconds, that was used in the correction of this image. The radionuclide positron fraction (fraction of decays that are by positron emission) that was used in the correction of this image. The activity per unit mass of the radiopharmaceutical, in Bq/micromole, at the Radiopharmaceutical Start Time (0018,1072). Name of the radiopharmaceutical. Sequence that identifies the radiopharmaceutical. This sequence shall contain exactly one item. Sequence of Items that describes the intervention drugs used. One or more items may be included in this sequence. Name of the intervention drug. Sequence that identifies the intervention drug name. Only a single Item shall be permitted in this Sequence. Time of administration of the intervention drug, using the same time base as for the Series Time (0008,0031). Time of completion of administration of the intervention drug, using the same time base as for the Series Time (0008,0031). Intervention drug dose, in mg. Heart beat duration sorting has been applied. Enumerated values: Y = yes N = no Text indicating trigger source. Defined terms: EKG Description of the type of PVC rejection criteria used. Number of beats skipped after a detected arrhythmia. Average number of heart beats per minute for the collection period for this image. This shall include all accepted beats as well as rejected beats. Description of type of framing performed. Defined Terms: FORW = forward BACK = backward PCNT = forward/backward by percentage See C.7.6.18.1.1.1.
Cardiac Framing Type (0018,1064) is the mechanism used to select the data acquired to construct the frames within a specified cardiac timing interval.C.7.6.18.2 Respiratory Synchronization Module Table C7.6.18-2 specifies the attributes of the Respiratory Synchronization Module. Table C.7.6.18-2 RESPIRATORY SYNCHRONIZATION MODULE ATTRIBUTES
Image identification characteristics. See C.8.9.4.1.1 for specialization.
For PET Images, Image Type (0008,0008) is specified to be Type 1. Note: For PET images, Image Type (0008,0008) Value 1 will be ORIGINAL for reconstructed images. DERIVED may be appropriate for some other results images. For PET images, Image Type (0008,0008) Value 2 will be PRIMARY.
Number of samples (planes) in this image. This value shall be 1. Specifies the intended interpretation of the pixel data. See C.8.9.4.1.2 for specialization.
For PET images, Photometric Interpretation (0028,0004) shall have one of the following Enumerated Values: MONOCHROME2 See C.7.6.3.1.2 for definition of this term.
Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated. Enumerated values: 16. Number of bits stored for each pixel sample. Each sample shall have the same number of bits stored. The value shall be the same as the value in Bits Allocated (0028,0100). Most significant bit for pixel sample data. Each sample shall have the same high bit. Shall be one less than the value in Bits Stored (0028,0101). The value b in relationship between stored values (SV) and pixel value units (U) defined in Units (0054,1001): U = m*SV+b. The Rescale Intercept is always zero for PET images. m in the equation specified in Rescale Intercept (0028,1052). The time that the pixel values in the image occurred. Frame Reference Time is the offset, in msec, from the Series reference time. See explanation in C.8.9.4.1.5. Time interval, in msec, from the start of the trigger to the beginning of data acquisition for this image. Required if Series Type (0054,1000), Value 1 is GATED. Nominal duration per individual frame, in msec. Required if Series Type (0054,1000), Value 1 is GATED. See C.8.9.4.1.3 for explanation.
The Frame Time (0018,1063) is the explicit duration of the gated frame when Cardiac Framing Type (0018,1064) is equal to FORW or BACK. Frame Time (0018,1063) is the nominal duration of the gated frame when Cardiac Framing Type (0018,1064) is equal to PCNT.
R-R interval lower limit for beat rejection, in msec. Required if Series Type (0054,1000), Value 1 is GATED and Beat Rejection Flag (0018,1080) is Y. R-R interval upper limit for beat rejection, in msec. Required if Series Type (0054,1000), Value 1 is GATED and Beat Rejection Flag (0018,1080) is Y. Specifies whether an Image has undergone lossy compression. Enumerated values: 00 = Image has NOT been subjected to lossy compression. 01 = Image has been subjected to lossy compression. See C.7.6.1.1.5. Required if Lossy Compression has been performed on the image.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
An index identifying the position of this image within a PET Series. See C.8.9.4.1.9 for explanation.
Image Index (0054,1330) is an index identifying the position of this image within a PET Series. Note: The scheme for encoding Image Index (0054,1330) is as follows. Images within a PET Series can be viewed as a multi-dimensional array whose possible dimensions include R-R Intervals, Time Slots, Time Slices, and Slices. The dimensions of the array are defined by the Series Type (0054,1000) Value 1. Each dimension of the array has an index that identifies the position of this image in the array. The indices are: R-R Interval Index, Time Slot Index, Time Slice Index, Slice Index. The indices are calculated as follows: Using these index values the position of this image within the multi-dimensional array (the Image Index (0054,1330)) is calculated as follows:
The date the acquisition of data that resulted in this image started. See C.8.9.4.1.4 for specialization.
For PET Images, Acquisition Date (0008,0022) and Acquisition Time (0008,0032) are specified to be Type 2. The Acquisition Date (0008,0022) and Acquisition Time (0008,0032) use the same time base as Series Time (0008,0031). For Series Type (0054,1000) Value 1 equal to STATIC, WHOLE BODY, or DYNAMIC, the Acquisition Time (0008,0032) is the real-world beginning of the accumulation of events into this Image. For STATIC, WHOLE BODY, or DYNAMIC Series, the Acquisition Time (0008,0032) may vary from Image to Image within a PET Series. For Series Type (0054,1000) Value 1 equal to GATED, the Acquisition Time (0008,0032) is the real-world beginning of the capability of accumulating events into this Image. (The actual accumulation of events has only occurred during an R-R Interval.) For GATED Series, the Acquisition Time (0008,0032) shall not vary from Image to Image within a PET Series.
The time the acquisition of data that resulted in this image started. See C.8.9.4.1.4 for specialization.
For PET Images, Acquisition Date (0008,0022) and Acquisition Time (0008,0032) are specified to be Type 2. The Acquisition Date (0008,0022) and Acquisition Time (0008,0032) use the same time base as Series Time (0008,0031). For Series Type (0054,1000) Value 1 equal to STATIC, WHOLE BODY, or DYNAMIC, the Acquisition Time (0008,0032) is the real-world beginning of the accumulation of events into this Image. For STATIC, WHOLE BODY, or DYNAMIC Series, the Acquisition Time (0008,0032) may vary from Image to Image within a PET Series. For Series Type (0054,1000) Value 1 equal to GATED, the Acquisition Time (0008,0032) is the real-world beginning of the capability of accumulating events into this Image. (The actual accumulation of events has only occurred during an R-R Interval.) For GATED Series, the Acquisition Time (0008,0032) shall not vary from Image to Image within a PET Series.
Elapsed time of the data acquisition for this image, in msec. See C.8.9.4.1.6 for explanation.
The accumulation of counts for a PET Image shall occur entirely between: (1) the acquisition starting time (as specified by Acquisition Date (0008,0022) and Acquisition Time (0008,0032)), and (2) the acquisition ending time, which is equal to the acquisition starting time in (1) plus the Actual Frame Duration (0018,1242). If the Series Type (0054,1000), Value 1 is GATED, then the actual accumulation of counts has only occurred during an R-R Interval.
Average duration of accepted beats, in msec, of the R-R interval. Number of heartbeats that fall within Low R-R Value (0018,1081) and High R-R Value (0018,1082), and were therefore accepted and contribute coincidence events to this R-R Interval. Number of heartbeats that fall outside Low R-R Value (0018,1081) and High R-R Value (0018,1082), and do not contribute coincidence events to this R-R Interval. However, they may contribute coincidence events to other R-R Intervals. The sum of events that occur in the primary event channel. The counts include Trues +Scatter+ Randoms if Randoms Correction Method (0054,1100) is NONE; otherwise the counts are Trues +Scatter. Sum of counts accumulated in secondary channels. See C.8.9.4.1.7 for explanation.
Secondary Counts Accumulated (0054,1311) is multi-valued and, if supplied, has Values corresponding to the Secondary Counts Type (0054,1220). The number and order of the Values in Secondary Counts Accumulated (0054,1311) shall be the same as Secondary Counts Type (0054,1220).
The slice-to-slice sensitivity correction factor that was used to correct this image. The value shall be one if no slice sensitivity correction was applied. The decay factor that was used to scale this image. Required if Decay Correction (0054,1102) is other than NONE. If decay correction is applied, all images in the Series shall be decay corrected to the same time. Factor that was used to scale this image from counts/sec to Bq/ml using a dose calibrator. The value shall be one if no dose calibration was applied. See C.8.9.4.1.8 for explanation.
The Dose Calibration Factor (0054,1322) is the factor that was used to scale this image from counts/sec to Bq/ml using an external dose calibrator. The value shall be one if no dose calibration was applied. The application of a dose calibration correction is specified by Corrected Image (0028,0051) equal to DCAL. Note: Dose Calibration Factor (0054,1322) is not equal to the inverse of the sensitivity (kcps/Bq/ml) of the scanner, which is usually measured for a given radiopharmaceutical distribution and excluding the effects of attenuation.
An estimate of the fraction of acquired counts that were due to scatter and were corrected in this image. The value shall be zero if no scatter correction was applied. The average dead time correction factor that was applied to this image. The value shall be one if no dead time correction was applied. Describes the anatomical direction that slices are progressing as the slices are considered in order (as defined by the Slice Index. See section C.8.9.4.1.9 for a definition of Slice Index). Meaningful only for cardiac images. When View Code Sequence (0054,0220) indicates a short axis view, then Enumerated Values are: APEX_TO_BASE BASE_TO_APEX Sequence that describes the projection of the anatomic region of interest. Only a single Item shall be permitted in this sequence. View Modifier. Required if needed to fully specify the View. Only a single Item shall be permitted in this sequence.
Type of equipment that originally acquired the data used to create the images in this Series. Enumerated Values: DX PX IO MG See section C.7.3.1.1.1 for further explanation. Uniquely identifies the Performed Procedure Step SOP Instance to which the Series is related (e.g. a Modality or General-Purpose Performed Procedure Step SOP Instance). The Sequence shall have one Item. Required if the Modality Performed Procedure Step SOP Class, General Purpose Performed Procedure Step SOP Class is supported. Identifies the intent of the images that are contained within this Series. Enumerated Values: FOR PRESENTATION FOR PROCESSING See C.8.11.1.1.1 for further explanation.
Presentation Intent Type (0008,0068) shall identify the intent for the purposes of display or other presentation of all Images within this Series. Notes: 1. Since this is a Series level attribute, all Images within a Series have the same value for this Attribute. 2. The intent of this restriction is to ensure that FOR PRESENTATION and FOR PROCESSING images are placed in separate Series, so that no confusion can arise as to which images are suitable for diagnostic reading as determined by local policy. A Series of Images intended for viewing by an observer, after application of any grayscale transformations specified in the image object such as VOI LUT, shall have an Enumerated Value of FOR PRESENTATION. Notes: 1. These images may still be of Image Type (0008,0008) ORIGINAL rather than DERIVED despite the possibility that they may have undergone some processing, such as unsharp masking. In this case a DERIVED image would have undergone yet further processing to make it substantially different from the original. See Figure C.8-13. 2. These images may still be subjected to processing or further processing, if appropriate, depending on the application. 3. These images are intended for display on a device, without (further) processing, since that device may not be capable of image processing. The quality of the displayed image or its suitability for any purpose is beyond the scope of the DICOM Standard. Images that have been corrected to account for characteristics of the detector but which are intended to be further processed before being displayed, shall have an Enumerated Value of FOR PROCESSING. Note: This type is provided to allow the functions of image acquisition and image processing for presentation to be separated and yet have images conveyed between the two processes using a DICOM object. Individual sites or users may choose to substitute their own specialized processing in place of that supplied by the implementor. Images available at this stage of processing may be useful for quality control and problem solving purposes, as well as academic research. Images of this type may also be archived, retrieved and processed with different algorithms or parameters in order to alter the appearance of specific features for clinical purposes. The nature of the detector correction that may have been applied before sending an image of type FOR PROCESSING is not specified. In particular, acquisitions that acquire several sets of matrices of pixel values (such as image data, gain offset and a defect map) must perform some processing (detector correction) before a DX Image object can be instantiated. The nature of the processing that may have been applied before sending an image of type FOR PRESENTATION is also not specified. It is expected that individual implementors will use Private Attributes to convey specifics of the processing applied that may be of use for further processing by those aware of the parameters and algorithms. The diversity of detector types and processing algorithms make it undesirable to standardize such parameters. Whether or not the spatial locations of all pixels are preserved during the processing of the source image that resulted in the current image can be indicated by Spatial Locations Preserved (0028,135A) in a Source Image Sequence (0008,2112) reference from the FOR PRESENTATION image to a FOR PROCESSING predecessor. If images from the same exposure exist with different Values of Presentation Intent Type (0008,0068), then they shall have different SOP Instance UIDs. Notes: 1. Source Image Sequence (0008,2112) may be used to relate these images. 2. The SOP Class UIDs of the two images will also be different.
Laterality of (possibly paired) body part (as described in Anatomic Region Sequence (0008,2218)) examined. Enumerated Values: R = right L = left U = unpaired B = both left and right Note: This Attribute is mandatory, in order to ensure that images may be positioned correctly relative to one another for display. Shall be consistent with any laterality information contained in Primary Anatomic Structure Modifier Sequence (0008,2230), if present. Note: Laterality (0020,0060) is a Series level Attribute and must be the same for all Images in the Series, hence it must be absent. Image identification characteristics. See C.8.11.3.1.1 for specialization.
Value 1 shall identify the Pixel Data Characteristics in accordance with Section C.7.6.1.1.2 where the Enumerated Values are defined to be ORIGINAL or DERIVED. Note: DX images may still be of type ORIGINAL rather than DERIVED despite the possibility that they may have undergone some processing. In this case a DERIVED image would have undergone yet further processing to make it substantially different from the original. Value 2 shall identify the Patient Examination Characteristics in accordance with Section C.7.6.1.1.2 where the Enumerated Values are defined to be PRIMARY or SECONDARY. Note: DX images generally use PRIMARY value for images captured from patient exposure. If images from the same exposure exist with different Values of Image Type, then they shall have different SOP Instance UIDs. Note: Source Image Sequence (0008,2112) may be used to relate these images. Value 3 (which is specific to the IOD) shall be present and have zero length (null value). Other Values (4 and beyond) are optional and implementation specific.
Number of samples in this image. Shall have an Enumerated Value of 1. Specifies the intended interpretation of the pixel data. Enumerated Values: MONOCHROME1 MONOCHROME2 Number of bits allocated for each pixel sample. Enumerated Values: 8, 16 Number of bits stored for each pixel sample. Enumerated Values: 6 to 16 Most significant bit for pixel sample data. Shall have an Enumerated Value of one less than the value in Bit Stored (0028,0101). Data representation of the pixel samples. Shall have the Enumerated Value: 0000H = Unsigned Integer. The relationship between the Pixel sample values and the X-Ray beam intensity. Enumerated Values: LIN = Linearly proportional to X-Ray beam intensity LOG = Logarithmically proportional to X-Ray beam intensity See C.8.11.3.1.2 for further explanation.
Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041) describe how the stored pixel values in Pixel Data (7FE0,0010) are related to the X-Ray beam intensity incident on the detector. They do not define a transformation intended to be applied to the pixel data for presentation. Note: For example, if Pixel Intensity Relationship (0028,1040) is LIN and Pixel Intensity Relationship Sign (0028,1041) is -1, then lower values of Pixel Data (7FE0,0010) indicate higher X-Ray beam intensities corresponding to less radiographically dense regions projected on the image such as through air, and higher values of Pixel Data (7FE0,0010) indicate lower X-Ray beam intensities corresponding to more radiographically dense regions projected on the image such as through bone and radio-opaque contrast agents. The transformation to be applied to the pixel data for presentation is defined by the successive application of the conceptual Modality LUT, the VOI Attributes and the conceptual Presentation LUT. This shall result in the output of P-Values. Rescale Slope (0028,1053) and Rescale Intercept (0028,1052) define a linear subset of a conceptual Modality LUT transformation. For IODs that include this Module, these Attributes define an identity transformation. IODs that include the DX Image Module shall not include the Modality LUT Module. The Presentation LUT Shape (2050,0020) defines a subset of a conceptual Presentation LUT. For IODs that include this Module, this Attribute defines an identity transformation or inverse identity transformation. IODs that include the DX Image Module shall not include the Presentation LUT Module. Photometric Interpretation (0028,0004) indicates whether lower values that are the output of the VOI Attributes should be displayed as darker or lighter. Since the output of the equivalent of a conceptual Presentation LUT is in P-Values, which are defined in PS 3.14 such that lower values correspond to lower luminance levels, then the definition of the Presentation LUT Shape (2050,0020), otherwise intended to be an identity transformation, must take into account the effect of the value specified for Photometric Interpretation (0028,0004). Note: Regardless of the values of Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041), the grayscale transformations to be applied to the Pixel Data (7FE0,0010) are defined by the equivalent of the Modality LUT (Rescale Slope (0028,1053) and Rescale Intercept (0028,1052)), Value of Interest Attributes, Photometric Interpretation (0028,0004) and the equivalent of the Presentation LUT (Presentation LUT Shape (2050,0020)). However, the combination of the grayscale transformations and the description of the pixel intensity relationship, together define whether, for example, air is expected to be displayed as black or white.
The sign of the relationship between the Pixel sample values stored in Pixel Data (7FE0,0010) and the X-Ray beam intensity. Enumerated Values; 1 = Lower pixel values correspond to less X-Ray beam intensity -1 = Higher pixel values correspond to less X-Ray beam intensity See C.8.11.3.1.2 for further explanation.
Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041) describe how the stored pixel values in Pixel Data (7FE0,0010) are related to the X-Ray beam intensity incident on the detector. They do not define a transformation intended to be applied to the pixel data for presentation. Note: For example, if Pixel Intensity Relationship (0028,1040) is LIN and Pixel Intensity Relationship Sign (0028,1041) is -1, then lower values of Pixel Data (7FE0,0010) indicate higher X-Ray beam intensities corresponding to less radiographically dense regions projected on the image such as through air, and higher values of Pixel Data (7FE0,0010) indicate lower X-Ray beam intensities corresponding to more radiographically dense regions projected on the image such as through bone and radio-opaque contrast agents. The transformation to be applied to the pixel data for presentation is defined by the successive application of the conceptual Modality LUT, the VOI Attributes and the conceptual Presentation LUT. This shall result in the output of P-Values. Rescale Slope (0028,1053) and Rescale Intercept (0028,1052) define a linear subset of a conceptual Modality LUT transformation. For IODs that include this Module, these Attributes define an identity transformation. IODs that include the DX Image Module shall not include the Modality LUT Module. The Presentation LUT Shape (2050,0020) defines a subset of a conceptual Presentation LUT. For IODs that include this Module, this Attribute defines an identity transformation or inverse identity transformation. IODs that include the DX Image Module shall not include the Presentation LUT Module. Photometric Interpretation (0028,0004) indicates whether lower values that are the output of the VOI Attributes should be displayed as darker or lighter. Since the output of the equivalent of a conceptual Presentation LUT is in P-Values, which are defined in PS 3.14 such that lower values correspond to lower luminance levels, then the definition of the Presentation LUT Shape (2050,0020), otherwise intended to be an identity transformation, must take into account the effect of the value specified for Photometric Interpretation (0028,0004). Note: Regardless of the values of Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041), the grayscale transformations to be applied to the Pixel Data (7FE0,0010) are defined by the equivalent of the Modality LUT (Rescale Slope (0028,1053) and Rescale Intercept (0028,1052)), Value of Interest Attributes, Photometric Interpretation (0028,0004) and the equivalent of the Presentation LUT (Presentation LUT Shape (2050,0020)). However, the combination of the grayscale transformations and the description of the pixel intensity relationship, together define whether, for example, air is expected to be displayed as black or white.
The value b in the relationship between stored values (SV) in Pixel Data (7FE0,0010) and the output units specified in Rescale Type (0028,1054). Output units = m*SV + b. Enumerated Value: 0 See C.8.11.3.1.2 for further explanation.
Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041) describe how the stored pixel values in Pixel Data (7FE0,0010) are related to the X-Ray beam intensity incident on the detector. They do not define a transformation intended to be applied to the pixel data for presentation. Note: For example, if Pixel Intensity Relationship (0028,1040) is LIN and Pixel Intensity Relationship Sign (0028,1041) is -1, then lower values of Pixel Data (7FE0,0010) indicate higher X-Ray beam intensities corresponding to less radiographically dense regions projected on the image such as through air, and higher values of Pixel Data (7FE0,0010) indicate lower X-Ray beam intensities corresponding to more radiographically dense regions projected on the image such as through bone and radio-opaque contrast agents. The transformation to be applied to the pixel data for presentation is defined by the successive application of the conceptual Modality LUT, the VOI Attributes and the conceptual Presentation LUT. This shall result in the output of P-Values. Rescale Slope (0028,1053) and Rescale Intercept (0028,1052) define a linear subset of a conceptual Modality LUT transformation. For IODs that include this Module, these Attributes define an identity transformation. IODs that include the DX Image Module shall not include the Modality LUT Module. The Presentation LUT Shape (2050,0020) defines a subset of a conceptual Presentation LUT. For IODs that include this Module, this Attribute defines an identity transformation or inverse identity transformation. IODs that include the DX Image Module shall not include the Presentation LUT Module. Photometric Interpretation (0028,0004) indicates whether lower values that are the output of the VOI Attributes should be displayed as darker or lighter. Since the output of the equivalent of a conceptual Presentation LUT is in P-Values, which are defined in PS 3.14 such that lower values correspond to lower luminance levels, then the definition of the Presentation LUT Shape (2050,0020), otherwise intended to be an identity transformation, must take into account the effect of the value specified for Photometric Interpretation (0028,0004). Note: Regardless of the values of Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041), the grayscale transformations to be applied to the Pixel Data (7FE0,0010) are defined by the equivalent of the Modality LUT (Rescale Slope (0028,1053) and Rescale Intercept (0028,1052)), Value of Interest Attributes, Photometric Interpretation (0028,0004) and the equivalent of the Presentation LUT (Presentation LUT Shape (2050,0020)). However, the combination of the grayscale transformations and the description of the pixel intensity relationship, together define whether, for example, air is expected to be displayed as black or white.
m in the equation specified by Rescale Intercept (0028,1052). Enumerated Value: 1 See C.8.11.3.1.2 for further explanation.
Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041) describe how the stored pixel values in Pixel Data (7FE0,0010) are related to the X-Ray beam intensity incident on the detector. They do not define a transformation intended to be applied to the pixel data for presentation. Note: For example, if Pixel Intensity Relationship (0028,1040) is LIN and Pixel Intensity Relationship Sign (0028,1041) is -1, then lower values of Pixel Data (7FE0,0010) indicate higher X-Ray beam intensities corresponding to less radiographically dense regions projected on the image such as through air, and higher values of Pixel Data (7FE0,0010) indicate lower X-Ray beam intensities corresponding to more radiographically dense regions projected on the image such as through bone and radio-opaque contrast agents. The transformation to be applied to the pixel data for presentation is defined by the successive application of the conceptual Modality LUT, the VOI Attributes and the conceptual Presentation LUT. This shall result in the output of P-Values. Rescale Slope (0028,1053) and Rescale Intercept (0028,1052) define a linear subset of a conceptual Modality LUT transformation. For IODs that include this Module, these Attributes define an identity transformation. IODs that include the DX Image Module shall not include the Modality LUT Module. The Presentation LUT Shape (2050,0020) defines a subset of a conceptual Presentation LUT. For IODs that include this Module, this Attribute defines an identity transformation or inverse identity transformation. IODs that include the DX Image Module shall not include the Presentation LUT Module. Photometric Interpretation (0028,0004) indicates whether lower values that are the output of the VOI Attributes should be displayed as darker or lighter. Since the output of the equivalent of a conceptual Presentation LUT is in P-Values, which are defined in PS 3.14 such that lower values correspond to lower luminance levels, then the definition of the Presentation LUT Shape (2050,0020), otherwise intended to be an identity transformation, must take into account the effect of the value specified for Photometric Interpretation (0028,0004). Note: Regardless of the values of Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041), the grayscale transformations to be applied to the Pixel Data (7FE0,0010) are defined by the equivalent of the Modality LUT (Rescale Slope (0028,1053) and Rescale Intercept (0028,1052)), Value of Interest Attributes, Photometric Interpretation (0028,0004) and the equivalent of the Presentation LUT (Presentation LUT Shape (2050,0020)). However, the combination of the grayscale transformations and the description of the pixel intensity relationship, together define whether, for example, air is expected to be displayed as black or white.
Specifies the output units of Rescale Slope (0028,1053) and Rescale Intercept (0028,1052). Enumerated Value: US = Unspecified See C.8.11.3.1.2 for further explanation.
Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041) describe how the stored pixel values in Pixel Data (7FE0,0010) are related to the X-Ray beam intensity incident on the detector. They do not define a transformation intended to be applied to the pixel data for presentation. Note: For example, if Pixel Intensity Relationship (0028,1040) is LIN and Pixel Intensity Relationship Sign (0028,1041) is -1, then lower values of Pixel Data (7FE0,0010) indicate higher X-Ray beam intensities corresponding to less radiographically dense regions projected on the image such as through air, and higher values of Pixel Data (7FE0,0010) indicate lower X-Ray beam intensities corresponding to more radiographically dense regions projected on the image such as through bone and radio-opaque contrast agents. The transformation to be applied to the pixel data for presentation is defined by the successive application of the conceptual Modality LUT, the VOI Attributes and the conceptual Presentation LUT. This shall result in the output of P-Values. Rescale Slope (0028,1053) and Rescale Intercept (0028,1052) define a linear subset of a conceptual Modality LUT transformation. For IODs that include this Module, these Attributes define an identity transformation. IODs that include the DX Image Module shall not include the Modality LUT Module. The Presentation LUT Shape (2050,0020) defines a subset of a conceptual Presentation LUT. For IODs that include this Module, this Attribute defines an identity transformation or inverse identity transformation. IODs that include the DX Image Module shall not include the Presentation LUT Module. Photometric Interpretation (0028,0004) indicates whether lower values that are the output of the VOI Attributes should be displayed as darker or lighter. Since the output of the equivalent of a conceptual Presentation LUT is in P-Values, which are defined in PS 3.14 such that lower values correspond to lower luminance levels, then the definition of the Presentation LUT Shape (2050,0020), otherwise intended to be an identity transformation, must take into account the effect of the value specified for Photometric Interpretation (0028,0004). Note: Regardless of the values of Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041), the grayscale transformations to be applied to the Pixel Data (7FE0,0010) are defined by the equivalent of the Modality LUT (Rescale Slope (0028,1053) and Rescale Intercept (0028,1052)), Value of Interest Attributes, Photometric Interpretation (0028,0004) and the equivalent of the Presentation LUT (Presentation LUT Shape (2050,0020)). However, the combination of the grayscale transformations and the description of the pixel intensity relationship, together define whether, for example, air is expected to be displayed as black or white.
Specifies an identity transformation for the Presentation LUT, other than to account for the value of Photometric Interpretation (0028,0004), such that the output of all grayscale transformations defined in the IOD containing this Module are defined to be P-Values. Enumerated Values: IDENTITY - output is in P-Values - shall be used if Photometric Interpretation (0028,0004) is MONOCHROME2. INVERSE - output after inversion is in P-Values - shall be used if Photometric Interpretation (0028,0004) is MONOCHROME1. See C.8.11.3.1.2 for further explanation.
Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041) describe how the stored pixel values in Pixel Data (7FE0,0010) are related to the X-Ray beam intensity incident on the detector. They do not define a transformation intended to be applied to the pixel data for presentation. Note: For example, if Pixel Intensity Relationship (0028,1040) is LIN and Pixel Intensity Relationship Sign (0028,1041) is -1, then lower values of Pixel Data (7FE0,0010) indicate higher X-Ray beam intensities corresponding to less radiographically dense regions projected on the image such as through air, and higher values of Pixel Data (7FE0,0010) indicate lower X-Ray beam intensities corresponding to more radiographically dense regions projected on the image such as through bone and radio-opaque contrast agents. The transformation to be applied to the pixel data for presentation is defined by the successive application of the conceptual Modality LUT, the VOI Attributes and the conceptual Presentation LUT. This shall result in the output of P-Values. Rescale Slope (0028,1053) and Rescale Intercept (0028,1052) define a linear subset of a conceptual Modality LUT transformation. For IODs that include this Module, these Attributes define an identity transformation. IODs that include the DX Image Module shall not include the Modality LUT Module. The Presentation LUT Shape (2050,0020) defines a subset of a conceptual Presentation LUT. For IODs that include this Module, this Attribute defines an identity transformation or inverse identity transformation. IODs that include the DX Image Module shall not include the Presentation LUT Module. Photometric Interpretation (0028,0004) indicates whether lower values that are the output of the VOI Attributes should be displayed as darker or lighter. Since the output of the equivalent of a conceptual Presentation LUT is in P-Values, which are defined in PS 3.14 such that lower values correspond to lower luminance levels, then the definition of the Presentation LUT Shape (2050,0020), otherwise intended to be an identity transformation, must take into account the effect of the value specified for Photometric Interpretation (0028,0004). Note: Regardless of the values of Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041), the grayscale transformations to be applied to the Pixel Data (7FE0,0010) are defined by the equivalent of the Modality LUT (Rescale Slope (0028,1053) and Rescale Intercept (0028,1052)), Value of Interest Attributes, Photometric Interpretation (0028,0004) and the equivalent of the Presentation LUT (Presentation LUT Shape (2050,0020)). However, the combination of the grayscale transformations and the description of the pixel intensity relationship, together define whether, for example, air is expected to be displayed as black or white.
Specifies whether an Image has undergone lossy compression. Enumerated Values: 00 = Image has NOT been subjected to lossy compression. 01 = Image has been subjected to lossy compression. See C.7.6.1.1.5 for further explanation.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
See C.7.6.1.1.5 for further explanation. Required if Lossy Compression has been performed on the Image.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
A text description of how this image was derived. See C.8.11.3.1.4 for further explanation.
If an Image is identified to be a Derived image in Image Type (0008,0008), Derivation Description (0008,2111) is an optional and implementation specific text description of the way the image was derived from an original image. As applied to DX images, it may be used to describe derivation operations such as edge enhancement, temporal filtering, digital subtraction, or other linear and non-linear transformations.
Indicates any visual processing performed on the images prior to exchange. See C.8.11.3.1.3 for further explanation.
Acquisition Device Processing Description (0018,1400) provides some indication in human readable text of the digital processing on the images before exchange. Examples of this processing are: edge enhanced, subtracted, time filtered, gamma corrected, convolved (spatially filtered).
Code representing the device-specific processing associated with the image (e.g. Organ Filtering code) Note: This Code is manufacturer specific but provides useful annotation information to the knowledgeable observer. Patient direction of the rows and columns of the image. See C.7.6.1.1.1 for further explanation.
The Patient Orientation (0020,0020) relative to the image plane shall be specified by two values that designate the anatomical direction of the positive row axis (left to right) and the positive column axis (top to bottom). The first entry is the direction of the rows, given by the direction of the last pixel in the first row from the first pixel in that row. The second entry is the direction of the columns, given by the direction of the last pixel in the first column from the first pixel in that column. Anatomical direction shall be designated by the capital letters: A (anterior), P (posterior), R (right), L (left), H (head), F (foot). Each value of the orientation attribute shall contain at least one of these characters. If refinements in the orientation descriptions are to be specified, then they shall be designated by one or two additional letters in each value. Within each value, the letters shall be ordered with the principal orientation designated in the first character.
Indicates whether a reference object (phantom) of known size is present in the image and was used for calibration. Enumerated Values: YES NO Device is identified using the Device module. See C.7.6.12 for further explanation.
Table C.7-18 describes the Attributes of devices or calibration objects (e.g., catheters, markers, baskets) that are associated with a study and/or image. Table C.7-18 DEVICE MODULE ATTRIBUTES
Indicates whether or not image contains sufficient burned in annotation to identify the patient and date the image was acquired. Enumerated Values: YES NO Defines a sequence of VOI LUTs. See C.8.11.3.1.5 for further explanation. One or more Items may be included in this Sequence. Required if Presentation Intent Type (0008,0068) is FOR PRESENTATION and Window Center (0028,1050) is not present. May also be present if Window Center (0028,1050) is present.
The Attributes of the VOI LUT Module (C.11.2) are specialized in the DX Image Module. Window Center (0028,1050) and Window Width (0028,1051) specify a linear conversion (unless otherwise specified by the value of VOI LUT Function (0028,1056); see C.11.2.1.3) from the output of the (conceptual) Modality LUT values to the input to the (conceptual) Presentation LUT. Window Center contains the value that is the center of the window. Window Width contains the width of the window. The application of the Window Center (0028,1050) and Window Width (0028,1051) shall not produce a signed result. 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. 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). The first value is the number of entries in the lookup table. The second value is the first stored pixel value mapped. This pixel value is mapped to the first entry in the LUT. All image pixel values less than the first value mapped are also mapped to the first entry in the LUT Data. An image pixel value one greater than the first value mapped is mapped to the second entry in the LUT Data. Subsequent image pixel values are mapped to the subsequent entries in the LUT Data up to an image pixel value equal to number of entries + first value mapped - 1 which is mapped to the last entry in the LUT Data. Image pixel values greater than number of entries + first value mapped are also mapped to the last entry in the LUT Data. The third value specifies the number of bits for each entry in the LUT Data (analogous to “bits stored”). It shall be between 10-16. The LUT Data shall be stored in a format equivalent to 16 “bits allocated” and “high bit” equal to “bits stored” - 1. The third value conveys the range of LUT entry values. These unsigned LUT entry values shall range between 0 and 2 n -1, where n is the third value of the LUT Descriptor. Notes: 1. The third value is restricted in the VOI LUT Module to 8 or 16 but is specialized here. 2. The first and second values are not specialized and are the same as in the VOI LUT Module. The LUT Data (0028,3006) contains the LUT entry values.
Specifies the format of the LUT Data in this Sequence. See C.8.11.3.1.5 for further explanation. Required if the VOI LUT Sequence (0028,3010) is sent.
The Attributes of the VOI LUT Module (C.11.2) are specialized in the DX Image Module. Window Center (0028,1050) and Window Width (0028,1051) specify a linear conversion (unless otherwise specified by the value of VOI LUT Function (0028,1056); see C.11.2.1.3) from the output of the (conceptual) Modality LUT values to the input to the (conceptual) Presentation LUT. Window Center contains the value that is the center of the window. Window Width contains the width of the window. The application of the Window Center (0028,1050) and Window Width (0028,1051) shall not produce a signed result. 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. 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). The first value is the number of entries in the lookup table. The second value is the first stored pixel value mapped. This pixel value is mapped to the first entry in the LUT. All image pixel values less than the first value mapped are also mapped to the first entry in the LUT Data. An image pixel value one greater than the first value mapped is mapped to the second entry in the LUT Data. Subsequent image pixel values are mapped to the subsequent entries in the LUT Data up to an image pixel value equal to number of entries + first value mapped - 1 which is mapped to the last entry in the LUT Data. Image pixel values greater than number of entries + first value mapped are also mapped to the last entry in the LUT Data. The third value specifies the number of bits for each entry in the LUT Data (analogous to “bits stored”). It shall be between 10-16. The LUT Data shall be stored in a format equivalent to 16 “bits allocated” and “high bit” equal to “bits stored” - 1. The third value conveys the range of LUT entry values. These unsigned LUT entry values shall range between 0 and 2 n -1, where n is the third value of the LUT Descriptor. Notes: 1. The third value is restricted in the VOI LUT Module to 8 or 16 but is specialized here. 2. The first and second values are not specialized and are the same as in the VOI LUT Module. The LUT Data (0028,3006) contains the LUT entry values.
Free form text explanation of the meaning of the LUT. LUT Data in this Sequence. Required if the VOI LUT Sequence (0028,3010) is sent. Defines a Window Center for display. See C.8.11.3.1.5 for further explanation. Required if Presentation Intent Type (0008,0068) is FOR PRESENTATION and VOI LUT Sequence (0028,3010) is not present. May also be present if VOI LUT Sequence (0028,3010) is present.
The Attributes of the VOI LUT Module (C.11.2) are specialized in the DX Image Module. Window Center (0028,1050) and Window Width (0028,1051) specify a linear conversion (unless otherwise specified by the value of VOI LUT Function (0028,1056); see C.11.2.1.3) from the output of the (conceptual) Modality LUT values to the input to the (conceptual) Presentation LUT. Window Center contains the value that is the center of the window. Window Width contains the width of the window. The application of the Window Center (0028,1050) and Window Width (0028,1051) shall not produce a signed result. 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. 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). The first value is the number of entries in the lookup table. The second value is the first stored pixel value mapped. This pixel value is mapped to the first entry in the LUT. All image pixel values less than the first value mapped are also mapped to the first entry in the LUT Data. An image pixel value one greater than the first value mapped is mapped to the second entry in the LUT Data. Subsequent image pixel values are mapped to the subsequent entries in the LUT Data up to an image pixel value equal to number of entries + first value mapped - 1 which is mapped to the last entry in the LUT Data. Image pixel values greater than number of entries + first value mapped are also mapped to the last entry in the LUT Data. The third value specifies the number of bits for each entry in the LUT Data (analogous to “bits stored”). It shall be between 10-16. The LUT Data shall be stored in a format equivalent to 16 “bits allocated” and “high bit” equal to “bits stored” - 1. The third value conveys the range of LUT entry values. These unsigned LUT entry values shall range between 0 and 2 n -1, where n is the third value of the LUT Descriptor. Notes: 1. The third value is restricted in the VOI LUT Module to 8 or 16 but is specialized here. 2. The first and second values are not specialized and are the same as in the VOI LUT Module. The LUT Data (0028,3006) contains the LUT entry values.
Window Width for display. See C.8.11.3.1.5 for further explanation. Required if Window Center (0028,1050) is sent.
The Attributes of the VOI LUT Module (C.11.2) are specialized in the DX Image Module. Window Center (0028,1050) and Window Width (0028,1051) specify a linear conversion (unless otherwise specified by the value of VOI LUT Function (0028,1056); see C.11.2.1.3) from the output of the (conceptual) Modality LUT values to the input to the (conceptual) Presentation LUT. Window Center contains the value that is the center of the window. Window Width contains the width of the window. The application of the Window Center (0028,1050) and Window Width (0028,1051) shall not produce a signed result. 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. 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). The first value is the number of entries in the lookup table. The second value is the first stored pixel value mapped. This pixel value is mapped to the first entry in the LUT. All image pixel values less than the first value mapped are also mapped to the first entry in the LUT Data. An image pixel value one greater than the first value mapped is mapped to the second entry in the LUT Data. Subsequent image pixel values are mapped to the subsequent entries in the LUT Data up to an image pixel value equal to number of entries + first value mapped - 1 which is mapped to the last entry in the LUT Data. Image pixel values greater than number of entries + first value mapped are also mapped to the last entry in the LUT Data. The third value specifies the number of bits for each entry in the LUT Data (analogous to “bits stored”). It shall be between 10-16. The LUT Data shall be stored in a format equivalent to 16 “bits allocated” and “high bit” equal to “bits stored” - 1. The third value conveys the range of LUT entry values. These unsigned LUT entry values shall range between 0 and 2 n -1, where n is the third value of the LUT Descriptor. Notes: 1. The third value is restricted in the VOI LUT Module to 8 or 16 but is specialized here. 2. The first and second values are not specialized and are the same as in the VOI LUT Module. The LUT Data (0028,3006) contains the LUT entry values.
Free form explanation of the meaning of the Window Center and Width. Multiple values correspond to multiple Window Center and Width values.
Time in mSec that the detector is active during acquisition of this image. Note: This activation window overlaps the time of the X-Ray exposure as defined by Exposure Time (0018,1150) and Detector Activation Offset From Exposure (0018,7016). Offset time in mSec that the detector becomes active after the X-Ray beam is turned on during acquisition of this image. May be negative. Shape of the Field of View, that is the image pixels stored in Pixel Data (7FE0,0010). Enumerated Values: RECTANGLE ROUND HEXAGONAL Dimensions in mm of the Field of View, that is the image pixels stored in Pixel Data (7FE0,0010). If Field of View Shape (0018,1147) is: RECTANGLE: row dimension followed by column. ROUND: diameter. HEXAGONAL: diameter of a circumscribed circle. Offset of the TLHC of a rectangle circumscribing the Field of View, that is the image pixels stored in Pixel Data (7FE0,0010), before rotation or flipping, from the TLHC of the physical detector area measured in physical detector pixels as a row offset followed by a column offset. Required if Field of View Rotation (0018,7032) or Field of View Horizontal Flip (0018,7034) is present. See C.8.11.4.1.1 for further explanation.
The relationship between the Physical Detector Area, the Active Detector Area, the Field of View (what is stored in the Pixel Data (7FE0,0010)), the Exposed Area (after X-Ray Collimation) and the Displayed Area is illustrated in the following diagrams. Note: Some of these Attributes relate the image data to manufacturer specific characteristics of the detector that may be used for quality control purposes, e.g. correlation of image artifacts with a detector defect map, analysis of noise performance, etc. The Displayed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the Display Shutter Module (see section C.7.6.11). If this Module is not present or supported, then the Displayed Area is equal to the Field of View. The Exposed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the X-Ray Collimator Module (see section C.8.7.3). For the Digital X-Ray IODs, the Field of View is usually rectangular in shape and the same size as the stored Pixel Data (7FE0,0010). The shape and size of the Field of View and the spacing of the pixels are defined by the following Attributes: - Field of View Shape (0018,1147), - Field of View Dimensions (0018,1149), - Imager Pixel Spacing (0018,1164), - Rows (0028,0010), - Columns (0028,0011) The following Attributes define the relationship of the Field of View to the Physical Detector Area: - Field of View Origin (0018,7030), - Field of View Rotation (0018,7032), - Field of View Horizontal Flip (0018,7034). For the Digital X-Ray IODs, the Active Area, i.e. that part of the detector matrix that was activated for this exposure, is usually rectangular in shape. The shape and size of the Active Area and the size and spacing of the detectors are defined by the following Attributes: - Detector Active Shape (0018,7024), - Detector Active Dimensions (0018,7026), - Detector Element Physical Size (0018,7020), - Detector Element Spacing (0018,7022). Notes: 1. The Detector Element Physical Size (0018,7020) and Detector Element Spacing (0018,7022) may be different if there are insensitive regions between each detector. 2. This model of description is not able to accurately describe multiple matrices of detectors that are “tiled” to produce a single image. The following optional Attribute defines the relationship of the Active Area to the Physical Detector Area: - Detector Active Origin (0018,7028). The relationship between detectors and stored image pixels is defined by Detector Binning (0018,701A) which specifies how many detectors, in each of the row and column directions, contribute to (are pooled or averaged to form) a single stored image pixel. Note: Detector Binning (0018,701A) may have values less than one if sub-sampling is used to derive an image with higher spatial resolution than the detector matrix. Figure C.8-14 Explanation of DX Detector Attributes Figure C.8-15 Explanation of DX Detector Attributes
Clockwise rotation in degrees of Field of View, that is the image pixels stored in Pixel Data (7FE0,0010), relative to the physical detector. Enumerated Values: 0, 90, 180, 270 Required if Field of View Horizontal Flip (0018,7034) is present. See C.8.11.4.1.1 for further explanation.
The relationship between the Physical Detector Area, the Active Detector Area, the Field of View (what is stored in the Pixel Data (7FE0,0010)), the Exposed Area (after X-Ray Collimation) and the Displayed Area is illustrated in the following diagrams. Note: Some of these Attributes relate the image data to manufacturer specific characteristics of the detector that may be used for quality control purposes, e.g. correlation of image artifacts with a detector defect map, analysis of noise performance, etc. The Displayed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the Display Shutter Module (see section C.7.6.11). If this Module is not present or supported, then the Displayed Area is equal to the Field of View. The Exposed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the X-Ray Collimator Module (see section C.8.7.3). For the Digital X-Ray IODs, the Field of View is usually rectangular in shape and the same size as the stored Pixel Data (7FE0,0010). The shape and size of the Field of View and the spacing of the pixels are defined by the following Attributes: - Field of View Shape (0018,1147), - Field of View Dimensions (0018,1149), - Imager Pixel Spacing (0018,1164), - Rows (0028,0010), - Columns (0028,0011) The following Attributes define the relationship of the Field of View to the Physical Detector Area: - Field of View Origin (0018,7030), - Field of View Rotation (0018,7032), - Field of View Horizontal Flip (0018,7034). For the Digital X-Ray IODs, the Active Area, i.e. that part of the detector matrix that was activated for this exposure, is usually rectangular in shape. The shape and size of the Active Area and the size and spacing of the detectors are defined by the following Attributes: - Detector Active Shape (0018,7024), - Detector Active Dimensions (0018,7026), - Detector Element Physical Size (0018,7020), - Detector Element Spacing (0018,7022). Notes: 1. The Detector Element Physical Size (0018,7020) and Detector Element Spacing (0018,7022) may be different if there are insensitive regions between each detector. 2. This model of description is not able to accurately describe multiple matrices of detectors that are “tiled” to produce a single image. The following optional Attribute defines the relationship of the Active Area to the Physical Detector Area: - Detector Active Origin (0018,7028). The relationship between detectors and stored image pixels is defined by Detector Binning (0018,701A) which specifies how many detectors, in each of the row and column directions, contribute to (are pooled or averaged to form) a single stored image pixel. Note: Detector Binning (0018,701A) may have values less than one if sub-sampling is used to derive an image with higher spatial resolution than the detector matrix. Figure C.8-14 Explanation of DX Detector Attributes Figure C.8-15 Explanation of DX Detector Attributes
Whether or not a horizontal flip has been applied to the Field of View, that is the image pixels stored in Pixel Data (7FE0,0010), after rotation relative to the physical detector as described in Field of View Rotation (0018,7032). Enumerated Values: NO YES Required if Field of View Rotation (0018,7032) is present. See C.8.11.4.1.1 for further explanation.
The relationship between the Physical Detector Area, the Active Detector Area, the Field of View (what is stored in the Pixel Data (7FE0,0010)), the Exposed Area (after X-Ray Collimation) and the Displayed Area is illustrated in the following diagrams. Note: Some of these Attributes relate the image data to manufacturer specific characteristics of the detector that may be used for quality control purposes, e.g. correlation of image artifacts with a detector defect map, analysis of noise performance, etc. The Displayed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the Display Shutter Module (see section C.7.6.11). If this Module is not present or supported, then the Displayed Area is equal to the Field of View. The Exposed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the X-Ray Collimator Module (see section C.8.7.3). For the Digital X-Ray IODs, the Field of View is usually rectangular in shape and the same size as the stored Pixel Data (7FE0,0010). The shape and size of the Field of View and the spacing of the pixels are defined by the following Attributes: - Field of View Shape (0018,1147), - Field of View Dimensions (0018,1149), - Imager Pixel Spacing (0018,1164), - Rows (0028,0010), - Columns (0028,0011) The following Attributes define the relationship of the Field of View to the Physical Detector Area: - Field of View Origin (0018,7030), - Field of View Rotation (0018,7032), - Field of View Horizontal Flip (0018,7034). For the Digital X-Ray IODs, the Active Area, i.e. that part of the detector matrix that was activated for this exposure, is usually rectangular in shape. The shape and size of the Active Area and the size and spacing of the detectors are defined by the following Attributes: - Detector Active Shape (0018,7024), - Detector Active Dimensions (0018,7026), - Detector Element Physical Size (0018,7020), - Detector Element Spacing (0018,7022). Notes: 1. The Detector Element Physical Size (0018,7020) and Detector Element Spacing (0018,7022) may be different if there are insensitive regions between each detector. 2. This model of description is not able to accurately describe multiple matrices of detectors that are “tiled” to produce a single image. The following optional Attribute defines the relationship of the Active Area to the Physical Detector Area: - Detector Active Origin (0018,7028). The relationship between detectors and stored image pixels is defined by Detector Binning (0018,701A) which specifies how many detectors, in each of the row and column directions, contribute to (are pooled or averaged to form) a single stored image pixel. Note: Detector Binning (0018,701A) may have values less than one if sub-sampling is used to derive an image with higher spatial resolution than the detector matrix. Figure C.8-14 Explanation of DX Detector Attributes Figure C.8-15 Explanation of DX Detector Attributes
Physical distance measured at the front plane of the detector housing between the center of each image pixel specified by a numeric pair - row spacing value(delimiter) column spacing value in mm. See 10.7.1.3 for further explanation of the value order. The value of this attribute shall never be adjusted to account for correction for the effect of geometric magnification or calibration against an object of known size; Pixel Spacing (0028,0030) is specified for that purpose. Identifier of the cassette that contains the photostimulable phosphor plate, for CR acquisitions. Identifier of the photostimulable phosphor plate, for CR acquisitions.
The type of detector used to acquire this image. Defined Terms: DIRECT = X-Ray photoconductor SCINTILLATOR = Phosphor used STORAGE = Storage phosphor FILM = Scanned film/screen The physical configuration of the detector. Defined Terms: AREA = single or tiled detector SLOT = scanned slot, slit or spot Free text description of detector. Text description of operating mode of detector (implementation specific). The ID or serial number of the detector used to acquire this image. The date on which the detector used to acquire this image as identified in Detector ID (0018,700A) was last calibrated. The time at which the detector used to acquire this image as identified in Detector ID (0018,700A) was last calibrated. Total number of X-Ray exposures that have been made on the detector used to acquire this image as identified in Detector ID (0018,700A) since it was calibrated. Total number of X-Ray exposures that have been made on the detector used to acquire this image as identified in Detector ID (0018,700A) since it was manufactured. Time in Seconds since an exposure was last made on this detector prior to the acquisition of this image. Number of active detectors used to generate a single pixel. Specified as number of row detectors per pixel then column. Name of the manufacturer of the detector component of the acquisition system Model name of the detector component of the acquisition system Whether or not the detector is operating within normal tolerances during this image acquisition. Enumerated Values: YES NO Note: This flag is intended to indicate whether or not there may have been some compromise of the diagnostic quality of the image due to some condition such as over-temperature, etc. Detector temperature during exposure in degrees Celsius. Detector sensitivity in manufacturer specific units. Note: This value is intended to provide a single location where manufacturer specific information can be found for annotation on a display or film, that has meaning to a knowledgeable observer. Physical dimensions of each detector element that comprises the detector matrix, in mm. Expressed as row dimension followed by column. Note: This may not be the same as Detector Element Spacing (0018,7022) due to the presence of spacing material between detector elements. Physical distance between the center of each detector element, specified by a numeric pair - row spacing value(delimiter) column spacing value in mm. See 10.7.1.3 for further explanation of the value order. Note: This may not be the same as the Imager Pixel Spacing (0018,1164), and should not be assumed to describe the stored image. Shape of the active area. Enumerated Value: RECTANGLE ROUND HEXAGONAL Note: This may be different from the Field of View Shape (0018,1147), and should not be assumed to describe the stored image. Dimensions in mm of the active area. If Detector Active Shape(0018,7024) is: RECTANGLE: row dimension followed by column. ROUND: diameter. HEXAGONAL: diameter of a circumscribed circle. Note: This may be different from the Field of View Dimensions (0018,1149), and should not be assumed to describe the stored image. Offset of the TLHC of a rectangle circumscribing the active detector area from the TLHC of a rectangle circumscribing the physical detector area, measured in physical detector pixels as a row offset followed by a column offset. See C.8.11.4.1.1 for further explanation.
The relationship between the Physical Detector Area, the Active Detector Area, the Field of View (what is stored in the Pixel Data (7FE0,0010)), the Exposed Area (after X-Ray Collimation) and the Displayed Area is illustrated in the following diagrams. Note: Some of these Attributes relate the image data to manufacturer specific characteristics of the detector that may be used for quality control purposes, e.g. correlation of image artifacts with a detector defect map, analysis of noise performance, etc. The Displayed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the Display Shutter Module (see section C.7.6.11). If this Module is not present or supported, then the Displayed Area is equal to the Field of View. The Exposed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the X-Ray Collimator Module (see section C.8.7.3). For the Digital X-Ray IODs, the Field of View is usually rectangular in shape and the same size as the stored Pixel Data (7FE0,0010). The shape and size of the Field of View and the spacing of the pixels are defined by the following Attributes: - Field of View Shape (0018,1147), - Field of View Dimensions (0018,1149), - Imager Pixel Spacing (0018,1164), - Rows (0028,0010), - Columns (0028,0011) The following Attributes define the relationship of the Field of View to the Physical Detector Area: - Field of View Origin (0018,7030), - Field of View Rotation (0018,7032), - Field of View Horizontal Flip (0018,7034). For the Digital X-Ray IODs, the Active Area, i.e. that part of the detector matrix that was activated for this exposure, is usually rectangular in shape. The shape and size of the Active Area and the size and spacing of the detectors are defined by the following Attributes: - Detector Active Shape (0018,7024), - Detector Active Dimensions (0018,7026), - Detector Element Physical Size (0018,7020), - Detector Element Spacing (0018,7022). Notes: 1. The Detector Element Physical Size (0018,7020) and Detector Element Spacing (0018,7022) may be different if there are insensitive regions between each detector. 2. This model of description is not able to accurately describe multiple matrices of detectors that are “tiled” to produce a single image. The following optional Attribute defines the relationship of the Active Area to the Physical Detector Area: - Detector Active Origin (0018,7028). The relationship between detectors and stored image pixels is defined by Detector Binning (0018,701A) which specifies how many detectors, in each of the row and column directions, contribute to (are pooled or averaged to form) a single stored image pixel. Note: Detector Binning (0018,701A) may have values less than one if sub-sampling is used to derive an image with higher spatial resolution than the detector matrix. Figure C.8-14 Explanation of DX Detector Attributes Figure C.8-15 Explanation of DX Detector Attributes
A Sequence that describes the radiographic method of patient, tube and detector positioning to achieve a well described projection or view. Only a single Item shall be permitted in this Sequence. Shall be consistent with the other Attributes in this Module, if present, but may more specifically describe the image acquisition. Description of imaging subject's position relative to the equipment. See C.7.3.1.1.2 for Defined Terms and further explanation. If present, shall be consistent with Patient Gantry Relationship Code Sequence (0054,0414) and Patient Orientation Modifier Code Sequence (0054,0412).
Patient Position (0018,5100) specifies the position of the patient relative to the imaging equipment space. This attribute is intended for annotation purposes only. It does not provide an exact mathematical relationship of the patient to the imaging equipment. When facing the front of the imaging equipment, Head First is defined as the patient’s head being positioned toward the front of the imaging equipment. Feet First is defined as the patient’s feet being positioned toward the front of the imaging equipment. Prone is defined as the patient’s face being positioned in a downward (gravity) direction. Supine is defined as the patient’s face being in an upward direction. Decubitus Right is defined as the patient’s right side being in a downward direction. Decubitus Left is defined as the patient’s left side being in a downward direction. The Defined Terms are:
Radiographic view of the image relative to the imaging subject's orientation. Shall be consistent with View Code Sequence (0054,0220). See C.8.11.5.1.1 for further explanation.
View Code Sequence (0054,0220) replaces the function of View Position (0018,5101), and describes the radiographic view of the image relative to the real-world patient orientation as described in PS 3.17 annex on Explanation of Patient Orientation.
Sequence that describes the projection of the anatomic region of interest on the image receptor. Note: It is strongly recommended that this Attribute be present, in order to ensure that images may be positioned correctly relative to one another for display. Shall be consistent with View Position (0018,5101). See C.8.11.5.1.1 for further explanation. Only a single Item shall be permitted in this Sequence.
View Code Sequence (0054,0220) replaces the function of View Position (0018,5101), and describes the radiographic view of the image relative to the real-world patient orientation as described in PS 3.17 annex on Explanation of Patient Orientation.
View modifier. Zero or more Items may be included in this Sequence. Sequence that describes the orientation of the patient with respect to gravity. See C.8.11.5.1.2 for further explanation. Only a single Item shall be permitted in this Sequence.
This Attribute is not related to Patient Orientation (0020,0020) and conveys a different concept entirely.
Patient Orientation Modifier. Required if needed to fully specify the orientation of the patient with respect to gravity. Only a single Item shall be permitted in this Sequence. Sequence which describes the orientation of the patient with respect to the gantry. Only a single Item shall be permitted in this Sequence. Distance in mm from source to the table, support or bucky side that is closest to the Imaging Subject, as measured along the central ray of the X-Ray beam. Note: 1. This definition is less useful in terms of estimating geometric magnification than a measurement to a defined point within the Imaging Subject, but accounts for what is realistically measurable in an automated fashion in a clinical setting. 2. This measurement does not take into account any air gap between the Imaging Subject and the "front" of the table or bucky. 3. If the detector is not mounted in a table or bucky, then the actual position relative to the patient is implementation or operator defined. 4. This value is traditionally referred to as Source Object Distance (SOD). See C.8.11.7 Mammography Image Module for explanation if Positioner Type (0018,1508) is MAMMOGRAPHIC.
Table C.8-74 contains IOD Attributes that describe a Digital Mammography X-Ray Image including its acquisition and positioning. Table C.8-74 MAMMOGRAPHY IMAGE MODULE ATTRIBUTES
Distance in mm from source to detector center. Note: This value is traditionally referred to as Source Image Receptor Distance (SID). See C.8.11.7 Mammography Image Module for explanation if Positioner Type (0018,1508) is MAMMOGRAPHIC.
Table C.8-74 contains IOD Attributes that describe a Digital Mammography X-Ray Image including its acquisition and positioning. Table C.8-74 MAMMOGRAPHY IMAGE MODULE ATTRIBUTES
Ratio of Source Image Receptor Distance (SID) over Source Object Distance (SOD). Defined Terms: CARM COLUMN MAMMOGRAPHIC PANORAMIC CEPHALOSTAT RIGID NONE Notes: 1. The term CARM can apply to any positioner with 2 degrees of freedom of rotation of the X-Ray beam about the Imaging Subject. 2. The term COLUMN can apply to any positioner with 1 degree of freedom of rotation of the X-Ray beam about the Imaging Subject. Position of the X-Ray beam about the patient from the RAO to LAO direction where movement from RAO to vertical is positive, if Positioner Type (0018,1508) is CARM. See C.8.7.5 XA Positioner Module for further explanation if Positioner Type (0018,1508) is CARM. See C.8.11.7 Mammography Image Module for explanation if Positioner Type (0018,1508) is MAMMOGRAPHIC. Position of the X-Ray beam about the patient from the CAU to CRA direction where movement from CAU to vertical is positive, if Positioner Type (0018,1508) is CARM. See C.8.7.5 XA Positioner Module for further explanation if Positioner Type (0018,1508) is CARM. See C.8.11.7 Mammography Image Module for explanation if Positioner Type (0018,1508) is MAMMOGRAPHIC. Angle of the X-Ray beam in the row direction in degrees relative to the normal to the detector plane. Positive values indicate that the X-Ray beam is tilted toward higher numbered columns. Negative values indicate that the X-Ray beam is tilted toward lower numbered columns. See C.8.7.5 XA Positioner Module for further explanation. See C.8.11.7 Mammography Image Module for explanation if Positioner Type (0018,1508) is MAMMOGRAPHIC. Angle of the X-Ray beam in the column direction in degrees relative to the normal to the detector plane. Positive values indicate that the X-Ray beam is tilted toward lower numbered rows. Negative values indicate that the X-Ray beam is tilted toward higher numbered rows. See C.8.7.5 XA Positioner Module for further explanation. See C.8.11.7 Mammography Image Module for explanation if Positioner Type (0018,1508) is MAMMOGRAPHIC. Angle of the X-Ray beam in degree relative to an orthogonal axis to the detector plane. Positive values indicate that the tilt is toward the head of the table. Note: The detector plane is assumed to be parallel to the table plane. Only meaningful if Positioner Type (0018,1508) is COLUMN. Defined Terms: FIXED TILTING NONE Angle of table plane in degrees relative to horizontal plane [Gravity plane]. Positive values indicate that the head of the table is upward. Only meaningful if Table Type (0018,113A) is TILTING. The average thickness in mm of the body part examined when compressed, if compression has been applied during exposure. The compression force applied to the body part during exposure, measured in Newtons.
Type of equipment that originally acquired the data used to create the images in this Series. Enumerated Value: MG See section C.7.3.1.1.1 for further explanation. Sequence that contains attributes from the Imaging Service Request. The sequence may have one or more Items. Enumerated Values: MAMMOGRAPHIC NONE Distance in mm from source to detector center on the chest wall line Notes: 1. This value is traditionally referred to as Source Image Distance (SID). 2. See C.8.11.7.1.1.
Figure C.8-8 shows the X-Ray beam for a digital mammography system. The X-Ray beam vector is defined from the Focal Spot to the center of the chest wall line of the Image Detection device. Figure C.8-8
Distance in mm from source to the bucky side that is closest to the Imaging Subject, as measured along the X-Ray beam vector. Notes: 1. This value is traditionally referred to as Source Object Distance (SOD). 2. See notes for this attribute in C.8.11.5 DX Positioning Module. 3. See C.8.11.7.1.1 for description of X-Ray beam vector.
Figure C.8-8 shows the X-Ray beam for a digital mammography system. The X-Ray beam vector is defined from the Focal Spot to the center of the chest wall line of the Image Detection device. Figure C.8-8
Position in degrees of the X-Ray beam vector in the coronal anatomical plane as if the patient were standing where movement of the X-Ray source from right to vertical is positive, and vertical is zero. Position in degrees of the X-Ray beam vector in the sagittal anatomical plane as if the patient were standing where movement of the X-Ray source from anterior to posterior is positive, and vertical is zero. Laterality of the region examined. Enumerated Values: R = right L = left B = both (e.g. cleavage) Organ to which Organ Dose (0040,0316) applies. Enumerated Value: BREAST Note: In the Mammography IOD, Organ Dose (0040,0316) refers to the mean glandular dose. Whether or not an implant is present. Enumerated Values: YES NO Indicates whether this image is a partial view, that is a subset of a single view of the breast. Enumerated Values: YES, NO If this Attribute is absent, then the image may or may not be a partial view. Note: This may occur when a breast is larger than the active area of the detector. If this Attribute is present, its value shall be NO if there is a View Modifier Code Sequence (0054,0222) Item of value (R-102D6, SNM3, "Magnification") or (R-102D7, SNM3, "Spot Compression"). Free text description of the portion of the breast captured in a partial view image. This Attribute shall not be present if there is a View Modifier Code Sequence (0054,0222) Item of value (R-102D6, SNM3, "Magnification") or (R-102D7, SNM3, "Spot Compression"). Sequence that describes the portion or section of the breast captured in a partial view image. One or two Items may be present. See C.8.11.7.1.3. If this Attribute is absent, then the image may or may not be a partial view. This Attribute shall not be present if there is a View Modifier Code Sequence (0054,0222) Item of value (R-102D6, SNM3, "Magnification") or (R-102D7, SNM3, "Spot Compression").
The following combinations of coded terms may be used to express the breast sections, for example, for the left cranio-caudal (L CC) view. These terms would also apply to the R CC, and the right and left FB, XCC, XCCL and XCCM views: Note: If six images are required, then the “Central, Anterior” combination would be added. The following combinations of coded terms may be used to express the breast sections, for example, for the left medio-lateral oblique (L MLO) view. These terms would also apply to the R MLO, and to the right and left LM, ML, LMO, and SIO views: Note: If six images are required, then the “Central, Anterior” combination would be added.
Sequence that describes the projection of the anatomic region of interest on the image receptor. Only a single Item shall be permitted in this Sequence. View modifier. Zero or more Items may be included in this Sequence.
Type of equipment that originally acquired the data used to create the images in this Series. Enumerated Values: IO See section C.7.3.1.1.1 for further explanation. Enumerated Values: NONE CEPHALOSTAT RIGID Laterality of the region examined. Enumerated Values: R = right L = left B = both (i.e. midline) Sequence that identifies the anatomic region of interest in this image. Only a single Item shall be permitted in this Sequence. Sequence that refines the anatomic region of interest in this image. Required if Primary Anatomic Structure Sequence (0008,2228) is not sent. Only a single Item shall be permitted in this Sequence. Sequence that describes the primary anatomic structures of interest in this image. See C.8.11.9.1.1 for further explanation. Required if Anatomic Region Modifier Sequence (0008,2220) is not sent. One or more Items may be included in this Sequence.
The Code Value (0008,0100) shall be drawn from the DICOM Content Mapping Resource, Context ID 4018, for permanent dentition, or Context ID 4019 for deciduous dentition. These Context Groups correspond to ISO 3950-1984 that describes a designation of permanent and deciduous dentition using a two digit code, the first digit of which designates a quadrant, and the second digit a tooth. The teeth imaged shall be listed as multiple Items in the Primary Anatomic Structure Sequence (0008,2228).
Image identification characteristics. See C.8.12.1.1.6 for specialization.
The Image Type attribute identifies important image characteristics in a multiple valued data element. For Visible Light, Image Type is specialized as follows: a. Value 1 shall identify the Pixel Data Characteristics in accordance with Section C.7.6.1.1.2; Enumerated Values are: ORIGINAL and DERIVED; b. Value 2 shall identify the Patient Examination Characteristics in accordance with Section C.7.6.1.1.2; Enumerated Values are: PRIMARY and SECONDARY. c. Value 3 may be absent, but if present shall identify the members of a stereo pair, in which case Referenced Image Sequence (0008,1140) is used to identify the other member of the pair. If present, the Enumerated Values are: d. Other Values are implementation specific (optional).
Specifies the intended interpretation of the pixel data. See C.8.12.1.1.1 for specialization of this Attribute.
The Enumerated Values of Photometric Interpretation (0028,0004) shall be: MONOCHROME2 RGB YBR_FULL_422 YBR_PARTIAL_420 YBR_RCT YBR_ICT Note: There is no formal color space defined, hence “false” color applications that encode near-visible light images may be encoded, for example, as RGB.
Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated. See C.8.12.1.1.2 for specialization of this Attribute. See PS 3.5 for further explanation.
The Enumerated Value of Bits Allocated (0028,0100) shall be 8; the Enumerated Value of Bits Stored (0028,0101) shall be 8; and the Enumerated Value of High Bit (0028,0102) shall be 7.
Number of bits stored for each pixel sample. Each sample shall have the same number of bits stored. See C.8.12.1.1.2 for specialization of this Attribute. See PS 3.5 for further explanation.
The Enumerated Value of Bits Allocated (0028,0100) shall be 8; the Enumerated Value of Bits Stored (0028,0101) shall be 8; and the Enumerated Value of High Bit (0028,0102) shall be 7.
Most significant bit for pixel sample data. Each sample shall have the same high bit. See C.8.12.1.1.2 for specialization of this Attribute. See PS 3.5 for further explanation.
The Enumerated Value of Bits Allocated (0028,0100) shall be 8; the Enumerated Value of Bits Stored (0028,0101) shall be 8; and the Enumerated Value of High Bit (0028,0102) shall be 7.
Data representation of the pixel samples. Each sample shall have the same pixel representation. See Section C.8.12.1.1.3 for specialization of this Attribute.
The Enumerated Value of Pixel Representation (0028,0103) shall be 0.
Number of samples (planes) per image. See C.8.12.1.1.4 for specialization of this Attribute.
The Enumerated Values of Samples per Pixel (0028,0002) shall be as follows: If the value of Photometric Interpretation (0028,0004) is MONOCHROME2, then the Enumerated Value of Samples per Pixel (0028,0002) shall be one (1). If the value of Photometric Interpretation (0028,0004) is RGB or YBR_FULL_422 or YBR_PARTIAL_420 or YBR_RCT or YBR_ICT, then the Enumerated Value of Samples per Pixel (0028,0002) shall be three (3).
Indicates whether the pixel data are sent color-by-plane or color-by-pixel. Required if Samples per Pixel (0028,0002) has a value greater than 1. See C.8.12.1.1.5 for specialization of this Attribute.
If present, the Enumerated Value of Planar Configuration (0028,0006) shall be 0. This value shall be present if Samples per Pixel (0028,0002) has a value greater than 1.
The time the image pixel data creation started. Required if the Image is part of a series in which the images are temporally related. Note: This Attribute was formerly known as Image Time. Specifies whether an Image has undergone lossy compression. Enumerated Values: 00 = Image has NOT been subjected to lossy compression. 01 = Image has been subjected to lossy compression. See C.7.6.1.1.5
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
A Sequence that references other images significantly related to this image. One or more items may be included in this sequence. Required if Image Type (0008,0008) Value 3 is present and has a value of "STEREO L" or "STEREO R". May also be present otherwise. See Section C.8.12.1.1.7.
When Image Type (0008,0008) Value 3 is STEREO L or STEREO R, Referenced Image Sequence (0008,1140) shall be used to identify the corresponding SOP Instance of the Stereoscopic acquisition. In this case, either:
Describes the purpose for which the reference is made. Zero or one item shall be present in the sequence. Window Center for display. See C.11.2.1.2 for further explanation. Meaningful only if Photometric Interpretation (0028,0004) is MONOCHROME2.
Window Center (0028,1050) and Window Width (0028,1051) specify a linear conversion from stored pixel values (after any Modality LUT or Rescale Slope and Intercept specified in the IOD have been applied) to values to be displayed. Window Center contains the input value that is the center of the window. Window Width contains the width of the window. Note: The terms “window center” and “window width” are not consistently used in practice, nor were they defined in previous versions of the standard. The definitions here are presented for the purpose of defining consistent meanings for identity and threshold transformations while preserving the common practice of using integral values for center and width. Window Width (0028,1051) shall always be greater than or equal to 1. When Window Width (0028,1051) is greater than 1, these Attributes select the range of input values that are to be mapped to the full range of the displayed output. When Window Width (0028,1051) is equal to 1, they specify a threshold below which input values will be displayed as the minimum output value. Note: Whether the minimum output value is rendered as black or white may depend on the value of Photometric Interpretation (0028,0004) or the presence of a Presentation LUT Module. These Attributes are applied according to the following pseudo-code, where x is the input value, y is an output value with a range from ymin to ymax, c is Window Center (0028,1050) and w is Window Width (0028,1051): if (x <= c - 0.5 - (w-1)/2), then y = ymin else if (x > c - 0.5 + (w-1)/2), then y = ymax, else y = ((x - (c - 0.5)) / (w-1) + 0.5) * (ymax - ymin)+ ymin Notes: 1. For the purpose of this definition, a floating point calculation without integer truncation is assumed, though the manner of implementation may vary as long as the result is the same. 2. The pseudo-code function computes a continuous value over the output range without any discontinuity at the boundaries. The value of 0 for w is expressly forbidden, and the value of 1 for w does not cause division by zero, since the continuous segment of the function will never be reached for that case. 3. For example, for an output range 0 to 255: c=2048, w=4096 becomes: if (x <= 0) then y = 0 else if (x > 4095) then y = 255 else y = ((x - 2047.5) / 4095 + 0.5) * (255-0) + 0 c=2048, w=1 becomes: if (x <= 2047.5) then y = 0 else if (x > 2047.5) then y = 255 else /* not reached */ c=0, w=100 becomes: if (x <= -50) then y = 0 else if (x > 49) then y = 255 else y = ((x + 0.5) / 99 + 0.5) * (255-0) + 0 c=0, w=1 becomes: if (x <= -0.5) then y = 0 else if (x > -0.5) then y = 255 else /* not reached */ 4. A Window Center of 2n-1 and a Window Width of 2n selects the range of input values from 0 to 2n-1. This represents an identity VOI LUT transformation in the case where no Modality LUT is specified and the stored pixel data are n bit unsigned integers. 5. A Window Width of 1 is typically used to represent a "threshold" operation in which those integer input values less than the Window Center are represented as the minimum displayed value and those greater than or equal to the Window Center are represented as the maximum displayed value. A Window Width of 2 will have the same result for integral input values. 6. The application of Window Center (0028,1050) and Window Width (0028,1051) may select a signed input range. There is no implication that this signed input range is clipped to zero. 7. The selected input range may exceed the actual range of the input values, thus effectively “compressing” the contrast range of the displayed data into a narrower band of the available contrast range, and “flattening” the appearance. There are no limits to the maximum value of the window width, or to the minimum or maximum value of window level, both of which may exceed the actual or possible range of input values. 8. Input values "below" the window are displayed as the minimum output value and input values "above" the window are displayed as the maximum output value. This is the common usage of the window operation in medical imaging. There is no provision for an alternative approach in which all values "outside" the window are displayed as the minimum output value. 9. The output of the Window Center/Width or VOI LUT transformation is either implicitly scaled to the full range of the display device if there is no succeeding transformation defined, or implicitly scaled to the full input range of the succeeding transformation step (such as the Presentation LUT), if present. See C.11.6.1. 10. Fractional values of Window Center and Window Width are permitted (since the VR of these Attributes is Decimal String), and though they are not often encountered, applications should be prepared to accept them. These Attributes shall be used only for Images with Photometric Interpretation (0028,0004) values of MONOCHROME1 and MONOCHROME2. They have no meaning for other Images. 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 may be presented. If any VOI LUT Table is included by an Image, a Window Width and Window Center or the VOI LUT Table, but not both, may be applied to the Image for display. Inclusion of both indicates that multiple alternative views may be presented. If multiple items are present in VOI LUT Sequence (0028,3010), only one may be applied to the Image for display. Multiple items indicate that multiple alternative views may be presented. If the VOI LUT Module is defined in an IOD and if neither a VOI LUT Sequence nor a Window Width and Window Center are present, then the VOI LUT stage of the grayscale pipeline is defined to be an identity transformation. Notes: 1. This requirement is specified so that IODs that define a particular output space for the grayscale pipeline, such as P-Values, are not in an undefined state when no VOI LUT Sequence or Window Width and Window Center are present. 2. Despite the Type 3 requirement for VOI LUT Sequence and Window Center, implementations that render images are expected to implement and apply these transformations when they are present in the image, unless overridden by the user, a presentation state, or a hanging protocol, and to allow the user to select which transformation to apply when multiple transformations are present.
Window Width for display. See C.11.2.1.2 for further explanation. Required if Window Center (0028,1050) is present.
Window Center (0028,1050) and Window Width (0028,1051) specify a linear conversion from stored pixel values (after any Modality LUT or Rescale Slope and Intercept specified in the IOD have been applied) to values to be displayed. Window Center contains the input value that is the center of the window. Window Width contains the width of the window. Note: The terms “window center” and “window width” are not consistently used in practice, nor were they defined in previous versions of the standard. The definitions here are presented for the purpose of defining consistent meanings for identity and threshold transformations while preserving the common practice of using integral values for center and width. Window Width (0028,1051) shall always be greater than or equal to 1. When Window Width (0028,1051) is greater than 1, these Attributes select the range of input values that are to be mapped to the full range of the displayed output. When Window Width (0028,1051) is equal to 1, they specify a threshold below which input values will be displayed as the minimum output value. Note: Whether the minimum output value is rendered as black or white may depend on the value of Photometric Interpretation (0028,0004) or the presence of a Presentation LUT Module. These Attributes are applied according to the following pseudo-code, where x is the input value, y is an output value with a range from ymin to ymax, c is Window Center (0028,1050) and w is Window Width (0028,1051): if (x <= c - 0.5 - (w-1)/2), then y = ymin else if (x > c - 0.5 + (w-1)/2), then y = ymax, else y = ((x - (c - 0.5)) / (w-1) + 0.5) * (ymax - ymin)+ ymin Notes: 1. For the purpose of this definition, a floating point calculation without integer truncation is assumed, though the manner of implementation may vary as long as the result is the same. 2. The pseudo-code function computes a continuous value over the output range without any discontinuity at the boundaries. The value of 0 for w is expressly forbidden, and the value of 1 for w does not cause division by zero, since the continuous segment of the function will never be reached for that case. 3. For example, for an output range 0 to 255: c=2048, w=4096 becomes: if (x <= 0) then y = 0 else if (x > 4095) then y = 255 else y = ((x - 2047.5) / 4095 + 0.5) * (255-0) + 0 c=2048, w=1 becomes: if (x <= 2047.5) then y = 0 else if (x > 2047.5) then y = 255 else /* not reached */ c=0, w=100 becomes: if (x <= -50) then y = 0 else if (x > 49) then y = 255 else y = ((x + 0.5) / 99 + 0.5) * (255-0) + 0 c=0, w=1 becomes: if (x <= -0.5) then y = 0 else if (x > -0.5) then y = 255 else /* not reached */ 4. A Window Center of 2n-1 and a Window Width of 2n selects the range of input values from 0 to 2n-1. This represents an identity VOI LUT transformation in the case where no Modality LUT is specified and the stored pixel data are n bit unsigned integers. 5. A Window Width of 1 is typically used to represent a "threshold" operation in which those integer input values less than the Window Center are represented as the minimum displayed value and those greater than or equal to the Window Center are represented as the maximum displayed value. A Window Width of 2 will have the same result for integral input values. 6. The application of Window Center (0028,1050) and Window Width (0028,1051) may select a signed input range. There is no implication that this signed input range is clipped to zero. 7. The selected input range may exceed the actual range of the input values, thus effectively “compressing” the contrast range of the displayed data into a narrower band of the available contrast range, and “flattening” the appearance. There are no limits to the maximum value of the window width, or to the minimum or maximum value of window level, both of which may exceed the actual or possible range of input values. 8. Input values "below" the window are displayed as the minimum output value and input values "above" the window are displayed as the maximum output value. This is the common usage of the window operation in medical imaging. There is no provision for an alternative approach in which all values "outside" the window are displayed as the minimum output value. 9. The output of the Window Center/Width or VOI LUT transformation is either implicitly scaled to the full range of the display device if there is no succeeding transformation defined, or implicitly scaled to the full input range of the succeeding transformation step (such as the Presentation LUT), if present. See C.11.6.1. 10. Fractional values of Window Center and Window Width are permitted (since the VR of these Attributes is Decimal String), and though they are not often encountered, applications should be prepared to accept them. These Attributes shall be used only for Images with Photometric Interpretation (0028,0004) values of MONOCHROME1 and MONOCHROME2. They have no meaning for other Images. 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 may be presented. If any VOI LUT Table is included by an Image, a Window Width and Window Center or the VOI LUT Table, but not both, may be applied to the Image for display. Inclusion of both indicates that multiple alternative views may be presented. If multiple items are present in VOI LUT Sequence (0028,3010), only one may be applied to the Image for display. Multiple items indicate that multiple alternative views may be presented. If the VOI LUT Module is defined in an IOD and if neither a VOI LUT Sequence nor a Window Width and Window Center are present, then the VOI LUT stage of the grayscale pipeline is defined to be an identity transformation. Notes: 1. This requirement is specified so that IODs that define a particular output space for the grayscale pipeline, such as P-Values, are not in an undefined state when no VOI LUT Sequence or Window Width and Window Center are present. 2. Despite the Type 3 requirement for VOI LUT Sequence and Window Center, implementations that render images are expected to implement and apply these transformations when they are present in the image, unless overridden by the user, a presentation state, or a hanging protocol, and to allow the user to select which transformation to apply when multiple transformations are present.
Sequence that identifies the anatomic region of interest in this image (i.e. external anatomy, surface anatomy, or general region of the body). Only a single Item shall be permitted in this sequence. Required if Number of Frames (0028,0008) is present and Specimen Accession Number (0040,050A) is absent. May be present otherwise. Sequence of Items that modifies the anatomic region of interest of this image One or more Items may be included in this Sequence. Describes the light color used for each channel to generate the image. If Photometric Interpretation (0028,0004) has one of the YBR values, the meaning is for pixel data in an equivalent RGB encoding. Note: Interpretation and representation of RGB images rely on the assumption that the red channel really contains the red wavelength range of illumination light, the blue channel the blue wavelength range, etc. Some modalities use the RGB Photometric Interpretation as a container representing 3 channels of any illumination wavelength. Shall have the same number of items as the value of Samples per Pixel (0028,0002). The channels shall be described in the order in which the channels are encoded.
The coordinates of the center point of the Image in the Slide Coordinate System Frame of Reference. Zero or one item shall be present in the sequence. See Section C.8.12.2.1.1 for further explanation.
This Section defines the Slide Coordinate System and specifies the Attributes that shall be used to describe the location of the center point of the Image pixel plane (as captured through a microscope) in the Slide Coordinate System Frame of Reference. Note: In Slide Microscopy (SM), the Microscope is equipped with a moveable Stage and position sensors that enable storage of the location of the center point of the displayed image with respect to the examined Specimen. The Stage is the part of the Microscope to which the Slide is attached for viewing. The Objective Lens is the lens that is closest to the Specimen. The Top Surface of the Slide is the surface of the Slide on which the Specimen in Mounted. The Bottom Surface of the Slide is the opposite surface. This Specification presumes that: 1) the Slide is rectangular; 2) the Top Surface of the Slide is oriented toward the Objective Lens of the Microscope; and 3) the Bottom Surface of the Slide is in perfect contact with the Microscope Stage when the Slide is attached to the Stage for viewing. Notes: 1. The Label of the Slide is presumed to be mounted-on or written-on the Top Surface of the Slide. 2. Specification of the mechanical form, function, or tolerances of the Microscope are outside the scope of this Standard. Figure C.8-16 depicts the Top Surface of the Slide on the Microscope Stage from the perspective of the Objective Lens. This is Reference Slide Orientation. The X, Y, and Z axes of the Slide Coordinate System in Reference Slide Orientation are defined as follows. The Y-axis is a line that includes the Left Edge of the Slide. The X-axis is a line that is orthogonal to the Y-axis and includes at least one point of the Specimen Edge of the Slide. The Z-axis is a line that passes through the intersection of the X-axis and Y-axis and is orthogonal to the Microscope Stage. The Origin (0,0,0) of the Slide Coordinate System is the point of intersection of the X, Y, and Z axes. Figure C.8-16 REFERENCE SLIDE ORIENTATION Notes: 1. An improperly-placed coverslip or Specimen that overlaps an Edge of a Slide is not considered part of the Edge a Slide for purposes of defining the Slide Coordinate System. However, such objects may cause inaccurate positioning of the Slide on the Stage. 2. If the Left Edge and Specimen Edge of the Slide are not orthogonal (e.g. the Slide is damaged or defective or the Specimen Edge is curvilinear), then the lower left-hand corner of the Slide may not be located at the Origin. 3. The definitions of X, Y, and Z axes are the same for inverted microscopes, with the Top Surface of the slide (i.e. Specimen side of the Slide) still being closest to the Objective Lens. Figure C.8-17 depicts the Z-axis center point location. The X-axis value of Image Center Point Location (0040,073A) shall increase from the Origin toward the Right Edge in Reference Slide Orientation. The Y-axis value of Image Center Point Location (0040,073A) shall increase from the Origin toward the Label Edge in Reference Slide Orientation. The Z-axis value of Image Center Point Location (0040,073A) shall be referenced as zero at the image substrate reference plane (i.e. utilized surface of a glass slide) and shall increase in a positive fashion coincident with increased distance from the substrate surface. Figure C.8-17 Z-AXIS CENTER POINT LOCATION, VIEW FROM RIGHT EDGE OF SLIDE
The X offset in millimeters from the Origin of the Slide Coordinate System. See Figure C.8-16. The Y offset in millimeters from the Origin of the Slide Coordinate System. See Figure C.8-16. The Z offset in microns from the image substrate reference plane (i.e. utilized surface of a glass slide). Physical distance in the Imaging Subject, i.e. Patient or Specimen, between the center of each pixel along specified axes. One or more items may be present. Axis of a coordinate system. This sequence shall contain exactly one item. The distance between the center-points of adjacent pixels along the axis specified by Coordinate System Axis Code Sequence (0040,08DA). Units of the measurement. This sequence shall contain exactly one item.
Image characteristics. See C.8.16.1 and C.8.13.3.1.1.
The Image Type (0008,0008) and associated Image Type related attributes provide a high level description of a multi-frame SOP Instance. These attributes describe properties that provide key summary information to users of the SOP Instance. Image Type (0008,0008) contains the highest level summary of what is in the SOP Instance. The Frame Type (0008,9007) attribute mirrors the corresponding Image Type attribute and applies to the frame level rather than to the image level. If more than one value is used by the set of frames for a given Frame Type (0008,9007) attribute value or associated attribute value then the corresponding value of the Image Type (0008,0008) or associated attribute shall contain a value of MIXED. This indicates that a mixed set of values exists within the multi-frame SOP Instance. The value MIXED shall only be used in the Image Type (0008,0008) when the corresponding values for the individual frames are not equal. When a value of an attribute is equal for all frames, the same value shall be used for the corresponding value of the Image Type (0008,0008). Values 2 and 3 of Image Type (0008,0008) are an exception to the rule for MIXED: Values 2 and 3 may never have the value of MIXED as described in sections C.8.16.1.2 and C.8.16.1.3. Image Type (0008,0008) and Frame Type (0008,9007) shall consist of four non-zero length values.
Number of samples (planes) in this image. This value shall be 1. Specifies the intended interpretation of the pixel data. Enumerated Value: MONOCHROME2. See C.7.6.3.1.2 for definition of this term.
The value of Photometric Interpretation (0028,0004) specifies the intended interpretation of the image pixel data. See PS 3.5 for restrictions imposed by compressed Transfer Syntaxes. The following values are defined. Other values are permitted but the meaning is not defined by this Standard. MONOCHROME1 = Pixel data represent a single monochrome image plane. The minimum sample value is intended to be displayed as white after any VOI gray scale transformations have been performed. See PS 3.4. This value may be used only when Samples per Pixel (0028,0002) has a value of 1. MONOCHROME2 = Pixel data represent a single monochrome image plane. The minimum sample value is intended to be displayed as black after any VOI gray scale transformations have been performed. See PS 3.4. This value may be used only when Samples per Pixel (0028,0002) has a value of 1. PALETTE COLOR = Pixel data describe a color image with a single sample per pixel (single image plane). The pixel value is used as an index into each of the Red, Blue, and Green Palette Color Lookup Tables (0028,1101-1103&1201-1203). This value may be used only when Samples per Pixel (0028,0002) has a value of 1. When the Photometric Interpretation is Palette Color; Red, Blue, and Green Palette Color Lookup Tables shall be present. RGB = Pixel data represent a color image described by red, green, and blue image planes. The minimum sample value for each color plane represents minimum intensity of the color. This value may be used only when Samples per Pixel (0028,0002) has a value of 3. HSV = Retired. ARGB = Retired. CMYK = Retired. YBR_FULL = Pixel data represent a color image described by one luminance (Y) and two chrominance planes (CB and CR). This photometric interpretation may be used only when Samples per Pixel (0028,0002) has a value of 3. Black is represented by Y equal to zero. The absence of color is represented by both CB and CR values equal to half full scale. Note: In the case where the Bits Allocated (0028,0100) has value of 8 half full scale is 128. In the case where Bits Allocated (0028,0100) has a value of 8 then the following equations convert between RGB and YCBCR Photometric Interpretation. Y = + .2990R + .5870G + .1140B CB = - .1687R - .3313G + .5000B + 128 CR = + .5000R - .4187G - .0813B + 128 Note: The above is based on CCIR Recommendation 601-2 dated 1990. YBR_FULL_422 = The same as YBR_FULL except that the CB and CR values are sampled horizontally at half the Y rate and as a result there are half as many CB and CR values as Y values. This Photometric Interpretation is only allowed with Planar Configuration (0028,0006) equal to 0. Two Y values shall be stored followed by one CB and one CR value. The CB and CR values shall be sampled at the location of the first of the two Y values. For each Row of Pixels, the first CB and CR samples shall be at the location of the first Y sample. The next CB and CR samples shall be at the location of the third Y sample etc. Note: This subsampling is often referred to as cosited sampling. YBR_PARTIAL_422 = The same as YBR_FULL_422 except that: 1. black corresponds to Y = 16; 2. Y is restricted to 220 levels (i.e. the maximum value is 235); 3. CB and CR each has a minimum value of 16; 4. CB and CR are restricted to 225 levels (i.e. the maximum value is 240); 5. lack of color is represented by CB and CR equal to 128. In the case where Bits Allocated (0028,0100) has value of 8 then the following equations convert between RGB and YBR_PARTIAL_422 Photometric Interpretation Y = + .2568R + .5041G + .0979B + 16 CB = - .1482R - .2910G + .4392B + 128 CR = + .4392R - .3678G - .0714B + 128 Note: The above is based on CCIR Recommendation 601-2 dated 1990. YBR_PARTIAL_420 = The same as YBR_PARTIAL_422 except that the CB and CR values are sampled horizontally and vertically at half the Y rate and as a result there are four times less CB and CR values than Y values, versus twice less for YBR_PARTIAL_422. This Photometric Interpretation is only allowed with Planar Configuration (0028,0006) equal to 0. The CB and CR values shall be sampled at the location of the first of the two Y values. For the first Row of Pixels (etc.), the first CB and CR samples shall be at the location of the first Y sample. The next CB and CR samples shall be at the location of the third Y sample etc. The next Rows of Pixels containing CB and CR samples (at the same locations than for the first Row) will be the third etc. YBR_ICT = Irreversible Color Transformation: Pixel data represent a color image described by one luminance (Y) and two chrominance planes (CB and CR). This photometric interpretation may be used only when Samples per Pixel (0028,0002) has a value of 3. Black is represented by Y equal to zero. The absence of color is represented by both CB and CR values equal to zero. Regardless of the value of Bits Allocated (0028,0100), the following equations convert between RGB and YCBCR Photometric Interpretation. Y = + .29900R + .58700G + .11400B CB = - .16875R - .33126G + .50000B CR = + .50000R - .41869G - .08131B Notes: 1. The above is based on ISO/IEC 15444-1 (JPEG 2000). 2. In a JPEG 2000 bitstream, DC level shifting (used if the untransformed components are unsigned) is applied before forward color transformation, and the transformed components may be signed (unlike in JPEG ISO/IEC 10918-1). 3. In JPEG 2000, spatial down-sampling of the chrominance components, if performed, is signaled in the JPEG 2000 bitstream. YBR_RCT = Reversible Color Transformation: Pixel data represent a color image described by one luminance (Y) and two chrominance planes (CB and CR). This photometric interpretation may be used only when Samples per Pixel (0028,0002) has a value of 3. Black is represented by Y equal to zero. The absence of color is represented by both CB and CR values equal to zero. Regardless of the value of Bits Allocated (0028,0100), the following equations convert between RGB and YBR_RCT Photometric Interpretation. Y = R + 2G +B) / 4 (Note:  mean floor) CB = B - G CR = R - G The following equations convert between YBR_RCT and RGB Photometric Interpretation. G = Y –  (CR + CB) / 4 R = CR + G B = CB + G Notes: 1. The above is based on ISO/IEC 15444-1 (JPEG 2000). 2. In a JPEG 2000 bitstream, DC level shifting (used if the untransformed components are unsigned) is applied before forward color transformation, and the transformed components may be signed (unlike in JPEG ISO/IEC 10918-1). 3. This photometric interpretation is a reversible approximation to the YUV transformation used in PAL and SECAM.
Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated. Enumerated Values: 8 and 16. Number of bits stored for each pixel sample. Each sample shall have the same number of bits stored. Enumerated Values: 8, 12 and 16. See C.8.13.1.1.1 for specialization.
Table C.8-80 specifies the allowed combinations of Bits Allocated (0028,0100) and Bits Stored (0028,0101). Table C.8-80 ALLOWED COMBINATIONS OF ATTRIBUTE VALUES FOR BITS ALLOCATED AND BITS STORED
Most significant bit for pixel sample data. Each sample shall have the same high bit. Shall be one less than the value in Bits Stored (0028,0101). Value of the prescribed spacing to be applied between the slices in a volume that is to be acquired. The spacing in mm is defined as the center-to-center distance of adjacent slices. Indicates whether or not the image contains sufficient burned in annotation to identify the patient and date the image was acquired. Enumerated Values: NO This means that images that contain this Module shall not contain such burned in annotations. Specifies whether an Image has undergone lossy compression. Enumerated Values: 00 = Image has NOT been subjected to lossy compression. 01 = Image has been subjected to lossy compression. See C.7.6.1.1.5 for further explanation.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
Describes the approximate lossy compression ratio(s) that have been applied to this image. See C.7.6.1.1.5 for further explanation. May be multivalued if successive lossy compression steps have been applied. Note: For example, a compression ratio of 30:1 would be described in this Attribute with a single value of 30. Required if Lossy Images Compression (0028,2110) is "01".
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
A label for the lossy compression method(s) that have been applied to this image. See C.7.6.1.1.5 for further explanation. May be multivalued if successive lossy compression steps have been applied; the value order shall correspond to the values of Lossy Image Compression Ratio (0028,2112). Required if Lossy Image Compression (0028,2110) is "01".
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
Specifies an identity transformation for the Presentation LUT, such that the output of all grayscale transformations defined in the IOD containing this Module are defined to be P-Values. Enumerated Values: IDENTITY - output is in P-Values. This icon image is representative of the Image. Only a single Item shall be permitted in this Sequence.
A number identifying the single continuous gathering of data over a period of time that resulted in this image. Note: This number is not required to be unique across SOP Instances in a series. See also the description of the Referenced Raw Data Sequence (0008,9121). The date and time that the acquisition of data started. Note: The synchronization of this time with an external clock is specified in the synchronization Module in Acquisition Time synchronized (0018,1800). Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. The time in seconds needed to run the prescribed pulse sequence. See C.7.6.16.2.2.1 for further explanation. Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise.
Figure C.7.6.16-2 shows the relationships among the various timing parameters used.
A sequence that identifies the set of Raw Data SOP Class/Instance pairs of the Raw data which were used to derive this Image. One or more Items may be included in this Sequence. Note: The items of in this sequence may identify raw data that has not been stored or encoded as a DICOM object. This allows recognition that images and spectra in different instances have been reconstructed from the same raw data. References to waveforms acquired in conjunction with this image. These Waveforms may or may not be temporally synchronized with this image. One or more Items may be included in this Sequence. Full set of Composite SOP Instances referred to inside the Referenced Image Sequences of this Enhanced MR Image SOP Instance. See C.8.13.2.1.2 for further explanation. One or more Items may be included in this sequence. Required if the Referenced Image Sequence (0008,1140) is present.
The intent of the Referenced Image Evidence Sequence (0008,9092) and Source Image Evidence Sequence (0008,9154) is to provide a list of all unique SOP Instances listed in the Referenced Image Sequence (0008,1140) and Source Image Sequence (0008,2112) attributes respectively.
Full set of Composite SOP Instances referred to inside the Source Image Sequences of this Enhanced MR Image SOP Instance. See C.8.13.2.1.2 for further explanation. One or more Items may be included in this sequence. Required if the Source Image Sequence (0008,2112) is present.
The intent of the Referenced Image Evidence Sequence (0008,9092) and Source Image Evidence Sequence (0008,9154) is to provide a list of all unique SOP Instances listed in the Referenced Image Sequence (0008,1140) and Source Image Sequence (0008,2112) attributes respectively.
References to Grayscale Presentation State instances acquired in conjunction with this instance. Note: May only be used to reference Presentation States belonging to the acquired data and not to reference Presentation States generated subsequently such as during interpretation. One or more Items may be included in this sequence. Required if Presentation State is generated during acquisition, shall not be present otherwise. Content Qualification Indicator Enumerated Values: PRODUCT RESEARCH SERVICE See C.8.13.2.1.1 for further explanation.
Content Qualification (0018,9004) shall have the value PRODUCT if the content (image or Spectroscopy data) was produced with approved hardware and software. It shall have the value RESEARCH or SERVICE if there is any doubt as to whether the content was produced with approved hardware and software. If data with Content Qualification (0018,9004) of RESEARCH or SERVICE is used to derive other content then it is expected that this derived content will also have Content Qualification (0018,9004) set to RESEARCH or SERVICE. The intent of this element is to allow annotation of an advisory message that indicates that this content may not be suitable for clinical interpretation.
Nucleus that is resonant at the transmitter frequency. Defined Terms: 1H 3HE 7LI 13C 19F 23NA 31P 129XE Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Describes k-space filtering applied. Shall be NONE if no k-space filter. Defined Terms: COSINE COSINE_SQUARED FERMI GAUSSIAN HAMMING HANNING LORENTZIAN LRNTZ_GSS_TRNSFM RIESZ TUKEY NONE Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Nominal field strength of the MR Magnet, in Tesla. Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Agency that established MR safety standard applicable to the acquisition of this Instance. Defined Terms: IEC FDA MHW Name and Version of the applicable standard. User-defined comments about the image.
Representation of complex data of frames in the SOP Instance. See C.8.13.3.1.5 for a description and Defined Terms.
The value of the Complex Image Component attribute (0008,9208) shall be used to indicate which component of the complex representation of the signal is represented in the pixel data. Table C.8-85 specifies the Defined Terms for Complex Image Component attribute (0008,9208). Table C.8-85 COMPLEX IMAGE COMPONENT ATTRIBUTE VALUES
Indication of acquisition contrast used with frames in the SOP Instance. See C.8.13.3.1.6 for a description and Defined Terms.
Table C.8-86 specifies the Defined Terms for Acquisition Contrast attribute (0008,9209). Table C.8-86 ACQUISITION CONTRAST VALUES
Name of the pulse sequence for annotation purposes. Potentially vendor-specific name. Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Identification of spatial data encoding scheme. Defined Terms: 1D 2D 3D Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Echo category of pulse sequences. Enumerated Values: SPIN GRADIENT BOTH Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Multiple Spin Echo category of pulse sequence used to collect different lines in k-space for a single frame. Enumerated Values: YES NO Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and Echo Pulse sequence (0018,9008) equals SPIN or BOTH. Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and Echo Pulse sequence (0018,9008) equals SPIN or BOTH. Technique that simultaneously excites several volumes. Enumerated Values: YES NO Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Phase Contrast Pulse sequence is a pulse sequence in which the flowing spins are velocity encoded in phase. Enumerated Values: YES NO Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Time of Flight contrast is created by the inflow of blood in the saturated plane. Enumerated Values: YES NO Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Steady State Sequence. Defined Terms: FREE_PRECESSION TRANSVERSE TIME_REVERSED LONGITUDINAL NONE Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Echo Planar category of Pulse Sequences. Enumerated Values: YES NO Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Saturation recovery pulse sequence. Enumerated Values: YES NO Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Spectrally Selected Suppression. Defined Terms: FAT WATER FAT_AND_WATER SILICON_GEL NONE Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Oversampling Phase. Enumerated Values: 2D = phase direction 3D = out of plane direction 2D_3D = both NONE Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Geometry category of k-Space traversal. Defined Terms: RECTILINEAR RADIAL SPIRAL Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Rectilinear phase encode reordering. Defined Terms: LINEAR CENTRIC SEGMENTED REVERSE_LINEAR REVERSE_CENTRIC Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and Geometry of k-Space Traversal (0018,9032) equals RECTILINEAR. Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and Geometry of k-Space Traversal (0018,9032) equals RECTILINEAR. Segmented k-Space traversal. If Geometry of k-Space Traversal is rectilinear, multiple lines can be acquired at one time. If Geometry of k-Space Traversal is spiral or radial, paths can be interleaved and acquired at one time. Enumerated Values: SINGLE = successive single echo coverage PARTIAL = segmented coverage FULL = single shot full coverage Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Coverage of k-Space in the ky-kz plane. Defined Terms: FULL CYLINDRICAL ELLIPSOIDAL WEIGHTED Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and MR Acquisition Type (0018,0023) equals 3D. Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and MR Acquisition Type (0018,0023) equals 3D. Number of interleaves or shots. Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Identifies the characteristics of this frame. Only a single Item shall be permitted in this sequence. Type of Frame. A multi-valued attribute analogous to the Image Type (0008,0008). Enumerated Values and Defined Terms are the same as those for the four values of the Image Type (0008,0008) attribute, except that the value MIXED is not allowed. See C.8.16.1 and C.8.13.3.1.1.
The Image Type (0008,0008) and associated Image Type related attributes provide a high level description of a multi-frame SOP Instance. These attributes describe properties that provide key summary information to users of the SOP Instance. Image Type (0008,0008) contains the highest level summary of what is in the SOP Instance. The Frame Type (0008,9007) attribute mirrors the corresponding Image Type attribute and applies to the frame level rather than to the image level. If more than one value is used by the set of frames for a given Frame Type (0008,9007) attribute value or associated attribute value then the corresponding value of the Image Type (0008,0008) or associated attribute shall contain a value of MIXED. This indicates that a mixed set of values exists within the multi-frame SOP Instance. The value MIXED shall only be used in the Image Type (0008,0008) when the corresponding values for the individual frames are not equal. When a value of an attribute is equal for all frames, the same value shall be used for the corresponding value of the Image Type (0008,0008). Values 2 and 3 of Image Type (0008,0008) are an exception to the rule for MIXED: Values 2 and 3 may never have the value of MIXED as described in sections C.8.16.1.2 and C.8.16.1.3. Image Type (0008,0008) and Frame Type (0008,9007) shall consist of four non-zero length values.
Identifies the timing and safety information of this frame. Only a single Item shall be permitted in this sequence. The time in ms between two successive excitations of the same volume. Shall be 0 (zero) if there is a single excitation per volume. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Steady state angle in degrees to which the magnetic vector is flipped from the magnetic vector of the primary field. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Number of lines in k-space acquired per excitation of the same volume regardless of the type of echo or the number of frames derived from them. See section C.8.12.5.2.1. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Number of RF echoes collected per RF shot (or excitation) per frame. A value of zero shall correspond to a pure gradient echo frame. Note that this value corresponds to the current frame. Several frames may be derived from the same shot. See section C.8.13.5.2.1. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Number of gradient echoes collected per RF echo per shot (or excitation) per frame. A value of zero shall correspond to a pure RF echo frame. If RF Echo Train Length (0018,9240) is non zero and Gradient Echo Train Length is as well then only the central echo will be an RF Spin Echo, all others will be gradient echoes. See section C.8.13.5.2.1. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Sequence containing the methods of SAR calculation and the corresponding values. One or more items may be present. Required if the system is capable of calculating Specific Absorption Rate (0018,9181). Specification of the method of SAR calculation as defined in Applicable Safety Standard Description (0018,9174). Defined Terms: IEC_WHOLE_BODY IEC_PARTIAL_BODY IEC_HEAD IEC_LOCAL Specific Absorption Rate in W/kg. Definition of gradient output unit, for which the value is stored in Gradient Output (0018,9182). Defined Terms: DB_DT = in T/s ELECTRIC_FIELD = in V/m PER_NERVE_STIM = percentage of peripheral nerve stimulation Required if the system is capable of calculating Gradient Output (0018,9182). Unit is defined by Gradient Output Type (0018,9180). Required if the system is capable of calculating Gradient Output (0018,9182). Sequence of operating mode information relating to the frame/SOP instance as required to adhere to the Applicable Safety Standard Agency (0018,9174) regulations. One or more Items may be included in this sequence. Required if required by law or regulations. May be present otherwise. Defined Terms: STATIC FIELD RF GRADIENT Operating mode applicable for the defined by the applicable standard. Defined Terms: IEC_NORMAL IEC_FIRST_LEVEL IEC_SECOND_LEVEL Identifies the geometry parameters of this frame. Only a single Item shall be permitted in this sequence. The axes of the in-plane phase encoding with respect to the frame. Enumerated Values: COLUMN ROW OTHER Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Number of Frequency Encoding steps (kx) acquired Required if Frame Type (0008,9007) Value 1 is ORIGINAL. May be present otherwise. Number of In-Plane Phase Encoding steps (ky) acquired Required if Frame Type (0008,9007) Value 1 is ORIGINAL. May be present otherwise. Number of Out-of-Plane Phase Encoding steps (kz) acquired Required if MR Acquisition Type (0018,0023) equals 3D and Frame Type (0008,9007) Value 1 is ORIGINAL. May be present otherwise. Fraction of acquisition matrix lines acquired, expressed as a percent. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Ratio of field of view dimension in phase direction to field of view dimension in frequency direction, expressed as a percent. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Identifies echo timing of this frame. Only a single Item shall be permitted in this sequence. The time in ms between the middle of the excitation pulse and the peak of the echo produced for kx=0. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Identifies general acquisition parameters of this frame. Only a single Item shall be permitted in this sequence. Inversion Recovery preparatory sequence. Enumerated Values: YES NO Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Times in ms after the middle of inverting RF pulse to middle of excitation pulse to detect the amount of longitudinal magnetization. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Inversion Recovery (0018,9009) equals YES. Otherwise may be present if Frame Type (0008,9007) Value 1 is DERIVED and Inversion Recovery (0018,9009) equals YES. Flow Compensation. Defined Terms: ACCELERATION VELOCITY OTHER NONE Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Flow Compensation Direction. Enumerated Values: PHASE FREQUENCY SLICE_SELECT SLICE_AND_FREQ SLICE_FREQ_PHASE PHASE_AND_FREQ SLICE_AND_PHASE OTHER Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Flow Compensation (0018,9010) equals other than NONE. Otherwise may be present if Frame Type (0008,9007) Value 1 is DERIVED and Flow Compensation (0018,9010) equals other than NONE. Spoiling. Enumerated Values: RF = RF spoiled GRADIENT = gradient spoiled RF_AND_GRADIENT NONE Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Echo Pulse Sequence (0018,9008) equals GRADIENT or BOTH. Otherwise may be present if Frame Type (0008,9007) Value 1 is DERIVED and Echo Pulse Sequence (0018,9008) equals GRADIENT or BOTH. T2 prepared Pulse Sequence. Enumerated Values: YES NO Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Spectrally Selected Excitation. Enumerated Values: WATER = water excitation FAT = fat excitation NONE Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Spatial Pre-saturation. Defined Terms: SLAB NONE Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Partial Fourier. Enumerated Values: YES NO Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Direction of Partial Fourier. Enumerated Values: PHASE FREQUENCY SLICE_SELECT COMBINATION Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Partial Fourier (0018,9081) equals YES. Otherwise may be present if Frame Type (0008,9007) Value 1 is DERIVED and Partial Fourier (0018,9081) equals YES. Parallel acquisition has been used to reduce measurement time. Enumerated Values: YES NO Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Parallel acquisition characteristics. Defined Terms: PILS SENSE SMASH OTHER Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Parallel Acquisition (0018,9077) equals YES. Otherwise may be present if Frame Type (0008,9007) Value 1 is DERIVED and Parallel Acquisition (0018,9077) equals YES. Measurement time reduction factor expressed as ratio of original and reduced measurement time for the in-plane direction. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Parallel Acquisition (0018,9077) equals YES. Otherwise may be present if Frame Type (0008,9007) Value 1 is DERIVED and Parallel Acquisition (0018,9077) equals YES. Measurement time reduction factor expressed as ratio of original and reduced measurement time for the out-of-plane direction Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Parallel Acquisition (0018,9077) equals YES. Otherwise may be present if Frame Type (0008,9007) Value 1 is DERIVED and Parallel Acquisition (0018,9077) equals YES. Measurement time reduction factor expressed as ratio of original and reduced measurement time for the second in-plane direction. Only required for MR Spectroscopy SOP Instances. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Parallel Acquisition (0018,9077) equals YES. Otherwise may be present if Frame Type (0008,9007) Value 1 is DERIVED and Parallel Acquisition (0018,9077) equals YES. Identifies sequence containing MR modifier Sequence Attributes. Only one item may be included in this sequence. Magnetization Transfer pulse sequence. Enumerated Values: ON_RESONANCE OFF_RESONANCE NONE Required if Frame Type (0008,9007) Value 1 is ORIGINAL. May be present otherwise. Blood Signal Nulling ("Black Blood") preparatory pulse sequence. Enumerated Values: YES NO Required if Frame Type (0008,9007) Value 1 is ORIGINAL. May be present otherwise. Tagging. Defined Terms: GRID LINE NONE Required if Frame Type (0008,9007) Value 1 is ORIGINAL. May be present otherwise. Space between lines in mm. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Tagging (0018,9028) is GRID or LINE. Otherwise may be present if Frame Type (0008,9007) Value 1 is DERIVED and Tagging (0018,9028) is GRID or LINE. Space between the lines in mm in the other direction. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Tagging (0018,9028) is GRID. Otherwise may be present if Frame Type (0008,9007) Value 1 is DERIVED and Tagging (0018,9028) is GRID. Angle of the tag lines relative to the rows axis (left to right) of the image, with a range of 0-180 degrees. The angle is increasing in clockwise direction. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Tagging (0018,9028) is GRID or LINE. Otherwise may be present if Frame Type (0008,9007) Value 1 is DERIVED and Tagging (0018,9028) is GRID or LINE. Angle of the tag lines relative to the rows axis (left to right) of the image, with a range of 0-180 degrees. The angle is increasing in clockwise direction. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Tagging (0018,9028) is GRID. Otherwise may be present if Frame Type (0008,9007) Value 1 is DERIVED and Tagging (0018,9028) is GRID. Thickness of the line in mm. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Tagging (0018,9028) is GRID or LINE. Otherwise may be present if Frame Type (0008,9007) Value 1 is DERIVED and Tagging (0018,9028) is GRID or LINE. Delay time in ms of the beginning of the application of the tagging pattern relative to the last R-peak. Center transmitter frequency in MHz. Required if Frame Type (0008,9007) Value 1 is ORIGINAL. May be present otherwise. Reciprocal of the effective sampling period, in hertz per pixel. Required if Frame Type (0008,9007) Value 1 is ORIGINAL. May be present otherwise. A sequence that provides information about each receive coil used. Only a single Item shall be permitted in this sequence. Name of receive coil used. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Name of manufacturer of receive coil. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Type of receive coil used. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Defined Terms: BODY VOLUME = head, extremity, etc. SURFACE MULTICOIL Indicates whether the receive coil is quadrature. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Enumerated Values: YES = quadrature or circularly polarized NO = linear A sequence that provides information regarding each element of a multi-coil. It should include attributes for all elements, whether used in the current acquisition or not. One or more Items shall be present. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Receive Coil Type (0018,9043) equals MULTICOIL. May be present otherwise only if Receive Coil Type (0018,9043) equals MULTICOIL. Name of element of multi-coil. Indicates whether the multi-coil element was used in the current acquisition. Enumerated Values: YES NO A textual description of the configuration of multi-coil elements which was used in the current acquisition. A sequence that provides information about the transmit coil used. Only a single Item shall be permitted in this sequence. Name of transmit coil used. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Name of manufacturer of transmit coil. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Type of transmit coil used. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Defined Terms: BODY VOLUME = head, extremity, etc. SURFACE Identifies the diffusion parameters of this frame. One Item shall be included in this sequence. Diffusion sensitization factor in sec/mm2. This is the actual b-value for original frames and those derived from frames with the same b-value, or the most representative b-value when derived from images with different b-values. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Diffusion b-matrix Sequence (0018,9601) is not present. May be present otherwise. Specifies whether diffusion conditions for the frame are directional, or isotropic with respect to direction. Defined Terms: DIRECTIONAL BMATRIX ISOTROPIC NONE = to be used when Frame Type (0008,9007) value 4 equals DIFFUSION_ANISO or Diffusion b-value (0018,9087) is 0 (zero). Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Sequence containing orientations of all diffusion sensitization gradients that were applied during the preparation phase for this frame. One or more Items may be present. Required if Diffusion Directionality (0018,9075) equals DIRECTIONAL The direction cosines of the diffusion gradient vector with respect to the patient Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. The directional diffusion sensitization expressed as a 3x3 matrix with diagonal symmetry (with six unique elements from which the other elements can be derived). The rows and columns of the matrix are the X (right to left), Y (anterior to posterior) and Z (foot to head) patient-relative orthogonal axes as defined in C.7.6.2.1.1. The values are in units of ms/mm2. Exactly one Item shall be present. Required if Diffusion Directionality (0018,9075) equals BMATRIX. The value of b[X,X]. The value of b[X,Y]. The value of b[X,Z]. The value of b[Y,Y]. The value of b[Y,Z]. The value of b[Z,Z]. Class of diffusion anisotropy calculation. Defined Terms: FRACTIONAL RELATIVE VOLUME_RATIO Required if Frame Type (0008,9007) value 4 equals DIFFUSION_ANISO. Identifies the averaging parameters of this frame. Only a single Item shall be permitted in this sequence. Maximum number of times any point in k-space is acquired. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. A sequence that provides the position of spatial saturation bands deposited as part of the pulse sequence. Zero or more Items may be included in this sequence. Thickness of slab in mm. The direction cosines of a normal vector perpendicular to the saturation plane with respect to the patient. See C.7.6.2.1.1 for further explanation.
The Image Position (0020,0032) specifies the x, y, and z coordinates of the upper left hand corner of the image; it is the center of the first voxel transmitted. Image Orientation (0020,0037) specifies the direction cosines of the first row and the first column with respect to the patient. These Attributes shall be provide as a pair. Row value for the x, y, and z axes respectively followed by the Column value for the x, y, and z axes respectively. The direction of the axes is defined fully by the patient’s orientation. The x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient. The patient based coordinate system is a right handed system, i.e. the vector cross product of a unit vector along the positive x-axis and a unit vector along the positive y-axis is equal to a unit vector along the positive z-axis. Note If a patient lies parallel to the ground, face-up on the table, with his feet-to-head direction same as the front-to-back direction of the imaging equipment, the direction of the axes of this patient based coordinate system and the equipment based coordinate system in previous versions of this Standard will coincide. The Image Plane Attributes, in conjunction with the Pixel Spacing Attribute, describe the position and orientation of the image slices relative to the patient-based coordinate system. In each image frame the Image Position (Patient) (0020,0032) specifies the origin of the image with respect to the patient-based coordinate system. RCS and the Image Orientation (Patient) (0020,0037) attribute values specify the orientation of the image frame rows and columns. The mapping of pixel location to the RCS is calculated as follows: size 12{ left [ matrix { P rSub { size 8{x} } {} ## P rSub { size 8{y} } {} ## P rSub { size 8{z} } {} ## 1 } right ]= left [ matrix { X rSub { size 8{x} } Δi {} # Y rSub { size 8{x} } Δj {} # 0 {} # S rSub { size 8{x} } {} ## X rSub { size 8{y} } Δi {} # Y rSub { size 8{y} } Δj {} # 0 {} # S rSub { size 8{y} } {} ## X rSub { size 8{z} } Δi {} # Y rSub { size 8{z} } Δj {} # 0 {} # S rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { i {} ## j {} ## 0 {} ## 1 } right ]} {} = M Where: Pxyz The coordinates of the voxel (i,j) in the frame’s image plane in units of mm. Sxyz The three values of the Image Position (Patient) (0020,0032) attributes. It is the location in mm from the origin of the RCS. Xxyz The values from the row (X) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. Yxyz The values from the column (Y) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. i Column index to the image plane. The first column is index zero. i Column pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. j Row index to the image plane. The first row index is zero. j Row pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. Additional constraints apply: 1) The row and column direction cosine vectors shall be orthogonal, i.e. their dot product shall be zero. 2) The row and column direction cosine vectors shall be normal, i.e. the dot product of each direction cosine vector with itself shall be unity.
The x, y, and z coordinates of the midpoint of the slab plane in mm with respect to the patient. See C.7.6.2.1.1 for further explanation.
The Image Position (0020,0032) specifies the x, y, and z coordinates of the upper left hand corner of the image; it is the center of the first voxel transmitted. Image Orientation (0020,0037) specifies the direction cosines of the first row and the first column with respect to the patient. These Attributes shall be provide as a pair. Row value for the x, y, and z axes respectively followed by the Column value for the x, y, and z axes respectively. The direction of the axes is defined fully by the patient’s orientation. The x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient. The patient based coordinate system is a right handed system, i.e. the vector cross product of a unit vector along the positive x-axis and a unit vector along the positive y-axis is equal to a unit vector along the positive z-axis. Note If a patient lies parallel to the ground, face-up on the table, with his feet-to-head direction same as the front-to-back direction of the imaging equipment, the direction of the axes of this patient based coordinate system and the equipment based coordinate system in previous versions of this Standard will coincide. The Image Plane Attributes, in conjunction with the Pixel Spacing Attribute, describe the position and orientation of the image slices relative to the patient-based coordinate system. In each image frame the Image Position (Patient) (0020,0032) specifies the origin of the image with respect to the patient-based coordinate system. RCS and the Image Orientation (Patient) (0020,0037) attribute values specify the orientation of the image frame rows and columns. The mapping of pixel location to the RCS is calculated as follows: size 12{ left [ matrix { P rSub { size 8{x} } {} ## P rSub { size 8{y} } {} ## P rSub { size 8{z} } {} ## 1 } right ]= left [ matrix { X rSub { size 8{x} } Δi {} # Y rSub { size 8{x} } Δj {} # 0 {} # S rSub { size 8{x} } {} ## X rSub { size 8{y} } Δi {} # Y rSub { size 8{y} } Δj {} # 0 {} # S rSub { size 8{y} } {} ## X rSub { size 8{z} } Δi {} # Y rSub { size 8{z} } Δj {} # 0 {} # S rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { i {} ## j {} ## 0 {} ## 1 } right ]} {} = M Where: Pxyz The coordinates of the voxel (i,j) in the frame’s image plane in units of mm. Sxyz The three values of the Image Position (Patient) (0020,0032) attributes. It is the location in mm from the origin of the RCS. Xxyz The values from the row (X) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. Yxyz The values from the column (Y) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. i Column index to the image plane. The first column is index zero. i Column pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. j Row index to the image plane. The first row index is zero. j Row pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. Additional constraints apply: 1) The row and column direction cosine vectors shall be orthogonal, i.e. their dot product shall be zero. 2) The row and column direction cosine vectors shall be normal, i.e. the dot product of each direction cosine vector with itself shall be unity.
Describes the chemical shift parameters used to measure the resonant peaks from which the MR metabolite map represented by this frame was derived. Only a single Item shall be permitted in this sequence. Text describing the Metabolite Map. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. When the measured peaks or their ratios can be related to metabolite substances, this sequence may be used to describe the metabolite substance whose resonant peaks are mapped in the Metabolite Map, or the ratio of substance resonant peaks that is mapped. Only one item shall be present in this Sequence. The list of frequencies that were used to create the Metabolite Map. One or more Items may be included in this sequence. Minimal value of Chemical Shift Frequency in ppm. Maximum value of Chemical Shift Frequency in ppm. Identifies the velocity encoding of this frame. Only a single Item shall be permitted in this sequence. The direction cosines of the velocity encoding vector with respect to the patient. See C.7.6.2.1.1 for further explanation. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise.
The Image Position (0020,0032) specifies the x, y, and z coordinates of the upper left hand corner of the image; it is the center of the first voxel transmitted. Image Orientation (0020,0037) specifies the direction cosines of the first row and the first column with respect to the patient. These Attributes shall be provide as a pair. Row value for the x, y, and z axes respectively followed by the Column value for the x, y, and z axes respectively. The direction of the axes is defined fully by the patient’s orientation. The x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient. The patient based coordinate system is a right handed system, i.e. the vector cross product of a unit vector along the positive x-axis and a unit vector along the positive y-axis is equal to a unit vector along the positive z-axis. Note If a patient lies parallel to the ground, face-up on the table, with his feet-to-head direction same as the front-to-back direction of the imaging equipment, the direction of the axes of this patient based coordinate system and the equipment based coordinate system in previous versions of this Standard will coincide. The Image Plane Attributes, in conjunction with the Pixel Spacing Attribute, describe the position and orientation of the image slices relative to the patient-based coordinate system. In each image frame the Image Position (Patient) (0020,0032) specifies the origin of the image with respect to the patient-based coordinate system. RCS and the Image Orientation (Patient) (0020,0037) attribute values specify the orientation of the image frame rows and columns. The mapping of pixel location to the RCS is calculated as follows: size 12{ left [ matrix { P rSub { size 8{x} } {} ## P rSub { size 8{y} } {} ## P rSub { size 8{z} } {} ## 1 } right ]= left [ matrix { X rSub { size 8{x} } Δi {} # Y rSub { size 8{x} } Δj {} # 0 {} # S rSub { size 8{x} } {} ## X rSub { size 8{y} } Δi {} # Y rSub { size 8{y} } Δj {} # 0 {} # S rSub { size 8{y} } {} ## X rSub { size 8{z} } Δi {} # Y rSub { size 8{z} } Δj {} # 0 {} # S rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { i {} ## j {} ## 0 {} ## 1 } right ]} {} = M Where: Pxyz The coordinates of the voxel (i,j) in the frame’s image plane in units of mm. Sxyz The three values of the Image Position (Patient) (0020,0032) attributes. It is the location in mm from the origin of the RCS. Xxyz The values from the row (X) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. Yxyz The values from the column (Y) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. i Column index to the image plane. The first column is index zero. i Column pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. j Row index to the image plane. The first row index is zero. j Row pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. Additional constraints apply: 1) The row and column direction cosine vectors shall be orthogonal, i.e. their dot product shall be zero. 2) The row and column direction cosine vectors shall be normal, i.e. the dot product of each direction cosine vector with itself shall be unity.
Minimum velocity in cm/s. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Maximum velocity in cm/s. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise.
Type of equipment that originally acquired the data used to create the images in this Series. Enumerated Values: MR See section C.7.3.1.1.1 for further explanation. Uniquely identifies the Performed Procedure Step SOP Instance to which the Series is related (e.g. a Modality or General-Purpose Performed Procedure Step SOP Instance). The Sequence shall have one Item. Required if the Modality Performed Procedure Step SOP Class , General Purpose Performed Procedure Step SOP Class is supported. Spectroscopy data characteristics. See C.8.14.5.1.1.
The Image Type (0008,0008) and Frame Type (0008,9007) are not included in this Macro but one or the other is always included in the Module or Macro that invokes this Macro, and they are therefore described here. In addition to the requirements specified in C.8.16.1 Image Type and Frame Type, the following additional requirements and Defined Terms are specified.
Precession frequency in MHz of the nucleus being addressed for each spectral axis. See section C.8.14.1.1 for further explanation of the ordering. Required if Image Type (0008,0008) Value 1 is ORIGINAL. May be present otherwise. Spectral width in Hz. See section C.8.14.1.1 for further explanation of the ordering. Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. The chemical shift at the transmitter frequency in ppm. See section C.8.14.1.1 for further explanation of the ordering. Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Name of volume localization technique used. Shall be "NONE" if no spatial localization was performed. Defined Terms: ILOPS ISIS PRIME PRESS SLIM SLOOP STEAM NONE Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. A sequence of one or more Items that provide the position of RF excitations used to select a volume of tissue. The selected volume is described by the intersection of the sequence Items. Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and Volume Localization Technique (0018,9054) is other than NONE. May be present if Volume Localization Technique (0018,9054) is other than NONE. Thickness of slab in mm. The direction cosines of a normal vector perpendicular to the selection plane with respect to the patient. See C.7.6.2.1.1 for further explanation.
The Image Position (0020,0032) specifies the x, y, and z coordinates of the upper left hand corner of the image; it is the center of the first voxel transmitted. Image Orientation (0020,0037) specifies the direction cosines of the first row and the first column with respect to the patient. These Attributes shall be provide as a pair. Row value for the x, y, and z axes respectively followed by the Column value for the x, y, and z axes respectively. The direction of the axes is defined fully by the patient’s orientation. The x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient. The patient based coordinate system is a right handed system, i.e. the vector cross product of a unit vector along the positive x-axis and a unit vector along the positive y-axis is equal to a unit vector along the positive z-axis. Note If a patient lies parallel to the ground, face-up on the table, with his feet-to-head direction same as the front-to-back direction of the imaging equipment, the direction of the axes of this patient based coordinate system and the equipment based coordinate system in previous versions of this Standard will coincide. The Image Plane Attributes, in conjunction with the Pixel Spacing Attribute, describe the position and orientation of the image slices relative to the patient-based coordinate system. In each image frame the Image Position (Patient) (0020,0032) specifies the origin of the image with respect to the patient-based coordinate system. RCS and the Image Orientation (Patient) (0020,0037) attribute values specify the orientation of the image frame rows and columns. The mapping of pixel location to the RCS is calculated as follows: size 12{ left [ matrix { P rSub { size 8{x} } {} ## P rSub { size 8{y} } {} ## P rSub { size 8{z} } {} ## 1 } right ]= left [ matrix { X rSub { size 8{x} } Δi {} # Y rSub { size 8{x} } Δj {} # 0 {} # S rSub { size 8{x} } {} ## X rSub { size 8{y} } Δi {} # Y rSub { size 8{y} } Δj {} # 0 {} # S rSub { size 8{y} } {} ## X rSub { size 8{z} } Δi {} # Y rSub { size 8{z} } Δj {} # 0 {} # S rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { i {} ## j {} ## 0 {} ## 1 } right ]} {} = M Where: Pxyz The coordinates of the voxel (i,j) in the frame’s image plane in units of mm. Sxyz The three values of the Image Position (Patient) (0020,0032) attributes. It is the location in mm from the origin of the RCS. Xxyz The values from the row (X) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. Yxyz The values from the column (Y) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. i Column index to the image plane. The first column is index zero. i Column pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. j Row index to the image plane. The first row index is zero. j Row pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. Additional constraints apply: 1) The row and column direction cosine vectors shall be orthogonal, i.e. their dot product shall be zero. 2) The row and column direction cosine vectors shall be normal, i.e. the dot product of each direction cosine vector with itself shall be unity.
The x, y, and z coordinates of the mid-point of the slab in mm. See C.7.6.2.1.1 for further explanation.
The Image Position (0020,0032) specifies the x, y, and z coordinates of the upper left hand corner of the image; it is the center of the first voxel transmitted. Image Orientation (0020,0037) specifies the direction cosines of the first row and the first column with respect to the patient. These Attributes shall be provide as a pair. Row value for the x, y, and z axes respectively followed by the Column value for the x, y, and z axes respectively. The direction of the axes is defined fully by the patient’s orientation. The x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient. The patient based coordinate system is a right handed system, i.e. the vector cross product of a unit vector along the positive x-axis and a unit vector along the positive y-axis is equal to a unit vector along the positive z-axis. Note If a patient lies parallel to the ground, face-up on the table, with his feet-to-head direction same as the front-to-back direction of the imaging equipment, the direction of the axes of this patient based coordinate system and the equipment based coordinate system in previous versions of this Standard will coincide. The Image Plane Attributes, in conjunction with the Pixel Spacing Attribute, describe the position and orientation of the image slices relative to the patient-based coordinate system. In each image frame the Image Position (Patient) (0020,0032) specifies the origin of the image with respect to the patient-based coordinate system. RCS and the Image Orientation (Patient) (0020,0037) attribute values specify the orientation of the image frame rows and columns. The mapping of pixel location to the RCS is calculated as follows: size 12{ left [ matrix { P rSub { size 8{x} } {} ## P rSub { size 8{y} } {} ## P rSub { size 8{z} } {} ## 1 } right ]= left [ matrix { X rSub { size 8{x} } Δi {} # Y rSub { size 8{x} } Δj {} # 0 {} # S rSub { size 8{x} } {} ## X rSub { size 8{y} } Δi {} # Y rSub { size 8{y} } Δj {} # 0 {} # S rSub { size 8{y} } {} ## X rSub { size 8{z} } Δi {} # Y rSub { size 8{z} } Δj {} # 0 {} # S rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { i {} ## j {} ## 0 {} ## 1 } right ]} {} = M Where: Pxyz The coordinates of the voxel (i,j) in the frame’s image plane in units of mm. Sxyz The three values of the Image Position (Patient) (0020,0032) attributes. It is the location in mm from the origin of the RCS. Xxyz The values from the row (X) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. Yxyz The values from the column (Y) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. i Column index to the image plane. The first column is index zero. i Column pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. j Row index to the image plane. The first row index is zero. j Row pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. Additional constraints apply: 1) The row and column direction cosine vectors shall be orthogonal, i.e. their dot product shall be zero. 2) The row and column direction cosine vectors shall be normal, i.e. the dot product of each direction cosine vector with itself shall be unity.
Indicates whether de-coupling was active. Enumerated Values: YES NO Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Nucleus being de-coupled. Defined Terms: 1H 3HE 7LI 13C 19F 23NA 31P 129XE See section C.8.14.1.1 for further explanation of the ordering. Required if De-coupling (0018,9059) equals YES. The center frequency (Hz) for the de-coupling. See section C.8.14.1.1 for further explanation of the ordering. Required if De-coupling (0018,9059) equals YES. The de-coupling modulation scheme used. Defined Terms: MLEV WALTZ NARROWBAND Required if De-coupling (0018,9059) equals YES. The chemical shift in ppm at the de-coupling frequency. See section C.8.14.1.1 for further explanation of the ordering. Required if De-coupling (0018,9059) equals YES. Describes time domain filtering or apodization applied. Shall be NONE if no filtering operations were applied to the time domain data. Defined Terms: COSINE COSINE_SQUARED EXPONENTIAL GAUSSIAN HAMMING HANNING LORENTZIAN LRNTZ_GSS_TRNSFM NONE See section C.8.14.1.1 for further explanation of the ordering. Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Number of zero fills added to the time domain data before FT. Shall be 0 (zero) if no zero filling performed. See section C.8.14.1.1 for further explanation of the ordering. Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Describes baseline correction techniques. Shall be NONE if no baseline correction was performed. Defined Terms: LINEAR_TILT LOCAL_LINEAR_FIT POLYNOMIAL_FIT SINC_DECONVOLUTN TIME_DOMAIN_FIT SPLINE NONE Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Specifies whether operations were performed to correct resonant frequency of metabolite peaks due to B0 field inhomogeneities. Enumerated Values: YES NO Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Describes whether a first order (frequency dependent) phase correction was applied to the spectral data. Enumerated Values: YES NO Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Enumerated Values: YES NO Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise.
Name of the pulse sequence for annotation purposes. Potentially vendor-specific name. Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Identification of data encoding scheme. Defined Terms: SINGLE_VOXEL ROW PLANE VOLUME Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Echo category of pulse sequences. Enumerated Values: SPIN GRADIENT BOTH Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Multiple Spin Echo category of pulse sequence used to collect different lines in k-space for a single frame. Enumerated Values: YES NO Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and Echo Pulse Sequence (0018,9008) equals SPIN or BOTH. Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and Echo Pulse Sequence (0018,9008) equals SPIN or BOTH. Technique that simultaneously excites several volumes. Enumerated Values: YES NO Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Steady State Sequence. Defined Terms: FREE_PRECESSION TRANSVERSE TIME_REVERSED LONGITUDINAL NONE Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Echo Planar category of pulse-sequences. Enumerated Values: YES NO Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Spectrally Selected Suppression. Defined Terms: WATER FAT FAT_AND_WATER SILICON_GEL NONE Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Geometry category of k-Space traversal. Defined Terms: RECTILINEAR RADIAL SPIRAL Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Rectilinear phase encode reordering. Defined Terms: LINEAR CENTRIC SEGMENTED REVERSE_LINEAR REVERSE_CENTRIC Required if Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and Geometry of k-Space Traversal (0018,9032) equals RECTILINEAR. Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and Geometry of k-Space Traversal (0018,9032) equals RECTILINEAR. Segmented k-Space traversal. If Geometry of k-Space Traversal is rectilinear, multiple lines can be acquired at one time. If Geometry of k-Space Traversal is spiral or radial, paths can be interleaved and acquired at one time. Enumerated Values: SINGLE = successive single echo coverage PARTIAL = segmented coverage FULL = single shot full coverage Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Coverage of k-Space. Defined Terms: FULL CYLINDRICAL ELLIPSOIDAL WEIGHTED Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED and MR Spectroscopy Acquisition Type (0018,9200) equals VOLUME. Otherwise may be present if Image Type (0008,0008) Value 1 is DERIVED and MR Spectroscopy Acquisition Type (0018,9200) equals VOLUME. Number of interleaves or shots. Required if Image Type (0008,0008) Value 1 is ORIGINAL or MIXED. May be present otherwise. Identifies sequence containing Frame Type Attributes. Only a single Item shall be permitted in this sequence. Spectroscopy data characteristics. See C.8.14.5.1.1.
The Image Type (0008,0008) and Frame Type (0008,9007) are not included in this Macro but one or the other is always included in the Module or Macro that invokes this Macro, and they are therefore described here. In addition to the requirements specified in C.8.16.1 Image Type and Frame Type, the following additional requirements and Defined Terms are specified.
Identifies the geometry parameters of this frame. Only a single Item shall be permitted in this sequence. Number of data points in the columns direction. Required if Frame Type (0008,9007) Value 1 is ORIGINAL. May be present otherwise. Number of Phase Encoding Rows. Required if Frame Type (0008,9007) Value 1 is ORIGINAL. May be present otherwise. Number of Phase Encoding Columns. Required if Frame Type (0008,9007) Value 1 is ORIGINAL. May be present otherwise. Number of out-of-plane Phase Encoding steps. Required if MR Spectroscopy Acquisition Type (0018,9200) equals PLANE and Frame Type (0008,9007) Value 1 is ORIGINAL. May be present otherwise. Fraction of acquisition matrix lines acquired, expressed as a percent. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Ratio of field of view dimension in phase direction to field of view dimension in frequency direction, expressed as a percent. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Number of voxels in the vertical direction in the frame. Number of voxels in the horizontal direction in the frame. Number of rows of data points in spectroscopic data. Number of columns of data points in spectroscopic data. Data representation of the data points. Each data point shall have the same representation. Enumerated Values: COMPLEX = Data is complex pair REAL = Data contains only real component IMAGINARY = Data contains only imaginary component MAGNITUDE = Magnitude data Domain of represented signal in column direction. Enumerated Values: FREQUENCY TIME Domain of represented signal in row direction. Enumerated Values: FREQUENCY TIME Required if Data Point Rows (0028,9001) has a value of more than 1. First Order Phase Correction Angle. Number of values is determined by Row  Column  Number of Frames. Required if First Order Phase Correction (0018,9198) equals YES A data stream of the signal intensities that comprise the spectroscopic data. See C.8.14.4.1 for further explanation.
The Spectroscopy Data attribute (5600,0020) contains the Signal intensities for the spectra. The order of voxels sent for each spectral plane is left to right, top to bottom, i.e., the upper left voxel (labeled 1,1) is sent first followed by the remainder of row 1, followed by the first voxel of row 2 (labeled 2,1) then the remainder of row 2 and so on. Each "voxel" represents an entire spectrum. The complete spectral data from each voxel is sent, followed by the spectral data from the next voxel position. The number of voxels on each frame are described by Rows (0028,0010) and Columns (0028,0011). The number of frames is described by Number of Frames (0028,0008). The frames may represent different locations in a 3D acquisition, or the same position at a different point of time, or a difference of some other combination of attributes. Note: Either Rows or Columns or both may have a value of 1 (e.g., for single voxel spectroscopy). A value of zero for the corresponding value of Pixel Spacing in the Pixel Measures Macro is permitted under these circumstances. See 10.7.1.3. The spectral data points are ordered from lower effective magnetic field strength (down-field) to higher effective magnetic field strength (up-field) when the Signal Domain Columns (0028,9003) or Signal Domain Rows (0028,9235) attributes contain the value FREQUENCY and from first sample acquired to last sample acquired when the Signal Domain Columns (0028,9003) or Signal Domain Rows (0028,9235) attributes contain the value TIME. For two-dimensional spectral acquisitions, the ordering is such that all data points from a row (corresponding to all data points acquired in an individual sampling period), are followed by all data points from the successive sampling period. Following all data of the rows from a given voxel position, the data from the subsequent voxel position are sent. The axis parallel to the row direction corresponds to the sampling time axis. The axis parallel to the column direction corresponds to the evolution time axis. The dimensions of each spectrum that make up a voxel are described by Data Point Rows (0028,9001) and Data Point Columns (0028,9002). In the case of 1D spectra, the number of Data Point Rows shall be 1. For a Data Representation (0028,9108) value of COMPLEX, the order of data points is real channel followed by imaginary channel for each spectral data point. For the other Data Representation values (REAL, IMAGINARY and MAGNITUDE), each spectral data point contains only a single value. The Figure C.8-18 depicts 6 frames each made up of 4 rows and 4 columns of voxels. Specific values for Data Point Rows (0028,9001) and Data Point Columns (0028,9002) of these voxels are not depicted.
Indication if geometric manipulations are possible with frames in the SOP Instance. See C.8.14.5.1.2 for a description and Enumerated Values.
See C.8.16.2.1.2. No additional requirements or Defined Terms.
Method used for volume calculations with frames in the SOP Instance. See C.8.14.5.1.3 for a description and Defined Terms.
See C.8.16.2.1.3 for requirements, but not Defined Terms. Table C.8-110 specifies the Defined Terms for the Volume Based Calculation Technique (0008,9207) attribute. Table C.8-110 VOLUME BASED CALCULATION TECHNIQUE ATTRIBUTE VALUES
Representation of complex data of frames in the SOP Instance. See C.8.14.5.1.4 for a description and Defined Terms.
The value of the Complex Image Component attribute (0008,9208) shall be used to indicate which component of the complex representation of the signal is represented in the spectroscopy data. Table C.8-111 specifies the Defined Terms for Complex Image Component attribute (0008,9208). Table C.8-111 COMPLEX IMAGE COMPONENT ATTRIBUTE VALUES
Indication of acquisition contrast used with frames in the SOP Instance. See C.8.14.5.1.5 for a description and Defined Terms.
Table C.8-112 specifies the Defined Terms for Acquisition Contrast attribute (0008,9209). Table C.8-112 ACQUISITION CONTRAST VALUES
Type of equipment that originally acquired the data used to create the images in this Series. Enumerated Values: CT See section C.7.3.1.1.1 for further explanation. Uniquely identifies the Performed Procedure Step SOP Instance to which the Series is related (e.g. a Modality or General-Purpose Performed Procedure Step SOP Instance). The Sequence shall have one Item. Required if the Modality Performed Procedure Step SOP Class , General Purpose Performed Procedure Step SOP Class is supported. Image characteristics. See sections C.8.16.1 and C.8.15.2.1.1. A number identifying the single continuous gathering of data over a period of time that resulted in this image. Note: This number is not required to be unique across SOP Instances in a series. See also the description of the Referenced Raw Data Sequence (0008,9121). The date and time that the acquisition of data started. Notes: 1. The synchronization of this time with an external clock is specified in the synchronization Module in Acquisition Time synchronized (0018,1800) . 2. See C.7.6.16.2.2.1 for an overview of all acquisition related timing attributes. Required if Image Type (0008,0008) Value 1 of this frame is ORIGINAL or MIXED, may be present otherwise.
Figure C.7.6.16-2 shows the relationships among the various timing parameters used.
The time in seconds needed to complete the acquisition of data. See C.7.6.16.2.2.1 for further explanation. Required if Image Type (0008,0008) Value 1 of this frame is ORIGINAL or MIXED, may be present otherwise.
Figure C.7.6.16-2 shows the relationships among the various timing parameters used.
A sequence that identifies the set of Raw Data SOP Class/Instance pairs of the Raw data that were used to derive this Image. One or more Items may be included in this Sequence. Note: The items of in this sequence may identify raw data that has not been stored or encoded as a DICOM object. This allows recognition that images in different instances have been reconstructed from the same raw data. References to waveforms acquired in conjunction with this image. These Waveforms may or may not be temporally synchronized with this image. One or more Items may be included in this sequence. Full set of Composite SOP Instances referring to image SOP Instances inside the frames of this Enhanced CT Image SOP Instance. See C.8.13.2.1.2 for further explanation. One or more Items may be included in this sequence. Required if the Referenced Image Sequence (0008,1140) is present.
The intent of the Referenced Image Evidence Sequence (0008,9092) and Source Image Evidence Sequence (0008,9154) is to provide a list of all unique SOP Instances listed in the Referenced Image Sequence (0008,1140) and Source Image Sequence (0008,2112) attributes respectively.
Full set of Composite SOP Instances used as source image SOP Instances inside the frames of this Enhanced CT Image SOP Instance. See C.8.13.2.1.2 for further explanation. One or more Items may be included in this sequence. Required if the Source Image Sequence (0008,2112) is present.
The intent of the Referenced Image Evidence Sequence (0008,9092) and Source Image Evidence Sequence (0008,9154) is to provide a list of all unique SOP Instances listed in the Referenced Image Sequence (0008,1140) and Source Image Sequence (0008,2112) attributes respectively.
References to Grayscale Presentation State instances acquired in conjunction with this instance. Note: May only be used to reference Presentation States belonging to the acquired data and not to reference Presentation States generated subsequently such as during interpretation. One or more Items may be included in this sequence. Required if Presentation State is generated during acquisition, shall not be present otherwise. Number of samples (planes) in this image. This value shall be 1. Specifies the intended interpretation of the pixel data. Enumerated Value: MONOCHROME2. See C.7.6.3.1.2 for definition of this term.
The value of Photometric Interpretation (0028,0004) specifies the intended interpretation of the image pixel data. See PS 3.5 for restrictions imposed by compressed Transfer Syntaxes. The following values are defined. Other values are permitted but the meaning is not defined by this Standard. MONOCHROME1 = Pixel data represent a single monochrome image plane. The minimum sample value is intended to be displayed as white after any VOI gray scale transformations have been performed. See PS 3.4. This value may be used only when Samples per Pixel (0028,0002) has a value of 1. MONOCHROME2 = Pixel data represent a single monochrome image plane. The minimum sample value is intended to be displayed as black after any VOI gray scale transformations have been performed. See PS 3.4. This value may be used only when Samples per Pixel (0028,0002) has a value of 1. PALETTE COLOR = Pixel data describe a color image with a single sample per pixel (single image plane). The pixel value is used as an index into each of the Red, Blue, and Green Palette Color Lookup Tables (0028,1101-1103&1201-1203). This value may be used only when Samples per Pixel (0028,0002) has a value of 1. When the Photometric Interpretation is Palette Color; Red, Blue, and Green Palette Color Lookup Tables shall be present. RGB = Pixel data represent a color image described by red, green, and blue image planes. The minimum sample value for each color plane represents minimum intensity of the color. This value may be used only when Samples per Pixel (0028,0002) has a value of 3. HSV = Retired. ARGB = Retired. CMYK = Retired. YBR_FULL = Pixel data represent a color image described by one luminance (Y) and two chrominance planes (CB and CR). This photometric interpretation may be used only when Samples per Pixel (0028,0002) has a value of 3. Black is represented by Y equal to zero. The absence of color is represented by both CB and CR values equal to half full scale. Note: In the case where the Bits Allocated (0028,0100) has value of 8 half full scale is 128. In the case where Bits Allocated (0028,0100) has a value of 8 then the following equations convert between RGB and YCBCR Photometric Interpretation. Y = + .2990R + .5870G + .1140B CB = - .1687R - .3313G + .5000B + 128 CR = + .5000R - .4187G - .0813B + 128 Note: The above is based on CCIR Recommendation 601-2 dated 1990. YBR_FULL_422 = The same as YBR_FULL except that the CB and CR values are sampled horizontally at half the Y rate and as a result there are half as many CB and CR values as Y values. This Photometric Interpretation is only allowed with Planar Configuration (0028,0006) equal to 0. Two Y values shall be stored followed by one CB and one CR value. The CB and CR values shall be sampled at the location of the first of the two Y values. For each Row of Pixels, the first CB and CR samples shall be at the location of the first Y sample. The next CB and CR samples shall be at the location of the third Y sample etc. Note: This subsampling is often referred to as cosited sampling. YBR_PARTIAL_422 = The same as YBR_FULL_422 except that: 1. black corresponds to Y = 16; 2. Y is restricted to 220 levels (i.e. the maximum value is 235); 3. CB and CR each has a minimum value of 16; 4. CB and CR are restricted to 225 levels (i.e. the maximum value is 240); 5. lack of color is represented by CB and CR equal to 128. In the case where Bits Allocated (0028,0100) has value of 8 then the following equations convert between RGB and YBR_PARTIAL_422 Photometric Interpretation Y = + .2568R + .5041G + .0979B + 16 CB = - .1482R - .2910G + .4392B + 128 CR = + .4392R - .3678G - .0714B + 128 Note: The above is based on CCIR Recommendation 601-2 dated 1990. YBR_PARTIAL_420 = The same as YBR_PARTIAL_422 except that the CB and CR values are sampled horizontally and vertically at half the Y rate and as a result there are four times less CB and CR values than Y values, versus twice less for YBR_PARTIAL_422. This Photometric Interpretation is only allowed with Planar Configuration (0028,0006) equal to 0. The CB and CR values shall be sampled at the location of the first of the two Y values. For the first Row of Pixels (etc.), the first CB and CR samples shall be at the location of the first Y sample. The next CB and CR samples shall be at the location of the third Y sample etc. The next Rows of Pixels containing CB and CR samples (at the same locations than for the first Row) will be the third etc. YBR_ICT = Irreversible Color Transformation: Pixel data represent a color image described by one luminance (Y) and two chrominance planes (CB and CR). This photometric interpretation may be used only when Samples per Pixel (0028,0002) has a value of 3. Black is represented by Y equal to zero. The absence of color is represented by both CB and CR values equal to zero. Regardless of the value of Bits Allocated (0028,0100), the following equations convert between RGB and YCBCR Photometric Interpretation. Y = + .29900R + .58700G + .11400B CB = - .16875R - .33126G + .50000B CR = + .50000R - .41869G - .08131B Notes: 1. The above is based on ISO/IEC 15444-1 (JPEG 2000). 2. In a JPEG 2000 bitstream, DC level shifting (used if the untransformed components are unsigned) is applied before forward color transformation, and the transformed components may be signed (unlike in JPEG ISO/IEC 10918-1). 3. In JPEG 2000, spatial down-sampling of the chrominance components, if performed, is signaled in the JPEG 2000 bitstream. YBR_RCT = Reversible Color Transformation: Pixel data represent a color image described by one luminance (Y) and two chrominance planes (CB and CR). This photometric interpretation may be used only when Samples per Pixel (0028,0002) has a value of 3. Black is represented by Y equal to zero. The absence of color is represented by both CB and CR values equal to zero. Regardless of the value of Bits Allocated (0028,0100), the following equations convert between RGB and YBR_RCT Photometric Interpretation. Y = R + 2G +B) / 4 (Note:  mean floor) CB = B - G CR = R - G The following equations convert between YBR_RCT and RGB Photometric Interpretation. G = Y –  (CR + CB) / 4 R = CR + G B = CB + G Notes: 1. The above is based on ISO/IEC 15444-1 (JPEG 2000). 2. In a JPEG 2000 bitstream, DC level shifting (used if the untransformed components are unsigned) is applied before forward color transformation, and the transformed components may be signed (unlike in JPEG ISO/IEC 10918-1). 3. This photometric interpretation is a reversible approximation to the YUV transformation used in PAL and SECAM.
Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated. This value shall be 16. Number of bits stored for each pixel sample. Each sample shall have the same number of bits stored. This value shall be 12 or16. Most significant bit for pixel sample data. Each sample shall have the same high bit. Shall be one less than the value in Bits Stored (0028,0101). Content Qualification Indicator Enumerated Values: PRODUCT RESEARCH SERVICE See C.8.13.2.1.1 for further explanation.
Content Qualification (0018,9004) shall have the value PRODUCT if the content (image or Spectroscopy data) was produced with approved hardware and software. It shall have the value RESEARCH or SERVICE if there is any doubt as to whether the content was produced with approved hardware and software. If data with Content Qualification (0018,9004) of RESEARCH or SERVICE is used to derive other content then it is expected that this derived content will also have Content Qualification (0018,9004) set to RESEARCH or SERVICE. The intent of this element is to allow annotation of an advisory message that indicates that this content may not be suitable for clinical interpretation.
User-defined comments about the image Indicates whether or not the image contains sufficient burned in annotation to identify the patient and date the image was acquired. Enumerated Values: NO This means that images that contain this Module shall not contain such burned in annotations. Specifies whether an Image has undergone lossy compression. Enumerated Values: 00 = Image has NOT been subjected to lossy compression. 01 = Image has been subjected to lossy compression. See C.7.6.1.1.5 for further explanation.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
Describes the approximate lossy compression ratio(s) that have been applied to this image. See C.7.6.1.1.5 for further explanation. May be multivalued if successive lossy compression steps have been applied. Note: For example, a compression ratio of 30:1 would be described in this Attribute with a single value of 30. Required if Lossy Images Compression (0028,2110) is "01".
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
A label for the lossy compression method(s) that have been applied to this image. See C.7.6.1.1.5 for further explanation. May be multivalued if successive lossy compression steps have been applied; the value order shall correspond to the values of Lossy Image Compression Ratio (0028,2112). Required if Lossy Image Compression (0028,2110) is "01".
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
Specifies an identity transformation for the Presentation LUT, such that the output of all grayscale transformations defined in the IOD containing this Module are defined to be P-Values. Enumerated Values: IDENTITY - output is in P-Values. This icon image is representative of the Image. Only a single Item shall be permitted in this Sequence.
Identifies the characteristics of this frame. Only a single Item shall be permitted in this sequence. Type of Frame. A multi-valued attribute analogous to the Image Type (0008,0008). Enumerated Values and Defined Terms are the same as those for the four values of the Image Type (0008,0008) attribute, except that the value MIXED is not allowed. See sections C.8.16.1 and C.8.15.2.1.1.1. Contains the attributes defining the CT acquisition mode. Only a single Item shall be permitted in this sequence. Description of the method used during acquisition of this frame. See C.8.15.3.2.1 for Defined Terms. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise.
Acquisition Type (0018,9302) has the following Defined Terms: SEQUENCED identifies that the acquisition was performed by acquiring single or multi detector data while rotating the source about the gantry while the table is not moving. Additional slices are acquired by incrementing the table position and again rotating the source about the gantry while the table is not moving. SPIRAL identifies that the acquisition was performed by acquiring data while rotating the source about the gantry while continuously moving the table. CONSTANT_ANGLE identifies that the acquisition was performed by holding the source at a constant angle and moving the table to obtain a projection image (e.g., a localizer image). STATIONARY identifies that the acquisition was performed by holding the table at a constant position and acquiring multiple slices over time at the same location. FREE identifies that the acquisition was performed while rotating the source about the gantry while the table movement is under direct control of a human operator or under the control of an analysis application (e.g., fluoroscopic image).
The constant angle at which the x-ray source is located during acquisition. 0 degrees means that the source is located at the highest point of the gantry orbit. Degrees increase from 0 to positive 360 in a clockwise direction as viewed when facing the gantry where the table enters the gantry. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Acquisition Type (0018,9302) is CONSTANT_ANGLE. May be present otherwise if Frame Type (0008,9007) Value 1 of this frame is DERIVED and Acquisition Type (0018,9302) is CONSTANT_ANGLE. Identifies that the acquisition was performed by repetitively acquiring the same volume set over a period of time. Note: The Acquisition Type (0018,9302) value may be SEQUENCED, SPIRAL or STATIONARY depending on whether table movement is necessary to cover the volume. Enumerated Values YES NO Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Identifies that near real-time display of a block of continuously acquired data was performed, which may result in a lower than usual image quality. Enumerated Values YES NO Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise.
Contains the attributes defining the details of the acquisition. Only a single Item shall be permitted in this sequence. Direction of rotation of the source about the gantry, as viewed while facing the gantry where the table enters the gantry. Enumerated Values: CW = clockwise CC = counter clockwise Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Acquisition Type (0018,9302) is other than CONSTANT_ANGLE. Otherwise may be present if Frame Type (0008,9007) Value 1 of this frame is DERIVED and Acquisition Type (0018,9302) is other than CONSTANT_ANGLE. The time in seconds of a complete revolution of the source around the gantry orbit. This value is independent of the Reconstruction Angle (0018,9319) of the frame. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Acquisition Type (0018,9302) is other than CONSTANT_ANGLE. Otherwise may be present if Frame Type (0008,9007) Value 1 of this frame is DERIVED and Acquisition Type (0018,9302) is other than CONSTANT_ANGLE. The width of a single row of acquired data (in mm). Note: Adjacent physical detector rows may have been combined to form a single effective acquisition row. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. The width of the total collimation (in mm) over the area of active x-ray detection. Note: This will be equal to the number of effective detector rows multiplied by single collimation width. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. The distance in mm from the top of the patient table to the center of rotation of the source (i.e. the data collection center or isocenter). The distance is positive when the table is below the data collection center. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Nominal angle of tilt in degrees of the scanning gantry. Not intended for mathematical computations. Zero degrees means the gantry is not tilted, negative degrees are when the top of the gantry is tilted away from where the table enters the gantry. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. The diameter in mm of the region over which data were collected. See C.8.15.3.6.1. Note: In the case of an Acquisition Type (0018,9302) of CONSTANT_ANGLE, the diameter is that in a plane normal to the central ray of the diverging X-Ray beam as it passes through the data collection center. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise.
In Figure C.8-19 the relationship of the Geometric Attributes within the CT Geometry and CT Reconstruction functional groups is shown. The figure, viewed from the front of the gantry (where the table enters the gantry), is informative only and is not meant to represent a standardization of an equipment-based frame of reference. Figure C.8-19: Geometry of CT Acquisition System
Contains the attributes defining the movement of the CT table. Only a single Item shall be permitted in this sequence. The distance in mm that the table moves in one second during the gathering of data that resulted in this frame. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Acquisition Type (0018,9302) is SPIRAL or CONSTANT_ANGLE. May be present otherwise if Frame Type (0008,9007) Value 1 of this frame is DERIVED and Acquisition Type (0018,9302) is SPIRAL or CONSTANT_ANGLE. Motion of the table (in mm) during a complete revolution of the source around the gantry orbit. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Acquisition Type (0018,9302) is SPIRAL. May be present otherwise if Frame Type (0008,9007) Value 1 of this frame is DERIVED and Acquisition Type (0018,9302) is SPIRAL. Ratio of the Table Feed per Rotation (0018,9310) to the Total Collimation Width (0018,9307). See C.8.15.3.4.1 for further explanation and some examples. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Acquisition Type (0018,9302) is SPIRAL. May be present otherwise if Frame Type (0008,9007) Value 1 of this frame is DERIVED and Acquisition Type (0018,9302) is SPIRAL.
The formula for Spiral Pitch Factor (0018,9311) in terms of Table Feed per Rotation (0018,9310) and Total Collimation Width (0018,9307) is: Spiral Pitch Factor = (Table Feed per Rotation (mm))/(Total Collimation Width (mm)) An example calculation of Spiral Pitch Factor (0018,9311) for a single slice spiral acquisition of an image with a Total Collimation Width of 2.5mm and a Table Feed per Rotation of 10mm is: Spiral Pitch Factor = (10 mm)/(2.5 mm) = 4.0 An example calculation of Spiral Pitch Factor (0018,9311) for a multiple slice spiral acquisition having a Total Collimation Width of 20mm and a Table Feed per Rotation of 10mm is: Spiral Pitch Factor = (10 mm)/(20 mm) = 0.5
Contains the attributes defining the CT geometry. Only a single Item shall be permitted in this sequence. Relative longitudinal position of acquisition location of this frame in mm from an implementation specific reference point. Shall be relative to the same reference point for all frames in this SOP Instance, but may be different from the reference point in other SOP Instances. Positions as the table moves into the gantry viewed from the front are more negative. Notes: 1. For contiguous slices reconstructed from multiple detectors one would expect different values for adjacent slices. 2. Lateral positioning or tilting or swiveling are not described. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. The x, y, and z coordinates (in the patient coordinate system) in mm of the center of the region in which data were collected. See C.8.15.3.6.1. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise.
In Figure C.8-19 the relationship of the Geometric Attributes within the CT Geometry and CT Reconstruction functional groups is shown. The figure, viewed from the front of the gantry (where the table enters the gantry), is informative only and is not meant to represent a standardization of an equipment-based frame of reference. Figure C.8-19: Geometry of CT Acquisition System
The x, y, and z coordinates (in the patient coordinate system) of the reconstruction center target point as used for reconstruction in mm. See C.8.15.3.6.1. Note: If the reconstructed image is not magnified or panned the value corresponds with the Data Collection Center (0018,9313) attribute. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise.
In Figure C.8-19 the relationship of the Geometric Attributes within the CT Geometry and CT Reconstruction functional groups is shown. The figure, viewed from the front of the gantry (where the table enters the gantry), is informative only and is not meant to represent a standardization of an equipment-based frame of reference. Figure C.8-19: Geometry of CT Acquisition System
Contains the attributes defining the CT geometry. Only a single Item shall be permitted in this sequence. Distance in mm from source to detector center. See C.8.15.3.6.1. Note: This value is traditionally referred to as Source Image Receptor Distance (SID). Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise.
In Figure C.8-19 the relationship of the Geometric Attributes within the CT Geometry and CT Reconstruction functional groups is shown. The figure, viewed from the front of the gantry (where the table enters the gantry), is informative only and is not meant to represent a standardization of an equipment-based frame of reference. Figure C.8-19: Geometry of CT Acquisition System
Distance in mm from source to data collection center. See C.8.15.3.6.1. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise.
In Figure C.8-19 the relationship of the Geometric Attributes within the CT Geometry and CT Reconstruction functional groups is shown. The figure, viewed from the front of the gantry (where the table enters the gantry), is informative only and is not meant to represent a standardization of an equipment-based frame of reference. Figure C.8-19: Geometry of CT Acquisition System
Contains the attributes holding information about the reconstruction techniques used. Only a single Item shall be permitted in this sequence. Description of the algorithm used when reconstructing the image from the data acquired during the acquisition process. Defined Terms: FILTER_BACK_PROJ ITERATIVE Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. A label describing the convolution kernel or algorithm used to reconstruct the data. A single value shall be present. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. A label describing the group that the Convolution Kernel (0018,1210) belongs. Defined Terms: BRAIN SOFT_TISSUE LUNG BONE CONSTANT_ANGLE Required if Convolution Kernel (0018,1210) is present. May be present otherwise. The diameter in mm of the region from 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 this region. See C.8.15.3.6.1. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Reconstruction Field of View (0018,9317) is not present. Otherwise may be present if Frame Type (0008,9007) Value 1 of this frame is DERIVED and Reconstruction Field of View (0018,9317) is not present.
In Figure C.8-19 the relationship of the Geometric Attributes within the CT Geometry and CT Reconstruction functional groups is shown. The figure, viewed from the front of the gantry (where the table enters the gantry), is informative only and is not meant to represent a standardization of an equipment-based frame of reference. Figure C.8-19: Geometry of CT Acquisition System
The field of view width (x-dimension) followed by height (y-dimension) as used for reconstruction in mm. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Reconstruction Diameter (0018,1100) is not present. Otherwise may be present if Frame Type (0008,9007) Value 1 of this frame is DERIVED and Reconstruction Diameter (0018,1100) is not present. Physical distance in the patient between the center of each reconstructed pixel, specified by a numeric pair - adjacent row spacing (delimiter) adjacent column spacing in mm. See 10.7.1.3 for further explanation of the value order. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Angle (in degrees) over which the data from which the frame was reconstructed was collected, where 360 degrees signifies a complete revolution of the source around the gantry orbit. It is possible, in the case of over-scanning that the Reconstruction Angle is greater than 360 degrees. Shall be 0 if Acquisition Type (0018,9302) is CONSTANT_ANGLE. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. A label describing the filter applied to the reconstructed image after the original reconstruction has been completed. Note: When Frame Type (0008,9007) Value 1 of this frame is DERIVED and Frame Type (0008,9007) Value 4 is FILTERED the type of filtration is described in Derivation Image Macro. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL.
Contains the attributes defining exposure information. Only a single Item shall be permitted in this sequence. Duration of exposure for this frame in milliseconds. If Acquisition Type (0018,9302) equals SPIRAL the duration of exposure shall be weighted by the Spiral Pitch Factor (0018,9311). Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Nominal X-Ray tube current in milliamperes. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. The exposure expressed in milliampere seconds, for example calculated from exposure time and X-Ray tube current. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. A label describing the type of exposure modulation used for the purpose of limiting the dose. Defined Terms: NONE Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. A percent value of dose saving due to the use of Exposure Modulation Type (0018,9323). A negative percent value of dose savings reflects an increase of exposure. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Exposure Modulation Type (0018,9323) is not equal to NONE. Otherwise may be present if Frame Type (0008,9007) Value 1 of this frame is DERIVED and Exposure Modulation Type (0018,9323) is not equal to NONE. Computed Tomography Dose Index (CTDIvol), in mGy according to IEC 60601-2-44, Ed.2.1 (Clause 29.1.103.4), The Volume CTDIvol. It describes the average dose for this frame for the selected CT conditions of operation. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. The type of phantom used for CTDI measurement according to IEC 60601-2-44. Only a single Item shall be permitted in this Sequence. Contains the attributes defining the x-ray information. Only a single Item shall be permitted in this sequence. Peak kilo voltage output of the x-ray generator used. Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Used nominal size of the focal spot in mm. The attribute may only have one or two values, for devices with variable focal spot, small dimension followed by large dimension Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. Type of filter(s) inserted into the X-Ray beam. Defined Terms: WEDGE BUTTERFLY MULTIPLE FLAT SHAPED NONE Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL. May be present otherwise. The X-Ray absorbing material used in the filter. May be multi-valued. Defined Terms: MOLYBDENUM ALUMINUM COPPER RHODIUM NIOBIUM EUROPIUM LEAD MIXED Note: MIXED may be used to indicate a filter type of complex composition for which listing the individual materials would be excessive or undesirable; it is not intended to mean "unknown". Required if Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and the value of Filter Type (0018,1160) is other than NONE. May be present otherwise. The calibration factor for the calcium mass score. These factors incorporate the effects of See C.8.2.1.1.7.
The calibration factors for the Calcium Scoring Mass Factor Patient (0018,9351) and Calcium Scoring Mass Factor Device (0018,9352) attributes are defined by the International Consortium for Multi-Detector CT Evaluation of Coronary Calcium, see McCollough, C.H. “A multi-institutional, multi-manufacturer, international standard for the quantification of coronary artery calcium using cardiac CT”.
The calibration factors for the calcium mass score of the device. These factors incorporate the effects of This a multi-value attribute, the first value specifies the mass factor for a small patient size, the second value for a medium patient size and the third value for a large patient size. See C.8.2.1.1.7.
The calibration factors for the Calcium Scoring Mass Factor Patient (0018,9351) and Calcium Scoring Mass Factor Device (0018,9352) attributes are defined by the International Consortium for Multi-Detector CT Evaluation of Coronary Calcium, see McCollough, C.H. “A multi-institutional, multi-manufacturer, international standard for the quantification of coronary artery calcium using cardiac CT”.
Contains the attributes involved in the transformation of stored pixel values. Only a single Item shall be permitted in this sequence. The value b in relationship between stored values (SV) and the output units. Output units = m*SV + b. m in the equation specified by Rescale Intercept (0028,1052). Specifies the output units of Rescale Slope (0028,1053) and Rescale Intercept (0028,1052). See C.11.1.1.2 for further explanation. If Frame Type (0008,9007) Value 1 of this frame is ORIGINAL and Frame Type (0008,9007) Value 3 is not LOCALIZER, the value shall be HU (Hounsfield Units).
Specifies the units of the output of the Modality LUT or rescale operation. Defined Terms: OD = The number in the LUT represents thousands of optical density. That is, a value of 2140 represents an optical density of 2.140. HU = Hounsfield Units (CT) US = Unspecified Other values are permitted, but are not defined by the DICOM Standard.
Contains the attributes defining the data acquisition in a multiple X-Ray source system beyond the primary source. The primary X-Ray source is specified in the CT X-Ray Details Sequence. One or more items may be present. Peak kilo voltage output of the X-Ray generator used. Nominal X-Ray tube current in milliamperes. The diameter in mm of the region over which data were collected. Used nominal size of the focal spot in mm. Type of filter(s) inserted into the X-Ray beam. The X-Ray absorbing material used in the filter. Indication of the presence or absence of color information that may be used during rendering. See C.8.16.2.1.1 for a description and Enumerated Values.
Table C.8-132 PIXEL PRESENTATION ATTRIBUTE VALUES
Indication if geometric manipulations are possible with frames in the SOP Instance. See C.8.16.2.1.2 for a description and Enumerated Values.
The value of the Volumetric Properties attribute (0008,9206) allows applications doing geometric manipulations (e.g., MAX_IP or MPR or planning) to determine if the image is an appropriate candidate for an operation without having to know all the details of the generating application. Table C.8-133 specifies the Enumerated Values for the Volumetric Properties (0008,9206) attribute. Table C.8-133 VOLUMETRIC PROPERTIES ATTRIBUTE VALUES
Method used for volume calculations with frames in the SOP Instance. See C.8.16.2.1.3 for a description and Defined Terms.
The value of the Volume Based Calculation Technique attribute (0008,9207) shall be used to indicate the method used for calculating pixels based on geometry. Shall have a value of NONE when Value 1 of Image Type (0008,0008) or Value 1 of Frame Type (0008,9007) is ORIGINAL. Table C.8-134 specifies the Defined Terms for the Volume Based Calculation Technique (0008,9207) attribute. Table C.8-134 VOLUME BASED CALCULATION TECHNIQUE ATTRIBUTE VALUES
Source equipment that produced the Ophthalmic Photography Series. Enumerated Value: OP Image identification characteristics. See C.8.17.2.1.4 for specialization.
The Image Type attribute (0008,0008) (General Image Module, C.7.6.1) identifies important image characteristics in a multiple valued data element. For the Ophthalmic Photography Image IOD, Image Type is specified as a Type 1 attribute and further specialized as follows: a. Value 1 shall identify the Pixel Data Characteristics in accordance with Section C.7.6.1.1.2; Enumerated Values are: ORIGINAL and DERIVED;
A number that identifies this image. Number of samples (planes) in this image. Enumerated values: 1 or 3. See C.8.17.2.1.2 for further explanation.
Samples per Pixel (0028,0002) shall be 1 or 3. Cameras producing 2-color images are required to use a value of 3 for Samples per Pixel (0028,0002) and a value of 2 for Samples per Pixel Used (0028,0003). For 2-color images with a RGB Photometric Interpretation, the R and G channel shall be used and the B channel shall have all values set to zero. Note: In the case of Photometric Interpretations typically used for compression such as YBR_FULL_422, the encoding will be as if the RGB values were transformed to YCbCr.
The number of samples (planes) containing information. Enumerated value: 2. Required if different from Samples per Pixel (0028,0002). See section C.8.17.2.1.2 Specifies the intended interpretation of the pixel data. See section C.8.17.2.1.3 Data representation of the pixel samples. Enumerated value: 0 Indicates whether the pixel data are sent color-by-plane or color-by-pixel. Required if Samples per Pixel (0028,0002) has a value greater than 1. Enumerated value shall be 0 (color-by-pixel). Nominal physical distance at the focal plane (in the retina) between the center of each pixel, specified by a numeric pair - adjacent row spacing (delimiter) adjacent column spacing in mm. See 10.7.1.3 for further explanation of the value order. Note: These values are specified as nominal because the physical distance may vary across the field of the images and the lens correction is likely to be imperfect. Required when Acquisition Device Type Code Sequence (0022,0015) contains an item with the value (SRT, R-1021A,"Fundus Camera"). May be present otherwise. The time the image pixel data creation started. The date the image pixel data creation started. The date and time that the acquisition of data started. Note: The synchronization of this time with an external clock is specified in the synchronization Module in Acquisition Time Synchronized (0018,1800). Required if Image Type (0008,0008) Value 1 is ORIGINAL. May be present otherwise. A Sequence that identifies the Images that were used to derive this Image. Required if Image Type Value 1 is DERIVED. Zero or more items may be present in the sequence. See C.7.6.1.1.4 for further explanation.
If an Image is identified to be a Derived image (see C.7.6.1.1.2 Image Type), Source Image Sequence (0008,2112) is an optional list of Referenced SOP Class UID (0008,1150)/ Referenced SOP Instance UID (0008,1150) pairs that identify the source images used to create the Derived image. It may be used whether or not there is a description of the way the image was derived in Derivation Description (0008,2111) or Derivation Code Sequence (0008,9215). Note: Multiple Items may be present within Source Image Sequence (0008,2112), in which case either: a) those images were combined to make the derived image (e.g. multiple source images to make an MPR or MIP), or b) each of the items represents a step in the successive derivation of an image (e.g. when an image has had successive lossy compression steps applied to it), c) some combination of the above. The Purpose of Reference Code Sequence (0040,A170) and the Attributes within the referenced images themselves may be used to determine the history of the derivation, which is not otherwise explicitly specified.
Describes the purpose for which the reference is made, that is what role the source image or frame(s) played in the derivation of this image. Only a single Item shall be permitted in this sequence. Specifies whether an Image has undergone lossy compression. Enumerated Values: 00 = Image has NOT been subjected to lossy compression. 01 = Image has been subjected to lossy compression. See C.7.6.1.1.5
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
Describes the approximate lossy compression ratio(s) that have been applied to this image. See C.7.6.1.1.5 for further explanation. May be multivalued if successive lossy compression steps have been applied. Notes: 1. For example, a compression ratio of 30:1 would be described in this Attribute with a single value of 30. 2. For historical reasons, the lossy compression ratio should also be described in Derivation Description (0008,2111) Required if Lossy Image Compression (0028,2110) has a value of "01".
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
A label for the lossy compression method(s) that have been applied to this image. See C.7.6.1.1.5 for further explanation. May be multivalued if successive lossy compression steps have been applied; the value order shall correspond to the values of Lossy Image Compression Ratio (0028,2112). Required if Lossy Image Compression (0028,2110) has a value of "01". Note: For historical reasons, the lossy compression method should also be described in Derivation Description (0008,2111).
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
Specifies an identity transformation for the Presentation LUT, such that the output of all grayscale transformations defined in the IOD containing this Module are defined to be P-Values. Enumerated Values: IDENTITY - output is in P-Values. Required if Photometric Interpretation (0028,0004) is MONOCHROME2 Indicates whether a reference object (phantom) of known size is present in the image and was used for calibration. Enumerated Values: YES NO Indicates whether or not image contains sufficient burned in annotation to identify the patient and date the image was acquired. Enumerated Value: YES NO
Enumerated Values: YES NO Coded value for patient movement or orientation, which is the intent, and not necessarily the result, based on what the patient is capable of. Required if the value of Patient Eye Movement Commanded (0022,0005) is YES. A single item shall be present in this sequence. Laterality of object imaged (as described in Anatomic Region Sequence (0008,2218)) examined. Enumerated Values: R = right eye L = left eye B = both left and right eye Shall be consistent with any laterality information contained in Primary Anatomic Structure Modifier Sequence (0008,2230), if present. Note: Laterality (0020,0060) is a Series level Attribute and must be the same for all Images in the Series. Since most Ophthalmic Photographic Image studies contain images of both eyes, the series level attribute will rarely be present. The position of this image on the retina (as defined by a specified nomenclature; the nomenclature is implicit in the code used). Only a single Item shall be permitted in this sequence. Type of equipment that originally acquired the data used to create the images in this Series. Enumerated Values: OPT See section C.7.3.1.1.1 for further explanation. A number that identifies this Series. Uniquely identifies the Performed Procedure Step SOP Instance to which the Series is related (e.g. a Modality or General-Purpose Performed Procedure Step SOP Instance). The Sequence shall have one Item. Required if the Modality Performed Procedure Step SOP Class or General Purpose Performed Procedure Step SOP Class is supported. Image identification characteristics. Number of samples (planes) in this image. See C.7.6.3.1.1 for further explanation. Value shall be 1.
Samples per Pixel (0028,0002) is the number of separate planes in this image. One, three, and four image planes are defined. Other numbers of image planes are allowed, but their meaning is not defined by this Standard. For monochrome (gray scale) and palette color images, the number of planes is 1. For RGB and other three vector color models, the value of this attribute is 3. For four vector color models, the value of this attribute is 4. All image planes shall have the same number of Rows (0028,0010), Columns (0028,0011), Bits Allocated (0028,0100), Bits Stored (0028,0101), High Bit (0028,0102), Pixel Representation (0028,0103), and Pixel Aspect Ratio (0028,0034). The data in each pixel may be represented as a “Composite Pixel Code”. If Samples Per Pixel is one, the Composite Pixel Code is just the “n” bit pixel sample, where “n” = Bits Allocated. If Samples Per Pixel is greater than one, Composite Pixel Code is a “k” bit concatenation of samples, where “k” = Bits Allocated multiplied by Samples Per Pixel, and with the sample representing the vector color designated first in the Photometric Interpretation name comprising the most significant bits of the Composite Pixel Code, followed in order by the samples representing the next vector colors, with the sample representing the vector color designated last in the Photometric Interpretation name comprising the least significant bits of the Composite Pixel Code. For example, for Photometric Interpretation = “RGB”, the most significant “Bits Allocated” bits contain the Red sample, the next “Bits Allocated” bits contain the Green sample, and the least significant “Bits Allocated” bits contain the Blue sample.
The date and time that the acquisition of data started. Note: The synchronization of this time with an external clock is specified in the synchronization Module in Acquisition Time synchronized (0018,1800) . The scan time in seconds used to create all frames of an Ophthalmic Tomography image. Required if Image Type (0008,0008) Value 1 is ORIGINAL. May be present otherwise. A number identifying the single continuous gathering of data over a period of time which resulted in this image. Specifies the intended interpretation of the pixel data. Enumerated Value shall be: MONOCHROME2 Data representation of pixel samples. Enumerated Value shall be 0. Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated. Bits Allocated (0028,0100) shall be 8 or 16 Number of bits stored for each pixel sample. Each sample shall have the same number of bits stored. Bits Stored (0028,0101) shall be 8, 12 or 16 Most significant bit for pixel sample data. Each sample shall have the same high bit. High Bit (0028,0102) shall be one less than Bits Stored Specifies an identity transformation for the Presentation LUT, such that the output of all grayscale transformations defined in the IOD containing this Module are defined to be P-Values. Enumerated Values: IDENTITY - output is in P-Values. Specifies whether an Image has undergone lossy compression (at a point in its lifetime). Enumerated Values: 00 = Image has NOT been subjected to lossy compression. 01 = Image has been subjected to lossy compression. Once this tag has been set to 01 it shall not be reset. If this tag is empty, no information is explicitly available. See C.7.6.1.1.5
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
Describes the approximate lossy compression ratio(s) that have been applied to this image. Required when compression has been applied. See C.7.6.1.1.5 for further explanation. May be multivalued if successive lossy compression steps have been applied. Notes: 1. For example, a compression ratio of 30:1 would be described in this Attribute with a single value of 30. 2. For historical reasons, the lossy compression ratio should also be described in Derivation Description (0008,2111).
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
A label for the lossy compression method(s) that have been applied to this image. See C.7.6.1.1.5 for further explanation. May be multi-valued if successive lossy compression steps have been applied; the value order shall correspond to the values of Lossy Image Compression Ratio (0028,2112). Required if Lossy Image Compression (0028,2110) has a value of "01". Note: For historical reasons, the lossy compression method should also be described in Derivation Description (0008,2111).
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
Indicates whether or not image contains sufficient burned in annotation to identify the patient and date the image was acquired. Enumerated Value: NO Offset of the first frame in a multi-frame image of a concatenation. Value shall be 0. Identifier for one SOP Instance belonging to a concatenation. Value shall be 1. The number of SOP Instances sharing the same Concatenation UID (0020,9161). Value Shall be 1.
Axial length of the eye in mm. The horizontal field of view in degrees The refractive state of the imaged eye at the time of acquisition. Zero or one Item shall be present. Zero length means the refractive state was not measured. Sphere value in diopters Cylinder value in diopters Axis value in degrees Emmetropic magnification value (dimensionless). Zero length means the emmetropic magnification was not measured. Value of intraocular pressure in mmHg. Zero length means the pressure was not measured Enumerated Values: YES NO If this tag is empty, no information is available. Information about the agent administered. Required if the value of Pupil Dilated (0022,000D) is YES. Zero or more items may be present. Note: An empty sequence indicates that an agent was used for dilation, but the name was not entered. The actual agent administered to dilate the pupil. One item shall be present. The concentration of the agent. Units of measure for the Mydriatic Agent Concentration. Required if Mydriatic Agent Concentration (0022,004E) is present. One item shall be present. The degree of the dilation in mm. Required if the value of Pupil Dilated (0022,000D) is YES. Describes the type of acquisition device. A single item shall be present in the sequence. Filters used in the light source path. Zero or more items may be present in the sequence. Nominal pass-through wavelength of light path filter in nm Pass band of light path filter in nm. This Attribute has two Values. The first is the shorter and the second the longer wavelength relative to the peak. The values are for the - 3dB nominal (1/2 of peak) pass through intensity. One of the two Values may be zero length, in which case it is a cutoff filter. Type of detector used for creating this image. Defined terms: CCD = Charge Coupled Device CMOS = Complementary Metal Oxide Semiconductor PHOTO = Photodetector INT = Interferometer Wavelength of the illuminator in nm. Required if Acquisition Device Type Code Sequence (0022,0015) contains an item with the value (A-00FBE, SRT, "Optical Coherence Tomography Scanner"). May be present otherwise. Power of the illuminator in microwatts at corneal plane. Required if Acquisition Device Type Code Sequence (0022,0015) contains an item with the value (SRT, A-00FBE,"Optical Coherence Tomography Scanner"). May be present otherwise. Bandwidth of the illuminator in nm. Required if Acquisition Device Type Code Sequence (0022,0015) contains an item with the value (A-00FBE, SRT, "Optical Coherence Tomography Scanner"). May be present otherwise. The inherent limiting resolution in microns for depth of the acquisition equipment for high contrast objects for the data gathering and reconstruction technique chosen. If variable, the value at the center of the scanning volume. Required if Acquisition Device Type Code Sequence (0022,0015) contains an item with the value (A-00FBE, SRT, "Optical Coherence Tomography Scanner"). May be present otherwise. Maximum distortion in depth direction in % of Depth Spatial Resolution. Required if Acquisition Device Type Code Sequence (0022,0015) contains an item with the value (SRT, A-00FBE,"Optical Coherence Tomography Scanner"). May be present otherwise. The inherent limiting resolution in microns of the acquisition equipment in the direction of a row. Required if Acquisition Device Type Code Sequence (0022,0015) contains an item with the value (A-00FBE, SRT, "Optical Coherence Tomography Scanner"). May be present otherwise. Maximum distortion in along-scan direction in % of Along-scan Spatial Resolution. Required if Acquisition Device Type Code Sequence (0022,0015) contains an item with the value (A-00FBE, SRT, "Optical Coherence Tomography Scanner"). May be present otherwise. The inherent limiting resolution in microns of the acquisition equipment perpendicular to the slice. Required if Acquisition Device Type Code Sequence (0022,0015) contains an item with the value (A-00FBE, SRT, "Optical Coherence Tomography Scanner"). May be present otherwise. Maximum distortion in across-scan direction in % of cross-scan Spatial Resolution. Required if Acquisition Device Type Code Sequence (0022,0015) contains an item with the value (A-00FBE, SRT, "Optical Coherence Tomography Scanner"). May be present otherwise. Specifies the column locations for this frame in terms of locations on a referenced image. One or more items shall be present. Image coordinates for the points on the referenced image that correspond to the points on this frame. See section C.8.17.10.1.1. Relative position in microns signifying the location of a Transverse image in the z-axis. Required if Ophthalmic Image Orientation (0022,0039) is TRANSVERSE. Enumerated Values: LINEAR NONLINEAR TRANSVERSE Source equipment that produced the Stereometric Series. Enumerated Value: SMR Sequence of items identifying pairs of images. There shall be one or more items in this sequence. Stereo separation angle in degrees Horizontal displacement of instrument between left and right image in mm Horizontal displacement of right image relative to left image in pixels for optimal display. Offset of right image to right means positive value. Vertical displacement of right image relative to left image in pixels for optimal display. Offset of right image downwards means positive value. Rotation of right image relative to left image in degrees for optimal display. The rotation of the right image against the left image counterclockwise is positive, rotation around the center is assumed. Left Image of the Pair. Only one Item shall be present in this Sequence. Right Image of the Pair. Only one Item shall be present in this Sequence. Type of equipment that originally acquired the data used to create the images in this Series. Enumerated Values: XA RF See section C.7.3.1.1.1 for further explanation. A number that identifies this Series. Uniquely identifies the Performed Procedure Step SOP Instance to which the Series is related (e.g. a Modality or General-Purpose Performed Procedure Step SOP Instance). Only a single Item is permitted in this sequence. Required if the Modality Performed Procedure Step SOP Class, General Purpose Performed Procedure Step SOP Class is supported. Image identification characteristics. See C.8.19.2.1.1 for specialization.
The Image Type attribute identifies important image characteristics in a multiple valued data element. For X-Ray, Image Type is specialized as follows: a. Value 1 shall identify the Pixel Data Characteristics in accordance with Section C.7.6.1.1.2; Enumerated Values are: ORIGINAL and DERIVED; b. Value 2 shall identify the Patient Examination Characteristics in accordance with Section C.7.6.1.1.2; Enumerated Values are: PRIMARY and SECONDARY. Note: X-Ray images generally use PRIMARY value for images captured from patient exposure. c. Value 3 shall identify the image set in terms of the imaging planes. Enumerated Values are: d. Other Values are implementation specific (optional).
Identification of the plane used to acquire this image. Defined Terms: MONOPLANE PLANE A PLANE B Notes: 1. MONOPLANE may only be used for a single plane system 2. PLANE A and PLANE B must be used for two plane systems, independent if the acquisition is single plane or biplane. 3. The value has to be in accordance with Image Type (0008,0008) value 3. If this value is SINGLE PLANE all three Defined Term are applicable. Required if Image Type (0008,0008) Value 3 is not equal to UNDEFINED. A number identifying the single continuous gathering of data over a period of time that resulted in this image. The date and time that the acquisition of data that resulted in this image started. Note: The synchronization of this time with an external clock is specified in the Synchronization Module in Acquisition Time Synchronized (0018,1800). Number of bits allocated for each pixel sample. Each sample shall have the same number of bits allocated. Enumerated Values: 8 and 16. Number of bits stored for each pixel sample. Each sample shall have the same number of bits stored. Enumerated Values: 8 to 16. See C.8.19.2.1.2 for specialization.
Table C.8.X2-2 specifies the allowed combinations of Bits Allocated (0028,0100) and Bits Stored (0028,0101). Table C.8.19.2-2 ALLOWED COMBINATIONS OF ATTRIBUTE VALUES FOR BITS ALLOCATED AND BITS STORED
Most significant bit for pixel sample data. Each sample shall have the same high bit. Shall be one less than the value in Bits Stored (0028,0101). Number of samples (color planes) in this image shall have a value of 1. Data representation of the pixel samples. Shall have the value: 0000H = Unsigned Integer. Specifies the intended interpretation of the pixel data. Enumerated Values: MONOCHROME1 MONOCHROME2 User defined name of the protocol used to acquire this image. User defined description of the protocol used to acquire this image. Identifies any acquisition technique that was used during the acquisition of the image. Defined Terms: TOMO = Tomography CHASE = Bolus Chasing STEP = Stepping ROTA = Rotation Content Qualification Indicator Enumerated Values: PRODUCT RESEARCH SERVICE See C.8.13.2.1.1 for further explanation.
Content Qualification (0018,9004) shall have the value PRODUCT if the content (image or Spectroscopy data) was produced with approved hardware and software. It shall have the value RESEARCH or SERVICE if there is any doubt as to whether the content was produced with approved hardware and software. If data with Content Qualification (0018,9004) of RESEARCH or SERVICE is used to derive other content then it is expected that this derived content will also have Content Qualification (0018,9004) set to RESEARCH or SERVICE. The intent of this element is to allow annotation of an advisory message that indicates that this content may not be suitable for clinical interpretation.
Sequence that describes the orientation of the patient with respect to gravity. See C.8.11.5.1.2 for further explanation. Only a single Item shall be permitted in this Sequence. Required if Positioner Type (0018,1508) equals CARM and C-arm Positioner Tabletop Relationship (0018,9474) equals YES. May be present otherwise.
This Attribute is not related to Patient Orientation (0020,0020) and conveys a different concept entirely.
Patient Orientation Modifier. Required if needed to fully specify the orientation of the patient with respect to gravity. Only a single Item shall be permitted in this Sequence. Sequence that describes the orientation of the patient with respect to the head of the table. See Section C.8.4.6.1.3 for further explanation. Zero or one item shall be present in the sequence. Required if Positioner Type (0018,1508) equals CARM and C-arm Positioner Tabletop Relationship (0018,9474) equals YES. May be present otherwise.
Patient Gantry Relationship Code Sequence (0054,0414) is used to describe the patient direction within the gantry, such as head-first or feet-first. When imaging the extremities, these directions are related to normal anatomic position. Example: In normal anatomic position, the fingers point towards the feet.
Body thickness in mm at examination location perpendicular to the table top for this series. Notes: 1. This is intended for estimation of the thickness of the patient at the tabletop, not for precise calculation of the size of the object in the X-Ray beam (see Calculated Anatomy Thickness (0018,9452) attribute). 2. For example, used to estimate the value range of the Distance Object to Table Top (0018,9403) attribute. Indicates whether or not the image contains sufficient burned in annotation to identify the patient and date the image was acquired. Enumerated Values: NO Specifies whether an Image has undergone lossy compression. Enumerated Values: 00 = Image has NOT been subjected to lossy compression. 01 = Image has been subjected to lossy compression. See C.7.6.1.1.5 for further explanation.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
See C.7.6.1.1.5 for further explanation. Required if Lossy Image Compression (0028,2110) equals 01.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
A label for the lossy compression method(s) that have been applied to this image. See C.7.6.1.1.5 for further explanation. May be multi valued if successive lossy compression steps have been applied; the value order shall correspond to the values of Lossy Image Compression Ratio (0028,2112). Note: For historical reasons, the lossy compression method may also be described in Derivation Description (0008,2111). Required if Lossy Image Compression (0028,2110) equals 01.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
A sequence that identifies the SOP Class/Instance pairs of the corresponding plane for a Biplane acquisition device. Only a single Item shall be permitted in this Sequence. Required if Image Type (0008,0008) Value 3 is BIPLANE A or BIPLANE B. Full set of Composite SOP Instances referred to inside the Referenced Image Sequences of this SOP Instance. See C.8.13.2.1.2 for further explanation. One or more Items may be permitted in this sequence. Required if the Referenced Image Sequence (0008,1140) is present.
The intent of the Referenced Image Evidence Sequence (0008,9092) and Source Image Evidence Sequence (0008,9154) is to provide a list of all unique SOP Instances listed in the Referenced Image Sequence (0008,1140) and Source Image Sequence (0008,2112) attributes respectively.
Full set of Composite SOP Instances referred to inside the Source Image Sequences of this SOP Instance. See C.8.13.2.1.2 for further explanation. One or more Items may be permitted in this sequence. Required if the Source Image Sequence (0008,2112) is present.
The intent of the Referenced Image Evidence Sequence (0008,9092) and Source Image Evidence Sequence (0008,9154) is to provide a list of all unique SOP Instances listed in the Referenced Image Sequence (0008,1140) and Source Image Sequence (0008,2112) attributes respectively.
A sequence which provides reference to a set of non-image SOP Class/Instance pairs significantly related to this Image, including waveforms that may or may not be temporally synchronized with this image. One or more Items may be included in this sequence. Code describing the purpose of the reference to the SOP Instances. Only a single Item shall be permitted in this sequence. User-defined comments about the image. Indicates whether or not this image is a quality control or phantom image. Enumerated Values: YES NO If this Attribute is absent, then the image may or may not be a quality control or phantom image. This icon image is representative of the Image. Only a single Item shall be permitted in this Sequence. Specifies a predefined identity transformation for the Presentation LUT such that the output of all grayscale transformations, if any, are defined to be in P-Values. Enumerated Values: IDENTITY - output is in P-Values - shall be used if Photometric Interpretation (0028,0004) is MONOCHROME2 INVERSE - output after inversion is in P-Values - shall be used if Photometric Interpretation (0028,0004) is MONOCHROME1.
Average of the peak kilo voltage outputs of the X-Ray generator used for all frames. Identify the general level of X-Ray dose exposure. Enumerated values are: SC = low dose exposure generally corresponding to fluoroscopic settings (e.g. preparation for diagnostic quality image acquisition); GR = high dose for diagnostic quality image acquisition (also called digital spot or cine); Average of the nominal X-Ray tube currents in milliamperes for all frames. Required if Exposure in mAs (0018,9332) is not present. May be present otherwise. Duration of X-Ray exposure in milliseconds. See C.8.7.2.1.1. Required if Exposure in mAs (0018,9332) is not present. May be present otherwise.
Exposure time is the cumulative time the patient received X-Ray exposure during this image (Multi-frame image acquisition). Calculation is pulse width * number of frames.
The exposure expressed in milliampereseconds, for example calculated from Exposure Time and X-Ray Tube Current. Required if either Exposure Time in ms (0018,9328) or X-Ray Tube Current in mA (0018,9330) are not present. May be present otherwise. Average width of X-Ray pulse in msec. The time in seconds needed for the complete acquisition. See C.7.6.16.2.2.1 for further explanation
Figure C.7.6.16-2 shows the relationships among the various timing parameters used.
Specifies X-Ray radiation mode. Defined Terms: CONTINUOUS PULSED Nominal focal spot size in mm used to acquire this image. The primary material in the anode of the X-Ray source. Defined Terms: TUNGSTEN MOLYBDENUM RHODIUM Type of rectification used in the X-Ray generator. Defined Terms: SINGLE PHASE THREE PHASE CONST POTENTIAL Identifies with type of X-Ray receptor is used. Enumerated Values: IMG_INTENSIFIER DIGITAL_DETECTOR Physical distance measured at the receptor plane of the detector between the centers of each pixel specified by a numeric pair - row spacing value (delimiter) column spacing value in mm. See 10.7.1.3 for further explanation of the value order. Note: These values are the actual pixel spacing distances of the stored pixel values of an image. Distance in mm between the receptor plane and the detector housing. The direction of the distance is positive from receptor plane to X-Ray source. Note: 1. A negative value is allowed in the case of an image intensifier the receptor plane can be a virtual plane located outside the detector housing depending the magnification factor of the intensifier. A negative value is not applicable for the digital detector. 2. Used to calculate the pixel size of the plane in the patient when markers are used, and they are placed on the detector housing. Defined Terms: CARM COLUMN Notes: 1. The term CARM can apply to any positioner with 2 degrees of freedom of rotation of the X-Ray beam about the Imaging Subject. 2. The term COLUMN can apply to any positioner with 1 degree of freedom of rotation of the X-Ray beam about the Imaging Subject. Describes for C-arm positioner type systems if positioner and tabletop has the same geometrical reference system. Enumerated Values: YES NO Note: The value NO is intended for mobile systems where there is no table fixed to the system Required if Positioner Type (0018,1508) equals CARM. X-Ray dose, measured in dGy*cm*cm, to which the patient was exposed for the acquisition of this image only. Notes: 1. The sum of the Image Area Dose Product of all images of a Series or a Study may not result in the actual area dose product to which the patient was exposed. 2. This may be an estimated value based on assumptions about the patient's body size and habitus.
Physical diameter of the maximum active area X-Ray intensifier in mm. Note: This attribute does not specify the field of view. The attribute Field of View Dimension(s) in Float (0018,9461) is intended for this value. Shape of the active area used for acquiring this image. Enumerated Value: RECTANGLE ROUND HEXAGONAL Note: This may be different from the Field of View Shape (0018,1147), and should not be assumed to describe the stored image. Dimensions in mm of the active area used for acquiring this image. If Intensifier Active Shape (0018,9427) is: RECTANGLE: row dimension followed by column. ROUND: diameter. HEXAGONAL: diameter of the circle circumscribing the hexagon. Note: This may be different from the Field of View Dimension(s) in Float (0018,9461), and should not be assumed to describe the stored image. Dimensions of the physical detector measured in mm as a row size followed by a column size. Position of the Isocenter measured in physical detector elements as a row offset followed by a column offset from the TLHC of a rectangle circumscribing the physical detector area. Required if Isocenter Reference System Sequence (0018,9462) is present. A sequence that describes general characteristics of this frame. Only a single Item shall be permitted in this sequence. A text description of how this frame was derived. See C.8.7.1.1.5 for further explanation.
If an Image is identified to be a Derived image (see C.8.9.1.1.1 Image Type), Derivation Description (0008,2111) is an optional and implementation specific text description of the way the image was derived from an original image. As applied to X-Ray images, it may be used to describe derivation operations such as edge enhancement, temporal filtering, digital subtraction, or other linear and non-linear transformations.
A coded description of how this frame was derived. See C.7.6.1.1.3 for further explanation. One or more Items may be included in this Sequence. More than one Item indicates that successive derivation steps have been applied.
If an Image is identified to be a derived image (see C.7.6.1.1.2 Image Type), Derivation Description (0008,2111) and Derivation Code Sequence (0008,9215) describe the way in which the image was derived. They may be used whether or not the Source Image Sequence (0008,2112) is provided. They may also be used in cases when the Derived Image pixel data is not significantly changed from one of the source images and the SOP Instance UID of the Derived Image is the same as the one used for the source image. Notes: 1. Examples of Derived Images that would normally be expected to affect professional interpretation and would thus have a new UID include: a. images resulting from image processing of another image (e.g. unsharp masking), b. a multiplanar reformatted CT image, c. a DSA image derived by subtracting pixel values of one image from another. d. an image that has been decompressed after having been compressed with a lossy compression algorithm. To ensure that the user has the necessary information about the lossy compression, the approximate compression ratio may be included in Derivation Description (0008,2111). An example of a Derived Image that would normally not be expected to affect professional interpretation and thus would not require a new UID is an image that has been padded with additional rows and columns for more display purposes. 2. An image may be lossy compressed, e.g., for long term archive purposes, and its SOP Instance UID changed. PS3.4 provides a mechanism by which a query for the original image Instance may return a reference to the UID of the lossy compressed version of the image using the Alternate Representation Sequence (0008,3001). This allows an application processing a SOP Instance that references the original image UID, e.g., a Structured Report, to obtain a reference to an accessible version of the image even if the original SOP Instance is no longer available.
Indicates any visual processing performed on the frame prior to exchange. See Section C.8.7.1.1.3.
Acquisition Device Processing Description (0018,1400) provides some indication in human readable text of the digital processing on the images before exchange. Examples of this processing are: edge enhanced, subtracted, time filtered, gamma corrected, convolved (spatially filtered).
Code representing the device-specific processing associated with the frame (e.g. Organ Filtering code) Note: This Code is manufacturer specific but provides useful annotation information to the knowledgeable observer.
Sequence containing the field of view for this frame. One or more items may be included in this sequence. Shape of the Field of View, that is the image pixels stored in Pixel Data (7FE0,0010). Enumerated Values: RECTANGLE ROUND HEXAGONAL Dimensions in mm of the Field of View, that is the image pixels stored in Pixel Data (7FE0,0010). If Field of View Shape (0018,1147) is: RECTANGLE: row dimension followed by column. ROUND: diameter. HEXAGONAL: diameter of the circle circumscribing the hexagon. Offset of the TLHC of a rectangle circumscribing the Field of View, i.e., the image pixels stored in Pixel Data (7FE0,0010) before rotation or flipping, from the TLHC of the physical detector area measured in physical detector pixels as a row offset followed by a column offset. See C.8.11.4.1.1 for further explanation. Required if X-Ray Receptor Type (0018,9420) is present and equals DIGITAL_DETECTOR.
The relationship between the Physical Detector Area, the Active Detector Area, the Field of View (what is stored in the Pixel Data (7FE0,0010)), the Exposed Area (after X-Ray Collimation) and the Displayed Area is illustrated in the following diagrams. Note: Some of these Attributes relate the image data to manufacturer specific characteristics of the detector that may be used for quality control purposes, e.g. correlation of image artifacts with a detector defect map, analysis of noise performance, etc. The Displayed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the Display Shutter Module (see section C.7.6.11). If this Module is not present or supported, then the Displayed Area is equal to the Field of View. The Exposed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the X-Ray Collimator Module (see section C.8.7.3). For the Digital X-Ray IODs, the Field of View is usually rectangular in shape and the same size as the stored Pixel Data (7FE0,0010). The shape and size of the Field of View and the spacing of the pixels are defined by the following Attributes: - Field of View Shape (0018,1147), - Field of View Dimensions (0018,1149), - Imager Pixel Spacing (0018,1164), - Rows (0028,0010), - Columns (0028,0011) The following Attributes define the relationship of the Field of View to the Physical Detector Area: - Field of View Origin (0018,7030), - Field of View Rotation (0018,7032), - Field of View Horizontal Flip (0018,7034). For the Digital X-Ray IODs, the Active Area, i.e. that part of the detector matrix that was activated for this exposure, is usually rectangular in shape. The shape and size of the Active Area and the size and spacing of the detectors are defined by the following Attributes: - Detector Active Shape (0018,7024), - Detector Active Dimensions (0018,7026), - Detector Element Physical Size (0018,7020), - Detector Element Spacing (0018,7022). Notes: 1. The Detector Element Physical Size (0018,7020) and Detector Element Spacing (0018,7022) may be different if there are insensitive regions between each detector. 2. This model of description is not able to accurately describe multiple matrices of detectors that are “tiled” to produce a single image. The following optional Attribute defines the relationship of the Active Area to the Physical Detector Area: - Detector Active Origin (0018,7028). The relationship between detectors and stored image pixels is defined by Detector Binning (0018,701A) which specifies how many detectors, in each of the row and column directions, contribute to (are pooled or averaged to form) a single stored image pixel. Note: Detector Binning (0018,701A) may have values less than one if sub-sampling is used to derive an image with higher spatial resolution than the detector matrix. Figure C.8-14 Explanation of DX Detector Attributes Figure C.8-15 Explanation of DX Detector Attributes
Clockwise rotation in degrees of Field of View, i.e., the image pixels stored in Pixel Data (7FE0,0010), relative to the physical detector. Enumerated Values: 0, 90, 180, 270 See C.8.11.4.1.1 for further explanation.
The relationship between the Physical Detector Area, the Active Detector Area, the Field of View (what is stored in the Pixel Data (7FE0,0010)), the Exposed Area (after X-Ray Collimation) and the Displayed Area is illustrated in the following diagrams. Note: Some of these Attributes relate the image data to manufacturer specific characteristics of the detector that may be used for quality control purposes, e.g. correlation of image artifacts with a detector defect map, analysis of noise performance, etc. The Displayed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the Display Shutter Module (see section C.7.6.11). If this Module is not present or supported, then the Displayed Area is equal to the Field of View. The Exposed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the X-Ray Collimator Module (see section C.8.7.3). For the Digital X-Ray IODs, the Field of View is usually rectangular in shape and the same size as the stored Pixel Data (7FE0,0010). The shape and size of the Field of View and the spacing of the pixels are defined by the following Attributes: - Field of View Shape (0018,1147), - Field of View Dimensions (0018,1149), - Imager Pixel Spacing (0018,1164), - Rows (0028,0010), - Columns (0028,0011) The following Attributes define the relationship of the Field of View to the Physical Detector Area: - Field of View Origin (0018,7030), - Field of View Rotation (0018,7032), - Field of View Horizontal Flip (0018,7034). For the Digital X-Ray IODs, the Active Area, i.e. that part of the detector matrix that was activated for this exposure, is usually rectangular in shape. The shape and size of the Active Area and the size and spacing of the detectors are defined by the following Attributes: - Detector Active Shape (0018,7024), - Detector Active Dimensions (0018,7026), - Detector Element Physical Size (0018,7020), - Detector Element Spacing (0018,7022). Notes: 1. The Detector Element Physical Size (0018,7020) and Detector Element Spacing (0018,7022) may be different if there are insensitive regions between each detector. 2. This model of description is not able to accurately describe multiple matrices of detectors that are “tiled” to produce a single image. The following optional Attribute defines the relationship of the Active Area to the Physical Detector Area: - Detector Active Origin (0018,7028). The relationship between detectors and stored image pixels is defined by Detector Binning (0018,701A) which specifies how many detectors, in each of the row and column directions, contribute to (are pooled or averaged to form) a single stored image pixel. Note: Detector Binning (0018,701A) may have values less than one if sub-sampling is used to derive an image with higher spatial resolution than the detector matrix. Figure C.8-14 Explanation of DX Detector Attributes Figure C.8-15 Explanation of DX Detector Attributes
Whether or not a horizontal flip has been applied to the Field of View, i.e., the image pixels stored in Pixel Data (7FE0,0010), after rotation relative to the physical detector as described in Field of View Rotation (0018,7032). Enumerated Values: NO YES See C.8.11.4.1.1 for further explanation.
The relationship between the Physical Detector Area, the Active Detector Area, the Field of View (what is stored in the Pixel Data (7FE0,0010)), the Exposed Area (after X-Ray Collimation) and the Displayed Area is illustrated in the following diagrams. Note: Some of these Attributes relate the image data to manufacturer specific characteristics of the detector that may be used for quality control purposes, e.g. correlation of image artifacts with a detector defect map, analysis of noise performance, etc. The Displayed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the Display Shutter Module (see section C.7.6.11). If this Module is not present or supported, then the Displayed Area is equal to the Field of View. The Exposed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the X-Ray Collimator Module (see section C.8.7.3). For the Digital X-Ray IODs, the Field of View is usually rectangular in shape and the same size as the stored Pixel Data (7FE0,0010). The shape and size of the Field of View and the spacing of the pixels are defined by the following Attributes: - Field of View Shape (0018,1147), - Field of View Dimensions (0018,1149), - Imager Pixel Spacing (0018,1164), - Rows (0028,0010), - Columns (0028,0011) The following Attributes define the relationship of the Field of View to the Physical Detector Area: - Field of View Origin (0018,7030), - Field of View Rotation (0018,7032), - Field of View Horizontal Flip (0018,7034). For the Digital X-Ray IODs, the Active Area, i.e. that part of the detector matrix that was activated for this exposure, is usually rectangular in shape. The shape and size of the Active Area and the size and spacing of the detectors are defined by the following Attributes: - Detector Active Shape (0018,7024), - Detector Active Dimensions (0018,7026), - Detector Element Physical Size (0018,7020), - Detector Element Spacing (0018,7022). Notes: 1. The Detector Element Physical Size (0018,7020) and Detector Element Spacing (0018,7022) may be different if there are insensitive regions between each detector. 2. This model of description is not able to accurately describe multiple matrices of detectors that are “tiled” to produce a single image. The following optional Attribute defines the relationship of the Active Area to the Physical Detector Area: - Detector Active Origin (0018,7028). The relationship between detectors and stored image pixels is defined by Detector Binning (0018,701A) which specifies how many detectors, in each of the row and column directions, contribute to (are pooled or averaged to form) a single stored image pixel. Note: Detector Binning (0018,701A) may have values less than one if sub-sampling is used to derive an image with higher spatial resolution than the detector matrix. Figure C.8-14 Explanation of DX Detector Attributes Figure C.8-15 Explanation of DX Detector Attributes
Manufacturer defined description of the field of view selected during acquisition.
Sequence containing the Exposure Control Sensing Region for this frame. One or more items may be included in this sequence. Shape of the Exposure Control Sensing Region. Enumerated Values: RECTANGULAR CIRCULAR POLYGONAL Required if Exposure Control Sensing Region Shape (0018,9435) is RECTANGULAR. Location of the left edge of the rectangular Exposure Control Sensing Region expressed as effective pixel column. See C.8.19.6.3.1.
The Exposure Control Sensing Region Left Vertical Edge (0018,9436), Exposure Control Sensing Region Right Vertical Edge (0018,9437), Exposure Control Sensing Region Upper Horizontal Edge (0018,9438), Exposure Control Sensing Region Lower Horizontal Edge (0018,9439) and Center of Circular Exposure Control Sensing Region (0018,9440) may have a negative value when the point defined by the attribute lies outside the left or upper border of the pixel data matrix. The top left pixel of the image has a pixel row and column value of 1.
Required if Exposure Control Sensing Region Shape (0018,9435) is RECTANGULAR. Location of the right edge of the rectangular Exposure Control Sensing Region expressed as effective pixel column. See C.8.19.6.3.1.
The Exposure Control Sensing Region Left Vertical Edge (0018,9436), Exposure Control Sensing Region Right Vertical Edge (0018,9437), Exposure Control Sensing Region Upper Horizontal Edge (0018,9438), Exposure Control Sensing Region Lower Horizontal Edge (0018,9439) and Center of Circular Exposure Control Sensing Region (0018,9440) may have a negative value when the point defined by the attribute lies outside the left or upper border of the pixel data matrix. The top left pixel of the image has a pixel row and column value of 1.
Required if Exposure Control Sensing Region Shape (0018,9435) is RECTANGULAR. Location of the upper edge of the rectangular Exposure Control Sensing Region expressed as effective pixel row. See C.8.19.6.3.1.
The Exposure Control Sensing Region Left Vertical Edge (0018,9436), Exposure Control Sensing Region Right Vertical Edge (0018,9437), Exposure Control Sensing Region Upper Horizontal Edge (0018,9438), Exposure Control Sensing Region Lower Horizontal Edge (0018,9439) and Center of Circular Exposure Control Sensing Region (0018,9440) may have a negative value when the point defined by the attribute lies outside the left or upper border of the pixel data matrix. The top left pixel of the image has a pixel row and column value of 1.
Required if Exposure Control Sensing Region Shape (0018,9435) is RECTANGULAR. Location of the lower edge of the rectangular Exposure Control Sensing Region expressed as effective pixel row. See C.8.19.6.3.1.
The Exposure Control Sensing Region Left Vertical Edge (0018,9436), Exposure Control Sensing Region Right Vertical Edge (0018,9437), Exposure Control Sensing Region Upper Horizontal Edge (0018,9438), Exposure Control Sensing Region Lower Horizontal Edge (0018,9439) and Center of Circular Exposure Control Sensing Region (0018,9440) may have a negative value when the point defined by the attribute lies outside the left or upper border of the pixel data matrix. The top left pixel of the image has a pixel row and column value of 1.
Required if Exposure Control Sensing Region Shape (0018,9435) is CIRCULAR. Location of the center of the circular Exposure Control Sensing Region expressed as effective pixel row and column. See C.8.19.6.3.1.
The Exposure Control Sensing Region Left Vertical Edge (0018,9436), Exposure Control Sensing Region Right Vertical Edge (0018,9437), Exposure Control Sensing Region Upper Horizontal Edge (0018,9438), Exposure Control Sensing Region Lower Horizontal Edge (0018,9439) and Center of Circular Exposure Control Sensing Region (0018,9440) may have a negative value when the point defined by the attribute lies outside the left or upper border of the pixel data matrix. The top left pixel of the image has a pixel row and column value of 1.
Required if Exposure Control Sensing Region Shape (0018,9435) is CIRCULAR. Radius of the circular Exposure Control Sensing Region expressed as effective number of pixels along the row direction. See C.8.19.6.3.1.
The Exposure Control Sensing Region Left Vertical Edge (0018,9436), Exposure Control Sensing Region Right Vertical Edge (0018,9437), Exposure Control Sensing Region Upper Horizontal Edge (0018,9438), Exposure Control Sensing Region Lower Horizontal Edge (0018,9439) and Center of Circular Exposure Control Sensing Region (0018,9440) may have a negative value when the point defined by the attribute lies outside the left or upper border of the pixel data matrix. The top left pixel of the image has a pixel row and column value of 1.
Required if Exposure Control Sensing Region Shape (0018,9435) is POLYGONAL. Multiple Values where the first set of two values are: row of the origin vertex; column of the origin vertex. Two or more pairs of values follow and are the effective pixel row and column coordinates of the other vertices of the polygon Exposure Control Sensing Region. Polygon Exposure Control Sensing Regions are implicitly closed from the last vertex to the origin vertex and all edges shall be non-intersecting except at the vertices. See C.8.19.6.3.1.
The Exposure Control Sensing Region Left Vertical Edge (0018,9436), Exposure Control Sensing Region Right Vertical Edge (0018,9437), Exposure Control Sensing Region Upper Horizontal Edge (0018,9438), Exposure Control Sensing Region Lower Horizontal Edge (0018,9439) and Center of Circular Exposure Control Sensing Region (0018,9440) may have a negative value when the point defined by the attribute lies outside the left or upper border of the pixel data matrix. The top left pixel of the image has a pixel row and column value of 1.
Sequence containing the pixel data properties for this frame. Only a single Item shall be permitted in this sequence. The relationship between the Pixel and the X-Ray beam intensity. See C.8.19.6.4.1.
Pixel Intensity Relationship (0028,1040) shall identify the relationship of the pixel values to the X-Ray beam intensity. Defined terms are:
The sign of the relationship between the Pixel sample values stored in Pixel Data (7FE0,0010) and the X-Ray beam intensity. Enumerated Values: 1 = Lower pixel values correspond to less X-Ray beam intensity -1 = Higher pixel values correspond to less X-Ray beam intensity See C.8.11.3.1.2 for further explanation.
Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041) describe how the stored pixel values in Pixel Data (7FE0,0010) are related to the X-Ray beam intensity incident on the detector. They do not define a transformation intended to be applied to the pixel data for presentation. Note: For example, if Pixel Intensity Relationship (0028,1040) is LIN and Pixel Intensity Relationship Sign (0028,1041) is -1, then lower values of Pixel Data (7FE0,0010) indicate higher X-Ray beam intensities corresponding to less radiographically dense regions projected on the image such as through air, and higher values of Pixel Data (7FE0,0010) indicate lower X-Ray beam intensities corresponding to more radiographically dense regions projected on the image such as through bone and radio-opaque contrast agents. The transformation to be applied to the pixel data for presentation is defined by the successive application of the conceptual Modality LUT, the VOI Attributes and the conceptual Presentation LUT. This shall result in the output of P-Values. Rescale Slope (0028,1053) and Rescale Intercept (0028,1052) define a linear subset of a conceptual Modality LUT transformation. For IODs that include this Module, these Attributes define an identity transformation. IODs that include the DX Image Module shall not include the Modality LUT Module. The Presentation LUT Shape (2050,0020) defines a subset of a conceptual Presentation LUT. For IODs that include this Module, this Attribute defines an identity transformation or inverse identity transformation. IODs that include the DX Image Module shall not include the Presentation LUT Module. Photometric Interpretation (0028,0004) indicates whether lower values that are the output of the VOI Attributes should be displayed as darker or lighter. Since the output of the equivalent of a conceptual Presentation LUT is in P-Values, which are defined in PS 3.14 such that lower values correspond to lower luminance levels, then the definition of the Presentation LUT Shape (2050,0020), otherwise intended to be an identity transformation, must take into account the effect of the value specified for Photometric Interpretation (0028,0004). Note: Regardless of the values of Pixel Intensity Relationship (0028,1040) and Pixel Intensity Relationship Sign (0028,1041), the grayscale transformations to be applied to the Pixel Data (7FE0,0010) are defined by the equivalent of the Modality LUT (Rescale Slope (0028,1053) and Rescale Intercept (0028,1052)), Value of Interest Attributes, Photometric Interpretation (0028,0004) and the equivalent of the Presentation LUT (Presentation LUT Shape (2050,0020)). However, the combination of the grayscale transformations and the description of the pixel intensity relationship, together define whether, for example, air is expected to be displayed as black or white.
Geometrical characteristics of the pixel data to indicate whether pixel spacing is uniform for all pixels or not. Enumerated Values: UNIFORM NON_UNIFORM The percentage of the maximum deviation of the pixel spacing values of images for which the geometric properties are non-uniform. Note: This attribute may be used to judge the result of measurements, 3D reconstructions, etc. Required if Geometrical Properties (0028,9444) equals NON_UNIFORM. The type or a combination of types of image processing applied to the pixel data before being stored. Defined Terms: DIGITAL_SUBTR HIGH_PASS_FILTER LOW_PASS_FILTER MULTI_BAND_FLTR FRAME_AVERAGING NONE
Sequence containing the detector properties for this frame. Only a single Item shall be permitted in this sequence. Time in mSec that the detector is active during acquisition of this image. Note: This activation window overlaps the time of the X-Ray exposure as defined by Exposure Time in ms (0018,9328) and Detector Activation Offset From Exposure (0018,7016). Offset time in mSec that the detector becomes active after the X-Ray beam is turned on during acquisition of this image. May be negative. Sequence containing the calibration flag for this frame. Only a single Item shall be permitted in this sequence. Indicates whether a reference object (phantom) of known size is present in the frame and was used for calibration. Enumerated Values: YES NO Note: Device is identified using the Device module. See C.7.6.12.
Table C.7-18 describes the Attributes of devices or calibration objects (e.g., catheters, markers, baskets) that are associated with a study and/or image. Table C.7-18 DEVICE MODULE ATTRIBUTES
Sequence containing object thickness for this frame. Only a single Item shall be permitted in this sequence. The physical thickness in mm of the anatomic region of interest as specified in the Anatomic Region Sequence (0008,2218) in the direction of the center of the beam. Note: The value takes in account the position relative to object and the X-Ray source - detector axis. Sequence containing the acquisition parameters for this frame. Only a single Item shall be permitted in this sequence. Exact peak kilo voltage output of the X-Ray generator used for this frame. Exact Nominal X-Ray tube current in milliamperes applied during the Acquisition Duration (0018,9220) for this frame. A sequence that describes the geometrical position of the patient relative to the equipment. Only a single Item shall be permitted in this sequence. Distance between the anatomic region of interest of observation and table top in mm. Notes: 1.This value is always positive, the object is assumed to be above the table. 2.The value of this attribute is depending on the patient position on the tabletop (supine, left or right decubitus, etc.) Physical distance within the anatomic region of interest in the center of the beam and perpendicular to the beam between the center of each pixel, specified by a numeric pair adjacent row spacing (delimiter) adjacent column spacing in mm. See C.8.19.6.9.2. See 10.7.1.3 for further explanation of the value order. Required if Distance Object to Table Top (0018,9403) is not empty. Note: This value is provided besides the values that are the input parameters of the calibration algorithm.
The value provided for the Beam Angle (0018,9449) attribute shall correspond to the other attribute values within this module and according to the mathematic terms listed in section C.8.19.6.9.1. The terms listed will result in infinite result when used with 90-degree beam angles. It is outside the scope of this Standard to define reasonable limits for single input values in the above-mentioned terms, or to define the mathematical accuracy of applications using those terms. Note: It may be reasonable to limit automatic calculations to a narrow range of +/- 60 degrees for Beam Angle and inform users about possible deviations in the calibration result when exceeding such range limits.
The distance of the top of the patient table to the center of rotation of the source (i.e. the isocenter) in mm. A positive value indicates that the tabletop is below the isocenter. Note: All the distances are measured perpendicular to the Table Top plane. Required if Image Type (0008,0008) Value 1 is ORIGINAL, may be present otherwise. The equipment related angle in degrees of the X-Ray beam relative to the perpendicular to the tabletop plane. An angle from 0 to +90 degrees indicates that the X-Ray source is below the table. The valid range is 0 to +180 degrees. Required if Image Type (0008,0008) Value 1 is ORIGINAL, may be present otherwise.
A sequence that describes the geometrical position of the positioner. Only a single Item shall be permitted in this sequence. Position of the X-Ray Image Intensifier about the patient from the RAO to LAO direction where movement from RAO to vertical is positive. See C.8.7.5.1.2. Required if Positioner Type (0018,1508) equals CARM.
The definitions of Positioner Angles shall be with respect to the patient as illustrated in Figures C.8-11 and C.8-12 Zero degree is referenced to the origin perpendicular to the patient's chest. The Positioner Primary Angle definition is like longitude (in the equatorial plan); the Positioner Secondary Angle definition is like latitude (in the sagittal plane). The Positioner Angle attributes apply to the first frame of a multi-frame image. The valid range of Primary Positioner Angle is -180 to +180 degrees and the Secondary Positioner Angle range is -90 to + 90 degrees. The Patient Plane is defined by the isocenter of the imaging device and slices through the patient such that it is perpendicular to the sagittal plane of the body. The Primary Axis of rotation is defined at the intersection of the Patient Plane and of the Sagittal Plane. The Positioner Primary Angle is defined in the transaxial plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest and + 90 degrees at the Patient left hand side (LAO) and -90 at the Patient right hand side (RAO). The valid range of Primary Positioner Angle is -180 to +180 degrees. The Secondary Axis is in the Patient Plane and is perpendicular to the Primary Axis at the isocenter. The Positioner Secondary Angle is defined in the Sagittal Plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest. +90 degrees corresponds to the cranial direction. The Secondary Positioner Angle range is -90 to + 90 degrees. At a 0 angle for both the Primary Angle (0018,1510) and Secondary Angle (0018,1511), the patient faces the Image Intensifier. The Positioner Primary Angle (0018,1510) and Secondary Angle (0018,1511) apply to the first frame of a multi-frame image. Figure C.8-11 Positioner Primary Angle Figure C.8-12 Positioner Secondary Angle
Position of the X-Ray Image Intensifier about the patient from the CAU to CRA direction where movement from CAU to vertical is positive. See C.8.7.5.1.2 Required if Positioner Type (0018,1508) equals CARM.
The definitions of Positioner Angles shall be with respect to the patient as illustrated in Figures C.8-11 and C.8-12 Zero degree is referenced to the origin perpendicular to the patient's chest. The Positioner Primary Angle definition is like longitude (in the equatorial plan); the Positioner Secondary Angle definition is like latitude (in the sagittal plane). The Positioner Angle attributes apply to the first frame of a multi-frame image. The valid range of Primary Positioner Angle is -180 to +180 degrees and the Secondary Positioner Angle range is -90 to + 90 degrees. The Patient Plane is defined by the isocenter of the imaging device and slices through the patient such that it is perpendicular to the sagittal plane of the body. The Primary Axis of rotation is defined at the intersection of the Patient Plane and of the Sagittal Plane. The Positioner Primary Angle is defined in the transaxial plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest and + 90 degrees at the Patient left hand side (LAO) and -90 at the Patient right hand side (RAO). The valid range of Primary Positioner Angle is -180 to +180 degrees. The Secondary Axis is in the Patient Plane and is perpendicular to the Primary Axis at the isocenter. The Positioner Secondary Angle is defined in the Sagittal Plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest. +90 degrees corresponds to the cranial direction. The Secondary Positioner Angle range is -90 to + 90 degrees. At a 0 angle for both the Primary Angle (0018,1510) and Secondary Angle (0018,1511), the patient faces the Image Intensifier. The Positioner Primary Angle (0018,1510) and Secondary Angle (0018,1511) apply to the first frame of a multi-frame image. Figure C.8-11 Positioner Primary Angle Figure C.8-12 Positioner Secondary Angle
Angle of the X-Ray beam in degree relative to an orthogonal axis to the detector plane. Positive values indicate that the tilt is towards the head of the patient. Notes: 1. The detector plane is assumed to be parallel to the table plane 2. This attribute differentiates form the attribute Column Angulation (0018,1450) by using the patient based coordinate system instead of the equipment based coordinate system. Required if Positioner Type (0018,1508) equals COLUMN.
A sequence that describes the geometrical position of the table top. Only a single Item shall be permitted in this sequence. Table Top Vertical position with respect to an arbitrary chosen reference by the equipment in (mm). Table motion downwards is positive Table Top Longitudinal position with respect to an arbitrary chosen reference by the equipment in (mm). Table motion towards LAO is positive assuming that the patient is positioned supine and its head is in normal position. Table Top Lateral position with respect to an arbitrary chosen reference by the equipment in (mm). Table motion towards CRA is positive assuming that the patient is positioned supine and its head is in normal position. Rotation of the table in the horizontal plane (clockwise when looking from above the table). Angle of the head-feet axis of the table in degrees relative to the horizontal plane. Positive values indicate that the head of the table is upwards. Angle of the left-right axis of the table in degrees relative to the horizontal plane. Positive values indicate that the left of the table is upwards. A sequence that describes the collimator shape. Only a single Item shall be permitted in this sequence. Shape(s) of the collimator. Enumerated Values: RECTANGULAR CIRCULAR POLYGONAL This multi-valued Attribute shall contain at most one of each Enumerated Value. Required if Collimator Shape (0018,1700) is RECTANGULAR. Location of the left edge of the rectangular collimator expressed as effective pixel column. See C.8.7.3.1.1 and C.8.19.6.12.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is RECTANGULAR. Location of the right edge of the rectangular collimator expressed as effective pixel column. See C.8.7.3.1.1 and C.8.19.6.12.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is RECTANGULAR. Location of the upper edge of the rectangular collimator expressed as effective pixel row. See C.8.7.3.1.1 and C.8.19.6.12.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is RECTANGULAR. Location of the lower edge of the rectangular collimator expressed as effective pixel row. See C.8.7.3.1.1 and C.8.19.6.12.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is CIRCULAR. Location of the center of the circular collimator expressed as effective pixel row and column. See C.8.7.3.1.1 and C.8.19.6.12.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is CIRCULAR. Radius of the circular collimator expressed as effective number of pixels along the row direction. See C.8.7.3.1.1 and C.8.19.6.12.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is POLYGONAL. Multiple Values where the first set of two values are: row of the origin vertex; column of the origin vertex. Two or more pairs of values follow and are the effective pixel row and column coordinates of the other vertices of the polygon collimator. Polygon collimators are implicitly closed from the last vertex to the origin vertex and all edges shall be non-intersecting except at the vertices. See C.8.19.6.12.1.
The top left pixel of the image has a pixel row and column value of 1.
A sequence that describes the Isocenter Reference Coordinate System (O, X, Y, Z). Only a single Item shall be permitted in this sequence. Position of the X-Ray center beam in the isocenter reference system in the X direction (deg). See C.8.19.6.13.1.2 for further explanation.
The positioner coordinate system (Op, Xp, Yp, Zp) is defined as follows:
Position of the X-Ray center beam in the isocenter reference system in the Z direction (deg). See C.8.19.6.13.1.2 for further explanation.
The positioner coordinate system (Op, Xp, Yp, Zp) is defined as follows:
Rotation of the X-Ray detector plane (deg). See C.8.19.6.13.1.2 for further explanation.
The positioner coordinate system (Op, Xp, Yp, Zp) is defined as follows:
X position of the Table Reference Point with respect to the Isocenter (mm). See C.8.19.6.13.1.3 for further explanation.
The table coordinate system (Ot, Xt, Yt, Zt) is defined as follows:
Y position of the Table Reference Point with respect to the Isocenter (mm). See C.8.19.6.13.1.3 for further explanation.
The table coordinate system (Ot, Xt, Yt, Zt) is defined as follows:
Z position of the Table Reference Point with respect to the Isocenter (mm). See C.8.19.6.13.1.3 for further explanation.
The table coordinate system (Ot, Xt, Yt, Zt) is defined as follows:
Rotation of the table in the horizontal plane. See C.8.19.6.13.1.3 for further explanation.
The table coordinate system (Ot, Xt, Yt, Zt) is defined as follows:
Angle of the head-feet axis of the table in degrees relative to the horizontal plane. See C.8.19.6.13.1.3 for further explanation.
The table coordinate system (Ot, Xt, Yt, Zt) is defined as follows:
Angle of the left-right axis of the table in degrees relative to the horizontal plane. See C.8.19.6.13.1.3 for further explanation.
The table coordinate system (Ot, Xt, Yt, Zt) is defined as follows:
Sequence containing the geometric properties for this frame. Only a single Item shall be permitted in this sequence. Distance from source to isocenter in mm. Distance from source to receptor plane perpendicular to the receptor plane in mm. Note: This value is traditionally referred to as Source Image Receptor Distance (SID). Describes the preferred playback sequencing for a multi-frame image. Enumerated Values: 0 = Looping (1,2...n,1,2,...n,1,2,....n,...) 1 = Sweeping (1,2,...n,n -1,...2,1,2,...n,...) Sequence that specifies the display frame rate of a selected set of frames. The Items are ordered in increasing frame number. The range of the frames may not overlap and the ranges shall be adjacent. One or more items may be included. The Frame Number of the first frame of the set of frames to be displayed in this Item. The Frame Number of the last frame of the set of frames to be displayed in this Item. A flag indicating that the range of frames in this item may be skipped. Defined Terms: DISPLAY SKIP Recommended rate at which the frames of this Item should be displayed in frames/second. Specifies the recommended viewing protocol(s). Defined terms: SUB = subtraction with mask images NAT = native viewing of image as stored Note: If an implementation does not recognize the defined term for Recommended Viewing Mode (0028,1090), reverting to native display mode is recommended. Edge enhancement filter percentage that is recommended by the pixel data creator as filter presetting for display purposes. The value of 100% corresponds to the maximum filter strength that can be applied by a specific application displaying the image. Modality Type Enumerated Value: SEG A number that identifies this Series Uniquely identifies the Performed Procedure Step SOP Instance to which the Series is related (e.g. a Modality or General-Purpose Performed Procedure Step SOP). Only a single Item is permitted in this sequence. Required if the SOP Instance was created in a workflow managed with the Modality Performed Procedure Step SOP Class or General Purpose Performed Procedure Step SOP Class. Value 1 shall be DERIVED. Value 2 shall be PRIMARY. No other values shall be present. Enumerated Values: 1 Enumerated Values: MONOCHROME2 Enumerated Values: 0 If Segmentation Type (0062,0001) is BINARY, shall be 1. Otherwise it shall be 8. See Section C.8.20.2.1.
As a consequence of the enumerated Bits Allocated and Bits Stored attribute values, single bit pixels shall be packed 8 to a byte as defined by the encoding rules in PS 3.5.
If Segmentation Type (0062,0001) is BINARY, shall be 1. Otherwise it shall be 8. See Section C.8.20.2.1.
As a consequence of the enumerated Bits Allocated and Bits Stored attribute values, single bit pixels shall be packed 8 to a byte as defined by the encoding rules in PS 3.5.
If Segmentation Type (0062,0001) is BINARY, shall be 0. Otherwise it shall be 7. See Section C.8.20.2.1.
As a consequence of the enumerated Bits Allocated and Bits Stored attribute values, single bit pixels shall be packed 8 to a byte as defined by the encoding rules in PS 3.5.
Specifies whether an Image has undergone lossy compression. Enumerated Values: 00 = Image has NOT been subjected to lossy compression. 01 = Image has been subjected to lossy compression. See Section C.8.20.2.2
If Lossy Image Compression (0028,2110) in any of the source images is “01”, the value shall be “01” for the Segmentation instance. The process of segmentation itself is defined not to be lossy compression, even though it involves loss. If the Segmentation instance is encoded using a lossy compression transfer syntax, then the value shall be set to “01”. Notes: It is not advisable to lossy compress a Segmentation SOP Instance. In particular, a binary segmentation should not be lossy compressed.
Describes the approximate lossy compression ratio(s) that have been applied to this image. See C.7.6.1.1.5 for further explanation. May be multivalued if successive lossy compression steps have been applied. Notes: 1. For example, a compression ratio of 30:1 would be described in this Attribute with a single value of 30. 2. For historical reasons, the lossy compression ratio may also be described in Derivation Description (0008,2111). Required if present in the source images or this IOD instance has been compressed.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
A label for the lossy compression method(s) that have been applied to this image. See C.7.6.1.1.5 for further explanation. May be multivalued if successive lossy compression steps have been applied; the value order shall correspond to the values of Lossy Image Compression Ratio (0028,2112). Note: For historical reasons, the lossy compression method may also be described in Derivation Description (0008,2111). Required if present in the source images or this IOD instance has been compressed. See section C.8.20.2.2.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
The type of encoding used to indicate the presence of the segmented property at a pixel/voxel location. Enumerated Values are: BINARY FRACTIONAL See section C.8.20.2.3. For fractional segmentation encoding, the meaning of the fractional value. Enumerated Values are: PROBABILITY OCCUPANCY Required if Segmentation Type (0062,0001) is FRACTIONAL. See section C.8.20.2.3. Specifies the value that represents 100%. There shall be no values in Pixel Data (7FE0,0010) greater than this value. Required if Segmentation Type (0062,0001) is FRACTIONAL. Describes the segments that are contained within the data. One or more items shall be present. Identification number of the segment. The value of Segment Number (0062,0004) shall be unique within the Segmentation instance in which it is created. See C.8.20.2.4.
Segment Number (0062,0004) shall be unique within each instance, start at a value of 1, and increase monotonically by 1.
User-defined label identifying this segment. This may be the same as the Code Meaning (0008,0104) of the Segmented Property Type Code Sequence (0062,000F). User-defined description for this segment. Type of algorithm used to generate the segment. Enumerated Values are: AUTOMATIC: calculated segment SEMIAUTOMATIC: calculated segment with user assistance MANUAL: user-entered segment Name of algorithm used to generate the segment. Required if Segment Algorithm Type (0062,0008) is not MANUAL. Sequence defining the general category of this segment. This sequence shall contain a single item. Sequence defining the specific property type of this segment. This sequence shall contain a single item. A default single gray unsigned value in which it is recommended that the maximum pixel value in this segment be rendered on a monochrome display. The units are specified in P-Values from a minimum of 0000H (black) up to a maximum of FFFFH (white). Note: The maximum P-Value for this Attribute may be different from the maximum P-Value from the output of the Presentation LUT, which may be less than 16 bits in depth. A default triplet value in which it is recommended that segment be rendered on a color display. The units are specified in PCS-Values, and the value is encoded as CIELab. See C.10.7.1.1.
Attributes such as Graphic Layer Recommended Display CIELab Value (0070,0401) consist of three unsigned short values:
Identifies the characteristics of this frame. Only a single Item shall be permitted in this sequence. Uniquely identifies the segment described in the Segment Sequence (0062,0002) by reference to the Segment Number (0062,0004). Referenced Segment Number (0062,000B) shall not be multi-valued. Image identification characteristics. See C.8.21.1.1.1 for specialization.
In addition to the requirements specified in C.8.16.1 Image Type, the following additional requirements and Defined Terms are specified.
Number of bits allocated for each voxel sample. Each sample shall have the same number of bits allocated. Enumerated Values: 8 and 16. Number of bits stored for each voxel sample. Each sample shall have the same number of bits stored. Enumerated Values: 8 to16. Most significant bit for pixel sample data. Each sample shall have the same high bit. Shall be one less than the value in Bits Stored (0028,0101). Number of samples (color planes) in this image shall have a value of 1. Specifies the intended interpretation of the voxel data. Enumerated Values: MONOCHROME2 Content Qualification Indicator Enumerated Values: PRODUCT RESEARCH SERVICE See C.8.13.2.1.1 for further explanation.
Content Qualification (0018,9004) shall have the value PRODUCT if the content (image or Spectroscopy data) was produced with approved hardware and software. It shall have the value RESEARCH or SERVICE if there is any doubt as to whether the content was produced with approved hardware and software. If data with Content Qualification (0018,9004) of RESEARCH or SERVICE is used to derive other content then it is expected that this derived content will also have Content Qualification (0018,9004) set to RESEARCH or SERVICE. The intent of this element is to allow annotation of an advisory message that indicates that this content may not be suitable for clinical interpretation.
Indicates whether or not the image contains sufficient burned in annotation to identify the patient and date the image was acquired. Enumerated Values: NO Specifies whether an Image has undergone lossy compression. Enumerated Values: 00 = Image has NOT been subjected to lossy compression. 01 = Image has been subjected to lossy compression. See C.7.6.1.1.5 for further explanation.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
See C.7.6.1.1.5 for further explanation. Required if Lossy Image Compression (0028,2110) equals 01.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
A label for the lossy compression method(s) that have been applied to this image. See C.7.6.1.1.5 for further explanation. May be multi-valued if successive lossy compression steps have been applied; the value order shall correspond to the values of Lossy Image Compression Ratio (0028,2112). Note: For historical reasons, the lossy compression method may also be described in Derivation Description (0008,2111). Required if Lossy Image Compression (0028,2110) equals 01.
The Attribute Lossy Image Compression (0028,2110) conveys that the Image has undergone lossy compression. It provides a means to record that the Image has been compressed (at a point in its lifetime) with a lossy algorithm and changes have been introduced into the pixel data. Once the value has been set to “01”, it shall not be reset. Note: If an image is compressed with a lossy algorithm, the attribute Lossy Image Compression (0028,2110) is set to “01”. Subsequently, if the image is decompressed and transferred in uncompressed format, this attribute value remains “01”. The value of the Lossy Image Compression (0028,2110) Attribute in SOP Instances containing multiple frames in which one or more of the frames have undergone lossy compression shall be “01”. Note: It is recommended that the applicable frames be noted in the Attribute Derivation Description (0008,2111). If an image is originally obtained as a lossy compressed image from the sensor, then Lossy Image Compression (0028,2110) is set to “01” and Value 1 of the Attribute Image Type (0008,0008) shall be set to ORIGINAL. If an image is a compressed version of another image, Lossy Image Compression (0028,2110) is set to “01”, Value 1 of the Attribute Image Type (0008,0008) shall be set to DERIVED, and if the predecessor was a DICOM image, then the Image shall receive a new SOP Instance UID. Note: 1. It is recommended that the approximate compression ratio be provided in the Attribute Derivation Description (0008,2111). Furthermore, it is recommended that Derivation Description (0008,2111) be used to indicate when pixel data changes might affect professional interpretation. (see C.7.6.1.1.3). 2. The attribute Lossy Image Compression (0028,2110) is defined as Type 3 for backward compatibility with existing IODs. It is expected to be required (i.e., defined as Type 1C) for new Image IODs and for existing IODs that undergo a major revision (e.g. a new IOD is specified). The Defined Terms for Lossy Image Compression Method (0028,2114) are: ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression
Full set of Composite SOP Instances referred to inside the Referenced Image Sequences of this SOP Instance. See C.8.13.2.1.2 for further explanation. One or more Items may be permitted in this sequence. Required if the Referenced Image Sequence (0008,1140) is present.
The intent of the Referenced Image Evidence Sequence (0008,9092) and Source Image Evidence Sequence (0008,9154) is to provide a list of all unique SOP Instances listed in the Referenced Image Sequence (0008,1140) and Source Image Sequence (0008,2112) attributes respectively.
User-defined comments about the image. Indicates whether or not this image is a quality control or phantom image. Enumerated Values: YES NO If this Attribute is absent, then the image may or may not be a quality control or phantom image. This icon image is representative of the Image. Specifies a predefined identity transformation for the Presentation LUT such that the output of all grayscale transformations, if any, are defined to be in P-Values. Enumerated Values: IDENTITY = output is in P-Values
A sequence that describes characteristics of the sources that are used to create a derived SOP Instance. One or more Items may be present. Indicates any visual processing performed on the frame prior to exchange. See Section C.8.7.1.1.3. Required if present and consistent in the contributing SOP Instances.
Acquisition Device Processing Description (0018,1400) provides some indication in human readable text of the digital processing on the images before exchange. Examples of this processing are: edge enhanced, subtracted, time filtered, gamma corrected, convolved (spatially filtered).
Code representing the device-specific processing associated with the frame (e.g. Organ Filtering code) Required if present and have an equal value in the contributing SOP Instances. Identification of the plane used to acquire this image. Defined Terms: MONOPLANE PLANE A PLANE B Required if present and consistent in the contributing SOP Instances. Physical distance measured at the receptor plane of the detector between the centers of each pixel specified by a numeric pair - row spacing value (delimiter) column spacing value in mm. Required if present and consistent in the contributing SOP Instances.
A sequence that describes characteristics of the sources that are used to create a derived SOP Instance. One or more Items may be present. Indicates any visual processing performed on the frame prior to exchange. See Section C.8.7.1.1.3. Required if present and consistent in the contributing SOP Instances.
Acquisition Device Processing Description (0018,1400) provides some indication in human readable text of the digital processing on the images before exchange. Examples of this processing are: edge enhanced, subtracted, time filtered, gamma corrected, convolved (spatially filtered).
Code representing the device-specific processing associated with the frame (e.g. Organ Filtering code). Required if present and have an equal value in the contributing SOP Instances. Physical distance measured at the receptor plane of the detector between the centers of each pixel specified by a numeric pair - row spacing value (delimiter) column spacing value in mm. Required if present and consistent 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. Note: The attribute is absent in the case where the images used to create the volume are not available as SOP Instances, e.g., the volume was directly generated by acquisition system. One or more Items may be included in this Sequence. Shape of the Field of View in the referenced images. Enumerated Values: RECTANGLE ROUND HEXAGONAL Required if present and consistent in the contributing SOP Instances. Dimensions in mm of the Field of View in the referenced images. If Field of View Shape (0018,1147) is: RECTANGLE: row dimension followed by column. ROUND: diameter. HEXAGONAL: diameter of the circle circumscribing the hexagon. Required if present and consistent in the contributing SOP Instances. Offset of the TLHC of a rectangle circumscribing the Field of View in the referenced images, before rotation or flipping, from the TLHC of the physical detector area measured in physical detector pixels as a row offset followed by a column offset. See C.8.11.4.1.1 for further explanation. Required if X-Ray Receptor Type (0018,9420) is present and equals DIGITAL_DETECTOR.
The relationship between the Physical Detector Area, the Active Detector Area, the Field of View (what is stored in the Pixel Data (7FE0,0010)), the Exposed Area (after X-Ray Collimation) and the Displayed Area is illustrated in the following diagrams. Note: Some of these Attributes relate the image data to manufacturer specific characteristics of the detector that may be used for quality control purposes, e.g. correlation of image artifacts with a detector defect map, analysis of noise performance, etc. The Displayed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the Display Shutter Module (see section C.7.6.11). If this Module is not present or supported, then the Displayed Area is equal to the Field of View. The Exposed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the X-Ray Collimator Module (see section C.8.7.3). For the Digital X-Ray IODs, the Field of View is usually rectangular in shape and the same size as the stored Pixel Data (7FE0,0010). The shape and size of the Field of View and the spacing of the pixels are defined by the following Attributes: - Field of View Shape (0018,1147), - Field of View Dimensions (0018,1149), - Imager Pixel Spacing (0018,1164), - Rows (0028,0010), - Columns (0028,0011) The following Attributes define the relationship of the Field of View to the Physical Detector Area: - Field of View Origin (0018,7030), - Field of View Rotation (0018,7032), - Field of View Horizontal Flip (0018,7034). For the Digital X-Ray IODs, the Active Area, i.e. that part of the detector matrix that was activated for this exposure, is usually rectangular in shape. The shape and size of the Active Area and the size and spacing of the detectors are defined by the following Attributes: - Detector Active Shape (0018,7024), - Detector Active Dimensions (0018,7026), - Detector Element Physical Size (0018,7020), - Detector Element Spacing (0018,7022). Notes: 1. The Detector Element Physical Size (0018,7020) and Detector Element Spacing (0018,7022) may be different if there are insensitive regions between each detector. 2. This model of description is not able to accurately describe multiple matrices of detectors that are “tiled” to produce a single image. The following optional Attribute defines the relationship of the Active Area to the Physical Detector Area: - Detector Active Origin (0018,7028). The relationship between detectors and stored image pixels is defined by Detector Binning (0018,701A) which specifies how many detectors, in each of the row and column directions, contribute to (are pooled or averaged to form) a single stored image pixel. Note: Detector Binning (0018,701A) may have values less than one if sub-sampling is used to derive an image with higher spatial resolution than the detector matrix. Figure C.8-14 Explanation of DX Detector Attributes Figure C.8-15 Explanation of DX Detector Attributes
Clockwise rotation in degrees of Field of View in the referenced images, relative to the physical detector. Enumerated Values: 0, 90, 180, 270 See C.8.11.4.1.1 for further explanation. Required if present and consistent in the contributing SOP Instances.
The relationship between the Physical Detector Area, the Active Detector Area, the Field of View (what is stored in the Pixel Data (7FE0,0010)), the Exposed Area (after X-Ray Collimation) and the Displayed Area is illustrated in the following diagrams. Note: Some of these Attributes relate the image data to manufacturer specific characteristics of the detector that may be used for quality control purposes, e.g. correlation of image artifacts with a detector defect map, analysis of noise performance, etc. The Displayed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the Display Shutter Module (see section C.7.6.11). If this Module is not present or supported, then the Displayed Area is equal to the Field of View. The Exposed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the X-Ray Collimator Module (see section C.8.7.3). For the Digital X-Ray IODs, the Field of View is usually rectangular in shape and the same size as the stored Pixel Data (7FE0,0010). The shape and size of the Field of View and the spacing of the pixels are defined by the following Attributes: - Field of View Shape (0018,1147), - Field of View Dimensions (0018,1149), - Imager Pixel Spacing (0018,1164), - Rows (0028,0010), - Columns (0028,0011) The following Attributes define the relationship of the Field of View to the Physical Detector Area: - Field of View Origin (0018,7030), - Field of View Rotation (0018,7032), - Field of View Horizontal Flip (0018,7034). For the Digital X-Ray IODs, the Active Area, i.e. that part of the detector matrix that was activated for this exposure, is usually rectangular in shape. The shape and size of the Active Area and the size and spacing of the detectors are defined by the following Attributes: - Detector Active Shape (0018,7024), - Detector Active Dimensions (0018,7026), - Detector Element Physical Size (0018,7020), - Detector Element Spacing (0018,7022). Notes: 1. The Detector Element Physical Size (0018,7020) and Detector Element Spacing (0018,7022) may be different if there are insensitive regions between each detector. 2. This model of description is not able to accurately describe multiple matrices of detectors that are “tiled” to produce a single image. The following optional Attribute defines the relationship of the Active Area to the Physical Detector Area: - Detector Active Origin (0018,7028). The relationship between detectors and stored image pixels is defined by Detector Binning (0018,701A) which specifies how many detectors, in each of the row and column directions, contribute to (are pooled or averaged to form) a single stored image pixel. Note: Detector Binning (0018,701A) may have values less than one if sub-sampling is used to derive an image with higher spatial resolution than the detector matrix. Figure C.8-14 Explanation of DX Detector Attributes Figure C.8-15 Explanation of DX Detector Attributes
Whether or not a horizontal flip has been applied to the Field of View in the referenced images, after rotation relative to the physical detector as described in Field of View Rotation (0018,7032). Enumerated Values: NO YES See C.8.11.4.1.1 for further explanation. Required if present and consistent in the contributing SOP Instances.
The relationship between the Physical Detector Area, the Active Detector Area, the Field of View (what is stored in the Pixel Data (7FE0,0010)), the Exposed Area (after X-Ray Collimation) and the Displayed Area is illustrated in the following diagrams. Note: Some of these Attributes relate the image data to manufacturer specific characteristics of the detector that may be used for quality control purposes, e.g. correlation of image artifacts with a detector defect map, analysis of noise performance, etc. The Displayed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the Display Shutter Module (see section C.7.6.11). If this Module is not present or supported, then the Displayed Area is equal to the Field of View. The Exposed Area is defined in pixel coordinates relative to the stored image pixel values by the Attributes of the X-Ray Collimator Module (see section C.8.7.3). For the Digital X-Ray IODs, the Field of View is usually rectangular in shape and the same size as the stored Pixel Data (7FE0,0010). The shape and size of the Field of View and the spacing of the pixels are defined by the following Attributes: - Field of View Shape (0018,1147), - Field of View Dimensions (0018,1149), - Imager Pixel Spacing (0018,1164), - Rows (0028,0010), - Columns (0028,0011) The following Attributes define the relationship of the Field of View to the Physical Detector Area: - Field of View Origin (0018,7030), - Field of View Rotation (0018,7032), - Field of View Horizontal Flip (0018,7034). For the Digital X-Ray IODs, the Active Area, i.e. that part of the detector matrix that was activated for this exposure, is usually rectangular in shape. The shape and size of the Active Area and the size and spacing of the detectors are defined by the following Attributes: - Detector Active Shape (0018,7024), - Detector Active Dimensions (0018,7026), - Detector Element Physical Size (0018,7020), - Detector Element Spacing (0018,7022). Notes: 1. The Detector Element Physical Size (0018,7020) and Detector Element Spacing (0018,7022) may be different if there are insensitive regions between each detector. 2. This model of description is not able to accurately describe multiple matrices of detectors that are “tiled” to produce a single image. The following optional Attribute defines the relationship of the Active Area to the Physical Detector Area: - Detector Active Origin (0018,7028). The relationship between detectors and stored image pixels is defined by Detector Binning (0018,701A) which specifies how many detectors, in each of the row and column directions, contribute to (are pooled or averaged to form) a single stored image pixel. Note: Detector Binning (0018,701A) may have values less than one if sub-sampling is used to derive an image with higher spatial resolution than the detector matrix. Figure C.8-14 Explanation of DX Detector Attributes Figure C.8-15 Explanation of DX Detector Attributes
Identifies the grid. May be multi-valued. Defined Terms are: FIXED FOCUSED RECIPROCATING PARALLEL CROSSED NONE Required if present and consistent in the contributing SOP Instances. Identifies the type of X-Ray receptor used. Enumerated Values: IMG_INTENSIFIER DIGITAL_DETECTOR Required if present and consistent in the contributing SOP Instances. Average of the peak kilo voltage outputs of the X-Ray generator used for all frames. Required if present and consistent in the contributing SOP Instances. Average of the nominal X-Ray tube currents in milliamperes for all frames. Required if present and consistent in the contributing SOP Instances. Duration of X-Ray exposure in milliseconds. See C.8.7.2.1.1. Required if present and consistent in the contributing SOP Instances.
Exposure time is the cumulative time the patient received X-Ray exposure during this image (Multi-frame image acquisition). Calculation is pulse width * number of frames.
The exposure expressed in milliampereseconds, for example calculated from Exposure Time and X-Ray Tube Current. Required if present and consistent in the contributing SOP Instances. Contrast or bolus agent. Required if present and consistent in the contributing SOP Instances. Sequence that identifies the contrast agent. One or more Items may be present. Required if present and consistent in the contributing SOP Instances. Start date and time of that part of an acquisition used for this acquisition context. Required if present and consistent in the contributing SOP Instances. End date and time of that part of an acquisition used for this acquisition context. Required if present and consistent in the contributing SOP Instances.
Exact peak kilo voltage output of the X-Ray generator used for this projection. Required if present and consistent in the contributing SOP Instances. Exact Nominal X-Ray tube current in milliamperes applied during the Frame Acquisition Duration (0018,9220) for this projection. Required if present and consistent in the contributing SOP Instances. The actual amount of time [in milliseconds] that was used to acquire data for this projection. See C.7.6.16.2.2.1 and C.7.6.16.2.2.3 for further explanation. Required if present and consistent in the contributing SOP Instances.
Figure C.7.6.16-2 shows the relationships among the various timing parameters used.
Shape(s) of the collimator. Enumerated Values: RECTANGULAR CIRCULAR POLYGONAL This multi-valued Attribute shall contain at most one of each Enumerated Value. Required if present and consistent in the contributing SOP Instances. Required if Collimator Shape (0018,1700) is RECTANGULAR. Location of the left edge of the rectangular collimator with respect to pixels in the image given as column. See C.8.7.3.1.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is RECTANGULAR. Location of the right edge of the rectangular collimator with respect to pixels in the image given as column. See C.8.7.3.1.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is RECTANGULAR. Location of the upper edge of the rectangular collimator with respect to pixels in the image given as row. See C.8.7.3.1.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is RECTANGULAR. Location of the lower edge of the rectangular collimator with respect to pixels in the image given as row. See C.8.7.3.1.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is CIRCULAR. Location of the center of the circular collimator with respect to pixels in the image given as row and column. See C.8.7.3.1.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is CIRCULAR. Radius of the circular collimator with respect to pixels in the image given as a number of pixels along the row direction. See C.8.7.3.1.1.
These attributes specify the pixel row or column where the X-Ray beam is fully obscured by a rectangular collimator: - if the left edge of the collimator is not visible, Collimator Left Vertical Edge (0018,1702) shall have a value of 0; - if the right edge of the collimator is not visible, Collimator Right Vertical Edge (0018,1704) value shall be 1 greater than the value of the Columns (0028,0011) attribute; - if the top edge of the collimator is not visible, Collimator Upper Horizontal Edge (0018,1706) shall have a value of 0; - if the bottom edge of the collimator is not visible, Collimator Lower Horizontal Edge (0018,1708) value shall be 1 greater than the value of the Rows (0028,0010) attribute.
Required if Collimator Shape (0018,1700) is POLYGONAL. Multiple Values where the first set of two values are: row of the origin vertex; column of the origin vertex. Two or more pairs of values follow and are the row and column coordinates of the other vertices of the polygon collimator. Polygon collimators are implicitly closed from the last vertex to the origin vertex and all edges shall be non-intersecting except at the vertices.
Each item represents an acquisition context related to one or more reconstructions. The values of the Acquisition Index (0020,9518) attribute may be used as index to Items in this sequence. One or more Items may be present. Dimensions of the physical detector measured in mm as a row size followed by a column size. Required if present and consistent in the contributing SOP Instances. Position of the Isocenter measured in physical detector elements as a row offset followed by a column offset from the TLHC of a rectangle circumscribing the physical detector area. Required if Isocenter Reference System Sequence (0018,9462) is present. Required if present and consistent in the contributing SOP Instances. Distance from source to receptor plane perpendicular to the receptor plane in mm or distance in mm from source to detector center on the chest wall line See C.8.11.7.1.1. Required if present and consistent in the contributing SOP Instances. Note: This value is traditionally referred to as Source Image Receptor Distance (SID).
Figure C.8-8 shows the X-Ray beam for a digital mammography system. The X-Ray beam vector is defined from the Focal Spot to the center of the chest wall line of the Image Detection device. Figure C.8-8
Distance from source to isocenter in mm. Required if present and consistent in the contributing SOP Instances. Nominal focal spot size in mm used to acquire this image. Required if present and consistent in the contributing SOP Instances. Type of filter(s) inserted into the X-Ray beam (e.g. wedges). Defined Terms: STRIP WEDGE BUTTERFLY MULTIPLE NONE Required if present and consistent in the contributing SOP Instances. The X-Ray absorbing material used in the filter. May be multi-valued. Defined Terms: MOLYBDENUM ALUMINUM COPPER RHODIUM NIOBIUM EUROPIUM LEAD Required if present and consistent in the contributing SOP Instances. The minimum thickness in mm of the X-Ray absorbing material used in the filters. May be multi-valued, with values corresponding to the respective values in Filter Material (0018,7050). Required if present and consistent in the contributing SOP Instances. The maximum thickness in mm of the X-Ray absorbing material used in the filters. May be multi-valued, with values corresponding to the respective values in Filter Material (0018,7050). Required if present and consistent in the contributing SOP Instances. Total amount of rotation of the primary positioner in degrees. Required if present and consistent in the contributing SOP Instances. Start position of the primary positioner in degrees. See C.8.7.5.1.2. Required if present and consistent in the contributing SOP Instances.
The definitions of Positioner Angles shall be with respect to the patient as illustrated in Figures C.8-11 and C.8-12 Zero degree is referenced to the origin perpendicular to the patient's chest. The Positioner Primary Angle definition is like longitude (in the equatorial plan); the Positioner Secondary Angle definition is like latitude (in the sagittal plane). The Positioner Angle attributes apply to the first frame of a multi-frame image. The valid range of Primary Positioner Angle is -180 to +180 degrees and the Secondary Positioner Angle range is -90 to + 90 degrees. The Patient Plane is defined by the isocenter of the imaging device and slices through the patient such that it is perpendicular to the sagittal plane of the body. The Primary Axis of rotation is defined at the intersection of the Patient Plane and of the Sagittal Plane. The Positioner Primary Angle is defined in the transaxial plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest and + 90 degrees at the Patient left hand side (LAO) and -90 at the Patient right hand side (RAO). The valid range of Primary Positioner Angle is -180 to +180 degrees. The Secondary Axis is in the Patient Plane and is perpendicular to the Primary Axis at the isocenter. The Positioner Secondary Angle is defined in the Sagittal Plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest. +90 degrees corresponds to the cranial direction. The Secondary Positioner Angle range is -90 to + 90 degrees. At a 0 angle for both the Primary Angle (0018,1510) and Secondary Angle (0018,1511), the patient faces the Image Intensifier. The Positioner Primary Angle (0018,1510) and Secondary Angle (0018,1511) apply to the first frame of a multi-frame image. Figure C.8-11 Positioner Primary Angle Figure C.8-12 Positioner Secondary Angle
Nominal increment of the primary positioner angle in degrees. Positive values indicate moving from RAO to LAO position through the anterior. See C.8.7.5.1.2. Required if present and consistent in the contributing SOP Instances.
The definitions of Positioner Angles shall be with respect to the patient as illustrated in Figures C.8-11 and C.8-12 Zero degree is referenced to the origin perpendicular to the patient's chest. The Positioner Primary Angle definition is like longitude (in the equatorial plan); the Positioner Secondary Angle definition is like latitude (in the sagittal plane). The Positioner Angle attributes apply to the first frame of a multi-frame image. The valid range of Primary Positioner Angle is -180 to +180 degrees and the Secondary Positioner Angle range is -90 to + 90 degrees. The Patient Plane is defined by the isocenter of the imaging device and slices through the patient such that it is perpendicular to the sagittal plane of the body. The Primary Axis of rotation is defined at the intersection of the Patient Plane and of the Sagittal Plane. The Positioner Primary Angle is defined in the transaxial plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest and + 90 degrees at the Patient left hand side (LAO) and -90 at the Patient right hand side (RAO). The valid range of Primary Positioner Angle is -180 to +180 degrees. The Secondary Axis is in the Patient Plane and is perpendicular to the Primary Axis at the isocenter. The Positioner Secondary Angle is defined in the Sagittal Plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest. +90 degrees corresponds to the cranial direction. The Secondary Positioner Angle range is -90 to + 90 degrees. At a 0 angle for both the Primary Angle (0018,1510) and Secondary Angle (0018,1511), the patient faces the Image Intensifier. The Positioner Primary Angle (0018,1510) and Secondary Angle (0018,1511) apply to the first frame of a multi-frame image. Figure C.8-11 Positioner Primary Angle Figure C.8-12 Positioner Secondary Angle
Total amount of rotation of the secondary positioner in degrees. Required if present and consistent in the contributing SOP Instances. Start position of the secondary positioner in degrees. See C.8.7.5.1.2. Required if present and consistent in the contributing SOP Instances.
The definitions of Positioner Angles shall be with respect to the patient as illustrated in Figures C.8-11 and C.8-12 Zero degree is referenced to the origin perpendicular to the patient's chest. The Positioner Primary Angle definition is like longitude (in the equatorial plan); the Positioner Secondary Angle definition is like latitude (in the sagittal plane). The Positioner Angle attributes apply to the first frame of a multi-frame image. The valid range of Primary Positioner Angle is -180 to +180 degrees and the Secondary Positioner Angle range is -90 to + 90 degrees. The Patient Plane is defined by the isocenter of the imaging device and slices through the patient such that it is perpendicular to the sagittal plane of the body. The Primary Axis of rotation is defined at the intersection of the Patient Plane and of the Sagittal Plane. The Positioner Primary Angle is defined in the transaxial plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest and + 90 degrees at the Patient left hand side (LAO) and -90 at the Patient right hand side (RAO). The valid range of Primary Positioner Angle is -180 to +180 degrees. The Secondary Axis is in the Patient Plane and is perpendicular to the Primary Axis at the isocenter. The Positioner Secondary Angle is defined in the Sagittal Plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest. +90 degrees corresponds to the cranial direction. The Secondary Positioner Angle range is -90 to + 90 degrees. At a 0 angle for both the Primary Angle (0018,1510) and Secondary Angle (0018,1511), the patient faces the Image Intensifier. The Positioner Primary Angle (0018,1510) and Secondary Angle (0018,1511) apply to the first frame of a multi-frame image. Figure C.8-11 Positioner Primary Angle Figure C.8-12 Positioner Secondary Angle
Nominal increment of the secondary positioner angle in degrees. Positive values indicate moving from CAU to CRA through the anterior. See C.8.7.5.1.2. Required if present and consistent in the contributing SOP Instances.
The definitions of Positioner Angles shall be with respect to the patient as illustrated in Figures C.8-11 and C.8-12 Zero degree is referenced to the origin perpendicular to the patient's chest. The Positioner Primary Angle definition is like longitude (in the equatorial plan); the Positioner Secondary Angle definition is like latitude (in the sagittal plane). The Positioner Angle attributes apply to the first frame of a multi-frame image. The valid range of Primary Positioner Angle is -180 to +180 degrees and the Secondary Positioner Angle range is -90 to + 90 degrees. The Patient Plane is defined by the isocenter of the imaging device and slices through the patient such that it is perpendicular to the sagittal plane of the body. The Primary Axis of rotation is defined at the intersection of the Patient Plane and of the Sagittal Plane. The Positioner Primary Angle is defined in the transaxial plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest and + 90 degrees at the Patient left hand side (LAO) and -90 at the Patient right hand side (RAO). The valid range of Primary Positioner Angle is -180 to +180 degrees. The Secondary Axis is in the Patient Plane and is perpendicular to the Primary Axis at the isocenter. The Positioner Secondary Angle is defined in the Sagittal Plane at the isocenter with zero degrees in the direction perpendicular to the patient's chest. +90 degrees corresponds to the cranial direction. The Secondary Positioner Angle range is -90 to + 90 degrees. At a 0 angle for both the Primary Angle (0018,1510) and Secondary Angle (0018,1511), the patient faces the Image Intensifier. The Positioner Primary Angle (0018,1510) and Secondary Angle (0018,1511) apply to the first frame of a multi-frame image. Figure C.8-11 Positioner Primary Angle Figure C.8-12 Positioner Secondary Angle
Sequence containing detailed acquisition context of each individual projection used in this acquisition context. Zero or more items may be present. Required if present and consistent in the contributing SOP Instances. Position of the X-Ray center beam for this projection in the isocenter reference system in the X direction (deg). See C.8.19.6.13.1.2 for further explanation. Required if present and consistent in the contributing SOP Instances.
The positioner coordinate system (Op, Xp, Yp, Zp) is defined as follows:
Position of the X-Ray center beam for this projection in the isocenter reference system in the Z direction (deg). See C.8.19.6.13.1.2 for further explanation. Required if present and consistent in the contributing SOP Instances.
The positioner coordinate system (Op, Xp, Yp, Zp) is defined as follows:
Rotation of the X-Ray detector plane for this projection (deg). See C.8.19.6.13.1.2 for further explanation. Required if present and consistent in the contributing SOP Instances.
The positioner coordinate system (Op, Xp, Yp, Zp) is defined as follows:
Each item represents a acquisition context related to a set of frames of SOP Instance defined by this IOD, The values of the Acquisition Index (0020,9518) attribute may be used as index to Items in this sequence. One or more Items may be present. Sequence containing detailed acquisition context of each individual projection used in this acquisition context. Zero or more items may be present. Required if present and consistent in the contributing SOP Instances. A sequence of Items each describing the characteristics of one 3D reconstruction included in this SOP instance. One or more items may be present. Free text description of the purpose of the reconstruction, e.g., mask volume. Name of the application that created the reconstruction. Version of the application that created the reconstruction. Name of the manufacturer of the application that created the reconstruction. Type of algorithm used to create the reconstruction. Defined Terms: FILTER_BACK_PROJ ITERATIVE Description of the algorithm used to create the reconstruction. The Item number(s) of the X-Ray 3D Acquisition Sequence (0018,9507) that describes the acquisition context(s) contributing to this reconstruction. A sequence that describes general characteristics of this frame. Only a single Item shall be permitted in this sequence. Type of Frame. A multi-valued attribute analogous to the Image Type (0008,0008). Enumerated Values and Defined Terms are the same as those for the four values of the Image Type (0008,0008) attribute, except that the value MIXED is not allowed. See C.8.16.1 and C.8.13.3.1.1.
The Image Type (0008,0008) and associated Image Type related attributes provide a high level description of a multi-frame SOP Instance. These attributes describe properties that provide key summary information to users of the SOP Instance. Image Type (0008,0008) contains the highest level summary of what is in the SOP Instance. The Frame Type (0008,9007) attribute mirrors the corresponding Image Type attribute and applies to the frame level rather than to the image level. If more than one value is used by the set of frames for a given Frame Type (0008,9007) attribute value or associated attribute value then the corresponding value of the Image Type (0008,0008) or associated attribute shall contain a value of MIXED. This indicates that a mixed set of values exists within the multi-frame SOP Instance. The value MIXED shall only be used in the Image Type (0008,0008) when the corresponding values for the individual frames are not equal. When a value of an attribute is equal for all frames, the same value shall be used for the corresponding value of the Image Type (0008,0008). Values 2 and 3 of Image Type (0008,0008) are an exception to the rule for MIXED: Values 2 and 3 may never have the value of MIXED as described in sections C.8.16.1.2 and C.8.16.1.3. Image Type (0008,0008) and Frame Type (0008,9007) shall consist of four non-zero length values.
The Item number of the X-Ray 3D Reconstruction Sequence (0018,9530) that describes the characteristics of the 3D Reconstruction to which this frame is part of.
Number of Rows in Overlay. Number of Columns in Overlay. Indicates whether this overlay represents a region of interest or other graphics. Enumerated Values: G = Graphics R = ROI. Location of first overlay point with respect to pixels in the image, given as row\column. The upper left pixel of the image has the coordinate 1\1. Column values greater than 1 indicate the overlay plane origin is to the right of the image origin. Row values greater than 1 indicate the overlay plane origin is below the image origin. Values less than 1 indicate the overlay plane origin is above or to the left of the image origin. Note: Values of 0\0 indicate that the overlay pixels start 1 row above and one column to the left of the image pixels. Number of Bits Allocated in the Overlay. The value of this Attribute shall be 1. Note: Formerly the standard described embedding the overlay data in the Image Pixel Data (7FE0,0010), in which case the value of this Attribute was required to be the same as Bits Allocated (0028,0100). This usage has been retired. See PS 3.3 2004. The value of this Attribute shall be 0. Note: Formerly the standard described embedding the overlay data in the Image Pixel Data (7FE0,0010), in which case the value of this Attribute specified the bit in which the overlay was stored. This usage has been retired. See PS 3.3 2004. Overlay pixel data. The order of pixels sent for each overlay is left to right, top to bottom, i.e., the upper left pixel is sent first followed by the remainder of the first row , followed by the first pixel of the 2nd row, then the remainder of the 2nd row and so on. Overlay data shall be contained in this Attribute . See C.9.2.1.1 for further explanation.
There are two specific types of overlays. The type is specified in this Attribute. A Region of Interest (ROI) is a specific use of an Overlay. The overlay bits corresponding to all the pixels included in the ROI shall be set to 1. All other bits are set to 0. This is used to specify an area of the image of particular interest. A Graphics overlay may express reference marks, graphic annotation, or bit mapped text, etc. A Graphics overlay may be used to mark the boundary of a ROI. If this is the case and the ROI statistical parameters are used, they will only refer to the pixels under the boundaries, not those in the included regions. The overlay bits corresponding to all the pixels included in the Graphics shall be set to 1. All other bits are set to 0.
User-defined comments about the overlay. Defined term which identifies the intended purpose of the Overlay Type. See C.9.2.1.3 for further explanation.
Two Defined Terms are specified: USER - User created graphic annotation (e.g. operator) AUTOMATED - Machine or algorithm generated graphic annotation, such as output of a Computer Assisted Diagnosis algorithm. Note: Additional or alternative Defined Terms may be specified in modality specific Modules, such as in the Ultrasound Image Module, C.8.5.6.1.11.
A user defined text string which may be used to label or name this overlay. Number of pixels in ROI area. See C.9.2.1.2 for further explanation.
These Attributes contain the statistical parameters of the ROI. The values of these parameters are for the overlay pixel values set to 1.
ROI Mean. See C.9.2.1.2 for further explanation.
These Attributes contain the statistical parameters of the ROI. The values of these parameters are for the overlay pixel values set to 1.
ROI standard deviation. See C.9.2.1.2 for further explanation.
These Attributes contain the statistical parameters of the ROI. The values of these parameters are for the overlay pixel values set to 1.
Number of Frames in Overlay. Required if Overlay data contains multiple frames. Frame number of Multi-frame Image to which this overlay applies; frames are numbered from 1. A sequence of Items each of which describes the displayed area selection for a group of images or frames. Sufficient Items shall be present to describe every image and frame listed in the Presentation State Relationship Module. One or more Items shall be present. Sequence of Items where each Item provides reference to a selected set of Image SOP Class/SOP Instance pairs that are defined in the Presentation State Relationship Module. One or more Items shall be present. Requiredif the displayed area selection in this Item does not apply to all the images and frames listed in the Presentation State Relationship Module. The top left (after spatial transformation) pixel in the referenced image to be displayed, given as column\row. Column is the horizontal (before spatial transformation) offset (X) and row is the vertical (before spatial transformation) offset (Y) relative to the origin of the pixel data before spatial transformation, which is 1\1. See Figure C.10.4-1. The bottom right (after spatial transformation) pixel in the referenced image to be displayed, given as column\row. Column is the horizontal (before spatial transformation) offset (X) and row is the vertical (before spatial transformation) offset (Y) relative to the origin of the pixel data before spatial transformation, which is 1\1. See Figure C.10.4-1. Manner of selection of display size. Enumerated Values: SCALE TO FIT TRUE SIZE MAGNIFY See C.10.4 for further explanation. Physical distance between the center of each pixel in the referenced image (before spatial transformation), specified by a numeric pair - adjacent row spacing (delimiter) adjacent column spacing in mm. See 10.7.1.3 for further explanation of the value order. Notes: 1. This value may be different from Pixel Spacing (0028,0030) or Imager Pixel Spacing (0018,1164) specified in the referenced image, which are ignored, since some form of calibration may have been performed (for example by reference to an object of known size in the image). 2. If the row and column spacing are different, then the pixel aspect ratio of the image is not 1:1. Required if Presentation Size Mode (0070,0100) is TRUE SIZE, in which case the values will correspond to the physical distance between the center of each pixel on the display device. May be present if Presentation Size Mode (0070,0100) is SCALE TO FIT or MAGNIFY, in which case the values are used to compute the aspect ratio of the image pixels. Ratio of the vertical size and the horizontal size of the pixels in the referenced image, to be used to display the referenced image, specified by a pair of integer values where the first value is the vertical pixel size and the second value is the horizontal pixel size. See C.7.6.3.1.7. Required if Presentation Pixel Spacing (0070,0101) is not present. Notes: 1. This value may be different from the aspect ratio specified by Pixel Aspect Ratio (0028,0034) in the referenced image, or implied by the values of Pixel Spacing (0028,0030) or Imager Pixel Spacing (0018,1164) specified in the referenced image, which are ignored. 2. This value must be specified even if the aspect ratio is 1:1.
The pixel aspect ratio is the ratio of the vertical size and horizontal size of the pixels in the image specified by a pair of integer values where the first value is the vertical pixel size, and the second value is the horizontal pixel size. To illustrate, consider the following example pixel size: Pixel Aspect Ratio = Vertical Size \ Horizontal Size = 0.30 mm \0.25 mm. Thus the Pixel Aspect Ratio could be represented as the multivalued integer string "6\5", "60\50", or any equivalent integer ratio.
Ratio of displayed pixels to source pixels, specified in one dimension. Required if Presentation Size Mode (0070,0100) is MAGNIFY. Notes: 1. A value of 1.0 would imply that one pixel in the referenced image would be displayed as one pixel on the display (i.e. it would not be interpolated if the aspect ratio of the image pixels is 1:1). 2. A value of 2.0 would imply that one pixel in the referenced image would be displayed as 4 pixels on the display (i.e. up-sampled by a factor of 2 in each of the row and column directions). 3. A value of 0.5 would imply that 4 pixels in the referenced image would be displayed as 1 pixel on the display (i.e. down-sampled by a factor of 2 in each of the row and column directions). 4. If the source pixels have an aspect ratio of other than 1:1, then they are assumed to have been interpolated to a display pixel aspect ratio of 1:1 prior to magnification.
A sequence of Items each of which represents a group of annotations composed of graphics or text or both. One or more Items shall be present. Sequence of Items where each Item provides reference to a selected set of Image SOP Class/SOP Instance pairs that are defined in the Presentation State Relationship Module. One or more Items shall be present. Required if graphic annotations in this Item do not apply to all the images and frames listed in the Presentation State Relationship Module. The layer defined in the Graphic Layer Module C.10.7 in which the graphics or text is to be rendered. Sequence that describes a text annotation. One or more Items may be present. Either one or both of Text Object Sequence (0070,0008) or Graphic Object Sequence (0070,0009) are required . Units of measure for the axes of the text bounding box. Defines whether or not the annotation is Image or Displayed Area relative. Both dimensions shall have the same units. Enumerated Values: PIXEL = Image relative position specified with sub-pixel resolution such that the origin at the Top Left Hand Corner (TLHC) of the TLHC pixel is 0.0\0.0, the Bottom Right Hand Corner (BRHC) of the TLHC pixel is 1.0\1.0, and the BRHC of the BRHC pixel is Columns\Rows (see figure C.10.5-1). The values must be within the range 0\0 to Columns\Rows. DISPLAY = Fraction of Specified Displayed Area where 0.0\0.0 is the TLHC and 1.0\1.0 is the BRHC. The values must be within the range 0.0 to 1.0. Required if Bounding Box Top Left Hand Corner (0070,0010) or Bounding Box Bottom Right Hand Corner (0070,0011) is present. Units of measure for the axes of the text anchor point annotation. Enumerated Values for Anchor Point Annotation Units (0070,0004) are the same as for Bounding Box Annotation Units (0070,0003). Required if Anchor Point (0070,0014) is present. Text data which is unformatted and whose manner of display within the defined bounding box or relative to the specified anchor point is implementation dependent. See C.10.5.1.1. The text value may contain spaces, as well as multiple lines separated by either LF, CR, CR LF or LF CR, but otherwise no format control characters (such as horizontal or vertical tab and form feed) shall be present, even if permitted by the Value Representation of ST. The text shall be interpreted as specified by Specific Character Set (0008,0005) if present in the SOP Common Module. Note: The text may contain single or multi-byte characters and use code extension techniques as described in PS 3.5 if permitted by the values of Specific Character Set (0008,0005).
The text shall be displayed if any part of the bounding box or anchor point is within the Specified Display Area. The text need not be confined to within the bounding box, but shall be rendered in a direction from the Top Left Hand Corner (TLHC) of the bounding box to the Bottom Right Hand Corner (BRHC) of the bounding box, even if these coordinates have been specified in an image relative space and then transformed (rotated, flipped or scaled). Notes: 1. An implementation may render text outside the confines of the bounding box if necessary to display all the specified text. 2. Alternatively, an implementation may choose to render the text in a scrolling box, or a link to another fixed or popup window as appropriate. Whether the contents of the bounding box completely opacify the underlying image or whether the box is “transparent” is undefined. Notes: 1. For example, an implementation may choose an “exclusive or” style opacification to be sure that the text is discernible over light and dark portions of the image. 2. Commonly, the region of the bounding box around the text will be rendered “transparently”, i.e. the image will be visible, though some implementations may choose to opacify the bounding box behind the text to improve its readability. An alternative to specifying a bounding box, is to specify an Anchor Point (0070,0014), i.e. some point in an image or Specified Displayed Area that is related to the text. The semantics of this relationship, and the manner of positioning or linking the text to this point, are unspecified. Notes: 1. For example, a description of a feature may be linked to a point in the image, and when that image is displayed, if it is magnified and panned, the rendered text (and any arrow or line drawn in response to Anchor Point Visibility (0070,0015)) might be repositioned as appropriate so as not to be cropped out of the Specified Displayed Area. 2. As another example, the text could be rendered in a pop-up window when a hypertext link flagged on the displayed image at the location of the Anchor Point (0070,0014) is selected. 3. The bounding box and anchor point need not be defined with the same axis units, i.e. one can be image pixel relative, and the other displayed area relative. The size, font and rotation of the individual rendered text characters are unspecified.
Location of the Top Left Hand Corner (TLHC) of the bounding box in which Unformatted Text Value (0070,0006) is to be displayed, in Bounding Box Annotation Units (0070,0003), given as column\row. Column is the horizontal offset and row is the vertical offset. Required if Anchor Point (0070,0014) is not present. Location of the Bottom Right Hand Corner (BRHC) of the bounding box in which Unformatted Text Value (0070,0006) is to be displayed, in Bounding Box Annotation Units (0070,0003), given as column\row. Column is the horizontal offset and row is the vertical offset. Required if Anchor Point (0070,0014) is not present. Location of the text relative to the vertical edges of the bounding box. Enumerated Values: LEFT = closest to left edge RIGHT = closest to right edge CENTER = centered Required if Bounding Box Top Left Hand Corner (0070,0010) is present. Location of a point in the image or Specified Displayed Area to which the Unformatted Text Value (0070,0006) is related, in Anchor Point Annotation Units (0070,0004), given as column\row. Column is the horizontal offset and row is the vertical offset. Required if Bounding Box Top Left Hand Corner (0070,0010) and Bounding Box Bottom Right Hand Corner (0070,0011) are not present. May be present even if a bounding box is specified (i.e. Bounding Box Top Left Hand Corner (0070,0010) and Bounding Box Bottom Right Hand Corner (0070,0011) are present). Flag to indicate whether or not a visible indication (such as a line or arrow) of the relationship between the text and the anchor point is to be displayed. Enumerated Values: Y = yes N = no Required if Anchor Point (0070,0014) is present. Sequence that describes a graphic annotation. One or more Items may be present. Either one or both of Text Object Sequence (0070,0008) or Graphic Object Sequence (0070,0009) are required. Units of measure for the axes of the graphic annotation. Enumerated Values for Graphic Annotation Units (0070,0005) are the same as for Bounding Box Annotation Units (0070,0003). Enumerated Value: 2 Number of data points in this graphic. Coordinates that specify this graphic annotation. See C.10.5.1.2 for further explanation.
Graphic Data (0070,0022) contains the points in the graphic annotation, each dimension for the first point, followed by dimensions for second point, etc. For a two dimensional curve: X1, Y1, X2, Y2, etc. The first (X) dimension corresponds to the image or Specified Displayed Area column (horizontal offset), and the second (Y) dimension corresponds to the image or Specified Displayed Area row (vertical offset). The Value Representation of all components of the N-tuple shall be the same. The image or Specified Displayed Area relative drawing space is defined in Graphic Annotation Units (0070,0005). If Graphic Type (0070,0023) is POINT, then two values (one point) shall be specified and the single point specified is to be drawn. If Graphic Type (0070,0023) is POLYLINE, then the points are to be interpreted as an n-tuple list of end points between which straight lines are to be drawn. If Graphic Type (0070,0023) is INTERPOLATED, then the points are to be interpreted as an n-tuple list of end points between which some form of implementation dependent curved lines are to be drawn. The rendered line shall pass through all the specified points. If Graphic Type (0070,0023) is CIRCLE, then exactly two points shall be present; the first point is to be interpreted as the center and the second point as a point on the circumference of a circle, some form of implementation dependent representation of which is to be drawn. If Graphic Type (0070,0023) is ELLIPSE, then exactly four points shall be present; the first two points are to be interpreted as the endpoints of the major axis and the second two points as the endpoints of the minor axis of an ellipse, some form of implementation dependent representation of which is to be drawn. The notion of “open” or “closed” has no inherent meaning in the context of an arbitrary graphic, other than in the condition for the presence of Graphic Filled (0070,0024). The graphic has no semantic notion of an associated observation such as a region of interest, except that which the unformatted text in the same Item may describe. The choice of pixel value used to represent the graphic on a display is defined in the Graphic Layer Module C.10.7. Figure C.10.5-1 Sub-pixel Addressing Units in PIXEL Space
The shape of graphic that is to be drawn. See C.10.5.1.2. Enumerated Values: POINT POLYLINE INTERPOLATED CIRCLE ELLIPSE
Graphic Data (0070,0022) contains the points in the graphic annotation, each dimension for the first point, followed by dimensions for second point, etc. For a two dimensional curve: X1, Y1, X2, Y2, etc. The first (X) dimension corresponds to the image or Specified Displayed Area column (horizontal offset), and the second (Y) dimension corresponds to the image or Specified Displayed Area row (vertical offset). The Value Representation of all components of the N-tuple shall be the same. The image or Specified Displayed Area relative drawing space is defined in Graphic Annotation Units (0070,0005). If Graphic Type (0070,0023) is POINT, then two values (one point) shall be specified and the single point specified is to be drawn. If Graphic Type (0070,0023) is POLYLINE, then the points are to be interpreted as an n-tuple list of end points between which straight lines are to be drawn. If Graphic Type (0070,0023) is INTERPOLATED, then the points are to be interpreted as an n-tuple list of end points between which some form of implementation dependent curved lines are to be drawn. The rendered line shall pass through all the specified points. If Graphic Type (0070,0023) is CIRCLE, then exactly two points shall be present; the first point is to be interpreted as the center and the second point as a point on the circumference of a circle, some form of implementation dependent representation of which is to be drawn. If Graphic Type (0070,0023) is ELLIPSE, then exactly four points shall be present; the first two points are to be interpreted as the endpoints of the major axis and the second two points as the endpoints of the minor axis of an ellipse, some form of implementation dependent representation of which is to be drawn. The notion of “open” or “closed” has no inherent meaning in the context of an arbitrary graphic, other than in the condition for the presence of Graphic Filled (0070,0024). The graphic has no semantic notion of an associated observation such as a region of interest, except that which the unformatted text in the same Item may describe. The choice of pixel value used to represent the graphic on a display is defined in the Graphic Layer Module C.10.7. Figure C.10.5-1 Sub-pixel Addressing Units in PIXEL Space
Whether or not the closed graphics element is displayed as filled (in some unspecified manner that shall be distinguishable from an outline) or as an outline. See C.10.5.1.2. Enumerated Values: Y = yes N = no Required if Graphic Data (0070,0022) is "closed", that is Graphic Type (0070,0023) is CIRCLE or ELLIPSE, or Graphic Type (0070,0023) is POLYLINE or INTERPOLATED and the first data point is the same as the last data point.
Graphic Data (0070,0022) contains the points in the graphic annotation, each dimension for the first point, followed by dimensions for second point, etc. For a two dimensional curve: X1, Y1, X2, Y2, etc. The first (X) dimension corresponds to the image or Specified Displayed Area column (horizontal offset), and the second (Y) dimension corresponds to the image or Specified Displayed Area row (vertical offset). The Value Representation of all components of the N-tuple shall be the same. The image or Specified Displayed Area relative drawing space is defined in Graphic Annotation Units (0070,0005). If Graphic Type (0070,0023) is POINT, then two values (one point) shall be specified and the single point specified is to be drawn. If Graphic Type (0070,0023) is POLYLINE, then the points are to be interpreted as an n-tuple list of end points between which straight lines are to be drawn. If Graphic Type (0070,0023) is INTERPOLATED, then the points are to be interpreted as an n-tuple list of end points between which some form of implementation dependent curved lines are to be drawn. The rendered line shall pass through all the specified points. If Graphic Type (0070,0023) is CIRCLE, then exactly two points shall be present; the first point is to be interpreted as the center and the second point as a point on the circumference of a circle, some form of implementation dependent representation of which is to be drawn. If Graphic Type (0070,0023) is ELLIPSE, then exactly four points shall be present; the first two points are to be interpreted as the endpoints of the major axis and the second two points as the endpoints of the minor axis of an ellipse, some form of implementation dependent representation of which is to be drawn. The notion of “open” or “closed” has no inherent meaning in the context of an arbitrary graphic, other than in the condition for the presence of Graphic Filled (0070,0024). The graphic has no semantic notion of an associated observation such as a region of interest, except that which the unformatted text in the same Item may describe. The choice of pixel value used to represent the graphic on a display is defined in the Graphic Layer Module C.10.7. Figure C.10.5-1 Sub-pixel Addressing Units in PIXEL Space
How far to rotate the image clockwise in degrees, before any Image Horizontal Flip (0070,0041) is applied. Enumerated Values: 0, 90,180,270 Notes: Negative values are not permitted since the Value Representation is unsigned. Whether or not to flip the image horizontally after any Image Rotation has been applied such that the left side of the image becomes the right side. Enumerated Values: Y = yes, N = no Note: No vertical flip is specified since the same result can be achieved by a combination of a 180 degree rotation and a horizontal flip. A sequence of Items each of which represents a single layer in which overlays, curves, graphics or text may be rendered. One or more Items shall be present. An Item is required for each layer referenced from the Graphic Annotation Module or the Overlay Activation Module. A string which identifies the layer. Note: This identifier may be used by other Attributes within the same presentation state instance to reference this layer. There is no requirement for the same identifiers to be used in different presentation states, and there is no mechanism for referencing layers in other presentation states. That is, a UID is not required. An integer indicating the order in which it is recommended that the layer be rendered, if the display is capable of distinguishing. Lower numbered layers are to be rendered first. A default single gray unsigned value in which it is recommended that the layer be rendered on a monochrome display. The units are specified in P-Values from a minimum of 0000H (black) up to a maximum of FFFFH (white). Note: The maximum P-Value for this Attribute may be different from the maximum P-Value from the output of the Presentation LUT, which may be less than 16 bits in depth. A default color triplet value in which it is recommended that the layer be rendered on a color display. The units are specified in PCS-Values, and the value is encoded as CIELab. See C.10.7.1.1.
Attributes such as Graphic Layer Recommended Display CIELab Value (0070,0401) consist of three unsigned short values:
A free text description of the contents of this layer.
A number that identifies this Waveform. The date the Waveform data was created. The time the Waveform data was created. The date and time that the acquisition of data that resulted in this waveform started; the reference timestamp for the Multiplex Group Time Offset (0018,1068) for a waveform multiplex group Note: The synchronization of this time with an external clock is specified in the Synchronization Module in Acquisition Time Synchronized (0018,1800). A sequence which provides reference to a set of SOP Class/Instance pairs significantly related to this Waveform. One or more Items may be included in this sequence. Code describing the purpose of the reference to the Instance(s). Only a single Item shall be permitted in this sequence. Sequence of one or more Items, each representing one waveform multiplex group. Ordering of Items in this Sequence is significant for external reference to specific multiplex groups. Offset time in milliseconds from a reference time (see C.10.9.1.1). Required if Acquisition Time Synchronized (0018,1800) value is Y; may be present otherwise. Offset time in milliseconds from a synchronization trigger to the first sample of a waveform multiplex group. May be positive or negative. Required if waveform acquisition is synchronized to a trigger. Sample number whose time corresponds to a synchronization trigger (see C.10.9.1.2). See C.10.9.1.3. Enumerated values: ORIGINAL DERIVED
Waveform Originality (003A,0004) shall have the value ORIGINAL if the Waveform Data samples are the original or source data, and shall have the value DERIVED if the Waveform Data samples have been derived in some manner from the sample data of other waveforms. Notes : 1. The Waveform Originality (003A,0004) attribute is comparable to the Image Type (0008,0008) attribute value 1 (see C.7.6.1.1.2). Within a single Multiplex Group, all channels shall have the same Originality value. 2. Waveform data which has been transcoded from a non-DICOM format may have Waveform Originality value ORIGINAL if the samples are unchanged from the originally acquired waveform samples.
Number of channels for this multiplex group. Number of samples per channel in this multiplex group. Frequency in Hz Label for multiplex group Sequence of one or more Items, with one Item per channel (see C.10.9.1.4). Ordering of Items in this Sequence is significant for reference to specific channels. Equipment physical channel number used for acquisition. Text label for channel which may be used for display purposes One or more values for the status of this channel within this SOP Instance. Defined terms: OK TEST DATA DISCONNECTED QUESTIONABLE INVALID UNCALIBRATED UNZEROED Precise location of a change in status may be noted in an Annotation. A coded descriptor of the waveform channel source (metric, anatomical position, function, and technique). Only a single Item shall be permitted in this sequence. (See C.10.9.1.4.1)
Channel Source Sequence (003A,0208) identifies the metric (quality being measured, e.g., voltage or pressure), the anatomical position of the sensor or probe, the function of the channel (e.g., measurement or stimulus), and any particulars of technique which affect those parameters (e.g., pull-back across multiple anatomic sites, or differential input from two distinct sites). If the full semantics of the source is not carried in a single coded entry (e.g., if it specifies the location but not the metric), additional qualifiers are identified in Channel Source Modifiers Sequence (003A,0209) coded entries. When a single sensor channel is used to collect a waveform from two (or more) anatomic sites, e.g., in hemodynamic pull-back procedures, multiple Channel Source Modifier items will identify the sequence of sites, if not encoded in the semantics of the Channel Source Coded Entry. Transition times from one site to another may be indicated with an Annotation, or pull-back rate may be indicated with an Acquisition Context Sequence Item (see Section C.7.6.14). The Baseline (default) Context IDs are defined by IOD in accordance with Section A.34. Restrictions in the IOD may also determine the pattern of specification of the waveform source, i.e., which item is to be encoded in the Channel Source sequence, and the order in which Channel Source Modifier items are to be encoded. Unless otherwise specified, pattern of specification of the waveform source shall be:
Sequence of one or more Items which further qualify the Waveform Source. Required if Channel Source Sequence (003A,0208) does not fully specify the semantics of the source. Ordering of Items in this Sequence may be semantically significant. A sequence which provides reference to a DICOM waveform from which this channel was derived. One or more Items may be included in this Sequence. Identifies the waveform multiplex group and channel within the referenced SOP Instance. Pair of values (M,C). Additional description of waveform channel derivation Nominal numeric value of unit quantity of sample. Required if samples represent defined (not arbitrary) units. A coded descriptor of the Units of measure for the Channel Sensitivity. Only a single Item shall be permitted in this sequence. (see C.10.9.1.4.2) Required if Channel Sensitivity (003A,0210) is present. Multiplier to be applied to encoded sample values to match units specified in Channel Sensitivity (003A,0210) (e.g., based on calibration data) (see C.10.9.1.4.2) Required if Channel Sensitivity (003A,0210) is present. Offset of encoded sample value 0 from actual 0 using the units defined in the Channel Sensitivity Units Sequence (003A,0211). Required if Channel Sensitivity (003A,0210) is present. Offset of first sample of channel from waveform multiplex group start time, in seconds (see C.10.9.1.4.3) Required if Channel Sample Skew is not present. Offset of first sample of channel from waveform multiplex group start time, in samples (see C.10.9.1.4.3) Required if Channel Time Skew is not present. Additional offset of first sample of channel to be used in aligning multiple channels for presentation or analysis, in seconds (see C.10.9.1.4.3) Number of significant bits within the waveform samples (see C.10.9.1.4.4) Nominal 3dB point of lower frequency of pass band; in Hz Nominal 3dB point of upper frequency of pass band; in Hz Center frequency of notch filter(s); in Hz Nominal 3dB bandwidth of notch filter(s); in Hz Minimum valid sample value as limited by the acquisition equipment (see C.10.9.1.4.5) Maximum valid sample value as limited by the acquisition equipment (see C.10.9.1.4.5) Size of each waveform data sample within the Waveform Data; see section C.10.9.1.5 Data representation of the waveform data points. See C.10.9.1.5.
Waveform Bits Allocated (5400,1004) specifies the number of bits allocated for each sample, and Waveform Sample Interpretation (5400,1006) specifies the data representation of each waveform sample. Waveform Bits Allocated shall be a multiple of 8. These data elements are related, and their defined terms are specified in Table C.10-10. Table C.10-10 Waveform Bits Allocated and Waveform Sample Interpretation Notes: 1. The set of valid values from within this table may be constrained by definition of the IOD (see Section A.34). 2. mu-law and A-law encoding is without the alternate bit inversion used for PCM transmission through the telephone network. This representation also applies to the Channel Minimum and Maximum Data Values, and Waveform Padding Value.
Value of waveform samples inserted in channels when input is absent or invalid. Required if acquisition equipment inserts padding. See C.10.9.1.6.
Equipment which produces digitized waveform curves may encode a specific value when the source is disconnected or otherwise invalid. This value is encoded like the Waveform Data attribute with one sample only. The Waveform Padding Value need not be within the range specified by the Channel Minimum and Maximum Data Values.
Encoded data samples - channel multiplexed See section C.10.9.1.7 The recommended time-based waveform data display scale in units of mm/s (see C.10.9.1.8). A color triplet value recommended for rendering the waveform display background on a color display. The units are specified in PCS-Values, and the value is encoded as CIELab. See C.10.7.1.1.
Attributes such as Graphic Layer Recommended Display CIELab Value (0070,0401) consist of three unsigned short values:
Sequence of Items, each Item describing a Presentation Group of one or more waveform channels to be displayed together. Note: A Presentation Group is conventionally denoted a "display page", and a waveform object may be rendered using several Presentation Groups under user display control. One or more Items may be present. A number that identifies the Presentation Group. Sequence of Items, each Item describing a channel to be displayed in the Presentation Group. One or more Items shall be present. Identifier of the displayed channel, specified as a pair of values (M,C) where the first value is the ordinal of the sequence item of the Waveform Sequence (5400,0100) attribute (i.e., the Multiplex Group Number), and the second value is the ordinal of the sequence item of the Channel Definition Sequence (003A,0200) attribute (i.e., the Waveform Channel Number) within the multiplex group. Note: In the context of a Channel Display Sequence (003A,0242) Item, only a single channel shall be referenced. The offset in seconds from the beginning of the channel waveform data to the first sample to be used for presentation. Value may be negative. A color triplet value recommended for rendering the channel on a color display. The units are specified in PCS-Values, and the value is encoded as CIELab. See C.10.7.1.1.
Attributes such as Graphic Layer Recommended Display CIELab Value (0070,0401) consist of three unsigned short values:
Position of the Channel within the Presentation Group display area (see C.10.9.1.9). Specifies display area shading between the displayed waveform channel and another line. The nature of the shading (e.g., solid, or cross-hatching) is implementation dependent. Enumerated Values: NONE - no shading BASELINE- shading between the waveform and the channel display baseline (sample value 0 equivalent location) ABSOLUTE - shading between the waveform and the channel real world actual value 0 (i.e., taking into account the Channel Baseline (003A,0213) value) DIFFERENCE - shading between the waveform and a second waveform in the Presentation Group at the same Channel Position that also has Display Shading Flag (003A,0246) value DIFFERENCE. Fraction of the Presentation Group vertical display dimension assigned to the unit quantity (least significant bit) of the Channel samples (see C.10.9.1.10). Required if Absolute Channel Display Scale (003A,0248) is not present, may be present otherwise. Nominal vertical display height in mm assigned to the unit quantity (least significant bit) of the Channel samples (see C.10.9.1.10). Required if Fractional Channel Display Scale (003A,0247) is not present, may be present otherwise.
Sequence of Annotation Items; one or more items shall be present Text Observation Value (annotation). Mutually exclusive with Concept Name Code Sequence (0040,A043) Code representing the fully specified name of the NUMERIC measurement or CODED concept. This sequence shall contain exactly one item. Mutually exclusive with Text Value (0070,0006). A sequence of items modifying or specializing the Concept Name. One or more Items may be included in this Sequence. Required if Concept Name Code Sequence (0040,A043) is sent and the value does not fully describe the semantics of the measurement or concept. A sequence that conveys the categorical coded nominal value. This sequence shall contain exactly one item. A sequence of items modifying or specializing the Concept. One or more Items may be included in this Sequence. Required if Concept Code Sequence (0040,A168) is sent and the value does not fully describe the semantics of the concept value. Numeric measurement value or values. Units of measurement. Coded entry sequence with one item only. List of channels in waveform to which annotation applies. See C.10.10.1.1
Referenced Waveform Channels (0040,A0B0) is a multi-value attribute which lists the channels to which an annotation of a waveform applies. Each channel is specified as a pair of values (M,C), where the first value is the ordinal of the sequence item of the Waveform Sequence (5400,0100) attribute (i.e., the Multiplex Group Number), and the second value is the ordinal of the sequence item of the Channel Definition Sequence (003A,0200) attribute (i.e., the Waveform Channel Number) within the multiplex group. If the specified channel number is 0, the annotation applies to all channels in the multiplex group. Note: As an example, an annotation which applies to the entire first multiplex group and channels 2 and 3 of the third multiplex group would have Referenced Channels value 0001 0000 0003 0002 0003 0003.
See C.10.10.1.2 for Enumerated Values. Required if Annotation does not apply to entire Referenced Waveform Channels; shall not be present if Annotation applies to entire temporal extent of referenced channels.
The Temporal Range Type attribute (0040,A130) defines the type of temporal extent of the annotated region of interest. A temporal point (or instant of time) may be defined by a waveform sample offset (for a single waveform multiplex group only), time offset, or absolute time. The following terms are Enumerated Values for Temporal Range Type: POINT = a single temporal point MULTIPOINT = multiple temporal points SEGMENT = a range between two temporal points MULTISEGMENT = multiple segments, each denoted by two temporal points BEGIN = a range beginning at one temporal point, and extending beyond the end of the acquired data END = a range beginning before the start of the acquired data, and extending to (and including) the identified temporal point
List of samples within a multiplex group specifying temporal points for annotation. Position of first sample is 1. Required if Temporal Range Type (0040,A130) is present, and if Referenced Time Offsets (0040,A138) and Referenced DateTime (0040,A13A) are not present. See C.10.10.1.3
Referenced Sample Positions (0040,A132) may be used only if Referenced Waveform Channels (0040,A0B0) refers to channels within a single multiplex group. The sample position is by channel, and applies to all channels specified in Referenced Channels (0040,A0B0).
Specifies temporal points for annotation by number of seconds after start of data. Required if Temporal Range Type (0040,A130) is present, and if Referenced Sample Positions (0040,A132) and Referenced DateTime (0040,A13A) are not present. Specifies temporal points for annotation by absolute time. Required if Temporal Range Type (0040,A130) is present, and if Referenced Sample Positions (0040,A132) and Referenced Time Offsets (0040,A138) are not present. Number identifying associated annotations (see C.10.10.1.4).
Defines a sequence of Modality LUTs. Only one Item may be present. Shall not be present if Rescale Intercept (0028,1052) is present. Specifies the format of the LUT Data in this Sequence. See C.11.1.1 for further explanation. Required if the Modality LUT Sequence (0028,3000) is sent.
Free form text explanation of the meaning of the LUT. Specifies the output values of this Modality LUT. See C.11.1.1.2 for further explanation. Required if the Modality LUT Sequence (0028,3000) is sent.
Specifies the units of the output of the Modality LUT or rescale operation. Defined Terms: OD = The number in the LUT represents thousands of optical density. That is, a value of 2140 represents an optical density of 2.140. HU = Hounsfield Units (CT) US = Unspecified Other values are permitted, but are not defined by the DICOM Standard.
LUT Data in this Sequence. Required if the Modality LUT Sequence (0028,3000) is sent. The value b in relationship between stored values (SV) and the output units specified in Rescale Type (0028,1054). Output units = m*SV + b. Required if Modality LUT Sequence (0028,3000) is not present. Shall not be present otherwise. m in the equation specified by Rescale Intercept (0028,1052). Required if Rescale Intercept is present. Specifies the output units of Rescale Slope (0028,1053) and Rescale Intercept (0028,1052). See C.11.1.1.2 for further explanation. Required if Rescale Intercept is present.
Specifies the units of the output of the Modality LUT or rescale operation. Defined Terms: OD = The number in the LUT represents thousands of optical density. That is, a value of 2140 represents an optical density of 2.140. HU = Hounsfield Units (CT) US = Unspecified Other values are permitted, but are not defined by the DICOM Standard.
Defines a sequence of VOI LUTs. One or more Items shall be present. Required if Window Center (0028,1050) is not present. May be present otherwise. Specifies the format of the LUT Data in this Sequence. See C.11.2.1.1 for further explanation.
The three values of the LUT Descriptor (0028,3002) describe the format of the LUT Data in the corresponding Data Element (0028,3006). The first value is the number of entries in the lookup table. When the number of table entries is equal to 216 then this value shall be 0. The second value is the first input value mapped. The Value Representation of the second value (US or SS) depends on the source of the input to the VOI LUT, and shall be: - the same as specified by Pixel Representation (0028,0103), if there is no Modality LUT or Rescale Slope and Intercept specified; - SS if the possible output range after application of the Rescale Slope and Intercept may be signed; Note: This is always the case for the CT Image IOD in which the Rescale Type is specified to be Hounsfield Units, which are always signed. - US otherwise. This input value is mapped to the first entry in the LUT. All input values less than the first value mapped are also mapped to the first entry in the LUT Data. An input value one greater than the first value mapped is mapped to the second entry in the LUT Data. Subsequent input values are mapped to the subsequent entries in the LUT Data up to an input value equal to number of entries + first value mapped - 1 which is mapped to the last entry in the LUT Data. Input values greater than or equal to number of entries + first value mapped are also mapped to the last entry in the LUT Data. The third value specifies the number of bits for each entry in the LUT Data. If the VOI LUT is included in an Image IOD, the third value of LUT Descriptor (0028,3002) shall be 8 or 16 bits, unless otherwise specialized. If the VOI LUT is included in a Presentation State IOD, the third value of LUT Descriptor (0028,3002) shall be between 8 and 16 inclusive. The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where in both cases the high bit is equal to bits stored - 1, and where bits stored is the third value. Notes: 1. Since the LUT Descriptor (0028,3002) Attribute is multi-valued, in an Explicit VR Transfer Syntax, only one value representation (US or SS) may be specified, even though the first and third values are always by definition interpreted as unsigned. The explicit VR actually used is dictated by the VR needed to represent the second value. 2. Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits; this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry. The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16. The LUT Data contains the LUT entry values. The output range is from 0 to 2n-1 where n is the third value of LUT Descriptor. This range is always unsigned.
Free form text explanation of the meaning of the LUT. LUT Data in this Sequence. Window Center for display. See C.11.2.1.2 for further explanation. Required if VOI LUT Sequence (0028,3010) is not present. May be present otherwise.
Window Center (0028,1050) and Window Width (0028,1051) specify a linear conversion from stored pixel values (after any Modality LUT or Rescale Slope and Intercept specified in the IOD have been applied) to values to be displayed. Window Center contains the input value that is the center of the window. Window Width contains the width of the window. Note: The terms “window center” and “window width” are not consistently used in practice, nor were they defined in previous versions of the standard. The definitions here are presented for the purpose of defining consistent meanings for identity and threshold transformations while preserving the common practice of using integral values for center and width. Window Width (0028,1051) shall always be greater than or equal to 1. When Window Width (0028,1051) is greater than 1, these Attributes select the range of input values that are to be mapped to the full range of the displayed output. When Window Width (0028,1051) is equal to 1, they specify a threshold below which input values will be displayed as the minimum output value. Note: Whether the minimum output value is rendered as black or white may depend on the value of Photometric Interpretation (0028,0004) or the presence of a Presentation LUT Module. These Attributes are applied according to the following pseudo-code, where x is the input value, y is an output value with a range from ymin to ymax, c is Window Center (0028,1050) and w is Window Width (0028,1051): if (x <= c - 0.5 - (w-1)/2), then y = ymin else if (x > c - 0.5 + (w-1)/2), then y = ymax, else y = ((x - (c - 0.5)) / (w-1) + 0.5) * (ymax - ymin)+ ymin Notes: 1. For the purpose of this definition, a floating point calculation without integer truncation is assumed, though the manner of implementation may vary as long as the result is the same. 2. The pseudo-code function computes a continuous value over the output range without any discontinuity at the boundaries. The value of 0 for w is expressly forbidden, and the value of 1 for w does not cause division by zero, since the continuous segment of the function will never be reached for that case. 3. For example, for an output range 0 to 255: c=2048, w=4096 becomes: if (x <= 0) then y = 0 else if (x > 4095) then y = 255 else y = ((x - 2047.5) / 4095 + 0.5) * (255-0) + 0 c=2048, w=1 becomes: if (x <= 2047.5) then y = 0 else if (x > 2047.5) then y = 255 else /* not reached */ c=0, w=100 becomes: if (x <= -50) then y = 0 else if (x > 49) then y = 255 else y = ((x + 0.5) / 99 + 0.5) * (255-0) + 0 c=0, w=1 becomes: if (x <= -0.5) then y = 0 else if (x > -0.5) then y = 255 else /* not reached */ 4. A Window Center of 2n-1 and a Window Width of 2n selects the range of input values from 0 to 2n-1. This represents an identity VOI LUT transformation in the case where no Modality LUT is specified and the stored pixel data are n bit unsigned integers. 5. A Window Width of 1 is typically used to represent a "threshold" operation in which those integer input values less than the Window Center are represented as the minimum displayed value and those greater than or equal to the Window Center are represented as the maximum displayed value. A Window Width of 2 will have the same result for integral input values. 6. The application of Window Center (0028,1050) and Window Width (0028,1051) may select a signed input range. There is no implication that this signed input range is clipped to zero. 7. The selected input range may exceed the actual range of the input values, thus effectively “compressing” the contrast range of the displayed data into a narrower band of the available contrast range, and “flattening” the appearance. There are no limits to the maximum value of the window width, or to the minimum or maximum value of window level, both of which may exceed the actual or possible range of input values. 8. Input values "below" the window are displayed as the minimum output value and input values "above" the window are displayed as the maximum output value. This is the common usage of the window operation in medical imaging. There is no provision for an alternative approach in which all values "outside" the window are displayed as the minimum output value. 9. The output of the Window Center/Width or VOI LUT transformation is either implicitly scaled to the full range of the display device if there is no succeeding transformation defined, or implicitly scaled to the full input range of the succeeding transformation step (such as the Presentation LUT), if present. See C.11.6.1. 10. Fractional values of Window Center and Window Width are permitted (since the VR of these Attributes is Decimal String), and though they are not often encountered, applications should be prepared to accept them. These Attributes shall be used only for Images with Photometric Interpretation (0028,0004) values of MONOCHROME1 and MONOCHROME2. They have no meaning for other Images. 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 may be presented. If any VOI LUT Table is included by an Image, a Window Width and Window Center or the VOI LUT Table, but not both, may be applied to the Image for display. Inclusion of both indicates that multiple alternative views may be presented. If multiple items are present in VOI LUT Sequence (0028,3010), only one may be applied to the Image for display. Multiple items indicate that multiple alternative views may be presented. If the VOI LUT Module is defined in an IOD and if neither a VOI LUT Sequence nor a Window Width and Window Center are present, then the VOI LUT stage of the grayscale pipeline is defined to be an identity transformation. Notes: 1. This requirement is specified so that IODs that define a particular output space for the grayscale pipeline, such as P-Values, are not in an undefined state when no VOI LUT Sequence or Window Width and Window Center are present. 2. Despite the Type 3 requirement for VOI LUT Sequence and Window Center, implementations that render images are expected to implement and apply these transformations when they are present in the image, unless overridden by the user, a presentation state, or a hanging protocol, and to allow the user to select which transformation to apply when multiple transformations are present.
Window Width for display. See C.11.2.1.2 for further explanation. Required if Window Center (0028,1050) is sent.
Window Center (0028,1050) and Window Width (0028,1051) specify a linear conversion from stored pixel values (after any Modality LUT or Rescale Slope and Intercept specified in the IOD have been applied) to values to be displayed. Window Center contains the input value that is the center of the window. Window Width contains the width of the window. Note: The terms “window center” and “window width” are not consistently used in practice, nor were they defined in previous versions of the standard. The definitions here are presented for the purpose of defining consistent meanings for identity and threshold transformations while preserving the common practice of using integral values for center and width. Window Width (0028,1051) shall always be greater than or equal to 1. When Window Width (0028,1051) is greater than 1, these Attributes select the range of input values that are to be mapped to the full range of the displayed output. When Window Width (0028,1051) is equal to 1, they specify a threshold below which input values will be displayed as the minimum output value. Note: Whether the minimum output value is rendered as black or white may depend on the value of Photometric Interpretation (0028,0004) or the presence of a Presentation LUT Module. These Attributes are applied according to the following pseudo-code, where x is the input value, y is an output value with a range from ymin to ymax, c is Window Center (0028,1050) and w is Window Width (0028,1051): if (x <= c - 0.5 - (w-1)/2), then y = ymin else if (x > c - 0.5 + (w-1)/2), then y = ymax, else y = ((x - (c - 0.5)) / (w-1) + 0.5) * (ymax - ymin)+ ymin Notes: 1. For the purpose of this definition, a floating point calculation without integer truncation is assumed, though the manner of implementation may vary as long as the result is the same. 2. The pseudo-code function computes a continuous value over the output range without any discontinuity at the boundaries. The value of 0 for w is expressly forbidden, and the value of 1 for w does not cause division by zero, since the continuous segment of the function will never be reached for that case. 3. For example, for an output range 0 to 255: c=2048, w=4096 becomes: if (x <= 0) then y = 0 else if (x > 4095) then y = 255 else y = ((x - 2047.5) / 4095 + 0.5) * (255-0) + 0 c=2048, w=1 becomes: if (x <= 2047.5) then y = 0 else if (x > 2047.5) then y = 255 else /* not reached */ c=0, w=100 becomes: if (x <= -50) then y = 0 else if (x > 49) then y = 255 else y = ((x + 0.5) / 99 + 0.5) * (255-0) + 0 c=0, w=1 becomes: if (x <= -0.5) then y = 0 else if (x > -0.5) then y = 255 else /* not reached */ 4. A Window Center of 2n-1 and a Window Width of 2n selects the range of input values from 0 to 2n-1. This represents an identity VOI LUT transformation in the case where no Modality LUT is specified and the stored pixel data are n bit unsigned integers. 5. A Window Width of 1 is typically used to represent a "threshold" operation in which those integer input values less than the Window Center are represented as the minimum displayed value and those greater than or equal to the Window Center are represented as the maximum displayed value. A Window Width of 2 will have the same result for integral input values. 6. The application of Window Center (0028,1050) and Window Width (0028,1051) may select a signed input range. There is no implication that this signed input range is clipped to zero. 7. The selected input range may exceed the actual range of the input values, thus effectively “compressing” the contrast range of the displayed data into a narrower band of the available contrast range, and “flattening” the appearance. There are no limits to the maximum value of the window width, or to the minimum or maximum value of window level, both of which may exceed the actual or possible range of input values. 8. Input values "below" the window are displayed as the minimum output value and input values "above" the window are displayed as the maximum output value. This is the common usage of the window operation in medical imaging. There is no provision for an alternative approach in which all values "outside" the window are displayed as the minimum output value. 9. The output of the Window Center/Width or VOI LUT transformation is either implicitly scaled to the full range of the display device if there is no succeeding transformation defined, or implicitly scaled to the full input range of the succeeding transformation step (such as the Presentation LUT), if present. See C.11.6.1. 10. Fractional values of Window Center and Window Width are permitted (since the VR of these Attributes is Decimal String), and though they are not often encountered, applications should be prepared to accept them. These Attributes shall be used only for Images with Photometric Interpretation (0028,0004) values of MONOCHROME1 and MONOCHROME2. They have no meaning for other Images. 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 may be presented. If any VOI LUT Table is included by an Image, a Window Width and Window Center or the VOI LUT Table, but not both, may be applied to the Image for display. Inclusion of both indicates that multiple alternative views may be presented. If multiple items are present in VOI LUT Sequence (0028,3010), only one may be applied to the Image for display. Multiple items indicate that multiple alternative views may be presented. If the VOI LUT Module is defined in an IOD and if neither a VOI LUT Sequence nor a Window Width and Window Center are present, then the VOI LUT stage of the grayscale pipeline is defined to be an identity transformation. Notes: 1. This requirement is specified so that IODs that define a particular output space for the grayscale pipeline, such as P-Values, are not in an undefined state when no VOI LUT Sequence or Window Width and Window Center are present. 2. Despite the Type 3 requirement for VOI LUT Sequence and Window Center, implementations that render images are expected to implement and apply these transformations when they are present in the image, unless overridden by the user, a presentation state, or a hanging protocol, and to allow the user to select which transformation to apply when multiple transformations are present.
Free form explanation of the meaning of the Window Center and Width. Multiple values correspond to multiple Window Center and Width values. Describes a VOI LUT function to apply to the values of Window Center (0028,1050) and Window Width (0028,1051). See C.11.2.1.3 for further explanation. Defined terms: LINEAR SIGMOID When this attribute is not present, the interpretation of the values of Window Center (0028,1050) and Window Width (0028,1051) is linear as in C.11.2.1.2.
The VOI LUT Function (0028,1056) specifies a potentially non-linear conversion for the output of the (conceptual) Modality LUT values to the input of the (conceptual) Presentation LUT. The behavior for the value LINEAR is defined in C.11.2.1.2. For all other values, the VOI LUT Function (0028,1056) shall include a unique descriptor of the LUT function to be used. Each descriptor is associated with a bivariate function of Window Center (0028,1050) and Window Width (0028,1051). If the VOI LUT Function (0028,1056) is present with a value other than LINEAR, the values provided in Window Center (0028,1050) and Window Width (0028,1051) shall not be interpreted as a linear conversion of the (conceptual) Modality LUT values to the input to the (conceptual) Presentation LUT – but as parameters for the function defined by the VOI LUT Function descriptor in (0028,1056). When defined, each descriptor must provide the functional relationship between the output of the (conceptual) Modality LUT values to the input of the (conceptual) Presentation LUT.
Defines a sequence of Presentation LUTs. Only a single item shall be included in this sequence. Specifies the format of the LUT Data in this Sequence. Required if Presentation LUT Sequence (2050,0010) is sent. See C.11.4.1 for further explanation.
The three values of the LUT Descriptor (0028,3002) describe the format of the data in LUT Data (0028,3006). The first value is the number of entries in the lookup table. When the number of table entries is equal to 216 then this value shall be 0. The number of entries shall be equal to the number of possible values in the input. (For 8 bit input will be 256 entries, for 12 bit input it will be 4096 entries) The second value is the first input value mapped, and shall always be 0. The Value Representation of the second value is always US. This input value is mapped to the first entry in the LUT. Subsequent input values are mapped to the subsequent entries in the LUT Data up to an input value equal to number of entries + first value mapped - 1 which is mapped to the last entry in the LUT Data. There are no input values greater than number of entries – 1. The third value specifies the number of bits for each entry in the LUT Data. It shall be between 10 and 16 inclusive. The LUT Data shall be stored in a format equivalent to 16 bits allocated where the high bit is equal to bits stored - 1, where bits stored is the third value. Note: Since the LUT Descriptor (0028,3002) Attribute is multi-valued, in an Explicit VR Transfer Syntax, only one value representation (US or SS) may be specified. Since all three values are always by definition interpreted as unsigned, the explicit VR actually used will always be US. LUT Data (0028,3006) contains the LUT entry values, which are P-Values. The output range is from 0 to 2n-1 where n is the third value of LUT Descriptor. This range is always unsigned. This range specifies the output range of the P-Values.
Free form text explanation of the meaning of the LUT. LUT Data in this Sequence. Specifies pre-defined Presentation LUT shapes. Enumerated Values : IDENTITY = input to the Presentation LUT is in P-Values, no further translation is necessary. LIN OD = input to Presentation LUT is in linear optical density over the range of Min Density (2010,0120) and Max Density (2010,1030). Note: LIN OD is only defined for hardcopy devices and is not applicable to softcopy devices.
Defines a sequence of Histograms. One or more Items may be included in this Sequence. The number of "bins" (entries) in the histogram. The stored pixel value corresponding to the lowest pixel value counted in the first bin. All image pixel values less than this value are not included in the histogram. Note: The Value Representation of this Attribute is determined by the value of Pixel Representation (0028,0103). The stored pixel value corresponding to the highest pixel value counted in the last bin. All image pixel values greater than this value are not included in the histogram. Note: The Value Representation of this Attribute is determined by the value of Pixel Representation (0028,0103). The number of consecutive stored pixel values included in a bin. All bins shall be of equal width. Free form text explanation of the meaning of the LUT. Histogram Data encoded as 32 bit unsigned counts of the number of pixel values in each bin. Defines a sequence of Presentation LUTs. Only a single item shall be included in this sequence. Required if Presentation LUT Shape (2050,0020) is absent. Specifies the format of the LUT Data in this Sequence. See C.11.6.1.1 for further explanation.
The three values of the LUT Descriptor (0028,3002) describe the format of the LUT Data in the corresponding Data Element (0028,3006). The first value is the number of entries in the lookup table. When the number of table entries is equal to 216 then this value shall be 0. The second value is the first implicitly scaled input value mapped, and shall always be 0. The Value Representation of the second value is always US. This implicitly scaled input value is mapped to the first entry in the LUT. There are no implicitly scaled input values less than the first value mapped. An implicitly scaled input value one greater than the first value mapped is mapped to the second entry in the LUT Data. Subsequent implicitly scaled input values are mapped to the subsequent entries in the LUT Data up to an implicitly scaled input value equal to number of entries + first value mapped - 1 which is mapped to the last entry in the LUT Data. There are no implicitly scaled input values greater than number of entries + first value mapped. The third value specifies the number of bits for each entry in the LUT Data. The third value of the LUT Descriptor (0028,3002) shall be between 8 and 16 inclusive. The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where the high bit is equal to bits stored - 1, and where bits stored is the third value. Notes: 1. Since the LUT Descriptor (0028,3002) Attribute is multi-valued, in an Explicit VR Transfer Syntax, only one value representation (US or SS) may be specified. Since all three values are always by definition interpreted as unsigned, the explicit VR actually used will always be US. 2. Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits; this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry. The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16. The LUT Data contains the LUT entry values, which are P-Values. The output range is from 0 to 2n-1 where n is the third value of LUT Descriptor. This range is always unsigned. This range specifies the output range of the P-Values.
Free form text explanation of the meaning of the LUT. LUT Data in this Sequence. Specifies predefined Presentation LUT transformation. Required if Presentation LUT Sequence (2050,0010) is absent. Enumerated Values: IDENTITY - no further translation necessary, input values are P-Values INVERSE - output values after inversion are P-Values See C.11.6.1.2.
A value of INVERSE shall mean the same as a value of IDENTITY, except that the minimum output value shall convey the meaning of the maximum available luminance, and the maximum value shall convey the minimum available luminance. In other words: P-Value = maximum value - output value
The layer (defined in Graphic Layer (0070,0002) of the Graphic Layer Module C.10.7) in which the Overlay described in group 60xx shall be displayed. If no layer is specified (zero length) then the overlay shall not be displayed. Required if Group 60xx is present in the referenced image(s) or the Presentation State instance containing this Module. Defines a sequence of VOI LUTs or Window Centers and Widths and to which images and frames they apply. No more than one VOI LUT Sequence containing a single Item or one pair of Window Center/Width values shall be specified for each image or frame. One or more Items shall be present. Sequence of Items where each Item provides reference to a selected set of Image SOP Class/SOP Instance pairs that are defined in the Presentation State Relationship Module, to which this VOI LUT or Window Center and Width applies. One or more Items shall be present. Required if the VOI LUT transformation in this Item does not apply to all the images and frames listed in the Presentation State Relationship Module. Type of equipment that originally acquired the data. Enumerated Value: PR = Presentation State See C.7.3.1.1.1.
Defined Terms for the Modality (0008,0060) are: Retired Defined Terms for the Modality (0008,0060) are: Note: 1. The XA modality incorporates the retired modality DS. 2. The RF modality incorporates the retired modalities CF, DF, VF. 3. The modality listed in the Modality Data Element (0008,0060) may not match the name of the IOD in which it appears. For example, a SOP instance from XA IOD may list the RF modality when an RF implementation produces an XA object. 4. The MR modality incorporates the retired modalities MA and MS.
Date on which this presentation was created. Note: This date may be different from the date that the DICOM SOP Instance was created, since the presentation state information contained may have been recorded earlier. Time at which this presentation was created. Note: This time may be different from the time that the DICOM SOP Instance was created, since the presentation state information contained may have been recorded earlier. Sequence of Items where each Item includes the Attributes of one Series to which the Presentation applies. One or more Items shall be present. Unique identifier of a Series that is part of the Study defined by the Study Instance UID (0020,000D) in the enclosing dataset. Note: The Study Instance UID (0020,000D) will be that of the presentation state itself, unless the macro is invoked from the Blending Sequence (0070,0402) in the Presentation State Blending Module, in which case it will be explicitly specified. Sequence of Items where each Item provides reference to a selected set of Image SOP Class/SOP Instance pairs to which the Presentation applies that are part of the Study defined by Study Instance UID (0020,000D) and the Series defined by Series Instance UID (0020,000E). One or more Items shall be present. The referenced SOP Class shall be the same for all Images in any Item of this Referenced Series Sequence (0008,1115). A single grayscale unsigned value used to replace those parts of the image occluded by the shutter, when rendered on a monochrome display. The units are specified in P-Values. Required if the Display Shutter Module or Bitmap Display Shutter Module is present. Note: The requirement in this module is type 1C which overrides the type 3 in the Display Shutter Module. A color triplet value used to replace those parts of the image occluded by the shutter, when rendered on a color display. The units are specified in PCS-Values, and the value is encoded as CIELab. See C.10.7.1.1. Required if the Display Shutter Module or Bitmap Display Shutter Module is present and the SOP Class is other than Grayscale Softcopy Presentation State Storage. Note: The requirement in this module is type 1C, which overrides the type 3 in the Display Shutter and Bitmap Display Shutter Modules.
Attributes such as Graphic Layer Recommended Display CIELab Value (0070,0401) consist of three unsigned short values:
Required if Mask Module is present. Only one Item shall be present. Applicable Frame Range (0028,6102) shall not be included in the Sequence Item. See C.7.6.10 for a complete definition of the Attributes in the Items of this Sequence other than Mask Operation(0028,6101) and Applicable Frame Range (0028,6102). Notes: 1. This Sequence is replicated here in order to specify one Item, additional conditions on Mask Operation (0028,6101) and to forbid Applicable Frame Range (0028,6102). 2. The role of Applicable Frame Range (0028,6102) is replaced by Referenced Frame Number (0008,1160).
Table C.7-16 specifies the Attributes that describe mask operations for a Multi-frame image. Table C.7-16 MASK MODULE ATTRIBUTES Note: Frame numbers begin at 1.
Type of mask operation to be performed Enumerated Values: AVG_SUB TID See C.7.6.10.1 for further explanation. Note: The requirement in this module is for Enumerated Values which override the requirements of the Mask Module.
Specified the number of contrast frames to average together before performing the mask operation. Required if Mask Frame Numbers (0028,6110) specifies more than one frame (i.e. is multi-valued). Note: The requirement in this module is conditional and overrides the optional requirements of the Mask Module. Specifies the recommended viewing protocol(s). Enumerated Value: SUB = for subtraction with mask images Required if Mask Subtraction Sequence (0028,6100) is present. Note: The requirement in this module is type 1C and an Enumerated Value is specified which override the requirements of the Mask Module. A Sequence of exactly two Items, one identifying and describing transformations upon a set of underlying grayscale images, and the other identifying and describing transformations upon a set of superimposed grayscale images. See C.11.14.1.1.
The Blending Sequence (0070,0402) Attribute is used to identify two sets of images, one to be superimposed upon the other. The sets of images and any subset of the frames therein in the case of multi-frame images are identified by Study, Series, SOP Instance and Frame Number. This module specifies no explicit relationship (such as pairing or ordering) between the sets of images and frames defined in the first item for the underlying images, and the second item for the superimposed images. This module does not define how the images are spatially related, and what re-sampling, if any, needs to be performed before the images are blended for rendering. Note: The images in the two sets may share the same Frame of Reference, in which case the rendering application can spatially relate the two sets of images based on their Image Position (Patient) (0020,0032) and Image Orientation (Patient) (0020,0037) Attributes. Alternatively, a Spatial Registration SOP Instance may exist that relates either two different Frames of Reference, or two sets of images identified by UID and frame. Whilst the two sets of images may already be spatially co-registered and oriented in the same plane, or even be sampled at the same in-plane and between-plane resolution, this will frequently not be the case. See PS 3.4 for behavioral requirements that apply to Storage SOP Classes using this Module.
Whether or not the contents of the Item represent the superimposed or underlying image set. Enumerated Values: SUPERIMPOSED UNDERLYING Unique identifier for the Study that contains the images, which may differ from the Study in which the presentation state is contained. Defines a sequence of VOI LUTs or Window Centers and Widths and to which images and frames they apply. No more than one VOI LUT Sequence containing a single Item or one pair of Window Center/Width values shall be specified for each image or frame. One or more Items shall be present. Required if a VOI LUT is to be applied to referenced image(s). Sequence of Items identifying images that are defined in the enclosing Item of the Blending Sequence (0070,0402), to which this VOI LUT or Window Center and Width applies. One or more Items shall be present. Required if the VOI LUT transformation in this Item does not apply to all the images and frames in the enclosing Item of the Blending Sequence (0070,0402). A value from 0.0 to 1.0 indicating the relative opacity of the pixels of the superimposed image, where 1.0 means that pixels of the superimposed image completely replace the pixels of the underlying image, and 0.0 means that the pixels of the underlying image completely replace the pixels of the superimposed image. See PS 3.4 for a detailed description of the blending operation. A reference to Spatial Registration Instances that may be used to register the underlying and superimposed images. Zero or more Items may be present. Note: A Spatial Registration Instance may identify registration between frames of reference, or between explicitly identified images. In the latter case, the list of images referenced by the Presentation State, not the list of images referenced by the Spatial Registration Instance, are to be blended.
An ICC Profile encoding the transformation of device-dependent color stored pixel values into PCS-Values. Uniquely identifies the SOP Class. See C.12.1.1.1 for further explanation. See also PS 3.4.
The SOP Class UID and SOP Instance UID Attributes are defined for all DICOM IODs. However, they are only encoded in Composite IODs with the Type equal to 1. See C.1.2.3. When encoded they shall be equal to their respective Attributes in the DIMSE Services and the File Meta Information header (see PS 3.10 Media Storage).
Uniquely identifies the SOP Instance. See C.12.1.1.1 for further explanation. See also PS 3.4.
The SOP Class UID and SOP Instance UID Attributes are defined for all DICOM IODs. However, they are only encoded in Composite IODs with the Type equal to 1. See C.1.2.3. When encoded they shall be equal to their respective Attributes in the DIMSE Services and the File Meta Information header (see PS 3.10 Media Storage).
Character Set that expands or replaces the Basic Graphic Set. Required if an expanded or replacement character set is used. See C.12.1.1.2 for Defined Terms.
Specific Character Set (0008,0005) identifies the Character Set that expands or replaces the Basic Graphic Set (ISO 646) for values of Data Elements that have Value Representation of SH, LO, ST, PN, LT or UT. See PS 3.5. If the Attribute Specific Character Set (0008,0005) is not present or has only a single value, Code Extension techniques are not used. Defined terms for the Attribute Specific Character Set (0008,0005), when single valued, are derived from the International Registration Number as per ISO 2375 (e.g., ISO_IR 100 for Latin alphabet No. 1). See Table C.12-2. Table C.12-2 DEFINED TERMS FOR SINGLE-BYTE CHARACTER SETS WITHOUT CODE EXTENSIONS Note: To use the single-byte code table of JIS X0201, the value of attribute Specific Character Set (0008,0005), value 1 should be ISO_IR 13. This means that ISO-IR 13 is designated as the G1 code element which is invoked in the GR area. It should be understood that, in addition, ISO-IR 14 is designated as the G0 code element and this is invoked in the GL area. If the attribute Specific Character Set (0008,0005) has more than one value, Code Extension techniques are used and Escape Sequences may be encountered in all character sets. Requirements for the use of Code Extension techniques are specified in PS 3.5. In order to indicate the presence of Code Extension, the Defined Terms for the repertoires have the prefix “ISO 2022”, e.g., ISO 2022 IR 100 for the Latin Alphabet No. 1. See Table 12-3 and Table 12-4. Table 12-3 describes single-byte character sets for value 1 to value n of the attribute Specific Character Set (0008,0005), and Table 12-4 describes multi-byte character sets for value 2 to value n of the attribute Specific Character Set (0008,0005). Note: A prefix other than “ISO 2022” may be needed in the future if other Code Extension techniques are adopted. Table C.12-3 DEFINED TERMS FOR SINGLE-BYTE CHARACTER SETS WITH CODE EXTENSIONS Note: If the attribute Specific Character Set (0008,0005) has more than one value and value 1 is empty, it is assumed that value 1 is ISO 2022 IR 6. Table C.12-4 DEFINED TERMS FOR MULTI-BYTE CHARACTER SETS WITH CODE EXTENSIONS There are multi-byte character sets that prohibit the use of Code Extension Techniques. The Unicode character set used in ISO 10646, when encoded in UTF-8, and the GB18030 character set, encoded per the rules of GB18030, both prohibit the use of Code Extension Techniques. These character sets may only be specified as value 1 in the Specific Character Set (0008,0005) attribute and there shall only be one value. The minimal length UTF-8 encoding shall always be used for ISO 10646. Notes: 1. The ISO standards for 10646 now prohibit the use of anything but the minimum length encoding for UTF-8. UTF-8 permits multiple different encodings, but when used to encode Unicode characters in accordance with ISO 10646-1 and 10646-2 (with extensions) only the minimal encodings are legal. 2. The representation for the characters in the DICOM Default Character Repertoire is the same single byte value for the Default Character Repertoire, ISO 10646 in UTF-8, and GB18030. It is also the 7-bit US-ASCII encoding. Table C.12-5 DEFINED TERMS FOR MULTI-BYTE CHARACTER SETS WITHOUT CODE EXTENSIONS
Date the SOP Instance was created. Time the SOP Instance was created. Uniquely identifies device which created the SOP Instance. Uniquely identifies a Related General SOP Class for the SOP Class of this Instance. See PS 3.4. The SOP Class in which the Instance was originally encoded, but which has been replaced during a fall-back conversion to the current Related General SOP Class. See PS 3.4. Sequence of items that map values of Coding Scheme Designator (0008,0102) to an external coding system registration, or to a private or local coding scheme. One or more items may be present in the sequence. The value of a Coding Scheme Designator, used in this SOP Instance, which is being mapped. The name of the external registry where further definition of the identified coding scheme may be obtained. Required if coding scheme is registered. Defined term: HL7 The coding scheme UID identifier. Required if coding scheme is identified by an ISO 8824 object identifier compatible with the UI VR. The coding scheme identifier as defined in an external registry. Required if coding scheme is registered and Coding Scheme UID (0008,010C) is not present. The coding scheme full common name The coding scheme version associated with the Coding Scheme Designator (0008,0102). Name of the organization responsible for the Coding Scheme. May include organizational contact information. Contains the offset from UTC to the timezone for all DA and TM Attributes present in this SOP Instance, and for all DT Attributes present in this SOP Instance that do not contain an explicitly encoded timezone offset. Encoded as an ASCII string in the format "&ZZXX". The components of this string, from left to right, are & = "+" or "-", and ZZ = Hours and XX = Minutes of offset. Leading space characters shall not be present. The offset for UTC shall be +0000; -0000 shall not be used. Notes: 1. This encoding is the same as described in PS 3.5 for the offset component of the DT Value Representation. 2. This Attribute does not apply to values with a DT Value Representation, that contains an explicitly encoded timezone offset. 3. The corrected time may cross a 24 hour boundary. For example, if Local Time = 1.00 a.m. and Offset = +0200, then UTC = 11.00 p.m. (23.00) the day before. 4. The "+" sign may not be omitted. Time earlier than UTC is expressed as a negative offset. Note: For example: UTC = 5.00 a.m. Local Time = 3.00 a.m. Offset = -0200 The local timezone offset is undefined if this Attribute is absent. Sequence of Items containing descriptive attributes of related equipment which has contributed to the acquisition, creation or modification of the composite instance. One or more Items may be included in this Sequence. See C.12.1.1.5 for further explanation.
Contributing Equipment Sequence (0018,A001) allows equipment to be described which has contributed towards the creation of the composite instance. The general class of contribution is denoted via a coded entry within the Purpose of Reference Code Sequence (0040,A170). Notes: 1. For example, a post-processing application creating DERIVED images from ORIGINAL images would place its own identification within the Equipment Module and identify the original acquisition equipment as an Item within the Contributing Equipment Sequence (0018,A001). Here, the value of the Purpose of Reference Code Sequence (0040,A170) within the Item would be (109101, DCM, ”Acquisition Equipment"). Image display applications wishing to annotate images with information related to the acquisition environment would prefer to extract such details from the Contributing Equipment Sequence rather than the Equipment Module. 2. For example, an image fusion application would place its own identification within the Equipment Module and identify each of the original acquisition equipment as separate Items within the Contributing Equipment Sequence (0018,A001). Here, the value of the Purpose of Reference Code Sequence (0040,A170) within each Item would be (109101, DCM, ”Acquisition Equipment"). 3. For example, a post-processing application creating DERIVED images from other DERIVED images would place its own identification within the Equipment Module and add the source equipment as an additional Item within the Contributing Equipment Sequence (0018,A001). Here, the value of the Purpose of Reference Code Sequence (0040,A170) within the Item would be (109102, DCM, ”Processing Equipment"). 4. For example, a gateway device that coerces attributes of existing composite instances (without creating new composite instances) would retain information about the creating equipment within the Equipment Module and provide its own identification as an Item within the Contributing Equipment Sequence (0018,A001). Here, the value of the Purpose of Reference Code Sequence (0040,A170) within the Item would be (109103, DCM, ”Modifying Equipment").
Describes the purpose for which the related equipment is being reference. Only a single Item shall be permitted in this sequence. See C.12.1.1.5 for further explanation.
Contributing Equipment Sequence (0018,A001) allows equipment to be described which has contributed towards the creation of the composite instance. The general class of contribution is denoted via a coded entry within the Purpose of Reference Code Sequence (0040,A170). Notes: 1. For example, a post-processing application creating DERIVED images from ORIGINAL images would place its own identification within the Equipment Module and identify the original acquisition equipment as an Item within the Contributing Equipment Sequence (0018,A001). Here, the value of the Purpose of Reference Code Sequence (0040,A170) within the Item would be (109101, DCM, ”Acquisition Equipment"). Image display applications wishing to annotate images with information related to the acquisition environment would prefer to extract such details from the Contributing Equipment Sequence rather than the Equipment Module. 2. For example, an image fusion application would place its own identification within the Equipment Module and identify each of the original acquisition equipment as separate Items within the Contributing Equipment Sequence (0018,A001). Here, the value of the Purpose of Reference Code Sequence (0040,A170) within each Item would be (109101, DCM, ”Acquisition Equipment"). 3. For example, a post-processing application creating DERIVED images from other DERIVED images would place its own identification within the Equipment Module and add the source equipment as an additional Item within the Contributing Equipment Sequence (0018,A001). Here, the value of the Purpose of Reference Code Sequence (0040,A170) within the Item would be (109102, DCM, ”Processing Equipment"). 4. For example, a gateway device that coerces attributes of existing composite instances (without creating new composite instances) would retain information about the creating equipment within the Equipment Module and provide its own identification as an Item within the Contributing Equipment Sequence (0018,A001). Here, the value of the Purpose of Reference Code Sequence (0040,A170) within the Item would be (109103, DCM, ”Modifying Equipment").
Manufacturer of the equipment that contributed to the composite instance. Institution where the equipment that contributed to the composite instance is located. Address of the institution where the equipment that contributed to the composite instance is located. User defined name identifying the machine that contributed to the composite instance. Department in the institution where the equipment that contributed to the composite instance is located. Manufacturer's model name of the equipment that contributed to the composite instance. Manufacturer's serial number of the equipment that contributed to the composite instance. Manufacturer's designation of the software version of the equipment that contributed to the composite instance. The inherent limiting resolution in mm of the acquisition equipment for high contrast objects for the data gathering and reconstruction technique chosen. If variable across the images of the series, the value at the image center. Date when the image acquisition device calibration was last changed in any way. Multiple entries may be used for additional calibrations at other times. See C.7.5.1.1.1 for further explanation.
Date of Last Calibration (0018,1200) and Time of Last Calibration (0018,1201) are used to convey the date and time of calibration. The Attribute Date of Last Calibration (0018,1200) may be supported alone, however, Time of Last Calibration (0018,1201) Attribute has no meaning unless Attribute Date of Last Calibration (0018,1200) is also supported. The order for each Attribute shall be from the oldest date/time to the most recent date/time. When the Attributes are both supported they shall be provided as pairs.
Time when the image acquisition device calibration was last changed in any way. Multiple entries may be used. See C.7.5.1.1.1 for further explanation.
Date of Last Calibration (0018,1200) and Time of Last Calibration (0018,1201) are used to convey the date and time of calibration. The Attribute Date of Last Calibration (0018,1200) may be supported alone, however, Time of Last Calibration (0018,1201) Attribute has no meaning unless Attribute Date of Last Calibration (0018,1200) is also supported. The order for each Attribute shall be from the oldest date/time to the most recent date/time. When the Attributes are both supported they shall be provided as pairs.
The Date & Time when the equipment contributed to the composite instance. Description of the contribution the equipment made to the composite instance. A number that identifies this Composite object instance. A flag that indicates the storage status of the SOP Instance. Not Specified (NS) implies that this SOP Instance has no special storage status, and hence no special actions need be taken. Original (OR) implies that this is the primary SOP instance for the purpose of storage, but that it has not yet been authorized for diagnostic use. Authorized Original (AO) implies that this is the primary SOP instance for the purpose of storage, which has been authorized for diagnostic use. Any copies of an Authorized Original should be given the status of Authorized Copy. Authorized Copy (AC) implies that this is a copy of an Authorized Original SOP Instance. Enumerated Values: NS, OR, AO, AC Note: Proper use of these flags is specified in Security Profiles. Implementations that do not conform to such Security Profiles may not necessarily handle these flags properly. The date and time when the SOP Instance Status (0100,0410) was set to AO. Any comments associated with the setting of the SOP Instance Status (0100,0410) to AO. The certification number issued to the Application Entity that set the SOP Instance Status (0100,0410) to AO. Sequence of Items containing encrypted DICOM data. One or more Items shall be present. Required if application level confidentiality is needed and certain recipients are allowed to decrypt all or portions of the Encrypted Attributes Data Set. See C.12.1.1.4.1.
Each Item of the Encrypted Attributes Sequence (0400,0500) contains an encrypted DICOM dataset containing a single instance of the Encrypted Attributes Data Set (Table C.12-7). It also contains encrypted content-encryption keys for one or more recipients. The encoding is based on the Enveloped-data Content Type of the Cryptographic Message Syntax defined in RFC 2630. It allows to encrypt the embedded Data Set for an arbitrary number of recipients using any of the three key management techniques supported by RFC 2630:
Transfer Syntax used to encode the encrypted content. Only Transfer Syntaxes that explicitly include the VR and use Little Endian encoding shall be used. Encrypted data. See C.12.1.1.4.2.
The Encrypted Content (0400,0520) Attribute contains an Enveloped-data content type of the cryptographic message syntax defined in RFC 2630. The encrypted content of the Enveloped-data content type is an instance of the Encrypted Attributes Data Set as shown in Table C.12-7 (i.e., it is a Sequence with a single Item), encoded with the Transfer Syntax specified by the Encrypted Content Transfer Syntax UID (0400,0510) Attribute. Figure C.12-2 shows an example of how the Encrypted Content is encoded. The exact use of this Data Set is defined in the Attribute Confidentiality Profiles in PS 3.15. Since the de-identified SOP Instance is a significantly altered version of the original Data Set, it is a new SOP Instance, with a SOP Instance UID that differs from the original Data Set. Note: 1. Content encryption may require that the content (the DICOM Data Set) be padded to a multiple of some block size. This shall be performed according to the Content-encryption Process defined in RFC-2630. 2. Any standard or private Transfer Syntax may be specified in Encrypted Content Transfer Syntax UID (0400,0510) unless encoding is performed in accordance with an Attribute Confidentiality Profile that specifies additional restrictions. In general, an application entity decoding the Encrypted Attributes Sequence may not assume any particular Transfer Syntax or set of Transfer Syntaxes to be used with Encrypted Content Transfer Syntax UID (0400,0510). 3. For certain applications it might be necessary to “blacken” (remove) identifying information that is burned in to the image pixel data. The Encrypted Attributes Data Set does not specify a means of restoring the original image information without the complete image pixel data being encoded inside the Modified Attributes Sequence (0400,0550). If access to the original, unmodified pixel data is required and the image pixel data cannot be replicated inside the Modified Attributes Sequence (0400,0550) due to resource considerations, the SOP Instance UID may be used to locate the original SOP Instance from which the de-identified version was derived. 4. There is no guarantee that the original SOP Instance can be reconstructed from the data in Encrypted Content. If access to the original data is required, the (de-encrypted) UIDs may be used to locate the original SOP Instance from which the de-identified version was derived. Table C.12-7 ENCRYPTED ATTRIBUTES DATA SET ATTRIBUTES
Sequence of Items containing all attributes that were removed or replaced by other values in the main dataset. One or more Items may be permitted in this sequence. The source that provided the SOP Instance prior to the removal or replacement of the values. For example, this might be the Institution from which imported SOP Instances were received. Date and time the attributes were removed and/or replaced. Identification of the system which removed and/or replaced the attributes. Reason for the attribute modification. Defined terms are: COERCE = Replace values of attributes such as Patient Name, ID, Accession Number, for example, during import of media from an external institution, or reconciliation against a master patient index. CORRECT = Replace incorrect values, such as Patient Name or ID, for example, when incorrect worklist item was chosen or operator input error. Sequence containing a single item that contains all the Attributes, with their previous values, that were modified or removed from the main data set. Sequence of items defining mapping and/or access mechanism for HL7 Structured Documents referenced from the current SOP Instance. One or more Items may be included in this sequence. See C.12.1.1.6. Required if HL7 Structured Documents are referenced within the Instance.
The HL7 Structured Document Reference Sequence (0040,A390) identifies instances of Structured Documents defined under an HL7 standard. The HL7 standards that define such documents include the Clinical Document Architecture (CDA) and Structured Product Labeling (SPL) standards. References to HL7 Structured Documents from within DICOM SOP Instances shall be encoded with a SOP Class UID and SOP Instance UID pair. The Abstract Syntax of an HL7 Structured Document is defined by its Hierarchical Message Description; the Object Identifier of the Hierarchical Message Description shall be used as the SOP Class UID for the Structured Document reference. Notes: 1. The Hierarchical Message Description Object Identifiers are specified in the HL7 OID Registry (http://hl7.org/oid). The HL7 OIDs for these types of documents are: CDA Release 1 2.16.840.1.113883.1.7.1 CDA Release 2 2.16.840.1.113883.1.7.2 SPL Release 1 2.16.840.1.113883.1.7.3 2. The Hierarchical Message Description Object Identifiers do not imply a network or media storage service, as do SOP Class UIDs. However, they do identify the Abstract Syntax, similar to SOP Class UIDs. The HL7 Structured Document instances are natively identified by an attribute using the Instance Identifier (II) Data Type, as defined in HL7 v3 Data Types - Abstract Specification. A UID as defined by the DICOM UI Value Representation is a valid identifier under the II Data Type; however, an II attribute is not always encodable as a UID. Therefore a UID shall be constructed for use within the DICOM Data Set that can be mapped to the native instance identifier encoded as an HL7 II Data Type. This mapping is performed through the combination of the local Referenced SOP Instance UID (0008,1155) and the HL7 Instance Identifier (0040,E001) attributes in the HL7 Structured Document Reference Sequence (0040,A390). Notes: 1. An HL7 II is not encodable as a UID if it exceeds 64 characters, or if it includes an extension. See HL7 v3 DT R1. 2. Even though an II may contain just a UID, applications should take care to use the II specified in HL7 Instance Identifier (0040,E001) to access the Structured Document. If the instance identifier used natively within the referenced document is encodable using the UI VR, i.e., it is an ISO 8824 OID up to 64 characters without an extension, it is recommended to be used as the Referenced SOP Instance UID within the current Instance. 3. The Referenced SOP Instance UID used to reference a particular HL7 Structured Document is not necessarily the same in all DICOM Instances. For example, two SR Documents may internally use different SOP Instance UIDs to reference the same HL7 Structured Document, but they will each contain a mapping to the same HL7 Instance Identifier as the external identifier. 4. The HL7 Instance Identifier is encoded in attribute (0040,E001) as a serialization of the UID and Extension (if any) separated by a caret character. This is the same format adopted in the IHE Cross-Enterprise Document Sharing (XDS) profile (see http://www.ihe.net). 5. See Figure C.12-3. Figure C.12-3 HL7 Structured Document References
Unique identifier for the class of HL7 Structured Document. Unique identifier for the HL7 Structured Document as used in DICOM instance references. Instance Identifier of the referenced HL7 Structured Document, encoded as a UID (OID or UUID), concatenated with a caret ("^") and Extension value (if Extension is present in Instance Identifier). Retrieval access path to HL7 Structured Document. Includes fully specified scheme, authority, path, and query in accordance with RFC 2396
A sequence of one or more items that describe the parameters used to calculate a MAC for use in Digital Signatures. A number, unique within this SOP Instance, used to identify this MAC Parameters Sequence (4FFE,0001) item from an Item of the Digital Signatures Sequence (FFFA,FFFA). The Transfer Syntax UID used to encode the values of the Data Elements included in the MAC calculation. Only Transfer Syntaxes that explicitly include the VR and use Little Endian encoding shall be used. Notes: Certain Transfer Syntaxes, particularly those that are used with compressed data, allow the fragmentation of the pixel data to change. If such fragmentation changes, Digital Signatures generated with such Transfer Syntaxes could become invalid. The algorithm used in generating the MAC to be encrypted to form the Digital Signature. Defined Terms: RIPEMD160 MD5 SHA1 . Note: Digital Signature Security Profiles (see PS 3.15) may require the use of a restricted subset of these terms. A list of Data Element Tags in the order they appear in the Data Set which identify the Data Elements used in creating the MAC for the Digital Signature. See Section C.12.1.1.3.1.1.
The Data Elements Signed Attribute shall list the Tags of the Data Elements that are included in the MAC calculation. The Tags listed shall reference Data Elements at the same level as the Mac Parameters Sequence (4FFE,0001) Data Element in which the Data Elements Signed Attribute appears. Tags included in Data Elements Signed shall be listed in the order in which they appear within the Data Set. The following Data Elements shall not be included either implicitly or explicitly in the list of Tags in Data Elements Signed, nor included as part of the MAC calculation:
Sequence holding Digital Signatures. One or more items may be included in this sequence. A number used to identify which MAC Parameters Sequence item was used in the calculation of this Digital Signature. A UID that can be used to uniquely reference this signature. The date and time the Digital Signature was created. The time shall include an offset (i.e., time zone indication) from Coordinated Universal Time. Note: This is not a certified timestamp, and hence is not completely verifiable. An application can compare this date and time with those of other signatures and the validity date of the certificate to gain confidence in the veracity of this date and time. The type of certificate used in (0400,0115). Defined Term: X509_1993_SIG Note: Digital Signature Security Profiles (see PS 3.15) may require the use of a restricted subset of these terms. A certificate that holds the identity of the entity producing this Digital Signature, that entity's public key or key identifier, and the algorithm and associated parameters with which that public key is to be used. Algorithms allowed are specified in Digital Signature Security Profiles (see PS 3.15). Notes: 1. As technology advances, additional encryption algorithms may be allowed in future versions. Implementations should take this possibility into account. 2. When symmetric encryption is used, the certificate merely identifies which key was used by which entity, but not the actual key itself. Some other means (e.g., a trusted third party) must be used to obtain the key. The MAC generated as described in Section C.12.1.1.3.1.1 and encrypted using the algorithm, parameters, and private key associated with the Certificate of the Signer (0400,0115). See Section C.12.1.1.3.1.2.
To generate the MAC, Data Elements referenced either explicitly or implicitly by the Tags in the Data Elements Signed list shall be encoded using the Transfer Syntax identified by the MAC Calculation Transfer Syntax UID (0400,0010) of the MAC Parameters Sequence item where the Data Elements Signed Attribute appears. Data shall be formed into a byte stream and presented to the MAC Algorithm for computation of the MAC according to the following rules: For all Data Elements except those with a VR of SQ or with a VR of OB with an undefined length, all Data Element fields, including the Tag, the VR, the reserved field (if any), the Value Length, and the Value, shall be placed into the byte stream in the order encountered. For Data Elements with a VR of SQ or with a VR of OB with an undefined length, the Tag, the VR, and the reserved field are placed into the byte stream. The Value Length shall not be included. This is followed by each Item Tag in the order encountered, without including the Value Length, followed by the contents of the Value for that item. In the case of an Item within a Data Element whose VR is SQ, these rules are applied recursively to all of the Data Elements within the Value of that Item. After all the Items have been incorporate into the byte stream, a Sequence Delimitation Item Tag (FFFE,E0DD) shall be added to the byte stream presented to the MAC Algorithm, regardless of whether or not it was originally present. Note: Since the Value Length of Data Elements with a VR of SQ can be either explicit or undefined, the Value Lengths of such Data Elements are left out of the MAC calculation. Similarly, the Value Length of Data Elements with a VR of OB with an undefined length are also left out so that they are handled consistently. If such Data Elements do come with undefined lengths, including the Item Tags that separate the Items or fragments insures that Data Elements cannot be moved between Items or Fragments without compromising the Digital Signature. For those Data Elements with explicit lengths, if the length of an item changes, the added or removed portions would also impact the MAC calculation, so it is not necessary to include explicit lengths in the MAC calculation. It is possible that including the Value Lengths could make cryptoanalysis easier. After the fields of all the Data Elements in the Data Elements Signed list have been placed into the byte stream presented to the MAC Algorithm according to the above rules, all of the Data Elements within the Digital Signatures Sequence item except the Certificate of Signer (0400,0115), Signature (0400,0120), Certified Timestamp Type (0400,0305), and Certified Timestamp (0400,0310) shall also be encoded according to the above rules, and presented to the MAC algorithm (i.e., the Attributes of the Digital Signature Sequence Item for this particular Digital Signature are also implicitly included in the list of Data Elements Signed, except as noted above). The resulting MAC code after processing this byte stream by the MAC Algorithm is then encrypted as specified in the Certificate of Signer and placed in the Value of the Signature Data Element. Notes: 1. The Transfer Syntax used in the MAC calculation may differ from the Transfer Syntax used to exchange the Data Set. 2. Digital Signatures require explicit VR in order to calculate the MAC. An Application Entity which receives a Data Set with an implicit VR Transfer Syntax may not be able to verify Digital Signatures that include Private Data Elements or Data Elements unknown to that Application Entity.This also true of any Data Elements whose VR is UN. Without knowledge of the Value Representation, the receiving Application Entity would be unable to perform proper byte swapping or be able to properly parse sequences in order to generate a MAC. 3. If more than one entity signs, each Digital Signature would appear in its own Digital Signatures Sequence item. The Digital Signatures may or may not share the same MAC Parameters Sequence item. 4. The notion of a notary public (i.e., someone who verifies the identity of the signer) for Digital Signatures is partially filled by the authority that issued the Certificate of Signer.
The type of certified timestamp used in the Certified Timestamp (0400,0310) Attribute. Required if Certified Timestamp (0400,0310) is present. Defined Terms: CMS_TSP - Internet X.509 Public Key Infrastructure Time Stamp Protocol Note: Digital Signature Security Profiles (see PS 3.15) may require the use of a restricted subset of these terms. A certified timestamp of the Digital Signature (0400,0120) Attribute Value, which shall be obtained when the Digital Signature is created. See Section C.12.1.1.3.1.3.
To generate a certified timestamp, the Value of the Signature (0400,0120) Attribute is sent to a third party, as specified by the protocol referred to by the Certified Timestamp Type (0400,0305) Attribute. The third party then generates and returns a certified timestamp in the form specified by that protocol. The certified timestamp returned by the third party is encoded as a stream of bytes in the Certified Timestamp Attribute. Note: The timestamp protocol may be specified by a Profile in PS 3.15.
The purpose of this Digital Signature. Only a single Item shall be permitted in this sequence.
Sequence of Items containing all Attributes that were removed or replaced by "dummy values" in the main dataset during de-identification of the SOP instance. Upon reversal of the de-identification process, the Attributes are copied back into the main dataset, replacing any dummy values that might have been created. Only a single Item shall be present. Sequence of items each identifying a Study other than the Study of which this Instance is a part, which Studies contain Instances that are referenced elsewhere in this Instance. One or more Items shall be present. Required if this Instance references Instances in other Studies. Unique identifier of the Study containing the referenced Instances. Number of copies to be printed for each film of the film session. Specifies the priority of the print job. Enumerated Values: HIGH MED LOW Type of medium on which the print job will be printed. Defined Terms: PAPER CLEAR FILM BLUE FILM MAMMO CLEAR FILM MAMMO BLUE FILM Film destination. Defined Terms: MAGAZINE = the exposed film is stored in film magazine PROCESSOR = the exposed film is developed in film processor BIN_i = the exposed film is deposited in a sorter bin where "I" represents the bin number. Film sorter BINs shall be numbered sequentially starting from one and no maxiumu is placed on the number of BINs. The encoding of the BIN number shall not contain leading zeros. Human readable label that identifies the film session Amount of memory allocated for the film session. Value is expressed in KB Identification of the owner of the film session A Sequence which provides references to a set of Film Box SOP Class/Instance pairs. Zero or more Items may be included in this Sequence. Type of image display format. Enumerated Values: STANDARD\C,R : film contains equal size rectangular image boxes with R rows of image boxes and C columns of image boxes; C and R are integers. ROW\R1,R2,R3, etc. : film contains rows with equal size rectangular image boxes with R1 image boxes in the first row, R2 image boxes in second row, R3 image boxes in third row, etc.; R1, R2, R3, etc. are integers. COL\C1,C2,C3, etc.: film contains columns with equal size rectangular image boxes with C1 image boxes in the first column, C2 image boxes in second column, C3 image boxes in third column, etc.; C1, C2, C3, etc. are integers. SLIDE : film contains 35mm slides; the number of slides for a particular film size is configuration dependent. SUPERSLIDE : film contains 40mm slides; the number of slides for a particular film size is configuration dependent. CUSTOM\i : film contains a customized ordering of rectangular image boxes; i identifies the image display format; the definition of the image display formats is defined in the Conformance Statement; i is an integer Identification of annotation display format. The definition of the annotation display formats and the annotation box position sequence are defined in the Conformance Statement Film orientation. Enumerated Values: PORTRAIT = vertical film position LANDSCAPE = horizontal film position Film size identification. Defined Terms: 8INX10IN 8_5INX11IN 10INX12IN 10INX14IN 11INX14IN 11INX17IN 14INX14IN 14INX17IN 24CMX24CM 24CMX30CM A4 A3 Note: 10INX14IN corresponds with 25.7CMX36.4CM A4 corresponds with 210 x 297 millimeters A3 corresponds with 297 x 420 millimeters Interpolation type by which the printer magnifies or decimates the image in order to fit the image in the image box on film. Defined Terms: REPLICATE BILINEAR CUBIC NONE Further specifies the type of the interpolation function. Values are defined in Conformance Statement. Only valid for Magnification Type (2010,0060) = CUBIC Density of the film areas surrounding and between images on the film. Defined Terms: BLACK WHITE i where i represents the desired density in hundredths of OD (e.g. 150 corresponds with 1.5 OD) Density of the image box area on the film that contains no image. Defined Terms: BLACK WHITE i where i represents the desired density in hundredths of OD (e.g. 150 corresponds with 1.5 OD) Minimum density of the images on the film, expressed in hundredths of OD. If Min Density is lower than minimum printer density than Min Density is set to minimum printer density. Maximum density of the images on the film, expressed in hundredths of OD. If Max Density is higher than maximum printer density than Max Density is set to maximum printer density. Specifies whether a trim box shall be printed surrounding each image on the film. Enumerated Values: YES NO Character string that contains either the ID of the printer configuration table that contains a set of values for implementation specific print parameters (e.g. perception LUT related parameters) or one or more configuration data values, encoded as characters. If there are multiple configuration data values encoded in the string, they shall be separated by backslashes. The definition of values shall be contained in the SCP's Conformance Statement. Defined Terms: CS000-CS999: Implementation specific curve type. Note: It is recommended that for SCPs, CS000 represent the lowest contrast and CS999 the highest contrast levels available. Luminance of lightbox illuminating a piece of transmissive film, or for the case of reflective media, luminance obtainable from diffuse reflection of the illumination present. Expressed as L0, in candelas per square meter (cd/m2). For transmissive film, luminance contribution due to reflected ambient light. Expressed as La, in candelas per square meter (cd/m2). Specifies the resolution at which images in this Film Box are to be printed. Defined Terms: STANDARD = approximately 4k x 5k printable pixels on a 14 x 17 inch film HIGH = Approximately twice the resolution of STANDARD. An ICC Profile encoding the transformation of device-dependent color stored pixel values into PCS-Values. See C.11.15. Note. This is an Input Device Profile that describes the characteristics of the pixel data in the film box, not an Output Device Profile that might describe the characteristics of the Print SCP.
Table C.11.15-1 contains Attributes that identify and describe an ICC Profile. Table C.11.15-1 ICC PROFILE MODULE ATTRIBUTES
A sequence which provides references to a Film Session SOP Class/Instance pairs. Only a single Item shall be permitted in this Sequence. A sequence which provides references to a set of Image Box SOP Class/Instance pairs. One or more Items may be included in this Sequence. A Sequence which provides references to a set of Basic Annotation Box SOP Class/Instance pairs. Zero or more Items may be included in this Sequence. A sequence which provides references to a Presentation LUT related SOP Class/Instance pairs. Only a single Item shall be included in this sequence. The position of the image on the film, based on Image Display Format (2010,0010). See C.13.5.1 for specification.
The position of the image on the film; the encoding of the image position sequence is based on the selected Image Display Format (2010,0010). The image position sequence shall be increasing order beginning with the value 1. Image Box Position (2020,0010) is defined as follows: - STANDARD display format: image box sequence shall be major row order (from left-to-right and from top-to-bottom); top left image position shall be equal to 1. - ROW display format: image box sequence shall be major row order (from left-to-right and from top-to-bottom); top left image position shall be set to 1. - COL display format: image box sequence shall be major column order (from top-to-bottom and from left-to-right); top left image position shall be equal to 1. - SLIDE display format: image box sequence shall be major row order (from left-to-right and from top-to-bottom); top left image position shall be set to 1. - SUPERSLIDE display format: image box sequence shall be major row order (from left-to-right and from top-to-bottom); top left image position shall be set to 1. - CUSTOM STANDARD display format: image box sequence shall be defined in the Conformance Statement; top left image position shall be set to 1.
Specifies whether minimum pixel values (after VOI LUT transformation) are to printed black or white. Enumerated Values: NORMAL = pixels shall be printed as specified by the Photometric Interpretation (0028,0004) REVERSE = pixels shall be printed with the opposite polarity as specified by the Photometric Interpretation (0028,0004) If Polarity (2020,0020) is not specified by the SCU, the SCP shall print with NORMAL polarity. Description is the same as in Table C.13-3. Overrides the Magnification Type specified for the Film Box Description is the same as in Table C.13-3. Overrides the Smoothing Type specified for the Film Box See Table C.13-3 for description of Configuration Information. Width (x-dimension) in mm of the image to be printed. This value overrides the size that corresponds with optimal filling of the Image Box. Specifies whether image pixels are to be decimated or cropped if the image rows or columns is greater than the available printable pixels in an Image Box. Decimation means that a magnification factor <1 is applied to the image. The method of decimation shall be that specified by Magnification Type (2010,0060) or the SCP default if not specified Cropping means that some image rows and/or columns are deleted before printing Enumerated Values: DECIMATE = a magnification factor <1 to be applied to the image. CROP = some image rows and/or columns are to be deleted before printing. The specific algorithm for cropping shall be described in the SCP Conformance Statement. FAIL = the SCP shall not crop or decimate A sequence which provides the content of the grayscale image pixel data to be printed. This is a specialization of the Image Pixel Module defined in C.7.6.3 of this part. It is encoded as a sequence of Attributes of the Image Pixel Module. Zero or one Item may be included in this Sequence. See PS 3.4 for further description. See C.7.6.3 for description of Image Pixel Module. Enumerated Value: 1
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module. Enumerated Values: MONOCHROME1 MONOCHROME2
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module. Enumerated Values: 8 (if Bits Stored = 8) 16 (if Bits Stored = 12)
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module. Enumerated Values: 8 12
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module. Enumerated Values: 7 (if BITS STORED = 8) 11 (if BITS STORED = 12)
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module. Enumerated Value: 0 (unsigned integer)
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
A sequence which provides the content of the color image pixel data to be printed. It is a specialization of the Image Pixel Module defined in C.7.6.3 of this part. It is encoded as a sequence of Attributes of the Image Pixel Module. Zero or one Item may be included in this Sequence. See PS 3.4 for further description. See C.7.6.3 for description of Image Pixel Module. Enumerated Value: 3
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module. Enumerated Value: RGB
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module. Enumerated Value: 1 (frame interleave)
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module.
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module.
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module.
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module. Enumerated Value: 8
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module. Enumerated Value: 8
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module. Enumerated Value: 7
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module. Enumerated Value: 0000H (unsigned integer)
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
See C.7.6.3 for description of Image Pixel Module
Table C.7-11a describes the Image Pixel Module. Table C.7-11a IMAGE PIXEL MODULE ATTRIBUTES Table C.7-11b specifies the common attributes that describe the pixel data of the image. Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES
The position of the annotation box in the parent film box. Annotation position sequence depends on the selected Annotation Display Format ID (2010,0030) Text string Execution status of print job. Enumerated Values: PENDING PRINTING DONE FAILURE Additional information about Execution Status (2100,0020). Defined Terms when the Execution Status is DONE or PRINTING: NORMAL Defined Terms when the Execution Status is FAILURE: INVALID PAGE DES = The specified page layout cannot be printed or other page description errors have been detected. INSUFFIC MEMORY = There is not enough memory available to complete this job. See Section C.13.9.1 for additional Defined Terms when the Execution Status is PENDING or FAILURE.
Additional Defined Terms for Printer Status Info (2110,0020) and Execution Status Info (2100,0030) are:
Date of print job creation. Time of print job creation. Priority of print job (see C.13.1 for further explanation). User defined name identifying the printer. DICOM Application Entity Title that issued the print operation.
Printer device status. Enumerated Values: NORMAL WARNING FAILURE Additional information about Printer Status (2110,0010). Defined Terms when the Printer Status is equal to NORMAL: NORMAL See Section C.13.9.1 for Defined Terms when the Printer Status is equal to WARNING or FAILURE.
Additional Defined Terms for Printer Status Info (2110,0020) and Execution Status Info (2100,0030) are:
User defined name identifying the printer. Manufacturer of the printer. Manufacturer's model number of the printer. Manufacturer's serial number of the printer. Manufacturer's designation of software version of the printer. Date when the printer was last calibrated. Time when the printer was last calibrated.
Contains printer configuration information for a single Application Entity title. See Print Management Service Class Structure in PS 3.4. The sequence shall contain one item for each physical printer/Meta SOP Class combination supported by the Application Entity title. The Meta-SOP Class and a list of optional SOP Classes supported. It shall contain one Meta SOP Class UID and 0-n optional SOP Class UIDs. Maximum number of kilobytes of memory that can be allocated for a Film Session. The value shall be 0 if Memory Allocation (2000,0060) is not supported. The maximum number of bits for each pixel that can be stored in printer memory. The number of bits used by the print engine for internal LUT calculation and printing of each pixel. A sequence which specifies the combinations of Medium Type and Film Size IDs available in the printer at this time and the Min and Max Densities supported by these media. The Item Number with the value of 1 is the printer default. There is no significance to other item numbers. One item for each Medium Type and Film Size ID installed shall be included. A number that labels this item. Each item in the sequence shall have a unique number. See C.13.1
Table C.13-1 BASIC FILM SESSION PRESENTATION MODULE ATTRIBUTES
See C.13.3
Table C.13-3 BASIC FILM BOX PRESENTATION MODULE ATTRIBUTES
Minimum density that can be printed, expressed in hundredths of OD. Maximum density that can be printed, expressed in hundredths of OD. A sequence which specifies combinations of Medium Type and Film Size ID for which the printer will accept an N-CREATE of a Film Box, but are not physically installed in the printer at this time. It also specifies the Min and Max Densities supported by these media. User intervention may be required to install these media in the printer. One item for each Medium Type and Film Size ID available, but not installed shall be included. See C.13.1
Table C.13-1 BASIC FILM SESSION PRESENTATION MODULE ATTRIBUTES
See C.13.3
Table C.13-3 BASIC FILM BOX PRESENTATION MODULE ATTRIBUTES
Minimum density that can be printed, expressed in hundredths of OD. Maximum density that can be printed, expressed in hundredths of OD. A sequence which specifies the Image Display Formats supported, rows and columns in Image Boxes for each format, pixel spacing, and whether Requested Image Size is supported as a function of Film Orientation, Film Size ID, and Printer Resolution ID. One item for each display format, film orientation, film size, and printer resolution combination shall be included. Number of printable rows in an Image Box. Number of printable columns in an Image Box See C.13.3
Table C.13-3 BASIC FILM BOX PRESENTATION MODULE ATTRIBUTES
See C.13.3
Table C.13-3 BASIC FILM BOX PRESENTATION MODULE ATTRIBUTES
See C.13.3
Table C.13-3 BASIC FILM BOX PRESENTATION MODULE ATTRIBUTES
Printer Resolution identification. Defined Terms are the same as Requested Resolution ID (2020,0050). See C.13.3.
Table C.13-3 BASIC FILM BOX PRESENTATION MODULE ATTRIBUTES
Physical distance on the printed film between the center of each pixel, specified by a numeric pair - adjacent row spacing (delimiter) adjacent column spacing in mm. See 10.7.1.3 for further explanation of the value order. Indicates whether the printer supports Requested Image Size (2020,0030) for this display format and film orientation and size combination. Enumerated Values: NO = not supported YES = supported The printer's default resolution identification. Defined Terms are the same as Requested Resolution ID (2020,0050). See C.13.3.
Table C.13-3 BASIC FILM BOX PRESENTATION MODULE ATTRIBUTES
Printer's default magnification type. See C.13.3 for Defined Terms.
Table C.13-3 BASIC FILM BOX PRESENTATION MODULE ATTRIBUTES
Other magnification types available in the printer. See C.13.3 for Defined Terms.
Table C.13-3 BASIC FILM BOX PRESENTATION MODULE ATTRIBUTES
Printer's default smoothing type. See C.13.3.
Table C.13-3 BASIC FILM BOX PRESENTATION MODULE ATTRIBUTES
Other smoothing types available in the printer. See C.13.3.
Table C.13-3 BASIC FILM BOX PRESENTATION MODULE ATTRIBUTES
A free form text description of Configuration Information (2010,0150) supported by the printer. The maximum number of films that can be collated for an N-ACTION of the Film Session. The value shall be 0 if N-ACTION of the Film Session is not supported. Indicates whether the printer will decimate or crop image pixels if the image rows or columns is greater than the available printable pixels in an Image Box. See C.13.5. Enumerated Values when the printer does not support Requested Decimate/Crop Behavior (2020,0040): DECIMATE = image will be decimated to fit. CROP = image will be cropped to fit. FAIL = N-SET of the Image Box will fail Enumerated Values when the printer supports Requested Decimate/Crop Behavior (2020,0040): DEF DECIMATE = image will be decimated to fit. DEF CROP = image will be cropped to fit DEF FAIL = N-SET of the Image Box will fail This value indicates the printer default if the SCU does not create or set Requested Decimate/Crop Behavior for the Image Box.
Table C.13-5 IMAGE BOX PIXEL PRESENTATION MODULE ATTRIBUTES Note: Referenced Image Overlay Box Sequence (2020,0130) and Original Image Sequence (2130,00C0) were previously included in this Module but have been retired. See PS 3.3 2004.
Uniquely identifies this Storage Commitment transaction. Application Entity Title where the SOP Instance(s) may be retrieved via a network based retrieve service. User or implementation specific human readable identification of a Storage Media on which the SOP Instances reside. Uniquely identifies a Storage Media on which the SOP Instances reside. A sequence of Items where each Item references a single SOP Instance for which storage commitment is requested / or has been provided. Application Entity Title from which the SOP Instance may be retrieved via a network based retrieve service. The user or implementation specific human readable identifier that identifies a Storage Media on which this SOP Instance resides. Uniquely identifies a Storage Media on which this SOP Instance resides. A sequence of Items where each Item references a single SOP Instance for which storage commitment could not be provided. The reason that storage commitment could not be provided for this SOP Instance. See Section C.14.1.1.
The following values and semantics shall be used for the Failure Reason Attribute : 0110H - Processing failure A general failure in processing the operation was encountered. 0112H - No such object instance One or more of the elements in the Referenced SOP Instance Sequence was not available. 0213H - Resource limitation The SCP does not currently have enough resources to store the requested SOP Instance(s). 0122H - Referenced SOP Class not supported Storage Commitment has been requested for a SOP Instance with a SOP Class that is not supported by the SCP. 0119H - Class / Instance conflict The SOP Class of an element in the Referenced SOP Instance Sequence did not correspond to the SOP class registered for this SOP Instance at the SCP. 0131H - Duplicate transaction UID The Transaction UID of the Storage Commitment Request is already in use.
Modality type. Enumerated Value: SR = SR Document Unique identifier of the Series. Note: No SR-specific semantics are specified. A number that identifies the Series. Note: No SR-specific semantics are specified. Date the Series started. Time the Series started. User provided description of the Series Uniquely identifies the Performed Procedure Step SOP Instance for which the Series is created. Zero or one item shall be present in the sequence. Notes: 1. The Performed Procedure Step referred to by this Attribute is the Step during which this Document is generated. 2. If this Document is generated during the same Modality or General Purpose Performed Procedure Step as the evidence in the current interpretation procedure, this attribute may contain reference to that Modality or General Purpose Performed Procedure Step. 3. This Attribute is not used to convey reference to the evidence in the current interpretation procedure. See Current Requested Procedure Evidence Sequence (0040,A375). 4. This Sequence may be sent zero length if the Performed Procedure Step is unknown. A number that identifies the SR Document. The estimated degree of completeness of this SR Document with respect to externally defined criteria in a manner specified in the Conformance Statement. Note: It may be desirable to make these criteria adaptable to local policies or user decisions. Enumerated Values: PARTIAL = Partial content. COMPLETE = Complete content. Explanation of the value sent in Completion Flag (0040,A491). Indicates whether this SR Document is Verified. Enumerated Values: UNVERIFIED = Not attested to. VERIFIED = Attested to by a Verifying Observer Name (0040,A075) who is accountable for its content. Note: The intent of this specification is that the "prevailing final version" of an SR Document is the version having the most recent Verification DateTime (0040,A030), Completion Flag (0040,A491) of COMPLETE and Verification Flag (0040,A493) of VERIFIED. The date the document content creation started. The time the document content creation started. The person or persons authorized to verify documents of this type and accept responsibility for the content of this document. One or more Items may be included in this sequence. Required if Verification Flag (0040,A493) is VERIFIED. Note: In HL7 Structured Documents, the comparable attribute is the "legalAuthenticator". The person authorized by the Verifying Organization (0040,A027) to verify documents of this type and who accepts responsibility for the content of this document. Coded identifier of Verifying Observer. Zero or one Items shall be permitted in this sequence. Organization to which the Verifying Observer Name (0040,A075) is accountable in the current interpretation procedure. Date and Time of verification by the Verifying Observer Name (0040,A075). The person or device that created the clinical content of this document. This attribute sets the default Observer Context for the root of the content tree. One or more Items may be included in this sequence. Persons or devices related to the clinical content of this document. One or more Items may be included in this sequence. Participant's role with respect to the clinical content of this document. See C.17.2.5. Defined Terms: SOURCE - Equipment that contributed to the content ENT - Data enterer (e.g., transcriptionist) ATTEST - Attestor Note: In HL7 Structured Documents, the participation comparable to Attestor is the "Authenticator".
The Verifying Observer Sequence (0040,A073), Author Observer Sequence (0040,A078), and Participant Sequence (0040,A07A) identify significant contributors to the SR document. The Author creates the clinical content of the document. The Verifying Observer verifies and accepts legal responsibility for the content. Other participants may include an Attestor, a person identified as a Participant who “signs” an SR document, but who does not have legal authority to verify the clinical content. E.g., an SR document may be authored and attested by a resident, and then verified by a staff physician; or a document may be authored by a CAD device and attested by a technologist, and then verified by a physician; or a technologist working with a measurement software package may be the author, the package is a Source participant, and the final content is verified by a physician. An individual shall not be identified in both the Verifying Observer Sequence (as the legal authenticator) and in the Participant Sequence as an Attestor. An individual may be identified in both the Author Observer Sequence and either the Verifying Observer Sequence or the Participant Sequence. The participation DateTime for the Verifying Observer is conveyed in Verification DateTime (0040,A030) within the Verifying Observer Sequence, for the Author Observer in the Observation DateTime (0040,A032) in the main Data Set (see C.17.3), and for other participants in Participation DateTime (0040,A082) within the Participant Sequence.
DateTime of participation with respect to the clinical content of this document. Custodial organization for this SR Document instance. Represents the organization from which the document originates and that is in charge of maintaining the document, i.e., the steward of the original source document. Note: This may or may not be identical to the Institution identified in the Equipment Module. Only a single item shall be present in this sequence. Name of Custodial Institution or Organization. Coded identifier of Custodial Institution or Organization. Zero or one Items may be included in this sequence. Shall refer to SR SOP Instances (e.g. prior or provisional reports) whose content has been wholly or partially included in this document with or without modification. One or more Items may be included in this sequence. Required if this document includes content from other documents. Note: The amendment process of an existing SR Document is not explicitly described, but several approaches may be considered. One may choose, for example, to create a new SR Document that includes the original content with any amendments applied or included. The structure of this amended SR Document may or may not reflect what was amended. However, the use of the Predecessor Document Sequence allows tracing back to the input SR Document, which in this case is the previous version. Duplicates of this document, stored with different SOP Instance UIDs. One or more Items may be included in this sequence. Required if this document is stored with different SOP Instance UIDs in one or more other Studies. See C.17.2.2 for further explanation.
If identical copies of an SR Document are to be included in multiple Studies then the entire SR Document shall be duplicated with appropriate changes for inclusion into the different Studies (i.e. Study Instance UID, Series Instance UID, SOP Instance UID, Identical Documents Sequence etc.). The Identical Documents Sequence Attribute in each SOP Instance shall contain references to all other duplicate SOP Instances. Note: If an SR Document contains an Identical Documents Sequence then it will not be further duplicated without producing a new complete set of duplicate SOP Instances with re-generated Identical Documents Sequences. This is a consequence of the rules for modification of SR Document content in PS3.4. For example, if there are two identical reports and an application is creating a third identical report, then the first two reports must be re-generated in order that their Identical Documents Sequence will reference the new duplicate document and all other identical documents. If a new SR Document is created using content from an SR Document that contains an Identical Documents Sequence and is part of the same Requested Procedure, then the new SR Document shall only contain a new Identical Documents Sequence if the new SR Document is duplicated. The Predecessor Documents Sequence in all the new SR Documents shall contain references to the original SR Document and all its duplicates as well as any other documents from which content is included. Note: It is up to an implementation to decide whether a new SR Document is duplicated across multiple Studies. This may require user input to make the decision.
Identifies Requested Procedures which are being fulfilled (completely or partially) by creation of this Document. One or more Items may be included in this sequence. Required if this Document fulfills at least one Requested Procedure. Unique identifier for the Study. Uniquely identifies the Study SOP Instance. Only a single Item shall be permitted in this sequence. A departmental IS generated number which identifies the order for the Study. The order number assigned to the Imaging Service Request by the party placing the order. The order number assigned to the Imaging Service Request by the party filling the order. Identifier of the related Requested Procedure Institution-generated administrative description or classification of Requested Procedure. A sequence that conveys the requested procedure. Zero or one Item may be included in this sequence. Reason for requesting this procedure. Coded Reason for requesting this procedure. One or more sequence items may be present. A Sequence that conveys the codes of the performed procedures pertaining to this SOP Instance. Zero or more Items may be included in this sequence. Full set of Composite SOP Instances, of which the creator is aware, which were created to satisfy the current Requested Procedure(s) for which this SR Document is generated or that are referenced in the content tree. One or more Items may be included in this sequence. Required if the creator is aware of Composite Objects acquired in order to satisfy the Requested Procedure(s) for which the SR Document is or if instances are referenced in the content tree. May be present otherwise. See C.17.2.3 for further explanation.
The intent of the Current Requested Procedure Evidence Sequence (0040,A375) is to reference all evidence created in order to satisfy the current Requested Procedure(s) for this SR Document. This shall include, but is not limited to, all current evidence referenced in the content tree. For a completed SR Document satisfying (i.e., being the final report for) the current Requested Procedure(s), this sequence shall list the full set of Composite SOP Instances created for the current Requested Procedure(s). For other SOP Instances that include the SR Document General Module, this sequence shall contain at minimum the set of Composite SOP Instances from the current Requested Procedure(s) that are referenced in the content tree. The Pertinent Other Evidence Sequence (0040,A385) attribute is used to reference all other evidence considered pertinent for this SR Document that is not listed in the Current Requested Procedure Evidence Sequence (0040,A375). This requires that the same SOP Instance shall not be referenced in both of these Sequences. For the purposes of inclusion in the Current Requested Procedure Evidence Sequence (0040,A375) and the Pertinent Other Evidence Sequence (0040,A385), the set of Composite SOP Instances is defined to include not only the images and waveforms referenced in the content tree, but also all presentation states, real world value maps and other accompanying composite instances that are referenced from the content items.
Other Composite SOP Instances that are considered to be pertinent evidence by the creator of this SR Document. This evidence must have been acquired in order to satisfy Requested Procedures other than the one(s) for which this SR Document is generated. One or more Items may be included in this sequence. Required if pertinent evidence from other Requested Procedures needs to be recorded. See C.17.2.3 for further explanation.
The intent of the Current Requested Procedure Evidence Sequence (0040,A375) is to reference all evidence created in order to satisfy the current Requested Procedure(s) for this SR Document. This shall include, but is not limited to, all current evidence referenced in the content tree. For a completed SR Document satisfying (i.e., being the final report for) the current Requested Procedure(s), this sequence shall list the full set of Composite SOP Instances created for the current Requested Procedure(s). For other SOP Instances that include the SR Document General Module, this sequence shall contain at minimum the set of Composite SOP Instances from the current Requested Procedure(s) that are referenced in the content tree. The Pertinent Other Evidence Sequence (0040,A385) attribute is used to reference all other evidence considered pertinent for this SR Document that is not listed in the Current Requested Procedure Evidence Sequence (0040,A375). This requires that the same SOP Instance shall not be referenced in both of these Sequences. For the purposes of inclusion in the Current Requested Procedure Evidence Sequence (0040,A375) and the Pertinent Other Evidence Sequence (0040,A385), the set of Composite SOP Instances is defined to include not only the images and waveforms referenced in the content tree, but also all presentation states, real world value maps and other accompanying composite instances that are referenced from the content items.
Sequence specifying SOP Instances significantly related to the current SOP Instance. Such referenced Instances may include equivalent documents or renderings of this document. One or more Items may be included in this sequence. Required if the identity of a CDA Document equivalent to the current SOP Instance is known at the time of creation of this SOP Instance (see C.17.2.6). May be present otherwise. Code describing the purpose of the reference to the Instance(s). Only a single Item shall be permitted in this sequence.
Unique identifier for the Study Sequence of Items where each Item includes the Attributes of a Series containing referenced Composite Object(s). One or more Items may be included in this sequence Enumerated Values: PSN - Person DEV - Device Name of the person observer for this document Instance. Required if Observer Type value is PSN. Coded identifier of person observer. Zero or one Items shall be permitted in this sequence. Required if Observer Type value is PSN. Name of the device observer for this document instance. Required if Observer Type value is DEV. Unique identifier of device observer. Required if Observer Type value is DEV. Manufacturer of the device observer. Required if Observer Type value is DEV. Model Name of the device observer. Required if Observer Type value is DEV. Institution or organization to which the identified person is responsible or accountable, or which manages the identified device. Institution or organization to which the identified person is responsible or accountable, or which manages the identified device. Zero or one Items shall be permitted in this Sequence. The type of the value encoded in this Content Item. Defined Terms: TEXT NUM CODE DATETIME DATE TIME UIDREF PNAME COMPOSITE IMAGE WAVEFORM SCOORD TCOORD CONTAINER See C.17.3.2.1 for further explanation.
The value of the name/value pair is encoded with one of the Value Types defined in Table C.17.3-7 (the choice of which may be constrained by the IOD in which this Module is contained). The Value Type (0040,A040) attribute explicitly conveys the type of Content Item value encoding. Table C.17.3-7 VALUE TYPE DEFINITIONS Note: It is recommended that drawings and sketches, sometimes used in reports, be represented byIMAGE Content Items that reference separate SOP Instances (e.g., 8-bit, MONOCHROME2, Secondary Capture, or Multi-frame Single Bit Secondary Capture).
Code describing the concept represented by this Content Item. Also conveys the value of Document Title and section headings in documents. Only a single Item shall be permitted in this sequence. Required if Value Type (0040,A040) is TEXT or NUM or CODE or DATETIME or DATE or TIME or UIDREF or PNAME. Required if Value Type (0040,A040) is CONTAINER and a heading is present, or this is the Root Content Item. Note: That is, containers without headings do not require Concept Name Code Sequence Required if Value Type (0040,A040) is COMPOSITE, IMAGE, WAVEFORM, SCOORD or TCOORD, and the Purpose of Reference is conveyed in the Concept Name. See C.17.3.2.2 for further explanation.
The Concept Name Code Sequence (0040,A043) conveys the name of the concept whose value is expressed by the value attribute or set of attributes. Depending on the Value Type (0040,A040), the meaning of the Concept Name Code Sequence may reflect specifics of the use of the particular data type (see Table C.17.3-7).
This is the value of the Content Item. Required if Value Type (0040,A040) is TEXT. Text data which is unformatted and whose manner of display is implementation dependent. The text value may contain spaces, as well as multiple lines separated by either LF, CR, CR LF or LF CR, but otherwise no format control characters (such as horizontal or vertical tab and form feed) shall be present, even if permitted by the Value Representation of UT. The text shall be interpreted as specified by Specific Character Set (0008,0005) if present in the SOP Common Module. Note: The text may contain single or multi-byte characters and use code extension techniques as described in PS 3.5 if permitted by the values of Specific Character Set (0008,0005). This is the value of the Content Item. Required if Value Type (0040,A040) is DATETIME. This is the value of the Content Item. Required if Value Type (0040,A040) is DATE. This is the value of the Content Item. Required if Value Type (0040,A040) is TIME. This is the value of the Content Item. Required if Value Type (0040,A040) is PNAME. This is the value of the Content Item. Required if Value Type (0040,A040) is UIDREF.
The date and time on which this Content Item was completed. For the purpose of recording measurements or logging events, completion time is defined as the time of data acquisition of the measurement, or the time of occurrence of the event. Required if the date and time are different from the Content Date (0008,0023) and Content Time (0008,0033) or the Observation DateTime (0040,A032) defined in higher items. May be present otherwise. Note: When Content Items are copied into successor reports, the Content Date (0008,0023) and Content Time (0008,0033) of the new report are likely to be different than the date and time of the original observation. Therefore this attribute may need to be included in any copied Content Items to satisfy the condition. A potentially recursively nested Sequence of Items that conveys content that is the Target of Relationships with the enclosing Source Content Item. One or more Items may be included in this sequence. Required if the enclosing Content Item has relationships. Notes: 1. If this Attribute is not present then the enclosing Item is a leaf. 2. The order of Items within this Sequence is semantically significant for presentation. See C.17.3.2.4 for further explanation.
The Content Sequence (0040,A730) provides the hierarchical structuring of the Content Tree (see C.17.3.1) by recursively nesting Content Items. A parent (or source) Content Item has an explicit relationship to each child (or target) Content Item, conveyed by the Relationship Type (0040,A010) attribute. Table C.17.3-8 describes the Relationship Types between Source Content Items and the Target Content Items. Table C.17.3-8 RELATIONSHIP TYPE DEFINITIONS
The type of relationship between the (enclosing) Source Content Item and the Target Content Item. IODs specify additional constraints on Relationships (including lists of Enumerated Values). Defined Terms: CONTAINS HAS PROPERTIES HAS OBS CONTEXT HAS ACQ CONTEXT INFERRED FROM SELECTED FROM HAS CONCEPT MOD See C.17.3.2.4 for further explanation.
The Content Sequence (0040,A730) provides the hierarchical structuring of the Content Tree (see C.17.3.1) by recursively nesting Content Items. A parent (or source) Content Item has an explicit relationship to each child (or target) Content Item, conveyed by the Relationship Type (0040,A010) attribute. Table C.17.3-8 describes the Relationship Types between Source Content Items and the Target Content Items. Table C.17.3-8 RELATIONSHIP TYPE DEFINITIONS
An ordered set of one or more integers that uniquely identifies the Target Content Item of the relationship. The root Content Item is referenced by a single value of 1. Each subsequent integer represents an ordinal position of a Content Item in the Content Sequence (0040,A730) in which it belongs. The Referenced Content Item Identifier is the set of these ordinal positions along the by-value relationship path. The number of values in this Multi-Value Attribute is exactly the number of relationships traversed in the SR content tree plus one. Note: 1. See C.17.3.2.5. 2. Content Items are ordered in a Content Sequence starting from 1 as defined in VR of SQ (See PS 3.5). Required if the Target Content Item is denoted by-reference, i.e. the Document Relationship Macro and Document Content Macro are not included.
Content Items are identified by their position in the Content Item tree. They have an implicit order as defined by the order of the Sequence Items. When a Content Item is the target of a by-reference relationship, its position is specified in the Referenced Content Item Identifier (0040,DB73) in a Content Sequence Item subsidiary to the source Content Item. Note: Figure C.17.3-3 illustrates an SR content tree and identifiers associated with each Content Item:
Modality type. Enumerated Value: KO = Key Object Selection Unique identifier of the Series. Note: No specific semantics are specified. A number that identifies the Series. Note: No specific semantics are specified. Date the Series started. Time the Series started. User provided description of the Series Uniquely identifies the Performed Procedure Step SOP Instance for which the Series is created. Zero or one item shall be present in the sequence. Notes: See notes on this attribute in Section C.17.1 SR Document Series Module A number that identifies the Document. The date the document content creation started. The time the document content creation started. Identifies Requested Procedures to which this Document pertains. One or more Items may be included in this sequence. Required if this Document pertains to at least one Requested Procedure. Unique identifier for the Study. Uniquely identifies the Study SOP Instance. Only a single Item shall be permitted in this sequence. A departmental IS generated number which identifies the order for the Study. The order number assigned to the Imaging Service Request by the party placing the order. The order number assigned to the Imaging Service Request by the party filling the order. Identifier of the related Requested Procedure Institution-generated administrative description or classification of Requested Procedure. A sequence that conveys the requested procedure. Zero or one Item may be included in this sequence. List of all Composite SOP Instances referenced in the Content Sequence (0040,A730) , including all presentation states, real world value maps and other accompanying composite instances that are referenced from the content items. One or more Items shall be included in this sequence. Note: In the context of the Key Object Selection, the current evidence is considered to be only the set of instances referenced within the Key Object Selection. Duplicates of this document, stored with different SOP Instance UIDs. One or more Items may be included in this sequence. Required if this Key Object Selection document references instances in more than one Study. See C.17.2.2 and C.17.6.2.1 for further explanation and conditions.
If identical copies of an SR Document are to be included in multiple Studies then the entire SR Document shall be duplicated with appropriate changes for inclusion into the different Studies (i.e. Study Instance UID, Series Instance UID, SOP Instance UID, Identical Documents Sequence etc.). The Identical Documents Sequence Attribute in each SOP Instance shall contain references to all other duplicate SOP Instances. Note: If an SR Document contains an Identical Documents Sequence then it will not be further duplicated without producing a new complete set of duplicate SOP Instances with re-generated Identical Documents Sequences. This is a consequence of the rules for modification of SR Document content in PS3.4. For example, if there are two identical reports and an application is creating a third identical report, then the first two reports must be re-generated in order that their Identical Documents Sequence will reference the new duplicate document and all other identical documents. If a new SR Document is created using content from an SR Document that contains an Identical Documents Sequence and is part of the same Requested Procedure, then the new SR Document shall only contain a new Identical Documents Sequence if the new SR Document is duplicated. The Predecessor Documents Sequence in all the new SR Documents shall contain references to the original SR Document and all its duplicates as well as any other documents from which content is included. Note: It is up to an implementation to decide whether a new SR Document is duplicated across multiple Studies. This may require user input to make the decision.
This is the value of the Content Item. Shall consist of a Sequence of Items conveying the measured value(s), which represent integers or real numbers and units of measurement. Zero or one Items shall be permitted in this sequence. Numeric measurement value. Only a single value shall be present. Units of measurement. Only a single Item shall be permitted in this sequence. Qualification of Numeric Value in Measured Value Sequence, or reason for absence of Measured Value Sequence Item. Only a single Item shall be permitted in this sequence. This is the value of the Content Item. Only a single Item shall be permitted in this sequence. References to Composite Object SOP Class/SOP Instance pairs. Only a single Item shall be permitted in this Sequence. Identifies the frame numbers within the Referenced SOP Instance to which the reference applies. The first frame shall be denoted as frame number 1. Note: This Attribute may be multi-valued. Required if the Referenced SOP Instance is a multi-frame image and the reference does not apply to all frames, and Referenced Segment Number (0062,000B) is not present. Identifies the segments to which the reference applies identified by Segment Number (0062,0004). Required if the Referenced SOP Instance is a Segmentation and the reference does not apply to all segments and Referenced Frame Number (0008,1160) is not present. Reference to a Softcopy Presentation State SOP Class/SOP Instance pair. Only a single Item shall be permitted in this sequence. Reference to a Real World Value Mapping SOP Class/SOP Instance pair. Only a single Item shall be permitted in this sequence. This Icon Image is representative of the Image. Only a single Item shall be permitted in this Sequence. The Icon Image may be no greater than 128 rows by 128 columns. List of channels in Waveform to which the reference applies. See C.18.5.1.1 Required if the Referenced SOP Instance is a Waveform that contains multiple Channels and not all Channels in the Waveform are referenced.
Referenced Waveform Channels (0040,A0B0) is a multi-value attribute which lists the channels referenced. Each channel is specified as a pair of values (M,C), where the first value is the sequence item number of the Waveform Sequence (5400,0100) attribute in the referenced object (i.e. the Multiplex Group Number), and the second value is the sequence item number of the Channel Definition Sequence (003A,0200) attribute (i.e., the Channel Number) within the multiplex group. If the specified channel number is 0, the annotation applies to all channels in the multiplex group. Note: As an example, an annotation which applies to the entire first multiplex group and channels 2 and 3 of the third multiplex group would have Referenced Waveform Channels (0040,A0B0) value 0001 0000 0003 0002 0003 0003.
An ordered set of (column,row) pairs that denote positions in an image specified with sub-pixel resolution such that the origin at the TLHC of the TLHC pixel is 0.0\0.0, the BRHC of the TLHC pixel is 1.0\1.0, and the BRHC of the BRHC pixel is Columns\Rows. The values must be within the range 0\0 to Columns\Rows. The values Columns (0028,0011) and Rows (0028,0010) are those contained in the referenced image. See C.18.6.1.1 for further explanation.
Graphic Data may be used to associate an anatomic or spatial Concept with a defined subset of one or more images. Graphic Data may be explicitly defined as a single point (i.e. to denote the epicenter of an anatomic site or lesion) or more than one point (i.e. representing a set of points or an open or closed polygon). Note: Spatial coordinates may be used to associate observational data with a set of Image features. Spatial coordinates also may be used to convey coordinates that are input data for a measurement.
See C.18.6.1.2 for Enumerated Values.
When annotation applies to an image, this attribute defines the type of geometry of the annotated region of interest. The following Enumerated Values are specified for image spatial coordinate geometries: POINT = a single pixel denoted by a single (column,row) pair MULTIPOINT = multiple pixels each denoted by an (column,row) pair POLYLINE = a series of connected line segments with ordered vertices denoted by (column,row) pairs; if the first and last vertices are the same it is a closed polygon CIRCLE = a circle defined by two (column,row) pairs. The first point is the central pixel. The second point is a pixel on the perimeter of the circle. ELLIPSE = an ellipse defined by four pixel (column,row) pairs, the first two points specifying the endpoints of the major axis and the second two points specifying the endpoints of the minor axis of an ellipse
See C.18.7.1.1 for Enumerated Values.
This Attribute defines the type of temporal extent of the region of interest. A temporal point (or instant of time) may be defined by a waveform sample offset (for a single waveform multiplex group only), time offset, or absolute time. The following Enumerated Values are specified for Temporal Range Type: POINT = a single temporal point MULTIPOINT = multiple temporal points SEGMENT = a range between two temporal points MULTISEGMENT = multiple segments, each denoted by two temporal points BEGIN = a range beginning at one temporal point, and extending beyond the end of the acquired data END = a range beginning before the start of the acquired data, and extending to (and including) the identified temporal point
List of samples within a multiplex group specifying temporal points of the referenced data. Position of first sample is 1. Required if the Referenced SOP Instance is a Waveform and Referenced Time Offsets (0040,A138) and Referenced DateTime (0040,A13A) are not present. May be used only if Referenced Channels (0040,A0B0) refers to channels within a single multiplex group. Specifies temporal points for reference by number of seconds after start of data. Required if Referenced Sample Positions (0040,A132) and Referenced DateTime (0040,A13A) are not present. Specifies temporal points for reference by absolute time. Required if Referenced Sample Positions (0040,A132) and Referenced Time Offsets (0040,A138) are not present.
This flag specifies for a CONTAINER whether or not its contained Content Items are logically linked in a continuous textual flow, or are separate items. Enumerated Values: SEPARATE CONTINUOUS See C.18.8.1.1 for further explanation.
Continuity of Content (0040,A050) specifies whether or not all the Content Items contained in a CONTAINER are logically linked in a continuous textual flow, or are separate entities. It only applies to the children contained in the container, and not their children (which if containers themselves, will have the attribute specified explicitly). Notes: 1. This allows the interspersing of measurements, codes, and image references, amongst text. For example, the following: “A mass of diameter = 3 cm was detected.” can be represented by the following Content Items in a CONTAINER with a Continuity of Content (0040,A050) of CONTINUOUS: TEXT “A mass of” NUM “Diameter” 3 “cm” TEXT “was detected.” 2. The Continuity of Content applies only to subsidiary Content Items with Relationship Type CONTAINS. Other subsidiary items, e.g., with Relationship Type HAS CONCEPT MOD or HAS OBS CONTEXT, are not part of the Continuity of Content, but apply to the Container as a whole.
Template that describes the content of this Content Item and its subsidiary Content Items. Only a single Item shall be permitted in this sequence. Required if a template was used to define the content of this Item, and the template consists of a single CONTAINER with nested content, and it is the outermost invocation of a set of nested templates that start with the same CONTAINER (see C.18.8.1.2). Mapping Resource that defines the template. See Section 8.4. Defined Terms: DCMR = DICOM Content Mapping Resource Template identifier.
A number that identifies this image. The value shall be unique within a series. The date the raw data creation was started. The time the raw data creation was started. The date and time that the acquisition of data started. Note: The synchronization of this time with an external clock is specified in the synchronization Module in Acquisition Time synchronized (0018,1800). Unique identification of the equipment and version of the software that has created the Raw Data information. The UID allows one to avoid attempting to interpret raw data with an unknown format. A sequence that provides reference to a set of SOP Class/Instance pairs identifying other Instances significantly related to this Instance. One or more Items may be included in this Sequence. Describes the purpose for which the reference is made. Only a single Item shall be permitted in this sequence. See C.7.6.16.2.5.1.
Referenced Image Sequence (0008,1140) shall be used to provide a reference to a set of SOP Class/Instance pairs identifying other data objects used to plan the acquisition of this image where the images shall share the same Frame of Reference UID (0020,0052). For each Item that contains such a reference, the value of the Purpose of Reference Code Sequence (0040,A170) shall be (”121311”, DCM, ”Localizer"). Applications can use the Referenced Image Sequence (0008,1140) in combination with data in Plane Position and Plane Orientation Macros to provide projections of the position of an image with respect to the referenced image. The Referenced Image Sequence (0008,1140) may also be present when references to other images (or frames within other images) are required for other reasons, as specified by Purpose of Reference Code Sequence (0040,A170). Note: An Image may contain references to itself (e.g. to other frames within itself).
Modality type. Enumerated Value: REG The date the content creation started. The time the content creation started. A sequence of one or more registration items. Each item defines a spatial registration to the referenced images in that item. All referenced images are in the same spatial frame of reference or atlas. Identifies a Frame of Reference that may or may not be an image set (e.g. atlas or physical space). See C.7.4.1.1.1 for further explanation. Required if Referenced Image Sequence (0008,1140) is absent. May be present otherwise.
The Frame of Reference UID (0020,0052) shall be used to uniquely identify a frame of reference for a series. Each series shall have a single Frame of Reference UID. However, multiple Series within a Study may share a Frame of Reference UID. All images in a Series that share the same Frame of Reference UID shall be spatially related to each other. Notes: 1. Previous versions of this Standard defined a Data Element "Location", which has been retired. Frame of Reference UID provides a completely unambiguous identification of the image location reference used to indicate position. 2. A common Frame of Reference UID may be used to spatially relate localizer images with a set of transverse images. However, in some cases (eg. multiple localizer images being related to a single set of transverse images) a common Frame of Reference UID may not be sufficient. The Referenced Image Sequence (0008,1140) provides an unambiguous method for relating localizer images.
Identifies the set of images registered in this sequence item. One or more items shall be present. Required if Frame of Reference UID (0020,0052) is absent. May be present otherwise. A sequence that specifies one spatial registration. Exactly one item shall be present User description or comments about the registration. Describes the information input into the registration process. Zero or one Items may be present in this Sequence. One or more items shall be present. Each item specifies a transformation. The item order is significant and corresponds to matrix multiplication order. See C.20.2.1.1.
The Frame of Reference Transformation Matrix (3006,00C6) AMB describes how to transform a point (Bx,By,Bz) with respect to RCSB into (Ax,Ay,Az) with respect to RCSA according to the equation below. A x A y A z 1 = M 11 M 12 M 13 T x M 21 M 22 M 23 T y M 31 M 32 M 33 T z 0 0 0 1 B x B y B z 1 size 12{ left [ matrix { "" lSup { size 8{A} } x {} ## "" lSup { size 8{A} } y {} ## "" lSup { size 8{A} } z {} ## 1 } right ]= left [ matrix { M rSub { size 8{"11"} } {} # M rSub { size 8{"12"} } {} # M rSub { size 8{"13"} } {} # T rSub { size 8{x} } {} ## M rSub { size 8{"21"} } {} # M rSub { size 8{"22"} } {} # M rSub { size 8{"23"} } {} # T rSub { size 8{y} } {} ## M rSub { size 8{"31"} } {} # M rSub { size 8{"32"} } {} # M rSub { size 8{"33"} } {} # T rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { "" lSup { size 8{B} } x {} ## "" lSup { size 8{B} } y {} ## "" lSup { size 8{B} } z {} ## 1 } right ]} {} The Frame of Reference Transformation Matrix is expressible as multiple matrices, each in a separate item of the Matrix Sequence (0070,030A). The equation below specifies the order of the matrix multiplication where M1, M2 and M3 are the first, second and third items in the sequence. x ' y ' z ' 1 T = M 3 M 2 M 1 x y z 1 T size 12{ left [ matrix { x' {} # y' {} # z' {} # 1{} } right ] rSup { size 8{T} } =M rSub { size 8{3} } left (M rSub { size 8{2} } left (M rSub { size 8{1} } left [ matrix { x {} # y {} # z {} # 1{} } right ] rSup { size 8{T} } right ) right )} {} where = Registration often involves two or more RCS, each with a corresponding Frame of Reference Transformation Matrix. For example, another Frame of Reference Transformation Matrix AMC can describe how to transform a point (Cx,Cy,Cz) with respect to RCSC into (Ax,Ay,Az) with respect to RCSA. It is straightforward to find the Frame of Reference Transformation Matrix BMC that describes how to transform the point (Cx,Cy,Cz) with respect to RCSC into the point (Bx,By,Bz) with respect to RCSB. The solution is to invert AMB and multiply by AMC, as shown below: B x B y B z 1 =  A Μ B  − 1 ∗ A M C C x C y C z 1 size 12{ left [ matrix { "" lSup { size 8{B} } x {} ## "" lSup { size 8{B} } y {} ## "" lSup { size 8{B} } z {} ## 1 } right ]= \( "" lSup { size 8{A} } Μ rSub { size 8{B} } \) rSup { size 8{ - 1} } * "" lSup { size 8{A} } M rSub { size 8{C} } left [ matrix { "" lSup { size 8{C} } x {} ## "" lSup { size 8{C} } y {} ## "" lSup { size 8{C} } z {} ## 1 } right ]} {}
A 4x4 homogeneous transformation matrix that registers the referenced images to the local RCS. Matrix elements shall be listed in row-major order. See C.20.2.1.1.
The Frame of Reference Transformation Matrix (3006,00C6) AMB describes how to transform a point (Bx,By,Bz) with respect to RCSB into (Ax,Ay,Az) with respect to RCSA according to the equation below. A x A y A z 1 = M 11 M 12 M 13 T x M 21 M 22 M 23 T y M 31 M 32 M 33 T z 0 0 0 1 B x B y B z 1 size 12{ left [ matrix { "" lSup { size 8{A} } x {} ## "" lSup { size 8{A} } y {} ## "" lSup { size 8{A} } z {} ## 1 } right ]= left [ matrix { M rSub { size 8{"11"} } {} # M rSub { size 8{"12"} } {} # M rSub { size 8{"13"} } {} # T rSub { size 8{x} } {} ## M rSub { size 8{"21"} } {} # M rSub { size 8{"22"} } {} # M rSub { size 8{"23"} } {} # T rSub { size 8{y} } {} ## M rSub { size 8{"31"} } {} # M rSub { size 8{"32"} } {} # M rSub { size 8{"33"} } {} # T rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { "" lSup { size 8{B} } x {} ## "" lSup { size 8{B} } y {} ## "" lSup { size 8{B} } z {} ## 1 } right ]} {} The Frame of Reference Transformation Matrix is expressible as multiple matrices, each in a separate item of the Matrix Sequence (0070,030A). The equation below specifies the order of the matrix multiplication where M1, M2 and M3 are the first, second and third items in the sequence. x ' y ' z ' 1 T = M 3 M 2 M 1 x y z 1 T size 12{ left [ matrix { x' {} # y' {} # z' {} # 1{} } right ] rSup { size 8{T} } =M rSub { size 8{3} } left (M rSub { size 8{2} } left (M rSub { size 8{1} } left [ matrix { x {} # y {} # z {} # 1{} } right ] rSup { size 8{T} } right ) right )} {} where = Registration often involves two or more RCS, each with a corresponding Frame of Reference Transformation Matrix. For example, another Frame of Reference Transformation Matrix AMC can describe how to transform a point (Cx,Cy,Cz) with respect to RCSC into (Ax,Ay,Az) with respect to RCSA. It is straightforward to find the Frame of Reference Transformation Matrix BMC that describes how to transform the point (Cx,Cy,Cz) with respect to RCSC into the point (Bx,By,Bz) with respect to RCSB. The solution is to invert AMB and multiply by AMC, as shown below: B x B y B z 1 =  A Μ B  − 1 ∗ A M C C x C y C z 1 size 12{ left [ matrix { "" lSup { size 8{B} } x {} ## "" lSup { size 8{B} } y {} ## "" lSup { size 8{B} } z {} ## 1 } right ]= \( "" lSup { size 8{A} } Μ rSub { size 8{B} } \) rSup { size 8{ - 1} } * "" lSup { size 8{A} } M rSub { size 8{C} } left [ matrix { "" lSup { size 8{C} } x {} ## "" lSup { size 8{C} } y {} ## "" lSup { size 8{C} } z {} ## 1 } right ]} {}
Type of Frame of Reference Transformation Matrix (3006,00C6). Defined terms: RIGID RIGID_SCALE AFFINE See C.20.2.1.2
There are three types of Registration Matrices: RIGID: This is a registration involving only translations and rotations. Mathematically, the matrix is constrained to be orthonormal and describes six degrees of freedom: three translations, and three rotations. RIGID_SCALE: This is a registration involving only translations, rotations and scaling. Mathematically, the matrix is constrained to be orthogonal and describes nine degrees of freedom: three translations, three rotations and three scales. This type of transformation is sometimes used in atlas mapping. AFFINE: This is a registration involving translations, rotations, scaling and shearing. Mathematically, there are no constraints on the elements of the Frame of Reference Transformation Matrix, so it conveys twelve degrees of freedom. This type of transformation is sometimes used in atlas mapping. See the PS 3.17 Annex on Transforms and Mappings for more detail.
The fiducials used to determine the Frame of Reference Transformation Matrix. One or more Items may be present. The UID that identifies the fiducial used as registration input.
The date the vector grid data creation started. The time the vector grid data creation started. A sequence of one or more registration items. Each item defines a spatial registration to the referenced images in that item. At least one item shall have a Deformable Registration Grid Sequence (0064,0005) with one item. See C.20.3.1.1.
The registrations in this module are applied to the Registered RCS coordinates in the following order. First, transform the coordinates using the matrix described in the Pre Deformation Matrix Registration Sequence (0064,000F). Next apply the deformation offsets to the resulting coordinates. Finally, transform those coordinates using the matrix described in the Post Deformation Matrix Registration Sequence (0064,0010). The resulting coordinate addresses the sample point within the Source RCS. Thus a source coordinate may be calculated using the following equation: (This assumes that the center position of each deformation voxel will be transformed) X Source Y Source Z Source 1 = M Post M Pr e X Start  i ∗ X R Y Start  j ∗ Y R Z Start  k ∗ Z R 1  ΔX ijk ΔY ijk ΔZ ijk 0 size 12{ left [ matrix { X rSub { size 8{ ital "Source"} } {} ## Y rSub { size 8{ ital "Source"} } {} ## Z rSub { size 8{ ital "Source"} } {} ## 1 } right ]=M rSub { size 8{ ital "Post"} } left (M rSub { size 8{"Pr"e} } left [ matrix { X rSub { size 8{ ital "Start"} } +i*X rSub { size 8{R} } {} ## Y rSub { size 8{ ital "Start"} } +j*Y rSub { size 8{R} } {} ## Z rSub { size 8{ ital "Start"} } +k*Z rSub { size 8{R} } {} ## 1 } right ]+ left [ matrix { ΔX rSub { size 8{ ital "ijk"} } {} ## ΔY rSub { size 8{ ital "ijk"} } {} ## ΔZ rSub { size 8{ ital "ijk"} } {} ## 0 } right ] right )} {} Where: The spatial coordinate in the Source RCS. The start coordinate, in the Registered RCS, of the deformation grid as specified in the Image Position (Patient) attribute (0020,0032). The index into the deformation grid in the X, Y, and Z dimension. The resolution of the deformation grid in the X, Y, and Z dimension as specified in the Grid Resolution attribute (0064,0008). The deformation specified at index (i,j,k) in the deformation grid. If the Deformation Registration Grid Sequence (0064,0005) has no items, the  values are zero. MPre The transformation matrix specified in the Pre Deformation Matrix Registration Sequence (0064,000F). MPost The transformation matrix specified in the Post Deformation Matrix Registration Sequence (0064,0010).
Identifies the Frame of Reference of a Source RCS. The Source RCS may or may not include an image set (e.g. atlas). See C.7.4.1.1.1 for further explanation.
The Frame of Reference UID (0020,0052) shall be used to uniquely identify a frame of reference for a series. Each series shall have a single Frame of Reference UID. However, multiple Series within a Study may share a Frame of Reference UID. All images in a Series that share the same Frame of Reference UID shall be spatially related to each other. Notes: 1. Previous versions of this Standard defined a Data Element "Location", which has been retired. Frame of Reference UID provides a completely unambiguous identification of the image location reference used to indicate position. 2. A common Frame of Reference UID may be used to spatially relate localizer images with a set of transverse images. However, in some cases (eg. multiple localizer images being related to a single set of transverse images) a common Frame of Reference UID may not be sufficient. The Referenced Image Sequence (0008,1140) provides an unambiguous method for relating localizer images.
Identifies the set of images registered in this sequence item. One or more items shall be present. Required if the registration applies to a subset of images within the specified Source Frame of Reference UID (0064,0003). All referenced images shall be in the same spatial frame of reference. User description or comments about the registration. Describes the method used for the registration process. Zero or one item shall be present. A sequence that specifies one spatial registration to be applied prior to the deformation. Exactly one item shall be present. Required if a matrix transformation is to be applied prior to deformation. A 4x4 homogeneous transformation matrix. Matrix elements shall be listed in row-major order. See C.20.2.1.1.
The Frame of Reference Transformation Matrix (3006,00C6) AMB describes how to transform a point (Bx,By,Bz) with respect to RCSB into (Ax,Ay,Az) with respect to RCSA according to the equation below. A x A y A z 1 = M 11 M 12 M 13 T x M 21 M 22 M 23 T y M 31 M 32 M 33 T z 0 0 0 1 B x B y B z 1 size 12{ left [ matrix { "" lSup { size 8{A} } x {} ## "" lSup { size 8{A} } y {} ## "" lSup { size 8{A} } z {} ## 1 } right ]= left [ matrix { M rSub { size 8{"11"} } {} # M rSub { size 8{"12"} } {} # M rSub { size 8{"13"} } {} # T rSub { size 8{x} } {} ## M rSub { size 8{"21"} } {} # M rSub { size 8{"22"} } {} # M rSub { size 8{"23"} } {} # T rSub { size 8{y} } {} ## M rSub { size 8{"31"} } {} # M rSub { size 8{"32"} } {} # M rSub { size 8{"33"} } {} # T rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { "" lSup { size 8{B} } x {} ## "" lSup { size 8{B} } y {} ## "" lSup { size 8{B} } z {} ## 1 } right ]} {} The Frame of Reference Transformation Matrix is expressible as multiple matrices, each in a separate item of the Matrix Sequence (0070,030A). The equation below specifies the order of the matrix multiplication where M1, M2 and M3 are the first, second and third items in the sequence. x ' y ' z ' 1 T = M 3 M 2 M 1 x y z 1 T size 12{ left [ matrix { x' {} # y' {} # z' {} # 1{} } right ] rSup { size 8{T} } =M rSub { size 8{3} } left (M rSub { size 8{2} } left (M rSub { size 8{1} } left [ matrix { x {} # y {} # z {} # 1{} } right ] rSup { size 8{T} } right ) right )} {} where = Registration often involves two or more RCS, each with a corresponding Frame of Reference Transformation Matrix. For example, another Frame of Reference Transformation Matrix AMC can describe how to transform a point (Cx,Cy,Cz) with respect to RCSC into (Ax,Ay,Az) with respect to RCSA. It is straightforward to find the Frame of Reference Transformation Matrix BMC that describes how to transform the point (Cx,Cy,Cz) with respect to RCSC into the point (Bx,By,Bz) with respect to RCSB. The solution is to invert AMB and multiply by AMC, as shown below: B x B y B z 1 =  A Μ B  − 1 ∗ A M C C x C y C z 1 size 12{ left [ matrix { "" lSup { size 8{B} } x {} ## "" lSup { size 8{B} } y {} ## "" lSup { size 8{B} } z {} ## 1 } right ]= \( "" lSup { size 8{A} } Μ rSub { size 8{B} } \) rSup { size 8{ - 1} } * "" lSup { size 8{A} } M rSub { size 8{C} } left [ matrix { "" lSup { size 8{C} } x {} ## "" lSup { size 8{C} } y {} ## "" lSup { size 8{C} } z {} ## 1 } right ]} {}
Type of Frame of Reference Transformation Matrix (3006,00C6). Defined terms: RIGID RIGID_SCALE AFFINE See C.20.2.1.2
There are three types of Registration Matrices: RIGID: This is a registration involving only translations and rotations. Mathematically, the matrix is constrained to be orthonormal and describes six degrees of freedom: three translations, and three rotations. RIGID_SCALE: This is a registration involving only translations, rotations and scaling. Mathematically, the matrix is constrained to be orthogonal and describes nine degrees of freedom: three translations, three rotations and three scales. This type of transformation is sometimes used in atlas mapping. AFFINE: This is a registration involving translations, rotations, scaling and shearing. Mathematically, there are no constraints on the elements of the Frame of Reference Transformation Matrix, so it conveys twelve degrees of freedom. This type of transformation is sometimes used in atlas mapping. See the PS 3.17 Annex on Transforms and Mappings for more detail.
A sequence that specifies one spatial registration to be applied after the application of the deformation. Exactly one item shall be present. Required if matrix transformation is to be performed after application of the deformation. A 4x4 homogeneous transformation matrix. Matrix elements shall be listed in row-major order. See C.20.2.1.1.
The Frame of Reference Transformation Matrix (3006,00C6) AMB describes how to transform a point (Bx,By,Bz) with respect to RCSB into (Ax,Ay,Az) with respect to RCSA according to the equation below. A x A y A z 1 = M 11 M 12 M 13 T x M 21 M 22 M 23 T y M 31 M 32 M 33 T z 0 0 0 1 B x B y B z 1 size 12{ left [ matrix { "" lSup { size 8{A} } x {} ## "" lSup { size 8{A} } y {} ## "" lSup { size 8{A} } z {} ## 1 } right ]= left [ matrix { M rSub { size 8{"11"} } {} # M rSub { size 8{"12"} } {} # M rSub { size 8{"13"} } {} # T rSub { size 8{x} } {} ## M rSub { size 8{"21"} } {} # M rSub { size 8{"22"} } {} # M rSub { size 8{"23"} } {} # T rSub { size 8{y} } {} ## M rSub { size 8{"31"} } {} # M rSub { size 8{"32"} } {} # M rSub { size 8{"33"} } {} # T rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { "" lSup { size 8{B} } x {} ## "" lSup { size 8{B} } y {} ## "" lSup { size 8{B} } z {} ## 1 } right ]} {} The Frame of Reference Transformation Matrix is expressible as multiple matrices, each in a separate item of the Matrix Sequence (0070,030A). The equation below specifies the order of the matrix multiplication where M1, M2 and M3 are the first, second and third items in the sequence. x ' y ' z ' 1 T = M 3 M 2 M 1 x y z 1 T size 12{ left [ matrix { x' {} # y' {} # z' {} # 1{} } right ] rSup { size 8{T} } =M rSub { size 8{3} } left (M rSub { size 8{2} } left (M rSub { size 8{1} } left [ matrix { x {} # y {} # z {} # 1{} } right ] rSup { size 8{T} } right ) right )} {} where = Registration often involves two or more RCS, each with a corresponding Frame of Reference Transformation Matrix. For example, another Frame of Reference Transformation Matrix AMC can describe how to transform a point (Cx,Cy,Cz) with respect to RCSC into (Ax,Ay,Az) with respect to RCSA. It is straightforward to find the Frame of Reference Transformation Matrix BMC that describes how to transform the point (Cx,Cy,Cz) with respect to RCSC into the point (Bx,By,Bz) with respect to RCSB. The solution is to invert AMB and multiply by AMC, as shown below: B x B y B z 1 =  A Μ B  − 1 ∗ A M C C x C y C z 1 size 12{ left [ matrix { "" lSup { size 8{B} } x {} ## "" lSup { size 8{B} } y {} ## "" lSup { size 8{B} } z {} ## 1 } right ]= \( "" lSup { size 8{A} } Μ rSub { size 8{B} } \) rSup { size 8{ - 1} } * "" lSup { size 8{A} } M rSub { size 8{C} } left [ matrix { "" lSup { size 8{C} } x {} ## "" lSup { size 8{C} } y {} ## "" lSup { size 8{C} } z {} ## 1 } right ]} {}
Type of Frame of Reference Transformation Matrix (3006,00C6). Defined terms: RIGID RIGID_SCALE AFFINE See C.20.2.1.2
There are three types of Registration Matrices: RIGID: This is a registration involving only translations and rotations. Mathematically, the matrix is constrained to be orthonormal and describes six degrees of freedom: three translations, and three rotations. RIGID_SCALE: This is a registration involving only translations, rotations and scaling. Mathematically, the matrix is constrained to be orthogonal and describes nine degrees of freedom: three translations, three rotations and three scales. This type of transformation is sometimes used in atlas mapping. AFFINE: This is a registration involving translations, rotations, scaling and shearing. Mathematically, there are no constraints on the elements of the Frame of Reference Transformation Matrix, so it conveys twelve degrees of freedom. This type of transformation is sometimes used in atlas mapping. See the PS 3.17 Annex on Transforms and Mappings for more detail.
Describes the deformation grid used to sample into the Source RCS. Exactly one item shall be present. Required if deformation is performed. See C.20.3.1.2.
The vector represents the deformation at the center of the voxel. Deformations between voxel centers shall be determined through interpolation of the surrounding vectors in an implementation dependent manner.
The direction of cosines of the first row and first column of the Vector Grid Data (0064,0009) with respect to the patient. See C.7.6.2.1.1 for further explanation.
The Image Position (0020,0032) specifies the x, y, and z coordinates of the upper left hand corner of the image; it is the center of the first voxel transmitted. Image Orientation (0020,0037) specifies the direction cosines of the first row and the first column with respect to the patient. These Attributes shall be provide as a pair. Row value for the x, y, and z axes respectively followed by the Column value for the x, y, and z axes respectively. The direction of the axes is defined fully by the patient’s orientation. The x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient. The patient based coordinate system is a right handed system, i.e. the vector cross product of a unit vector along the positive x-axis and a unit vector along the positive y-axis is equal to a unit vector along the positive z-axis. Note If a patient lies parallel to the ground, face-up on the table, with his feet-to-head direction same as the front-to-back direction of the imaging equipment, the direction of the axes of this patient based coordinate system and the equipment based coordinate system in previous versions of this Standard will coincide. The Image Plane Attributes, in conjunction with the Pixel Spacing Attribute, describe the position and orientation of the image slices relative to the patient-based coordinate system. In each image frame the Image Position (Patient) (0020,0032) specifies the origin of the image with respect to the patient-based coordinate system. RCS and the Image Orientation (Patient) (0020,0037) attribute values specify the orientation of the image frame rows and columns. The mapping of pixel location to the RCS is calculated as follows: size 12{ left [ matrix { P rSub { size 8{x} } {} ## P rSub { size 8{y} } {} ## P rSub { size 8{z} } {} ## 1 } right ]= left [ matrix { X rSub { size 8{x} } Δi {} # Y rSub { size 8{x} } Δj {} # 0 {} # S rSub { size 8{x} } {} ## X rSub { size 8{y} } Δi {} # Y rSub { size 8{y} } Δj {} # 0 {} # S rSub { size 8{y} } {} ## X rSub { size 8{z} } Δi {} # Y rSub { size 8{z} } Δj {} # 0 {} # S rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { i {} ## j {} ## 0 {} ## 1 } right ]} {} = M Where: Pxyz The coordinates of the voxel (i,j) in the frame’s image plane in units of mm. Sxyz The three values of the Image Position (Patient) (0020,0032) attributes. It is the location in mm from the origin of the RCS. Xxyz The values from the row (X) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. Yxyz The values from the column (Y) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. i Column index to the image plane. The first column is index zero. i Column pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. j Row index to the image plane. The first row index is zero. j Row pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. Additional constraints apply: 1) The row and column direction cosine vectors shall be orthogonal, i.e. their dot product shall be zero. 2) The row and column direction cosine vectors shall be normal, i.e. the dot product of each direction cosine vector with itself shall be unity.
The x, y, and z coordinates of the upper left hand voxel (center of the first voxel transmitted) of the grid, in mm in the Registered Frame of Reference. See C.7.6.2.1.1 for further explanation.
The Image Position (0020,0032) specifies the x, y, and z coordinates of the upper left hand corner of the image; it is the center of the first voxel transmitted. Image Orientation (0020,0037) specifies the direction cosines of the first row and the first column with respect to the patient. These Attributes shall be provide as a pair. Row value for the x, y, and z axes respectively followed by the Column value for the x, y, and z axes respectively. The direction of the axes is defined fully by the patient’s orientation. The x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient. The patient based coordinate system is a right handed system, i.e. the vector cross product of a unit vector along the positive x-axis and a unit vector along the positive y-axis is equal to a unit vector along the positive z-axis. Note If a patient lies parallel to the ground, face-up on the table, with his feet-to-head direction same as the front-to-back direction of the imaging equipment, the direction of the axes of this patient based coordinate system and the equipment based coordinate system in previous versions of this Standard will coincide. The Image Plane Attributes, in conjunction with the Pixel Spacing Attribute, describe the position and orientation of the image slices relative to the patient-based coordinate system. In each image frame the Image Position (Patient) (0020,0032) specifies the origin of the image with respect to the patient-based coordinate system. RCS and the Image Orientation (Patient) (0020,0037) attribute values specify the orientation of the image frame rows and columns. The mapping of pixel location to the RCS is calculated as follows: size 12{ left [ matrix { P rSub { size 8{x} } {} ## P rSub { size 8{y} } {} ## P rSub { size 8{z} } {} ## 1 } right ]= left [ matrix { X rSub { size 8{x} } Δi {} # Y rSub { size 8{x} } Δj {} # 0 {} # S rSub { size 8{x} } {} ## X rSub { size 8{y} } Δi {} # Y rSub { size 8{y} } Δj {} # 0 {} # S rSub { size 8{y} } {} ## X rSub { size 8{z} } Δi {} # Y rSub { size 8{z} } Δj {} # 0 {} # S rSub { size 8{z} } {} ## 0 {} # 0 {} # 0 {} # 1{} } right ] left [ matrix { i {} ## j {} ## 0 {} ## 1 } right ]} {} = M Where: Pxyz The coordinates of the voxel (i,j) in the frame’s image plane in units of mm. Sxyz The three values of the Image Position (Patient) (0020,0032) attributes. It is the location in mm from the origin of the RCS. Xxyz The values from the row (X) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. Yxyz The values from the column (Y) direction cosine of the Image Orientation (Patient) (0020,0037) attribute. i Column index to the image plane. The first column is index zero. i Column pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. j Row index to the image plane. The first row index is zero. j Row pixel resolution of the Pixel Spacing (0028,0030) attribute in units of mm. Additional constraints apply: 1) The row and column direction cosine vectors shall be orthogonal, i.e. their dot product shall be zero. 2) The row and column direction cosine vectors shall be normal, i.e. the dot product of each direction cosine vector with itself shall be unity.
The dimensions of the grid, in voxels. A triple representing the number of voxels along the X, Y, and Z axes. The resolution of the grid voxels. A triple representing the size of a deformation voxel in along the X, Y, and Z dimension, in mm. A data stream of vectors. See C.20.3.1.3 for further explanation.
The Vector Grid Data attribute (0064,0009) contains the vector data. Each voxel in the Vector Grid Data attribute (0064,0009) is represented by an vector. The vector describes the direction and magnitude of the deformation at the center of the deformation voxel. The order of vectors sent for each vector plane shall be left to right, top to bottom, i.e., the upper left vector (labeled 1,1) is sent first followed by the remainder of row 1, followed by the first vector of row 2 (labeled 2,1) then the remainder of row 2 and so on. A vector triple with values of (NaN,NaN,NaN) shall indicate that the transformation at that point of the deformation grid is undefined. The size of this attribute value is determined by the dimensions specified in the Grid Dimensions attribute (0064,0007). For dimensions of XD\YD\ZD, the size of the attribute value can be calculated with the equation: Number of Bytes = XD * YD * ZD * 3 * 4
The fiducials used to determine the registration. One or more Items may be present. The UID that identifies the fiducial used as registration input.
Modality type. Enumerated Value: FID The date the content creation started. The time the content creation started. A sequence of one or more items, each of which is a fiducial set. Identifies a Frame of Reference that may or may not be an image set (e.g. an atlas or physical space). See C.7.4.1.1.1 for further explanation. Required if Referenced Image Sequence (0008,1140) is absent. May be present otherwise.
The Frame of Reference UID (0020,0052) shall be used to uniquely identify a frame of reference for a series. Each series shall have a single Frame of Reference UID. However, multiple Series within a Study may share a Frame of Reference UID. All images in a Series that share the same Frame of Reference UID shall be spatially related to each other. Notes: 1. Previous versions of this Standard defined a Data Element "Location", which has been retired. Frame of Reference UID provides a completely unambiguous identification of the image location reference used to indicate position. 2. A common Frame of Reference UID may be used to spatially relate localizer images with a set of transverse images. However, in some cases (eg. multiple localizer images being related to a single set of transverse images) a common Frame of Reference UID may not be sufficient. The Referenced Image Sequence (0008,1140) provides an unambiguous method for relating localizer images.
Identifies the set of images in which the fiducials are located. Required if Frame of Reference UID (0020,0052) is absent. May be present otherwise. One or more Items shall be present. All referenced images shall have the same Frame of Reference UID if present in the images. A sequence that specifies one or more fiducials, one item per fiducial. A fiducial assignment identifier that is unique within this Fiducial Sequence item but may match the fiducial identifier of an equivalent feature in another item. A code sequence for a term that identifies a well-known fiducial type (potentially including methodology, anatomy, tools, etc.). Only one item shall be present. Required if Identifier (0070,0310) is absent. May be present otherwise. Globally unique identifier for the fiducial instance of this fiducial assignment. User description or comments about the fiducial. See C.21.2.1.1 for defined terms.
For convenient registration, correlated Fiducials exist in each image set of the Registration Sequence. Correlated Fiducials are identified with either Fiducial Identifier (0070,0310) or Fiducial Identifier Code Sequence (0070,0311). Shape Type (0070,0306) defines the geometric interpretation of the Contour Data (3006,0050) and Graphic Data (0070,0022). A point is defined as a triplet (x,y,z) in the case of spatial data or a pair (x,y) in the case of graphic data. Defined Terms are: POINT = a single point designating a single fiducial point. Note: A point may be the epicenter of a more complex shape such as sphere. LINE = two points that specify a line or axis such as the inter-orbital line. The point locations have no significance other than identifying the line, i.e. they are not line segment end points. PLANE = three points that identify a plane such as the laterality plane SURFACE = three or more points (usually many) that reside on, or near, a region of a curved surface. The surface may be flat or curved, closed or open. The point order has no significance. RULER = two or more evenly spaced collinear points ordered sequentially along the line, such as a physical ruler placed in the imaging field. L_SHAPE = three points of two perpendicular line segments, AB and BC, having a common end point B. The order of the points is: ABC. May represent an L-shaped marker placed in the imaging field. T_SHAPE = three points of two perpendicular line segments AB and CD, such that C bisects AB. The order is ABD. SHAPE = three or more points that specify the shape of a well-known fiducial type. The term in the Fiducial Identifier Code Sequence (0070,0311) defines the shape and the order of the points that represent it.
Number of points (triplets) in Contour Data (3006,0050). Required if Contour Data is present. Specifies the coordinates of this item's fiducial. One triplet (x,y,z) shall be present for each point in the fiducial. See C.21.2.1.2 for further explanation. Required if Frame of Reference UID (0020,0052) is present in this item of the Fiducial Set Sequence (0070,031C). Shall not be present otherwise. Note: Contour Data may not be properly encoded if Explicit-VR transfer syntax is used and the VL of this attribute exceeds 65534 bytes.
Contour Data (3006,0050) is an ordered set of triplets that defines a shape. The triplets (x,y,z) denote points in the Reference Coordinate System of the Registration Instance. Note: Contours may associate observational data with a set of Image features or specify coordinates that are input data for a measurement.
The estimated uncertainty radius for the Contour Data in mm. See C.21.2.1.3
The uncertainty is an estimate of the standard deviation of the fiducial location process.
The image pixel locations of the fiducial's points. Shall contain one or more items. More than one item shall be present only if a fiducial spans more than one image. Required if Contour Data is not present. May be present otherwise. Graphic point coordinates of the fiducial points in the image of the Referenced Image Sequence. If Fiducial's Contour Data (3006,0050) is present, these points correlate to the points in the Contour Data, one row-column pair for each point and in the same order. See C.10.5.1.2 for further explanation.
Graphic Data (0070,0022) contains the points in the graphic annotation, each dimension for the first point, followed by dimensions for second point, etc. For a two dimensional curve: X1, Y1, X2, Y2, etc. The first (X) dimension corresponds to the image or Specified Displayed Area column (horizontal offset), and the second (Y) dimension corresponds to the image or Specified Displayed Area row (vertical offset). The Value Representation of all components of the N-tuple shall be the same. The image or Specified Displayed Area relative drawing space is defined in Graphic Annotation Units (0070,0005). If Graphic Type (0070,0023) is POINT, then two values (one point) shall be specified and the single point specified is to be drawn. If Graphic Type (0070,0023) is POLYLINE, then the points are to be interpreted as an n-tuple list of end points between which straight lines are to be drawn. If Graphic Type (0070,0023) is INTERPOLATED, then the points are to be interpreted as an n-tuple list of end points between which some form of implementation dependent curved lines are to be drawn. The rendered line shall pass through all the specified points. If Graphic Type (0070,0023) is CIRCLE, then exactly two points shall be present; the first point is to be interpreted as the center and the second point as a point on the circumference of a circle, some form of implementation dependent representation of which is to be drawn. If Graphic Type (0070,0023) is ELLIPSE, then exactly four points shall be present; the first two points are to be interpreted as the endpoints of the major axis and the second two points as the endpoints of the minor axis of an ellipse, some form of implementation dependent representation of which is to be drawn. The notion of “open” or “closed” has no inherent meaning in the context of an arbitrary graphic, other than in the condition for the presence of Graphic Filled (0070,0024). The graphic has no semantic notion of an associated observation such as a region of interest, except that which the unformatted text in the same Item may describe. The choice of pixel value used to represent the graphic on a display is defined in the Graphic Layer Module C.10.7. Figure C.10.5-1 Sub-pixel Addressing Units in PIXEL Space
A sequence that specifies the image containing the fiducial's graphic coordinates. Only one item shall be present. Shall be an image within the set of the images in the Referenced Image Sequence (0008,1140) of the encapsulating Fiducial Set Sequence (0070,031C) item.
User or implementation specific human readable identification of the Storage Media to be created. Uniquely identifies a Storage Media to be created. Number of copies of set of media to be created for storing this file-set. Note: If the entire request fits on a single piece of media per copy, then this value corresponds to the actual number of pieces of media to be created. Specifies the priority of the request. Enumerated Values: HIGH MED LOW Specifies whether or not to extract label information from the instances. Enumerated Values: YES NO Unformatted free text to include in the label instead of or in addition to information extracted from the instances. An implementation-dependent code string that may be used as a hint to select a particular layout or format of label. Unstructured text that describes where and to whom the media is to be sent. String that describes the bar code value to be printed on the media label. Note It is SCU responsibility to convey a value for this attribute coherent in length and content with the requested Barcode Symbology (2200,0006). Code string that describes the bar code symbology that shall be used for printing the Barcode Value (2200,0005). See Section C.22.1.1 for Defined Terms.
Defined Terms for Barcode Symbology (2200,0006) are: Note This table doesn’t suppose to list all the bar code symbologies in use (there are currently more than 400). Implementations supporting other symbologies can extend this list. Implementation specific code values shall be defined in the Conformance Statement.
A flag indicating if the SCP is allowed to split this request over more than one piece of media. Enumerated Values: YES NO Note: 1. The SCP is not required to support the split of a media creation request across more than one piece of media. 2. If the size of the set of SOP instances is greater than the media storage capacity, and this flag has been set to NO, the SCP shall refuse to process the request. A flag indicating if the SCP is allowed to perform lossy compression. Enumerated Values: YES NO A flag indicating if the SCP should include in the media additional Non-DICOM information/objects Defined Terms: NO FOR_PHYSICIAN FOR_PATIENT FOR_TEACHING FOR_RESEARCH A flag indicating if the SCP should include on the media a DICOM Instance Display Application. Enumerated Values: NO YES A flag to indicate whether or not the SCU intends to issue a subsequent media creation request referencing some or all of the instances contained in Referenced SOP Sequence (0008,1199). Enumerated Values: YES NO A sequence of Items where each Item references a single SOP Instance, the Media Application Profile to be used, and, where applicable, the icon representing the referenced image The Media Application Profile to be used for this SOP Instance. Note: This is the label of the profile as defined in PS 3.11, e.g. "STD-XABC-CD". This Icon Image is representative of the Image. Execution status of a request. See Section C.22.1.2 for Enumerated Values
Enumerated Values for Execution Status (2100,0020) are:
Additional information about Execution Status (2100,0020). When Execution Status is DONE, CREATING or IDLE, Defined Terms are: NORMAL See Section C.22.1.3 for Defined Terms when the Execution Status is PENDING or FAILURE.
Defined Terms for Execution Status Info (2100,0030) are: Note: For most of the above statuses, the SCU can obtain more details about the processing errors (e.g., what are the SOP instances not available) by using the Failure Reason Attribute (0008,1197) within the Failed SOP Sequence (0008,1198).
Number of pieces of media that have been successfully created, in order to store all copies of the requested file-set. Note: If the entire request fits on a single piece of media per copy, then this value corresponds to the number of copies of media created. A sequence of Items describing SOP Instances for which media creation failed. The Media Application Profile used for this SOP Instance. Note: This is the label of the profile as defined in PS 3.11, e.g. "STD-XABC-CD". The reason that media creation failed for this SOP Instance. See Section C.22.1.4.
Defined Terms for Failure Reason (0008,1197) are:
Attributes associated with the Failure Reason (0008,1197). See Section C.22.1.4.
Defined Terms for Failure Reason (0008,1197) are:
A Sequence describing the identifiers of all pieces of media created to satisfy the request. One or more items are allowed. Note: If the SCP splits a media creation request across more than one piece of media (e.g. if it doesn't fit on one), then all the created pieces of media will be included in this Sequence. User or implementation specific human readable identification of the Storage Media that has been created. Uniquely identifies the Storage Media that has been created.
Short descriptor that identifies the Hanging Protocol. Explanation of the objective or intent of the Hanging Protocol. Identifies the level at which this Hanging Protocol is defined, and the intended use. Enumerated values: MANUFACTURER SITE USER_GROUP SINGLE_USER Identifies the creator of the Hanging Protocol. Date and time on which the Hanging Protocol was created. Sequence that defines the type of imaging studies to which this Hanging Protocol applies. One or more sequence items shall be present. See C.23.1.1.1.
The Hanging Protocol Definition Sequence (0072,000C) provides a collection of one or more sequence items that defines the intent for the Hanging Protocol with respect to modality, anatomy, laterality, procedure and/or reason. This allows for some degree of flexibility in defining the intent for the Hanging Protocol, while providing a precise structure for query matching using the existing rules for Sequence Matching, as defined in PS 3.4. Notes:1. The Hanging Protocol Definition Sequence (0072,000C) does not imply anything about the related image sets. These are defined in the Image Sets Sequence (0072,0020). 2. When creating a Hanging Protocol Instance, the values that are used for Procedure Code Sequence (0008,1032) or Reason for Requested Procedure Code Sequence (0040,100A) may come from a variety of sources, but are expected to be consistent throughout the domain in which a Hanging Protocol Instance will be exchanged. The following are recommended as potential sources of values. Procedure Code Sequence (0008,1032):
Type of equipment that originally acquired the data used to create images or related objects to which this Hanging Protocol applies. See C.7.3.1.1.1 for Defined Terms. Required if Anatomic Region Sequence (0008,2218) is not present. May be present otherwise.
Defined Terms for the Modality (0008,0060) are: Retired Defined Terms for the Modality (0008,0060) are: Note: 1. The XA modality incorporates the retired modality DS. 2. The RF modality incorporates the retired modalities CF, DF, VF. 3. The modality listed in the Modality Data Element (0008,0060) may not match the name of the IOD in which it appears. For example, a SOP instance from XA IOD may list the RF modality when an RF implementation produces an XA object. 4. The MR modality incorporates the retired modalities MA and MS.
Sequence that identifies the anatomic region of interest to which this Hanging Protocol applies. One or more sequence items may be present. Required if Modality (0008,0060) is not present. May be present otherwise. Laterality of the body part to which this Hanging Protocol applies. Enumerated Values: R - Right L - Left B - Both U - Unpaired Zero length means not applicable. Required if Anatomic Region Sequence (0008,2218) is present. Sequence that identifies a procedure to which this Hanging Protocol applies. Zero or more sequence items may be present. Sequence that identifies a reason for procedure to which this Hanging Protocol applies. Zero or more sequence items may be present. Identifies the number of prior image sets used in this Hanging Protocol. Sequence describing one or more types of Image Sets to which the Hanging Protocol applies. One or more sequence items shall be present. See C.23.1.1.2.
The Image Sets Sequence (0072,0020) within a Hanging Protocol Instance serves to identify the type of image or other object sets to which the Hanging Protocol is intended to apply. Multiple types of image sets may be identified for a Hanging Protocol, to combine, for example, multiple imaging studies for a specific anatomy, or multiple imaging studies performed over a period of time, to monitor the progress of a condition. All image sets shall be for the same patient. The images to be included in an Image Set may be specified directly by matching attribute values within the images, or indirectly through Key Object Selection Documents or Presentation States by matching their attribute values. Key Object Selection Documents shall be matched by their SOP Class UID. The available Key Object Selection Documents may be further matched on the values of their other attributes (e.g., Concept Name Code Sequence, Coding Scheme Designator = “DCM” and Code Value = “113003”, which has a code meaning of “For Surgery”). When the Hanging Protocol Instance is applied, the image object instances referenced by the matching Key Object Selection Document instances comprise the image set. Presentation States shall be matched by their SOP Class UID. The available Presentation States may be further matched on the values of their other attributes (e.g., Content Label). When the Hanging Protocol Instance is applied, the image object instances referenced by the matching Presentation State instances comprise the image set. Note: Image Sets Sequence (0072,0020) allows other objects such as waveforms and SR documents to be identified. However, Hanging Protocol Display module operations such as filtering, reformatting, and sorting are defined only for image objects. The only expectation for non-image objects is to associate the objects with a position on a screen. Each sequence item in the Image Sets Sequence (0072,0020) shall follow these rules:
Sequence containing Image Set selection attributes and values that are used to identify one type of image or object set for the Hanging Protocol. One or more sequence items shall be present. See C.23.1.1.3.
The Image Set Selector Sequence (0072,0022) contains sequence items that specify the DICOM attribute tags and values that shall be used to identify the image or other object set. The Image Set Selector Usage Flag (0072,0024) indicates whether the attribute identified by the Selector Attribute (0072,0026) causes matching to succeed or fail if the attribute is not available in an image object. Within a sequence item, the Selector Attribute (0072,0026) identifies a DICOM attribute tag that is likely to be present in image or other object instances that are desired for the Image Set. If it is a multi-valued attribute, the Selector Value Number (0072,0028) indicates which value is intended to be used for matching. The Selector Attribute VR (0072,0050) identifies the Value Representation of the Selector Attribute (0072,0026). The value of Selector Attribute VR (0072,0050) determines which attribute of the Hanging Protocol Selector Attribute Value Macro is required to specify one or more desired values for the DICOM attribute tag. If more than one value is specified for the attribute, or more than one sequence item is specified in the Selector Code Sequence Value (0072,0080), then image object instances with a corresponding attribute that matches any one of the values shall be included in the Image Set. Note: The values used for the Selector Attribute (0072,0026) are intended to identify a type of image set via the general categories of modality, anatomy, procedure intent and/or reason. Therefore the values of the tags represented by Selector Attribute (0072,0026) are likely to be coded terms, enumerated values, defined terms or free text. The use of free text attributes is less desirable, because their values are less predictable for matching. In an image object, some attributes occur at the top level, or nested within a Sequence or Functional Group Sequence, or both. In addition, a Private Attribute may be identified as a Selector Attribute (0072,0026). The attributes of the Hanging Protocol Selector Attribute Context Macro identify a Sequence, Functional Group Sequence, or Private Group context for the Selector Attribute (0072,0026). The creator of a Hanging Protocol Instance uses this collection of attributes to identify one type of image set to which the Hanging Protocol is intended to apply. The user of a Hanging Protocol Instance (e.g., softcopy review workstation or pre-fetching application) uses this collection of attributes to match a specific image set to a Hanging Protocol, and/or to determine which image sets need to be retrieved in order to use a Hanging Protocol Instance. The Key Attributes to match against to obtain image sets are specified in the Selector Attribute (0072,0026) and its context in each sequence item. If the value of the tag represented by Selector Attribute (0072,0026) contains a free text description (i.e., Selector Attribute VR = LO, SH, ST, LT, UT), whether exact or partial matching is used to identify a specific image instance when applying a Hanging Protocol Instance is implementation dependent.
Indicates the behavior of matching against an image object when the Selector Attribute (0072,0026) is not available in the image object. Enumerated Values: MATCH - if the attribute is not in the image object, consider the image to be a match anyway. NO_MATCH - if the attribute is not in the image object, then do not consider the image to be a match. Data Element Tag of an Attribute from an Image or other IOD to use for Image Set selection. The Value Representation of the Selector Attribute (0072,0026). See PS 3.5 for Enumerated Values of Value Representation. Positive integer identifying which value of a multi-valued attribute identified by Selector Attribute (0072,0026) is to be used for Image Set selection. The value 1 identifies the first value. The value zero identifies any value. Sequence containing time based Image Set selection categories and values that are used to identify one type of image set for the Hanging Protocol per sequence item. One or more sequence items shall be present. The Image Set Selector Sequence (0072,0022) shall be applied to each sequence item to define an image set. See C.23.1.1.2.
The Image Sets Sequence (0072,0020) within a Hanging Protocol Instance serves to identify the type of image or other object sets to which the Hanging Protocol is intended to apply. Multiple types of image sets may be identified for a Hanging Protocol, to combine, for example, multiple imaging studies for a specific anatomy, or multiple imaging studies performed over a period of time, to monitor the progress of a condition. All image sets shall be for the same patient. The images to be included in an Image Set may be specified directly by matching attribute values within the images, or indirectly through Key Object Selection Documents or Presentation States by matching their attribute values. Key Object Selection Documents shall be matched by their SOP Class UID. The available Key Object Selection Documents may be further matched on the values of their other attributes (e.g., Concept Name Code Sequence, Coding Scheme Designator = “DCM” and Code Value = “113003”, which has a code meaning of “For Surgery”). When the Hanging Protocol Instance is applied, the image object instances referenced by the matching Key Object Selection Document instances comprise the image set. Presentation States shall be matched by their SOP Class UID. The available Presentation States may be further matched on the values of their other attributes (e.g., Content Label). When the Hanging Protocol Instance is applied, the image object instances referenced by the matching Presentation State instances comprise the image set. Note: Image Sets Sequence (0072,0020) allows other objects such as waveforms and SR documents to be identified. However, Hanging Protocol Display module operations such as filtering, reformatting, and sorting are defined only for image objects. The only expectation for non-image objects is to associate the objects with a position on a screen. Each sequence item in the Image Sets Sequence (0072,0020) shall follow these rules:
A monotonically increasing integer, starting from 1, incrementing by one, unique within the Hanging Protocol Instance. Note: Each item of the Display Sets Sequence (0072,0200) references one Image Set Number (0072,0032). Category of the Time Based Image Set selector. Enumerated Values: RELATIVE_TIME ABSTRACT_PRIOR Exactly two numeric values, indicating the start and end values of a prior range of instance acquisition times relative to the date and time of a current image set. The units shall be specified in Relative Time Units (0072,003A). The value pair 0\0 shall indicate a current image set. The value pair n\n shall indicate "prior from the instance acquisition time of a current image set by n units". Required if the value of Image Set Selector Category (0072,0034) is RELATIVE_TIME. Note: 1. A value pair "1\7" with Relative Time Units (0072,003A) of DAYS would indicate the range "prior by 1 to 7 days before a current image set". 2. The VR of this attribute is unsigned, hence future time cannot be represented. Units of time for Relative Time (0072,0038). Enumerated Values: SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS. Required if Relative Time (0072,0038) is present. Identifies a prior image set in abstract terms. Exactly two integer values, indicating the range of prior studies to include. Each value shall be greater than zero, where 1 indicates the most recent prior and higher values indicate successively older priors. The special value -1 shall indicate the oldest prior. Notes: 1. The value pair n\n indicates the nth prior. 2. The value pair -1\-1 indicates the oldest prior. 3. The value pair m\n indicates the mth through nth priors, where m is the more recent prior. 4. The value pair 1\-1 indicates all priors. 5. The value pair m\-1 indicates the mth prior and all priors older than m. Required if Image Set Selector Category (0072,0034) is ABSTRACT_PRIOR and Abstract Prior Code Sequence (0072,003E) is not present. Identifies a prior image set using coded terminology. Only one sequence item shall be present. Required if Image Set Selector Category (0072,0034) is ABSTRACT_PRIOR and Abstract Prior Value (0072,003C) is not present. Description of the objective of the image set defined by this sequence item. Sequence that provides a coded identifier for the person, group, or site for which this Hanging Protocol was defined. Zero or one item shall be present in the sequence. Note: If a standardized naming schema becomes available, it should be used. Meanwhile, local coding schemes such as employee numbers and department numbers are likely to be used. Group or site for which this Hanging Protocol was defined. Sequence that identifies the Hanging Protocol from which this Hanging Protocol was derived, or on which it is based. One sequence item may be present.
Positive integer indicating the number of screens for which this Hanging Protocol is intended. Sequence of zero or more items that describes the set of screens for which this Hanging Protocol is intended. Positive integer indicating the intended number of rows of the addressable area of the screen in pixels. Note: The goal is not absolute size matching. Positive integer indicating the intended number of columns of the addressable area of the screen in pixels. Note: The goal is not absolute size matching. Exactly four unitless floating point values indicating the rectangular coordinate position of the screen within the overall bounding box that encompasses all the screens. See C.23.2.1.1.
For the Display Environment Spatial Position (0072,0108) attribute, the lower left corner of the overall bounding box has Cartesian coordinates of (0.0,0.0). The upper right corner has coordinates of (1.0,1.0). The scale of the box is based on the Number of Vertical Pixels (0072,0104) and Number of Horizontal Pixels (0072,0106), not the physical size of the screens that are part of the workstation. The coordinates of each individual screen’s box are defined in absolute coordinates relative to the (0,0) and (1,1) range of the overall box. Position of a box is given by a (x1,y1), (x2,y2) pair that identifies the upper left corner and lower right corner if the box is rectangular. Note: The goal is not absolute position matching of the image boxes rendered on the screens using Hanging Protocol layout information, but that the relative positioning of the image boxes should be consistent between different workstations. The following figure depicts a 1K x 1K screen positioned to the left of a 2K x 2.5K screen. The Display Environment Spatial Position (0072,0108) of the 1K x 1K screen is (0.0,0.4) (0.33,0.0), and the Display Environment Spatial Position (0072,0108) of the 2K x 2.5K screen is (0.33,1.0) (1.0,0.0).
Positive integer indicating the desired minimum number of grayscale bits per pixel of the screen. Required if Screen Minimum Color Bit Depth (0072,010C) is not present. Positive integer indicating the desired minimum total number of bits per color channel used to present a pixel. Required if Screen Minimum Grayscale Bit Depth (0072,010A) is not present. Note: A 24-bit color system with 8 bits per color channel (red, green, blue) would have a value of 8. Positive integer indicating the desired maximum time in milliseconds required by the application to repaint the full screen once (i.e., recalculate all pixels and paint them to the screen). Note: This is not the screen refresh time.
Sequence that describes one or more display sets used to present the Image Sets defined in the Image Sets Sequence (0072,0020). One or more sequence items shall be present. See C.23.3.1.
The attributes of a Display Set Sequence Item shall be applied to the image set represented by the value of Image Set Number (0072,0032) in the following order:
A monotonically increasing integer, starting from 1, incrementing by one, unique within the Hanging Protocol Instance. It shall be used to identify linked display sets in the Display Set Scrolling Group (0072,0212). Description of the objective of the display set defined by this sequence item. Positive integer value that designates this Display Set as part of a specific presentation group. All Display Sets with the same Display Set Presentation Group (0072,0204) value shall be displayed at the same time. The value 1 shall indicate that this Display Set is part of the initial presentation group.Subsequent values incrementing by 1 shall imply successive temporal ordering of display. Image Set Number (0072,0032) value from a Time Based Image Sets Sequence (0072,0030) Item within the Image Sets Sequence (0072,0020) Item that is selected for display by this Display Set. Note: Multiple Image Boxes Sequence (0072,0300) Items within a Display Sets Sequence (0072,0200) Item may be used to spread one image set over multiple image boxes with the same Display Set characteristics. Sequence that defines the image boxes for this Display Set. Exactly one sequence item shall be present unless Image Box Layout Type (0072,0304) is TILED, in which case one or more items shall be present. A monotonically increasing integer that identifies the order of image boxes for scrolling, starting from 1, incrementing by one, unique within a Display Set Sequence Item. Exactly four unitless floating point values indicating the rectangular coordinate position of the image box within the overall bounding box that encompasses all the display space (across all screens). See C.23.2.1.1.
For the Display Environment Spatial Position (0072,0108) attribute, the lower left corner of the overall bounding box has Cartesian coordinates of (0.0,0.0). The upper right corner has coordinates of (1.0,1.0). The scale of the box is based on the Number of Vertical Pixels (0072,0104) and Number of Horizontal Pixels (0072,0106), not the physical size of the screens that are part of the workstation. The coordinates of each individual screen’s box are defined in absolute coordinates relative to the (0,0) and (1,1) range of the overall box. Position of a box is given by a (x1,y1), (x2,y2) pair that identifies the upper left corner and lower right corner if the box is rectangular. Note: The goal is not absolute position matching of the image boxes rendered on the screens using Hanging Protocol layout information, but that the relative positioning of the image boxes should be consistent between different workstations. The following figure depicts a 1K x 1K screen positioned to the left of a 2K x 2.5K screen. The Display Environment Spatial Position (0072,0108) of the 1K x 1K screen is (0.0,0.4) (0.33,0.0), and the Display Environment Spatial Position (0072,0108) of the 2K x 2.5K screen is (0.33,1.0) (1.0,0.0).
Type of layout of the image box. All types except for TILED are single rectangles containing a single frame of image pixel data. The types are primarily distinguished by their interaction technique. Defined Terms: TILED: a scrollable array of rectangles, each containing a single frame of image pixel data. STACK: a single rectangle containing a steppable single frame, intended for user-controlled stepping through the image set, usually via continuous device interaction (e.g., mouse scrolling) or by single stepping (mouse or button click). CINE: a single rectangle, intended for video type play back where the user controls are play sequence, rate of play, and direction. PROCESSED: intended for interactive 3D visualizations that have custom interfaces. SINGLE: a single rectangle, intended for images and objects with no defined methods of interaction. Note: This value may also be used for non-image objects, such as waveforms and SR documents. Positive integer defining the horizontal Image Box tile dimension; the number of columns. Required if the value of Image Box Layout Type (0072,0304) is TILED. Positive integer defining the vertical Image Box tile dimension; the number of rows. Required if the value of Image Box Layout Type (0072,0304) is TILED. Enumerated Values: VERTICAL: scroll images by row HORIZONTAL: scroll images by column. Required if the value of Image Box Layout Type (0072,0304) is TILED, and the value of Image Box Tile Horizontal Dimension (0072,0306) or Image Box Tile Vertical Dimension (0072,0308) is greater than 1. Defines the type of small increment scrolling to be applied to this Image Box. Required if the value of Image Box Layout Type (0072,0304) is TILED, and the value of Image Box Tile Horizontal Dimension (0072,0306) or Image Box Tile Vertical Dimension (0072,0308) is greater than 1. Scrolling is not specified if zero length. Enumerated Values: PAGE: In a TILED image box, replace all image slots with the next N x M images in the set, ROW_COLUMN: in a TILED image box, move each row or column of images to the next row or column, depending on Image Box Scroll Direction (0072,0310) IMAGE: In a TILED image box, move each image to the next slot, either horizontally or vertically, depending on Image Box Scroll Direction (0072,0310) Note: If there are multiple image boxes of different Tile Dimensions in a Display Set, then only IMAGE scrolling applies, and the value of this attribute is ignored. Defines the positive integer number of pages, rows, columns, or images per small increment scroll, based on the values of Image Box Small Scroll Type (0072,0312) and Image Box Scroll Direction (0072,0310). The value applies to both forward and backward scrolling. Required if Image Box Small Scroll Type (0072,0312) is present with a value. Defines the type of large increment scrolling to be applied to this Image Box. Required if the value of Image Box Layout Type (0072,0304) is TILED, and the value of Image Box Tile Horizontal Dimension (0072,0306) or Image Box Tile Vertical Dimension (0072,0308) is greater than 1. Enumerated Values: PAGE: In a TILED image box, replace all image slots with the next N x M images in the set, ROW_COLUMN: in a TILED image box, move each row or column of images to the next row or column, depending on Image Box Scroll Direction (0072,0310) IMAGE: In a TILED image box, move each image to the next slot, either horizontally or vertically, depending on Image Box Scroll Direction (0072,0310) Note: If there are multiple image boxes of different Tile Dimensions in a Display Set, then only IMAGE scrolling applies, and the value of the attribute is ignored. Defines the positive integer number of pages, rows, columns, or images per large increment scroll, based on the values of Image Box Large Scroll Type (0072,0316) and Image Box Scroll Direction (0072,cc50). The value applies to both forward and backward scrolling. Required if Image Box Large Scroll Type (0072,0316) is present with a value. If this Image Box overlaps in spatial position with others, this attribute indicates the layer of this Image Box in relation to the others. The value shall be a positive integer in the range 1 to 100, where 1 = top and 100 = bottom. If this attribute is not present, then the expected behavior is not defined. Describes the preferred playback sequencing for the Image Box. Overrides any Preferred Playback Sequencing (0018,1244) value in the image objects being displayed. Required if the value of Image Box Layout Type (0072,0304) is CINE. Enumerated Values: 0 = Looping (1,2...n,1,2,...n,1,2,....n,...) 1 = Sweeping (1,2,...n,n-1,...2,1,2,...n,...) 2 = Stop (1,2…n) Recommended rate at which the frames of a multi-frame image shall be displayed, in frames/second. Shall have a value greater than zero. Overrides any Recommended Display Frame Rate (0008,2144) value in the image objects being displayed. Required if the value of Image Box Layout Type (0072,0304) is CINE and if Cine Relative to Real-Time (0072,0330) is not present. A positive unitless floating point numeric factor equal to playback rate divided by acquisition rate. Required if the value of Image Box Layout Type (0072,0304) is CINE and if Recommended Display Frame Rate (0008,2144) is not present. Note: The capture rate may change within the image object, as specified in Frame Time (0018,1063) or Frame Time Vector (0018,1065). Sequence that defines filter criteria to be applied to the image set identified by Image Set Number (0072,0032). Zero or more items shall be included in this sequence. See C.23.3.1.1.
The items in the Filter Operations Sequence (0072,0400) determine which subset of the images in the identified Image Set are to be displayed in the associated Display Set image boxes. If there are multiple Items in the Filter Operations Sequence (0072,0400), the filter operations shall be applied in Item order, and the output of the preceding filter shall serve as the input to the succeeding filter (i.e., an AND operation). When Filter-by Category (0072,0402) has a value of IMAGE_PLANE, Selector Attribute VR (0072,0050) shall have a value of “CS”, and abstract enumerated values shall be used for the value of the associated Selector CS Value (0072,0062) attribute, which may be computed from the values of Image Orientation (Patient) (0020,0037) or Patient Orientation (0020,0020). Enumerated Values: TRANSVERSE, CORONAL, SAGITTAL, OBLIQUE. Note: Cross-sectional images do not normally contain a categorical description of the image plane, but rather only a patient-relative row and column direction cosines that are unit vectors. The category of image plane can be determined first by categorizing the row and column major directions (or detecting if the orientation is oblique according to a pre-specified threshold), and then using those categories to select a plan category. The following pseudo-code can be used to determine the major axis (R or L, A or P, H or F) from a single direction cosine that is an (x,y,z) tuple (as defined in C.7.6.2.1.1): if (abs(x) > threshold) axis = “RL” else if (abs(y) > threshold) axis = “AP” else if (abs(z) > threshold) axis = “HF” else is OBLIQUE Having determined the major axis of the row and column, the category of plane can be obtained from a table lookup: Alternatively, one can obtain a single vector that is the normal to the orientation (cross product of the row and column unit vectors), then find which of the x, y and z components has the maximum absolute value that is above threshold; if x then SAGITTAL, if y then CORONAL, if z then TRANSVERSE; if all of the components are below threshold then the orientation is OBLIQUE. Since it is also necessary to determine whether or not to flip or rotate the image into the preferred orientation (as specified by Display Set Patient orientation (0072,0700)) for the category of plane (e.g., sagittals are normally viewed with row direction posteriorly and column direction towards the feet), the categorical row and column direction to use can be obtained as above, additional accounting for the sign of the direction cosine, e.g.: if x < 0 then orientationX = “R” else orientationX = “L” if y < 0 then orientationY = “A” else orientationY = “P” if z < 0 then orientationZ = “F” else orientationZ = “H” if (abs(x) > threshold) orientation = orientationX … An application that is applying a Hanging Protocol Instance shall support any value for Selector Attribute (0072,0026). If the attribute identified by Selector Attribute is not present in an image of the referenced Image Set, then the image is included in the filter output. The attributes of the Hanging Protocol Selector Attribute Context Macro specify whether the Selector Attribute (0072,0026) is contained in a Sequence, Functional Group Sequence, or Private Group. Notes: 1. The following attributes from image IODs are examples of some possible values for the Selector Attribute (0072,0026) of the Filter Operations Sequence (0072,0400). This is not a complete list:
Category of the filter operation. See C.23.3.1.1. Defined terms: IMAGE_PLANE Required if Selector Attribute (0072,0026) is not present.
The items in the Filter Operations Sequence (0072,0400) determine which subset of the images in the identified Image Set are to be displayed in the associated Display Set image boxes. If there are multiple Items in the Filter Operations Sequence (0072,0400), the filter operations shall be applied in Item order, and the output of the preceding filter shall serve as the input to the succeeding filter (i.e., an AND operation). When Filter-by Category (0072,0402) has a value of IMAGE_PLANE, Selector Attribute VR (0072,0050) shall have a value of “CS”, and abstract enumerated values shall be used for the value of the associated Selector CS Value (0072,0062) attribute, which may be computed from the values of Image Orientation (Patient) (0020,0037) or Patient Orientation (0020,0020). Enumerated Values: TRANSVERSE, CORONAL, SAGITTAL, OBLIQUE. Note: Cross-sectional images do not normally contain a categorical description of the image plane, but rather only a patient-relative row and column direction cosines that are unit vectors. The category of image plane can be determined first by categorizing the row and column major directions (or detecting if the orientation is oblique according to a pre-specified threshold), and then using those categories to select a plan category. The following pseudo-code can be used to determine the major axis (R or L, A or P, H or F) from a single direction cosine that is an (x,y,z) tuple (as defined in C.7.6.2.1.1): if (abs(x) > threshold) axis = “RL” else if (abs(y) > threshold) axis = “AP” else if (abs(z) > threshold) axis = “HF” else is OBLIQUE Having determined the major axis of the row and column, the category of plane can be obtained from a table lookup: Alternatively, one can obtain a single vector that is the normal to the orientation (cross product of the row and column unit vectors), then find which of the x, y and z components has the maximum absolute value that is above threshold; if x then SAGITTAL, if y then CORONAL, if z then TRANSVERSE; if all of the components are below threshold then the orientation is OBLIQUE. Since it is also necessary to determine whether or not to flip or rotate the image into the preferred orientation (as specified by Display Set Patient orientation (0072,0700)) for the category of plane (e.g., sagittals are normally viewed with row direction posteriorly and column direction towards the feet), the categorical row and column direction to use can be obtained as above, additional accounting for the sign of the direction cosine, e.g.: if x < 0 then orientationX = “R” else orientationX = “L” if y < 0 then orientationY = “A” else orientationY = “P” if z < 0 then orientationZ = “F” else orientationZ = “H” if (abs(x) > threshold) orientation = orientationX … An application that is applying a Hanging Protocol Instance shall support any value for Selector Attribute (0072,0026). If the attribute identified by Selector Attribute is not present in an image of the referenced Image Set, then the image is included in the filter output. The attributes of the Hanging Protocol Selector Attribute Context Macro specify whether the Selector Attribute (0072,0026) is contained in a Sequence, Functional Group Sequence, or Private Group. Notes: 1. The following attributes from image IODs are examples of some possible values for the Selector Attribute (0072,0026) of the Filter Operations Sequence (0072,0400). This is not a complete list:
Operation to be applied based on the presence or absence of the attribute represented by Selector Attribute (0072,0026) in each image of the Image Set. Required if Selector Attribute (0072,0026) is present and Filter-by Operator (0072,0406) is not present. Enumerated Values: PRESENT: Include the image if the attribute is present NOT_PRESENT: Include the image if the attribute is not present Data Element Tag of an Attribute from an Image IOD to use as a filter. See C.23.3.1.1 for potential attributes. Required if Filter-by Category (0072,0402) is not present.
The items in the Filter Operations Sequence (0072,0400) determine which subset of the images in the identified Image Set are to be displayed in the associated Display Set image boxes. If there are multiple Items in the Filter Operations Sequence (0072,0400), the filter operations shall be applied in Item order, and the output of the preceding filter shall serve as the input to the succeeding filter (i.e., an AND operation). When Filter-by Category (0072,0402) has a value of IMAGE_PLANE, Selector Attribute VR (0072,0050) shall have a value of “CS”, and abstract enumerated values shall be used for the value of the associated Selector CS Value (0072,0062) attribute, which may be computed from the values of Image Orientation (Patient) (0020,0037) or Patient Orientation (0020,0020). Enumerated Values: TRANSVERSE, CORONAL, SAGITTAL, OBLIQUE. Note: Cross-sectional images do not normally contain a categorical description of the image plane, but rather only a patient-relative row and column direction cosines that are unit vectors. The category of image plane can be determined first by categorizing the row and column major directions (or detecting if the orientation is oblique according to a pre-specified threshold), and then using those categories to select a plan category. The following pseudo-code can be used to determine the major axis (R or L, A or P, H or F) from a single direction cosine that is an (x,y,z) tuple (as defined in C.7.6.2.1.1): if (abs(x) > threshold) axis = “RL” else if (abs(y) > threshold) axis = “AP” else if (abs(z) > threshold) axis = “HF” else is OBLIQUE Having determined the major axis of the row and column, the category of plane can be obtained from a table lookup: Alternatively, one can obtain a single vector that is the normal to the orientation (cross product of the row and column unit vectors), then find which of the x, y and z components has the maximum absolute value that is above threshold; if x then SAGITTAL, if y then CORONAL, if z then TRANSVERSE; if all of the components are below threshold then the orientation is OBLIQUE. Since it is also necessary to determine whether or not to flip or rotate the image into the preferred orientation (as specified by Display Set Patient orientation (0072,0700)) for the category of plane (e.g., sagittals are normally viewed with row direction posteriorly and column direction towards the feet), the categorical row and column direction to use can be obtained as above, additional accounting for the sign of the direction cosine, e.g.: if x < 0 then orientationX = “R” else orientationX = “L” if y < 0 then orientationY = “A” else orientationY = “P” if z < 0 then orientationZ = “F” else orientationZ = “H” if (abs(x) > threshold) orientation = orientationX … An application that is applying a Hanging Protocol Instance shall support any value for Selector Attribute (0072,0026). If the attribute identified by Selector Attribute is not present in an image of the referenced Image Set, then the image is included in the filter output. The attributes of the Hanging Protocol Selector Attribute Context Macro specify whether the Selector Attribute (0072,0026) is contained in a Sequence, Functional Group Sequence, or Private Group. Notes: 1. The following attributes from image IODs are examples of some possible values for the Selector Attribute (0072,0026) of the Filter Operations Sequence (0072,0400). This is not a complete list:
The Value Representation of the Selector Attribute (0072,0026). Required if Selector Attribute (0072,0026) or Filter-by Category (0072,0402), and Filter-by Operator (0072,0406) are present. Positive integer identifying which value of the attribute identified by Selector Attribute (0072,0026) is to be used for filtering. The value 1 identifies the first value. The value zero identifies any value. Required if Selector Attribute (0072,0026) and Filter-by Operator (0072,0406) are present. Operation to be applied between the value(s) in the Hanging Protocol Selector Attribute Value Macro ("selector"), and the value(s) of the attribute identified by Selector Attribute (0072,0026) in each image of the Image Set. See C.23.3.1.1. Required if Filter-by Category (0072,0402) is present, or if Selector Attribute (0072,0026) is present and Filter-by Attribute Presence (0072,0404) is not present. Enumerated Values: RANGE_INCL: the values lie within the specified range, or are equal to the endpoints; applies only to numeric, date or time Selector Attribute (0072,0026); two values shall be present in the selector, the first of which is less than or equal to the second RANGE_EXCL: the values lie outside the specified range, and are not equal to the endpoints; applies only to numeric Selector Attribute (0072,0026); two values shall be present in the selector, the first of which is less than or equal to the second GREATER_OR_EQUAL: applies only to numeric Selector Attribute (0072,0026) LESS_OR_EQUAL: applies only to numeric Selector Attribute (0072,0026) GREATER_THAN: applies only to numeric Selector Attribute (0072,0026) LESS_THAN: applies only to numeric Selector Attribute (0072,0026) MEMBER_OF: one of the values in the image is present in the values of the selector; if one value is present in each, this is an "equal to" operator NOT_MEMBER_OF: none of the values in the image is present in the values of the selector; if one value is present in each, this is a "not equal to" operator
The items in the Filter Operations Sequence (0072,0400) determine which subset of the images in the identified Image Set are to be displayed in the associated Display Set image boxes. If there are multiple Items in the Filter Operations Sequence (0072,0400), the filter operations shall be applied in Item order, and the output of the preceding filter shall serve as the input to the succeeding filter (i.e., an AND operation). When Filter-by Category (0072,0402) has a value of IMAGE_PLANE, Selector Attribute VR (0072,0050) shall have a value of “CS”, and abstract enumerated values shall be used for the value of the associated Selector CS Value (0072,0062) attribute, which may be computed from the values of Image Orientation (Patient) (0020,0037) or Patient Orientation (0020,0020). Enumerated Values: TRANSVERSE, CORONAL, SAGITTAL, OBLIQUE. Note: Cross-sectional images do not normally contain a categorical description of the image plane, but rather only a patient-relative row and column direction cosines that are unit vectors. The category of image plane can be determined first by categorizing the row and column major directions (or detecting if the orientation is oblique according to a pre-specified threshold), and then using those categories to select a plan category. The following pseudo-code can be used to determine the major axis (R or L, A or P, H or F) from a single direction cosine that is an (x,y,z) tuple (as defined in C.7.6.2.1.1): if (abs(x) > threshold) axis = “RL” else if (abs(y) > threshold) axis = “AP” else if (abs(z) > threshold) axis = “HF” else is OBLIQUE Having determined the major axis of the row and column, the category of plane can be obtained from a table lookup: Alternatively, one can obtain a single vector that is the normal to the orientation (cross product of the row and column unit vectors), then find which of the x, y and z components has the maximum absolute value that is above threshold; if x then SAGITTAL, if y then CORONAL, if z then TRANSVERSE; if all of the components are below threshold then the orientation is OBLIQUE. Since it is also necessary to determine whether or not to flip or rotate the image into the preferred orientation (as specified by Display Set Patient orientation (0072,0700)) for the category of plane (e.g., sagittals are normally viewed with row direction posteriorly and column direction towards the feet), the categorical row and column direction to use can be obtained as above, additional accounting for the sign of the direction cosine, e.g.: if x < 0 then orientationX = “R” else orientationX = “L” if y < 0 then orientationY = “A” else orientationY = “P” if z < 0 then orientationZ = “F” else orientationZ = “H” if (abs(x) > threshold) orientation = orientationX … An application that is applying a Hanging Protocol Instance shall support any value for Selector Attribute (0072,0026). If the attribute identified by Selector Attribute is not present in an image of the referenced Image Set, then the image is included in the filter output. The attributes of the Hanging Protocol Selector Attribute Context Macro specify whether the Selector Attribute (0072,0026) is contained in a Sequence, Functional Group Sequence, or Private Group. Notes: 1. The following attributes from image IODs are examples of some possible values for the Selector Attribute (0072,0026) of the Filter Operations Sequence (0072,0400). This is not a complete list:
Sequence that defines sorting criteria to be applied to the result of filter and reformat operations, to define the order in which to present the images in the Image Boxes. Zero or more items shall be included in this sequence. See C.23.3.1.2.
The Items in the Sorting Operations Sequence (0072,0600) define the order in which the images resulting from the filter and reformat operations on the Image Set are to be displayed in the associated Image Boxes of the Display Set. The sorting criteria may include the value of a numeric, date, or time Attribute that is expected to be present in each of the image objects in the filtered Image Set, and/or an abstract sorting category. A sorting direction shall be associated with each sorting criterion. If a textual Attribute is used for sorting, then the INCREASING sorting direction indicates alphabetical order, and DECREASING indicates reverse alphabetical order. If a code sequence Attribute is used for sorting, then the Code Meaning (0008,0104) shall be sorted alphabetically. If a string numeric Attribute is used for sorting (VR of IS or DS), then sorting shall be on the numeric value, and padding shall be ignored. When sorting by date or time Attribute, then sorting shall be on the temporal value, not the alphabetic string. If there are multiple Items in the Sorting Operations Sequence (0072,0600), then the sorting operations shall be applied in Item order. The least rapidly varying attribute for the sorting operation shall be the first Item in the sequence. Note: For example, a Sorting Operations Sequence (0072,0600) with two Items: Item #1: (0018,5101) View Position, INCREASING Item #2: (0008,0020) Study Date, INCREASING results in the following order, based on these attribute values in the image objects: When the Sort-by Category (0072,0602) is used with a value of ALONG_AXIS, such as for CT, MR or other cross-sectional image sets, the sorting operation is computed from the values Image Position (Patient) (0020,0032) and Image Orientation (Patient) (0020,0037) in the image objects. For the image set to be displayed, a “dominant axis” of the set shall be determined. The dominant axis is the normal to the Image Orientation (Patient) (0020,0037) attribute (assuming all selected images are parallel), computed as the dot product in a right-handed coordinate system (see C.7.6.2.1.1). The INCREASING direction for ALONG_AXIS of the image set shall be in the positive direction along the dominant axis. The DECREASING direction shall be in the negative direction along that axis. When the Sort-by Category (0072,0602) is used with a value of BY_ACQ_TIME, the sorting operation is computed from appropriate values in the image objects (e.g., Frame Acquisition DateTime, Acquisition Time, Content Time, Acquisition DateTime), since the specific attribute used may vary from one Image Instance or SOP Class to another, yet the Hanging Protocol Instance may be generally applicable. An application that is applying a Hanging Protocol Instance shall support any value for Selector Attribute (0072,0026), provided that it is present in the referenced Image Set. The attributes of the Hanging Protocol Selector Attribute Context Macro specify whether the Selector Attribute (0072,0026) is contained in a Sequence, Functional Group Sequence or Private Group. Notes: 1. The following attributes from image IODs are examples of some possible values for the Selector Attribute (0072,0026) of the Sorting Operations Sequence (0072,0600). This is not a complete list:
Data Element Tag of an Attribute from an Image IOD to be used for sorting. See C.23.3.1.2 for potential attributes. Required if Sort-by Category (0072,0602) is not present.
The Items in the Sorting Operations Sequence (0072,0600) define the order in which the images resulting from the filter and reformat operations on the Image Set are to be displayed in the associated Image Boxes of the Display Set. The sorting criteria may include the value of a numeric, date, or time Attribute that is expected to be present in each of the image objects in the filtered Image Set, and/or an abstract sorting category. A sorting direction shall be associated with each sorting criterion. If a textual Attribute is used for sorting, then the INCREASING sorting direction indicates alphabetical order, and DECREASING indicates reverse alphabetical order. If a code sequence Attribute is used for sorting, then the Code Meaning (0008,0104) shall be sorted alphabetically. If a string numeric Attribute is used for sorting (VR of IS or DS), then sorting shall be on the numeric value, and padding shall be ignored. When sorting by date or time Attribute, then sorting shall be on the temporal value, not the alphabetic string. If there are multiple Items in the Sorting Operations Sequence (0072,0600), then the sorting operations shall be applied in Item order. The least rapidly varying attribute for the sorting operation shall be the first Item in the sequence. Note: For example, a Sorting Operations Sequence (0072,0600) with two Items: Item #1: (0018,5101) View Position, INCREASING Item #2: (0008,0020) Study Date, INCREASING results in the following order, based on these attribute values in the image objects: When the Sort-by Category (0072,0602) is used with a value of ALONG_AXIS, such as for CT, MR or other cross-sectional image sets, the sorting operation is computed from the values Image Position (Patient) (0020,0032) and Image Orientation (Patient) (0020,0037) in the image objects. For the image set to be displayed, a “dominant axis” of the set shall be determined. The dominant axis is the normal to the Image Orientation (Patient) (0020,0037) attribute (assuming all selected images are parallel), computed as the dot product in a right-handed coordinate system (see C.7.6.2.1.1). The INCREASING direction for ALONG_AXIS of the image set shall be in the positive direction along the dominant axis. The DECREASING direction shall be in the negative direction along that axis. When the Sort-by Category (0072,0602) is used with a value of BY_ACQ_TIME, the sorting operation is computed from appropriate values in the image objects (e.g., Frame Acquisition DateTime, Acquisition Time, Content Time, Acquisition DateTime), since the specific attribute used may vary from one Image Instance or SOP Class to another, yet the Hanging Protocol Instance may be generally applicable. An application that is applying a Hanging Protocol Instance shall support any value for Selector Attribute (0072,0026), provided that it is present in the referenced Image Set. The attributes of the Hanging Protocol Selector Attribute Context Macro specify whether the Selector Attribute (0072,0026) is contained in a Sequence, Functional Group Sequence or Private Group. Notes: 1. The following attributes from image IODs are examples of some possible values for the Selector Attribute (0072,0026) of the Sorting Operations Sequence (0072,0600). This is not a complete list:
Positive integer identifying which value of the attribute identified by Selector Attribute (0072,0026) is to be used for sorting. The value of 1 identifies the first value. Shall not be zero. Required if Selector Attribute (0072,0026) is present. Category of the sorting operation. See C.23.3.1.2. Defined terms: ALONG_AXIS: for CT, MR, other cross-sectional image sets BY_ACQ_TIME Required if Selector Attribute (0072,0026) is not present.
The Items in the Sorting Operations Sequence (0072,0600) define the order in which the images resulting from the filter and reformat operations on the Image Set are to be displayed in the associated Image Boxes of the Display Set. The sorting criteria may include the value of a numeric, date, or time Attribute that is expected to be present in each of the image objects in the filtered Image Set, and/or an abstract sorting category. A sorting direction shall be associated with each sorting criterion. If a textual Attribute is used for sorting, then the INCREASING sorting direction indicates alphabetical order, and DECREASING indicates reverse alphabetical order. If a code sequence Attribute is used for sorting, then the Code Meaning (0008,0104) shall be sorted alphabetically. If a string numeric Attribute is used for sorting (VR of IS or DS), then sorting shall be on the numeric value, and padding shall be ignored. When sorting by date or time Attribute, then sorting shall be on the temporal value, not the alphabetic string. If there are multiple Items in the Sorting Operations Sequence (0072,0600), then the sorting operations shall be applied in Item order. The least rapidly varying attribute for the sorting operation shall be the first Item in the sequence. Note: For example, a Sorting Operations Sequence (0072,0600) with two Items: Item #1: (0018,5101) View Position, INCREASING Item #2: (0008,0020) Study Date, INCREASING results in the following order, based on these attribute values in the image objects: When the Sort-by Category (0072,0602) is used with a value of ALONG_AXIS, such as for CT, MR or other cross-sectional image sets, the sorting operation is computed from the values Image Position (Patient) (0020,0032) and Image Orientation (Patient) (0020,0037) in the image objects. For the image set to be displayed, a “dominant axis” of the set shall be determined. The dominant axis is the normal to the Image Orientation (Patient) (0020,0037) attribute (assuming all selected images are parallel), computed as the dot product in a right-handed coordinate system (see C.7.6.2.1.1). The INCREASING direction for ALONG_AXIS of the image set shall be in the positive direction along the dominant axis. The DECREASING direction shall be in the negative direction along that axis. When the Sort-by Category (0072,0602) is used with a value of BY_ACQ_TIME, the sorting operation is computed from appropriate values in the image objects (e.g., Frame Acquisition DateTime, Acquisition Time, Content Time, Acquisition DateTime), since the specific attribute used may vary from one Image Instance or SOP Class to another, yet the Hanging Protocol Instance may be generally applicable. An application that is applying a Hanging Protocol Instance shall support any value for Selector Attribute (0072,0026), provided that it is present in the referenced Image Set. The attributes of the Hanging Protocol Selector Attribute Context Macro specify whether the Selector Attribute (0072,0026) is contained in a Sequence, Functional Group Sequence or Private Group. Notes: 1. The following attributes from image IODs are examples of some possible values for the Selector Attribute (0072,0026) of the Sorting Operations Sequence (0072,0600). This is not a complete list:
Sorting direction to be applied to the value(s) in the image set of the attribute identified by Selector Attribute (0072,0026) or Sort-by Category (0072,0602). Enumerated Values: INCREASING, DECREASING Type of blending of superimposed and underlying images from the image set, performed before reformatting. See C.23.3.1.3. Defined Terms: COLOR - apply a pseudo-color to the superimposed image while blending
A Blending Operation Type (0072,0500) of COLOR implies that the filtered selected image set contains two sets of images appropriate for blending, such as CT and PET images defined in the same frame of reference or associated by a spatial registration object. The decision as to which subset are the underlying images and which subset are the superimposed images is left to the discretion of the display application. There is no mechanism to explicitly specify the two subsets. The relative opacity and color-related aspects of blending are not specified by the Hanging Protocol, and are left to the discretion of the application.
Reformatting operation to be applied to the Image Set. Defined terms: MPR, 3D_RENDERING, SLAB The desired thickness of the reformatted images in millimeters. Required if value of Reformatting Operation Type (0072,0510) is SLAB or MPR. May be present otherwise. The desired spacing of the reformatted images in millimeters. The spacing is measured from the center-to-center of each reconstructed image. Required if value of Reformatting Operation Type (0072,0510) is SLAB or MPR. May be present otherwise. Initial view of the reformatted images. Required if the value of Reformatting Operation Type (0072,0510) is MPR or 3D_RENDERING. May be present otherwise. Defined Terms: SAGITTAL, TRANSVERSE, CORONAL, OBLIQUE Describes the intended 3D rendering type. One or more values shall be present. The first value shall not be zero length. Required if the value of Reformatting Operation Type (0072,0510) is 3D_RENDERING: Defined Terms for value 1: MIP, SURFACE, VOLUME Additional values may be used to identify implementation specific sub-types. Patient direction of the rows and columns of the images, as intended for display. See C.23.3.1.4.
The attributes that indicate the presentation intent for each Display Set of a Hanging Protocol Instance are: Display Set Patient Orientation (0072,0700), VOI Type (0072,0702), Pseudo-color Type (0072,0704), Show Grayscale Inverted (0072,0706), Show Image True Size Flag (0072,0710), Show Graphic Annotation Flag (0072,0712), Show Patient Demographics Flag (0072,0714), and Show Acquisition Techniques Flag (0072,0716).
Indicates direction in which to horizontally justify the image within a viewport that is not the same shape (aspect ratio) as the image. Enumerated Values: LEFT CENTER RIGHT Note: Typically used in mammography display applications in which images from the patient's left and right are displayed "back to back", rather than centered. Indicates direction in which to vertically justify the image within a viewport that is not the same shape (aspect ratio) as the image. Enumerated Values: TOP CENTER BOTTOM Expected value of interest transformation for display (e.g., Window Center and Window Width or VOI LUT). Defined Terms: LUNG MEDIASTINUM ABDO_PELVIS LIVER SOFT_TISSUE BONE BRAIN POST_FOSSA A category of pseudo-color palette choice to be applied after application of the VOI LUT. If this attribute is not present, a pseudo-color palette shall not be applied. Defined Terms: BLACK_BODY HOT_IRON DEFAULT Whether or not to invert the rendered luminance of the displayed values. See C.23.3.1.4. Enumerated values: YES = The maximum output value after the display pipeline has been applied shall be displayed with the minimum available luminance. NO = The maximum output value after the display pipeline has been applied shall be displayed with the maximum available luminance. Notes: 1. The YES and NO values of this Attribute correspond to the Presentation LUT Shape (2050,0020) values of INVERSE and IDENTITY, as described in C.11.6.1.2. 2. Only applicable to display of grayscale images.
The attributes that indicate the presentation intent for each Display Set of a Hanging Protocol Instance are: Display Set Patient Orientation (0072,0700), VOI Type (0072,0702), Pseudo-color Type (0072,0704), Show Grayscale Inverted (0072,0706), Show Image True Size Flag (0072,0710), Show Graphic Annotation Flag (0072,0712), Show Patient Demographics Flag (0072,0714), and Show Acquisition Techniques Flag (0072,0716).
Indicates whether or not to display images with the physical size of the rendered image pixel the same on the screen as specified in the image attributes, unless overridden by a Presentation State instance. Enumerated values: YES = Display images at True Size. NO = The rendered size is not specified. Indicates whether or not to display items from the Graphic Annotation Sequence (0070,0001) in an applied Presentation State, and the attributes of the Overlay Plane module in the image objects or applied Presentation State. Enumerated Values: YES NO Indicates whether or not to display patient and study identification information. Enumerated Values: YES NO Indicates whether or not to display image acquisition technique information. Enumerated Values: YES NO Description of the intent of the Display Set Presentation Group (0072,0204). If present, shall have the same value in all sequence Items assigned the same value for Display Set Presentation Group (0072,0204). If one or more Image Sets identified by Image Set Number (0072,0032) in the Display Sets Sequence (0072,0200) Items is not available, indicate whether or not to maintain the expected layout in the absence of complete Image Sets. Enumerated Values: MAINTAIN_LAYOUT: If one or more Image Sets is not available, maintain the layout with empty Image Boxes. ADAPT_LAYOUT: If one or more Image Sets is not available, rearrange the layout at the discretion of the application. If this attribute is zero length, then the expected behavior is not defined. Each sequence item of this attribute identifies a group of Display Sets to which synchronized scrolling is to be applied. Zero or more sequence items may be present. The dimensions along which the synchronization occurs shall be those specified in the Sorting Operations Sequence (0072,0600). Multi-valued list of two or more Display Set Number (0072,0202) values. Indicates that the images within the specified Display Sets are scrolled in parallel, to maintain the established synchronization. Describes a geometric relationship between Display Sets for the purpose of static or interactive localization or navigation. One or more sequence items may be present. Display Set Number (0072,0202) of the Display Set where the geometric relationship to the Reference Display Sets (0072,0218) is graphically depicted. Required if there is a one-way interaction such that the location of the Reference Display Sets is indicated on or controlled by the Navigation Display Set. Note: For example, the graphical representation may indicate either the number of slices displayed or contained in the Reference Display Set(s). One or more Display Set Number (0072,0202) values. If Navigation Display Set is present, shall list those Display Sets that are controlled by or indicated on the Navigation Display Set. If Navigation Display Set is absent, shall indicate that all of the Reference Display Sets cross-reference each other.
The modality appropriate for the encapsulated document. This Type definition shall override the definition in the SC Equipment Module. See section C.7.3.1.1.1 for Defined Terms. Note: SR may be an appropriate value for an Encapsulated CDA document with a structured XML Body. Unique identifier of the Series. A number that identifies the Series. Uniquely identifies the Performed Procedure Step SOP Instance for which the Series is created. Only a single Item shall be permitted in this sequence. Note: The Performed Procedure Step referred to by this Attribute is the Step during which this Document is generated. User provided description of the Series Sequence that contains attributes from the Imaging Service Request. The sequence may have one or more Items. A number that identifies this SOP Instance. The value shall be unique within a series. The date the document content creation was started. The time the document content creation was started. The date and time that the original generation of the data in the document started. Indicates whether or not the encapsulated document contains sufficient burned in annotation to identify the patient and date the data was acquired. Enumerated Values: YES NO Identification of patient and date as text in an encapsulated document (e.g., in an XML attribute or element) is equivalent to "burned in annotation". A de-identified document may use the value NO. A sequence that identifies the set of Instances that were used to derive the encapsulated document. One or more Items may be included in this Sequence. Required if derived from one or more DICOM Instances. May be present otherwise. The title of the document. Note: In the case of a PDF encapsulated document, this may be the value of the "Title" entry in the "Document Information Directory" as encoded in the PDF data. A coded representation of the document title. Zero or one item may be present. Indicates whether the Encapsulated Document is Verified. Enumerated Values: UNVERIFIED = Not attested by a legally accountable person. VERIFIED = Attested to (signed) by a Verifying Observer or Legal Authenticator named in the document, who is accountable for its content. Instance Identifier of the encapsulated HL7 Structured Document, encoded as a UID (OID or UUID), concatenated with a caret ("^") and Extension value (if Extension is present in Instance Identifier). Required if encapsulated document is a CDA document. The type of the encapsulated document stream described using the MIME Media Type (see RFC 2046). MIME Types of subcomponents of the encapsulated document. Required if the encapsulated document incorporates subcomponents with MIME types different than the primary MIME Type of the encapsulated document. Note: An Encapsulated CDA that includes an embedded JPEG image and an embedded PDF would list "image/jpeg\application/pdf". Encapsulated Document stream, containing a document encoded according to the MIME Type. Modality type. Enumerated Value: RWV The date the content creation started. The time the content creation started. A sequence of one or more real world value mapping items. Each item defines a single mapping and a list of images to which the mapping applies. A sequence listing the images to which the mapping applies. One or more items shall be present. Identifier of the contrast agent, drug, or device being characterized, typically from a package bar code, RFID, or other materials management ID. This ID might not be globally unique and might conflict with other IDs used within the scope of the institution. Manufacturer of product. Coded type of product. One Item shall be included in the Sequence. Trade or generic name of product. Note: May be multi-valued. Further description in free form text describing the drug or device. Note: This attribute is limited by the LT Value Representation to 10240 characters. Larger text descriptions, or graphical descriptions, may be referenced in the Pertinent Documents Sequence (0038,0100). Identifier of the manufacturing batch of which this product is part. The date and time after which the manufacturer no longer ensures the safety, quality, and/or proper functioning of the material. Parameters of the product. Zero or more Items may be included in the Sequence. Reference to a Product Label document for the product. Zero or more Items may be included in this sequence. Unique identifier for the class of an HL7 Structured Product Label document. Unique identifier for the HL7 Structured Product Label Document as used in DICOM instance references (see C.12.1.1.6) Instance Identifier of the referenced HL7 Structured Document, encoded as a UID (OID or UUID), concatenated with a caret ("^") and Extension value (if Extension is present in Instance Identifier). Retrieval access path to Product Label Document. Includes fully specified scheme, authority, path, and query in accordance with RFC 2396 Status of request for substance administration. Enumerated Values: APPROVED - Use of the substance for the patient is approved, with related notes (e.g., appropriate dose for age/weight) in Approval Status Further Description (0044,0003) WARNING - The substance may be used for the patient subject to warnings described in Approval Status Further Description (0044,0003) CONTRA_INDICATED - The substance should not be used for the patient for the reasons described in Approval Status Further Description (0044,0003) Description of warning or contra-indication, or notes on approval. Timestamp for the Substance Administration Approval response Route of administration for drug or contrast. One Item may be present in this Sequence. Patient's full name Primary identification number or code for the patient. Identifier of the Assigning Authority (system, organization, agency, or department) that issued the Patient ID. Identification number of the visit as assigned by the healthcare provider Name of healthcare provider that issued the Admission ID Identifier of the contrast agent, drug, or device administered, typically from a package bar code, RFID, or other materials management ID. This ID might not be globally unique and might conflict with other IDs used within the scope of the institution. Trade or generic name of product. Note: May be multi-valued. Text description of the contrast agent, drug, or device administered. Date and Time of Substance Administration Comments provided by the operator responsible for the substance administration. Identifier for a device that controls substance administration, e.g., injector, infusion pump, etc. Route of administration for drug or contrast. One Item may be present in this Sequence. Parameters of the substance as administered to the patient, e.g., volume, quantity. Zero or more Items may be included in the Sequence. Person administering the substance to the patient, or legally responsible for the administration, and authorized to add an entry to the Medication Administration Record. One or more Items may be present in this Sequence. Coded identifier of the person administering the contrast agent, drug, or device. One Item may be present in this Sequence. User or implementation specific Identifier (up to 16 characters). For definition, see PS 3.10. The File-set ID is intended to be a short human readable label to easily (but not necessarily uniquely) identify a specific File-set to facilitate operator manipulation of the physical media on which the File-set is stored. Assignment of Value and semantics are environment specific. ID of a File (in the same File-set) used for user comments related to the File-set (e.g. a readme file). The Specific Character set used may be specified in the Specific Character Set of the File-set Descriptor File (0004,1142). Note: This File is not DICOM formatted (no Preamble, nor DICM Prefix and Meta Information). Character set used in the File-set Descriptor File with a File ID as specified in File-set Descriptor File ID (0004,1141). Required to specify the expanded or replacement character set. If absent, only the Basic Graphic set is used. See C.12.1.1.2 for Defined Terms.
Specific Character Set (0008,0005) identifies the Character Set that expands or replaces the Basic Graphic Set (ISO 646) for values of Data Elements that have Value Representation of SH, LO, ST, PN, LT or UT. See PS 3.5. If the Attribute Specific Character Set (0008,0005) is not present or has only a single value, Code Extension techniques are not used. Defined terms for the Attribute Specific Character Set (0008,0005), when single valued, are derived from the International Registration Number as per ISO 2375 (e.g., ISO_IR 100 for Latin alphabet No. 1). See Table C.12-2. Table C.12-2 DEFINED TERMS FOR SINGLE-BYTE CHARACTER SETS WITHOUT CODE EXTENSIONS Note: To use the single-byte code table of JIS X0201, the value of attribute Specific Character Set (0008,0005), value 1 should be ISO_IR 13. This means that ISO-IR 13 is designated as the G1 code element which is invoked in the GR area. It should be understood that, in addition, ISO-IR 14 is designated as the G0 code element and this is invoked in the GL area. If the attribute Specific Character Set (0008,0005) has more than one value, Code Extension techniques are used and Escape Sequences may be encountered in all character sets. Requirements for the use of Code Extension techniques are specified in PS 3.5. In order to indicate the presence of Code Extension, the Defined Terms for the repertoires have the prefix “ISO 2022”, e.g., ISO 2022 IR 100 for the Latin Alphabet No. 1. See Table 12-3 and Table 12-4. Table 12-3 describes single-byte character sets for value 1 to value n of the attribute Specific Character Set (0008,0005), and Table 12-4 describes multi-byte character sets for value 2 to value n of the attribute Specific Character Set (0008,0005). Note: A prefix other than “ISO 2022” may be needed in the future if other Code Extension techniques are adopted. Table C.12-3 DEFINED TERMS FOR SINGLE-BYTE CHARACTER SETS WITH CODE EXTENSIONS Note: If the attribute Specific Character Set (0008,0005) has more than one value and value 1 is empty, it is assumed that value 1 is ISO 2022 IR 6. Table C.12-4 DEFINED TERMS FOR MULTI-BYTE CHARACTER SETS WITH CODE EXTENSIONS There are multi-byte character sets that prohibit the use of Code Extension Techniques. The Unicode character set used in ISO 10646, when encoded in UTF-8, and the GB18030 character set, encoded per the rules of GB18030, both prohibit the use of Code Extension Techniques. These character sets may only be specified as value 1 in the Specific Character Set (0008,0005) attribute and there shall only be one value. The minimal length UTF-8 encoding shall always be used for ISO 10646. Notes: 1. The ISO standards for 10646 now prohibit the use of anything but the minimum length encoding for UTF-8. UTF-8 permits multiple different encodings, but when used to encode Unicode characters in accordance with ISO 10646-1 and 10646-2 (with extensions) only the minimal encodings are legal. 2. The representation for the characters in the DICOM Default Character Repertoire is the same single byte value for the Default Character Repertoire, ISO 10646 in UTF-8, and GB18030. It is also the 7-bit US-ASCII encoding. Table C.12-5 DEFINED TERMS FOR MULTI-BYTE CHARACTER SETS WITHOUT CODE EXTENSIONS
Offset of the first byte (of the Item Data Element) of the first Directory Record of the Root Directory Entity. This Offset is a number of bytes starting with the first byte of the File Meta Information. When the Root Directory Entity contains no Directory Record, this offset shall be set to 00000000H. Note: This offset includes the File Preamble and the DICM Prefix. Offset of the first byte (of the Item Data Element) of the last Directory Record of the Root Directory Entity. This Offset is a number of bytes starting with the first byte of the File Meta Information. When the Root Directory Entity contains no Directory Record, this offset shall be set to 00000000H. Note: This offset includes the File Preamble and the DICM Prefix. When set, this Flag indicates that an inconsistency within the Directory or between the Directory and the Files of the File-set may exist. Potential recovery actions are implementation specific and are beyond the scope of this Standard. Enumerated Values: 0000H: no known inconsistencies FFFFH: the FSR or FSU shall assume that inconsistencies are present. This flag shall be set by implementations before a File-set update which, if interrupted, may result in an inconsistent File-set. Note: There may be error conditions where an inconsistency is present but this flag is not set. There may also be conditions where no inconsistencies are present but the flag is set. Sequence of zero or more Items where each Item contains a Directory Record by including the Directory Elements from (0004,1400) to (0004,1511) and Record selection Keys as defined below (marked with a >). A zero length Value indicates that no Directory Records are contained in the Root Directory Entity. Offset of the first byte (of the Item Data Element) of the next Directory Record of the same Directory Entity. This Offset is an unsigned integer representing a number of bytes starting with the first byte of the File Meta-information. A zero offset shall be used to mean that there is no other Directory Record in this Directory Entity. This Offset may be used to keep an inactive Record (0004,1410) chained with the next Directory Record of the same Directory Entity. Note: This offset includes the File Preamble and the DICM Prefix. This flag facilitates the deletion of referenced files. Enumerated Values: FFFFH = record is in use. 0000H = record is inactive. All attributes of an inactive Directory Record except (0004,1400) and (0004,1410) shall be ignored. Other Values are reserved and shall not be set by File-set Creators, but if present shall be interpreted as FFFFH by File-set Readers or Updaters. If a Directory Record is changed from in use to inactive, the FSU shall ensure that all Directory Records of referenced lower-level Directory Entities are changed to inactive. Offset of the first byte (of the Item Data Element) of the first Directory Record of the Referenced Lower Level Directory Entity. This Offset is a number of bytes starting with the first byte of the File Meta Information. When no lower-level Directory Entity (containing at least one Directory Record) is referenced, this Attribute shall have a Value of 00000000H. Note: This offset includes the File Preamble and the DICM Prefix. Defines a specialized type of Directory Record by reference to its position in the Media Storage Directory Information Model (see Section F.4). Enumerated Values (see Section F.5): PATIENT STUDY SERIES IMAGE RT DOSE RT STRUCTURE SET RT PLAN RT TREAT RECORD PRESENTATION WAVEFORM SR DOCUMENT KEY OBJECT DOC SPECTROSCOPY RAW DATA REGISTRATION FIDUCIAL HANGING PROTOCOL ENCAP DOC HL7 STRUC DOC VALUE MAP STEREOMETRIC PRIVATE = Privately defined record hierarchy position. Type shall be defined by Private Record UID (0004,1432). Notes: 1. Enumerated Values PRINT QUEUE, FILM SESSION, FILM BOX, and IMAGE BOX were previously defined in DICOM for this Attribute. They are now retired. See PS3.3-1998. 2. Enumerated Values OVERLAY, MODALITY LUT, VOI LUT, CURVE, TOPIC, VISIT, RESULTS, INTERPRETATION, STUDY COMPONENT and STORED PRINT were previously defined in DICOM for this Attribute. They are now retired. See PS3.3-2004. 3. Enumerated Value MRDR was previously defined in DICOM for this Attribute, to allow indirect reference to a File by multiple Directory Records. It is now retired. FSUs and FSRs are unlikely to be capable of supporting this mechanism. See PS3.3-2004. Required if the Directory Record Type (0004,1430) is of Value PRIVATE. This UID is used to define a non-standard type of Directory Record by reference to its position in a private extension to the Basic Directory IOD Information Model (see Section F.5). This UID shall be registered according to the procedures defined in PS 3.5. Its meaning may or may not be specified in a Conformance Statement. A Multiple Value (See PS 3.5) which represents the ordered components of the File ID containing a "referenced object" or Referenced SOP Instance. A maximum of 8 components, each from 1 to 8 characters shall be used (see Section 8.2). Note: The Referenced File ID provides the means to "locate" the File through the DICOM File Service provided by the Media Format Layer. All referenced Files shall be with the File-set to which the Directory belongs. Any File within the File-set (to which the Directory belongs) shall be referenced by at most one Directory Record. When the Directory Record does not reference any SOP Instance this attribute shall not be present. Unique ID for the SOP Class of the Instance stored in the referenced File. Required if the Directory Record references a SOP Instance. Unique Identifier for the SOP Instance stored in the referenced file. Required if the Directory Record references a SOP Instance. Unique Identifier for the Transfer Syntax used to encode the Instance stored in the referenced file. Required if the Directory Record references a SOP Instance. Unique ID for the Related General SOP Class(es) related to the SOP Class of the Instance stored in the referenced file. Required if the Directory Record references a SOP Instance that encodes the Related General SOP Class UID (0008,001A). Note: This may be useful to an FSR that does not support the SOP Class of the referenced Instance, but which does support one of the Related General SOP Classes. Required if an extended or replacement character set is used in one of the keys Required if an extended or replacement character set is used in one of the keys Required only if (0004,1511) is absent. (See Note) Required if an extended or replacement character set is used in one of the keys This Icon Image is representative of the Series. It may or may not correspond to one of the images of the Series. Only a single Item shall be permitted in this Sequence. Required if an extended or replacement character set is used in one of the keys. This Icon Image is representative of the Image. Only a single Item shall be permitted in this Sequence. Required if an extended or replacement character set is used in one of the keys. This Icon Image is representative of the RT Dose. Only a single Item shall be permitted in this Sequence. Required if an extended or replacement character set is used in one of the keys. Required if an extended or replacement character set is used in one of the keys Required if an extended or replacement character set is used in one of the keys Required if an extended or replacement character set is used in one of the keys. Date on which this presentation was created. Note: This date may be different from the date that the DICOM SOP Instance was created, since the presentation state information contained may have been recorded earlier. Time at which this presentation was created. Note: This time may be different from the time that the DICOM SOP Instance was created, since the presentation state information contained may have been recorded earlier. Sequence of Items where each Item includes the Attributes of one Series to which the Presentation applies. Required if the IOD of the Presentation SOP Instance referenced by this directory record includes the Presentation State Relationship Module. One or more Items may be included in this Sequence. Unique identifier of a Series that is part of this Study. Sequence of Items where each Item provides reference to an Image SOP Instance . Sequence of exactly two Items where each Item includes the Attributes of a Study to which the Presentation applies. Required if the SOP Instance referenced by this directory record includes the Blending Sequence (0070,0402) attribute. Unique identifier for a Study that contains the images to which the Presentation applies. Sequence of Items where each Item includes the Attributes of one Series to which the Presentation applies. Only a single item shall be permitted in this Sequence. Unique identifier of the Series Sequence of Items where each Item provides reference to an Image SOP Instance to which the Presentation applies Required if an extended or replacement character set is used in one of the keys. Required if an extended or replacement character set is used in one of the keys. Most recent Date and Time of verification among those defined in the Verifying Observer Sequence (0040,A073). Required if Verification Flag (0040,A493) is VERIFIED. Code describing the concept represented by the root Content Item (Document Title). This sequence shall contain exactly one Item. Contains the Target Content Items that modify the Concept Name Code Sequence of the root Content Item (Document Title). Required if the root Content Item is the Source Content Item of HAS CONCEPT MOD relationships. One or more Items shall be included in this Sequence. All, and only, Content Items with the HAS CONCEPT MOD relationship from the root Content Item shall be included in this Sequence. Enumerated Value: HAS CONCEPT MOD Required if an extended or replacement character set is used in one of the keys. Code describing the concept represented by the root Content Item (Document Title). This sequence shall contain exactly one Item. Contains the Target Content Items that modify the Concept Name Code Sequence of the root Content Item (Document Title). Required if the root Content Item is the Source Content Item of HAS CONCEPT MOD relationships. One or more Items shall be included in this Sequence. All, and only, Content Items with the HAS CONCEPT MOD relationship from the root Content Item shall be included in this Sequence. Enumerated Value: HAS CONCEPT MOD Required if an extended or replacement character set is used in one of the keys. Required if present in the spectroscopy instance. This Icon Image is representative of the Spectroscopy instance. Only a single Item shall be permitted in this Sequence. Required if an extended or replacement character set is used in one of the keys. This Icon Image is representative of the Raw Data instance. Only a single Item shall be permitted in this Sequence. Required if an extended or replacement character set is used in one of the keys. The date the content creation started. The time the content creation started. Required if an extended or replacement character set is used in one of the keys. The date the content creation started. The time the content creation started. Required if an extended or replacement character set is used in one of the keys Sequence that defines the type of imaging studies to which this Hanging Protocol applies. One or more sequence items shall be present. Required if Anatomic Region Sequence (0008,2218) is not present. May be present otherwise. Required if Modality (0008,0060) is not present. May be present otherwise. Required if Anatomic Region Sequence (0008,2218) is present. One or more Items may be included in this Sequence. One or more Items may be included in this sequence. Sequence that provides a coded identifier for the person, group, or site for which this Hanging Protocol was defined. Zero or one Items may be included in this Sequence. Required if an extended or replacement character set is used in one of the keys. The date the content creation started. The time the content creation started. A number that identifies this instance The title of the document. Instance Identifier from the referenced HL7 Structured Document, encoded as a UID (OID or UUID), concatenated with a caret ("^") and Extension value (if Extension is present in Instance Identifier). Required if encapsulated document is an HL7 Structured Document. A coded representation of the document title. Zero or one item may be present. The type of the encapsulated document stream described using the MIME Media Type (see RFC 2046). Required if an extended or replacement character set is used in one of the keys. Instance Identifier from the referenced HL7 Structured Document, encoded as a UID (OID or UUID), concatenated with a caret ("^") and Extension value (if Extension is present in Instance Identifier). Effective Time from the referenced HL7 Structured Document Document Type Code from the referenced HL7 Structured Document. Required if the HL7 Structured Document contains a Document Type Code. Only a single Item shall be permitted in this Sequence. Document Title from the referenced HL7 Structured Document. Required if the HL7 Structured Document contains a Document Title. Required if an extended or replacement character set is used in one of the keys. The date the content creation started. The time the content creation started. Required if an extended or replacement character set is used in one of the keys. GDCM-3.0.10/Source/InformationObjectDefinition/Part3.xsl000066400000000000000000001202521412732066400227220ustar00rootroot00000000000000 ' " ’“”– ­ SHOULD NOT HAPPEN Error: could not MATCH UNHANDLED NO TABLE REF ERROR: ^([CF]\.[0-9a-z\.]+)\s*(.*)$ See Section ([C]\.[0-9\.]+) See ([C]\.[0-9a-f\.]+) — NOT IOD/Macro or Module ref= name= att name= Info: section found Info: all paragraphs extracted Error: section found multiple times! Error: section not found! (.*Enumerated [Vv]alue[s]?\s*(are)*\s*:)(.*) (.*Defined [Tt]erm[s]?\s*(are)*\s*:)(.*) type="text/xsl" href="ma2html.xsl" to produce output use: $ xsltproc ma2html.xsl ModuleAttributes.xml 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. GDCM-3.0.10/Source/InformationObjectDefinition/Part3New.xsl000066400000000000000000000201671412732066400234000ustar00rootroot00000000000000 to produce output use: $ xsltproc ma2html.xsl ModuleAttributes.xml 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. ' ' Table . Section GDCM-3.0.10/Source/InformationObjectDefinition/Part4.xml000066400000000000000000000514301412732066400227160ustar00rootroot00000000000000 GDCM-3.0.10/Source/InformationObjectDefinition/Part4.xsl000066400000000000000000000143741412732066400227320ustar00rootroot00000000000000 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. DX IOD Digital Mammography IOD Digital Intra-oral X-Ray IOD Enhanced CT Image Enhanced MR Image MR Spectroscopy Enhanced MR Color Image Enhanced US Volume GDCM-3.0.10/Source/InformationObjectDefinition/Part4ToC++.xsl000066400000000000000000000035411412732066400234600ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc Part4ToC++.xsl Part4.xml > gdcmSOPClassUIDToIOD.cxx /*========================================================================= 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 "gdcmSOPClassUIDToIOD.h" namespace gdcm { static const char * const SOPClassToIOD[][2] = { {" " , " "}, { 0, 0 } }; } // end namespace gdcm GDCM-3.0.10/Source/InformationObjectDefinition/README.txt000066400000000000000000000007471412732066400227050ustar00rootroot00000000000000Part 3.3 Footnote: http://www.devarticles.com/c/a/XML/An-Introduction-to-XML-Schemas/ http://www.xml.com/pub/a/2000/11/29/schemas/part1.html http://xmlfr.org/w3c/TR/xmlschema-0/ http://xmlfr.org/documentations/tutoriels/001218-0001 http://xml.ascc.net/schematron/ http://xml.ascc.net/resource/schematron/schematron.html http://209.85.129.104/search?q=cache:sTA73AQ9KKMJ:lists.xml.org/archives/xml-dev/200005/msg00741.html+xml+schema+condition&hl=fr&gl=fr&ct=clnk&cd=2&client=firefox-a GDCM-3.0.10/Source/InformationObjectDefinition/Template.xml.in000066400000000000000000000041701412732066400241030ustar00rootroot00000000000000
GDCM-3.0.10/Source/InformationObjectDefinition/ValueRepresentation.xsd000066400000000000000000000475211412732066400257270ustar00rootroot00000000000000 --> ` GDCM-3.0.10/Source/InformationObjectDefinition/extract.xsl000066400000000000000000000021241412732066400234000ustar00rootroot00000000000000 GDCM-3.0.10/Source/InformationObjectDefinition/gdcmDefinedTerms.cxx000066400000000000000000000011451412732066400251300ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDefinedTerms.h" namespace gdcm {} GDCM-3.0.10/Source/InformationObjectDefinition/gdcmDefinedTerms.h000066400000000000000000000030761412732066400245620ustar00rootroot00000000000000/*========================================================================= 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 GDCMDEFINEDTERMS_H #define GDCMDEFINEDTERMS_H #include "gdcmTypes.h" namespace gdcm { /** * \brief Defined Terms are used when the specified explicit Values may be extended by implementors to include additional new Values. These new Values shall be specified in the Conformance Statement (see PS 3.2) and shall not have the same meaning as currently defined Values in this standard. A Data Element with Defined Terms that does not contain a Value equivalent to one of the Values currently specified in this standard shall not be considered to have an invalid value. Note: Interpretation Type ID (4008,0210) is an example of a Data Element having Defined Terms. It is defined to have a Value that may be one of the set of standard Values; REPORT or AMENDMENT (see PS 3.3). Because this Data Element has Defined Terms other Interpretation Type IDs may be defined by the implementor. * */ class GDCM_EXPORT DefinedTerms { public: DefinedTerms() = default; private: }; } // end namespace gdcm #endif //GDCMDEFINEDTERMS_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmDefs.cxx000066400000000000000000000275141412732066400234500ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDefs.h" #include "gdcmTableReader.h" #include "gdcmMediaStorage.h" //#include "gdcmGlobal.h" #include "gdcmTrace.h" #include "gdcmFile.h" #include namespace gdcm { Defs::Defs() = default; Defs::~Defs() = default; void Defs::LoadDefaults() { // TableReader tr(*this); // const Global &g = Global::GetInstance(); // const char *filename = g.Locate( "Part3.xml" ); // // if( filename ) // { // tr.SetFilename(filename); // tr.Read(); // } // else // { // gdcmErrorMacro( "Could not find Part3.xml file. Please report" ); // throw Exception( "Impossible" ); // } } void Defs::LoadFromFile(const char *filename) { assert( filename ); TableReader tr(*this); tr.SetFilename(filename); tr.Read(); } // http://dicom.nema.org/medical/dicom/current/output/chtml/part04/sect_B.5.html#table_B.5-1 const char *Defs::GetIODNameFromMediaStorage(MediaStorage const &ms) { const char *iodname; switch(ms) { case MediaStorage::MediaStorageDirectoryStorage: iodname = "Basic Directory IOD Modules"; break; case MediaStorage::MRImageStorage: iodname = "MR Image IOD Modules"; break; case MediaStorage::EnhancedMRImageStorage: iodname = "Enhanced MR Image IOD Modules"; break; case MediaStorage::CTImageStorage: iodname = "CT Image IOD Modules"; break; case MediaStorage::EnhancedCTImageStorage: iodname = "Enhanced CT Image IOD Modules"; break; case MediaStorage::ComputedRadiographyImageStorage: iodname = "CR Image IOD Modules"; break; case MediaStorage::XRayAngiographicImageStorage: //case MediaStorage::XRayAngiographicBiPlaneImageStorageRetired: // FIXME ??? iodname = "X Ray Angiographic Image IOD Modules"; break; case MediaStorage::UltrasoundImageStorageRetired: case MediaStorage::UltrasoundImageStorage: iodname = "US Image IOD Modules"; break; case MediaStorage::UltrasoundMultiFrameImageStorageRetired: case MediaStorage::UltrasoundMultiFrameImageStorage: iodname ="US Multi Frame Image IOD Modules"; break; case MediaStorage::SecondaryCaptureImageStorage: iodname = "SC Image IOD Modules"; break; case MediaStorage::XRayRadiofluoroscopingImageStorage: iodname = "XRF Image IOD Modules"; break; case MediaStorage::MRSpectroscopyStorage: iodname = "MR Spectroscopy IOD Modules"; break; case MediaStorage::NuclearMedicineImageStorageRetired: case MediaStorage::NuclearMedicineImageStorage: iodname = "NM Image IOD Modules"; break; case MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage: iodname = "Multi Frame Single Bit SC Image IOD Modules"; break; case MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage: iodname = "Multi Frame Grayscale Byte SC Image IOD Modules"; break; case MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage: iodname = "Multi Frame Grayscale Word SC Image IOD Modules"; break; case MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage: iodname = "Multi Frame True Color SC Image IOD Modules"; break; case MediaStorage::EncapsulatedPDFStorage: iodname = "Encapsulated PDF IOD Modules"; break; case MediaStorage::EncapsulatedCDAStorage: iodname = "Encapsulated CDA IOD Modules"; break; case MediaStorage::VLPhotographicImageStorage: iodname = "VL Photographic Image IOD Modules"; break; case MediaStorage::SegmentationStorage: iodname = "Segmentation IOD Modules"; break; case MediaStorage::RawDataStorage: iodname = "Raw Data IOD Modules"; break; case MediaStorage::MammographyCADSR: iodname = "Mammography CAD SR IOD Modules"; break; case MediaStorage::VideoEndoscopicImageStorage: iodname = "Video Endoscopic Image IOD Modules"; break; case MediaStorage::RTImageStorage: iodname = "RT Image IOD Modules"; break; case MediaStorage::RTDoseStorage: iodname = "RT Dose IOD Modules"; break; case MediaStorage::RTStructureSetStorage: iodname = "RT Structure Set IOD Modules"; break; case MediaStorage::RTPlanStorage: iodname = "RT Plan IOD Modules"; break; case MediaStorage::ModalityPerformedProcedureStepSOPClass: iodname = "Modality Performed Procedure Step IOD Modules"; break; case MediaStorage::HangingProtocolStorage: iodname = "Hanging Protocol IOD Modules"; break; case MediaStorage::KeyObjectSelectionDocument: iodname = "Key Object Selection Document IOD Modules"; break; case MediaStorage::ComprehensiveSR: iodname = "Comprehensive SR IOD Modules"; break; case MediaStorage::HemodynamicWaveformStorage: iodname = "Hemodynamic IOD Modules"; break; case MediaStorage::DigitalIntraoralXrayImageStorageForPresentation: case MediaStorage::DigitalIntraoralXRayImageStorageForProcessing: iodname = "Digital Intra Oral X Ray Image IOD Modules"; break; case MediaStorage::DigitalXRayImageStorageForPresentation: case MediaStorage::DigitalXRayImageStorageForProcessing: iodname = "Digital X Ray Image IOD Modules"; break; case MediaStorage::DigitalMammographyImageStorageForPresentation: case MediaStorage::DigitalMammographyImageStorageForProcessing: iodname = "Digital Mammography X Ray Image IOD Modules"; break; case MediaStorage::GrayscaleSoftcopyPresentationStateStorageSOPClass: iodname = "Grayscale Softcopy Presentation State IOD Modules"; break; case MediaStorage::LeadECGWaveformStorage: iodname = "12 Lead ECG IOD Modules"; break; case MediaStorage::GeneralECGWaveformStorage: iodname = "General ECG IOD Modules"; break; case MediaStorage::AmbulatoryECGWaveformStorage: iodname = "Ambulatory ECG IOD Modules"; break; case MediaStorage::BasicVoiceAudioWaveformStorage: iodname = "Basic Voice Audio IOD Modules"; break; case MediaStorage::SpacialFiducialsStorage: iodname = "Spatial Fiducials IOD Modules"; break; case MediaStorage::BasicTextSR: iodname = "Basic Text SR IOD Modules"; break; case MediaStorage::CardiacElectrophysiologyWaveformStorage: iodname = "Basic Cardiac EP IOD Modules"; break; case MediaStorage::PETImageStorage: iodname = "PET Image IOD Modules"; break; case MediaStorage::EnhancedSR: iodname = "Enhanced SR IOD Modules"; break; case MediaStorage::SpacialRegistrationStorage: iodname = "Spatial Registration IOD Modules"; break; case MediaStorage::RTIonPlanStorage: iodname = "RT Ion Plan IOD Modules"; break; case MediaStorage::XRay3DAngiographicImageStorage: iodname = "X Ray 3D Angiographic Image IOD Modules"; break; case MediaStorage::EnhancedXAImageStorage: iodname = "Enhanced X Ray Angiographic Image IOD Modules"; break; case MediaStorage::RTIonBeamsTreatmentRecordStorage: iodname = "RT Ion Beams Treatment Record IOD Modules"; break; case MediaStorage::RTTreatmentSummaryRecordStorage: iodname = "RT Treatment Summary Record IOD Modules"; break; case MediaStorage::VLEndoscopicImageStorage: iodname = "VL Endoscopic Image IOD Modules"; break; case MediaStorage::XRayRadiationDoseSR: iodname = "X Ray Radiation Dose SR IOD Modules"; break; case MediaStorage::FujiPrivateCRImageStorage: iodname = "Fuji Private CR Image IOD Modules"; break; case MediaStorage::FujiPrivateMammoCRImageStorage: iodname = "Fuji Private Mammo CR Image IOD Modules"; break; case MediaStorage::CSANonImageStorage: iodname = "Siemens Non-image IOD Modules"; break; case MediaStorage::VLMicroscopicImageStorage: iodname = "VL Microscopic Image IOD Modules"; break; case MediaStorage::XRay3DCraniofacialImageStorage: iodname = "X Ray 3D Craniofacial Image IOD Modules"; break; default: iodname = nullptr; } return iodname; } const IOD& Defs::GetIODFromFile(const File& file) const { MediaStorage ms; ms.SetFromFile(file); // SetFromDataSet does not handle DICOMDIR const IODs &iods = GetIODs(); const char *iodname = GetIODNameFromMediaStorage( ms ); if( !iodname ) { gdcmErrorMacro( "Not implemented: " << ms ); throw "Not Implemented"; } const IOD &iod = iods.GetIOD( iodname ); return iod; } Type Defs::GetTypeFromTag(const File& file, const Tag& tag) const { Type ret; MediaStorage ms; ms.SetFromFile(file); // SetFromDataSet does not handle DICOMDIR const IODs &iods = GetIODs(); const Modules &modules = GetModules(); const char *iodname = GetIODNameFromMediaStorage( ms ); if( !iodname ) { gdcmErrorMacro( "Not implemented: " << ms ); return ret; } const IOD &iod = iods.GetIOD( iodname ); const Macros ¯os = GetMacros(); IOD::SizeType niods = iod.GetNumberOfIODs(); // Iterate over each iod entry in order: for(unsigned int idx = 0; idx < niods; ++idx) { const IODEntry &iodentry = iod.GetIODEntry(idx); const char *ref = iodentry.GetRef(); //Usage::UsageType ut = iodentry.GetUsageType(); const Module &module = modules.GetModule( ref ); if( module.FindModuleEntryInMacros(macros, tag ) ) { const ModuleEntry &module_entry = module.GetModuleEntryInMacros(macros,tag); ret = module_entry.GetType(); } } return ret; } bool Defs::Verify(const File& file) const { MediaStorage ms; ms.SetFromFile(file); const IODs &iods = GetIODs(); const Modules &modules = GetModules(); const char *iodname = GetIODNameFromMediaStorage( ms ); if( !iodname ) { gdcmErrorMacro( "Not implemented" ); return false; } const IOD &iod = iods.GetIOD( iodname ); //std::cout << iod << std::endl; //std::cout << iod.GetIODEntry(14) << std::endl; IOD::SizeType niods = iod.GetNumberOfIODs(); bool v = true; // Iterate over each iod entry in order: for(unsigned int idx = 0; idx < niods; ++idx) { const IODEntry &iodentry = iod.GetIODEntry(idx); const char *ref = iodentry.GetRef(); Usage::UsageType ut = iodentry.GetUsageType(); const Module &module = modules.GetModule( ref ); //std::cout << module << std::endl; v = v && module.Verify( file.GetDataSet(), ut ); } return v; } bool Defs::Verify(const DataSet& ds) const { MediaStorage ms; ms.SetFromDataSet(ds); const IODs &iods = GetIODs(); const Modules &modules = GetModules(); const char *iodname = GetIODNameFromMediaStorage( ms ); if( !iodname ) { gdcmErrorMacro( "Not implemented" ); return false; } const IOD &iod = iods.GetIOD( iodname ); //std::cout << iod << std::endl; //std::cout << iod.GetIODEntry(14) << std::endl; IOD::SizeType niods = iod.GetNumberOfIODs(); bool v = true; // Iterate over each iod entry in order: for(unsigned int idx = 0; idx < niods; ++idx) { const IODEntry &iodentry = iod.GetIODEntry(idx); const char *ref = iodentry.GetRef(); Usage::UsageType ut = iodentry.GetUsageType(); const Module &module = modules.GetModule( ref ); //std::cout << module << std::endl; v = v && module.Verify( ds, ut ); } return v; } } // end namespace gdcm GDCM-3.0.10/Source/InformationObjectDefinition/gdcmDefs.h000066400000000000000000000040051412732066400230630ustar00rootroot00000000000000/*========================================================================= 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 GDCMDEFS_H #define GDCMDEFS_H #include "gdcmModules.h" #include "gdcmMacros.h" #include "gdcmIODs.h" #include namespace gdcm { class DataSet; class File; class MediaStorage; /** * \brief FIXME I do not like the name 'Defs' * \note bla */ class GDCM_EXPORT Defs { public: Defs(); ~Defs(); Defs &operator=(const Defs &val) = delete; Defs(const Defs &val) = delete; const Modules &GetModules() const { return Part3Modules; } 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 const Macros &GetMacros() const { return Part3Macros; } Macros &GetMacros() { return Part3Macros; } const IODs & GetIODs() const { return Part3IODs; } IODs & GetIODs() { return Part3IODs; } bool IsEmpty() const { return GetModules().IsEmpty(); } bool Verify(const File& file) const; // \deprecated DO NOT USE bool Verify(const DataSet& ds) const; Type GetTypeFromTag(const File& file, const Tag& tag) const; static const char *GetIODNameFromMediaStorage(MediaStorage const &ms); const IOD& GetIODFromFile(const File& file) const; protected: friend class Global; void LoadDefaults(); void LoadFromFile(const char *filename); private: // Part 3 stuff: Macros Part3Macros; Modules Part3Modules; IODs Part3IODs; }; } // end namespace gdcm #endif //GDCMDEFS_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmEnumeratedValues.cxx000066400000000000000000000011511412732066400260250ustar00rootroot00000000000000/*========================================================================= 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 "gdcmEnumeratedValues.h" namespace gdcm {} GDCM-3.0.10/Source/InformationObjectDefinition/gdcmEnumeratedValues.h000066400000000000000000000030411412732066400254520ustar00rootroot00000000000000/*========================================================================= 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 GDCMENUMERATEDVALUES_H #define GDCMENUMERATEDVALUES_H #include "gdcmTypes.h" namespace gdcm { /** * \brief * Element. A Data Element with Enumerated Values that does not have a Value equivalent to one of the * Values specified in this standard has an invalid value within the scope of a specific Information * Object/SOP Class definition. * Note: * 1. Patient Sex (0010, 0040) is an example of a Data Element having Enumerated Values. It is defined to * have a Value that is either "M", "F", or "O" (see PS 3.3). No other Value shall be given to this Data * Element. * 2. Future modifications of this standard may add to the set of allowed values for Data Elements with * Enumerated Values. Such additions by themselves may or may not require a change in SOP Class * UIDs, depending on the semantics of the Data Element. */ class GDCM_EXPORT EnumeratedValues { public: EnumeratedValues() = default; private: }; } // end namespace gdcm #endif //GDCMENUMERATEDVALUES_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmIOD.cxx000066400000000000000000000027621412732066400232000ustar00rootroot00000000000000/*========================================================================= 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 "gdcmIOD.h" #include "gdcmDataSet.h" #include "gdcmModule.h" #include "gdcmModules.h" #include "gdcmDefs.h" namespace gdcm { Type IOD::GetTypeFromTag(const Defs &defs, const Tag& tag) const { Type ret; const IOD &iod = *this; static const Modules &modules = defs.GetModules(); static const Macros ¯os = defs.GetMacros(); const size_t niods = iod.GetNumberOfIODs(); // Iterate over each iod entry in order: bool found = false; for(unsigned int idx = 0; !found && idx < niods; ++idx) { const IODEntry &iodentry = iod.GetIODEntry(idx); const char *ref = iodentry.GetRef(); //Usage::UsageType ut = iodentry.GetUsageType(); const Module &module = modules.GetModule( ref ); if( module.FindModuleEntryInMacros(macros, tag ) ) { const ModuleEntry &module_entry = module.GetModuleEntryInMacros(macros,tag); ret = module_entry.GetType(); found = true; } } return ret; } } GDCM-3.0.10/Source/InformationObjectDefinition/gdcmIOD.h000066400000000000000000000035531412732066400226240ustar00rootroot00000000000000/*========================================================================= 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 GDCMIOD_H #define GDCMIOD_H #include "gdcmTypes.h" #include "gdcmTag.h" #include "gdcmIODEntry.h" #include namespace gdcm { class DataSet; class Defs; /** * \brief Class for representing a IOD * \note bla * * \sa Dict */ class GDCM_EXPORT IOD { public: typedef std::vector MapIODEntry; typedef MapIODEntry::size_type SizeType; IOD() = default; friend std::ostream& operator<<(std::ostream& _os, const IOD &_val); void Clear() { IODInternal.clear(); } void AddIODEntry(const IODEntry & iode) { IODInternal.push_back(iode); } SizeType GetNumberOfIODs() const { return IODInternal.size(); } const IODEntry& GetIODEntry(SizeType idx) const { return IODInternal[idx]; } Type GetTypeFromTag(const Defs &defs, const Tag& tag) const; private: //IOD &operator=(const IOD &_val); // purposely not implemented //IOD(const IOD &_val); // purposely not implemented MapIODEntry IODInternal; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& _os, const IOD &_val) { IOD::MapIODEntry::const_iterator it = _val.IODInternal.begin(); for(;it != _val.IODInternal.end(); ++it) { _os << *it << '\n'; } return _os; } } // end namespace gdcm #endif //GDCMIOD_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmIODEntry.cxx000066400000000000000000000023011412732066400242070ustar00rootroot00000000000000/*========================================================================= 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 "gdcmIODEntry.h" #include // abort namespace gdcm { Usage::UsageType IODEntry::GetUsageType() const { assert( !usage.empty() ); if( usage == "M" ) { return Usage::Mandatory; } else if( usage == "U" ) { return Usage::UserOption; } else if( usage.find( "U - " ) < usage.size() ) { return Usage::UserOption; } else if( usage.find( "C- " ) < usage.size() ) { return Usage::Conditional; } else if( usage.find( "C - " ) < usage.size() ) { return Usage::Conditional; } //else assert(0); // Keep me so that I can debug Part3.xml return Usage::Invalid; } } GDCM-3.0.10/Source/InformationObjectDefinition/gdcmIODEntry.h000066400000000000000000000057401412732066400236460ustar00rootroot00000000000000/*========================================================================= 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 GDCMIODENTRY_H #define GDCMIODENTRY_H #include "gdcmUsage.h" #include "gdcmType.h" #include namespace gdcm { /** * \brief Class for representing a IODEntry * \note A.1.3 IOD Module Table and Functional Group Macro Table This Section of each IOD defines in a tabular form the Modules comprising the IOD. The following information must be specified for each Module in the table: - The name of the Module or Functional Group - A reference to the Section in Annex C which defines the Module or Functional Group - The usage of the Module or Functional Group; whether it is: - Mandatory (see A.1.3.1) , abbreviated M - Conditional (see A.1.3.2) , abbreviated C - User Option (see A.1.3.3) , abbreviated U The Modules referenced are defined in Annex C. A.1.3.1 MANDATORY MODULES For each IOD, Mandatory Modules shall be supported per the definitions, semantics and requirements defined in Annex C. PS 3.3 - 2008 Page 96 - Standard - A.1.3.2 CONDITIONAL MODULES Conditional Modules are Mandatory Modules if specific conditions are met. If the specified conditions are not met, this Module shall not be supported; that is, no information defined in that Module shall be sent. A.1.3.3 USER OPTION MODULES User Option Modules may or may not be supported. If an optional Module is supported, the Attribute Types specified in the Modules in Annex C shall be supported. * \sa DictEntry */ class GDCM_EXPORT IODEntry { public: IODEntry(const char *name = "", const char *ref = "", const char *usag = ""):Name(name),Ref(ref),usage(usag) { } friend std::ostream& operator<<(std::ostream& _os, const IODEntry &_val); void SetIE(const char *ie) { IE = ie; } const char *GetIE() const { return IE.c_str(); } void SetName(const char *name) { Name = name; } const char *GetName() const { return Name.c_str(); } void SetRef(const char *ref) { Ref = ref; } const char *GetRef() const { return Ref.c_str(); } void SetUsage(const char *usag) { usage = usag; } const char *GetUsage() const { return usage.c_str(); } Usage::UsageType GetUsageType() const; private: std::string IE; std::string Name; std::string Ref; std::string usage; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& _os, const IODEntry &_val) { _os << _val.IE << "\t" << _val.Name << "\t" << _val.Ref << "\t" << _val.usage; return _os; } } // end namespace gdcm #endif //GDCMIODENTRY_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmIODs.h000066400000000000000000000040321412732066400230000ustar00rootroot00000000000000/*========================================================================= 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 GDCMIODS_H #define GDCMIODS_H #include "gdcmTypes.h" #include "gdcmIOD.h" #include namespace gdcm { /** * \brief Class for representing a IODs * \note bla * \sa IOD */ class GDCM_EXPORT IODs { public: typedef std::string IODName; typedef std::map IODMapType; IODs() = default; friend std::ostream& operator<<(std::ostream& _os, const IODs &_val); void Clear() { IODsInternal.clear(); } void AddIOD(const char *name , const IOD & module ) { IODsInternal.insert( IODMapType::value_type(name, module)); } const IOD &GetIOD(const char *name) const { //return IODsInternal[name]; IODMapType::const_iterator it = IODsInternal.find( name ); assert( it != IODsInternal.end() ); assert( it->first == name ); return it->second; } typedef IODMapType::const_iterator IODMapTypeConstIterator; IODMapTypeConstIterator Begin() const { return IODsInternal.begin(); } IODMapTypeConstIterator End() const { return IODsInternal.end(); } private: IODMapType IODsInternal; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& _os, const IODs &_val) { IODs::IODMapType::const_iterator it = _val.IODsInternal.begin(); for(;it != _val.IODsInternal.end(); ++it) { const std::string &name = it->first; const IOD &m = it->second; _os << name << " " << m << '\n'; } return _os; } } // end namespace gdcm #endif //GDCMIODS_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmMacro.cxx000066400000000000000000000043611412732066400236230ustar00rootroot00000000000000/*========================================================================= 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 "gdcmMacro.h" #include "gdcmDataSet.h" #include "gdcmUsage.h" //#include "gdcmDefs.h" #include "gdcmModuleEntry.h" // MacroEntry //#include "gdcmGlobal.h" namespace gdcm { bool Macro::FindMacroEntry(const Tag &tag) const { MapModuleEntry::const_iterator it = ModuleInternal.find(tag); if( it != ModuleInternal.end() ) { return true; } // Not found anywhere :( return false; } const MacroEntry& Macro::GetMacroEntry(const Tag &tag) const { MapModuleEntry::const_iterator it = ModuleInternal.find(tag); if( it != ModuleInternal.end() ) { assert( it->first == tag ); return it->second; } // Not found anywhere :( throw "Could not find Module for Tag requested"; } bool Macro::Verify(const DataSet& ds, Usage const & usage) const { bool success = true; if( usage == Usage::UserOption ) return success; Macro::MapModuleEntry::const_iterator it = ModuleInternal.begin(); for(;it != ModuleInternal.end(); ++it) { const Tag &tag = it->first; const ModuleEntry &me = it->second; const gdcm::Type &type = me.GetType(); if( ds.FindDataElement( tag ) ) { // element found const DataElement &de = ds.GetDataElement( tag ); if ( de.IsEmpty() && (type == Type::T1 || type == Type::T1C ) ) { gdcmWarningMacro( "T1 element cannot be empty: " << de ); success = false; } } else { if( type == Type::T1 || type == Type::T1C ) { gdcmWarningMacro( "DataSet is missing tag: " << tag ); gdcmWarningMacro( "ModuleEntry specify: " << me ); gdcmWarningMacro( "Usage is: " << usage ); success = false; } } } return success; } } GDCM-3.0.10/Source/InformationObjectDefinition/gdcmMacro.h000066400000000000000000000057031412732066400232510ustar00rootroot00000000000000/*========================================================================= 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 GDCMMACRO_H #define GDCMMACRO_H #include "gdcmTypes.h" #include "gdcmTag.h" #include "gdcmMacroEntry.h" #include #include namespace gdcm { class DataSet; class Usage; /** * \brief Class for representing a Macro * \note Attribute Macro: * a set of Attributes that are described in a single table that is referenced * by multiple Module or other tables. * \sa Module */ class GDCM_EXPORT Macro { public: typedef std::map MapModuleEntry; typedef std::vector ArrayIncludeMacrosType; //typedef MapModuleEntry::const_iterator ConstIterator; //typedef MapModuleEntry::iterator Iterator; //ConstIterator Begin() const { return ModuleInternal.begin(); } //Iterator Begin() { return ModuleInternal.begin(); } //ConstIterator End() const { return ModuleInternal.end(); } //Iterator End() { return ModuleInternal.end(); } Macro() = default; friend std::ostream& operator<<(std::ostream& _os, const Macro&_val); void Clear() { ModuleInternal.clear(); } /// Will add a ModuleEntry directly at root-level. See Macro for nested-included level. void AddMacroEntry(const Tag& tag, const MacroEntry & module) { ModuleInternal.insert( MapModuleEntry::value_type(tag, module)); } /// Find or Get a ModuleEntry. ModuleEntry are either search are root-level /// or within nested-macro included in module. bool FindMacroEntry(const Tag &tag) const; const MacroEntry& GetMacroEntry(const Tag &tag) const; void SetName( const char *name) { Name = name; } const char *GetName() const { return Name.c_str(); } // Verify will print on std::cerr for error // Upon success will return true, false otherwise bool Verify(const DataSet& ds, Usage const & usage) const; private: //Module &operator=(const Module &_val); // purposely not implemented //Module(const Module &_val); // purposely not implemented MapModuleEntry ModuleInternal; std::string Name; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& _os, const Macro &_val) { _os << _val.Name << '\n'; Macro::MapModuleEntry::const_iterator it = _val.ModuleInternal.begin(); for(;it != _val.ModuleInternal.end(); ++it) { const Tag &t = it->first; const MacroEntry &de = it->second; _os << t << " " << de << '\n'; } return _os; } } // end namespace gdcm #endif //GDCMMACRO_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmMacroEntry.h000066400000000000000000000051131412732066400242660ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ #if 0 #ifndef GDCMMACROENTRY_H #define GDCMMACROENTRY_H #include "gdcmTypes.h" #include "gdcmType.h" #include namespace gdcm { /** * \brief Class for representing a ModuleEntry * \note bla * \sa DictEntry */ class GDCM_EXPORT MacroEntry { public: MacroEntry(const char *name = "", const char *type = "3", const char *description = ""):Name(name)/*,Type(type)*/,DescriptionField(description) { DataElementType = Type::GetTypeType(type); } virtual ~MacroEntry() {} // important friend std::ostream& operator<<(std::ostream& _os, const MacroEntry &_val); void SetName(const char *name) { Name = name; } const char *GetName() const { return Name.c_str(); } void SetType(const Type &type) { DataElementType = type; } const Type &GetType() const { return DataElementType; } /* * WARNING: 'Description' is currently a std::string, but it might change in the future * do not expect it to remain the same, and always use the ModuleEntry::Description typedef * instead. */ typedef std::string Description; void SetDescription(const char *d) { DescriptionField = d; } const Description & GetDescription() const { return DescriptionField; } protected: // PS 3.3 repeats the name of an attribute, but often contains typos // for now we will not use this info, but instead access the DataDict instead std::string Name; // An attribute, encoded as a Data Element, may or may not be required in a // Data Set, depending on that Attribute's Data Element Type. Type DataElementType; // TODO: for now contains the raw description (with enumerated values, defined terms...) Description DescriptionField; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& _os, const MacroEntry &_val) { _os << _val.Name << "\t" << _val.DataElementType << "\t" << _val.DescriptionField; return _os; } } // end namespace gdcm #endif //GDCMMODULEENTRY_H #endif #ifndef GDCMMACROENTRY_H #define GDCMMACROENTRY_H #include "gdcmModuleEntry.h" #endif GDCM-3.0.10/Source/InformationObjectDefinition/gdcmMacros.cxx000066400000000000000000000011401412732066400237760ustar00rootroot00000000000000/*========================================================================= 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 "gdcmMacros.h" namespace gdcm { } GDCM-3.0.10/Source/InformationObjectDefinition/gdcmMacros.h000066400000000000000000000040721412732066400234320ustar00rootroot00000000000000/*========================================================================= 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 GDCMMACROS_H #define GDCMMACROS_H #include "gdcmTypes.h" #include "gdcmMacro.h" #include namespace gdcm { /** * \brief Class for representing a Modules * \note bla * \sa Module */ class GDCM_EXPORT Macros { public: typedef std::map ModuleMapType; Macros() = default; friend std::ostream& operator<<(std::ostream& _os, const Macros&_val); void Clear() { ModulesInternal.clear(); } // A Module is inserted based on it's ref void AddMacro(const char *ref, const Macro & module ) { assert( ref && *ref ); assert( ModulesInternal.find( ref ) == ModulesInternal.end() ); ModulesInternal.insert( ModuleMapType::value_type(ref, module)); } const Macro &GetMacro(const char *name) const { assert( name && *name ); ModuleMapType::const_iterator it = ModulesInternal.find( name ); assert( it != ModulesInternal.end() ); assert( it->first == name ); return it->second; } bool IsEmpty() const { return ModulesInternal.empty(); } private: ModuleMapType ModulesInternal; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& _os, const Macros &_val) { Macros::ModuleMapType::const_iterator it = _val.ModulesInternal.begin(); for(;it != _val.ModulesInternal.end(); ++it) { const std::string &name = it->first; const Macro &m = it->second; _os << name << " " << m << '\n'; } return _os; } } // end namespace gdcm #endif //GDCMMODULES_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmModule.cxx000066400000000000000000000071531412732066400240110ustar00rootroot00000000000000/*========================================================================= 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 "gdcmModule.h" #include "gdcmDataSet.h" #include "gdcmUsage.h" //#include "gdcmDefs.h" #include "gdcmMacros.h" // Macros //#include "gdcmGlobal.h" namespace gdcm { bool Module::FindModuleEntryInMacros(Macros const ¯os, const Tag &tag) const { (void)macros; MapModuleEntry::const_iterator it = ModuleInternal.find(tag); if( it != ModuleInternal.end() ) { return true; } // Need to search within Nested-Included Macro: // start with easy case: if( ArrayIncludeMacros.empty() ) return false; // we need to loop over all Included-Macro: //static const Global &g = Global::GetInstance(); //static const Defs &defs = g.GetDefs(); //static const Macros ¯os = defs.GetMacros(); #if 0 for( ArrayIncludeMacrosType::const_iterator it = ArrayIncludeMacros.begin(); it != ArrayIncludeMacros.end(); ++it) { const std::string &name = *it; const Macro ¯o = macros.GetMacro( name.c_str() ); if( macro.FindMacroEntry( tag ) ) { return true; } } #endif // Not found anywhere :( return false; } const ModuleEntry& Module::GetModuleEntryInMacros(Macros const ¯os, const Tag &tag) const { MapModuleEntry::const_iterator it = ModuleInternal.find(tag); if( it != ModuleInternal.end() ) { assert( it->first == tag ); return it->second; } // Need to search within Nested-Included Macro: // start with easy case: if( ArrayIncludeMacros.empty() ) { throw "Could not find Module for Tag requested"; } // we need to loop over all Included-Macro: //static const Global &g = Global::GetInstance(); //static const Defs &defs = g.GetDefs(); //static const Macros ¯os = defs.GetMacros(); for( ArrayIncludeMacrosType::const_iterator it2 = ArrayIncludeMacros.begin(); it2 != ArrayIncludeMacros.end(); ++it2) { const std::string &name = *it2; const Macro ¯o= macros.GetMacro( name.c_str() ); if( macro.FindMacroEntry( tag ) ) { return macro.GetMacroEntry(tag); } } // Not found anywhere :( throw "Could not find Module for Tag requested"; } bool Module::Verify(const DataSet& ds, Usage const & usage) const { bool success = true; if( usage == Usage::UserOption ) return success; Module::MapModuleEntry::const_iterator it = ModuleInternal.begin(); for(;it != ModuleInternal.end(); ++it) { const Tag &tag = it->first; const ModuleEntry &me = it->second; const gdcm::Type &type = me.GetType(); if( ds.FindDataElement( tag ) ) { // element found const DataElement &de = ds.GetDataElement( tag ); if ( de.IsEmpty() && (type == Type::T1 || type == Type::T1C ) ) { gdcmWarningMacro( "T1 element cannot be empty: " << de ); success = false; } } else { if( type == Type::T1 || type == Type::T1C ) { gdcmWarningMacro( "DataSet is missing tag: " << tag ); gdcmWarningMacro( "ModuleEntry specify: " << me ); gdcmWarningMacro( "Usage is: " << usage ); success = false; } } } return success; } } GDCM-3.0.10/Source/InformationObjectDefinition/gdcmModule.h000066400000000000000000000062371412732066400234400ustar00rootroot00000000000000/*========================================================================= 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 GDCMMODULE_H #define GDCMMODULE_H #include "gdcmTypes.h" #include "gdcmTag.h" #include "gdcmModuleEntry.h" #include #include namespace gdcm { class DataSet; class Usage; class Macros; /** * \brief Class for representing a Module * \note * Module: A set of Attributes within an Information Entity or Normalized IOD which * are logically related to each other. * \sa Macro */ class GDCM_EXPORT Module { public: typedef std::map MapModuleEntry; typedef std::vector ArrayIncludeMacrosType; //typedef MapModuleEntry::const_iterator ConstIterator; //typedef MapModuleEntry::iterator Iterator; //ConstIterator Begin() const { return ModuleInternal.begin(); } //Iterator Begin() { return ModuleInternal.begin(); } //ConstIterator End() const { return ModuleInternal.end(); } //Iterator End() { return ModuleInternal.end(); } Module() = default; friend std::ostream& operator<<(std::ostream& _os, const Module &_val); void Clear() { ModuleInternal.clear(); } /// Will add a ModuleEntry directly at root-level. See Macro for nested-included level. void AddModuleEntry(const Tag& tag, const ModuleEntry & module) { ModuleInternal.insert( MapModuleEntry::value_type(tag, module)); } void AddMacro(const char *include) { ArrayIncludeMacros.push_back( include ); } /// Find or Get a ModuleEntry. ModuleEntry are either search are root-level /// or within nested-macro included in module. bool FindModuleEntryInMacros(Macros const ¯os, const Tag &tag) const; const ModuleEntry& GetModuleEntryInMacros(Macros const ¯os, const Tag &tag) const; void SetName( const char *name) { Name = name; } const char *GetName() const { return Name.c_str(); } // Verify will print on std::cerr for error // Upon success will return true, false otherwise bool Verify(const DataSet& ds, Usage const & usage) const; private: //Module &operator=(const Module &_val); // purposely not implemented //Module(const Module &_val); // purposely not implemented MapModuleEntry ModuleInternal; std::string Name; ArrayIncludeMacrosType ArrayIncludeMacros; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& _os, const Module &_val) { _os << _val.Name << '\n'; Module::MapModuleEntry::const_iterator it = _val.ModuleInternal.begin(); for(;it != _val.ModuleInternal.end(); ++it) { const Tag &t = it->first; const ModuleEntry &de = it->second; _os << t << " " << de << '\n'; } return _os; } } // end namespace gdcm #endif //GDCMMODULE_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmModuleEntry.h000066400000000000000000000050271412732066400244560ustar00rootroot00000000000000/*========================================================================= 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 GDCMMODULEENTRY_H #define GDCMMODULEENTRY_H #include "gdcmTypes.h" #include "gdcmType.h" #include namespace gdcm { /** * \brief Class for representing a ModuleEntry * \note bla * \sa DictEntry */ class GDCM_EXPORT ModuleEntry { public: ModuleEntry(const char *name = "", const char *type = "3", const char *description = ""):Name(name)/*,Type(type)*/,DescriptionField(description) { DataElementType = Type::GetTypeType(type); } virtual ~ModuleEntry() = default; // important friend std::ostream& operator<<(std::ostream& _os, const ModuleEntry &_val); void SetName(const char *name) { Name = name; } const char *GetName() const { return Name.c_str(); } void SetType(const Type &type) { DataElementType = type; } const Type &GetType() const { return DataElementType; } /* * WARNING: 'Description' is currently a std::string, but it might change in the future * do not expect it to remain the same, and always use the ModuleEntry::Description typedef * instead. */ typedef std::string Description; void SetDescription(const char *d) { DescriptionField = d; } const Description & GetDescription() const { return DescriptionField; } protected: // PS 3.3 repeats the name of an attribute, but often contains typos // for now we will not use this info, but instead access the DataDict instead std::string Name; // An attribute, encoded as a Data Element, may or may not be required in a // Data Set, depending on that Attribute's Data Element Type. Type DataElementType; // TODO: for now contains the raw description (with enumerated values, defined terms...) Description DescriptionField; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& _os, const ModuleEntry &_val) { _os << _val.Name << "\t" << _val.DataElementType << "\t" << _val.DescriptionField; return _os; } typedef ModuleEntry MacroEntry; } // end namespace gdcm #endif //GDCMMODULEENTRY_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmModules.cxx000066400000000000000000000011411412732066400241630ustar00rootroot00000000000000/*========================================================================= 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 "gdcmModules.h" namespace gdcm { } GDCM-3.0.10/Source/InformationObjectDefinition/gdcmModules.h000066400000000000000000000041121412732066400236110ustar00rootroot00000000000000/*========================================================================= 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 GDCMMODULES_H #define GDCMMODULES_H #include "gdcmTypes.h" #include "gdcmModule.h" #include namespace gdcm { /** * \brief Class for representing a Modules * \note bla * \sa Module */ class GDCM_EXPORT Modules { public: typedef std::map ModuleMapType; Modules() = default; friend std::ostream& operator<<(std::ostream& _os, const Modules &_val); void Clear() { ModulesInternal.clear(); } // A Module is inserted based on it's ref void AddModule(const char *ref, const Module & module ) { assert( ref && *ref ); assert( ModulesInternal.find( ref ) == ModulesInternal.end() ); ModulesInternal.insert( ModuleMapType::value_type(ref, module)); } const Module &GetModule(const char *name) const { assert( name && *name ); ModuleMapType::const_iterator it = ModulesInternal.find( name ); assert( it != ModulesInternal.end() ); assert( it->first == name ); return it->second; } bool IsEmpty() const { return ModulesInternal.empty(); } private: ModuleMapType ModulesInternal; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& _os, const Modules &_val) { Modules::ModuleMapType::const_iterator it = _val.ModulesInternal.begin(); for(;it != _val.ModulesInternal.end(); ++it) { const std::string &name = it->first; const Module &m = it->second; _os << name << " " << m << '\n'; } return _os; } } // end namespace gdcm #endif //GDCMMODULES_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmNestedModuleEntries.cxx000066400000000000000000000011321412732066400264750ustar00rootroot00000000000000/*========================================================================= 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 "gdcmNestedModuleEntries.h" GDCM-3.0.10/Source/InformationObjectDefinition/gdcmNestedModuleEntries.h000066400000000000000000000036051412732066400261310ustar00rootroot00000000000000/*========================================================================= 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 GDCMNESTEDMODULEENTRIES_H #define GDCMNESTEDMODULEENTRIES_H #include "gdcmModuleEntry.h" #include namespace gdcm { /** * \brief Class for representing a NestedModuleEntries * \note bla * \sa ModuleEntry */ class GDCM_EXPORT NestedModuleEntries : public ModuleEntry { public: NestedModuleEntries(const char *name = "", const char *type = "3", const char *description = ""):ModuleEntry(name,type,description) { } friend std::ostream& operator<<(std::ostream& _os, const NestedModuleEntries &_val); typedef std::vector::size_type SizeType; SizeType GetNumberOfModuleEntries() { return ModuleEntriesList.size(); } const ModuleEntry &GetModuleEntry(SizeType idx) const { return ModuleEntriesList[idx]; } ModuleEntry &GetModuleEntry(SizeType idx) { return ModuleEntriesList[idx]; } void AddModuleEntry(const ModuleEntry &me) { ModuleEntriesList.push_back( me ); } private: std::vector ModuleEntriesList; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& _os, const NestedModuleEntries &_val) { _os << "Nested:" << _val.Name << "\t" << _val.DataElementType << "\t" << _val.DescriptionField; return _os; } typedef NestedModuleEntries NestedMacroEntries; } // end namespace gdcm #endif //GDCMNESTEDMODULEENTRIES_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmPatient.cxx000066400000000000000000000011371412732066400241640ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPatient.h" namespace gdm {} GDCM-3.0.10/Source/InformationObjectDefinition/gdcmPatient.h000066400000000000000000000016101412732066400236050ustar00rootroot00000000000000/*========================================================================= 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 GDCMPATIENT_H #define GDCMPATIENT_H #include "gdcmTypes.h" #include "gdcmStudy.h" namespace gdcm { /** * \brief * See PS 3.3 - 2007 * DICOM MODEL OF THE REAL-WORLD, p 54 */ class GDCM_EXPORT Patient { public: Patient() = default; private: std::vector StudyList; }; } // end namespace gdcm #endif //GDCMPATIENT_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmSeries.cxx000066400000000000000000000011371412732066400240120ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSeries.h" namespace gdcm {} GDCM-3.0.10/Source/InformationObjectDefinition/gdcmSeries.h000066400000000000000000000014561412732066400234430ustar00rootroot00000000000000/*========================================================================= 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 GDCMSERIES_H #define GDCMSERIES_H #include "gdcmTypes.h" namespace gdcm { /** * \brief Series */ class GDCM_EXPORT Series { public: Series() = default; private: // Image, Waveform... }; } // end namespace gdcm #endif //GDCMSERIES_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmStudy.cxx000066400000000000000000000011361412732066400236670ustar00rootroot00000000000000/*========================================================================= 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 "gdcmStudy.h" namespace gdcm {} GDCM-3.0.10/Source/InformationObjectDefinition/gdcmStudy.h000066400000000000000000000015351412732066400233170ustar00rootroot00000000000000/*========================================================================= 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 GDCMSTUDY_H #define GDCMSTUDY_H #include "gdcmTypes.h" #include "gdcmSeries.h" #include namespace gdcm { /** * \brief Study */ class GDCM_EXPORT Study { public: Study() = default; private: std::vector SeriesList; }; } // end namespace gdcm #endif //GDCMSTUDY_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmTable.cxx000066400000000000000000000011661412732066400236110ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTable.h" namespace gdcm { } // end namespace gdcm GDCM-3.0.10/Source/InformationObjectDefinition/gdcmTable.h000066400000000000000000000031131412732066400232300ustar00rootroot00000000000000/*========================================================================= 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 GDCMTABLE_H #define GDCMTABLE_H #include "gdcmTableEntry.h" #include "gdcmTag.h" #include namespace gdcm { /** * \brief Table */ class Table { public: typedef std::map MapTableEntry; Table() = default; ~Table() = default; Table &operator=(const Table &_val) = delete; Table(const Table&_val) = delete; friend std::ostream& operator<<(std::ostream& _os, const Table &_val); void InsertEntry(Tag const &tag, TableEntry const &te) { #ifndef NDEBUG MapTableEntry::size_type s = TableInternal.size(); #endif TableInternal.insert( MapTableEntry::value_type(tag, te)); assert( s < TableInternal.size() ); } const TableEntry &GetTableEntry(const Tag &tag) const { MapTableEntry::const_iterator it = TableInternal.find(tag); if (it == TableInternal.end()) { assert( 0 && "Impossible" ); return GetTableEntry(Tag(0,0)); } return it->second; } MapTableEntry TableInternal; }; } // end namespace gdcm #endif //GDCMTABLE_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmTableEntry.h000066400000000000000000000021021412732066400242470ustar00rootroot00000000000000/*========================================================================= 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 GDCMTABLEENTRY_H #define GDCMTABLEENTRY_H #include "gdcmType.h" #include namespace gdcm { /** * \brief TableEntry */ class TableEntry { public: TableEntry(const char *attribute = nullptr, Type const &type = Type(), const char * des = nullptr ) : Attribute(attribute ? attribute : ""),TypeField(type),Description(des ? des : "") {} ~TableEntry() = default; private: std::string Attribute; Type TypeField; std::string Description; }; } // end namespace gdcm #endif //GDCMTABLEENTRY_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmTableReader.cxx000066400000000000000000000331671412732066400247420ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTableReader.h" #include "gdcmTable.h" #include #include #include "gdcm_expat.h" #include // for stderr #include namespace gdcm { #if 1 #ifdef XML_LARGE_SIZE #if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400 #define XML_FMT_INT_MOD "I64" #else #define XML_FMT_INT_MOD "ll" #endif #else #define XML_FMT_INT_MOD "l" #endif #else #define XML_FMT_INT_MOD "" #endif #ifndef BUFSIZ #define BUFSIZ 4096 #endif #ifndef XMLCALL #define XMLCALL #endif #ifndef XML_STATUS_ERROR #define XML_STATUS_ERROR 0 #endif static void XMLCALL startElement(void *userData, const char *name, const char **atts) { TableReader *tr = reinterpret_cast(userData); tr->StartElement(name, atts); } static void XMLCALL endElement(void *userData, const char *name) { TableReader *tr = reinterpret_cast(userData); tr->EndElement(name); } static void XMLCALL characterDataHandler(void* userData, const char* data, int length) { TableReader *tr = reinterpret_cast(userData); tr->CharacterDataHandler(data,length); } void TableReader::HandleMacroEntryDescription(const char **atts) { (void)atts; assert( ParsingMacroEntryDescription == false ); ParsingMacroEntryDescription = true; assert( *atts == nullptr ); assert( Description == "" ); } void TableReader::HandleModuleInclude(const char **atts) { const char *ref = *atts; assert( strcmp(ref, "ref") == 0 ); (void)ref; //removing warning const char *include = *(atts+1); CurrentModule.AddMacro( include ); //assert( *(atts+2) == 0 ); // description ? } void TableReader::HandleModuleEntryDescription(const char **atts) { (void)atts; assert( ParsingModuleEntryDescription == false ); ParsingModuleEntryDescription = true; assert( *atts == nullptr ); assert( Description == "" ); } void TableReader::HandleMacroEntry(const char **atts) { std::string strgrp = "group"; std::string strelt = "element"; std::string strname = "name"; std::string strtype = "type"; Tag &tag = CurrentTag; MacroEntry &moduleentry = CurrentMacroEntry; const char **current = atts; while(*current /*&& current+1*/) { if( strgrp == *current ) { unsigned int v; const char *raw = *(current+1); int r = sscanf(raw, "%04x", &v); assert( r == 1 ); assert( v <= 0xFFFF ); (void)r; //removing warning tag.SetGroup( (uint16_t)v ); } else if( strelt == *current ) { unsigned int v; const char *raw = *(current+1); int r = sscanf(raw, "%04x", &v); assert( r == 1 ); assert( v <= 0xFFFF ); (void)r; //removing warning tag.SetElement( (uint16_t)v ); } else if( strname == *current ) { const char *raw = *(current+1); moduleentry.SetName( raw ); } else if( strtype == *current ) { const char *raw = *(current+1); moduleentry.SetType( Type::GetTypeType(raw) ); } else { assert(0); } ++current; ++current; } } void TableReader::HandleModuleEntry(const char **atts) { std::string strgrp = "group"; std::string strelt = "element"; std::string strname = "name"; std::string strtype = "type"; Tag &tag = CurrentTag; ModuleEntry &moduleentry = CurrentModuleEntry; const char **current = atts; while(*current /*&& current+1*/) { if( strgrp == *current ) { unsigned int v; const char *raw = *(current+1); int r = sscanf(raw, "%04x", &v); assert( r == 1 ); assert( v <= 0xFFFF ); (void)r; //removing warning tag.SetGroup( (uint16_t)v ); } else if( strelt == *current ) { unsigned int v; const char *raw = *(current+1); int r = sscanf(raw, "%04x", &v); assert( r == 1 ); assert( v <= 0xFFFF ); (void)r; //removing warning tag.SetElement( (uint16_t)v ); } else if( strname == *current ) { const char *raw = *(current+1); moduleentry.SetName( raw ); } else if( strtype == *current ) { const char *raw = *(current+1); moduleentry.SetType( Type::GetTypeType(raw) ); } else { assert(0); } ++current; ++current; } } void TableReader::HandleIODEntry(const char **atts) { std::string strie = "ie"; std::string strname = "name"; std::string strref = "ref"; std::string strusage = "usage"; // std::string strdesc = "description"; IODEntry &iodentry = CurrentIODEntry; const char **current = atts; while(*current /*&& current+1*/) { const char *raw = *(current+1); if( strie == *current ) { iodentry.SetIE( raw ); } else if( strname == *current ) { iodentry.SetName( raw ); } else if( strref == *current ) { iodentry.SetRef( raw ); } else if( strusage == *current ) { iodentry.SetUsage( raw ); } else if( strdesc == *current ) { //iodentry.SetDescription( raw ); } else { assert(0); } ++current; ++current; } } void TableReader::HandleIOD(const char **atts) { HandleModule(atts); } void TableReader::HandleMacro(const char **atts) { HandleModule(atts); } void TableReader::HandleModule(const char **atts) { std::string strref = "ref"; std::string strname = "name"; std::string strtable = "table"; const char **current = atts; while(*current /*&& current+1*/) { if( strref == *current ) { CurrentModuleRef = *(current+1); } else if( strtable == *current ) { // ref to table is needed for referencing Macro CurrentMacroRef = *(current+1); } else if( strname == *current ) { CurrentModuleName = *(current+1); } else { assert(0); } ++current; ++current; } } void TableReader::StartElement(const char *name, const char **atts) { //int i; //int *depthPtr = (int *)userData; // for (i = 0; i < *depthPtr; i++) // putchar('\t'); //std::cout << name << /*" : " << atts[0] << "=" << atts[1] <<*/ std::endl; if( strcmp(name, "tables" ) == 0 ) { //*depthPtr += 1; } else if( strcmp(name, "macro" ) == 0 ) { ParsingMacro = true; HandleMacro(atts); } else if( strcmp(name, "module" ) == 0 ) { //std::cout << "Start Module" << std::endl; ParsingModule = true; HandleModule(atts); } else if( strcmp(name, "iod" ) == 0 ) { ParsingIOD = true; HandleIOD(atts); } else if( strcmp(name, "entry" ) == 0 ) { if( ParsingModule ) { ParsingModuleEntry = true; HandleModuleEntry(atts); } else if( ParsingMacro ) { ParsingMacroEntry = true; HandleMacroEntry(atts); } else if( ParsingIOD ) { ParsingIODEntry = true; HandleIODEntry(atts); } } else if( strcmp(name, "description" ) == 0 ) { if( ParsingModuleEntry ) { HandleModuleEntryDescription(atts); } else if( ParsingMacroEntry ) { HandleMacroEntryDescription(atts); } else /*if( ParsingIODoEntry )*/ { assert(0); } } else if( strcmp(name, "section" ) == 0 ) { // TODO ! } else if( strcmp(name, "include" ) == 0 ) { // TODO ! HandleModuleInclude(atts); } else if ( strcmp(name,"standard-sop-classes") == 0 ) { // TODO ! } else if ( strcmp(name,"mapping") == 0 ) { // TODO ! } else if ( strcmp(name,"unrecognized-rows") == 0 ) { // TODO ! } else if ( strcmp(name,"retired-defined-terms") == 0 ) { // TODO ! } else if ( strcmp(name,"enumerated-values") == 0 ) { // TODO ! } else if ( strcmp(name,"defined-terms") == 0 ) { // TODO ! } else if ( strcmp(name,"term") == 0 ) { // TODO ! } else if ( strcmp(name,"sop-classes") == 0 ) { // TODO ! } else if ( strcmp(name,"standard-and-related-general-sop-classes") == 0 ) { // TODO ! } else if ( strcmp(name,"media-storage-standard-sop-classes") == 0 ) { // TODO ! } else if ( strcmp(name,"retired-standard-sop-classes") == 0 ) { // TODO ! } else if ( strcmp(name,"modality-specific-sop-class-conversions") == 0 ) { // TODO ! } else if ( strcmp(name,"standard-sop-classes2") == 0 ) { // TODO ! } else { assert(0); } } void TableReader::EndElement(const char *name) { // int *depthPtr = (int *)userData; // *depthPtr -= 1; if( strcmp(name, "tables" ) == 0 ) { } else if( strcmp(name, "macro" ) == 0 ) { //std::cout << "Start Macro" << std::endl; CurrentMacro.SetName( CurrentModuleName.c_str() ); CurrentDefs.GetMacros().AddMacro( CurrentMacroRef.c_str(), CurrentMacro); CurrentMacroRef.clear(); CurrentModuleName.clear(); CurrentMacro.Clear(); ParsingMacro = false; } else if( strcmp( "module", name) == 0 ) { CurrentModule.SetName( CurrentModuleName.c_str() ); CurrentDefs.GetModules().AddModule( CurrentModuleRef.c_str(), CurrentModule); //std::cout << "End Module: " << CurrentModuleRef << "," << CurrentModuleName << std::endl; CurrentModuleRef.clear(); CurrentModuleName.clear(); CurrentModule.Clear(); ParsingModule = false; } else if( strcmp(name, "iod" ) == 0 ) { CurrentDefs.GetIODs().AddIOD( CurrentModuleName.c_str(), CurrentIOD); CurrentModuleName.clear(); CurrentIOD.Clear(); ParsingIOD = false; } else if( strcmp(name, "entry" ) == 0 ) { if( ParsingModule ) { ParsingModuleEntry = false; CurrentModule.AddModuleEntry( CurrentTag, CurrentModuleEntry); } else if( ParsingMacro ) { ParsingMacroEntry = false; CurrentMacro.AddMacroEntry( CurrentTag, CurrentMacroEntry); } else if( ParsingIOD ) { ParsingIODEntry = false; CurrentIOD.AddIODEntry( CurrentIODEntry); } } else if( strcmp(name, "description" ) == 0 ) { if( ParsingModuleEntry ) { ParsingModuleEntryDescription = false; CurrentModuleEntry.SetDescription( Description.c_str() ); Description = ""; } else if( ParsingMacroEntry ) { ParsingMacroEntryDescription = false; //assert( !Description.empty() ); CurrentMacroEntry.SetDescription( Description.c_str() ); Description = ""; } else { assert(0); } } else if( strcmp(name, "mapping" ) == 0 ) { // TODO ! } else if( strcmp(name, "standard-sop-classes" ) == 0 ) { // TODO ! } else if ( strcmp(name,"standard-and-related-general-sop-classes") == 0 ) { // TODO ! } else if ( strcmp(name,"media-storage-standard-sop-classes") == 0 ) { // TODO ! } else if( strcmp(name, "section" ) == 0 ) { // TODO ! } else if( strcmp(name, "unrecognized-rows" ) == 0 ) { // TODO ! } else if( strcmp(name, "retired-defined-terms" ) == 0 ) { // TODO ! } else if( strcmp(name, "enumerated-values" ) == 0 ) { // TODO ! } else if( strcmp(name, "defined-terms" ) == 0 ) { // TODO ! } else if( strcmp(name, "term" ) == 0 ) { // TODO ! } else if( strcmp(name, "sop-classes" ) == 0 ) { // TODO ! } else if ( strcmp(name,"retired-standard-sop-classes") == 0 ) { // TODO ! } else if ( strcmp(name,"modality-specific-sop-class-conversions") == 0 ) { // TODO ! } else if ( strcmp(name,"standard-sop-classes2") == 0 ) { // TODO ! } else if( strcmp(name, "include" ) == 0 ) { if( ParsingModule ) { } else if( ParsingMacro ) { //abort(); } else { assert(0); } } else { assert(0); } } void TableReader::CharacterDataHandler(const char *data, int length) { if( ParsingModuleEntryDescription ) { std::string name( data, length); assert( (unsigned int)length == strlen( name.c_str() ) ); Description.append( name ); } else if( ParsingMacroEntryDescription ) { std::string name( data, length); assert( (unsigned int)length == strlen( name.c_str() ) ); Description.append( name ); } else { //assert(0); } } int TableReader::Read() { std::ifstream is( Filename.c_str(), std::ios::binary ); char buf[BUFSIZ]; XML_Parser parser = XML_ParserCreate(nullptr); int done; //int depth = 0; XML_SetUserData(parser, this); XML_SetElementHandler(parser, startElement, endElement); XML_SetCharacterDataHandler(parser, characterDataHandler); int ret = 0; do { is.read(buf, sizeof(buf)); std::streamsize len = is.gcount(); done = (unsigned int)len < sizeof(buf); if (XML_Parse(parser, buf, (int)len, done) == XML_STATUS_ERROR) { fprintf(stderr, "%s at line %" XML_FMT_INT_MOD "u\n", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser)); ret = 1; // Mark as error done = 1; // exit while } } while (!done); XML_ParserFree(parser); is.close(); return ret; } } // end namespace gdcm GDCM-3.0.10/Source/InformationObjectDefinition/gdcmTableReader.h000066400000000000000000000057551412732066400243710ustar00rootroot00000000000000/*========================================================================= 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 GDCMTABLEREADER_H #define GDCMTABLEREADER_H #include "gdcmTypes.h" #include "gdcmDefs.h" //#include "gdcmModule.h" //#include "gdcmIOD.h" //#include "gdcmIODs.h" //#include "gdcmModules.h" #include #include #include namespace gdcm { /** * \brief Class for representing a TableReader * \note This class is an empty shell meant to be derived */ class GDCM_EXPORT TableReader { public: TableReader(Defs &defs):CurrentDefs(defs),ParsingModule(false),ParsingModuleEntry(false), ParsingModuleEntryDescription(false), ParsingMacro(false), ParsingMacroEntry(false), ParsingMacroEntryDescription(false), ParsingIOD(false), ParsingIODEntry(false), Description() {} virtual ~TableReader() = default; // Set/Get filename void SetFilename(const char *filename) { Filename = filename; } const char *GetFilename() { return Filename.c_str(); } int Read(); //protected: // You need to override those function in your subclasses: virtual void StartElement(const char *name, const char **atts); virtual void EndElement(const char *name); virtual void CharacterDataHandler(const char *data, int length); void HandleModuleEntry(const char **atts); void HandleModule(const char **atts); void HandleModuleEntryDescription(const char **atts); void HandleMacroEntry(const char **atts); void HandleMacro(const char **atts); void HandleMacroEntryDescription(const char **atts); void HandleModuleInclude(const char **atts); void HandleIODEntry(const char **atts); void HandleIOD(const char **atts); //const Modules & GetModules() const { return CurrentModules; } //const Macros & GetMacros() const { return CurrentMacros; } //const IODs & GetIODs() const { return CurrentIODs; } const Defs & GetDefs() const { return CurrentDefs; } private: std::string Filename; Defs &CurrentDefs; //Macros CurrentMacros; //Modules CurrentModules; //IODs CurrentIODs; Macro CurrentMacro; Module CurrentModule; IOD CurrentIOD; MacroEntry CurrentMacroEntry; ModuleEntry CurrentModuleEntry; IODEntry CurrentIODEntry; std::string CurrentModuleName; std::string CurrentModuleRef; std::string CurrentMacroRef; bool ParsingModule; bool ParsingModuleEntry; bool ParsingModuleEntryDescription; bool ParsingMacro; bool ParsingMacroEntry; bool ParsingMacroEntryDescription; bool ParsingIOD; bool ParsingIODEntry; Tag CurrentTag; std::string Description; }; } // end namespace gdcm #endif //GDCMTABLEREADER_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmTables.h.in000066400000000000000000000012641412732066400240250ustar00rootroot00000000000000/*========================================================================= 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 GDCMTABLES_H #define GDCMTABLES_H const char * const gdcmTables[] = { @GDCM_XML_TABLES@ 0 }; #endif // GDCMTABLES_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmType.cxx000066400000000000000000000020321412732066400234740ustar00rootroot00000000000000/*========================================================================= 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 "gdcmType.h" #include namespace gdcm { static const char *TypeStrings[] = { "1", "1C", "2", "2C", "3", "UNKNOWN", nullptr }; const char *Type::GetTypeString(TypeType type) { return TypeStrings[type]; } Type::TypeType Type::GetTypeType(const char *type) { int i = 0; while(TypeStrings[i] != nullptr) { if( strcmp(type, TypeStrings[i]) == 0 ) return (TypeType)i; ++i; } return UNKNOWN; } } // end namespace gdcm GDCM-3.0.10/Source/InformationObjectDefinition/gdcmType.h000066400000000000000000000035541412732066400231330ustar00rootroot00000000000000/*========================================================================= 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 GDCMTYPE_H #define GDCMTYPE_H #include "gdcmTypes.h" #include namespace gdcm { /** * \brief Type * \note * PS 3.5 * 7.4 DATA ELEMENT TYPE * 7.4.1 TYPE 1 REQUIRED DATA ELEMENTS * 7.4.2 TYPE 1C CONDITIONAL DATA ELEMENTS * 7.4.3 TYPE 2 REQUIRED DATA ELEMENTS * 7.4.4 TYPE 2C CONDITIONAL DATA ELEMENTS * 7.4.5 TYPE 3 OPTIONAL DATA ELEMENTS * * The intent of Type 2 Data Elements is to allow a zero length to be conveyed * when the operator or application does not know its value or has a specific * reason for not specifying its value. It is the intent that the device should * support these Data Elements. */ class GDCM_EXPORT Type { public: typedef enum { T1 = 0, T1C, T2, T2C, T3, UNKNOWN } TypeType; Type(TypeType type = UNKNOWN) : TypeField(type) { } operator TypeType () const { return TypeField; } friend std::ostream &operator<<(std::ostream &os, const Type &vr); static const char *GetTypeString(TypeType type); static TypeType GetTypeType(const char *type); private: TypeType TypeField; }; //----------------------------------------------------------------------------- inline std::ostream &operator<<(std::ostream &_os, const Type &val) { _os << Type::GetTypeString(val.TypeField); return _os; } } // end namespace gdcm #endif //GDCMTYPE_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmUsage.cxx000066400000000000000000000022011412732066400236150ustar00rootroot00000000000000/*========================================================================= 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 "gdcmUsage.h" #include namespace gdcm { static const char *UsageStrings[] = { "Mandatory", // (see A.1.3.1) , abbreviated M "Conditional", // (see A.1.3.2) , abbreviated C "UserOption", // (see A.1.3.3) , abbreviated U nullptr }; const char *Usage::GetUsageString(UsageType type) { return UsageStrings[type]; } Usage::UsageType Usage::GetUsageType(const char *type) { int i = 0; while(UsageStrings[i] != nullptr) { if( strcmp(type, UsageStrings[i]) == 0 ) return (UsageType)i; ++i; } return Invalid; } } // end namespace gdcm GDCM-3.0.10/Source/InformationObjectDefinition/gdcmUsage.h000066400000000000000000000051561412732066400232560ustar00rootroot00000000000000/*========================================================================= 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 GDCMUSAGE_H #define GDCMUSAGE_H #include "gdcmTypes.h" #include namespace gdcm { /** * \brief Usage * \note A.1.3 IOD Module Table and Functional Group Macro Table This Section of each IOD defines in a tabular form the Modules comprising the IOD. The following information must be specified for each Module in the table: - The name of the Module or Functional Group - A reference to the Section in Annex C which defines the Module or Functional Group - The usage of the Module or Functional Group; whether it is: - Mandatory (see A.1.3.1) , abbreviated M - Conditional (see A.1.3.2) , abbreviated C - User Option (see A.1.3.3) , abbreviated U The Modules referenced are defined in Annex C. A.1.3.1 MANDATORY MODULES For each IOD, Mandatory Modules shall be supported per the definitions, semantics and requirements defined in Annex C. A.1.3.2 CONDITIONAL MODULES Conditional Modules are Mandatory Modules if specific conditions are met. If the specified conditions are not met, this Module shall not be supported; that is, no information defined in that Module shall be sent. A.1.3.3 USER OPTION MODULES User Option Modules may or may not be supported. If an optional Module is supported, the Attribute Types specified in the Modules in Annex C shall be supported. */ class GDCM_EXPORT Usage { public: typedef enum { Mandatory, // (see A.1.3.1) , abbreviated M Conditional, // (see A.1.3.2) , abbreviated C UserOption, // (see A.1.3.3) , abbreviated U Invalid } UsageType; Usage(UsageType type = Invalid) : UsageField(type) { } operator UsageType () const { return UsageField; } friend std::ostream &operator<<(std::ostream &os, const Usage &vr); static const char *GetUsageString(UsageType type); static UsageType GetUsageType(const char *type); private: UsageType UsageField; }; //----------------------------------------------------------------------------- inline std::ostream &operator<<(std::ostream &_os, const Usage &val) { _os << Usage::GetUsageString(val.UsageField); return _os; } } // end namespace gdcm #endif //GDCMUSAGE_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmXMLDictReader.cxx000066400000000000000000000124611412732066400251510ustar00rootroot00000000000000/*========================================================================= 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 "gdcmXMLDictReader.h" #include "gdcmDict.h" #include #include // abort namespace gdcm { XMLDictReader::XMLDictReader():ParsingDescription(false),Description() { } void XMLDictReader::HandleEntry(const char **atts) { assert( !ParsingDescription ); VR vr; VM vm; assert( vm == VM::VM0 ); std::string name; bool ret; Tag &tag = CurrentTag; DictEntry &de = CurrentDE; int i = 0; const char **current = atts; // Supported attributes: std::string group = "group"; std::string element = "element"; std::string strvr = "vr"; std::string strvm = "vm"; std::string retired = "retired"; std::string retiredtrue = "true"; std::string retiredfalse = "false"; std::string version = "version"; std::string strname = "name"; while(*current /*&& current+1*/) { assert( *(current + 1) ); if( group == *current ) { unsigned int v; const char *raw = *(current+1); int r = sscanf(raw, "%04x", &v); assert( r == 1 ); assert( v <= 0xFFFF ); char sv[4+1]; r = sprintf(sv, "%04x", v); assert( r == 4 ); if( strncmp(raw, sv, 4) == 0 ) // GroupXX { tag.SetGroup( v ); } else { assert( (raw[0] == '5' && raw[1] == '0') || (raw[0] == '6' && raw[1] == '0') ); if( raw[0] == '5' ) tag.SetGroup( 0x5000 ); if( raw[0] == '6' ) tag.SetGroup( 0x6000 ); CurrentDE.SetGroupXX( true ); } } else if( element == *current ) { unsigned int v; const char *raw = *(current+1); int r = sscanf(raw, "%04x", &v); assert( r == 1 ); assert( v <= 0xFFFF ); char sv[4+1]; r = sprintf(sv, "%04x", v); assert( r == 4 ); if( strncmp(raw, sv, 4) == 0 ) { tag.SetElement( v ); } else { assert( raw[0] == '3' && raw[1] == '1' ); tag.SetElement( 0x3100 ); CurrentDE.SetElementXX( true ); } } else if( strvr == *current ) { vr = VR::GetVRTypeFromFile( *(current + 1) ); //assert( vr != VR::INVALID ); } else if( strvm == *current ) { vm = VM::GetVMType( *(current + 1) ); //assert( *(current+1) != '\0' ); //assert( vm != VM::VM0 ); //assert( vm != VM::VM_END ); } else if( retired == *current ) { if( retiredtrue == *(current+1) ) { ret = true; } else if( retiredfalse == *(current+1) ) { ret = false; } else { assert(0); } } else if( version == *current ) { // ?? } else if( strname == *current ) { name = *(current+1); } else { assert(0); } // goes on to the next attribute (need to skip value) ++current; ++current; } // Done ! de = DictEntry(name.c_str(), vr, vm, ret ); } void XMLDictReader::HandleDescription(const char **atts) { assert( ParsingDescription ); assert( *atts == NULL ); assert( Description == "" ); #if 0 DictEntry &de = CurrentDE; const char **current = atts; std::string description; while(*current /*&& current+1*/) { assert( *(current + 1) ); ++current; } // Done ! //de.SetName( description.c_str() ); #endif } void XMLDictReader::StartElement(const char *name, const char **atts) { std::string dict = "dict"; std::string entry = "entry"; std::string description = "description"; // aka name Tag currenttag; //DictEntry currentde("",VR::INVALID,VM::VM0,true); if( dict == name ) { // dict ?? } else if( entry == name ) { HandleEntry(atts); } else if( description == name ) { ParsingDescription = true; // mark that we are processing description element // We need a second pass to fill in the currentde struct: HandleDescription(atts); } else { std::cerr << name << std::endl; assert(0); } } void XMLDictReader::EndElement(const char *name) { std::string entry = "entry"; std::string dict = "dict"; std::string description = "description"; // free form text usually the raw description of tag if( entry == name ) { // Ok currentde is now valid let's insert it into the Dict: DICOMDict.AddDictEntry( CurrentTag, CurrentDE); } else if( description == name ) { assert( ParsingDescription ); ParsingDescription = false; // TODO: do something with description ?? Description = ""; } else if ( dict == name ) { } else { assert(0); } } void XMLDictReader::CharacterDataHandler(const char *data, int length) { if( ParsingDescription ) { std::string name( data, length); assert( length == strlen( name.c_str() ) ); Description.append( name ); } } } GDCM-3.0.10/Source/InformationObjectDefinition/gdcmXMLDictReader.h000066400000000000000000000026221412732066400245740ustar00rootroot00000000000000/*========================================================================= 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 GDCMXMLDICTREADER_H #define GDCMXMLDICTREADER_H #include "gdcmTableReader.h" #include "gdcmDict.h" #include "gdcmDictEntry.h" #include "gdcmTag.h" namespace gdcm { /** * \brief Class for representing a XMLDictReader * \note bla * Will read the DICOMV3.xml file */ class GDCM_EXPORT XMLDictReader : public TableReader { public: XMLDictReader(); ~XMLDictReader() {} void StartElement(const char *name, const char **atts); void EndElement(const char *name); void CharacterDataHandler(const char *data, int length); const Dict & GetDict() { return DICOMDict; } protected: void HandleEntry(const char **atts); void HandleDescription(const char **atts); private: Dict DICOMDict; Tag CurrentTag; DictEntry CurrentDE; bool ParsingDescription; std::string Description; }; } // end namespace gdcm #endif //GDCMXMLDICTREADER_H GDCM-3.0.10/Source/InformationObjectDefinition/gdcmXMLPrivateDictReader.cxx000066400000000000000000000142421412732066400265030ustar00rootroot00000000000000/*========================================================================= 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 "gdcmXMLPrivateDictReader.h" #include "gdcmDict.h" #include #include // abort namespace gdcm { XMLPrivateDictReader::XMLPrivateDictReader():ParsingDescription(false),Description() { } void XMLPrivateDictReader::HandleEntry(const char **atts) { assert( !ParsingDescription ); std::string name; std::string owner; VR vr; VM::VMType vm = VM::VM0; bool ret = false; PrivateTag &tag = CurrentTag; DictEntry &de = CurrentDE; int i = 0; const char **current = atts; // Supported attributes: std::string group = "group"; std::string element = "element"; std::string strvr = "vr"; std::string strvm = "vm"; std::string retired = "retired"; std::string retiredtrue = "true"; std::string retiredfalse = "false"; std::string version = "version"; std::string strowner = "owner"; std::string strname = "name"; while(*current /*&& current+1*/) { assert( *(current + 1) ); if( group == *current ) { unsigned int v; const char *raw = *(current+1); int r = sscanf(raw, "%04x", &v); assert( r == 1 ); assert( v <= 0xFFFF ); char sv[4+1]; r = sprintf(sv, "%04x", v); assert( r == 4 ); if( strncmp(raw, sv, 4) == 0 ) // GroupXX { tag.SetGroup( v ); } else { assert( (raw[0] == '5' && raw[1] == '0') || (raw[0] == '6' && raw[1] == '0') || (raw[0] == '7' && raw[1] == '0') ); if( raw[0] == '5' ) tag.SetGroup( 0x5000 ); else if( raw[0] == '6' ) tag.SetGroup( 0x6000 ); else if( raw[0] == '7' ) tag.SetGroup( 0x7000 ); else assert(0); CurrentDE.SetGroupXX( true ); } } else if( element == *current ) { const char *raw = *(current+1); assert( (raw[0] == 'x' && raw[1] == 'x' ) || (raw[2] == 'x' && raw[3] == 'x') ); if (raw[2] == 'x' && raw[3] == 'x') { if( raw[0] == '0' && raw[1] == '0' ) { tag.SetElement( 0x0000 ); CurrentDE.SetElementXX( true ); } else if( raw[0] == '1' && raw[1] == '0' ) { tag.SetElement( 0x1000 ); CurrentDE.SetElementXX( true ); } else { assert(0); // FIXME } } else { unsigned int v; int r = sscanf(raw+2, "%02x", &v); assert( r == 1 ); assert( v <= 0xFF ); char sv[4+1]; r = sprintf(sv, "xx%02x", v); assert( r == 4 ); if( strncmp(raw, sv, 4) == 0 ) { tag.SetElement( v ); } else { assert(0); } } } else if( strvr == *current ) { vr = VR::GetVRTypeFromFile( *(current + 1) ); //assert( vr != VR::INVALID ); } else if( strvm == *current ) { vm = VM::GetVMType( *(current + 1) ); //assert( *(current+1) != '\0' ); //assert( vm != VM::VM0 ); //assert( vm != VM::VM_END ); } else if( retired == *current ) { if( retiredtrue == *(current+1) ) { ret = true; } else if( retiredfalse == *(current+1) ) { ret = false; } else { assert(0); } } else if( version == *current ) { // ?? } else if( strowner == *current ) { owner = *(current+1); } else if( strname == *current ) { name = *(current+1); } else { assert(0); } // goes on to the next attribute (need to skip value) ++current; ++current; } // Done ! de = DictEntry(name.c_str(), vr, vm, ret ); tag.SetOwner( owner.c_str() ); } void XMLPrivateDictReader::HandleDescription(const char **atts) { assert( ParsingDescription ); assert( *atts == NULL ); assert( Description == "" ); #if 0 DictEntry &de = CurrentDE; const char **current = atts; std::string description; while(*current /*&& current+1*/) { assert( *(current + 1) ); ++current; } // Done ! //de.SetName( description.c_str() ); #endif } void XMLPrivateDictReader::StartElement(const char *name, const char **atts) { std::string dict = "dict"; std::string entry = "entry"; std::string description = "description"; // aka name Tag currenttag; //DictEntry currentde("",VR::INVALID,VM::VM0,true); if( dict == name ) { // dict ?? } else if( entry == name ) { HandleEntry(atts); } else if( description == name ) { ParsingDescription = true; // mark that we are processing description element // We need a second pass to fill in the currentde struct: HandleDescription(atts); } else { std::cerr << name << std::endl; assert(0); } } void XMLPrivateDictReader::EndElement(const char *name) { std::string entry = "entry"; std::string dict = "dict"; std::string description = "description"; // free form text usually the raw description of tag if( entry == name ) { // Ok currentde is now valid let's insert it into the Dict: PDict.AddDictEntry( CurrentTag, CurrentDE); } else if( description == name ) { assert( ParsingDescription ); ParsingDescription = false; // TODO: do something with description ?? // // Invalidate Description ? Description = ""; } else if ( dict == name ) { } else { assert(0); } } void XMLPrivateDictReader::CharacterDataHandler(const char *data, int length) { if( ParsingDescription ) { std::string name( data, length); assert( length == strlen( name.c_str() ) ); Description.append( name ); } } } GDCM-3.0.10/Source/InformationObjectDefinition/gdcmXMLPrivateDictReader.h000066400000000000000000000027271412732066400261350ustar00rootroot00000000000000/*========================================================================= 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 GDCMXMLPRIVATEDICTREADER_H #define GDCMXMLPRIVATEDICTREADER_H #include "gdcmTableReader.h" #include "gdcmDict.h" #include "gdcmDictEntry.h" #include "gdcmTag.h" namespace gdcm { /** * \brief Class for representing a XMLPrivateDictReader * \note bla * Will read the Private.xml file */ class GDCM_EXPORT XMLPrivateDictReader : public TableReader { public: XMLPrivateDictReader(); ~XMLPrivateDictReader() {} void StartElement(const char *name, const char **atts); void EndElement(const char *name); void CharacterDataHandler(const char *data, int length); const PrivateDict & GetPrivateDict() { return PDict; } protected: void HandleEntry(const char **atts); void HandleDescription(const char **atts); private: PrivateDict PDict; PrivateTag CurrentTag; DictEntry CurrentDE; bool ParsingDescription; std::string Description; }; } // end namespace gdcm #endif //GDCMXMLPRIVATEDICTREADER_H GDCM-3.0.10/Source/InformationObjectDefinition/getelements.xsl000066400000000000000000000041021412732066400242400ustar00rootroot00000000000000 (,)

Tag Name Type Description
GDCM-3.0.10/Source/InformationObjectDefinition/ma2html.xsl000066400000000000000000000041021412732066400232700ustar00rootroot00000000000000 (,)

Tag Name Type Description
GDCM-3.0.10/Source/InformationObjectDefinition/ma2pdf.xsl000066400000000000000000000133411412732066400231020ustar00rootroot00000000000000 PS 3.3-2007 Page - Standard - Name Tag Type Description ( , ) GDCM-3.0.10/Source/MediaStorageAndFileFormat/000077500000000000000000000000001412732066400205125ustar00rootroot00000000000000GDCM-3.0.10/Source/MediaStorageAndFileFormat/CMakeLists.txt000066400000000000000000000147211412732066400232570ustar00rootroot00000000000000# Define the srcs for Media Storage And FileFormat # MSFF set(MSFF_SRCS gdcmEmptyMaskGenerator.cxx gdcmEquipmentManufacturer.cxx gdcmFileStreamer.cxx gdcmJSON.cxx gdcmFileChangeTransferSyntax.cxx gdcmAnonymizer.cxx gdcmFileAnonymizer.cxx gdcmIconImageFilter.cxx gdcmIconImageGenerator.cxx gdcmDICOMDIRGenerator.cxx gdcmSpacing.cxx gdcmFileExplicitFilter.cxx gdcmFileDerivation.cxx gdcmImageFragmentSplitter.cxx gdcmTagPath.cxx gdcmSimpleSubjectWatcher.cxx gdcmAnonymizeEvent.cxx gdcmPixmap.cxx gdcmBitmap.cxx gdcmRescaler.cxx gdcmImageToImageFilter.cxx gdcmBitmapToBitmapFilter.cxx gdcmPixmapToPixmapFilter.cxx gdcmImageChangeTransferSyntax.cxx gdcmImageApplyLookupTable.cxx gdcmFileDecompressLookupTable.cxx gdcmOrientation.cxx gdcmDataSetHelper.cxx gdcmImageChangePlanarConfiguration.cxx gdcmImageChangePhotometricInterpretation.cxx gdcmDirectionCosines.cxx gdcmSorter.cxx gdcmSerieHelper.cxx gdcmIPPSorter.cxx gdcmApplicationEntity.cxx gdcmDICOMDIR.cxx gdcmSpectroscopy.cxx gdcmEncapsulatedDocument.cxx gdcmSplitMosaicFilter.cxx gdcmFiducials.cxx gdcmWaveform.cxx gdcmPersonName.cxx gdcmIconImage.cxx gdcmUIDGenerator.cxx gdcmUUIDGenerator.cxx gdcmPrinter.cxx gdcmDictPrinter.cxx gdcmXMLPrinter.cxx gdcmScanner.cxx gdcmStrictScanner.cxx gdcmPixmapReader.cxx gdcmImageReader.cxx gdcmPixmapWriter.cxx gdcmImageWriter.cxx gdcmStringFilter.cxx gdcmImageHelper.cxx gdcmValidate.cxx gdcmDumper.cxx gdcmImage.cxx gdcmImageConverter.cxx gdcmImageCodec.cxx gdcmJPEG12Codec.cxx gdcmRLECodec.cxx gdcmPDFCodec.cxx gdcmAudioCodec.cxx gdcmJPEG16Codec.cxx gdcmJPEGLSCodec.cxx gdcmJPEG8Codec.cxx gdcmJPEGCodec.cxx gdcmPVRGCodec.cxx gdcmKAKADUCodec.cxx gdcmPNMCodec.cxx gdcmPGXCodec.cxx gdcmRAWCodec.cxx gdcmLookupTable.cxx gdcmOverlay.cxx gdcmCurve.cxx gdcmPhotometricInterpretation.cxx gdcmPixelFormat.cxx gdcmSegmentedPaletteColorLookupTable.cxx gdcmStreamImageReader.cxx gdcmImageRegionReader.cxx #gdcmStreamImageWriter.cxx gdcmDirectoryHelper.cxx gdcmSegment.cxx gdcmSurface.cxx gdcmMeshPrimitive.cxx gdcmSegmentWriter.cxx gdcmSurfaceWriter.cxx gdcmSegmentReader.cxx gdcmSurfaceReader.cxx gdcmSurfaceHelper.cxx gdcmSegmentHelper.cxx gdcmJPEG2000Codec.cxx ) list(APPEND MSFF_SRCS ${GDCM_SOURCE_DIR}/Utilities/gdcmrle/rle.cxx ${GDCM_SOURCE_DIR}/Utilities/gdcmrle/info.cxx ${GDCM_SOURCE_DIR}/Utilities/gdcmrle/io.cxx ) # Do the proper thing when building static...if only there was configured # headers or def files instead if(NOT BUILD_SHARED_LIBS) set_source_files_properties(gdcmJPEG2000Codec.cxx PROPERTIES COMPILE_FLAGS -DOPJ_STATIC ) set_source_files_properties(gdcmJPEGLSCodec.cxx PROPERTIES COMPILE_DEFINITIONS CHARLS_STATIC ) else() set_source_files_properties(gdcmJPEGLSCodec.cxx PROPERTIES COMPILE_FLAGS -DCHARLS_DLL ) endif() # Add the include paths include_directories( "${GDCM_SOURCE_DIR}/Source/Common" "${GDCM_BINARY_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition" "${GDCM_SOURCE_DIR}/Source/DataDictionary" "${GDCM_SOURCE_DIR}/Source/InformationObjectDefinition" ${CMAKE_CURRENT_SOURCE_DIR} # FIXME: "${GDCM_SOURCE_DIR}/Utilities" "${GDCM_BINARY_DIR}/Utilities" ) # CharLS if(GDCM_USE_JPEGLS) #include_directories("${GDCM_BINARY_DIR}/Utilities/gdcmcharls") endif() if(GDCM_USE_SYSTEM_CHARLS) include_directories(${CHARLS_INCLUDE_DIRS} ) else() include_directories( "${GDCM_BINARY_DIR}/Utilities/gdcmcharls" ) endif() if(GDCM_USE_SYSTEM_OPENJPEG) include_directories(${OPENJPEG_INCLUDE_DIRS} ) else() include_directories( "${GDCM_BINARY_DIR}/Utilities/gdcmopenjpeg" "${GDCM_BINARY_DIR}/Utilities/gdcmopenjpeg/src/lib/openjp2" ) endif() if(GDCM_USE_SYSTEM_LJPEG) include_directories(${LJPEG_INCLUDE_DIRS} ) endif() if(NOT GDCM_USE_SYSTEM_ZLIB) include_directories( "${GDCM_BINARY_DIR}/Utilities/gdcmzlib" ) endif() if(GDCM_USE_SYSTEM_UUID) include_directories( ${UUID_INCLUDE_DIR} ) set(GDCMUUID ${UUID_LIBRARIES}) else() include_directories( "${GDCM_BINARY_DIR}/Utilities/gdcmuuid" # uuid_mangle.h ) set(GDCMUUID gdcmuuid) endif() if(GDCM_USE_SYSTEM_JSON) include_directories( ${JSON_INCLUDE_DIRS} ) endif() add_library(gdcmMSFF ${MSFF_SRCS}) # gdcmPVRGCodec calls gdcmjpeg if(GDCM_USE_PVRG) if(NOT GDCM_USE_SYSTEM_PVRG) add_dependencies(gdcmMSFF gdcmjpeg) endif() endif() # main libs: target_link_libraries(gdcmMSFF LINK_PUBLIC gdcmIOD gdcmDSED gdcmDICT) target_link_libraries(gdcmMSFF LINK_PRIVATE ${GDCM_LJPEG_LIBRARIES} ${GDCM_OPENJPEG_LIBRARIES}) if(GDCM_USE_JPEGLS) target_link_libraries(gdcmMSFF LINK_PRIVATE ${GDCM_CHARLS_LIBRARIES}) endif() if(CMAKE_COMPILER_IS_GNUCXX AND MINGW) # I am getting: # CMakeFiles/gdcmMSFF.dir/gdcmScanner.obj(.text$_ZN4gdcm6ReaderC1Ev[gdcm::Reader::Reader()]+0x3a):gdcmScanner.cxx: variable 'vtable for gdcm::Reader' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details. # CMakeFiles/gdcmMSFF.dir/gdcmImageReader.obj(.text$_ZN4gdcm6ReaderC2Ev[gdcm::Reader::Reader()]+0x3a):gdcmImageReader.cxx: variable 'vtable for gdcm::Reader' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details. # CMakeFiles/gdcmMSFF.dir/gdcmImageWriter.obj(.text$_ZN4gdcm6WriterC2Ev[gdcm::Writer::Writer()]+0x3a):gdcmImageWriter.cxx: variable 'vtable for gdcm::Writer' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details. set_target_properties(gdcmMSFF PROPERTIES LINK_FLAGS "-Wl,--enable-runtime-pseudo-reloc") endif() #if(HAVE_UUIDCREATE) if(WIN32) # For UuidCreate # http://msdn.microsoft.com/en-us/library/aa379205(VS.85).aspx target_link_libraries(gdcmMSFF LINK_PRIVATE rpcrt4) #endif() else() target_link_libraries(gdcmMSFF LINK_PRIVATE ${GDCMUUID}) endif() if(GDCM_USE_SYSTEM_JSON) target_link_libraries(gdcmMSFF LINK_PRIVATE ${JSON_LIBRARIES}) endif() # handling of static lib within shared is a mess: #target_link_libraries(gdcmMSFF gdcmrle) set_target_properties(gdcmMSFF PROPERTIES ${GDCM_LIBRARY_PROPERTIES}) # libs install_library(gdcmMSFF) # PDB install_pdb(gdcmMSFF) # include files install_includes("*.h" "*.txx") GDCM-3.0.10/Source/MediaStorageAndFileFormat/FileMetaInformation.txt000066400000000000000000000071401412732066400251510ustar00rootroot00000000000000PS 3.10-2006 Page 21 Attribute Name Tag Type Attribute Description File Preamble No Tag or Length Fields 1 A fixed 128 byte field available for Application Profile or implementation specified use. If not used by an Application Profile or a specific implementation all bytes shall be set to 00H. File-set Readers or Updaters shall not rely on the content of this Preamble to determine that this File is or is not a DICOM File. DICOM Prefix No Tag or Length Fields 1 Four bytes containing the character string "DICM". This Prefix is intended to be used to recognize that this File is or not a DICOM File. Group Length (0002,0000) 1 Number of bytes following this File Meta Element (end of the Value field) up to and including the last File Meta Element of the Group 2 File Meta Information File Meta Information Version (0002,0001) 1 This is a two byte field where each bit identifies a version of this File Meta Information header. In version 1 the first byte value is 00H and the second value byte value is 01H. Implementations reading Files with Meta Information where this attribute has bit 0 (lsb) of the second byte set to 1 may interpret the File Meta Information as specified in this version of PS 3.10. All other bits shall not be checked. Note: A bit field where each bit identifies a version, allows explicit indication of the support of multiple previous versions. Future versions of the File Meta Information that can be read by version 1 readers will have bit 0 of the second byte set to 1 Media Storage SOP Class UID (0002,0002) 1 Uniquely identifies the SOP Class associated with the Data Set. SOP Class UIDs allowed for media storage are specified in PS 3.4 of the DICOM Standard - Media Storage Application Profiles. Media Storage SOP Instance UID (0002,0003) 1 Uniquely identifies the SOP Instance associated with the Data Set placed in the file and following the File Meta Information. Transfer Syntax UID (0002,0010) 1 Uniquely identifies the Transfer Syntax used to encode the following Data Set. This Transfer Syntax does not apply to the File Meta Information. Note: It is recommended to use one of the DICOM Transfer Syntaxes supporting explicit Value Representation encoding to facilitate interpretation of File Meta Element Values. JPIP Referenced Pixel Data Transfer Syntaxes are not used. (See PS 3.5 of the DICOM Standard). Implementation Class UID (0002,0012) 1 Uniquely identifies the implementation which wrote this file and its content. It provides an unambiguous identification of the type of implementation which last wrote the file in the event of interchange problems. It follows the same policies as defined by PS 3.7 of the DICOM Standard (association negotiation). Implementation Version Name (0002,0013) 3 Identifies a version for an Implementation Class UID (0002,0012) using up to 16 characters of the repertoire identified in Section 8.5. It follows the same policies as defined by PS 3.7 of the DICOM Standard (association PS 3.10-2006 Page 22 negotiation). Source Application Entity Title (0002,0016) 3 The DICOM Application Entity (AE) Title of the AE which wrote this file's content (or last updated it). If used, it allows the tracing of the source of errors in the event of media interchange problems. The policies associated with AE Titles are the same as those defined in PS 3.8 of the DICOM Standard. Private Information Creator UID (0002,0100) 3 The UID of the creator of the private information (0002,0102). Private Information (0002,0102) 1C Contains Private Information placed in the File Meta Information. The creator shall be identified in (0002,0100). Required if Private Information Creator UID (0002,0100) is present. GDCM-3.0.10/Source/MediaStorageAndFileFormat/README.txt000066400000000000000000000144541412732066400222200ustar00rootroot00000000000000Part 3.8 PS 3.10-2006 Page 10 3.3 PRESENTATION SERVICE DEFINITIONS This Part of the Standard makes use of the following terms defined in ISO 8822: a. Abstract Syntax; b. Abstract Syntax Name. 3.4 DICOM INTRODUCTION AND OVERVIEW DEFINITIONS This Part of the Standard makes use of the following terms defined in PS 3.1 of the DICOM Standard: - Attribute. 3.5 DICOM INFORMATION OBJECT DEFINITIONS This Part of the Standard makes use of the following terms defined in PS 3.3 of the DICOM Standard: a. Information Object Definition. 3.6 DICOM DATA STRUCTURE AND ENCODING DEFINITIONS This Part of the Standard makes use of the following terms defined in PS 3.5 of the DICOM Standard: a. Data Element; b. Data Set; c. Data Element Type; d. Value; e. Value Multiplicity; f. Value Representation; 3.7 DICOM MESSAGE EXCHANGE DEFINITIONS This Part of the Standard makes use of the following terms defined in PS 3.7 of the DICOM Standard: a. Service Object Pair (SOP) Class; b. Service Object Pair (SOP) Instance; c. Implementation Class UID. 3.8 DICOM MEDIA STORAGE AND FILE FORMAT DEFINITIONS The following definitions are commonly used in this Part of the Standard: Application Profile: A Media Storage Application Profile defines a selection of choices at the various layers of the DICOM Media Storage Model which are applicable to a specific need or context in which the media interchange is intended to be performed. DICOM File Service: The DICOM File Service specifies a minimum abstract view of files to be provided by the Media Format Layer. Constraining access to the content of files by the Application Entities through such a DICOM File Service boundary ensures Media Format and Physical Media independence. DICOM File: A DICOM File is a File with a content formatted according to the requirements of this Part of the DICOM Standard. In particular such files shall contain, the File Meta Information and a properly formatted Data Set. PS 3.10-2006 Page 11 DICOMDIR File: A unique and mandatory DICOM File within a File-set which contains the Media Storage Directory SOP Class. This File is given a single component File ID, DICOMDIR. File: A File is an ordered string of zero or more bytes, where the first byte is at the beginning of the file and the last byte at the end of the File. Files are identified by a unique File ID and may by written, read and/or deleted. File ID: Files are identified by a File ID which is unique within the context of the File-set they belong to. A set of ordered File ID Components (up to a maximum of eight) forms a File ID. File ID Component: A string of one to eight characters of a defined character set. File Meta Information: The File Meta Information includes identifying information on the encapsulated Data Set. It is a mandatory header at the beginning of every DICOM File. 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. File-set Creator: An Application Entity that creates the DICOMDIR File (see section 8.6) and zero or more DICOM Files. File-set Reader: An Application Entity that accesses one or more files in a File-set. File-set Updater: An Application Entity that accesses Files, creates additional Files, or deletes existing Files in a File-set. A File-set Updater makes the appropriate alterations to the DICOMDIR file reflecting the additions or deletions. DICOM File Format: The DICOM File Format provides a means to encapsulate in a File the Data Set representing a SOP Instance related to a DICOM Information Object. Media Format: Data structures and associated policies which organizes the bit streams defined by the Physical Media format into data file structures and associated file directories. Media Storage Model: The DICOM Media Storage Model pertains to the data structures used at different layers to achieve interoperability through media interchange. Media Storage Services: DICOM Media Storage Services define a set of operations with media that facilitate storage to and retrieval from the media of DICOM SOP Instances. Physical Media: A piece of material with recording capabilities for streams of bits. Characteristics of a Physical Media include form factor, mechanical characteristics, recording properties and rules for recording and organizing bit streams in accessible structures Secure DICOM File: A DICOM File that is encapsulated with the Cryptographic Message Syntax specified in RFC 2630. Secure File-set: A File-set in which all DICOM Files are Secure DICOM Files. Secure Media Storage Application Profile: A DICOM Media Storage Application Profile that requires a Secure File-set. PS 3.10-2006 Page 12 4 Symbols and Abbreviations The following symbols and abbreviations are used in this Part of the Standard. ACC American College of Cardiology ACR American College of Radiology ASCII American Standard Code for Information Interchange AE Application Entity ANSI American National Standards Institute CEN/TC/251 Comite Europeen de Normalisation - Technical Committee 251 - Medical Informatics DICOM Digital Imaging and Communications in Medicine FSC File-set Creator FSR File-set Reader FSU File-set Updater HL7 Health Level 7 HTML Hypertext Transfer Markup Language IEEE Institute of Electrical and Electronics Engineers ISO International Standards Organization ID Identifier IOD Information Object Definition JIRA Japan Industries Association of Radiation Apparatus MIME Multipurpose Internet Mail Extensions NEMA National Electrical Manufacturers Association OSI Open Systems Interconnection SOP Service-Object Pair TCP/IP Transmission Control Protocol/Internet Protocol UID Unique Identifier VR Value Representation XML Extensible Markup Language 5 Conventions Words are capitalized in this document to help the reader understand that these words have been previously defined in Section 3 of this document and are to be interpreted with that meaning. A Tag is represented as (gggg,eeee), where gggg equates to the Group Number and eeee equates to the Element Number within that Group. Tags are represented in hexadecimal notation as specified in PS 3.5 of the DICOM Standard.. Attributes of File Meta Information are assigned a Type which indicates if a specific Attribute is required depending on the Media Storage Services. The following Type designations are derived from the PS 3.5 designations but take into account the Media Storage environment: GDCM-3.0.10/Source/MediaStorageAndFileFormat/TODO.txt000066400000000000000000000025601412732066400220230ustar00rootroot00000000000000ISO_IR 100 : 28591 : Latin Alphabet No. 1 Unextended ISO_IR 101 : 28592 : Latin Alphabet No. 2 Unextended ISO_IR 109 : 28593 : Latin Alphabet No. 3 Unextended ISO_IR 110 : 28594 : Latin Alphabet No. 4 Unextended ISO_IR 144 : 28595 : Cyrillic Unextended ISO_IR 127 : 28596 : Arabic Unextended ISO_IR 126 : 28597 : Greek Unextended ISO_IR 138 : 28598 : Hebrew Unextended ISO_IR 148 : 28599 : Latin Alphabet No. 5 (Turkish) Unextended ISO_IR 13 : 932 : JIS X 0201 (Shift JIS) Unextended ISO_IR 166 : 874 : TIS 620-2533 (Thai) Unextended ISO_IR 192 : 65001 : Unicode in UTF-8 ISO 2022 IR 6 : 28591 : Default ISO 2022 IR 100 : 28591 : Latin Alphabet No. 1 Extended ISO 2022 IR 101 : 28592 : Latin Alphabet No. 2 Extended ISO 2022 IR 109 : 28593 : Latin Alphabet No. 3 Extended ISO 2022 IR 110 : 28594 : Latin Alphabet No. 4 Extended ISO 2022 IR 144 : 28595 : Cyrillic Extended ISO 2022 IR 127 : 28596 : Arabic Extended ISO 2022 IR 126 : 28597 : Greek Extended ISO 2022 IR 138 : 28598 : Hebrew Extended ISO 2022 IR 148 : 28599 : Latin Alphabet No. 5 (Turkish) Extended ISO 2022 IR 13 : 50222 : JIS X 0201 (Shift JIS) Extended ISO 2022 IR 166 : 874 : TIS 620-2533 (Thai) Extended ISO 2022 IR 87 : 50222 : JIS X 0208 (Kanji) Extended ISO 2022 IR 159 : 50222 : JIS X 0212 (Kanji) Extended ISO 2022 IR 149 : 20949 : KS X 1001 (Hangul and Hanja) Extended GB18030 : 54936 : Chinese (Simplified) Extended GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmAnonymizeEvent.cxx000066400000000000000000000011761412732066400250510ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAnonymizeEvent.h" namespace gdcm { } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmAnonymizeEvent.h000066400000000000000000000030241412732066400244700ustar00rootroot00000000000000/*========================================================================= 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 GDCMANONYMIZEEVENT_H #define GDCMANONYMIZEEVENT_H #include "gdcmEvent.h" #include "gdcmTag.h" namespace gdcm { /** * \brief AnonymizeEvent * \details Special type of event triggered during the Anonymization process * * \see Anonymizer */ class AnonymizeEvent : public AnyEvent { public: typedef AnonymizeEvent Self; typedef AnyEvent Superclass; AnonymizeEvent(Tag const &tag = 0):m_Tag(tag) {} ~AnonymizeEvent() override = default; AnonymizeEvent(const Self&s) : AnyEvent(s){}; void operator=(const Self&) = delete; const char * GetEventName() const override { return "AnonymizeEvent"; } bool CheckEvent(const ::gdcm::Event* e) const override { return (dynamic_cast(e) == nullptr ? false : true) ; } ::gdcm::Event* MakeObject() const override { return new Self; } void SetTag(const Tag& t ) { m_Tag = t; } Tag const & GetTag() const { return m_Tag; } private: Tag m_Tag; }; } // end namespace gdcm #endif //GDCMANONYMIZEEVENT_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmAnonymizer.cxx000066400000000000000000001111601412732066400242240ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAnonymizer.h" #include "gdcmGlobal.h" #include "gdcmStringFilter.h" #include "gdcmSequenceOfItems.h" #include "gdcmExplicitDataElement.h" #include "gdcmSwapper.h" #include "gdcmDataSetHelper.h" #include "gdcmUIDGenerator.h" #include "gdcmAttribute.h" #include "gdcmDummyValueGenerator.h" #include "gdcmDicts.h" #include "gdcmType.h" #include "gdcmDefs.h" #include "gdcmCryptographicMessageSyntax.h" #include "gdcmEvent.h" #include "gdcmAnonymizeEvent.h" namespace gdcm { // PS 3.15 - 2008 // Table E.1-1 // BALCPA static Tag BasicApplicationLevelConfidentialityProfileAttributes[] = { // Attribute Name Tag /* Instance Creator UID */ Tag(0x0008,0x0014), /* SOP Instance UID */ Tag(0x0008,0x0018), /* Accession Number */ Tag(0x0008,0x0050), /* Institution Name */ Tag(0x0008,0x0080), /* Institution Address */ Tag(0x0008,0x0081), /* Referring Physician's Name */ Tag(0x0008,0x0090), /* Referring Physician's Address */ Tag(0x0008,0x0092), /* Referring Physician's Telephone Numbers */ Tag(0x0008,0x0094), /* Station Name */ Tag(0x0008,0x1010), /* Study Description */ Tag(0x0008,0x1030), /* Series Description */ Tag(0x0008,0x103E), /* Institutional Department Name */ Tag(0x0008,0x1040), /* Physician(s) of Record */ Tag(0x0008,0x1048), /* Performing Physicians' Name */ Tag(0x0008,0x1050), /* Name of Physician(s) Reading Study */ Tag(0x0008,0x1060), /* Operators' Name */ Tag(0x0008,0x1070), /* Admitting Diagnoses Description */ Tag(0x0008,0x1080), /* Referenced SOP Instance UID */ Tag(0x0008,0x1155), /* Derivation Description */ Tag(0x0008,0x2111), /* Patient's Name */ Tag(0x0010,0x0010), /* Patient ID */ Tag(0x0010,0x0020), /* Patient's Birth Date */ Tag(0x0010,0x0030), /* Patient's Birth Time */ Tag(0x0010,0x0032), /* Patient's Sex */ Tag(0x0010,0x0040), /* Other Patient Ids */ Tag(0x0010,0x1000), /* Other Patient Names */ Tag(0x0010,0x1001), /* Patient's Age */ Tag(0x0010,0x1010), /* Patient's Size */ Tag(0x0010,0x1020), /* Patient's Weight */ Tag(0x0010,0x1030), /* Medical Record Locator */ Tag(0x0010,0x1090), /* Ethnic Group */ Tag(0x0010,0x2160), /* Occupation */ Tag(0x0010,0x2180), /* Additional Patient's History */ Tag(0x0010,0x21B0), /* Patient Comments */ Tag(0x0010,0x4000), /* Device Serial Number */ Tag(0x0018,0x1000), /* Protocol Name */ Tag(0x0018,0x1030), /* Study Instance UID */ Tag(0x0020,0x000D), /* Series Instance UID */ Tag(0x0020,0x000E), /* Study ID */ Tag(0x0020,0x0010), /* Frame of Reference UID */ Tag(0x0020,0x0052), /* Synchronization Frame of Reference UID */ Tag(0x0020,0x0200), /* Image Comments */ Tag(0x0020,0x4000), /* Request Attributes Sequence */ Tag(0x0040,0x0275), /* UID */ Tag(0x0040,0xA124), /* Content Sequence */ Tag(0x0040,0xA730), /* Storage Media File-set UID */ Tag(0x0088,0x0140), /* Referenced Frame of Reference UID */ Tag(0x3006,0x0024), /* Related Frame of Reference UID */ Tag(0x3006,0x00C2) }; Anonymizer::~Anonymizer() = default; bool Anonymizer::Empty( Tag const &t) { // There is a secret code path to make it work for VR::SQ since operation is just 'make empty' return Replace(t, "", 0); } bool Anonymizer::Remove( Tag const &t ) { DataSet &ds = F->GetDataSet(); if(ds.FindDataElement(t)) return ds.Remove( t ) == 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 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( t, value, len ); } bool Anonymizer::Replace( Tag const &t, const char *value, VL const & vl ) { if( t.GetGroup() < 0x0008 ) return false; static const Global &g = GlobalInstance; static const Dicts &dicts = g.GetDicts(); DataSet &ds = F->GetDataSet(); // Let's do the private tag: bool ret = false; if ( t.IsPrivate() && !t.IsPrivateCreator() ) { // Only one operation is allowed: making a private tag empty ... if ( vl == 0 ) { if( ds.FindDataElement( t ) ) { DataElement de ( ds.GetDataElement(t) ); if ( de.GetVR() != VR::INVALID ) { if( de.GetVR() == VR::SQ ) { if( vl == 0 && value && *value == 0 ) { DataElement de2( t ); de2.SetVR( VR::SQ ); ds.Replace( de2 ); return true; } gdcmDebugMacro( "Cannot replace a VR:SQ" ); return false; } } de.SetByteValue( "", vl ); ds.Insert( de ); ret = true; } else { // TODO assert( 0 && "TODO" ); ret = false; } } } else { // Ok this is a public element assert( t.IsPublic() || t.IsPrivateCreator() ); const DictEntry &dictentry = dicts.GetDictEntry(t); if ( dictentry.GetVR() == VR::INVALID || dictentry.GetVR() == VR::UN || dictentry.GetVR() == VR::SQ ) { // Make the VR::SQ empty if( dictentry.GetVR() == VR::SQ && vl == 0 && value && *value == 0 ) { DataElement de( t ); de.SetVR( VR::SQ ); //de.SetByteValue( "", 0 ); ds.Replace( de ); } else { // Let's give up ! gdcmWarningMacro( "Cannot process tag: " << t << " with vr: " << dictentry.GetVR() ); } //ret = false; } else if ( dictentry.GetVR() & VR::VRBINARY ) { if( vl == 0 ) { DataElement de( t ); if( ds.FindDataElement( t ) ) { de.SetVR( ds.GetDataElement(t).GetVR() ); } else { de.SetVR( dictentry.GetVR() ); } de.SetByteValue( "", 0 ); ds.Replace( de ); ret = true; } else { gdcmWarningMacro( "You need to explicitly specify the length for this type of vr: " << dictentry.GetVR() ); ret = false; } #if 0 StringFilter sf; sf.SetFile( *F ); std::string s = sf.FromString(t, value, vl); DataElement de( t ); if( ds.FindDataElement( t ) ) { de.SetVR( ds.GetDataElement(t).GetVR() ); } else { de.SetVR( dictentry.GetVR() ); } de.SetByteValue( s.c_str(), s.size() ); ds.Replace( de ); ret = true; #endif } else { // vr from dict seems to be ascii, so it seems reasonable to write a ByteValue here: assert( dictentry.GetVR() & VR::VRASCII ); if( value ) { std::string padded( value, vl ); // All ASCII VR needs to be padded with a space if( vl.IsOdd() ) { if( dictentry.GetVR() == VR::UI ) { // \0 is automatically added when using a ByteValue } else { padded += " "; } } // Hum, we could have cases where a public element would not be known, in which case // it is a good idea to first check for the VR as found in the file: DataElement de( t ); if( ds.FindDataElement( t ) ) { de.SetVR( ds.GetDataElement(t).GetVR() ); } else { de.SetVR( dictentry.GetVR() ); } const VL::Type paddedSize = (VL::Type) padded.size();//casting to avoid size_t warning on 64 de.SetByteValue( padded.c_str(), paddedSize ); ds.Replace( de ); ret = true; } } } return ret; } static bool Anonymizer_RemoveRetired(File const &file, DataSet &ds) { static const Global &g = GlobalInstance; static const Dicts &dicts = g.GetDicts(); static const Dict &pubdict = dicts.GetPublicDict(); DataSet::Iterator it = ds.Begin(); for( ; it != ds.End(); ) { const DataElement &de1 = *it; // std::set::erase invalidate iterator, so we need to make a copy first: DataSet::Iterator dup = it; ++it; if( de1.GetTag().IsPublic() ) { const DictEntry &entry = pubdict.GetDictEntry( de1.GetTag() ); if( entry.GetRetired() ) { ds.GetDES().erase(dup); } } else { const DataElement &de = *dup; VR vr = DataSetHelper::ComputeVR(file, ds, de.GetTag() ); if( vr.Compatible(VR::SQ) ) { SmartPointer sq = de.GetValueAsSQ(); if( sq ) { SequenceOfItems::SizeType n = sq->GetNumberOfItems(); for( SequenceOfItems::SizeType i = 1; i <= n; i++) // item starts at 1, not 0 { Item &item = sq->GetItem( i ); DataSet &nested = item.GetNestedDataSet(); Anonymizer_RemoveRetired( file, nested ); } DataElement de_dup = *dup; de_dup.SetValue( *sq ); de_dup.SetVLToUndefined(); // FIXME ds.Replace( de_dup ); } } } } return true; } bool Anonymizer::RemoveRetired() { DataSet &ds = F->GetDataSet(); return Anonymizer_RemoveRetired(*F, ds); } static bool Anonymizer_RemoveGroupLength(File const &file, DataSet &ds) { DataSet::Iterator it = ds.Begin(); for( ; it != ds.End(); ) { const DataElement &de1 = *it; // std::set::erase invalidate iterator, so we need to make a copy first: DataSet::Iterator dup = it; ++it; if( de1.GetTag().IsGroupLength() ) { ds.GetDES().erase(dup); } else { const DataElement &de = *dup; VR vr = DataSetHelper::ComputeVR(file, ds, de.GetTag() ); if( vr.Compatible(VR::SQ) ) { SmartPointer sq = de.GetValueAsSQ(); if( sq ) { SequenceOfItems::SizeType n = sq->GetNumberOfItems(); for( SequenceOfItems::SizeType i = 1; i <= n; i++) // item starts at 1, not 0 { Item &item = sq->GetItem( i ); DataSet &nested = item.GetNestedDataSet(); Anonymizer_RemoveGroupLength( file, nested ); } DataElement de_dup = *dup; de_dup.SetValue( *sq ); de_dup.SetVLToUndefined(); // FIXME ds.Replace( de_dup ); } } } } return true; } bool Anonymizer::RemoveGroupLength() { DataSet &ds = F->GetDataSet(); return Anonymizer_RemoveGroupLength(*F, ds); } static bool Anonymizer_RemovePrivateTags(File const &file, DataSet &ds) { DataSet::Iterator it = ds.Begin(); for( ; it != ds.End(); ) { const DataElement &de1 = *it; // std::set::erase invalidate iterator, so we need to make a copy first: DataSet::Iterator dup = it; ++it; if( de1.GetTag().IsPrivate() ) { ds.GetDES().erase(dup); } else { const DataElement &de = *dup; VR vr = DataSetHelper::ComputeVR(file, ds, de.GetTag() ); if( vr.Compatible(VR::SQ) ) { SmartPointer sq = de.GetValueAsSQ(); if( sq ) { SequenceOfItems::SizeType n = sq->GetNumberOfItems(); for( SequenceOfItems::SizeType i = 1; i <= n; i++) // item starts at 1, not 0 { Item &item = sq->GetItem( i ); DataSet &nested = item.GetNestedDataSet(); Anonymizer_RemovePrivateTags( file, nested ); } DataElement de_dup = *dup; de_dup.SetValue( *sq ); de_dup.SetVLToUndefined(); // FIXME ds.Replace( de_dup ); } } } } return true; } bool Anonymizer::RemovePrivateTags() { DataSet &ds = F->GetDataSet(); return Anonymizer_RemovePrivateTags(*F, ds); } /* * Implementation note: * In order to implement the dummy 'memory' we use a static std::map * this works great but we cannot be thread safe. * In order to be thread safe, we would need to externalize this map generation * maybe using a Scanner do the operation once (Scanner is doing) the merging * automatically... * this is left as an exercise for the reader :) */ bool Anonymizer::BasicApplicationLevelConfidentialityProfile(bool deidentify) { this->InvokeEvent( StartEvent() ); bool ret; if( deidentify ) ret = BasicApplicationLevelConfidentialityProfile1(); else ret = BasicApplicationLevelConfidentialityProfile2(); this->InvokeEvent( EndEvent() ); return ret; } std::vector Anonymizer::GetBasicApplicationLevelConfidentialityProfileAttributes() { static const unsigned int deidSize = sizeof(Tag); static const unsigned int numDeIds = sizeof(BasicApplicationLevelConfidentialityProfileAttributes) / deidSize; static const Tag *start = BasicApplicationLevelConfidentialityProfileAttributes; static const Tag *end = start + numDeIds; return std::vector(start, end); } bool Anonymizer::CheckIfSequenceContainsAttributeToAnonymize(File const &file, SequenceOfItems* sqi) const { static const unsigned int deidSize = sizeof(Tag); static const unsigned int numDeIds = sizeof(BasicApplicationLevelConfidentialityProfileAttributes) / deidSize; static const Tag *start = BasicApplicationLevelConfidentialityProfileAttributes; static const Tag *end = start + numDeIds; bool found = false; for(const Tag *ptr = start ; ptr != end && !found ; ++ptr) { const Tag& tag = *ptr; found = sqi->FindDataElement( tag ); } // ok we can exit. if( found ) return true; // now look into sub-sequence: SequenceOfItems::SizeType n = sqi->GetNumberOfItems(); for( SequenceOfItems::SizeType i = 1; i <= n; i++) // item starts at 1, not 0 { Item &item = sqi->GetItem( i ); DataSet &nested = item.GetNestedDataSet(); DataSet::Iterator it = nested.Begin(); for( ; it != nested.End() && !found; ++it) { const DataElement &de = *it; VR vr = DataSetHelper::ComputeVR(file, nested, de.GetTag() ); SmartPointer sqi2 = nullptr; if( vr == VR::SQ ) { sqi2 = de.GetValueAsSQ(); } if( sqi2 ) { found = CheckIfSequenceContainsAttributeToAnonymize(file, sqi2); } } } return found; } // Implementation note: // This function trigger: // 1 StartEvent // 1 EndEvent // 6 IterationEvent // N AnonymizeEvent (depend on number of tag found) bool Anonymizer::BasicApplicationLevelConfidentialityProfile1() { static const unsigned int deidSize = sizeof(Tag); static const unsigned int numDeIds = sizeof(BasicApplicationLevelConfidentialityProfileAttributes) / deidSize; static const Tag *start = BasicApplicationLevelConfidentialityProfileAttributes; static const Tag *end = start + numDeIds; if( !CMS ) { gdcmErrorMacro( "Need a certificate" ); return false; } CryptographicMessageSyntax &p7 = *CMS; //p7.SetCertificate( this->x509 ); DataSet &ds = F->GetDataSet(); if( ds.FindDataElement( Tag(0x0400,0x0500) ) || ds.FindDataElement( Tag(0x0012,0x0062) ) || ds.FindDataElement( Tag(0x0012,0x0063) ) ) { gdcmErrorMacro( "EncryptedContentTransferSyntax Attribute is present !" ); return false; } #if 0 if( !ds.FindDataElement( Tag(0x0008,0x0018) ) || ds.GetDataElement( Tag(0x0008,0x0018) ).IsEmpty() ) { return false; } #endif // PS 3.15 // E.1 BASIC APPLICATION LEVEL CONFIDENTIALITY PROFILE // An Application may claim conformance to the Basic Application Level Confidentiality Profile as a deidentifier // if it protects all Attributes that might be used by unauthorized entities to identify the patient. // Protection in this context is defined as the following process: // 1. The application may create one or more instances of the Encrypted Attributes Data Set and copy // Attributes to be protected into the (single) item of the Modified Attributes Sequence (0400,0550) of // one or more of the Encrypted Attributes Data Set instances. // Create an instance of the Encrypted Attributes DataSet // Modified Attributes Sequence (0400,0550) 1 Sequence of Items containing all Attributes // that were removed or replaced by "dummy values" in the main dataset during deidentification // of the SOP instance. Upon reversal of the de-identification process, the // Attributes are copied back into the main dataset, replacing any dummy values that // might have been created. Only a single Item shall be present. // Create a Sequence SmartPointer sq1 = new SequenceOfItems(); sq1->SetLengthToUndefined(); // Create a *single* item Item item1; item1.SetVLToUndefined(); DataSet &encryptedds = item1.GetNestedDataSet(); // Loop over root level attributes: for(const Tag *ptr = start ; ptr != end ; ++ptr) { const Tag& tag = *ptr; if( ds.FindDataElement( tag ) ) encryptedds.Insert( ds.GetDataElement( tag ) ); } this->InvokeEvent( IterationEvent() ); // Check that root level sequence do not contains any of those attributes { DataSet::ConstIterator it = ds.Begin(); for( ; it != ds.End(); ++it ) { const DataElement &de = *it; //const SequenceOfItems *sqi = de.GetSequenceOfItems(); SmartPointer sqi = nullptr; VR vr = DataSetHelper::ComputeVR(*F, ds, de.GetTag() ); if( vr == VR::SQ ) { sqi = de.GetValueAsSQ(); } if( sqi ) { bool found = CheckIfSequenceContainsAttributeToAnonymize(*F, sqi); if( found ) { // A special Tag was found within the SQ,let's store the entire Sequence of Item: if( !encryptedds.FindDataElement( de.GetTag() ) ) { // What if we found a Patient Name within a Content Sequence // we do not need to insert twice this DICOM Attribute encryptedds.Insert( de ); } else { assert( de == encryptedds.GetDataElement( de.GetTag() ) ); } } } } } this->InvokeEvent( IterationEvent() ); sq1->AddItem(item1); DataElement des( Tag(0x0400,0x0550) ); des.SetVR(VR::SQ); des.SetValue(*sq1); des.SetVLToUndefined(); std::ostringstream os; des.Write(os); std::string encrypted_str = os.str(); // Note: 1. Content encryption may require that the content (the DICOM Data Set) be padded to a // multiple of some block size. This shall be performed according to the Content-encryption // Process defined in RFC-2630. size_t encrypted_len = encrypted_str.size() * 20; // this is really overestimated char *orig = new char[ encrypted_len ]; char *buf = new char[ encrypted_len ]; memset( buf, 0, encrypted_len ); memset( orig, 0, encrypted_len ); memcpy( orig, encrypted_str.c_str(), encrypted_str.size() ); size_t encrypted_len2 = encrypted_len; bool b = p7.Encrypt( buf, encrypted_len, orig, encrypted_str.size() ); if( !b ) { delete[] orig; delete[] buf; gdcmErrorMacro( "Problem with Encrypt" ); return false; } assert( encrypted_len <= encrypted_len2 ); (void)encrypted_len2;//warning removal { // Create a Sequence SmartPointer sq = new SequenceOfItems(); sq->SetLengthToUndefined(); // FIXME: should be user configurable: //TransferSyntax encrypted_ts = TransferSyntax::ImplicitVRLittleEndian; TransferSyntax encrypted_ts = TransferSyntax::ExplicitVRLittleEndian; // DataElement encrypted_ts_de( Tag(0x400,0x510) ); encrypted_ts_de.SetVR( Attribute<0x0400, 0x0510>::GetVR() ); const VL::Type encryptedStrLen = (VL::Type)strlen(encrypted_ts.GetString()); encrypted_ts_de.SetByteValue( encrypted_ts.GetString(), encryptedStrLen ); // DataElement encrypted_de( Tag(0x400,0x520) ); encrypted_de.SetVR( Attribute<0x0400, 0x0520>::GetVR() ); const VL::Type encryptedLenSize = (VL::Type)encrypted_len; encrypted_de.SetByteValue( (char*)buf, encryptedLenSize ); delete[] buf; delete[] orig; // Create an item Item item2; item2.SetVLToUndefined(); DataSet &nds = item2.GetNestedDataSet(); nds.Insert(encrypted_ts_de); nds.Insert(encrypted_de); sq->AddItem(item2); // 4. All instances of the Encrypted Attributes Data Set shall be encoded // with a DICOM Transfer Syntax, encrypted, and stored in the dataset to be // protected as an Item of the Encrypted Attributes Sequence (0400,0500). // The encryption shall be done using RSA [RFC 2313] for the key transport // of the content-encryption keys. A de-identifier conforming to this // security profile may use either AES or Triple-DES for // content-encryption. The AES key length may be any length allowed by the // RFCs. The Triple-DES key length is 168 bits as defined by ANSI X9.52. // Encoding shall be performed according to the specifications for RSA Key // Transport and Triple DES Content Encryption in RFC-3370 and for AES // Content Encryption in RFC-3565. // 5. No requirements on the size of the asymmetric key pairs used for RSA // key transport are defined in this confidentiality scheme. // Implementations claiming conformance to the Basic Application Level // Confidentiality Profile as a de-identifier shall always protect (e.g. // encrypt and replace) the SOP Instance UID (0008,0018) Attribute as well // as all references to other SOP Instances, whether contained in the main // dataset or embedded in an Item of a Sequence of Items, that could // potentially be used by unauthorized entities to identify the patient. // Insert sequence into data set DataElement subdes( Tag(0x0400,0x0500) ); subdes.SetVR(VR::SQ); subdes.SetValue(*sq); subdes.SetVLToUndefined(); ds.Insert(subdes); } this->InvokeEvent( IterationEvent() ); // 2. Each Attribute to be protected shall then either be removed from the // dataset, or have its value replaced by a different "replacement value" // which does not allow identification of the patient. //for(const Tag *ptr = start ; ptr != end ; ++ptr) // { // const Tag& tag = *ptr; // // FIXME Type 1 ! // if( ds.FindDataElement( tag ) ) BALCPProtect(F->GetDataSet(), tag); // } // Check that root level sequence do not contains any of those attributes try { RecurseDataSet( F->GetDataSet() ); } catch(std::exception &ex) { gdcmDebugMacro( "Problem during RecurseDataSet"); (void)ex; //to get rid of the warning. TODO: spit out the exception return false; } catch(...) { gdcmDebugMacro( "Unknown Problem during RecurseDataSet" ); return false; } this->InvokeEvent( IterationEvent() ); // Group Length are removed since PS 3.3-2008 RemoveGroupLength(); // 3. At the discretion of the de-identifier, Attributes may be added to the // dataset to be protected. ... // 6. The attribute Patient Identity Removed (0012,0062) shall be replaced or // added to the dataset with a value of YES, and a value inserted in // De-identification Method (0012,0063) or De-identification Method Code // Sequence (0012,0064). Replace( Tag(0x0012,0x0062), "YES"); Replace( Tag(0x0012,0x0063), "BASIC APPLICATION LEVEL CONFIDENTIALITY PROFILE"); this->InvokeEvent( IterationEvent() ); #if 0 // Since the de-identified SOP Instance is a significantly altered version of // the original Data Set, it is a new SOP Instance, with a SOP Instance UID // that differs from the original Data Set. UIDGenerator uid; if( ds.FindDataElement( Tag(0x0008,0x0018) ) ) { Replace( Tag(0x008,0x0018), uid.Generate() ); } this->InvokeEvent( IterationEvent() ); #endif return true; } 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; //if( tag == Tag(0x0020,0x000d) // Study Instance UID : UI // || tag == Tag(0x0020,0x0052) // // || tag == Tag(0x0020,0x000e) ) // Series Instance UID : UI // { // return true; // } return false; } static const Tag SpecialTypeTags[] = { /* Patient's Name */ Tag(0x0010,0x0010), /* Patient ID */ Tag(0x0010,0x0020), /* Study ID */ Tag(0x0020,0x0010), /* Series Number */ Tag(0x0020,0x0011) }; bool Anonymizer::CanEmptyTag(Tag const &tag, const IOD &iod) const { static const Global &g = Global::GetInstance(); //static const Dicts &dicts = g.GetDicts(); static const Defs &defs = g.GetDefs(); const DataSet &ds = F->GetDataSet(); (void)ds; //Type told = defs.GetTypeFromTag(*F, tag); Type t = iod.GetTypeFromTag(defs, tag); //assert( t == told ); gdcmDebugMacro( "Type for tag=" << tag << " is " << t ); //assert( t != Type::UNKNOWN ); if( t == Type::T1 || t == Type::T1C ) { return false; } // What if we are dealing with a Standard Extended SOP class // eg. gdcmData/05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm // where Attribute is not present in standard DICOM IOD - (0x0088,0x0140) UI Storage Media FileSet UID if( t == Type::UNKNOWN ) { return true; } // http://groups.google.com/group/comp.protocols.dicom/browse_thread/thread/b1b23101bb655b81 /* ... 3. It is the responsibility of the de-identifier to ensure the consistency of dummy values for Attributes such as Study Instance UID (0020,000D) or Frame of Reference UID (0020,0052) if multiple related SOP Instances are protected. ... I think it would also make sense to quote the following attributes: * Patient ID, * Study ID, * Series Number. It is required they have consistent values when one is about to generate a DICOMDIR => Sup 142 */ static const unsigned int deidSize = sizeof(Tag); static const unsigned int numDeIds = sizeof(SpecialTypeTags) / deidSize; bool b = std::binary_search(SpecialTypeTags, SpecialTypeTags + numDeIds, tag); // This is a Type 3 attribute but with VR=UI // //assert( dicts.GetDictEntry(tag).GetVR() != VR::UI ); return !b; } Anonymizer::DummyMapNonUIDTags Anonymizer::dummyMapNonUIDTags; Anonymizer::DummyMapUIDTags Anonymizer::dummyMapUIDTags; void Anonymizer::ClearInternalUIDs() { dummyMapNonUIDTags.clear(); dummyMapUIDTags.clear(); } bool Anonymizer::BALCPProtect(DataSet &ds, Tag const & tag, IOD const & iod) { // \precondition assert( ds.FindDataElement(tag) ); AnonymizeEvent ae; ae.SetTag( tag ); this->InvokeEvent( ae ); bool canempty = CanEmptyTag( tag, iod ); if( !canempty ) { DataElement copy; copy = ds.GetDataElement( tag ); if ( IsVRUI( tag ) ) { std::string UIDToAnonymize = ""; UIDGenerator uid; if( !copy.IsEmpty() ) { if( const ByteValue *bv = copy.GetByteValue() ) { UIDToAnonymize = std::string( bv->GetPointer(), bv->GetLength() ); } } std::string anonymizedUID = ""; if( !UIDToAnonymize.empty() ) { if ( dummyMapUIDTags.count( UIDToAnonymize ) == 0 ) { anonymizedUID = uid.Generate(); dummyMapUIDTags[ UIDToAnonymize ] = anonymizedUID; } else { anonymizedUID = dummyMapUIDTags[ UIDToAnonymize ]; } } else { // gdcmData/LEADTOOLS_FLOWERS-16-MONO2-JpegLossless.dcm // has an empty 0008,0018 attribute, let's try to handle creating new UID anonymizedUID = uid.Generate(); } copy.SetByteValue( anonymizedUID.c_str(), (uint32_t)anonymizedUID.size() ); ds.Replace( copy ); } else { TagValueKey tvk; tvk.first = tag; assert( dummyMapNonUIDTags.count( tvk ) == 0 || dummyMapNonUIDTags.count( tvk ) == 1 ); if( dummyMapNonUIDTags.count( tvk ) == 0 ) { const char *ret = DummyValueGenerator::Generate( tvk.second.c_str() ); if( ret ) { dummyMapNonUIDTags[ tvk ] = ret; } else dummyMapNonUIDTags[ tvk ] = ""; } std::string &v = dummyMapNonUIDTags[ tvk ]; copy.SetByteValue( v.c_str(), (uint32_t)v.size() ); } ds.Replace( copy ); } else { //Empty( tag ); DataElement copy = ds.GetDataElement( tag ); copy.Empty(); ds.Replace( copy ); } return true; } void Anonymizer::RecurseDataSet( DataSet & ds ) { if( ds.IsEmpty() ) return; static const unsigned int deidSize = sizeof(Tag); static const unsigned int numDeIds = sizeof(BasicApplicationLevelConfidentialityProfileAttributes) / deidSize; static const Tag *start = BasicApplicationLevelConfidentialityProfileAttributes; static const Tag *end = start + numDeIds; static const Global &g = Global::GetInstance(); static const Defs &defs = g.GetDefs(); const IOD& iod = defs.GetIODFromFile(*F); for(const Tag *ptr = start ; ptr != end ; ++ptr) { const Tag& tag = *ptr; // FIXME Type 1 ! if( ds.FindDataElement( tag ) ) { BALCPProtect(ds, tag, iod); } } DataSet::ConstIterator it = ds.Begin(); for( ; it != ds.End(); /*++it*/ ) { assert( it != ds.End() ); DataElement de = *it; ++it; //const SequenceOfItems *sqi = de.GetSequenceOfItems(); VR vr = DataSetHelper::ComputeVR(*F, ds, de.GetTag() ); SmartPointer sqi = nullptr; if( vr == VR::SQ ) { sqi = de.GetValueAsSQ(); } if( sqi ) { de.SetValue( *sqi ); // EXTREMELY IMPORTANT #2912092 de.SetVLToUndefined(); assert( sqi->IsUndefinedLength() ); //de.GetVL().SetToUndefined(); //sqi->SetLengthToUndefined(); SequenceOfItems::SizeType n = sqi->GetNumberOfItems(); for( SequenceOfItems::SizeType i = 1; i <= n; ++i ) { Item &item = sqi->GetItem( i ); DataSet &nested = item.GetNestedDataSet(); RecurseDataSet( nested ); } } ds.Replace( de ); } } //void Anonymizer::SetAESKey(AES const &aes) //{ // AESKey = aes; //} // //const AES &Anonymizer::GetAESKey() const //{ // return AESKey; //} bool Anonymizer::BasicApplicationLevelConfidentialityProfile2() { if( !CMS ) { gdcmErrorMacro( "Need a certificate" ); return false; } // 1. The application shall decrypt, using its recipient key, one instance of // the Encrypted Content (0400,0520) Attribute within the Encrypted // Attributes Sequence (0400,0500) and decode the resulting block of bytes // into a DICOM dataset using the Transfer Syntax specified in the Encrypted // Content Transfer Syntax UID (0400,0510). Re-identifiers claiming // conformance to this profile shall be capable of decrypting the Encrypted // Content using either AES or Triple-DES in all possible key lengths // specified in this profile CryptographicMessageSyntax &p7 = *CMS; //p7.SetCertificate( this->x509 ); DataSet &ds = F->GetDataSet(); if( !ds.FindDataElement( Tag(0x0400,0x0500) ) ) { gdcmDebugMacro( "Could not find EncryptedAttributesSQ" ); return false; } const DataElement &EncryptedAttributesSequence = ds.GetDataElement( Tag(0x0400,0x0500) ); //const SequenceOfItems *sq = EncryptedAttributesSequence.GetSequenceOfItems(); SmartPointer sq = EncryptedAttributesSequence.GetValueAsSQ(); const Item &item1 = sq->GetItem(1); const DataSet &nds1 = item1.GetNestedDataSet(); if( !nds1.FindDataElement( Tag(0x0400,0x0510) ) || nds1.GetDataElement( Tag(0x0400,0x0510) ).IsEmpty() ) { gdcmDebugMacro( "Missing EncryptedContentTransferSyntax Attribute" ); return false; } const DataElement &EncryptedContentTransferSyntax = nds1.GetDataElement( Tag(0x0400,0x0510) ); std::string ts( EncryptedContentTransferSyntax.GetByteValue()->GetPointer(), EncryptedContentTransferSyntax.GetByteValue()->GetLength() ); if( TransferSyntax::GetTSType( ts.c_str() ) != TransferSyntax::ExplicitVRLittleEndian ) { gdcmDebugMacro( "Only ExplicitVRLittleEndian is supported" ); return false; } if( !nds1.FindDataElement( Tag(0x0400,0x0520) ) || nds1.GetDataElement( Tag(0x0400,0x0520) ).IsEmpty() ) { gdcmDebugMacro( "Missing EncryptedContent Attribute" ); return false; } const DataElement &EncryptedContent = nds1.GetDataElement( Tag(0x0400,0x0520) ); const ByteValue *bv = EncryptedContent.GetByteValue(); size_t encrypted_len = bv->GetLength(); char *orig = new char[ encrypted_len ]; char *buf = new char[ encrypted_len ]; memcpy(orig, bv->GetPointer(), encrypted_len ); size_t encrypted_len2 = encrypted_len; bool b = p7.Decrypt( buf, encrypted_len, orig, encrypted_len); if( !b ) { // ooops gdcmDebugMacro( "Could not decrypt" ); return false; } assert( encrypted_len <= encrypted_len2 ); (void)encrypted_len2;//warning removal std::stringstream ss; ss.str( std::string((char*)buf, encrypted_len) ); DataSet des; DataElement dummy; try { dummy.Read(ss); } //catch( std::Exception & e) catch( ... ) { delete[] buf; delete[] orig; return false; } des.Insert( dummy ); //des.Read(ss); //des.ReadNested(ss); //std::cout << des << std::endl; //std::cout << dummy << std::endl; //std::cout << ss.tellg() << std::endl; assert( (size_t)ss.tellg() <= encrypted_len ); // TODO: check that for i = ss.tellg() to encrypted_len, ss[i] == 0 delete[] buf; delete[] orig; // 2. The application shall move all Attributes contained in the single item // of the Modified Attributes Sequence (0400,0550) of the decoded dataset // into the main dataset, replacing dummy value Attributes that may be // present in the main dataset. //assert( dummy.GetVR() == VR::SQ ); { //const SequenceOfItems *sqi = dummy.GetSequenceOfItems(); SmartPointer sqi = dummy.GetValueAsSQ(); assert( sqi && sqi->GetNumberOfItems() == 1 ); Item const & item2 = sqi->GetItem( 1 ); const DataSet &nds2 = item2.GetNestedDataSet(); DataSet::ConstIterator it = nds2.Begin(); for( ; it != nds2.End(); ++it ) { ds.Replace( *it ); } // FIXME the above Replace assume that the encrypted content will replace // any dummy values. What if the anonymizer was dumb and forgot // to encrypt say UID 8,18 ? We would be left with the Instance UID // of the encrypted one ? if( !nds2.FindDataElement( Tag(0x8,0x18) ) ) { MediaStorage ms; ms.SetFromFile( *F ); if( ms != MediaStorage::MediaStorageDirectoryStorage ) { gdcmErrorMacro( "Could not find Instance UID" ); return false; } } } // 3. The attribute Patient Identity Removed (0012,0062) shall be replaced or // added to the dataset with a value of NO and De-identification Method // (0012,0063) and De-identification Method Code Sequence (0012,0064) shall // be removed. //Replace( Tag(0x0012,0x0062), "NO"); Remove( Tag(0x0012,0x0062) ); Remove( Tag(0x0012,0x0063) ); Remove( Tag(0x0400,0x0500) ); // ?? return true; } void Anonymizer::SetCryptographicMessageSyntax(CryptographicMessageSyntax *cms) { CMS = cms; } const CryptographicMessageSyntax *Anonymizer::GetCryptographicMessageSyntax() const { return CMS; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmAnonymizer.h000066400000000000000000000152711412732066400236570ustar00rootroot00000000000000/*========================================================================= 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 GDCMANONYMIZER_H #define GDCMANONYMIZER_H #include "gdcmFile.h" #include "gdcmSubject.h" #include "gdcmEvent.h" #include "gdcmSmartPointer.h" #include namespace gdcm { class TagPath; class IOD; class CryptographicMessageSyntax; /** * \brief Anonymizer * \details This class is a multi purpose anonymizer. It can work in 2 mode: * - Full (irreversible) anonymizer (aka dumb mode) * - reversible de-identifier/re-identifier (aka smart mode). This implements the Basic Application Level Confidentiality Profile, DICOM PS 3.15-2009 * * 1. dumb mode * This is a dumb anonymizer implementation. All it allows user is simple operation such as: * * Tag based functions: * - complete removal of DICOM attribute (Remove) * - make a tag empty, ie make it's length 0 (Empty) * - replace with another string-based value (Replace) * * DataSet based functions: * - Remove all group length attribute from a DICOM dataset (Group Length element are deprecated, DICOM 2008) * - Remove all private attributes * - Remove all retired attributes * * All function calls actually execute the user specified request. Previous * implementation were calling a general Anonymize function but traversing a * std::set is O(n) operation, while a simple user specified request is * O(log(n)) operation. So 'm' user interaction is O(m*log(n)) which is < O(n) * complexity. * * 2. smart mode * this mode implements the Basic Application Level Confidentiality Profile * (DICOM PS 3.15-2008) In this case, it is extremely important to use the same * Anonymizer class when anonymizing a FileSet. Once the Anonymizer * is destroyed its memory of known (already processed) UIDs will be lost. * which will make the anonymizer behaves incorrectly for attributes such as * Series UID Study UID where user want some consistency. When attribute is * Type 1 / Type 1C, a dummy generator will take in the existing value and * produce a dummy value (a sha1 representation). sha1 algorithm is considered * to be cryptographically strong (compared to md5sum) so that we meet the * following two conditions: * - Produce the same dummy value for the same input value * - do not provide an easy way to retrieve the original value from the sha1 generated value * * This class implement the Subject/Observer pattern trigger the following event: * \li AnonymizeEvent * \li IterationEvent * \li StartEvent * \li EndEvent * * \see CryptographicMessageSyntax */ class GDCM_EXPORT Anonymizer : public Subject { public: Anonymizer():F(new File),CMS(nullptr) {} ~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 ); /// 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 ); /// 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 ); /// 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 ); /// Main function that loop over all elements and remove private tags bool RemovePrivateTags(); /// Main function that loop over all elements and remove group length bool RemoveGroupLength(); /// 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; } File &GetFile() { return *F; } /// PS 3.15 / E.1.1 De-Identifier /// An Application may claim conformance to the Basic Application Level Confidentiality Profile as a deidentifier /// if it protects all Attributes that might be used by unauthorized entities to identify the patient. /// NOT THREAD SAFE bool BasicApplicationLevelConfidentialityProfile(bool deidentify = true); /// Set/Get CMS key that will be used to encrypt the dataset within BasicApplicationLevelConfidentialityProfile void SetCryptographicMessageSyntax( CryptographicMessageSyntax *cms ); const CryptographicMessageSyntax *GetCryptographicMessageSyntax() const; /// for wrapped language: instantiate a reference counted object static SmartPointer New() { return new Anonymizer; } /// Return the list of Tag that will be considered when anonymizing a DICOM file. static std::vector GetBasicApplicationLevelConfidentialityProfileAttributes(); /// Clear the internal mapping of real UIDs to generated UIDs /// \warning the mapping is definitely lost static void ClearInternalUIDs(); protected: // Internal function used to either empty a tag or set it's value to a dummy value (Type 1 vs Type 2) bool BALCPProtect(DataSet &ds, Tag const & tag, const IOD &iod); bool CanEmptyTag(Tag const &tag, const IOD &iod) const; void RecurseDataSet( DataSet & ds ); private: bool BasicApplicationLevelConfidentialityProfile1(); bool BasicApplicationLevelConfidentialityProfile2(); bool CheckIfSequenceContainsAttributeToAnonymize(File const &file, SequenceOfItems* sqi) const; private: // I would prefer to have a smart pointer to DataSet but DataSet does not derive from Object... SmartPointer F; CryptographicMessageSyntax *CMS; typedef std::pair< Tag, std::string > TagValueKey; typedef std::map< TagValueKey, std::string > DummyMapNonUIDTags; typedef std::map< std::string, std::string > DummyMapUIDTags; static DummyMapNonUIDTags dummyMapNonUIDTags; static DummyMapUIDTags dummyMapUIDTags; }; /** * \example ManipulateFile.cs * \example ClinicalTrialIdentificationWorkflow.cs * This is a C# example on how to use Anonymizer */ } // end namespace gdcm #endif //GDCMANONYMIZER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmApplicationEntity.cxx000066400000000000000000000011521412732066400255300ustar00rootroot00000000000000/*========================================================================= 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 "gdcmApplicationEntity.h" namespace gdcm {} GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmApplicationEntity.h000066400000000000000000000034721412732066400251640ustar00rootroot00000000000000/*========================================================================= 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 GDCMAPPLICATIONENTITY_H #define GDCMAPPLICATIONENTITY_H #include "gdcmTypes.h" #include #include // abort namespace gdcm { /** * \brief ApplicationEntity * \details * - AE Application Entity * - A string of characters that identifies an Application Entity with leading * and trailing spaces (20H) being non-significant. A value consisting solely * of spaces shall not be used. * - Default Character Repertoire excluding character code 5CH (the BACKSLASH \ in * ISO-IR 6), and control characters LF, FF, CR and ESC. * - 16 bytes maximum */ class GDCM_EXPORT ApplicationEntity { public: static const unsigned int MaxNumberOfComponents = 1; static const unsigned int MaxLength = 16; std::string Internal; static const char Separator = ' '; static const char Padding = ' '; //static const char Excluded[5] = { '\\' /* 5CH */, '\n' /* LF */, '\f', /* FF */, '\r' /* CR */, 0x1b /* ESC */}; bool IsValid() const { return true; } void Squeeze() { // trim leading and trailing white spaces } void SetBlob(const std::vector& v) { (void)v; assert(0); //TODO } void Print(std::ostream &os) const { (void)os; assert(0); //TODO } }; } // end namespace gdcm #endif //GDCMAPPLICATIONENTITY_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmAudioCodec.cxx000066400000000000000000000014541412732066400240740ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAudioCodec.h" #include "gdcmDataElement.h" namespace gdcm { AudioCodec::AudioCodec() = default; AudioCodec::~AudioCodec() = default; bool AudioCodec::Decode(DataElement const &is, DataElement &os) { os = is; return true; } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmAudioCodec.h000066400000000000000000000020271412732066400235160ustar00rootroot00000000000000/*========================================================================= 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 GDCMAUDIOCODEC_H #define GDCMAUDIOCODEC_H #include "gdcmCodec.h" namespace gdcm { /** * \brief AudioCodec */ class GDCM_EXPORT AudioCodec : public Codec { public: AudioCodec(); ~AudioCodec() override; bool CanCode(TransferSyntax const &) const override { return false; } bool CanDecode(TransferSyntax const &) const override { return false; } bool Decode(DataElement const &is, DataElement &os) override; }; } // end namespace gdcm #endif //GDCMAUDIOCODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmBitmap.cxx000066400000000000000000001065351412732066400233170ustar00rootroot00000000000000/*========================================================================= 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 "gdcmBitmap.h" #include "gdcmSequenceOfFragments.h" #include "gdcmRAWCodec.h" #include "gdcmJPEGCodec.h" #include "gdcmPVRGCodec.h" #include "gdcmKAKADUCodec.h" #include "gdcmJPEGLSCodec.h" #include "gdcmJPEG2000Codec.h" #include "gdcmRLECodec.h" #include namespace gdcm { /* * PICKER-16-MONO2-Nested_icon.dcm: (0088,0200) SQ (Sequence with undefined length #=1) # u/l, 1 BitmapSequence (fffe,e000) na (Item with undefined length #=10) # u/l, 1 Item (0028,0002) US 1 # 2, 1 SamplesPerPixel (0028,0004) CS [MONOCHROME2] # 12, 1 PhotometricInterpretation (0028,0010) US 64 # 2, 1 Rows (0028,0011) US 64 # 2, 1 Columns (0028,0034) IS [1\1] # 4, 2 PixelAspectRatio (0028,0100) US 8 # 2, 1 BitsAllocated (0028,0101) US 8 # 2, 1 BitsStored (0028,0102) US 7 # 2, 1 HighBit (0028,0103) US 0 # 2, 1 PixelRepresentation (7fe0,0010) OW 0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000... # 4096, 1 PixelData (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem */ Bitmap::Bitmap(): PlanarConfiguration(0), NumberOfDimensions(2), TS(), PF(), PI(), Dimensions(), PixelData(), LUT(new LookupTable), NeedByteSwap(false), LossyFlag(false) {} Bitmap::~Bitmap() = default; /* * Internal implementation everything assume that NumberOfDimensions was set */ unsigned int Bitmap::GetNumberOfDimensions() const { assert( NumberOfDimensions ); return NumberOfDimensions; } void Bitmap::SetNumberOfDimensions(unsigned int dim) { NumberOfDimensions = dim; assert( NumberOfDimensions ); Dimensions.resize( 3 /*NumberOfDimensions*/ ); // fill with 0 assert( NumberOfDimensions == 2 || NumberOfDimensions == 3 ); if( NumberOfDimensions == 2 ) { Dimensions[2] = 1; //Spacing[2] = 1; } } const unsigned int *Bitmap::GetDimensions() const { assert( NumberOfDimensions ); return &Dimensions[0]; } unsigned int Bitmap::GetDimension(unsigned int idx) const { assert( NumberOfDimensions ); return Dimensions[idx]; } void Bitmap::SetDimensions(const unsigned int *dims) { assert( NumberOfDimensions ); //assert( Dimensions.empty() ); #if 0 Dimensions = std::vector(dims, dims+NumberOfDimensions); #else assert( Dimensions.size() == 3 ); Dimensions[0] = dims[0]; Dimensions[1] = dims[1]; if( NumberOfDimensions == 2 ) Dimensions[2] = 1; else Dimensions[2] = dims[2]; #endif } void Bitmap::SetDimension(unsigned int idx, unsigned int dim) { //assert( dim ); assert( NumberOfDimensions ); assert( idx < NumberOfDimensions ); Dimensions.resize( 3 /*NumberOfDimensions*/ ); // Can dim be 0 ?? // -> no ! //assert( dim ); // PhilipsLosslessRice.dcm Dimensions[idx] = dim; if( NumberOfDimensions == 2 ) { Dimensions[2] = 1; } } // TODO does it make sense to PlanarConfiguration in Bitmap // and SamplesPerPixel in PixelFormat when those two are linked... unsigned int Bitmap::GetPlanarConfiguration() const { if( PlanarConfiguration && PF.GetSamplesPerPixel() != 3 ) { // LEADTOOLS_FLOWERS-8-PAL-RLE.dcm // User specify PlanarConfiguration whereas SamplesPerPixel != 3 gdcmWarningMacro( "Can't set PlanarConfiguration if SamplesPerPixel is not 3" ); // Let's assume it's this way... return 0; } return PlanarConfiguration; } void Bitmap::SetPlanarConfiguration(unsigned int pc) { // precondition assert( pc == 0 || pc == 1 ); PlanarConfiguration = pc; if( pc ) { // LEADTOOLS_FLOWERS-8-MONO2-Uncompressed.dcm if( PF.GetSamplesPerPixel() != 3 ) // Please set PixelFormat first { gdcmWarningMacro( "Cannot have Planar Configuration in non RGB input. Discarding" ); PlanarConfiguration = 0; } const TransferSyntax &ts = GetTransferSyntax(); if( ts == TransferSyntax::JPEGBaselineProcess1 || ts == TransferSyntax::JPEGExtendedProcess2_4 || ts == TransferSyntax::JPEGExtendedProcess3_5 || ts == TransferSyntax::JPEGSpectralSelectionProcess6_8 || ts == TransferSyntax::JPEGFullProgressionProcess10_12 || ts == TransferSyntax::JPEGLosslessProcess14 || ts == TransferSyntax::JPEGLosslessProcess14_1 || ts == TransferSyntax::JPEGLSLossless || ts == TransferSyntax::JPEGLSNearLossless || ts == TransferSyntax::JPEG2000Lossless || ts == TransferSyntax::JPEG2000 || ts == TransferSyntax::JPIPReferenced || ts == TransferSyntax::RLELossless // FIXME internally GDCM produce per-pixel output ) { // PS 3.6 - 2011 8.2.4 JPEG 2000 IMAGE COMPRESSION // The value of Planar Configuration (0028,0006) is irrelevant since the // manner of encoding components is specified in the JPEG 2000 standard, // hence it shall be set to 0. // By extension, this behavior has been applied also to JPEG and JPEG-LS gdcmWarningMacro( "Cannot have Planar Configuration in JPEG/JPEG-LS/JPEG 2000. Discarding" ); PlanarConfiguration = 0; } } // \postcondition assert( PlanarConfiguration == 0 || PlanarConfiguration == 1 ); } void Bitmap::Clear() { Dimensions.clear(); } const PhotometricInterpretation &Bitmap::GetPhotometricInterpretation() const { return PI; } void Bitmap::SetPhotometricInterpretation( PhotometricInterpretation const &pi) { PI = pi; } #if 0 bool Bitmap::GetBuffer(char *buffer) const { if( IsEmpty() ) { buffer = 0; return false; } const ByteValue *bv = PixelData.GetByteValue(); if( !bv ) { // KODAK_CompressedIcon.dcm // contains a compressed Icon Sequence, one has to guess this is lossless jpeg... #ifdef MDEBUG const SequenceOfFragments *sqf = PixelData.GetSequenceOfFragments(); std::ofstream os( "/tmp/kodak.ljpeg", std::ios::binary); sqf->WriteBuffer( os ); #endif gdcmWarningMacro( "Compressed Icon are not support for now" ); buffer = 0; return false; } assert( bv ); RAWCodec codec; //assert( GetPhotometricInterpretation() == PhotometricInterpretation::MONOCHROME2 ); //codec.SetPhotometricInterpretation( GetPhotometricInterpretation() ); if( GetPhotometricInterpretation() != PhotometricInterpretation::MONOCHROME2 ) { gdcmWarningMacro( "PhotometricInterpretation: " << GetPhotometricInterpretation() << " not handled for now" ); } codec.SetPhotometricInterpretation( PhotometricInterpretation::MONOCHROME2 ); codec.SetPixelFormat( GetPixelFormat() ); codec.SetPlanarConfiguration( 0 ); DataElement out; bool r = codec.Decode(PixelData, out); assert( r ); const ByteValue *outbv = out.GetByteValue(); assert( outbv ); //unsigned long check = outbv->GetLength(); // FIXME memcpy(buffer, outbv->GetPointer(), outbv->GetLength() ); // FIXME return r; } #endif unsigned long Bitmap::GetBufferLength() const { //assert( !IsEncapsulated() ); if( PF == PixelFormat::UNKNOWN ) return 0; assert( NumberOfDimensions ); //assert( NumberOfDimensions == Dimensions.size() ); if( NumberOfDimensions != Dimensions.size() ) { assert( Dimensions[2] == 1 ); } unsigned long len = 0; unsigned int mul = 1; // First multiply the dimensions: std::vector::const_iterator it = Dimensions.begin(); for(; it != Dimensions.end(); ++it) { if( *it == 0 ) { gdcmWarningMacro("Dimension has been found to be zero" ); } mul *= *it; } // Multiply by the pixel size: // Special handling of packed format: if( PF == PixelFormat::UINT12 || PF == PixelFormat::INT12 ) { #if 1 mul *= PF.GetPixelSize(); #else assert( PF.GetSamplesPerPixel() == 1 ); unsigned int save = mul; save *= 12; save /= 8; assert( save * 8 / 12 == mul ); mul = save; #endif } else if( PF == PixelFormat::SINGLEBIT ) { assert( PF.GetSamplesPerPixel() == 1 ); const size_t bytesPerRow = Dimensions[0] / 8 + (Dimensions[0] % 8 != 0 ? 1 : 0); size_t save = bytesPerRow * Dimensions[1]; if( NumberOfDimensions > 2 ) save *= Dimensions[2]; if(Dimensions[0] % 8 == 0 ) assert( save * 8 == mul ); mul = (unsigned int)save; } else if( PF.GetBitsAllocated() % 8 != 0 ) { // gdcmDataExtra/gdcmSampleData/images_of_interest/USBitsAllocated14.dcm // BitsAllocated :14 // BitsStored :14 // HighBit :13 assert( PF.GetSamplesPerPixel() == 1 ); const ByteValue *bv = PixelData.GetByteValue(); assert( bv ); unsigned int ref = bv->GetLength() / mul; if( !GetTransferSyntax().IsEncapsulated() ) assert( bv->GetLength() % mul == 0 ); mul *= ref; } else { mul *= PF.GetPixelSize(); } len = mul; //assert( len != 0 ); return len; } bool Bitmap::TryRAWCodec(char *buffer, bool &lossyflag) const { RAWCodec codec; const TransferSyntax &ts = GetTransferSyntax(); if(!buffer) { if( codec.CanDecode( ts ) ) // short path { lossyflag = false; if( GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL_422 ) { lossyflag = true; } return true; } return false; } const ByteValue *bv = PixelData.GetByteValue(); if( bv ) { unsigned long len = GetBufferLength(); if( !codec.CanDecode( ts ) ) return false; codec.SetPlanarConfiguration( GetPlanarConfiguration() ); codec.SetPhotometricInterpretation( GetPhotometricInterpretation() ); codec.SetLUT( GetLUT() ); codec.SetPixelFormat( GetPixelFormat() ); codec.SetNeedByteSwap( GetNeedByteSwap() ); codec.SetNeedOverlayCleanup( AreOverlaysInPixelData() || UnusedBitsPresentInPixelData() ); DataElement out; //bool r = codec.Decode(PixelData, out); bool r = codec.DecodeBytes(bv->GetPointer(), bv->GetLength(), buffer, len); if( GetNeedByteSwap() ) { // Internally DecodeBytes always does the byteswapping step, so remove internal flag Bitmap *i = const_cast(this); i->SetNeedByteSwap(false); } if( !r ) return false; //const ByteValue *outbv = out.GetByteValue(); //assert( outbv ); if( len != bv->GetLength() ) { // SIEMENS_GBS_III-16-ACR_NEMA_1.acr // This is also handling the famous DermaColorLossLess.dcm issue // where RGB image is odd length (GetBufferLength()) but // ByteValue::GetLength is rounded up to the next even byte length // gdcmDebugMacro( "Pixel Length " << bv->GetLength() << // " is different from computed value " << len ); // ((ByteValue*)outbv)->SetLength( len ); } #if 0 if ( GetPixelFormat() != codec.GetPixelFormat() ) { Bitmap *i = (Bitmap*)this; i->SetPixelFormat( codec.GetPixelFormat() ); } #endif unsigned long check; // = outbv->GetLength(); // FIXME check = len; // DermaColorLossLess.dcm assert( check == len || check == len + 1 ); (void)check;// removing warning //if(buffer) memcpy(buffer, outbv->GetPointer(), outbv->GetLength() ); // FIXME return r; } return false; } bool Bitmap::TryJPEGCodec(char *buffer, bool &lossyflag) const { JPEGCodec codec; const TransferSyntax &ts = GetTransferSyntax(); if(!buffer) { if( codec.CanDecode( ts ) ) // short path { TransferSyntax ts2; const SequenceOfFragments *sf = PixelData.GetSequenceOfFragments(); if( !sf ) return false; const Fragment &frag = sf->GetFragment(0); const ByteValue &bv2 = dynamic_cast(frag.GetValue()); PixelFormat pf = GetPixelFormat(); // PixelFormat::UINT8; codec.SetPixelFormat( pf ); std::stringstream ss; ss.write( bv2.GetPointer(), bv2.GetLength() ); bool b = codec.GetHeaderInfo( ss, ts2 ); //bool b = codec.GetHeaderInfo( bv2.GetPointer(), bv2.GetLength() , ts2 ); if(!b) return false; assert( b ); lossyflag = codec.IsLossy(); // we need to know the actual pixeltype after ::Read #if 0 if( codec.GetPixelFormat() != GetPixelFormat() ) { Bitmap *i = (Bitmap*)this; i->SetPixelFormat( codec.GetPixelFormat() ); } #else const PixelFormat & cpf = codec.GetPixelFormat(); // SC16BitsAllocated_8BitsStoredJPEG.dcm if( cpf.GetBitsAllocated() <= pf.GetBitsAllocated() ) { if( cpf.GetPixelRepresentation() == pf.GetPixelRepresentation() ) { if( cpf.GetSamplesPerPixel() == pf.GetSamplesPerPixel() ) { if( cpf.GetBitsStored() < pf.GetBitsStored() ) { Bitmap *i = const_cast(this); gdcmWarningMacro( "Encapsulated stream has fewer bits actually stored on disk. correcting." ); 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() ); } } } } #endif if( GetDimensions()[0] != codec.GetDimensions()[0] || GetDimensions()[1] != codec.GetDimensions()[1] ) { gdcmWarningMacro( "dimension mismatch for JPEG" ); (const_cast(this))->SetDimensions( codec.GetDimensions() ); //JPEGNote_bogus.dcm } return true; } return false; } if( codec.CanDecode( ts ) ) { unsigned long len = GetBufferLength(); codec.SetNumberOfDimensions( GetNumberOfDimensions() ); codec.SetDimensions( GetDimensions() ); codec.SetPlanarConfiguration( GetPlanarConfiguration() ); codec.SetPhotometricInterpretation( GetPhotometricInterpretation() ); codec.SetPixelFormat( GetPixelFormat() ); codec.SetNeedOverlayCleanup( AreOverlaysInPixelData() || UnusedBitsPresentInPixelData() ); DataElement out; bool r = codec.Decode(PixelData, out); // PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm if( !r ) { return false; } // FIXME ! This should be done all the time for all codec: // Did PI change or not ? if ( GetPlanarConfiguration() != codec.GetPlanarConfiguration() ) { Bitmap *i = const_cast(this); (void)i; //i->SetPlanarConfiguration( codec.GetPlanarConfiguration() ); } // I cannot re-activate the following since I would loose the palette color information // (this is not stored in the JPEG header). //if ( GetPhotometricInterpretation() != codec.GetPhotometricInterpretation() ) // { // // HACK // // YBRisGray.dcm // Bitmap *i = (Bitmap*)this; // i->SetPhotometricInterpretation( codec.GetPhotometricInterpretation() ); // } #if 1 const PixelFormat & cpf = codec.GetPixelFormat(); const PixelFormat & pf = GetPixelFormat(); if ( pf != cpf ) { // gdcmData/DCMTK_JPEGExt_12Bits.dcm if( pf.GetPixelRepresentation() == cpf.GetPixelRepresentation() ) { if( pf.GetBitsAllocated() == 12 ) { Bitmap *i = const_cast(this); i->GetPixelFormat().SetBitsAllocated( 16 ); i->GetPixelFormat().SetBitsStored( 12 ); } } } #else const PixelFormat & cpf = codec.GetPixelFormat(); const PixelFormat & pf = GetPixelFormat(); // SC16BitsAllocated_8BitsStoredJPEG.dcm if( cpf.GetBitsAllocated() <= pf.GetBitsAllocated() ) { if( cpf.GetPixelRepresentation() == pf.GetPixelRepresentation() ) { if( cpf.GetSamplesPerPixel() == pf.GetSamplesPerPixel() ) { if( cpf.GetBitsStored() < pf.GetBitsStored() ) { Bitmap *i = const_cast(this); gdcmWarningMacro( "Encapsulated stream has fewer bits actually stored on disk. correcting." ); i->GetPixelFormat().SetBitsAllocated( cpf.GetBitsAllocated() ); i->GetPixelFormat().SetBitsStored( cpf.GetBitsStored() ); } } } } #endif //if ( GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL_422 //|| GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL ) // { // Bitmap *i = (Bitmap*)this; // i->SetPhotometricInterpretation( PhotometricInterpretation::RGB ); // } const ByteValue *outbv = out.GetByteValue(); assert( outbv ); unsigned long check = outbv->GetLength(); // FIXME (void)check; // DermaColorLossLess.dcm has a len of 63531, but DICOM will give us: 63532 ... if( len > outbv->GetLength() ) { gdcmErrorMacro( "Impossible length: " << len << " should be (max): " << outbv->GetLength() ); return false; } assert( len <= outbv->GetLength() ); if(buffer) memcpy(buffer, outbv->GetPointer(), len /*outbv->GetLength()*/ ); // FIXME lossyflag = codec.IsLossy(); //assert( codec.IsLossy() == ts.IsLossy() ); return true; } return false; } bool Bitmap::TryJPEGCodec2(std::ostream &os) const { unsigned long len = GetBufferLength(); const TransferSyntax &ts = GetTransferSyntax(); JPEGCodec codec; if( codec.CanCode( ts ) ) { codec.SetDimensions( GetDimensions() ); codec.SetPlanarConfiguration( GetPlanarConfiguration() ); codec.SetPhotometricInterpretation( GetPhotometricInterpretation() ); codec.SetPixelFormat( GetPixelFormat() ); codec.SetNeedOverlayCleanup( AreOverlaysInPixelData() || UnusedBitsPresentInPixelData() ); DataElement out; bool r = codec.Code(PixelData, out); // PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm if( !r ) { return false; } // FIXME ! This should be done all the time for all codec: // Did PI change or not ? if ( GetPhotometricInterpretation() != codec.GetPhotometricInterpretation() ) { // HACK //Bitmap *i = (Bitmap*)this; //i->SetPhotometricInterpretation( codec.GetPhotometricInterpretation() ); } const ByteValue *outbv = out.GetByteValue(); assert( outbv ); unsigned long check = outbv->GetLength(); // FIXME (void)check; // DermaColorLossLess.dcm has a len of 63531, but DICOM will give us: 63532 ... assert( outbv->GetLength() < len ); (void)len; //memcpy(buffer, outbv->GetPointer(), outbv->GetLength() ); os.write( outbv->GetPointer(), outbv->GetLength() ); return true; } return false; } bool Bitmap::TryPVRGCodec(char *buffer, bool &lossyflag) const { unsigned long len = GetBufferLength(); const TransferSyntax &ts = GetTransferSyntax(); PVRGCodec codec; if( codec.CanDecode( ts ) ) { codec.SetPixelFormat( GetPixelFormat() ); //codec.SetBufferLength( len ); //codec.SetNumberOfDimensions( GetNumberOfDimensions() ); codec.SetPlanarConfiguration( GetPlanarConfiguration() ); codec.SetPhotometricInterpretation( GetPhotometricInterpretation() ); codec.SetNeedOverlayCleanup( AreOverlaysInPixelData() || UnusedBitsPresentInPixelData() ); codec.SetDimensions( GetDimensions() ); DataElement out; bool r = codec.Decode(PixelData, out); if(!r) return false; codec.SetLossyFlag( ts.IsLossy() ); assert( r ); if ( GetPlanarConfiguration() != codec.GetPlanarConfiguration() ) { Bitmap *i = const_cast(this); i->PlanarConfiguration = codec.GetPlanarConfiguration(); } const ByteValue *outbv = out.GetByteValue(); assert( outbv ); unsigned long check = outbv->GetLength(); // FIXME (void)check; assert( len <= outbv->GetLength() ); if(buffer) memcpy(buffer, outbv->GetPointer(), len /*outbv->GetLength()*/ ); // FIXME lossyflag = codec.IsLossy(); //assert( codec.IsLossy() == ts.IsLossy() ); return r; } return false; } bool Bitmap::TryKAKADUCodec(char *buffer, bool &lossyflag) const { unsigned long len = GetBufferLength(); const TransferSyntax &ts = GetTransferSyntax(); KAKADUCodec codec; if( codec.CanDecode( ts ) ) { codec.SetPixelFormat( GetPixelFormat() ); //codec.SetBufferLength( len ); codec.SetNumberOfDimensions( GetNumberOfDimensions() ); codec.SetPlanarConfiguration( GetPlanarConfiguration() ); codec.SetPhotometricInterpretation( GetPhotometricInterpretation() ); codec.SetNeedOverlayCleanup( AreOverlaysInPixelData() || UnusedBitsPresentInPixelData() ); codec.SetDimensions( GetDimensions() ); DataElement out; bool r = codec.Decode(PixelData, out); if( !r ) return false; const ByteValue *outbv = out.GetByteValue(); assert( outbv ); unsigned long check = outbv->GetLength(); // FIXME (void)check; assert( len <= outbv->GetLength() ); // DermaColorLossLess.dcm has a len of 63531, but DICOM will give us: 63532 ... assert( len <= outbv->GetLength() ); if(buffer) memcpy(buffer, outbv->GetPointer(), len /*outbv->GetLength()*/ ); // FIXME //assert( codec.IsLossy() == ts.IsLossy() ); lossyflag = codec.IsLossy(); if( codec.IsLossy() != ts.IsLossy() ) { gdcmErrorMacro( "EVIL file, it is declared as lossless but is in fact lossy." ); } return r; } return false; } bool Bitmap::TryJPEGLSCodec(char *buffer, bool &lossyflag) const { JPEGLSCodec codec; const TransferSyntax &ts = GetTransferSyntax(); if(!buffer) { if( codec.CanDecode( ts ) ) // short path { TransferSyntax ts2; const SequenceOfFragments *sf = PixelData.GetSequenceOfFragments(); if( !sf ) return false; const Fragment &frag = sf->GetFragment(0); const ByteValue &bv2 = dynamic_cast(frag.GetValue()); std::stringstream ss; ss.write( bv2.GetPointer(), bv2.GetLength() ); bool b = codec.GetHeaderInfo( ss, ts2 ); //bool b = codec.GetHeaderInfo( bv2.GetPointer(), bv2.GetLength() , ts2 ); if( !b ) return false; lossyflag = codec.IsLossy(); // we need to know the actual pixeltype after ::Read #if 0 // This is actually very dangerous to change the pixel format right here. What if // user stored a 16/10/9 signed image using JPEG-LS, JPEG-LS would be required to use // the full spectrum of the unsigned short 16 bits range to store that image and would // therefore -rightfully- declared as 16 bits... if( codec.GetPixelFormat() != GetPixelFormat() ) { Bitmap *i = (Bitmap*)this; i->SetPixelFormat( codec.GetPixelFormat() ); } #endif return true; } return false; } if( codec.CanDecode( ts ) ) { unsigned long len = GetBufferLength(); codec.SetPixelFormat( GetPixelFormat() ); codec.SetBufferLength( len ); codec.SetNumberOfDimensions( GetNumberOfDimensions() ); codec.SetPlanarConfiguration( GetPlanarConfiguration() ); codec.SetPhotometricInterpretation( GetPhotometricInterpretation() ); codec.SetNeedOverlayCleanup( AreOverlaysInPixelData() || UnusedBitsPresentInPixelData() ); codec.SetDimensions( GetDimensions() ); DataElement out; bool r = codec.Decode(PixelData, out); if( !r ) return false; const ByteValue *outbv = out.GetByteValue(); assert( outbv ); unsigned long check = outbv->GetLength(); // FIXME (void)check; assert( len <= outbv->GetLength() ); // DermaColorLossLess.dcm has a len of 63531, but DICOM will give us: 63532 ... assert( len <= outbv->GetLength() ); if(buffer) memcpy(buffer, outbv->GetPointer(), len /*outbv->GetLength()*/ ); // FIXME //assert( codec.IsLossy() == ts.IsLossy() ); lossyflag = codec.IsLossy(); if( codec.IsLossy() != ts.IsLossy() ) { gdcmErrorMacro( "EVIL file, it is declared as lossless but is in fact lossy." ); } const PixelFormat & cpf = codec.GetPixelFormat(); const PixelFormat & pf = GetPixelFormat(); if( cpf.GetBitsAllocated() == pf.GetBitsAllocated() ) { if( cpf.GetPixelRepresentation() == pf.GetPixelRepresentation() ) { if( cpf.GetSamplesPerPixel() == pf.GetSamplesPerPixel() ) { if( cpf.GetBitsStored() < pf.GetBitsStored() ) { Bitmap *i = const_cast(this); gdcmWarningMacro( "Encapsulated stream has fewer bits actually stored on disk. correcting." ); 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() ); } } } } else { gdcmWarningMacro( "Bits Allocated are different. This is pretty bad using info from codestream" ); Bitmap *i = const_cast(this); i->SetPixelFormat( codec.GetPixelFormat() ); } return r; } return false; } bool Bitmap::IsLossy() const { // FIXME each call is expensive... //bool lossyflag; //if( this->GetBufferInternal(0, lossyflag) ) // { // return lossyflag; // } //return false; return LossyFlag; } bool Bitmap::ComputeLossyFlag() { bool lossyflag; if( this->GetBufferInternal(nullptr, lossyflag) ) { LossyFlag = lossyflag; return true; } LossyFlag = false; return false; } bool Bitmap::TryJPEG2000Codec(char *buffer, bool &lossyflag) const { JPEG2000Codec codec; const TransferSyntax &ts = GetTransferSyntax(); if(!buffer) { if( codec.CanDecode( ts ) ) // short path { TransferSyntax ts2; const SequenceOfFragments *sf = PixelData.GetSequenceOfFragments(); if( !sf ) return false; const Fragment &frag = sf->GetFragment(0); const ByteValue &bv2 = dynamic_cast(frag.GetValue()); bool b = codec.GetHeaderInfo( bv2.GetPointer(), bv2.GetLength() , ts2 ); if( !b ) return false; lossyflag = codec.IsLossy(); // we need to know the actual pixeltype after ::Read #if 0 if( codec.GetPixelFormat() != GetPixelFormat() ) { // Because J2K support the full spectrum I do not see any issue // with the following: Bitmap *i = (Bitmap*)this; i->SetPixelFormat( codec.GetPixelFormat() ); } #else // lets only check the only issue we have: // OsirixFake16BitsStoredFakeSpacing.dcm const PixelFormat & cpf = codec.GetPixelFormat(); const PixelFormat & pf = GetPixelFormat(); if( cpf.GetBitsAllocated() == pf.GetBitsAllocated() ) { if( cpf.GetPixelRepresentation() == pf.GetPixelRepresentation() ) { if( cpf.GetSamplesPerPixel() == pf.GetSamplesPerPixel() ) { if( cpf.GetBitsStored() < pf.GetBitsStored() ) { Bitmap *i = const_cast(this); gdcmWarningMacro( "Encapsulated stream has fewer bits actually stored on disk. correcting." ); 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() ); } } } } else { // SC16BitsAllocated_8BitsStoredJ2K.dcm gdcmWarningMacro( "Bits Allocated are different. This is pretty bad using info from codestream" ); Bitmap *i = const_cast(this); i->SetPixelFormat( codec.GetPixelFormat() ); } #endif return true; } return false; } if( codec.CanDecode( ts ) ) { unsigned long len = GetBufferLength(); codec.SetPixelFormat( GetPixelFormat() ); codec.SetNumberOfDimensions( GetNumberOfDimensions() ); codec.SetPlanarConfiguration( GetPlanarConfiguration() ); codec.SetPhotometricInterpretation( GetPhotometricInterpretation() ); codec.SetNeedOverlayCleanup( AreOverlaysInPixelData() || UnusedBitsPresentInPixelData() ); codec.SetDimensions( GetDimensions() ); DataElement out; bool r = codec.Decode(PixelData, out); if(!r) return false; assert( r ); const ByteValue *outbv = out.GetByteValue(); assert( outbv ); unsigned long check = outbv->GetLength(); // FIXME (void)check; assert( len <= outbv->GetLength() ); if(buffer) memcpy(buffer, outbv->GetPointer(), len /*outbv->GetLength()*/ ); // FIXME lossyflag = codec.IsLossy(); if( codec.IsLossy() && !ts.IsLossy() ) { assert( codec.IsLossy() ); assert( !ts.IsLossy() ); gdcmErrorMacro( "EVIL file, it is declared as lossless but is in fact lossy." ); } #if 0 if( codec.GetPixelFormat() != GetPixelFormat() ) { Bitmap *i = (Bitmap*)this; i->SetPixelFormat( codec.GetPixelFormat() ); } #else // lets only check the only issue we have: // OsirixFake16BitsStoredFakeSpacing.dcm const PixelFormat & cpf = codec.GetPixelFormat(); const PixelFormat & pf = GetPixelFormat(); if( cpf.GetBitsAllocated() == pf.GetBitsAllocated() ) { if( cpf.GetPixelRepresentation() == pf.GetPixelRepresentation() ) { if( cpf.GetSamplesPerPixel() == pf.GetSamplesPerPixel() ) { if( cpf.GetBitsStored() < pf.GetBitsStored() ) { Bitmap *i = const_cast(this); gdcmWarningMacro( "Encapsulated stream has fewer bits actually stored on disk. correcting." ); i->GetPixelFormat().SetBitsStored( cpf.GetBitsStored() ); } } } } #endif return r; } return false; } bool Bitmap::TryJPEG2000Codec2(std::ostream &os) const { unsigned long len = GetBufferLength(); (void)len; const TransferSyntax &ts = GetTransferSyntax(); JPEG2000Codec codec; if( codec.CanCode( ts ) ) { codec.SetDimensions( GetDimensions() ); codec.SetPixelFormat( GetPixelFormat() ); codec.SetNumberOfDimensions( GetNumberOfDimensions() ); codec.SetPlanarConfiguration( GetPlanarConfiguration() ); codec.SetPhotometricInterpretation( GetPhotometricInterpretation() ); codec.SetNeedOverlayCleanup( AreOverlaysInPixelData() || UnusedBitsPresentInPixelData() ); DataElement out; bool r = codec.Code(PixelData, out); assert( r ); const ByteValue *outbv = out.GetByteValue(); assert( outbv ); unsigned long check = outbv->GetLength(); // FIXME (void)check; //memcpy(buffer, outbv->GetPointer(), outbv->GetLength() ); // FIXME os.write(outbv->GetPointer(), outbv->GetLength() ); return r; } return false; } bool Bitmap::TryRLECodec(char *buffer, bool &lossyflag ) const { unsigned long len = GetBufferLength(); const TransferSyntax &ts = GetTransferSyntax(); RLECodec codec; if( codec.CanDecode( ts ) ) { //assert( sf->GetNumberOfFragments() == 1 ); //assert( sf->GetNumberOfFragments() == GetDimensions(2) ); codec.SetDimensions( GetDimensions() ); codec.SetNumberOfDimensions( GetNumberOfDimensions() ); codec.SetPlanarConfiguration( GetPlanarConfiguration() ); codec.SetPhotometricInterpretation( GetPhotometricInterpretation() ); codec.SetPixelFormat( GetPixelFormat() ); codec.SetLUT( GetLUT() ); codec.SetNeedOverlayCleanup( AreOverlaysInPixelData() || UnusedBitsPresentInPixelData() ); codec.SetBufferLength( len ); DataElement out; bool r = codec.Decode(PixelData, out); if( !r ) return false; const ByteValue *outbv = out.GetByteValue(); //unsigned long check = outbv->GetLength(); // FIXME // DermaColorLossLess.dcm has a len of 63531, but DICOM will give us: 63532 ... assert( len <= outbv->GetLength() ); if(buffer) memcpy(buffer, outbv->GetPointer(), len /*outbv->GetLength()*/ ); // FIXME lossyflag = false; return true; } return false; } // Access the raw data bool Bitmap::GetBuffer(char *buffer) const { bool dummy; return GetBufferInternal(buffer, dummy); } bool Bitmap::GetBufferInternal(char *buffer, bool &lossyflag) const { bool success = false; if( !success ) success = TryRAWCodec(buffer, lossyflag); if( !success ) success = TryJPEGCodec(buffer, lossyflag); if( !success ) success = TryPVRGCodec(buffer, lossyflag); // AFTER IJG trial ! //if( !success ) success = TryKAKADUCodec(buffer, lossyflag); if( !success ) success = TryJPEG2000Codec(buffer, lossyflag); if( !success ) success = TryJPEGLSCodec(buffer, lossyflag); if( !success ) success = TryRLECodec(buffer, lossyflag); //if( !success ) success = TryDeltaEncodingCodec(buffer); if( !success ) { buffer = nullptr; //throw Exception( "No codec found for this image"); } return success; } // Compress the raw data bool Bitmap::GetBuffer2(std::ostream &os) const { bool success = false; //if( !success ) success = TryRAWCodec2(buffer); if( !success ) success = TryJPEGCodec2(os); //if( !success ) success = TryJPEG2000Codec2(os); //if( !success ) success = TryRLECodec2(buffer); if( !success ) { //buffer = 0; throw Exception( "No codec found for this image"); } return success; } bool Bitmap::IsTransferSyntaxCompatible( TransferSyntax const & ts ) const { if( GetTransferSyntax() == ts ) return true; // Special cases: if( GetTransferSyntax() == TransferSyntax::JPEGExtendedProcess2_4 ) { if( GetPixelFormat().GetBitsAllocated() == 8 ) { if( ts == TransferSyntax::JPEGBaselineProcess1 ) return true; } } // default: return false; } void Bitmap::Print(std::ostream &os) const { Object::Print(os); //assert( NumberOfDimensions ); if( !IsEmpty() ) { os << "NumberOfDimensions: " << NumberOfDimensions << "\n"; assert( Dimensions.size() ); os << "Dimensions: ("; std::vector::const_iterator it = Dimensions.begin(); os << *it; for(++it; it != Dimensions.end(); ++it) { os << "," << *it; } os << ")\n"; PF.Print(os); os << "PhotometricInterpretation: " << PI << "\n"; os << "PlanarConfiguration: " << PlanarConfiguration << "\n"; os << "TransferSyntax: " << TS << "\n"; } } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmBitmap.h000066400000000000000000000135201412732066400227330ustar00rootroot00000000000000/*========================================================================= 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 GDCMBITMAP_H #define GDCMBITMAP_H #include "gdcmObject.h" #include "gdcmCurve.h" #include "gdcmDataElement.h" //#include "gdcmIconImage.h" #include "gdcmLookupTable.h" #include "gdcmOverlay.h" #include "gdcmPhotometricInterpretation.h" #include "gdcmPixelFormat.h" #include "gdcmSmartPointer.h" #include "gdcmTransferSyntax.h" #include namespace gdcm { /** * \brief Bitmap class * \details A bitmap based image. Used as parent for both IconImage and the main Pixel Data Image * It does not contains any World Space information (IPP, IOP) */ class GDCM_EXPORT Bitmap : public Object { public: Bitmap(); ~Bitmap() override; void Print(std::ostream &) const override; virtual bool AreOverlaysInPixelData() const { return false; } virtual bool UnusedBitsPresentInPixelData() const { return false; } /// Return the number of dimension of the pixel data bytes; for example 2 for a 2D matrices of values unsigned int GetNumberOfDimensions() const; void SetNumberOfDimensions(unsigned int dim); /// return the planar configuration unsigned int GetPlanarConfiguration() const; /// \warning you need to call SetPixelFormat first (before SetPlanarConfiguration) for consistency checking void SetPlanarConfiguration(unsigned int pc); /// INTERNAL do not use bool GetNeedByteSwap() const { return NeedByteSwap; } void SetNeedByteSwap(bool b) { NeedByteSwap = b; } /// Transfer syntax void SetTransferSyntax(TransferSyntax const &ts) { TS = ts; } const TransferSyntax &GetTransferSyntax() const { return TS; } bool IsTransferSyntaxCompatible( TransferSyntax const & ts ) const; void SetDataElement(DataElement const &de) { PixelData = de; } const DataElement& GetDataElement() const { return PixelData; } DataElement& GetDataElement() { return PixelData; } /// Set/Get LUT void SetLUT(LookupTable const &lut) { LUT = SmartPointer( const_cast(&lut) ); } const LookupTable &GetLUT() const { return *LUT; } LookupTable &GetLUT() { return *LUT; } /// Return the dimension of the pixel data, first dimension (x), then 2nd (y), then 3rd (z)... const unsigned int *GetDimensions() const; unsigned int GetDimension(unsigned int idx) const; void SetColumns(unsigned int col) { SetDimension(0,col); } unsigned int GetColumns() const { return GetDimension(0); } void SetRows(unsigned int rows) { SetDimension(1,rows); } unsigned int GetRows() const { return GetDimension(1); } void SetDimensions(const unsigned int dims[3]); void SetDimension(unsigned int idx, unsigned int dim); /// Get/Set PixelFormat const PixelFormat &GetPixelFormat() const { return PF; } PixelFormat &GetPixelFormat() { return PF; } void SetPixelFormat(PixelFormat const &pf) { PF = pf; PF.Validate(); } /// return the photometric interpretation const PhotometricInterpretation &GetPhotometricInterpretation() const; void SetPhotometricInterpretation(PhotometricInterpretation const &pi); bool IsEmpty() const { return Dimensions.empty(); } void Clear(); /// Return the length of the image after decompression /// WARNING for palette color: It will NOT take into account the Palette Color /// thus you need to multiply this length by 3 if computing the size of equivalent RGB image unsigned long GetBufferLength() const; /// Access the raw data bool GetBuffer(char *buffer) const; /// Return whether or not the image was compressed using a lossy compressor or not bool IsLossy() const; /// Specifically set that the image was compressed using a lossy compression mechanism void SetLossyFlag(bool f) { LossyFlag = f; } protected: bool TryRAWCodec(char *buffer, bool &lossyflag) const; bool TryJPEGCodec(char *buffer, bool &lossyflag) const; bool TryPVRGCodec(char *buffer, bool &lossyflag) const; bool TryKAKADUCodec(char *buffer, bool &lossyflag) const; bool TryJPEGLSCodec(char *buffer, bool &lossyflag) const; bool TryJPEG2000Codec(char *buffer, bool &lossyflag) const; bool TryRLECodec(char *buffer, bool &lossyflag) const; bool TryJPEGCodec2(std::ostream &os) const; bool TryJPEG2000Codec2(std::ostream &os) const; bool GetBuffer2(std::ostream &os) const; friend class PixmapReader; friend class ImageChangeTransferSyntax; // Function to compute the lossy flag based only on the image buffer. // Watch out that image can be lossy but in implicit little endian format... bool ComputeLossyFlag(); //private: protected: unsigned int PlanarConfiguration; unsigned int NumberOfDimensions; TransferSyntax TS; PixelFormat PF; // SamplesPerPixel, BitsAllocated, BitsStored, HighBit, PixelRepresentation PhotometricInterpretation PI; // Mind dump: unsigned int is required here, since we are reading (0028,0008) Number Of Frames // which is VR::IS, so I cannot simply assumed that unsigned short is enough... :( std::vector Dimensions; // Col/Row DataElement PixelData; // copied from 7fe0,0010 typedef SmartPointer LUTPtr; LUTPtr LUT; // I believe the following 3 ivars can be derived from TS ... bool NeedByteSwap; // FIXME: remove me bool LossyFlag; private: bool GetBufferInternal(char *buffer, bool &lossyflag) const; }; } // end namespace gdcm #endif //GDCMBITMAP_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmBitmapToBitmapFilter.cxx000066400000000000000000000024131412732066400261130ustar00rootroot00000000000000/*========================================================================= 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 "gdcmBitmapToBitmapFilter.h" #include "gdcmImage.h" #include #include // abort #include // memcpy namespace gdcm { BitmapToBitmapFilter::BitmapToBitmapFilter() = default; void BitmapToBitmapFilter::SetInput(const Bitmap& image) { Input = image; const Bitmap *p = ℑ if( dynamic_cast(p) ) { Output = new Image; } else if( dynamic_cast(p) ) { Output = new Pixmap; } else if( dynamic_cast(p) ) { Output = new Bitmap; } else { Output = nullptr; assert( 0 ); } } const Bitmap &BitmapToBitmapFilter::GetOutputAsBitmap() const { return *Output; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmBitmapToBitmapFilter.h000066400000000000000000000023561412732066400255460ustar00rootroot00000000000000/*========================================================================= 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 GDCMBITMAPTOBITMAPFILTER_H #define GDCMBITMAPTOBITMAPFILTER_H #include "gdcmBitmap.h" namespace gdcm { /** * \brief BitmapToBitmapFilter class * \details Super class for all filter taking an image and producing an output image */ class GDCM_EXPORT BitmapToBitmapFilter { public: BitmapToBitmapFilter(); ~BitmapToBitmapFilter() = default; /// Set input image void SetInput(const Bitmap& image); /// Get Output image const Bitmap &GetOutput() const { return *Output; } // SWIG/Java hack: const Bitmap &GetOutputAsBitmap() const; protected: SmartPointer Input; SmartPointer Output; }; } // end namespace gdcm #endif //GDCMBITMAPTOBITMAPFILTER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmCodec.h000066400000000000000000000014511412732066400225340ustar00rootroot00000000000000/*========================================================================= 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 GDCMCODEC_H #define GDCMCODEC_H #include "gdcmCoder.h" #include "gdcmDecoder.h" namespace gdcm { /** * \brief Codec class */ class GDCM_EXPORT Codec : public Coder, public Decoder { }; } // end namespace gdcm #endif //GDCMCODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmCoder.h000066400000000000000000000024521412732066400225550ustar00rootroot00000000000000/*========================================================================= 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 GDCMCODER_H #define GDCMCODER_H #include "gdcmTypes.h" #include "gdcmDataElement.h" // FIXME namespace gdcm { class TransferSyntax; class DataElement; /** * \brief Coder */ class GDCM_EXPORT Coder { public: virtual ~Coder() = default; /// Return whether this coder support this transfer syntax (can code it) virtual bool CanCode(TransferSyntax const &) const = 0; // Note: in / out are reserved keyword in C#. Change to in_ / out_ /// Code virtual bool Code(DataElement const &in_, DataElement &out_) { (void)in_; (void)out_; return false; } protected: virtual bool InternalCode(const char *bv, unsigned long len, std::ostream &os) { (void)bv;(void)os;(void)len;return false; } }; } // end namespace gdcm #endif //GDCMCODER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmConstCharWrapper.h000066400000000000000000000031531412732066400247450ustar00rootroot00000000000000/*========================================================================= 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 GDCMCONSTCHARWRAPPER_H #define GDCMCONSTCHARWRAPPER_H namespace gdcm { #error /* * This class is a pure hack. Its only goal is to work around a bad bug in : * $ swig -version * SWIG Version 1.3.31 * * See * - http://sourceforge.net/mailarchive/forum.php?thread_name=bf0c3b3f0802290552y5163989t76572b80a044ce28%40mail.gmail.com&forum_name=swig-user * * 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: * * - http://sourceforge.net/mailarchive/forum.php?thread_name=bf0c3b3f0802290552y5163989t76572b80a044ce28%40mail.gmail.com&forum_name=swig-user */ /** * \brief Do not use me */ class ConstCharWrapper { public: ConstCharWrapper(const char *i=0):Internal(i) {} operator const char * () const { return Internal; } private: const char *Internal; }; } // end namespace gdcm #endif //GDCMCONSTCHARWRAPPER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmCurve.cxx000066400000000000000000000415121412732066400231600ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCurve.h" #include "gdcmDataElement.h" #include "gdcmDataSet.h" #include "gdcmAttribute.h" #include namespace gdcm { /* C.10.2.1 Curve Attribute Descriptions C.10.2.1.1 Type of data A description of the Type of Data (50xx,0020) in this curve. Defined Terms: TAC = time activity curve PROF = image profile HIST = histogram ROI = polygraphic region of interest TABL = table of values FILT = filter kernel POLY = poly line ECG = ecg data PRESSURE = pressure data FLOW = flow data PHYSIO = physio data RESP = Respiration trace */ class CurveInternal { public: CurveInternal(): TypeOfData(), CurveDescription(), Data() {} /* (5004,0000) UL 2316 # 4, 1 CurveGroupLength (5004,0005) US 1 # 2, 1 CurveDimensions (5004,0010) US 1126 # 2, 1 NumberOfPoints (5004,0020) CS [PHYSIO] # 6, 1 TypeOfData (5004,0022) LO (no value available) # 0, 0 CurveDescription (5000,0030) SH [DPPS\NONE] # 10, 2 AxisUnits (5004,0103) US 0 # 2, 1 DataValueRepresentation (5000,0110) US 0\1 # 4, 2 CurveDataDescriptor (5000,0112) US 0 # 2, 1 CoordinateStartValue (5000,0114) US 300 # 2, 1 CoordinateStepValue (5000,2500) LO [Physio_1] # 8, 1 CurveLabel (5004,3000) OW 0020\0020\0020\0020\0020\0020\0020\0020\0020\0020\0020\0020\0020... # 2252, 1 CurveData */ // Identifier need to be in the [5000,50FF] range (no odd number): unsigned short Group{0}; unsigned short Dimensions{0}; unsigned short NumberOfPoints{0}; std::string TypeOfData; std::string CurveDescription; unsigned short DataValueRepresentation{0}; std::vector Data; std::vector CurveDataDescriptor; unsigned short CoordinateStartValue; unsigned short CoordinateStepValue; void Print(std::ostream &os) const { os << "Group 0x" << std::hex << Group << std::dec << std::endl; os << "Dimensions :" << Dimensions << std::endl; os << "NumberOfPoints :" << NumberOfPoints << std::endl; 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]; for(int i = 0; i < NumberOfPoints; i+=2) { os << p[i] << "," << p[i+1] << std::endl; } } }; Curve::Curve() { Internal = new CurveInternal; } Curve::~Curve() { delete Internal; } Curve::Curve(Curve const &ov):Object(ov) { //delete Internal; Internal = new CurveInternal; // TODO: copy CurveInternal into other... *Internal = *ov.Internal; } void Curve::Print(std::ostream &os) const { Internal->Print( os ); } unsigned int Curve::GetNumberOfCurves(DataSet const & ds) { Tag overlay(0x5000,0x0000); // First possible overlay bool finished = false; unsigned int numoverlays = 0; while( !finished ) { const DataElement &de = ds.FindNextDataElement( overlay ); if( de.GetTag().GetGroup() > 0x50FF ) // last possible curve { finished = true; } else if( de.GetTag().IsPrivate() ) { // Move on to the next public one: overlay.SetGroup( (uint16_t)(de.GetTag().GetGroup() + 1) ); overlay.SetElement( 0 ); // reset just in case... } else { // Yeah this is an overlay element //if( ds.FindDataElement( Tag(overlay.GetGroup(),0x3000 ) ) ) if( ds.FindDataElement( Tag(de.GetTag().GetGroup(),0x3000 ) ) ) { // ok so far so good... //const DataElement& overlaydata = ds.GetDataElement(Tag(overlay.GetGroup(),0x3000)); const DataElement& overlaydata = ds.GetDataElement(Tag(de.GetTag().GetGroup(),0x3000)); if( !overlaydata.IsEmpty() ) { ++numoverlays; } } // Store found tag in overlay: overlay = de.GetTag(); // Move on to the next possible one: overlay.SetGroup( (uint16_t)(overlay.GetGroup() + 2) ); // reset to element 0x0 just in case... overlay.SetElement( 0 ); } } return numoverlays; } void Curve::Update(const DataElement & de) { assert( de.GetTag().IsPublic() ); const ByteValue* bv = de.GetByteValue(); if( !bv ) return; // Discard any empty element (will default to another value) assert( bv->GetPointer() && bv->GetLength() ); std::string s( bv->GetPointer(), bv->GetLength() ); // What if a \0 can be found before the end of string... //assert( strlen( s.c_str() ) == s.size() ); // First thing check consistency: if( !GetGroup() ) { SetGroup( de.GetTag().GetGroup() ); } else // check consistency { assert( GetGroup() == de.GetTag().GetGroup() ); // programmer error } //std::cerr << "Tag: " << de.GetTag() << std::endl; if( de.GetTag().GetElement() == 0x0000 ) // CurveGroupLength { // ?? } else if( de.GetTag().GetElement() == 0x0005 ) // CurveDimensions { Attribute<0x5000,0x0005> at; at.SetFromDataElement( de ); SetDimensions( at.GetValue() ); } else if( de.GetTag().GetElement() == 0x0010 ) // NumberOfPoints { Attribute<0x5000,0x0010> at; at.SetFromDataElement( de ); SetNumberOfPoints( at.GetValue() ); } else if( de.GetTag().GetElement() == 0x0020 ) // TypeOfData { SetTypeOfData( s.c_str() ); } else if( de.GetTag().GetElement() == 0x0022 ) // CurveDescription { SetCurveDescription( s.c_str() ); } else if( de.GetTag().GetElement() == 0x0030 ) // AxisUnits { gdcmWarningMacro( "TODO" ); } else if( de.GetTag().GetElement() == 0x0040 ) // Axis Labels { gdcmWarningMacro( "TODO" ); } else if( de.GetTag().GetElement() == 0x0103 ) // DataValueRepresentation { Attribute<0x5000,0x0103> at; at.SetFromDataElement( de ); SetDataValueRepresentation( at.GetValue() ); } else if( de.GetTag().GetElement() == 0x0104 ) // Minimum Coordinate Value { gdcmWarningMacro( "TODO" ); } else if( de.GetTag().GetElement() == 0x0105 ) // Maximum Coordinate Value { gdcmWarningMacro( "TODO" ); } else if( de.GetTag().GetElement() == 0x0106 ) // Curve Range { gdcmWarningMacro( "TODO" ); } else if( de.GetTag().GetElement() == 0x0110 ) // CurveDataDescriptor { Attribute<0x5000,0x0110> at; at.SetFromDataElement( de ); SetCurveDataDescriptor( at.GetValues(), at.GetNumberOfValues() ); } else if( de.GetTag().GetElement() == 0x0112 ) // CoordinateStartValue { Attribute<0x5000,0x0112> at; at.SetFromDataElement( de ); SetCoordinateStartValue( at.GetValue() ); } else if( de.GetTag().GetElement() == 0x0114 ) // CoordinateStepValue { Attribute<0x5000,0x0114> at; at.SetFromDataElement( de ); SetCoordinateStepValue( at.GetValue() ); } else if( de.GetTag().GetElement() == 0x2500 ) // CurveLabel { gdcmWarningMacro( "TODO" ); } else if( de.GetTag().GetElement() == 0x2600 ) // Referenced Overlay Sequence { gdcmWarningMacro( "TODO" ); } else if( de.GetTag().GetElement() == 0x2610 ) // Referenced Overlay Group { gdcmWarningMacro( "TODO" ); } else if( de.GetTag().GetElement() == 0x3000 ) // CurveData { SetCurve(bv->GetPointer(), bv->GetLength()); } else { assert( 0 && "should not happen: Unknown curve tag" ); } } void Curve::SetGroup(unsigned short group) { Internal->Group = group; } unsigned short Curve::GetGroup() const { return Internal->Group; } void Curve::SetDimensions(unsigned short dimensions) { Internal->Dimensions = dimensions; } unsigned short Curve::GetDimensions() const { return Internal->Dimensions; } void Curve::SetNumberOfPoints(unsigned short numberofpoints) { Internal->NumberOfPoints = numberofpoints; } unsigned short Curve::GetNumberOfPoints() const { return Internal->NumberOfPoints; } void Curve::SetTypeOfData(const char *typeofdata) { if( typeofdata ) Internal->TypeOfData = typeofdata; } const char *Curve::GetTypeOfData() const { return Internal->TypeOfData.c_str(); } static const char * const TypeOfDataDescription[][2] = { { "TAC" , "time activity curve" }, { "PROF" , "image profile" }, { "HIST" , "histogram" }, { "ROI" , "polygraphic region of interest" }, { "TABL" , "table of values" }, { "FILT" , "filter kernel" }, { "POLY" , "poly line" }, { "ECG" , "ecg data" }, { "PRESSURE" , "pressure data" }, { "FLOW" , "flow data" }, { "PHYSIO" , "physio data" }, { "RESP" , "Respiration trace" }, { nullptr , nullptr } }; const char *Curve::GetTypeOfDataDescription() const { using TypeOfDataDescriptionType = const char *const (*)[2]; TypeOfDataDescriptionType t = TypeOfDataDescription; int i = 0; const char *p = t[i][0]; while( p ) { if( Internal->TypeOfData == p ) { break; } ++i; p = t[i][0]; } return t[i][1]; } void Curve::SetCurveDescription(const char *curvedescription) { if( curvedescription ) Internal->CurveDescription = curvedescription; } void Curve::SetDataValueRepresentation(unsigned short datavaluerepresentation) { Internal->DataValueRepresentation = datavaluerepresentation; } unsigned short Curve::GetDataValueRepresentation() const { return Internal->DataValueRepresentation; } void Curve::SetCurveDataDescriptor(const uint16_t * values, size_t num) { Internal->CurveDataDescriptor = std::vector(values, values+num); } std::vector const &Curve::GetCurveDataDescriptor() const { return Internal->CurveDataDescriptor; } void Curve::SetCoordinateStartValue( unsigned short v ) { Internal->CoordinateStartValue = v; } void Curve::SetCoordinateStepValue( unsigned short v ) { Internal->CoordinateStepValue = v; } bool Curve::IsEmpty() const { return Internal->Data.empty(); } void Curve::SetCurve(const char *array, unsigned int length) { if( !array || length == 0 ) return; Internal->Data.resize( length ); std::copy(array, array+length, Internal->Data.begin()); //assert( 8 * length == (unsigned int)Internal->Rows * Internal->Columns ); //assert( Internal->Data.size() == length ); } void Curve::Decode(std::istream &is, std::ostream &os) { (void)is; (void)os; assert(0); } /* PS 3.3 - 2004 C.10.2.1.2 Data value representation 0000H = unsigned short (US) 0001H = signed short (SS) 0002H = floating point single (FL) 0003H = floating point double (FD) 0004H = signed long (SL) */ inline size_t getsizeofrep( unsigned short dr ) { size_t val = 0; switch( dr ) { case 0: val = sizeof( uint16_t ); break; case 1: val = sizeof( int16_t ); break; case 2: val = sizeof( float ); break; case 3: val = sizeof( double ); break; case 4: val = sizeof( int32_t ); break; } return val; } /* C.10.2.1.5 Curve data descriptor, coordinate start value, coordinate step value The Curve Data for dimension(s) containing evenly distributed data can be eliminated by using a method that defines the Coordinate Start Value and Coordinate Step Value (interval). The one dimensional data list is then calculated rather than being enumerated. For the Curve Data Descriptor (50xx,0110) an Enumerated Value describing how each component of the N-tuple curve is described, either by points or interval spacing. One value for each dimension. Where: 0000H = Dimension component described using interval spacing 0001H = Dimension component described using values Using interval spacing: Dimension component(s) described by interval spacing use Attributes of Coordinate Start Value (50xx,0112), Coordinate Step Value (50xx,0114) and Number of Points (50xx,0010). The 1- dimensional data list is calculated by using a start point of Coordinate Start Value and adding the interval (Coordinate Step Value) to obtain each data point until the Number of Points is satisfied. The data points of this dimension will be absent from Curve Data (50xx,3000). */ double Curve::ComputeValueFromStartAndStep(unsigned int idx) const { assert( !Internal->CurveDataDescriptor.empty() ); const double res = Internal->CoordinateStartValue + Internal->CoordinateStepValue * idx; return res; } void Curve::GetAsPoints(float *array) const { assert( getsizeofrep(Internal->DataValueRepresentation) ); if( Internal->CurveDataDescriptor.empty() ) { assert( Internal->Data.size() == (uint32_t)Internal->NumberOfPoints * Internal->Dimensions * getsizeofrep( Internal->DataValueRepresentation) ); } else { assert( Internal->Data.size() == (uint32_t)Internal->NumberOfPoints * 1 * getsizeofrep( Internal->DataValueRepresentation) ); } assert( Internal->Dimensions == 1 || Internal->Dimensions == 2 ); const int mult = Internal->Dimensions; int genidx = -1; if( !Internal->CurveDataDescriptor.empty() ) { assert( Internal->CurveDataDescriptor.size() == Internal->Dimensions ); assert( Internal->CurveDataDescriptor.size() == 2 ); // FIXME if( Internal->CurveDataDescriptor[0] == 0 ) { assert( Internal->CurveDataDescriptor[1] == 1 ); genidx = 0; } else if( Internal->CurveDataDescriptor[1] == 0 ) { assert( Internal->CurveDataDescriptor[0] == 1 ); genidx = 1; } else { assert( 0 && "TODO" ); } } const char * beg = &Internal->Data[0]; const char * end = beg + Internal->Data.size(); if( genidx == -1 ) { assert( end == beg + 2 * Internal->NumberOfPoints ); (void)beg;(void)end; } else { assert( end == beg + mult * Internal->NumberOfPoints ); (void)beg;(void)end; } if( Internal->DataValueRepresentation == 0 ) { // 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]; // X if( genidx == 0 ) for(int i = 0; i < Internal->NumberOfPoints; i++ ) array[3*i+0] = (float)ComputeValueFromStartAndStep( i ); else for(int i = 0; i < Internal->NumberOfPoints; i++ ) array[3*i+0] = p[i + 0]; // Y if( genidx == 1 ) for(int i = 0; i < Internal->NumberOfPoints; i++ ) array[3*i+1] = (float)ComputeValueFromStartAndStep( i ); else { if( mult == 2 && genidx == -1 ) { for(int i = 0; i < Internal->NumberOfPoints; i++ ) array[3*i+1] = p[i + 1]; } else if( mult == 2 && genidx == 0 ) { for(int i = 0; i < Internal->NumberOfPoints; i++ ) array[3*i+1] = p[i + 0]; } else { for(int i = 0; i < Internal->NumberOfPoints; i++ ) array[3*i+1] = 0; } } // Z for(int i = 0; i < Internal->NumberOfPoints; i++ ) array[3*i+2] = 0; } else if( Internal->DataValueRepresentation == 1 ) { int16_t * p = (int16_t*)(void*)&Internal->Data[0]; for(int i = 0; i < Internal->NumberOfPoints; i++ ) { array[3*i+0] = p[mult*i + 0]; if( mult > 1 ) array[3*i+1] = p[mult*i + 1]; else array[3*i+1] = 0; array[3*i+2] = 0; } } else if( Internal->DataValueRepresentation == 2 ) { float * p = (float*)(void*)&Internal->Data[0]; for(int i = 0; i < Internal->NumberOfPoints; i++ ) { array[3*i+0] = p[mult*i + 0]; if( mult > 1 ) array[3*i+1] = p[mult*i + 1]; else array[3*i+1] = 0; array[3*i+2] = 0; } } else if( Internal->DataValueRepresentation == 3 ) { double * p = (double*)(void*)&Internal->Data[0]; for(int i = 0; i < Internal->NumberOfPoints; i++ ) { array[3*i+0] = (float)p[mult*i + 0]; if( mult > 1 ) array[3*i+1] = (float)p[mult*i + 1]; else array[3*i+1] = 0; array[3*i+2] = 0; } } else if( Internal->DataValueRepresentation == 4 ) { int32_t * p = (int32_t*)(void*)&Internal->Data[0]; for(int i = 0; i < Internal->NumberOfPoints; i++ ) { array[3*i+0] = (float)p[mult*i + 0]; if( mult > 1 ) array[3*i+1] = (float)p[mult*i + 1]; else array[3*i+1] = 0; array[3*i+2] = 0; } } else { assert( 0 ); } } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmCurve.h000066400000000000000000000050761412732066400226120ustar00rootroot00000000000000/*========================================================================= 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 GDCMCURVE_H #define GDCMCURVE_H #include "gdcmTypes.h" #include "gdcmObject.h" #include namespace gdcm { class CurveInternal; class ByteValue; class DataSet; class DataElement; /** * \brief Curve class to handle element 50xx,3000 Curve Data * \details * WARNING: This is deprecated and lastly defined in PS 3.3 - 2004 * * Examples: * - GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm * - GE_DLX-8-MONO2-Multiframe.dcm * - gdcmSampleData/Philips_Medical_Images/integris_HV_5000/xa_integris.dcm * - TOSHIBA-CurveData[1-3].dcm */ class GDCM_EXPORT Curve : public Object { public: Curve(); ~Curve() override; void Print(std::ostream &) const override; void GetAsPoints(float *array) const; static unsigned int GetNumberOfCurves(DataSet const & ds); // Update curve data from dataelmenet de: void Update(const DataElement & de); void SetGroup(unsigned short group); unsigned short GetGroup() const; void SetDimensions(unsigned short dimensions); unsigned short GetDimensions() const; void SetNumberOfPoints(unsigned short numberofpoints); unsigned short GetNumberOfPoints() const; void SetTypeOfData(const char *typeofdata); const char *GetTypeOfData() const; // See PS 3.3 - 2004 - C.10.2.1.1 Type of data const char *GetTypeOfDataDescription() const; void SetCurveDescription(const char *curvedescription); void SetDataValueRepresentation(unsigned short datavaluerepresentation); unsigned short GetDataValueRepresentation() const; void SetCurveDataDescriptor(const uint16_t * values, size_t num); std::vector const &GetCurveDataDescriptor() const; void SetCoordinateStartValue( unsigned short v ); void SetCoordinateStepValue( unsigned short v ); void SetCurve(const char *array, unsigned int length); bool IsEmpty() const; void Decode(std::istream &is, std::ostream &os); Curve(Curve const &ov); private: double ComputeValueFromStartAndStep(unsigned int idx) const; CurveInternal *Internal; }; } // end namespace gdcm #endif //GDCMCURVE_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDICOMDIR.cxx000066400000000000000000000011411412732066400232600ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDICOMDIR.h" namespace gdcm {} GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDICOMDIR.h000066400000000000000000000020031412732066400227030ustar00rootroot00000000000000/*========================================================================= 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 GDCMDICOMDIR_H #define GDCMDICOMDIR_H #include #include "gdcmFileSet.h" namespace gdcm { /** * \brief DICOMDIR class * * \details Structured for handling DICOMDIR */ class GDCM_EXPORT DICOMDIR { public: DICOMDIR() = default; DICOMDIR(FileSet fs):_FS(std::move(std::move(fs))) {} private: FileSet _FS; //13 sept 2010 mmr-- added the underscore to FS to compile under Sunos gcc }; } // end namespace gdcm #endif //GDCMDICOMDIR_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDICOMDIRGenerator.cxx000066400000000000000000001142131412732066400251340ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDICOMDIRGenerator.h" #include "gdcmFile.h" #include "gdcmSmartPointer.h" #include "gdcmUIDGenerator.h" #include "gdcmFilename.h" #include "gdcmScanner.h" #include "gdcmAttribute.h" #include "gdcmSequenceOfItems.h" #include "gdcmFileMetaInformation.h" #include "gdcmExplicitDataElement.h" #include "gdcmTag.h" #include "gdcmVR.h" #include "gdcmCodeString.h" namespace gdcm { class DICOMDIRGeneratorInternal { public: DICOMDIRGeneratorInternal():F(new File) {} SmartPointer F; using FilenamesType = Directory::FilenamesType; FilenamesType fns; using FilenameType = Directory::FilenameType; FilenameType rootdir; Scanner scanner; std::vector OffsetTable; std::string FileSetID; }; bool DICOMDIRGenerator::ComputeDirectoryRecordsOffset(const SequenceOfItems *sqi, VL start) { SequenceOfItems::SizeType nitems = sqi->GetNumberOfItems(); std::vector &offsets = Internals->OffsetTable; Internals->OffsetTable.resize( nitems + 1 ); offsets[0] = start; for(SequenceOfItems::SizeType i = 1; i <= nitems; ++i) { const Item &item = sqi->GetItem(i); offsets[i] = offsets[i-1] + item.GetLength(); } //#define MDEBUG #ifdef MDEBUG for(unsigned int i = 0; i <= nitems; ++i) { std::cout << "offset #" << i << " -> "<< offsets[i] << std::endl; } #endif return true; } static const char *GetLowerLevelDirectoryRecord(const char *input) { if( !input ) return nullptr; if( strcmp( input, "PATIENT " ) == 0 ) { return "STUDY "; } else if( strcmp( input, "STUDY ") == 0 ) { return "SERIES"; } else if( strcmp( input, "SERIES" ) == 0 ) { return "IMAGE "; } else if( strcmp( input, "IMAGE " ) == 0 ) { return nullptr; } assert( 0 ); //std::cerr << "COULD NOT FIND:" << input << std::endl; return nullptr; } DICOMDIRGenerator::MyPair DICOMDIRGenerator::GetReferenceValueForDirectoryType(size_t itemidx) { /* * PS 3.11 - 2008 / D.3.3 Directory Information in DICOMDIR * The Patient ID at the patient level shall be unique for each patient directory record in one File Set. */ /* * This function will return the Patient ID when directorytype == "PATIENT" * This function will return the Study Instance UID when directorytype == "STUDY" * This function will return the Series Instance UID when directorytype == "SERIES" * This function will return the SOP Instance UID when directorytype == "IMAGE" */ MyPair ret; const SequenceOfItems *sqi = GetDirectoryRecordSequence(); const Item &item = sqi->GetItem(itemidx); const DataSet &ds = item.GetNestedDataSet(); Attribute<0x4,0x1430> directoryrecordtype; directoryrecordtype.Set( ds ); const char *input = directoryrecordtype.GetValue(); assert( input ); if( strcmp( input, "PATIENT " ) == 0 ) { Attribute<0x10,0x20> patientid; patientid.Set( ds ); assert( patientid.GetValue() ); ret.first = patientid.GetValue(); ret.second = patientid.GetTag(); } else if( strcmp( input, "STUDY ") == 0 ) { Attribute <0x20,0xd> studyuid; studyuid.Set( ds ); assert( studyuid.GetValue() ); ret.first = studyuid.GetValue(); ret.second = studyuid.GetTag(); } else if( strcmp( input, "SERIES" ) == 0 ) { Attribute <0x20,0xe> seriesuid; seriesuid.Set( ds ); assert( seriesuid.GetValue() ); ret.first = seriesuid.GetValue(); ret.second = seriesuid.GetTag(); } else if( strcmp( input, "IMAGE " ) == 0 ) { Attribute <0x04,0x1511> sopuid; sopuid.Set( ds ); assert( sopuid.GetValue() ); ret.first = sopuid.GetValue(); ret.second = Tag(0x8,0x18); // watch out ! } else { assert( 0 ); } return ret; } static Tag GetParentTag(Tag const &t) { Tag ret; if( t == Tag(0x8,0x18) ) { ret = Tag(0x20,0xe); } else if( t == Tag(0x20,0xe) ) { ret = Tag(0x20,0xd); } else if( t == Tag(0x20,0xd) ) { ret = Tag(0x10,0x20); } else if( t == Tag(0x10,0x20) ) { ret = Tag(0x0,0x0); } else { assert( 0 ); } return ret; } bool DICOMDIRGenerator::SeriesBelongToStudy(const char *seriesuid, const char *studyuid) { assert( seriesuid ); assert( studyuid ); const Scanner &scanner = GetScanner(); Scanner::TagToValue const &ttv = scanner.GetMappingFromTagToValue(Tag(0x20,0xe), seriesuid); Tag tstudyuid(0x20,0xd); bool b = false; if( ttv.find( tstudyuid ) != ttv.end() ) { const char *v = ttv.find(tstudyuid)->second; if( v && strcmp(v, studyuid ) == 0 ) { b = true; } } return b; } bool DICOMDIRGenerator::ImageBelongToSeries(const char *sopuid, const char *seriesuid, Tag const &t1, Tag const &t2) { assert( seriesuid ); assert( sopuid ); const Scanner &scanner = GetScanner(); Scanner::TagToValue const &ttv = scanner.GetMappingFromTagToValue(t1, sopuid); bool b = false; if( ttv.find( t2 ) != ttv.end() ) { const char *v = ttv.find(t2)->second; if( v && strcmp(v, seriesuid) == 0 ) { b = true; } } return b; } bool DICOMDIRGenerator::ImageBelongToSameSeries(const char *sopuid1, const char *sopuid2, Tag const &t) { assert( sopuid1 ); assert( sopuid2 ); const Scanner &scanner = GetScanner(); Scanner::TagToValue const &ttv1 = scanner.GetMappingFromTagToValue(t, sopuid1); Scanner::TagToValue const &ttv2 = scanner.GetMappingFromTagToValue(t, sopuid2); Tag tseriesuid = GetParentTag( t ); if( tseriesuid == Tag(0x0,0x0) ) { // Let's pretend that Patient belong to the same 'root' element: return true; } bool b = false; const char *seriesuid1 = nullptr; if( ttv1.find( tseriesuid ) != ttv1.end() ) { seriesuid1 = ttv1.find(tseriesuid)->second; } const char *seriesuid2 = nullptr; if( ttv2.find( tseriesuid ) != ttv2.end() ) { seriesuid2 = ttv2.find(tseriesuid)->second; } assert( seriesuid1 ); assert( seriesuid2 ); b = strcmp( seriesuid1, seriesuid2) == 0; return b; } size_t DICOMDIRGenerator::FindLowerLevelDirectoryRecord( size_t item1, const char *directorytype ) { // return FindNextDirectoryRecord( item1, GetLowerLevelDirectoryRecord( directorytype ) ); const char *lowerdirectorytype = GetLowerLevelDirectoryRecord( directorytype ); if( !lowerdirectorytype ) return 0; const SequenceOfItems *sqi = GetDirectoryRecordSequence(); SequenceOfItems::SizeType nitems = sqi->GetNumberOfItems(); for(SequenceOfItems::SizeType i = item1 + 1; i <= nitems; ++i) { const Item &item = sqi->GetItem(i); const DataSet &ds = item.GetNestedDataSet(); Attribute<0x4,0x1430> directoryrecordtype; directoryrecordtype.Set( ds ); // found a match ? if( strcmp( lowerdirectorytype, directoryrecordtype.GetValue() ) == 0 ) { // Need to make sure belong to same parent record: MyPair refval1 = GetReferenceValueForDirectoryType(item1); MyPair refval2 = GetReferenceValueForDirectoryType(i); bool b = ImageBelongToSeries(refval2.first.c_str(), refval1.first.c_str(), refval2.second, refval1.second); if( b ) return i; } //assert( strncmp( lowerdirectorytype, directoryrecordtype.GetValue(), strlen( lowerdirectorytype ) ) != 0 ); } // Not found return 0; } /* * Finding the next Directory Record type is easy, simply starting from the start and iterating * to the end guarantee travering everything without omitting anyone. * * TODO: Need to make sure that Series belong to the same Study... */ size_t DICOMDIRGenerator::FindNextDirectoryRecord( size_t item1, const char *directorytype ) { if( !directorytype ) return 0; const SequenceOfItems *sqi = GetDirectoryRecordSequence(); SequenceOfItems::SizeType nitems = sqi->GetNumberOfItems(); for(SequenceOfItems::SizeType i = item1 + 1; i <= nitems; ++i) { const Item &item = sqi->GetItem(i); const DataSet &ds = item.GetNestedDataSet(); Attribute<0x4,0x1430> directoryrecordtype; directoryrecordtype.Set( ds ); // found a match ? if( strcmp( directorytype, directoryrecordtype.GetValue() ) == 0 ) { // Need to make sure belong to same parent record: MyPair refval1 = GetReferenceValueForDirectoryType(item1); MyPair refval2 = GetReferenceValueForDirectoryType(i); bool b = ImageBelongToSameSeries(refval1.first.c_str(), refval2.first.c_str(), refval1.second); if( b ) return i; } //assert( strncmp( directorytype, directoryrecordtype.GetValue(), strlen( directorytype ) ) != 0 ); } // Not found return 0; } bool DICOMDIRGenerator::TraverseDirectoryRecords(VL start ) { SequenceOfItems *sqi = GetDirectoryRecordSequence(); ComputeDirectoryRecordsOffset(sqi, start); SequenceOfItems::SizeType nitems = sqi->GetNumberOfItems(); for(SequenceOfItems::SizeType i = 1; i <= nitems; ++i) { Item &item = sqi->GetItem(i); DataSet &ds = item.GetNestedDataSet(); Attribute<0x4,0x1430> directoryrecordtype; directoryrecordtype.Set( ds ); //std::cout << "FOUND DIRECTORY TYPE:" << directoryrecordtype.GetValue() << std::endl; size_t next = FindNextDirectoryRecord( i, directoryrecordtype.GetValue() ); if( next ) { Attribute<0x4,0x1400> offsetofthenextdirectoryrecord = {0}; offsetofthenextdirectoryrecord.SetValue( Internals->OffsetTable[ next - 1 ] ); ds.Replace( offsetofthenextdirectoryrecord.GetAsDataElement() ); } size_t lower = FindLowerLevelDirectoryRecord( i, directoryrecordtype.GetValue() ); if( lower ) { Attribute<0x4,0x1420> offsetofreferencedlowerleveldirectoryentity = {0}; offsetofreferencedlowerleveldirectoryentity.SetValue( Internals->OffsetTable[ lower - 1 ] ); ds.Replace( offsetofreferencedlowerleveldirectoryentity.GetAsDataElement() ); } } return true; } template void SingleDataElementInserter(DataSet &ds, Scanner const & scanner) { Attribute patientsname; Scanner::ValuesType patientsnames = scanner.GetValues( patientsname.GetTag() ); #ifndef NDEBUG const unsigned int npatient = patientsnames.size(); assert( npatient == 1 ); #endif Scanner::ValuesType::const_iterator it = patientsnames.begin(); patientsname.SetValue( it->c_str() ); ds.Insert( patientsname.GetAsDataElement() ); } /* (fffe,e000) na "Directory Record" PATIENT #=8 # u/l, 1 Item # offset=$374 (0004,1400) up 0 # 4, 1 OffsetOfTheNextDirectoryRecord (0004,1410) US 65535 # 2, 1 RecordInUseFlag (0004,1420) up 502 # 4, 1 OffsetOfReferencedLowerLevelDirectoryEntity (0004,1430) CS [PATIENT] # 8, 1 DirectoryRecordType (0010,0010) PN [Test^PixelSpacing] # 18, 1 PatientsName (0010,0020) LO [62354PQGRRST] # 12, 1 PatientID (0010,0030) DA (no value available) # 0, 0 PatientsBirthDate (0010,0040) CS (no value available) # 0, 0 PatientsSex (fffe,e00d) na "ItemDelimitationItem" # 0, 0 ItemDelimitationItem */ bool DICOMDIRGenerator::AddPatientDirectoryRecord() { DataSet &rootds = GetFile().GetDataSet(); Scanner const & scanner = GetScanner(); Attribute<0x10,0x20> patientid; Scanner::ValuesType patientids = scanner.GetValues( patientid.GetTag() ); //unsigned int npatients = patientids.size(); const DataElement &de = rootds.GetDataElement( Tag(0x4,0x1220) ); //SequenceOfItems * sqi = (SequenceOfItems*)de.GetSequenceOfItems(); SmartPointer sqi = de.GetValueAsSQ(); Scanner::ValuesType::const_iterator it = patientids.begin(); for( ; it != patientids.end(); ++it) { Item item; item.SetVLToUndefined(); DataSet &ds = item.GetNestedDataSet(); // (0004,1400) up 0 # 4, 1 OffsetOfTheNextDirectoryRecord // (0004,1410) US 65535 # 2, 1 RecordInUseFlag // (0004,1420) up 502 # 4, 1 OffsetOfReferencedLowerLevelDirectoryEntity // (0004,1430) CS [PATIENT] # 8, 1 DirectoryRecordType Attribute<0x4,0x1400> offsetofthenextdirectoryrecord = {0}; ds.Insert( offsetofthenextdirectoryrecord.GetAsDataElement() ); Attribute<0x4,0x1410> recordinuseflag = {0xFFFF}; ds.Insert( recordinuseflag.GetAsDataElement() ); Attribute<0x4,0x1420> offsetofreferencedlowerleveldirectoryentity = {0}; ds.Insert( offsetofreferencedlowerleveldirectoryentity.GetAsDataElement() ); Attribute<0x4,0x1430> directoryrecordtype; directoryrecordtype.SetValue( "PATIENT" ); ds.Insert( directoryrecordtype.GetAsDataElement() ); const char *pid = it->c_str(); if( ! (pid && *pid) ) { const char *fn = scanner.GetFilenameFromTagToValue(patientid.GetTag(), pid); gdcmErrorMacro( "Missing Patient ID from file: " << fn ); (void)fn; //warning removal return false; } gdcmAssertAlwaysMacro( pid && *pid ); patientid.SetValue( pid ); ds.Insert( patientid.GetAsDataElement() ); Scanner::TagToValue const &ttv = scanner.GetMappingFromTagToValue(patientid.GetTag(), pid); Attribute<0x10,0x10> patientsname; if( ttv.find( patientsname.GetTag() ) != ttv.end() ) { patientsname.SetValue( ttv.find(patientsname.GetTag())->second ); ds.Insert( patientsname.GetAsDataElement() ); } //SingleDataElementInserter<0x10,0x10>(ds, scanner); //SingleDataElementInserter<0x10,0x20>(ds, scanner); //SingleDataElementInserter<0x10,0x30>(ds, scanner); //SingleDataElementInserter<0x10,0x40>(ds, scanner); sqi->AddItem( item ); } return true; } /* (fffe,e000) na "Directory Record" STUDY #=10 # u/l, 1 Item # offset=$502 (0004,1400) up 0 # 4, 1 OffsetOfTheNextDirectoryRecord (0004,1410) US 65535 # 2, 1 RecordInUseFlag (0004,1420) up 748 # 4, 1 OffsetOfReferencedLowerLevelDirectoryEntity (0004,1430) CS [STUDY] # 6, 1 DirectoryRecordType (0008,0020) DA [20050624] # 8, 1 StudyDate (0008,0030) TM [104221] # 6, 1 StudyTime (0008,0050) SH [8-13547713751] # 14, 1 AccessionNumber (0008,1030) LO [Test support of different pixel spacing attributes] # 50, 1 StudyDescription (0020,000d) UI [1.3.6.1.4.1.5962.1.2.65535.1119624141.7160.0] # 44, 1 StudyInstanceUID (0020,0010) SH [734591762345] # 12, 1 StudyID (fffe,e00d) na "ItemDelimitationItem" # 0, 0 ItemDelimitationItem */ bool DICOMDIRGenerator::AddStudyDirectoryRecord() { DataSet &rootds = GetFile().GetDataSet(); Scanner const & scanner = GetScanner(); Attribute<0x20,0xd> studyinstanceuid; Scanner::ValuesType studyinstanceuids = scanner.GetValues( studyinstanceuid.GetTag() ); const DataElement &de = rootds.GetDataElement( Tag(0x4,0x1220) ); //SequenceOfItems * sqi = (SequenceOfItems*)de.GetSequenceOfItems(); SmartPointer sqi = de.GetValueAsSQ(); Scanner::ValuesType::const_iterator it = studyinstanceuids.begin(); for( ; it != studyinstanceuids.end(); ++it) { Item item; item.SetVLToUndefined(); DataSet &ds = item.GetNestedDataSet(); Attribute<0x4,0x1400> offsetofthenextdirectoryrecord = {0}; ds.Insert( offsetofthenextdirectoryrecord.GetAsDataElement() ); Attribute<0x4,0x1410> recordinuseflag = {0xFFFF}; ds.Insert( recordinuseflag.GetAsDataElement() ); Attribute<0x4,0x1420> offsetofreferencedlowerleveldirectoryentity = {0}; ds.Insert( offsetofreferencedlowerleveldirectoryentity.GetAsDataElement() ); Attribute<0x4,0x1430> directoryrecordtype; directoryrecordtype.SetValue( "STUDY" ); ds.Insert( directoryrecordtype.GetAsDataElement() ); const char *studyuid = it->c_str(); if( ! (studyuid && *studyuid) ) { const char *fn = scanner.GetFilenameFromTagToValue(studyinstanceuid.GetTag(), studyuid); gdcmErrorMacro( "Missing Study Instance UID from file: " << fn ); (void)fn;//warning removal return false; } gdcmAssertAlwaysMacro( studyuid && *studyuid ); studyinstanceuid.SetValue( studyuid ); ds.Insert( studyinstanceuid.GetAsDataElement() ); //SingleDataElementInserter<0x20,0xd>(ds, scanner); //SingleDataElementInserter<0x8,0x20>(ds, scanner); //SingleDataElementInserter<0x8,0x30>(ds, scanner); //SingleDataElementInserter<0x8,0x1030>(ds, scanner); //SingleDataElementInserter<0x8,0x50>(ds, scanner); //SingleDataElementInserter<0x20,0x10>(ds, scanner); Scanner::TagToValue const &ttv = scanner.GetMappingFromTagToValue(studyinstanceuid.GetTag(), studyuid); Attribute<0x8,0x20> studydate; if( ttv.find( studydate.GetTag() ) != ttv.end() ) { studydate.SetValue( ttv.find(studydate.GetTag())->second ); ds.Insert( studydate.GetAsDataElement() ); } Attribute<0x8,0x30> studytime; if( ttv.find( studytime.GetTag() ) != ttv.end() ) { studytime.SetValue( ttv.find(studytime.GetTag())->second ); ds.Insert( studytime.GetAsDataElement() ); } Attribute<0x8,0x1030> studydesc; if( ttv.find( studydesc.GetTag() ) != ttv.end() ) { studydesc.SetValue( ttv.find(studydesc.GetTag())->second ); ds.Insert( studydesc.GetAsDataElement() ); } Attribute<0x8,0x50> accessionnumber; if( ttv.find( accessionnumber.GetTag() ) != ttv.end() ) { accessionnumber.SetValue( ttv.find(accessionnumber.GetTag())->second ); ds.Insert( accessionnumber.GetAsDataElement() ); } Attribute<0x20,0x10> studyid; if( ttv.find( studyid.GetTag() ) != ttv.end() ) { studyid.SetValue( ttv.find(studyid.GetTag())->second ); ds.Insert( studyid.GetAsDataElement() ); } sqi->AddItem( item ); } return true; } /* (fffe,e000) na "Directory Record" SERIES #=11 # u/l, 1 Item # offset=$748 (0004,1400) up 1214 # 4, 1 OffsetOfTheNextDirectoryRecord (0004,1410) US 65535 # 2, 1 RecordInUseFlag (0004,1420) up 938 # 4, 1 OffsetOfReferencedLowerLevelDirectoryEntity (0004,1430) CS [SERIES] # 6, 1 DirectoryRecordType (0008,0060) CS [CR] # 2, 1 Modality (0008,0080) LO (no value available) # 0, 0 InstitutionName (0008,0081) ST (no value available) # 0, 0 InstitutionAddress (0008,103e) LO [Computed Radiography] # 20, 1 SeriesDescription (0008,1050) PN (no value available) # 0, 0 PerformingPhysiciansName (0020,000e) UI [1.3.6.1.4.1.5962.1.3.65535.4.1119624143.7187.0] # 46, 1 SeriesInstanceUID (0020,0011) IS [4] # 2, 1 SeriesNumber (fffe,e00d) na "ItemDelimitationItem" # 0, 0 ItemDelimitationItem */ bool DICOMDIRGenerator::AddSeriesDirectoryRecord() { DataSet &rootds = GetFile().GetDataSet(); Scanner const & scanner = GetScanner(); Attribute<0x20,0xe> seriesinstanceuid; Scanner::ValuesType seriesinstanceuids = scanner.GetValues( seriesinstanceuid.GetTag() ); const DataElement &de = rootds.GetDataElement( Tag(0x4,0x1220) ); //SequenceOfItems * sqi = (SequenceOfItems*)de.GetSequenceOfItems(); SmartPointer sqi = de.GetValueAsSQ(); Scanner::ValuesType::const_iterator it = seriesinstanceuids.begin(); for( ; it != seriesinstanceuids.end(); ++it) { Item item; item.SetVLToUndefined(); DataSet &ds = item.GetNestedDataSet(); Attribute<0x4,0x1400> offsetofthenextdirectoryrecord = {0}; ds.Insert( offsetofthenextdirectoryrecord.GetAsDataElement() ); Attribute<0x4,0x1410> recordinuseflag = {0xFFFF}; ds.Insert( recordinuseflag.GetAsDataElement() ); Attribute<0x4,0x1420> offsetofreferencedlowerleveldirectoryentity = {0}; ds.Insert( offsetofreferencedlowerleveldirectoryentity.GetAsDataElement() ); Attribute<0x4,0x1430> directoryrecordtype; directoryrecordtype.SetValue( "SERIES" ); ds.Insert( directoryrecordtype.GetAsDataElement() ); const char *seriesuid = it->c_str(); if( ! (seriesuid && *seriesuid) ) { const char *fn = scanner.GetFilenameFromTagToValue(seriesinstanceuid.GetTag(), seriesuid); gdcmErrorMacro( "Missing Study Instance UID from file: " << fn ); (void)fn;//warning removal return false; } gdcmAssertAlwaysMacro( seriesuid && *seriesuid ); seriesinstanceuid.SetValue( seriesuid ); ds.Insert( seriesinstanceuid.GetAsDataElement() ); Scanner::TagToValue const &ttv = scanner.GetMappingFromTagToValue(seriesinstanceuid.GetTag(), seriesuid); Attribute<0x8,0x60> modality; if( ttv.find( modality.GetTag() ) != ttv.end() ) { modality.SetValue( ttv.find(modality.GetTag())->second ); ds.Insert( modality.GetAsDataElement() ); } Attribute<0x20,0x11> seriesnumber; if( ttv.find( seriesnumber.GetTag() ) != ttv.end() ) { seriesnumber.SetValue( atoi(ttv.find(seriesnumber.GetTag())->second) ); ds.Insert( seriesnumber.GetAsDataElement() ); } sqi->AddItem( item ); } return true; } /* (fffe,e000) na "Directory Record" IMAGE #=13 # u/l, 1 Item # offset=$1398 refFileID="IMAGES\DXIMAGE" (0004,1400) up 0 # 4, 1 OffsetOfTheNextDirectoryRecord (0004,1410) US 65535 # 2, 1 RecordInUseFlag (0004,1420) up 0 # 4, 1 OffsetOfReferencedLowerLevelDirectoryEntity (0004,1430) CS [IMAGE] # 6, 1 DirectoryRecordType (0004,1500) CS [IMAGES\DXIMAGE] # 14, 2 ReferencedFileID (0004,1510) UI =DigitalXRayImageStorageForPresentation # 28, 1 ReferencedSOPClassUIDInFile (0004,1511) UI [1.3.6.1.4.1.5962.1.1.65535.3.1.1119624143.7180.0] # 48, 1 ReferencedSOPInstanceUIDInFile (0004,1512) UI =LittleEndianExplicit # 20, 1 ReferencedTransferSyntaxUIDInFile (0008,0008) CS [ORIGINAL\PRIMARY] # 16, 2 ImageType (0020,0013) IS [1] # 2, 1 InstanceNumber (0028,0004) CS [MONOCHROME2] # 12, 1 PhotometricInterpretation (0028,0008) IS [1] # 2, 1 NumberOfFrames (0050,0004) CS (no value available) # 0, 0 CalibrationImage (fffe,e00d) na "ItemDelimitationItem" # 0, 0 ItemDelimitationItem */ bool DICOMDIRGenerator::AddImageDirectoryRecord() { DataSet &rootds = GetFile().GetDataSet(); Scanner const & scanner = GetScanner(); const Attribute<0x8,0x18> sopinstanceuid = { "" }; Scanner::ValuesType sopinstanceuids = scanner.GetValues( sopinstanceuid.GetTag() ); //unsigned int ninstance = sopinstanceuids.size(); const DataElement &de = rootds.GetDataElement( Tag(0x4,0x1220) ); //SequenceOfItems * sqi = (SequenceOfItems*)de.GetSequenceOfItems(); SmartPointer sqi = de.GetValueAsSQ(); Scanner::ValuesType::const_iterator it = sopinstanceuids.begin(); Filename rootdir = Internals->rootdir.c_str(); const char *rd = rootdir.ToWindowsSlashes(); size_t strlen_rd = strlen( rd ); for( ; it != sopinstanceuids.end(); ++it) { Item item; item.SetVLToUndefined(); DataSet &ds = item.GetNestedDataSet(); Attribute<0x4,0x1400> offsetofthenextdirectoryrecord = {0}; ds.Insert( offsetofthenextdirectoryrecord.GetAsDataElement() ); Attribute<0x4,0x1410> recordinuseflag = {0xFFFF}; ds.Insert( recordinuseflag.GetAsDataElement() ); Attribute<0x4,0x1420> offsetofreferencedlowerleveldirectoryentity = {0}; ds.Insert( offsetofreferencedlowerleveldirectoryentity.GetAsDataElement() ); Attribute<0x4,0x1430> directoryrecordtype; directoryrecordtype.SetValue( "IMAGE" ); ds.Insert( directoryrecordtype.GetAsDataElement() ); const char *sopuid = it->c_str(); Scanner::TagToValue const &ttv = scanner.GetMappingFromTagToValue(sopinstanceuid.GetTag(), sopuid); Attribute<0x0004,0x1500> referencedfileid; const char *fn_str = scanner.GetFilenameFromTagToValue(sopinstanceuid.GetTag(), sopuid); referencedfileid.SetNumberOfValues( 1 ); Filename fn = fn_str; std::string relative = fn.ToWindowsSlashes(); std::string::size_type l = relative.find( rd ); if( l != std::string::npos ) { assert( l == 0 ); // FIXME relative.replace( l, strlen_rd, "" ); fn = relative.c_str() + 1; } referencedfileid.SetValue( fn.ToWindowsSlashes() ); ds.Insert( referencedfileid.GetAsDataElement() ); Attribute<0x0004,0x1510> referencedsopclassuidinfile; Attribute<0x8,0x16> sopclassuid; if( ttv.find( sopclassuid.GetTag() ) != ttv.end() ) { referencedsopclassuidinfile.SetValue( ttv.find(sopclassuid.GetTag())->second ); } ds.Insert( referencedsopclassuidinfile.GetAsDataElement() ); Attribute<0x0004,0x1511> referencedsopinstanceuidinfile; if( ttv.find( sopinstanceuid.GetTag() ) != ttv.end() ) { referencedsopinstanceuidinfile.SetValue( ttv.find(sopinstanceuid.GetTag())->second ); } ds.Insert( referencedsopinstanceuidinfile.GetAsDataElement() ); Attribute<0x0004,0x1512> referencedtransfersyntaxuidinfile; Attribute<0x2,0x10> transfersyntaxuid; if( ttv.find( transfersyntaxuid.GetTag() ) != ttv.end() ) { referencedtransfersyntaxuidinfile.SetValue( ttv.find(transfersyntaxuid.GetTag())->second ); } ds.Insert( referencedtransfersyntaxuidinfile.GetAsDataElement() ); Attribute<0x20,0x13> instancenumber = { 0 }; if( ttv.find( instancenumber.GetTag() ) != ttv.end() ) { instancenumber.SetValue( atoi(ttv.find(instancenumber.GetTag())->second) ); } ds.Insert( instancenumber.GetAsDataElement() ); Attribute<0x8,0x8> imagetype; //Scanner::ValuesType imagetypes = scanner.GetValues( imagetype.GetTag() ); //Scanner::ValuesType::const_iterator it = imagetypes.begin(); //assert( imagetypes.size() == 1 ); //imagetype.SetNumberOfValues( 1 ); //imagetype.SetValue( it->c_str() ); //ds.Replace( imagetype.GetAsDataElement() ); DataElement de2( imagetype.GetTag() ); de2.SetVR( imagetype.GetVR() ); if( ttv.find( imagetype.GetTag() ) != ttv.end() ) { const char *v = ttv.find(imagetype.GetTag())->second; VL::Type strlenV = (VL::Type)strlen(v); de2.SetByteValue( v, strlenV ); } ds.Insert( de2 ); sqi->AddItem( item ); } return true; } DICOMDIRGenerator::DICOMDIRGenerator( ) { Internals = new DICOMDIRGeneratorInternal; } DICOMDIRGenerator::~DICOMDIRGenerator( ) { delete Internals; } static bool IsCompatibleWithISOIEC9660MediaFormat(const char *filename) { if(!filename) return false; // (0004,1500) CS [IMG001] # 6, 1 ReferencedFileID // Attribute< 0x4, 0x1500 > at; DataElement de( at.GetTag() ); std::string copy = filename; if( copy.size() % 2 ) { copy.push_back( ' ' ); } VL::Type copySize = (VL::Type)copy.size(); de.SetByteValue( copy.c_str(), copySize ) ; at.SetFromDataElement( de ); unsigned int n = at.GetNumberOfValues(); // A volume may have at most 8 levels of directories, where the root // directory is defined as level 1. if( n > 8 ) { gdcmDebugMacro( "8 Levels of directories" ); return false; } for( unsigned int i = 0; i < n; ++i) { CodeString cs = at.GetValue( i ); if( !cs.IsValid() || cs.Size() > 8 ) { gdcmDebugMacro( "Problem with CS: " << cs ); return false; } } return true; } void DICOMDIRGenerator::SetFilenames( FilenamesType const & fns ) { Internals->fns = fns; } void DICOMDIRGenerator::SetRootDirectory( FilenameType const & root ) { Internals->rootdir = root; } bool DICOMDIRGenerator::Generate() { Scanner &scanner = GetScanner(); // scanner.AddTag( Tag(0x02,0x10) ); // scanner.AddTag( Tag(0x10,0x10) ); // scanner.AddTag( Tag(0x10,0x20) ); // scanner.AddTag( Tag(0x8,0x60) ); // scanner.AddTag( Tag(0x20,0x11) ); // scanner.AddTag( Tag(0x8,0x18) ); // scanner.AddTag( Tag(0x8,0x20) ); // scanner.AddTag( Tag(0x8,0x30) ); // scanner.AddTag( Tag(0x8,0x1030) ); // scanner.AddTag( Tag(0x8,0x50) ); // scanner.AddTag( Tag(0x20,0x13) ); // scanner.AddTag( Tag(0x20,0xd) ); // scanner.AddTag( Tag(0x20,0x10) ); // scanner.AddTag( Tag(0x20,0xe) ); // scanner.AddTag( Tag(0x28,0x4) ); // scanner.AddTag( Tag(0x28,0x8) ); // scanner.AddTag( Tag(0x50,0x4) ); // scanner.AddTag( Tag(0x10,0x30) ); // scanner.AddTag( Tag(0x10,0x40) ); // scanner.AddTag( Tag(0x8,0x80) ); // scanner.AddTag( Tag(0x8,0x16) ); // scanner.AddTag( Tag(0x2,0x10) ); // scanner.AddTag( Tag(0x8,0x8) ); FilenamesType const &filenames = Internals->fns; Filename rootdir = Internals->rootdir.c_str(); const char *rd = rootdir.ToWindowsSlashes(); size_t strlen_rd = strlen( rd ); // Let's check that filenames are ok for iso9660 + compatible with VR:CS { FilenamesType::const_iterator it = filenames.begin(); for( ; it != filenames.end(); ++it ) { Filename fn = it->c_str(); const char *f = fn.ToWindowsSlashes(); std::string relative = f; std::string::size_type l = relative.find( rd ); if( l != std::string::npos ) { assert( l == 0 ); // FIXME relative.replace( l, strlen_rd, "" ); f = relative.c_str() + 1; } if( !IsCompatibleWithISOIEC9660MediaFormat( f ) ) { gdcmErrorMacro( "Invalid file name: " << f ); return false; } } } if( !scanner.Scan( filenames ) ) { return false; } //scanner.Print( std::cout ); Scanner::ValuesType vt = scanner.GetValues( Tag(0x2,0x10) ); Scanner::ValuesType vtref; vtref.insert( TransferSyntax::GetTSString( TransferSyntax::ExplicitVRLittleEndian ) ); if( vt == vtref ) { // All files are ExplicitVRLittleEndian which is required for DICOMDIR } else { gdcmErrorMacro( "Found Transfer Syntax not ExplicitVRLittleEndian." ); return false; } // (0004,1220) SQ (Sequence with undefined length #=8) # u/l, 1 DirectoryRecordSequence DataSet &ds = GetFile().GetDataSet(); Attribute<0x4,0x1130> filesetid; filesetid.SetValue( Internals->FileSetID.c_str() ); ds.Insert( filesetid.GetAsDataElement() ); CodeString cs = filesetid.GetValue(); if( !cs.IsValid() ) { gdcmErrorMacro( "Invalid File Set ID: " << filesetid.GetValue() ); return false; } Attribute<0x4,0x1200> offsetofthefirstdirectoryrecordoftherootdirectoryentity = {0}; ds.Insert( offsetofthefirstdirectoryrecordoftherootdirectoryentity.GetAsDataElement() ); Attribute<0x4,0x1202> offsetofthelastdirectoryrecordoftherootdirectoryentity = { 0 }; ds.Insert( offsetofthelastdirectoryrecordoftherootdirectoryentity.GetAsDataElement() ); Attribute<0x4,0x1212> filesetconsistencyflag = {0}; ds.Insert( filesetconsistencyflag.GetAsDataElement() ); DataElement de_drs( Tag(0x4,0x1220) ); // DirectoryRecordSequence SequenceOfItems * sqi0 = new SequenceOfItems; de_drs.SetVR( VR::SQ ); de_drs.SetValue( *sqi0 ); de_drs.SetVLToUndefined(); ds.Insert( de_drs ); bool b; b = AddPatientDirectoryRecord(); if( !b ) return false; b = AddStudyDirectoryRecord(); if( !b ) return false; b = AddSeriesDirectoryRecord(); if( !b ) return false; b = AddImageDirectoryRecord(); if( !b ) return false; /* The DICOMDIR File shall use the Explicit VR Little Endian Transfer Syntax (UID=1.2.840.10008.1.2.1) to encode the Media Storage Directory SOP Class. The DICOMDIR File shall comply with the DICOM File Format specified in Section 7 of this Standard. In particular the: a. SOP Class UID in the File Meta Information (header of the DICOMDIR File) shall have the Value specified in PS 3.4 of this Standard for the Media Storage Directory SOP Class; b. SOP Instance UID in the File Meta Information (header of the DICOMDIR File) shall contain the File-set UID Value. The File-set UID is assigned by the Application Entity which created the File-set (FSC role, see Section 8.3) with zero or more DICOM Files. This File-set UID Value shall not be changed by any other Application Entities reading or updating the content of the File-set. */ FileMetaInformation &h = GetFile().GetHeader(); Attribute<0x2,0x2> at1; MediaStorage ms = MediaStorage::MediaStorageDirectoryStorage; const char* msstr = MediaStorage::GetMSString(ms); at1.SetValue( msstr ); h.Insert( at1.GetAsDataElement() ); Attribute<0x2,0x3> at2; UIDGenerator uid; const char *mediastoragesopinstanceuid = uid.Generate(); if( !UIDGenerator::IsValid( mediastoragesopinstanceuid ) ) { return true; } at2.SetValue( mediastoragesopinstanceuid ); h.Insert( at2.GetAsDataElement() ); TransferSyntax ts = TransferSyntax::ExplicitVRLittleEndian; h.SetDataSetTransferSyntax( ts ); //std::cout << ds << std::endl; //std::cout << h << std::endl; /* Very important step it should be the *VERY* last one */ // We need to compute all offset, which can be only done when all attributes have been inserted. // Let's start with offsetofthefirstdirectoryrecordoftherootdirectoryentity : h.FillFromDataSet( ds ); VL fmi_len = h.GetFullLength(); VL fmi_len_offset = 0; { DataSet::ConstIterator it = ds.Begin(); for(; it != ds.End() && it->GetTag() != Tag(0x0004,0x1220); ++it) { const DataElement &detmp = *it; fmi_len_offset += detmp.GetLength(); } // Now add the partial length for attribute 0004,1220: fmi_len_offset += it->GetTag().GetLength(); fmi_len_offset += it->GetVR().GetLength(); fmi_len_offset += it->GetVR().GetLength(); } //std::cerr << fmi_len << " and " << fmi_len_offset << std::endl; offsetofthefirstdirectoryrecordoftherootdirectoryentity.SetValue( fmi_len + fmi_len_offset ); ds.Replace( offsetofthefirstdirectoryrecordoftherootdirectoryentity.GetAsDataElement() ); VL fmi_len_offset2 = 0; { DataSet::ConstIterator it = ds.Begin(); for( ; it != ds.End() && it->GetTag() <= Tag(0x0004,0x1220); ++it) { const DataElement &detmp = *it; fmi_len_offset2 += detmp.GetLength(); } } { //const DataElement &de_drs = ds.GetDataElement( Tag(0x4,0x1220) ); // DirectoryRecordSequence SmartPointer sqi = de_drs.GetValueAsSQ(); SequenceOfItems::SizeType n = sqi->GetNumberOfItems(); const Item &item = sqi->GetItem( n ); // last item VL sub = item.GetLength(); // Let's subtract item length as well as the item sequence delimiter end (tag + vl => 8) offsetofthelastdirectoryrecordoftherootdirectoryentity.SetValue( fmi_len + fmi_len_offset2 - sub - 8 ); ds.Replace( offsetofthelastdirectoryrecordoftherootdirectoryentity.GetAsDataElement() ); TraverseDirectoryRecords(offsetofthefirstdirectoryrecordoftherootdirectoryentity.GetValue() ); } return true; } void DICOMDIRGenerator::SetFile(const File& f) { Internals->F = f; } File &DICOMDIRGenerator::GetFile() { return *Internals->F; } Scanner &DICOMDIRGenerator::GetScanner() { return Internals->scanner; } SequenceOfItems *DICOMDIRGenerator::GetDirectoryRecordSequence() { DataSet &ds = GetFile().GetDataSet(); const DataElement &de = ds.GetDataElement( Tag(0x4,0x1220) ); //SequenceOfItems * sqi = (SequenceOfItems*)de.GetSequenceOfItems(); SmartPointer sqi = de.GetValueAsSQ(); return sqi; } const char *DICOMDIRGenerator::ComputeFileID(const char *input) { assert( 0 ); (void)input; return nullptr; } void DICOMDIRGenerator::SetDescriptor( const char *d ) { Internals->FileSetID = d; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDICOMDIRGenerator.h000066400000000000000000000075471412732066400245740ustar00rootroot00000000000000/*========================================================================= 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 GDCMDICOMDIRGENERATOR_H #define GDCMDICOMDIRGENERATOR_H #include "gdcmDirectory.h" #include "gdcmTag.h" #include // std::pair namespace gdcm { class File; class Scanner; class SequenceOfItems; class VL; class DICOMDIRGeneratorInternal; /** * \brief DICOMDIRGenerator class * \details This is a STD-GEN-CD DICOMDIR generator. * ref: PS 3.11-2008 Annex D (Normative) - General Purpose CD-R and DVD Interchange Profiles * * \note * PS 3.11 - 2008 / D.3.2 Physical Medium And Medium Format * The STD-GEN-CD and STD-GEN-SEC-CD application profiles require the 120 mm CD-R physical * medium with the ISO/IEC 9660 Media Format, as defined in PS3.12. * See also PS 3.12 - 2008 / Annex F 120mm CD-R Medium (Normative) and * PS 3.10 - 2008 / 8 DICOM File Service / 8.1 FILE-SET * * \warning: * PS 3.11 - 2008 / D.3.1 SOP Classes and Transfer Syntaxes * Composite Image & Stand-alone Storage are required to be stored as Explicit VR Little * Endian Uncompressed (1.2.840.10008.1.2.1). When a DICOM file is found using another * Transfer Syntax the generator will simply stops. * * \warning * - Input files should be Explicit VR Little Endian * - filenames should be valid VR::CS value (16 bytes, upper case ...) * * \bug: * There is a current limitation of not handling Referenced SOP Class UID / * Referenced SOP Instance UID simply because the Scanner does not allow us * See PS 3.11 / Table D.3-2 STD-GEN Additional DICOMDIR Keys */ class GDCM_EXPORT DICOMDIRGenerator { public: typedef Directory::FilenamesType FilenamesType; typedef Directory::FilenameType FilenameType; DICOMDIRGenerator(); ~DICOMDIRGenerator(); /// Set the list of filenames from which the DICOMDIR should be generated from void SetFilenames( FilenamesType const & fns ); /// Set the root directory from which the filenames should be considered. void SetRootDirectory( FilenameType const & root ); /// Set the File Set ID. /// \warning this need to be a valid VR::CS value void SetDescriptor( const char *d ); /// Main function to generate the DICOMDIR bool Generate(); /// Set/Get file. The DICOMDIR file will be valid once a call to Generate has been done void SetFile(const File& f); File &GetFile(); protected: Scanner &GetScanner(); bool AddPatientDirectoryRecord(); bool AddStudyDirectoryRecord(); bool AddSeriesDirectoryRecord(); bool AddImageDirectoryRecord(); private: const char *ComputeFileID(const char *); bool TraverseDirectoryRecords(VL start ); bool ComputeDirectoryRecordsOffset(const SequenceOfItems *sqi, VL start); size_t FindNextDirectoryRecord( size_t item1, const char *directorytype ); SequenceOfItems *GetDirectoryRecordSequence(); size_t FindLowerLevelDirectoryRecord( size_t item1, const char *directorytype ); typedef std::pair< std::string, Tag> MyPair; MyPair GetReferenceValueForDirectoryType(size_t item); bool SeriesBelongToStudy(const char *seriesuid, const char *studyuid); bool ImageBelongToSeries(const char *sopuid, const char *seriesuid, Tag const &t1, Tag const &t2); bool ImageBelongToSameSeries(const char *sopuid, const char *seriesuid, Tag const &t); DICOMDIRGeneratorInternal * Internals; }; /** * \example GenerateDICOMDIR.cs * This is a C# example on how to use DICOMDIRGenerator */ } // end namespace gdcm #endif //GDCMDICOMDIRGENERATOR_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDataSetHelper.cxx000066400000000000000000000271531412732066400245660ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDataSetHelper.h" #include "gdcmFile.h" #include "gdcmDataSet.h" #include "gdcmSequenceOfItems.h" #include "gdcmImplicitDataElement.h" #include "gdcmGlobal.h" #include "gdcmDicts.h" #include "gdcmDict.h" #include "gdcmAttribute.h" namespace gdcm { /* See PS 3.5 - 2008 Annex A (Normative) Transfer Syntax Specifications */ VR ComputeVRImplicitLittleEndian(DataSet const &ds, const Tag& tag) { (void)ds; (void)tag; /* A.1 DICOM IMPLICIT VR LITTLE ENDIAN TRANSFER SYNTAX a) The Data Elements contained in the Data Set structure shall be encoded with Implicit VR (without a VR Field) as specified in Section 7.1.3. b) The encoding of the overall Data Set structure (Data Element Tags, Value Length, and Value) shall be in Little Endian as specified in Section 7.3. c) The encoding of the Data Elements of the Data Set shall be as follows according to their Value Representations: - For all Value Representations defined in this part, except for the Value Representations OB and OW, the encoding shall be in Little Endian as specified in Section 7.3 - For the Value Representations OB and OW, the encoding shall meet the following specification depending on the Data Element Tag: - Data Element (7FE0,0010) Pixel Data has the Value Representation OW and shall be encoded in Little Endian. - Data Element (60xx,3000) Overlay Data has the Value Representation OW and shall be encoded in Little Endian. - Data Element (5400,1010) Waveform Data shall have Value Representation OW and shall be encoded in Little Endian. - Data Elements (0028,1201), (0028,1202),(0028,1203) Red, Green, Blue Palette Lookup Table Data have the Value Representation OW and shall be encoded in Little Endian. Note: Previous versions of the Standard either did not specify the encoding of these Data Elements in this Part, but specified a VR of US or SS in PS 3.6 (1993), or specified OW in this Part but a VR of US, SS or OW in PS 3.6 (1996). The actual encoding of the values and their byte order would be identical in each case. - Data Elements (0028,1101), (0028,1102),(0028,1103) Red, Green, Blue Palette Lookup Table Descriptor have the Value Representation SS or US (depending on rules specified in the IOD in PS 3.3), and shall be encoded in Little Endian. The first and third values are always interpreted as unsigned, regardless of the Value Representation. - Data Elements (0028,1221),(0028,1222),(0028,1223) Segmented Red, Green, Blue Palette Color Lookup table Data have the Value Representation OW and shall be encoded in Little Endian. - Data Element (0028,3006) Lookup Table Data has the Value Representation US, SS or OW and shall be encoded in Little Endian. - Data Element (0028,3002) Lookup Table Descriptor has the Value Representation SS or US (depending on rules specified in the IOD in PS 3.3), and shall be encoded in Little Endian. The first and third values are always interpreted as unsigned, regardless of the Value Representation. */ VR vr = VR::INVALID; return vr; } VR DataSetHelper::ComputeVR(File const &file, DataSet const &ds, const Tag& tag) { const Global& g = GlobalInstance; const Dicts &dicts = g.GetDicts(); //const Dict &d = dicts.GetPublicDict(); std::string strowner; const char *owner = nullptr; const Tag& t = tag; if( t.IsPrivate() && !t.IsPrivateCreator() ) { strowner = ds.GetPrivateCreator(t); owner = strowner.c_str(); } const DictEntry &entry = dicts.GetDictEntry(t,owner); const VR &refvr = entry.GetVR(); //const VM &vm = entry.GetVM(); // not much we can do... if( refvr == VR::INVALID || refvr == VR::UN ) { // New public/private tag, let's forward what is found in the file (hopefully correct) if( ds.FindDataElement( t ) ) { const DataElement &de = ds.GetDataElement( t ); const VR &devr = de.GetVR(); if( devr != VR::INVALID && devr != VR::UN ) { gdcmWarningMacro("Please report. Missing dict entry for: [" << (owner ? owner : "") << "]" << " de is: " << de ); return devr; } // CP-246 if( devr == VR::UN && de.IsUndefinedLength() ) { return VR::SQ; } } // postcondition says it cannot be VR::INVALID, so return VR::UN return VR::UN; } VR vr = refvr; // Special handling of US or SS vr: if( vr == VR::US_SS ) { // I believe all US_SS VR derived from the value from 0028,0103 ... except 0028,0071 if( t != Tag(0x0028,0x0071) ) { // In case of SAX parser, we would have had to process Pixel Representation already: Attribute<0x0028,0x0103> at; const Tag &pixelrep = at.GetTag(); assert( pixelrep < t ); const DataSet &rootds = file.GetDataSet(); // FIXME // PhilipsWith15Overlays.dcm has a Private SQ with public elements such as // 0028,3002, so we cannot look up element in current dataset, but have to get the root dataset // to loop up... // FIXME: // gdcmDataExtra/gdcmSampleData/ImagesPapyrus/TestImages/wristb.pap // It's the contrary: root dataset does not have a Pixel Representation, but each SQ do... //assert( rootds.FindDataElement( pixelrep ) || ds.FindDataElement( pixelrep ) ); if( ds.FindDataElement( pixelrep ) ) { at.SetFromDataElement( ds.GetDataElement( pixelrep ) ); } else if( rootds.FindDataElement( pixelrep ) ) { at.SetFromDataElement( rootds.GetDataElement( pixelrep ) ); } else { //throw Exception( "Unhandled" ); gdcmWarningMacro( "Unhandled" ); // Typical to PDF encapsulated with some illegal attribute vr = VR::INVALID; } //assert( at.GetValue() == 0 || at.GetValue() == 1 ); if( at.GetValue() == 1 ) { vr = VR::SS; } else /*if( at.GetValue() == 0 )*/ { // default to VR:US always (even when attribute is missing, or impossible to compute). This is much better than VR:UN anyway vr = VR::US; } } else { // FIXME ??? vr = VR::US; } } else if( vr == VR::OB_OW ) { Tag pixeldata(0x7fe0,0x0010); Tag waveformpaddingvalue(0x5400,0x100a); Tag waveformdata(0x5400,0x1010); Tag overlaydata(0x6000,0x3000); Tag curvedata(0x5000,0x3000); Tag audiodata(0x5000,0x200c); Tag variablepixeldata(0x7f00,0x0010); Tag bitsallocated(0x0028,0x0100); Tag channelminval(0x5400,0x0110); Tag channelmaxval(0x5400,0x0112); //assert( ds.FindDataElement( pixeldata ) ); int v = -1; if( waveformdata == t || waveformpaddingvalue == t ) { Tag waveformbitsallocated(0x5400,0x1004); // For Waveform Data: // (5400,1004) US 16 # 2,1 Waveform Bits Allocated assert( ds.FindDataElement( waveformbitsallocated ) ); Attribute<0x5400,0x1004> at; at.SetFromDataElement( ds.GetDataElement( waveformbitsallocated ) ); v = at.GetValue(); } else // ( pixeldata == t ) { // For Pixel Data: if( !ds.FindDataElement( bitsallocated ) ) return VR::UN; Attribute<0x0028,0x0100> at; at.SetFromDataElement( ds.GetDataElement( bitsallocated ) ); } (void)v; if( pixeldata == t || t.IsGroupXX(overlaydata) ) { vr = VR::OW; if( ds.FindDataElement( t ) ) { const DataElement &de = ds.GetDataElement( t ); const gdcm::SequenceOfFragments * sqf = de.GetSequenceOfFragments(); if( sqf ) vr = VR::OB; } } else if( waveformdata == t || waveformpaddingvalue == t ) { //assert( v == 8 || v == 16 ); vr = VR::OW; } else if ( t.IsGroupXX(audiodata) ) { vr = VR::OB; } else if ( t.IsGroupXX(curvedata) ) { vr = VR::OB; } else if ( t.IsGroupXX(variablepixeldata) ) { vr = VR::OB; } else if ( t == channelminval || t == channelmaxval ) { vr = VR::OB; } else { // We may reach here coming from a private attribute if( t.IsPrivate() && !t.IsPrivateCreator() ) { // ?HitachiMedical.Dream.Cabinet.ApplicationObjects.ImageAppData? vr = VR::UN; // no clue which VR to pick, try to re-use the one from the file: if( ds.FindDataElement( t ) ) { const DataElement &de = ds.GetDataElement( t ); const VR &devr = de.GetVR(); if( devr != VR::INVALID && devr != VR::UN ) { gdcmWarningMacro("Possibly incorrect VR for: " << de ); vr = devr; } } } else { // Do we need to update this logic ? gdcmAssertAlwaysMacro( 0 && "Should not happen" ); } } } else if( vr == VR::US_SS_OW || vr == VR::US_OW ) { vr = VR::OW; } // TODO need to treat US_SS_OW too // \postcondition: assert( vr.IsVRFile() ); assert( vr != VR::INVALID ); if( tag.IsGroupLength() ) { assert( vr == VR::UL ); } if( tag.IsPrivateCreator() ) { assert( vr == VR::LO ); } return vr; } /* SequenceOfItems* DataSetHelper::ComputeSQFromByteValue(File const & file, DataSet const &ds, const Tag &tag) { const TransferSyntax &ts = file.GetHeader().GetDataSetTransferSyntax(); assert( ts != TransferSyntax::DeflatedExplicitVRLittleEndian ); const DataElement &de = ds.GetDataElement( tag ); if( de.IsEmpty() ) { return 0; } Value &v = const_cast(de.GetValue()); SequenceOfItems *sq = dynamic_cast(&v); if( sq ) // all set ! { SmartPointer sqi = sq; return sqi; } try { if( ts.GetSwapCode() == SwapCode::BigEndian ) { assert(0); } else { if( ts.GetNegociatedType() == TransferSyntax::Implicit ) { assert( de.GetVR() == VR::INVALID ); const ByteValue *bv = de.GetByteValue(); assert( bv ); SequenceOfItems *sqi = new SequenceOfItems; sqi->SetLength( bv->GetLength() ); std::stringstream ss; ss.str( std::string( bv->GetPointer(), bv->GetLength() ) ); sqi->Read( ss ); return sqi; } else { assert( de.GetVR() == VR::UN ); // cp 246, IVRLE SQ const ByteValue *bv = de.GetByteValue(); assert( bv ); SequenceOfItems *sqi = new SequenceOfItems; sqi->SetLength( bv->GetLength() ); std::stringstream ss; ss.str( std::string( bv->GetPointer(), bv->GetLength() ) ); sqi->Read( ss ); return sqi; } } } catch( ParseException &pex ) { gdcmDebugMacro( pex.what() ); } catch( Exception &ex ) { gdcmDebugMacro( ex.what() ); } catch( ... ) { gdcmWarningMacro( "Unknown exception" ); } return 0; } */ } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDataSetHelper.h000066400000000000000000000023371412732066400242100ustar00rootroot00000000000000/*========================================================================= 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 GDCMDATASETHELPER_H #define GDCMDATASETHELPER_H #include "gdcmTypes.h" #include "gdcmVR.h" namespace gdcm { class DataSet; class File; class Tag; class SequenceOfItems; /** * \brief DataSetHelper (internal class, not intended for user level) * * \details */ class GDCM_EXPORT DataSetHelper { public: /// ds -> current dataset, which is not the same as the root dataset /// return VR::INVALID in case of error static VR ComputeVR(File const & file, DataSet const &ds, const Tag& tag); //static SequenceOfItems* ComputeSQFromByteValue(File const & file, DataSet const &ds, const Tag &tag); protected: }; } // end namespace gdcm #endif // GDCMDATASETHELPER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDecoder.h000066400000000000000000000022571412732066400230710ustar00rootroot00000000000000/*========================================================================= 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 GDCMDECODER_H #define GDCMDECODER_H #include "gdcmTypes.h" #include "gdcmDataElement.h" // FIXME namespace gdcm { class TransferSyntax; class DataElement; /** * \brief Decoder */ class GDCM_EXPORT Decoder { public: virtual ~Decoder() = default; /// Return whether this decoder support this transfer syntax (can decode it) virtual bool CanDecode(TransferSyntax const &) const = 0; /// Decode virtual bool Decode(DataElement const &, DataElement &) { return false; } protected: virtual bool DecodeByStreams(std::istream &, std::ostream &) { return false; } }; } // end namespace gdcm #endif //GDCMDECODER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDeltaEncodingCodec.cxx000066400000000000000000000022301412732066400255240ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDeltaEncodingCodec.h" #include "gdcmTransferSyntax.h" #include "gdcmByteSwap.txx" #include "gdcmDataElement.h" #include "gdcmSequenceOfFragments.h" #include namespace gdcm { DeltaEncodingCodec::DeltaEncodingCodec() { } DeltaEncodingCodec::~DeltaEncodingCodec() { } bool DeltaEncodingCodec::CanDecode(TransferSyntax const &ts) { return true; // FIXME } bool DeltaEncodingCodec::Decode(DataElement const &in, DataElement &out) { out = in; return true; } bool DeltaEncodingCodec::Decode(std::istream &is, std::ostream &os) { abort(); return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDeltaEncodingCodec.h000066400000000000000000000021201412732066400251470ustar00rootroot00000000000000/*========================================================================= 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 GDCMDELTAENCODINGCODEC_H #define GDCMDELTAENCODINGCODEC_H #include "gdcmImageCodec.h" #error do not use namespace gdcm { /** * \brief DeltaEncodingCodec compression used by some private * vendor */ class DeltaEncodingCodec : public ImageCodec { public: DeltaEncodingCodec(); ~DeltaEncodingCodec(); bool CanDecode(TransferSyntax const &ts); bool Decode(DataElement const &is, DataElement &os); protected: bool Decode(std::istream &is, std::ostream &os); }; } // end namespace gdcm #endif //GDCMDELTAENCODINGCODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDictPrinter.cxx000066400000000000000000000372051412732066400243270ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDictPrinter.h" #include "gdcmDict.h" #include "gdcmGlobal.h" #include "gdcmDicts.h" #include "gdcmSequenceOfItems.h" namespace gdcm { //----------------------------------------------------------------------------- DictPrinter::DictPrinter() { PrintStyle = XML; } //----------------------------------------------------------------------------- DictPrinter::~DictPrinter() = default; VM GuessVMType(DataElement const &de) { if( de.IsEmpty() ) return VM::VM1; const VR &vr = de.GetVR(); const VL &vl = de.GetVL(); const Value& value = de.GetValue(); VM vm; if( VR::IsBinary( vr ) ) { if( vr == VR::SQ ) { vm = VM::VM1; // ?? } else if( vr & VR::OB_OW ) { vm = VM::VM1; } else { vm = VM::GetVMTypeFromLength( value.GetLength(), vr.GetSize() ); } } else { assert( VR::IsASCII( vr ) || vr == VR::INVALID ); switch(vr) { case VR::INVALID: vm = VM::VM1; break; case VR::UN: // TODO need to do some magic guessing vm = VM::VM1; break; case VR::DA: case VR::TM: case VR::LT: case VR::SH: case VR::UI: case VR::LO: case VR::ST: case VR::UT: case VR::AE: case VR::AS: vm = VM::VM1; break; case VR::PN: vm = VM::VM1; // I think it is ok break; case VR::IS: case VR::DS: case VR::DT: case VR::CS: { // Need to count \\ character const ByteValue *bv = dynamic_cast(&value); vm = VM::VM1; // why not ? if(!de.IsEmpty()) { assert( bv && "not bv" ); const char *array = bv->GetPointer(); size_t c = VM::GetNumberOfElementsFromArray(array, vl); vm = VM::GetVMTypeFromLength( c, 1 ); } } break; default: vm = VM::VM0; assert( 0 ); // Impossible happen ! (someone added new VR and forgot this switch) } } return vm; } struct OWNER_VERSION { const char* owner; const char* version; }; // See getowner.xsl static const OWNER_VERSION OwnerVersionTable[] ={ {"","EMPTY!"}, {"","2"}, {"","3"}, {"1.2.840.113663.1","ATL"}, {"1.2.840.113681","DUP"}, {"1.2.840.113708.794.1.1.2.0","ARM"}, {"2.16.840.1.114059.1.1.6.1.50.1","DEX"}, {"ACUSON","ACU"}, {"ADAC_IMG","ADAC"}, {"AEGIS_DICOM_2.00","AEG"}, {"AGFA PACS Archive Mirroring 1.0 ","MIT"}, {"AGFA","AGFA"}, {"AGFA_ADC_Compact","AGFA"}, {"Applicare/RadWorks/Version 5.0","APL"}, {"Applicare/RadWorks/Version 6.0","APL"}, {"Applicare/RadWorks/Version 6.0/Summary","APL"}, {"BioPri","BIO"}, {"CAMTRONICS IP ","CMT"}, {"CAMTRONICS","CMT"}, {"CARDIO-D.R. 1.0 ","PDIC"}, {"Canon Inc.","CAN"}, {"DIDI TO PCR 1.1 ","PSPI"}, {"DIGISCAN IMAGE","SSPI"}, {"DLX_ANNOT_01","DLX"}, {"DLX_EXAMS_01","DLX"}, {"DLX_LKUP_01 ","GEM"}, {"DLX_PATNT_01","DLX"}, {"DLX_SERIE_01","DLX"}, {"DLX_SERIE_01","GEM"}, {"ELSCINT1","EL1"}, {"FDMS 1.0","FUJ"}, {"FFP DATA","SSPI"}, {"GE ??? From Adantage Review CS","GEM"}, {"GEIIS PACS","GEM"}, {"GEIIS ","GEM"}, {"GEMS_3DSTATE_001","GEM"}, {"GEMS_ACQU_01","GEM"}, {"GEMS_ACRQA_1.0 BLOCK1 ","GEM"}, {"GEMS_ACRQA_1.0 BLOCK2 ","GEM"}, {"GEMS_ACRQA_1.0 BLOCK3 ","GEM"}, {"GEMS_ACRQA_2.0 BLOCK1 ","GEM"}, {"GEMS_ACRQA_2.0 BLOCK2 ","GEM"}, {"GEMS_ACRQA_2.0 BLOCK3 ","GEM"}, {"GEMS_ADWSoft_3D1","GEM"}, {"GEMS_ADWSoft_DPO","GEM"}, {"GEMS_AWSOFT_CD1 ","GEM"}, {"GEMS_AWSoft_SB1 ","GEM"}, {"GEMS_CTHD_01","GEM"}, {"GEMS_CT_CARDIAC_001 ","GEM"}, {"GEMS_CT_HINO_01 ","GEM"}, {"GEMS_CT_VES_01","GEM"}, {"GEMS_DL_FRAME_01","GEM"}, {"GEMS_DL_IMG_01","GEM"}, {"GEMS_DL_PATNT_01","GEM"}, {"GEMS_DL_SERIES_01 ","GEM"}, {"GEMS_DL_STUDY_01","GEM"}, {"GEMS_DRS_1","GEM"}, {"GEMS_FALCON_03","GEM"}, {"GEMS_GDXE_ATHENAV2_INTERNAL_USE ","GEM"}, {"GEMS_GDXE_FALCON_04 ","GEM"}, {"GEMS_GENIE_1","GEM"}, {"GEMS_GNHD_01","GEM"}, {"GEMS_HELIOS_01","GEM"}, {"GEMS_IDEN_01","GEM"}, {"GEMS_IMAG_01","GEM"}, {"GEMS_IMPS_01","GEM"}, {"GEMS_IQTB_IDEN_47 ","GEM"}, {"GEMS_PARM_01","GEM"}, {"GEMS_PATI_01","GEM"}, {"GEMS_PETD_01","GEM"}, {"GEMS_RELA_01","GEM"}, {"GEMS_SENO_02","GEM"}, {"GEMS_SERS_01","GEM"}, {"GEMS_STDY_01","GEM"}, {"GEMS_YMHD_01","GEM"}, {"GE_GENESIS_REV3.0 ","GEM"}, {"HOLOGIC ","HOL"}, {"Hologic ","HOL"}, {"ISG shadow","ISG"}, {"ISI ","SSPI"}, {"KINETDX ","KDX"}, {"KINETDX_GRAPHICS","KDX"}, {"LODOX_STATSCAN","LDX"}, {"LORAD Selenia ","LOR"}, {"MERGE TECHNOLOGIES, INC.","MRG"}, {"MITRA LINKED ATTRIBUTES 1.0 ","MIT"}, {"MITRA MARKUP 1.0","MIT"}, {"MITRA OBJECT ATTRIBUTES 1.0 ","MIT"}, {"MITRA OBJECT DOCUMENT 1.0 ","MIT"}, {"MITRA OBJECT UTF8 ATTRIBUTES 1.0","MIT"}, {"MITRA PRESENTATION 1.0","MIT"}, {"MMCPrivate","HIT"}, {"Mayo/IBM Archive Project","MIBM"}, {"MeVis BreastCare","MEV"}, {"Mortara_Inc ","MOR"}, {"PAPYRUS 3.0 ","PA3"}, {"PAPYRUS ","PAP"}, {"PHILIPS MR R5.5/PART","PSPI"}, {"PHILIPS MR R5.6/PART","PSPI"}, {"PHILIPS MR SPECTRO;1","PSPI"}, {"PHILIPS MR","PSPI"}, {"PHILIPS MR/LAST ","PSPI"}, {"PHILIPS MR/PART ","PSPI"}, {"PHILIPS NM -Private ","PMNM"}, {"PHILIPS-MR-1","PDIC"}, {"PMS-THORA-5.1 ","PDIC"}, {"PMTF INFORMATION DATA ","TSH"}, {"Philips Imaging DD 001","PMFE"}, {"Philips Imaging DD 129","PMFE"}, {"Philips MR Imaging DD 001 ","PMFE"}, {"Philips MR Imaging DD 002 ","PMFE"}, {"Philips MR Imaging DD 003 ","PMFE"}, {"Philips MR Imaging DD 004 ","PMFE"}, {"Philips MR Imaging DD 005 ","PMFE"}, {"Philips PET Private Group ","PPET"}, {"Philips X-ray Imaging DD 001","PMFE"}, {"Picker MR Private Group ","PCK"}, {"Picker NM Private Group ","PCK"}, {"SCHICK TECHNOLOGIES - Change Item Creator ID","SCH"}, {"SCHICK TECHNOLOGIES - Change List Creator ID","SCH"}, {"SCHICK TECHNOLOGIES - Image Security Creator ID ","SCH"}, {"SCHICK TECHNOLOGIES - Note List Creator ID","SCH"}, {"SECTRA_Ident_01 ","SEC"}, {"SECTRA_ImageInfo_01 ","SEC"}, {"SECTRA_OverlayInfo_01 ","SEC"}, {"SEGAMI MIML ","MOR"}, {"SHS MagicView 300 ","SSPI"}, {"SIEMENS CM VA0 ACQU","SSPI"}, {"SIEMENS CM VA0 CMS ","SSPI"}, {"SIEMENS CM VA0 LAB ","SSPI"}, {"SIEMENS CSA HEADER","SSPI"}, {"SIEMENS CSA NON-IMAGE ","SSPI"}, {"SIEMENS CSA REPORT","SSPI"}, {"SIEMENS CT VA0 COAD","SSPI"}, {"SIEMENS CT VA0 GEN ","SSPI"}, {"SIEMENS CT VA0 IDE ","SSPI"}, {"SIEMENS CT VA0 ORI ","SSPI"}, {"SIEMENS CT VA0 OST ","SSPI"}, {"SIEMENS CT VA0 RAW ","SSPI"}, {"SIEMENS DFR.01 MANIPULATED","SSPI"}, {"SIEMENS DFR.01 ORIGINAL ","SSPI"}, {"SIEMENS DICOM ","SSPI"}, {"SIEMENS DLR.01","SPI"}, {"SIEMENS DLR.01","SSPI"}, {"SIEMENS ISI ","SSPI"}, {"SIEMENS MED DISPLAY 0000","SSPI"}, {"SIEMENS MED DISPLAY ","SSPI"}, {"SIEMENS MED ECAT FILE INFO","SSPI"}, {"SIEMENS MED HG","SSPI"}, {"SIEMENS MED MAMMO " ,"SSPI"}, {"SIEMENS MED MG","SSPI"}, {"SIEMENS MED NM","SSPI"}, {"SIEMENS MED SP DXMG WH AWS 1","SSPI"}, {"SIEMENS MED ","SSPI"}, {"SIEMENS MEDCOM HEADER ","SSPI"}, {"SIEMENS MEDCOM HEADER2","SSPI"}, {"SIEMENS MEDCOM OOG","SSPI"}, {"SIEMENS MR VA0 COAD","SSPI"}, {"SIEMENS MR VA0 GEN ","SSPI"}, {"SIEMENS MR VA0 RAW ","SSPI"}, {"SIEMENS NUMARIS II","SSPI"}, {"SIEMENS RA GEN","SSPI"}, {"SIEMENS RA PLANE A","SSPI"}, {"SIEMENS RA PLANE B","SSPI"}, {"SIEMENS RIS ","SSPI"}, {"SIEMENS SIENET","SSPI"}, {"SIEMENS SMS-AX ACQ 1.0 ","SSPI"}, {"SIEMENS SMS-AX ORIGINAL IMAGE INFO 1.0 ","SSPI"}, {"SIEMENS SMS-AX QUANT 1.0 ","SSPI"}, {"SIEMENS SMS-AX VIEW 1.0","SSPI"}, {"SIEMENS Selma ","SSPI"}, {"SIEMENS WH SR 1.0 ","SSPI"}, {"SIEMENS_FLCOMPACT_VA01A_PROC","SSPI"}, {"SIENET","SSPI"}, {"SPI RELEASE 1 ","SPI"}, {"SPI Release 1 ","SPI"}, //{"SPI ","SPI"}, // FIXME ?? {"SPI ","SSPI"}, {"SPI-P Release 1 ","PSPI"}, {"SPI-P Release 1;1 ","PSPI"}, {"SPI-P Release 1;2 ","PSPI"}, {"SPI-P Release 1;3 ","PSPI"}, {"SPI-P Release 2;1 ","PSPI"}, {"SPI-P-CTBE Release 1","PSPI"}, {"SPI-P-CTBE-Private Release 1","PSPI"}, {"SPI-P-GV-CT Release 1 ","PSPI"}, {"SPI-P-PCR Release 2 ","PSPI"}, {"SPI-P-Private-CWS Release 1 ","PSPI"}, {"SPI-P-Private-DCI Release 1 ","PSPI"}, {"SPI-P-Private-DiDi Release 1","PSPI"}, {"SPI-P-Private_CDS Release 1 ","PSPI"}, {"SPI-P-Private_ICS Release 1 ","PSPI"}, {"SPI-P-Private_ICS Release 1;1 ","PSPI"}, {"SPI-P-Private_ICS Release 1;2 ","PSPI"}, {"SPI-P-Private_ICS Release 1;4 ","PSPI"}, {"SPI-P-Private_ICS Release 1;5 ","PSPI"}, {"SPI-P-XSB-DCI Release 1 ","PSPI"}, {"SPI-P-XSB-VISUB Release 1 ","PSPI"}, {"STENTOR ","STE"}, {"Siemens: Thorax/Multix FD Image Stamp ","SSPI"}, {"Siemens: Thorax/Multix FD Lab Settings","SSPI"}, {"Siemens: Thorax/Multix FD Post Processing ","SSPI"}, {"Siemens: Thorax/Multix FD Raw Image Settings","SSPI"}, {"Siemens: Thorax/Multix FD Version ","SSPI"}, {"Silhouette Annot V1.0 ","ISG"}, {"Silhouette Graphics Export V1.0 ","ISG"}, {"Silhouette Line V1.0","ISG"}, {"Silhouette ROI V1.0 ","ISG"}, {"Silhouette Sequence Ids V1.0","ISG"}, {"Silhouette V1.0 ","ISG"}, {"Silhouette VRS 3.0","ISG"}, {"TOSHIBA COMAPL HEADER ","TSH"}, {"TOSHIBA COMAPL OOG","TSH"}, {"TOSHIBA ENCRYPTED SR DATA ","TSH"}, {"TOSHIBA MDW HEADER","TSH"}, {"TOSHIBA MDW NON-IMAGE ","TSH"}, {"TOSHIBA_MEC_1.0 ","TSH"}, {"TOSHIBA_MEC_CT3 ","TSH"}, {"TOSHIBA_MEC_CT_1.0","TSH"}, {"TOSHIBA_MEC_MR3 ","TSH"}, {"TOSHIBA_MEC_OT3 ","TSH"}, {"TOSHIBA_MEC_XA3 ","TSH"}, {"Viewing Protocol",""}, {"http://www.gemedicalsystems.com/it_solutions/rad_pacs/","GEM"}, // Manually added: { "GEMS_Ultrasound_ImageGroup_001", "GEM" }, { "GEMS_Ultrasound_MovieGroup_001", "GEM" }, { "SIEMENS MED OCS SITE NAME ", "SSPI" }, { "PHILIPS IMAGING DD 001", "PMFE" }, { "PHILIPS MR IMAGING DD 001 ", "PMFE" }, { "INTELERAD MEDICAL SYSTEMS ", "IMS" }, { "SIEMENS CT VA1 DUMMY", "SSPI" }, { "PATRIOT_PRIVATE_IMAGE_DATA", "PPID" }, { "VEPRO VIF 3.0 DATA", "VV3D" }, { "VEPRO DICOM TRANSFER 1.0", "VDT1" }, { "HMC ", "HMC" }, { "Philips3D ", "PM3D" }, { "SIEMENS MED SMS USG ANTARES ", "SSPI" }, { "ACUSON:1.2.840.113680.1.0:7f10", "ACU" }, { "ACUSON:1.2.840.113680.1.0 ", "ACU" }, { "SIEMENS MR HEADER", "SSPI" }, // !! { "INTEGRIS 1.0", "INT1" }, { "SYNARC_1.0", "SYN" }, { "MeVis eatDicom", "MVD" }, { "PHILIPS MR/PART 6 ", "PMFE" }, { "PHILIPS MR/PART 7 ", "PMFE" }, { "PHILIPS MR/PART 12", "PMFE" }, { "HMC - CT - ID ", "HMC" }, { "SPI-P-Private_ICS Release 1;8 ", "SPI" }, { "ACUSON:1.2.840.113680.1.0:7ffe", "ACU" }, { "SIEMENS MED OCS FIELD NAME", "SSPI" }, { "SIEMENS MED OCS FIELD ID", "SSPI" }, { "SIEMENS MED OCS CALIBRATION DATE", "SSPI" }, { "SIEMENS MED OCS NUMBER OF SUB FRAMES", "SSPI" }, { "SIEMENS MED OCS AE TITLE", "SSPI" }, { "GEMS_ADWSoft_DPO1 ", "GEM" }, { "SPI-P-Private_ICS Release 1;6 ", "SSPI" }, { "SIEMENS MR HEADER ", "SSPI" }, { "NO PRIVATE CREATOR", "BLA" }, { "SFS1.00 ", "SFS" }, { "ATL PRIVATE TAGS", "ATL" }, { "Philips EV Imaging DD 022 ", "PMFE" }, { "Harmony R1.0 C2 ", "HRMY" }, { "Harmony R1.0", "HRMY" }, { "Harmony R2.0", "HRMY" }, { "Harmony R1.0 C3 ", "HRMY" }, { "Philips US Imaging DD 017 ", "PMFE" }, { "Philips US Imaging DD 023 ", "PMFE" }, { "Philips US Imaging DD 033 ", "PMFE" }, { "Philips US Imaging DD 034 ", "PMFE" }, { "Philips US Imaging DD 035 ", "PMFE" }, { "Philips US Imaging DD 036 ", "PMFE" }, { "Philips US Imaging DD 038 ", "PMFE" }, { "Philips US Imaging DD 039 ", "PMFE" }, { "Philips US Imaging DD 040 ", "PMFE" }, { "Philips US Imaging DD 042 ", "PMFE" }, { "Philips US Imaging DD 043 ", "PMFE" }, { "Philips US Imaging DD 081 ", "PMFE" }, { "Array DICOM private elements version1.0 ", "ARRAY" }, { "PI Private Block (0781:3000 - 0781:30FF)", "PIP" }, { "XXXXXXXXXXXXXXXX", "ANO" }, // FIXME ! { "XXXXXXXXXXXXXX", "ANO"}, { "XXXXXXXXX_xx", "ANO" }, // FIXME { " MED NM", "ANO" }, // Clearly should be SIEMENS { nullptr, nullptr }, }; std::string GetVersion(std::string const &owner) { const OWNER_VERSION *p = OwnerVersionTable; while( p->owner ) { //#ifndef NDEBUG // if( strlen(p->owner) % 2 ) // { // // HEY ! // std::cerr << "OWNER= \"" << p->owner << "\"" << std::endl; // assert(0); // } //#endif //if( owner == p->owner ) if( strcmp(owner.c_str(), p->owner) == 0 ) { return p->version; } ++p; } std::cerr << "OWNER= \"" << owner << "\"" << std::endl; return "GDCM:UNKNOWN"; } // TODO: make it protected: std::string GetOwner(DataSet const &ds, DataElement const &de) { return ds.GetPrivateCreator(de.GetTag()); } void DictPrinter::PrintDataElement2(std::ostream& os, const DataSet &ds, const DataElement &de) { const Global& g = GlobalInstance; const Dicts &dicts = g.GetDicts(); //const SequenceOfItems *sqi = de.GetSequenceOfItems(); //const SequenceOfFragments *sqf = de.GetSequenceOfFragments(); std::string strowner; const char *owner = nullptr; const Tag& t = de.GetTag(); if( t.IsPrivate() && !t.IsPrivateCreator() ) { strowner = ds.GetPrivateCreator(t); owner = strowner.c_str(); } const DictEntry &entry = dicts.GetDictEntry(t,owner); if( de.GetTag().IsPrivate() && de.GetTag().GetElement() >= 0x0100 ) { //owner = GetOwner(ds,de); //version = GetVersion(owner); const VR &vr = de.GetVR(); VR pvr = vr; if( vr == VR::INVALID ) pvr = VR::UN; if( de.GetTag().GetElement() == 0x0 ) { pvr = VR::UL; } else if( de.GetTag().GetElement() <= 0xFF ) { pvr = VR::LO; owner = "Private Creator"; } VM vm = GuessVMType(de); if( PrintStyle == XML ) { os << "> 8) << "\" "; os << "vr=\"" << pvr << "\" vm=\"" << vm << "\" "; if( de.GetTag().IsPrivate() ) { os << R"(name="?" owner=")" << owner << /*"\" version=\"" << version << */ "\"/>\n"; } } else if ( PrintStyle == CXX ) { 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() ) { os << "\"" << owner << "\","; } std::string vm_str = VM::GetVMString(vm); 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 ) { SmartPointer sqi = de.GetValueAsSQ(); if( sqi ) { SequenceOfItems::ItemVector::const_iterator it = sqi->Items.begin(); for(; it != sqi->Items.end(); ++it) { const Item &item = *it; const DataSet &nestedds = item.GetNestedDataSet(); PrintDataSet2(os, nestedds); } } } } //----------------------------------------------------------------------------- void DictPrinter::PrintDataSet2(std::ostream& os, const DataSet &ds) { DataSet::ConstIterator it = ds.Begin(); for( ; it != ds.End(); ++it ) { const DataElement &de = *it; PrintDataElement2(os, ds, de); } } void DictPrinter::Print(std::ostream& os) { const DataSet &ds = F->GetDataSet(); PrintDataSet2(os, ds); //os << "\n"; } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDictPrinter.h000066400000000000000000000020561412732066400237500ustar00rootroot00000000000000/*========================================================================= 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 GDCMDICTPRINTER_H #define GDCMDICTPRINTER_H #include "gdcmPrinter.h" namespace gdcm { /** * \brief DictPrinter class */ // It's a sink there is no output class GDCM_EXPORT DictPrinter : public Printer { public: DictPrinter(); ~DictPrinter(); void Print(std::ostream& os); protected: void PrintDataElement2(std::ostream& os, const DataSet &ds, const DataElement &ide); void PrintDataSet2(std::ostream& os, const DataSet &ds); }; } // end namespace gdcm #endif //GDCMDICTPRINTER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx000066400000000000000000000076241412732066400253460ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDirectionCosines.h" #include #include // fabs #include // sscanf namespace gdcm { DirectionCosines::DirectionCosines() { Values[0] = 1; Values[1] = 0; Values[2] = 0; Values[3] = 0; Values[4] = 1; Values[5] = 0; } DirectionCosines::DirectionCosines(const double dircos[6]) { Values[0] = dircos[0]; Values[1] = dircos[1]; Values[2] = dircos[2]; Values[3] = dircos[3]; Values[4] = dircos[4]; Values[5] = dircos[5]; } DirectionCosines::~DirectionCosines() = default; void DirectionCosines::Print(std::ostream &os) const { os << Values[0] << ","; os << Values[1] << ","; os << Values[2] << ","; os << Values[3] << ","; os << Values[4] << ","; os << Values[5]; } bool DirectionCosines::IsValid() const { // gdcmData/gdcm-MR-SIEMENS-16-2.acr // => {-1, -0, 0, -0, 0.05233599990606308, 0.99862951040267944} const double epsilon = 1e-3; //std::numeric_limits::epsilon(); double norm_v1 = Values[0] * Values[0] + Values[1]*Values[1] + Values[2]*Values[2]; double norm_v2 = Values[3] * Values[3] + Values[4]*Values[4] + Values[5]*Values[5]; double dot = Dot(); bool ret = false; if( fabs(norm_v1 - 1) < epsilon && fabs(norm_v2 - 1) < epsilon ) { if( fabs(dot) < epsilon ) { ret = true; } } return ret; } void DirectionCosines::Cross(double z[3]) const { //assert( Dot() == 0 ); const double *x = Values; const double *y = x+3; double Zx = x[1]*y[2] - x[2]*y[1]; double Zy = x[2]*y[0] - x[0]*y[2]; double Zz = x[0]*y[1] - x[1]*y[0]; z[0] = Zx; z[1] = Zy; z[2] = Zz; } static inline double DotImpl(const double x[3], const double y[3]) { return x[0]*y[0] + x[1]*y[1] + x[2]*y[2]; } double DirectionCosines::Dot(const double x[3], const double y[3]) { return DotImpl(x, y); } double DirectionCosines::Dot() const { return DotImpl(Values, Values+3); } // static function is within gdcm:: namespace, so should not pollute too much on UNIX static inline double Norm(const double x[3]) { return sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]); } void DirectionCosines::Normalize(double v[3]) { double den; if ( (den = Norm(v)) != 0.0 ) { for (int i=0; i < 3; i++) { v[i] /= den; } } } void DirectionCosines::Normalize() { double *x = Values; double den; if ( (den = Norm(x)) != 0.0 ) { for (int i=0; i < 3; i++) { x[i] /= den; } } x = Values+3; if ( (den = Norm(x)) != 0.0 ) { for (int i=0; i < 3; i++) { x[i] /= den; } } } bool DirectionCosines::SetFromString(const char *str) { if( str ) { const int n = sscanf( str, R"(%lf\%lf\%lf\%lf\%lf\%lf)", Values, Values+1, Values+2, Values+3, Values+4, Values+5 ); if( n == 6 ) { return true; } } // else Values[0] = 1; Values[1] = 0; Values[2] = 0; Values[3] = 0; Values[4] = 1; Values[5] = 0; return false; } double DirectionCosines::CrossDot(DirectionCosines const &dc) const { double z1[3]; Cross(z1); double z2[3]; dc.Cross(z2); const double *x = z1; const double *y = z2; return x[0]*y[0] + x[1]*y[1] + x[2]*y[2]; } double DirectionCosines::ComputeDistAlongNormal(const double ipp[3]) const { double normal[3]; Cross(normal); double dist = 0.; for (int i = 0; i < 3; ++i) dist += normal[i]*ipp[i]; return dist; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h000066400000000000000000000036761412732066400247760ustar00rootroot00000000000000/*========================================================================= 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 GDCMDIRECTIONCOSINES_H #define GDCMDIRECTIONCOSINES_H #include "gdcmTypes.h" namespace gdcm { /** * \brief class to handle DirectionCosines */ class GDCM_EXPORT DirectionCosines { public: DirectionCosines(); DirectionCosines(const double dircos[6]); // Cannot get the following signature to be wrapped with swig... //DirectionCosines(const double *dircos = 0 ); ~DirectionCosines(); /// Print void Print(std::ostream &) const; /// Compute Cross product void Cross(double z[3]) const; /// Compute Dot double Dot() const; /// Compute Dot static double Dot(const double x[3], const double y[3]); /// Normalize in-place void Normalize(); /// Normalize in-place static void Normalize(double v[3]); /// Make the class behave like a const double * operator const double* () const { return Values; } /// Return whether or not this is a valid direction cosines bool IsValid() const; /// Initialize from string str. It requires 6 floating point separated by a /// backslash character. bool SetFromString(const char *str); /// Compute the Dot product of the two cross vector of both DirectionCosines object double CrossDot(DirectionCosines const &dc) const; /// Compute the distance along the normal double ComputeDistAlongNormal(const double ipp[3]) const; private: double Values[6]; }; } // end namespace gdcm #endif //GDCMDIRECTIONCOSINES_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDirectoryHelper.cxx000066400000000000000000000250271412732066400252030ustar00rootroot00000000000000 #include "gdcmDirectoryHelper.h" #include "gdcmScanner.h" #include "gdcmIPPSorter.h" #include "gdcmAttribute.h" #include "gdcmDataElement.h" #include "gdcmReader.h" namespace gdcm{ //given an SOPClassUID, get the number of series that are that SOP Class //that is, the MR images, the CT Images, whatever. Just have to be sure to give the proper //SOP Class UID. //returns an empty vector if nothing's there or if something goes wrong. Directory::FilenamesType DirectoryHelper::GetSeriesUIDsBySOPClassUID(const std::string& inDirectory, const std::string& inSOPClassUID) { Scanner theScanner; Directory theDir; theScanner.AddTag(Tag(0x0008, 0x0016));//SOP Class UID theScanner.AddTag(Tag(0x0020, 0x000e));//Series UID Directory::FilenamesType theReturn; try { theDir.Load(inDirectory); theScanner.Scan(theDir.GetFilenames()); //now find all series UIDs Directory::FilenamesType theSeriesValues = theScanner.GetOrderedValues(Tag(0x0020,0x000e)); //now count the number of series that are of that given SOPClassUID size_t theNumSeries = theSeriesValues.size(); for (size_t i = 0; i < theNumSeries; i++){ std::string theFirstFilename = 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 if( std::string::npos != endpos ) theSOPClassUID = theSOPClassUID.substr( 0, endpos+1 ); if (theSOPClassUID == inSOPClassUID.c_str()){ theReturn.push_back(theSeriesValues[i]); } } return theReturn; } catch (...){ Directory::FilenamesType theBlank; return theBlank;//something broke during scanning } } //given the name of a directory, return the list of CT Image UIDs Directory::FilenamesType DirectoryHelper::GetCTImageSeriesUIDs(const std::string& inDirectory) { return GetSeriesUIDsBySOPClassUID(inDirectory, "1.2.840.10008.5.1.4.1.1.2"); } //given the name of a directory, return the list of CT Image UIDs Directory::FilenamesType DirectoryHelper::GetMRImageSeriesUIDs(const std::string& inDirectory) { return GetSeriesUIDsBySOPClassUID(inDirectory, "1.2.840.10008.5.1.4.1.1.4"); } //given the name of a directory, return the list of CT Image UIDs Directory::FilenamesType DirectoryHelper::GetRTStructSeriesUIDs(const std::string& inDirectory) { return GetSeriesUIDsBySOPClassUID(inDirectory, "1.2.840.10008.5.1.4.1.1.481.3"); } //given a directory and a series UID, provide all filenames with that series UID. Directory::FilenamesType DirectoryHelper::GetFilenamesFromSeriesUIDs(const std::string& inDirectory, const std::string& inSeriesUID) { Scanner theScanner; Directory theDir; theScanner.AddTag(Tag(0x0020, 0x000e));//Series UID Directory::FilenamesType theReturn; try { theDir.Load(inDirectory); theScanner.Scan(theDir.GetFilenames()); //now find all series UIDs Directory::FilenamesType theSeriesValues = theScanner.GetOrderedValues(Tag(0x0020,0x000e)); //now count the number of series that are of that given SOPClassUID size_t theNumSeries = theSeriesValues.size(); for (size_t i = 0; i < theNumSeries; i++) { 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 if( std::string::npos != endpos ) theSeriesUID = theSeriesUID.substr( 0, endpos+1 ); if (inSeriesUID == theSeriesUID) { Directory::FilenamesType theFilenames = theScanner.GetAllFilenamesFromTagToValue(Tag(0x0020, 0x000e), theSeriesValues[i].c_str()); Directory::FilenamesType::const_iterator citor; for (citor = theFilenames.begin(); citor < theFilenames.end(); citor++) { theReturn.push_back(*citor); } // theReturn.push_back(theScanner.GetFilenameFromTagToValue(Tag(0x0020,0x000e), // theSeriesValues[i].c_str())); } } return theReturn; } catch (...){ Directory::FilenamesType theBlank; return theBlank;//something broke during scanning } } //the code in GetSeriesUIDsBySOPClassUID will enumerate the CT images in a directory //This code will retrieve an image by its Series UID. //this code doesn't return pointers or smart pointers because it's intended to //be easily wrapped by calling languages that don't know pointers (ie, Java) //this function is a proof of concept //for it to really work, it needs to also std::vector DirectoryHelper::LoadImageFromFiles(const std::string& inDirectory, const std::string& inSeriesUID) { Scanner theScanner; Directory theDir; theScanner.AddTag(Tag(0x0020, 0x000e));//Series UID std::vector theReturn; std::vector blank;//returned in case of an error try { theDir.Load(inDirectory); theScanner.Scan(theDir.GetFilenames()); //now find all series UIDs Directory::FilenamesType theSeriesValues = theScanner.GetOrderedValues(Tag(0x0020,0x000e)); //now count the number of series that are of that given SOPClassUID size_t theNumSeries = theSeriesValues.size(); for (size_t i = 0; i < theNumSeries; i++){ if (inSeriesUID == theSeriesValues[i]){ //find all files that have that series UID, and then load them via //the vtkImageReader Directory::FilenamesType theFiles = theScanner.GetAllFilenamesFromTagToValue(Tag(0x0020, 0x000e), theSeriesValues[i].c_str()); IPPSorter sorter; sorter.SetComputeZSpacing(true); sorter.SetZSpacingTolerance(0.000001); if (!sorter.Sort(theFiles)){ gdcmWarningMacro("Unable to sort Image Files."); return blank; } Directory::FilenamesType theSortedFiles = sorter.GetFilenames(); for (unsigned long j = 0; j < theSortedFiles.size(); ++j){ Reader theReader; theReader.SetFileName(theSortedFiles[j].c_str()); theReader.Read(); theReturn.push_back(theReader.GetFile().GetDataSet()); } return theReturn; } } return blank; } catch (...){ gdcmWarningMacro("Something went wrong reading CT images."); return blank; } } //When writing RTStructs, each contour will have z position defined. //use that z position to determine the SOPInstanceUID for that plane. std::string DirectoryHelper::RetrieveSOPInstanceUIDFromZPosition(double inZPos, const std::vector& inDS) { std::vector::const_iterator itor; Tag thePosition(0x0020, 0x0032); Tag theSOPInstanceUID(0x0008, 0x0018); Tag theSpacingBetweenSlice(0x0018, 0x0088); double interSlice = 0.01; if (inDS.begin() != inDS.end() && inDS.begin()->FindDataElement(theSpacingBetweenSlice)) { DataElement tmpDe = inDS.begin()->GetDataElement(theSpacingBetweenSlice); Attribute<0x0018,0x0088> tmpAt; tmpAt.SetFromDataElement(tmpDe); interSlice = fabs(tmpAt.GetValue())/2.0; } std::string blank;//return only if there's a problem for (itor = inDS.begin(); itor != inDS.end(); itor++) { if (itor->FindDataElement(thePosition)) { DataElement de = itor->GetDataElement(thePosition); Attribute<0x0020,0x0032> at; at.SetFromDataElement( de ); if (fabs(at.GetValue(2) - inZPos)GetDataElement(theSOPInstanceUID); const ByteValue* theVal = de2.GetByteValue(); size_t theValLen = theVal->GetLength(); std::string theReturn(de2.GetByteValue()->GetPointer(), theValLen); return theReturn; } } } return blank; } //When writing RTStructs, the frame of reference is done by planes to start with std::string DirectoryHelper::RetrieveSOPInstanceUIDFromIndex(int inIndex, const std::vector& inDS) { Tag theSOPInstanceUID(0x0008, 0x0018); std::string blank;//return only if there's a problem if (inDS[inIndex].FindDataElement(theSOPInstanceUID)){ DataElement de = inDS[inIndex].GetDataElement(theSOPInstanceUID); const ByteValue* theVal = de.GetByteValue(); size_t theValLen = theVal->GetLength(); std::string theReturn(de.GetByteValue()->GetPointer(), theValLen); return theReturn; } return blank; } //each plane needs to know the SOPClassUID, and that won't change from image to image //so, retrieve this once at the start of writing. std::string DirectoryHelper::GetSOPClassUID(const std::vector& inDS) { Tag theSOPClassUID(0x0008, 0x0016); std::string blank;//return only if there's a problem if (inDS[0].FindDataElement(theSOPClassUID)){ DataElement de = inDS[0].GetDataElement(theSOPClassUID); const ByteValue* theVal = de.GetByteValue(); size_t theValLen = theVal->GetLength(); std::string theReturn(de.GetByteValue()->GetPointer(), theValLen); return theReturn; } return blank; } //retrieve the frame of reference from the set of datasets std::string DirectoryHelper::GetFrameOfReference(const std::vector& inDS){ Tag theSOPClassUID(0x0020, 0x0052); std::string blank;//return only if there's a problem if (inDS[0].FindDataElement(theSOPClassUID)){ DataElement de = inDS[0].GetDataElement(theSOPClassUID); const ByteValue* theVal = de.GetByteValue(); size_t theValLen = theVal->GetLength(); std::string theReturn(de.GetByteValue()->GetPointer(), theValLen); return theReturn; } return blank; } //---------------------------------------------------------------------------- //used by the vtkGDCMImageReader and vtkGDCMPolyDataReader. Could be used elsewhere, I suppose. std::string DirectoryHelper::GetStringValueFromTag(const Tag& t, const DataSet& ds) { std::string buffer; if( ds.FindDataElement( t ) ) { const DataElement& de = ds.GetDataElement( t ); const ByteValue *bv = de.GetByteValue(); if( bv ) // Can be Type 2 { buffer = std::string( bv->GetPointer(), bv->GetLength() ); // Will be padded with at least one \0 } } // Since return is a const char* the very first \0 will be considered return buffer.c_str(); // Yes, I mean .c_str() } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDirectoryHelper.h000066400000000000000000000070141412732066400246240ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDirectory.h" #include "gdcmDataSet.h" namespace gdcm { /** * \brief DirectoryHelper * \details this class is designed to help mitigate some of the commonly performed * operations on directories. namely: * 1) the ability to determine the number of series in a directory by what type * of series is present * 2) the ability to find all ct series in a directory * 3) the ability to find all mr series in a directory * 4) to load a set of DataSets from a series that's already been sorted by the * IPP sorter * 5) For rtstruct stuff, you need to know the sopinstanceuid of each z plane, * so there's a retrieval function for that * 6) then a few other functions for rtstruct writeouts */ class GDCM_EXPORT DirectoryHelper { public: //returns all series UIDs in a given directory that match a particular SOP Instance UID static Directory::FilenamesType GetSeriesUIDsBySOPClassUID(const std::string& inDirectory, const std::string& inSOPClassUID); //specific implementations of the SOPClassUID grabber, so you don't have to //remember the SOP Class UIDs of CT or MR images. static Directory::FilenamesType GetCTImageSeriesUIDs(const std::string& inDirectory); static Directory::FilenamesType GetMRImageSeriesUIDs(const std::string& inDirectory); static Directory::FilenamesType GetRTStructSeriesUIDs(const std::string& inDirectory); //given a directory and a series UID, provide all filenames with that series UID. static Directory::FilenamesType GetFilenamesFromSeriesUIDs(const std::string& inDirectory, const std::string& inSeriesUID); //given a series UID, load all the images associated with that series UID //these images will be IPP sorted, so that they can be used for gathering all //the necessary information for generating an RTStruct //this function should be called by the writer once, if the writer's dataset //vector is empty. Make sure to have a new writer for new rtstructs. static std::vector LoadImageFromFiles(const std::string& inDirectory, const std::string& inSeriesUID); //When writing RTStructs, each contour will have z position defined. //use that z position to determine the SOPInstanceUID for that plane. static std::string RetrieveSOPInstanceUIDFromZPosition(double inZPos, const std::vector& inDS); //When writing RTStructs, the frame of reference is done by planes to start with static std::string RetrieveSOPInstanceUIDFromIndex(int inIndex, const std::vector& inDS); //each plane needs to know the SOPClassUID, and that won't change from image to image //so, retrieve this once at the start of writing. static std::string GetSOPClassUID(const std::vector& inDS); //retrieve the frame of reference from the set of datasets static std::string GetFrameOfReference(const std::vector& inDS); //both the image and polydata readers use these functions to get std::strings static std::string GetStringValueFromTag(const Tag& t, const DataSet& ds); }; } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDumper.cxx000066400000000000000000000011401412732066400233210ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDumper.h" namespace gdcm { } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmDumper.h000066400000000000000000000020061412732066400227500ustar00rootroot00000000000000/*========================================================================= 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 GDCMDUMPER_H #define GDCMDUMPER_H #include "gdcmPrinter.h" 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 */ class GDCM_EXPORT Dumper : public Printer { public: Dumper() { PrintStyle = CONDENSED_STYLE; } ~Dumper() = default; }; } // end namespace gdcm #endif //GDCMDUMPER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmEmptyMaskGenerator.cxx000066400000000000000000000360241412732066400256570ustar00rootroot00000000000000/*========================================================================= 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 "gdcmEmptyMaskGenerator.h" #include "gdcmImage.h" #include "gdcmImageWriter.h" #include "gdcmFileDerivation.h" #include "gdcmUIDGenerator.h" #include "gdcmImageRegionReader.h" #include "gdcmDirectory.h" #include "gdcmScanner.h" #include "gdcmFilename.h" #include "gdcmFileStreamer.h" #include "gdcmAnonymizer.h" #include "gdcmAttribute.h" #include "gdcmTagKeywords.h" namespace gdcm { struct EmptyMaskGenerator::impl { static const Tag TSOPClassUID; static const Tag TSOPInstanceUID; static const Tag TSeriesInstanceUID; static const Tag TFrameOfReferenceUID; SOPClassUIDMode mode; std::string inputdir; std::string outputdir; UIDGenerator uid; std::map< std::string, std::string > seriesuidhash; std::map< std::string, std::string > framerefuidhash; Scanner s; bool collectuids(Tag const & tag, std::map< std::string, std::string > & hash); bool setup(const char * dirname, const char * outdir); bool setmask( File & file ); bool derive( const char * filename, File & file ) const; bool anonymizeattributes( const char * filename, File & file ); bool populateattributes( const char * filename, File const & orifile, File & file ); bool setts( File & file ); bool run(const char * filename, const char * outfile); }; const Tag EmptyMaskGenerator::impl::TSOPClassUID = Tag(0x0008,0x0016); const Tag EmptyMaskGenerator::impl::TSOPInstanceUID = Tag(0x0008,0x0018); const Tag EmptyMaskGenerator::impl::TSeriesInstanceUID = Tag(0x0020,0x000e); const Tag EmptyMaskGenerator::impl::TFrameOfReferenceUID = Tag(0x0020,0x0052); bool EmptyMaskGenerator::impl::collectuids( Tag const & tag, std::map< std::string, std::string > & hash) { Scanner::ValuesType vt = s.GetValues(tag); for( Scanner::ValuesType::const_iterator it = vt.begin(); it != vt.end(); ++it ) { const char * newuid = uid.Generate(); hash.insert( std::make_pair( *it, newuid ) ); } return true; } bool EmptyMaskGenerator::impl::setmask( File & file ) { DataSet& ds = file.GetDataSet(); namespace kwd = Keywords; kwd::ImageType imtype; kwd::ImageType copy; imtype.SetFromDataSet( ds ); unsigned int nvalues = imtype.GetNumberOfValues(); unsigned int newvalues = std::max( nvalues, 4u ); copy.SetNumberOfValues( newvalues ); // copy original ones: for( unsigned int i = 0u; i < nvalues; ++i ) { copy.SetValue(i, imtype.GetValue(i) ); } // Make up non empty values: static const CSComp values[] = {"DERIVED","SECONDARY","OTHER"}; for( unsigned int i = nvalues; i < 3u; ++i ) { copy.SetValue(i, values[i] ); } // The fourth value is required to be set to 'MASK' for SD copy.SetValue( 3u, "MASK" ); ds.Replace( copy.GetAsDataElement() ); return true; } bool EmptyMaskGenerator::impl::setup(const char * dirname, const char * outdir) { if( !System::FileIsDirectory( dirname ) ) return false; if( !System::MakeDirectory( outdir ) ) return false; Directory d; // recursive search by default const unsigned int nfiles = d.Load( dirname, true ); if( nfiles == 0 ) { gdcmDebugMacro( "No files found in: " << dirname ); return false; } Directory::FilenamesType const & filenames = d.GetFilenames(); s.AddTag( TSOPClassUID ); s.AddTag( TSOPInstanceUID ); s.AddTag( TSeriesInstanceUID ); s.AddTag( TFrameOfReferenceUID ); // reduce verbosity when looping over a set of files: Trace::WarningOff(); if( !s.Scan( filenames ) ) { gdcmDebugMacro( "Scanner failure for directory: " << dirname ); return false; } if( !collectuids( TSeriesInstanceUID, seriesuidhash ) ) return false; // Frame of Reference are relative to Series UID // http://dicom.nema.org/medical/Dicom/2015a/output/chtml/part03/sect_C.7.4.html if( !collectuids( TFrameOfReferenceUID, framerefuidhash ) ) return false; return true; } bool EmptyMaskGenerator::impl::derive( const char * filename, File & file ) const { FileDerivation fd; const char * referencedsopclassuid = s.GetValue (filename, TSOPClassUID); const char * referencedsopinstanceuid = s.GetValue (filename, TSOPInstanceUID); if( !fd.AddReference( referencedsopclassuid, referencedsopinstanceuid ) ) { gdcmDebugMacro( "Impossible to AddRef: " << filename ); // This is not considered an error to not reference, eg. UID padded with 0 } // CID 7202 Source Image Purposes of Reference // DCM 121321 Mask image for image processing operation fd.SetPurposeOfReferenceCodeSequenceCodeValue( 121321 ); // CID 7203 Image Derivation // DCM 113047 Pixel by pixel mask fd.SetDerivationCodeSequenceCodeValue( 113047 ); fd.SetDerivationDescription( "Empty Mask Derivation" ); // always append derivation history to any existing one: fd.SetAppendDerivationHistory( true ); fd.SetFile( file ); if( !fd.Derive() ) { gdcmDebugMacro( "Sorry could not derive using input info" ); return false; } return true; } bool EmptyMaskGenerator::impl::anonymizeattributes( const char * filename, File & file ) { Anonymizer ano; ano.SetFile( file ); ano.RemoveGroupLength(); ano.RemovePrivateTags(); namespace kwd = Keywords; ano.Remove( kwd::WindowCenter::GetTag() ); ano.Remove( kwd::WindowWidth::GetTag() ); if( !ano.Replace (TSOPInstanceUID, uid.Generate()) ) return false; const char * oldseriesuid = s.GetValue (filename, TSeriesInstanceUID); const char * oldframerefuid = s.GetValue (filename, TFrameOfReferenceUID); if( oldseriesuid ) { std::map< std::string, std::string >::const_iterator it1 = seriesuidhash.find( oldseriesuid ); if( !ano.Replace (TSeriesInstanceUID, it1->second.c_str() ) ) return false; } if( oldframerefuid ) { std::map< std::string, std::string >::const_iterator it2 = framerefuidhash.find( oldframerefuid ); if( !ano.Replace (TFrameOfReferenceUID, it2->second.c_str() ) ) return false; } return true; } bool EmptyMaskGenerator::impl::populateattributes( const char * filename, File const & orifile, File & file ) { namespace kwd = Keywords; DataSet & ds = file.GetDataSet(); // ContentDate char date[22]; const size_t datelen = 8; System::GetCurrentDateTime(date); kwd::ContentDate contentdate; // Do not copy the whole cstring: contentdate.SetValue( DAComp( date, datelen ) ); ds.Insert( contentdate.GetAsDataElement() ); // ContentTime const size_t timelen = 6 + 1 + 6; // time + milliseconds kwd::ContentTime contenttime; // Do not copy the whole cstring: contenttime.SetValue( TMComp(date+datelen, timelen) ); ds.Insert( contenttime.GetAsDataElement() ); const DataSet & orids = orifile.GetDataSet(); kwd::SeriesInstanceUID seriesinstanceuid; seriesinstanceuid.SetValue( uid.Generate() ); // In case original instance is missing Series Instance UID kwd::SeriesNumber seriesnumber = { 1 }; const char * oldseriesuid = s.GetValue (filename, TSeriesInstanceUID); if( oldseriesuid ) { std::map< std::string, std::string >::iterator it = seriesuidhash.find( oldseriesuid ); seriesinstanceuid.SetValue( it->second.c_str() ); std::map< std::string, std::string >::difference_type diff = std::distance(seriesuidhash.begin(),it); seriesnumber.SetValue( 1 + (int)diff ); // Start at one } ds.Insert( seriesinstanceuid.GetAsDataElement() ); ds.Insert( seriesnumber.GetAsDataElement() ); kwd::FrameOfReferenceUID frameref; frameref.SetValue( uid.Generate() ); const char * oldframerefuid = s.GetValue (filename, TFrameOfReferenceUID); if( oldframerefuid ) { std::map< std::string, std::string >::const_iterator it = framerefuidhash.find( oldframerefuid ); frameref.SetValue( it->second.c_str() ); } ds.Insert( frameref.GetAsDataElement() ); kwd::InstanceNumber instancenum = { 1 }; if( orids.FindDataElement( instancenum.GetTag() ) ) { instancenum.SetFromDataSet( orids ); } else { static unsigned int counter = 0; // unsigned will wrap properly instancenum.SetValue( counter++ ); } ds.Insert( instancenum.GetAsDataElement() ); kwd::StudyInstanceUID studyinstanceuid; studyinstanceuid.SetFromDataSet( orids ); ds.Insert( studyinstanceuid.GetAsDataElement() ); kwd::StudyID studyid = { "ST1" }; studyid.SetFromDataSet( orids ); ds.Insert( studyid.GetAsDataElement() ); kwd::PatientID patientid; patientid.SetFromDataSet( orids ); ds.Insert( patientid.GetAsDataElement() ); kwd::PositionReferenceIndicator pri; ds.Insert( pri.GetAsDataElement() ); kwd::BodyPartExamined bodypartex; bodypartex.SetFromDataSet( orids ); ds.Insert( bodypartex.GetAsDataElement() ); // Sync with Body Part Examined: kwd::Laterality lat; if( orids.FindDataElement( lat.GetTag() ) ) { lat.SetFromDataSet( orids ); ds.Insert( lat.GetAsDataElement() ); } kwd::PatientOrientation pator; pator.SetFromDataSet( orids ); ds.Insert( pator.GetAsDataElement() ); kwd::BurnedInAnnotation bia = { "NO" }; ds.Insert( bia.GetAsDataElement() ); kwd::ConversionType convtype = { "SYN" }; ds.Insert( convtype.GetAsDataElement() ); kwd::PresentationLUTShape plutshape = { "IDENTITY" }; // MONOCHROME2 ds.Insert( plutshape.GetAsDataElement() ); kwd::SOPClassUID sopclassuid; // gdcm will pick the Word in case Byte class is not compatible: MediaStorage ms = MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage; sopclassuid.SetValue( ms.GetString() ); ds.Insert( sopclassuid.GetAsDataElement() ); return true; } bool EmptyMaskGenerator::impl::setts( File & file ) { FileMetaInformation & fmi = file.GetHeader(); const TransferSyntax & orits = fmi.GetDataSetTransferSyntax(); TransferSyntax::TSType newts = TransferSyntax::ImplicitVRLittleEndian; if( orits.IsExplicit() ) { newts = TransferSyntax::ExplicitVRLittleEndian; } fmi.Clear(); fmi.SetDataSetTransferSyntax( newts ); return true; } bool EmptyMaskGenerator::impl::run(const char * filename, const char * outfile) { if( !s.IsKey( filename ) ) { gdcmErrorMacro( "Not DICOM file: " << filename ); return false; } ImageRegionReader irr; irr.SetFileName( filename ); if( !irr.ReadInformation() ) { gdcmErrorMacro( "Impossible to ReadInformation (not an image?): " << filename ); return false; } size_t buflen = irr.ComputeBufferLength(); Image & img = irr.GetImage(); if( img.GetPhotometricInterpretation() != PhotometricInterpretation::MONOCHROME1 && img.GetPhotometricInterpretation() != PhotometricInterpretation::MONOCHROME2 ) { gdcmErrorMacro( "Cannot process PhotometricInterpretation from: " << filename ); return false; } if( mode == UseOriginalSOPClassUID ) { File & file = irr.GetFile(); // derive operation needs to operate on original attributes (before anonymization): if( !derive( filename, file ) ) return false; // copy original attributes: if( !anonymizeattributes( filename, file ) ) return false; if( !setmask( file ) ) return false; if( !setts( file ) ) return false; Writer w; w.SetFile( file ); w.SetFileName( outfile ); if( !w.Write() ) { return false; } } else if ( mode == UseGrayscaleSecondaryImageStorage ) { ImageWriter w; File & file = w.GetFile(); if( !derive( filename, file ) ) return false; // create attributes: if( !populateattributes( filename, irr.GetFile(), file ) ) return false; if( !setmask( file ) ) return false; if( !setts( file ) ) return false; PixelFormat & pf = img.GetPixelFormat(); pf.SetPixelRepresentation(0); // always overwrite to unsigned img.SetSlope(1); img.SetIntercept(0); w.SetImage( img ); w.SetFileName( outfile ); // sentinel, SC is never acceptable: if( w.ComputeTargetMediaStorage() == MediaStorage::SecondaryCaptureImageStorage ) { gdcmErrorMacro( "Failure to compute MediaStorage: " << filename ); return false; } if( !w.Write() ) { return false; } } else { // possibly dead code, but make sure to report an error for invalid state: return false; } // now create the empty pixel data element, a chunk at a time: FileStreamer fs; fs.SetTemplateFileName(outfile); fs.SetOutputFileName(outfile); Tag pixeldata (0x7fe0, 0x0010); fs.CheckDataElement( pixeldata ); // double check generated output if( !fs.StartDataElement( pixeldata ) ) { gdcmErrorMacro( "StartDataElement" ); return false; } { const unsigned int chunk = 4096u; char bytes[chunk] = {}; const unsigned int nchunks = (unsigned int)( buflen / chunk); const unsigned int remain = buflen % chunk; for( unsigned int i = 0; i < nchunks; ++i ) { // Read the source file into a byte array. fs.AppendToDataElement( pixeldata, bytes, chunk ); } fs.AppendToDataElement( pixeldata, bytes, remain ); } if( !fs.StopDataElement( pixeldata ) ) { // Most likely an issue with Pixel Data Length computation: gdcmErrorMacro( "StopDataElement" ); return false; } return true; } EmptyMaskGenerator::EmptyMaskGenerator():pimpl(new impl) { } EmptyMaskGenerator::~EmptyMaskGenerator() { delete pimpl; } void EmptyMaskGenerator::SetSOPClassUIDMode( SOPClassUIDMode mode ) { pimpl->mode = mode; } void EmptyMaskGenerator::SetInputDirectory(const char * dirname) { if( dirname ) pimpl->inputdir = dirname; } void EmptyMaskGenerator::SetOutputDirectory(const char * dirname) { if( dirname ) pimpl->outputdir = dirname; } bool EmptyMaskGenerator::Execute() { const char * dirname = pimpl->inputdir.c_str(); const char * outdir = pimpl->outputdir.c_str(); if( !pimpl->setup(dirname, outdir) ) { return false; } bool success = true; Directory::FilenamesType const & filenames = pimpl->s.GetFilenames(); for( Directory::FilenamesType::const_iterator it = filenames.begin(); it != filenames.end(); ++it ) { const char * filename = it->c_str(); Filename fn( filename ); std::string outfile = outdir; outfile += '/'; outfile += fn.GetName(); if( !pimpl->run( filename, outfile.c_str() ) ) { gdcmErrorMacro( "Failure to EmptyMask" ); // Since we may have failed in the middle of writing of the file, remove it: if( System::FileExists(outfile.c_str()) && !System::RemoveFile(outfile.c_str()) ) { gdcmErrorMacro( "Failure to RemoveFile: " << outfile ); // may want to call exit() here, since we failed to remove a file we created in this process: return false; } // declare failure to process a file, but continue main loop: success = false; } } return success; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmEmptyMaskGenerator.h000066400000000000000000000052231412732066400253010ustar00rootroot00000000000000/*========================================================================= 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 GDCMEMPTYMASKGENERATOR_H #define GDCMEMPTYMASKGENERATOR_H #include "gdcmSubject.h" namespace gdcm { /** * \brief EmptyMaskGenerator * Main class to generate a Empty Mask Series from an input Series. This class * takes an input folder and generates a series of DICOM files in the specified * output directory. * This class handles multiples DICOM Series within the same input directory. * * The class allow two mode of operations: * - UseOriginalSOPClassUID * - UseGrayscaleSecondaryImageStorage * * UseOriginalSOPClassUID is the mode where original attributes are copied from * the original DICOM instance. * * UseGrayscaleSecondaryImageStorage is the mode where attributes are generated * so as to create a MultiframeGrayscaleByteSecondaryCaptureImageStorage * (MultiframeGrayscaleWordSecondaryCaptureImageStorage) instance. * * In both mode: * - the Study references (StudyInstanceUID and StudyID) are preserved. * - the PatientID reference is preserved. * - the Image Type attribute will be setup so that the fourth * element is set to 'MASK'. * - a new Series Instance UID is generated. It is thus required to run the process * over all files using the same input Series Instance UID so that a proper mapping * from the old Series UID is done to the new one. * Since a new Series Instance UID is generated, there is no sense to * preserve the original Frame of Reference UID, although it would have made * sense here. */ class GDCM_EXPORT EmptyMaskGenerator { public: EmptyMaskGenerator(); ~EmptyMaskGenerator(); enum SOPClassUIDMode { UseOriginalSOPClassUID = 0, // default UseGrayscaleSecondaryImageStorage }; /// Select generation of SOP Class UID method: /// Default is UseOriginalSOPClassUID void SetSOPClassUIDMode( SOPClassUIDMode mode ); /// Specify input directory void SetInputDirectory( const char * dirname ); /// Specify output directory void SetOutputDirectory( const char * dirname ); /// Main loop bool Execute(); private: struct impl; // PIMPL idiom impl* pimpl; }; } // end namespace gdcm #endif //GDCMEMPTYMASKGENERATOR_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmEncapsulatedDocument.cxx000066400000000000000000000011551412732066400262020ustar00rootroot00000000000000/*========================================================================= 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 "gdcmEncapsulatedDocument.h" namespace gdcm {} GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmEncapsulatedDocument.h000066400000000000000000000015521412732066400256300ustar00rootroot00000000000000/*========================================================================= 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 GDCMENCAPSULATEDDOCUMENT_H #define GDCMENCAPSULATEDDOCUMENT_H #include "gdcmFile.h" namespace gdcm { /** * \brief EncapsulatedDocument */ class GDCM_EXPORT EncapsulatedDocument { public: EncapsulatedDocument() = default; private: }; } // end namespace gdcm #endif //GDCMENCAPSULATEDDOCUMENT_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmEquipmentManufacturer.cxx000066400000000000000000000076231412732066400264250ustar00rootroot00000000000000/*========================================================================= 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 "gdcmEquipmentManufacturer.h" #include "gdcmAttribute.h" #include "gdcmSystem.h" namespace gdcm { struct Mapping { EquipmentManufacturer::Type type; size_t nstrings; 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 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) #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 ) }; 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; } } // 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; } 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; } 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; } return UNKNOWN; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmEquipmentManufacturer.h000066400000000000000000000020171412732066400260420ustar00rootroot00000000000000/*========================================================================= 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 GDCMEQUIPMENTMANUFACTURER_H #define GDCMEQUIPMENTMANUFACTURER_H #include "gdcmTypes.h" namespace gdcm { class DataSet; /** * \brief * \details * */ class GDCM_EXPORT EquipmentManufacturer { public: typedef enum { UNKNOWN = 0, FUJI, GEMS, HITACHI, KODAK, MARCONI, PMS, SIEMENS, TOSHIBA } Type; static Type Compute( DataSet const & ds ); private: }; } // end namespace gdcm #endif // GDCMEQUIPMENTMANUFACTURER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmFiducials.cxx000066400000000000000000000011421412732066400237720ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFiducials.h" namespace gdcm {} GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmFiducials.h000066400000000000000000000014501412732066400234210ustar00rootroot00000000000000/*========================================================================= 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 GDCMFIDUCIALS_H #define GDCMFIDUCIALS_H #include "gdcmFile.h" namespace gdcm { /** * \brief Fiducials */ class GDCM_EXPORT Fiducials { public: Fiducials() = default; private: }; } // end namespace gdcm #endif //GDCMFIDUCIALS_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmFileAnonymizer.cxx000066400000000000000000000376661412732066400250460ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileAnonymizer.h" #include "gdcmReader.h" #include #include #include #include #include // sort #ifdef _MSC_VER #pragma warning (disable : 4068 ) /* disable unknown pragma warnings */ #endif // 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 #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif namespace gdcm { enum Action { EMPTY, REMOVE, REPLACE }; struct PositionEmpty { std::streampos BeginPos; std::streampos EndPos; Action action; bool IsTagFound; // Required for EMPTY DataElement DE; bool operator() (const PositionEmpty & i, const PositionEmpty & j) { if( i.BeginPos == j.BeginPos ) { return i.DE.GetTag() < j.DE.GetTag(); } // else return (int)i.BeginPos < (int)j.BeginPos; } }; class FileAnonymizerInternals { public: std::string InputFilename; std::string OutputFilename; std::set EmptyTags; std::set RemoveTags; std::map ReplaceTags; TransferSyntax TS; std::vector PositionEmptyArray; }; FileAnonymizer::FileAnonymizer() { Internals = new FileAnonymizerInternals; } FileAnonymizer::~FileAnonymizer() { delete Internals; } void FileAnonymizer::Empty( Tag const &t ) { if( t.GetGroup() >= 0x0008 ) { Internals->EmptyTags.insert( t ); } } void FileAnonymizer::Remove( Tag const &t ) { if( t.GetGroup() >= 0x0008 ) { Internals->RemoveTags.insert( t ); } } void FileAnonymizer::Replace( Tag const &t, const char *value ) { if( value && t.GetGroup() >= 0x0008 ) { Internals->ReplaceTags.insert( std::make_pair( t, value) ); } } void FileAnonymizer::Replace( Tag const &t, const char *value, VL const & vl ) { if( value && t.GetGroup() >= 0x0008 ) { Internals->ReplaceTags.insert( std::make_pair( t, std::string(value, vl) ) ); } } void FileAnonymizer::SetInputFileName(const char *filename_native) { if( filename_native ) Internals->InputFilename = filename_native; } void FileAnonymizer::SetOutputFileName(const char *filename_native) { if( filename_native ) Internals->OutputFilename = filename_native; } // portable way to check for existence (actually: accessibility): static inline bool file_exist(const char *filename) { std::ifstream infile(filename, std::ios::binary); return infile.good(); } bool FileAnonymizer::ComputeReplaceTagPosition() { /* Implementation details: We should make sure that the user know what she is doing in case of SQ. Let's assume a User call Replace( Tag(0x0008,0x2112), "FOOBAR" ) For quite a lot of DICOM implementation this Tag is required to be a SQ. Therefore even if the Attribute is declared with VR:UN, some implementation will try very hard to decode it as SQ...which obviously will fail Instead do not support SQ at all here and document it should not be used for SQ */ assert( !Internals->InputFilename.empty() ); const char *filename = Internals->InputFilename.c_str(); assert( filename ); const bool inplace = file_exist(Internals->OutputFilename.c_str()); std::map::reverse_iterator rit = Internals->ReplaceTags.rbegin(); for ( ; rit != Internals->ReplaceTags.rend(); rit++ ) { PositionEmpty pe; std::set removeme; const Tag & t = rit->first; const std::string & valuereplace = rit->second; removeme.insert( t ); std::ifstream is( filename, std::ios::binary ); Reader reader; reader.SetStream( is ); if( !reader.ReadSelectedTags( removeme ) ) { return false; } pe.EndPos = pe.BeginPos = is.tellg(); pe.action = REPLACE; pe.IsTagFound = false; const File & f = reader.GetFile(); const DataSet &ds = f.GetDataSet(); const TransferSyntax &ts = f.GetHeader().GetDataSetTransferSyntax(); Internals->TS = ts; pe.DE.SetTag( t ); if( ds.FindDataElement( t ) ) { const DataElement &de = ds.GetDataElement( t ); pe.IsTagFound = true; pe.DE.SetVL( de.GetVL() ); // Length is not used, unless to check undefined flag pe.DE.SetVR( de.GetVR() ); assert( pe.DE.GetVL().IsUndefined() == de.GetVL().IsUndefined() ); assert( pe.DE.GetVR() == de.GetVR() ); assert( pe.DE.GetTag() == de.GetTag() ); if( de.GetVL().IsUndefined() ) { // This is a SQ gdcmErrorMacro( "Replacing a SQ is not supported. Use Remove() or Empty()" ); return false; } else { if( inplace && valuereplace.size() != de.GetVL() ) { gdcmErrorMacro( "inplace mode requires same length attribute" ); // TODO we could allow smaller size (and pad with space...) return false; } assert( !de.GetVL().IsUndefined() ); pe.BeginPos -= de.GetVL(); pe.BeginPos -= 2 * de.GetVR().GetLength(); // (VR+) VL pe.BeginPos -= 4; // Tag assert( (int)pe.EndPos == (int)pe.BeginPos + (int)de.GetVL() + 2 * de.GetVR().GetLength() + 4 ); } pe.DE.SetByteValue( valuereplace.c_str(), (uint32_t)valuereplace.size() ); assert( pe.DE.GetVL() == valuereplace.size() ); } else { if( inplace ) { gdcmErrorMacro( "inplace mode requires existing tag (cannot insert). Tag: " << t ); return false; } // We need to insert an Empty Data Element ! //FIXME, for some public element we could do something nicer than VR:UN pe.DE.SetVR( VR::UN ); pe.DE.SetByteValue( valuereplace.c_str(), (uint32_t)valuereplace.size() ); assert( pe.DE.GetVL() == valuereplace.size() ); } // We need to push_back outside of if() since Action:Replace // on a missing tag, means insert it ! Internals->PositionEmptyArray.push_back( pe ); is.close(); } return true; } bool FileAnonymizer::ComputeRemoveTagPosition() { assert( !Internals->InputFilename.empty() ); const char *filename = Internals->InputFilename.c_str(); assert( filename ); const bool inplace = file_exist(Internals->OutputFilename.c_str()); if( inplace && !Internals->RemoveTags.empty()) { gdcmErrorMacro( "inplace mode requires existing tag (cannot remove)" ); return false; } std::set::reverse_iterator rit = Internals->RemoveTags.rbegin(); for ( ; rit != Internals->RemoveTags.rend(); rit++ ) { PositionEmpty pe; std::set removeme; const Tag & t = *rit; removeme.insert( t ); std::ifstream is( filename, std::ios::binary ); Reader reader; reader.SetStream( is ); if( !reader.ReadSelectedTags( removeme ) ) { return false; } pe.EndPos = pe.BeginPos = is.tellg(); pe.action = REMOVE; pe.IsTagFound = false; const File & f = reader.GetFile(); const DataSet &ds = f.GetDataSet(); const TransferSyntax &ts = f.GetHeader().GetDataSetTransferSyntax(); Internals->TS = ts; pe.DE.SetTag( t ); if( ds.FindDataElement( t ) ) { const DataElement &de = ds.GetDataElement( t ); pe.IsTagFound = true; pe.DE.SetVL( de.GetVL() ); // Length is not used, unless to check undefined flag pe.DE.SetVR( de.GetVR() ); assert( pe.DE.GetVL().IsUndefined() == de.GetVL().IsUndefined() ); assert( pe.DE.GetVR() == de.GetVR() ); assert( pe.DE.GetTag() == de.GetTag() ); if( de.GetVL().IsUndefined() ) { // This is a SQ VL vl; if( ts.GetNegociatedType() == TransferSyntax::Implicit ) { vl = de.GetLength(); } else { vl = de.GetLength(); } assert( pe.BeginPos > vl ); pe.BeginPos -= vl; } else { assert( !de.GetVL().IsUndefined() ); pe.BeginPos -= de.GetVL(); pe.BeginPos -= 2 * de.GetVR().GetLength(); // (VR+) VL pe.BeginPos -= 4; // Tag assert( (int)pe.EndPos == (int)pe.BeginPos + (int)de.GetVL() + 2 * de.GetVR().GetLength() + 4 ); } Internals->PositionEmptyArray.push_back( pe ); } else { // Yay no need to do anything ! } is.close(); } return true; } bool FileAnonymizer::ComputeEmptyTagPosition() { // FIXME we sometime empty, attributes that are already empty... assert( !Internals->InputFilename.empty() ); const char *filename = Internals->InputFilename.c_str(); assert( filename ); const bool inplace = file_exist(Internals->OutputFilename.c_str()); if( inplace && !Internals->EmptyTags.empty()) { gdcmErrorMacro( "inplace mode requires existing tag (cannot empty)" ); return false; } std::set::reverse_iterator rit = Internals->EmptyTags.rbegin(); for ( ; rit != Internals->EmptyTags.rend(); rit++ ) { PositionEmpty pe; std::set removeme; const Tag & t = *rit; removeme.insert( t ); std::ifstream is( filename, std::ios::binary ); Reader reader; reader.SetStream( is ); if( !reader.ReadSelectedTags( removeme ) ) { return false; } pe.EndPos = pe.BeginPos = is.tellg(); pe.action = EMPTY; pe.IsTagFound = false; const File & f = reader.GetFile(); const DataSet &ds = f.GetDataSet(); const TransferSyntax &ts = f.GetHeader().GetDataSetTransferSyntax(); Internals->TS = ts; pe.DE.SetTag( t ); if( ds.FindDataElement( t ) ) { const DataElement &de = ds.GetDataElement( t ); pe.IsTagFound = true; pe.DE.SetVL( de.GetVL() ); // Length is not used, unless to check undefined flag pe.DE.SetVR( de.GetVR() ); assert( pe.DE.GetVL().IsUndefined() == de.GetVL().IsUndefined() ); assert( pe.DE.GetVR() == de.GetVR() ); assert( pe.DE.GetTag() == de.GetTag() ); if( de.GetVL().IsUndefined() ) { // This is a SQ VL vl; if( ts.GetNegociatedType() == TransferSyntax::Implicit ) { vl = de.GetLength(); } else { vl = de.GetLength(); } assert( pe.BeginPos > vl ); pe.BeginPos -= vl; pe.BeginPos += 4; // Tag if( ts.GetNegociatedType() == TransferSyntax::Implicit ) { pe.BeginPos += 0; } else { pe.BeginPos += de.GetVR().GetLength(); } } else { assert( !de.GetVL().IsUndefined() ); pe.BeginPos -= de.GetVL(); if( ts.GetNegociatedType() == TransferSyntax::Implicit ) { pe.BeginPos -= 4; } else { pe.BeginPos -= de.GetVR().GetLength(); assert( (int)pe.EndPos == (int)pe.BeginPos + (int)de.GetVL() + de.GetVR().GetLength() ); } } } else { // We need to insert an Empty Data Element ! //FIXME, for some public element we could do something nicer than VR:UN pe.DE.SetVR( VR::UN ); pe.DE.SetVL( 0 ); } // We need to push_back outside of if() since Action:Empty // on a missing tag, means insert it ! Internals->PositionEmptyArray.push_back( pe ); is.close(); } return true; } bool FileAnonymizer::Write() { if( Internals->OutputFilename.empty() ) return false; const char *outfilename = Internals->OutputFilename.c_str(); if( Internals->InputFilename.empty() ) return false; const char *filename = Internals->InputFilename.c_str(); Internals->PositionEmptyArray.clear(); // Compute offsets if( !ComputeRemoveTagPosition() || !ComputeEmptyTagPosition() || !ComputeReplaceTagPosition() ) { return false; } // Make sure we will copy from lower offset to highest: // need to loop from the end. Sometimes a replace operation will have *exact* // same file offset for multiple attributes. In which case we need to insert // first the last attribute, and at the end the first attribute PositionEmpty pe_sort = {}; std::sort (Internals->PositionEmptyArray.begin(), Internals->PositionEmptyArray.end(), pe_sort); // Step 2. Copy & skip proper portion std::ios::openmode om; const bool inplace = file_exist(outfilename); if( inplace ) { // overwrite: om = std::ofstream::in | std::ofstream::out | std::ios::binary; } else { // create om = std::ofstream::out | std::ios::binary; } std::fstream of( outfilename, om ); std::ifstream is( filename, std::ios::binary ); std::streampos prev = 0; const TransferSyntax &ts = Internals->TS; std::vector::const_iterator it = Internals->PositionEmptyArray.begin(); for( ; it != Internals->PositionEmptyArray.end(); ++it ) { const PositionEmpty & pe = *it; Action action = pe.action; if( pe.IsTagFound ) { const DataElement & de = pe.DE; int vrlen = de.GetVR().GetLength(); if( ts.GetNegociatedType() == TransferSyntax::Implicit ) { vrlen = 4; } std::streampos end = pe.BeginPos; // FIXME: most efficient way to copy chunk of file in c++ ? for( int i = (int)prev; i < end; ++i) { of.put( (char)is.get() ); } if( action == EMPTY ) { assert( !inplace ); // Create a 0 Value Length (VR+Tag was copied in previous loop) for( int i = 0; i < vrlen; ++i) { of.put( 0 ); } } else if( action == REPLACE ) { if( ts.GetSwapCode() == SwapCode::BigEndian ) { if( ts.GetNegociatedType() == TransferSyntax::Implicit ) { gdcmErrorMacro( "Cannot write Virtual Big Endian" ); return true; } else { pe.DE.Write( of ); } } else { if( ts.GetNegociatedType() == TransferSyntax::Implicit ) { pe.DE.Write( of ); } else { pe.DE.Write( of ); } } } // Skip the Value assert( is.good() ); is.seekg( pe.EndPos ); assert( is.good() ); prev = is.tellg(); assert( prev == pe.EndPos ); } else { std::streampos end = pe.BeginPos; // FIXME: most efficient way to copy chunk of file in c++ ? for( int i = (int)prev; i < end; ++i) { of.put( (char)is.get() ); } if( ts.GetSwapCode() == SwapCode::BigEndian ) { if( ts.GetNegociatedType() == TransferSyntax::Implicit ) { gdcmErrorMacro( "Cannot write Virtual Big Endian" ); return true; } else { pe.DE.Write( of ); } } else { if( ts.GetNegociatedType() == TransferSyntax::Implicit ) { pe.DE.Write( of ); } else { pe.DE.Write( of ); } } prev = is.tellg(); } } of << is.rdbuf(); of.close(); is.close(); #if 0 Reader r; r.SetFileName( outfilename ); if( !r.Read() ) { gdcmErrorMacro( "Output file got corrupted, please report" ); return false; } #endif return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmFileAnonymizer.h000066400000000000000000000055501412732066400244560ustar00rootroot00000000000000/*========================================================================= 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 GDCMFILEANONYMIZER_H #define GDCMFILEANONYMIZER_H #include "gdcmSubject.h" #include "gdcmEvent.h" #include "gdcmTag.h" #include "gdcmVL.h" namespace gdcm { class FileAnonymizerInternals; /** * \brief FileAnonymizer * * \details This Anonymizer is a file-based Anonymizer. It requires a valid DICOM * file and will use the Value Length to skip over any information. * * It will not load the DICOM dataset taken from SetInputFileName() into memory * and should consume much less memory than Anonymizer. * * \warning: Each time you call Replace() with a value. This value will copied, * and stored in memory. The behavior is not ideal for extremely large data * (larger than memory size). This class is really meant to take a large DICOM * input file and then only changed some small attribute. * * caveats: * \li This class will NOT work with unordered attributes in a DICOM File, * \li This class does neither recompute nor update the Group Length element, * \li This class currently does not update the File Meta Information header. * \li Only strict inplace Replace operation is supported when input and output * file are the same. */ class GDCM_EXPORT FileAnonymizer : public Subject { public: FileAnonymizer(); ~FileAnonymizer() override; /// Make Tag t empty /// Warning: does not handle SQ element void Empty( Tag const &t ); /// remove a tag (even a SQ can be removed) void Remove( Tag const &t ); /// 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 /// WARNING: Do not ever try to write a value in a SQ Data Element ! void Replace( Tag const &t, const char *value_str ); /// when the value contains \0, it is a good idea to specify the length. This function /// is required when dealing with VRBINARY tag void Replace( Tag const &t, const char *value_data, VL const & vl ); /// Set input filename void SetInputFileName(const char *filename_native); /// Set output filename void SetOutputFileName(const char *filename_native); /// Write the output file bool Write(); private: bool ComputeEmptyTagPosition(); bool ComputeRemoveTagPosition(); bool ComputeReplaceTagPosition(); FileAnonymizerInternals *Internals; }; } // end namespace gdcm #endif //GDCMFILEANONYMIZER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmFileChangeTransferSyntax.cxx000066400000000000000000000356341412732066400270050ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileChangeTransferSyntax.h" #include "gdcmImageCodec.h" #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmImageRegionReader.h" #include "gdcmJPEGCodec.h" #include "gdcmJPEGLSCodec.h" #include "gdcmJPEG2000Codec.h" #include "gdcmRLECodec.h" #include "gdcmImageHelper.h" #include "gdcmEvent.h" #include "gdcmProgressEvent.h" #include "gdcmUIDGenerator.h" #include "gdcmAttribute.h" #include "gdcmFileDerivation.h" #include "gdcmFileAnonymizer.h" namespace gdcm { class FileChangeTransferSyntaxInternals { public: FileChangeTransferSyntaxInternals() = default; ~FileChangeTransferSyntaxInternals() { delete IC; } ImageCodec *IC{nullptr}; bool InitializeCopy{false}; std::streampos PixelDataPos; std::string InFilename; std::string OutFilename; TransferSyntax TS; std::vector Dims; PixelFormat PF; PhotometricInterpretation PI; unsigned int PC; bool Needbyteswap; double Progress; }; FileChangeTransferSyntax::FileChangeTransferSyntax() { Internals = new FileChangeTransferSyntaxInternals; } FileChangeTransferSyntax::~FileChangeTransferSyntax() { delete Internals; } bool FileChangeTransferSyntax::Change() { this->InvokeEvent( StartEvent() ); if( !InitializeCopy() ) { gdcmDebugMacro( "Could not InitializeCopy" ); return false; } const char *filename = this->Internals->InFilename.c_str(); std::ifstream is( filename, std::ios::binary ); is.seekg( Internals->PixelDataPos, std::ios::beg ); const char *outfilename = this->Internals->OutFilename.c_str(); std::fstream os( outfilename, std::ofstream::in | std::ofstream::out | std::ios::binary ); os.seekp( 0, std::ios::end ); const std::vector & dims = Internals->Dims; const PixelFormat &pf = Internals->PF; const PhotometricInterpretation &pi = Internals->PI; unsigned int pc = Internals->PC; const int pixsize = pf.GetPixelSize(); const bool needbyteswap = Internals->Needbyteswap; ImageCodec *codec = Internals->IC; codec->SetDimensions( dims ); codec->SetNumberOfDimensions( 2 ); codec->SetPlanarConfiguration( pc ); codec->SetPhotometricInterpretation( pi ); codec->SetNeedByteSwap( needbyteswap ); codec->SetNeedOverlayCleanup( pf.GetBitsAllocated() != pf.GetBitsStored() ); codec->SetPixelFormat( pf ); // need to be last ! VL vl; vl.SetToUndefined(); DataElement de( Tag(0x7fe0,0x0010), vl, VR::OB ); switch ( pf.GetBitsAllocated() ) { case 8: de.SetVR( VR::OB ); break; //case 12: case 16: case 32: de.SetVR( VR::OW ); break; default: return false; } de.GetTag().Write( os ); de.GetVR().Write( os ); de.GetVL().Write( os ); Fragment frag; // Basic Offset Table frag.Write( os ); Internals->Progress = 0; bool b = Internals->IC->StartEncode(os); assert( b ); size_t len = 0; // actual size compressed: if( Internals->IC->IsRowEncoder() ) { std::vector vbuffer; vbuffer.resize( dims[0] * pixsize ); char *data = &vbuffer[0]; const size_t datalen = vbuffer.size(); const size_t nscanlines = dims[2] * dims[1]; const double progresstick = 1. / (double)nscanlines; for( unsigned int z = 0; z < dims[2]; ++z ) { // frag header: frag.Write( os ); std::streampos start = os.tellp(); for( unsigned int y = 0; y < dims[1]; ++y ) { is.read( data, datalen ); assert( is.good() ); b = Internals->IC->CleanupUnusedBits(data, datalen); if( !b ) return false; b = Internals->IC->AppendRowEncode(os, data, datalen); if( !b ) return false; Internals->Progress += progresstick; ProgressEvent pe; pe.SetProgress( Internals->Progress ); this->InvokeEvent( pe ); } const std::streampos end = os.tellp(); // Compute JPEG length: const VL jpegvl = (uint32_t)(end - start); len += jpegvl; start -= 4; if( jpegvl.IsOdd() ) { // 0 - padding: os.put( 0 ); } os.seekp( start, std::ios::beg ); jpegvl.Write( os ); os.seekp( 0, std::ios::end ); } } else if( Internals->IC->IsFrameEncoder() ) { std::vector vbuffer; vbuffer.resize( dims[0] * dims[1] * pixsize ); char *data = &vbuffer[0]; const size_t datalen = vbuffer.size(); const size_t nscanlines = dims[2]; const double progresstick = 1. / (double)nscanlines; for( unsigned int z = 0; z < dims[2]; ++z ) { // frag header: frag.Write( os ); std::streampos start = os.tellp(); { is.read( data, datalen ); assert( is.good() ); b = Internals->IC->CleanupUnusedBits(data, datalen); if( !b ) return false; b = Internals->IC->AppendFrameEncode(os, data, datalen); if( !b ) return false; Internals->Progress += progresstick; ProgressEvent pe; pe.SetProgress( Internals->Progress ); this->InvokeEvent( pe ); } const std::streampos end = os.tellp(); // Compute JPEG length: const VL jpegvl = (uint32_t)(end - start); len += jpegvl; start -= 4; if( jpegvl.IsOdd() ) { // 0 - padding: os.put( 0 ); } os.seekp( start, std::ios::beg ); jpegvl.Write( os ); os.seekp( 0, std::ios::end ); } } else { // dead code ? return false; } b = Internals->IC->StopEncode(os); assert( b ); const Tag seqDelItem(0xfffe,0xe0dd); seqDelItem.Write(os); VL zero = 0; zero.Write(os); is.close(); os.close(); size_t reflen = dims[0] * dims[1] * pixsize; double level = (double)reflen / (double)len; if( !UpdateCompressionLevel(level) ) { gdcmDebugMacro( "Could not UpdateCompressionLevel" ); return false; } this->InvokeEvent( EndEvent() ); return true; } bool FileChangeTransferSyntax::UpdateCompressionLevel(double level) { // no need to update if not lossy: if( !Internals->IC->GetLossyFlag() ) return true; double ratio = level; Attribute<0x0028,0x2112> at2; at2.SetValues( &ratio, 1); DataElement de = at2.GetAsDataElement(); // file has been flushed to disk at this point, need to update the compression level now: const char * fn = Internals->OutFilename.c_str(); FileAnonymizer fa; fa.SetInputFileName(fn); fa.SetOutputFileName(fn); const ByteValue * bv = de.GetByteValue(); fa.Replace( de.GetTag(), bv->GetPointer(), 16/* bv->GetLength()*/ ); if( !fa.Write() ) { gdcmDebugMacro( "FileAnonymizer failure" ); return false; } return true; } void FileChangeTransferSyntax::SetTransferSyntax( TransferSyntax const & ts ) { Internals->TS = ts; delete Internals->IC; JPEGCodec jpeg; JPEGLSCodec jpegls; JPEG2000Codec jpeg2000; RLECodec rle; ImageCodec *codecs[] = { &jpeg, &jpegls, &jpeg2000, &rle }; const int n = sizeof( codecs ) / sizeof( *codecs ); for( int i = 0; i < n; ++i ) { if( codecs[i]->CanCode( ts ) ) { Internals->IC = codecs[i]->Clone(); } } assert( Internals->TS ); } ImageCodec * FileChangeTransferSyntax::GetCodec() { return Internals->IC; } void FileChangeTransferSyntax::SetInputFileName(const char *filename_native) { if( filename_native ) Internals->InFilename = filename_native; } void FileChangeTransferSyntax::SetOutputFileName(const char *filename_native) { if( filename_native ) Internals->OutFilename = filename_native; } bool FileChangeTransferSyntax::InitializeCopy() { if( !Internals->IC ) { return false; } if( !this->Internals->InitializeCopy ) { const char *filename = this->Internals->InFilename.c_str(); const char *outfilename = this->Internals->OutFilename.c_str(); { // Make sure to update image meta data: std::ifstream is( filename, std::ios::binary ); ImageRegionReader reader; reader.SetStream( is ); if( !reader.ReadInformation() ) { gdcmDebugMacro( "ImageRegionReader::ReadInformation failed" ); return false; } is.clear(); // important Internals->PixelDataPos = is.tellg(); File & file = reader.GetFile(); DataSet & ds = file.GetDataSet(); if( ds.FindDataElement( Tag(0x7fe0,0x0010) ) ) { const DataElement & de = ds.GetDataElement( Tag(0x7fe0,0x0010) ); gdcmAssertAlwaysMacro( "Impossible happen"); (void)de; return false; } FileMetaInformation & fmi = file.GetHeader(); const TransferSyntax &ts = fmi.GetDataSetTransferSyntax(); if( ts.IsEncapsulated() ) { gdcmDebugMacro( "Don't know how to handle encapsulated TS: " << ts ); return false; } if( ts == TransferSyntax::ImplicitVRBigEndianPrivateGE || ts == TransferSyntax::ExplicitVRBigEndian ) { gdcmDebugMacro( "Don't know how to handle TS: " << ts ); return false; } Internals->Needbyteswap = (ts == TransferSyntax::ImplicitVRBigEndianPrivateGE || ts == TransferSyntax::ExplicitVRBigEndian ); Internals->Dims = ImageHelper::GetDimensionsValue(file); Internals->PF = ImageHelper::GetPixelFormatValue(file); Internals->PI = ImageHelper::GetPhotometricInterpretationValue(file); if( Internals->PI == PhotometricInterpretation::YBR_FULL_422 && ( ts == TransferSyntax::ImplicitVRLittleEndian || ts == TransferSyntax::ExplicitVRLittleEndian ) ) { gdcmDebugMacro( "Don't know how to handle YBR_FULL_422/raw" ); return false; } Internals->PC = ImageHelper::GetPlanarConfigurationValue(file); if( Internals->PC ) { gdcmDebugMacro( "Don't know how to handle Planar Configuration" ); return false; } is.close(); // do the lossy transfer syntax handling: if( Internals->IC->GetLossyFlag() ) { if( !ds.FindDataElement( Tag(0x0008,0x0016) ) || ds.GetDataElement( Tag(0x0008,0x0016) ).IsEmpty() ) { gdcmErrorMacro( "Missing Tag" ); return false; } if( !ds.FindDataElement( Tag(0x0008,0x0018) ) || ds.GetDataElement( Tag(0x0008,0x0018) ).IsEmpty() ) { gdcmErrorMacro( "Missing Tag" ); return false; } const DataElement &sopclassuid = ds.GetDataElement( Tag(0x0008,0x0016) ); const DataElement &sopinstanceuid = ds.GetDataElement( Tag(0x0008,0x0018) ); // Make sure that const char* pointer will be properly padded with \0 char: std::string sopclassuid_str( sopclassuid.GetByteValue()->GetPointer(), sopclassuid.GetByteValue()->GetLength() ); std::string sopinstanceuid_str( sopinstanceuid.GetByteValue()->GetPointer(), sopinstanceuid.GetByteValue()->GetLength() ); UIDGenerator uid; //ds.Remove( Tag(0x8,0x18) ); { const char *sop = uid.Generate(); DataElement de( Tag(0x0008,0x0018) ); VL::Type strlenSOP = (VL::Type) strlen(sop); de.SetByteValue( sop, strlenSOP ); de.SetVR( Attribute<0x0008, 0x0018>::GetVR() ); ds.Replace( de ); } FileDerivation fd; fd.SetFile( file ); fd.AddReference( sopclassuid_str.c_str(), sopinstanceuid_str.c_str() ); // CID 7202 Source Image Purposes of Reference // {"DCM",121320,"Uncompressed predecessor"}, fd.SetPurposeOfReferenceCodeSequenceCodeValue( 121320 ); // CID 7203 Image Derivation // { "DCM",113040,"Lossy Compression" }, fd.SetDerivationCodeSequenceCodeValue( 113040 ); fd.SetDerivationDescription( "lossy conversion" ); if( !fd.Derive() ) { gdcmErrorMacro( "could not derive using input info" ); return false; } /* (0028,2110) CS [01] # 2, 1 LossyImageCompression (0028,2112) DS [15.95] # 6, 1 LossyImageCompressionRatio (0028,2114) CS [ISO_10918_1] # 12, 1 LossyImageCompressionMethod */ Attribute<0x0028,0x2110> at1; at1.SetValue( "01" ); ds.Replace( at1.GetAsDataElement() ); #if 0 double ratio = 1234567890123456; // DS is 16bytes Attribute<0x0028,0x2112> at2; at2.SetValues( &ratio, 1); ds.Replace( at2.GetAsDataElement() ); #else char buf[16+1]; buf[16] = 0; memset( buf, ' ', 16 ); DataElement de1( Tag(0x0028,0x2112) ); de1.SetByteValue( buf, (uint32_t)strlen( buf ) ); ds.Replace( de1 ); #endif /* The Defined Terms for Lossy Image Compression Method (0028,2114) are : ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression */ Attribute<0x0028,0x2114> at3; const TransferSyntax ts_orig = Internals->TS; if( ts_orig == TransferSyntax::JPEG2000 ) { static const CSComp newvalues2[] = {"ISO_15444_1"}; at3.SetValues( newvalues2, 1 ); } else if( ts_orig == TransferSyntax::JPEGLSNearLossless ) { static const CSComp newvalues2[] = {"ISO_14495_1"}; at3.SetValues( newvalues2, 1 ); } else if ( ts_orig == TransferSyntax::JPEGBaselineProcess1 || ts_orig == TransferSyntax::JPEGExtendedProcess2_4 || ts_orig == TransferSyntax::JPEGExtendedProcess3_5 || ts_orig == TransferSyntax::JPEGSpectralSelectionProcess6_8 || ts_orig == TransferSyntax::JPEGFullProgressionProcess10_12 ) { static const CSComp newvalues2[] = {"ISO_10918_1"}; at3.SetValues( newvalues2, 1 ); } else { gdcmErrorMacro( "Pixel Data is lossy but I cannot find the original transfer syntax" ); return false; } ds.Replace( at3.GetAsDataElement() ); } Writer writer; fmi.Clear(); fmi.SetDataSetTransferSyntax( Internals->TS ); writer.SetFileName( outfilename ); writer.SetFile( file ); if( !writer.Write() ) return false; } this->Internals->InitializeCopy = true; } return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmFileChangeTransferSyntax.h000066400000000000000000000043211412732066400264170ustar00rootroot00000000000000/*========================================================================= 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 GDCMFILECHANGETRANSFERSYNTAX_H #define GDCMFILECHANGETRANSFERSYNTAX_H #include "gdcmSubject.h" #include "gdcmSmartPointer.h" namespace gdcm { class FileChangeTransferSyntaxInternals; class ImageCodec; class TransferSyntax; /** * \brief FileChangeTransferSyntax * * \details This class is a file-based (limited) replacement of the in-memory * ImageChangeTransferSyntax. * * This class provide a file-based compression-only mechanism. It will take in * an uncompressed DICOM image file (Pixel Data element). Then produced as * output a compressed DICOM file (Transfer Syntax will be updated). * * Currently it supports the following transfer syntax: * - JPEGLosslessProcess14_1 */ class GDCM_EXPORT FileChangeTransferSyntax : public Subject { public: FileChangeTransferSyntax(); ~FileChangeTransferSyntax() override; /// Set input filename (raw DICOM) void SetInputFileName(const char *filename_native); /// Set output filename (target compressed DICOM) void SetOutputFileName(const char *filename_native); /// Change the transfer syntax bool Change(); /// Specify the Target Transfer Syntax void SetTransferSyntax( TransferSyntax const & ts ); /// Retrieve the actual codec (valid after calling SetTransferSyntax) /// Only advanced users should call this function. ImageCodec * GetCodec(); /// for wrapped language: instantiate a reference counted object static SmartPointer New() { return new FileChangeTransferSyntax; } private: bool InitializeCopy(); bool UpdateCompressionLevel(double level); FileChangeTransferSyntaxInternals *Internals; }; } // end namespace gdcm #endif //GDCMFILEANONYMIZER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmFileDecompressLookupTable.cxx000066400000000000000000000074221412732066400271440ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileDecompressLookupTable.h" #include "gdcmAttribute.h" #include #include namespace gdcm { bool FileDecompressLookupTable::Change() { DataSet &ds = F->GetDataSet(); PixelFormat pf = PixelData->GetPixelFormat(); PhotometricInterpretation pi = PixelData->GetPhotometricInterpretation(); if ( pi == PhotometricInterpretation::PALETTE_COLOR ) { const LookupTable &lut = PixelData->GetLUT(); assert( lut.Initialized() ); // assert( (pf.GetBitsAllocated() == 8 && pf.GetPixelRepresentation() == 0) // || (pf.GetBitsAllocated() == 16 && pf.GetPixelRepresentation() == 0) ); // lut descriptor: // (0028,1101) US 256\0\16 # 6, 3 RedPaletteColorLookupTableDescriptor // (0028,1102) US 256\0\16 # 6, 3 GreenPaletteColorLookupTableDescriptor // (0028,1103) US 256\0\16 # 6, 3 BluePaletteColorLookupTableDescriptor // lut data: unsigned short length, subscript, bitsize; unsigned short rawlut8[256]; unsigned short rawlut16[65536]; unsigned short *rawlut = rawlut8; unsigned int lutlen = 256; if( pf.GetBitsAllocated() == 16 ) { rawlut = rawlut16; lutlen = 65536; } unsigned int l; // FIXME: should I really clear rawlut each time ? // RED memset(rawlut,0,lutlen*2); lut.GetLUT(LookupTable::RED, (unsigned char*)rawlut, l); DataElement redde( Tag(0x0028, 0x1201) ); redde.SetVR( VR::OW ); redde.SetByteValue( (char*)rawlut, l); ds.Replace( redde ); // descriptor: Attribute<0x0028, 0x1101, VR::US, VM::VM3> reddesc; lut.GetLUTDescriptor(LookupTable::RED, length, subscript, bitsize); reddesc.SetValue(length,0); reddesc.SetValue(subscript,1); reddesc.SetValue(bitsize,2); ds.Replace( reddesc.GetAsDataElement() ); // GREEN memset(rawlut,0,lutlen*2); lut.GetLUT(LookupTable::GREEN, (unsigned char*)rawlut, l); DataElement greende( Tag(0x0028, 0x1202) ); greende.SetVR( VR::OW ); greende.SetByteValue( (char*)rawlut, l); ds.Replace( greende ); // descriptor: Attribute<0x0028, 0x1102, VR::US, VM::VM3> greendesc; lut.GetLUTDescriptor(LookupTable::GREEN, length, subscript, bitsize); greendesc.SetValue(length,0); greendesc.SetValue(subscript,1); greendesc.SetValue(bitsize,2); ds.Replace( greendesc.GetAsDataElement() ); // BLUE memset(rawlut,0,lutlen*2); lut.GetLUT(LookupTable::BLUE, (unsigned char*)rawlut, l); DataElement bluede( Tag(0x0028, 0x1203) ); bluede.SetVR( VR::OW ); bluede.SetByteValue( (char*)rawlut, l); ds.Replace( bluede ); // descriptor: Attribute<0x0028, 0x1103, VR::US, VM::VM3> bluedesc; lut.GetLUTDescriptor(LookupTable::BLUE, length, subscript, bitsize); bluedesc.SetValue(length,0); bluedesc.SetValue(subscript,1); bluedesc.SetValue(bitsize,2); ds.Replace( bluedesc.GetAsDataElement() ); ds.Remove( Tag(0x0028, 0x1221) ); ds.Remove( Tag(0x0028, 0x1222) ); ds.Remove( Tag(0x0028, 0x1223) ); return true; } return false; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmFileDecompressLookupTable.h000066400000000000000000000030221412732066400265610ustar00rootroot00000000000000/*========================================================================= 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 GDCMFILEDECOMPRESSLOOKUPTABLE_H #define GDCMFILEDECOMPRESSLOOKUPTABLE_H #include "gdcmSubject.h" #include "gdcmFile.h" #include "gdcmPixmap.h" namespace gdcm { class DataElement; /** * \brief FileDecompressLookupTable class * \details It decompress the segmented LUT into linearized one (only PALETTE_COLOR images) * Output will be a PhotometricInterpretation=RGB image */ class GDCM_EXPORT FileDecompressLookupTable : public Subject { public: FileDecompressLookupTable() = default; ~FileDecompressLookupTable() override = default; /// Decompress bool Change(); /// Set/Get File void SetFile(const File& f) { F = f; } File &GetFile() { return *F; } const Pixmap& GetPixmap() const { return *PixelData; } Pixmap& GetPixmap() { return *PixelData; } void SetPixmap(Pixmap const &img) { PixelData = img; } protected: private: SmartPointer F; SmartPointer PixelData; }; } // end namespace gdcm #endif //GDCMFILEDECOMPRESSLOOKUPTABLE_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmFileDerivation.cxx000066400000000000000000000361111412732066400247770ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileDerivation.h" #include "gdcmFile.h" #include "gdcmAttribute.h" #include "gdcmUIDGenerator.h" #include #include /* PS 3.16 - 2008 CID 7202 Source Image Purposes of Reference Context ID 7202 Source Image Purposes of Reference Type: Extensible Version: 20051101 Coding Scheme Designator (0008,0102) Code Value (0008,0100) Code Meaning (0008,0104) DCM 121320 Uncompressed predecessor DCM 121321 Mask image for image processing operation DCM 121322 Source image for image processing operation DCM 121329 Source image for montage DCM 121330 Lossy compressed predecessor */ /* CID 7203 Image Derivation Context ID 7203 Image Derivation Type: Extensible Version: 20050822 Coding Scheme Designator (0008,0102) Code Value (0008,0100) Code Meaning (0008,0104) DCM 113040 Lossy Compression DCM 113041 Apparent Diffusion Coefficient DCM 113042 Pixel by pixel addition DCM 113043 Diffusion weighted DCM 113044 Diffusion Anisotropy DCM 113045 Diffusion Attenuated DCM 113046 Pixel by pixel division DCM 113047 Pixel by pixel mask DCM 113048 Pixel by pixel Maximum DCM 113049 Pixel by pixel mean DCM 113050 Metabolite Maps from spectroscopy data DCM 113051 Pixel by pixel Minimum DCM 113052 Mean Transit Time DCM 113053 Pixel by pixel multiplication DCM 113054 Negative Enhancement Integral DCM 113055 Regional Cerebral Blood Flow DCM 113056 Regional Cerebral Blood Volume DCM 113057 R-Coefficient Map DCM 113058 Proton Density map DCM 113059 Signal Change Map DCM 113060 Signal to Noise Map DCM 113061 Standard Deviation DCM 113062 Pixel by pixel subtraction DCM 113063 T1 Map DCM 113064 T2* Map DCM 113065 T2 Map DCM 113066 Time Course of Signal DCM 113067 Temperature encoded DCM 113068 Student's T-Test DCM 113069 Time To Peak map DCM 113070 Velocity encoded DCM 113071 Z-Score Map DCM 113072 Multiplanar reformatting DCM 113073 Curved multiplanar reformatting DCM 113074 Volume rendering DCM 113075 Surface rendering DCM 113076 Segmentation DCM 113077 Volume editing DCM 113078 Maximum intensity projection DCM 113079 Minimum intensity projection DCM 113085 Spatial resampling DCM 113086 Edge enhancement DCM 113087 Smoothing DCM 113088 Gaussian blur DCM 113089 Unsharp mask DCM 113090 Image stitching */ namespace gdcm { /* Annex D DICOM Controlled Terminology Definitions (Normative) This Annex specifies the meanings of codes defined in DICOM, either explicitly or by reference to another part of DICOM or an external reference document or standard. DICOM Code Definitions (Coding Scheme Designator 'DCM' Coding Scheme Version '01') */ struct CodeDefinition { const char *CodingSchemeDesignator; unsigned int CodeValue; const char *CodeMeaning; }; // CID 7202 Source Image Purposes of Reference static const CodeDefinition SourceImagePurposesofReference[] = { {"DCM",121320,"Uncompressed predecessor"}, {"DCM",121321,"Mask image for image processing operation"}, {"DCM",121322,"Source image for image processing operation"}, {"DCM",121329,"Source image for montage"}, {"DCM",121330,"Lossy compressed predecessor"}, {nullptr,0,nullptr} // sentinel }; // CID 7203 Image Derivation static const CodeDefinition ImageDerivation[] = { { "DCM",113040,"Lossy Compression" }, { "DCM",113041,"Apparent Diffusion Coefficient" }, { "DCM",113042,"Pixel by pixel addition" }, { "DCM",113043,"Diffusion weighted" }, { "DCM",113044,"Diffusion Anisotropy" }, { "DCM",113045,"Diffusion Attenuated" }, { "DCM",113046,"Pixel by pixel division" }, { "DCM",113047,"Pixel by pixel mask" }, { "DCM",113048,"Pixel by pixel Maximum" }, { "DCM",113049,"Pixel by pixel mean" }, { "DCM",113050,"Metabolite Maps from spectroscopy data" }, { "DCM",113051,"Pixel by pixel Minimum" }, { "DCM",113052,"Mean Transit Time" }, { "DCM",113053,"Pixel by pixel multiplication" }, { "DCM",113054,"Negative Enhancement Integral" }, { "DCM",113055,"Regional Cerebral Blood Flow" }, { "DCM",113056,"Regional Cerebral Blood Volume" }, { "DCM",113057,"R-Coefficient Map" }, { "DCM",113058,"Proton Density map" }, { "DCM",113059,"Signal Change Map" }, { "DCM",113060,"Signal to Noise Map" }, { "DCM",113061,"Standard Deviation" }, { "DCM",113062,"Pixel by pixel subtraction" }, { "DCM",113063,"T1 Map" }, { "DCM",113064,"T2* Map" }, { "DCM",113065,"T2 Map" }, { "DCM",113066,"Time Course of Signal" }, { "DCM",113067,"Temperature encoded" }, { "DCM",113068,"Student's T-Test" }, { "DCM",113069,"Time To Peak map" }, { "DCM",113070,"Velocity encoded" }, { "DCM",113071,"Z-Score Map" }, { "DCM",113072,"Multiplanar reformatting" }, { "DCM",113073,"Curved multiplanar reformatting" }, { "DCM",113074,"Volume rendering" }, { "DCM",113075,"Surface rendering" }, { "DCM",113076,"Segmentation" }, { "DCM",113077,"Volume editing" }, { "DCM",113078,"Maximum intensity projection" }, { "DCM",113079,"Minimum intensity projection" }, { "DCM",113085,"Spatial resampling" }, { "DCM",113086,"Edge enhancement" }, { "DCM",113087,"Smoothing" }, { "DCM",113088,"Gaussian blur" }, { "DCM",113089,"Unsharp mask" }, { "DCM",113090,"Image stitching" }, {nullptr,0,nullptr} // sentinel }; // CID 7205 Purpose Of Reference to Alternate Representation static const CodeDefinition PurposeOfReferencetoAlternateRepresentation[] = { { "DCM",121324,"Source image" }, { "DCM",121325,"Lossy compressed image" }, { "DCM",121326,"Alternate SOP Class instance" }, { "DCM",121327,"Full fidelity image" }, { "DCM",121328,"Alternate Photometric Interpretation image" }, {nullptr,0,nullptr} // sentinel }; class FileDerivationInternals { public: FileDerivationInternals():References(),DerivationDescription() {} std::vector< std::pair< std::string, std::string > > References; unsigned int DerivationCodeSequenceCodeValue{0}; unsigned int PurposeOfReferenceCodeSequenceCodeValue{0}; std::string DerivationDescription; bool AppendDerivationHistory{false}; }; FileDerivation::FileDerivation():F(new File),Internals(new FileDerivationInternals) { } FileDerivation::~FileDerivation() { delete Internals; } const CodeDefinition * GetCodeDefinition( unsigned int codevalue, const CodeDefinition list[] ) { const CodeDefinition * cds = list; while( cds->CodeMeaning && cds->CodeValue != codevalue ) { ++cds; } if( cds->CodeValue ) return cds; // else return nullptr; } void FileDerivation::SetDerivationDescription( const char *dd ) { this->Internals->DerivationDescription = dd; } void FileDerivation::SetDerivationCodeSequenceCodeValue(unsigned int codevalue) { this->Internals->DerivationCodeSequenceCodeValue = codevalue; } void FileDerivation::SetPurposeOfReferenceCodeSequenceCodeValue(unsigned int codevalue) { this->Internals->PurposeOfReferenceCodeSequenceCodeValue = codevalue; } bool FileDerivation::AddReference(const char *referencedsopclassuid, const char *referencedsopinstanceuid) { if( !UIDGenerator::IsValid(referencedsopclassuid) ) { return false; } if( !UIDGenerator::IsValid(referencedsopinstanceuid) ) { return false; } // Internals->References.emplace_back( referencedsopclassuid, referencedsopinstanceuid ); return true; } void FileDerivation::SetAppendDerivationHistory(bool b) { Internals->AppendDerivationHistory = b; } /* PS 3.3 - 2008 C.7.6.1.1.3 Derivation Description If an Image is identified to be a derived image (see C.7.6.1.1.2 Image Type), Derivation Description (0008,2111) and Derivation Code Sequence (0008,9215) describe the way in which the image was derived. They may be used whether or not the Source Image Sequence (0008,2112) is provided. They may also be used in cases when the Derived Image pixel data is not significantly changed from one of the source images and the SOP Instance UID of the Derived Image is the same as the one used for the source image. */ bool FileDerivation::AddDerivationDescription() { File &file = GetFile(); DataSet &ds = file.GetDataSet(); if( !this->Internals->DerivationDescription.empty() ) { Attribute<0x0008,0x2111> at1; at1.SetValue( this->Internals->DerivationDescription.c_str() ); ds.Replace( at1.GetAsDataElement() ); } const Tag sisq(0x8,0x9215); SmartPointer sqi; sqi = new SequenceOfItems; // should we append the derivation after any existing one ? if( Internals->AppendDerivationHistory ) { if( ds.FindDataElement( sisq ) ) sqi = ds.GetDataElement( sisq ).GetValueAsSQ(); } sqi->SetLengthToUndefined(); Item item; item.SetVLToUndefined(); //Item &item1 = sqi->GetItem(1); DataSet &subds3 = item.GetNestedDataSet(); unsigned int codevalue = this->Internals->DerivationCodeSequenceCodeValue; const CodeDefinition *cd = GetCodeDefinition( codevalue, ImageDerivation ); if ( !cd ) { return false; } std::ostringstream os; os << cd->CodeValue; Attribute<0x0008,0x0100> at1; at1.SetValue( os.str() ); subds3.Replace( at1.GetAsDataElement() ); Attribute<0x0008,0x0102> at2; at2.SetValue( cd->CodingSchemeDesignator ); subds3.Replace( at2.GetAsDataElement() ); Attribute<0x0008,0x0104> at3; at3.SetValue( cd->CodeMeaning ); subds3.Replace( at3.GetAsDataElement() ); sqi->AddItem( item ); DataElement de( sisq ); de.SetVR( VR::SQ ); de.SetValue( *sqi ); de.SetVLToUndefined(); ds.Replace( de ); return true; } /* PS 3.3 - 2008 C.7.6.1.1.4 Source image sequence If an Image is identified to be a Derived image (see C.7.6.1.1.2 Image Type), Source Image Sequence (0008,2112) is an optional list of Referenced SOP Class UID (0008,1150)/ Referenced SOP Instance UID (0008,1150) pairs that identify the source images used to create the Derived image. It may be used whether or not there is a description of the way the image was derived in Derivation Description (0008,2111) or Derivation Code Sequence (0008,9215). */ bool FileDerivation::AddSourceImageSequence() { File &file = GetFile(); DataSet &ds = file.GetDataSet(); const Tag sisq(0x8,0x2112); SmartPointer sqi; sqi = new SequenceOfItems; if( ds.FindDataElement( sisq ) ) { sqi = ds.GetDataElement( sisq ).GetValueAsSQ(); } sqi->SetLengthToUndefined(); if( !Internals->AppendDerivationHistory && sqi->GetNumberOfItems() ) { gdcmWarningMacro( "Do not support appending Referenced Image" ); return false; } std::vector< std::pair< std::string, std::string > >::const_iterator it = Internals->References.begin(); for( ; it != Internals->References.end(); ++it ) { Item item1; item1.SetVLToUndefined(); DataSet &subds = item1.GetNestedDataSet(); /* (0008,1150) UI =UltrasoundImageStorage # 28, 1 ReferencedSOPClassUID (0008,1155) UI [1.2.840.1136190195280574824680000700.3.0.1.19970424140438] # 58, 1 ReferencedSOPInstanceUID */ { Attribute<0x8,0x1150> sopinstanceuid; sopinstanceuid.SetValue( it->first ); subds.Replace( sopinstanceuid.GetAsDataElement() ); Attribute<0x8,0x1155> sopclassuid; sopclassuid.SetValue( it->second ); subds.Replace( sopclassuid.GetAsDataElement() ); } if( !AddPurposeOfReferenceCodeSequence(subds) ) { return false; } sqi->AddItem( item1 ); } DataElement de( sisq); de.SetVR( VR::SQ ); de.SetValue( *sqi ); de.SetVLToUndefined(); ds.Replace( de ); return true; } bool FileDerivation::AddPurposeOfReferenceCodeSequence(DataSet &subds) { /* (0040,a170) SQ (Sequence with undefined length #=1) # u/l, 1 PurposeOfReferenceCodeSequence (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item (0008,0100) SH [121320] # 6, 1 CodeValue (0008,0102) SH [DCM] # 4, 1 CodingSchemeDesignator (0008,0104) LO [Uncompressed predecessor] # 24, 1 CodeMeaning (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem */ const Tag prcs(0x0040,0xa170); if( !subds.FindDataElement( prcs) ) { SequenceOfItems *sqi2 = new SequenceOfItems; DataElement de( prcs ); de.SetVR( VR::SQ ); de.SetValue( *sqi2 ); de.SetVLToUndefined(); subds.Insert( de ); } //SequenceOfItems *sqi = (SequenceOfItems*)subds.GetDataElement( prcs ).GetSequenceOfItems(); SmartPointer sqi = subds.GetDataElement( prcs ).GetValueAsSQ(); sqi->SetLengthToUndefined(); if( !sqi->GetNumberOfItems() ) { Item item; //( Tag(0xfffe,0xe000) ); item.SetVLToUndefined(); sqi->AddItem( item ); } Item &item2 = sqi->GetItem(1); DataSet &subds2 = item2.GetNestedDataSet(); /* (0008,0100) SH [121320] # 6, 1 CodeValue (0008,0102) SH [DCM] # 4, 1 CodingSchemeDesignator (0008,0104) LO [Uncompressed predecessor] # 24, 1 CodeMeaning */ unsigned int codevalue = this->Internals->PurposeOfReferenceCodeSequenceCodeValue; const CodeDefinition *cd = GetCodeDefinition( codevalue, SourceImagePurposesofReference ); if( !cd ) { cd = GetCodeDefinition( codevalue, PurposeOfReferencetoAlternateRepresentation ); } if (!cd) { return false; } std::ostringstream os; os << cd->CodeValue; Attribute<0x0008,0x0100> at1; at1.SetValue( os.str() ); subds2.Replace( at1.GetAsDataElement() ); Attribute<0x0008,0x0102> at2; at2.SetValue( cd->CodingSchemeDesignator ); subds2.Replace( at2.GetAsDataElement() ); Attribute<0x0008,0x0104> at3; at3.SetValue( cd->CodeMeaning ); subds2.Replace( at3.GetAsDataElement() ); return true; } bool FileDerivation::Derive() { File &file = GetFile(); DataSet &ds = file.GetDataSet(); { // (0008,0008) CS [ORIGINAL\SECONDARY] # 18, 2 ImageType Attribute<0x0008,0x0008> at3; static const CSComp values[] = {"DERIVED","SECONDARY"}; at3.SetValues( values, 2, true ); // true => copy data ! if( ds.FindDataElement( at3.GetTag() ) ) { const DataElement &de = ds.GetDataElement( at3.GetTag() ); if( !de.IsEmpty() ) at3.SetFromDataElement( de ); // Make sure that value #1 is at least 'DERIVED', so override in all cases: at3.SetValue( 0, values[0] ); } ds.Replace( at3.GetAsDataElement() ); } // { // Attribute<0x0008,0x2111> at1; // at1.SetValue( "lossy conversion" ); // ds.Replace( at1.GetAsDataElement() ); // } bool b = AddSourceImageSequence(); if( !b ) { gdcmDebugMacro( "Could not AddSourceImageSequence" ); return false; } b = AddDerivationDescription(); if( !b ) { gdcmDebugMacro( "Could not AddDerivationDescription" ); return false; } return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmFileDerivation.h000066400000000000000000000062761412732066400244350ustar00rootroot00000000000000/*========================================================================= 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 GDCMFILEDERIVATION_H #define GDCMFILEDERIVATION_H #include "gdcmFile.h" namespace gdcm { class FileDerivationInternals; class DataSet; /** * \brief FileDerivation class * \details See PS 3.16 - 2008 For the list of Code Value that can be used for in * Derivation Code Sequence * * URL: http://medical.nema.org/medical/dicom/2008/08_16pu.pdf * * DICOM Part 16 has two Context Groups CID 7202 and CID 7203 which contain a * set of codes defining reason for a source image reference (ie. reason code * for referenced image sequence) and a coded description of the deriation * applied to the new image data from the original. Both these context groups * are extensible. * * File Derivation is compulsory when creating a lossy derived image. */ class GDCM_EXPORT FileDerivation { public: FileDerivation(); ~FileDerivation(); /// Create the proper reference. Need to pass the original SOP Class UID and the original /// SOP Instance UID, so that those value can be used as Reference. /// \warning referencedsopclassuid and referencedsopinstanceuid needs to be \0 padded. This /// is not compatible with how ByteValue->GetPointer works. bool AddReference(const char *referencedsopclassuid, const char *referencedsopinstanceuid); // CID 7202 Source Image Purposes of Reference // {"DCM",121320,"Uncompressed predecessor"}, /// Specify the Purpose Of Reference Code Value. Eg. 121320 void SetPurposeOfReferenceCodeSequenceCodeValue(unsigned int codevalue); // CID 7203 Image Derivation // { "DCM",113040,"Lossy Compression" }, /// Specify the Derivation Code Sequence Code Value. Eg 113040 void SetDerivationCodeSequenceCodeValue(unsigned int codevalue); /// Specify the Derivation Description. Eg "lossy conversion" void SetDerivationDescription( const char *dd ); /// Specify if Derivation history should be appended (default false) /// When false, this is an error if input already has a derivation history /// When true, both Purpose of Reference Code Value and Derivation Code Sequence Code Value can have their history appended. void SetAppendDerivationHistory(bool b); /// Change bool Derive(); /// Set/Get File void SetFile(const File& f) { F = f; } File &GetFile() { return *F; } const File &GetFile() const { return *F; } protected: bool AddDerivationDescription(); bool AddSourceImageSequence(); bool AddPurposeOfReferenceCodeSequence(DataSet &ds); private: SmartPointer F; FileDerivationInternals *Internals; }; /** * \example GenFakeImage.cxx * \example ReformatFile.cs * This is a C++ example on how to use FileDerivation */ } // end namespace gdcm #endif //GDCMFILEDERIVATION_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmFileExplicitFilter.cxx000066400000000000000000000147211412732066400256250ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileExplicitFilter.h" #include "gdcmExplicitDataElement.h" #include "gdcmSequenceOfFragments.h" #include "gdcmSequenceOfItems.h" #include "gdcmFragment.h" #include "gdcmGlobal.h" #include "gdcmDict.h" #include "gdcmDicts.h" #include "gdcmGroupDict.h" #include "gdcmVR.h" #include "gdcmVM.h" #include "gdcmDataSetHelper.h" namespace gdcm { void FileExplicitFilter::SetRecomputeItemLength(bool b) { RecomputeItemLength = b; } void FileExplicitFilter::SetRecomputeSequenceLength(bool b) { RecomputeSequenceLength = b; } bool FileExplicitFilter::ChangeFMI() { /* FileMetaInformation &fmi = F->GetHeader(); TransferSyntax ts = TransferSyntax::ImplicitVRLittleEndian; { ts = TransferSyntax::ExplicitVRLittleEndian; } const char *tsuid = TransferSyntax::GetTSString( ts ); DataElement de( Tag(0x0002,0x0010) ); de.SetByteValue( tsuid, strlen(tsuid) ); de.SetVR( Attribute<0x0002, 0x0010>::GetVR() ); fmi.Replace( de ); //fmi.Remove( Tag(0x0002,0x0012) ); // will be regenerated //fmi.Remove( Tag(0x0002,0x0013) ); // ' ' ' fmi.SetDataSetTransferSyntax(ts); */ return true; } bool FileExplicitFilter::ProcessDataSet(DataSet &ds, Dicts const & dicts) { if( RecomputeSequenceLength || RecomputeItemLength ) { gdcmWarningMacro( "Not implemented sorry" ); return false; } DataSet::Iterator it = ds.Begin(); for( ; it != ds.End(); ) { DataElement de = *it; std::string strowner; const char *owner = nullptr; const Tag& t = de.GetTag(); if( t.IsPrivate() && !ChangePrivateTags // As a special exception we convert to proper VR : // - Private Group Length // - Private Creator // This makes the output more readable (and this should be relative safe) && !t.IsGroupLength() && !t.IsPrivateCreator() ) { // nothing to do ! just skip ++it; continue; } if( t.IsPrivate() && !t.IsPrivateCreator() ) { strowner = ds.GetPrivateCreator(t); owner = strowner.c_str(); } const DictEntry &entry = dicts.GetDictEntry(t,owner); const VR &vr = entry.GetVR(); //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 ); } //SequenceOfItems *sqi = de.GetSequenceOfItems(); //SequenceOfItems *sqi = dynamic_cast(&de.GetValue()); SmartPointer sqi = nullptr; if( vr == VR::SQ || cvr == VR::SQ ) // CP-246 + Private SQ (not in dict) { sqi = de.GetValueAsSQ(); if(!sqi) { if( !de.IsEmpty() ) { gdcmWarningMacro("DICOM file written out may not be readable" ); cvr = VR::UN; } } } if( de.GetByteValue() && !sqi ) { // all set //assert( cvr != VR::SQ /*&& cvr != VR::UN*/ ); assert( cvr != VR::INVALID ); if( cvr != VR::UN ) { // about to change , make some paranoid test: //assert( cvr.Compatible( oldvr ) ); // LT != LO but there are somewhat compatible if( cvr & VR::VRASCII ) { //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) ) { gdcmErrorMacro( "Cannot convert VR for tag: " << t << " " << oldvr << " is incompatible with " << cvr << " as given by ref. dict." ); return false; } } else if( cvr & VR::VRBINARY ) { // PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm if( !( oldvr & VR::VRBINARY || oldvr == VR::INVALID || oldvr == VR::UN ) ) { gdcmErrorMacro( "Cannot convert VR for tag: " << t << " " << oldvr << " is incompatible with " << cvr << " as given by ref. dict." ); return false; } } else { assert( 0 ); // programmer error } // let's do one more check we are going to make this attribute explicit VR, there is // still a special case, when VL is > uint16_max then we must give up: if( !(cvr & VR::VL32) && de.GetVL() > UINT16_MAX ) { cvr = VR::UN; } de.SetVR( cvr ); } } else if( sqi ) { assert( cvr == VR::SQ || cvr == VR::UN ); de.SetVR( VR::SQ ); if( de.GetByteValue() ) { de.SetValue( *sqi ); //de.SetVL( sqi->ComputeLength() ); } de.SetVLToUndefined(); assert( sqi->GetLength().IsUndefined() ); // recursive SequenceOfItems::ItemVector::iterator sit = sqi->Items.begin(); for(; sit != sqi->Items.end(); ++sit) { //Item &item = const_cast(*sit); Item &item = *sit; item.SetVLToUndefined(); DataSet &nds = item.GetNestedDataSet(); //const DataElement &deitem = item; ProcessDataSet(nds, dicts); item.SetVL( item.GetLength() ); } } else if( de.GetSequenceOfFragments() ) { assert( cvr & VR::OB_OW ); } else { // Ok length is 0, it can be a 0 length explicit SQ (implicit) or a ByteValue... // we cannot make any error here, simply change the VR de.SetVR( cvr ); } ++it; ds.Replace( de ); } return true; } bool FileExplicitFilter::Change() { //if( !UseVRUN) // { // gdcmErrorMacro( "Not implemented" ); // return false; // } const Global& g = GlobalInstance; const Dicts &dicts = g.GetDicts(); DataSet &ds = F->GetDataSet(); bool b = ProcessDataSet(ds, dicts); return b; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmFileExplicitFilter.h000066400000000000000000000047001412732066400252460ustar00rootroot00000000000000/*========================================================================= 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 GDCMFILEEXPLICITFILTER_H #define GDCMFILEEXPLICITFILTER_H #include "gdcmFile.h" namespace gdcm { class Dicts; /** * \brief FileExplicitFilter class * \details After changing a file from Implicit to Explicit representation (see * ImageChangeTransferSyntax) one operation is to make sure the VR of each * DICOM attribute are accurate and do match the one from PS 3.6. Indeed when a * file is written in Implicit representation, the VR is not stored directly * in the file. * * \warning changing an implicit dataset to an explicit dataset is NOT a * trivial task of simply changing the VR to the dict one: * \li One has to make sure SQ is properly set * \li One has to recompute the explicit length SQ * \li One has to make sure that VR is valid for the encoding * \li One has to make sure that VR 16bits can store the original value length */ class GDCM_EXPORT FileExplicitFilter { public: FileExplicitFilter():F(new File),ChangePrivateTags(false),UseVRUN(true),RecomputeItemLength(false),RecomputeSequenceLength(false) {} ~FileExplicitFilter() = default; /// Decide whether or not to VR'ify private tags void SetChangePrivateTags(bool b) { ChangePrivateTags = b;} /// When VR=16bits in explicit but Implicit has a 32bits length, use VR=UN void SetUseVRUN(bool b) { UseVRUN = b; } /// By default set Sequence & Item length to Undefined to avoid recomputing length: void SetRecomputeItemLength(bool b); void SetRecomputeSequenceLength(bool b); /// Set FMI Transfer Syntax /// Change bool Change(); /// Set/Get File void SetFile(const File& f) { F = f; } File &GetFile() { return *F; } protected: bool ProcessDataSet(DataSet &ds, Dicts const & dicts); bool ChangeFMI(); private: SmartPointer F; bool ChangePrivateTags; bool UseVRUN; bool RecomputeItemLength; bool RecomputeSequenceLength; }; } // end namespace gdcm #endif //GDCMFILEEXPLICITFILTER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmFileStreamer.cxx000066400000000000000000000622121412732066400244560ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileStreamer.h" #include "gdcmTag.h" #include "gdcmPrivateTag.h" #include "gdcmDataElement.h" #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmAttribute.h" #include "gdcmEvent.h" #include "gdcmProgressEvent.h" #define _FILE_OFFSET_BITS 64 #include #include // fstat #include #if defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__)) #include typedef int64_t off64_t; #else #if defined(__APPLE__) || defined(__FreeBSD__) # define off64_t off_t #endif #include // ftruncate #endif namespace gdcm { // Implementation detail: // FILE* have been chosen over std::fstream since it has been reported to lead // to vastly superior speed. The only issue in doing so, is the manual // handling of 64bits offset. Create thin wrapper: // See here for discussion: // http://stackoverflow.com/questions/17863594/size-of-off-t-at-compilation-time // Basically enforce use of off64_t over off_t since on windows off_t is pretty // much guarantee to be 32bits only. static inline int FSeeko(FILE *stream, off64_t offset, int whence) { #if _WIN32 #if defined(__MINGW32__) return fseek(stream, offset, whence); // 32bits #else return _fseeki64(stream, offset, whence); #endif #else return fseeko(stream, offset, whence); #endif } static inline off64_t FTello(FILE *stream) { #if _WIN32 #if defined(__MINGW32__) return ftell( stream ); // 32bits #else return _ftelli64( stream ); #endif #else return ftello( stream ); #endif } static inline bool FTruncate( const int fd, const off64_t len ) { #if _WIN32 #if defined(__MINGW32__) const long size = len; const int ret = _chsize( fd, size ); // 32bits return ret == 0 ? true : false; #else const __int64 size = len; const errno_t err = _chsize_s( fd, size ); return err == 0 ? true : false; #endif #else const int ret = ftruncate(fd, len); return ret == 0 ? true : false; #endif } static bool prepare_file( FILE * pFile, const off64_t offset, const off64_t inslen ) { // fast path if( inslen == 0 ) return true; const size_t BUFFERSIZE = 4096; char buffer[BUFFERSIZE]; struct stat sb; assert( pFile ); int fd = fileno( pFile ); if (fstat(fd, &sb) == 0) { if( inslen < 0 ) { off64_t bytes_to_move = sb.st_size - offset; off64_t read_start_offset = offset; while (bytes_to_move != 0) { const size_t bytes_this_time = static_cast(std::min((off64_t)BUFFERSIZE, bytes_to_move)); const off64_t rd_off = read_start_offset; const off64_t wr_off = rd_off + inslen; if( FSeeko(pFile, rd_off, SEEK_SET) ) { return false; } if (fread(buffer, 1, bytes_this_time, pFile) != bytes_this_time) { return false; } assert( wr_off < rd_off ); if( FSeeko(pFile, wr_off, SEEK_SET) ) { return false; } if (fwrite(buffer, 1, bytes_this_time, pFile) != bytes_this_time) { return false; } bytes_to_move -= bytes_this_time; read_start_offset += bytes_this_time; } assert( read_start_offset == sb.st_size ); if( !FTruncate( fd, sb.st_size + inslen ) ) { return false; } } else { #if 0 assert(sb.st_size >= offset); #endif if (sb.st_size > offset) { off64_t bytes_to_move = sb.st_size - offset; off64_t read_end_offset = sb.st_size; while (bytes_to_move != 0) { const size_t bytes_this_time = static_cast(std::min((off64_t)BUFFERSIZE, bytes_to_move)); const off64_t rd_off = read_end_offset - bytes_this_time; assert( (off64_t)rd_off >= offset ); const off64_t wr_off = rd_off + inslen; if( FSeeko(pFile, rd_off, SEEK_SET) ) { return false; } if (fread(buffer, 1, bytes_this_time, pFile) != bytes_this_time) { return false; } if( FSeeko(pFile, wr_off, SEEK_SET) ) { return false; } if (fwrite(buffer, 1, bytes_this_time, pFile) != bytes_this_time) { return false; } bytes_to_move -= bytes_this_time; read_end_offset = rd_off; } assert( read_end_offset == offset ); } } // easy case when sb.st_size == offset ... } // fstat return true; } enum Operation { NOOPERATION, DATAELEMENT, GROUPDATAELEMENT }; class FileStreamerInternals { public: FileStreamerInternals(): CurrentTag(0x0,0x0) { PrivateCreator.SetByteValue("",0); } bool SetTag( const Tag & t ) { if( !IsValid() ) return false; // else CurrentTag = t; operation = DATAELEMENT; return true; } bool SetPrivateCreator( const DataElement & de, const size_t maxsizde, const uint8_t startoffset ) { if( !IsValid() ) return false; // else PrivateCreator = de; operation = GROUPDATAELEMENT; StartOffset = startoffset; static const size_t limitmax = std::numeric_limits::max(); if( maxsizde % 2 == 0 && maxsizde < limitmax ) { MaxSizeDE = maxsizde; return true; } return false; } bool Match( Operation op, Tag const & t ) { if( operation != op ) return false; if( CurrentTag != t ) return false; return true; } bool Match( Operation op, DataElement const & de ) { if( operation != op ) return false; if( PrivateCreator != de ) return false; return true; } bool Reset( const Tag & ) { CurrentTag = Tag(0x0,0x0); operation = NOOPERATION; return true; } bool Reset( const DataElement & ) { PrivateCreator.SetTag( Tag(0x0,0x0) ); operation = NOOPERATION; return true; } bool IsValid() { if( TemplateFilename.empty() ) return false; if( OutFilename.empty() ) return false; if( operation != NOOPERATION ) return false; if( CurrentTag != Tag(0x0,0x0) ) return false; if( PrivateCreator.GetTag() != Tag(0x0,0x0) ) return false; if( PrivateCreator.GetVL() != 0 ) return false; return true; } bool CheckDataElement( const Tag & t ) { static const Tag pixeldata(0x7fe0,0x0010); if( t != pixeldata ) return false; CheckPixelDataElement = true; return true; } bool StartDataElement( const Tag & t ) { Self->InvokeEvent( StartEvent() ); const char *outfilename = OutFilename.c_str(); assert( outfilename ); actualde = 0; { std::ifstream is( outfilename, std::ios::binary ); if( !is.good() ) return false; std::set tagset; tagset.insert( t ); Reader reader; reader.SetStream( is ); if( !reader.ReadSelectedTags( tagset, false ) ) { return false; } const File & f = reader.GetFile(); const DataSet &ds = f.GetDataSet(); const TransferSyntax &ts = f.GetHeader().GetDataSetTransferSyntax(); TS = ts; // At least on Visual Studio compiler, I need to call clear(), to get // proper tellg() value: if( is.eof() ) is.clear(); thepos = is.tellg(); is.close(); if( ds.FindDataElement( t ) ) { const DataElement & de = ds.GetDataElement( t ); // Here is the actual trick: if( !de.IsEmpty() ) { // if you trigger this assertion, this means we have been allocating // memory for an element when not needed. assert( (de.GetByteValue() && de.GetByteValue()->GetPointer() == nullptr) || de.GetSequenceOfFragments() ); } actualde = de.GetVL() + 2 * de.GetVR().GetLength() + 4; thepos -= actualde; } else { // no attribute found, easy case ! } } assert( pFile == nullptr ); pFile = fopen(outfilename, "r+b"); assert( pFile ); CurrentDataLenth = 0; return true; } bool AppendToDataElement( const Tag & t, const char *data, size_t len ) { // copy trailing stuff if( CurrentDataLenth == 0 ) { size_t dicomlen = 4 + 4; // Tag + VL for Implicit if( TS.GetNegociatedType() == TransferSyntax::Explicit ) dicomlen += 4; off64_t newlen = len; assert( (size_t)newlen == len ); newlen += dicomlen; newlen -= actualde; off64_t plength = newlen; assert( ReservedDataLength >= 0 ); if( ReservedDataLength ) { if( (newlen + ReservedDataLength) >= (off64_t)len ) { plength = newlen + ReservedDataLength - len; } else { plength = newlen + ReservedDataLength - len; } ReservedDataLength -= len; assert( ReservedDataLength >= 0 ); } //if( !prepare_file( pFile, (off64_t)thepos + actualde, newlen ) ) if( !prepare_file( pFile, (off64_t)thepos + actualde, plength ) ) { return false; } // insert new data in between const Tag tag = t; const VL vl = 0; // will be updated later (UpdateDataElement) const size_t ddsize = WriteHelper( thepos, tag, vl ); assert( ddsize == dicomlen ); (void)ddsize; thepos += dicomlen; } else { assert( pFile ); const off64_t curpos = FTello(pFile); assert( curpos == thepos ); if( ReservedDataLength >= (off64_t)len ) { // simply update remaining reserved buffer: ReservedDataLength -= len; } else { const off64_t plength = len - ReservedDataLength; assert( plength >= 0 ); if( !prepare_file( pFile, (off64_t)curpos, plength) ) { return false; } ReservedDataLength = 0; // no more reserved buffer } FSeeko(pFile, curpos, SEEK_SET); } assert( ReservedDataLength >= 0 ); fwrite(data, 1, len, pFile); thepos += len; CurrentDataLenth += len; assert( CurrentDataLenth < std::numeric_limits::max() ); return true; } bool StopDataElement( const Tag & t ) { // Update DataElement: const size_t currentdatalenth = CurrentDataLenth; assert( ReservedDataLength >= 0); //const off64_t refpos = FTello(pFile); if( !UpdateDataElement( t ) ) { return false; } if( ReservedDataLength > 0) { const off64_t curpos = thepos; if( !prepare_file( pFile, curpos + ReservedDataLength, - ReservedDataLength) ) { return false; } ReservedDataLength = 0; } assert( ReservedDataLength == 0); fclose(pFile); pFile = nullptr; // Do some extra work: if( CheckPixelDataElement ) { const char *outfilename = OutFilename.c_str(); Reader reader; reader.SetFileName( outfilename ); std::set tagset; // (0028,0002) US 3 # 2,1 Samples per Pixel // (0028,0010) US 256 # 2,1 Rows // (0028,0011) US 256 # 2,1 Columns // (0028,0100) US 16 # 2,1 Bits Allocated // (0028,0008) IS [56] # 2,1 Number of Frames Attribute<0x28,0x02> spp = { 1 }; Attribute<0x28,0x10> rows; Attribute<0x28,0x11> cols; Attribute<0x28,0x100> ba = { 0 }; Attribute<0x28,0x08> nframes = { 1 }; tagset.insert( spp.GetTag() ); tagset.insert( rows.GetTag() ); tagset.insert( cols.GetTag() ); tagset.insert( ba.GetTag() ); tagset.insert( nframes.GetTag() ); if( !reader.ReadSelectedTags( tagset, true) ) { return false; } const File & f = reader.GetFile(); const DataSet &ds = f.GetDataSet(); const FileMetaInformation &fmi = f.GetHeader(); const TransferSyntax &ts = fmi.GetDataSetTransferSyntax(); if( ts.IsEncapsulated() ) { gdcmDebugMacro( "Only RAW (uncompressed) Pixel Data is supported for now" ); return false; } spp.SetFromDataSet( ds ); rows.SetFromDataSet( ds ); cols.SetFromDataSet( ds ); ba.SetFromDataSet( ds ); nframes.SetFromDataSet( ds ); if( ba.GetValue() % 8 != 0 ) { gdcmErrorMacro( "old ACR NEMA file: " << ba.GetValue() ); return false; } const size_t computedlength = spp.GetValue() * nframes.GetValue() * rows.GetValue() * cols.GetValue() * ( ba.GetValue() / 8 ); if( computedlength != currentdatalenth ) { gdcmDebugMacro( "Invalid size for Pixel Data Element: " << computedlength << " vs " << currentdatalenth ); return false; } } Self->InvokeEvent( EndEvent() ); return true; } bool ReserveDataElement( size_t len ) { ReservedDataLength = len; return true; } bool ReserveGroupDataElement( unsigned short ndataelement ) { if( ndataelement <= 256 ) { this->ReservedGroupDataElement = ndataelement; return true; } return false; } bool StartGroupDataElement( const PrivateTag & ori_pt ) { Self->InvokeEvent( StartEvent() ); // Need to cleanup the whole group, well not really, since as per DICOM // mechanism we can simply append const char *outfilename = OutFilename.c_str(); DataElement private_creator = ori_pt.GetAsDataElement(); assert( outfilename ); Tag curtag = ori_pt; { bool cont = false; do { Self->InvokeEvent( IterationEvent() ); std::set tagset; PrivateTag pt = curtag; tagset.insert( pt ); std::ifstream is( outfilename, std::ios::binary ); if( !is.good() ) return false; Reader reader; reader.SetStream( is ); if( !reader.ReadSelectedPrivateTags( tagset, false ) ) { return false; } const File & f = reader.GetFile(); const DataSet &ds = f.GetDataSet(); cont = ds.FindDataElement( curtag ); if( cont ) { curtag.SetElement( (uint16_t)(curtag.GetElement() + 0x1) ); } else { const TransferSyntax &ts = f.GetHeader().GetDataSetTransferSyntax(); TS = ts; thepos = is.tellg(); } is.close(); } while( cont ); // found a free spot: private_creator.GetTag().SetElement( curtag.GetElement() ); actualde = 0; } // copy trailing stuff std::string dicomdata; { std::stringstream ss; assert( private_creator.GetTag().IsPrivateCreator() ); if( TS.GetSwapCode() == SwapCode::BigEndian ) { if( TS.GetNegociatedType() == TransferSyntax::Explicit ) { private_creator.Write( ss ); } else { return true; } } else { if( TS.GetNegociatedType() == TransferSyntax::Explicit ) { private_creator.Write( ss ); } else { private_creator.Write( ss ); } } dicomdata = ss.str(); } // find thepcpos: std::streampos thepcpos = 0; { std::set tagset; Tag prev = private_creator.GetTag(); //assert( prev.GetElement() ); prev.SetElement( (uint16_t)(prev.GetElement() - 0x1) ); tagset.insert( prev ); std::ifstream is( outfilename, std::ios::binary ); if( !is.good() ) return false; Reader reader; reader.SetStream( is ); if( !reader.ReadSelectedTags( tagset, false ) ) { return false; } thepcpos = is.tellg(); is.close(); } const size_t pclen = dicomdata.size(); assert( pFile == nullptr ); pFile = fopen(outfilename, "r+b"); assert( pFile ); if( !prepare_file( pFile, (off64_t)thepcpos, pclen ) ) { return false; } FSeeko(pFile, thepcpos, SEEK_SET); { fwrite(dicomdata.c_str(), 1, dicomdata.size(), pFile); #if 0 fflush(pFile); // need to flush so that prepareFile works as expected. #endif thepos += pclen; } CurrentGroupTag.SetElement( this->StartOffset ); // First possible CurrentGroupTag.SetPrivateCreator( private_creator.GetTag() ); CurrentDataLenth = 0; if( this->ReservedGroupDataElement ) { if( !this->ReserveDataElement( MaxSizeDE ) ) { return false; } } return true; } bool AppendToGroupDataElement( const DataElement & , const char *data, size_t len ) { size_t len_to_move = len; while( len_to_move != 0 ) { Self->InvokeEvent( IterationEvent() ); const size_t len_this_time = std::min(MaxSizeDE - CurrentDataLenth, len_to_move); assert( len_this_time % 2 == 0 ); if( !AppendToDataElement( CurrentGroupTag, data, len_this_time ) ) { return false; } assert( CurrentDataLenth <= MaxSizeDE ); len_to_move -= len_this_time; if( CurrentDataLenth == MaxSizeDE ) { // flush assert( CurrentDataLenth % 2 == 0 ); if( !UpdateDataElement( CurrentGroupTag ) ) { return false; } assert( CurrentDataLenth == 0 ); CurrentGroupTag.SetElement( (uint16_t)(CurrentGroupTag.GetElement() + 1) ); const int lowbits = CurrentGroupTag.GetElement() & 0x00ff; if( lowbits == 0 ) { // we are wrapping, this is not handled: gdcmDebugMacro( "Too many data elements. Giving up" ); return false; } } } return true; } bool StopGroupDataElement( const DataElement & ) { return StopDataElement( CurrentGroupTag ); } TransferSyntax TS; std::string TemplateFilename; std::string OutFilename; private: Operation operation{NOOPERATION}; Tag CurrentTag; DataElement PrivateCreator; size_t MaxSizeDE{0}; uint8_t StartOffset{0}; public: bool CheckTemplateFileName{false}; bool InitializeCopy{false}; bool CheckPixelDataElement{false}; private: // really private ! FILE* pFile{nullptr}; std::streampos thepos; size_t actualde; size_t CurrentDataLenth; Tag CurrentGroupTag; off64_t ReservedDataLength{0}; unsigned short ReservedGroupDataElement{0}; public: FileStreamer *Self{nullptr}; private: bool UpdateDataElement( const Tag & t ) { // This function will set the VL for current DataElement: if( CurrentDataLenth ) { if( CurrentDataLenth % 2 == 1 ) { const off64_t curpos = FTello(pFile); if( ReservedDataLength >= 1 ) { // simply update remaining reserved buffer: ReservedDataLength -= 1; } else { if( !prepare_file( pFile, (off64_t)curpos, 1) ) { return false; } } FSeeko(pFile, curpos, SEEK_SET); int ret = fputc(0, pFile); // Set to NULL padding ? thepos += 1; assert( ret != EOF ); (void)ret; CurrentDataLenth += 1; } assert( CurrentDataLenth % 2 == 0 ); off64_t vlpos = thepos; vlpos -= CurrentDataLenth; vlpos -= 4; // VL if( TS.GetNegociatedType() == TransferSyntax::Explicit ) { vlpos -= 4; // VR } vlpos -= 4; // Tag gdcmAssertAlwaysMacro( vlpos >= 0 ); const Tag tag = t; gdcmAssertAlwaysMacro( CurrentDataLenth < std::numeric_limits::max() ); const VL vl = (uint32_t)CurrentDataLenth; size_t ret = WriteHelper( vlpos, tag, vl ); (void)ret; CurrentDataLenth = 0; } return true; } size_t WriteHelper( off64_t offset, const Tag & tag, const VL & vl ) { FSeeko(pFile, offset, SEEK_SET); std::stringstream ss; if( TS.GetSwapCode() == SwapCode::BigEndian ) tag.Write(ss); else tag.Write(ss); if( TS.GetNegociatedType() == TransferSyntax::Explicit ) { VR un = VR::UN; un.Write(ss); } if( TS.GetSwapCode() == SwapCode::BigEndian ) vl.Write(ss); else vl.Write(ss); const std::string dicomdata = ss.str(); fwrite(dicomdata.c_str(), 1, dicomdata.size(), pFile); return dicomdata.size(); } }; FileStreamer::FileStreamer() { Internals = new FileStreamerInternals; } FileStreamer::~FileStreamer() { delete Internals; } void FileStreamer::SetTemplateFileName(const char *filename_native) { if( filename_native ) Internals->TemplateFilename = filename_native; } bool FileStreamer::InitializeCopy() { #if 0 static int checksize = 0; if( !checksize ) { const int soff = sizeof( off64_t ); const int si64 = sizeof( int64_t ); if( soff != si64 ) return false; if( !(sizeof(sb.st_size) > 4) ) // LFS ? { return false; } ++checksize; } #endif if( !this->Internals->InitializeCopy ) { const char *filename = this->Internals->TemplateFilename.c_str(); const char *outfilename = this->Internals->OutFilename.c_str(); if( this->Internals->CheckTemplateFileName ) { // Prefer a GDCM copy, even if this is slower in most cases, this // guarantee that the output file will be correct as per-DICOM spec, // which will greatly simplify the rest of the process. Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) return false; if( strcmp( filename, outfilename ) ) { Writer writer; writer.SetFileName( outfilename ); writer.SetFile( reader.GetFile() ); if( !writer.Write() ) return false; } } else { assert( filename ); assert( outfilename ); std::ifstream is( filename, std::ios::binary ); if( !is.good() ) return false; if( strcmp( filename, outfilename ) ) { std::ofstream of( outfilename, std::ios::binary ); if( !of.good() ) return false; of << is.rdbuf(); of.close(); } is.close(); } this->Internals->InitializeCopy = true; this->Internals->Self = this; } return true; } bool FileStreamer::StartDataElement( const Tag & t ) { if( !this->Internals->SetTag( t ) ) { gdcmDebugMacro( "Could not StartDataElement" ); return false; } if( !InitializeCopy() ) { gdcmDebugMacro( "Could not InitializeCopy" ); return false; } return Internals->StartDataElement( t ); } bool FileStreamer::AppendToDataElement( const Tag & t, const char *data, size_t len ) { if( !this->Internals->Match( DATAELEMENT, t) ) { gdcmDebugMacro( "Could not AppendToDataElement" ); return false; } return this->Internals->AppendToDataElement( t, data, len ); } bool FileStreamer::StopDataElement( const Tag & t ) { if( !this->Internals->Reset(t) ) { return false; } return this->Internals->StopDataElement( t ); } bool FileStreamer::StartGroupDataElement( const PrivateTag & pt, size_t maxsizede, uint8_t startoffset ) { const DataElement private_creator = pt.GetAsDataElement(); if( !this->Internals->SetPrivateCreator( private_creator, maxsizede, startoffset ) ) { gdcmDebugMacro( "Could not StartGroupDataElement" ); return false; } if( !InitializeCopy() ) { gdcmDebugMacro( "Could not InitializeCopy" ); return false; } return Internals->StartGroupDataElement( pt ); } bool FileStreamer::AppendToGroupDataElement( const PrivateTag & pt, const char *data, size_t len ) { const DataElement private_creator = pt.GetAsDataElement(); if( !this->Internals->Match( GROUPDATAELEMENT, private_creator) ) { gdcmDebugMacro( "Could not AppendToGroupDataElement" ); return false; } return this->Internals->AppendToGroupDataElement( private_creator, data, len ); } bool FileStreamer::StopGroupDataElement( const PrivateTag & pt ) { const DataElement private_creator = pt.GetAsDataElement(); if( !this->Internals->Reset( private_creator ) ) { return false; } return this->Internals->StopGroupDataElement( private_creator ); } bool FileStreamer::ReserveGroupDataElement( unsigned short ndataelement ) { return Internals->ReserveGroupDataElement( ndataelement ); } bool FileStreamer::ReserveDataElement( size_t len ) { return Internals->ReserveDataElement( len ); } void FileStreamer::SetOutputFileName(const char *filename_native) { if( filename_native ) Internals->OutFilename = filename_native; } void FileStreamer::CheckTemplateFileName(bool check) { this->Internals->CheckTemplateFileName = check; } bool FileStreamer::CheckDataElement( const Tag & t ) { return this->Internals->CheckDataElement( t ); } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmFileStreamer.h000066400000000000000000000102211412732066400240740ustar00rootroot00000000000000/*========================================================================= 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 GDCMFILESTREAMER_H #define GDCMFILESTREAMER_H #include "gdcmSubject.h" #include "gdcmSmartPointer.h" namespace gdcm { class FileStreamerInternals; class Tag; class PrivateTag; /** * \brief FileStreamer * \details This class let a user create a massive DICOM DataSet from a template DICOM * file, by appending chunks of data. * * This class support two mode of operation: * 1. Creating a single DataElement by appending chunk after chunk of data. * * 2. Creating a set of DataElement within the same group, using a private * creator for start. New DataElement are added any time the user defined * maximum size for data element is reached. * * \warning any existing DataElement is removed, pick carefully which * DataElement to add. */ class GDCM_EXPORT FileStreamer : public Subject { public: FileStreamer(); ~FileStreamer() override; /// Set input DICOM template filename void SetTemplateFileName(const char *filename_native); // Decide to check template or not (default: false) /// Instead of simply blindly copying the input DICOM Template file, GDCM will /// be used to check the input file, and correct any issues recognized within /// the file. Only use if you do not have control over the input template /// file. void CheckTemplateFileName(bool check); /// Set output filename (target file) void SetOutputFileName(const char *filename_native); /// Decide to check the Data Element to be written (default: off) /// The implementation has default strategy for checking validity of DataElement. /// Currently it only support checking for the following tags: /// - (7fe0,0010) Pixel Data bool CheckDataElement( const Tag & t ); /// Start Single Data Element Operation /// This will delete any existing Tag t. Need to call it only once. bool StartDataElement( const Tag & t ); /// Append to previously started Tag t bool AppendToDataElement( const Tag & t, const char *array, size_t len ); /// Stop appending to tag t. This will compute the proper attribute length. bool StopDataElement( const Tag & t ); /// Add a hint on the final size of the dataelement. When optimally chosen, /// this reduce the number of file in-place copying. Should be called before /// StartDataElement bool ReserveDataElement( size_t len ); /// Start Private Group (multiple DataElement) Operation. Each newly added /// DataElement will have a length lower than \param maxsizede . /// When not specified, maxsizede is set to maximum size allowed by DICOM (= 2^32). /// startoffset can be used to specify the very first element you want to /// start with (instead of the first possible). Value should be in [0x0, 0xff] /// This will find the first available private creator. /// \bug maxsizede should be a value lower than the actual total size of the buffer to be copied bool StartGroupDataElement( const PrivateTag & pt, size_t maxsizede = 0, uint8_t startoffset = 0 ); /// Append to previously started private creator bool AppendToGroupDataElement( const PrivateTag & pt, const char *array, size_t len ); /// Stop appending to private creator bool StopGroupDataElement( const PrivateTag & pt ); /// Optimisation: pre-allocate the number of dataelement within the private /// group (ndataelement <= 256). Should be called before StartGroupDataElement bool ReserveGroupDataElement( unsigned short ndataelement ); /// for wrapped language: instantiate a reference counted object static SmartPointer New() { return new FileStreamer; } private: bool InitializeCopy(); FileStreamerInternals *Internals; }; } // end namespace gdcm #endif //GDCMFILESTREAMER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmIPPSorter.cxx000066400000000000000000000243501412732066400237240ustar00rootroot00000000000000/*========================================================================= 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 "gdcmIPPSorter.h" #include "gdcmScanner.h" #include "gdcmElement.h" #include "gdcmDirectionCosines.h" #include #include namespace gdcm { IPPSorter::IPPSorter() { ComputeZSpacing = true; DropDuplicatePositions = false; ZSpacing = 0; ZTolerance = 1e-6; DirCosTolerance = 0.; } inline double spacing_round(double n, int d) /* pow is defined as pow( double, double) or pow(double int) on M$ comp */ { return floor(n * pow(10., d) + .5) / pow(10., d); } struct dircos_key { double dircos[6]; void read( const std::string & str ) { DirectionCosines dc; dc.SetFromString( str.c_str() ); const double * ptr = dc; memcpy( dircos, ptr, sizeof(dircos) ); } }; struct dircos_comp { bool operator()( dircos_key const & lhs, dircos_key const & rhs ) const { const double *iop1 = lhs.dircos; const double *iop2 = rhs.dircos; return std::lexicographical_compare(iop1, iop1+6, iop2, iop2+6); } }; bool IPPSorter::Sort(std::vector const & filenames) { // BUG: I cannot clear Filenames since input filenames could also be the output of ourself... // Filenames.clear(); ZSpacing = 0; if( filenames.empty() ) { Filenames.clear(); return true; } Scanner scanner; const Tag tipp(0x0020,0x0032); // Image Position (Patient) const Tag tiop(0x0020,0x0037); // Image Orientation (Patient) const Tag tframe(0x0020,0x0052); // Frame of Reference UID const Tag tgantry(0x0018,0x1120); // Gantry/Detector Tilt // Temporal Position Identifier (0020,0100) 3 Temporal order of a dynamic or functional set of Images. //const Tag tpi(0x0020,0x0100); scanner.AddTag( tipp ); scanner.AddTag( tiop ); scanner.AddTag( tframe ); scanner.AddTag( tgantry ); bool b = scanner.Scan( filenames ); if( !b ) { gdcmDebugMacro( "Scanner failed" ); return false; } Scanner::ValuesType gantry = scanner.GetValues(tgantry); if( gantry.size() > 1 ) { gdcmDebugMacro( "More than one Gantry/Detector Tilt" ); return false; } if( gantry.size() == 1 ) { std::stringstream ss( *gantry.begin() ); double tilt; ss >> tilt; if( tilt != 0.0 ) { gdcmDebugMacro( "Gantry/Detector Tilt is not 0" ); return false; } } Scanner::ValuesType iops = scanner.GetValues(tiop); Scanner::ValuesType frames = scanner.GetValues(tframe); if( DirCosTolerance == 0. ) { if( iops.size() != 1 ) { std::set< dircos_key, dircos_comp > s; for( Scanner::ValuesType::const_iterator it = iops.begin(); it != iops.end(); ++it ) { dircos_key dk; dk.read( *it ); s.insert( dk ); } // sometime we want to handle: // iops = {[0] = "1\\0\\0\\0\\1\\-0", [1] = "1\\0\\0\\0\\1\\0 "} if( s.size() != 1 ) { gdcmDebugMacro( "More than one IOP (or no IOP): " << iops.size() << ". Try changing DirCosTolerance" ); return false; } } } const size_t fsize = frames.size(); // Should I really tolerate issue with Frame of Reference UID ? if( fsize == 1 ) // by the book { // TODO: need to check not empty ? technically PMS used to send MR Image Storage with empty FoR } else if( fsize == 0 || fsize == filenames.size() ) // Should I really tolerate no Frame of Reference UID ? { gdcmWarningMacro( "Odd number of Frame Of Reference UID (continuing with caution): " << fsize ); } else { gdcmErrorMacro( "Sorry your setup with Frame Of Reference UID does not make any sense: " << fsize ); return false; } const char *reference = filenames[0].c_str(); // we cannot simply consider the first file, what if this is not DICOM ? for(std::vector::const_iterator it1 = filenames.begin(); it1 != filenames.end(); ++it1) { const char *filename = it1->c_str(); bool iskey = scanner.IsKey(filename); if( iskey ) { reference = filename; } } Scanner::TagToValue const &t2v = scanner.GetMapping(reference); Scanner::TagToValue::const_iterator it = t2v.find( tiop ); // Take the first file in the list of filenames, if not IOP is found, simply gives up: if( it == t2v.end() ) { // DEAD CODE gdcmDebugMacro( "No iop in: " << reference ); return false; } if( it->first != tiop ) { // first file does not contains Image Orientation (Patient), let's give up gdcmDebugMacro( "No iop in first file "); return false; } const char *dircos = it->second; if( !dircos ) { // first file does contains Image Orientation (Patient), but it is empty gdcmDebugMacro( "Empty iop in first file "); return false; } // https://www.itk.org/pipermail/insight-users/2003-September/004762.html // Compute normal: // The steps I take when reconstructing a volume are these: First, // calculate the slice normal from IOP: double normal[3]; DirectionCosines dc; dc.SetFromString( dircos ); if( !dc.IsValid() ) return false; dc.Cross( normal ); // You only have to do this once for all slices in the volume. Next, for // each slice, calculate the distance along the slice normal using the IPP // tag ("dist" is initialized to zero before reading the first slice) : //typedef std::multimap SortedFilenames; using SortedFilenames = std::map; SortedFilenames sorted; { std::vector::const_iterator it1 = filenames.begin(); DirectionCosines dc2; for(; it1 != filenames.end(); ++it1) { const char *filename = it1->c_str(); bool iskey = scanner.IsKey(filename); if( iskey ) { const char *value = scanner.GetValue(filename, tipp); if( value ) { if( DirCosTolerance != 0. ) { const char *value2 = scanner.GetValue(filename, tiop); if( !dc2.SetFromString( value2 ) ) { if( value2 ) { gdcmWarningMacro( filename << " cannot read IOP: " << value2 ); } return false; } double cd = dc2.CrossDot( dc ); // result should be as close to 1 as possible: if( fabs(1 - cd) > DirCosTolerance ) { gdcmWarningMacro( filename << " Problem with DirCosTolerance: " ); // Cannot print cd since 0.9999 is printed as 1... may confuse user return false; } //dc2.Normalize(); //dc2.Print( std::cout << std::endl ); } //gdcmDebugMacro( filename << " has " << ipp << " = " << value ); Element ipp; std::stringstream ss; ss.str( value ); ipp.Read( ss ); double dist = 0; for (int i = 0; i < 3; ++i) dist += normal[i]*ipp[i]; // FIXME: This test is weak, since implicitly we are doing a != on floating point value if( sorted.find(dist) != sorted.end() ) { if( this->DropDuplicatePositions ) { gdcmWarningMacro( "dropping file " << filename << " since Z position: " << dist << " already found" ); continue; } gdcmWarningMacro( "dist: " << dist << " for " << filename << " already found in " << sorted.find(dist)->second ); return false; } sorted.insert( SortedFilenames::value_type(dist,filename) ); } else { gdcmDebugMacro( "File: " << filename << " has no Tag" << tipp << ". Skipping." ); } } else { gdcmDebugMacro( "File: " << filename << " could not be read. Skipping." ); } } } assert( !sorted.empty() ); { SortedFilenames::const_iterator it2 = sorted.begin(); double prev = it2->first; Filenames.emplace_back(it2->second ); if( sorted.size() > 1 ) { bool spacingisgood = true; ++it2; double current = it2->first; double zspacing = current - prev; for( ; it2 != sorted.end(); ++it2) { //std::cout << it2->first << " " << it2->second << std::endl; current = it2->first; Filenames.emplace_back(it2->second ); if( fabs((current - prev) - zspacing) > ZTolerance ) { gdcmDebugMacro( "ZTolerance test failed. You need to decrease ZTolerance." ); spacingisgood = false; } // update prev for the next for-loop prev = current; } // is spacing good ? if( spacingisgood && ComputeZSpacing ) { // If user ask for a ZTolerance of 1e-4, there is no need for us to // store the extra digits... this will make sure to return 2.2 from a 2.1999938551239993 value const int l = (int)( -log10(ZTolerance) ); ZSpacing = spacing_round(zspacing, l); } if( !spacingisgood ) { std::ostringstream os; os << "Filenames and 'z' positions" << std::endl; double prev1 = 0.; for(SortedFilenames::const_iterator it1 = sorted.begin(); it1 != sorted.end(); ++it1) { std::string f = it1->second; if( f.length() > 62 ) { f = f.substr(0,10) + " ... " + f.substr(f.length()-47); } double d = it1->first - prev1; if( it1 != sorted.begin() && fabs(d - zspacing) > ZTolerance) os << "* "; else os << " "; os << it1->first << "\t" << f << std::endl; prev1 = it1->first; } gdcmDebugMacro( os.str() ); } assert( spacingisgood == false || (ComputeZSpacing ? (ZSpacing > ZTolerance && ZTolerance > 0) : ZTolerance > 0) ); } } // return true: means sorting succeed, it does not mean spacing computation succeeded ! return true; } #if !defined(GDCM_LEGACY_REMOVE) bool IPPSorter::ComputeSpacing(std::vector const & filenames) { (void)filenames; return false; } #endif } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmIPPSorter.h000066400000000000000000000111771412732066400233540ustar00rootroot00000000000000/*========================================================================= 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 GDCMIPPSORTER_H #define GDCMIPPSORTER_H #include "gdcmSorter.h" #include #include namespace gdcm { /** * \brief IPPSorter * \details Implement a simple Image Position (Patient) sorter, along the Image * Orientation (Patient) direction. * This algorithm does NOT support duplicate and will FAIL in case of duplicate * IPP. * \warning See special note for SetZSpacingTolerance when computing the * ZSpacing from the IPP of each DICOM files (default tolerance for consistent * spacing is: 1e-6mm) * * For more information on Spacing, and how it is defined in DICOM, advanced * users may refers to: * * http://gdcm.sourceforge.net/wiki/index.php/Imager_Pixel_Spacing * * \bug There are currently a couple of bugs in this implementation: * \li Gantry Tilt is not considered (always an error) * \li Application programmer should only sort valid DataSet (eg. MRImageStorage, CTImageStorage, PETImageStorage) */ class GDCM_EXPORT IPPSorter : public Sorter { public: IPPSorter(); // FIXME: I do not like public virtual function... /// Main entry point to the sorter. /// It will execute the filter, option should be set before /// running this function (SetZSpacingTolerance, ...) /// Return value indicate if sorting could be achieved,. Warning this does *NOT* imply /// that spacing is consistent, it only means the file are sorted according to IPP /// You should check if ZSpacing is 0 or not to deduce if file are actually a 3D volume bool Sort(std::vector const & filenames) override; /// Functions related to Z-Spacing computation /// Set to true when sort algorithm should also perform a regular /// Z-Spacing computation using the Image Position (Patient) /// Potential reason for failure: /// 1. ALL slices are taken into account, if one slice if /// missing then ZSpacing will be set to 0 since the spacing /// will not be found to be regular along the Series void SetComputeZSpacing(bool b) { ComputeZSpacing = b; } /// 2. Another reason for failure is that that Z-Spacing is only /// slightly changing (eg 1e-3) along the series, a human can determine /// that this is ok and change the tolerance from its default value: 1e-6 void SetZSpacingTolerance(double tol) { ZTolerance = tol; } double GetZSpacingTolerance() const { return ZTolerance; } /// Sometimes IOP along a series is slightly changing for example: /// "0.999081\\0.0426953\\0.00369272\\-0.0419025\\0.955059\\0.293439", /// "0.999081\\0.0426953\\0.00369275\\-0.0419025\\0.955059\\0.293439", /// "0.999081\\0.0426952\\0.00369272\\-0.0419025\\0.955059\\0.293439", /// We need an API to define the tolerance which is allowed. Internally /// the cross vector of each direction cosines is computed. The tolerance /// then define the distance in between 1.0 to the dot product of those /// cross vectors. In a perfect world this dot product is of course 1.0 which /// imply a DirectionCosines tolerance of exactly 0.0 (default). void SetDirectionCosinesTolerance(double tol) { DirCosTolerance = tol; } double GetDirectionCosinesTolerance() const { return DirCosTolerance; } /// Makes the IPPSorter ignore multiple images located at the same position. /// Only the first occurrence will be kept. /// DropDuplicatePositions defaults to false. void SetDropDuplicatePositions(bool b) { DropDuplicatePositions = b; } /// Read-only function to provide access to the computed value for the Z-Spacing /// The ComputeZSpacing must have been set to true before execution of /// sort algorithm. Call this function *after* calling Sort(); /// Z-Spacing will be 0 on 2 occasions: /// \li Sorting simply failed, potentially duplicate IPP => ZSpacing = 0 /// \li ZSpacing could not be computed (Z-Spacing is not constant, or ZTolerance is too low) double GetZSpacing() const { return ZSpacing; } protected: bool ComputeZSpacing; bool DropDuplicatePositions; double ZSpacing; double ZTolerance; double DirCosTolerance; private: GDCM_LEGACY(bool ComputeSpacing(std::vector const & filenames)) }; } // end namespace gdcm #endif //GDCMIPPSORTER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmIconImage.cxx000066400000000000000000000076001412732066400237270ustar00rootroot00000000000000/*========================================================================= 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 "gdcmIconImage.h" namespace gdcm { } // end namespace gdcm #if 0 #include "gdcmRAWCodec.h" #include "gdcmSequenceOfFragments.h" namespace gdcm { /* * PICKER-16-MONO2-Nested_icon.dcm: (0088,0200) SQ (Sequence with undefined length #=1) # u/l, 1 IconImageSequence (fffe,e000) na (Item with undefined length #=10) # u/l, 1 Item (0028,0002) US 1 # 2, 1 SamplesPerPixel (0028,0004) CS [MONOCHROME2] # 12, 1 PhotometricInterpretation (0028,0010) US 64 # 2, 1 Rows (0028,0011) US 64 # 2, 1 Columns (0028,0034) IS [1\1] # 4, 2 PixelAspectRatio (0028,0100) US 8 # 2, 1 BitsAllocated (0028,0101) US 8 # 2, 1 BitsStored (0028,0102) US 7 # 2, 1 HighBit (0028,0103) US 0 # 2, 1 PixelRepresentation (7fe0,0010) OW 0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000... # 4096, 1 PixelData (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem */ IconImage::IconImage(): TS(), PF(), PI(), Dimensions(), Spacing(), PixelData() {} IconImage::~IconImage() {} void IconImage::SetDimension(unsigned int idx, unsigned int dim) { assert( idx < NumberOfDimensions ); Dimensions.resize( NumberOfDimensions ); // Can dim be 0 ?? Dimensions[idx] = dim; } void IconImage::Clear() { Dimensions.clear(); } const PhotometricInterpretation &IconImage::GetPhotometricInterpretation() const { return PI; } void IconImage::SetPhotometricInterpretation( PhotometricInterpretation const &pi) { PI = pi; } bool IconImage::GetBuffer(char *buffer) const { if( IsEmpty() ) { buffer = 0; return false; } const ByteValue *bv = PixelData.GetByteValue(); if( !bv ) { // KODAK_CompressedIcon.dcm // contains a compressed Icon Sequence, one has to guess this is lossless jpeg... #ifdef MDEBUG const SequenceOfFragments *sqf = PixelData.GetSequenceOfFragments(); std::ofstream os( "/tmp/kodak.ljpeg", std::ios::binary ); sqf->WriteBuffer( os ); #endif gdcmWarningMacro( "Compressed Icon are not support for now" ); buffer = 0; return false; } assert( bv ); RAWCodec codec; //assert( GetPhotometricInterpretation() == PhotometricInterpretation::MONOCHROME2 ); //codec.SetPhotometricInterpretation( GetPhotometricInterpretation() ); if( GetPhotometricInterpretation() != PhotometricInterpretation::MONOCHROME2 ) { gdcmWarningMacro( "PhotometricInterpretation: " << GetPhotometricInterpretation() << " not handled for now" ); } codec.SetPhotometricInterpretation( PhotometricInterpretation::MONOCHROME2 ); codec.SetPixelFormat( GetPixelFormat() ); codec.SetPlanarConfiguration( 0 ); DataElement out; bool r = codec.Decode(PixelData, out); assert( r ); const ByteValue *outbv = out.GetByteValue(); assert( outbv ); //unsigned long check = outbv->GetLength(); // FIXME memcpy(buffer, outbv->GetPointer(), outbv->GetLength() ); // FIXME return r; } } #endif GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmIconImage.h000066400000000000000000000047361412732066400233630ustar00rootroot00000000000000/*========================================================================= 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 GDCMICONIMAGE_H #define GDCMICONIMAGE_H #if 0 #include "gdcmObject.h" #include "gdcmDataElement.h" #include "gdcmPhotometricInterpretation.h" #include "gdcmPixelFormat.h" #include "gdcmTransferSyntax.h" #include namespace gdcm { /** * \brief IconImage class */ class GDCM_EXPORT IconImage : public Object { public: IconImage(); ~IconImage(); void Print(std::ostream &) const {} /// Transfer syntax void SetTransferSyntax(TransferSyntax const &ts) { TS = ts; } const TransferSyntax &GetTransferSyntax() const { return TS; } void SetDataElement(DataElement const &de) { PixelData = de; } const DataElement& GetDataElement() const { return PixelData; } void SetColumns(unsigned int col) { SetDimension(0,col); } void SetRows(unsigned int rows) { SetDimension(1,rows); } void SetDimension(unsigned int idx, unsigned int dim); int GetColumns() const { return Dimensions[0]; } int GetRows() const { return Dimensions[1]; } // Get/Set PixelFormat const PixelFormat &GetPixelFormat() const { return PF; } void SetPixelFormat(PixelFormat const &pf) { PF = pf; } const PhotometricInterpretation &GetPhotometricInterpretation() const; void SetPhotometricInterpretation(PhotometricInterpretation const &pi); bool IsEmpty() const { return Dimensions.size() == 0; } void Clear(); bool GetBuffer(char *buffer) const; private: TransferSyntax TS; PixelFormat PF; // SamplesPerPixel, BitsAllocated, BitsStored, HighBit, PixelRepresentation PhotometricInterpretation PI; std::vector Dimensions; // Col/Row std::vector Spacing; // PixelAspectRatio ? DataElement PixelData; // copied from 7fe0,0010 static const unsigned int NumberOfDimensions = 2; }; } // end namespace gdcm #endif #include "gdcmBitmap.h" namespace gdcm { //class GDCM_EXPORT IconImage : public Pixmap {}; typedef Bitmap IconImage; } #endif //GDCMICONIMAGE_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmIconImageFilter.cxx000066400000000000000000000445131412732066400251010ustar00rootroot00000000000000/*========================================================================= 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 "gdcmIconImageFilter.h" #include "gdcmIconImage.h" #include "gdcmAttribute.h" #include "gdcmPrivateTag.h" #include "gdcmJPEGCodec.h" namespace gdcm { class IconImageFilterInternals { public: std::vector < SmartPointer< IconImage > > icons; }; IconImageFilter::IconImageFilter():F(new File),Internals(new IconImageFilterInternals) { } IconImageFilter::~IconImageFilter() { delete Internals; } void IconImageFilter::ExtractIconImages() { const DataSet &rootds = F->GetDataSet(); const FileMetaInformation &header = F->GetHeader(); const TransferSyntax &ts = header.GetDataSetTransferSyntax(); // PICKER-16-MONO2-Nested_icon.dcm const Tag ticonimage(0x0088,0x0200); // Public Icon if( rootds.FindDataElement( ticonimage ) ) { const DataElement &iconimagesq = rootds.GetDataElement( ticonimage ); SmartPointer sq = iconimagesq.GetValueAsSQ(); // Is SQ empty ? if( sq && sq->GetNumberOfItems() == 1 ) { gdcmAssertAlwaysMacro( sq->GetNumberOfItems() == 1 ); SmartPointer< IconImage > si1 = new IconImage; IconImage &pixeldata = *si1; SequenceOfItems::ConstIterator it = sq->Begin(); const DataSet &ds = it->GetNestedDataSet(); { Attribute<0x0028,0x0011> at = { 0 }; at.SetFromDataSet( ds ); pixeldata.SetDimension(0, at.GetValue() ); } { Attribute<0x0028,0x0010> at = { 0 }; at.SetFromDataSet( ds ); pixeldata.SetDimension(1, at.GetValue() ); } PixelFormat pf; { Attribute<0x0028,0x0100> at = { 0 }; at.SetFromDataSet( ds ); pf.SetBitsAllocated( at.GetValue() ); } { Attribute<0x0028,0x0101> at = { 0 }; at.SetFromDataSet( ds ); pf.SetBitsStored( at.GetValue() ); } { Attribute<0x0028,0x0102> at = { 0 }; at.SetFromDataSet( ds ); pf.SetHighBit( at.GetValue() ); } { Attribute<0x0028,0x0103> at = { 0 }; at.SetFromDataSet( ds ); pf.SetPixelRepresentation( at.GetValue() ); } { Attribute<0x0028,0x0002> at = { 1 }; at.SetFromDataSet( ds ); pf.SetSamplesPerPixel( at.GetValue() ); } pixeldata.SetPixelFormat( pf ); // D 0028|0004 [CS] [Photometric Interpretation] [MONOCHROME2 ] const Tag tphotometricinterpretation(0x0028, 0x0004); assert( ds.FindDataElement( tphotometricinterpretation ) ); const ByteValue *photometricinterpretation = ds.GetDataElement( tphotometricinterpretation ).GetByteValue(); std::string photometricinterpretation_str( photometricinterpretation->GetPointer(), photometricinterpretation->GetLength() ); PhotometricInterpretation pi( PhotometricInterpretation::GetPIType( photometricinterpretation_str.c_str())); assert( pi != PhotometricInterpretation::UNKNOWN); pixeldata.SetPhotometricInterpretation( pi ); // if ( pi == PhotometricInterpretation::PALETTE_COLOR ) { SmartPointer lut = new LookupTable; const Tag testseglut(0x0028, (0x1221 + 0)); if( ds.FindDataElement( testseglut ) ) { gdcmAssertAlwaysMacro(0 && "Please report this image"); } lut->Allocate( pf.GetBitsAllocated() ); // for each red, green, blue: for(int i=0; i<3; ++i) { // (0028,1101) US 0\0\16 // (0028,1102) US 0\0\16 // (0028,1103) US 0\0\16 const Tag tdescriptor(0x0028, (uint16_t)(0x1101 + i)); //const Tag tdescriptor(0x0028, 0x3002); Element el_us3; // Now pass the byte array to a DICOMizer: el_us3.SetFromDataElement( ds[tdescriptor] ); //.GetValue() ); lut->InitializeLUT( LookupTable::LookupTableType(i), el_us3[0], el_us3[1], el_us3[2] ); // (0028,1201) OW // (0028,1202) OW // (0028,1203) OW const Tag tlut(0x0028, (uint16_t)(0x1201 + i)); //const Tag tlut(0x0028, 0x3006); // Segmented LUT // (0028,1221) OW // (0028,1222) OW // (0028,1223) OW const Tag seglut(0x0028, (uint16_t)(0x1221 + i)); if( ds.FindDataElement( tlut ) ) { const ByteValue *lut_raw = ds.GetDataElement( tlut ).GetByteValue(); assert( lut_raw ); // LookupTableType::RED == 0 lut->SetLUT( LookupTable::LookupTableType(i), (const unsigned char*)lut_raw->GetPointer(), lut_raw->GetLength() ); //assert( pf.GetBitsAllocated() == el_us3.GetValue(2) ); //unsigned long check = // (el_us3.GetValue(0) ? el_us3.GetValue(0) : 65536) // * el_us3.GetValue(2) / 8; //assert( check == lut_raw->GetLength() ); (void)check; } else if( ds.FindDataElement( seglut ) ) { const ByteValue *lut_raw = ds.GetDataElement( seglut ).GetByteValue(); assert( lut_raw ); lut->SetLUT( LookupTable::LookupTableType(i), (const unsigned char*)lut_raw->GetPointer(), lut_raw->GetLength() ); //assert( pf.GetBitsAllocated() == el_us3.GetValue(2) ); //unsigned long check = // (el_us3.GetValue(0) ? el_us3.GetValue(0) : 65536) // * el_us3.GetValue(2) / 8; //assert( check == lut_raw->GetLength() ); (void)check; } else { gdcmWarningMacro( "Icon Sequence is incomplete. Giving up" ); pixeldata.Clear(); return; } } pixeldata.SetLUT(*lut); } const Tag tpixeldata = Tag(0x7fe0, 0x0010); if( !ds.FindDataElement( tpixeldata ) ) { gdcmWarningMacro( "Icon Sequence is incomplete. Giving up" ); pixeldata.Clear(); return; } const DataElement& de = ds.GetDataElement( tpixeldata ); pixeldata.SetDataElement( de ); // Pass TransferSyntax: pixeldata.SetTransferSyntax( ts ); Internals->icons.emplace_back(pixeldata ); } } // AMIInvalidPrivateDefinedLengthSQasUN.dcm // GE_CT_With_Private_compressed-icon.dcm // MR_GE_with_Private_Compressed_Icon_0009_1110.dcm // FIXME: // Not all tags from the private sequence can be handled // For instance an icon has a window center/width ... const PrivateTag tgeiconimage(0x0009,0x0010,"GEIIS"); // Private Icon if( rootds.FindDataElement( tgeiconimage ) ) { const DataElement &iconimagesq = rootds.GetDataElement( tgeiconimage ); //const SequenceOfItems* sq = iconimagesq.GetSequenceOfItems(); SmartPointer sq = iconimagesq.GetValueAsSQ(); // Is SQ empty ? assert( sq ); if( !sq ) return; SmartPointer< IconImage > si1 = new IconImage; IconImage &pixeldata = *si1; SequenceOfItems::ConstIterator it = sq->Begin(); const DataSet &ds = it->GetNestedDataSet(); // D 0028|0011 [US] [Columns] [512] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0011) ); Attribute<0x0028,0x0011> at = { 0 }; at.SetFromDataSet( ds ); pixeldata.SetDimension(0, at.GetValue() ); } // D 0028|0010 [US] [Rows] [512] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0010) ); Attribute<0x0028,0x0010> at = { 0 }; at.SetFromDataSet( ds ); pixeldata.SetDimension(1, at.GetValue() ); } PixelFormat pf1; // D 0028|0100 [US] [Bits Allocated] [16] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0100) ); Attribute<0x0028,0x0100> at = { 0 }; at.SetFromDataSet( ds ); pf1.SetBitsAllocated( at.GetValue() ); } // D 0028|0101 [US] [Bits Stored] [12] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0101) ); Attribute<0x0028,0x0101> at = { 0 }; at.SetFromDataSet( ds ); pf1.SetBitsStored( at.GetValue() ); } // D 0028|0102 [US] [High Bit] [11] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0102) ); Attribute<0x0028,0x0102> at = { 0 }; at.SetFromDataSet( ds ); pf1.SetHighBit( at.GetValue() ); } // D 0028|0103 [US] [Pixel Representation] [0] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0103) ); Attribute<0x0028,0x0103> at = { 0 }; at.SetFromDataSet( ds ); pf1.SetPixelRepresentation( at.GetValue() ); } // (0028,0002) US 1 # 2, 1 SamplesPerPixel { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0002) ); Attribute<0x0028,0x0002> at = { 1 }; at.SetFromDataSet( ds ); pf1.SetSamplesPerPixel( at.GetValue() ); } pixeldata.SetPixelFormat( pf1 ); // D 0028|0004 [CS] [Photometric Interpretation] [MONOCHROME2 ] const Tag tphotometricinterpretation(0x0028, 0x0004); assert( ds.FindDataElement( tphotometricinterpretation ) ); const ByteValue *photometricinterpretation = ds.GetDataElement( tphotometricinterpretation ).GetByteValue(); std::string photometricinterpretation_str( photometricinterpretation->GetPointer(), photometricinterpretation->GetLength() ); PhotometricInterpretation pi( PhotometricInterpretation::GetPIType( photometricinterpretation_str.c_str())); assert( pi != PhotometricInterpretation::UNKNOWN); pixeldata.SetPhotometricInterpretation( pi ); const Tag tpixeldata = Tag(0x7fe0, 0x0010); assert( ds.FindDataElement( tpixeldata ) ); { const DataElement& de = ds.GetDataElement( tpixeldata ); #if 0 JPEGCodec jpeg; jpeg.SetPhotometricInterpretation( pixeldata.GetPhotometricInterpretation() ); jpeg.SetPlanarConfiguration( 0 ); PixelFormat pf = pixeldata.GetPixelFormat(); // Apparently bits stored can only be 8 or 12: if( pf.GetBitsStored() == 16 ) { pf.SetBitsStored( 12 ); } jpeg.SetPixelFormat( pf ); DataElement de2; jpeg.Decode( de, de2); pixeldata.SetDataElement( de2 ); #endif #if 0 JPEGCodec jpeg; jpeg.SetPhotometricInterpretation( pixeldata.GetPhotometricInterpretation() ); jpeg.SetPixelFormat( pixeldata.GetPixelFormat() ); DataElement de2; jpeg.Decode( de, de2); PixelFormat &pf2 = jpeg.GetPixelFormat(); #endif #if 1 std::istringstream is; const ByteValue *bv = de.GetByteValue(); assert( bv ); is.str( std::string( bv->GetPointer(), bv->GetLength() ) ); TransferSyntax jpegts; JPEGCodec jpeg; jpeg.SetPixelFormat( pf1 ); // important to initialize bool b = jpeg.GetHeaderInfo( is, jpegts ); if( !b ) { assert( 0 ); } //jpeg.GetPixelFormat().Print (std::cout); pixeldata.SetPixelFormat( jpeg.GetPixelFormat() ); // Set appropriate transfer Syntax pixeldata.SetTransferSyntax( jpegts ); #endif pixeldata.SetDataElement( de ); } Internals->icons.emplace_back(pixeldata ); } // AFAIK this icon SQ is undocumented , but I found it in: // gdcmDataExtra/gdcmBreakers/2929J888_8b_YBR_RLE_PlanConf0_breaker.dcm // aka 'SmallPreview' // The SQ contains a DataElement: // (0002,0010) UI [1.2.840.10008.1.2.1] # 20,1 Transfer Syntax UID // sigh... const PrivateTag tgeiconimage2(0x6003,0x0010,"GEMS_Ultrasound_ImageGroup_001"); if( rootds.FindDataElement( tgeiconimage2 ) ) { const DataElement &iconimagesq = rootds.GetDataElement( tgeiconimage2 ); //const SequenceOfItems* sq = iconimagesq.GetSequenceOfItems(); SmartPointer sq = iconimagesq.GetValueAsSQ(); // Is SQ empty ? assert( sq ); if( !sq ) return; SmartPointer< IconImage > si1 = new IconImage; IconImage &pixeldata = *si1; SequenceOfItems::ConstIterator it = sq->Begin(); const DataSet &ds = it->GetNestedDataSet(); // D 0028|0011 [US] [Columns] [512] { const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0011) ); Attribute<0x0028,0x0011> at; at.SetFromDataElement( de ); pixeldata.SetDimension(0, at.GetValue() ); } // D 0028|0010 [US] [Rows] [512] { const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0010) ); Attribute<0x0028,0x0010> at; at.SetFromDataElement( de ); pixeldata.SetDimension(1, at.GetValue() ); } PixelFormat pf; // D 0028|0100 [US] [Bits Allocated] [16] { const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0100) ); Attribute<0x0028,0x0100> at; at.SetFromDataElement( de ); pf.SetBitsAllocated( at.GetValue() ); } // D 0028|0101 [US] [Bits Stored] [12] { const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0101) ); Attribute<0x0028,0x0101> at; at.SetFromDataElement( de ); pf.SetBitsStored( at.GetValue() ); } // D 0028|0102 [US] [High Bit] [11] { const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0102) ); Attribute<0x0028,0x0102> at; at.SetFromDataElement( de ); pf.SetHighBit( at.GetValue() ); } // D 0028|0103 [US] [Pixel Representation] [0] { const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0103) ); Attribute<0x0028,0x0103> at; at.SetFromDataElement( de ); pf.SetPixelRepresentation( at.GetValue() ); } // (0028,0002) US 1 # 2, 1 SamplesPerPixel { const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0002) ); Attribute<0x0028,0x0002> at; at.SetFromDataElement( de ); pf.SetSamplesPerPixel( at.GetValue() ); } pixeldata.SetPixelFormat( pf ); // D 0028|0004 [CS] [Photometric Interpretation] [MONOCHROME2 ] const Tag tphotometricinterpretation(0x0028, 0x0004); assert( ds.FindDataElement( tphotometricinterpretation ) ); const ByteValue *photometricinterpretation = ds.GetDataElement( tphotometricinterpretation ).GetByteValue(); std::string photometricinterpretation_str( photometricinterpretation->GetPointer(), photometricinterpretation->GetLength() ); PhotometricInterpretation pi( PhotometricInterpretation::GetPIType( photometricinterpretation_str.c_str())); assert( pi != PhotometricInterpretation::UNKNOWN); pixeldata.SetPhotometricInterpretation( pi ); //const Tag tpixeldata = Tag(0x7fe0, 0x0010); const PrivateTag tpixeldata(0x6003,0x0011,"GEMS_Ultrasound_ImageGroup_001"); assert( ds.FindDataElement( tpixeldata ) ); { const DataElement& de = ds.GetDataElement( tpixeldata ); pixeldata.SetDataElement( de ); /* JPEGCodec jpeg; jpeg.SetPhotometricInterpretation( pixeldata.GetPhotometricInterpretation() ); jpeg.SetPlanarConfiguration( 0 ); PixelFormat pf = pixeldata.GetPixelFormat(); // Apparently bits stored can only be 8 or 12: if( pf.GetBitsStored() == 16 ) { pf.SetBitsStored( 12 ); } jpeg.SetPixelFormat( pf ); DataElement de2; jpeg.Decode( de, de2); pixeldata.SetDataElement( de2 ); */ } { Attribute<0x002,0x0010> at; at.SetFromDataSet( ds ); TransferSyntax tstype = TransferSyntax::GetTSType( at.GetValue() ); pixeldata.SetTransferSyntax( tstype ); } Internals->icons.emplace_back(pixeldata ); } } /* [ICONDATA2] PrivateCreator = VEPRO VIM 5.0 DATA Group = 0x0055 Element = 0x0030 Data.ID = C|0|3 Data.Type = C|3|1 Data.Width = I|4|2 Data.Height = I|6|2 */ namespace { struct VeproData { char ID[3]; char Type; uint16_t Width; uint16_t Height; }; } // documentation was found in : VIM/VIMSYS/dcmviewpriv.dat void IconImageFilter::ExtractVeproIconImages() { const DataSet &rootds = F->GetDataSet(); const PrivateTag ticon1(0x55,0x0030,"VEPRO VIF 3.0 DATA"); const PrivateTag ticon2(0x55,0x0030,"VEPRO VIM 5.0 DATA"); const ByteValue * bv = nullptr; // Prefer VIF over VIM ? if( rootds.FindDataElement( ticon1 ) ) { const DataElement &de = rootds.GetDataElement( ticon1 ); bv = de.GetByteValue(); } else if( rootds.FindDataElement( ticon2 ) ) { const DataElement &de = rootds.GetDataElement( ticon2 ); bv = de.GetByteValue(); } if( bv ) { const char *buf = bv->GetPointer(); size_t len = bv->GetLength(); VeproData data; memcpy(&data, buf, sizeof(data)); const char *raw = buf + sizeof(data); size_t offset = 4; // All header starts with the letter 'RAW\0', it looks like we need // to skip them (all 4 of them) int magic = memcmp( raw, "RAW\0", 4 ); gdcmAssertAlwaysMacro( magic == 0 ); unsigned int dims[3] = {}; dims[0] = data.Width; dims[1] = data.Height; assert( dims[0] * dims[1] == len - sizeof(data) - offset ); DataElement pd; pd.SetByteValue( raw + offset, (uint32_t)(len - sizeof(data) - offset) ); SmartPointer< IconImage > si1 = new IconImage; IconImage &pixeldata = *si1; pixeldata.SetDataElement( pd ); pixeldata.SetDimension(0, dims[0] ); pixeldata.SetDimension(1, dims[1] ); PixelFormat pf = PixelFormat::UINT8; pixeldata.SetPixelFormat( pf ); pixeldata.SetPhotometricInterpretation( PhotometricInterpretation::MONOCHROME2 ); Internals->icons.emplace_back(pixeldata ); } } bool IconImageFilter::Extract() { Internals->icons.clear(); ExtractIconImages(); ExtractVeproIconImages(); return GetNumberOfIconImages() != 0; } unsigned int IconImageFilter::GetNumberOfIconImages() const { // what is icons are in undefined length sequence ? return (unsigned int)Internals->icons.size(); } IconImage& IconImageFilter::GetIconImage( unsigned int i ) const { assert( i < Internals->icons.size() ); return *Internals->icons[i]; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmIconImageFilter.h000066400000000000000000000045771412732066400245340ustar00rootroot00000000000000/*========================================================================= 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 GDCMICONIMAGEFILTER_H #define GDCMICONIMAGEFILTER_H #include "gdcmFile.h" #include "gdcmIconImage.h" namespace gdcm { class IconImageFilterInternals; /** * \brief IconImageFilter * \details This filter will extract icons from a File * This filter will loop over all known sequence (public and private) that may * contains an IconImage and retrieve them. The filter will fails with a value * of false if no icon can be found * Since it handle both public and private icon type, one should not assume the * icon is in uncompress form, some private vendor store private icon in * JPEG8/JPEG12 * * Implementation details: * This filter supports the following Icons: * - (0088,0200) Icon Image Sequence * - (0009,10,GEIIS) GE IIS Thumbnail Sequence * - (6003,10,GEMS_Ultrasound_ImageGroup_001) GEMS Image Thumbnail Sequence * - (0055,30,VEPRO VIF 3.0 DATA) Icon Data * - (0055,30,VEPRO VIM 5.0 DATA) ICONDATA2 * * \warning the icon stored in those private attribute do not conform to * definition of Icon Image Sequence (do not simply copy/paste). For example * some private icon can be expressed as 12bits pixel, while the DICOM standard * only allow 8bits icons. * * \see ImageReader */ class GDCM_EXPORT IconImageFilter { public: IconImageFilter(); ~IconImageFilter(); /// Set/Get File void SetFile(const File& f) { F = f; } File &GetFile() { return *F; } const File &GetFile() const { return *F; } /// Extract all Icon found in File bool Extract(); /// Retrieve extract IconImage (need to call Extract first) unsigned int GetNumberOfIconImages() const; IconImage& GetIconImage( unsigned int i ) const; protected: void ExtractIconImages(); void ExtractVeproIconImages(); private: SmartPointer F; IconImageFilterInternals *Internals; }; } // end namespace gdcm #endif //GDCMICONIMAGEFILTER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmIconImageGenerator.cxx000066400000000000000000000777421412732066400256140ustar00rootroot00000000000000/*========================================================================= 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 "gdcmIconImageGenerator.h" #include "gdcmIconImage.h" #include "gdcmAttribute.h" #include "gdcmPrivateTag.h" #include "gdcmImage.h" #include "gdcmJPEGCodec.h" #include "gdcmRescaler.h" #include #include #include #include namespace gdcm { class IconImageGeneratorInternals { public: IconImageGeneratorInternals() { dims[0] = dims[1] = 0; Min = 0; Max = 0; UseMinMax = false; AutoMinMax = false; ConvertRGBToPaletteColor = true; UseOutsideValuePixel = false; OutsideValuePixel = 0; } unsigned int dims[2]; double Min; double Max; bool UseMinMax; bool AutoMinMax; bool ConvertRGBToPaletteColor; bool UseOutsideValuePixel; double OutsideValuePixel; }; IconImageGenerator::IconImageGenerator():P(new Pixmap),I(new IconImage),Internals(new IconImageGeneratorInternals) { } IconImageGenerator::~IconImageGenerator() { delete Internals; } // Implementation detail: // This function was required at some point in time since the implementation // RGB -> PALETTE is extremely slow void IconImageGenerator::ConvertRGBToPaletteColor(bool b) { Internals->ConvertRGBToPaletteColor = b; } void IconImageGenerator::SetOutputDimensions(const unsigned int dims[2]) { Internals->dims[0] = dims[0]; Internals->dims[1] = dims[1]; } namespace quantization { // retrieved from: // http://en.literateprograms.org/Special:Downloadcode/Median_cut_algorithm_(C_Plus_Plus) /* Copyright (c) 2011 the authors listed at the following URL, and/or the authors of referenced articles or incorporated external code: http://en.literateprograms.org/Median_cut_algorithm_(C_Plus_Plus)?action=history&offset=20080309133934 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Retrieved from: http://en.literateprograms.org/Median_cut_algorithm_(C_Plus_Plus)?oldid=12754 */ const int NUM_DIMENSIONS = 3; struct Point { unsigned char x[NUM_DIMENSIONS]; }; class Block { Point minCorner, maxCorner; Point* points; int pointsLength; public: Block(Point* points, std::ptrdiff_t pointsLength); Point * getPoints(); int numPoints() const; int longestSideIndex() const; int longestSideLength() const; bool operator<(const Block& rhs) const; void shrink(); }; template class CoordinatePointComparator { public: bool operator()(Point left, Point right) { return left.x[index] < right.x[index]; } }; //std::list medianCut(Point* image, int numPoints, unsigned int desiredSize); Block::Block(Point* pts, std::ptrdiff_t ptslen) { assert( ptslen > 0 ); this->points = pts; this->pointsLength = (int)ptslen; for(int i=0; i < NUM_DIMENSIONS; i++) { minCorner.x[i] = std::numeric_limits::min(); maxCorner.x[i] = std::numeric_limits::max(); } } Point * Block::getPoints() { return points; } int Block::numPoints() const { return pointsLength; } int Block::longestSideIndex() const { int m = maxCorner.x[0] - minCorner.x[0]; int maxIndex = 0; for(int i=1; i < NUM_DIMENSIONS; i++) { int diff = maxCorner.x[i] - minCorner.x[i]; if (diff > m) { m = diff; maxIndex = i; } } return maxIndex; } int Block::longestSideLength() const { int i = longestSideIndex(); return maxCorner.x[i] - minCorner.x[i]; } bool Block::operator<(const Block& rhs) const { return this->longestSideLength() < rhs.longestSideLength(); } void Block::shrink() { int i,j; for(j=0; j medianCut(DataElement const &PixelData, int numPoints, unsigned int desiredSize, std::vector & outputimage ) { assert( numPoints > 0 ); //Point* Points = (Point*)malloc(sizeof(Point) * numPoints); Point* Points = new Point[numPoints]; assert( Points ); const ByteValue *bv = PixelData.GetByteValue(); assert( bv ); const unsigned char *inbuffer = (const unsigned char*)bv->GetPointer(); assert( inbuffer ); size_t bvlen = bv->GetLength(); (void)bvlen; assert( bvlen == (size_t) numPoints * 3 ); // only 8bits RGB please for(int i = 0; i < numPoints; i++) { #if 0 memcpy(&Points[i], inbuffer + 3 * i, 3); #else Points[i].x[0] = inbuffer[ 3 * i + 0 ]; Points[i].x[1] = inbuffer[ 3 * i + 1 ]; Points[i].x[2] = inbuffer[ 3 * i + 2 ]; #endif } Point* image = Points; std::priority_queue blockQueue; Block initialBlock(image, numPoints); initialBlock.shrink(); blockQueue.push(initialBlock); while (blockQueue.size() < desiredSize /*&& blockQueue.top().numPoints() > 1*/ ) { Block longestBlock = blockQueue.top(); blockQueue.pop(); Point * begin = longestBlock.getPoints(); Point * median = longestBlock.getPoints() + (longestBlock.numPoints()+1)/2; Point * end = longestBlock.getPoints() + longestBlock.numPoints(); switch(longestBlock.longestSideIndex()) { case 0: std::nth_element(begin, median, end, CoordinatePointComparator<0>()); break; case 1: std::nth_element(begin, median, end, CoordinatePointComparator<1>()); break; case 2: std::nth_element(begin, median, end, CoordinatePointComparator<2>()); break; } Block block1(begin, median-begin), block2(median, end-median); block1.shrink(); block2.shrink(); blockQueue.push(block1); blockQueue.push(block2); } std::list result; //int s = blockQueue.size(); outputimage.resize( numPoints ); //const ByteValue *bv = PixelData.GetByteValue(); //const char *inbuffer = bv->GetPointer(); while(!blockQueue.empty()) { Block block = blockQueue.top(); blockQueue.pop(); Point * points = block.getPoints(); int sum[NUM_DIMENSIONS] = {0,0,0}; for(int i=0; i < block.numPoints(); i++) { for(int j=0; j < NUM_DIMENSIONS; j++) { sum[j] += points[i].x[j]; } } Point averagePoint; for(int j=0; j < NUM_DIMENSIONS; j++) { averagePoint.x[j] = sum[j] / block.numPoints(); } result.push_back(averagePoint); //int index = std::distance(s.begin(), it.first); size_t index = result.size(); assert( index <= 256 ); for(int i = 0; i < numPoints; i++) { const unsigned char *currentcolor = inbuffer + 3 * i; for(size_t j = 0; j < (size_t)block.numPoints(); j++) { assert( currentcolor < inbuffer + bvlen ); assert( currentcolor + 3 <= inbuffer + bvlen ); if( std::equal( currentcolor, currentcolor + 3, points[j].x ) ) { //assert( outputimage[i] == 0 ); assert( index > 0 ); outputimage[i] = (unsigned char)(index - 1); } } } } delete[] Points; return result; } } // end namespace quantization // Create LUT with a maximum number of color equal to \param maxcolor void IconImageGenerator::BuildLUT( Bitmap & bitmap, unsigned int maxcolor ) { assert( Internals->ConvertRGBToPaletteColor ); using namespace quantization; const unsigned int *dims = bitmap.GetDimensions(); unsigned int numPoints = dims[0]*dims[1]; std::vector indeximage; std::list palette = medianCut(bitmap.GetDataElement(), numPoints, maxcolor, indeximage); size_t ncolors = palette.size(); LookupTable & lut = bitmap.GetLUT(); lut.Clear(); lut.Allocate( 8 ); std::vector< unsigned char > buffer[3]; for( int i = 0; i < 3; ++i ) buffer[i].reserve( ncolors ); std::list::const_iterator it = palette.begin(); for( ; it != palette.end(); ++it ) { Point const & p = *it; for( int i = 0; i < 3; ++i ) buffer[i].push_back( p.x[i] ); } 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 ); } bitmap.GetDataElement().SetByteValue( (char*)&indeximage[0], (uint32_t)indeximage.size() ); assert( lut.Initialized() ); } void IconImageGenerator::SetOutsideValuePixel(double v) { if( Internals->AutoMinMax ) { Internals->UseOutsideValuePixel = true; Internals->OutsideValuePixel = v; } } void IconImageGenerator::AutoPixelMinMax(bool b) { if( b ) { Internals->UseMinMax = false; Internals->AutoMinMax = true; } } void IconImageGenerator::SetPixelMinMax(double min, double max) { Internals->Min = min; Internals->Max = max; Internals->UseMinMax = true; Internals->AutoMinMax = false; } template void ComputeMinMax( const TPixelType *p, size_t npixels , double & min, double &max, double discardvalue) { assert( npixels ); const TPixelType discard = (TPixelType)discardvalue; assert( (double)discard == discardvalue ); TPixelType lmin = std::numeric_limits< TPixelType>::max(); TPixelType lmax = std::numeric_limits< TPixelType>::min(); for( size_t i = 0; i < npixels; ++i ) { if( p[i] < lmin && p[i] != discard ) { lmin = p[i]; } else if( p[i] > lmax /* && p[i] != discard */ ) { lmax = p[i]; } } //assert( lmin != std::numeric_limits< TPixelType>::max() ); //assert( lmax != std::numeric_limits< TPixelType>::min() ); // what if lmin == lmax == 0 for example: // let's fake a slightly different min/max found: if( lmin == lmax ) { if( lmax == std::numeric_limits::max() ) { lmin--; assert( lmin + 1 > lmin ); } else { lmax++; } } min = lmin; max = lmax; // std::cout << min << " " << max << std::endl; } template void ComputeMinMax( const TPixelType *p, size_t npixels , double & min, double &max) { assert( npixels ); TPixelType lmin = std::numeric_limits< TPixelType>::max(); TPixelType lmax = std::numeric_limits< TPixelType>::min(); for( size_t i = 0; i < npixels; ++i ) { if( p[i] < lmin ) { lmin = p[i]; } else if( p[i] > lmax ) { lmax = p[i]; } } //assert( lmin != std::numeric_limits< TPixelType>::max() ); //assert( lmax != std::numeric_limits< TPixelType>::min() ); // what if lmin == lmax == 0 for example: // let's fake a slightly different min/max found: if( lmin == lmax ) { if( lmax == std::numeric_limits::max() ) { lmin--; assert( lmin + 1 > lmin ); } else { lmax++; } } min = lmin; max = lmax; // std::cout << min << " " << max << std::endl; } bool IconImageGenerator::Generate() { /* PS 3.3-2009 F.7 ICON IMAGE KEY DEFINITION a. Only monochrome and palette color images shall be used. Samples per Pixel (0028,0002) shall have a Value of 1, Photometric Interpretation (0028,0004) shall have a Value of either MONOCHROME 1, MONOCHROME 2 or PALETTE COLOR, Planar Configuration (0028,0006) shall not be present Note: True color icon images are not supported. This is due to the fact that the reduced size of the Icon Image makes the quality of a palette color image (with 256 colors) sufficient in most cases. This simplifies the handling of Icon Images by File-set Readers and File-set Updaters. b. If an FSR/FSU supports Icons (i.e. does not ignore them) then it shall support at least a maximum size of 64 by 64 Icons. An FSC may write Icons of any size. Icons larger than 64 by 64 may be ignored by FSRs and FSUs unless specialized by Application Profiles c. Pixel samples have a Value of either 1 or 8 for Bits Allocated (0028,0100) and Bits Stored (0028,0101). High Bit (0028,0102) shall have a Value of one less than the Value used in Bit Stored d. Pixel Representation (0028,0103) shall used an unsigned integer representation (Value 0000H) e. Pixel Aspect Ratio (0028,0034) shall have a Value of 1:1 f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall be used */ I->Clear(); I->SetNumberOfDimensions(2); I->SetDimension(0, Internals->dims[0] ); I->SetDimension(1, Internals->dims[1] ); PixelFormat oripf = P->GetPixelFormat(); if( P->GetPhotometricInterpretation() != PhotometricInterpretation::MONOCHROME1 && P->GetPhotometricInterpretation() != PhotometricInterpretation::MONOCHROME2 && P->GetPhotometricInterpretation() != PhotometricInterpretation::PALETTE_COLOR && P->GetPhotometricInterpretation() != PhotometricInterpretation::RGB && P->GetPhotometricInterpretation() != PhotometricInterpretation::YBR_FULL && P->GetPhotometricInterpretation() != PhotometricInterpretation::YBR_FULL_422 && P->GetPhotometricInterpretation() != PhotometricInterpretation::YBR_RCT && P->GetPhotometricInterpretation() != PhotometricInterpretation::YBR_ICT ) { gdcmErrorMacro( "PhotometricInterpretation is not supported: " << P->GetPhotometricInterpretation() ); return false; } if( P->GetPhotometricInterpretation() == PhotometricInterpretation::RGB || P->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL || P->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL_422 || P->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_RCT || P->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_ICT ) { if( Internals->ConvertRGBToPaletteColor ) { I->SetPhotometricInterpretation( PhotometricInterpretation::PALETTE_COLOR ); } else { I->SetPhotometricInterpretation( PhotometricInterpretation::RGB ); } } else { I->SetPhotometricInterpretation( P->GetPhotometricInterpretation() ); assert( I->GetPhotometricInterpretation() == PhotometricInterpretation::MONOCHROME1 || I->GetPhotometricInterpretation() == PhotometricInterpretation::MONOCHROME2 || I->GetPhotometricInterpretation() == PhotometricInterpretation::PALETTE_COLOR ); if( !Internals->ConvertRGBToPaletteColor && P->GetPhotometricInterpretation() == PhotometricInterpretation::PALETTE_COLOR ) { I->SetPhotometricInterpretation( PhotometricInterpretation::RGB ); } } assert( I->GetPlanarConfiguration() == 0 ); // FIXME we should not retrieve the whole image, ideally we only need a // single 2D frame std::vector< char > vbuffer; size_t framelen = P->GetBufferLength(); if( P->GetNumberOfDimensions() == 3 ) { const unsigned int *dims = P->GetDimensions(); assert( framelen % dims[2] == 0 ); framelen /= dims[2]; } vbuffer.resize( P->GetBufferLength() ); char *buffer = &vbuffer[0]; bool boolean = P->GetBuffer(buffer); if( !boolean ) return false; // truncate to the size of a single frame: vbuffer.resize( framelen ); // Important: After call to GetBuffer() in case we have a 12bits stored image I->SetPixelFormat( P->GetPixelFormat() ); DataElement& pixeldata = I->GetDataElement(); std::vector< char > vbuffer2; vbuffer2.resize( I->GetBufferLength() ); uint8_t ps = I->GetPixelFormat().GetPixelSize(); char *iconb = &vbuffer2[0]; char *imgb = &vbuffer[0]; const unsigned int *imgdims = P->GetDimensions(); const unsigned int stepi = imgdims[0] / Internals->dims[0]; const unsigned int stepj = imgdims[1] / Internals->dims[1]; // Let's cherry-pick pixel from the input image. The nice thing about this approach // is that this also works for palletized image. // In the future it would be nice to also support averaging a group of pixel, instead // of always picking the top-left pixel from the block. for(unsigned int i = 0; i < Internals->dims[1]; ++i ) for(unsigned int j = 0; j < Internals->dims[0]; ++j ) { assert( (i * Internals->dims[0] + j) * ps < I->GetBufferLength() ); assert( (i * imgdims[0] * stepj + j * stepi) * ps < framelen /*P->GetBufferLength()*/ ); memcpy(iconb + (i * Internals->dims[0] + j) * ps, imgb + (i * imgdims[0] * stepj + j * stepi) * ps, ps ); } // Apply LUT if( P->GetPhotometricInterpretation() == PhotometricInterpretation::PALETTE_COLOR ) { std::string tempvbuf(&vbuffer2[0], vbuffer2.size()); std::istringstream is( tempvbuf ); std::stringstream ss; P->GetLUT().Decode( is, ss ); if( I->GetPixelFormat().GetBitsAllocated() == 16 ) { //assert( I->GetPixelFormat().GetPixelRepresentation() == 0 ); std::string s = ss.str(); Rescaler r; r.SetPixelFormat( I->GetPixelFormat() ); //r.SetPixelFormat( PixelFormat::UINT16 ); // FIXME: This is not accurate. We should either: // - Read the value from window/level to get better min,max value // - iterate over all possible value to find the min,max as we are looping // over all values anyway const double min = 0; // oripf.GetMin(); const double max = 65536 - 1; //oripf.GetMax(); r.SetSlope( 255. / (max - min + 0) ); // UINT8_MAX const double step = min * r.GetSlope(); r.SetIntercept( 0 - step ); // paranoid self check: assert( r.GetIntercept() + r.GetSlope() * min == 0. ); assert( r.GetIntercept() + r.GetSlope() * max == 255. ); r.SetTargetPixelType( PixelFormat::UINT8 ); r.SetUseTargetPixelType(true); std::vector v8; v8.resize( Internals->dims[0] * Internals->dims[1] * 3 ); if( !r.Rescale(&v8[0],&s[0],s.size()) ) { assert( 0 ); // should not happen in real life gdcmErrorMacro( "Problem in the rescaler" ); return false; } if( Internals->ConvertRGBToPaletteColor ) { LookupTable &lut = I->GetLUT(); lut.Allocate(); // re-encode: std::stringstream ss2; ss2.str( std::string( &v8[0], 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() ); BuildLUT( *I, 256 ); } else { I->SetPixelFormat( PixelFormat::UINT8 ); I->GetPixelFormat().SetSamplesPerPixel( 3 ); pixeldata.SetByteValue( &v8[0], (uint32_t)v8.size() ); } } else { assert( I->GetPixelFormat() == PixelFormat::UINT8 ); std::string s = ss.str(); if( Internals->ConvertRGBToPaletteColor ) { LookupTable &lut = I->GetLUT(); lut.Allocate(); // As per standard, we only support 8bits icon I->SetPixelFormat( PixelFormat::UINT8 ); pixeldata.SetByteValue( &s[0], (uint32_t)s.size() ); BuildLUT(*I, 256 ); } else { I->SetPixelFormat( PixelFormat::UINT8 ); I->GetPixelFormat().SetSamplesPerPixel( 3 ); pixeldata.SetByteValue( &s[0], (uint32_t)s.size() ); } } } else if( P->GetPhotometricInterpretation() == PhotometricInterpretation::RGB || P->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL || P->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL_422 || P->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_ICT || P->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_RCT ) { std::string tempvbuf( &vbuffer2[0], 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_out = ybr; unsigned char *ybr_end = ybr + vbuffer2.size(); int R, G, B; for( ; ybr != ybr_end; ) { unsigned char a = (unsigned char)(*ybr); ++ybr; unsigned char b = (unsigned char)(*ybr); ++ybr; unsigned char c = (unsigned char)(*ybr); ++ybr; R = 38142 *(a-16) + 52298 *(c -128); G = 38142 *(a-16) - 26640 *(c -128) - 12845 *(b -128); B = 38142 *(a-16) + 66093 *(b -128); R = (R+16384)>>15; G = (G+16384)>>15; B = (B+16384)>>15; if (R < 0) R = 0; if (G < 0) G = 0; if (B < 0) B = 0; if (R > 255) R = 255; if (G > 255) G = 255; if (B > 255) B = 255; *ybr_out = (unsigned char)R; ++ybr_out; *ybr_out = (unsigned char)G; ++ybr_out; *ybr_out = (unsigned char)B; ++ybr_out; } #if 0 std::ofstream d( "/tmp/d.rgb", std::ios::binary ); d.write( &tempvbuf[0], tempvbuf.size() ); d.close(); #endif assert( ybr_out == ybr_end ); } else // ( P->GetPlanarConfiguration() == 1 ) { std::string tempvbufybr = tempvbuf; unsigned char *ybr = (unsigned char*)&tempvbufybr[0]; unsigned char *ybr_end = ybr + vbuffer2.size(); assert( vbuffer2.size() % 3 == 0 ); size_t ybrl = vbuffer2.size() / 3; unsigned char *ybra = ybr + 0 * ybrl; unsigned char *ybrb = ybr + 1 * ybrl; unsigned char *ybrc = ybr + 2 * ybrl; unsigned char *ybr_out = (unsigned char*)&tempvbuf[0]; unsigned char *ybr_out_end = ybr_out + vbuffer2.size(); int R, G, B; for( ; ybr_out != ybr_out_end; ) { unsigned char a = (unsigned char)(*ybra); ++ybra; unsigned char b = (unsigned char)(*ybrb); ++ybrb; unsigned char c = (unsigned char)(*ybrc); ++ybrc; R = 38142 *(a-16) + 52298 *(c -128); G = 38142 *(a-16) - 26640 *(c -128) - 12845 *(b -128); B = 38142 *(a-16) + 66093 *(b -128); R = (R+16384)>>15; G = (G+16384)>>15; B = (B+16384)>>15; if (R < 0) R = 0; if (G < 0) G = 0; if (B < 0) B = 0; if (R > 255) R = 255; if (G > 255) G = 255; if (B > 255) B = 255; *ybr_out = (unsigned char)R; ++ybr_out; *ybr_out = (unsigned char)G; ++ybr_out; *ybr_out = (unsigned char)B; ++ybr_out; } assert( ybra + 2 * ybrl == ybr_end ); (void)ybr_end; assert( ybrb + 1 * ybrl == ybr_end ); assert( ybrc + 0 * ybrl == ybr_end ); } } else { if( P->GetPlanarConfiguration() == 1 ) { assert( I->GetPixelFormat() == PixelFormat::UINT8 ); std::string tempvbufrgb = tempvbuf; unsigned char *rgb = (unsigned char*)&tempvbufrgb[0]; unsigned char *rgb_end = rgb + vbuffer2.size(); assert( vbuffer2.size() % 3 == 0 ); size_t rgbl = vbuffer2.size() / 3; unsigned char *rgba = rgb + 0 * rgbl; unsigned char *rgbb = rgb + 1 * rgbl; unsigned char *rgbc = rgb + 2 * rgbl; unsigned char *rgb_out = (unsigned char*)&tempvbuf[0]; unsigned char *rgb_out_end = rgb_out + vbuffer2.size(); for( ; rgb_out != rgb_out_end; ) { unsigned char a = (unsigned char)(*rgba); ++rgba; unsigned char b = (unsigned char)(*rgbb); ++rgbb; unsigned char c = (unsigned char)(*rgbc); ++rgbc; *rgb_out = a; ++rgb_out; *rgb_out = b; ++rgb_out; *rgb_out = c; ++rgb_out; } assert( rgba + 2 * rgbl == rgb_end ); (void)rgb_end; assert( rgbb + 1 * rgbl == rgb_end ); assert( rgbc + 0 * rgbl == rgb_end ); } } std::istringstream is( tempvbuf ); if( I->GetPixelFormat() == PixelFormat::UINT8 ) { std::string s = is.str(); if( Internals->ConvertRGBToPaletteColor ) { // As per standard, we only support 8bits icon I->SetPixelFormat( PixelFormat::UINT8 ); pixeldata.SetByteValue( &s[0], (uint32_t)s.size() ); BuildLUT(*I, 256 ); } else { I->SetPixelFormat( PixelFormat::UINT8 ); I->GetPixelFormat().SetSamplesPerPixel( 3 ); pixeldata.SetByteValue( &s[0], (uint32_t)s.size() ); } } else { assert( I->GetPixelFormat() == PixelFormat::UINT16 ); assert( I->GetPixelFormat().GetPixelRepresentation() == 0 ); std::string s = is.str(); Rescaler r; r.SetPixelFormat( I->GetPixelFormat() ); //r.SetPixelFormat( PixelFormat::UINT16 ); // FIXME: This is not accurate. We should either: // - Read the value from window/level to get better min,max value // - iterate over all possible value to find the min,max as we are looping // over all values anyway const double min = 0; // oripf.GetMin(); const double max = 65536 - 1; //oripf.GetMax(); r.SetSlope( 255. / (max - min + 0) ); // UINT8_MAX const double step = min * r.GetSlope(); r.SetIntercept( 0 - step ); // paranoid self check: assert( r.GetIntercept() + r.GetSlope() * min == 0. ); assert( r.GetIntercept() + r.GetSlope() * max == 255. ); r.SetTargetPixelType( PixelFormat::UINT8 ); r.SetUseTargetPixelType(true); std::vector v8; v8.resize( Internals->dims[0] * Internals->dims[1] * 3 ); if( !r.Rescale(&v8[0],&s[0],s.size()) ) { assert( 0 ); // should not happen in real life gdcmErrorMacro( "Problem in the rescaler" ); return false; } if( Internals->ConvertRGBToPaletteColor ) { LookupTable &lut = I->GetLUT(); lut.Allocate(); I->SetPixelFormat( PixelFormat::UINT8 ); pixeldata.SetByteValue( &v8[0], (uint32_t)v8.size() ); BuildLUT(*I, 256 ); } else { I->SetPixelFormat( PixelFormat::UINT8 ); I->GetPixelFormat().SetSamplesPerPixel( 3 ); pixeldata.SetByteValue( &v8[0], (uint32_t)v8.size() ); } } } else { // MONOCHROME1 / MONOCHROME2 ... char *buffer2 = &vbuffer2[0]; pixeldata.SetByteValue( buffer2, (uint32_t)vbuffer2.size() ); Rescaler r; r.SetPixelFormat( I->GetPixelFormat() ); // FIXME: This is not accurate. We should either: // - Read the value from window/level to get better min,max value // - iterate over all possible value to find the min,max as we are looping // over all values anyway double min = (double)oripf.GetMin(); double max = (double)oripf.GetMax(); if( Internals->UseMinMax ) { min = Internals->Min; max = Internals->Max; } if( Internals->AutoMinMax ) { void *p = &vbuffer2[0]; size_t len = vbuffer2.size(); const PixelFormat &pf = I->GetPixelFormat(); assert( pf.GetSamplesPerPixel() == 1 ); if( Internals->UseOutsideValuePixel ) { const double d = Internals->OutsideValuePixel; switch ( pf.GetScalarType() ) { case PixelFormat::UINT8: ComputeMinMax( (const uint8_t*)p, len / sizeof( uint8_t ), min, max, d); break; case PixelFormat::INT8: ComputeMinMax( (const int8_t*)p, len / sizeof( int8_t ), min, max, d); break; case PixelFormat::UINT16: ComputeMinMax( (const uint16_t*)p, len / sizeof( uint16_t ), min, max, d); break; case PixelFormat::INT16: ComputeMinMax( (const int16_t*)p, len / sizeof( int16_t ), min, max, d); break; default: assert( 0 ); // should not happen break; } // ok we have found the min value, we should now be able to replace all value 'd' with this min now: switch ( pf.GetScalarType() ) { case PixelFormat::UINT8: std::replace( (uint8_t*)p, (uint8_t*)p + len / sizeof( uint8_t ), (uint8_t)d, (uint8_t)min); break; case PixelFormat::INT8: std::replace( (int8_t*)p, (int8_t*)p + len / sizeof( int8_t ), (int8_t)d, (int8_t)min); break; case PixelFormat::UINT16: std::replace( (uint16_t*)p, (uint16_t*)p + len / sizeof( uint16_t ), (uint16_t)d, (uint16_t)min); break; case PixelFormat::INT16: std::replace( (int16_t*)p, (int16_t*)p + len / sizeof( int16_t ), (int16_t)d, (int16_t)min); break; default: assert( 0 ); // should not happen break; } } switch ( pf.GetScalarType() ) { case PixelFormat::UINT8: ComputeMinMax( (const uint8_t*)p, len / sizeof( uint8_t ), min, max); break; case PixelFormat::INT8: ComputeMinMax( (const int8_t*)p, len / sizeof( int8_t ), min, max); break; case PixelFormat::UINT16: ComputeMinMax( (const uint16_t*)p, len / sizeof( uint16_t ), min, max); break; case PixelFormat::INT16: ComputeMinMax( (const int16_t*)p, len / sizeof( int16_t ), min, max); break; default: assert( 0 ); // should not happen break; } } r.SetSlope( 255. / (max - min + 0) ); // UINT8_MAX const double step = min * r.GetSlope(); r.SetIntercept( 0 - step ); // paranoid self check: assert( (int)(0.5 + r.GetIntercept() + r.GetSlope() * min) == 0 ); assert( (int)(0.5 + r.GetIntercept() + r.GetSlope() * max) == 255 ); r.SetTargetPixelType( PixelFormat::UINT8 ); r.SetUseTargetPixelType(true); std::vector v8; v8.resize( Internals->dims[0] * Internals->dims[1] ); if( !r.Rescale(&v8[0],&vbuffer2[0],vbuffer2.size()) ) { assert( 0 ); // should not happen in real life gdcmErrorMacro( "Problem in the rescaler" ); return false; } // As per standard, we only support 8bits icon I->SetPixelFormat( PixelFormat::UINT8 ); pixeldata.SetByteValue( &v8[0], (uint32_t)v8.size() ); } // \postcondition if( !Internals->ConvertRGBToPaletteColor && I->GetPhotometricInterpretation() == PhotometricInterpretation::RGB ) { assert( I->GetPixelFormat().GetSamplesPerPixel() == 3 ); } else { assert( I->GetPixelFormat().GetSamplesPerPixel() == 1 ); } assert( I->GetPixelFormat().GetBitsAllocated() == 8 ); assert( I->GetPixelFormat().GetBitsStored() == 8 ); assert( I->GetPixelFormat().GetHighBit() == 7 ); assert( I->GetPixelFormat().GetPixelRepresentation() == 0 ); return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmIconImageGenerator.h000066400000000000000000000061401412732066400252210ustar00rootroot00000000000000/*========================================================================= 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 GDCMICONIMAGEGENERATOR_H #define GDCMICONIMAGEGENERATOR_H #include "gdcmPixmap.h" #include "gdcmIconImage.h" namespace gdcm { class IconImageGeneratorInternals; /** * \brief IconImageGenerator * \details This filter will generate a valid Icon from the Pixel Data element (an * instance of Pixmap). * To generate a valid Icon, one is only allowed the following Photometric * Interpretation: * - MONOCHROME1 * - MONOCHROME2 * - PALETTE_COLOR * * The Pixel Bits Allocated is restricted to 8bits, therefore 16 bits image * needs to be rescaled. By default the filter will use the full scalar range * of 16bits image to rescale to unsigned 8bits. * This may not be ideal for some situation, in which case the API * SetPixelMinMax can be used to overwrite the default min,max interval used. * * \see ImageReader */ class GDCM_EXPORT IconImageGenerator { public: IconImageGenerator(); ~IconImageGenerator(); /// Set/Get File void SetPixmap(const Pixmap& p) { P = p; } Pixmap &GetPixmap() { return *P; } const Pixmap &GetPixmap() const { return *P; } /// Set Target dimension of output Icon void SetOutputDimensions(const unsigned int dims[2]); /// Override default min/max to compute best rescale for 16bits -> 8bits /// downscale. Typically those value can be read from the SmallestImagePixelValue /// LargestImagePixelValue DICOM attribute. void SetPixelMinMax(double min, double max); /// Instead of explicitly specifying the min/max value for the rescale /// operation, let the internal mechanism compute the min/max of icon and /// rescale to best appropriate. void AutoPixelMinMax(bool b); /// Converting from RGB to PALETTE_COLOR can be a slow operation. However DICOM /// standard requires that color icon be described as palette. Set this boolean /// to false only if you understand the consequences. /// default value is true, false generates invalid Icon Image Sequence void ConvertRGBToPaletteColor(bool b); /// Set a pixel value that should be discarded. This happen typically for CT image, where /// a pixel has been used to pad outside the image (see Pixel Padding Value). /// Requires AutoPixelMinMax(true) void SetOutsideValuePixel(double v); /// Generate Icon bool Generate(); /// Retrieve generated Icon const IconImage& GetIconImage() const { return *I; } protected: private: void BuildLUT( Bitmap & bitmap, unsigned int maxcolor ); SmartPointer P; SmartPointer I; IconImageGeneratorInternals *Internals; }; } // end namespace gdcm #endif //GDCMICONIMAGEGENERATOR_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImage.cxx000066400000000000000000000101741412732066400231160ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImage.h" #include "gdcmTrace.h" #include "gdcmExplicitDataElement.h" #include "gdcmByteValue.h" #include "gdcmDataSet.h" #include "gdcmSequenceOfFragments.h" #include "gdcmFragment.h" #include #include namespace gdcm { const double *Image::GetSpacing() const { assert( NumberOfDimensions ); return &Spacing[0]; } double Image::GetSpacing(unsigned int idx) const { assert( NumberOfDimensions ); //if( idx < Spacing.size() ) { return Spacing[idx]; } //assert( 0 && "Should not happen" ); //return 1; // FIXME ??? } void Image::SetSpacing(const double *spacing) { assert( NumberOfDimensions ); Spacing.assign(spacing, spacing+NumberOfDimensions); } void Image::SetSpacing(unsigned int idx, double spacing) { //assert( spacing > 1.e3 ); Spacing.resize( 3 /*idx + 1*/ ); Spacing[idx] = spacing; } const double *Image::GetOrigin() const { assert( NumberOfDimensions ); if( !Origin.empty() ) return &Origin[0]; return nullptr; } double Image::GetOrigin(unsigned int idx) const { assert( NumberOfDimensions ); if( idx < Origin.size() ) { return Origin[idx]; } return 0; // FIXME ??? } void Image::SetOrigin(const float *ori) { assert( NumberOfDimensions ); Origin.resize( NumberOfDimensions ); for(unsigned int i = 0; i < NumberOfDimensions; ++i) { Origin[i] = static_cast(ori[i]); } } void Image::SetOrigin(const double *ori) { assert( NumberOfDimensions ); Origin.assign(ori, ori+NumberOfDimensions); } void Image::SetOrigin(unsigned int idx, double ori) { Origin.resize( idx + 1 ); Origin[idx] = ori; } const double *Image::GetDirectionCosines() const { assert( NumberOfDimensions ); if( !DirectionCosines.empty() ) return &DirectionCosines[0]; return nullptr; } double Image::GetDirectionCosines(unsigned int idx) const { assert( NumberOfDimensions ); if( idx < DirectionCosines.size() ) { return DirectionCosines[idx]; } return 0; // FIXME !! } void Image::SetDirectionCosines(const float *dircos) { assert( NumberOfDimensions ); DirectionCosines.resize( 6 ); for(int i = 0; i < 6; ++i) { DirectionCosines[i] = static_cast(dircos[i]); } } void Image::SetDirectionCosines(const double *dircos) { assert( NumberOfDimensions ); DirectionCosines.assign(dircos, dircos+6); } void Image::SetDirectionCosines(unsigned int idx, double dircos) { DirectionCosines.resize( idx + 1 ); DirectionCosines[idx] = dircos; } void Image::Print(std::ostream &os) const { Pixmap::Print(os); if( NumberOfDimensions ) { { os << "Origin: ("; if( !Origin.empty() ) { std::vector::const_iterator it = Origin.begin(); os << *it; for(++it; it != Origin.end(); ++it) { os << "," << *it; } } os << ")\n"; } { os << "Spacing: ("; std::vector::const_iterator it = Spacing.begin(); os << *it; for(++it; it != Spacing.end(); ++it) { os << "," << *it; } os << ")\n"; } { os << "DirectionCosines: ("; if( !DirectionCosines.empty() ) { std::vector::const_iterator it = DirectionCosines.begin(); os << *it; for(++it; it != DirectionCosines.end(); ++it) { os << "," << *it; } } os << ")\n"; } { os << "Rescale Intercept/Slope: (" << Intercept << "," << Slope << ")\n"; } //std::vector Spacing; //std::vector Origin; } } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImage.h000066400000000000000000000072551412732066400225510ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMAGE_H #define GDCMIMAGE_H #include "gdcmPixmap.h" #include namespace gdcm { /** * \brief Image * \details This is the container for an Image in the general sense. * From this container you should be able to request information like: * - Origin * - Dimension * - PixelFormat * ... * But also to retrieve the image as a raw buffer (char *) * Since we have to deal with both RAW data and JPEG stream (which * internally encode all the above information) this API might seems * redundant. One way to solve that would be to subclass Image * with JPEGImage which would from the stream extract the header info * and fill it to please Image...well except origin for instance * * Basically you can see it as a storage for the Pixel Data element (7fe0,0010). * * \warning This class does some heuristics to guess the Spacing but is not * compatible with DICOM CP-586. In case of doubt use PixmapReader instead * * \see ImageReader PixmapReader */ class GDCM_EXPORT Image : public Pixmap { public: Image ():Spacing(),SC(),Intercept(0),Slope(1) { //DirectionCosines.resize(6); Origin.resize( 3 /*NumberOfDimensions*/ ); // fill with 0 DirectionCosines.resize( 6 ); // fill with 0 DirectionCosines[0] = 1; DirectionCosines[4] = 1; Spacing.resize( 3 /*NumberOfDimensions*/, 1 ); // fill with 1 } ~Image() override = default; /// Return a 3-tuples specifying the spacing /// NOTE: 3rd value can be an arbitrary 1 value when the spacing was not specified (ex. 2D image). /// WARNING: when the spacing is not specifier, a default value of 1 will be returned const double *GetSpacing() const; double GetSpacing(unsigned int idx) const; void SetSpacing(const double spacing[3]); void SetSpacing(unsigned int idx, double spacing); /// Return a 3-tuples specifying the origin /// Will return (0,0,0) if the origin was not specified. const double *GetOrigin() const; double GetOrigin(unsigned int idx) const; void SetOrigin(const float origin[3]); void SetOrigin(const double origin[3]); void SetOrigin(unsigned int idx, double ori); /// Return a 6-tuples specifying the direction cosines /// A default value of (1,0,0,0,1,0) will be return when the direction cosines was not specified. const double *GetDirectionCosines() const; double GetDirectionCosines(unsigned int idx) const; void SetDirectionCosines(const float dircos[6]); void SetDirectionCosines(const double dircos[6]); void SetDirectionCosines(unsigned int idx, double dircos); /// print void Print(std::ostream &os) const override; /// intercept void SetIntercept(double intercept) { Intercept = intercept; } double GetIntercept() const { return Intercept; } /// slope void SetSlope(double slope) { Slope = slope; } double GetSlope() const { return Slope; } private: std::vector Spacing; std::vector Origin; std::vector DirectionCosines; // I believe the following 3 ivars can be derived from TS ... SwapCode SC; double Intercept; double Slope; }; /** * \example DecompressImage.cs * This is a C# example on how to use Image */ } // end namespace gdcm #endif //GDCMIMAGE_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageApplyLookupTable.cxx000066400000000000000000000071011412732066400262620ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageApplyLookupTable.h" #include namespace gdcm { struct ImageApplyLookupTable::impl { bool rgb8; }; ImageApplyLookupTable::ImageApplyLookupTable():pimpl(new impl) { pimpl->rgb8 = false; } ImageApplyLookupTable::~ImageApplyLookupTable() { delete pimpl; } bool ImageApplyLookupTable::Apply() { Output = Input; const Bitmap &image = *Input; PhotometricInterpretation pi = image.GetPhotometricInterpretation(); if( pi != PhotometricInterpretation::PALETTE_COLOR ) { gdcmDebugMacro( "Image is not palettized" ); return false; } const LookupTable &lut = image.GetLUT(); int bitsample = lut.GetBitSample(); if( !bitsample ) return false; if( pimpl->rgb8 && !lut.IsRGB8() ) { gdcmDebugMacro( "LUT is not compatible with RGB8" ); return false; } const unsigned long len = image.GetBufferLength(); std::vector v; v.resize( len ); char *p = &v[0]; image.GetBuffer( p ); std::stringstream is; if( !is.write( p, len ) ) { gdcmErrorMacro( "Could not write to stringstream" ); return false; } DataElement &de = Output->GetDataElement(); #if 0 std::ostringstream os; lut.Decode(is, os); const std::string str = os.str(); VL::Type strSize = (VL::Type)str.size(); de.SetByteValue( str.c_str(), strSize); #else std::vector v2; v2.resize( len * 3 ); if( pimpl->rgb8 ) lut.Decode8(&v2[0], v2.size(), &v[0], v.size()); else lut.Decode(&v2[0], v2.size(), &v[0], v.size()); assert( v2.size() < (size_t)std::numeric_limits::max() ); if( pimpl->rgb8 ) de.SetByteValue( &v2[0], (uint32_t)v2.size() / 2); else de.SetByteValue( &v2[0], (uint32_t)v2.size() ); #endif Output->GetLUT().Clear(); Output->SetPhotometricInterpretation( PhotometricInterpretation::RGB ); Output->GetPixelFormat().SetSamplesPerPixel( 3 ); if( pimpl->rgb8 ) Output->GetPixelFormat().SetBitsAllocated(8); Output->SetPlanarConfiguration( 0 ); // FIXME OT-PAL-8-face.dcm has a PlanarConfiguration while being PALETTE COLOR... const TransferSyntax &ts = image.GetTransferSyntax(); //assert( ts == TransferSyntax::RLELossless ); if( ts.IsExplicit() ) { Output->SetTransferSyntax( TransferSyntax::ExplicitVRLittleEndian ); } else { assert( ts.IsImplicit() ); Output->SetTransferSyntax( TransferSyntax::ImplicitVRLittleEndian ); } // I do not have access to the DataSet: #if 0 { // usual tags: ds.Remove( Tag(0x0028, 0x1101) ); ds.Remove( Tag(0x0028, 0x1102) ); ds.Remove( Tag(0x0028, 0x1103) ); ds.Remove( Tag(0x0028, 0x1201) ); ds.Remove( Tag(0x0028, 0x1202) ); ds.Remove( Tag(0x0028, 0x1203) ); // Don't forget the segmented one: ds.Remove( Tag(0x0028, 0x1221) ); ds.Remove( Tag(0x0028, 0x1222) ); ds.Remove( Tag(0x0028, 0x1223) ); // PaletteColorLookupTableUID ?? ds.Remove( Tag(0x0028, 0x1199) ); } #endif bool success = true; return success; } void ImageApplyLookupTable::SetRGB8(bool b) { pimpl->rgb8 = b; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageApplyLookupTable.h000066400000000000000000000023051412732066400257100ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMAGEAPPLYLOOKUPTABLE_H #define GDCMIMAGEAPPLYLOOKUPTABLE_H #include "gdcmImageToImageFilter.h" namespace gdcm { class DataElement; /** * \brief ImageApplyLookupTable class * \details It applies the LUT the PixelData (only PALETTE_COLOR images) * Output will be a PhotometricInterpretation=RGB image */ class GDCM_EXPORT ImageApplyLookupTable : public ImageToImageFilter { public: ImageApplyLookupTable(); ~ImageApplyLookupTable(); /// Apply bool Apply(); /// RGB8 ? void SetRGB8(bool b); protected: private: struct impl; // PIMPL idiom impl* pimpl; }; } // end namespace gdcm #endif //GDCMIMAGEAPPLYLOOKUPTABLE_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageChangePhotometricInterpretation.cxx000066400000000000000000000236621412732066400314000ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageChangePhotometricInterpretation.h" #include "gdcmSequenceOfFragments.h" #include "gdcmSequenceOfItems.h" #include "gdcmFragment.h" #include "gdcmRAWCodec.h" namespace gdcm { /* * http://groups.google.com/group/comp.protocols.dicom/browse_thread/thread/10f91b14e3013a11 * http://groups.google.com/group/comp.protocols.dicom/browse_thread/thread/1190189387c1702c * http://groups.google.com/group/comp.protocols.dicom/browse_thread/thread/a9e118fbbf6dcc9f * http://forum.dcmtk.org/viewtopic.php?p=5441&sid=61ad1304edb31203c4136890ab651405 YBR_FULL as Photometric Interpretation is really the right thing to do. The problem is that the JPEG bitstream as such does not contain any indication of the color model - it just specifies that there are three samples per pixel. In theory it is well possible to apply baseline JPEG compression to RGB pixel data, although this is an unusual approach since YCbCr provides for better compression ratio at given image quality. A JFIF header would contain that information, but the JFIF header is neither required nor recommended in the DICOM JPEG bitstream. In the absence of that information, and with a JPEG compressed DICOM file where Photometric Interpretation is "RGB", the parser needs to decide whether the encoder did something unusual but legal and decompress the JPEG bitstream as RGB, or whether the encoder just failed to correctly encode the color model of the JPEG bitstream (which in my experience is in most cases the correct assumption) and ignore Photometric Interpretation (and thus incorrectly decode unusual but legal images). */ bool ImageChangePhotometricInterpretation::ChangeMonochrome() { // Ok let's give up on this one for now. // We would need to take care of Pixel Padding Value to actually be able to // invert the image without this information we potentially will be making // mistake. just like Largest Image Pixel Value and other would be wrong const Bitmap &image = *Input; PhotometricInterpretation pi = image.GetPhotometricInterpretation(); if( pi != PhotometricInterpretation::MONOCHROME1 && pi != PhotometricInterpretation::MONOCHROME2 ) return false; if( pi == PI ) { return true; } unsigned long len = image.GetBufferLength(); char *p = new char[len]; image.GetBuffer( p ); std::stringstream is; is.write( p, len ); delete[] p; //ImageCodec ic; RAWCodec ic; ic.SetPixelFormat(image.GetPixelFormat()); std::ostringstream os; ic.DoInvertMonochrome( is, os ); DataElement &de = Output->GetDataElement(); std::string str = os.str(); VL::Type strSize = (VL::Type)str.size(); de.SetByteValue( str.c_str(), strSize); //Output->GetLUT().Clear(); Output->SetPhotometricInterpretation( PI ); //Output->GetPixelFormat().SetSamplesPerPixel( 3 ); //Output->SetPlanarConfiguration( 0 ); // FIXME OT-PAL-8-face.dcm has a PlanarConfiguration while being PALETTE COLOR... //const TransferSyntax &ts = image.GetTransferSyntax(); ////assert( ts == TransferSyntax::RLELossless ); //if( ts.IsExplicit() ) // { // Output->SetTransferSyntax( TransferSyntax::ExplicitVRLittleEndian ); // } //else // { // assert( ts.IsImplicit() ); // Output->SetTransferSyntax( TransferSyntax::ImplicitVRLittleEndian ); // } bool success = true; return success; } bool ImageChangePhotometricInterpretation::ChangeYBR2RGB() { // Ok let's give up on this one for now. // We would need to take care of Pixel Padding Value to actually be able to // invert the image without this information we potentially will be making // mistake. just like Largest Image Pixel Value and other would be wrong const Bitmap &image = *Input; PhotometricInterpretation pi = image.GetPhotometricInterpretation(); //assert( pi == PhotometricInterpretation::MONOCHROME1 || pi == PhotometricInterpretation::MONOCHROME2 ); if( pi == PI ) { return true; } unsigned long len = image.GetBufferLength(); char *p8 = new char[len]; image.GetBuffer( p8 ); const PixelFormat &pf = image.GetPixelFormat(); if( image.GetPlanarConfiguration() != 0 ) return false; if( pf.GetSamplesPerPixel() != 3 || pf.GetPixelRepresentation() != 0 ) return false; if( pf.GetBitsAllocated() == 16 ) { unsigned short *p = (unsigned short*)p8; unsigned short rgb[3]; unsigned short ybr[3]; for( unsigned long i = 0; i < len / (3 * 2); ++i ) { ybr[0] = p[ 3 * i + 0]; ybr[1] = p[ 3 * i + 1]; ybr[2] = p[ 3 * i + 2]; YBR2RGB(rgb, ybr); p[ 3 * i + 0] = rgb[0]; p[ 3 * i + 1] = rgb[1]; p[ 3 * i + 2] = rgb[2]; } } else if( pf.GetBitsAllocated() == 8 ) { unsigned char *p = (unsigned char*)p8; unsigned char rgb[3]; unsigned char ybr[3]; for( unsigned long i = 0; i < len / 3; ++i ) { ybr[0] = p[ 3 * i + 0]; ybr[1] = p[ 3 * i + 1]; ybr[2] = p[ 3 * i + 2]; YBR2RGB(rgb, ybr); p[ 3 * i + 0] = rgb[0]; p[ 3 * i + 1] = rgb[1]; p[ 3 * i + 2] = rgb[2]; } } DataElement &de = Output->GetDataElement(); de.SetByteValue( p8, len); //Output->GetLUT().Clear(); Output->SetPhotometricInterpretation( PI ); //Output->GetPixelFormat().SetSamplesPerPixel( 3 ); //Output->SetPlanarConfiguration( 0 ); // FIXME OT-PAL-8-face.dcm has a PlanarConfiguration while being PALETTE COLOR... //const TransferSyntax &ts = image.GetTransferSyntax(); ////assert( ts == TransferSyntax::RLELossless ); //if( ts.IsExplicit() ) // { // Output->SetTransferSyntax( TransferSyntax::ExplicitVRLittleEndian ); // } //else // { // assert( ts.IsImplicit() ); // Output->SetTransferSyntax( TransferSyntax::ImplicitVRLittleEndian ); // } bool success = true; delete[] p8; return success; } bool ImageChangePhotometricInterpretation::ChangeRGB2YBR() { // Ok let's give up on this one for now. // We would need to take care of Pixel Padding Value to actually be able to // invert the image without this information we potentially will be making // mistake. just like Largest Image Pixel Value and other would be wrong const Bitmap &image = *Input; PhotometricInterpretation pi = image.GetPhotometricInterpretation(); //assert( pi == PhotometricInterpretation::MONOCHROME1 || pi == PhotometricInterpretation::MONOCHROME2 ); if( pi == PI ) { return true; } unsigned long len = image.GetBufferLength(); char *p8 = new char[len]; image.GetBuffer( p8 ); const PixelFormat &pf = image.GetPixelFormat(); if( image.GetPlanarConfiguration() != 0 ) return false; if( pf.GetSamplesPerPixel() != 3 || pf.GetPixelRepresentation() != 0 ) return false; if( pf.GetBitsAllocated() == 16 ) { unsigned short *p = (unsigned short*)p8; unsigned short rgb[3]; unsigned short ybr[3]; for( unsigned long i = 0; i < len / (3 * 2); ++i ) { rgb[0] = p[ 3 * i + 0]; rgb[1] = p[ 3 * i + 1]; rgb[2] = p[ 3 * i + 2]; RGB2YBR(ybr, rgb, pf.GetBitsStored()); p[ 3 * i + 0] = ybr[0]; p[ 3 * i + 1] = ybr[1]; p[ 3 * i + 2] = ybr[2]; } } else if( pf.GetBitsAllocated() == 8 ) { unsigned char *p = (unsigned char*)p8; unsigned char rgb[3]; unsigned char ybr[3]; for( unsigned long i = 0; i < len / 3; ++i ) { rgb[0] = p[ 3 * i + 0]; rgb[1] = p[ 3 * i + 1]; rgb[2] = p[ 3 * i + 2]; RGB2YBR(ybr, rgb, pf.GetBitsStored()); p[ 3 * i + 0] = ybr[0]; p[ 3 * i + 1] = ybr[1]; p[ 3 * i + 2] = ybr[2]; } } DataElement &de = Output->GetDataElement(); de.SetByteValue( p8, len); //Output->GetLUT().Clear(); Output->SetPhotometricInterpretation( PI ); //Output->GetPixelFormat().SetSamplesPerPixel( 3 ); //Output->SetPlanarConfiguration( 0 ); // FIXME OT-PAL-8-face.dcm has a PlanarConfiguration while being PALETTE COLOR... //const TransferSyntax &ts = image.GetTransferSyntax(); ////assert( ts == TransferSyntax::RLELossless ); //if( ts.IsExplicit() ) // { // Output->SetTransferSyntax( TransferSyntax::ExplicitVRLittleEndian ); // } //else // { // assert( ts.IsImplicit() ); // Output->SetTransferSyntax( TransferSyntax::ImplicitVRLittleEndian ); // } bool success = true; delete[] p8; return success; } bool ImageChangePhotometricInterpretation::Change() { // PS 3.3 - 2008 C.7.6.3.1.2 Photometric Interpretation Output = Input; if( PI == PhotometricInterpretation::YBR_FULL ) { if( Input->GetPhotometricInterpretation() != PhotometricInterpretation::RGB ) return false; /* In the case where Bits Allocated (0028,0100) has a value of 8 then the following equations convert between RGB and YCBCR Photometric Interpretation. Y = + .2990R + .5870G + .1140B CB = - .1687R - .3313G + .5000B + 128 CR = + .5000R - .4187G - .0813B + 128 Note: The above is based on CCIR Recommendation 601-2 dated 1990. */ return ChangeRGB2YBR(); } else if( PI == PhotometricInterpretation::RGB ) { if( Input->GetPhotometricInterpretation() != PhotometricInterpretation::YBR_FULL ) return false; /* octave: * B = [.2990,.5870,.1140;- .16874, - .33126, .5000; .5000, - .41869, - .08131] * inv(B) * 1.0000e+00 -3.6820e-05 1.4020e+00 * 1.0000e+00 -3.4411e-01 -7.1410e-01 * 1.0000e+00 1.7720e+00 -1.3458e-04 */ return ChangeYBR2RGB(); } else if( PI == PhotometricInterpretation::MONOCHROME1 || PI == PhotometricInterpretation::MONOCHROME2 ) { return ChangeMonochrome(); } //else return false; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageChangePhotometricInterpretation.h000066400000000000000000000073761412732066400310310ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMAGECHANGEPHOTOMETRICINTERPRETATION_H #define GDCMIMAGECHANGEPHOTOMETRICINTERPRETATION_H #include "gdcmImageToImageFilter.h" #include "gdcmPhotometricInterpretation.h" #include namespace gdcm { class DataElement; /** * \brief ImageChangePhotometricInterpretation class * \details Class to change the Photometric Interpretation of an input DICOM */ class GDCM_EXPORT ImageChangePhotometricInterpretation : public ImageToImageFilter { public: ImageChangePhotometricInterpretation():PI() {} ~ImageChangePhotometricInterpretation() = default; /// Set/Get requested PhotometricInterpretation void SetPhotometricInterpretation(PhotometricInterpretation const &pi) { PI = pi; } const PhotometricInterpretation &GetPhotometricInterpretation() const { return PI; } /// Change bool Change(); /// colorspace conversion (based on CCIR Recommendation 601-2) /// -> T.871 template static void RGB2YBR(T ybr[3], const T rgb[3], unsigned short storedbits = 8); template static void YBR2RGB(T rgb[3], const T ybr[3], unsigned short storedbits = 8); protected: bool ChangeMonochrome(); bool ChangeYBR2RGB(); bool ChangeRGB2YBR(); private: PhotometricInterpretation PI; }; template static inline int Round(T x) { return (int)(x+0.5); } template static inline T Clamp(int v) { assert( std::numeric_limits::min() == 0 ); return v < 0 ? 0 : (v > std::numeric_limits::max() ? std::numeric_limits::max() : v); } template void ImageChangePhotometricInterpretation::RGB2YBR(T ybr[3], const T rgb[3], unsigned short storedbits) { // Implementation details, since the equations from: // http://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.7.6.3.html#sect_C.7.6.3.1.2 // are rounded to the 4th decimal precision, prefer the exact equation from the original document at: // CCIR Recommendation 601-2, also found in T.871 (Section §7, page 4) const double R = rgb[0]; const double G = rgb[1]; const double B = rgb[2]; assert( storedbits <= sizeof(T) * 8 ); const int halffullscale = 1 << (storedbits - 1); const int Y = Round( 0.299 * R + 0.587 * G + 0.114 * B ); const int CB = Round((-0.299 * R - 0.587 * G + 0.886 * B)/1.772 + halffullscale); const int CR = Round(( 0.701 * R - 0.587 * G - 0.114 * B)/1.402 + halffullscale); ybr[0] = Clamp(Y ); ybr[1] = Clamp(CB); ybr[2] = Clamp(CR); } template void ImageChangePhotometricInterpretation::YBR2RGB(T rgb[3], const T ybr[3], unsigned short storedbits) { const double Y = ybr[0]; const double Cb = ybr[1]; const double Cr = ybr[2]; assert( storedbits <= sizeof(T) * 8 ); const int halffullscale = 1 << (storedbits - 1); const int R = Round(Y + 1.402 * (Cr-halffullscale) ); const int G = Round(Y -( 0.114 * 1.772 * (Cb-halffullscale) + 0.299 * 1.402 * (Cr-halffullscale))/0.587); const int B = Round(Y + 1.772 * (Cb-halffullscale) ); rgb[0] = Clamp(R); rgb[1] = Clamp(G); rgb[2] = Clamp(B); } } // end namespace gdcm #endif //GDCMIMAGECHANGEPHOTOMETRICINTERPRETATION_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageChangePlanarConfiguration.cxx000066400000000000000000000110041412732066400301030ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageChangePlanarConfiguration.h" #include "gdcmSequenceOfFragments.h" #include "gdcmSequenceOfItems.h" #include "gdcmFragment.h" namespace gdcm { /* * C.7.6.3.1.3 Planar Configuration * Note: Planar Configuration (0028,0006) is not meaningful when a compression transfer syntax is * used that involves reorganization of sample components in the compressed bit stream. In such * cases, since the Attribute is required to be sent, then an appropriate value to use may be * specified in the description of the Transfer Syntax in PS 3.5, though in all likelihood the value of * the Attribute will be ignored by the receiving implementation. */ bool ImageChangePlanarConfiguration::Change() { if( PlanarConfiguration != 0 && PlanarConfiguration != 1 ) return false; // seriously Output = Input; if( Input->GetPixelFormat().GetSamplesPerPixel() != 3 ) { return true; } assert( Input->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL || Input->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL_422 || Input->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_RCT || Input->GetPhotometricInterpretation() == PhotometricInterpretation::RGB ); if( Input->GetPlanarConfiguration() == PlanarConfiguration ) { return true; } const Bitmap &image = *Input; const unsigned int *dims = image.GetDimensions(); unsigned long len = image.GetBufferLength(); char *p = new char[len]; image.GetBuffer( p ); assert( len % 3 == 0 ); PixelFormat pf = Input->GetPixelFormat(); const size_t ps = pf.GetPixelSize(); const size_t framesize = dims[0] * dims[1] * ps; assert( framesize * dims[2] == len ); char *copy = new char[len]; size_t size = framesize / 3; if( PlanarConfiguration == 0 ) { for(unsigned int z = 0; z < dims[2]; ++z) { const char *frame = p + z * framesize; const void *r = frame + 0; const void *g = frame + size; const void *b = frame + size + size; void *framecopy = copy + z * framesize; if( pf.GetBitsAllocated() == 16 ) { ImageChangePlanarConfiguration::RGBPlanesToRGBPixels((uint16_t*)framecopy, (const uint16_t*)r, (const uint16_t*)g,(const uint16_t*)b, size/2 ); } else if( pf.GetBitsAllocated() == 8 ) { ImageChangePlanarConfiguration::RGBPlanesToRGBPixels((uint8_t*)framecopy, (const uint8_t*)r, (const uint8_t*)g, (const uint8_t*)b, size); } } } else // User requested to do PlanarConfiguration == 1 { assert( PlanarConfiguration == 1 ); for(unsigned int z = 0; z < dims[2]; ++z) { const void *frame = p + z * framesize; char *framecopy = copy + z * framesize; void *r = framecopy + 0; void *g = framecopy + size; void *b = framecopy + size + size; if( pf.GetBitsAllocated() == 16 ) { ImageChangePlanarConfiguration::RGBPixelsToRGBPlanes((uint16_t*)r, (uint16_t*)g, (uint16_t*)b, (const uint16_t*)frame, size/2); } else if( pf.GetBitsAllocated() == 8 ) { ImageChangePlanarConfiguration::RGBPixelsToRGBPlanes((uint8_t*)r, (uint8_t*)g, (uint8_t*)b, (const uint8_t*)frame, size); } } } delete[] p; DataElement &de = Output->GetDataElement(); de.SetByteValue( copy, (uint32_t)len ); delete[] copy; Output->SetPlanarConfiguration( PlanarConfiguration ); if( Input->GetTransferSyntax().IsImplicit() ) { assert( Output->GetTransferSyntax().IsImplicit() ); } else if( Input->GetTransferSyntax() == TransferSyntax::ExplicitVRBigEndian ) { Output->SetTransferSyntax( TransferSyntax::ExplicitVRBigEndian ); } else { Output->SetTransferSyntax( TransferSyntax::ExplicitVRLittleEndian ); } //assert( Output->GetTransferSyntax().IsRaw() ); assert( Output->GetPhotometricInterpretation() == Input->GetPhotometricInterpretation() ); return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageChangePlanarConfiguration.h000066400000000000000000000053231412732066400275370ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMAGECHANGEPLANARCONFIGURATION_H #define GDCMIMAGECHANGEPLANARCONFIGURATION_H #include "gdcmImageToImageFilter.h" namespace gdcm { class DataElement; /** * \brief ImageChangePlanarConfiguration class * \details Class to change the Planar configuration of an input DICOM * By default it will change into the more usual representation: PlanarConfiguration = 0 */ class GDCM_EXPORT ImageChangePlanarConfiguration : public ImageToImageFilter { public: ImageChangePlanarConfiguration():PlanarConfiguration(0) {} ~ImageChangePlanarConfiguration() = default; /// Set/Get requested PlanarConfigation void SetPlanarConfiguration(unsigned int pc) { PlanarConfiguration = pc; } unsigned int GetPlanarConfiguration() const { return PlanarConfiguration; } /// s is the size of one plane (r,g or b). Thus the output buffer needs to be at least 3*s bytes long /// s can be seen as the number of RGB pixels in the output template static size_t RGBPlanesToRGBPixels(T *out, const T *r, const T *g, const T *b, size_t s); /// Convert a regular RGB pixel image (R,G,B,R,G,B...) into a planar R,G,B image (R,R..,G,G...B,B) /// \warning this works on a frame basis, you need to loop over all frames in multiple frames /// image to apply this function template static size_t RGBPixelsToRGBPlanes(T *r, T *g, T *b, const T* rgb, size_t s); /// Change bool Change(); protected: private: unsigned int PlanarConfiguration; }; template size_t ImageChangePlanarConfiguration::RGBPlanesToRGBPixels(T *out, const T *r, const T *g, const T *b, size_t s) { T *pout = out; for(size_t i = 0; i < s; ++i ) { *pout++ = *r++; *pout++ = *g++; *pout++ = *b++; } assert( (size_t)(pout - out) == 3 * s ); return pout - out; } template size_t ImageChangePlanarConfiguration::RGBPixelsToRGBPlanes(T *r, T *g, T *b, const T *rgb, size_t s) { const T *prgb = rgb; for(size_t i = 0; i < s; ++i ) { *r++ = *prgb++; *g++ = *prgb++; *b++ = *prgb++; } assert( (size_t)(prgb - rgb) == 3 * s ); return prgb - rgb; } } // end namespace gdcm #endif //GDCMIMAGECHANGEPLANARCONFIGURATION_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageChangeTransferSyntax.cxx000066400000000000000000000476371412732066400271560ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageChangeTransferSyntax.h" #include "gdcmSequenceOfFragments.h" #include "gdcmSequenceOfItems.h" #include "gdcmFragment.h" #include "gdcmPixmap.h" #include "gdcmBitmap.h" #include "gdcmRAWCodec.h" #include "gdcmJPEGCodec.h" #include "gdcmJPEGLSCodec.h" #include "gdcmJPEG2000Codec.h" #include "gdcmRLECodec.h" namespace gdcm { /* bool ImageChangeTransferSyntax::TryRAWCodecIcon(const DataElement &pixelde) { unsigned long len = Input->GetIconImage().GetBufferLength(); //assert( len == pixelde.GetByteValue()->GetLength() ); const TransferSyntax &ts = GetTransferSyntax(); RAWCodec codec; if( codec.CanCode( ts ) ) { codec.SetDimensions( Input->GetIconImage().GetDimensions() ); codec.SetPlanarConfiguration( Input->GetIconImage().GetPlanarConfiguration() ); codec.SetPhotometricInterpretation( Input->GetIconImage().GetPhotometricInterpretation() ); codec.SetPixelFormat( Input->GetIconImage().GetPixelFormat() ); codec.SetNeedOverlayCleanup( Input->GetIconImage().AreOverlaysInPixelData() ); DataElement out; //bool r = codec.Code(Input->GetDataElement(), out); bool r = codec.Code(pixelde, out); DataElement &de = Output->GetIconImage().GetDataElement(); de.SetValue( out.GetValue() ); if( !r ) { return false; } return true; } return false; } */ void UpdatePhotometricInterpretation( Bitmap const &input, Bitmap &output ) { // when decompressing J2K, need to revert to proper photo inter in uncompressed TS: if( input.GetPhotometricInterpretation() == PhotometricInterpretation::YBR_RCT || input.GetPhotometricInterpretation() == PhotometricInterpretation::YBR_ICT ) { output.SetPhotometricInterpretation( PhotometricInterpretation::RGB ); } // when decompressing loss jpeg, need to revert to proper photo inter in uncompressed TS: if( input.GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL_422 ) { output.SetPhotometricInterpretation( PhotometricInterpretation::YBR_FULL ); } assert( output.GetPhotometricInterpretation() == PhotometricInterpretation::RGB || output.GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL || output.GetPhotometricInterpretation() == PhotometricInterpretation::MONOCHROME1 || output.GetPhotometricInterpretation() == PhotometricInterpretation::MONOCHROME2 || output.GetPhotometricInterpretation() == PhotometricInterpretation::ARGB || output.GetPhotometricInterpretation() == PhotometricInterpretation::PALETTE_COLOR ); // programmer error } bool ImageChangeTransferSyntax::TryRAWCodec(const DataElement &pixelde, Bitmap const &input, Bitmap &output) { unsigned long len = input.GetBufferLength(); (void)len; //assert( len == pixelde.GetByteValue()->GetLength() ); const TransferSyntax &ts = GetTransferSyntax(); RAWCodec codec; if( codec.CanCode( ts ) ) { codec.SetDimensions( input.GetDimensions() ); codec.SetPlanarConfiguration( input.GetPlanarConfiguration() ); codec.SetPhotometricInterpretation( input.GetPhotometricInterpretation() ); codec.SetPixelFormat( input.GetPixelFormat() ); codec.SetNeedOverlayCleanup( input.AreOverlaysInPixelData() || input.UnusedBitsPresentInPixelData() ); DataElement out; //bool r = codec.Code(input.GetDataElement(), out); bool r = codec.Code(pixelde, out); if( !r ) { return false; } DataElement &de = output.GetDataElement(); de.SetValue( out.GetValue() ); UpdatePhotometricInterpretation( input, output ); return true; } return false; } bool ImageChangeTransferSyntax::TryRLECodec(const DataElement &pixelde, Bitmap const &input, Bitmap &output) { unsigned long len = input.GetBufferLength(); (void)len; //assert( len == pixelde.GetByteValue()->GetLength() ); const TransferSyntax &ts = GetTransferSyntax(); RLECodec codec; if( codec.CanCode( ts ) ) { codec.SetDimensions( input.GetDimensions() ); codec.SetPlanarConfiguration( input.GetPlanarConfiguration() ); codec.SetPhotometricInterpretation( input.GetPhotometricInterpretation() ); codec.SetPixelFormat( input.GetPixelFormat() ); codec.SetNeedOverlayCleanup( input.AreOverlaysInPixelData() || input.UnusedBitsPresentInPixelData() ); DataElement out; //bool r = codec.Code(input.GetDataElement(), out); bool r = codec.Code(pixelde, out); if( !r ) { return false; } DataElement &de = output.GetDataElement(); de.SetValue( out.GetValue() ); UpdatePhotometricInterpretation( input, output ); if( input.GetPixelFormat().GetSamplesPerPixel() == 3 ) { if( input.GetPlanarConfiguration() == 0 ) { // http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_G.2.html // The use of separate segments implies that the Planar Configuration (0028,0006) will always be 1 for RLE compressed images. output.SetPlanarConfiguration(1); } } return true; } return false; } bool ImageChangeTransferSyntax::TryJPEGCodec(const DataElement &pixelde, Bitmap const &input, Bitmap &output) { unsigned long len = input.GetBufferLength(); (void)len; //assert( len == pixelde.GetByteValue()->GetLength() ); const TransferSyntax &ts = GetTransferSyntax(); JPEGCodec jpgcodec; // pass lossy/lossless flag: // JPEGCodec are easier to deal with since there is no dual transfer syntax // that can be both lossy and lossless: if( ts.IsLossy() ) { //assert( !ts.IsLossless() ); // I cannot do since since Try* functions are called with all TS, I could be receiving a JPEGLS TS... jpgcodec.SetLossless( false ); } ImageCodec *codec = &jpgcodec; JPEGCodec *usercodec = dynamic_cast(UserCodec); if( usercodec && usercodec->CanCode( ts ) ) { codec = usercodec; } if( codec->CanCode( ts ) ) { codec->SetDimensions( input.GetDimensions() ); // FIXME: GDCM always apply the planar configuration to 0... //if( input.GetPlanarConfiguration() ) // { // output.SetPlanarConfiguration( 0 ); // } codec->SetPlanarConfiguration( input.GetPlanarConfiguration() ); codec->SetPhotometricInterpretation( input.GetPhotometricInterpretation() ); codec->SetPixelFormat( input.GetPixelFormat() ); codec->SetNeedOverlayCleanup( input.AreOverlaysInPixelData() || input.UnusedBitsPresentInPixelData() ); // let's check we are not trying to compress 16bits with JPEG/Lossy/8bits if( !input.GetPixelFormat().IsCompatible( ts ) ) { gdcmErrorMacro("Pixel Format incompatible with TS" ); return false; } DataElement out; //bool r = codec.Code(input.GetDataElement(), out); bool r = codec->Code(pixelde, out); // FIXME: this is not the best place to change the Output image internal type, // but since I know IJG is always applying the Planar Configuration, it does make // any sense to EVER produce a JPEG image where the Planar Configuration would be one // so let's be nice and actually sync JPEG configuration with DICOM Planar Conf. output.SetPlanarConfiguration( 0 ); //output.SetPhotometricInterpretation( PhotometricInterpretation::RGB ); // Indeed one cannot produce a true lossless RGB image according to DICOM standard // when doing lossless jpeg: if( output.GetPhotometricInterpretation() == PhotometricInterpretation::RGB ) { gdcmWarningMacro( "Technically this is not defined in the standard. \n" "Some validator may complains this image is invalid, but would be wrong."); } // PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm if( !r ) { return false; } DataElement &de = output.GetDataElement(); de.SetValue( out.GetValue() ); UpdatePhotometricInterpretation( input, output ); // When compressing with JPEG I think planar should always be: //output.SetPlanarConfiguration(0); // FIXME ! This should be done all the time for all codec: // Did PI change or not ? if ( !output.GetPhotometricInterpretation().IsSameColorSpace( codec->GetPhotometricInterpretation() ) ) { // HACK //Image *i = (Image*)this; //i->SetPhotometricInterpretation( codec.GetPhotometricInterpretation() ); assert(0); } return true; } return false; } bool ImageChangeTransferSyntax::TryJPEGLSCodec(const DataElement &pixelde, Bitmap const &input, Bitmap &output) { unsigned long len = input.GetBufferLength(); (void)len; //assert( len == pixelde.GetByteValue()->GetLength() ); const TransferSyntax &ts = GetTransferSyntax(); JPEGLSCodec jlscodec; ImageCodec *codec = &jlscodec; JPEGLSCodec *usercodec = dynamic_cast(UserCodec); if( usercodec && usercodec->CanCode( ts ) ) { codec = usercodec; } if( codec->CanCode( ts ) ) { codec->SetDimensions( input.GetDimensions() ); codec->SetPixelFormat( input.GetPixelFormat() ); //codec.SetNumberOfDimensions( input.GetNumberOfDimensions() ); codec->SetPlanarConfiguration( input.GetPlanarConfiguration() ); codec->SetPhotometricInterpretation( input.GetPhotometricInterpretation() ); codec->SetNeedOverlayCleanup( input.AreOverlaysInPixelData() || input.UnusedBitsPresentInPixelData() ); DataElement out; //bool r = codec.Code(input.GetDataElement(), out); bool r; if( input.AreOverlaysInPixelData() || input.UnusedBitsPresentInPixelData() ) { ByteValue *bv = const_cast(pixelde.GetByteValue()); assert( bv ); gdcm::DataElement tmp; tmp.SetByteValue( bv->GetPointer(), bv->GetLength()); bv = const_cast(tmp.GetByteValue()); r = codec->CleanupUnusedBits((char*)bv->GetVoidPointer(), bv->GetLength()); if(!r) return false; r = codec->Code(tmp, out); } else { r = codec->Code(pixelde, out); } if(!r) return false; DataElement &de = output.GetDataElement(); de.SetValue( out.GetValue() ); UpdatePhotometricInterpretation( input, output ); if( input.GetPixelFormat().GetSamplesPerPixel() == 3 ) { if( input.GetPlanarConfiguration() == 0 ) { // http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_8.2.3.html#table_8.2.3-1 output.SetPlanarConfiguration(1); } } return r; } return false; } bool ImageChangeTransferSyntax::TryJPEG2000Codec(const DataElement &pixelde, Bitmap const &input, Bitmap &output) { unsigned long len = input.GetBufferLength(); (void)len; //assert( len == pixelde.GetByteValue()->GetLength() ); const TransferSyntax &ts = GetTransferSyntax(); JPEG2000Codec j2kcodec; ImageCodec *codec = &j2kcodec; JPEG2000Codec *usercodec = dynamic_cast(UserCodec); if( usercodec && usercodec->CanCode( ts ) ) { codec = usercodec; } if( codec->CanCode( ts ) ) { codec->SetDimensions( input.GetDimensions() ); codec->SetPixelFormat( input.GetPixelFormat() ); codec->SetNumberOfDimensions( input.GetNumberOfDimensions() ); codec->SetPlanarConfiguration( input.GetPlanarConfiguration() ); codec->SetPhotometricInterpretation( input.GetPhotometricInterpretation() ); codec->SetNeedOverlayCleanup( input.AreOverlaysInPixelData() || input.UnusedBitsPresentInPixelData() ); DataElement out; //bool r = codec.Code(input.GetDataElement(), out); bool r = codec->Code(pixelde, out); // The value of Planar Configuration (0028,0006) is irrelevant since the // manner of encoding components is specified in the JPEG 2000 standard, // hence it shall be set to 0. output.SetPlanarConfiguration( 0 ); if( input.GetPixelFormat().GetSamplesPerPixel() == 3 ) { if( input.GetPhotometricInterpretation().IsSameColorSpace( PhotometricInterpretation::RGB ) ) { if( ts == TransferSyntax::JPEG2000Lossless ) { output.SetPhotometricInterpretation( PhotometricInterpretation::YBR_RCT ); } else { assert( ts == TransferSyntax::JPEG2000 ); output.SetPhotometricInterpretation( PhotometricInterpretation::YBR_ICT ); } } else { assert( input.GetPhotometricInterpretation().IsSameColorSpace( PhotometricInterpretation::YBR_FULL ) ); if( ts == TransferSyntax::JPEG2000Lossless ) { output.SetPhotometricInterpretation( PhotometricInterpretation::YBR_FULL ); // Indeed one cannot produce a true lossless RGB image according to DICOM standard gdcmWarningMacro( "Technically this is not defined in the standard. \n" "Some validator may complains this image is invalid, but would be wrong."); } else { assert( ts == TransferSyntax::JPEG2000 ); //output.SetPhotometricInterpretation( PhotometricInterpretation::YBR_ICT ); // FIXME: technically when doing lossy we could be standard compliant and first convert to // RGB THEN compress to YBR_ICT. For now produce improper j2k image output.SetPhotometricInterpretation( PhotometricInterpretation::YBR_FULL ); } } } else { assert( input.GetPixelFormat().GetSamplesPerPixel() == 1 ); } if( !r ) return false; DataElement &de = output.GetDataElement(); de.SetValue( out.GetValue() ); UpdatePhotometricInterpretation( input, output ); return r; } return false; } bool ImageChangeTransferSyntax::Change() { if( TS == TransferSyntax::TS_END ) { if( !Force ) return false; // When force option is set but no specific TransferSyntax has been set, only inspect the // encapsulated stream... // See ImageReader::Read if( Input->GetTransferSyntax().IsEncapsulated() && Input->GetTransferSyntax() != TransferSyntax::RLELossless ) { Output = Input; return true; } return false; } // let's get rid of some easy case: if( Input->GetPhotometricInterpretation() == PhotometricInterpretation::PALETTE_COLOR && TS.IsLossy() ) { gdcmErrorMacro( "PALETTE_COLOR and Lossy compression are impossible. Convert to RGB first." ); return false; } Output = Input; // if( TS.IsLossy() && !TS.IsLossless() ) // Output->SetLossyFlag( true ); // Fast path if( Input->GetTransferSyntax() == TS && !Force ) return true; // FIXME // For now only support raw input, otherwise we would need to first decompress them if( (Input->GetTransferSyntax() != TransferSyntax::ImplicitVRLittleEndian && Input->GetTransferSyntax() != TransferSyntax::ExplicitVRLittleEndian && Input->GetTransferSyntax() != TransferSyntax::ExplicitVRBigEndian) // YBR_FULL_422 / raw needs to be decompressed: || ( (Input->GetTransferSyntax() == TransferSyntax::ImplicitVRLittleEndian || Input->GetTransferSyntax() == TransferSyntax::ExplicitVRLittleEndian || Input->GetTransferSyntax() == TransferSyntax::ExplicitVRBigEndian) && Input->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL_422 ) || Force ) { // In memory decompression: DataElement pixeldata( Tag(0x7fe0,0x0010) ); ByteValue *bv0 = new ByteValue(); uint32_t len0 = (uint32_t)Input->GetBufferLength(); bv0->SetLength( len0 ); bool b = Input->GetBuffer( (char*)bv0->GetVoidPointer() ); if( !b ) { gdcmErrorMacro( "Error in getting buffer from input image." ); return false; } pixeldata.SetValue( *bv0 ); bool success = false; if( !success ) success = TryRAWCodec(pixeldata, *Input, *Output); if( !success ) success = TryJPEGCodec(pixeldata, *Input, *Output); if( !success ) success = TryJPEGLSCodec(pixeldata, *Input, *Output); if( !success ) success = TryJPEG2000Codec(pixeldata, *Input, *Output); if( !success ) success = TryRLECodec(pixeldata, *Input, *Output); Output->SetTransferSyntax( TS ); if( !success ) { //assert(0); return false; } // same goes for icon DataElement iconpixeldata( Tag(0x7fe0,0x0010) ); Bitmap &bitmap = *Input; if( Pixmap *pixmap = dynamic_cast( &bitmap ) ) { Bitmap &outbitmap = *Output; Pixmap *outpixmap = dynamic_cast( &outbitmap ); assert( outpixmap != nullptr ); if( !pixmap->GetIconImage().IsEmpty() ) { // same goes for icon ByteValue *bv = new ByteValue(); uint32_t len = (uint32_t)pixmap->GetIconImage().GetBufferLength(); bv->SetLength( len ); bool bb = pixmap->GetIconImage().GetBuffer( (char*)bv->GetVoidPointer() ); if( !bb ) { return false; } iconpixeldata.SetValue( *bv ); success = false; if( !success ) success = TryRAWCodec(iconpixeldata, pixmap->GetIconImage(), outpixmap->GetIconImage()); if( !success ) success = TryJPEGCodec(iconpixeldata, pixmap->GetIconImage(), outpixmap->GetIconImage()); if( !success ) success = TryJPEGLSCodec(iconpixeldata, pixmap->GetIconImage(), outpixmap->GetIconImage()); if( !success ) success = TryJPEG2000Codec(iconpixeldata, pixmap->GetIconImage(), outpixmap->GetIconImage()); if( !success ) success = TryRLECodec(iconpixeldata, pixmap->GetIconImage(), outpixmap->GetIconImage()); outpixmap->GetIconImage().SetTransferSyntax( TS ); if( !success ) { //assert(0); return false; } assert( outpixmap->GetIconImage().GetTransferSyntax() == TS ); } } //Output->ComputeLossyFlag(); assert( Output->GetTransferSyntax() == TS ); //if( TS.IsLossy() ) assert( Output->IsLossy() ); return success; } // too bad we actually have to do some work... bool success = false; if( !success ) success = TryRAWCodec(Input->GetDataElement(), *Input, *Output); if( !success ) success = TryJPEGCodec(Input->GetDataElement(), *Input, *Output); if( !success ) success = TryJPEG2000Codec(Input->GetDataElement(), *Input, *Output); if( !success ) success = TryJPEGLSCodec(Input->GetDataElement(), *Input, *Output); if( !success ) success = TryRLECodec(Input->GetDataElement(), *Input, *Output); Output->SetTransferSyntax( TS ); if( !success ) { //assert(0); return false; } Bitmap &bitmap = *Input; if( Pixmap *pixmap = dynamic_cast( &bitmap ) ) { if( !pixmap->GetIconImage().IsEmpty() && CompressIconImage ) { Bitmap &outbitmap = *Output; Pixmap *outpixmap = dynamic_cast( &outbitmap ); // same goes for icon success = false; if( !success ) success = TryRAWCodec(pixmap->GetIconImage().GetDataElement(), pixmap->GetIconImage(), outpixmap->GetIconImage()); if( !success ) success = TryJPEGCodec(pixmap->GetIconImage().GetDataElement(), pixmap->GetIconImage(), outpixmap->GetIconImage()); if( !success ) success = TryJPEGLSCodec(pixmap->GetIconImage().GetDataElement(), pixmap->GetIconImage(), outpixmap->GetIconImage()); if( !success ) success = TryJPEG2000Codec(pixmap->GetIconImage().GetDataElement(), pixmap->GetIconImage(), outpixmap->GetIconImage()); if( !success ) success = TryRLECodec(pixmap->GetIconImage().GetDataElement(), pixmap->GetIconImage(), outpixmap->GetIconImage()); outpixmap->GetIconImage().SetTransferSyntax( TS ); if( !success ) { //assert(0); return false; } assert( outpixmap->GetIconImage().GetTransferSyntax() == TS ); } } //Output->ComputeLossyFlag(); assert( Output->GetTransferSyntax() == TS ); return success; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageChangeTransferSyntax.h000066400000000000000000000064661412732066400265760ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMAGECHANGETRANSFERSYNTAX_H #define GDCMIMAGECHANGETRANSFERSYNTAX_H #include "gdcmImageToImageFilter.h" #include "gdcmTransferSyntax.h" namespace gdcm { class DataElement; class ImageCodec; /** * \brief ImageChangeTransferSyntax class * \details Class to change the transfer syntax of an input DICOM * * If only Force param is set but no input TransferSyntax is set, it is assumed * that user only wants to inspect encapsulated stream (advanced dev. option). * * When using UserCodec it is very important that the TransferSyntax (as set in * SetTransferSyntax) is actually understood by UserCodec (ie. * UserCodec->CanCode( TransferSyntax ) ). Otherwise the behavior is to use a * default codec. * * \sa JPEGCodec JPEGLSCodec JPEG2000Codec */ class GDCM_EXPORT ImageChangeTransferSyntax : public ImageToImageFilter { public: ImageChangeTransferSyntax():TS(TransferSyntax::TS_END),Force(false),CompressIconImage(false),UserCodec(nullptr) {} ~ImageChangeTransferSyntax() = default; /// Set target Transfer Syntax void SetTransferSyntax(const TransferSyntax &ts) { TS = ts; } /// Get Transfer Syntax const TransferSyntax &GetTransferSyntax() const { return TS; } /// Change bool Change(); /// Decide whether or not to also compress the Icon Image using the same /// Transfer Syntax. Default is to simply decompress icon image void SetCompressIconImage(bool b) { CompressIconImage = b; } /// When target Transfer Syntax is identical to input target syntax, no /// operation is actually done. /// This is an issue when someone wants to re-compress using GDCM internal /// implementation a JPEG (for example) image void SetForce( bool f ) { Force = f; } /// Allow user to specify exactly which codec to use. this is needed to /// specify special qualities or compression option. /// \warning if the codec 'ic' is not compatible with the TransferSyntax /// requested, it will not be used. It is the user responsibility to check /// that UserCodec->CanCode( TransferSyntax ) void SetUserCodec(ImageCodec *ic) { UserCodec = ic; } protected: bool TryJPEGCodec(const DataElement &pixelde, Bitmap const &input, Bitmap &output); bool TryJPEG2000Codec(const DataElement &pixelde, Bitmap const &input, Bitmap &output); bool TryJPEGLSCodec(const DataElement &pixelde, Bitmap const &input, Bitmap &output); bool TryRAWCodec(const DataElement &pixelde, Bitmap const &input, Bitmap &output); bool TryRLECodec(const DataElement &pixelde, Bitmap const &input, Bitmap &output); private: TransferSyntax TS; bool Force; bool CompressIconImage; ImageCodec *UserCodec; }; /** * \example StandardizeFiles.cs * This is a C++ example on how to use ImageChangeTransferSyntax */ } // end namespace gdcm #endif //GDCMIMAGECHANGETRANSFERSYNTAX_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageCodec.cxx000066400000000000000000000507311412732066400240570ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageCodec.h" #include "gdcmJPEGCodec.h" #include "gdcmByteSwap.txx" #include "gdcmImageChangePhotometricInterpretation.h" #include "gdcmTrace.h" #include #include #include #include #include namespace gdcm { class ImageInternals { public: }; ImageCodec::ImageCodec() { PlanarConfiguration = 0; RequestPlanarConfiguration = false; RequestPaddedCompositePixelCode = false; PI = PhotometricInterpretation::UNKNOWN; //LUT = LookupTable(LookupTable::UNKNOWN); LUT = new LookupTable; NeedByteSwap = false; NeedOverlayCleanup = false; Dimensions[0] = Dimensions[1] = Dimensions[2] = 0; NumberOfDimensions = 0; LossyFlag = false; } ImageCodec::~ImageCodec() = default; bool ImageCodec::GetHeaderInfo(std::istream &, TransferSyntax &) { // This function should really be virtual pure. assert( 0 ); return false; } void ImageCodec::SetLossyFlag(bool l) { LossyFlag = l; } bool ImageCodec::GetLossyFlag() const { return LossyFlag; } bool ImageCodec::IsLossy() const { return LossyFlag; } void ImageCodec::SetNumberOfDimensions(unsigned int dim) { NumberOfDimensions = dim; } unsigned int ImageCodec::GetNumberOfDimensions() const { return NumberOfDimensions; } const PhotometricInterpretation &ImageCodec::GetPhotometricInterpretation() const { return PI; } void ImageCodec::SetPhotometricInterpretation( PhotometricInterpretation const &pi) { PI = pi; } bool ImageCodec::DoByteSwap(std::istream &is, std::ostream &os) { // FIXME: Do some stupid work: std::streampos start = is.tellg(); assert( 0 - start == 0 ); is.seekg( 0, std::ios::end); size_t buf_size = (size_t)is.tellg(); //assert(buf_size < INT_MAX); char *dummy_buffer = new char[(unsigned int)buf_size]; is.seekg(start, std::ios::beg); is.read( dummy_buffer, buf_size); is.seekg(start, std::ios::beg); // reset //SwapCode sc = is.GetSwapCode(); assert( !(buf_size % 2) ); #ifdef GDCM_WORDS_BIGENDIAN if( PF.GetBitsAllocated() == 16 ) { ByteSwap::SwapRangeFromSwapCodeIntoSystem((uint16_t*) (void*)dummy_buffer, SwapCode::LittleEndian, buf_size/2); } #else // GE_DLX-8-MONO2-PrivateSyntax.dcm is 8bits // assert( PF.GetBitsAllocated() == 16 ); if ( PF.GetBitsAllocated() == 16 ) { ByteSwap::SwapRangeFromSwapCodeIntoSystem((uint16_t*) (void*)dummy_buffer, SwapCode::BigEndian, buf_size/2); } #endif os.write(dummy_buffer, buf_size); delete[] dummy_buffer; return true; } bool ImageCodec::DoYBR(std::istream &is, std::ostream &os) { // FIXME: Do some stupid work: std::streampos start = is.tellg(); assert( 0 - start == 0 ); is.seekg( 0, std::ios::end); size_t buf_size = (size_t)is.tellg(); //assert(buf_size < INT_MAX); char *dummy_buffer = new char[(unsigned int)buf_size]; is.seekg(start, std::ios::beg); is.read( dummy_buffer, buf_size); is.seekg(start, std::ios::beg); // reset //SwapCode sc = is.GetSwapCode(); // Code is coming from: // http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf assert( !(buf_size % 3) ); unsigned long size = (unsigned long)buf_size/3; //assert(buf_size < INT_MAX); unsigned char *copy = new unsigned char[ (unsigned int)buf_size ]; memmove( copy, dummy_buffer, (size_t)buf_size); assert(0); // Do not use this code ! // FIXME FIXME FIXME // The following is bogus: we are doing two operation at once: // Planar configuration AND YBR... doh ! 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); R = (R+16384)>>15; G = (G+16384)>>15; B = (B+16384)>>15; if (R < 0) R = 0; if (G < 0) G = 0; if (B < 0) B = 0; if (R > 255) R = 255; if (G > 255) G = 255; if (B > 255) B = 255; *(p++) = (unsigned char)R; *(p++) = (unsigned char)G; *(p++) = (unsigned char)B; a++; b++; c++; } delete[] copy; os.write(dummy_buffer, buf_size); delete[] dummy_buffer; return true; } bool ImageCodec::DoYBRFull422(std::istream &is, std::ostream &os) { // FIXME: Do some stupid work: std::streampos start = is.tellg(); assert( 0 - start == 0 ); is.seekg( 0, std::ios::end); const size_t buf_size = (size_t)is.tellg(); const size_t rgb_buf_size = buf_size * 3 / 2; unsigned char *dummy_buffer = new unsigned char[buf_size]; is.seekg(start, std::ios::beg); is.read( (char*)dummy_buffer, buf_size); is.seekg(start, std::ios::beg); // reset assert( !(rgb_buf_size % 3) ); assert( !(buf_size % 2) ); unsigned char *copy = new unsigned char[ rgb_buf_size ]; const size_t size = buf_size/4; for (size_t j = 0; j < size; ++j) { unsigned char ybr422[4]; ybr422[0] = dummy_buffer[4*j+0]; ybr422[1] = dummy_buffer[4*j+1]; ybr422[2] = dummy_buffer[4*j+2]; ybr422[3] = dummy_buffer[4*j+3]; #if 0 unsigned char ybr1[3]; unsigned char ybr2[3]; ybr1[0] = ybr422[0]; ybr1[1] = ybr422[2]; ybr1[2] = ybr422[3]; ybr2[0] = ybr422[1]; ybr2[1] = ybr422[2]; ybr2[2] = ybr422[3]; unsigned char rgb[6]; ImageChangePhotometricInterpretation::YBR2RGB(rgb + 0, ybr1); ImageChangePhotometricInterpretation::YBR2RGB(rgb + 3, ybr2); memcpy(copy + 6 * j, rgb, 6 ); #else unsigned char ybr[6]; // ybr1 + ybr2 ybr[0] = ybr422[0]; ybr[1] = ybr422[2]; ybr[2] = ybr422[3]; ybr[3] = ybr422[1]; ybr[4] = ybr422[2]; ybr[5] = ybr422[3]; memcpy(copy + 6 * j, ybr, 6 ); #endif } os.write((char*)copy, rgb_buf_size); delete[] copy; delete[] dummy_buffer; return true; } bool ImageCodec::DoPlanarConfiguration(std::istream &is, std::ostream &os) { // FIXME: Do some stupid work: std::streampos start = is.tellg(); assert( 0 - start == 0 ); is.seekg( 0, std::ios::end); size_t buf_size = (size_t)is.tellg(); //assert(buf_size < INT_MAX); char *dummy_buffer = new char[(unsigned int)buf_size]; is.seekg(start, std::ios::beg); is.read( dummy_buffer, buf_size); is.seekg(start, std::ios::beg); // reset //SwapCode sc = is.GetSwapCode(); // US-RGB-8-epicard.dcm //assert( image.GetNumberOfDimensions() == 3 ); assert( buf_size % 3 == 0 ); unsigned long size = (unsigned long)buf_size/3; char *copy = new char[ (unsigned int)buf_size ]; //memmove( copy, dummy_buffer, buf_size); const char *r = dummy_buffer /*copy*/; const char *g = dummy_buffer /*copy*/ + size; const char *b = dummy_buffer /*copy*/ + size + size; char *p = copy /*dummy_buffer*/; for (unsigned long j = 0; j < size; ++j) { *(p++) = *(r++); *(p++) = *(g++); *(p++) = *(b++); } delete[] dummy_buffer /*copy*/; os.write(copy /*dummy_buffer*/, buf_size); delete[] copy; return true; } bool ImageCodec::DoSimpleCopy(std::istream &is, std::ostream &os) { #if 1 std::streampos start = is.tellg(); assert( 0 - start == 0 ); is.seekg( 0, std::ios::end); size_t buf_size = (size_t)is.tellg(); //assert(buf_size < INT_MAX); char *dummy_buffer = new char[(unsigned int)buf_size]; is.seekg(start, std::ios::beg); is.read( dummy_buffer, buf_size); is.seekg(start, std::ios::beg); // reset os.write( dummy_buffer, buf_size); delete[] dummy_buffer ; #else // This code is ideal but is failing on an RLE image...need to figure out // what is wrong to reactivate this code. os.rdbuf( is.rdbuf() ); #endif return true; } bool ImageCodec::DoPaddedCompositePixelCode(std::istream &is, std::ostream &os) { // FIXME: Do some stupid work: std::streampos start = is.tellg(); assert( 0 - start == 0 ); is.seekg( 0, std::ios::end); size_t buf_size = (size_t)is.tellg(); //assert(buf_size < INT_MAX); char *dummy_buffer = new char[(unsigned int)buf_size]; is.seekg(start, std::ios::beg); is.read( dummy_buffer, buf_size); is.seekg(start, std::ios::beg); // reset //SwapCode sc = is.GetSwapCode(); assert( !(buf_size % 2) ); bool ret = true; if( GetPixelFormat().GetBitsAllocated() == 16 ) { for(size_t i = 0; i < buf_size/2; ++i) { #ifdef GDCM_WORDS_BIGENDIAN os.write( dummy_buffer+i, 1 ); os.write( dummy_buffer+i+buf_size/2, 1 ); #else os.write( dummy_buffer+i+buf_size/2, 1 ); os.write( dummy_buffer+i, 1 ); #endif } } else if( GetPixelFormat().GetBitsAllocated() == 32 ) { assert( !(buf_size % 4) ); for(size_t i = 0; i < buf_size/4; ++i) { #ifdef GDCM_WORDS_BIGENDIAN os.write( dummy_buffer+i, 1 ); os.write( dummy_buffer+i+1*buf_size/4, 1 ); os.write( dummy_buffer+i+2*buf_size/4, 1 ); os.write( dummy_buffer+i+3*buf_size/4, 1 ); #else os.write( dummy_buffer+i+3*buf_size/4, 1 ); os.write( dummy_buffer+i+2*buf_size/4, 1 ); os.write( dummy_buffer+i+1*buf_size/4, 1 ); os.write( dummy_buffer+i, 1 ); #endif } } else { ret = false; } delete[] dummy_buffer; return ret; } bool ImageCodec::DoInvertMonochrome(std::istream &is, std::ostream &os) { if ( PF.GetPixelRepresentation() ) { if ( PF.GetBitsAllocated() == 8 ) { uint8_t c; while( is.read((char*)&c,1) ) { c = (uint8_t)(255 - c); os.write((char*)&c, 1 ); } } else if ( PF.GetBitsAllocated() == 16 ) { assert( PF.GetBitsStored() != 12 ); uint16_t smask16 = 65535; uint16_t c; while( is.read((char*)&c,2) ) { c = (uint16_t)(smask16 - c); os.write((char*)&c, 2); } } } else { if ( PF.GetBitsAllocated() == 8 ) { uint8_t c; while( is.read((char*)&c,1) ) { c = (uint8_t)(255 - c); os.write((char*)&c, 1); } } else if ( PF.GetBitsAllocated() == 16 ) { uint16_t mask = 1; for (int j=0; j mask ) { // IMAGES/JPLY/RG3_JPLY aka CompressedSamples^RG3/1.3.6.1.4.1.5962.1.1.11.1.5.20040826185059.5457 // gdcmData/D_CLUNIE_RG3_JPLY.dcm // stores a 12bits JPEG stream with scalar value [0,1024], however // the DICOM header says the data are stored on 10bits [0,1023], thus this HACK: gdcmWarningMacro( "Bogus max value: "<< c << " max should be at most: " << mask << " results will be truncated. Use at own risk"); c = mask; } assert( c <= mask ); c = (uint16_t)(mask - c); assert( c <= mask ); os.write((char*)&c, 2); } } } return true; } struct ApplyMask { uint16_t operator()(uint16_t c) const { return (uint16_t)((c >> (BitsStored - HighBit - 1)) & pmask); } unsigned short BitsStored; unsigned short HighBit; uint16_t pmask; }; bool ImageCodec::CleanupUnusedBits(char * data8, size_t datalen) { if( !NeedOverlayCleanup ) return true; void * data = data8; assert( PF.GetBitsAllocated() > 8 ); if( PF.GetBitsAllocated() == 16 ) { // pmask : to mask the 'unused bits' (may contain overlays) uint16_t pmask = 0xffff; pmask = (uint16_t)(pmask >> ( PF.GetBitsAllocated() - PF.GetBitsStored() )); if( PF.GetPixelRepresentation() ) { // smask : to check the 'sign' when BitsStored != BitsAllocated uint16_t smask = 0x0001; 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 )); uint16_t *start = (uint16_t*)data; for( uint16_t *p = start ; p != start + datalen / 2; ++p ) { uint16_t c = *p; c = (uint16_t)(c >> (PF.GetBitsStored() - PF.GetHighBit() - 1)); if ( c & smask ) { c = (uint16_t)(c | nmask); } else { c = c & pmask; } *p = c; } } else // Pixel are unsigned { uint16_t *start = (uint16_t*)data; for( uint16_t *p = start ; p != start + datalen / 2; ++p ) { uint16_t c = *p; c = (uint16_t)( (c >> (PF.GetBitsStored() - PF.GetHighBit() - 1)) & pmask); *p = c; } } } else { assert(0); // TODO return false; } return true; } // Cleanup the unused bits bool ImageCodec::DoOverlayCleanup(std::istream &is, std::ostream &os) { assert( PF.GetBitsAllocated() > 8 ); if( PF.GetBitsAllocated() == 16 ) { // pmask : to mask the 'unused bits' (may contain overlays) uint16_t pmask = 0xffff; pmask = (uint16_t)(pmask >> ( PF.GetBitsAllocated() - PF.GetBitsStored() )); if( PF.GetPixelRepresentation() ) { // smask : to check the 'sign' when BitsStored != BitsAllocated uint16_t smask = 0x0001; 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 )); uint16_t c; while( is.read((char*)&c,2) ) { c = (uint16_t)(c >> (PF.GetBitsStored() - PF.GetHighBit() - 1)); if ( c & smask ) { c = (uint16_t)(c | nmask); } else { c = c & pmask; } os.write((char*)&c, 2 ); } } else // Pixel are unsigned { #if 1 // On Windows, is.read and os.write are expensive operations. // If we called it for each value then conversion would be extremely slow. // Therefore we read/mask/write 1000 values at once. const unsigned int bufferSize = 1000; std::vector buffer(bufferSize); while (is) { is.read((char *)&buffer[0], 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); } #else //std::ostreambuf_iterator end_of_stream_iterator; //std::ostreambuf_iterator out_iter(os.rdbuf()); //while( out_iter != end_of_stream_iterator ) // { // *out_iter = // (*out_iter >> (PF.GetBitsStored() - PF.GetHighBit() - 1)) & pmask; // } std::istreambuf_iterator it_in(is); std::istreambuf_iterator eos; std::ostreambuf_iterator it_out(os); ApplyMask am; am.BitsStored = PF.GetBitsStored(); am.HighBit = PF.GetHighBit(); am.pmask = pmask; std::transform(it_in, eos, it_out, am); #endif } } else { assert(0); // TODO return false; } return true; } bool ImageCodec::Decode(DataElement const &, DataElement &) { return true; } bool ImageCodec::DecodeByStreams(std::istream &is, std::ostream &os) { assert( PlanarConfiguration == 0 || PlanarConfiguration == 1); assert( PI != PhotometricInterpretation::UNKNOWN ); std::stringstream bs_os; // ByteSwap std::stringstream pcpc_os; // Padded Composite Pixel Code std::stringstream pi_os; // PhotometricInterpretation std::stringstream pl_os; // PlanarConf std::istream *cur_is = &is; // First thing do the byte swap: if( NeedByteSwap ) { // MR_GE_with_Private_Compressed_Icon_0009_1110.dcm DoByteSwap(*cur_is,bs_os); cur_is = &bs_os; } if ( RequestPaddedCompositePixelCode ) { // D_CLUNIE_CT2_RLE.dcm DoPaddedCompositePixelCode(*cur_is,pcpc_os); cur_is = &pcpc_os; } // Second thing do palette color. // This way PALETTE COLOR will be applied before we do // Planar Configuration switch(PI) { case PhotometricInterpretation::MONOCHROME2: case PhotometricInterpretation::RGB: case PhotometricInterpretation::ARGB: break; case PhotometricInterpretation::MONOCHROME1: // CR-MONO1-10-chest.dcm //DoInvertMonochrome(*cur_is, pi_os); //cur_is = &pi_os; break; case PhotometricInterpretation::YBR_FULL: //DoYBR(*cur_is,pi_os); //cur_is = &pi_os; { const JPEGCodec *c = dynamic_cast(this); if( c ) { // The following is required for very special case of color space conversion // dcmdrle ACUSON-24-YBR_FULL-RLE.dcm bla.dcm // dcmcjpeg bla.dcm foo.dcm // foo.dcm would be not displayed correctly //this->SetPhotometricInterpretation( PhotometricInterpretation::RGB ); } } break; case PhotometricInterpretation::PALETTE_COLOR: //assert( LUT ); // Nothing needs to be done break; case PhotometricInterpretation::YBR_FULL_422: { // US-GE-4AICL142.dcm // Hopefully it has been done by the JPEG decoder itself... const JPEGCodec *c = dynamic_cast(this); if( !c ) { //gdcmErrorMacro( "YBR_FULL_422 is not implemented in GDCM. Image will be displayed incorrectly" ); //this->SetPhotometricInterpretation( PhotometricInterpretation::RGB ); DoYBRFull422(*cur_is,pl_os); cur_is = &pl_os; } } break; case PhotometricInterpretation::YBR_ICT: break; case PhotometricInterpretation::YBR_RCT: break; default: gdcmErrorMacro( "Unhandled PhotometricInterpretation: " << PI ); return false; assert(0); } if( /*PlanarConfiguration ||*/ RequestPlanarConfiguration ) { DoPlanarConfiguration(*cur_is,pl_os); cur_is = &pl_os; } // Do the overlay cleanup (cleanup the unused bits) // must be the last operation (duh!) if ( PF.GetBitsAllocated() != PF.GetBitsStored() && PF.GetBitsAllocated() != 8 ) { // Technically we should only run this operation if the image declares it has overlay AND // there is no (0x60xx,0x3000) element, for example: // - XA_GE_JPEG_02_with_Overlays.dcm // - SIEMENS_GBS_III-16-ACR_NEMA_1.acr // Sigh, I finally found someone not declaring that unused bits where not zero: // gdcmConformanceTests/dcm4chee_unusedbits_not_zero.dcm if( NeedOverlayCleanup ) DoOverlayCleanup(*cur_is,os); else { // Once the issue with IMAGES/JPLY/RG3_JPLY aka gdcmData/D_CLUNIE_RG3_JPLY.dcm is solved the previous // code will be replace with a simple call to: DoSimpleCopy(*cur_is,os); } } else { assert( PF.GetBitsAllocated() == PF.GetBitsStored() ); DoSimpleCopy(*cur_is,os); } return true; } bool ImageCodec::IsValid(PhotometricInterpretation const &) { return false; } void ImageCodec::SetDimensions(const unsigned int d[3]) { Dimensions[0] = d[0]; Dimensions[1] = d[1]; Dimensions[2] = d[2]; } void ImageCodec::SetDimensions(const std::vector & d) { size_t theSize = d.size(); assert(theSize<= 3); for (size_t i = 0; i < 3; i++) { if (i < theSize) Dimensions[i] = d[i]; else Dimensions[i] = 1; } } bool ImageCodec::StartEncode( std::ostream & ) { assert(0); return false; } bool ImageCodec::IsRowEncoder() { return false; } bool ImageCodec::IsFrameEncoder() { return false; } bool ImageCodec::AppendRowEncode( std::ostream & , const char * , size_t ) { assert(0); return false; } // TODO: technically the frame encoder could use the row encoder when present // this could reduce code duplication bool ImageCodec::AppendFrameEncode( std::ostream & , const char * , size_t ) { assert(0); return false; } bool ImageCodec::StopEncode( std::ostream & ) { assert(0); return false; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageCodec.h000066400000000000000000000112451412732066400235010ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMAGECODEC_H #define GDCMIMAGECODEC_H #include "gdcmCodec.h" #include "gdcmPhotometricInterpretation.h" #include "gdcmLookupTable.h" #include "gdcmSmartPointer.h" #include "gdcmPixelFormat.h" namespace gdcm { /** * \brief ImageCodec * \note Main codec, this is a central place for all implementation */ class GDCM_EXPORT ImageCodec : public Codec { friend class ImageChangePhotometricInterpretation; public: ImageCodec(); ~ImageCodec() override; bool CanCode(TransferSyntax const &) const override { return false; } bool CanDecode(TransferSyntax const &) const override { return false; } bool Decode(DataElement const &is_, DataElement &os) override; bool IsLossy() const; void SetLossyFlag(bool l); bool GetLossyFlag() const; virtual bool GetHeaderInfo(std::istream &is_, TransferSyntax &ts); virtual ImageCodec * Clone() const = 0; protected: bool DecodeByStreams(std::istream &is_, std::ostream &os) override; virtual bool IsValid(PhotometricInterpretation const &pi); public: unsigned int GetPlanarConfiguration() const { return PlanarConfiguration; } void SetPlanarConfiguration(unsigned int pc) { assert( pc == 0 || pc == 1 ); PlanarConfiguration = pc; } PixelFormat &GetPixelFormat() { return PF; } const PixelFormat &GetPixelFormat() const { return PF; } virtual void SetPixelFormat(PixelFormat const &pf) { PF = pf; } const PhotometricInterpretation &GetPhotometricInterpretation() const; void SetPhotometricInterpretation(PhotometricInterpretation const &pi); bool GetNeedByteSwap() const { return NeedByteSwap; } void SetNeedByteSwap(bool b) { NeedByteSwap = b; } void SetNeedOverlayCleanup(bool b) { NeedOverlayCleanup = b; } void SetLUT(LookupTable const &lut) { LUT = SmartPointer( const_cast(&lut) ); } const LookupTable &GetLUT() const { return *LUT; } void SetDimensions(const unsigned int d[3]); void SetDimensions(const std::vector & d); const unsigned int *GetDimensions() const { return Dimensions; } void SetNumberOfDimensions(unsigned int dim); unsigned int GetNumberOfDimensions() const; bool CleanupUnusedBits(char * data, size_t datalen); protected: // Streaming (write) API: /// This is a high level API to encode in a streaming fashion. Each plugin /// will handle differently the caching mechanism so that a limited memory is /// used when compressing dataset. /// Codec will fall into two categories: /// - Full row encoder: only a single scanline (row) of data is needed to be loaded at a time; /// - Full frame encoder (default): a complete frame (row x col) is needed to be loaded at a time friend class FileChangeTransferSyntax; virtual bool StartEncode( std::ostream & os ); virtual bool IsRowEncoder(); virtual bool IsFrameEncoder(); virtual bool AppendRowEncode( std::ostream & out, const char * data, size_t datalen ); virtual bool AppendFrameEncode( std::ostream & out, const char * data, size_t datalen ); virtual bool StopEncode( std::ostream & os); protected: bool RequestPlanarConfiguration; bool RequestPaddedCompositePixelCode; //private: unsigned int PlanarConfiguration; PhotometricInterpretation PI; PixelFormat PF; bool NeedByteSwap; bool NeedOverlayCleanup; typedef SmartPointer LUTPtr; LUTPtr LUT; unsigned int Dimensions[3]; // FIXME unsigned int NumberOfDimensions; bool LossyFlag; bool DoOverlayCleanup(std::istream &is_, std::ostream &os); bool DoByteSwap(std::istream &is_, std::ostream &os); bool DoYBR(std::istream &is_, std::ostream &os); bool DoYBRFull422(std::istream &is_, std::ostream &os); bool DoPlanarConfiguration(std::istream &is_, std::ostream &os); bool DoSimpleCopy(std::istream &is_, std::ostream &os); bool DoPaddedCompositePixelCode(std::istream &is_, std::ostream &os); bool DoInvertMonochrome(std::istream &is_, std::ostream &os); //template //bool DoInvertPlanarConfiguration(T *output, const T *input, uint32_t length); }; } // end namespace gdcm #endif //GDCMIMAGECODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageConverter.cxx000066400000000000000000000017201412732066400250030ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageConverter.h" #include "gdcmImage.h" namespace gdcm { ImageConverter::ImageConverter() { Output = new Image; } ImageConverter::~ImageConverter() { delete Output; } void ImageConverter::SetInput(Image const &input) { Input = const_cast(&input); } const Image& ImageConverter::GetOuput() const { return *Output; } void ImageConverter::Convert() { } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageConverter.h000066400000000000000000000024211412732066400244270ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMAGECONVERTER_H #define GDCMIMAGECONVERTER_H #include "gdcmTypes.h" namespace gdcm { class Image; /** * \brief Image Converter * \note * This is the class used to convert from on Image to another * This is typically used to convert let say YBR JPEG compressed * Image to a RAW RGB Image. So that the buffer can be directly * pass to third party application. * This filter is application level and not integrated directly in GDCM */ class GDCM_EXPORT ImageConverter { public: ImageConverter(); ~ImageConverter(); void SetInput(Image const &input); const Image& GetOuput() const; void Convert(); private: Image *Input; Image *Output; }; } // end namespace gdcm #endif //GDCMIMAGECONVERTER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageFragmentSplitter.cxx000066400000000000000000000062501412732066400263310ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageFragmentSplitter.h" #include "gdcmSequenceOfFragments.h" namespace gdcm { bool ImageFragmentSplitter::Split() { Output = Input; const Bitmap &image = *Input; const unsigned int *dims = image.GetDimensions(); if( dims[2] != 1 ) { gdcmDebugMacro( "Cannot split a 3D image" ); return false; } const DataElement& pixeldata = image.GetDataElement(); const SequenceOfFragments *sqf = pixeldata.GetSequenceOfFragments(); if( !sqf ) { gdcmDebugMacro( "Cannot split a non-encapsulated syntax" ); return false; } if ( sqf->GetNumberOfFragments() != 1 ) { gdcmDebugMacro( "Case not handled (for now)" ); return false; } //assert( sqf->GetNumberOfFragments() == 1 ); // WARNING do not keep the same Basic Offset Table... const Fragment& frag = sqf->GetFragment(0); const ByteValue *bv = frag.GetByteValue(); const char *p = bv->GetPointer(); unsigned long len = bv->GetLength(); if( FragmentSizeMax > len && !Force ) { // I think it is ok return true; } // prevent zero division if( FragmentSizeMax == 0 ) { gdcmDebugMacro( "Need to set a real value for fragment size" ); return false; // seriously... } unsigned long nfrags = len / FragmentSizeMax; unsigned long lastfrag = len % FragmentSizeMax; SmartPointer sq = new SequenceOfFragments; // Let's do all complete frag: for(unsigned long i = 0; i < nfrags; ++i) { Fragment splitfrag; splitfrag.SetByteValue( p + i * FragmentSizeMax, FragmentSizeMax); sq->AddFragment( splitfrag ); } // Last (incomplete one): if( lastfrag ) { Fragment splitfrag; splitfrag.SetByteValue( p + nfrags * FragmentSizeMax, (uint32_t)lastfrag ); assert( nfrags * FragmentSizeMax + lastfrag == len ); sq->AddFragment( splitfrag ); } Output->GetDataElement().SetValue( *sq ); bool success = true; return success; } void ImageFragmentSplitter::SetFragmentSizeMax(unsigned int fragsize) { /* * A.4 TRANSFER SYNTAXES FOR ENCAPSULATION OF ENCODED PIXEL DATA * * All items containing an encoded fragment shall be made of an even number of bytes * greater or equal to two. The last fragment of a frame may be padded, if necessary, * to meet the sequence item format requirements of the DICOM Standard. */ FragmentSizeMax = fragsize; if( fragsize % 2 ) { // what if FragmentSizeMax == 0 ... FragmentSizeMax--; } // How do I handle this one... if( fragsize < 2 ) { FragmentSizeMax = 2; } // \postcondition: assert( FragmentSizeMax >= 2 && (FragmentSizeMax % 2) == 0 ); } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageFragmentSplitter.h000066400000000000000000000030431412732066400257530ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMAGEFRAGMENTSPLITTER_H #define GDCMIMAGEFRAGMENTSPLITTER_H #include "gdcmImageToImageFilter.h" namespace gdcm { class DataElement; /** * \brief ImageFragmentSplitter class * \details For single frame image, DICOM standard allow splitting the frame into multiple fragments */ class GDCM_EXPORT ImageFragmentSplitter : public ImageToImageFilter { public: ImageFragmentSplitter():FragmentSizeMax(0),Force(false) {} ~ImageFragmentSplitter() = default; /// Split bool Split(); /// FragmentSizeMax needs to be an even number void SetFragmentSizeMax(unsigned int fragsize); unsigned int GetFragmentSizeMax() const { return FragmentSizeMax; } /// When file already has all it's segment < FragmentSizeMax there is not need to run the filter. /// Unless the user explicitly say 'force' recomputation ! void SetForce( bool f ) { Force = f; } protected: private: unsigned int FragmentSizeMax; bool Force; }; } // end namespace gdcm #endif //GDCMIMAGEFRAGMENTSPLITTER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageHelper.cxx000066400000000000000000003250501412732066400242600ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageHelper.h" #include "gdcmMediaStorage.h" #include "gdcmFile.h" #include "gdcmDataSet.h" #include "gdcmDataElement.h" #include "gdcmItem.h" #include "gdcmSequenceOfItems.h" #include "gdcmGlobal.h" #include "gdcmDictEntry.h" #include "gdcmDicts.h" #include "gdcmAttribute.h" #include "gdcmImage.h" #include "gdcmDirectionCosines.h" #include "gdcmSegmentedPaletteColorLookupTable.h" #include "gdcmByteValue.h" #include // fabs /* TODO: * * (0028,9145) SQ (Sequence with undefined length #=1) # u/l, 1 PixelValueTransformationSequence * (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item * (0028,1052) DS [0.00000] # 8, 1 RescaleIntercept * (0028,1053) DS [1.00000] # 8, 1 RescaleSlope * (0028,1054) LO [US] # 2, 1 RescaleType * (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem * (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem * * Same goes for window level... */ namespace gdcm { bool ImageHelper::ForceRescaleInterceptSlope = false; bool ImageHelper::PMSRescaleInterceptSlope = true; bool ImageHelper::ForcePixelSpacing = false; static bool GetOriginValueFromSequence(const DataSet& ds, const Tag& tfgs, std::vector &ori) { if( !ds.FindDataElement( tfgs ) ) return false; //const SequenceOfItems * sqi = ds.GetDataElement( tfgs ).GetSequenceOfItems(); SmartPointer sqi = ds.GetDataElement( tfgs ).GetValueAsSQ(); if( !(sqi && sqi->GetNumberOfItems() > 0) ) return false; // Get first item: const Item &item = sqi->GetItem(1); const DataSet & subds = item.GetNestedDataSet(); // Plane position Sequence const Tag tpms(0x0020,0x9113); if( !subds.FindDataElement(tpms) ) return false; //const SequenceOfItems * sqi2 = subds.GetDataElement( tpms ).GetSequenceOfItems(); SmartPointer sqi2 = subds.GetDataElement( tpms ).GetValueAsSQ(); if( sqi2 && !sqi2->IsEmpty() ) { const Item &item2 = sqi2->GetItem(1); const DataSet & subds2 = item2.GetNestedDataSet(); // const Tag tps(0x0020,0x0032); if( !subds2.FindDataElement(tps) ) return false; const DataElement &de = subds2.GetDataElement( tps ); //assert( bv ); Attribute<0x0020,0x0032> at; at.SetFromDataElement( de ); //at.Print( std::cout ); ori.push_back( at.GetValue(0) ); ori.push_back( at.GetValue(1) ); ori.push_back( at.GetValue(2) ); return true; } return false; } static bool GetDirectionCosinesValueFromSequence(const DataSet& ds, const Tag& tfgs, std::vector &dircos) { if( !ds.FindDataElement( tfgs ) ) return false; //const SequenceOfItems * sqi = ds.GetDataElement( tfgs ).GetSequenceOfItems(); SmartPointer sqi = ds.GetDataElement( tfgs ).GetValueAsSQ(); if( !(sqi && sqi->GetNumberOfItems() > 0) ) return false; // Get first item: const Item &item = sqi->GetItem(1); const DataSet & subds = item.GetNestedDataSet(); // Plane position Sequence const Tag tpms(0x0020,0x9116); if( !subds.FindDataElement(tpms) ) return false; //const SequenceOfItems * sqi2 = subds.GetDataElement( tpms ).GetSequenceOfItems(); SmartPointer sqi2 = subds.GetDataElement( tpms ).GetValueAsSQ(); if( !(sqi2 && sqi2->GetNumberOfItems()) ) return false; assert( sqi2 && sqi2->GetNumberOfItems() ); // Take it from the first item const Item &item2 = sqi2->GetItem(1); const DataSet & subds2 = item2.GetNestedDataSet(); // const Tag tps(0x0020,0x0037); if( !subds2.FindDataElement(tps) ) return false; const DataElement &de = subds2.GetDataElement( tps ); //assert( bv ); Attribute<0x0020,0x0037> at; at.SetFromDataElement( de ); dircos.push_back( at.GetValue(0) ); dircos.push_back( at.GetValue(1) ); dircos.push_back( at.GetValue(2) ); dircos.push_back( at.GetValue(3) ); dircos.push_back( at.GetValue(4) ); dircos.push_back( at.GetValue(5) ); return true; } static bool GetInterceptSlopeValueFromSequence(const DataSet& ds, const Tag& tfgs, std::vector &intslope) { if( !ds.FindDataElement( tfgs ) ) return false; //const SequenceOfItems * sqi = ds.GetDataElement( tfgs ).GetSequenceOfItems(); SmartPointer sqi = ds.GetDataElement( tfgs ).GetValueAsSQ(); if( !(sqi && sqi->GetNumberOfItems() > 0) ) return false; // Get first item: const Item &item = sqi->GetItem(1); const DataSet & subds = item.GetNestedDataSet(); // (0028,9145) SQ (Sequence with undefined length) # u/l,1 Pixel Value Transformation Sequence const Tag tpms(0x0028,0x9145); if( !subds.FindDataElement(tpms) ) return false; //const SequenceOfItems * sqi2 = subds.GetDataElement( tpms ).GetSequenceOfItems(); SmartPointer sqi2 = subds.GetDataElement( tpms ).GetValueAsSQ(); assert( sqi2 ); const Item &item2 = sqi2->GetItem(1); const DataSet & subds2 = item2.GetNestedDataSet(); { // (0028,1052) DS [0] # 2,1 Rescale Intercept const Tag tps(0x0028,0x1052); if( !subds2.FindDataElement(tps) ) return false; const DataElement &de = subds2.GetDataElement( tps ); //assert( bv ); Attribute<0x0028,0x1052> at; at.SetFromDataElement( de ); //at.Print( std::cout ); intslope.push_back( at.GetValue() ); } { // (0028,1053) DS [5.65470085470085] # 16,1 Rescale Slope const Tag tps(0x0028,0x1053); if( !subds2.FindDataElement(tps) ) return false; const DataElement &de = subds2.GetDataElement( tps ); //assert( bv ); Attribute<0x0028,0x1053> at; at.SetFromDataElement( de ); //at.Print( std::cout ); intslope.push_back( at.GetValue() ); } assert( intslope.size() == 2 ); return true; } static bool ComputeZSpacingFromIPP(const DataSet &ds, double &zspacing) { // first we need to get the direction cosines: const Tag t1(0x5200,0x9229); const Tag t2(0x5200,0x9230); std::vector cosines; // For some reason TOSHIBA-EnhancedCT.dcm is storing the direction cosines in the per-frame section // and not the shared one... oh well bool b1 = GetDirectionCosinesValueFromSequence(ds, t1, cosines) || GetDirectionCosinesValueFromSequence(ds,t2,cosines); if(!b1) { cosines.resize( 6 ); bool b2 = ImageHelper::GetDirectionCosinesFromDataSet(ds, cosines); if( b2 ) { gdcmWarningMacro( "Image Orientation (Patient) cannot be stored here!. Continuing" ); b1 = b2; } else { gdcmErrorMacro( "Image Orientation (Patient) was not found" ); cosines[0] = 1; cosines[1] = 0; cosines[2] = 0; cosines[3] = 0; cosines[4] = 1; cosines[5] = 0; } } assert( b1 && cosines.size() == 6 ); // yeah we really need that const Tag tfgs(0x5200,0x9230); if( !ds.FindDataElement( tfgs ) ) return false; //const SequenceOfItems * sqi = ds.GetDataElement( tfgs ).GetSequenceOfItems(); SmartPointer sqi = ds.GetDataElement( tfgs ).GetValueAsSQ(); if( !sqi ) return false; assert( sqi ); double normal[3]; DirectionCosines dc( &cosines[0] ); dc.Cross( normal ); // For each item SequenceOfItems::SizeType nitems = sqi->GetNumberOfItems(); if( nitems > 1 ) { std::vector dircos_subds2; dircos_subds2.resize(6); std::vector distances; for(SequenceOfItems::SizeType i0 = 1; i0 <= nitems; ++i0) { const Item &item = sqi->GetItem(i0); const DataSet & subds = item.GetNestedDataSet(); // (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence const Tag tpms(0x0020,0x9113); if( !subds.FindDataElement(tpms) ) return false; //const SequenceOfItems * sqi2 = subds.GetDataElement( tpms ).GetSequenceOfItems(); SmartPointer sqi2 = subds.GetDataElement( tpms ).GetValueAsSQ(); assert( sqi2 ); const Item &item2 = sqi2->GetItem(1); const DataSet & subds2 = item2.GetNestedDataSet(); // Check Image Orientation (Patient) if( ImageHelper::GetDirectionCosinesFromDataSet(subds2, dircos_subds2) ) { assert( dircos_subds2 == cosines ); } // (0020,0032) DS [-82.5\-82.5\1153.75] # 20, 3 ImagePositionPatient const Tag tps(0x0020,0x0032); if( !subds2.FindDataElement(tps) ) return false; const DataElement &de = subds2.GetDataElement( tps ); Attribute<0x0020,0x0032> ipp; ipp.SetFromDataElement(de); double dist = 0; for (int i = 0; i < 3; ++i) dist += normal[i]*ipp[i]; distances.push_back( dist ); } assert( distances.size() == nitems ); double meanspacing = 0; double prev = distances[0]; for(unsigned int i = 1; i < nitems; ++i) { const double current = distances[i] - prev; meanspacing += current; prev = distances[i]; } bool timeseries = false; if( nitems > 1 ) { meanspacing /= (double)(nitems - 1); if( meanspacing == 0.0 ) { // Could be a time series. Assume time spacing of 1. for now: gdcmDebugMacro( "Assuming time series for Z-spacing" ); meanspacing = 1.0; timeseries = true; } } zspacing = meanspacing; if( nitems > 1 ) assert( zspacing != 0.0 ); // technically this should not happen if( !timeseries ) { // Check spacing is consistent: const double ZTolerance = 1e-3; // ??? FIXME prev = distances[0]; for(unsigned int i = 1; i < nitems; ++i) { const double current = distances[i] - prev; if( fabs(current - zspacing) > ZTolerance ) { // For now simply gives up gdcmErrorMacro( "This Enhanced Multiframe is not supported for now. Sorry" ); return false; } prev = distances[i]; } } } else { // single slice, this is not an error to not find the zspacing in this case. zspacing = 1.0; const Tag tfgs0(0x5200,0x9229); if( !ds.FindDataElement( tfgs0 ) ) return true; SmartPointer sqi0 = ds.GetDataElement( tfgs0 ).GetValueAsSQ(); if( !(sqi0 && sqi0->GetNumberOfItems() > 0) ) return true; // Get first item: const Item &item = sqi0->GetItem(1); const DataSet & subds = item.GetNestedDataSet(); // const Tag tpms(0x0028,0x9110); if( !subds.FindDataElement(tpms) ) return true; //const SequenceOfItems * sqi2 = subds.GetDataElement( tpms ).GetSequenceOfItems(); SmartPointer sqi2 = subds.GetDataElement( tpms ).GetValueAsSQ(); assert( sqi2 ); const Item &item2 = sqi2->GetItem(1); const DataSet & subds2 = item2.GetNestedDataSet(); // const Tag tps(0x0018,0x0088); if( !subds2.FindDataElement(tps) ) return true; const DataElement &de = subds2.GetDataElement( tps ); Attribute<0x0018,0x0088> at; at.SetFromDataElement( de ); zspacing = at.GetValue(); } return true; } // EnhancedMRImageStorage & EnhancedCTImageStorage static bool GetSpacingValueFromSequence(const DataSet& ds, const Tag& tfgs, std::vector &sp) { // (0028,9110) SQ (Sequence with undefined length #=1) # u/l, 1 PixelMeasuresSequence // (fffe,e000) na (Item with undefined length #=2) # u/l, 1 Item // (0018,0050) DS [0.5] # 4, 1 SliceThickness // (0028,0030) DS [0.322\0.322] # 12, 2 PixelSpacing // //const Tag tfgs(0x5200,0x9229); //const Tag tfgs(0x5200,0x9230); //assert( ds.FindDataElement( tfgs ) ); if( !ds.FindDataElement( tfgs ) ) return false; //const SequenceOfItems * sqi = ds.GetDataElement( tfgs ).GetSequenceOfItems(); SmartPointer sqi = ds.GetDataElement( tfgs ).GetValueAsSQ(); if( !(sqi && sqi->GetNumberOfItems() > 0) ) return false; // Get first item: const Item &item = sqi->GetItem(1); const DataSet & subds = item.GetNestedDataSet(); // const Tag tpms(0x0028,0x9110); if( !subds.FindDataElement(tpms) ) return false; //const SequenceOfItems * sqi2 = subds.GetDataElement( tpms ).GetSequenceOfItems(); SmartPointer sqi2 = subds.GetDataElement( tpms ).GetValueAsSQ(); assert( sqi2 ); const Item &item2 = sqi2->GetItem(1); const DataSet & subds2 = item2.GetNestedDataSet(); // const Tag tps(0x0028,0x0030); if( !subds2.FindDataElement(tps) ) return false; const DataElement &de = subds2.GetDataElement( tps ); //assert( bv ); Attribute<0x0028,0x0030> at; at.SetFromDataElement( de ); //at.Print( std::cout ); sp.push_back( at.GetValue(1) ); sp.push_back( at.GetValue(0) ); // BUG ! Check for instance: // gdcmData/BRTUM001.dcm // Slice Thickness is 5.0 while the Zspacing should be 6.0 ! #if 0 // Do the 3rd dimension zspacing: // const Tag tst(0x0018,0x0050); if( !subds2.FindDataElement(tst) ) return false; const DataElement &de2 = subds2.GetDataElement( tst ); Attribute<0x0018,0x0050> at2; at2.SetFromDataElement( de2 ); //at2.Print( std::cout ); sp.push_back( at2.GetValue(0) ); #endif double zspacing; bool b = ComputeZSpacingFromIPP(ds, zspacing); if( !b ) return false; sp.push_back( zspacing ); return true; } static SmartPointer InsertOrReplaceSQ( DataSet & ds, const Tag &tag ) { SmartPointer sqi; if( !ds.FindDataElement( tag ) ) { sqi = new SequenceOfItems; DataElement de( tag ); de.SetVR( VR::SQ ); de.SetValue( *sqi ); assert( de.GetVL().IsUndefined() ); de.SetVLToUndefined(); ds.Insert( de ); } sqi = ds.GetDataElement( tag ).GetValueAsSQ(); sqi->SetLengthToUndefined(); DataElement de_dup = ds.GetDataElement( tag ); de_dup.SetValue( *sqi ); ds.Replace( de_dup ); return sqi; } // UltrasoundMultiframeImageStorage static bool GetUltraSoundSpacingValueFromSequence(const DataSet& ds, std::vector &sp) { /* (0018,6011) SQ (Sequence with explicit length #=1) # 196, 1 SequenceOfUltrasoundRegions (fffe,e000) na (Item with explicit length #=15) # 188, 1 Item (0018,6012) US 1 # 2, 1 RegionSpatialFormat (0018,6014) US 1 # 2, 1 RegionDataType (0018,6016) UL 0 # 4, 1 RegionFlags (0018,6018) UL 0 # 4, 1 RegionLocationMinX0 (0018,601a) UL 0 # 4, 1 RegionLocationMinY0 (0018,601c) UL 479 # 4, 1 RegionLocationMaxX1 (0018,601e) UL 479 # 4, 1 RegionLocationMaxY1 (0018,6020) SL 0 # 4, 1 ReferencePixelX0 (0018,6022) SL 0 # 4, 1 ReferencePixelY0 (0018,6024) US 3 # 2, 1 PhysicalUnitsXDirection (0018,6026) US 3 # 2, 1 PhysicalUnitsYDirection (0018,6028) FD 0 # 8, 1 ReferencePixelPhysicalValueX (0018,602a) FD 0 # 8, 1 ReferencePixelPhysicalValueY (0018,602c) FD 0.002 # 8, 1 PhysicalDeltaX (0018,602e) FD 0.002 # 8, 1 PhysicalDeltaY (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem */ const Tag tsqusreg(0x0018,0x6011); if( !ds.FindDataElement( tsqusreg ) ) return false; //const SequenceOfItems * sqi = ds.GetDataElement( tsqusreg ).GetSequenceOfItems(); SmartPointer sqi = ds.GetDataElement( tsqusreg ).GetValueAsSQ(); if( !sqi ) return false; assert( sqi ); // Get first item: const Item &item = sqi->GetItem(1); const DataSet & subds = item.GetNestedDataSet(); // (0018,602c) FD 0.002 # 8, 1 PhysicalDeltaX // (0018,602e) FD 0.002 # 8, 1 PhysicalDeltaY Attribute<0x0018,0x602c> at1; Attribute<0x0018,0x602e> at2; const DataElement &de1 = subds.GetDataElement( at1.GetTag() ); at1.SetFromDataElement( de1 ); assert( at1.GetNumberOfValues() == 1 ); const DataElement &de2 = subds.GetDataElement( at2.GetTag() ); at2.SetFromDataElement( de2 ); assert( at2.GetNumberOfValues() == 1 ); sp.push_back( at1.GetValue() ); sp.push_back( at2.GetValue() ); return true; } static void SetUltraSoundSpacingValueFromSequence(DataSet& ds, std::vector const &spacing) { /* (0018,6011) SQ (Sequence with explicit length #=1) # 196, 1 SequenceOfUltrasoundRegions (fffe,e000) na (Item with explicit length #=15) # 188, 1 Item (0018,6012) US 1 # 2, 1 RegionSpatialFormat (0018,6014) US 1 # 2, 1 RegionDataType (0018,6016) UL 0 # 4, 1 RegionFlags (0018,6018) UL 0 # 4, 1 RegionLocationMinX0 (0018,601a) UL 0 # 4, 1 RegionLocationMinY0 (0018,601c) UL 479 # 4, 1 RegionLocationMaxX1 (0018,601e) UL 479 # 4, 1 RegionLocationMaxY1 (0018,6020) SL 0 # 4, 1 ReferencePixelX0 (0018,6022) SL 0 # 4, 1 ReferencePixelY0 (0018,6024) US 3 # 2, 1 PhysicalUnitsXDirection (0018,6026) US 3 # 2, 1 PhysicalUnitsYDirection (0018,6028) FD 0 # 8, 1 ReferencePixelPhysicalValueX (0018,602a) FD 0 # 8, 1 ReferencePixelPhysicalValueY (0018,602c) FD 0.002 # 8, 1 PhysicalDeltaX (0018,602e) FD 0.002 # 8, 1 PhysicalDeltaY (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem */ const Tag tsqusreg(0x0018,0x6011); SmartPointer sqi = InsertOrReplaceSQ( ds, tsqusreg); if( !sqi->GetNumberOfItems() ) { Item item; //( Tag(0xfffe,0xe000) ); sqi->AddItem( item ); } Item &item1 = sqi->GetItem(1); item1.SetVLToUndefined(); DataSet &subds = item1.GetNestedDataSet(); // (0018,602c) FD 0.002 # 8, 1 PhysicalDeltaX // (0018,602e) FD 0.002 # 8, 1 PhysicalDeltaY Attribute<0x0018,0x602c> at1; at1.SetValue( spacing[0] ); Attribute<0x0018,0x602e> at2; at2.SetValue( spacing[1] ); subds.Replace( at1.GetAsDataElement() ); subds.Replace( at2.GetAsDataElement() ); } /* Enhanced stuff looks like: (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item (0020,0032) DS [73.5100815890831\-129.65028828174\189.777023529388] # 50, 3 ImagePositionPatient (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem (0020,9116) SQ (Sequence with undefined length #=1) # u/l, 1 PlaneOrientationSequence (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item (0020,0037) DS [0.01604138687252\0.99942564964294\-0.0298495516180\0.0060454937629... # 102, 6 ImageOrientationPatient (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem (0028,9110) SQ (Sequence with undefined length #=1) # u/l, 1 PixelMeasuresSequence (fffe,e000) na (Item with undefined length #=2) # u/l, 1 Item (0018,0050) DS [1] # 2, 1 SliceThickness (0028,0030) DS [0.83333331346511\0.83333331346511] # 34, 2 PixelSpacing (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem */ std::vector ImageHelper::GetOriginValue(File const & f) { std::vector ori; MediaStorage ms; ms.SetFromFile(f); const DataSet& ds = f.GetDataSet(); if( ms == MediaStorage::EnhancedCTImageStorage || ms == MediaStorage::EnhancedMRImageStorage || ms == MediaStorage::EnhancedMRColorImageStorage || ms == MediaStorage::EnhancedPETImageStorage || ms == MediaStorage::OphthalmicTomographyImageStorage || ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage || ms == MediaStorage::XRay3DAngiographicImageStorage || ms == MediaStorage::XRay3DCraniofacialImageStorage || ms == MediaStorage::SegmentationStorage || ms == MediaStorage::IVOCTForProcessing || ms == MediaStorage::IVOCTForPresentation || ms == MediaStorage::BreastTomosynthesisImageStorage || ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation || ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing || ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage || ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage || ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage ) { const Tag t1(0x5200,0x9229); const Tag t2(0x5200,0x9230); if( GetOriginValueFromSequence(ds,t1, ori) || GetOriginValueFromSequence(ds, t2, ori) ) { assert( ori.size() == 3 ); return ori; } ori.resize( 3 ); gdcmWarningMacro( "Could not find Origin" ); return ori; } if( ms == MediaStorage::NuclearMedicineImageStorage ) { const Tag t1(0x0054,0x0022); if( ds.FindDataElement( t1 ) ) { SmartPointer sqi = ds.GetDataElement( t1 ).GetValueAsSQ(); if( sqi && sqi->GetNumberOfItems() >= 1) { // Get first item: const Item &item = sqi->GetItem(1); const DataSet & subds = item.GetNestedDataSet(); const Tag timagepositionpatient(0x0020, 0x0032); assert( subds.FindDataElement( timagepositionpatient ) ); Attribute<0x0020,0x0032> at = {{0,0,0}}; // default value if empty at.SetFromDataSet( subds ); ori.resize( at.GetNumberOfValues() ); for( unsigned int i = 0; i < at.GetNumberOfValues(); ++i ) { ori[i] = at.GetValue(i); } return ori; } } ori.resize( 3 ); gdcmWarningMacro( "Could not find Origin" ); return ori; } ori.resize( 3 ); // else const Tag timagepositionpatient(0x0020, 0x0032); if( ms != MediaStorage::SecondaryCaptureImageStorage && ds.FindDataElement( timagepositionpatient ) ) { const DataElement& de = ds.GetDataElement( timagepositionpatient ); Attribute<0x0020,0x0032> at = {{0,0,0}}; // default value if empty at.SetFromDataElement( de ); for( unsigned int i = 0; i < at.GetNumberOfValues(); ++i ) { ori[i] = at.GetValue(i); } } else { ori[0] = 0; ori[1] = 0; ori[2] = 0; } assert( ori.size() == 3 ); return ori; } bool ImageHelper::GetDirectionCosinesFromDataSet(DataSet const & ds, std::vector & dircos) { // \precondition: this dataset is not a secondary capture ! // else const Tag timageorientationpatient(0x0020, 0x0037); if( ds.FindDataElement( timageorientationpatient ) /*&& !ds.GetDataElement( timageorientationpatient ).IsEmpty()*/ ) { const DataElement& de = ds.GetDataElement( timageorientationpatient ); Attribute<0x0020,0x0037> at = {{1,0,0,0,1,0}}; // default value if empty at.SetFromDataElement( de ); for( unsigned int i = 0; i < at.GetNumberOfValues(); ++i ) { dircos[i] = at.GetValue(i); } DirectionCosines dc( &dircos[0] ); if( !dc.IsValid() ) { dc.Normalize(); if( dc.IsValid() ) { gdcmWarningMacro( "DirectionCosines was not normalized. Fixed" ); const double * p = dc; dircos = std::vector(p, p + 6); //return dircos; } else { // PAPYRUS_CR_InvalidIOP.dcm gdcmWarningMacro( "Could not get DirectionCosines. Will be set to unit vector." ); //dircos[0] = 1; //dircos[1] = 0; //dircos[2] = 0; //dircos[3] = 0; //dircos[4] = 1; //dircos[5] = 0; return false; } } return true; } return false; } std::vector ImageHelper::GetDirectionCosinesValue(File const & f) { std::vector dircos; MediaStorage ms; ms.SetFromFile(f); const DataSet& ds = f.GetDataSet(); if( ms == MediaStorage::EnhancedCTImageStorage || ms == MediaStorage::EnhancedMRImageStorage || ms == MediaStorage::EnhancedMRColorImageStorage || ms == MediaStorage::EnhancedPETImageStorage || ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage || ms == MediaStorage::XRay3DAngiographicImageStorage || ms == MediaStorage::XRay3DCraniofacialImageStorage || ms == MediaStorage::SegmentationStorage || ms == MediaStorage::IVOCTForPresentation || ms == MediaStorage::IVOCTForProcessing || ms == MediaStorage::BreastTomosynthesisImageStorage || ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation || ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing || ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage || ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage || ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage ) { const Tag t1(0x5200,0x9229); const Tag t2(0x5200,0x9230); if( GetDirectionCosinesValueFromSequence(ds,t1, dircos) || GetDirectionCosinesValueFromSequence(ds, t2, dircos) ) { assert( dircos.size() == 6 ); return dircos; } else { dircos.resize( 6 ); bool b2 = ImageHelper::GetDirectionCosinesFromDataSet(ds, dircos); if( b2 ) { gdcmWarningMacro( "Image Orientation (Patient) cannot be stored here!. Continuing" ); } else { gdcmErrorMacro( "Image Orientation (Patient) was not found" ); dircos[0] = 1; dircos[1] = 0; dircos[2] = 0; dircos[3] = 0; dircos[4] = 1; dircos[5] = 0; } return dircos; } } if( ms == MediaStorage::NuclearMedicineImageStorage ) { const Tag t1(0x0054,0x0022); if( ds.FindDataElement( t1 ) ) { SmartPointer sqi = ds.GetDataElement( t1 ).GetValueAsSQ(); if( sqi && sqi->GetNumberOfItems() >= 1 ) { // Get first item: const Item &item = sqi->GetItem(1); const DataSet & subds = item.GetNestedDataSet(); dircos.resize( 6 ); bool b2 = ImageHelper::GetDirectionCosinesFromDataSet(subds, dircos); if( b2 ) { } else { gdcmErrorMacro( "Image Orientation (Patient) was not found" ); dircos[0] = 1; dircos[1] = 0; dircos[2] = 0; dircos[3] = 0; dircos[4] = 1; dircos[5] = 0; } return dircos; } } } dircos.resize( 6 ); if( ms == MediaStorage::SecondaryCaptureImageStorage || !GetDirectionCosinesFromDataSet(ds, dircos) ) { dircos[0] = 1; dircos[1] = 0; dircos[2] = 0; dircos[3] = 0; dircos[4] = 1; dircos[5] = 0; } assert( dircos.size() == 6 ); return dircos; } void ImageHelper::SetForceRescaleInterceptSlope(bool b) { ForceRescaleInterceptSlope = b; } bool ImageHelper::GetForceRescaleInterceptSlope() { return ForceRescaleInterceptSlope; } void ImageHelper::SetPMSRescaleInterceptSlope(bool b) { PMSRescaleInterceptSlope = b; } bool ImageHelper::GetPMSRescaleInterceptSlope() { return PMSRescaleInterceptSlope; } void ImageHelper::SetForcePixelSpacing(bool b) { ForcePixelSpacing = b; } bool ImageHelper::GetForcePixelSpacing() { return ForcePixelSpacing; } bool GetRescaleInterceptSlopeValueFromDataSet(const DataSet& ds, std::vector & interceptslope) { Attribute<0x0028,0x1052> at1; bool intercept = ds.FindDataElement(at1.GetTag()); if( intercept ) { if( !ds.GetDataElement(at1.GetTag()).IsEmpty() ) { at1.SetFromDataElement( ds.GetDataElement(at1.GetTag()) ); interceptslope[0] = at1.GetValue(); } } Attribute<0x0028,0x1053> at2; bool slope = ds.FindDataElement(at2.GetTag()); if ( slope ) { if( !ds.GetDataElement(at2.GetTag()).IsEmpty() ) { at2.SetFromDataElement( ds.GetDataElement(at2.GetTag()) ); interceptslope[1] = at2.GetValue(); if( interceptslope[1] == 0 ) { // come' on ! WTF gdcmDebugMacro( "Cannot have slope == 0. Defaulting to 1.0 instead" ); interceptslope[1] = 1; } } } return intercept || slope; } /// This function returns pixel information about an image from its dataset /// That includes samples per pixel and bit depth (in that order) /// Returns a PixelFormat PixelFormat ImageHelper::GetPixelFormatValue(const File& f) { // D 0028|0011 [US] [Columns] [512] //[10/20/10 9:05:07 AM] Mathieu Malaterre: PixelFormat pf; const DataSet& ds = f.GetDataSet(); // D 0028|0100 [US] [Bits Allocated] [16] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0100) ); Attribute<0x0028,0x0100> at = { 0 }; at.SetFromDataSet( ds ); pf.SetBitsAllocated( at.GetValue() ); } // D 0028|0101 [US] [Bits Stored] [12] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0101) ); Attribute<0x0028,0x0101> at = { 0 }; at.SetFromDataSet( ds ); pf.SetBitsStored( at.GetValue() ); } // D 0028|0102 [US] [High Bit] [11] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0102) ); Attribute<0x0028,0x0102> at = { 0 }; at.SetFromDataSet( ds ); pf.SetHighBit( at.GetValue() ); } // D 0028|0103 [US] [Pixel Representation] [0] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0103) ); Attribute<0x0028,0x0103> at = { 0 }; at.SetFromDataSet( ds ); pf.SetPixelRepresentation( at.GetValue() ); } // (0028,0002) US 1 # 2, 1 SamplesPerPixel { //if( ds.FindDataElement( Tag(0x0028, 0x0002) ) ) { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0002) ); Attribute<0x0028,0x0002> at = { 1 }; at.SetFromDataSet( ds ); pf.SetSamplesPerPixel( at.GetValue() ); } // else pf will default to 1... } return pf; } /// This function checks tags (0x0028, 0x0010) and (0x0028, 0x0011) for the /// rows and columns of the image in pixels (as opposed to actual distances). /// Also checks 0054, 0081 for the number of z slices for a 3D image /// If that tag is not present, default the z dimension to 1 std::vector ImageHelper::GetDimensionsValue(const File& f) { DataSet const & ds = f.GetDataSet(); MediaStorage ms; ms.SetFromFile(f); std::vector theReturn(3); #if 0 if( ms == MediaStorage::VLWholeSlideMicroscopyImageStorage ) { { Attribute<0x0048,0x0006> at = { 0 }; at.SetFromDataSet( ds ); theReturn[0] = at.GetValue(); } { Attribute<0x0048,0x0007> at = { 0 }; at.SetFromDataSet( ds ); theReturn[1] = at.GetValue(); } theReturn[2] = 1; } else #endif { { Attribute<0x0028,0x0011> at = { 0 }; // Columns at.SetFromDataSet( ds ); theReturn[0] = at.GetValue(); } { Attribute<0x0028,0x0010> at = { 0 }; // Rows at.SetFromDataSet( ds ); theReturn[1] = at.GetValue(); } { Attribute<0x0028,0x0008> at = { 0 }; at.SetFromDataSet( ds ); int numberofframes = at.GetValue(); theReturn[2] = 1; if( numberofframes > 1 ) { theReturn[2] = at.GetValue(); } } // ACR-NEMA legacy { Attribute<0x0028,0x0005> at = { 0 }; if( ds.FindDataElement( at.GetTag() ) ) { const DataElement &de = ds.GetDataElement( at.GetTag() ); // SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm picks VR::SS instead... if( at.GetVR().Compatible( de.GetVR() ) ) { at.SetFromDataSet( ds ); int imagedimensions = at.GetValue(); if( imagedimensions == 3 ) { Attribute<0x0028,0x0012> at2 = { 0 }; at2.SetFromDataSet( ds ); theReturn[2] = at2.GetValue(); } } else { gdcmWarningMacro( "Sorry cannot read attribute (wrong VR): " << at.GetTag() ); } } } } return theReturn; } void ImageHelper::SetDimensionsValue(File& f, const Pixmap & img) { const unsigned int *dims = img.GetDimensions(); MediaStorage ms; ms.SetFromFile(f); DataSet& ds = f.GetDataSet(); assert( MediaStorage::IsImage( ms ) ); { Attribute<0x0028,0x0010> rows; rows.SetValue( (uint16_t)dims[1] ); ds.Replace( rows.GetAsDataElement() ); Attribute<0x0028,0x0011> columns; columns.SetValue( (uint16_t)dims[0] ); ds.Replace( columns.GetAsDataElement() ); Attribute<0x0028,0x0008> numframes = { 0 }; numframes.SetValue( dims[2] ); if( img.GetNumberOfDimensions() == 3 && dims[2] >= 1 ) { if( ms.MediaStorage::GetModalityDimension() > 2 ) ds.Replace( numframes.GetAsDataElement() ); else if( ms.MediaStorage::GetModalityDimension() == 2 && dims[2] == 1 ) ds.Remove( numframes.GetTag() ); else { gdcmErrorMacro( "MediaStorage does not allow 3rd dimension. But value is: " << dims[2] ); gdcmAssertAlwaysMacro( "Could not set third dimension" ); } } else if( img.GetNumberOfDimensions() == 2 && dims[2] == 1 ) { // This is a MF instances, need to set Number of Frame to 1 when Required if (ms.MediaStorage::GetModalityDimension() > 2) { // Only include Multi-Frame when required (not Conditional): if( ms == MediaStorage::XRayAngiographicImageStorage // A.14.3 XA Image IOD Module Table: Multi-frame C.7.6.6 C - Required if pixel data is Multi - frame Cine data ) { ds.Remove(numframes.GetTag()); } else { ds.Replace(numframes.GetAsDataElement()); } } } else // cleanup ds.Remove( numframes.GetTag() ); } // cleanup pass: if( ms == MediaStorage::EnhancedCTImageStorage || ms == MediaStorage::EnhancedMRImageStorage || ms == MediaStorage::EnhancedMRColorImageStorage || ms == MediaStorage::EnhancedPETImageStorage || ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage || ms == MediaStorage::XRay3DAngiographicImageStorage || ms == MediaStorage::XRay3DCraniofacialImageStorage || ms == MediaStorage::SegmentationStorage || ms == MediaStorage::IVOCTForProcessing || ms == MediaStorage::IVOCTForPresentation || ms == MediaStorage::BreastTomosynthesisImageStorage || ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation || ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing || ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage || ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage || ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage ) { const Tag tfgs(0x5200,0x9230); if( ds.FindDataElement( tfgs ) ) { SmartPointer sqi = ds.GetDataElement( tfgs ).GetValueAsSQ(); assert( sqi ); sqi->SetLengthToUndefined(); sqi->SetNumberOfItems( dims[2] ); } } } std::vector ImageHelper::GetRescaleInterceptSlopeValue(File const & f) { std::vector interceptslope; MediaStorage ms; ms.SetFromFile(f); const DataSet& ds = f.GetDataSet(); if( ms == MediaStorage::EnhancedCTImageStorage || ms == MediaStorage::EnhancedMRImageStorage /*|| ms == MediaStorage::EnhancedMRColorImageStorage*/ || ms == MediaStorage::EnhancedPETImageStorage || ms == MediaStorage::XRay3DAngiographicImageStorage || ms == MediaStorage::XRay3DCraniofacialImageStorage || ms == MediaStorage::SegmentationStorage || ms == MediaStorage::BreastTomosynthesisImageStorage || ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation || ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing || ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage || ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage || ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage ) { const Tag t1(0x5200,0x9229); const Tag t2(0x5200,0x9230); if( GetInterceptSlopeValueFromSequence(ds,t1, interceptslope) || GetInterceptSlopeValueFromSequence(ds,t2, interceptslope) ) { assert( interceptslope.size() == 2 ); return interceptslope; } // Workaround to get intercept/slope from some Philips // XRay3DAngiographic files if (ms == MediaStorage::XRay3DAngiographicImageStorage && ForceRescaleInterceptSlope) { const Tag t3(0x0018,0x9530); if(ds.FindDataElement( t3 )) { SmartPointer sqi = ds.GetDataElement( t3 ).GetValueAsSQ(); if(sqi && sqi->GetNumberOfItems() > 0) { const Item &item = sqi->GetItem(1); const DataSet & subds = item.GetNestedDataSet(); const Tag tpi(0x0028,0x1052); const Tag tps(0x0028,0x1053); if( subds.FindDataElement(tps) && subds.FindDataElement(tpi)) { const DataElement &dei = subds.GetDataElement( tpi ); Attribute<0x0028,0x1052> ati; ati.SetFromDataElement( dei ); interceptslope.push_back( ati.GetValue() ); const DataElement &des = subds.GetDataElement( tps ); Attribute<0x0028,0x1053> ats; ats.SetFromDataElement( des ); interceptslope.push_back( ats.GetValue() ); return interceptslope; } } } } //else // { // interceptslope.resize( 2 ); // interceptslope[0] = 0; // interceptslope[1] = 1; // bool b = GetRescaleInterceptSlopeValueFromDataSet(ds, interceptslope); // gdcmAssertMacro( b ); (void)b; // return interceptslope; // } } // else interceptslope.resize( 2 ); interceptslope[0] = 0; interceptslope[1] = 1; if( ms == MediaStorage::CTImageStorage || ms == MediaStorage::ComputedRadiographyImageStorage || ms == MediaStorage::PETImageStorage || ms == MediaStorage::SecondaryCaptureImageStorage || ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage || ForceRescaleInterceptSlope ) { bool b = GetRescaleInterceptSlopeValueFromDataSet(ds, interceptslope); if( !b ) { gdcmDebugMacro( "No Modality LUT found (Rescale Intercept/Slope)" ); } } else if ( ms == MediaStorage::MRImageStorage ) { #if 0 const Tag trwvms(0x0040,0x9096); // Real World Value Mapping Sequence if( ds.FindDataElement( trwvms ) ) { SmartPointer sqi = ds.GetDataElement( trwvms ).GetValueAsSQ(); if( sqi ) { const Tag trwvlutd(0x0040,0x9212); // Real World Value LUT Data if( ds.FindDataElement( trwvlutd ) ) { gdcmAssertAlwaysMacro(0); // Not supported ! } // don't know how to handle multiples: gdcmAssertAlwaysMacro( sqi->GetNumberOfItems() == 1 ); const Item &item = sqi->GetItem(1); const DataSet & subds = item.GetNestedDataSet(); //const Tag trwvi(0x0040,0x9224); // Real World Value Intercept //const Tag trwvs(0x0040,0x9225); // Real World Value Slope Attribute<0x0040,0x9224> at1 = {0}; at1.SetFromDataSet( subds ); Attribute<0x0040,0x9225> at2 = {1}; at2.SetFromDataSet( subds ); interceptslope[0] = at1.GetValue(); interceptslope[1] = at2.GetValue(); } } #else // See the long thread at: // https://groups.google.com/d/msg/comp.protocols.dicom/M4kdqcrs50Y/_TSx0EjtAQAJ // in particular this paper: // Errors in Quantitative Image Analysis due to Platform-Dependent Image Scaling // http://www.ncbi.nlm.nih.gov/pmc/articles/PMC3998685/ const PrivateTag tpriv_rescaleintercept( 0x2005,0x09,"Philips MR Imaging DD 005" ); const PrivateTag tpriv_rescaleslope( 0x2005,0x0a,"Philips MR Imaging DD 005" ); if( ds.FindDataElement( tpriv_rescaleintercept ) && ds.FindDataElement( tpriv_rescaleslope ) ) { // The following will work out of the box for Philips whether or not // "Combine MR Rescaling" was set: // PMS DICOM CS states that Modality LUT for MR Image Storage is to be // used for image processing. VOI LUT are always recomputed, so output // from GDCM may not look right for display (sorry!) const DataElement &priv_rescaleintercept = ds.GetDataElement( tpriv_rescaleintercept ); const DataElement &priv_rescaleslope = ds.GetDataElement( tpriv_rescaleslope ); Element el_ri = {{ 0 }}; el_ri.SetFromDataElement( priv_rescaleintercept ); Element el_rs = {{ 1 }}; el_rs.SetFromDataElement( priv_rescaleslope ); if( PMSRescaleInterceptSlope ) { interceptslope[0] = el_ri.GetValue(); 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] << "]" ); } } else { 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] << "]" ); } } #endif } else if ( ms == MediaStorage::RTDoseStorage ) { // TODO. Should I check FrameIncrementPointer ? (0028,0009) AT (3004,000c) Attribute<0x3004,0x000e> gridscaling = { 0 }; gridscaling.SetFromDataSet( ds ); interceptslope[0] = 0; interceptslope[1] = gridscaling.GetValue(); if( interceptslope[1] == 0 ) { // come' on ! WTF gdcmWarningMacro( "Cannot have slope == 0. Defaulting to 1.0 instead" ); interceptslope[1] = 1; } } // \post condition slope can never be 0: assert( interceptslope[1] != 0. ); return interceptslope; } Tag ImageHelper::GetSpacingTagFromMediaStorage(MediaStorage const &ms) { Tag t; // gdcmData/MR00010001.dcm => GeneralElectricMagneticResonanceImageStorage // (0018,0088) DS [] # 4, 1 SpacingBetweenSlices // (0028,0030) DS [ 0.8593750000\0.8593750000] # 26, 2 PixelSpacing switch(ms) { case MediaStorage::EnhancedUSVolumeStorage: // Enhanced stuff are handled elsewhere... look carefully :) //case MediaStorage::EnhancedMRImageStorage: //case MediaStorage::EnhancedCTImageStorage: //case MediaStorage::XRay3DAngiographicImageStorage //case MediaStorage::XRay3DCraniofacialImageStorage // gdcmWarningMacro( "Enhanced image are not currently supported. Spacing will be wrong" ); case MediaStorage::CTImageStorage: case MediaStorage::MRImageStorage: case MediaStorage::RTDoseStorage: case MediaStorage::NuclearMedicineImageStorage: case MediaStorage::PETImageStorage: case MediaStorage::GeneralElectricMagneticResonanceImageStorage: case MediaStorage::PhilipsPrivateMRSyntheticImageStorage: case MediaStorage::VLPhotographicImageStorage: // VL Image IOD case MediaStorage::VLMicroscopicImageStorage: case MediaStorage::IVOCTForProcessing: case MediaStorage::IVOCTForPresentation: // (0028,0030) DS [2.0\2.0] # 8, 2 PixelSpacing t = Tag(0x0028,0x0030); break; case MediaStorage::ComputedRadiographyImageStorage: // See pixelspacingtestimages/DISCIMG/IMAGES/CRIMAGE case MediaStorage::DigitalXRayImageStorageForPresentation: case MediaStorage::DigitalXRayImageStorageForProcessing: case MediaStorage::DigitalMammographyImageStorageForPresentation: case MediaStorage::DigitalMammographyImageStorageForProcessing: case MediaStorage::DigitalIntraoralXrayImageStorageForPresentation: case MediaStorage::DigitalIntraoralXRayImageStorageForProcessing: case MediaStorage::XRayAngiographicImageStorage: case MediaStorage::XRayRadiofluoroscopingImageStorage: case MediaStorage::XRayAngiographicBiPlaneImageStorageRetired: case MediaStorage::FujiPrivateMammoCRImageStorage: // (0018,1164) DS [0.5\0.5] # 8, 2 ImagerPixelSpacing t = Tag(0x0018,0x1164); break; case MediaStorage::RTImageStorage: // gdcmData/SYNGORTImage.dcm t = Tag(0x3002,0x0011); // ImagePlanePixelSpacing break; case MediaStorage::SecondaryCaptureImageStorage: case MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage: case MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage: case MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage: case MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage: // See PS 3.3-2008. Table C.8-25 SC IMAGE MODULE ATTRIBUTES // and Table C.8-25b SC MULTI-FRAME IMAGE MODULE ATTRIBUTES t = Tag(0x0018,0x2010); break; case MediaStorage::HardcopyGrayscaleImageStorage: case MediaStorage::HardcopyColorImageStorage: t = Tag(0x0018,0x2010); // Nominal Scanned Pixel Spacing break; case MediaStorage::GEPrivate3DModelStorage: // FIXME FIXME !!! case MediaStorage::Philips3D: case MediaStorage::VideoEndoscopicImageStorage: gdcmWarningMacro( "FIXME" ); t = Tag(0xffff,0xffff); break; case MediaStorage::UltrasoundMultiFrameImageStorage: // gdcmData/US-MONO2-8-8x-execho.dcm // this should be handled somewhere else //assert(0); gdcmWarningMacro( "FIXME" ); t = Tag(0xffff,0xffff); break; case MediaStorage::UltrasoundImageStorage: // ?? case MediaStorage::UltrasoundImageStorageRetired: case MediaStorage::UltrasoundMultiFrameImageStorageRetired: // (0028,0034) IS [4\3] # 4, 2 PixelAspectRatio t = Tag(0xffff,0xffff); // FIXME t = Tag(0x0028,0x0034); // FIXME break; default: gdcmDebugMacro( "Do not handle: " << ms ); t = Tag(0xffff,0xffff); break; } // should only override unless Modality set it already // basically only Secondary Capture should reach that point if( ForcePixelSpacing && t == Tag(0xffff,0xffff) ) { t = Tag(0x0028,0x0030); } return t; } Tag ImageHelper::GetZSpacingTagFromMediaStorage(MediaStorage const &ms) { Tag t; switch(ms) { case MediaStorage::EnhancedUSVolumeStorage: case MediaStorage::MRImageStorage: case MediaStorage::NuclearMedicineImageStorage: // gdcmData/Nm.dcm case MediaStorage::GeneralElectricMagneticResonanceImageStorage: // (0018,0088) DS [3] # 2, 1 SpacingBetweenSlices t = Tag(0x0018,0x0088); break; // No spacing AFAIK for those: /* $ dciodvfy gdcmData/D_CLUNIE_CT1_JPLL.dcm CTImage Warning - Attribute is not present in standard DICOM IOD - (0x0018,0x0088) DS Spacing Between Slices Warning - Dicom dataset contains attributes not present in standard DICOM IOD - this is a Standard Extended SOP Class */ case MediaStorage::PETImageStorage: // ?? case MediaStorage::CTImageStorage: case MediaStorage::RTImageStorage: // ImagerPixelSpacing section: case MediaStorage::ComputedRadiographyImageStorage: // ?? case MediaStorage::DigitalXRayImageStorageForPresentation: case MediaStorage::DigitalXRayImageStorageForProcessing: case MediaStorage::DigitalMammographyImageStorageForPresentation: case MediaStorage::DigitalMammographyImageStorageForProcessing: case MediaStorage::DigitalIntraoralXrayImageStorageForPresentation: case MediaStorage::DigitalIntraoralXRayImageStorageForProcessing: case MediaStorage::XRayAngiographicImageStorage: case MediaStorage::XRayRadiofluoroscopingImageStorage: case MediaStorage::XRayAngiographicBiPlaneImageStorageRetired: // US: case MediaStorage::UltrasoundImageStorage: case MediaStorage::UltrasoundMultiFrameImageStorage: case MediaStorage::UltrasoundImageStorageRetired: case MediaStorage::UltrasoundMultiFrameImageStorageRetired: // SC: case MediaStorage::SecondaryCaptureImageStorage: case MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage: case MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage: case MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage: case MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage: case MediaStorage::HardcopyGrayscaleImageStorage: t = Tag(0xffff,0xffff); break; case MediaStorage::RTDoseStorage: // gdcmData/BogugsItemAndSequenceLengthCorrected.dcm t = Tag(0x3004,0x000c); break; case MediaStorage::GEPrivate3DModelStorage: case MediaStorage::Philips3D: case MediaStorage::VideoEndoscopicImageStorage: gdcmWarningMacro( "FIXME" ); t = Tag(0xffff,0xffff); break; default: gdcmDebugMacro( "Do not handle Z spacing for: " << ms ); t = Tag(0xffff,0xffff); break; } if( ForcePixelSpacing && t == Tag(0xffff,0xffff) ) { t = Tag(0x0018,0x0088); } return t; } std::vector ImageHelper::GetSpacingValue(File const & f) { std::vector sp; sp.reserve(3); MediaStorage ms; ms.SetFromFile(f); const DataSet& ds = f.GetDataSet(); if( ms == MediaStorage::EnhancedCTImageStorage || ms == MediaStorage::EnhancedMRImageStorage || ms == MediaStorage::EnhancedMRColorImageStorage || ms == MediaStorage::EnhancedPETImageStorage || ms == MediaStorage::OphthalmicTomographyImageStorage || ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage || ms == MediaStorage::XRay3DAngiographicImageStorage || ms == MediaStorage::XRay3DCraniofacialImageStorage || ms == MediaStorage::SegmentationStorage || ms == MediaStorage::IVOCTForProcessing || ms == MediaStorage::IVOCTForPresentation || ms == MediaStorage::BreastTomosynthesisImageStorage || ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation || ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing || ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage || ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage || ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage) { // const Tag t1(0x5200,0x9229); const Tag t2(0x5200,0x9230); if( GetSpacingValueFromSequence(ds,t1, sp) || GetSpacingValueFromSequence(ds, t2, sp) ) { assert( sp.size() == 3 ); return sp; } // Else. // How do I send an error ? sp.resize( 3 ); // FIXME !! sp[0] = 1.; sp[1] = 1.; sp[2] = 1.; gdcmWarningMacro( "Could not find Spacing" ); return sp; } else if( ms == MediaStorage::UltrasoundMultiFrameImageStorage || ms == MediaStorage::UltrasoundImageStorage ) { if( GetUltraSoundSpacingValueFromSequence(ds, sp) ) { // 3rd dimension is too difficult to handle for now... // (0018,1065) DS [0\ 957\ 990\ 990\1023\1023\ 990\ 990\1023\ 957\1023\1023\1023\ 990... # 562,113 FrameTimeVector sp.push_back( 1.0 ); return sp; } else { // TODO this one is easy: // (0028,0009) AT (0018,1063) # 4, 1 FrameIncrementPointer // -> (0018,1063) DS [76.000000] # 10, 1 FrameTime gdcmWarningMacro( "No spacing value found" ); sp.push_back( 1.0 ); sp.push_back( 1.0 ); sp.push_back( 1.0 ); return sp; } } Tag spacingtag = GetSpacingTagFromMediaStorage(ms); if( spacingtag != Tag(0xffff,0xffff) && ds.FindDataElement( spacingtag ) && !ds.GetDataElement( spacingtag ).IsEmpty() ) { const DataElement& de = ds.GetDataElement( spacingtag ); const Global &g = GlobalInstance; const Dicts &dicts = g.GetDicts(); const DictEntry &entry = dicts.GetDictEntry(de.GetTag()); const VR & vr = entry.GetVR(); assert( vr.Compatible( de.GetVR() ) ); switch(vr) { case VR::DS: { Element el; std::stringstream ss; const ByteValue *bv = de.GetByteValue(); assert( bv ); std::string s = std::string( bv->GetPointer(), bv->GetLength() ); ss.str( s ); // Stupid file: CT-MONO2-8-abdo.dcm // The spacing is something like that: [0.2\0\0.200000] // I would need to throw an exception that VM is not compatible el.SetLength( entry.GetVM().GetLength() * entry.GetVR().GetSizeof() ); std::string::size_type found = s.find('\\'); if( found != std::string::npos ) { el.Read( ss ); assert( el.GetLength() == 2 ); for(unsigned int i = 0; i < el.GetLength(); ++i) { if( el.GetValue(i) ) { sp.push_back( el.GetValue(i) ); } else { gdcmWarningMacro( "Cannot have a spacing of 0" ); sp.push_back( 1.0 ); } } std::swap( sp[0], sp[1]); } else { double singleval; ss >> singleval; if( singleval == 0.0 ) { singleval = 1.0; } sp.push_back( singleval ); sp.push_back( singleval ); } assert( sp.size() == (unsigned int)entry.GetVM() ); } break; case VR::IS: { Element el; std::stringstream ss; const ByteValue *bv = de.GetByteValue(); assert( bv ); std::string s = std::string( bv->GetPointer(), bv->GetLength() ); ss.str( s ); el.SetLength( entry.GetVM().GetLength() * entry.GetVR().GetSizeof() ); el.Read( ss ); for(unsigned int i = 0; i < el.GetLength(); ++i) { if( el.GetValue(i) ) sp.push_back( el.GetValue(i) ); else { gdcmWarningMacro( "Cannot have a spacing of 0" ); sp.push_back( 1.0 ); } } std::swap( sp[0], sp[1]); assert( sp.size() == (unsigned int)entry.GetVM() ); } break; default: assert(0); break; } } else { sp.push_back( 1.0 ); sp.push_back( 1.0 ); } assert( sp.size() == 2 ); // Make sure multiframe: std::vector dims = ImageHelper::GetDimensionsValue( f ); // Do Z: Tag zspacingtag = ImageHelper::GetZSpacingTagFromMediaStorage(ms); if( zspacingtag != Tag(0xffff,0xffff) && ds.FindDataElement( zspacingtag ) ) { const DataElement& de = ds.GetDataElement( zspacingtag ); if( de.IsEmpty() ) { sp.push_back( 1.0 ); } else { const Global &g = GlobalInstance; const Dicts &dicts = g.GetDicts(); const DictEntry &entry = dicts.GetDictEntry(de.GetTag()); const VR & vr = entry.GetVR(); assert( de.GetVR() == vr || de.GetVR() == VR::INVALID || de.GetVR() == VR::UN ); if( entry.GetVM() == VM::VM1 ) { switch(vr) { case VR::DS: { Element el; std::stringstream ss; const ByteValue *bv = de.GetByteValue(); assert( bv ); std::string s = std::string( bv->GetPointer(), bv->GetLength() ); ss.str( s ); el.SetLength( entry.GetVM().GetLength() * entry.GetVR().GetSizeof() ); el.Read( ss ); for(unsigned int i = 0; i < el.GetLength(); ++i) { const double value = el.GetValue(i); sp.push_back( value ); } //assert( sp.size() == entry.GetVM() ); } break; default: assert(0); break; } } else { assert( entry.GetVM() == VM::VM2_n ); assert( vr == VR::DS ); Attribute<0x28,0x8> numberoframes; const DataElement& de1 = ds.GetDataElement( numberoframes.GetTag() ); numberoframes.SetFromDataElement( de1 ); Attribute<0x3004,0x000c> gridframeoffsetvector; const DataElement& de2 = ds.GetDataElement( gridframeoffsetvector.GetTag() ); gridframeoffsetvector.SetFromDataElement( de2 ); double v1 = gridframeoffsetvector[0]; double v2 = gridframeoffsetvector[1]; // FIXME. I should check consistency sp.push_back( v2 - v1 ); } } } else if( ds.FindDataElement( Tag(0x0028,0x0009) ) ) // Frame Increment Pointer { const DataElement& de = ds.GetDataElement( Tag(0x0028,0x0009) ); Attribute<0x0028,0x0009,VR::AT,VM::VM1> at; at.SetFromDataElement( de ); assert( ds.FindDataElement( at.GetTag() ) ); if( ds.FindDataElement( at.GetValue() ) ) { /* $ dcmdump D_CLUNIE_NM1_JPLL.dcm" | grep 0028,0009 (0028,0009) AT (0054,0010)\(0054,0020) # 8, 2 FrameIncrementPointer */ const DataElement& de2 = ds.GetDataElement( at.GetValue() ); if( at.GetValue() == Tag(0x0018,0x1063) && at.GetNumberOfValues() == 1 ) { Attribute<0x0018,0x1063> at2; at2.SetFromDataElement( de2 ); if( dims[2] > 1 ) { sp.push_back( at2.GetValue() ); } else { if( at2.GetValue() != 0. ) { gdcmErrorMacro( "Number of Frame should be equal to 0" ); sp.push_back( 0.0 ); } else { sp.push_back( 1.0 ); } } } else { gdcmWarningMacro( "Don't know how to handle spacing for: " << de ); sp.push_back( 1.0 ); } } else { gdcmErrorMacro( "Tag: " << at.GetTag() << " was found to point to missing" "Tag: " << at.GetValue() << " default to 1.0." ); sp.push_back( 1.0 ); } } else { sp.push_back( 1.0 ); } assert( sp.size() == 3 ); assert( sp[0] != 0. ); assert( sp[1] != 0. ); //if( ms != MediaStorage::MRImageStorage ) // assert( sp[2] != 0. ); return sp; } void ImageHelper::SetSpacingValue(DataSet & ds, const std::vector & spacing) { MediaStorage ms; ms.SetFromDataSet(ds); assert( MediaStorage::IsImage( ms ) ); if( ms == MediaStorage::SecondaryCaptureImageStorage ) { Tag pixelspacing(0x0028,0x0030); Tag imagerpixelspacing(0x0018,0x1164); Tag spacingbetweenslice(0x0018,0x0088); //ds.Remove( pixelspacing ); //ds.Remove( imagerpixelspacing ); //ds.Remove( spacingbetweenslice ); //return; } assert( spacing.size() == 3 ); if( ms == MediaStorage::EnhancedCTImageStorage || ms == MediaStorage::EnhancedMRImageStorage || ms == MediaStorage::EnhancedMRColorImageStorage || ms == MediaStorage::EnhancedPETImageStorage || ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage || ms == MediaStorage::XRay3DAngiographicImageStorage || ms == MediaStorage::XRay3DCraniofacialImageStorage || ms == MediaStorage::SegmentationStorage || ms == MediaStorage::IVOCTForPresentation || ms == MediaStorage::IVOCTForProcessing || ms == MediaStorage::BreastTomosynthesisImageStorage || ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation || ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing || ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage || ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage || ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage ) { /* (0028,9110) SQ (Sequence with undefined length #=1) # u/l, 1 PixelMeasuresSequence (fffe,e000) na (Item with undefined length #=2) # u/l, 1 Item (0018,0050) DS [5.00000] # 8, 1 SliceThickness (0028,0030) DS [0.820312\0.820312] # 18, 2 PixelSpacing (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem */ { const Tag tfgs(0x5200,0x9229); SmartPointer sqi = InsertOrReplaceSQ( ds, tfgs ); if( !sqi->GetNumberOfItems() ) { Item item; //( Tag(0xfffe,0xe000) ); sqi->AddItem( item ); } Item &item1 = sqi->GetItem(1); item1.SetVLToUndefined(); DataSet &subds = item1.GetNestedDataSet(); const Tag tpms(0x0028,0x9110); sqi = InsertOrReplaceSQ( subds, tpms ); if( !sqi->GetNumberOfItems() ) { Item item; //( Tag(0xfffe,0xe000) ); sqi->AddItem( item ); } Item &item2 = sqi->GetItem(1); item2.SetVLToUndefined(); DataSet &subds2 = item2.GetNestedDataSet(); // // do not set spacing between slices since GDCM always recompute it from the IOP/IPP Attribute<0x0018,0x0088> at2; at2.SetValue( fabs(spacing[2]) ); Attribute<0x0028,0x0030> at1; at1.SetValue( spacing[1], 0 ); at1.SetValue( spacing[0], 1 ); subds2.Replace( at1.GetAsDataElement() ); subds2.Replace( at2.GetAsDataElement() ); } // cleanup per-frame { const Tag tfgs(0x5200,0x9230); if( ds.FindDataElement( tfgs ) ) { SmartPointer sqi = InsertOrReplaceSQ( ds, tfgs ); SequenceOfItems::SizeType nitems = sqi->GetNumberOfItems(); for(SequenceOfItems::SizeType i0 = 1; i0 <= nitems; ++i0) { Item &item = sqi->GetItem(i0); item.SetVLToUndefined(); DataSet & subds = item.GetNestedDataSet(); const Tag tpms(0x0028,0x9110); subds.Remove(tpms); } } } // cleanup root (famous MR -> EMR case) { const Tag t1(0x0018,0x0088); ds.Remove(t1); const Tag t2(0x0028,0x0030); ds.Remove(t2); } return; } else if( ms == MediaStorage::UltrasoundMultiFrameImageStorage || ms == MediaStorage::UltrasoundImageStorage ) { SetUltraSoundSpacingValueFromSequence(ds, spacing); return; } Tag spacingtag = GetSpacingTagFromMediaStorage(ms); Tag zspacingtag = GetZSpacingTagFromMediaStorage(ms); //std::vector spacingtags; //spacingtags.push_back( spacingtag ); //spacingtags.push_back( zspacingtag ); { const Tag ¤tspacing = spacingtag; if( currentspacing != Tag(0xffff,0xffff) ) { DataElement de( currentspacing ); const Global &g = GlobalInstance; const Dicts &dicts = g.GetDicts(); const DictEntry &entry = dicts.GetDictEntry(de.GetTag()); const VR & vr = entry.GetVR(); const VM & vm = entry.GetVM(); (void)vm; assert( de.GetVR() == vr || de.GetVR() == VR::INVALID ); switch(vr) { case VR::DS: { Element el; el.SetLength( entry.GetVM().GetLength() * vr.GetSizeof() ); assert( entry.GetVM() == VM::VM2 ); for( unsigned int i = 0; i < entry.GetVM().GetLength(); ++i) { el.SetValue( spacing[i], i ); } el.SetValue( spacing[1], 0 ); el.SetValue( spacing[0], 1 ); //assert( el.GetValue(0) == spacing[0] && el.GetValue(1) == spacing[1] ); std::stringstream os; el.Write( os ); de.SetVR( VR::DS ); if( os.str().size() % 2 ) os << " "; VL::Type osStrSize = (VL::Type)os.str().size(); de.SetByteValue( os.str().c_str(),osStrSize ); ds.Replace( de ); } break; case VR::IS: { Element el; el.SetLength( entry.GetVM().GetLength() * vr.GetSizeof() ); assert( entry.GetVM() == VM::VM2 ); for( unsigned int i = 0; i < entry.GetVM().GetLength(); ++i) { el.SetValue( (int)spacing[i], i ); } //assert( el.GetValue(0) == spacing[0] && el.GetValue(1) == spacing[1] ); std::stringstream os; el.Write( os ); de.SetVR( VR::IS ); if( os.str().size() % 2 ) os << " "; VL::Type osStrSize = (VL::Type)os.str().size(); de.SetByteValue( os.str().c_str(), osStrSize ); ds.Replace( de ); } break; default: assert(0); } } } { const Tag ¤tspacing = zspacingtag; if( currentspacing != Tag(0xffff,0xffff) ) { DataElement de( currentspacing ); const Global &g = GlobalInstance; const Dicts &dicts = g.GetDicts(); const DictEntry &entry = dicts.GetDictEntry(de.GetTag()); const VR & vr = entry.GetVR(); const VM & vm = entry.GetVM(); (void)vm; assert( de.GetVR() == vr || de.GetVR() == VR::INVALID ); if( entry.GetVM() == VM::VM2_n ) { assert( vr == VR::DS ); assert( de.GetTag() == Tag(0x3004,0x000c) ); Attribute<0x28,0x8> numberoframes; // Make we are multiframes: if( ds.FindDataElement( numberoframes.GetTag() ) ) { const DataElement& de1 = ds.GetDataElement( numberoframes.GetTag() ); numberoframes.SetFromDataElement( de1 ); Element el; el.SetLength( numberoframes.GetValue() * vr.GetSizeof() ); assert( entry.GetVM() == VM::VM2_n ); double spacing_start = 0; assert( 0 < numberoframes.GetValue() ); for( int i = 0; i < numberoframes.GetValue(); ++i) { el.SetValue( spacing_start, i ); spacing_start += spacing[2]; } //assert( el.GetValue(0) == spacing[0] && el.GetValue(1) == spacing[1] ); std::stringstream os; el.Write( os ); de.SetVR( VR::DS ); if( os.str().size() % 2 ) os << " "; VL::Type osStrSize = (VL::Type)os.str().size(); de.SetByteValue( os.str().c_str(), osStrSize ); ds.Replace( de ); } } else { switch(vr) { case VR::DS: { Element el; el.SetLength( entry.GetVM().GetLength() * vr.GetSizeof() ); assert( entry.GetVM() == VM::VM1 ); for( unsigned int i = 0; i < entry.GetVM().GetLength(); ++i) { el.SetValue( spacing[i+2], i ); } //assert( el.GetValue(0) == spacing[0] && el.GetValue(1) == spacing[1] ); std::stringstream os; el.Write( os ); de.SetVR( VR::DS ); if( os.str().size() % 2 ) os << " "; VL::Type osStrSize = (VL::Type)os.str().size(); de.SetByteValue( os.str().c_str(), osStrSize ); ds.Replace( de ); } break; default: assert(0); } } } } } static void SetDataElementInSQAsItemNumber(DataSet & ds, DataElement const & de, Tag const & sqtag, unsigned int itemidx) { const Tag tfgs = sqtag; //(0x5200,0x9230); SmartPointer sqi = InsertOrReplaceSQ( ds, tfgs ); if( sqi->GetNumberOfItems() < itemidx ) { Item item; //( Tag(0xfffe,0xe000) ); sqi->AddItem( item ); } Item &item1 = sqi->GetItem(itemidx); item1.SetVLToUndefined(); DataSet &subds = item1.GetNestedDataSet(); const Tag tpms(0x0020,0x9113); sqi = InsertOrReplaceSQ( subds, tpms ); if( !sqi->GetNumberOfItems() ) { Item item; //( Tag(0xfffe,0xe000) ); sqi->AddItem( item ); } Item &item2 = sqi->GetItem(1); item2.SetVLToUndefined(); DataSet &subds2 = item2.GetNestedDataSet(); //Attribute<0x0020,0x0032> ipp = {{0,0,0}}; // default value //ipp.SetValue( origin[0], 0); //ipp.SetValue( origin[1], 1); //ipp.SetValue( origin[2], 2); subds2.Replace( de ); } void ImageHelper::SetOriginValue(DataSet & ds, const Image & image) { const double *origin = image.GetOrigin(); //assert( origin.size() == 3 ); MediaStorage ms; ms.SetFromDataSet(ds); assert( MediaStorage::IsImage( ms ) ); if( ms == MediaStorage::SecondaryCaptureImageStorage ) { // https://sourceforge.net/p/gdcm/bugs/322/ // default behavior is simply to pass return; } // FIXME Hardcoded if( ms != MediaStorage::CTImageStorage && ms != MediaStorage::MRImageStorage && ms != MediaStorage::RTDoseStorage && ms != MediaStorage::PETImageStorage //&& ms != MediaStorage::ComputedRadiographyImageStorage && ms != MediaStorage::SegmentationStorage && ms != MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage && ms != MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage && ms != MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage && ms != MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage && ms != MediaStorage::XRay3DAngiographicImageStorage && ms != MediaStorage::XRay3DCraniofacialImageStorage && ms != MediaStorage::EnhancedMRImageStorage && ms != MediaStorage::EnhancedMRColorImageStorage && ms != MediaStorage::EnhancedPETImageStorage && ms != MediaStorage::EnhancedCTImageStorage && ms != MediaStorage::IVOCTForPresentation && ms != MediaStorage::IVOCTForProcessing && ms != MediaStorage::BreastTomosynthesisImageStorage && ms != MediaStorage::BreastProjectionXRayImageStorageForPresentation && ms != MediaStorage::BreastProjectionXRayImageStorageForProcessing && ms != MediaStorage::LegacyConvertedEnhancedMRImageStorage && ms != MediaStorage::LegacyConvertedEnhancedCTImageStorage && ms != MediaStorage::LegacyConvertedEnhancedPETImageStorage ) { // FIXME: should I remove the ipp tag ??? return; } if( ms == MediaStorage::EnhancedCTImageStorage || ms == MediaStorage::EnhancedMRImageStorage || ms == MediaStorage::EnhancedMRColorImageStorage || ms == MediaStorage::EnhancedPETImageStorage || ms == MediaStorage::XRay3DAngiographicImageStorage || ms == MediaStorage::XRay3DCraniofacialImageStorage || ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage || ms == MediaStorage::SegmentationStorage || ms == MediaStorage::IVOCTForPresentation || ms == MediaStorage::IVOCTForProcessing || ms == MediaStorage::BreastTomosynthesisImageStorage || ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation || ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing || ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage || ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage || ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage) { /* (0020,9113) SQ (Sequence with undefined length #=1) # u/l, 1 PlanePositionSequence (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item (0020,0032) DS [40.0000\-105.000\105.000] # 24, 3 ImagePositionPatient (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem */ const Tag tfgs(0x5200,0x9230); Attribute<0x0020,0x0032> ipp = {{0,0,0}}; // default value double zspacing = image.GetSpacing(2); unsigned int dimz = image.GetDimension(2); const double *cosines = image.GetDirectionCosines(); DirectionCosines dc( cosines ); double normal[3]; dc.Cross( normal ); for(unsigned int i = 0; i < dimz; ++i ) { double new_origin[3]; for (int j = 0; j < 3; j++) { // the n'th slice is n * z-spacing aloung the IOP-derived // z-axis new_origin[j] = origin[j] + normal[j] * i * zspacing; } ipp.SetValue( new_origin[0], 0); ipp.SetValue( new_origin[1], 1); ipp.SetValue( new_origin[2], 2); SetDataElementInSQAsItemNumber(ds, ipp.GetAsDataElement(), tfgs, i+1); } // cleanup the sharedgroup: { const Tag tfgs0(0x5200,0x9229); if( ds.FindDataElement( tfgs0 ) ) { SmartPointer sqi = ds.GetDataElement( tfgs0 ).GetValueAsSQ(); assert( sqi ); SequenceOfItems::SizeType nitems = sqi->GetNumberOfItems(); for(SequenceOfItems::SizeType i0 = 1; i0 <= nitems; ++i0) { // Get first item: Item &item = sqi->GetItem(i0); item.SetVLToUndefined(); DataSet & subds = item.GetNestedDataSet(); const Tag tpms(0x0020,0x9113); subds.Remove(tpms); } } } // Cleanup root level: { const Tag tiop(0x0020,0x0032); ds.Remove(tiop); } // C.7.6.6.1.2 Frame Increment Pointer // (0028,0009) AT (0018,2005) # 4,1-n Frame Increment Pointer if( ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage ) { if( dimz > 1 ) { Attribute<0x0028,0x0009> fip; fip.SetNumberOfValues( 1 ); fip.SetValue( tfgs ); ds.Replace( fip.GetAsDataElement() ); } } return; } // Image Position (Patient) Attribute<0x0020,0x0032> ipp = {{0,0,0}}; // default value ipp.SetValue( origin[0], 0); ipp.SetValue( origin[1], 1); ipp.SetValue( origin[2], 2); ds.Replace( ipp.GetAsDataElement() ); } void ImageHelper::SetDirectionCosinesValue(DataSet & ds, const std::vector & dircos) { MediaStorage ms; ms.SetFromDataSet(ds); assert( MediaStorage::IsImage( ms ) ); if( ms == MediaStorage::SecondaryCaptureImageStorage ) { // https://sourceforge.net/p/gdcm/bugs/322/ // default behavior is simply to pass return; } // FIXME Hardcoded if( ms != MediaStorage::CTImageStorage && ms != MediaStorage::MRImageStorage && ms != MediaStorage::RTDoseStorage && ms != MediaStorage::PETImageStorage //&& ms != MediaStorage::ComputedRadiographyImageStorage && ms != MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage && ms != MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage && ms != MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage && ms != MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage && ms != MediaStorage::SegmentationStorage && ms != MediaStorage::XRay3DAngiographicImageStorage && ms != MediaStorage::XRay3DCraniofacialImageStorage && ms != MediaStorage::EnhancedMRImageStorage && ms != MediaStorage::EnhancedMRColorImageStorage && ms != MediaStorage::EnhancedPETImageStorage && ms != MediaStorage::EnhancedCTImageStorage && ms != MediaStorage::IVOCTForPresentation && ms != MediaStorage::IVOCTForProcessing && ms != MediaStorage::BreastTomosynthesisImageStorage && ms != MediaStorage::BreastProjectionXRayImageStorageForPresentation && ms != MediaStorage::BreastProjectionXRayImageStorageForProcessing && ms != MediaStorage::LegacyConvertedEnhancedMRImageStorage && ms != MediaStorage::LegacyConvertedEnhancedCTImageStorage && ms != MediaStorage::LegacyConvertedEnhancedPETImageStorage ) { // FIXME: should I remove the iop tag ??? return; } // Image Orientation (Patient) Attribute<0x0020,0x0037> iop = {{1,0,0,0,1,0}}; // default value assert( dircos.size() == 6 ); DirectionCosines dc( &dircos[0] ); if( !dc.IsValid() ) { gdcmWarningMacro( "Direction Cosines are not valid. Using default value (1\\0\\0\\0\\1\\0)" ); } else { iop.SetValue( dircos[0], 0); iop.SetValue( dircos[1], 1); iop.SetValue( dircos[2], 2); iop.SetValue( dircos[3], 3); iop.SetValue( dircos[4], 4); iop.SetValue( dircos[5], 5); } if( ms == MediaStorage::EnhancedCTImageStorage || ms == MediaStorage::EnhancedMRImageStorage || ms == MediaStorage::EnhancedMRColorImageStorage || ms == MediaStorage::EnhancedPETImageStorage || ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage || ms == MediaStorage::XRay3DAngiographicImageStorage || ms == MediaStorage::XRay3DCraniofacialImageStorage || ms == MediaStorage::SegmentationStorage || ms == MediaStorage::IVOCTForPresentation || ms == MediaStorage::IVOCTForProcessing || ms == MediaStorage::BreastTomosynthesisImageStorage || ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation || ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing || ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage || ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage || ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage ) { /* (0020,9116) SQ (Sequence with undefined length #=1) # u/l, 1 PlaneOrientationSequence (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item (0020,0037) DS [0.00000\1.00000\0.00000\0.00000\0.00000\-1.00000] # 48, 6 ImageOrientationPatient (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem */ { const Tag tfgs(0x5200,0x9229); SmartPointer sqi = InsertOrReplaceSQ( ds, tfgs ); if( !sqi->GetNumberOfItems() ) { Item item; //( Tag(0xfffe,0xe000) ); sqi->AddItem( item ); } Item &item1 = sqi->GetItem(1); item1.SetVLToUndefined(); DataSet &subds = item1.GetNestedDataSet(); const Tag tpms(0x0020,0x9116); sqi = InsertOrReplaceSQ( subds, tpms ); if( !sqi->GetNumberOfItems() ) { Item item; //( Tag(0xfffe,0xe000) ); sqi->AddItem( item ); } Item &item2 = sqi->GetItem(1); item2.SetVLToUndefined(); DataSet &subds2 = item2.GetNestedDataSet(); subds2.Replace( iop.GetAsDataElement() ); } // cleanup per-frame { const Tag tfgs(0x5200,0x9230); if( ds.FindDataElement( tfgs ) ) { SmartPointer sqi = ds.GetDataElement( tfgs ).GetValueAsSQ(); assert( sqi ); SequenceOfItems::SizeType nitems = sqi->GetNumberOfItems(); for(SequenceOfItems::SizeType i0 = 1; i0 <= nitems; ++i0) { // Get first item: Item &item = sqi->GetItem(i0); item.SetVLToUndefined(); DataSet & subds = item.GetNestedDataSet(); const Tag tpms(0x0020,0x9116); subds.Remove(tpms); } } } // Cleanup root level: { const Tag tiop(0x0020,0x0037); ds.Remove(tiop); } return; } ds.Replace( iop.GetAsDataElement() ); } void ImageHelper::SetRescaleInterceptSlopeValue(File & f, const Image & img) { MediaStorage ms; // SetFromFile is required here, SetFromDataSet is not enough for all cases ms.SetFromFile(f); assert( MediaStorage::IsImage( ms ) ); DataSet &ds = f.GetDataSet(); // FIXME Hardcoded if( ms != MediaStorage::CTImageStorage && ms != MediaStorage::ComputedRadiographyImageStorage && ms != MediaStorage::MRImageStorage // FIXME ! && ms != MediaStorage::PETImageStorage && ms != MediaStorage::RTDoseStorage && ms != MediaStorage::SecondaryCaptureImageStorage && ms != MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage && ms != MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage && ms != MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage && ms != MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage && ms != MediaStorage::EnhancedMRImageStorage /*&& ms != MediaStorage::EnhancedMRColorImageStorage*/ && ms != MediaStorage::EnhancedCTImageStorage && ms != MediaStorage::EnhancedPETImageStorage && ms != MediaStorage::XRay3DAngiographicImageStorage && ms != MediaStorage::XRay3DCraniofacialImageStorage && ms != MediaStorage::SegmentationStorage && ms != MediaStorage::IVOCTForPresentation && ms != MediaStorage::IVOCTForProcessing && ms != MediaStorage::BreastTomosynthesisImageStorage && ms != MediaStorage::BreastProjectionXRayImageStorageForPresentation && ms != MediaStorage::BreastProjectionXRayImageStorageForProcessing && ms != MediaStorage::LegacyConvertedEnhancedMRImageStorage && ms != MediaStorage::LegacyConvertedEnhancedCTImageStorage && ms != MediaStorage::LegacyConvertedEnhancedPETImageStorage ) { if( img.GetIntercept() != 0. || img.GetSlope() != 1. ) { gdcmErrorMacro( "Cannot have non-identity intercept/slope values." ); throw "Impossible"; // Please report } return; } if( ms == MediaStorage::SegmentationStorage ) return; // seg storage cannot have rescale slope if( ms == MediaStorage::EnhancedCTImageStorage || ms == MediaStorage::EnhancedMRImageStorage /*|| ms == MediaStorage::EnhancedMRColorImageStorage*/ || ms == MediaStorage::EnhancedPETImageStorage || ms == MediaStorage::XRay3DAngiographicImageStorage || ms == MediaStorage::XRay3DCraniofacialImageStorage || ms == MediaStorage::BreastTomosynthesisImageStorage || ms == MediaStorage::BreastProjectionXRayImageStorageForPresentation || ms == MediaStorage::BreastProjectionXRayImageStorageForProcessing || ms == MediaStorage::LegacyConvertedEnhancedMRImageStorage || ms == MediaStorage::LegacyConvertedEnhancedCTImageStorage || ms == MediaStorage::LegacyConvertedEnhancedPETImageStorage ) { /* (0020,9116) SQ (Sequence with undefined length #=1) # u/l, 1 PlaneOrientationSequence (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item (0020,0037) DS [0.00000\1.00000\0.00000\0.00000\0.00000\-1.00000] # 48, 6 ImageOrientationPatient (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem */ { const Tag tfgs(0x5200,0x9229); SmartPointer sqi = InsertOrReplaceSQ( ds, tfgs ); if( !sqi->GetNumberOfItems() ) { Item item; //( Tag(0xfffe,0xe000) ); sqi->AddItem( item ); } Item &item1 = sqi->GetItem(1); item1.SetVLToUndefined(); DataSet &subds = item1.GetNestedDataSet(); const Tag tpms(0x0028,0x9145); sqi = InsertOrReplaceSQ( subds, tpms ); if( !sqi->GetNumberOfItems() ) { Item item; //( Tag(0xfffe,0xe000) ); sqi->AddItem( item ); } Item &item2 = sqi->GetItem(1); item2.SetVLToUndefined(); DataSet &subds2 = item2.GetNestedDataSet(); Attribute<0x0028,0x1052> at1; at1.SetValue( img.GetIntercept() ); subds2.Replace( at1.GetAsDataElement() ); Attribute<0x0028,0x1053> at2; at2.SetValue( img.GetSlope() ); subds2.Replace( at2.GetAsDataElement() ); } // cleanup per-frame { const Tag tfgs(0x5200,0x9230); if( ds.FindDataElement( tfgs ) ) { SmartPointer sqi = ds.GetDataElement( tfgs ).GetValueAsSQ(); assert( sqi ); SequenceOfItems::SizeType nitems = sqi->GetNumberOfItems(); for(SequenceOfItems::SizeType i0 = 1; i0 <= nitems; ++i0) { // Get first item: Item &item = sqi->GetItem(i0); DataSet & subds = item.GetNestedDataSet(); // (0028,9145) SQ (Sequence with undefined length) # u/l,1 Pixel Value Transformation Sequence const Tag tpms(0x0028,0x9145); subds.Remove(tpms); } } } // cleanup root (famous MR -> EMR case) { const Tag t1(0x0028,0x1052); ds.Remove(t1); const Tag t2(0x0028,0x1053); ds.Remove(t2); const Tag t3(0x0028,0x1053); ds.Remove(t3); } return; } if( ms == MediaStorage::RTDoseStorage ) { if( img.GetIntercept() != 0 ) { gdcmErrorMacro( "Cannot have an intercept value for RTDOSE, only Scaling allowed" ); return; } Attribute<0x3004,0x00e> at2; at2.SetValue( img.GetSlope() ); ds.Replace( at2.GetAsDataElement() ); Attribute<0x0028,0x0009> framePointer; framePointer.SetNumberOfValues(1); framePointer.SetValue( Tag(0x3004,0x000C) ); ds.Replace( framePointer.GetAsDataElement() ); return; } if( ms == MediaStorage::MRImageStorage ) { #if 0 /* * http://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.7.6.16.2.html#table_C.7.6.16-12b (0040,9096) SQ (Sequence with undefined length) # u/l,1 Real World Value Mapping Sequence (fffe,e000) na (Item with defined length) (0028,3003) LO [Grey Scale LUT] # 14,1 LUT Explanation (0040,08ea) SQ (Sequence with undefined length) # u/l,1 Measurement Units Code Sequence (fffe,e000) na (Item with defined length) (0008,0100) SH [mm2/s ] # 6,1 Code Value (0008,0102) SH [UCUM] # 4,1 Coding Scheme Designator (0008,0103) SH [1.4 ] # 4,1 Coding Scheme Version (0008,0104) LO [mm2/s ] # 6,1 Code Meaning (fffe,e0dd) (0040,9210) SH [GE_GREY ] # 8,1 LUT Label (0040,9211) US 4904 # 2,1 Real World Value Last Value Mapped (0040,9216) US 359 # 2,1 Real World Value First Value Mapped (0040,9224) FD 0 # 8,1 Real World Value Intercept (0040,9225) FD 1e-06 # 8,1 Real World Value Slope */ if( img.GetIntercept() != 0.0 || img.GetSlope() != 1.0 ) { SmartPointer sq = new SequenceOfItems; Item it; DataSet & subds = it.GetNestedDataSet(); Attribute<0x0040,0x9224> at1 = {0}; at1.SetValue( img.GetIntercept() ); Attribute<0x0040,0x9225> at2 = {1}; at2.SetValue( img.GetSlope() ); subds.Insert( at1.GetAsDataElement() ); subds.Insert( at2.GetAsDataElement() ); sq->AddItem( it ); const Tag trwvms(0x0040,0x9096); // Real World Value Mapping Sequence DataElement de( trwvms ); de.SetVR( VR::SQ ); de.SetValue(*sq); ds.Replace( de ); } ds.Remove( Tag(0x28,0x1052) ); ds.Remove( Tag(0x28,0x1053) ); ds.Remove( Tag(0x28,0x1054) ); #else //if( img.GetIntercept() != 0.0 || img.GetSlope() != 1.0 ) { if( ForceRescaleInterceptSlope ) { gdcmDebugMacro( "Forcing MR Image Storage / Modality LUT: [" << img.GetIntercept() << "," << img.GetSlope() ); Attribute<0x0028,0x1052> at1; at1.SetValue( img.GetIntercept() ); ds.Replace( at1.GetAsDataElement() ); Attribute<0x0028,0x1053> at2; at2.SetValue( img.GetSlope() ); ds.Replace( at2.GetAsDataElement() ); Attribute<0x0028,0x1054> at3; // Rescale Type at3.SetValue( "US" ); // Compatible with Enhanced MR Image Storage ds.Replace( at3.GetAsDataElement() ); } } #endif } else { Attribute<0x0028,0x1052> at1; at1.SetValue( img.GetIntercept() ); ds.Replace( at1.GetAsDataElement() ); Attribute<0x0028,0x1053> at2; at2.SetValue( img.GetSlope() ); ds.Replace( at2.GetAsDataElement() ); Attribute<0x0028,0x1054> at3; // Rescale Type at3.SetValue( "US" ); // FIXME if( ms == MediaStorage::SecondaryCaptureImageStorage ) { // As per 3-2009, US is the only valid enumerated value: ds.Replace( at3.GetAsDataElement() ); } else if( ms == MediaStorage::PETImageStorage ) { // not there anyway: ds.Remove( at3.GetTag() ); } else { // In case user decide to override the default: ds.ReplaceEmpty( at3.GetAsDataElement() ); } } } bool ImageHelper::GetRealWorldValueMappingContent(File const & f, RealWorldValueMappingContent & ret) { MediaStorage ms; ms.SetFromFile(f); const DataSet& ds = f.GetDataSet(); if( ms == MediaStorage::MRImageStorage ) { const Tag trwvms(0x0040,0x9096); // Real World Value Mapping Sequence if( ds.FindDataElement( trwvms ) ) { SmartPointer sqi0 = ds.GetDataElement( trwvms ).GetValueAsSQ(); if( sqi0 ) { const Tag trwvlutd(0x0040,0x9212); // Real World Value LUT Data if( ds.FindDataElement( trwvlutd ) ) { gdcmAssertAlwaysMacro(0); // Not supported ! } // don't know how to handle multiples: gdcmAssertAlwaysMacro( sqi0->GetNumberOfItems() == 1 ); const Item &item0 = sqi0->GetItem(1); const DataSet & subds0 = item0.GetNestedDataSet(); //const Tag trwvi(0x0040,0x9224); // Real World Value Intercept //const Tag trwvs(0x0040,0x9225); // Real World Value Slope { Attribute<0x0040,0x9224> at1 = {0}; at1.SetFromDataSet( subds0 ); Attribute<0x0040,0x9225> at2 = {1}; at2.SetFromDataSet( subds0 ); ret.RealWorldValueIntercept = at1.GetValue(); ret.RealWorldValueSlope = at2.GetValue(); } const Tag tmucs(0x0040,0x08ea); // Measurement Units Code Sequence if( subds0.FindDataElement( tmucs ) ) { SmartPointer sqi = subds0.GetDataElement( tmucs ).GetValueAsSQ(); if( sqi ) { gdcmAssertAlwaysMacro( sqi->GetNumberOfItems() == 1 ); const Item &item = sqi->GetItem(1); const DataSet & subds = item.GetNestedDataSet(); Attribute<0x0008,0x0100> at1; at1.SetFromDataSet( subds ); Attribute<0x0008,0x0104> at2; at2.SetFromDataSet( subds ); ret.CodeValue = at1.GetValue().Trim(); ret.CodeMeaning = at2.GetValue().Trim(); } } } return true; } } return false; } bool ImageHelper::ComputeSpacingFromImagePositionPatient(const std::vector & imageposition, std::vector & spacing) { if( imageposition.size() % 3 != 0 ) { return false; } std::vector::const_iterator it = imageposition.begin(); //const double x0 = *it++; //const double y0 = *it++; //const double z0 = *it++; spacing[0] = spacing[1] = spacing[2] = 0.; for( ; it != imageposition.end(); ++it) { const double x = *it++; const double y = *it++; const double z = *it; spacing[0] += x; spacing[1] += y; spacing[2] += z; } size_t n = imageposition.size() / 3; spacing[0] /= (double)n; spacing[1] /= (double)n; spacing[2] /= (double)n; return true; } //functions to get more information from a file //useful for the stream image reader, which fills in necessary image information //distinctly from the reader-style data input //code is borrowed from gdcmPixmapReader::ReadImage(MediaStorage const &ms) PhotometricInterpretation ImageHelper::GetPhotometricInterpretationValue(File const& f) { // 5. Photometric Interpretation // D 0028|0004 [CS] [Photometric Interpretation] [MONOCHROME2 ] PixelFormat pf = GetPixelFormatValue(f); const Tag tphotometricinterpretation(0x0028, 0x0004); const ByteValue *photometricinterpretation = ImageHelper::GetPointerFromElement(tphotometricinterpretation, f); PhotometricInterpretation pi = PhotometricInterpretation::UNKNOWN; if( photometricinterpretation ) { std::string photometricinterpretation_str( photometricinterpretation->GetPointer(), photometricinterpretation->GetLength() ); pi = PhotometricInterpretation::GetPIType( photometricinterpretation_str.c_str() ); } else { if( pf.GetSamplesPerPixel() == 1 ) { gdcmWarningMacro( "No PhotometricInterpretation found, default to MONOCHROME2" ); pi = PhotometricInterpretation::MONOCHROME2; } else if( pf.GetSamplesPerPixel() == 3 ) { gdcmWarningMacro( "No PhotometricInterpretation found, default to RGB" ); pi = PhotometricInterpretation::RGB; } else if( pf.GetSamplesPerPixel() == 4 ) { gdcmWarningMacro( "No PhotometricInterpretation found, default to ARGB" ); pi = PhotometricInterpretation::ARGB; } } bool isacrnema = false; DataSet ds = f.GetDataSet(); const Tag trecognitioncode(0x0008,0x0010); if( ds.FindDataElement( trecognitioncode ) && !ds.GetDataElement( trecognitioncode ).IsEmpty() ) { // PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm // PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm gdcmDebugMacro( "Mixture of ACR NEMA and DICOM file" ); isacrnema = true; } if( !pf.GetSamplesPerPixel() || (pi.GetSamplesPerPixel() != pf.GetSamplesPerPixel()) ) { if( pi != PhotometricInterpretation::UNKNOWN ) { pf.SetSamplesPerPixel( pi.GetSamplesPerPixel() ); } else if ( isacrnema ) { assert ( pf.GetSamplesPerPixel() == 0 ); assert ( pi == PhotometricInterpretation::UNKNOWN ); pf.SetSamplesPerPixel( 1 ); pi = PhotometricInterpretation::MONOCHROME2; } else { gdcmWarningMacro( "Cannot recognize image type. Does not looks like ACR-NEMA and is missing both Sample Per Pixel AND PhotometricInterpretation. Please report" ); } } return pi; } //returns the configuration of colors in a plane, either RGB RGB RGB or RRR GGG BBB //code is borrowed from gdcmPixmapReader::ReadImage(MediaStorage const &ms) unsigned int ImageHelper::GetPlanarConfigurationValue(const File& f) { // 4. Planar Configuration // D 0028|0006 [US] [Planar Configuration] [1] const Tag planarconfiguration = Tag(0x0028, 0x0006); PixelFormat pf = GetPixelFormatValue(f); unsigned int pc = 0; // FIXME: Whatif planaconfiguration is send in a grayscale image... it would be empty... // well hopefully :( DataSet const & ds = f.GetDataSet(); if( ds.FindDataElement( planarconfiguration ) && !ds.GetDataElement( planarconfiguration ).IsEmpty() ) { const DataElement& de = ds.GetDataElement( planarconfiguration ); Attribute<0x0028,0x0006> at = { 0 }; at.SetFromDataElement( de ); //unsigned int pc = ReadUSFromTag( planarconfiguration, ss, conversion ); pc = at.GetValue(); if( pc && pf.GetSamplesPerPixel() != 3 ) { gdcmDebugMacro( "Cannot have PlanarConfiguration=1, when Sample Per Pixel != 3" ); pc = 0; } } return pc; } //returns the lookup table of an image file SmartPointer ImageHelper::GetLUT(File const& f) { DataSet const & ds = f.GetDataSet(); PixelFormat pf = GetPixelFormatValue(f); PhotometricInterpretation pi = GetPhotometricInterpretationValue(f); // Do the Palette Color: // 1. Modality LUT Sequence bool modlut = ds.FindDataElement(Tag(0x0028,0x3000) ); if( modlut ) { gdcmWarningMacro( "Modality LUT (0028,3000) are not handled. Image will not be displayed properly" ); } // 2. LUTData (0028,3006) // technically I do not need to warn about LUTData since either modality lut XOR VOI LUT need to // be sent to require a LUT Data... bool lutdata = ds.FindDataElement(Tag(0x0028,0x3006) ); if( lutdata ) { gdcmWarningMacro( "LUT Data (0028,3006) are not handled. Image will not be displayed properly" ); } // 3. VOILUTSequence (0028,3010) bool voilut = ds.FindDataElement(Tag(0x0028,0x3010) ); if( voilut ) { gdcmWarningMacro( "VOI LUT (0028,3010) are not handled. Image will not be displayed properly" ); } // (0028,0120) US 32767 # 2, 1 PixelPaddingValue bool pixelpaddingvalue = ds.FindDataElement(Tag(0x0028,0x0120)); // PS 3.3 - 2008 / C.7.5.1.1.2 Pixel Padding Value and Pixel Padding Range Limit if(pixelpaddingvalue) { // Technically if Pixel Padding Value is 0 on MONOCHROME2 image, then appearance should be fine... bool vizissue = true; if( pf.GetPixelRepresentation() == 0 ) { Element ppv; if( !ds.GetDataElement(Tag(0x0028,0x0120) ).IsEmpty() ) { ppv.SetFromDataElement( ds.GetDataElement(Tag(0x0028,0x0120)) ); //.GetValue() ); if( pi == PhotometricInterpretation::MONOCHROME2 && ppv.GetValue() == 0 ) { vizissue = false; } } } else if( pf.GetPixelRepresentation() == 1 ) { gdcmDebugMacro( "TODO" ); } // test if there is any viz issue: if( vizissue ) { gdcmDebugMacro( "Pixel Padding Value (0028,0120) is not handled. Image will not be displayed properly" ); } } SmartPointer lut = new LookupTable; const Tag testseglut(0x0028, (0x1221 + 0)); if( ds.FindDataElement( testseglut ) ) { lut = new SegmentedPaletteColorLookupTable; } //SmartPointer lut = new SegmentedPaletteColorLookupTable; lut->Allocate( pf.GetBitsAllocated() ); // for each red, green, blue: for(int i=0; i<3; ++i) { // (0028,1101) US 0\0\16 // (0028,1102) US 0\0\16 // (0028,1103) US 0\0\16 const Tag tdescriptor(0x0028, (uint16_t)(0x1101 + i)); //const Tag tdescriptor(0x0028, 0x3002); Element el_us3 = {{ 0, 0, 0}}; // Now pass the byte array to a DICOMizer: el_us3.SetFromDataElement( ds[tdescriptor] ); //.GetValue() ); lut->InitializeLUT( LookupTable::LookupTableType(i), el_us3[0], el_us3[1], el_us3[2] ); // (0028,1201) OW // (0028,1202) OW // (0028,1203) OW const Tag tlut(0x0028, (uint16_t)(0x1201 + i)); //const Tag tlut(0x0028, 0x3006); // Segmented LUT // (0028,1221) OW // (0028,1222) OW // (0028,1223) OW const Tag seglut(0x0028, (uint16_t)(0x1221 + i)); if( ds.FindDataElement( tlut ) ) { const ByteValue *lut_raw = ds.GetDataElement( tlut ).GetByteValue(); if( lut_raw ) { // LookupTableType::RED == 0 lut->SetLUT( LookupTable::LookupTableType(i), (const unsigned char*)lut_raw->GetPointer(), lut_raw->GetLength() ); //assert( pf.GetBitsAllocated() == el_us3.GetValue(2) ); } else { lut->Clear(); } unsigned long check = (el_us3.GetValue(0) ? el_us3.GetValue(0) : 65536) * el_us3.GetValue(2) / 8; assert( !lut->Initialized() || check == lut_raw->GetLength() ); (void)check; } else if( ds.FindDataElement( seglut ) ) { const ByteValue *lut_raw = ds.GetDataElement( seglut ).GetByteValue(); if( lut_raw ) { lut->SetLUT( LookupTable::LookupTableType(i), (const unsigned char*)lut_raw->GetPointer(), lut_raw->GetLength() ); //assert( pf.GetBitsAllocated() == el_us3.GetValue(2) ); } else { lut->Clear(); } //unsigned long check = // (el_us3.GetValue(0) ? el_us3.GetValue(0) : 65536) // * el_us3.GetValue(2) / 8; //assert( check == lut_raw->GetLength() ); (void)check; } else { assert(0); } } if( ! lut->Initialized() ) { gdcmDebugMacro("LUT was uninitialized!"); } return lut; } const ByteValue* ImageHelper::GetPointerFromElement(Tag const &tag, const File& inF) { const DataSet &ds = inF.GetDataSet(); if( ds.FindDataElement( tag ) ) { const DataElement &de = ds.GetDataElement( tag ); return de.GetByteValue(); } return nullptr; } MediaStorage ImageHelper::ComputeMediaStorageFromModality(const char *modality, unsigned int dimension, PixelFormat const & pixeltype, PhotometricInterpretation const & pi, double intercept , double slope ) { // FIXME: Planar Configuration (0028,0006) shall not be present MediaStorage ms = MediaStorage::SecondaryCaptureImageStorage; ms.GuessFromModality(modality, dimension ); // refine for SC family if( dimension != 2 && (ms == MediaStorage::SecondaryCaptureImageStorage // dim 2 || ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage ) // dim 3 ) { // A.8.3.4 Multi-frame Grayscale Byte SC Image IOD Content Constraints /* - Samples per Pixel (0028,0002) shall be 1 - Photometric Interpretation (0028,0004) shall be MONOCHROME2 - Bits Allocated (0028,0100) shall be 8 - Bits Stored (0028,0101) shall be 8 - High Bit (0028,0102) shall be 7 - Pixel Representation (0028,0103) shall be 0 - Planar Configuration (0028,0006) shall not be present */ if( dimension == 3 && pixeltype.GetSamplesPerPixel() == 1 && pi == PhotometricInterpretation::MONOCHROME2 && pixeltype.GetBitsAllocated() == 8 && pixeltype.GetBitsStored() == 8 && pixeltype.GetHighBit() == 7 && pixeltype.GetPixelRepresentation() == 0 ) { ms = MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage; if( intercept != 0 || slope != 1 ) { // A.8.3.4 Multi-frame Grayscale Byte SC Image IOD Content Constraints gdcmErrorMacro( "Cannot have shift/scale" ); return MediaStorage::MS_END; } } else if( dimension == 3 && pixeltype.GetSamplesPerPixel() == 1 && pi == PhotometricInterpretation::MONOCHROME2 && pixeltype.GetBitsAllocated() == 1 && pixeltype.GetBitsStored() == 1 && pixeltype.GetHighBit() == 0 && pixeltype.GetPixelRepresentation() == 0 ) { ms = MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage; // FIXME: GDCM does not handle bit packing... if( intercept != 0 || slope != 1 ) { gdcmDebugMacro( "Cannot have shift/scale" ); return MediaStorage::MS_END; } } else if( dimension == 3 && pixeltype.GetSamplesPerPixel() == 1 && pi == PhotometricInterpretation::MONOCHROME2 && pixeltype.GetBitsAllocated() == 16 && pixeltype.GetBitsStored() <= 16 && pixeltype.GetBitsStored() >= 9 && pixeltype.GetHighBit() == pixeltype.GetBitsStored() - 1 && pixeltype.GetPixelRepresentation() == 0 ) { ms = MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage; // A.8.4.4 Multi-frame Grayscale Word SC Image IOD Content Constraints // Rescale Slope and Rescale Intercept are not constrained in this IOD to // any particular values. E.g., they may be used to recover floating // point values scaled to the integer range of the stored pixel values, // Rescale Slope may be less than one, e.g., a Rescale Slope of 1.0/65535 // would allow represent floating point values from 0 to 1.0. } else if( dimension == 3 && /* A.8.5.4 Multi-frame True Color SC Image IOD Content Constraints */ pixeltype.GetSamplesPerPixel() == 3 && ( pi == PhotometricInterpretation::RGB || pi == PhotometricInterpretation::YBR_RCT || pi == PhotometricInterpretation::YBR_ICT || pi == PhotometricInterpretation::YBR_PARTIAL_420 || pi == PhotometricInterpretation::YBR_FULL_422 ) && pixeltype.GetBitsAllocated() == 8 && pixeltype.GetBitsStored() == 8 && pixeltype.GetHighBit() == 7 && pixeltype.GetPixelRepresentation() == 0 ) { ms = MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage; if( intercept != 0 || slope != 1 ) { gdcmDebugMacro( "Cannot have shift/scale" ); return MediaStorage::MS_END; } } else { gdcmDebugMacro( "Cannot handle Multi Frame image in SecondaryCaptureImageStorage" ); return MediaStorage::MS_END; } } // check MR Image Storage if( ms == MediaStorage::MRImageStorage ) { if( intercept != 0.0 || slope != 1.0 ) { if( !ForceRescaleInterceptSlope ) { // hopefully this is not a lame choice: ms = MediaStorage::EnhancedMRImageStorage; } } } // check 'DX' / dim == 2: if( ms == MediaStorage::DigitalXRayImageStorageForPresentation ) { if( intercept != 0.0 || slope != 1.0 ) { // hopefully this is not a lame choice: ms = MediaStorage::XRay3DCraniofacialImageStorage; } } return ms; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageHelper.h000066400000000000000000000156631412732066400237130ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMAGEHELPER_H #define GDCMIMAGEHELPER_H #include "gdcmTypes.h" #include "gdcmTag.h" #include #include "gdcmPixelFormat.h" #include "gdcmPhotometricInterpretation.h" #include "gdcmSmartPointer.h" #include "gdcmLookupTable.h" namespace gdcm { class MediaStorage; class DataSet; class File; class Image; class Pixmap; class ByteValue; // minimal struct: struct RealWorldValueMappingContent { double RealWorldValueIntercept; double RealWorldValueSlope; // http://dicom.nema.org/MEDICAL/DICOM/2014c/output/chtml/part16/sect_CID_7181.html std::string CodeValue; std::string CodeMeaning; }; /** * \brief ImageHelper (internal class, not intended for user level) * * \details * Helper for writing World images in DICOM. DICOM has a 'template' approach to image where * MR Image Storage are distinct object from Enhanced MR Image Storage. For example the * Pixel Spacing in one object is not at the same position (ie Tag) as in the other * this class is the central (read: fragile) place where all the dispatching is done from * a unified view of a world image (typically VTK or ITK point of view) down to the low * level DICOM point of view. * * \warning: do not expect the API of this class to be maintained at any point, since as * Modalities are added the API might have to be augmented or behavior changed to cope * with new modalities. */ class GDCM_EXPORT ImageHelper { public: /// GDCM 1.x compatibility issue: /// Do not use anymore. This hack was used for some MR Image Storage /// generated by Philips Modality. /// When "Combine MR Rescaling" is set to TRUE, rescaling is removed. But /// when set to FALSE, the Modality LUT was exported. Internally GDCM now /// handles this gracefully. static void SetForceRescaleInterceptSlope(bool); static bool GetForceRescaleInterceptSlope(); /// Since GDCM 2.6.1 Philips Medical System are read using the Private Field /// For Rescale Slope/Intercept by default. This mechanism can be deactivated /// using the following API: /// This option has no effect when ForceRescaleInterceptSlope is set to true /// GDCM will only read those private attribute but never write them out. static void SetPMSRescaleInterceptSlope(bool); static bool GetPMSRescaleInterceptSlope(); /// GDCM 1.x compatibility issue: /// When using ReWrite an MR Image Storage would be rewritten as Secondary Capture Object while /// still having a Pixel Spacing tag (0028,0030). If you have deal with those files, use this /// very special flag to handle them /// Unless explicitly set elsewhere by the standard, it will use value from 0028,0030 / 0018,0088 /// for the Pixel Spacing of the Image static void SetForcePixelSpacing(bool); static bool GetForcePixelSpacing(); /// This function checks tags (0x0028, 0x0010) and (0x0028, 0x0011) for the /// rows and columns of the image in pixels (as opposed to actual distances). /// The output is {col , row} static std::vector GetDimensionsValue(const File& f); static void SetDimensionsValue(File& f, const Pixmap & img); /// This function returns pixel information about an image from its dataset /// That includes samples per pixel and bit depth (in that order) static PixelFormat GetPixelFormatValue(const File& f); /// Set/Get shift/scale from/to a file /// \warning this function reads/sets the Slope/Intercept in appropriate /// class storage, but also Grid Scaling in RT Dose Storage /// Can't take a dataset because the mediastorage of the file must be known static std::vector GetRescaleInterceptSlopeValue(File const & f); static void SetRescaleInterceptSlopeValue(File & f, const Image & img); // read only for now static bool GetRealWorldValueMappingContent(File const & f, RealWorldValueMappingContent & rwvmc); /// Set/Get Origin (IPP) from/to a file static std::vector GetOriginValue(File const & f); static void SetOriginValue(DataSet & ds, const Image & img); /// Get Direction Cosines (IOP) from/to a file /// Requires a file because mediastorage must be known static std::vector GetDirectionCosinesValue(File const & f); /// Set Direction Cosines (IOP) from/to a file /// When IOD does not defines what is IOP (eg. typically Secondary Capture Image Storage) /// this call will simply remove the IOP attribute. /// Else in case of MR/CT image storage, this call will properly lookup the correct attribute /// to store the IOP. // FIXME: There is a major issue for image with multiple IOP (eg. Enhanced * Image Storage). static void SetDirectionCosinesValue(DataSet & ds, const std::vector & dircos); /// Set/Get Spacing from/to a File static std::vector GetSpacingValue(File const & f); static void SetSpacingValue(DataSet & ds, const std::vector & spacing); /// DO NOT USE static bool ComputeSpacingFromImagePositionPatient(const std::vector &imageposition, std::vector & spacing); static bool GetDirectionCosinesFromDataSet(DataSet const & ds, std::vector & dircos); //functions to get more information from a file //useful for the stream image reader, which fills in necessary image information //distinctly from the reader-style data input static PhotometricInterpretation GetPhotometricInterpretationValue(File const& f); //returns the configuration of colors in a plane, either RGB RGB RGB or RRR GGG BBB static unsigned int GetPlanarConfigurationValue(const File& f); /// returns the lookup table of an image file static SmartPointer GetLUT(File const& f); // Moved from PixampReader to here. Generally used for photometric interpretation. static const ByteValue* GetPointerFromElement(Tag const &tag, File const& f); /// Moved from MediaStorage here, since we need extra info stored in PixelFormat & PhotometricInterpretation static MediaStorage ComputeMediaStorageFromModality(const char *modality, unsigned int dimension = 2, PixelFormat const & pf = PixelFormat(), PhotometricInterpretation const & pi = PhotometricInterpretation(), double rescaleintercept = 0, double rescaleslope = 1 ); protected: static Tag GetSpacingTagFromMediaStorage(MediaStorage const &ms); static Tag GetZSpacingTagFromMediaStorage(MediaStorage const &ms); private: static bool ForceRescaleInterceptSlope; static bool PMSRescaleInterceptSlope; static bool ForcePixelSpacing; }; } // end namespace gdcm #endif // GDCMIMAGEHELPER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageReader.cxx000066400000000000000000000106001412732066400242330ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageReader.h" #include "gdcmExplicitDataElement.h" #include "gdcmImplicitDataElement.h" #include "gdcmValue.h" #include "gdcmFileMetaInformation.h" #include "gdcmElement.h" #include "gdcmPhotometricInterpretation.h" #include "gdcmTransferSyntax.h" #include "gdcmAttribute.h" #include "gdcmImageHelper.h" #include "gdcmPrivateTag.h" #include "gdcmJPEGCodec.h" namespace gdcm { ImageReader::ImageReader() { PixelData = new Image; } ImageReader::~ImageReader() = default; const Image& ImageReader::GetImage() const { return dynamic_cast(*PixelData); } Image& ImageReader::GetImage() { return dynamic_cast(*PixelData); } //void ImageReader::SetImage(Image const &img) //{ // PixelData = img; //} bool ImageReader::Read() { return PixmapReader::Read(); } bool ImageReader::ReadImage(MediaStorage const &ms) { if( !PixmapReader::ReadImage(ms) ) { return false; } //const DataSet &ds = F->GetDataSet(); Image& pixeldata = GetImage(); // 4 1/2 Let's do Pixel Spacing std::vector spacing = ImageHelper::GetSpacingValue(*F); // FIXME: Only SC is allowed not to have spacing: 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] ); if( spacing.size() > pixeldata.GetNumberOfDimensions() ) // FIXME HACK { pixeldata.SetSpacing(pixeldata.GetNumberOfDimensions(), spacing[pixeldata.GetNumberOfDimensions()] ); } } // 4 2/3 Let's do Origin std::vector origin = ImageHelper::GetOriginValue(*F); if( !origin.empty() ) { pixeldata.SetOrigin( &origin[0] ); if( origin.size() > pixeldata.GetNumberOfDimensions() ) // FIXME HACK { pixeldata.SetOrigin(pixeldata.GetNumberOfDimensions(), origin[pixeldata.GetNumberOfDimensions()] ); } } std::vector dircos = ImageHelper::GetDirectionCosinesValue(*F); if( !dircos.empty() ) { pixeldata.SetDirectionCosines( &dircos[0] ); } // Do the Rescale Intercept & Slope std::vector is = ImageHelper::GetRescaleInterceptSlopeValue(*F); pixeldata.SetIntercept( is[0] ); pixeldata.SetSlope( is[1] ); return true; } bool ImageReader::ReadACRNEMAImage() { if( !PixmapReader::ReadACRNEMAImage() ) { return false; } const DataSet &ds = F->GetDataSet(); Image& pixeldata = GetImage(); // 4 1/2 Let's do Pixel Spacing const Tag tpixelspacing(0x0028, 0x0030); if( ds.FindDataElement( tpixelspacing ) ) { const DataElement& de = ds.GetDataElement( tpixelspacing ); Attribute<0x0028,0x0030> at; at.SetFromDataElement( de ); pixeldata.SetSpacing( 0, at.GetValue(0)); pixeldata.SetSpacing( 1, at.GetValue(1)); } // 4 2/3 Let's do Origin const Tag timageposition(0x0020, 0x0030); if( ds.FindDataElement( timageposition) ) { const DataElement& de = ds.GetDataElement( timageposition); Attribute<0x0020,0x0030> at = {{}}; at.SetFromDataElement( de ); pixeldata.SetOrigin( at.GetValues() ); if( at.GetNumberOfValues() > pixeldata.GetNumberOfDimensions() ) // FIXME HACK { pixeldata.SetOrigin(pixeldata.GetNumberOfDimensions(), at.GetValue(pixeldata.GetNumberOfDimensions()) ); } } const Tag timageorientation(0x0020, 0x0035); if( ds.FindDataElement( timageorientation) ) { const DataElement& de = ds.GetDataElement( timageorientation); Attribute<0x0020,0x0035> at = {{1,0,0,0,1,0}};//to get rid of brackets warnings in linux, lots of {} at.SetFromDataElement( de ); pixeldata.SetDirectionCosines( at.GetValues() ); } // Do the Rescale Intercept & Slope std::vector is = ImageHelper::GetRescaleInterceptSlopeValue(*F); pixeldata.SetIntercept( is[0] ); pixeldata.SetSlope( is[1] ); return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageReader.h000066400000000000000000000031041412732066400236610ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMAGEREADER_H #define GDCMIMAGEREADER_H #include "gdcmPixmapReader.h" #include "gdcmImage.h" namespace gdcm { class MediaStorage; /** * \brief ImageReader * \note its role is to convert the DICOM DataSet into a Image * representation * Image is different from Pixmap has it has a position and a direction in * Space. * * \see Image */ class GDCM_EXPORT ImageReader : public PixmapReader { public: ImageReader(); ~ImageReader() override;//needs to be virtual to ensure lack of memory leaks /// Read the DICOM image. There are two reason for failure: /// 1. The input filename is not DICOM /// 2. The input DICOM file does not contains an Image. bool Read() override; // Following methods are valid only after a call to 'Read' /// Return the read image const Image& GetImage() const; Image& GetImage(); //void SetImage(Image const &img); protected: bool ReadImage(MediaStorage const &ms) override; bool ReadACRNEMAImage() override; }; } // end namespace gdcm #endif //GDCMIMAGEREADER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageRegionReader.cxx000066400000000000000000000407361412732066400254140ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageRegionReader.h" #include "gdcmImageHelper.h" #include "gdcmBoxRegion.h" #include "gdcmRAWCodec.h" #include "gdcmRLECodec.h" #include "gdcmJPEG2000Codec.h" #include "gdcmJPEGCodec.h" #include "gdcmJPEGLSCodec.h" namespace gdcm { class ImageRegionReaderInternals { public: ImageRegionReaderInternals() { TheRegion = nullptr; Modified = false; FileOffset = -1; } ~ImageRegionReaderInternals() { delete TheRegion; } void SetRegion(Region const & r) { delete TheRegion; TheRegion = r.Clone(); assert( TheRegion ); Modified = true; } Region *GetRegion() const { return TheRegion; } std::streampos GetFileOffset() const { return FileOffset; } void SetFileOffset( std::streampos f ) { FileOffset = f; } private: Region *TheRegion; bool Modified; std::streamoff FileOffset; }; ImageRegionReader::ImageRegionReader() { Internals = new ImageRegionReaderInternals; } ImageRegionReader::~ImageRegionReader() { delete Internals; } void ImageRegionReader::SetRegion(Region const & region) { Internals->SetRegion( region ); } Region const &ImageRegionReader::GetRegion() const { if( Internals->GetRegion() ) { return *Internals->GetRegion(); } else { static BoxRegion full; std::vector dims = ImageHelper::GetDimensionsValue(GetFile()); full.SetDomain(0, dims[0] - 1, 0, dims[1] - 1, 0, dims[2] - 1 ); return full; } } size_t ImageRegionReader::ComputeBufferLength() const { // Is this a legal extent: size_t npixels = 0; if( Internals->GetRegion() ) { if( !Internals->GetRegion()->IsValid() ) { gdcmDebugMacro( "Sorry not a valid extent. Giving up" ); return 0; } npixels = this->Internals->GetRegion()->Area(); } else { std::vector dims = ImageHelper::GetDimensionsValue(GetFile()); BoxRegion full; // Use BoxRegion to do robust computation full.SetDomain(0, dims[0] - 1, 0, dims[1] - 1, 0, dims[2] - 1 ); if(! full.IsValid() ) { gdcmDebugMacro( "Sorry not a valid extent. Giving up" ); return 0; } npixels = full.Area(); } const PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(GetFile()); const size_t bytesPerPixel = pixelInfo.GetPixelSize(); return npixels*bytesPerPixel; } bool ImageRegionReader::ReadInformation() { std::set st; Tag tpixeldata(0x7fe0, 0x0010); // never read this one st.insert(tpixeldata); if (!ReadUpToTag(tpixeldata, st)) { gdcmWarningMacro("Failed ReadUpToTag."); return false; } const bool iseof = GetStreamPtr()->eof(); if( iseof ) { gdcmDebugMacro( "No Pixel Data, sorry" ); return false; } std::streampos fileoffset = GetStreamPtr()->tellg(); assert( fileoffset != std::streampos(-1) ); Internals->SetFileOffset( fileoffset ); const File &file = GetFile(); const DataSet &ds = file.GetDataSet(); (void)ds; //std::cout << ds << std::endl; MediaStorage ms; ms.SetFromFile(file); assert( ms != MediaStorage::VLWholeSlideMicroscopyImageStorage ); if( !MediaStorage::IsImage( ms ) ) { gdcmDebugMacro( "Not an image recognized. Giving up"); return false; } // populate Image meta data if( !ReadImageInternal(ms, false) ) { return false; } // FIXME Copy/paste from ImageReader::ReadImage Image& pixeldata = GetImage(); // 4 1/2 Let's do Pixel Spacing std::vector spacing = ImageHelper::GetSpacingValue(*F); // FIXME: Only SC is allowed not to have spacing: 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] ); if( spacing.size() > pixeldata.GetNumberOfDimensions() ) // FIXME HACK { pixeldata.SetSpacing(pixeldata.GetNumberOfDimensions(), spacing[pixeldata.GetNumberOfDimensions()] ); } } // 4 2/3 Let's do Origin std::vector origin = ImageHelper::GetOriginValue(*F); if( !origin.empty() ) { pixeldata.SetOrigin( &origin[0] ); if( origin.size() > pixeldata.GetNumberOfDimensions() ) // FIXME HACK { pixeldata.SetOrigin(pixeldata.GetNumberOfDimensions(), origin[pixeldata.GetNumberOfDimensions()] ); } } std::vector dircos = ImageHelper::GetDirectionCosinesValue(*F); if( !dircos.empty() ) { pixeldata.SetDirectionCosines( &dircos[0] ); } // Do the Rescale Intercept & Slope std::vector is = ImageHelper::GetRescaleInterceptSlopeValue(*F); pixeldata.SetIntercept( is[0] ); pixeldata.SetSlope( is[1] ); return true; } BoxRegion ImageRegionReader::ComputeBoundingBox() { BoxRegion boundingbox; if( Internals->GetRegion() ) boundingbox = this->Internals->GetRegion()->ComputeBoundingBox(); else { std::vector dims = ImageHelper::GetDimensionsValue(GetFile()); boundingbox.SetDomain( 0, dims[0] - 1, 0, dims[1] - 1, 0, dims[2] - 1 ); } return boundingbox; } bool ImageRegionReader::ReadRAWIntoBuffer(char *buffer, size_t buflen) { (void)buflen; std::vector dimensions = ImageHelper::GetDimensionsValue(GetFile()); PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(GetFile()); const FileMetaInformation &header = GetFile().GetHeader(); const TransferSyntax &ts = header.GetDataSetTransferSyntax(); bool needbyteswap = (ts == TransferSyntax::ImplicitVRBigEndianPrivateGE || ts == TransferSyntax::ExplicitVRBigEndian ); RAWCodec theCodec; if( !theCodec.CanDecode( ts ) ) return false; theCodec.SetPlanarConfiguration( ImageHelper::GetPlanarConfigurationValue(GetFile())); if( ImageHelper::GetPhotometricInterpretationValue(GetFile()) == PhotometricInterpretation::YBR_FULL_422 ) return false; theCodec.SetPhotometricInterpretation( ImageHelper::GetPhotometricInterpretationValue(GetFile())); //theCodec.SetLUT( GetLUT() ); theCodec.SetPixelFormat( ImageHelper::GetPixelFormatValue(GetFile()) ); theCodec.SetNeedByteSwap( needbyteswap ); theCodec.SetNeedOverlayCleanup( pixelInfo.GetBitsAllocated() != pixelInfo.GetBitsStored() ); theCodec.SetDimensions(ImageHelper::GetDimensionsValue(GetFile())); std::istream* theStream = GetStreamPtr(); BoxRegion boundingbox = ComputeBoundingBox(); unsigned int xmin = boundingbox.GetXMin(); unsigned int xmax = boundingbox.GetXMax(); unsigned int ymin = boundingbox.GetYMin(); unsigned int ymax = boundingbox.GetYMax(); unsigned int zmin = boundingbox.GetZMin(); unsigned int zmax = boundingbox.GetZMax(); assert( xmax >= xmin ); assert( ymax >= ymin ); unsigned int rowsize = xmax - xmin + 1; unsigned int colsize = ymax - ymin + 1; unsigned int bytesPerPixel = pixelInfo.GetPixelSize(); std::vector buffer1; buffer1.resize( rowsize*bytesPerPixel ); char *tmpBuffer1 = &buffer1[0]; std::vector buffer2; buffer2.resize( rowsize*bytesPerPixel ); char *tmpBuffer2 = &buffer2[0]; unsigned int y, z; std::streamoff theOffset; for (z = zmin; z <= zmax; ++z) { for (y = ymin; y <= ymax; ++y) { theStream->seekg(std::ios::beg); theOffset = (size_t)Internals->GetFileOffset() + (z*dimensions[1]*dimensions[0] + y*dimensions[0] + xmin)*bytesPerPixel; theStream->seekg(theOffset); theStream->read(tmpBuffer1, rowsize*bytesPerPixel); if (!theCodec.DecodeBytes(tmpBuffer1, rowsize*bytesPerPixel, tmpBuffer2, rowsize*bytesPerPixel)) { return false; } #if 0 const char * check = &(buffer[((z-zmin)*rowsize*colsize + (y-ymin)*rowsize)*bytesPerPixel]); assert( check >= buffer && check < buffer + buflen ); assert( check + rowsize*bytesPerPixel <= buffer + buflen ); #endif memcpy(&(buffer[((z-zmin)*rowsize*colsize + (y-ymin)*rowsize)*bytesPerPixel]), tmpBuffer2, rowsize*bytesPerPixel); } } return true; } bool ImageRegionReader::ReadRLEIntoBuffer(char *buffer, size_t buflen) { (void)buflen; std::vector dimensions = ImageHelper::GetDimensionsValue(GetFile()); const PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(GetFile()); const FileMetaInformation &header = GetFile().GetHeader(); const TransferSyntax &ts = header.GetDataSetTransferSyntax(); bool needbyteswap = (ts == TransferSyntax::ImplicitVRBigEndianPrivateGE || ts == TransferSyntax::ExplicitVRBigEndian ); RLECodec theCodec; if( !theCodec.CanDecode( ts ) ) return false; theCodec.SetPlanarConfiguration( ImageHelper::GetPlanarConfigurationValue(GetFile())); theCodec.SetPhotometricInterpretation( ImageHelper::GetPhotometricInterpretationValue(GetFile())); //theCodec.SetLUT( GetLUT() ); theCodec.SetPixelFormat( ImageHelper::GetPixelFormatValue(GetFile()) ); theCodec.SetNeedByteSwap( needbyteswap ); theCodec.SetNeedOverlayCleanup( pixelInfo.GetBitsAllocated() != pixelInfo.GetBitsStored() ); std::vector d = ImageHelper::GetDimensionsValue(GetFile()); theCodec.SetDimensions(d ); theCodec.SetNumberOfDimensions( 2 ); if( d[2] > 1 ) theCodec.SetNumberOfDimensions( 3 ); std::istream* theStream = GetStreamPtr(); BoxRegion boundingbox = ComputeBoundingBox(); unsigned int xmin = boundingbox.GetXMin(); unsigned int xmax = boundingbox.GetXMax(); unsigned int ymin = boundingbox.GetYMin(); unsigned int ymax = boundingbox.GetYMax(); unsigned int zmin = boundingbox.GetZMin(); unsigned int zmax = boundingbox.GetZMax(); assert( xmax >= xmin ); assert( ymax >= ymin ); bool ret = theCodec.DecodeExtent( buffer, xmin, xmax, ymin, ymax, zmin, zmax, *theStream ); return ret; } bool ImageRegionReader::ReadJPEG2000IntoBuffer(char *buffer, size_t buflen) { (void)buflen; std::vector dimensions = ImageHelper::GetDimensionsValue(GetFile()); const PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(GetFile()); const FileMetaInformation &header = GetFile().GetHeader(); const TransferSyntax &ts = header.GetDataSetTransferSyntax(); bool needbyteswap = (ts == TransferSyntax::ImplicitVRBigEndianPrivateGE || ts == TransferSyntax::ExplicitVRBigEndian ); JPEG2000Codec theCodec; if( !theCodec.CanDecode( ts ) ) return false; theCodec.SetPlanarConfiguration( ImageHelper::GetPlanarConfigurationValue(GetFile())); theCodec.SetPhotometricInterpretation( ImageHelper::GetPhotometricInterpretationValue(GetFile())); //theCodec.SetLUT( GetLUT() ); theCodec.SetPixelFormat( ImageHelper::GetPixelFormatValue(GetFile()) ); theCodec.SetNeedByteSwap( needbyteswap ); theCodec.SetNeedOverlayCleanup( pixelInfo.GetBitsAllocated() != pixelInfo.GetBitsStored() ); std::vector d = ImageHelper::GetDimensionsValue(GetFile()); theCodec.SetDimensions(d ); theCodec.SetNumberOfDimensions( 2 ); if( d[2] > 1 ) theCodec.SetNumberOfDimensions( 3 ); std::istream* theStream = GetStreamPtr(); BoxRegion boundingbox = ComputeBoundingBox(); unsigned int xmin = boundingbox.GetXMin(); unsigned int xmax = boundingbox.GetXMax(); unsigned int ymin = boundingbox.GetYMin(); unsigned int ymax = boundingbox.GetYMax(); unsigned int zmin = boundingbox.GetZMin(); unsigned int zmax = boundingbox.GetZMax(); assert( xmax >= xmin ); assert( ymax >= ymin ); bool ret = theCodec.DecodeExtent( buffer, xmin, xmax, ymin, ymax, zmin, zmax, *theStream ); return ret; } bool ImageRegionReader::ReadJPEGIntoBuffer(char *buffer, size_t buflen) { (void)buflen; std::vector dimensions = ImageHelper::GetDimensionsValue(GetFile()); const PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(GetFile()); const FileMetaInformation &header = GetFile().GetHeader(); const TransferSyntax &ts = header.GetDataSetTransferSyntax(); bool needbyteswap = (ts == TransferSyntax::ImplicitVRBigEndianPrivateGE || ts == TransferSyntax::ExplicitVRBigEndian ); JPEGCodec theCodec; if( !theCodec.CanDecode( ts ) ) return false; theCodec.SetPlanarConfiguration( ImageHelper::GetPlanarConfigurationValue(GetFile())); theCodec.SetPhotometricInterpretation( ImageHelper::GetPhotometricInterpretationValue(GetFile())); //theCodec.SetLUT( GetLUT() ); theCodec.SetNeedByteSwap( needbyteswap ); theCodec.SetNeedOverlayCleanup( pixelInfo.GetBitsAllocated() != pixelInfo.GetBitsStored() ); std::vector d = ImageHelper::GetDimensionsValue(GetFile()); theCodec.SetDimensions(d ); theCodec.SetNumberOfDimensions( 2 ); if( d[2] > 1 ) theCodec.SetNumberOfDimensions( 3 ); // last call: theCodec.SetPixelFormat( ImageHelper::GetPixelFormatValue(GetFile()) ); std::istream* theStream = GetStreamPtr(); BoxRegion boundingbox = ComputeBoundingBox(); unsigned int xmin = boundingbox.GetXMin(); unsigned int xmax = boundingbox.GetXMax(); unsigned int ymin = boundingbox.GetYMin(); unsigned int ymax = boundingbox.GetYMax(); unsigned int zmin = boundingbox.GetZMin(); unsigned int zmax = boundingbox.GetZMax(); assert( xmax >= xmin ); assert( ymax >= ymin ); bool ret = theCodec.DecodeExtent( buffer, xmin, xmax, ymin, ymax, zmin, zmax, *theStream ); return ret; } bool ImageRegionReader::ReadJPEGLSIntoBuffer(char *buffer, size_t buflen) { (void)buflen; std::vector dimensions = ImageHelper::GetDimensionsValue(GetFile()); const PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(GetFile()); const FileMetaInformation &header = GetFile().GetHeader(); const TransferSyntax &ts = header.GetDataSetTransferSyntax(); bool needbyteswap = (ts == TransferSyntax::ImplicitVRBigEndianPrivateGE || ts == TransferSyntax::ExplicitVRBigEndian ); JPEGLSCodec theCodec; if( !theCodec.CanDecode( ts ) ) return false; theCodec.SetPlanarConfiguration( ImageHelper::GetPlanarConfigurationValue(GetFile())); theCodec.SetPhotometricInterpretation( ImageHelper::GetPhotometricInterpretationValue(GetFile())); //theCodec.SetLUT( GetLUT() ); theCodec.SetPixelFormat( ImageHelper::GetPixelFormatValue(GetFile()) ); theCodec.SetNeedByteSwap( needbyteswap ); theCodec.SetNeedOverlayCleanup( pixelInfo.GetBitsAllocated() != pixelInfo.GetBitsStored() ); std::vector d = ImageHelper::GetDimensionsValue(GetFile()); theCodec.SetDimensions(d ); theCodec.SetNumberOfDimensions( 2 ); if( d[2] > 1 ) theCodec.SetNumberOfDimensions( 3 ); std::istream* theStream = GetStreamPtr(); BoxRegion boundingbox = ComputeBoundingBox(); unsigned int xmin = boundingbox.GetXMin(); unsigned int xmax = boundingbox.GetXMax(); unsigned int ymin = boundingbox.GetYMin(); unsigned int ymax = boundingbox.GetYMax(); unsigned int zmin = boundingbox.GetZMin(); unsigned int zmax = boundingbox.GetZMax(); assert( xmax >= xmin ); assert( ymax >= ymin ); bool ret = theCodec.DecodeExtent( buffer, xmin, xmax, ymin, ymax, zmin, zmax, *theStream ); return ret; } bool ImageRegionReader::ReadIntoBuffer(char *buffer, size_t buflen) { size_t thelen = ComputeBufferLength(); if( thelen == 0 ) { // does not sound right, something seems odd. gdcmDebugMacro( "Cannot load an image of 0 bytes" ); return false; } if( buflen < thelen ) { gdcmDebugMacro( "buffer cannot be smaller than computed buffer length" ); return false; } assert( Internals->GetFileOffset() != std::streampos(-1) ); gdcmDebugMacro( "Using FileOffset: " << Internals->GetFileOffset() ); std::istream* theStream = GetStreamPtr(); theStream->seekg( Internals->GetFileOffset() ); bool success = false; if( !success ) success = ReadRAWIntoBuffer(buffer, buflen); if( !success ) success = ReadRLEIntoBuffer(buffer, buflen); if( !success ) success = ReadJPEGIntoBuffer(buffer, buflen); if( !success ) success = ReadJPEGLSIntoBuffer(buffer, buflen); if( !success ) success = ReadJPEG2000IntoBuffer(buffer, buflen); return success; } bool ImageRegionReader::Read() { return false; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageRegionReader.h000066400000000000000000000051351412732066400250330ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMAGEEXTENTREADER_H #define GDCMIMAGEEXTENTREADER_H #include "gdcmImageReader.h" #include "gdcmImage.h" #include "gdcmRegion.h" namespace gdcm { class ImageRegionReaderInternals; /** * \brief ImageRegionReader * \details This class is able to read a region from a DICOM file containing an image. This implementation * requires that the information stored in the DICOM header are consistent with what is in the * encapsulated Pixel Data. This is technically not required by DICOM standard, which makes * this implementation illegal with regards to the famous JPEG note: * http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_8.2.html#para_4bcb841e-c6bf-4e26-82a5-3fad3c942da0 * \see ImageReader */ class GDCM_EXPORT ImageRegionReader : public ImageReader { public: ImageRegionReader(); ~ImageRegionReader() override; /// Set/Get Region to be read void SetRegion(Region const & region); Region const &GetRegion() const; /// Explicit call which will compute the minimal buffer length that can hold the whole /// uncompressed image as defined by Region `region`. /// \return 0 upon error size_t ComputeBufferLength() const; /// Read meta information (not Pixel Data) from the DICOM file. /// \return false upon error bool ReadInformation(); /// Read into buffer: /// For Python, the `buflen` param is deduced directly from the input /// bytearray passed as parameter (function only takes one param). /// \return false upon error bool ReadIntoBuffer(char *inreadbuffer, size_t buflen); protected: /// To prevent user from calling super class Read() function bool Read() override; private: BoxRegion ComputeBoundingBox(); bool ReadRAWIntoBuffer(char *buffer, size_t buflen); bool ReadRLEIntoBuffer(char *buffer, size_t buflen); bool ReadJPEG2000IntoBuffer(char *buffer, size_t buflen); bool ReadJPEGIntoBuffer(char *buffer, size_t buflen); bool ReadJPEGLSIntoBuffer(char *buffer, size_t buflen); ImageRegionReaderInternals *Internals; }; } // end namespace gdcm #endif //GDCMIMAGEEXTENTREADER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageToImageFilter.cxx000066400000000000000000000016541412732066400255350ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageToImageFilter.h" #include "gdcmImage.h" namespace gdcm { ImageToImageFilter::ImageToImageFilter() { Input = new Image; Output = new Image; } Image &ImageToImageFilter::GetInput() { return dynamic_cast(*Input); } const Image &ImageToImageFilter::GetOutput() const { return dynamic_cast(*Output); } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageToImageFilter.h000066400000000000000000000022451412732066400251570ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMAGETOIMAGEFILTER_H #define GDCMIMAGETOIMAGEFILTER_H #include "gdcmPixmapToPixmapFilter.h" namespace gdcm { class Image; /** * \brief ImageToImageFilter class * \details Super class for all filter taking an image and producing an output image */ class GDCM_EXPORT ImageToImageFilter : public PixmapToPixmapFilter { public: ImageToImageFilter(); ~ImageToImageFilter() = default; Image &GetInput(); // NOTE: covariant return-type to preserve backward compatible API /// Get Output image const Image &GetOutput() const; protected: }; } // end namespace gdcm #endif //GDCMIMAGETOIMAGEFILTER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageWriter.cxx000066400000000000000000000336201412732066400243140ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageWriter.h" #include "gdcmTrace.h" #include "gdcmDataSet.h" #include "gdcmDataElement.h" #include "gdcmAttribute.h" #include "gdcmUIDGenerator.h" #include "gdcmSystem.h" #include "gdcmImageHelper.h" #include "gdcmLookupTable.h" #include "gdcmItem.h" #include "gdcmSequenceOfItems.h" namespace gdcm { ImageWriter::ImageWriter() { PixelData = new Image; } ImageWriter::~ImageWriter() = default; MediaStorage ImageWriter::ComputeTargetMediaStorage() { MediaStorage ms; if( !ms.SetFromFile( GetFile() ) ) { // Let's fix some old ACR-NEMA stuff: ms = ImageHelper::ComputeMediaStorageFromModality( ms.GetModality(), PixelData->GetNumberOfDimensions(), PixelData->GetPixelFormat(), PixelData->GetPhotometricInterpretation(), GetImage().GetIntercept(), GetImage().GetSlope() ); } // double check for MR Image Storage: if( ms == MediaStorage::MRImageStorage && ( GetImage().GetIntercept() != 0.0 || GetImage().GetSlope() != 1.0 ) ) { ms = ImageHelper::ComputeMediaStorageFromModality( ms.GetModality(), PixelData->GetNumberOfDimensions(), PixelData->GetPixelFormat(), PixelData->GetPhotometricInterpretation(), GetImage().GetIntercept(), GetImage().GetSlope() ); } // double check for Grayscale since they need specific pixel type if( ms == MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage || ms == MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage ) { // Always pretend to use number of dimension = 3 here: ms = ImageHelper::ComputeMediaStorageFromModality( ms.GetModality(), 3 /*PixelData->GetNumberOfDimensions()*/, PixelData->GetPixelFormat(), PixelData->GetPhotometricInterpretation(), GetImage().GetIntercept(), GetImage().GetSlope() ); } return ms; } bool ImageWriter::Write() { const MediaStorage ms = ComputeTargetMediaStorage(); if( !PrepareWrite( ms ) ) return false; //assert( Stream.is_open() ); File& file = GetFile(); DataSet& ds = file.GetDataSet(); // Some Type 2 Element: // PatientName if( !ds.FindDataElement( Tag(0x0010,0x0010) ) ) { DataElement de( Tag(0x0010,0x0010) ); de.SetVR( Attribute<0x0010,0x0010>::GetVR() ); ds.Insert( de ); } // PatientID if( !ds.FindDataElement( Tag(0x0010,0x0020) ) ) { DataElement de( Tag(0x0010,0x0020) ); de.SetVR( Attribute<0x0010,0x0020>::GetVR() ); ds.Insert( de ); } // PatientBirthDate if( !ds.FindDataElement( Tag(0x0010,0x0030) ) ) { DataElement de( Tag(0x0010,0x0030) ); de.SetVR( Attribute<0x0010,0x0030>::GetVR() ); ds.Insert( de ); } // PatientSex if( !ds.FindDataElement( Tag(0x0010,0x0040) ) ) { DataElement de( Tag(0x0010,0x0040) ); de.SetVR( Attribute<0x0010,0x0040>::GetVR() ); ds.Insert( de ); } // Laterality if( false && !ds.FindDataElement( Tag(0x0020,0x0060) ) ) { DataElement de( Tag(0x0020,0x0060) ); de.SetVR( Attribute<0x0020,0x0060>::GetVR() ); ds.Insert( de ); } // StudyDate char date[22]; const size_t datelen = 8; int res = System::GetCurrentDateTime(date); assert( res ); (void)res;//warning removal if( !ds.FindDataElement( Tag(0x0008,0x0020) ) ) { DataElement de( Tag(0x0008,0x0020) ); // Do not copy the whole cstring: de.SetByteValue( date, datelen ); de.SetVR( Attribute<0x0008,0x0020>::GetVR() ); ds.Insert( de ); } // StudyTime const size_t timelen = 6 + 1 + 6; // time + milliseconds Attribute<0x0008, 0x0030> studytime; if( !ds.FindDataElement( studytime.GetTag() ) ) { // Do not copy the whole cstring: studytime.SetValue( CSComp(date+datelen, timelen) ); ds.Insert( studytime.GetAsDataElement() ); } // ReferringPhysicianName if( !ds.FindDataElement( Tag(0x0008,0x0090) ) ) { DataElement de( Tag(0x0008,0x0090) ); de.SetVR( Attribute<0x0008,0x0090>::GetVR() ); ds.Insert( de ); } // StudyID if( !ds.FindDataElement( Tag(0x0020,0x0010) ) ) { // FIXME: this one is actually bad since the value is needed for DICOMDIR construction DataElement de( Tag(0x0020,0x0010) ); de.SetVR( Attribute<0x0020,0x0010>::GetVR() ); ds.Insert( de ); } // AccessionNumber if( !ds.FindDataElement( Tag(0x0008,0x0050) ) ) { DataElement de( Tag(0x0008,0x0050) ); de.SetVR( Attribute<0x0008,0x0050>::GetVR() ); ds.Insert( de ); } // SeriesNumber if( !ds.FindDataElement( Tag(0x0020,0x0011) ) ) { DataElement de( Tag(0x0020,0x0011) ); de.SetVR( Attribute<0x0020,0x0011>::GetVR() ); ds.Insert( de ); } // InstanceNumber if( !ds.FindDataElement( Tag(0x0020,0x0013) ) ) { DataElement de( Tag(0x0020,0x0013) ); de.SetVR( Attribute<0x0020,0x0013>::GetVR() ); ds.Insert( de ); } assert( ms != MediaStorage::MS_END ); // Patient Orientation if( ms == MediaStorage::SecondaryCaptureImageStorage && !ds.FindDataElement( Tag(0x0020,0x0020) ) ) { DataElement de( Tag(0x0020,0x0020) ); de.SetVR( Attribute<0x0020,0x0020>::GetVR() ); ds.Insert( de ); } // (re)Compute MediaStorage: if( !ds.FindDataElement( Tag(0x0008, 0x0060) ) ) { const char *modality = ms.GetModality(); DataElement de( Tag(0x0008, 0x0060 ) ); VL::Type strlenModality = (VL::Type)strlen(modality); de.SetByteValue( modality, strlenModality ); de.SetVR( Attribute<0x0008, 0x0060>::GetVR() ); ds.Insert( de ); } else { const ByteValue *bv = ds.GetDataElement( Tag(0x0008, 0x0060 ) ).GetByteValue(); std::string modality2; if( bv ) { modality2 = std::string( bv->GetPointer(), bv->GetLength() ); //assert( modality2.find( ' ' ) == std::string::npos ); // no space ... } else { // remove empty Modality, and set a new one... ds.Remove( Tag(0x0008, 0x0060 ) ); // Modality is Type 1 ! assert( ms != MediaStorage::MS_END ); } /* if( modality2 != ms.GetModality() ) { assert( std::string(ms.GetModality()).find( ' ' ) == std::string::npos ); // no space ... DataElement de( Tag(0x0008, 0x0060 ) ); de.SetByteValue( ms.GetModality(), strlen(ms.GetModality()) ); de.SetVR( Attribute<0x0008, 0x0060>::GetVR() ); ds.Insert( de ); // FIXME: should we always replace ? // Well technically you could have a SecondaryCaptureImageStorage with a modality of NM... } */ } if( !ds.FindDataElement( Tag(0x0008, 0x0064) ) ) { if( ms == MediaStorage::SecondaryCaptureImageStorage ) { // (0008,0064) CS [SI] # 2, 1 ConversionType const char conversion[] = "WSD "; // FIXME DataElement de( Tag(0x0008, 0x0064 ) ); VL::Type strlenConversion = (VL::Type)strlen(conversion); de.SetByteValue( conversion, strlenConversion ); de.SetVR( Attribute<0x0008, 0x0064>::GetVR() ); ds.Insert( de ); } } Image & pixeldata = GetImage(); PixelFormat pf = pixeldata.GetPixelFormat(); PhotometricInterpretation pi = pixeldata.GetPhotometricInterpretation(); // Do the Rescale Intercept & Slope if( pi == PhotometricInterpretation::MONOCHROME1 || pi == PhotometricInterpretation::MONOCHROME2 ) { assert( pf.GetSamplesPerPixel() == 1 ); ImageHelper::SetRescaleInterceptSlopeValue(GetFile(), pixeldata); if( ms == MediaStorage::RTDoseStorage && pixeldata.GetIntercept() != 0 ) { return false; } else if( ms == MediaStorage::MRImageStorage && (pixeldata.GetIntercept() != 0 || pixeldata.GetSlope() != 1.0) ) { if( !gdcm::ImageHelper::GetForceRescaleInterceptSlope() ) return false; } } else { gdcmAssertAlwaysMacro( pixeldata.GetIntercept() == 0 && pixeldata.GetSlope() == 1 ); } // Attribute<0x0028, 0x0006> planarconfiguration; // planarconfiguration.SetValue( PixelData->GetPlanarConfiguration() ); // ds.Replace( planarconfiguration.GetAsDataElement() ); // PhotometricInterpretation // const Tag tphotometricinterpretation(0x0028, 0x0004); //if( !ds.FindDataElement( Tag(0x0028, 0x0004) ) ) { //if( pi == PhotometricInterpretation::RGB // || pi == PhotometricInterpretation::YBR_FULL ) // FIXME // { // Attribute<0x0028, 0x0006> planarconfiguration; // planarconfiguration.SetValue( PixelData->GetPlanarConfiguration() ); // ds.Replace( planarconfiguration.GetAsDataElement() ); // } //else if ( pi == PhotometricInterpretation::PALETTE_COLOR ) { const LookupTable &lut = PixelData->GetLUT(); assert( lut.Initialized() ); // assert( (pf.GetBitsAllocated() == 8 && pf.GetPixelRepresentation() == 0) // || (pf.GetBitsAllocated() == 16 && pf.GetPixelRepresentation() == 0) ); // lut descriptor: // (0028,1101) US 256\0\16 # 6, 3 RedPaletteColorLookupTableDescriptor // (0028,1102) US 256\0\16 # 6, 3 GreenPaletteColorLookupTableDescriptor // (0028,1103) US 256\0\16 # 6, 3 BluePaletteColorLookupTableDescriptor // lut data: unsigned short length, subscript, bitsize; unsigned short rawlut8[256]; unsigned short rawlut16[65536]; unsigned short *rawlut = rawlut8; unsigned int lutlen = 256; if( pf.GetBitsAllocated() == 16 ) { rawlut = rawlut16; lutlen = 65536; } unsigned int l; // FIXME: should I really clear rawlut each time ? // RED memset(rawlut,0,lutlen*2); lut.GetLUT(LookupTable::RED, (unsigned char*)rawlut, l); DataElement redde( Tag(0x0028, 0x1201) ); redde.SetVR( VR::OW ); redde.SetByteValue( (char*)rawlut, l); ds.Replace( redde ); // descriptor: Attribute<0x0028, 0x1101, VR::US, VM::VM3> reddesc; lut.GetLUTDescriptor(LookupTable::RED, length, subscript, bitsize); reddesc.SetValue(length,0); reddesc.SetValue(subscript,1); reddesc.SetValue(bitsize,2); ds.Replace( reddesc.GetAsDataElement() ); // GREEN memset(rawlut,0,lutlen*2); lut.GetLUT(LookupTable::GREEN, (unsigned char*)rawlut, l); DataElement greende( Tag(0x0028, 0x1202) ); greende.SetVR( VR::OW ); greende.SetByteValue( (char*)rawlut, l); ds.Replace( greende ); // descriptor: Attribute<0x0028, 0x1102, VR::US, VM::VM3> greendesc; lut.GetLUTDescriptor(LookupTable::GREEN, length, subscript, bitsize); greendesc.SetValue(length,0); greendesc.SetValue(subscript,1); greendesc.SetValue(bitsize,2); ds.Replace( greendesc.GetAsDataElement() ); // BLUE memset(rawlut,0,lutlen*2); lut.GetLUT(LookupTable::BLUE, (unsigned char*)rawlut, l); DataElement bluede( Tag(0x0028, 0x1203) ); bluede.SetVR( VR::OW ); bluede.SetByteValue( (char*)rawlut, l); ds.Replace( bluede ); // descriptor: Attribute<0x0028, 0x1103, VR::US, VM::VM3> bluedesc; lut.GetLUTDescriptor(LookupTable::BLUE, length, subscript, bitsize); bluedesc.SetValue(length,0); bluedesc.SetValue(subscript,1); bluedesc.SetValue(bitsize,2); ds.Replace( bluedesc.GetAsDataElement() ); } ds.Remove( Tag(0x0028, 0x1221) ); ds.Remove( Tag(0x0028, 0x1222) ); ds.Remove( Tag(0x0028, 0x1223) ); } // FIXME shouldn't this be done by the ImageApplyLookupTable filter ? if( pi == PhotometricInterpretation::RGB ) { // usual tags: ds.Remove( Tag(0x0028, 0x1101) ); ds.Remove( Tag(0x0028, 0x1102) ); ds.Remove( Tag(0x0028, 0x1103) ); ds.Remove( Tag(0x0028, 0x1201) ); ds.Remove( Tag(0x0028, 0x1202) ); ds.Remove( Tag(0x0028, 0x1203) ); // Don't forget the segmented one: ds.Remove( Tag(0x0028, 0x1221) ); ds.Remove( Tag(0x0028, 0x1222) ); ds.Remove( Tag(0x0028, 0x1223) ); // PaletteColorLookupTableUID ?? ds.Remove( Tag(0x0028, 0x1199) ); } // Attribute<0x0028, 0x0004> photometricinterpretation; // photometricinterpretation.SetValue( pi ); // ds.Replace( photometricinterpretation.GetAsDataElement() ); Attribute<0x0028,0x0004> piat; //const DataElement &pide = ds.GetDataElement( piat.GetTag() ); //const char *str1 = pide.GetByteValue()->GetPointer(); { const char *pistr = PhotometricInterpretation::GetPIString(pi); DataElement de( Tag(0x0028, 0x0004 ) ); VL::Type strlenPistr = (VL::Type)strlen(pistr); de.SetByteValue( pistr, strlenPistr ); de.SetVR( piat.GetVR() ); ds.Replace( de ); } // Spacing: std::vector sp; sp.resize(3); // important ! sp[0] = pixeldata.GetSpacing(0); sp[1] = pixeldata.GetSpacing(1); sp[2] = pixeldata.GetSpacing(2); // might be a dummy value... ImageHelper::SetSpacingValue(ds, sp); // Direction Cosines: const double *dircos = pixeldata.GetDirectionCosines(); if( dircos ) { std::vector iop; iop.resize(6); iop[0] = dircos[0]; iop[1] = dircos[1]; iop[2] = dircos[2]; iop[3] = dircos[3]; iop[4] = dircos[4]; iop[5] = dircos[5]; ImageHelper::SetDirectionCosinesValue(ds, iop); } // Origin: const double *origin = pixeldata.GetOrigin(); if( origin ) { ImageHelper::SetOriginValue(ds, pixeldata); } assert( Stream ); if( !Writer::Write() ) { return false; } return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmImageWriter.h000066400000000000000000000035611412732066400237420ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMAGEWRITER_H #define GDCMIMAGEWRITER_H #include "gdcmPixmapWriter.h" #include "gdcmImage.h" namespace gdcm { class Image; /** * \brief ImageWriter * * This is an extended version of the PixmapWriter. Pay attention that: * 1. It will populate missing attribute for Secondary Capture Image Storage instances, * 2. It may also change an input MR Image Storage instance into a pseudo Enhanced MR Image Storage instance whenever Modality LUT is required. * 3. Some DataElement related to gdcm::Image may be slightly altered. */ class GDCM_EXPORT ImageWriter : public PixmapWriter { public: ImageWriter(); ~ImageWriter() override; /// Set/Get Image to be written /// It will overwrite anything Image infos found in DataSet /// (see parent class to see how to pass dataset) const Image& GetImage() const override { return dynamic_cast(*PixelData); } Image& GetImage() override { return dynamic_cast(*PixelData); } // FIXME //void SetImage(Image const &img); /// Write bool Write() override; // Execute() /// internal function used to compute a target MediaStorage the most appropriate /// User may want to call this function ahead of time (before Write) MediaStorage ComputeTargetMediaStorage(); protected: private: }; } // end namespace gdcm #endif //GDCMIMAGEWRITER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmJPEG12Codec.cxx000066400000000000000000000015651412732066400237260ustar00rootroot00000000000000/*========================================================================= 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 "gdcmJPEG12Codec.h" #include "gdcm_ljpeg12.h" #include #define JPEGBITSCodec JPEG12Codec #define my_error_mgr my_error_mgr_12BIT #define JPEGInternals JPEGInternals_12BIT #define my_source_mgr my_source_mgr_12BIT #define my_destination_mgr my_destination_mgr_12BIT #include "gdcmJPEGBITSCodec.hxx" GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmJPEG12Codec.h000066400000000000000000000025021412732066400233430ustar00rootroot00000000000000/*========================================================================= 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 GDCMJPEG12CODEC_H #define GDCMJPEG12CODEC_H #include "gdcmJPEGCodec.h" namespace gdcm { class JPEGInternals_12BIT; class ByteValue; /** * \brief Class to do JPEG 12bits (lossy & lossless) * \note internal class */ class JPEG12Codec : public JPEGCodec { public: JPEG12Codec(); ~JPEG12Codec() override; bool DecodeByStreams(std::istream &is, std::ostream &os) override; bool InternalCode(const char *input, unsigned long len, std::ostream &os) override; bool GetHeaderInfo(std::istream &is, TransferSyntax &ts) override; protected: bool IsStateSuspension() const override; bool EncodeBuffer(std::ostream &os, const char *data, size_t datalen) override; private: JPEGInternals_12BIT *Internals; }; } // end namespace gdcm #endif //GDCMJPEG12CODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmJPEG16Codec.cxx000066400000000000000000000015651412732066400237320ustar00rootroot00000000000000/*========================================================================= 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 "gdcmJPEG16Codec.h" #include "gdcm_ljpeg16.h" #include #define JPEGBITSCodec JPEG16Codec #define my_error_mgr my_error_mgr_16BIT #define JPEGInternals JPEGInternals_16BIT #define my_source_mgr my_source_mgr_16BIT #define my_destination_mgr my_destination_mgr_16BIT #include "gdcmJPEGBITSCodec.hxx" GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmJPEG16Codec.h000066400000000000000000000024721412732066400233550ustar00rootroot00000000000000/*========================================================================= 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 GDCMJPEG16CODEC_H #define GDCMJPEG16CODEC_H #include "gdcmJPEGCodec.h" namespace gdcm { class JPEGInternals_16BIT; class ByteValue; /** * \brief Class to do JPEG 16bits (lossless) * \note internal class */ class JPEG16Codec : public JPEGCodec { public: JPEG16Codec(); ~JPEG16Codec() override; bool DecodeByStreams(std::istream &is, std::ostream &os) override; bool InternalCode(const char *input, unsigned long len, std::ostream &os) override; bool GetHeaderInfo(std::istream &is, TransferSyntax &ts) override; protected: bool IsStateSuspension() const override; bool EncodeBuffer(std::ostream &os, const char *data, size_t datalen) override; private: JPEGInternals_16BIT *Internals; }; } // end namespace gdcm #endif //GDCMJPEG16CODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmJPEG2000Codec.cxx000066400000000000000000001503701412732066400240640ustar00rootroot00000000000000/*========================================================================= 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 "gdcmJPEG2000Codec.h" #include "gdcmTransferSyntax.h" #include "gdcmTrace.h" #include "gdcmDataElement.h" #include "gdcmSequenceOfFragments.h" #include "gdcmSwapper.h" #include #include // snprintf #include #if defined(_MSC_VER) && (_MSC_VER < 1900) #define snprintf _snprintf #endif #include "gdcm_openjpeg.h" namespace gdcm { /* Part 1 Table A.2 List of markers and marker segments */ using MarkerType = enum { FF30 = 0xFF30, FF31 = 0xFF31, FF32 = 0xFF32, FF33 = 0xFF33, FF34 = 0xFF34, FF35 = 0xFF35, FF36 = 0xFF36, FF37 = 0xFF37, FF38 = 0xFF38, FF39 = 0xFF39, FF3A = 0xFF3A, FF3B = 0xFF3B, FF3C = 0xFF3C, FF3D = 0xFF3D, FF3E = 0xFF3E, FF3F = 0xFF3F, SOC = 0xFF4F, CAP = 0xFF50, SIZ = 0xFF51, COD = 0xFF52, COC = 0xFF53, TLM = 0xFF55, PLM = 0XFF57, PLT = 0XFF58, QCD = 0xFF5C, QCC = 0xFF5D, RGN = 0xFF5E, POC = 0xFF5F, PPM = 0XFF60, PPT = 0XFF61, CRG = 0xFF63, COM = 0xFF64, SOT = 0xFF90, SOP = 0xFF91, EPH = 0XFF92, SOD = 0xFF93, EOC = 0XFFD9 /* EOI in old jpeg */ }; using OtherType = enum { JP = 0x6a502020, FTYP = 0x66747970, JP2H = 0x6a703268, JP2C = 0x6a703263, JP2 = 0x6a703220, IHDR = 0x69686472, COLR = 0x636f6c72, XML = 0x786d6c20, CDEF = 0x63646566, CMAP = 0x636D6170, PCLR = 0x70636c72, RES = 0x72657320 }; static inline bool hasnolength( uint_fast16_t marker ) { switch( marker ) { case FF30: case FF31: case FF32: case FF33: case FF34: case FF35: case FF36: case FF37: case FF38: case FF39: case FF3A: case FF3B: case FF3C: case FF3D: case FF3E: case FF3F: case SOC: case SOD: case EOC: case EPH: return true; } return false; } static inline bool read16(const char ** input, size_t * len, uint16_t * ret) { if( *len >= 2 ) { union { uint16_t v; char bytes[2]; } u; memcpy(u.bytes, *input, 2); *ret = SwapperDoOp::Swap(u.v); *input += 2; *len -= 2; return true; } return false; } static inline bool read32(const char ** input, size_t * len, uint32_t * ret) { if( *len >= 4 ) { union { uint32_t v; char bytes[4]; } u; memcpy(u.bytes, *input, 4); *ret = SwapperDoOp::Swap(u.v); *input += 4; *len -= 4; return true; } return false; } static inline bool read64(const char ** input, size_t * len, uint64_t * ret) { if( *len >= 8 ) { union { uint64_t v; char bytes[8]; } u; memcpy(u.bytes, *input, 8); *ret = SwapperDoOp::Swap(u.v); *input += 8; *len -= 8; return true; } return false; } static bool parsej2k_imp( const char * const stream, const size_t file_size, bool * lossless, bool * mct ) { uint16_t marker; size_t lenmarker; const char * cur = stream; size_t cur_size = file_size; *lossless = false; // default init while( read16(&cur, &cur_size, &marker) ) { if ( !hasnolength( marker ) ) { uint16_t l; bool r = read16( &cur, &cur_size, &l ); if( !r || l < 2 ) break; lenmarker = (size_t)l - 2; if( marker == COD ) { const uint8_t MCTransformation = *(cur+4); if( MCTransformation == 0x0 ) *mct = false; else if( MCTransformation == 0x1 ) *mct = true; else return false; const uint8_t Transformation = *(cur+9); if( Transformation == 0x0 ) { *lossless = false; return true; } else if( Transformation == 0x1 ) *lossless = true; else return false; } cur += lenmarker; cur_size -= lenmarker; } else if( marker == SOD ) return true; } return false; } static bool parsejp2_imp( const char * const stream, const size_t file_size, bool * lossless, bool * mct ) { uint32_t marker; uint64_t len64; /* ref */ uint32_t len32; /* local 32bits op */ const char * cur = stream; size_t cur_size = file_size; while( read32(&cur, &cur_size, &len32) ) { bool b0 = read32(&cur, &cur_size, &marker); if( !b0 ) break; len64 = len32; if( len32 == 1 ) /* 64bits ? */ { bool b = read64(&cur, &cur_size, &len64); assert( b ); (void)b; len64 -= 8; } if( marker == JP2C ) { const size_t start = cur - stream; if( !len64 ) { len64 = (size_t)(file_size - start + 8); } assert( len64 >= 8 ); return parsej2k_imp( cur, (size_t)(len64 - 8), lossless, mct ); } const size_t lenmarker = (size_t)(len64 - 8); cur += lenmarker; } return false; } /** sample error callback expecting a FILE* client object */ void error_callback(const char *msg, void *) { (void)msg; gdcmErrorMacro( "Error in gdcmopenjpeg" << msg ); } /** sample warning callback expecting a FILE* client object */ void warning_callback(const char *msg, void *) { (void)msg; gdcmWarningMacro( "Warning in gdcmopenjpeg" << msg ); } /** sample debug callback expecting no client object */ void info_callback(const char *msg, void *) { (void)msg; gdcmDebugMacro( "Info in gdcmopenjpeg" << msg ); } #define J2K_CFMT 0 #define JP2_CFMT 1 #define JPT_CFMT 2 #define PXM_DFMT 10 #define PGX_DFMT 11 #define BMP_DFMT 12 #define YUV_DFMT 13 #define TIF_DFMT 14 #define RAW_DFMT 15 #define TGA_DFMT 16 #define PNG_DFMT 17 #define CODEC_JP2 OPJ_CODEC_JP2 #define CODEC_J2K OPJ_CODEC_J2K #define CLRSPC_GRAY OPJ_CLRSPC_GRAY #define CLRSPC_SRGB OPJ_CLRSPC_SRGB struct myfile { char *mem; char *cur; size_t len; }; void gdcm_error_callback(const char* msg, void* ) { fprintf( stderr, "%s", msg ); } OPJ_SIZE_T opj_read_from_memory(void * p_buffer, OPJ_SIZE_T p_nb_bytes, myfile* p_file) { //OPJ_UINT32 l_nb_read = fread(p_buffer,1,p_nb_bytes,p_file); OPJ_SIZE_T l_nb_read; if( p_file->cur + p_nb_bytes <= p_file->mem + p_file->len ) { l_nb_read = 1*p_nb_bytes; } else { l_nb_read = (OPJ_SIZE_T)(p_file->mem + p_file->len - p_file->cur); assert( l_nb_read < p_nb_bytes ); } memcpy(p_buffer,p_file->cur,l_nb_read); p_file->cur += l_nb_read; assert( p_file->cur <= p_file->mem + p_file->len ); //std::cout << "l_nb_read: " << l_nb_read << std::endl; return l_nb_read ? l_nb_read : ((OPJ_SIZE_T)-1); } OPJ_SIZE_T opj_write_from_memory (void * p_buffer, OPJ_SIZE_T p_nb_bytes, myfile* p_file) { //return fwrite(p_buffer,1,p_nb_bytes,p_file); OPJ_SIZE_T l_nb_write; //if( p_file->cur + p_nb_bytes < p_file->mem + p_file->len ) // { l_nb_write = 1*p_nb_bytes; // } //else // { // l_nb_write = p_file->mem + p_file->len - p_file->cur; // assert( l_nb_write < p_nb_bytes ); // } memcpy(p_file->cur,p_buffer,l_nb_write); p_file->cur += l_nb_write; p_file->len += l_nb_write; //assert( p_file->cur < p_file->mem + p_file->len ); return l_nb_write; //return p_nb_bytes; } OPJ_OFF_T opj_skip_from_memory (OPJ_OFF_T p_nb_bytes, myfile * p_file) { //if (fseek(p_user_data,p_nb_bytes,SEEK_CUR)) // { // return -1; // } if( p_file->cur + p_nb_bytes <= p_file->mem + p_file->len ) { p_file->cur += p_nb_bytes; return p_nb_bytes; } p_file->cur = p_file->mem + p_file->len; return -1; } OPJ_BOOL opj_seek_from_memory (OPJ_OFF_T p_nb_bytes, myfile * p_file) { //if (fseek(p_user_data,p_nb_bytes,SEEK_SET)) // { // return false; // } //return true; assert( p_nb_bytes >= 0 ); if( (size_t)p_nb_bytes <= p_file->len ) { p_file->cur = p_file->mem + p_nb_bytes; return OPJ_TRUE; } p_file->cur = p_file->mem + p_file->len; return OPJ_FALSE; } opj_stream_t* OPJ_CALLCONV opj_stream_create_memory_stream (myfile* p_mem,OPJ_SIZE_T p_size,bool p_is_read_stream) { opj_stream_t* l_stream = nullptr; if (! p_mem) { return nullptr; } l_stream = opj_stream_create(p_size,p_is_read_stream); if (! l_stream) { return nullptr; } opj_stream_set_user_data(l_stream,p_mem,nullptr); opj_stream_set_read_function(l_stream,(opj_stream_read_fn) opj_read_from_memory); opj_stream_set_write_function(l_stream, (opj_stream_write_fn) opj_write_from_memory); opj_stream_set_skip_function(l_stream, (opj_stream_skip_fn) opj_skip_from_memory); opj_stream_set_seek_function(l_stream, (opj_stream_seek_fn) opj_seek_from_memory); opj_stream_set_user_data_length(l_stream, p_mem->len /* p_size*/); /* important to avoid an assert() */ return l_stream; } /* * Divide an integer by a power of 2 and round upwards. * * a divided by 2^b */ inline int int_ceildivpow2(int a, int b) { return (a + (1 << b) - 1) >> b; } class JPEG2000Internals { public: JPEG2000Internals() { memset(&coder_param, 0, sizeof(coder_param)); opj_set_default_encoder_parameters(&coder_param); } opj_cparameters coder_param; int nNumberOfThreadsForDecompression{ -1 }; }; void JPEG2000Codec::SetRate(unsigned int idx, double rate) { Internals->coder_param.tcp_rates[idx] = (float)rate; if( Internals->coder_param.tcp_numlayers <= (int)idx ) { Internals->coder_param.tcp_numlayers = idx + 1; } Internals->coder_param.cp_disto_alloc = 1; } double JPEG2000Codec::GetRate(unsigned int idx ) const { return (double)Internals->coder_param.tcp_rates[idx]; } void JPEG2000Codec::SetQuality(unsigned int idx, double q) { Internals->coder_param.tcp_distoratio[idx] = (float)q; if( Internals->coder_param.tcp_numlayers <= (int)idx ) { Internals->coder_param.tcp_numlayers = idx + 1; } Internals->coder_param.cp_fixed_quality = 1; } double JPEG2000Codec::GetQuality(unsigned int idx) const { return (double)Internals->coder_param.tcp_distoratio[idx]; } void JPEG2000Codec::SetTileSize(unsigned int tx, unsigned int ty) { Internals->coder_param.cp_tdx = tx; Internals->coder_param.cp_tdy = ty; Internals->coder_param.tile_size_on = true; } void JPEG2000Codec::SetNumberOfResolutions(unsigned int nres) { Internals->coder_param.numresolution = nres; } void JPEG2000Codec::SetNumberOfThreadsForDecompression( int nThreads) { #if ((OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR >= 3) || (OPJ_VERSION_MAJOR > 2)) if( nThreads < 0 ) { const int x = opj_get_num_cpus(); Internals->nNumberOfThreadsForDecompression = x == 1 ? 0 : x; } else { Internals->nNumberOfThreadsForDecompression = nThreads; } #else (void)nThreads; Internals->nNumberOfThreadsForDecompression = 0; #endif } void JPEG2000Codec::SetReversible(bool res) { LossyFlag = !res; Internals->coder_param.irreversible = !res; } void JPEG2000Codec::SetMCT(unsigned int mct) { // Set the Multiple Component Transformation value (COD -> SGcod) // 0 for none, 1 to apply to components 0, 1, 2 Internals->coder_param.tcp_mct = mct; } JPEG2000Codec::JPEG2000Codec() { Internals = new JPEG2000Internals; SetNumberOfThreadsForDecompression( -1 ); } JPEG2000Codec::~JPEG2000Codec() { delete Internals; } bool JPEG2000Codec::CanDecode(TransferSyntax const &ts) const { return ts == TransferSyntax::JPEG2000Lossless || ts == TransferSyntax::JPEG2000 || ts == TransferSyntax::JPEG2000Part2Lossless || ts == TransferSyntax::JPEG2000Part2; } bool JPEG2000Codec::CanCode(TransferSyntax const &ts) const { return ts == TransferSyntax::JPEG2000Lossless || ts == TransferSyntax::JPEG2000 || ts == TransferSyntax::JPEG2000Part2Lossless || ts == TransferSyntax::JPEG2000Part2; } /* A.4.4 JPEG 2000 image compression If the object allows multi-frame images in the pixel data field, then for these JPEG 2000 Part 1 Transfer Syntaxes, each frame shall be encoded separately. Each fragment shall contain encoded data from a single frame. Note: That is, the processes defined in ISO/IEC 15444-1 shall be applied on a per-frame basis. The proposal for encapsulation of multiple frames in a non-DICOM manner in so-called 'Motion-JPEG' or 'M-JPEG' defined in 15444-3 is not used. */ bool JPEG2000Codec::Decode(DataElement const &in, DataElement &out) { if( NumberOfDimensions == 2 ) { const SequenceOfFragments *sf = in.GetSequenceOfFragments(); const ByteValue *j2kbv = in.GetByteValue(); if( !sf && !j2kbv ) return false; SmartPointer sf_bug = new SequenceOfFragments; if ( j2kbv ) { gdcmWarningMacro( "Pixel Data is not encapsulated correctly. Continuing anyway" ); assert( !sf ); std::stringstream is; size_t j2kbv_len = j2kbv->GetLength(); char *mybuffer = new char[j2kbv_len]; bool b = j2kbv->GetBuffer(mybuffer, (unsigned long)j2kbv_len); if( b ) is.write(mybuffer, j2kbv_len); delete[] mybuffer; if( !b ) return false; try { sf_bug->Read(is,true); } catch ( ... ) { return false; } sf = &*sf_bug; } if( !sf ) return false; std::stringstream is; unsigned long totalLen = sf->ComputeByteLength(); char *buffer = new char[totalLen]; sf->GetBuffer(buffer, totalLen); is.write(buffer, totalLen); delete[] buffer; std::stringstream os; bool r = DecodeByStreams(is, os); if(!r) return false; out = in; std::string str = os.str(); out.SetByteValue( &str[0], (uint32_t)str.size() ); //memcpy(buffer, os.str().c_str(), len); return r; } else if ( NumberOfDimensions == 3 ) { /* I cannot figure out how to use openjpeg to support multiframes * as encoded in DICOM * MM: Hack. If we are lucky enough the number of encapsulated fragments actually match * the number of Z frames. * MM: hopefully this is the standard so people are following it ... */ //#ifdef SUPPORT_MULTIFRAMESJ2K_ONLY const SequenceOfFragments *sf = in.GetSequenceOfFragments(); if( !sf ) return false; std::stringstream os; if( sf->GetNumberOfFragments() != Dimensions[2] ) { gdcmErrorMacro( "Not handled" ); return false; } for(unsigned int i = 0; i < sf->GetNumberOfFragments(); ++i) { std::stringstream is; const Fragment &frag = sf->GetFragment(i); if( frag.IsEmpty() ) return false; const ByteValue *bv = frag.GetByteValue(); if( !bv ) return false; size_t bv_len = bv->GetLength(); char *mybuffer = new char[bv_len]; bv->GetBuffer(mybuffer, bv->GetLength()); is.write(mybuffer, bv->GetLength()); delete[] mybuffer; bool r = DecodeByStreams(is, os); if(!r) return false; assert( r == true ); } std::string str = os.str(); assert( str.size() ); out.SetByteValue( &str[0], (uint32_t)str.size() ); return true; } // else return false; } static inline bool check_comp_valid(opj_image_t *image) { int compno = 0; opj_image_comp_t *comp = &image->comps[compno]; if (comp->prec > 32) // I doubt openjpeg will reach here. return false; bool invalid = false; if (image->numcomps == 3) { opj_image_comp_t *comp1 = &image->comps[1]; opj_image_comp_t *comp2 = &image->comps[2]; if (comp->prec != comp1->prec) invalid = true; if (comp->prec != comp2->prec) invalid = true; if (comp->sgnd != comp1->sgnd) invalid = true; if (comp->sgnd != comp2->sgnd) invalid = true; if (comp->h != comp1->h) invalid = true; if (comp->h != comp2->h) invalid = true; if (comp->w != comp1->w) invalid = true; if (comp->w != comp2->w) invalid = true; } return !invalid; } std::pair JPEG2000Codec::DecodeByStreamsCommon(char *dummy_buffer, size_t buf_size) { opj_dparameters_t parameters; /* decompression parameters */ opj_codec_t* dinfo = nullptr; /* handle to a decompressor */ opj_stream_t *cio = nullptr; opj_image_t *image = nullptr; unsigned char *src = (unsigned char*)dummy_buffer; uint32_t file_length = (uint32_t)buf_size; // 32bits truncation should be ok since DICOM cannot have larger than 2Gb image // WARNING: OpenJPEG is very picky when there is a trailing 00 at the end of the JPC // so we need to make sure to remove it: // See for example: DX_J2K_0Padding.dcm // and D_CLUNIE_CT1_J2KR.dcm // Marker 0xffd9 EOI End of Image (JPEG 2000 EOC End of codestream) // gdcmData/D_CLUNIE_CT1_J2KR.dcm contains a trailing 0xFF which apparently is ok... while( file_length > 0 && src[file_length-1] != 0xd9 ) { file_length--; } // what if 0xd9 is never found ? if( !( file_length > 0 && src[file_length-1] == 0xd9 ) ) { return std::make_pair( nullptr, 0 ); } /* set decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); const char jp2magic[] = "\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A"; if( memcmp( src, jp2magic, sizeof(jp2magic) ) == 0 ) { /* JPEG-2000 compressed image data ... sigh */ // gdcmData/ELSCINT1_JP2vsJ2K.dcm // gdcmData/MAROTECH_CT_JP2Lossy.dcm gdcmWarningMacro( "J2K start like JPEG-2000 compressed image data instead of codestream" ); parameters.decod_format = JP2_CFMT; assert(parameters.decod_format == JP2_CFMT); } else { /* JPEG-2000 codestream */ parameters.decod_format = J2K_CFMT; assert(parameters.decod_format == J2K_CFMT); } parameters.cod_format = PGX_DFMT; assert(parameters.cod_format == PGX_DFMT); /* get a decoder handle */ switch(parameters.decod_format) { case J2K_CFMT: dinfo = opj_create_decompress(CODEC_J2K); break; case JP2_CFMT: dinfo = opj_create_decompress(CODEC_JP2); break; default: gdcmErrorMacro( "Impossible happen" ); return std::make_pair(0,0); } #if ((OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR >= 3) || (OPJ_VERSION_MAJOR > 2)) opj_codec_set_threads(dinfo, Internals->nNumberOfThreadsForDecompression); #endif int reversible; myfile mysrc; myfile *fsrc = &mysrc; fsrc->mem = fsrc->cur = (char*)src; fsrc->len = file_length; OPJ_UINT32 *s[2]; // the following hack is used for the file: DX_J2K_0Padding.dcm // see the function j2k_read_sot in openjpeg (line: 5946) // to deal with zero length Psot OPJ_UINT32 fl = file_length - 100; s[0] = &fl; s[1] = nullptr; opj_set_error_handler(dinfo, gdcm_error_callback, s); cio = opj_stream_create_memory_stream(fsrc,OPJ_J2K_STREAM_CHUNK_SIZE, true); /* setup the decoder decoding parameters using user parameters */ OPJ_BOOL bResult; bResult = opj_setup_decoder(dinfo, ¶meters); if( !bResult ) { opj_destroy_codec(dinfo); opj_stream_destroy(cio); gdcmErrorMacro( "opj_setup_decoder failure" ); return std::make_pair(0,0); } #if 0 OPJ_INT32 l_tile_x0,l_tile_y0; OPJ_UINT32 l_tile_width,l_tile_height,l_nb_tiles_x,l_nb_tiles_y; #endif bResult = opj_read_header( cio, dinfo, &image); if( !bResult ) { opj_destroy_codec(dinfo); opj_stream_destroy(cio); gdcmErrorMacro( "opj_setup_decoder failure" ); return std::make_pair(0,0); } #if 0 /* Optional if you want decode the entire image */ opj_set_decode_area(dinfo, image, (OPJ_INT32)parameters.DA_x0, (OPJ_INT32)parameters.DA_y0, (OPJ_INT32)parameters.DA_x1, (OPJ_INT32)parameters.DA_y1); #endif bResult = opj_decode(dinfo, cio,image); if (!bResult ) { opj_destroy_codec(dinfo); opj_stream_destroy(cio); gdcmErrorMacro( "opj_decode failed" ); return std::make_pair(0,0); } bResult = bResult && (image != nullptr); bResult = bResult && opj_end_decompress(dinfo,cio); if (!image || !check_comp_valid(image) ) { opj_destroy_codec(dinfo); opj_stream_destroy(cio); gdcmErrorMacro( "opj_decode failed" ); return std::make_pair(0,0); } #if 0 if( image->color_space ) { if( image->color_space == CLRSPC_GRAY ) { assert( this->GetPhotometricInterpretation() == PhotometricInterpretation::MONOCHROME2 || this->GetPhotometricInterpretation() == PhotometricInterpretation::MONOCHROME1 || this->GetPhotometricInterpretation() == PhotometricInterpretation::PALETTE_COLOR ); } else if( image->color_space == CLRSPC_SRGB ) { assert( this->GetPhotometricInterpretation() == PhotometricInterpretation::RGB ); } else { assert(0); } } #endif bool b = false; bool lossless; bool mct; if( parameters.decod_format == JP2_CFMT ) b = parsejp2_imp( dummy_buffer, buf_size, &lossless, &mct); else if( parameters.decod_format == J2K_CFMT ) b = parsej2k_imp( dummy_buffer, buf_size, &lossless, &mct); reversible = 0; if( b ) { reversible = lossless; } LossyFlag = !reversible; assert( image->numcomps == this->GetPixelFormat().GetSamplesPerPixel() ); assert( image->numcomps == this->GetPhotometricInterpretation().GetSamplesPerPixel() ); if( this->GetPhotometricInterpretation() == PhotometricInterpretation::RGB || this->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL ) { if( mct ) { gdcmWarningMacro("Invalid PhotometricInterpretation, should be YBR_RCT"); } } else if( this->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_RCT || this->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_ICT ) { if( !mct ) { gdcmWarningMacro("Invalid PhotometricInterpretation, should be RGB"); } } else { if( mct ) { gdcmWarningMacro("MCT flag was set in SamplesPerPixel = 1 image. corrupt j2k ?"); } } /* close the byte stream */ opj_stream_destroy(cio); // Copy buffer unsigned long len = Dimensions[0]*Dimensions[1] * (PF.GetBitsAllocated() / 8) * image->numcomps; char *raw = new char[len]; //assert( len == fsrc->len ); for (unsigned int compno = 0; compno < (unsigned int)image->numcomps; compno++) { opj_image_comp_t *comp = &image->comps[compno]; int w = image->comps[compno].w; int wr = int_ceildivpow2(image->comps[compno].w, image->comps[compno].factor); //int h = image.comps[compno].h; int hr = int_ceildivpow2(image->comps[compno].h, image->comps[compno].factor); //assert( wr * hr * 1 * image->numcomps * (comp->prec/8) == len ); // ELSCINT1_JP2vsJ2K.dcm // -> prec = 12, bpp = 0, sgnd = 0 //assert( wr == Dimensions[0] ); //assert( hr == Dimensions[1] ); if( comp->sgnd != PF.GetPixelRepresentation() ) { PF.SetPixelRepresentation( (uint16_t)comp->sgnd ); } #ifndef GDCM_SUPPORT_BROKEN_IMPLEMENTATION assert( comp->prec == PF.GetBitsStored()); // D_CLUNIE_RG3_JPLY.dcm assert( comp->prec - 1 == PF.GetHighBit()); #endif //assert( comp->prec >= PF.GetBitsStored()); if( comp->prec != PF.GetBitsStored() ) { if( comp->prec <= 8 ) PF.SetBitsAllocated( 8 ); else if( comp->prec <= 16 ) PF.SetBitsAllocated( 16 ); else if( comp->prec <= 32 ) PF.SetBitsAllocated( 32 ); PF.SetBitsStored( (unsigned short)comp->prec ); PF.SetHighBit( (unsigned short)(comp->prec - 1) ); // ?? } assert( PF.IsValid() ); assert( comp->prec <= 32 ); if (comp->prec <= 8) { uint8_t *data8 = (uint8_t*)raw + compno; for (int i = 0; i < wr * hr; i++) { int v = image->comps[compno].data[i / wr * w + i % wr]; *data8 = (uint8_t)v; data8 += image->numcomps; } } else if (comp->prec <= 16) { // ELSCINT1_JP2vsJ2K.dcm is a 12bits image uint16_t *data16 = (uint16_t*)(void*)raw + compno; for (int i = 0; i < wr * hr; i++) { int v = image->comps[compno].data[i / wr * w + i % wr]; *data16 = (uint16_t)v; data16 += image->numcomps; } } else { uint32_t *data32 = (uint32_t*)(void*)raw + compno; for (int i = 0; i < wr * hr; i++) { int v = image->comps[compno].data[i / wr * w + i % wr]; *data32 = (uint32_t)v; data32 += image->numcomps; } } } /* free remaining structures */ if (dinfo) { opj_destroy_codec(dinfo); } /* free image data structure */ opj_image_destroy(image); return std::make_pair(raw,len); } bool JPEG2000Codec::DecodeByStreams(std::istream &is, std::ostream &os) { // FIXME: Do some stupid work: is.seekg( 0, std::ios::end); size_t buf_size = (size_t)is.tellg(); char *dummy_buffer = new char[buf_size]; is.seekg(0, std::ios::beg); is.read( dummy_buffer, buf_size); std::pair raw_len = this->DecodeByStreamsCommon(dummy_buffer, buf_size); /* free the memory containing the code-stream */ delete[] dummy_buffer; if( !raw_len.first || !raw_len.second ) return false; os.write( raw_len.first, raw_len.second); delete[] raw_len.first; return true; } template void rawtoimage_fill2(const T *inputbuffer, int w, int h, int numcomps, opj_image_t *image, int pc, int bitsallocated, int bitsstored, int highbit, int sign) { uint16_t pmask = 0xffff; pmask = (uint16_t)(pmask >> ( bitsallocated - bitsstored )); const T *p = inputbuffer; if( sign ) { // smask : to check the 'sign' when BitsStored != BitsAllocated uint16_t smask = 0x0001; smask = (uint16_t)( smask << ( 16 - (bitsallocated - bitsstored + 1) )); // nmask : to propagate sign bit on negative values int16_t nmask = (int16_t)0x8000; nmask = (int16_t)(nmask >> ( bitsallocated - bitsstored - 1 )); if( pc ) { for(int compno = 0; compno < numcomps; compno++) { for (int i = 0; i < w * h; i++) { /* compno : 0 = GREY, (0, 1, 2) = (R, G, B) */ uint16_t c = *p; c = (uint16_t)(c >> (bitsstored - highbit - 1)); if ( c & smask ) { c = (uint16_t)(c | nmask); } else { c = c & pmask; } int16_t fix; memcpy(&fix, &c, sizeof fix); image->comps[compno].data[i] = fix; ++p; } } } else { for (int i = 0; i < w * h; i++) { for(int compno = 0; compno < numcomps; compno++) { /* compno : 0 = GREY, (0, 1, 2) = (R, G, B) */ uint16_t c = *p; c = (uint16_t)(c >> (bitsstored - highbit - 1)); if ( c & smask ) { c = (uint16_t)(c | nmask); } else { c = c & pmask; } int16_t fix; memcpy(&fix, &c, sizeof fix); image->comps[compno].data[i] = fix; ++p; } } } } else { if( pc ) { for(int compno = 0; compno < numcomps; compno++) { for (int i = 0; i < w * h; i++) { /* compno : 0 = GREY, (0, 1, 2) = (R, G, B) */ uint16_t c = *p; c = (uint16_t)( (c >> (bitsstored - highbit - 1)) & pmask); image->comps[compno].data[i] = c; ++p; } } } else { for (int i = 0; i < w * h; i++) { for(int compno = 0; compno < numcomps; compno++) { /* compno : 0 = GREY, (0, 1, 2) = (R, G, B) */ uint16_t c = *p; c = (uint16_t)( (c >> (bitsstored - highbit - 1)) & pmask); image->comps[compno].data[i] = c; ++p; } } } } } template void rawtoimage_fill(const T *inputbuffer, int w, int h, int numcomps, opj_image_t *image, int pc) { const T *p = inputbuffer; if( pc ) { for(int compno = 0; compno < numcomps; compno++) { for (int i = 0; i < w * h; i++) { /* compno : 0 = GREY, (0, 1, 2) = (R, G, B) */ image->comps[compno].data[i] = *p; ++p; } } } else { for (int i = 0; i < w * h; i++) { for(int compno = 0; compno < numcomps; compno++) { /* compno : 0 = GREY, (0, 1, 2) = (R, G, B) */ image->comps[compno].data[i] = *p; ++p; } } } } opj_image_t* rawtoimage(const char *inputbuffer8, opj_cparameters_t *parameters, size_t fragment_size, int image_width, int image_height, int sample_pixel, int bitsallocated, int bitsstored, int highbit, int sign, int quality, int pc) { (void)quality; (void)fragment_size; int w, h; int numcomps; OPJ_COLOR_SPACE color_space; opj_image_cmptparm_t cmptparm[3]; /* maximum of 3 components */ opj_image_t * image = nullptr; const void * inputbuffer = inputbuffer8; assert( sample_pixel == 1 || sample_pixel == 3 ); if( sample_pixel == 1 ) { numcomps = 1; color_space = CLRSPC_GRAY; } else // sample_pixel == 3 { numcomps = 3; color_space = CLRSPC_SRGB; /* Does OpenJPEg support: CLRSPC_SYCC ?? */ } if( bitsallocated % 8 != 0 ) { gdcmDebugMacro( "BitsAllocated is not % 8" ); return nullptr; } assert( bitsallocated % 8 == 0 ); // eg. fragment_size == 63532 and 181 * 117 * 3 * 8 == 63531 ... assert( ((fragment_size + 1)/2 ) * 2 == (((size_t)image_height * image_width * numcomps * (bitsallocated/8) + 1)/ 2 )* 2 ); int subsampling_dx = parameters->subsampling_dx; int subsampling_dy = parameters->subsampling_dy; // FIXME w = image_width; h = image_height; /* initialize image components */ memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t)); //assert( bitsallocated == 8 ); for(int i = 0; i < numcomps; i++) { cmptparm[i].prec = bitsstored; cmptparm[i].prec = bitsallocated; // FIXME cmptparm[i].bpp = bitsallocated; cmptparm[i].sgnd = sign; cmptparm[i].dx = subsampling_dx; cmptparm[i].dy = subsampling_dy; cmptparm[i].w = w; cmptparm[i].h = h; } /* create the image */ image = opj_image_create(numcomps, &cmptparm[0], color_space); if(!image) { return nullptr; } /* set image offset and reference grid */ image->x0 = parameters->image_offset_x0; image->y0 = parameters->image_offset_y0; image->x1 = parameters->image_offset_x0 + (w - 1) * subsampling_dx + 1; image->y1 = parameters->image_offset_y0 + (h - 1) * subsampling_dy + 1; /* set image data */ //assert( fragment_size == numcomps*w*h*(bitsallocated/8) ); if (bitsallocated <= 8) { if( sign ) { rawtoimage_fill((const int8_t*)inputbuffer,w,h,numcomps,image,pc); } else { rawtoimage_fill((const uint8_t*)inputbuffer,w,h,numcomps,image,pc); } } else if (bitsallocated <= 16) { if( bitsallocated != bitsstored ) { if( sign ) { rawtoimage_fill2((const int16_t*)inputbuffer,w,h,numcomps,image,pc, bitsallocated, bitsstored, highbit, sign); } else { rawtoimage_fill2((const uint16_t*)inputbuffer,w,h,numcomps,image,pc, bitsallocated, bitsstored, highbit, sign); } } else { if( sign ) { rawtoimage_fill((const int16_t*)inputbuffer,w,h,numcomps,image,pc); } else { rawtoimage_fill((const uint16_t*)inputbuffer,w,h,numcomps,image,pc); } } } else if (bitsallocated <= 32) { if( sign ) { rawtoimage_fill((const int32_t*)inputbuffer,w,h,numcomps,image,pc); } else { rawtoimage_fill((const uint32_t*)inputbuffer,w,h,numcomps,image,pc); } } else // dead branch ? { opj_image_destroy(image); return nullptr; } return image; } bool JPEG2000Codec::CodeFrameIntoBuffer(char * outdata, size_t outlen, size_t & complen, const char * inputdata, size_t inputlength ) { complen = 0; // default init #if 0 if( NeedOverlayCleanup ) { gdcmErrorMacro( "TODO" ); return false; } #endif const unsigned int *dims = this->GetDimensions(); int image_width = dims[0]; int image_height = dims[1]; int numZ = 0; //dims[2]; const PixelFormat &pf = this->GetPixelFormat(); int sample_pixel = pf.GetSamplesPerPixel(); int bitsallocated = pf.GetBitsAllocated(); int bitsstored = pf.GetBitsStored(); int highbit = pf.GetHighBit(); int sign = pf.GetPixelRepresentation(); int quality = 100; //// input_buffer is ONE image //// fragment_size is the size of this image (fragment) (void)numZ; bool bSuccess; //bool delete_comment = true; opj_cparameters_t parameters; /* compression parameters */ opj_image_t *image = nullptr; //quality = 100; /* set encoding parameters to default values */ //memset(¶meters, 0, sizeof(parameters)); //opj_set_default_encoder_parameters(¶meters); memcpy(¶meters, &(Internals->coder_param), sizeof(parameters)); if ((parameters.cp_disto_alloc || parameters.cp_fixed_alloc || parameters.cp_fixed_quality) && (!(parameters.cp_disto_alloc ^ parameters.cp_fixed_alloc ^ parameters.cp_fixed_quality))) { gdcmErrorMacro( "Error: options -r -q and -f cannot be used together." ); return false; } /* mod fixed_quality */ /* if no rate entered, lossless by default */ if (parameters.tcp_numlayers == 0) { parameters.tcp_rates[0] = 0; parameters.tcp_numlayers = 1; parameters.cp_disto_alloc = 1; } if(parameters.cp_comment == nullptr) { const char comment[] = "Created by GDCM/OpenJPEG version %s"; const char * vers = opj_version(); parameters.cp_comment = (char*)malloc(strlen(comment) + 10); snprintf( parameters.cp_comment, strlen(comment) + 10, comment, vers ); /* no need to delete parameters.cp_comment on exit */ //delete_comment = false; } // Compute the proper number of resolutions to use. // This is mostly done for images smaller than 64 pixels // along any dimension. unsigned int numberOfResolutions = 0; unsigned int tw = image_width >> 1; unsigned int th = image_height >> 1; while( tw && th ) { numberOfResolutions++; tw >>= 1; th >>= 1; } // Clamp the number of resolutions to 6. if( numberOfResolutions > 6 ) { numberOfResolutions = 6; } parameters.numresolution = numberOfResolutions; /* decode the source image */ /* ----------------------- */ image = rawtoimage((const char*)inputdata, ¶meters, inputlength, image_width, image_height, sample_pixel, bitsallocated, bitsstored, highbit, sign, quality, this->GetPlanarConfiguration() ); if (!image) { return false; } /* encode the destination image */ /* ---------------------------- */ parameters.cod_format = J2K_CFMT; /* J2K format output */ size_t codestream_length; opj_codec_t* cinfo = nullptr; opj_stream_t *cio = nullptr; /* get a J2K compressor handle */ cinfo = opj_create_compress(CODEC_J2K); /* setup the encoder parameters using the current image and using user parameters */ opj_setup_encoder(cinfo, ¶meters, image); myfile mysrc; myfile *fsrc = &mysrc; char *buffer_j2k = new char[inputlength * 2]; // overallocated for weird case fsrc->mem = fsrc->cur = buffer_j2k; fsrc->len = 0; //inputlength; /* open a byte stream for writing */ /* allocate memory for all tiles */ cio = opj_stream_create_memory_stream(fsrc,OPJ_J2K_STREAM_CHUNK_SIZE,false); if (! cio) { return false; } /* encode the image */ /*if (*indexfilename) // If need to extract codestream information bSuccess = opj_encode_with_info(cinfo, cio, image, &cstr_info); else*/ bSuccess = opj_start_compress(cinfo,image,cio) ? true : false; bSuccess = bSuccess && opj_encode(cinfo, cio); bSuccess = bSuccess && opj_end_compress(cinfo, cio); if (!bSuccess) { opj_stream_destroy(cio); return false; } codestream_length = mysrc.len; /* write the buffer to disk */ //f = fopen(parameters.outfile, "wb"); //if (!f) { // fprintf(stderr, "failed to open %s for writing\n", parameters.outfile); // return 1; //} //fwrite(cio->buffer, 1, codestream_length, f); //#define MDEBUG #ifdef MDEBUG static int c = 0; std::ostringstream os; os << "/tmp/debug"; os << c; c++; os << ".j2k"; std::ofstream debug(os.str().c_str(), std::ios::binary); debug.write((char*)(cio->buffer), codestream_length); debug.close(); #endif bool success = false; if( codestream_length <= outlen ) { success = true; memcpy(outdata, (char*)(mysrc.mem), codestream_length); } delete [] buffer_j2k; /* close and free the byte stream */ opj_stream_destroy(cio); /* free remaining compression structures */ opj_destroy_codec(cinfo); complen = codestream_length; /* free user parameters structure */ if(parameters.cp_comment) free(parameters.cp_comment); if(parameters.cp_matrice) free(parameters.cp_matrice); /* free image data */ opj_image_destroy(image); return success; } // Compress into JPEG bool JPEG2000Codec::Code(DataElement const &in, DataElement &out) { out = in; // // Create a Sequence Of Fragments: SmartPointer sq = new SequenceOfFragments; const unsigned int *dims = this->GetDimensions(); int image_width = dims[0]; int image_height = dims[1]; const ByteValue *bv = in.GetByteValue(); const char *input = bv->GetPointer(); unsigned long len = bv->GetLength(); unsigned long image_len = len / dims[2]; size_t inputlength = image_len; for(unsigned int dim = 0; dim < dims[2]; ++dim) { const char *inputdata = input + dim * image_len; std::vector rgbyteCompressed; rgbyteCompressed.resize(image_width * image_height * 4); size_t cbyteCompressed; const bool b = this->CodeFrameIntoBuffer((char*)&rgbyteCompressed[0], 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 ); sq->AddFragment( frag ); } assert( sq->GetNumberOfFragments() == dims[2] ); out.SetValue( *sq ); return true; } bool JPEG2000Codec::GetHeaderInfo(std::istream &is, TransferSyntax &ts) { // FIXME: Do some stupid work: is.seekg( 0, std::ios::end); size_t buf_size = (size_t)is.tellg(); char *dummy_buffer = new char[buf_size]; is.seekg(0, std::ios::beg); is.read( dummy_buffer, buf_size); bool b = GetHeaderInfo( dummy_buffer, (size_t)buf_size, ts ); delete[] dummy_buffer; return b; } bool JPEG2000Codec::GetHeaderInfo(const char * dummy_buffer, size_t buf_size, TransferSyntax &ts) { opj_dparameters_t parameters; /* decompression parameters */ opj_codec_t* dinfo = nullptr; /* handle to a decompressor */ opj_stream_t *cio = nullptr; opj_image_t *image = nullptr; const unsigned char *src = (const unsigned char*)dummy_buffer; size_t file_length = buf_size; /* set decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); const char jp2magic[] = "\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A"; if( memcmp( src, jp2magic, sizeof(jp2magic) ) == 0 ) { /* JPEG-2000 compressed image data */ // gdcmData/ELSCINT1_JP2vsJ2K.dcm gdcmWarningMacro( "J2K start like JPEG-2000 compressed image data instead of codestream" ); parameters.decod_format = JP2_CFMT; assert(parameters.decod_format == JP2_CFMT); } else { /* JPEG-2000 codestream */ parameters.decod_format = J2K_CFMT; assert(parameters.decod_format == J2K_CFMT); } parameters.cod_format = PGX_DFMT; assert(parameters.cod_format == PGX_DFMT); /* get a decoder handle */ switch(parameters.decod_format ) { case J2K_CFMT: dinfo = opj_create_decompress(CODEC_J2K); break; case JP2_CFMT: dinfo = opj_create_decompress(CODEC_JP2); break; default: gdcmErrorMacro( "Impossible happen" ); return false; } #if ((OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR >= 3) || (OPJ_VERSION_MAJOR > 2)) opj_codec_set_threads(dinfo, Internals->nNumberOfThreadsForDecompression); #endif myfile mysrc; myfile *fsrc = &mysrc; fsrc->mem = fsrc->cur = (char*)const_cast(src); fsrc->len = file_length; // the hack is not used when reading meta-info of a j2k stream: opj_set_error_handler(dinfo, gdcm_error_callback, nullptr); cio = opj_stream_create_memory_stream(fsrc,OPJ_J2K_STREAM_CHUNK_SIZE, true); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); bool bResult; #if 0 OPJ_INT32 l_tile_x0,l_tile_y0; OPJ_UINT32 l_tile_width,l_tile_height,l_nb_tiles_x,l_nb_tiles_y; #endif bResult = opj_read_header( cio, dinfo, &image) ? true : false; if(!bResult) { opj_stream_destroy(cio); return false; } //image = opj_decode(dinfo, cio); //bResult = bResult && (image != 00); //bResult = bResult && opj_end_decompress(dinfo,cio); //if (!image) // { // opj_destroy_codec(dinfo); // opj_stream_destroy(cio); // gdcmErrorMacro( "opj_decode failed" ); // return false; // } int reversible; int mct = 0; #if 0 reversible = opj_get_reversible(dinfo, ¶meters ); assert( reversible == 0 || reversible == 1 ); // FIXME assert( mct == 0 || mct == 1 ); #else bool b = false; bool lossless; bool mctb; if( parameters.decod_format == JP2_CFMT ) b = parsejp2_imp( dummy_buffer, buf_size, &lossless, &mctb); else if( parameters.decod_format == J2K_CFMT ) b = parsej2k_imp( dummy_buffer, buf_size, &lossless, &mctb); reversible = 0; if( b ) { reversible = lossless; mct = mctb; } #endif LossyFlag = !reversible; int compno = 0; opj_image_comp_t *comp = &image->comps[compno]; if( !check_comp_valid( image ) ) { gdcmErrorMacro( "Invalid test failed" ); return false; } this->Dimensions[0] = comp->w; this->Dimensions[1] = comp->h; if( comp->prec <= 8 ) { this->PF = PixelFormat( PixelFormat::UINT8 ); } else if( comp->prec <= 16 ) { this->PF = PixelFormat( PixelFormat::UINT16 ); } else if( comp->prec <= 32 ) { this->PF = PixelFormat( PixelFormat::UINT32 ); } else { gdcmErrorMacro( "do not handle precision: " << comp->prec ); return false; } this->PF.SetBitsStored( (unsigned short)comp->prec ); this->PF.SetHighBit( (unsigned short)(comp->prec - 1) ); this->PF.SetPixelRepresentation( (unsigned short)comp->sgnd ); if( image->numcomps == 1 ) { // normally we have codec only, but in some case we have a JP2 with // color space info: // - gdcmData/MAROTECH_CT_JP2Lossy.dcm // - gdcmData/D_CLUNIE_CT1_J2KI.dcm -> color_space = 32767 //assert( image->color_space == 0 || image->color_space == CLRSPC_GRAY ); PI = PhotometricInterpretation::MONOCHROME2; this->PF.SetSamplesPerPixel( 1 ); } else if( image->numcomps == 3 ) { //assert( image->color_space == 0 ); //PI = PhotometricInterpretation::RGB; /* 8.2.4 JPEG 2000 IMAGE COMPRESSION The JPEG 2000 bit stream specifies whether or not a reversible or irreversible multi-component (color) transformation, if any, has been applied. If no multi-component transformation has been applied, then the components shall correspond to those specified by the DICOM Attribute Photometric Interpretation (0028,0004). If the JPEG 2000 Part 1 reversible multi-component transformation has been applied then the DICOM Attribute Photometric Interpretation (0028,0004) shall be YBR_RCT. If the JPEG 2000 Part 1 irreversible multi-component transformation has been applied then the DICOM Attribute Photometric Interpretation (0028,0004) shall be YBR_ICT. Notes: 1. For example, single component may be present, and the Photometric Interpretation (0028,0004) may be MONOCHROME2. 2. Though it would be unusual, would not take advantage of correlation between the red, green and blue components, and would not achieve effective compression, a Photometric Interpretation of RGB could be specified as long as no multi-component transformation was specified by the JPEG 2000 bit stream. 3. Despite the application of a multi-component color transformation and its reflection in the Photometric Interpretation attribute, the color space remains undefined. There is currently no means of conveying standard color spaces either by fixed values (such as sRGB) or by ICC profiles. Note in particular that the JP2 file header is not sent in the JPEG 2000 bitstream that is encapsulated in DICOM. */ if( mct ) PI = PhotometricInterpretation::YBR_RCT; else PI = PhotometricInterpretation::RGB; this->PF.SetSamplesPerPixel( 3 ); } else if( image->numcomps == 4 ) { /* Yes this is legal */ // http://www.crc.ricoh.com/~gormish/jpeg2000conformance/ // jpeg2000testimages/Part4TestStreams/codestreams_profile0/p0_06.j2k gdcmErrorMacro( "Image is 4 components which is not supported anymore in DICOM (ARGB is retired)" ); // TODO: How about I get the 3 comps and set the alpha plane in the overlay ? return false; } else { // jpeg2000testimages/Part4TestStreams/codestreams_profile0/p0_13.j2k gdcmErrorMacro( "Image is " << image->numcomps << " components which is not supported in DICOM" ); return false; } assert( PI != PhotometricInterpretation::UNKNOWN ); bool bmct = false; if( bmct ) { if( reversible ) { ts = TransferSyntax::JPEG2000Part2Lossless; } else { ts = TransferSyntax::JPEG2000Part2; if( PI == PhotometricInterpretation::YBR_RCT ) { // FIXME ??? PI = PhotometricInterpretation::YBR_ICT; } } } else { if( reversible ) { ts = TransferSyntax::JPEG2000Lossless; } else { ts = TransferSyntax::JPEG2000; if( PI == PhotometricInterpretation::YBR_RCT ) { // FIXME ??? PI = PhotometricInterpretation::YBR_ICT; } } } //assert( ts.IsLossy() == this->GetPhotometricInterpretation().IsLossy() ); //assert( ts.IsLossless() == this->GetPhotometricInterpretation().IsLossless() ); if( this->GetPhotometricInterpretation().IsLossy() ) { assert( ts.IsLossy() ); } if( ts.IsLossless() && !ts.IsLossy() ) { assert( this->GetPhotometricInterpretation().IsLossless() ); } /* close the byte stream */ opj_stream_destroy(cio); /* free remaining structures */ if (dinfo) { opj_destroy_codec(dinfo); } /* free image data structure */ opj_image_destroy(image); return true; } bool JPEG2000Codec::DecodeExtent( char *buffer, unsigned int xmin, unsigned int xmax, unsigned int ymin, unsigned int ymax, unsigned int zmin, unsigned int zmax, std::istream & is ) { BasicOffsetTable bot; bot.Read( is ); const unsigned int * dimensions = this->GetDimensions(); // retrieve pixel format *after* DecodeByStreamsCommon ! const PixelFormat pf = this->GetPixelFormat(); // make a copy ! assert( pf.GetBitsAllocated() % 8 == 0 ); assert( pf != PixelFormat::SINGLEBIT ); assert( pf != PixelFormat::UINT12 && pf != PixelFormat::INT12 ); if( NumberOfDimensions == 2 ) { char *dummy_buffer = nullptr; std::vector vdummybuffer; size_t buf_size = 0; const Tag seqDelItem(0xfffe,0xe0dd); Fragment frag; while( frag.ReadPreValue(is) && frag.GetTag() != seqDelItem ) { size_t fraglen = frag.GetVL(); size_t oldlen = vdummybuffer.size(); if( fraglen == 0 && oldlen == 0 ) break; // update buf_size = fraglen + oldlen; vdummybuffer.resize( buf_size ); dummy_buffer = &vdummybuffer[0]; // read J2K is.read( &vdummybuffer[oldlen], fraglen ); } assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 ); assert( zmin == zmax ); assert( zmin == 0 ); std::pair raw_len = this->DecodeByStreamsCommon(dummy_buffer, buf_size); if( !raw_len.first || !raw_len.second ) return false; // check pixel format *after* DecodeByStreamsCommon ! const PixelFormat & pf2 = this->GetPixelFormat(); // SC16BitsAllocated_8BitsStoredJ2K.dcm if( pf.GetSamplesPerPixel() != pf2.GetSamplesPerPixel() || pf.GetBitsAllocated() != pf2.GetBitsAllocated() /* || pf.GetPixelRepresentation() != pf2.GetPixelRepresentation() // TODO, we are a bit too aggressive here */ ) { gdcmErrorMacro( "Invalid PixelFormat found (mismatch DICOM vs J2K)" ); return false; } char *raw = raw_len.first; const unsigned int rowsize = xmax - xmin + 1; const unsigned int colsize = ymax - ymin + 1; const unsigned int bytesPerPixel = pf.GetPixelSize(); const char *tmpBuffer1 = raw; unsigned int z = 0; for (unsigned int y = ymin; y <= ymax; ++y) { size_t theOffset = 0 + (z*dimensions[1]*dimensions[0] + y*dimensions[0] + xmin)*bytesPerPixel; tmpBuffer1 = raw + theOffset; memcpy(&(buffer[((z-zmin)*rowsize*colsize + (y-ymin)*rowsize)*bytesPerPixel]), tmpBuffer1, rowsize*bytesPerPixel); } delete[] raw_len.first; } else if ( NumberOfDimensions == 3 ) { const Tag seqDelItem(0xfffe,0xe0dd); Fragment frag; std::streamoff thestart = is.tellg(); unsigned int numfrags = 0; std::vector< size_t > offsets; while( frag.ReadPreValue(is) && frag.GetTag() != seqDelItem ) { //std::streamoff relstart = is.tellg(); //assert( relstart - thestart == 8 ); std::streamoff off = frag.GetVL(); offsets.push_back( (size_t)off ); is.seekg( off, std::ios::cur ); ++numfrags; } assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 ); assert( numfrags == offsets.size() ); if( numfrags != Dimensions[2] ) { gdcmErrorMacro( "Not handled" ); return false; } for( unsigned int z = zmin; z <= zmax; ++z ) { size_t curoffset = std::accumulate( offsets.begin(), offsets.begin() + z, size_t(0) ); is.seekg( thestart + curoffset + 8 * z, std::ios::beg ); is.seekg( 8, std::ios::cur ); const size_t buf_size = offsets[z]; char *dummy_buffer = new char[ buf_size ]; is.read( dummy_buffer, buf_size ); std::pair raw_len = this->DecodeByStreamsCommon(dummy_buffer, buf_size); /* free the memory containing the code-stream */ delete[] dummy_buffer; if( !raw_len.first || !raw_len.second ) return false; // check pixel format *after* DecodeByStreamsCommon ! const PixelFormat & pf2 = this->GetPixelFormat(); if( pf.GetSamplesPerPixel() != pf2.GetSamplesPerPixel() || pf.GetBitsAllocated() != pf2.GetBitsAllocated() ) { gdcmErrorMacro( "Invalid PixelFormat found (mismatch DICOM vs J2K)" ); return false; } char *raw = raw_len.first; const unsigned int rowsize = xmax - xmin + 1; const unsigned int colsize = ymax - ymin + 1; const unsigned int bytesPerPixel = pf.GetPixelSize(); const char *tmpBuffer1 = raw; for (unsigned int y = ymin; y <= ymax; ++y) { size_t theOffset = 0 + (0*dimensions[1]*dimensions[0] + y*dimensions[0] + xmin)*bytesPerPixel; tmpBuffer1 = raw + theOffset; memcpy(&(buffer[((z-zmin)*rowsize*colsize + (y-ymin)*rowsize)*bytesPerPixel]), tmpBuffer1, rowsize*bytesPerPixel); } delete[] raw_len.first; } } return true; } ImageCodec * JPEG2000Codec::Clone() const { JPEG2000Codec * copy = new JPEG2000Codec; return copy; } bool JPEG2000Codec::StartEncode( std::ostream & ) { return true; } bool JPEG2000Codec::IsRowEncoder() { return false; } bool JPEG2000Codec::IsFrameEncoder() { return true; } bool JPEG2000Codec::AppendRowEncode( std::ostream & , const char * , size_t ) { return false; } bool JPEG2000Codec::AppendFrameEncode( std::ostream & out, const char * data, size_t datalen ) { const unsigned int * dimensions = this->GetDimensions(); const PixelFormat & pf = this->GetPixelFormat(); assert( datalen == dimensions[0] * dimensions[1] * pf.GetPixelSize() ); (void)pf; std::vector rgbyteCompressed; rgbyteCompressed.resize(dimensions[0] * dimensions[1] * 4); size_t cbyteCompressed; const bool b = this->CodeFrameIntoBuffer((char*)&rgbyteCompressed[0], rgbyteCompressed.size(), cbyteCompressed, data, datalen ); if( !b ) return false; out.write( (char*)&rgbyteCompressed[0], cbyteCompressed ); return true; } bool JPEG2000Codec::StopEncode( std::ostream & ) { return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmJPEG2000Codec.h000066400000000000000000000062141412732066400235060ustar00rootroot00000000000000/*========================================================================= 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 GDCMJPEG2000CODEC_H #define GDCMJPEG2000CODEC_H #include "gdcmImageCodec.h" namespace gdcm { class JPEG2000Internals; /** * \brief Class to do JPEG 2000 * \note * the class will produce JPC (JPEG 2000 codestream), since some private implementor * are using full jp2 file the decoder tolerate jp2 input * this is an implementation of an ImageCodec */ class GDCM_EXPORT JPEG2000Codec : public ImageCodec { friend class ImageRegionReader; friend class Bitmap; public: JPEG2000Codec(); ~JPEG2000Codec() override; bool CanDecode(TransferSyntax const &ts) const override; bool CanCode(TransferSyntax const &ts) const override; bool Decode(DataElement const &is, DataElement &os) override; bool Code(DataElement const &in, DataElement &out) override; bool GetHeaderInfo(std::istream &is, TransferSyntax &ts) override; ImageCodec * Clone() const override; // JPEG-2000 / OpenJPEG specific way of encoding lossy-ness // ref: http://www.openjpeg.org/index.php?menu=doc#encoder void SetRate(unsigned int idx, double rate); double GetRate(unsigned int idx = 0) const; void SetQuality(unsigned int idx, double q); double GetQuality(unsigned int idx = 0) const; void SetTileSize(unsigned int tx, unsigned int ty); void SetNumberOfResolutions(unsigned int nres); /// Set Number of threads /// @param nThreads : number of threads for decompression codec, if 0 or 1 decompression is done in current thread, if negative value is set determine how many virtual threads are available void SetNumberOfThreadsForDecompression(int nThreads); void SetReversible(bool res); void SetMCT(unsigned int mct); protected: bool DecodeExtent( char *buffer, unsigned int xmin, unsigned int xmax, unsigned int ymin, unsigned int ymax, unsigned int zmin, unsigned int zmax, std::istream & is ); bool DecodeByStreams(std::istream &is, std::ostream &os) override; bool StartEncode( std::ostream & ) override; bool IsRowEncoder() override; bool IsFrameEncoder() override; bool AppendRowEncode( std::ostream & out, const char * data, size_t datalen ) override; bool AppendFrameEncode( std::ostream & out, const char * data, size_t datalen ) override; bool StopEncode( std::ostream & ) override; private: std::pair DecodeByStreamsCommon(char *dummy_buffer, size_t buf_size); bool CodeFrameIntoBuffer(char * outdata, size_t outlen, size_t & complen, const char * indata, size_t inlen ); bool GetHeaderInfo(const char * dummy_buffer, size_t len, TransferSyntax &ts); JPEG2000Internals *Internals; }; } // end namespace gdcm #endif //GDCMJPEG2000CODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmJPEG8Codec.cxx000066400000000000000000000015561412732066400236530ustar00rootroot00000000000000/*========================================================================= 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 "gdcmJPEG8Codec.h" #include "gdcm_ljpeg8.h" #include #define JPEGBITSCodec JPEG8Codec #define my_error_mgr my_error_mgr_8BIT #define JPEGInternals JPEGInternals_8BIT #define my_source_mgr my_source_mgr_8BIT #define my_destination_mgr my_destination_mgr_8BIT #include "gdcmJPEGBITSCodec.hxx" GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmJPEG8Codec.h000066400000000000000000000024711412732066400232750ustar00rootroot00000000000000/*========================================================================= 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 GDCMJPEG8CODEC_H #define GDCMJPEG8CODEC_H #include "gdcmJPEGCodec.h" namespace gdcm { class JPEGInternals_8BIT; class ByteValue; /** * \brief Class to do JPEG 8bits (lossy & lossless) * \note internal class */ class JPEG8Codec : public JPEGCodec { public: JPEG8Codec(); ~JPEG8Codec() override; bool DecodeByStreams(std::istream &is, std::ostream &os) override; bool InternalCode(const char *input, unsigned long len, std::ostream &os) override; bool GetHeaderInfo(std::istream &is, TransferSyntax &ts) override; protected: bool IsStateSuspension() const override; bool EncodeBuffer(std::ostream &os, const char *data, size_t datalen) override; private: JPEGInternals_8BIT *Internals; }; } // end namespace gdcm #endif //GDCMJPEG8CODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmJPEGBITSCodec.hxx000066400000000000000000001533511412732066400242530ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTrace.h" #include "gdcmTransferSyntax.h" #include /* * jdatasrc.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains decompression data source routines for the case of * reading JPEG data from a file (or any stdio stream). While these routines * are sufficient for most applications, some will want to use a different * source manager. * IMPORTANT: we assume that fread() will correctly transcribe an array of * JOCTETs from 8-bit-wide elements on external storage. If char is wider * than 8 bits on your machine, you may need to do some tweaking. */ /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ namespace gdcm { /* Expanded data source object for stdio input */ typedef struct { struct jpeg_source_mgr pub; /* public fields */ std::istream * infile; /* source stream */ JOCTET * buffer; /* start of buffer */ boolean start_of_file; /* have we gotten any data yet? */ } my_source_mgr; typedef my_source_mgr * my_src_ptr; #define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ /* * Initialize source --- called by jpeg_read_header * before any data is actually read. */ METHODDEF(void) init_source (j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr) cinfo->src; /* We reset the empty-input-file flag for each image, * but we don't clear the input buffer. * This is correct behavior for reading a series of images from one source. */ src->start_of_file = TRUE; } /* * Fill the input buffer --- called whenever buffer is emptied. * * In typical applications, this should read fresh data into the buffer * (ignoring the current state of next_input_byte & bytes_in_buffer), * reset the pointer & count to the start of the buffer, and return TRUE * indicating that the buffer has been reloaded. It is not necessary to * fill the buffer entirely, only to obtain at least one more byte. * * There is no such thing as an EOF return. If the end of the file has been * reached, the routine has a choice of ERREXIT() or inserting fake data into * the buffer. In most cases, generating a warning message and inserting a * fake EOI marker is the best course of action --- this will allow the * decompressor to output however much of the image is there. However, * the resulting error message is misleading if the real problem is an empty * input file, so we handle that case specially. * * In applications that need to be able to suspend compression due to input * not being available yet, a FALSE return indicates that no more data can be * obtained right now, but more may be forthcoming later. In this situation, * the decompressor will return to its caller (with an indication of the * number of scanlines it has read, if any). The application should resume * decompression after it has loaded more data into the input buffer. Note * that there are substantial restrictions on the use of suspension --- see * the documentation. * * When suspending, the decompressor will back up to a convenient restart point * (typically the start of the current MCU). next_input_byte & bytes_in_buffer * indicate where the restart point will be if the current call returns FALSE. * Data beyond this point must be rescanned after resumption, so move it to * the front of the buffer rather than discarding it. */ METHODDEF(boolean) fill_input_buffer (j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr) cinfo->src; size_t nbytes; //FIXME FIXME FIXME FIXME FIXME //nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); std::streampos pos = src->infile->tellg(); std::streampos end = src->infile->seekg(0, std::ios::end).tellg(); src->infile->seekg(pos, std::ios::beg); //FIXME FIXME FIXME FIXME FIXME if( end == pos ) { /* Start the I/O suspension simply by returning false here: */ return FALSE; } if( (end - pos) < INPUT_BUF_SIZE ) { src->infile->read( (char*)src->buffer, (size_t)(end - pos) ); } else { src->infile->read( (char*)src->buffer, INPUT_BUF_SIZE); } std::streamsize gcount = src->infile->gcount(); assert(gcount < INT_MAX); nbytes = (size_t)gcount; if (nbytes <= 0) { if (src->start_of_file) /* Treat empty input file as fatal error */ ERREXIT(cinfo, JERR_INPUT_EMPTY); WARNMS(cinfo, JWRN_JPEG_EOF); /* Insert a fake EOI marker */ src->buffer[0] = (JOCTET) 0xFF; src->buffer[1] = (JOCTET) JPEG_EOI; nbytes = 2; } src->pub.next_input_byte = src->buffer; src->pub.bytes_in_buffer = nbytes; src->start_of_file = FALSE; return TRUE; } /* * Skip data --- used to skip over a potentially large amount of * uninteresting data (such as an APPn marker). * * Writers of suspendable-input applications must note that skip_input_data * is not granted the right to give a suspension return. If the skip extends * beyond the data currently in the buffer, the buffer can be marked empty so * that the next read will cause a fill_input_buffer call that can suspend. * Arranging for additional bytes to be discarded before reloading the input * buffer is the application writer's problem. */ METHODDEF(void) skip_input_data (j_decompress_ptr cinfo, long num_bytes) { my_src_ptr src = (my_src_ptr) cinfo->src; /* Just a dumb implementation for now. Could use fseek() except * it doesn't work on pipes. Not clear that being smart is worth * any trouble anyway --- large skips are infrequent. */ if (num_bytes > 0) { while (num_bytes > (long) src->pub.bytes_in_buffer) { num_bytes -= (long) src->pub.bytes_in_buffer; (void) fill_input_buffer(cinfo); /* note we assume that fill_input_buffer will never return FALSE, * so suspension need not be handled. */ } src->pub.next_input_byte += (size_t) num_bytes; src->pub.bytes_in_buffer -= (size_t) num_bytes; } } /* * An additional method that can be provided by data source modules is the * resync_to_restart method for error recovery in the presence of RST markers. * For the moment, this source module just uses the default resync method * provided by the JPEG library. That method assumes that no backtracking * is possible. */ /* * Terminate source --- called by jpeg_finish_decompress * after all data has been read. Often a no-op. * * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding * application must deal with any cleanup that should happen even * for error exit. */ METHODDEF(void) term_source (j_decompress_ptr cinfo) { (void)cinfo; /* no work necessary here */ } /* * Prepare for input from a stdio stream. * The caller must have already opened the stream, and is responsible * for closing it after finishing decompression. */ GLOBAL(void) jpeg_stdio_src (j_decompress_ptr cinfo, std::istream & infile, bool flag) { my_src_ptr src; /* The source object and input buffer are made permanent so that a series * of JPEG images can be read from the same file by calling jpeg_stdio_src * only before the first one. (If we discarded the buffer at the end of * one image, we'd likely lose the start of the next one.) * This makes it unsafe to use this manager and a different source * manager serially with the same JPEG object. Caveat programmer. */ if (cinfo->src == nullptr) { /* first time for this JPEG object? */ cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_source_mgr)); src = (my_src_ptr) cinfo->src; src->buffer = (JOCTET *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * SIZEOF(JOCTET)); } src = (my_src_ptr) cinfo->src; src->pub.init_source = init_source; src->pub.fill_input_buffer = fill_input_buffer; src->pub.skip_input_data = skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ src->pub.term_source = term_source; src->infile = &infile; if( flag ) { src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ src->pub.next_input_byte = nullptr; /* until buffer loaded */ } } } // end namespace gdcm namespace gdcm { /* * The following was copy/paste from example.c */ struct my_error_mgr { struct jpeg_error_mgr pub; /* "public" fields */ jmp_buf setjmp_buffer; /* for return to caller */ }; typedef struct my_error_mgr* my_error_ptr; class JPEGInternals { public: JPEGInternals():cinfo(),jerr(),StateSuspension(0),SampBuffer(nullptr) {} jpeg_decompress_struct cinfo; jpeg_compress_struct cinfo_comp; my_error_mgr jerr; int StateSuspension; void *SampBuffer; }; JPEGBITSCodec::JPEGBITSCodec() { Internals = new JPEGInternals; BitSample = BITS_IN_JSAMPLE; } JPEGBITSCodec::~JPEGBITSCodec() { delete Internals; } /* * Here's the routine that will replace the standard error_exit method: */ extern "C" { METHODDEF(void) my_error_exit (j_common_ptr cinfo) { /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ my_error_ptr myerr = (my_error_ptr) cinfo->err; /* Always display the message. */ /* We could postpone this until after returning, if we chose. */ (*cinfo->err->output_message) (cinfo); /* Return control to the setjmp point */ longjmp(myerr->setjmp_buffer, 1); } } bool JPEGBITSCodec::GetHeaderInfo(std::istream &is, TransferSyntax &ts) { /* This struct contains the JPEG decompression parameters and pointers to * working space (which is allocated as needed by the JPEG library). */ jpeg_decompress_struct &cinfo = Internals->cinfo; /* We use our private extension JPEG error handler. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ my_error_mgr &jerr = Internals->jerr; /* More stuff */ //FILE * infile; /* source file */ //JSAMPARRAY buffer; /* Output row buffer */ //int row_stride; /* physical row width in output buffer */ if( Internals->StateSuspension == 0 ) { // Step 1: allocate and initialize JPEG decompression object // // We set up the normal JPEG error routines, then override error_exit. cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; // Establish the setjmp return context for my_error_exit to use. if (setjmp(jerr.setjmp_buffer)) { // If we get here, the JPEG code has signaled an error. // We need to clean up the JPEG object, close the input file, and return. // But first handle the case IJG does not like: if ( jerr.pub.msg_code == JERR_BAD_PRECISION /* 18 */ ) { this->BitSample = jerr.pub.msg_parm.i[0]; assert( this->BitSample == 1 || this->BitSample == 8 || this->BitSample == 12 || this->BitSample == 16 ); assert( this->BitSample == cinfo.data_precision ); } jpeg_destroy_decompress(&cinfo); // TODO: www.dcm4che.org/jira/secure/attachment/10185/ct-implicit-little.dcm // weird Icon Image from GE... return false; } } if( Internals->StateSuspension == 0 ) { // Now we can initialize the JPEG decompression object. jpeg_create_decompress(&cinfo); // Step 2: specify data source (eg, a file) jpeg_stdio_src(&cinfo, is, true); } else { jpeg_stdio_src(&cinfo, is, false); } /* Step 3: read file parameters with jpeg_read_header() */ if ( Internals->StateSuspension < 2 ) { if( jpeg_read_header(&cinfo, TRUE) == JPEG_SUSPENDED ) { Internals->StateSuspension = 2; } // First of all are we using the proper JPEG decoder (correct bit sample): if( jerr.pub.num_warnings ) { if ( jerr.pub.msg_code == 128 ) { this->BitSample = jerr.pub.msg_parm.i[0]; jpeg_destroy_decompress(&cinfo); return false; } else { assert( 0 ); } } this->Dimensions[1] = cinfo.image_height; /* Number of rows in image */ this->Dimensions[0] = cinfo.image_width; /* Number of columns in image */ int prep = this->PF.GetPixelRepresentation(); //this->BitSample = cinfo.data_precision; int precision = cinfo.data_precision; // if lossy it should only be 8 or 12, but for lossless it can be [2-16] if( precision == 1 ) { // lossless ! this->PF = PixelFormat( PixelFormat::SINGLEBIT ); } else if( precision <= 8 ) { this->PF = PixelFormat( PixelFormat::UINT8 ); } else if( precision <= 12 ) { this->PF = PixelFormat( PixelFormat::UINT12 ); } else if( precision <= 16 ) { // lossless ! this->PF = PixelFormat( PixelFormat::UINT16 ); } else { assert( 0 ); } this->PF.SetPixelRepresentation( (uint16_t)prep ); this->PF.SetBitsStored( (uint16_t)precision ); assert( (precision - 1) >= 0 ); this->PF.SetHighBit( (uint16_t)(precision - 1) ); this->PlanarConfiguration = 0; // Let's check the color space: // JCS_UNKNOWN -> 0 // JCS_GRAYSCALE, /* monochrome */ // JCS_RGB, /* red/green/blue */ // JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ // JCS_CMYK, /* C/M/Y/K */ // JCS_YCCK /* Y/Cb/Cr/K */ if( cinfo.jpeg_color_space == JCS_UNKNOWN ) { // I do not know if this possible, it looks like IJG always computes a default if( cinfo.num_components == 1 ) { PI = PhotometricInterpretation::MONOCHROME2; this->PF.SetSamplesPerPixel( 1 ); } else if( cinfo.num_components == 3 ) { PI = PhotometricInterpretation::RGB; this->PF.SetSamplesPerPixel( 3 ); } else { assert( 0 ); } } else if( cinfo.jpeg_color_space == JCS_GRAYSCALE ) { assert( cinfo.num_components == 1 ); PI = PhotometricInterpretation::MONOCHROME2; this->PF.SetSamplesPerPixel( 1 ); } else if( cinfo.jpeg_color_space == JCS_RGB ) { assert( cinfo.num_components == 3 ); PI = PhotometricInterpretation::RGB; this->PF.SetSamplesPerPixel( 3 ); } else if( cinfo.jpeg_color_space == JCS_YCbCr ) { assert( cinfo.num_components == 3 ); PI = PhotometricInterpretation::YBR_FULL_422; if( cinfo.process == JPROC_LOSSLESS ) PI = PhotometricInterpretation::RGB; // wotsit ? this->PF.SetSamplesPerPixel( 3 ); this->PlanarConfiguration = 1; } else if( cinfo.jpeg_color_space == JCS_CMYK ) { assert( cinfo.num_components == 4 ); PI = PhotometricInterpretation::CMYK; this->PF.SetSamplesPerPixel( 4 ); } else if( cinfo.jpeg_color_space == JCS_YCCK ) { assert( cinfo.num_components == 4 ); PI = PhotometricInterpretation::YBR_FULL_422; // 4th plane ?? this->PF.SetSamplesPerPixel( 4 ); assert( 0 ); //TODO } else { assert( 0 ); //TODO } } if( cinfo.process == JPROC_LOSSLESS ) { int predictor = cinfo.Ss; /* not very user friendly... */ switch(predictor) { case 1: ts = TransferSyntax::JPEGLosslessProcess14_1; break; default: ts = TransferSyntax::JPEGLosslessProcess14; break; } } else if( cinfo.process == JPROC_SEQUENTIAL ) { if( this->BitSample == 8 ) ts = TransferSyntax::JPEGBaselineProcess1; else if( this->BitSample == 12 ) ts = TransferSyntax::JPEGExtendedProcess2_4; } else if( cinfo.process == JPROC_PROGRESSIVE ) { if( this->BitSample == 8 ) { ts = TransferSyntax::JPEGFullProgressionProcess10_12; } else if( this->BitSample == 12 ) { ts = TransferSyntax::JPEGFullProgressionProcess10_12; } else { assert(0); // TODO return false; } } else { assert(0); // TODO return false; } if( cinfo.process == JPROC_LOSSLESS ) { LossyFlag = false; } else { LossyFlag = true; } // Pixel density stuff: /* UINT8 density_unit UINT16 X_density UINT16 Y_density The resolution information to be written into the JFIF marker; not used otherwise. density_unit may be 0 for unknown, 1 for dots/inch, or 2 for dots/cm. The default values are 0,1,1 indicating square pixels of unknown size. */ if( cinfo.density_unit != 0 || cinfo.X_density != 1 || cinfo.Y_density != 1 ) { gdcmWarningMacro( "Pixel Density from JFIF Marker is not supported (for now)" ); //return false; } #if 0 switch ( cinfo.jpeg_color_space ) { case JCS_GRAYSCALE: if( GetPhotometricInterpretation() != PhotometricInterpretation::MONOCHROME1 && GetPhotometricInterpretation() != PhotometricInterpretation::MONOCHROME2 ) { gdcmWarningMacro( "Wrong PhotometricInterpretation. DICOM says: " << GetPhotometricInterpretation() << " but JPEG says: " << cinfo.jpeg_color_space ); //Internals->SetPhotometricInterpretation( PhotometricInterpretation::MONOCHROME2 ); this->PI = PhotometricInterpretation::MONOCHROME2; } break; case JCS_RGB: assert( GetPhotometricInterpretation() == PhotometricInterpretation::RGB ); break; case JCS_YCbCr: if( GetPhotometricInterpretation() != PhotometricInterpretation::YBR_FULL && GetPhotometricInterpretation() != PhotometricInterpretation::YBR_FULL_422 ) { // DermaColorLossLess.dcm (lossless) // LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm (lossy) gdcmWarningMacro( "Wrong PhotometricInterpretation. DICOM says: " << GetPhotometricInterpretation() << " but JPEG says: " << cinfo.jpeg_color_space ); // Here it gets nasty since apparently when this occurs lossless means // we should not do any color conversion, but we *might* be breaking // correct DICOM file. // FIXME FIXME /* prevent the library from performing any color space conversion */ if ( cinfo.process == JPROC_LOSSLESS ) { cinfo.jpeg_color_space = JCS_UNKNOWN; cinfo.out_color_space = JCS_UNKNOWN; } } break; default: assert(0); return false; } //assert( cinfo.data_precision == BITS_IN_JSAMPLE ); //assert( cinfo.data_precision == this->BitSample ); /* Step 4: set parameters for decompression */ /* no op */ } /* Step 5: Start decompressor */ if (Internals->StateSuspension < 3 ) { if ( jpeg_start_decompress(&cinfo) == FALSE ) { /* Suspension: jpeg_start_decompress */ Internals->StateSuspension = 3; } /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled * output image dimensions available, as well as the output colormap * if we asked for color quantization. * In this example, we need to make an output work buffer of the right size. */ /* JSAMPLEs per row in output buffer */ row_stride = cinfo.output_width * cinfo.output_components; row_stride *= sizeof(JSAMPLE); /* Make a one-row-high sample array that will go away when done with image */ buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); /* Save the buffer in case of suspension to be able to reuse it later: */ Internals->SampBuffer = buffer; } else { /* JSAMPLEs per row in output buffer */ row_stride = cinfo.output_width * cinfo.output_components; row_stride *= sizeof(JSAMPLE); /* Suspension: re-use the buffer: */ buffer = (JSAMPARRAY)Internals->SampBuffer; } /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ while (cinfo.output_scanline < cinfo.output_height) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if that's more convenient. */ if( jpeg_read_scanlines(&cinfo, buffer, 1) == 0 ) { /* Suspension in jpeg_read_scanlines */ Internals->StateSuspension = 3; return true; } os.write((char*)buffer[0], row_stride); } /* Step 7: Finish decompression */ if( jpeg_finish_decompress(&cinfo) == FALSE ) { /* Suspension: jpeg_finish_decompress */ Internals->StateSuspension = 4; } #endif /* Step 8: Release JPEG decompression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_decompress(&cinfo); /* After finish_decompress, we can close the input file. * Here we postpone it until after no more JPEG errors are possible, * so as to simplify the setjmp error logic above. (Actually, I don't * think that jpeg_destroy can do an error exit, but why assume anything...) */ //fclose(infile); /* At this point you may want to check to see whether any corrupt-data * warnings occurred (test whether jerr.pub.num_warnings is nonzero). */ /* In any case make sure the we reset the internal state suspension */ Internals->StateSuspension = 0; /* And we're done! */ return true; } /* * Note: see dcmdjpeg +cn option to avoid the YBR => RGB loss */ bool JPEGBITSCodec::DecodeByStreams(std::istream &is, std::ostream &os) { /* This struct contains the JPEG decompression parameters and pointers to * working space (which is allocated as needed by the JPEG library). */ jpeg_decompress_struct &cinfo = Internals->cinfo; /* We use our private extension JPEG error handler. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ my_error_mgr &jerr = Internals->jerr; /* More stuff */ //FILE * infile; /* source file */ JSAMPARRAY buffer; /* Output row buffer */ size_t row_stride; /* physical row width in output buffer */ if( Internals->StateSuspension == 0 ) { // Step 1: allocate and initialize JPEG decompression object // // We set up the normal JPEG error routines, then override error_exit. cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; // Establish the setjmp return context for my_error_exit to use. if (setjmp(jerr.setjmp_buffer)) { // If we get here, the JPEG code has signaled an error. // We need to clean up the JPEG object, close the input file, and return. // But first handle the case IJG does not like: if ( jerr.pub.msg_code == JERR_BAD_PRECISION /* 18 */ ) { this->BitSample = jerr.pub.msg_parm.i[0]; //assert( this->BitSample == 8 || this->BitSample == 12 || this->BitSample == 16 ); } jpeg_destroy_decompress(&cinfo); // TODO: www.dcm4che.org/jira/secure/attachment/10185/ct-implicit-little.dcm // weird Icon Image from GE... return false; } } if( Internals->StateSuspension == 0 ) { // Now we can initialize the JPEG decompression object. jpeg_create_decompress(&cinfo); // Step 2: specify data source (eg, a file) jpeg_stdio_src(&cinfo, is, true); } else { jpeg_stdio_src(&cinfo, is, false); } /* Step 3: read file parameters with jpeg_read_header() */ if ( Internals->StateSuspension < 2 ) { if( jpeg_read_header(&cinfo, TRUE) == JPEG_SUSPENDED ) { Internals->StateSuspension = 2; } // First of all are we using the proper JPEG decoder (correct bit sample): if( jerr.pub.num_warnings ) { // PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm if ( jerr.pub.msg_code == JWRN_MUST_DOWNSCALE ) { // PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm // PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm // MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm // LJPEG_BuginGDCM12.dcm gdcmDebugMacro( "JWRN_MUST_DOWNSCALE" ); this->BitSample = jerr.pub.msg_parm.i[0]; assert( cinfo.data_precision == this->BitSample ); jpeg_destroy_decompress(&cinfo); return false; } else { assert( 0 ); } } // Let's check the color space: // JCS_UNKNOWN -> 0 // JCS_GRAYSCALE // JCS_RGB // JCS_YCbCr // JCS_CMYK // JCS_YCCK // Sanity checks: const unsigned int * dims = this->GetDimensions(); if( cinfo.image_width != dims[0] || cinfo.image_height != dims[1] ) { gdcmWarningMacro( "dimension mismatch. JPEG is " << cinfo.image_width << "," << cinfo.image_height << " while DICOM " << dims[0] << "," << dims[1] ); //this->Dimensions[0] = cinfo.image_width; //this->Dimensions[1] = cinfo.image_height; /* * Long story short, the real issue is that class such as ImageRegionReader expect to read the * image information without ever touching the JPEG codestream... */ return false; } assert( cinfo.image_width == dims[0] ); assert( cinfo.image_height == dims[1] ); switch ( cinfo.jpeg_color_space ) { case JCS_GRAYSCALE: if( GetPhotometricInterpretation() != PhotometricInterpretation::MONOCHROME1 && GetPhotometricInterpretation() != PhotometricInterpretation::MONOCHROME2 ) { gdcmWarningMacro( "Wrong PhotometricInterpretation. DICOM says: " << GetPhotometricInterpretation() << " but JPEG says: " << (int)cinfo.jpeg_color_space ); //Internals->SetPhotometricInterpretation( PhotometricInterpretation::MONOCHROME2 ); this->PI = PhotometricInterpretation::MONOCHROME2; } break; case JCS_RGB: //assert( GetPhotometricInterpretation() == PhotometricInterpretation::RGB ); if ( cinfo.process == JPROC_LOSSLESS ) { cinfo.jpeg_color_space = JCS_UNKNOWN; cinfo.out_color_space = JCS_UNKNOWN; } if( GetPhotometricInterpretation() == PhotometricInterpretation::YBR_RCT || GetPhotometricInterpretation() == PhotometricInterpretation::YBR_ICT ) this->PI = PhotometricInterpretation::RGB; break; case JCS_YCbCr: if( GetPhotometricInterpretation() != PhotometricInterpretation::YBR_FULL && GetPhotometricInterpretation() != PhotometricInterpretation::YBR_FULL_422 ) { // DermaColorLossLess.dcm (lossless) // LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm (lossy) gdcmWarningMacro( "Wrong PhotometricInterpretation. DICOM says: " << GetPhotometricInterpretation() << " but JPEG says: " << (int)cinfo.jpeg_color_space ); // Here it gets nasty since apparently when this occurs lossless means // we should not do any color conversion, but we *might* be breaking // correct DICOM file. // FIXME FIXME /* prevent the library from performing any color space conversion */ cinfo.jpeg_color_space = JCS_UNKNOWN; cinfo.out_color_space = JCS_UNKNOWN; } if ( cinfo.process == JPROC_LOSSLESS ) { //cinfo.jpeg_color_space = JCS_UNKNOWN; //cinfo.out_color_space = JCS_UNKNOWN; } if( GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL || GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL_422 ) { cinfo.jpeg_color_space = JCS_UNKNOWN; cinfo.out_color_space = JCS_UNKNOWN; //this->PlanarConfiguration = 1; } break; case JCS_CMYK: assert( GetPhotometricInterpretation() == PhotometricInterpretation::CMYK ); if ( cinfo.process == JPROC_LOSSLESS ) { cinfo.jpeg_color_space = JCS_UNKNOWN; cinfo.out_color_space = JCS_UNKNOWN; } break; case JCS_UNKNOWN: if ( cinfo.process == JPROC_LOSSLESS ) { cinfo.jpeg_color_space = JCS_UNKNOWN; cinfo.out_color_space = JCS_UNKNOWN; } break; default: assert(0); return false; } //assert( cinfo.data_precision == BITS_IN_JSAMPLE ); //assert( cinfo.data_precision == this->BitSample ); /* Step 4: set parameters for decompression */ /* no op */ } /* Step 5: Start decompressor */ if (Internals->StateSuspension < 3 ) { if ( jpeg_start_decompress(&cinfo) == FALSE ) { /* Suspension: jpeg_start_decompress */ Internals->StateSuspension = 3; } /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled * output image dimensions available, as well as the output colormap * if we asked for color quantization. * In this example, we need to make an output work buffer of the right size. */ /* JSAMPLEs per row in output buffer */ row_stride = cinfo.output_width * cinfo.output_components; row_stride *= sizeof(JSAMPLE); /* Make a one-row-high sample array that will go away when done with image */ buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, (JDIMENSION)row_stride, 1); /* Save the buffer in case of suspension to be able to reuse it later: */ Internals->SampBuffer = buffer; } else { /* JSAMPLEs per row in output buffer */ row_stride = cinfo.output_width * cinfo.output_components; row_stride *= sizeof(JSAMPLE); /* Suspension: re-use the buffer: */ buffer = (JSAMPARRAY)Internals->SampBuffer; } /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ while (cinfo.output_scanline < cinfo.output_height) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if that's more convenient. */ if( jpeg_read_scanlines(&cinfo, buffer, 1) == 0 ) { /* Suspension in jpeg_read_scanlines */ Internals->StateSuspension = 3; return true; } os.write((char*)buffer[0], row_stride); } /* Step 7: Finish decompression */ if( jpeg_finish_decompress(&cinfo) == FALSE ) { /* Suspension: jpeg_finish_decompress */ Internals->StateSuspension = 4; return true; } /* we are done decompressing the file, now is a good time to store the type of compression used: lossless or not */ if( cinfo.process == JPROC_LOSSLESS ) { LossyFlag = false; } else { LossyFlag = true; } /* Step 8: Release JPEG decompression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_decompress(&cinfo); /* After finish_decompress, we can close the input file. * Here we postpone it until after no more JPEG errors are possible, * so as to simplify the setjmp error logic above. (Actually, I don't * think that jpeg_destroy can do an error exit, but why assume anything...) */ //fclose(infile); /* At this point you may want to check to see whether any corrupt-data * warnings occurred (test whether jerr.pub.num_warnings is nonzero). */ /* gdcmData/D_CLUNIE_MR4_JPLY.dcm produces a single warning: * Invalid SOS parameters for sequential JPEG * Be nice with this one: */ if( jerr.pub.num_warnings > 1 ) { gdcmErrorMacro( "Too many warning during decompression of JPEG stream: " << jerr.pub.num_warnings ); return false; } /* In any case make sure the we reset the internal state suspension */ Internals->StateSuspension = 0; /* And we're done! */ return true; } /* * jdatadst.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains compression data destination routines for the case of * emitting JPEG data to a file (or any stdio stream). While these routines * are sufficient for most applications, some will want to use a different * destination manager. * IMPORTANT: we assume that fwrite() will correctly transcribe an array of * JOCTETs into 8-bit-wide elements on external storage. If char is wider * than 8 bits on your machine, you may need to do some tweaking. */ /** * \brief very low level C 'structure', used to decode jpeg file * Should not appear in the Doxygen supplied documentation */ typedef struct { struct jpeg_destination_mgr pub; /* public fields */ std::ostream * outfile; /* target stream */ JOCTET * buffer; /* start of buffer */ } my_destination_mgr; typedef my_destination_mgr * my_dest_ptr; #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ /* * Initialize destination --- called by jpeg_start_compress * before any data is actually written. */ METHODDEF(void) init_destination (j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; /* Allocate the output buffer --- it will be released when done with image */ dest->buffer = (JOCTET *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } /* * Empty the output buffer --- called whenever buffer fills up. * * In typical applications, this should write the entire output buffer * (ignoring the current state of next_output_byte & free_in_buffer), * reset the pointer & count to the start of the buffer, and return TRUE * indicating that the buffer has been dumped. * * In applications that need to be able to suspend compression due to output * overrun, a FALSE return indicates that the buffer cannot be emptied now. * In this situation, the compressor will return to its caller (possibly with * an indication that it has not accepted all the supplied scanlines). The * application should resume compression after it has made more room in the * output buffer. Note that there are substantial restrictions on the use of * suspension --- see the documentation. * * When suspending, the compressor will back up to a convenient restart point * (typically the start of the current MCU). next_output_byte & free_in_buffer * indicate where the restart point will be if the current call returns FALSE. * Data beyond this point will be regenerated after resumption, so do not * write it out when emptying the buffer externally. */ METHODDEF(boolean) empty_output_buffer (j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; //if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != // (size_t) OUTPUT_BUF_SIZE) // ERREXIT(cinfo, JERR_FILE_WRITE); size_t output_buf_size = OUTPUT_BUF_SIZE; if( !dest->outfile->write((char*)dest->buffer, output_buf_size) ) { ERREXIT(cinfo, JERR_FILE_WRITE); } dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; return TRUE; } /* * Terminate destination --- called by jpeg_finish_compress * after all data has been written. Usually needs to flush buffer. * * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding * application must deal with any cleanup that should happen even * for error exit. */ METHODDEF(void) term_destination (j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; /* Write any data remaining in the buffer */ if (datacount > 0) { //if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) // ERREXIT(cinfo, JERR_FILE_WRITE); if( !dest->outfile->write((char*)dest->buffer, datacount) ) ERREXIT(cinfo, JERR_FILE_WRITE); } //fflush(dest->outfile); dest->outfile->flush(); /* Make sure we wrote the output file OK */ //if (ferror(dest->outfile)) if (dest->outfile->fail()) ERREXIT(cinfo, JERR_FILE_WRITE); } /* * Prepare for output to a stdio stream. * The caller must have already opened the stream, and is responsible * for closing it after finishing compression. */ GLOBAL(void) jpeg_stdio_dest (j_compress_ptr cinfo, /*FILE * */ std::ostream * outfile) { my_dest_ptr dest; /* The destination object is made permanent so that multiple JPEG images * can be written to the same file without re-executing jpeg_stdio_dest. * This makes it dangerous to use this manager and a different destination * manager serially with the same JPEG object, because their private object * sizes may be different. Caveat programmer. */ if (cinfo->dest == nullptr) { /* first time for this JPEG object? */ cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_destination_mgr)); } dest = (my_dest_ptr) cinfo->dest; dest->pub.init_destination = init_destination; dest->pub.empty_output_buffer = empty_output_buffer; dest->pub.term_destination = term_destination; dest->outfile = outfile; } /* * Sample routine for JPEG compression. We assume that the target file name * and a compression quality factor are passed in. */ bool JPEGBITSCodec::InternalCode(const char* input, unsigned long len, std::ostream &os) { int quality = 100; (void)len; (void)quality; JSAMPLE * image_buffer = (JSAMPLE*)(void*)const_cast(input); /* Points to large array of R,G,B-order data */ const unsigned int *dims = this->GetDimensions(); int image_height = dims[1]; /* Number of rows in image */ int image_width = dims[0]; /* Number of columns in image */ /* This struct contains the JPEG compression parameters and pointers to * working space (which is allocated as needed by the JPEG library). * It is possible to have several such structures, representing multiple * compression/decompression processes, in existence at once. We refer * to any one struct (and its associated working data) as a "JPEG object". */ struct jpeg_compress_struct cinfo; /* This struct represents a JPEG error handler. It is declared separately * because applications often want to supply a specialized error handler * (see the second half of this file for an example). But here we just * take the easy way out and use the standard error handler, which will * print a message on stderr and call exit() if compression fails. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ struct my_error_mgr jerr; /* More stuff */ //FILE * outfile; /* target file */ std::ostream * outfile = &os; JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ size_t row_stride; /* physical row width in image buffer */ /* Step 1: allocate and initialize JPEG compression object */ /* We have to set up the error handler first, in case the initialization * step fails. (Unlikely, but it could happen if you are out of memory.) * This routine fills in the contents of struct jerr, and returns jerr's * address which we place into the link field in cinfo. */ cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; // Establish the setjmp return context for my_error_exit to use. if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_compress(&cinfo); return false; } /* Now we can initialize the JPEG compression object. */ jpeg_create_compress(&cinfo); /* Step 2: specify data destination (eg, a file) */ /* Note: steps 2 and 3 can be done in either order. */ /* Here we use the library-supplied code to send compressed data to a * stdio stream. You can also write your own code to do something else. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to write binary files. */ //if ((outfile = fopen(filename, "wb")) == NULL) { // fprintf(stderr, "can't open %s\n", filename); // exit(1); //} jpeg_stdio_dest(&cinfo, outfile); /* Step 3: set parameters for compression */ /* First we supply a description of the input image. * Four fields of the cinfo struct must be filled in: */ cinfo.image_width = image_width; /* image width and height, in pixels */ cinfo.image_height = image_height; switch( this->GetPhotometricInterpretation() ) { case PhotometricInterpretation::MONOCHROME1: case PhotometricInterpretation::MONOCHROME2: case PhotometricInterpretation::PALETTE_COLOR: cinfo.input_components = 1; /* # of color components per pixel */ cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */ break; case PhotometricInterpretation::RGB: case PhotometricInterpretation::YBR_RCT: case PhotometricInterpretation::YBR_ICT: cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ break; case PhotometricInterpretation::YBR_FULL: case PhotometricInterpretation::YBR_FULL_422: case PhotometricInterpretation::YBR_PARTIAL_420: case PhotometricInterpretation::YBR_PARTIAL_422: cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_YCbCr; /* colorspace of input image */ break; case PhotometricInterpretation::HSV: case PhotometricInterpretation::ARGB: case PhotometricInterpretation::CMYK: // TODO ! case PhotometricInterpretation::UNKNOWN: case PhotometricInterpretation::PI_END: // To please compiler return false; } //if ( cinfo.process == JPROC_LOSSLESS ) // { // cinfo.in_color_space = JCS_UNKNOWN; // } //assert( cinfo.image_height * cinfo.image_width * cinfo.input_components * sizeof(JSAMPLE) == len ); /* Now use the library's routine to set default compression parameters. * (You must set at least cinfo.in_color_space before calling this, * since the defaults depend on the source color space.) */ jpeg_set_defaults(&cinfo); /* * predictor = 1 * point_transform = 0 * => lossless transformation. * Basically you need to have point_transform = 0, but you can pick whichever predictor [1...7] you want * TODO: is there a way to pick the right predictor (best compression/fastest ?) */ if( !LossyFlag ) { jpeg_simple_lossless (&cinfo, 1, 0); //jpeg_simple_lossless (&cinfo, 7, 0); } /* Now you can set any non-default parameters you wish to. * Here we just illustrate the use of quality (quantization table) scaling: */ if( !LossyFlag ) { assert( Quality == 100 ); } jpeg_set_quality(&cinfo, Quality, TRUE /* limit to baseline-JPEG values */); /* * See write_file_header */ cinfo.write_JFIF_header = 0; //cinfo.density_unit = 2; //cinfo.X_density = 2; //cinfo.Y_density = 5; /* Step 4: Start compressor */ /* TRUE ensures that we will write a complete interchange-JPEG file. * Pass TRUE unless you are very sure of what you're doing. */ jpeg_start_compress(&cinfo, TRUE); /* Step 5: while (scan lines remain to be written) */ /* jpeg_write_scanlines(...); */ /* Here we use the library's state variable cinfo.next_scanline as the * loop counter, so that we don't have to keep track ourselves. * To keep things simple, we pass one scanline per call; you can pass * more if you wish, though. */ row_stride = image_width * cinfo.input_components; /* JSAMPLEs per row in image_buffer */ if( this->GetPlanarConfiguration() == 0 ) { while (cinfo.next_scanline < cinfo.image_height) { /* jpeg_write_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could pass * more than one scanline at a time if that's more convenient. */ row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); } } else { /* * warning: Need to read C.7.6.3.1.3 Planar Configuration (see note about Planar Configuration dummy value) */ JSAMPLE *tempbuffer = (JSAMPLE*)malloc( row_stride * sizeof(JSAMPLE) ); row_pointer[0] = tempbuffer; int offset = image_height * image_width; while (cinfo.next_scanline < cinfo.image_height) { assert( row_stride % 3 == 0 ); JSAMPLE* ptempbuffer = tempbuffer; JSAMPLE* red = image_buffer + cinfo.next_scanline * row_stride / 3; JSAMPLE* green = image_buffer + cinfo.next_scanline * row_stride / 3 + offset; JSAMPLE* blue = image_buffer + cinfo.next_scanline * row_stride / 3 + offset * 2; for(size_t i = 0; i < row_stride / 3; ++i ) { *ptempbuffer++ = *red++; *ptempbuffer++ = *green++; *ptempbuffer++ = *blue++; } (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); } free(tempbuffer); } /* Step 6: Finish compression */ jpeg_finish_compress(&cinfo); /* After finish_compress, we can close the output file. */ //fclose(outfile); /* Step 7: release JPEG compression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_compress(&cinfo); /* And we're done! */ return true; } bool JPEGBITSCodec::EncodeBuffer(std::ostream &os, const char *data, size_t datalen) { (void)datalen; JSAMPLE * image_buffer = (JSAMPLE*)(void*)const_cast(data); /* Points to large array of R,G,B-order data */ const unsigned int *dims = this->GetDimensions(); int image_height = dims[1]; /* Number of rows in image */ int image_width = dims[0]; /* Number of columns in image */ /* This struct contains the JPEG compression parameters and pointers to * working space (which is allocated as needed by the JPEG library). * It is possible to have several such structures, representing multiple * compression/decompression processes, in existence at once. We refer * to any one struct (and its associated working data) as a "JPEG object". */ jpeg_compress_struct &cinfo = Internals->cinfo_comp; /* This struct represents a JPEG error handler. It is declared separately * because applications often want to supply a specialized error handler * (see the second half of this file for an example). But here we just * take the easy way out and use the standard error handler, which will * print a message on stderr and call exit() if compression fails. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ my_error_mgr &jerr = Internals->jerr; /* More stuff */ //FILE * outfile; /* target file */ std::ostream *outfile = &os; JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ size_t row_stride; /* physical row width in image buffer */ if( Internals->StateSuspension == 0 ) { /* Step 1: allocate and initialize JPEG compression object */ /* We have to set up the error handler first, in case the initialization * step fails. (Unlikely, but it could happen if you are out of memory.) * This routine fills in the contents of struct jerr, and returns jerr's * address which we place into the link field in cinfo. */ cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; // Establish the setjmp return context for my_error_exit to use. if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_compress(&cinfo); return false; } /* Now we can initialize the JPEG compression object. */ jpeg_create_compress(&cinfo); /* Step 2: specify data destination (eg, a file) */ /* Note: steps 2 and 3 can be done in either order. */ /* Here we use the library-supplied code to send compressed data to a * stdio stream. You can also write your own code to do something else. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to write binary files. */ //if ((outfile = fopen(filename, "wb")) == NULL) { // fprintf(stderr, "can't open %s\n", filename); // exit(1); //} } if( Internals->StateSuspension == 0 ) { jpeg_stdio_dest(&cinfo, outfile); } /* Step 3: set parameters for compression */ /* First we supply a description of the input image. * Four fields of the cinfo struct must be filled in: */ if( Internals->StateSuspension == 0 ) { cinfo.image_width = image_width; /* image width and height, in pixels */ cinfo.image_height = image_height; } if( Internals->StateSuspension == 0 ) { switch( this->GetPhotometricInterpretation() ) { case PhotometricInterpretation::MONOCHROME1: case PhotometricInterpretation::MONOCHROME2: case PhotometricInterpretation::PALETTE_COLOR: cinfo.input_components = 1; /* # of color components per pixel */ cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */ break; case PhotometricInterpretation::RGB: case PhotometricInterpretation::YBR_RCT: case PhotometricInterpretation::YBR_ICT: cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ break; case PhotometricInterpretation::YBR_FULL: case PhotometricInterpretation::YBR_FULL_422: case PhotometricInterpretation::YBR_PARTIAL_420: case PhotometricInterpretation::YBR_PARTIAL_422: cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_YCbCr; /* colorspace of input image */ break; case PhotometricInterpretation::HSV: case PhotometricInterpretation::ARGB: case PhotometricInterpretation::CMYK: // TODO ! case PhotometricInterpretation::UNKNOWN: case PhotometricInterpretation::PI_END: // To please compiler return false; } } //if ( cinfo.process == JPROC_LOSSLESS ) // { // cinfo.in_color_space = JCS_UNKNOWN; // } //assert( cinfo.image_height * cinfo.image_width * cinfo.input_components * sizeof(JSAMPLE) == len ); /* Now use the library's routine to set default compression parameters. * (You must set at least cinfo.in_color_space before calling this, * since the defaults depend on the source color space.) */ if( Internals->StateSuspension == 0 ) { jpeg_set_defaults(&cinfo); } /* * predictor = 1 * point_transform = 0 * => lossless transformation. * Basically you need to have point_transform = 0, but you can pick whichever predictor [1...7] you want * TODO: is there a way to pick the right predictor (best compression/fastest ?) */ if( Internals->StateSuspension == 0 ) { if( !LossyFlag ) { jpeg_simple_lossless (&cinfo, 1, 0); //jpeg_simple_lossless (&cinfo, 7, 0); } } /* Now you can set any non-default parameters you wish to. * Here we just illustrate the use of quality (quantization table) scaling: */ if( !LossyFlag ) { assert( Quality == 100 ); } if( Internals->StateSuspension == 0 ) { jpeg_set_quality(&cinfo, Quality, TRUE /* limit to baseline-JPEG values */); } if( Internals->StateSuspension == 0 ) { /* * See write_file_header */ cinfo.write_JFIF_header = 0; } //cinfo.density_unit = 2; //cinfo.X_density = 2; //cinfo.Y_density = 5; /* Step 4: Start compressor */ if( Internals->StateSuspension == 0 ) { /* TRUE ensures that we will write a complete interchange-JPEG file. * Pass TRUE unless you are very sure of what you're doing. */ jpeg_start_compress(&cinfo, TRUE); Internals->StateSuspension = 1; } /* Step 5: while (scan lines remain to be written) */ /* jpeg_write_scanlines(...); */ /* Here we use the library's state variable cinfo.next_scanline as the * loop counter, so that we don't have to keep track ourselves. * To keep things simple, we pass one scanline per call; you can pass * more if you wish, though. */ row_stride = image_width * cinfo.input_components; /* JSAMPLEs per row in image_buffer */ if ( Internals->StateSuspension == 1 ) { assert( this->GetPlanarConfiguration() == 0 ); assert( row_stride * sizeof(JSAMPLE) == datalen ); { //while (cinfo.next_scanline < cinfo.image_height) { /* jpeg_write_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could pass * more than one scanline at a time if that's more convenient. */ row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride * 0]; const JDIMENSION nscanline = jpeg_write_scanlines(&cinfo, row_pointer, 1); assert( nscanline == 1 ); (void)nscanline; assert(cinfo.next_scanline <= cinfo.image_height); //} } if(cinfo.next_scanline == cinfo.image_height) { Internals->StateSuspension = 2; } } /* Step 6: Finish compression */ if (Internals->StateSuspension == 2 ) { jpeg_finish_compress(&cinfo); /* After finish_compress, we can close the output file. */ //fclose(outfile); } /* Step 7: release JPEG compression object */ if (Internals->StateSuspension == 2 ) { /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_compress(&cinfo); Internals->StateSuspension = 0; } /* And we're done! */ return true; } bool JPEGBITSCodec::IsStateSuspension() const { return Internals->StateSuspension != 0; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmJPEGCodec.cxx000066400000000000000000000521371412732066400235640ustar00rootroot00000000000000/*========================================================================= 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 "gdcmJPEGCodec.h" #include "gdcmTransferSyntax.h" #include "gdcmTrace.h" #include "gdcmDataElement.h" #include "gdcmSequenceOfFragments.h" #include "gdcmSwapper.h" #include "gdcmJPEG8Codec.h" #include "gdcmJPEG12Codec.h" #include "gdcmJPEG16Codec.h" #include #include namespace gdcm { JPEGCodec::JPEGCodec():BitSample(0)/*,Lossless(true)*/,Quality(100) { Internal = nullptr; } JPEGCodec::~JPEGCodec() { delete Internal; } void JPEGCodec::SetQuality(double q) { Quality = (int)q;//not sure why a double is passed and stored in an int. //the casting will happen here anyway, so making it explicit removes a warning. } double JPEGCodec::GetQuality() const { return Quality; } void JPEGCodec::SetLossless(bool l) { LossyFlag = !l; } bool JPEGCodec::GetLossless() const { return !LossyFlag; } bool JPEGCodec::CanDecode(TransferSyntax const &ts) const { return ts == TransferSyntax::JPEGBaselineProcess1 || ts == TransferSyntax::JPEGExtendedProcess2_4 || ts == TransferSyntax::JPEGExtendedProcess3_5 || ts == TransferSyntax::JPEGSpectralSelectionProcess6_8 || ts == TransferSyntax::JPEGFullProgressionProcess10_12 || ts == TransferSyntax::JPEGLosslessProcess14 || ts == TransferSyntax::JPEGLosslessProcess14_1; } bool JPEGCodec::CanCode(TransferSyntax const &ts) const { return ts == TransferSyntax::JPEGBaselineProcess1 || ts == TransferSyntax::JPEGExtendedProcess2_4 || ts == TransferSyntax::JPEGExtendedProcess3_5 || ts == TransferSyntax::JPEGSpectralSelectionProcess6_8 || ts == TransferSyntax::JPEGFullProgressionProcess10_12 || ts == TransferSyntax::JPEGLosslessProcess14 || ts == TransferSyntax::JPEGLosslessProcess14_1; } void JPEGCodec::SetPixelFormat(PixelFormat const &pt) { ImageCodec::SetPixelFormat(pt); // Here is the deal: D_CLUNIE_RG3_JPLY.dcm is a 12Bits Stored / 16 Bits Allocated image // the jpeg encapsulated is: a 12 Sample Precision // so far so good. // So what if we are dealing with image such as: SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm // which is also a 12Bits Stored / 16 Bits Allocated image // however the jpeg encapsulated is now a 16 Sample Precision // We have the choice to decide to use Bits Stored or Bits Allocated, however in the case of // such an image as: gdcmData/MR16BitsAllocated_8BitsStored.dcm we are required to use // bits allocated to deal with the logic to decide with the encoder SetBitSample( pt.GetBitsAllocated() ); //SetBitSample( pt.GetBitsStored() ); } void JPEGCodec::SetupJPEGBitCodec(int bit) { BitSample = bit; delete Internal; Internal = nullptr; // what should I do with those single bit images ? if ( BitSample <= 8 ) { gdcmDebugMacro( "Using JPEG8" ); Internal = new JPEG8Codec; } else if ( /*BitSample > 8 &&*/ BitSample <= 12 ) { gdcmDebugMacro( "Using JPEG12" ); Internal = new JPEG12Codec; } else if ( /*BitSample > 12 &&*/ BitSample <= 16 ) { gdcmDebugMacro( "Using JPEG16" ); Internal = new JPEG16Codec; } else { // gdcmNonImageData/RT/RTDOSE.dcm gdcmWarningMacro( "Cannot instantiate JPEG codec for bit sample: " << bit ); } } void JPEGCodec::SetBitSample(int bit) { SetupJPEGBitCodec(bit); if( Internal ) { Internal->SetDimensions( this->GetDimensions() ); Internal->SetPlanarConfiguration( this->GetPlanarConfiguration() ); Internal->SetPhotometricInterpretation( this->GetPhotometricInterpretation() ); Internal->SetLossless( this->GetLossless() ); Internal->SetQuality( this->GetQuality() ); Internal->ImageCodec::SetPixelFormat( this->ImageCodec::GetPixelFormat() ); //Internal->SetNeedOverlayCleanup( this->AreOverlaysInPixelData() ); } } /* A.4.1 JPEG image compression For all images, including all frames of a multi-frame image, the JPEG Interchange Format shall be used (the table specification shall be included). */ bool JPEGCodec::Decode(DataElement const &in, DataElement &out) { assert( Internal ); out = in; // Fragments... const SequenceOfFragments *sf0 = in.GetSequenceOfFragments(); const ByteValue *jpegbv = in.GetByteValue(); if( !sf0 && !jpegbv ) return false; std::stringstream os; if( sf0 ) { for(unsigned int i = 0; i < sf0->GetNumberOfFragments(); ++i) { std::stringstream is; const Fragment &frag = sf0->GetFragment(i); if( frag.IsEmpty() ) return false; const ByteValue &bv = dynamic_cast(frag.GetValue()); size_t bv_len = bv.GetLength(); char *mybuffer = new char[bv_len]; bool b = bv.GetBuffer(mybuffer, bv.GetLength()); assert( b ); (void)b; is.write(mybuffer, bv.GetLength()); delete[] mybuffer; bool r = DecodeByStreams(is, os); // PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm if( !r ) { gdcmDebugMacro( "Failed to decompress Frag #" << i ); const bool suspended = Internal->IsStateSuspension(); const size_t nfrags = sf0->GetNumberOfFragments(); // In case of chunked-jpeg, this is always an error if( suspended ) return false; // Ok so we are decoding a multiple frame jpeg DICOM file: // if we are lucky, we might be trying to decode some sort of broken multi-frame // DICOM file. In this case check that we have read all Fragment properly: if( i >= this->GetDimensions()[2] ) { // JPEGInvalidSecondFrag.dcm assert( nfrags == this->GetNumberOfDimensions() ); (void)nfrags; // sentinel gdcmWarningMacro( "Invalid JPEG Fragment found at pos #" << i + 1 << ". Skipping it" ); } else return false; } } } else if ( jpegbv ) { // GEIIS Icon: std::stringstream is0; size_t jpegbv_len = jpegbv->GetLength(); char *mybuffer0 = new char[jpegbv_len]; bool b0 = jpegbv->GetBuffer(mybuffer0, jpegbv->GetLength()); assert( b0 ); (void)b0; is0.write(mybuffer0, jpegbv->GetLength()); delete[] mybuffer0; bool r = DecodeByStreams(is0, os); if( !r ) { // let's try another time: // JPEGDefinedLengthSequenceOfFragments.dcm is0.seekg(0); SequenceOfFragments sf_bug; try { sf_bug.Read(is0,true); } catch ( ... ) { return false; } const SequenceOfFragments *sf = &sf_bug; for(unsigned int i = 0; i < sf->GetNumberOfFragments(); ++i) { std::stringstream is; const Fragment &frag = sf->GetFragment(i); if( frag.IsEmpty() ) return false; const ByteValue &bv = dynamic_cast(frag.GetValue()); size_t bv_len = bv.GetLength(); char *mybuffer = new char[bv_len]; bool b = bv.GetBuffer(mybuffer, bv.GetLength()); assert( b ); (void)b; is.write(mybuffer, bv.GetLength()); delete[] mybuffer; bool r2 = DecodeByStreams(is, os); if( !r2 ) { return false; } } } } //assert( pos == len ); const size_t sizeOfOs = (size_t)os.tellp(); os.seekp( 0, std::ios::beg ); ByteValue * bv = new ByteValue; bv->SetLength( (uint32_t)sizeOfOs ); bv->Read( os ); out.SetValue( *bv ); return true; } void JPEGCodec::ComputeOffsetTable(bool b) { (void)b; // Not implemented assert(0); } bool JPEGCodec::GetHeaderInfo( std::istream & is, TransferSyntax &ts ) { assert( Internal ); if ( !Internal->GetHeaderInfo(is, ts) ) { // let's check if this is one of those buggy lossless JPEG if( this->BitSample != Internal->BitSample ) { // MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm // PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm gdcmWarningMacro( "DICOM header said it was " << this->BitSample << " but JPEG header says it's: " << Internal->BitSample ); if( this->BitSample < Internal->BitSample ) { //assert(0); // Outside buffer will be too small } is.seekg(0, std::ios::beg); SetupJPEGBitCodec( Internal->BitSample ); if( Internal && Internal->GetHeaderInfo(is, ts) ) { // Forward everything back to meta jpeg codec: this->SetLossyFlag( Internal->GetLossyFlag() ); this->SetDimensions( Internal->GetDimensions() ); this->SetPhotometricInterpretation( Internal->GetPhotometricInterpretation() ); int prep = this->GetPixelFormat().GetPixelRepresentation(); this->PF = Internal->GetPixelFormat(); // DO NOT CALL SetPixelFormat this->PF.SetPixelRepresentation( (uint16_t)prep ); return true; } else { //assert(0); // FATAL ERROR gdcmErrorMacro( "Do not support this JPEG Type" ); return false; } } return false; } // else // Forward everything back to meta jpeg codec: this->SetLossyFlag( Internal->GetLossyFlag() ); this->SetDimensions( Internal->GetDimensions() ); this->SetPhotometricInterpretation( Internal->GetPhotometricInterpretation() ); this->PF = Internal->GetPixelFormat(); // DO NOT CALL SetPixelFormat if( this->PI != Internal->PI ) { gdcmWarningMacro( "PhotometricInterpretation issue" ); this->PI = Internal->PI; } return true; } bool JPEGCodec::Code(DataElement const &in, DataElement &out) { out = in; // Create a Sequence Of Fragments: SmartPointer sq = new SequenceOfFragments; const Tag itemStart(0xfffe, 0xe000); //sq->GetTable().SetTag( itemStart ); //const char dummy[4] = {}; //sq->GetTable().SetByteValue( dummy, sizeof(dummy) ); const ByteValue *bv = in.GetByteValue(); if(!bv) return false; // broken DICOM file ? const unsigned int *dims = this->GetDimensions(); const char *input = bv->GetPointer(); unsigned long len = bv->GetLength(); unsigned long image_len = len / dims[2]; if(!Internal) return false; // forward parameter to low level bits implementation (8/12/16) Internal->SetLossless( this->GetLossless() ); Internal->SetQuality( this->GetQuality() ); for(unsigned int dim = 0; dim < dims[2]; ++dim) { std::stringstream os; const char *p = input + dim * image_len; bool r = Internal->InternalCode(p, image_len, os); if( !r ) { return false; } std::string str = os.str(); assert( str.size() ); Fragment frag; //frag.SetTag( itemStart ); VL::Type strSize = (VL::Type)str.size(); frag.SetByteValue( &str[0], strSize ); sq->AddFragment( frag ); } //unsigned int n = sq->GetNumberOfFragments(); assert( sq->GetNumberOfFragments() == dims[2] ); out.SetValue( *sq ); return true; } bool JPEGCodec::DecodeByStreams(std::istream &is, std::ostream &os) { std::stringstream tmpos; if ( !Internal->DecodeByStreams(is,tmpos) ) { #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // let's check if this is one of those buggy lossless JPEG if( this->BitSample != Internal->BitSample ) { // MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm // PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm gdcmWarningMacro( "DICOM header said it was " << this->BitSample << " but JPEG header says it's: " << Internal->BitSample ); if( this->BitSample < Internal->BitSample ) { //assert(0); // Outside buffer will be too small } is.seekg(0, std::ios::beg); SetupJPEGBitCodec( Internal->BitSample ); if( Internal ) { //Internal->SetPixelFormat( this->GetPixelFormat() ); // FIXME Internal->SetDimensions( this->GetDimensions() ); Internal->SetPlanarConfiguration( this->GetPlanarConfiguration() ); // meaningless ? Internal->SetPhotometricInterpretation( this->GetPhotometricInterpretation() ); if( Internal->DecodeByStreams(is,tmpos) ) { return ImageCodec::DecodeByStreams(tmpos,os); } else { gdcmErrorMacro( "Could not succeed after 2 tries" ); } } } #endif return false; } if( this->PlanarConfiguration != Internal->PlanarConfiguration ) { gdcmWarningMacro( "PlanarConfiguration issue" ); this->PlanarConfiguration = Internal->PlanarConfiguration; //this->RequestPlanarConfiguration = true; } if( this->PI != Internal->PI ) { gdcmWarningMacro( "PhotometricInterpretation issue" ); this->PI = Internal->PI; } if( this->PF == PixelFormat::UINT12 || this->PF == PixelFormat::INT12 ) { this->PF.SetBitsAllocated( 16 ); } return ImageCodec::DecodeByStreams(tmpos,os); } bool JPEGCodec::IsValid(PhotometricInterpretation const &pi) { bool ret = false; switch( pi ) { // JPEGCodec can produce the following PhotometricInterpretation as output: case PhotometricInterpretation::MONOCHROME1: case PhotometricInterpretation::MONOCHROME2: case PhotometricInterpretation::PALETTE_COLOR: case PhotometricInterpretation::RGB: case PhotometricInterpretation::YBR_FULL: case PhotometricInterpretation::YBR_FULL_422: case PhotometricInterpretation::YBR_PARTIAL_422: case PhotometricInterpretation::YBR_PARTIAL_420: ret = true; break; default: ; // case HSV: // case ARGB: // retired // case CMYK: // case YBR_RCT: // case YBR_ICT: // ret = false; } return ret; } bool JPEGCodec::DecodeExtent( char *buffer, unsigned int xmin, unsigned int xmax, unsigned int ymin, unsigned int ymax, unsigned int zmin, unsigned int zmax, std::istream & is ) { BasicOffsetTable bot; bot.Read( is ); const unsigned int * dimensions = this->GetDimensions(); const PixelFormat & pf = this->GetPixelFormat(); //assert( pf.GetBitsAllocated() % 8 == 0 ); assert( pf != PixelFormat::SINGLEBIT ); //assert( pf != PixelFormat::UINT12 && pf != PixelFormat::INT12 ); if( NumberOfDimensions == 2 ) { //char *dummy_buffer = NULL; std::vector vdummybuffer; size_t buf_size = 0; const Tag seqDelItem(0xfffe,0xe0dd); Fragment frag; unsigned int nfrags = 0; try { while( frag.ReadPreValue(is) && frag.GetTag() != seqDelItem ) { ++nfrags; size_t fraglen = frag.GetVL(); size_t oldlen = vdummybuffer.size(); // update buf_size = fraglen + oldlen; vdummybuffer.resize( buf_size ); //dummy_buffer = &vdummybuffer[0]; // read J2K is.read( &vdummybuffer[oldlen], fraglen ); } assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 ); } catch(Exception &ex) { (void)ex; #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION // that's ok ! In all cases the whole file was read, because // Fragment::Read only fail on eof() reached 1. // SIEMENS-JPEG-CorruptFrag.dcm is more difficult to deal with, we have a // partial fragment, read we decide to add it anyway to the stack of // fragments (eof was reached so we need to clear error bit) if( frag.GetTag() == Tag(0xfffe,0xe000) ) { gdcmWarningMacro( "Pixel Data Fragment could be corrupted. Use file at own risk" ); //Fragments.push_back( frag ); is.clear(); // clear the error bit } // 2. GENESIS_SIGNA-JPEG-CorruptFrag.dcm else if ( frag.GetTag() == Tag(0xddff,0x00e0) ) { assert( nfrags == 1 ); const ByteValue *bv = frag.GetByteValue(); assert( (unsigned char)bv->GetPointer()[ bv->GetLength() - 1 ] == 0xfe ); // Yes this is an extra copy, this is a bug anyway, go fix YOUR code frag.SetByteValue( bv->GetPointer(), bv->GetLength() - 1 ); assert( 0 ); gdcmWarningMacro( "JPEG Fragment length was declared with an extra byte" " at the end: stripped !" ); is.clear(); // clear the error bit } else { // 3. gdcm-JPEG-LossLess3a.dcm: easy case, an extra tag was found // instead of terminator (eof is the next char) gdcmWarningMacro( "Reading failed at Tag:" << frag.GetTag() << ". Use file at own risk." << ex.what() ); } #endif /* GDCM_SUPPORT_BROKEN_IMPLEMENTATION */ } assert( zmin == zmax ); assert( zmin == 0 ); std::stringstream iis; iis.write( &vdummybuffer[0], vdummybuffer.size() ); std::stringstream os; bool b = DecodeByStreams(iis,os); if(!b) return false; assert( b ); const unsigned int rowsize = xmax - xmin + 1; const unsigned int colsize = ymax - ymin + 1; const unsigned int bytesPerPixel = pf.GetPixelSize(); os.seekg(0, std::ios::beg ); assert( os.good() ); std::istream *theStream = &os; std::vector buffer1; buffer1.resize( rowsize*bytesPerPixel ); char *tmpBuffer1 = &buffer1[0]; unsigned int y, z; std::streamoff theOffset; for (z = zmin; z <= zmax; ++z) { for (y = ymin; y <= ymax; ++y) { theStream->seekg(std::ios::beg); theOffset = 0 + (z*dimensions[1]*dimensions[0] + y*dimensions[0] + xmin)*bytesPerPixel; theStream->seekg(theOffset); theStream->read(tmpBuffer1, rowsize*bytesPerPixel); memcpy(&(buffer[((z-zmin)*rowsize*colsize + (y-ymin)*rowsize)*bytesPerPixel]), tmpBuffer1, rowsize*bytesPerPixel); } } } else if ( NumberOfDimensions == 3 ) { const Tag seqDelItem(0xfffe,0xe0dd); Fragment frag; std::streamoff thestart = is.tellg(); unsigned int numfrags = 0; std::vector< size_t > offsets; while( frag.ReadPreValue(is) && frag.GetTag() != seqDelItem ) { //std::streamoff relstart = is.tellg(); //assert( relstart - thestart == 8 ); const std::streamoff off = frag.GetVL(); offsets.push_back( (size_t)off ); is.seekg( off, std::ios::cur ); ++numfrags; } assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 ); assert( numfrags == offsets.size() ); if( numfrags != Dimensions[2] ) { gdcmErrorMacro( "Not handled" ); return false; } for( unsigned int z = zmin; z <= zmax; ++z ) { size_t curoffset = std::accumulate( offsets.begin(), offsets.begin() + z, size_t(0) ); is.seekg( thestart + curoffset + 8 * z, std::ios::beg ); is.seekg( 8, std::ios::cur ); //const size_t buf_size = offsets[z]; //char *dummy_buffer = new char[ buf_size ]; //is.read( dummy_buffer, buf_size ); std::stringstream os; const bool b = DecodeByStreams(is, os); (void)b; assert( b ); /* free the memory containing the code-stream */ //delete[] dummy_buffer; os.seekg(0, std::ios::beg ); assert( os.good() ); std::istream *theStream = &os; unsigned int rowsize = xmax - xmin + 1; unsigned int colsize = ymax - ymin + 1; unsigned int bytesPerPixel = pf.GetPixelSize(); std::vector buffer1; buffer1.resize( rowsize*bytesPerPixel ); char *tmpBuffer1 = &buffer1[0]; unsigned int y; std::streamoff theOffset; for (y = ymin; y <= ymax; ++y) { theStream->seekg(std::ios::beg); theOffset = 0 + (0*dimensions[1]*dimensions[0] + y*dimensions[0] + xmin)*bytesPerPixel; theStream->seekg(theOffset); theStream->read(tmpBuffer1, rowsize*bytesPerPixel); memcpy(&(buffer[((z-zmin)*rowsize*colsize + (y-ymin)*rowsize)*bytesPerPixel]), tmpBuffer1, rowsize*bytesPerPixel); } } } return true; } bool JPEGCodec::IsStateSuspension() const { assert( 0 ); return false; } ImageCodec * JPEGCodec::Clone() const { JPEGCodec *copy = new JPEGCodec; ImageCodec &ic = *copy; ic = *this; assert( copy->PF == PF ); //copy->SetupJPEGBitCodec( BitSample ); copy->SetPixelFormat( GetPixelFormat() ); assert( copy->BitSample == BitSample || BitSample == 0 ); //copy->Lossless = Lossless; copy->Quality = Quality; return copy; } bool JPEGCodec::EncodeBuffer( std::ostream & out, const char *inbuffer, size_t inlen) { assert( Internal ); return Internal->EncodeBuffer(out, inbuffer, inlen); } bool JPEGCodec::StartEncode( std::ostream & ) { return true; } bool JPEGCodec::IsRowEncoder() { return true; } bool JPEGCodec::IsFrameEncoder() { assert(0); return false; } bool JPEGCodec::AppendRowEncode( std::ostream & os, const char * data, size_t datalen) { return EncodeBuffer(os, data, datalen ); } // TODO: technically the frame encoder could use the row encoder when present // this could reduce code duplication bool JPEGCodec::AppendFrameEncode( std::ostream & , const char * , size_t ) { assert(0); return false; } bool JPEGCodec::StopEncode( std::ostream & ) { return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmJPEGCodec.h000066400000000000000000000065561412732066400232150ustar00rootroot00000000000000/*========================================================================= 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 GDCMJPEGCODEC_H #define GDCMJPEGCODEC_H #include "gdcmImageCodec.h" namespace gdcm { class PixelFormat; class TransferSyntax; /** * \brief JPEG codec * \details Class to do JPEG (8bits, 12bits, 16bits lossy & lossless). * It redispatch in between the different codec implementation: JPEG8Codec, * JPEG12Codec & JPEG16Codec * It also support inconsistency in between DICOM header and JPEG compressed stream * ImageCodec implementation for the JPEG case * * \note * Things you should know if you ever want to dive into DICOM/JPEG world (among other): * * - http://groups.google.com/group/comp.protocols.dicom/browse_thread/thread/625e46919f2080e1 * - http://groups.google.com/group/comp.protocols.dicom/browse_thread/thread/75fdfccc65a6243 * - http://groups.google.com/group/comp.protocols.dicom/browse_thread/thread/2d525ef6a2f093ed * - http://groups.google.com/group/comp.protocols.dicom/browse_thread/thread/6b93af410f8c921f */ class GDCM_EXPORT JPEGCodec : public ImageCodec { friend class ImageRegionReader; public: JPEGCodec(); ~JPEGCodec() override; bool CanDecode(TransferSyntax const &ts) const override; bool CanCode(TransferSyntax const &ts) const override; bool Decode(DataElement const &is, DataElement &os) override; void SetPixelFormat(PixelFormat const &pf) override; /// Compute the offset table: void ComputeOffsetTable(bool b); /// Compress into JPEG bool Code(DataElement const &in, DataElement &out) override; bool GetHeaderInfo(std::istream &is, TransferSyntax &ts) override; ImageCodec * Clone() const override; //void SetReversible(bool res); void SetQuality(double q); double GetQuality() const; void SetLossless(bool l); bool GetLossless() const; virtual bool EncodeBuffer( std::ostream & out, const char *inbuffer, size_t inlen); protected: bool DecodeExtent( char *buffer, unsigned int xmin, unsigned int xmax, unsigned int ymin, unsigned int ymax, unsigned int zmin, unsigned int zmax, std::istream & is ); bool DecodeByStreams(std::istream &is, std::ostream &os) override; bool IsValid(PhotometricInterpretation const &pi) override; bool StartEncode( std::ostream & ) override; bool IsRowEncoder() override; bool IsFrameEncoder() override; bool AppendRowEncode( std::ostream & out, const char * data, size_t datalen ) override; bool AppendFrameEncode( std::ostream & out, const char * data, size_t datalen ) override; bool StopEncode( std::ostream & ) override; protected: // Internal method called by SetPixelFormat // Instantiate the right jpeg codec (8, 12 or 16) void SetBitSample(int bit); virtual bool IsStateSuspension() const; protected: int BitSample; //bool Lossless; int Quality; private: void SetupJPEGBitCodec(int bit); JPEGCodec *Internal; }; } // end namespace gdcm #endif //GDCMJPEGCODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmJPEGLSCodec.cxx000066400000000000000000000414611412732066400240210ustar00rootroot00000000000000/*========================================================================= 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 "gdcmJPEGLSCodec.h" #include "gdcmTransferSyntax.h" #include "gdcmSequenceOfFragments.h" #include "gdcmDataElement.h" #include "gdcmSwapper.h" #include #include // memcpy // CharLS includes #include "gdcm_charls.h" #if defined(__GNUC__) && GCC_VERSION < 50101 #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif namespace gdcm { JPEGLSCodec::JPEGLSCodec():BufferLength(0)/*,Lossless(true)*/,LossyError(0) { } JPEGLSCodec::~JPEGLSCodec() = default; void JPEGLSCodec::SetLossless(bool l) { LossyFlag = !l; } bool JPEGLSCodec::GetLossless() const { return !LossyFlag; } bool JPEGLSCodec::GetHeaderInfo(std::istream &is, TransferSyntax &ts) { #ifndef GDCM_USE_JPEGLS return false; #else using namespace charls; is.seekg( 0, std::ios::end); size_t buf_size = (size_t)is.tellg(); //assert(buf_size < INT_MAX); char *dummy_buffer = new char[(unsigned int)buf_size]; is.seekg(0, std::ios::beg); is.read( dummy_buffer, buf_size); JlsParameters metadata = {}; if (JpegLsReadHeader(dummy_buffer, buf_size, &metadata, nullptr) != ApiResult::OK) { return false; } delete[] dummy_buffer; // $1 = {width = 512, height = 512, bitspersample = 8, components = 1, allowedlossyerror = 0, ilv = ILV_NONE, colorTransform = 0, custom = {MAXVAL = 0, T1 = 0, T2 = 0, T3 = 0, RESET = 0}} this->Dimensions[0] = metadata.width; this->Dimensions[1] = metadata.height; if( metadata.bitsPerSample <= 8 ) { this->PF = PixelFormat( PixelFormat::UINT8 ); } else if( metadata.bitsPerSample <= 16 ) { assert( metadata.bitsPerSample > 8 ); this->PF = PixelFormat( PixelFormat::UINT16 ); } else { assert(0); } this->PF.SetBitsStored( (uint16_t)metadata.bitsPerSample ); assert( this->PF.IsValid() ); // switch( metadata.bitspersample ) // { // case 8: // this->PF = PixelFormat( PixelFormat::UINT8 ); // break; // case 12: // this->PF = PixelFormat( PixelFormat::UINT16 ); // this->PF.SetBitsStored( 12 ); // break; // case 16: // this->PF = PixelFormat( PixelFormat::UINT16 ); // break; // default: // assert(0); // } if( metadata.components == 1 ) { PI = PhotometricInterpretation::MONOCHROME2; this->PF.SetSamplesPerPixel( 1 ); } else if( metadata.components == 3 ) { PI = PhotometricInterpretation::RGB; PlanarConfiguration = 1; this->PF.SetSamplesPerPixel( 3 ); } else assert(0); // allowedlossyerror == 0 => Lossless LossyFlag = metadata.allowedLossyError != 0; if( metadata.allowedLossyError == 0 ) { ts = TransferSyntax::JPEGLSLossless; } else { ts = TransferSyntax::JPEGLSNearLossless; } return true; #endif } bool JPEGLSCodec::CanDecode(TransferSyntax const &ts) const { #ifndef GDCM_USE_JPEGLS return false; #else return ts == TransferSyntax::JPEGLSLossless || ts == TransferSyntax::JPEGLSNearLossless; #endif } bool JPEGLSCodec::CanCode(TransferSyntax const &ts) const { #ifndef GDCM_USE_JPEGLS return false; #else return ts == TransferSyntax::JPEGLSLossless || ts == TransferSyntax::JPEGLSNearLossless; #endif } bool JPEGLSCodec::DecodeByStreamsCommon(const char *buffer, size_t totalLen, std::vector &rgbyteOut) { using namespace charls; const unsigned char* pbyteCompressed = (const unsigned char*)buffer; size_t cbyteCompressed = totalLen; JlsParameters params = {}; if(JpegLsReadHeader(pbyteCompressed, cbyteCompressed, ¶ms, nullptr) != ApiResult::OK ) { gdcmDebugMacro( "Could not parse JPEG-LS header" ); return false; } // 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); if (result != ApiResult::OK) { gdcmErrorMacro( "Could not decode JPEG-LS stream" ); return false; } return true; } bool JPEGLSCodec::Decode(DataElement const &in, DataElement &out) { #ifndef GDCM_USE_JPEGLS return false; #else using namespace charls; if( NumberOfDimensions == 2 ) { const SequenceOfFragments *sf = in.GetSequenceOfFragments(); if (!sf) return false; unsigned long totalLen = sf->ComputeByteLength(); char *buffer = new char[totalLen]; sf->GetBuffer(buffer, totalLen); std::vector rgbyteOut; bool b = DecodeByStreamsCommon(buffer, totalLen, rgbyteOut); if( !b ) return false; delete[] buffer; out = in; out.SetByteValue( (char*)&rgbyteOut[0], (uint32_t)rgbyteOut.size() ); return true; } else if( NumberOfDimensions == 3 ) { const SequenceOfFragments *sf = in.GetSequenceOfFragments(); if (!sf) return false; if (sf->GetNumberOfFragments() != Dimensions[2]) return false; std::stringstream os; for(unsigned int i = 0; i < sf->GetNumberOfFragments(); ++i) { const Fragment &frag = sf->GetFragment(i); if( frag.IsEmpty() ) return false; const ByteValue *bv = frag.GetByteValue(); if (!bv) return false; size_t totalLen = bv->GetLength(); char *mybuffer = new char[totalLen]; bv->GetBuffer(mybuffer, bv->GetLength()); const unsigned char* pbyteCompressed = (const unsigned char*)mybuffer; while( totalLen > 0 && pbyteCompressed[totalLen-1] != 0xd9 ) { totalLen--; } // what if 0xd9 is never found ? assert( totalLen > 0 && pbyteCompressed[totalLen-1] == 0xd9 ); size_t cbyteCompressed = totalLen; JlsParameters params = {}; if( JpegLsReadHeader(pbyteCompressed, cbyteCompressed, ¶ms, nullptr) != ApiResult::OK ) { gdcmDebugMacro( "Could not parse JPEG-LS header" ); return false; } // allowedlossyerror == 0 => Lossless LossyFlag = params.allowedLossyError!= 0; 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); bool r = true; delete[] mybuffer; if (result != ApiResult::OK) { return false; } os.write( (const char*)&rgbyteOut[0], 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() ); return true; } return false; #endif } bool JPEGLSCodec::CodeFrameIntoBuffer(char * outdata, size_t outlen, size_t & complen, const char * indata, size_t inlen ) { #ifndef GDCM_USE_JPEGLS return false; #else using namespace charls; const unsigned int *dims = this->GetDimensions(); int image_width = dims[0]; int image_height = dims[1]; const PixelFormat &pf = this->GetPixelFormat(); int sample_pixel = pf.GetSamplesPerPixel(); int bitsallocated = pf.GetBitsAllocated(); int bitsstored = pf.GetBitsStored(); JlsParameters params = {}; /* The fields in JlsCustomParameters do not control lossy/lossless. They provide the possibility to tune the JPEG-LS internals for better compression ratios. Expect a lot of work and testing to achieve small improvements. Lossy/lossless is controlled by the field allowedlossyerror. If you put in 0, encoding is lossless. If it is non-zero, then encoding is lossy. The value of 3 is often suggested as a default. The nice part about JPEG-LS encoding is that in lossy encoding, there is a guaranteed maximum error for each pixel. So a pixel that has value 12, encoded with a maximum lossy error of 3, may be decoded as a value between 9 and 15, but never anything else. In medical imaging this could be a useful guarantee. The not so nice part is that you may see striping artifacts when decoding "non-natural" images. I haven't seen the effects myself on medical images, but I suspect screenshots may suffer the most. Also, the bandwidth saving is not as big as with other lossy schemes. As for 12 bit, I am about to commit a unit test (with the sample you gave me) that does a successful round trip encoding of 12 bit color. I did notice that for 12 bit, the encoder fails if the unused bits are non-zero, but the sample dit not suffer from that. */ params.allowedLossyError = !LossyFlag ? 0 : LossyError; params.components = sample_pixel; // D_CLUNIE_RG3_JPLY.dcm. The famous 16bits allocated / 10 bits stored with the pixel value = 1024 // CharLS properly encode 1024 considering it as 10bits data, so the output // Using bitsstored for the encoder gives a slightly better compression ratio, and is indeed the // right way of doing it. // gdcmData/PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm if( true || pf.GetPixelRepresentation() ) { // gdcmData/CT_16b_signed-UsedBits13.dcm params.bitsPerSample = bitsallocated; } else { params.bitsPerSample = bitsstored; } params.height = image_height; params.width = image_width; if (sample_pixel == 4) { params.interleaveMode = InterleaveMode::Line; } else if (sample_pixel == 3) { params.interleaveMode = InterleaveMode::Line; params.colorTransformation = ColorTransformation::HP1; } ApiResult error = JpegLsEncode(outdata, outlen, &complen, indata, inlen, ¶ms, nullptr); if( error != ApiResult::OK ) { gdcmErrorMacro( "Error compressing: " << (int)error ); return false; } assert( complen < outlen ); return true; #endif } // Compress into JPEG bool JPEGLSCodec::Code(DataElement const &in, DataElement &out) { #ifndef GDCM_USE_JPEGLS return false; #else out = in; // // Create a Sequence Of Fragments: SmartPointer sq = new SequenceOfFragments; const unsigned int *dims = this->GetDimensions(); int image_width = dims[0]; int image_height = dims[1]; const ByteValue *bv = in.GetByteValue(); const char *input = bv->GetPointer(); unsigned long len = bv->GetLength(); unsigned long image_len = len / dims[2]; size_t inputlength = image_len; for(unsigned int dim = 0; dim < dims[2]; ++dim) { const char *inputdata = input + dim * image_len; std::vector rgbyteCompressed; 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 ); if( !b ) return false; Fragment frag; frag.SetByteValue( (char*)&rgbyteCompressed[0], (uint32_t)cbyteCompressed ); sq->AddFragment( frag ); } assert( sq->GetNumberOfFragments() == dims[2] ); out.SetValue( *sq ); return true; #endif } void JPEGLSCodec::SetLossyError(int error) { LossyError = error; } bool JPEGLSCodec::Decode(DataElement const &, char* , size_t, uint32_t , uint32_t , uint32_t , uint32_t , uint32_t , uint32_t ) { return false; } bool JPEGLSCodec::DecodeExtent( char *buffer, unsigned int xmin, unsigned int xmax, unsigned int ymin, unsigned int ymax, unsigned int zmin, unsigned int zmax, std::istream & is ) { BasicOffsetTable bot; bot.Read( is ); const unsigned int * dimensions = this->GetDimensions(); const PixelFormat & pf = this->GetPixelFormat(); assert( pf.GetBitsAllocated() % 8 == 0 ); assert( pf != PixelFormat::SINGLEBIT ); assert( pf != PixelFormat::UINT12 && pf != PixelFormat::INT12 ); if( NumberOfDimensions == 2 ) { char *dummy_buffer = nullptr; std::vector vdummybuffer; size_t buf_size = 0; const Tag seqDelItem(0xfffe,0xe0dd); Fragment frag; while( frag.ReadPreValue(is) && frag.GetTag() != seqDelItem ) { size_t fraglen = frag.GetVL(); size_t oldlen = vdummybuffer.size(); // update buf_size = fraglen + oldlen; vdummybuffer.resize( buf_size ); dummy_buffer = &vdummybuffer[0]; // read J2K is.read( &vdummybuffer[oldlen], fraglen ); } assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 ); assert( zmin == zmax ); assert( zmin == 0 ); std::vector outv; bool b = DecodeByStreamsCommon(dummy_buffer, buf_size, outv); if( !b ) return false; unsigned char *raw = &outv[0]; const unsigned int rowsize = xmax - xmin + 1; const unsigned int colsize = ymax - ymin + 1; const unsigned int bytesPerPixel = pf.GetPixelSize(); if( outv.size() != dimensions[0] * dimensions[1] * bytesPerPixel ) { gdcmDebugMacro( "Inconsistent buffer size. Giving up" ); return false; } const unsigned char *tmpBuffer1 = raw; unsigned int z = 0; for (unsigned int y = ymin; y <= ymax; ++y) { size_t theOffset = 0 + (z*dimensions[1]*dimensions[0] + y*dimensions[0] + xmin)*bytesPerPixel; tmpBuffer1 = raw + theOffset; memcpy(&(buffer[((z-zmin)*rowsize*colsize + (y-ymin)*rowsize)*bytesPerPixel]), tmpBuffer1, rowsize*bytesPerPixel); } } else if ( NumberOfDimensions == 3 ) { const Tag seqDelItem(0xfffe,0xe0dd); Fragment frag; std::streamoff thestart = is.tellg(); unsigned int numfrags = 0; std::vector< size_t > offsets; while( frag.ReadPreValue(is) && frag.GetTag() != seqDelItem ) { //std::streamoff relstart = is.tellg(); //assert( relstart - thestart == 8 ); std::streamoff off = frag.GetVL(); offsets.push_back( (size_t)off ); is.seekg( off, std::ios::cur ); ++numfrags; } assert( frag.GetTag() == seqDelItem && frag.GetVL() == 0 ); assert( numfrags == offsets.size() ); if( numfrags != Dimensions[2] ) { gdcmErrorMacro( "Not handled" ); return false; } for( unsigned int z = zmin; z <= zmax; ++z ) { size_t curoffset = std::accumulate( offsets.begin(), offsets.begin() + z, size_t(0) ); is.seekg( thestart + curoffset + 8 * z, std::ios::beg ); is.seekg( 8, std::ios::cur ); const size_t buf_size = offsets[z]; char *dummy_buffer = new char[ buf_size ]; is.read( dummy_buffer, buf_size ); std::vector outv; bool b = DecodeByStreamsCommon(dummy_buffer, buf_size, outv); delete[] dummy_buffer; if( !b ) return false; unsigned char *raw = &outv[0]; const unsigned int rowsize = xmax - xmin + 1; const unsigned int colsize = ymax - ymin + 1; const unsigned int bytesPerPixel = pf.GetPixelSize(); if( outv.size() != dimensions[0] * dimensions[1] * bytesPerPixel ) { gdcmDebugMacro( "Inconsistent buffer size. Giving up" ); return false; } const unsigned char *tmpBuffer1 = raw; for (unsigned int y = ymin; y <= ymax; ++y) { size_t theOffset = 0 + (0*dimensions[1]*dimensions[0] + y*dimensions[0] + xmin)*bytesPerPixel; tmpBuffer1 = raw + theOffset; memcpy(&(buffer[((z-zmin)*rowsize*colsize + (y-ymin)*rowsize)*bytesPerPixel]), tmpBuffer1, rowsize*bytesPerPixel); } } } return true; } ImageCodec * JPEGLSCodec::Clone() const { JPEGLSCodec * copy = new JPEGLSCodec; return copy; } bool JPEGLSCodec::StartEncode( std::ostream & ) { return true; } bool JPEGLSCodec::IsRowEncoder() { return false; } bool JPEGLSCodec::IsFrameEncoder() { return true; } bool JPEGLSCodec::AppendRowEncode( std::ostream & , const char * , size_t ) { return false; } bool JPEGLSCodec::AppendFrameEncode( std::ostream & out, const char * data, size_t datalen ) { const unsigned int * dimensions = this->GetDimensions(); const PixelFormat & pf = this->GetPixelFormat(); (void)pf; assert( datalen == dimensions[0] * dimensions[1] * pf.GetPixelSize() ); std::vector rgbyteCompressed; rgbyteCompressed.resize(dimensions[0] * dimensions[1] * 4); size_t cbyteCompressed; const bool b = this->CodeFrameIntoBuffer((char*)&rgbyteCompressed[0], rgbyteCompressed.size(), cbyteCompressed, data, datalen ); if( !b ) return false; out.write( (char*)&rgbyteCompressed[0], cbyteCompressed ); return true; } bool JPEGLSCodec::StopEncode( std::ostream & ) { return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmJPEGLSCodec.h000066400000000000000000000061471412732066400234500ustar00rootroot00000000000000/*========================================================================= 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 GDCMJPEGLSCODEC_H #define GDCMJPEGLSCODEC_H #include "gdcmImageCodec.h" namespace gdcm { class JPEGLSInternals; /** * \brief JPEG-LS * \note codec that implement the JPEG-LS compression * this is an implementation of ImageCodec for JPEG-LS * * It uses the CharLS JPEG-LS implementation https://github.com/team-charls/charls */ class GDCM_EXPORT JPEGLSCodec : public ImageCodec { friend class ImageRegionReader; public: JPEGLSCodec(); ~JPEGLSCodec() override; bool CanDecode(TransferSyntax const &ts) const override; bool CanCode(TransferSyntax const &ts) const override; unsigned long GetBufferLength() const { return BufferLength; } void SetBufferLength(unsigned long l) { BufferLength = l; } bool Decode(DataElement const &is, DataElement &os) override; bool Decode(DataElement const &in, char* outBuffer, size_t inBufferLength, uint32_t inXMin, uint32_t inXMax, uint32_t inYMin, uint32_t inYMax, uint32_t inZMin, uint32_t inZMax); bool Code(DataElement const &in, DataElement &out) override; bool GetHeaderInfo(std::istream &is, TransferSyntax &ts) override; ImageCodec * Clone() const override; void SetLossless(bool l); bool GetLossless() const; /* * test.acr can look pretty bad, even with a lossy error of 2. Explanation follows: * I agree that the test image looks ugly. In this particular case I can * explain though. * * The image is 8 bit, but it does not use the full 8 bit dynamic range. The * black pixels have value 234 and the white 255. If you set allowed lossy * error to 2, you allow an error of about 10% of the actual dynamic range. * That is of course very visible. */ /// [0-3] generally void SetLossyError(int error); protected: bool DecodeExtent( char *buffer, unsigned int xmin, unsigned int xmax, unsigned int ymin, unsigned int ymax, unsigned int zmin, unsigned int zmax, std::istream & is ); bool StartEncode( std::ostream & ) override; bool IsRowEncoder() override; bool IsFrameEncoder() override; bool AppendRowEncode( std::ostream & out, const char * data, size_t datalen ) override; bool AppendFrameEncode( std::ostream & out, const char * data, size_t datalen ) override; bool StopEncode( std::ostream & ) override; private: bool DecodeByStreamsCommon(const char *buffer, size_t totalLen, std::vector &rgbyteOut); bool CodeFrameIntoBuffer(char * outdata, size_t outlen, size_t & complen, const char * indata, size_t inlen ); unsigned long BufferLength; int LossyError; }; } // end namespace gdcm #endif //GDCMJPEGLSCODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmJSON.cxx000066400000000000000000000727371412732066400226620ustar00rootroot00000000000000/*========================================================================= 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 "gdcmJSON.h" #include "gdcmGlobal.h" #include "gdcmDicts.h" #include "gdcmBase64.h" #include "gdcmSystem.h" #ifdef GDCM_USE_SYSTEM_JSON #include #endif #ifdef GDCM_HAVE_JSON_OBJECT_OBJECT_GET_EX // https://github.com/json-c/json-c/issues/142 static inline json_object * json_object_object_get_old(json_object * obj, const char * name) { json_object * sub; return json_object_object_get_ex(obj, name, & sub) ? sub : NULL; } #else #define json_object_object_get_old json_object_object_get #endif /* * Implementation is done based on Sup166, which may change in the future. */ // TODO: CP 246 / VR=SQ + Sequence: ! // Clarification needed: // "00081070":{ // "Tag":"00081070", // "VR":"PN", // "Value":[ // null // ] // }, // Need to pay attention that: // \ISO 2022 IR 13\ISO 2022 IR 87 // encodes to: // [ null, "ISO 2022 IR 13", "ISO 2022 IR 87" ] // or ? // [ "", "ISO 2022 IR 13", "ISO 2022 IR 87" ] // TODO: // DS/IS should be encoded as number // Question, does F.2.5 DICOM JSON Model Null Values // imply: // "Sequence": [ null ] ? // does not make any sense to send Group Length... // Clarification needed, specs says IS should be a Number but example uses // String namespace gdcm { #ifdef GDCM_USE_SYSTEM_JSON static inline void wstrim(std::string& str) { str.erase(0, str.find_first_not_of(' ')); str.erase(str.find_last_not_of(' ')+1); } static inline bool CanContainBackslash( const VR::VRType vrtype ) { assert( VR::IsASCII( vrtype ) ); // PS 3.5-2011 / Table 6.2-1 DICOM VALUE REPRESENTATIONS switch( vrtype ) { case VR::AE: // ScheduledStationAETitle //case VR::AS: // no //case VR::AT: // binary case VR::CS: // SpecificCharacterSet case VR::DA: // CalibrationDate case VR::DS: // FrameTimeVector case VR::DT: // ReferencedDateTime //case VR::FD: // binary //case VR::FL: case VR::IS: // ReferencedFrameNumber case VR::LO: // OtherPatientIDs //case VR::LT: // VM1 //case VR::OB: // binary //case VR::OD: // binary //case VR::OF: // binary //case VR::OW: // binary case VR::PN: // PerformingPhysicianName case VR::SH: // PatientTelephoneNumbers //case VR::SL: // binary //case VR::SQ: // binary //case VR::SS: // binary //case VR::ST: // VM1 case VR::TM: // CalibrationTime case VR::UI: // SOPClassesInStudy //case VR::UL: // binary //case VR::UN: // binary //case VR::US: // binary //case VR::UT: // VM1 assert( !(vrtype & VR::VR_VM1) ); return true; default: ; } return false; } #endif class JSONInternal { public: JSONInternal()= default; bool PrettyPrint{false}; bool PreferKeyword{false}; }; JSON::JSON() { Internals = new JSONInternal; } JSON::~JSON() { delete Internals; } void JSON::SetPrettyPrint(bool onoff) { Internals->PrettyPrint = onoff; } bool JSON::GetPrettyPrint() const { return Internals->PrettyPrint; } void JSON::PrettyPrintOn() { Internals->PrettyPrint = true; } void JSON::PrettyPrintOff() { Internals->PrettyPrint = false; } #ifdef GDCM_USE_SYSTEM_JSON /* "StudyInstanceUID": { "Tag": "0020000D", "VR": "UI", "Value": [ "1.2.392.200036.9116.2.2.2.1762893313.1029997326.945873" ] }, */ static void DataElementToJSONArray( const VR::VRType vr, const DataElement & de, json_object *my_array ) { if( de.IsEmpty() ) { // F.2.5 DICOM JSON Model Null Values if( vr == VR::PN ) { json_object *my_object_comp = json_object_new_object(); json_object_array_add(my_array, my_object_comp ); } //else // json_object_array_add(my_array, NULL ); return; } // else assert( !de.IsEmpty() ); const bool checkbackslash = CanContainBackslash( vr ); const ByteValue * bv = de.GetByteValue(); const char * value = bv->GetPointer(); size_t len = bv->GetLength(); if( vr == VR::UI ) { const std::string strui( value, len ); const size_t lenuid = strlen( strui.c_str() ); // trick to remove trailing \0 json_object_array_add(my_array, json_object_new_string_len(strui.c_str(), lenuid)); } else if( vr == VR::PN ) { const char *str1 = value; // remove whitespace: while( str1[len-1] == ' ' ) { len--; } assert( str1 ); std::stringstream ss; static const char *Keys[] = { "Alphabetic", "Ideographic", "Phonetic", }; while (1) { assert( str1 && (size_t)(str1 - value) <= len ); const char * sep = strchr(str1, '\\'); const size_t llen = (sep != NULL) ? (sep - str1) : (value + len - str1); const std::string component(str1, llen); const char *str2 = component.c_str(); assert( str2 ); const size_t len2 = component.size(); assert( len2 == llen ); int idx = 0; json_object *my_object_comp = json_object_new_object(); while (1) { assert( str2 && (size_t)(str2 - component.c_str() ) <= len2 ); const char * sep2 = strchr(str2, '='); const size_t llen2 = (sep2 != NULL) ? (sep2 - str2) : (component.c_str() + len2 - str2); const std::string group(str2, llen2); const char *thekey = Keys[idx++]; json_object_object_add(my_object_comp, thekey, json_object_new_string_len( group.c_str(), group.size() ) ); if (sep2 == NULL) break; str2 = sep2 + 1; } json_object_array_add(my_array, my_object_comp); if (sep == NULL) break; str1 = sep + 1; assert( checkbackslash ); } } else if( vr == VR::DS || vr == VR::IS ) { const char *str1 = value; assert( str1 ); VRToType::Type vris; VRToType::Type vrds; while (1) { std::stringstream ss; assert( str1 && (size_t)(str1 - value) <= len ); const char * sep = strchr(str1, '\\'); const size_t llen = (sep != NULL) ? (sep - str1) : (value + len - str1); // This is complex, IS/DS should not be stored as string anymore switch( vr ) { case VR::IS: ss.str( std::string(str1, llen) ); ss >> vris; json_object_array_add(my_array, json_object_new_int(vris)); // json_object_new_int takes an int32_t break; case VR::DS: ss.str( std::string(str1, llen) ); ss >> vrds; json_object_array_add(my_array, json_object_new_double(vrds)); break; default: assert( 0 ); // programmer error } if (sep == NULL) break; str1 = sep + 1; assert( checkbackslash ); } } else if( checkbackslash ) { const char *str1 = value; assert( str1 ); while (1) { assert( str1 && (size_t)(str1 - value) <= len ); const char * sep = strchr(str1, '\\'); const size_t llen = (sep != NULL) ? (sep - str1) : (value + len - str1); json_object_array_add(my_array, json_object_new_string_len(str1, llen)); if (sep == NULL) break; str1 = sep + 1; } } else // default { json_object_array_add(my_array, json_object_new_string_len(value, len)); } } // Encode from DICOM to JSON // TODO: do I really need libjson for this task ? // FIXME: once again everything is loaded into memory static void ProcessNestedDataSet( const DataSet & ds, json_object *my_object, const bool preferkeyword ) { const Global& g = GlobalInstance; const Dicts &dicts = g.GetDicts(); const Dict &d = dicts.GetPublicDict(); (void)d; std::vector buffer; for( DataSet::ConstIterator it = ds.Begin(); it != ds.End(); ++it ) { const DataElement &de = *it; VR::VRType vr = de.GetVR(); const Tag& t = de.GetTag(); if( t.IsGroupLength() ) continue; // I do not see why we should send those ? std::string strowner; const char *owner = 0; if( t.IsPrivate() && !t.IsPrivateCreator() ) { strowner = ds.GetPrivateCreator(t); owner = strowner.c_str(); } const DictEntry &entry = dicts.GetDictEntry(t,owner); const std::string & str_tag = t.PrintAsContinuousUpperCaseString(); const bool issequence = vr == VR::SQ || de.IsUndefinedLength(); const bool isprivatecreator = t.IsPrivateCreator(); if( issequence ) vr = VR::SQ; else if( isprivatecreator ) vr = VR::LO; // always prefer VR::LO (over invalid/UN) else if( vr == VR::INVALID ) vr = VR::UN; const char * vr_str = VR::GetVRString(vr); assert( VR::GetVRTypeFromFile(vr_str) != VR::INVALID ); json_object *my_object_cur; my_object_cur = json_object_new_object(); json_object *my_array; my_array = json_object_new_array(); //json_object_object_add(my_object_cur, "Tag", // json_object_new_string( str_tag.c_str()) ); json_object_object_add(my_object_cur, "VR", json_object_new_string_len( vr_str, 2 ) ); if( owner ) { json_object_object_add(my_object_cur, "PrivateCreator", json_object_new_string( owner ) ); } if( vr == VR::SQ ) { SmartPointer sqi; sqi = de.GetValueAsSQ(); if( sqi ) { int nitems = sqi->GetNumberOfItems(); for(int i = 1; i <= nitems; ++i) { const Item &item = sqi->GetItem( i ); const DataSet &nested = item.GetNestedDataSet(); json_object *my_object_sq; my_object_sq = json_object_new_object(); ProcessNestedDataSet( nested, my_object_sq, preferkeyword ); json_object_array_add(my_array, my_object_sq ); } } else if( const SequenceOfFragments *sqf = de.GetSequenceOfFragments() ) { json_object_array_add(my_array, NULL ); // FIXME assert( 0 ); } else { assert( de.IsEmpty() ); //json_object_array_add(my_array, NULL ); // F.2.5 req ? } //json_object_object_add(my_object_cur, "Sequence", my_array ); int numel = json_object_array_length ( my_array ); if( numel ) json_object_object_add(my_object_cur, "Value", my_array ); } else if( VR::IsASCII( vr ) ) { DataElementToJSONArray( vr, de, my_array ); int numel = json_object_array_length ( my_array ); if( numel ) { if( vr == VR::PN ) { //json_object_object_add(my_object_cur, "PersonName", my_array ); json_object_object_add(my_object_cur, "Value", my_array ); } else json_object_object_add(my_object_cur, "Value", my_array ); } } else { const char *wheretostore = "Value"; switch( vr ) { case VR::FD: { // Does not work, see https://github.com/json-c/json-c/pull/59 Element el; el.Set( de.GetValue() ); int ellen = el.GetLength(); for( int i = 0; i < ellen; ++i ) { json_object_array_add(my_array, json_object_new_double( el.GetValue( i ) )); } } break; case VR::FL: { Element el; el.Set( de.GetValue() ); int ellen = el.GetLength(); for( int i = 0; i < ellen; ++i ) { json_object_array_add(my_array, json_object_new_double( el.GetValue( i ) )); } } break; case VR::SS: { Element el; el.Set( de.GetValue() ); int ellen = el.GetLength(); for( int i = 0; i < ellen; ++i ) { json_object_array_add(my_array, json_object_new_int( el.GetValue( i ) )); } } break; case VR::US: { Element el; el.Set( de.GetValue() ); int ellen = el.GetLength(); for( int i = 0; i < ellen; ++i ) { json_object_array_add(my_array, json_object_new_int( el.GetValue( i ) )); } } break; case VR::SL: { Element el; el.Set( de.GetValue() ); int ellen = el.GetLength(); for( int i = 0; i < ellen; ++i ) { json_object_array_add(my_array, json_object_new_int( el.GetValue( i ) )); } } break; case VR::UL: { Element el; el.Set( de.GetValue() ); int ellen = el.GetLength(); for( int i = 0; i < ellen; ++i ) { json_object_array_add(my_array, json_object_new_int( el.GetValue( i ) )); } } break; case VR::AT: { Element el; el.Set( de.GetValue() ); int ellen = el.GetLength(); for( int i = 0; i < ellen; ++i ) { const std::string atstr = el.GetValue( i ).PrintAsContinuousUpperCaseString(); json_object_array_add(my_array, json_object_new_string( atstr.c_str() )); } } break; case VR::UN: case VR::INVALID: case VR::OD: case VR::OF: case VR::OB: case VR::OW: { assert( !de.IsUndefinedLength() ); // handled before const ByteValue * bv = de.GetByteValue(); wheretostore = "InlineBinary"; if( bv ) { const char *src = bv->GetPointer(); const size_t len = bv->GetLength(); assert( len % 2 == 0 ); const size_t len64 = Base64::GetEncodeLength(src, len); buffer.resize( len64 ); const size_t ret = Base64::Encode( &buffer[0], len64, src, len ); assert( ret != 0 ); json_object_array_add(my_array, json_object_new_string_len(&buffer[0], len64)); } } break; default: assert( 0 ); // programmer error } json_object_object_add(my_object_cur, wheretostore, my_array ); } //const char *keyword = entry.GetKeyword(); //assert( keyword && *keyword ); //if( preferkeyword && keyword && *keyword && !t.IsPrivateCreator() ) // { // json_object_object_add(my_object, keyword, my_object_cur ); // } //else { json_object_object_add(my_object, str_tag.c_str(), my_object_cur ); } } } #endif bool JSON::Code(DataSet const & ds, std::ostream & os) { #ifdef GDCM_USE_SYSTEM_JSON json_object *my_object; my_object = json_object_new_object(); ProcessNestedDataSet( ds, my_object, Internals->PreferKeyword ); const char* str = NULL; if( Internals->PrettyPrint ) { #ifdef JSON_C_VERSION str = json_object_to_json_string_ext(my_object, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY ); #else str = json_object_to_json_string( my_object ); #endif } else { str = json_object_to_json_string( my_object ); } os << str; json_object_put(my_object); // free memory return true; #else (void)ds; (void)os; return false; #endif } #ifdef GDCM_USE_SYSTEM_JSON // Paranoid static inline bool CheckTagKeywordConsistency( const char *name, const Tag & thetag ) { // Can be keyword or tag assert( name ); // start with easy one: // only test first string character: bool istag = *name >= '0' && *name <= '9'; // should be relatively efficient if( istag ) { assert( strlen(name) == 8 ); Tag t; t.ReadFromContinuousString( name ); return t == thetag; } // else keyword: const Global& g = GlobalInstance; const Dicts &dicts = g.GetDicts(); const Dict &d = dicts.GetPublicDict(); const char * keyword = d.GetKeywordFromTag(thetag); if( !keyword ) { gdcmDebugMacro( "Unknown Keyword: " << name ); return true; } // else assert( strcmp( name, keyword ) == 0 ); return strcmp( name, keyword ) == 0; } #endif #ifdef GDCM_USE_SYSTEM_JSON #ifdef JSON_C_VERSION static void ProcessJSONElement( const char *tag_str, json_object * obj, DataElement & de ) { json_type jtype = json_object_get_type( obj ); assert( jtype == json_type_object ); json_object * jvr = json_object_object_get_old(obj, "VR"); const char * vr_str = json_object_get_string ( jvr ); de.GetTag().ReadFromContinuousString( tag_str ); const char * pc_str = 0; if( de.GetTag().IsPrivate() && !de.GetTag().IsPrivateCreator() ) { json_object * jprivatecreator = json_object_object_get_old(obj, "PrivateCreator"); pc_str = json_object_get_string ( jprivatecreator ); assert( pc_str ); } VR::VRType vrtype = VR::GetVRTypeFromFile( vr_str ); assert( vrtype != VR::INVALID ); assert( vrtype != VR::VR_END ); de.SetVR( vrtype ); if( vrtype == VR::SQ ) { json_object * jvalue = json_object_object_get_old(obj, "Value"); json_type jvaluetype = json_object_get_type( jvalue ); assert( jvaluetype != json_type_null && jvaluetype == json_type_array ); #ifndef NDEBUG json_object * jseq = json_object_object_get_old(obj, "Sequence"); json_type jsqtype = json_object_get_type( jseq ); assert( jsqtype == json_type_null ); #endif if( jvaluetype == json_type_array ) { // Create a Sequence SmartPointer sq = new SequenceOfItems; sq->SetLengthToUndefined(); int sqlen = json_object_array_length ( jvalue ); for( int itemidx = 0; itemidx < sqlen; ++itemidx ) { json_object * jitem = json_object_array_get_idx ( jvalue, itemidx ); json_type jitemtype = json_object_get_type( jitem ); assert( jitemtype == json_type_object ); //const char * dummy = json_object_to_json_string ( jitem ); // Create an item Item item; item.SetVLToUndefined(); DataSet &nds = item.GetNestedDataSet(); #ifdef JSON_C_VERSION json_object_iterator it; json_object_iterator itEnd; it = json_object_iter_begin(jitem); itEnd = json_object_iter_end(jitem); while (!json_object_iter_equal(&it, &itEnd)) { const char *name = json_object_iter_peek_name(&it); assert( name ); json_object * value = json_object_iter_peek_value (&it); DataElement lde; ProcessJSONElement( name, value, lde ); nds.Insert( lde ); json_object_iter_next(&it); } #endif sq->AddItem(item); } // Insert sequence into data set de.SetValue(*sq); de.SetVLToUndefined(); } } else if( VR::IsASCII( vrtype ) ) { /* F.2.5 DICOM JSON Model Null Values If an attribute is present in DICOM but empty, it shall be preserved in the DICOM JSON object and passed with the value of "null". For example: "Value": [ null ] */ json_object * jvalue = json_object_object_get_old(obj, "Value"); #ifndef NDEBUG json_object * jpn = json_object_object_get_old(obj, "PersonName"); json_type jpntype = json_object_get_type( jpn ); assert( jpntype == json_type_null ); #endif json_type jvaluetype = json_object_get_type( jvalue ); //const char * dummy = json_object_to_json_string ( jvalue ); assert( jvaluetype == json_type_null || jvaluetype == json_type_array ); if( jvaluetype == json_type_array ) { //assert( vrtype != VR::PN ); const int valuelen = json_object_array_length ( jvalue ); std::string str; for( int validx = 0; validx < valuelen; ++validx ) { if( validx ) str += '\\'; json_object * value = json_object_array_get_idx ( jvalue, validx ); json_type valuetype = json_object_get_type( value ); if( value ) { assert( valuetype != json_type_null ); std::string value_str; std::stringstream ss; VRToType::Type vris; VRToType::Type vrds; switch( vrtype ) { case VR::PN: { json_object * jopn[3]; jopn[0] = json_object_object_get_old(value, "Alphabetic"); jopn[1]= json_object_object_get_old(value, "Ideographic"); jopn[2]= json_object_object_get_old(value, "Phonetic"); for( int i = 0; i < 3; ++i ) { const char *tmp = json_object_get_string ( jopn[i] ); if( tmp ) { if( i ) value_str += '='; value_str += tmp; } } } break; case VR::IS: vris = json_object_get_int( value ); ss << vris; value_str = ss.str(); break; case VR::DS: vrds = json_object_get_double( value ); ss << vrds; value_str = ss.str(); break; default: value_str = json_object_get_string ( value ); } str += value_str; } else { // We have a [ null ] array, so at most there is a single item: assert( valuelen == 1 ); assert( valuetype == json_type_null ); } } if( str.size() % 2 ) { if( vrtype == VR::UI ) str.push_back( 0 ); else str.push_back( ' ' ); } de.SetByteValue( &str[0], str.size() ); } #ifndef NDEBUG else if( jpntype == json_type_array ) { assert( 0 ); } #endif } else { json_object * jvaluebin = json_object_object_get_old(obj, "InlineBinary"); json_type jvaluebintype = json_object_get_type( jvaluebin ); json_object * jvalue = json_object_object_get_old(obj, "Value"); json_type jvaluetype = json_object_get_type( jvalue ); //const char * dummy = json_object_to_json_string ( jvalue ); assert( jvaluetype == json_type_array || jvaluetype == json_type_null ); if( jvaluetype == json_type_array ) { DataElement locde; const int valuelen = json_object_array_length ( jvalue ); const int vrsizeof = vrtype == VR::INVALID ? 0 : de.GetVR().GetSizeof(); switch( vrtype ) { case VR::FD: { Element el; el.SetLength( valuelen * vrsizeof ); for( int validx = 0; validx < valuelen; ++validx ) { json_object * value = json_object_array_get_idx ( jvalue, validx ); assert( json_object_get_type( value ) == json_type_double ); const double v = json_object_get_double ( value ); el.SetValue(v, validx); } locde = el.GetAsDataElement(); } break; case VR::FL: { Element el; el.SetLength( valuelen * vrsizeof ); for( int validx = 0; validx < valuelen; ++validx ) { json_object * value = json_object_array_get_idx ( jvalue, validx ); assert( json_object_get_type( value ) == json_type_double ); const double v = json_object_get_double ( value ); el.SetValue(v, validx); } locde = el.GetAsDataElement(); } break; case VR::SS: { Element el; el.SetLength( valuelen * vrsizeof ); for( int validx = 0; validx < valuelen; ++validx ) { json_object * value = json_object_array_get_idx ( jvalue, validx ); assert( json_object_get_type( value ) == json_type_int ); const int v = json_object_get_int( value ); el.SetValue(v, validx); } locde = el.GetAsDataElement(); } break; case VR::US: { Element el; el.SetLength( valuelen * vrsizeof ); for( int validx = 0; validx < valuelen; ++validx ) { json_object * value = json_object_array_get_idx ( jvalue, validx ); assert( json_object_get_type( value ) == json_type_int ); const int v = json_object_get_int( value ); el.SetValue(v, validx); } locde = el.GetAsDataElement(); } break; case VR::SL: { Element el; el.SetLength( valuelen * vrsizeof ); for( int validx = 0; validx < valuelen; ++validx ) { json_object * value = json_object_array_get_idx ( jvalue, validx ); assert( json_object_get_type( value ) == json_type_int ); const int v = json_object_get_int( value ); el.SetValue(v, validx); } locde = el.GetAsDataElement(); } break; case VR::UL: { Element el; el.SetLength( valuelen * vrsizeof ); for( int validx = 0; validx < valuelen; ++validx ) { json_object * value = json_object_array_get_idx ( jvalue, validx ); assert( json_object_get_type( value ) == json_type_int ); const int v = json_object_get_int( value ); el.SetValue(v, validx); } locde = el.GetAsDataElement(); } break; case VR::AT: { Element el; el.SetLength( valuelen * vrsizeof ); for( int validx = 0; validx < valuelen; ++validx ) { json_object * value = json_object_array_get_idx ( jvalue, validx ); assert( json_object_get_type( value ) == json_type_string ); const char *atstr = json_object_get_string( value ); Tag t; t.ReadFromContinuousString( atstr ); el.SetValue(t, validx); } locde = el.GetAsDataElement(); } break; default: assert( 0 ); } if( !locde.IsEmpty() ) de.SetValue( locde.GetValue() ); } else if( jvaluebintype == json_type_array ) { DataElement locde; const int valuelen = json_object_array_length ( jvaluebin ); switch( vrtype ) { case VR::UN: case VR::INVALID: case VR::OB: case VR::OD: case VR::OF: case VR::OW: { assert( valuelen == 1 || valuelen == 0 ); if( valuelen ) { json_object * value = json_object_array_get_idx ( jvaluebin, 0 ); json_type valuetype = json_object_get_type( value ); if( value ) { assert( valuetype != json_type_null ); const char * value_str = json_object_get_string ( value ); assert( value_str ); const size_t len64 = strlen( value_str ); const size_t len = Base64::GetDecodeLength( value_str, len64 ); std::vector buffer; buffer.resize( len ); const size_t ret = Base64::Decode( &buffer[0], len, value_str, len64 ); assert( ret != 0 ); locde.SetByteValue( &buffer[0], len ); } else { // We have a [ null ] array, so at most there is a single item: assert( valuelen == 1 ); assert( valuetype == json_type_null ); } } } break; default: assert( 0 ); } if( !locde.IsEmpty() ) de.SetValue( locde.GetValue() ); } else { assert( jvaluebintype == json_type_null && jvaluetype == json_type_null ); } } } #endif #endif bool JSON::Decode(std::istream & is, DataSet & ds) { #ifdef GDCM_USE_SYSTEM_JSON #ifdef JSON_C_VERSION json_object *jobj = NULL; const char *mystring = NULL; int stringlen = 0; enum json_tokener_error jerr; std::string str; json_tokener * tok = json_tokener_new (); do { std::getline( is, str ); mystring = str.c_str(); stringlen = str.size(); jobj = json_tokener_parse_ex(tok, mystring, stringlen); //if( is.eof() ) break; } while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue ); if (jerr != json_tokener_success) { fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr)); // Handle errors, as appropriate for your application. assert( 0 ); } if (tok->char_offset < stringlen) // XXX shouldn't access internal fields { // Handle extra characters after parsed object as desired. // e.g. issue an error, parse another object from that point, etc... } // Success, use jobj here. json_tokener_free( tok ); #else std::stringstream ss; std::string str; while( std::getline( is, str ) ) { ss << str; } const std::string & wholestr = ss.str(); json_object *obj; obj = json_tokener_parse( wholestr.c_str() ); #endif #ifdef JSON_C_VERSION json_object_iterator it; json_object_iterator itEnd; it = json_object_iter_begin(jobj); itEnd = json_object_iter_end(jobj); while (!json_object_iter_equal(&it, &itEnd)) { const char *name = json_object_iter_peek_name(&it); assert( name ); json_object * value = json_object_iter_peek_value (&it); DataElement de; ProcessJSONElement( name, value, de ); ds.Insert( de ); json_object_iter_next(&it); } return true; #else gdcmErrorMacro( "Version too old" ); return false; #endif #else (void)is; (void)ds; return false; #endif } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmJSON.h000066400000000000000000000021741412732066400222730ustar00rootroot00000000000000/*========================================================================= 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 GDCMJSON_H #define GDCMJSON_H /* See Sup 166 (QIDO-RS) http://www.dclunie.com/dicom-status/status.html#Supplement166 */ #include "gdcmFile.h" #include "gdcmDataElement.h" namespace gdcm { class JSONInternal; class GDCM_EXPORT JSON { public: JSON(); ~JSON(); bool GetPrettyPrint() const; void SetPrettyPrint(bool onoff); void PrettyPrintOn(); void PrettyPrintOff(); bool Code(DataSet const & in, std::ostream & os); bool Decode(std::istream & is, DataSet & out); private: JSONInternal *Internals; }; } // end namespace gdcm #endif //GDCMXMLPRINTER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmKAKADUCodec.cxx000066400000000000000000000142641412732066400237760ustar00rootroot00000000000000/*========================================================================= 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 "gdcmKAKADUCodec.h" #include "gdcmTransferSyntax.h" #include "gdcmDataElement.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmSequenceOfFragments.h" #include "gdcmPNMCodec.h" #include "gdcmByteSwap.txx" namespace gdcm { /* */ KAKADUCodec::KAKADUCodec() { //NeedByteSwap = true; } KAKADUCodec::~KAKADUCodec() = default; bool KAKADUCodec::CanDecode(TransferSyntax const &ts) const { #ifndef GDCM_USE_KAKADU (void)ts; return false; #else return ts == TransferSyntax::JPEG2000Lossless || ts == TransferSyntax::JPEG2000; #endif } bool KAKADUCodec::CanCode(TransferSyntax const &) const { return false; } /* KAKADU command line is a bit tricky to use: * * kdu_expand */ bool KAKADUCodec::Decode(DataElement const &in, DataElement &out) { #ifndef GDCM_USE_KAKADU (void)in; (void)out; return false; #else // First thing creates a j2k file from the fragment: const SequenceOfFragments *sf = in.GetSequenceOfFragments(); if(!sf) return false; if( NumberOfDimensions == 2 ) { // http://msdn.microsoft.com/en-us/library/hs3e7355.aspx // -> check if tempnam needs the 'free' char *tempinput = tempnam(0, "gdcminkduexp"); char *tempoutput = tempnam(0, "gdcmoutkduexp"); if( !tempinput || !tempoutput ) { //free(input); //free(output); return false; } std::string input = tempinput; input += ".j2k"; std::string output = tempoutput; output += ".rawl"; std::ofstream outfile(input.c_str(), std::ios::binary); sf->WriteBuffer(outfile); outfile.close(); // flush ! //Filename fn( System::GetCurrentProcessFileName() ); //std::string executable_path = fn.GetPath(); #ifdef GDCM_USE_SYSTEM_KAKADU std::string kakadu_command = GDCM_KAKADU_EXPAND_EXECUTABLE; kakadu_command += " -quiet"; #else #error not implemented #endif // ./bin/kakadujpeg -d -s jpeg.jpg -ci 0 out.raw kakadu_command += " -i "; kakadu_command += input; kakadu_command += " -o "; kakadu_command += output; //std::cerr << kakadu_command << std::endl; gdcmDebugMacro( kakadu_command ); int ret = system(kakadu_command.c_str()); //std::cerr << "system: " << ret << std::endl; size_t len = System::FileSize(output.c_str()); if(!len) return false; std::ifstream is(output.c_str(), std::ios::binary); char * buf = new char[len]; is.read(buf, len); out.SetTag( Tag(0x7fe0,0x0010) ); out.SetByteValue( buf, len ); delete[] buf; if( !System::RemoveFile(input.c_str()) ) { gdcmErrorMacro( "Could not delete input: " << input ); } if( !System::RemoveFile(output.c_str()) ) { gdcmErrorMacro( "Could not delete output: " << output ); } free(tempinput); free(tempoutput); } else if ( NumberOfDimensions == 3 ) { std::stringstream os; if( sf->GetNumberOfFragments() != Dimensions[2] ) { gdcmErrorMacro( "Not handled" ); return false; } for(unsigned int i = 0; i < sf->GetNumberOfFragments(); ++i) { // http://msdn.microsoft.com/en-us/library/hs3e7355.aspx // -> check if tempnam needs the 'free' char *tempinput = tempnam(0, "gdcminkduexp"); char *tempoutput = tempnam(0, "gdcmoutkduexp"); if( !tempinput || !tempoutput ) { //free(input); //free(output); return false; } std::string input = tempinput; input += ".j2k"; std::string output = tempoutput; output += ".rawl"; std::ofstream outfile(input.c_str(), std::ios::binary); const Fragment &frag = sf->GetFragment(i); assert( !frag.IsEmpty() ); const ByteValue *bv = frag.GetByteValue(); assert( bv ); //sf->WriteBuffer(outfile); bv->WriteBuffer( outfile ); outfile.close(); // flush ! //Filename fn( System::GetCurrentProcessFileName() ); //std::string executable_path = fn.GetPath(); #ifdef GDCM_USE_SYSTEM_KAKADU std::string kakadu_command = GDCM_KAKADU_EXPAND_EXECUTABLE; kakadu_command += " -quiet"; #else #error not implemented #endif // ./bin/kakadujpeg -d -s jpeg.jpg -ci 0 out.raw kakadu_command += " -i "; kakadu_command += input; kakadu_command += " -o "; kakadu_command += output; //std::cerr << kakadu_command << std::endl; gdcmDebugMacro( kakadu_command ); int ret = system(kakadu_command.c_str()); //std::cerr << "system: " << ret << std::endl; size_t len = System::FileSize(output.c_str()); if(!len) return false; std::ifstream is(output.c_str(), std::ios::binary); char * buf = new char[len]; is.read(buf, len); os.write(buf, len); //out.SetByteValue( buf, len ); delete[] buf; if( !System::RemoveFile(input.c_str()) ) { gdcmErrorMacro( "Could not delete input: " << input ); } if( !System::RemoveFile(output.c_str()) ) { gdcmErrorMacro( "Could not delete output: " << output ); } free(tempinput); free(tempoutput); } std::string str = os.str(); assert( str.size() ); out.SetTag( Tag(0x7fe0,0x0010) ); out.SetByteValue( &str[0], str.size() ); } else { gdcmErrorMacro( "Not handled" ); return false; } // FIXME: //LossyFlag = true; //return ImageCodec::Decode(in,out); return true; #endif } // Compress into JPEG bool KAKADUCodec::Code(DataElement const &in, DataElement &out) { #ifndef GDCM_USE_KAKADU (void)in; (void)out; return false; #else // That would be neat, please contribute :) return false; #endif } ImageCodec * KAKADUCodec::Clone() const { return nullptr; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmKAKADUCodec.h000066400000000000000000000021571412732066400234210ustar00rootroot00000000000000/*========================================================================= 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 GDCMKAKADUCODEC_H #define GDCMKAKADUCODEC_H #include "gdcmImageCodec.h" namespace gdcm { /** * \brief KAKADUCodec */ class KAKADUCodec : public ImageCodec { public: KAKADUCodec(); ~KAKADUCodec() override; bool CanDecode(TransferSyntax const &ts) const override; bool CanCode(TransferSyntax const &ts) const override; bool Decode(DataElement const &is, DataElement &os) override; bool Code(DataElement const &in, DataElement &out) override; ImageCodec * Clone() const override; private: }; } // end namespace gdcm #endif //GDCMKAKADUCODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmLookupTable.cxx000066400000000000000000000526771412732066400243330ustar00rootroot00000000000000/*========================================================================= 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 "gdcmLookupTable.h" #include "gdcmSwapper.h" #include #include #include #include #include namespace gdcm { class LookupTableInternal { public: LookupTableInternal():RGB() { Length[0] = Length[1] = Length[2] = 0; Subscript[0] = Subscript[1] = Subscript[2] = 0; BitSize[0] = BitSize[1] = BitSize[2] = 0; } unsigned int Length[3]; // In DICOM the length is specified on a short // but 65536 is expressed as 0 ... unsigned short Subscript[3]; unsigned short BitSize[3]; std::vector RGB; }; LookupTable::LookupTable() { Internal = new LookupTableInternal; BitSample = 0; IncompleteLUT = false; } LookupTable::~LookupTable() { delete Internal; } bool LookupTable::Initialized() const { bool b1 = BitSample != 0; bool b2 = Internal->BitSize[0] != 0 && Internal->BitSize[1] != 0 && Internal->BitSize[2] != 0; return b1 && b2; } void LookupTable::Clear() { BitSample = 0; IncompleteLUT = false; delete Internal; Internal = new LookupTableInternal; } void LookupTable::Allocate( unsigned short bitsample ) { if( bitsample == 8 ) { Internal->RGB.resize( 256 * 3 ); } else if ( bitsample == 16 ) { Internal->RGB.resize( 65536 * 2 * 3 ); } else { gdcmAssertAlwaysMacro(0); } BitSample = bitsample; } void LookupTable::InitializeLUT(LookupTableType type, unsigned short length, unsigned short subscript, unsigned short bitsize) { if( bitsize != 8 && bitsize != 16 ) { return; } assert( type >= RED && type <= BLUE ); assert( subscript == 0 ); assert( bitsize == 8 || bitsize == 16 ); if( length == 0 ) { Internal->Length[type] = 65536; } else { if( length != 256 ) { IncompleteLUT = true; } Internal->Length[type] = length; } Internal->Subscript[type] = subscript; Internal->BitSize[type] = bitsize; } unsigned int LookupTable::GetLUTLength(LookupTableType type) const { return Internal->Length[type]; } void LookupTable::SetLUT(LookupTableType type, const unsigned char *array, unsigned int length) { (void)length; //if( !Initialized() ) return; if( !Internal->Length[type] ) { gdcmDebugMacro( "Need to set length first" ); return; } if( !IncompleteLUT ) { assert( Internal->RGB.size() == 3*Internal->Length[type]*(BitSample/8) ); } // Too funny: 05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm // There is pseudo PALETTE_COLOR LUT in the Icon, if one look carefully the LUT values // goes like this: 0, 1, 2, 3, 4, 5, 6, 7 ... if( BitSample == 8 ) { const unsigned int mult = Internal->BitSize[type]/8; const unsigned int mult2 = length / Internal->Length[type]; assert( Internal->Length[type] * mult2 == length ); if( Internal->Length[type]*mult == length || Internal->Length[type]*mult + 1 == length ) { assert( mult2 == 1 || mult2 == 2 ); unsigned int offset = 0; if( mult == 2 ) { offset = 1; } for( unsigned int i = 0; i < Internal->Length[type]; ++i) { assert( i*mult+offset < length ); assert( 3*i+type < Internal->RGB.size() ); Internal->RGB[3*i+type] = array[i*mult+offset]; } } else { unsigned int offset = 0; assert( mult2 == 2 ); for( unsigned int i = 0; i < Internal->Length[type]; ++i) { assert( i*mult2+offset < length ); assert( 3*i+type < Internal->RGB.size() ); Internal->RGB[3*i+type] = array[i*mult2+offset]; } } } else if( BitSample == 16 ) { assert( Internal->Length[type]*(BitSample/8) == length ); uint16_t *uchar16 = (uint16_t*)(void*)&Internal->RGB[0]; const uint16_t *array16 = (const uint16_t*)(const void*)array; for( unsigned int i = 0; i < Internal->Length[type]; ++i) { assert( 2*i < length ); assert( 2*(3*i+type) < Internal->RGB.size() ); uchar16[3*i+type] = array16[i]; } } } void LookupTable::GetLUT(LookupTableType type, unsigned char *array, unsigned int &length) const { if( BitSample == 8 ) { const unsigned int mult = Internal->BitSize[type]/8; length = Internal->Length[type]*mult; unsigned int offset = 0; if( mult == 2 ) { offset = 1; } for( unsigned int i = 0; i < Internal->Length[type]; ++i) { assert( i*mult+offset < length ); assert( 3*i+type < Internal->RGB.size() ); array[i*mult+offset] = Internal->RGB[3*i+type]; } } else if( BitSample == 16 ) { length = Internal->Length[type]*(BitSample/8); uint16_t *uchar16 = (uint16_t*)(void*)&Internal->RGB[0]; uint16_t *array16 = (uint16_t*)(void*)array; for( unsigned int i = 0; i < Internal->Length[type]; ++i) { assert( 2*i < length ); assert( 2*(3*i+type) < Internal->RGB.size() ); array16[i] = uchar16[3*i+type]; } } } void LookupTable::GetLUTDescriptor(LookupTableType type, unsigned short &length, unsigned short &subscript, unsigned short &bitsize) const { assert( type >= RED && type <= BLUE ); if( Internal->Length[type] == 65536 ) { length = 0; } else { length = (unsigned short)Internal->Length[type]; } subscript = Internal->Subscript[type]; bitsize = Internal->BitSize[type]; // postcondition assert( subscript == 0 ); assert( bitsize == 8 || bitsize == 16 ); } void LookupTable::InitializeRedLUT(unsigned short length, unsigned short subscript, unsigned short bitsize) { InitializeLUT(RED, length, subscript, bitsize); } void LookupTable::InitializeGreenLUT(unsigned short length, unsigned short subscript, unsigned short bitsize) { InitializeLUT(GREEN, length, subscript, bitsize); } void LookupTable::InitializeBlueLUT(unsigned short length, unsigned short subscript, unsigned short bitsize) { InitializeLUT(BLUE, length, subscript, bitsize); } void LookupTable::SetRedLUT(const unsigned char *red, unsigned int length) { SetLUT(RED, red, length); } void LookupTable::SetGreenLUT(const unsigned char *green, unsigned int length) { SetLUT(GREEN, green, length); } void LookupTable::SetBlueLUT(const unsigned char *blue, unsigned int length) { SetLUT(BLUE, blue, length); } namespace { using U8 = union { uint8_t rgb[4]; // 3rd value = 0 uint32_t I; }; using U16 = union { uint16_t rgb[4]; // 3rd value = 0 uint64_t I; }; struct ltstr8 { bool operator()(U8 u1, U8 u2) const { return u1.I < u2.I; } }; struct ltstr16 { bool operator()(U16 u1, U16 u2) const { return u1.I < u2.I; } }; } // end namespace inline void printrgb( const unsigned char *rgb ) { std::cout << int(rgb[0]) << "," << int(rgb[1]) << "," << int(rgb[2]); } void LookupTable::Encode(std::istream &is, std::ostream &os) { if ( BitSample == 8 ) { #if 0 // FIXME: // There is a very subbtle 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; RGBColorIndexer s; int count = 0; while( !is.eof() ) { U8 u; u.rgb[3] = 0; is.read( (char*)u.rgb, 3); assert( u.rgb[3] == 0 ); //assert( u.rgb[0] == u.rgb[1] && u.rgb[1] == u.rgb[2] ); std::pair it = s.insert( u ); if( it.second ) ++count; int d = std::distance(s.begin(), it.first); //std::cout << count << " Index: " << d << " -> "; printrgb( u.rgb ); std::cout << "\n"; //assert( s.size() < 256 ); assert( d < s.size() ); //assert( d < 256 && d >= 0 ); } // now generate output image // this has two been done in two passes as std::set always re-balance is.clear(); is.seekg( 0 ); while( !is.eof() ) { U8 u; u.rgb[3] = 0; is.read( (char*)u.rgb, 3); assert( u.rgb[3] == 0 ); //assert( u.rgb[0] == u.rgb[1] && u.rgb[1] == u.rgb[2] ); std::pair it = s.insert( u ); int d = std::distance(s.begin(), it.first); //std::cout << "Index: " << d << " -> "; printrgb( u.rgb ); std::cout << "\n"; assert( d < s.size() ); //assert( d < 256 && d >= 0 ); os.put( d ); } // now setup the LUT itself: unsigned short ncolor = s.size(); // FIXME: shop'off any RGB that is not at the beginning. if( ncolor > 256 ) ncolor = 256; InitializeRedLUT(ncolor, 0, 8); InitializeGreenLUT(ncolor, 0, 8); InitializeBlueLUT(ncolor, 0, 8); //int i = Internal->RGB.size(); //assert( Internal->RGB.size() == 5 ); int idx = 0; for( RGBColorIndexer::const_iterator it = s.begin(); it != s.end() && idx < 256; ++it, ++idx ) { assert( idx == std::distance( s.begin(), it ) ); //std::cout << "Index: " << idx << " -> "; printrgb( it->rgb ); std::cout << "\n"; Internal->RGB[3*idx+RED] = it->rgb[RED]; Internal->RGB[3*idx+GREEN] = it->rgb[GREEN]; Internal->RGB[3*idx+BLUE] = it->rgb[BLUE]; } #else while( !is.eof() ) { U8 u; u.rgb[3] = 0; is.read( (char*)u.rgb, 3); assert( u.rgb[3] == 0 ); int d = 0; assert( d < 256 && d >= 0 ); os.put( (char)d ); } #endif } else if ( BitSample == 16 ) { #if 0 typedef std::set< U16, ltstr16 > RGBColorIndexer; RGBColorIndexer s; while( !is.eof() ) { U16 u; u.rgb[3] = 0; is.read( (char*)u.rgb, 3*2); assert( u.rgb[3] == 0 ); //assert( u.rgb[0] == u.rgb[1] && u.rgb[1] == u.rgb[2] ); std::pair it = s.insert( u ); int d = std::distance(s.begin(), it.first); //std::cout << "Index: " << d << " -> "; printrgb( u.rgb ); std::cout << "\n"; assert( d < s.size() ); assert( d < 65536 && d >= 0 ); } // now generate output image // this has two been done in two passes as std::set always re-balance is.clear(); is.seekg( 0 ); while( !is.eof() ) { U16 u; u.rgb[3] = 0; is.read( (char*)u.rgb, 3*2); assert( u.rgb[3] == 0 ); //assert( u.rgb[0] == u.rgb[1] && u.rgb[1] == u.rgb[2] ); std::pair it = s.insert( u ); unsigned short d = std::distance(s.begin(), it.first); //std::cout << "Index: " << d << " -> "; printrgb( u.rgb ); std::cout << "\n"; assert( d < s.size() ); assert( d < 65536 && d >= 0 ); os.write( (const char*)&d , 2 ); } // now setup the LUT itself: unsigned short ncolor = s.size(); InitializeRedLUT(ncolor, 0, 16); InitializeGreenLUT(ncolor, 0, 16); InitializeBlueLUT(ncolor, 0, 16); //int i = Internal->RGB.size(); //assert( Internal->RGB.size() == 5 ); int idx = 0; uint16_t *rgb16 = (uint16_t*)&Internal->RGB[0]; for( RGBColorIndexer::const_iterator it = s.begin(); it != s.end(); ++it, ++idx ) { assert( idx == std::distance( s.begin(), it ) ); //std::cout << "Index: " << idx << " -> "; printrgb( it->rgb ); std::cout << "\n"; rgb16[3*idx+RED] = it->rgb[RED]; rgb16[3*idx+GREEN] = it->rgb[GREEN]; rgb16[3*idx+BLUE] = it->rgb[BLUE]; } #else while( !is.eof() ) { U16 u; u.rgb[3] = 0; is.read( (char*)u.rgb, 3*2); assert( u.rgb[3] == 0 ); int d = 0; assert( d < 65536 && d >= 0 ); os.write( (const char*)&d , 2 ); } #endif } } void LookupTable::Decode(std::istream &is, std::ostream &os) const { assert( Initialized() ); if ( BitSample == 8 ) { unsigned char idx; unsigned char rgb[3]; while( !is.eof() ) { is.read( (char*)(&idx), 1); if( is.eof() || !is.good() ) break; if( IncompleteLUT ) { assert( idx < Internal->Length[RED] ); assert( idx < Internal->Length[GREEN] ); assert( idx < Internal->Length[BLUE] ); } rgb[RED] = Internal->RGB[3*idx+RED]; rgb[GREEN] = Internal->RGB[3*idx+GREEN]; rgb[BLUE] = Internal->RGB[3*idx+BLUE]; os.write((char*)rgb, 3 ); } } else if ( BitSample == 16 ) { // gdcmData/NM-PAL-16-PixRep1.dcm const uint16_t *rgb16 = (uint16_t*)(void*)&Internal->RGB[0]; while( !is.eof() ) { unsigned short idx; unsigned short rgb[3]; is.read( (char*)(&idx), 2); if( is.eof() || !is.good() ) break; if( IncompleteLUT ) { assert( idx < Internal->Length[RED] ); assert( idx < Internal->Length[GREEN] ); assert( idx < Internal->Length[BLUE] ); } rgb[RED] = rgb16[3*idx+RED]; rgb[GREEN] = rgb16[3*idx+GREEN]; rgb[BLUE] = rgb16[3*idx+BLUE]; os.write((char*)rgb, 3*2); } } } bool LookupTable::Decode(char *output, size_t outlen, const char *input, size_t inlen ) const { bool success = false; if( outlen < 3 * inlen ) { gdcmDebugMacro( "Out buffer too small" ); return false; } if( !Initialized() ) { gdcmDebugMacro( "Not Initialized" ); return false; } if ( BitSample == 8 ) { const unsigned char * end = (const unsigned char*)input + inlen; unsigned char * rgb = (unsigned char*)output; for( const unsigned char * idx = (const unsigned char*)input; idx != end; ++idx ) { if( IncompleteLUT ) { assert( *idx < Internal->Length[RED] ); assert( *idx < Internal->Length[GREEN] ); assert( *idx < Internal->Length[BLUE] ); } rgb[RED] = Internal->RGB[3 * *idx+RED]; rgb[GREEN] = Internal->RGB[3 * *idx+GREEN]; rgb[BLUE] = Internal->RGB[3 * *idx+BLUE]; rgb += 3; } success = true; } else if ( BitSample == 16 ) { const uint16_t *rgb16 = (const uint16_t*)(void*)&Internal->RGB[0]; assert( inlen % 2 == 0 ); const uint16_t * end = (const uint16_t*)(const void*)(input + inlen); uint16_t * rgb = (uint16_t*)(void*)output; for( const uint16_t * idx = (const uint16_t*)(const void*)input; idx != end; ++idx ) { if( IncompleteLUT ) { assert( *idx < Internal->Length[RED] ); assert( *idx < Internal->Length[GREEN] ); assert( *idx < Internal->Length[BLUE] ); } rgb[RED] = rgb16[3 * *idx+RED]; rgb[GREEN] = rgb16[3 * *idx+GREEN]; rgb[BLUE] = rgb16[3 * *idx+BLUE]; rgb += 3; } success = true; } return success; } bool LookupTable::Decode8(char *output, size_t outlen, const char *input, size_t inlen ) const { bool success = false; if( outlen < 3 * inlen ) { gdcmDebugMacro( "Out buffer too small" ); return false; } if( !Initialized() ) { gdcmDebugMacro( "Not Initialized" ); return false; } if ( BitSample == 8 ) { const unsigned char * end = (const unsigned char*)input + inlen; unsigned char * rgb = (unsigned char*)output; for( const unsigned char * idx = (const unsigned char*)input; idx != end; ++idx ) { if( IncompleteLUT ) { assert( *idx < Internal->Length[RED] ); assert( *idx < Internal->Length[GREEN] ); assert( *idx < Internal->Length[BLUE] ); } rgb[RED] = Internal->RGB[3 * *idx+RED]; rgb[GREEN] = Internal->RGB[3 * *idx+GREEN]; rgb[BLUE] = Internal->RGB[3 * *idx+BLUE]; rgb += 3; } success = true; } else if ( BitSample == 16 ) { const uint16_t *rgb16 = (const uint16_t*)(void*)&Internal->RGB[0]; assert( inlen % 2 == 0 ); const uint16_t * end = (const uint16_t*)(const void*)(input + inlen); uint8_t * rgb = (uint8_t*)output; for( const uint16_t * idx = (const uint16_t*)(const void*)input; idx != end; ++idx ) { if( IncompleteLUT ) { assert( *idx < Internal->Length[RED] ); assert( *idx < Internal->Length[GREEN] ); assert( *idx < Internal->Length[BLUE] ); } rgb[RED] = rgb16[3 * *idx+RED] >> 8; rgb[GREEN] = rgb16[3 * *idx+GREEN] >> 8; rgb[BLUE] = rgb16[3 * *idx+BLUE] >> 8; rgb += 3; } success = true; } return success; } const unsigned char *LookupTable::GetPointer() const { if ( BitSample == 8 ) { return &Internal->RGB[0]; } return nullptr; } bool LookupTable::GetBufferAsRGBA(unsigned char *rgba) const { bool ret = false; if ( BitSample == 8 ) { std::vector::const_iterator it = Internal->RGB.begin(); for(; it != Internal->RGB.end() ;) { // RED *rgba++ = *it++; // GREEN *rgba++ = *it++; // BLUE *rgba++ = *it++; // ALPHA *rgba++ = 255; } ret = true; } else if ( BitSample == 16 ) { /* assert( Internal->Length[type]*(BitSample/8) == length ); uint16_t *uchar16 = (uint16_t*)&Internal->RGB[0]; const uint16_t *array16 = (uint16_t*)array; for( unsigned int i = 0; i < Internal->Length[type]; ++i) { assert( 2*i < length ); assert( 2*(3*i+type) < Internal->RGB.size() ); uchar16[3*i+type] = array16[i]; std::cout << i << " -> " << array16[i] << "\n"; } ret = true; */ //std::vector::const_iterator it = Internal->RGB.begin(); uint16_t *uchar16 = (uint16_t*)(void*)&Internal->RGB[0]; uint16_t *rgba16 = (uint16_t*)(void*)rgba; size_t s = Internal->RGB.size(); s /= 2; s /= 3; memset(rgba,0,Internal->RGB.size() * 4 / 3); // FIXME for(size_t i = 0; i < s; ++i) { // RED *rgba16++ = *uchar16++; // GREEN *rgba16++ = *uchar16++; // BLUE *rgba16++ = *uchar16++; // ALPHA *rgba16++ = 255*255; } ret = true; } return ret; } bool LookupTable::WriteBufferAsRGBA(const unsigned char *rgba) { bool ret = false; if ( BitSample == 8 ) { std::vector::iterator it = Internal->RGB.begin(); for(; it != Internal->RGB.end() ;) { // RED *it++ = *rgba++; // GREEN *it++ = *rgba++; // BLUE *it++ = *rgba++; // ALPHA rgba++; // = 255; } ret = true; } else if ( BitSample == 16 ) { //assert( Internal->Length[type]*(BitSample/8) == length ); uint16_t *uchar16 = (uint16_t*)(void*)&Internal->RGB[0]; const uint16_t *rgba16 = (const uint16_t*)(const void*)rgba; size_t s = Internal->RGB.size(); s /= 2; s /= 3; assert( s == 65536 ); for( unsigned int i = 0; i < s /*i < Internal->Length[type]*/; ++i) { //assert( 2*i < length ); //assert( 2*(3*i+type) < Internal->RGB.size() ); //uchar16[3*i+type] = array16[i]; //std::cout << i << " -> " << array16[i] << "\n"; // RED *uchar16++ = *rgba16++; // GREEN *uchar16++ = *rgba16++; // BLUE *uchar16++ = *rgba16++; // rgba16++; // = *rgba16++; } ret = true; //ret = false; } return ret; } void LookupTable::Print(std::ostream &os) const { if( BitSample == 16 ) { uint16_t maxlut[3] = { 0 , 0 , 0}; uint16_t minlut[3] = { 0xffff, 0xffff, 0xffff }; uint16_t *uchar16 = (uint16_t*)(void*)&Internal->RGB[0]; if( Internal->Length[BLUE] != Internal->Length[RED] || Internal->Length[RED] != Internal->Length[GREEN] ) return; for( unsigned int i = 0; i < Internal->Length[BLUE]; ++i) { os << std::dec <RGB.size() ); const uint16_t val = SwapperDoOp::Swap(uchar16[3*i+type]); minlut[type] = std::min( minlut[type], val ); maxlut[type] = std::max( maxlut[type], val ); os << std::hex << std::setw( 4 ) << std::setfill( '0' ) << val << ","; } os << std::endl; } os << "MINLUT: "; for(int type = RED; type <= BLUE; ++type ) os << std::hex << std::setw( 4 ) << std::setfill( '0' ) << minlut[type] << ","; os << std::endl; os << "MAXLUT: "; for(int type = RED; type <= BLUE; ++type ) os << std::hex << std::setw( 4 ) << std::setfill( '0' ) << maxlut[type] << ","; os << std::endl; } } bool LookupTable::IsRGB8() const { if( BitSample == 16 ) { uint16_t maxlut[3] = { 0 , 0 , 0}; uint16_t minlut[3] = { 0xffff, 0xffff, 0xffff }; uint16_t *uchar16 = (uint16_t*)(void*)&Internal->RGB[0]; 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) { for(int type = RED; type <= BLUE; ++type ) { assert( 2*(3*i+type) < Internal->RGB.size() ); const uint16_t val = SwapperDoOp::Swap(uchar16[3*i+type]); minlut[type] = std::min( minlut[type], val ); maxlut[type] = std::max( maxlut[type], val ); if( maxlut[type] > 0xff ) return false; } } } return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmLookupTable.h000066400000000000000000000070671412732066400237510ustar00rootroot00000000000000/*========================================================================= 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 GDCMLOOKUPTABLE_H #define GDCMLOOKUPTABLE_H #include "gdcmTypes.h" #include "gdcmObject.h" #include namespace gdcm { class LookupTableInternal; /** * \brief LookupTable class */ class GDCM_EXPORT LookupTable : public Object { public: typedef enum { RED = 0, // Keep RED == 0 GREEN, BLUE, GRAY, UNKNOWN } LookupTableType; LookupTable(); ~LookupTable() override; void Print(std::ostream &) const override; /// Allocate the LUT void Allocate( unsigned short bitsample = 8 ); /// Generic interface: //TODO: check to see if length should be unsigned short, unsigned int, or whatever void InitializeLUT(LookupTableType type, unsigned short length, unsigned short subscript, unsigned short bitsize); unsigned int GetLUTLength(LookupTableType type) const; virtual void SetLUT(LookupTableType type, const unsigned char *array, unsigned int length); void GetLUT(LookupTableType type, unsigned char *array, unsigned int &length) const; void GetLUTDescriptor(LookupTableType type, unsigned short &length, unsigned short &subscript, unsigned short &bitsize) const; /// RED / GREEN / BLUE specific: void InitializeRedLUT(unsigned short length, unsigned short subscript, unsigned short bitsize); void SetRedLUT(const unsigned char *red, unsigned int length); void InitializeGreenLUT(unsigned short length, unsigned short subscript, unsigned short bitsize); void SetGreenLUT(const unsigned char *green, unsigned int length); void InitializeBlueLUT(unsigned short length, unsigned short subscript, unsigned short bitsize); void SetBlueLUT(const unsigned char *blue, unsigned int length); /// Clear the LUT void Clear(); /// Decode the LUT void Decode(std::istream &is, std::ostream &os) const; /// Decode the LUT /// outputbuffer will contains the RGB decoded PALETTE COLOR input image of size inlen /// the outputbuffer should be at least 3 times the size of inlen bool Decode(char *outputbuffer, size_t outlen, const char *inputbuffer, size_t inlen) const; /// Return whether 16 bits LUT is in RGB 8 bits space bool IsRGB8() const; /// Decode into RGB 8 bits space bool Decode8(char *outputbuffer, size_t outlen, const char *inputbuffer, size_t inlen) const; LookupTable(LookupTable const &lut):Object(lut) { assert(0); } /// return the LUT as RGBA buffer bool GetBufferAsRGBA(unsigned char *rgba) const; /// return a raw pointer to the LUT const unsigned char *GetPointer() const; /// Write the LUT as RGBA bool WriteBufferAsRGBA(const unsigned char *rgba); /// return the bit sample unsigned short GetBitSample() const { return BitSample; } /// return whether the LUT has been initialized bool Initialized() const; private: /// Unfinished work void Encode(std::istream &is, std::ostream &os); protected: LookupTableInternal *Internal; unsigned short BitSample; // refer to the pixel type (not the bit size of LUT) bool IncompleteLUT:1; }; } // end namespace gdcm #endif //GDCMLOOKUPTABLE_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmMeshPrimitive.cxx000066400000000000000000000065531412732066400246670ustar00rootroot00000000000000/*========================================================================= 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 "gdcmMeshPrimitive.h" #include "gdcmCodeString.h" #include namespace gdcm { static const char * MPStrings[] = { "VERTEX", "EDGE", "TRIANGLE", "TRIANGLESTRIP", "TRIANGLEFAN", "LINE", "FACET", nullptr }; const char * MeshPrimitive::GetMPTypeString(const MPType type) { assert( type <= MPType_END ); return MPStrings[(int)type]; } MeshPrimitive::MPType MeshPrimitive::GetMPType(const char * type) { if(!type) return MPType_END; // Delete possible space as last character String<> str( type ); str.Trim(); std::string typeClearStr = str.Trim(); const char * typeClear = typeClearStr.c_str(); for(unsigned int i = 0; MPStrings[i] != nullptr; ++i) { if( strcmp(typeClear, MPStrings[i]) == 0 ) { return (MPType)i; } } // Ouch ! We did not find anything, that's pretty bad, let's hope that // the toolkit which wrote the image is buggy and tolerate space padded binary // string CodeString codestring = typeClear; std::string cs = codestring.GetAsString(); for(unsigned int i = 0; MPStrings[i] != nullptr; ++i) { if( strcmp(cs.c_str(), MPStrings[i]) == 0 ) { return (MPType)i; } } return MPType_END; } MeshPrimitive::MeshPrimitive(): PrimitiveType(MPType_END), PrimitiveData(1, DataElement()) { } MeshPrimitive::~MeshPrimitive() = default; MeshPrimitive::MPType MeshPrimitive::GetPrimitiveType() const { return PrimitiveType; } void MeshPrimitive::SetPrimitiveType(const MPType type) { assert( type <= MPType_END ); PrimitiveType = type; } const DataElement & MeshPrimitive::GetPrimitiveData() const { return PrimitiveData.front(); } DataElement & MeshPrimitive::GetPrimitiveData() { return PrimitiveData.front(); } void MeshPrimitive::SetPrimitiveData(DataElement const & de) { PrimitiveData.insert(PrimitiveData.begin(), de); } const MeshPrimitive::PrimitivesData & MeshPrimitive::GetPrimitivesData() const { return PrimitiveData; } MeshPrimitive::PrimitivesData & MeshPrimitive::GetPrimitivesData() { return PrimitiveData; } void MeshPrimitive::SetPrimitivesData(PrimitivesData const & DEs) { PrimitiveData = DEs; } void MeshPrimitive::SetPrimitiveData(const unsigned int idx, DataElement const & de) { PrimitiveData.insert(PrimitiveData.begin() + idx, de); } void MeshPrimitive::AddPrimitiveData(DataElement const & de) { PrimitiveData.push_back(de); } const DataElement & MeshPrimitive::GetPrimitiveData(const unsigned int idx) const { assert( idx < this->GetNumberOfPrimitivesData() ); return PrimitiveData[idx]; } DataElement & MeshPrimitive::GetPrimitiveData(const unsigned int idx) { assert( idx < this->GetNumberOfPrimitivesData() ); return PrimitiveData[idx]; } unsigned int MeshPrimitive::GetNumberOfPrimitivesData() const { return (unsigned int)PrimitiveData.size(); } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmMeshPrimitive.h000066400000000000000000000045351412732066400243120ustar00rootroot00000000000000/*========================================================================= 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 GDCMMESHPRIMITIVE_H #define GDCMMESHPRIMITIVE_H #include #include namespace gdcm { /** * \brief This class defines surface mesh primitives. * \details It is designed from surface mesh primitives macro. * * \see PS 3.3 C.27.4 */ class GDCM_EXPORT MeshPrimitive : public Object { public: typedef std::vector< DataElement > PrimitivesData; /** * \brief This enumeration defines primitive types. * * \see PS 3.3 C.27.4.1 */ typedef enum { VERTEX = 0, EDGE, TRIANGLE, TRIANGLE_STRIP, TRIANGLE_FAN, LINE, FACET, MPType_END } MPType; static const char * GetMPTypeString(const MPType type); static MPType GetMPType(const char * type); MeshPrimitive(); ~MeshPrimitive() override; MPType GetPrimitiveType() const; void SetPrimitiveType(const MPType type); const DataElement & GetPrimitiveData() const; DataElement & GetPrimitiveData(); void SetPrimitiveData(DataElement const & de); const PrimitivesData & GetPrimitivesData() const; PrimitivesData & GetPrimitivesData(); void SetPrimitivesData(PrimitivesData const & DEs); const DataElement & GetPrimitiveData(const unsigned int idx) const; DataElement & GetPrimitiveData(const unsigned int idx); void SetPrimitiveData(const unsigned int idx, DataElement const & de); void AddPrimitiveData(DataElement const & de); unsigned int GetNumberOfPrimitivesData() const; protected: // Use to define tag where PrimitiveData will be put. MPType PrimitiveType; // PrimitiveData contains point index list. // It shall have 1 or 1-n DataElement following PrimitiveType. PrimitivesData PrimitiveData; }; } #endif // GDCMMESHPRIMITIVE_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmOrientation.cxx000066400000000000000000000073361412732066400243750ustar00rootroot00000000000000/*========================================================================= 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 "gdcmOrientation.h" #include namespace gdcm { Orientation::Orientation() = default; Orientation::~Orientation() = default; void Orientation::Print(std::ostream &os) const { os << "ObliquityThresholdCosineValue: " << ObliquityThresholdCosineValue; } static const char *OrientationStrings[] = { "UNKNOWN", "AXIAL", "CORONAL", "SAGITTAL", "OBLIQUE", nullptr }; // http://public.kitware.com/pipermail/insight-users/2005-March/012246.html // 0.5477 would be the square root of 1 (unit vector sum of squares) divided by 3 (oblique axes - a "double" oblique) // 0.7071 would be the square root of 1 (unit vector sum of squares) divided by 2 (oblique axes) double Orientation::ObliquityThresholdCosineValue = 0.8; //const double Orientation::obliquityThresholdCosineValue = 0.7071; char Orientation::GetMajorAxisFromPatientRelativeDirectionCosine(double x, double y, double z) { char axis = 0; const char orientationX = x < 0 ? 'R' : 'L'; const char orientationY = y < 0 ? 'A' : 'P'; const char orientationZ = z < 0 ? 'F' : 'H'; const double absX = std::fabs(x); const double absY = std::fabs(y); const double absZ = std::fabs(z); // The tests here really don't need to check the other dimensions, // just the threshold, since the sum of the squares should be == 1.0 // but just in case ... if (absX>ObliquityThresholdCosineValue && absX>absY && absX>absZ) { axis = orientationX; } else if (absY>ObliquityThresholdCosineValue && absY>absX && absY>absZ) { axis = orientationY; } else if (absZ>ObliquityThresholdCosineValue && absZ>absX && absZ>absY) { axis = orientationZ; } else { // nothing } return axis; } void Orientation::SetObliquityThresholdCosineValue(double val) { Orientation::ObliquityThresholdCosineValue = val; } double Orientation::GetObliquityThresholdCosineValue() { return Orientation::ObliquityThresholdCosineValue; } Orientation::OrientationType Orientation::GetType(const double dircos[6]) { OrientationType type = Orientation::UNKNOWN; if( dircos ) { char rowAxis = GetMajorAxisFromPatientRelativeDirectionCosine(dircos[0],dircos[1],dircos[2]); char colAxis = GetMajorAxisFromPatientRelativeDirectionCosine(dircos[3],dircos[4],dircos[5]); if (rowAxis != 0 && colAxis != 0 ) { if ((rowAxis == 'R' || rowAxis == 'L') && (colAxis == 'A' || colAxis == 'P')) type = Orientation::AXIAL; else if ((colAxis == 'R' || colAxis == 'L') && (rowAxis == 'A' || rowAxis == 'P')) type = Orientation::AXIAL; else if ((rowAxis == 'R' || rowAxis == 'L') && (colAxis == 'H' || colAxis == 'F')) type = Orientation::CORONAL; else if ((colAxis == 'R' || colAxis == 'L') && (rowAxis == 'H' || rowAxis == 'F')) type = Orientation::CORONAL; else if ((rowAxis == 'A' || rowAxis == 'P') && (colAxis == 'H' || colAxis == 'F')) type = Orientation::SAGITTAL; else if ((colAxis == 'A' || colAxis == 'P') && (rowAxis == 'H' || rowAxis == 'F')) type = Orientation::SAGITTAL; } else { type = Orientation::OBLIQUE; } } return type; } const char *Orientation::GetLabel(OrientationType type) { return OrientationStrings[type]; } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmOrientation.h000066400000000000000000000034311412732066400240120ustar00rootroot00000000000000/*========================================================================= 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 GDCMORIENTATION_H #define GDCMORIENTATION_H #include "gdcmTypes.h" namespace gdcm { /** * \brief class to handle Orientation */ class GDCM_EXPORT Orientation { friend std::ostream& operator<<(std::ostream &_os, const Orientation &o); public: Orientation(); ~Orientation(); /// Print void Print(std::ostream &) const; typedef enum { UNKNOWN, AXIAL, CORONAL, SAGITTAL, OBLIQUE } OrientationType; /// Return the type of orientation from a direction cosines /// Input is an array of 6 double static OrientationType GetType(const double dircos[6]); /// ObliquityThresholdCosineValue stuff static void SetObliquityThresholdCosineValue(double val); static double GetObliquityThresholdCosineValue(); /// Return the label of an Orientation static const char *GetLabel(OrientationType type); protected: static char GetMajorAxisFromPatientRelativeDirectionCosine(double x, double y, double z); private: static double ObliquityThresholdCosineValue; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const Orientation &o) { o.Print( os ); return os; } } // end namespace gdcm #endif //GDCMORIENTATION_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmOverlay.cxx000066400000000000000000000450571412732066400235250ustar00rootroot00000000000000/*========================================================================= 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 "gdcmOverlay.h" #include "gdcmTag.h" #include "gdcmDataElement.h" #include "gdcmDataSet.h" #include "gdcmAttribute.h" #include namespace gdcm { class OverlayInternal { public: OverlayInternal(): Description(), Type(), Data() { Origin[0] = Origin[1] = 0; } /* (6000,0010) US 484 # 2, 1 OverlayRows (6000,0011) US 484 # 2, 1 OverlayColumns (6000,0015) IS [1] # 2, 1 NumberOfFramesInOverlay (6000,0022) LO [Siemens MedCom Object Graphics] # 30, 1 OverlayDescription (6000,0040) CS [G] # 2, 1 OverlayType (6000,0050) SS 1\1 # 4, 2 OverlayOrigin (6000,0051) US 1 # 2, 1 ImageFrameOrigin (6000,0100) US 1 # 2, 1 OverlayBitsAllocated (6000,0102) US 0 # 2, 1 OverlayBitPosition (6000,3000) OW 0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000... # 29282, 1 OverlayData */ bool InPixelData{false}; // Identifier need to be in the [6000,60FF] range (no odd number): unsigned short Group{0}; // Descriptor: unsigned short Rows{0}; // (6000,0010) US 484 # 2, 1 OverlayRows unsigned short Columns{0}; // (6000,0011) US 484 # 2, 1 OverlayColumns unsigned int NumberOfFrames{0}; // (6000,0015) IS [1] # 2, 1 NumberOfFramesInOverlay std::string Description; // (6000,0022) LO [Siemens MedCom Object Graphics] # 30, 1 OverlayDescription std::string Type; // (6000,0040) CS [G] # 2, 1 OverlayType signed short Origin[2]; // (6000,0050) SS 1\1 # 4, 2 OverlayOrigin unsigned short FrameOrigin{0}; // (6000,0051) US 1 # 2, 1 ImageFrameOrigin unsigned short BitsAllocated{0}; // (6000,0100) US 1 # 2, 1 OverlayBitsAllocated unsigned short BitPosition{0}; // (6000,0102) US 0 # 2, 1 OverlayBitPosition //std::vector Data; std::vector Data; // hold the Overlay data, but not the trailing DICOM padding (\0) void Print(std::ostream &os) const { os << "Group 0x" << std::hex << Group << std::dec << std::endl; os << "Rows " << Rows << std::endl; os << "Columns " << Columns << std::endl; os << "NumberOfFrames " << NumberOfFrames << std::endl; os << "Description " << Description << std::endl; os << "Type " << Type << std::endl; os << "Origin[2] " << Origin[0] << "," << Origin[1] << std::endl; os << "FrameOrigin " << FrameOrigin << std::endl; os << "BitsAllocated " << BitsAllocated << std::endl; os << "BitPosition " << BitPosition << std::endl; //std::vector Data; } }; Overlay::Overlay() { Internal = new OverlayInternal; } Overlay::~Overlay() { delete Internal; } Overlay::Overlay(Overlay const &ov):Object(ov) { //delete Internal; Internal = new OverlayInternal; // TODO: copy OverlayInternal into other... *Internal = *ov.Internal; } Overlay & Overlay::operator=(Overlay const &ov) { assert( Internal ); *Internal = *ov.Internal; return *this; } void Overlay::Update(const DataElement & de) { /* 8.1.2 Overlay data encoding of related data elements Encoded Overlay Planes always have a bit depth of 1, and are encoded separately from the Pixel Data in Overlay Data (60xx,3000). The following two Data Elements shall define the Overlay Plane structure: - Overlay Bits Allocated (60xx,0100) - Overlay Bit Position (60xx,0102) Notes: 1. There is no Data Element analogous to Bits Stored (0028,0101) since Overlay Planes always have a bit depth of 1. 2. Restrictions on the allowed values for these Data Elements are defined in PS 3.3. Formerly overlay data stored in unused bits of Pixel Data (7FE0,0010) was described, and these attributes had meaningful values but this usage has been retired. See PS 3.5 2004. For overlays encoded in Overlay Data Element (60xx,3000), Overlay Bits Allocated (60xx,0100) is always 1 and Overlay Bit Position (60xx,0102) is always 0. */ assert( de.GetTag().IsPublic() ); const ByteValue* bv = de.GetByteValue(); if( !bv ) return; // Discard any empty element (will default to another value) assert( bv->GetPointer() && bv->GetLength() ); std::string s( bv->GetPointer(), bv->GetLength() ); // What if a \0 can be found before the end of string... //assert( strlen( s.c_str() ) == s.size() ); // First thing check consistency: if( !GetGroup() ) { SetGroup( de.GetTag().GetGroup() ); } else // check consistency { assert( GetGroup() == de.GetTag().GetGroup() ); // programmer error } //std::cerr << "Tag: " << de.GetTag() << std::endl; if( de.GetTag().GetElement() == 0x0000 ) // OverlayGroupLength { // ?? } else if( de.GetTag().GetElement() == 0x0010 ) // OverlayRows { Attribute<0x6000,0x0010> at; at.SetFromDataElement( de ); SetRows( at.GetValue() ); } else if( de.GetTag().GetElement() == 0x0011 ) // OverlayColumns { Attribute<0x6000,0x0011> at; at.SetFromDataElement( de ); SetColumns( at.GetValue() ); } else if( de.GetTag().GetElement() == 0x0015 ) // NumberOfFramesInOverlay { Attribute<0x6000,0x0015> at; at.SetFromDataElement( de ); SetNumberOfFrames( at.GetValue() ); } else if( de.GetTag().GetElement() == 0x0022 ) // OverlayDescription { SetDescription( s.c_str() ); } else if( de.GetTag().GetElement() == 0x0040 ) // OverlayType { SetType( s.c_str() ); } else if( de.GetTag().GetElement() == 0x0045 ) // OverlaySubtype { gdcmWarningMacro( "FIXME" ); } else if( de.GetTag().GetElement() == 0x0050 ) // OverlayOrigin { Attribute<0x6000,0x0050> at; at.SetFromDataElement( de ); SetOrigin( at.GetValues() ); } else if( de.GetTag().GetElement() == 0x0051 ) // ImageFrameOrigin { Attribute<0x6000,0x0051> at; at.SetFromDataElement( de ); SetFrameOrigin( at.GetValue() ); } else if( de.GetTag().GetElement() == 0x0060 ) // OverlayCompressionCode (RET) { assert( s == "NONE" ); // FIXME ?? } else if( de.GetTag().GetElement() == 0x0100 ) // OverlayBitsAllocated { Attribute<0x6000,0x0100> at; at.SetFromDataElement( de ); // if OverlayBitsAllocated is 1 it imply OverlayData element // if OverlayBitsAllocated is 16 it imply Overlay in unused pixel bits if( at.GetValue() != 1 ) { gdcmDebugMacro( "Unsupported OverlayBitsAllocated: " << at.GetValue() ); } SetBitsAllocated( at.GetValue() ); } else if( de.GetTag().GetElement() == 0x0102 ) // OverlayBitPosition { Attribute<0x6000,0x0102> at; at.SetFromDataElement( de ); if( at.GetValue() != 0 ) // For old ACR when using unused bits... { gdcmDebugMacro( "Unsupported OverlayBitPosition: " << at.GetValue() ); } SetBitPosition( at.GetValue() ); } else if( de.GetTag().GetElement() == 0x0110 ) // OverlayFormat (RET) { assert( s == "RECT" ); } else if( de.GetTag().GetElement() == 0x0200 ) // OverlayLocation (RET) { Attribute<0x6000,0x0200> at; at.SetFromDataElement( de ); gdcmWarningMacro( "FIXME: " << at.GetValue() ); } else if( de.GetTag().GetElement() == 0x1301 ) // ROIArea { gdcmWarningMacro( "FIXME" ); } else if( de.GetTag().GetElement() == 0x1302 ) // ROIMean { gdcmWarningMacro( "FIXME" ); } else if( de.GetTag().GetElement() == 0x1303 ) // ROIStandardDeviation { gdcmWarningMacro( "FIXME" ); } else if( de.GetTag().GetElement() == 0x1500 ) // OverlayLabel { gdcmWarningMacro( "FIXME" ); } else if( de.GetTag().GetElement() == 0x3000 ) // OverlayData { SetOverlay(bv->GetPointer(), bv->GetLength()); } else { gdcmErrorMacro( "Tag is not supported: " << de.GetTag() << std::endl ); assert(0); } } bool Overlay::GrabOverlayFromPixelData(DataSet const &ds) { const unsigned int ovlength = Internal->Rows * Internal->Columns / 8; Internal->Data.resize( ovlength ); // set to 0 if( Internal->BitsAllocated == 8 ) { if( !ds.FindDataElement( Tag(0x7fe0,0x0010) ) ) { gdcmWarningMacro("Could not find Pixel Data. Cannot extract Overlay." ); return false; } const DataElement &pixeldata = ds.GetDataElement( Tag(0x7fe0,0x0010) ); const ByteValue *bv = pixeldata.GetByteValue(); if( !bv ) { gdcmWarningMacro("Could not extract overlay from encapsulated stream." ); return false; } const char *array = bv->GetPointer(); const unsigned int length = ovlength * 8 * 1; //bv->GetLength(); const uint8_t *p = (const uint8_t*)(const void*)array; const uint8_t *end = (const uint8_t*)(const void*)(array + length); assert( 8 * ovlength == (unsigned int)Internal->Rows * Internal->Columns ); if( Internal->Data.empty() ) { gdcmWarningMacro("Internal Data is empty." ); return false; } unsigned char * overlay = (unsigned char*)&Internal->Data[0]; int c = 0; uint8_t pmask = (uint8_t)(1 << Internal->BitPosition); assert( length / 1 == ovlength * 8 ); while( p != end ) { const uint8_t val = *p & pmask; assert( val == 0x0 || val == pmask ); // 128 -> 0x80 if( val ) { overlay[ c / 8 ] |= (unsigned char)(0x1 << c%8); } else { // else overlay[ c / 8 ] is already 0 } ++p; ++c; } assert( (unsigned)c / 8 == ovlength ); } else if( Internal->BitsAllocated == 16 ) { //assert( Internal->BitPosition >= 12 ); if( !ds.FindDataElement( Tag(0x7fe0,0x0010) ) ) { gdcmWarningMacro("Could not find Pixel Data. Cannot extract Overlay." ); return false; } const DataElement &pixeldata = ds.GetDataElement( Tag(0x7fe0,0x0010) ); const ByteValue *bv = pixeldata.GetByteValue(); if( !bv ) { // XA_GE_JPEG_02_with_Overlays.dcm gdcmWarningMacro("Could not extract overlay from encapsulated stream." ); return false; } assert( bv ); const char *array = bv->GetPointer(); // SIEMENS_GBS_III-16-ACR_NEMA_1.acr is pain to support, // I cannot simply use the bv->GetLength I have to use the image dim: const unsigned int length = ovlength * 8 * 2; //bv->GetLength(); const uint16_t *p = (const uint16_t*)(const void*)array; const uint16_t *end = (const uint16_t*)(const void*)(array + length); //const unsigned int ovlength = length / (8*2); assert( 8 * ovlength == (unsigned int)Internal->Rows * Internal->Columns ); if( Internal->Data.empty() ) { gdcmWarningMacro("Internal Data is empty." ); return false; } unsigned char * overlay = (unsigned char*)&Internal->Data[0]; int c = 0; uint16_t pmask = (uint16_t)(1 << Internal->BitPosition); assert( length / 2 == ovlength * 8 ); while( p != end ) { const uint16_t val = *p & pmask; assert( val == 0x0 || val == pmask ); // 128 -> 0x80 if( val ) { overlay[ c / 8 ] |= (unsigned char)(0x1 << c%8); } else { // else overlay[ c / 8 ] is already 0 } ++p; ++c; } assert( (unsigned)c / 8 == ovlength ); } else { gdcmErrorMacro( "Could not grab Overlay from image. Please report." ); return false; } return true; } void Overlay::SetGroup(unsigned short group) { Internal->Group = group; } unsigned short Overlay::GetGroup() const { return Internal->Group; } void Overlay::SetRows(unsigned short rows) { Internal->Rows = rows; } unsigned short Overlay::GetRows() const { return Internal->Rows; } void Overlay::SetColumns(unsigned short columns) { Internal->Columns = columns; } unsigned short Overlay::GetColumns() const { return Internal->Columns; } void Overlay::SetNumberOfFrames(unsigned int numberofframes) { Internal->NumberOfFrames = numberofframes; } void Overlay::SetDescription(const char* description) { if( description ) Internal->Description = description; } const char *Overlay::GetDescription() const { return Internal->Description.c_str(); } void Overlay::SetType(const char* type) { if( type ) Internal->Type = type; } const char *Overlay::GetType() const { return Internal->Type.c_str(); } static const char *OverlayTypeStrings[] = { "INVALID", "G ", "R ", }; const char *Overlay::GetOverlayTypeAsString(OverlayType ot) { return OverlayTypeStrings[ (int) ot ]; } Overlay::OverlayType Overlay::GetOverlayTypeFromString(const char *s) { static const int n = sizeof( OverlayTypeStrings ) / sizeof ( *OverlayTypeStrings ); if( s ) { for( int i = 0; i < n; ++i ) { if( strcmp(s, OverlayTypeStrings[i] ) == 0 ) { return (OverlayType)i; } } } // could not find the proper type, maybe padded with \0 ? if( s && strlen(s) == 1 ) { for( int i = 0; i < n; ++i ) { if( strncmp(s, OverlayTypeStrings[i], 1 ) == 0 ) { gdcmDebugMacro( "Invalid Padding for OVerlay Type" ); return (OverlayType)i; } } } return Overlay::Invalid; } Overlay::OverlayType Overlay::GetTypeAsEnum() const { return GetOverlayTypeFromString( GetType() ); } void Overlay::SetOrigin(const signed short origin[2]) { if( origin ) { Internal->Origin[0] = origin[0]; Internal->Origin[1] = origin[1]; } } const signed short * Overlay::GetOrigin() const { return &Internal->Origin[0]; } void Overlay::SetFrameOrigin(unsigned short frameorigin) { Internal->FrameOrigin = frameorigin; } void Overlay::SetBitsAllocated(unsigned short bitsallocated) { Internal->BitsAllocated = bitsallocated; } unsigned short Overlay::GetBitsAllocated() const { return Internal->BitsAllocated; } void Overlay::SetBitPosition(unsigned short bitposition) { Internal->BitPosition = bitposition; } unsigned short Overlay::GetBitPosition() const { return Internal->BitPosition; } bool Overlay::IsEmpty() const { return Internal->Data.empty(); } bool Overlay::IsZero() const { if( IsEmpty() ) return false; std::vector::const_iterator it = Internal->Data.begin(); for(; it != Internal->Data.end(); ++it ) { if( *it ) return true; } return false; } bool Overlay::IsInPixelData() const { return Internal->InPixelData; } void Overlay::IsInPixelData(bool b) { Internal->InPixelData = b; } /* * row,col = 400,400 => 20000 * row,col = 1665,1453 => 302406 * row,col = 20,198 => 495 words + 1 dicom \0 padding */ inline unsigned int compute_bit_and_dicom_padding(unsigned short rows, unsigned short columns) { unsigned int word_padding = ( rows * columns + 7 ) / 8; // need to send full word (8bits at a time) return word_padding + word_padding%2; // Cannot have odd length } void Overlay::SetOverlay(const char *array, size_t length) { if( !array || !length ) return; const size_t computed_length = (Internal->Rows * Internal->Columns + 7) / 8; Internal->Data.resize( computed_length ); // filled with 0 if length < computed_length if( length < computed_length ) { gdcmWarningMacro( "Not enough data found in Overlay. Proceed with caution" ); std::copy(array, array+length, Internal->Data.begin()); } else { // do not try to copy more than allocated: // technically we may be missing the trailing DICOM padding (\0), but we have all the data needed anyway: std::copy(array, array+computed_length, Internal->Data.begin()); } /* warning need to take into account padding to the next word (8bits) */ //assert( length == compute_bit_and_dicom_padding(Internal->Rows, Internal->Columns) ); assert( Internal->Data.size() == computed_length ); } const ByteValue &Overlay::GetOverlayData() const { static ByteValue bv; bv = ByteValue( Internal->Data ); return bv; } size_t Overlay::GetUnpackBufferLength() const { const size_t unpacklen = Internal->Rows * Internal->Columns; return unpacklen; } bool Overlay::GetUnpackBuffer(char *buffer, size_t len) const { const size_t unpacklen = GetUnpackBufferLength(); if( len < unpacklen ) return false; unsigned char *unpackedbytes = (unsigned char*)buffer; const unsigned char *begin = unpackedbytes; for( std::vector::const_iterator it = Internal->Data.begin(); it != Internal->Data.end(); ++it ) { assert( unpackedbytes <= begin + len ); // We never store more than actually required // const unsigned char &packedbytes = *it; // weird bug with gcc 3.3 (prerelease on SuSE) apparently: unsigned char packedbytes = static_cast(*it); unsigned char mask = 1; for (unsigned int i = 0; i < 8 && unpackedbytes < begin + len; ++i) { if ( (packedbytes & mask) == 0) { *unpackedbytes = 0; } else { *unpackedbytes = 255; } ++unpackedbytes; mask <<= 1; } } assert(unpackedbytes <= begin + len); return true; } void Overlay::Decompress(std::ostream &os) const { const size_t unpacklen = GetUnpackBufferLength(); unsigned char unpackedbytes[8]; //std::vector::const_iterator beg = Internal->Data.begin(); size_t curlen = 0; for( std::vector::const_iterator it = Internal->Data.begin(); it != Internal->Data.end(); ++it ) { unsigned char packedbytes = *it; unsigned char mask = 1; unsigned int i = 0; for (; i < 8 && curlen < unpacklen; ++i) { if ( (packedbytes & mask) == 0) { unpackedbytes[i] = 0; } else { unpackedbytes[i] = 255; } mask <<= 1; ++curlen; } os.write(reinterpret_cast(unpackedbytes), i); } } void Overlay::Print(std::ostream &os) const { Internal->Print( os ); } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmOverlay.h000066400000000000000000000073561412732066400231520ustar00rootroot00000000000000/*========================================================================= 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 GDCMOVERLAY_H #define GDCMOVERLAY_H #include "gdcmTypes.h" #include "gdcmObject.h" namespace gdcm { class OverlayInternal; class ByteValue; class DataSet; class DataElement; /** * \brief Overlay class * \note * see AreOverlaysInPixelData * * \todo * Is there actually any way to recognize an overlay ? On images with multiple overlay I do not see * any way to differentiate them (other than the group tag). * * Example: */ class GDCM_EXPORT Overlay : public Object { public: Overlay(); ~Overlay() override; /// Print void Print(std::ostream &) const override; /// Update overlay from data element de: void Update(const DataElement & de); /// Set Group number void SetGroup(unsigned short group); /// Get Group number unsigned short GetGroup() const; /// set rows void SetRows(unsigned short rows); /// get rows unsigned short GetRows() const; /// set columns void SetColumns(unsigned short columns); /// get columns unsigned short GetColumns() const; /// set number of frames void SetNumberOfFrames(unsigned int numberofframes); /// set description void SetDescription(const char* description); /// get description const char *GetDescription() const; typedef enum { Invalid = 0, Graphics = 1, ROI = 2 } OverlayType; /// set type void SetType(const char* type); /// get type const char *GetType() const; OverlayType GetTypeAsEnum() const; static const char *GetOverlayTypeAsString(OverlayType ot); static OverlayType GetOverlayTypeFromString(const char *); /// set origin void SetOrigin(const signed short origin[2]); /// get origin const signed short * GetOrigin() const; /// set frame origin void SetFrameOrigin(unsigned short frameorigin); /// set bits allocated void SetBitsAllocated(unsigned short bitsallocated); /// return bits allocated unsigned short GetBitsAllocated() const; /// set bit position void SetBitPosition(unsigned short bitposition); /// return bit position unsigned short GetBitPosition() const; /// set overlay from byte array + length void SetOverlay(const char *array, size_t length); /// bool GrabOverlayFromPixelData(DataSet const &ds); /// Return the Overlay Data as ByteValue: /// Not thread safe const ByteValue &GetOverlayData() const; /// Return whether or not the Overlay is empty: bool IsEmpty() const; /// return true if all bits are set to 0 bool IsZero() const; /// return if the Overlay is stored in the pixel data or not bool IsInPixelData() const; /// Set whether or no the OverlayData is in the Pixel Data: void IsInPixelData(bool b); /// Decode the internal OverlayData (packed bits) into unpacked representation void Decompress(std::ostream &os) const; /// Retrieve the size of the buffer needed to hold the Overlay /// as specified by Col & Row parameters size_t GetUnpackBufferLength() const; /// Retrieve the unpack buffer for Overlay. This is an error if /// the size if below GetUnpackBufferLength() bool GetUnpackBuffer(char *buffer, size_t len) const; Overlay(Overlay const &ov); Overlay &operator=(Overlay const &ov); private: OverlayInternal *Internal; }; } // end namespace gdcm #endif //GDCMOVERLAY_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPDFCodec.cxx000066400000000000000000000014401412732066400234370ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPDFCodec.h" #include "gdcmDataElement.h" namespace gdcm { PDFCodec::PDFCodec() = default; PDFCodec::~PDFCodec() = default; bool PDFCodec::Decode(DataElement const &is, DataElement &os) { os = is; return true; } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPDFCodec.h000066400000000000000000000020171412732066400230650ustar00rootroot00000000000000/*========================================================================= 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 GDCMPDFCODEC_H #define GDCMPDFCODEC_H #include "gdcmCodec.h" namespace gdcm { /** * \brief PDFCodec class */ class GDCM_EXPORT PDFCodec : public Codec { public: PDFCodec(); ~PDFCodec() override; bool CanCode(TransferSyntax const &) const override { return false; } bool CanDecode(TransferSyntax const &) const override { return false; } bool Decode(DataElement const &is, DataElement &os) override; }; } // end namespace gdcm #endif //GDCMPDFCODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPGXCodec.cxx000066400000000000000000000053401412732066400234670ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPGXCodec.h" #include "gdcmTransferSyntax.h" #include "gdcmSystem.h" #include "gdcmDataElement.h" #include "gdcmSequenceOfFragments.h" #include "gdcmSwapper.h" #include "gdcmFilenameGenerator.h" namespace gdcm { PGXCodec::PGXCodec() = default; PGXCodec::~PGXCodec() = default; bool PGXCodec::CanDecode(TransferSyntax const &) const { return false; } bool PGXCodec::CanCode(TransferSyntax const &) const { return false; } bool PGXCodec::Write(const char *filename, const DataElement &out) const { if( !filename ) return false; //const PhotometricInterpretation &pi = this->GetPhotometricInterpretation(); std::vector filenames; const PixelFormat& pf = GetPixelFormat(); unsigned short nsamples = pf.GetSamplesPerPixel(); FilenameGenerator fg; std::string base = filename; std::string::size_type dot_pos = base.size() - 4; std::string prefix = base.substr(0, dot_pos ); fg.SetPrefix( prefix.c_str() ); fg.SetPattern( "_%d.pgx" ); size_t zdim = Dimensions[2]; size_t num_images = zdim * nsamples; fg.SetNumberOfFilenames(num_images); if( !fg.Generate() ) return false; const ByteValue *bv = out.GetByteValue(); if(!bv) { gdcmErrorMacro( "PGX Codec does not handle compress syntax." "You need to decompress first." ); return false; } const unsigned int *dims = this->GetDimensions(); size_t image_size = dims[0] * dims[1]; const char *img_buffer = bv->GetPointer(); for( unsigned int i = 0; i < num_images; ++i, img_buffer += image_size ) { const char *targetname = fg.GetFilename( i ); std::ofstream os( targetname, std::ios::binary ); os << "PG ML "; os << (pf.GetPixelRepresentation() ? "-" : "+"); os << " "; os << pf.GetBitsStored(); os << " "; os << dims[0] << " " << dims[1] << "\n"; os.write( img_buffer, image_size ); os.close(); } return true; } bool PGXCodec::Read(const char *filename, DataElement &out) const { (void)filename; (void)out; return false; } bool PGXCodec::GetHeaderInfo(std::istream &is, TransferSyntax &ts) { (void)is; (void)ts; return false; } ImageCodec * PGXCodec::Clone() const { return nullptr; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPGXCodec.h000066400000000000000000000023751412732066400231210ustar00rootroot00000000000000/*========================================================================= 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 GDCMPGXCODEC_H #define GDCMPGXCODEC_H #include "gdcmImageCodec.h" namespace gdcm { /** * \brief Class to do PGX * \details See PGX as used in JPEG 2000 implementation and reference images */ class GDCM_EXPORT PGXCodec : public ImageCodec { public: PGXCodec(); ~PGXCodec() override; bool CanDecode(TransferSyntax const &ts) const override; bool CanCode(TransferSyntax const &ts) const override; bool GetHeaderInfo(std::istream &is, TransferSyntax &ts) override; ImageCodec * Clone() const override; bool Read(const char *filename, DataElement &out) const; bool Write(const char *filename, const DataElement &out) const; private: }; } // end namespace gdcm #endif //GDCMPGXCODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPNMCodec.cxx000066400000000000000000000221701412732066400234630ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPNMCodec.h" #include "gdcmTransferSyntax.h" #include "gdcmSystem.h" #include "gdcmDataElement.h" #include "gdcmSequenceOfFragments.h" #include "gdcmSwapper.h" namespace gdcm { PNMCodec::PNMCodec():BufferLength(0) { } PNMCodec::~PNMCodec() = default; bool PNMCodec::CanDecode(TransferSyntax const &) const { return false; } bool PNMCodec::CanCode(TransferSyntax const &) const { return false; } static uint8_t reverseBitsByte(uint8_t x) { uint8_t b = 0; for (int i = 0; i < 8; ++i) { b <<= 1; b |= (x & 1); x >>= 1; } return b; } bool PNMCodec::Write(const char *filename, const DataElement &out) const { std::ofstream os(filename, std::ios::binary); const unsigned int *dims = this->GetDimensions(); const PhotometricInterpretation &pi = this->GetPhotometricInterpretation(); const PixelFormat& pf = GetPixelFormat(); if( pi == PhotometricInterpretation::MONOCHROME2 || pi == PhotometricInterpretation::MONOCHROME1 ) // warning viz will be surprising { // FIXME possible mismatch pi vs pf (eg. pbm with mono2) if( pf == PixelFormat::SINGLEBIT) os << "P4\n"; else os << "P5\n"; } else if( pi == PhotometricInterpretation::RGB || pi == PhotometricInterpretation::PALETTE_COLOR ) { os << "P6\n"; } else { gdcmErrorMacro( "PhotometricInterpretation unhandled: " << pi ); return false; } os << dims[0] << " " << dims[1] << "\n"; const unsigned int pc = this->GetPlanarConfiguration(); if( pc ) { gdcmErrorMacro( "PlanarConfiguration unhandled: " << pc ); return false; } switch(pf) { case PixelFormat::SINGLEBIT: break; case PixelFormat::UINT8: //case PixelFormat::INT8: os << "255\n"; break; case PixelFormat::UINT16: //case PixelFormat::INT16: os << "65535\n"; break; default: gdcmErrorMacro( "Unhandled PF: " << pf ); return false; } const ByteValue *bv = out.GetByteValue(); // FIXME: PNM Codec cannot handle encapsulated syntax... sigh if(!bv) { gdcmErrorMacro( "PNM Codec does not handle compress syntax. You need to decompress first." ); return false; } assert(bv); if( pi == PhotometricInterpretation::PALETTE_COLOR ) { std::stringstream is; is.write( bv->GetPointer(), bv->GetLength() ); const LookupTable &lut = this->GetLUT(); lut.Decode(is, os); } else { if( pf.GetBitsAllocated() == 16 ) { bv->Write( os ); } else if( pf.GetBitsAllocated() == 1 ) { const uint8_t *x = (const uint8_t*) bv->GetPointer(); for( size_t i = 0; i < bv->GetLength(); i++ ) { uint8_t b = reverseBitsByte(x[i]); os.write((char*)&b, 1); } } else { //bv->Write( os ); bv->WriteBuffer( os ); } } os.close(); return true; } bool PNMCodec::Read(const char *filename, DataElement &out) const { size_t len = System::FileSize(filename); std::ifstream is(filename, std::ios::binary); std::string type, str; std::getline(is,type); PhotometricInterpretation pi; if( type == "P5" ) pi = PhotometricInterpretation::MONOCHROME2; else if( type == "P6" ) pi = PhotometricInterpretation::RGB; else { std::cerr << "Unhandled PGM type: " << type << std::endl; return false; } // skip comments: while( is.peek() == '#' ) { std::getline(is, str); //std::cout << str << std::endl; } unsigned int dims[3] = {}; is >> dims[0]; is >> dims[1]; unsigned int maxval; is >> maxval; // some kind of empty line... if( is.peek() == '\n' ) { is.get(); } std::streampos pos = is.tellg(); //assert(pos < INT_MAX); size_t m = (len - (size_t)pos ) / ( dims[0]*dims[1] ); if( m * dims[0] * dims[1] != len - pos ) { std::cerr << "Problem computing length" << std::endl; return false; } PixelFormat pf; switch(maxval) { case 255: pf = PixelFormat::UINT8; break; case 1023: pf = PixelFormat::UINT16; pf.SetBitsStored( 10 ); break; case 4095: pf = PixelFormat::UINT16; pf.SetBitsStored( 12 ); break; case 32767: pf = PixelFormat::UINT16; pf.SetBitsStored( 15 ); break; case 65535: pf = PixelFormat::UINT16; break; default: std::cerr << "Unhandled max val: " << maxval << std::endl; return false; } if( pi == PhotometricInterpretation::RGB ) { pf.SetSamplesPerPixel( 3 ); } //if ( maxval * 8 != bpp ) return 1; size_t pdlen = GetBufferLength(); assert( pdlen ); char * buf = new char[pdlen]; // is should be at right offset, just read! is.read(buf, len); if( !is.eof() ) { delete[] buf; return false; } out.SetTag( Tag(0x7fe0,0x0010) ); VL::Type pdLenSize = (VL::Type)pdlen; out.SetByteValue( buf, pdLenSize ); delete[] buf; is.close(); return true; } static inline int log2( int n ) { int bits = 0; while (n > 0) { bits++; n >>= 1; } return bits; } bool PNMCodec::GetHeaderInfo(std::istream &is, TransferSyntax &ts) { is.seekg( 0, std::ios::end ); std::streampos len = is.tellg(); //assert(len < INT_MAX); is.seekg( 0, std::ios::beg ); std::string type, str; std::getline(is,type); PhotometricInterpretation pi; if( type == "P4" ) // P4 => mono W/B ! pi = PhotometricInterpretation::MONOCHROME1; else if( type == "P5" ) pi = PhotometricInterpretation::MONOCHROME2; else if( type == "P6" ) // P3 => ASCII pi = PhotometricInterpretation::RGB; else { std::cerr << "Unhandled PGM type: " << type << std::endl; return false; } // skip comments: while( is.peek() == '#' ) { std::getline(is, str); //std::cout << str << std::endl; } unsigned int dims[3] = {}; is >> dims[0]; is >> dims[1]; unsigned int maxval; if( type == "P4" ) maxval = 1; else is >> maxval; // http://netpbm.sourceforge.net/doc/pgm.html // some kind of empty line... if( is.peek() == '\n' ) { is.get(); } std::streamoff pos = is.tellg(); //assert(len < INT_MAX); //assert(pos < INT_MAX); size_t m = ((size_t)len - (size_t)pos ) / ( dims[0]*dims[1] ); bool cond; if( type == "P4" ) { const size_t bytesPerRow = dims[0] / 8 + (dims[0] % 8 != 0 ? 1 : 0); cond = bytesPerRow * dims[1] != ((size_t)len - (size_t)pos); } else cond = m * dims[0] * dims[1] != (size_t)len - (size_t)pos; if( cond ) { std::cerr << "Problem computing length" << std::endl; std::cerr << "Pos: " << len - pos << std::endl; std::cerr << "expected: " << m * dims[0] * dims[1] << std::endl; return false; } PixelFormat pf = GetPixelFormat(); #if 0 switch(maxval) { case 255: pf = PixelFormat::UINT8; break; case 1023: pf = PixelFormat::UINT16; pf.SetBitsStored( 10 ); break; case 4095: pf = PixelFormat::UINT16; pf.SetBitsStored( 12 ); break; case 32767: pf = PixelFormat::UINT16; pf.SetBitsStored( 15 ); break; case 65535: pf = PixelFormat::UINT16; break; default: std::cerr << "Unhandled max val: " << maxval << std::endl; return false; } #else const int nbits = log2( maxval ); // handle case where nbits = 0 also: if( nbits > 0 && nbits <= 1 ) { pf.SetBitsAllocated( 1 ); } else if( nbits > 1 && nbits <= 8 ) { pf.SetBitsAllocated( 8 ); pf.SetBitsStored( (unsigned short)nbits ); } else if( nbits > 8 && nbits <= 16 ) { pf.SetBitsAllocated( 16 ); pf.SetBitsStored( (unsigned short)nbits ); } else if( nbits > 16 && nbits <= 32 ) { pf.SetBitsAllocated( 32 ); pf.SetBitsStored( (unsigned short)nbits ); } else { std::cerr << "Unhandled max val: " << maxval << std::endl; return false; } #endif if( pi == PhotometricInterpretation::RGB ) { pf.SetSamplesPerPixel( 3 ); } //if ( maxval * 8 != bpp ) return 1; //image.SetTransferSyntax( TransferSyntax::ExplicitVRBigEndian ); // PGM are big endian //image.SetTransferSyntax( TransferSyntax::ExplicitVRLittleEndian ); // PGM are big endian //image.SetTransferSyntax( TransferSyntax::ImplicitVRBigEndianPrivateGE ); // PGM are big endian if( pf.GetBitsAllocated() > 8 ) ts = TransferSyntax::ImplicitVRBigEndianPrivateGE; else //ts = TransferSyntax::ImplicitVRLittleEndian; // nicer to handle than private GE ts = TransferSyntax::ExplicitVRLittleEndian; // nicer to handle than private GE SetPhotometricInterpretation( pi ); SetPixelFormat( pf ); SetDimensions( dims ); return true; } ImageCodec * PNMCodec::Clone() const { return nullptr; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPNMCodec.h000066400000000000000000000030731412732066400231110ustar00rootroot00000000000000/*========================================================================= 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 GDCMPNMCODEC_H #define GDCMPNMCODEC_H #include "gdcmImageCodec.h" namespace gdcm { /** * \brief Class to do PNM * \details PNM is the Portable anymap file format. The main web page can be found at: * http://netpbm.sourceforge.net/ * \note * Only support P5 & P6 PNM file (binary grayscale and binary rgb) */ class GDCM_EXPORT PNMCodec : public ImageCodec { public: PNMCodec(); ~PNMCodec() override; bool CanDecode(TransferSyntax const &ts) const override; bool CanCode(TransferSyntax const &ts) const override; unsigned long GetBufferLength() const { return BufferLength; } void SetBufferLength(unsigned long l) { BufferLength = l; } bool GetHeaderInfo(std::istream &is, TransferSyntax &ts) override; ImageCodec * Clone() const override; bool Read(const char *filename, DataElement &out) const; bool Write(const char *filename, const DataElement &out) const; //bool Write(const char *filename); private: unsigned long BufferLength; }; } // end namespace gdcm #endif //GDCMPNMCODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPVRGCodec.cxx000066400000000000000000000126311412732066400236100ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPVRGCodec.h" #include "gdcmTransferSyntax.h" #include "gdcmDataElement.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmSequenceOfFragments.h" #include "gdcmPNMCodec.h" #include "gdcmByteSwap.txx" namespace gdcm { /* http://groups.google.com/group/comp.compression/browse_thread/thread/e2e20d85a436cfa5 */ PVRGCodec::PVRGCodec() { NeedByteSwap = true; } PVRGCodec::~PVRGCodec() = default; bool PVRGCodec::CanDecode(TransferSyntax const &ts) const { #ifndef GDCM_USE_PVRG (void)ts; return false; #else return ts == TransferSyntax::JPEGBaselineProcess1 || ts == TransferSyntax::JPEGExtendedProcess2_4 || ts == TransferSyntax::JPEGExtendedProcess3_5 || ts == TransferSyntax::JPEGSpectralSelectionProcess6_8 || ts == TransferSyntax::JPEGFullProgressionProcess10_12 || ts == TransferSyntax::JPEGLosslessProcess14 || ts == TransferSyntax::JPEGLosslessProcess14_1; #endif } bool PVRGCodec::CanCode(TransferSyntax const &) const { return false; } /* PVRG command line is a bit tricky to use: * * ./bin/pvrg-jpeg -d -s jpeg.jpg -ci 0 out.raw * * means decompress input file: jpeg.jpg into out.raw * warning the -ci is important otherwise JFIF is assumed * and comp # is assumed to be 1... * -u reduce verbosity */ bool PVRGCodec::Decode(DataElement const &in, DataElement &out) { #ifndef GDCM_USE_PVRG (void)in; (void)out; return false; #else // First thing create a jpegls file from the fragment: const SequenceOfFragments *sf = in.GetSequenceOfFragments(); if(!sf) { gdcmDebugMacro( "Could not find SequenceOfFragments" ); return false; } #ifdef GDCM_USE_SYSTEM_PVRG std::string pvrg_command = GDCM_PVRG_JPEG_EXECUTABLE; #else Filename fn( System::GetCurrentProcessFileName() ); std::string executable_path = fn.GetPath(); std::string pvrg_command = executable_path + "/gdcmjpeg"; #endif if( !System::FileExists( pvrg_command.c_str() ) ) { gdcmErrorMacro( "Could not find: " << pvrg_command ); return false; } // http://msdn.microsoft.com/en-us/library/hs3e7355.aspx // -> check if tempnam needs the 'free' char *input = tempnam(0, "gdcminpvrg"); char *output = tempnam(0, "gdcmoutpvrg"); if( !input || !output ) { //free(input); //free(output); return false; } std::ofstream outfile(input, std::ios::binary); sf->WriteBuffer(outfile); outfile.close(); // flush ! // -u -> set Notify to 0 (less verbose) //pvrg_command += " -ci 0 -d -u "; pvrg_command += " -d -u "; // ./bin/pvrgjpeg -d -s jpeg.jpg -ci 0 out.raw pvrg_command += "-s "; pvrg_command += input; //pvrg_command += " -ci 0 "; //pvrg_command += output; //std::cerr << pvrg_command << std::endl; gdcmDebugMacro( pvrg_command ); int ret = system(pvrg_command.c_str()); //std::cerr << "system: " << ret << std::endl; if( ret ) { gdcmErrorMacro( "Looks like pvrg gave up in input, with ret value: " << ret ); return false; } int numoutfile = GetPixelFormat().GetSamplesPerPixel(); std::string wholebuf; for( int file = 0; file < numoutfile; ++file ) { std::ostringstream os; os << input; os << "."; os << file; // don't ask const std::string altfile = os.str(); const size_t len = System::FileSize(altfile.c_str()); if( !len ) { gdcmDebugMacro( "Output file was really empty: " << altfile ); return false; } const char *rawfile = altfile.c_str(); gdcmDebugMacro( "Processing: " << rawfile ); std::ifstream is(rawfile, std::ios::binary); std::string buf; buf.resize( len ); is.read(&buf[0], len); out.SetTag( Tag(0x7fe0,0x0010) ); if ( PF.GetBitsAllocated() == 16 ) { ByteSwap::SwapRangeFromSwapCodeIntoSystem((uint16_t*) &buf[0], #ifdef GDCM_WORDS_BIGENDIAN SwapCode::LittleEndian, #else SwapCode::BigEndian, #endif len/2); } wholebuf.insert( wholebuf.end(), buf.begin(), buf.end() ); if( !System::RemoveFile(rawfile) ) { gdcmErrorMacro( "Could not delete output: " << rawfile); } } out.SetByteValue( &wholebuf[0], (uint32_t)wholebuf.size() ); if( numoutfile == 3 ) { this->PlanarConfiguration = 1; } if( !System::RemoveFile(input) ) { gdcmErrorMacro( "Could not delete input: " << input ); } free(input); free(output); // FIXME: LossyFlag = true; //return ImageCodec::Decode(in,out); return true; #endif } void PVRGCodec::SetLossyFlag( bool l ) { LossyFlag = l; } // Compress into JPEG bool PVRGCodec::Code(DataElement const &in, DataElement &out) { #ifndef GDCM_USE_PVRG (void)in; (void)out; return false; #else (void)in; (void)out; /* Do I really want to produce JPEG by PVRG ? Shouldn't IJG handle all cases nicely ? */ return false; #endif } ImageCodec * PVRGCodec::Clone() const { return nullptr; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPVRGCodec.h000066400000000000000000000027301412732066400232340ustar00rootroot00000000000000/*========================================================================= 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 GDCMPVRGCODEC_H #define GDCMPVRGCODEC_H #include "gdcmImageCodec.h" 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. * * In an ideal world, you should not need this codec at all. But to support * some broken file such as: * * PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm * * we have to... */ class PVRGCodec : public ImageCodec { public: PVRGCodec(); ~PVRGCodec() override; bool CanDecode(TransferSyntax const &ts) const override; bool CanCode(TransferSyntax const &ts) const override; bool Decode(DataElement const &is, DataElement &os) override; bool Code(DataElement const &in, DataElement &out) override; void SetLossyFlag( bool l ); ImageCodec * Clone() const override; private: }; } // end namespace gdcm #endif //GDCMPVRGCODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPersonName.cxx000066400000000000000000000011441412732066400241400ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPersonName.h" namespace gdcm {} GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPersonName.h000066400000000000000000000047171412732066400235760ustar00rootroot00000000000000/*========================================================================= 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 GDCMPERSONNAME_H #define GDCMPERSONNAME_H #include "gdcmTypes.h" #include #include // std::min #include // strlen namespace gdcm { /** * \brief PersonName class */ class GDCM_EXPORT PersonName { public: static const unsigned int MaxNumberOfComponents = 5; static const unsigned int MaxLength = 64; char Component[MaxNumberOfComponents][MaxLength+1]; static const char Separator = '^'; static const char Padding = ' '; unsigned int GetNumberOfComponents() const { unsigned int r = 0; for(unsigned int i = 0; i < 5; ++i) { if( *Component[i] != '\0' ) r = i; } return r+1; } unsigned int GetMaxLength() const { return MaxLength; }; void SetBlob(const std::vector& v) { (void)v; //assert(0); //TODO } void SetComponents(const char *comp1 = "", const char *comp2 = "", const char *comp3 = "", const char *comp4 = "", const char *comp5 = "") { const char *components[5] = { comp1, comp2, comp3, comp4, comp5 }; SetComponents( components ); } void SetComponents(const char *components[]) { if( components ) for(unsigned int i = 0; i < 5; ++i) { if( components[i] && strlen(components[i]) < GetMaxLength() ) strcpy(Component[i], components[i]); assert( strlen(Component[i]) < GetMaxLength() ); } } void Print(std::ostream &os) const { //os << "Family Name Complex: " << Component[0] << std::endl; //os << "Given Name Complex: " << Component[1] << std::endl; //os << "Middle Name : " << Component[2] << std::endl; //os << "Name Suffix : " << Component[3] << std::endl; //os << "Name Prefix : " << Component[4] << std::endl; os << Component[0] << '^'; os << Component[1] << '^'; os << Component[2] << '^'; os << Component[3] << '^'; os << Component[4]; } }; } // end namespace gdcm #endif //GDCMPERSONNAME_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPhotometricInterpretation.cxx000066400000000000000000000132561412732066400273250ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPhotometricInterpretation.h" #include "gdcmTransferSyntax.h" #include "gdcmTrace.h" #include "gdcmCodeString.h" #include "gdcmVR.h" #include #include #include namespace gdcm { /* * HSV/ARGB/CMYK can still be found in PS 3.3 - 2000: * * HSV = Pixel data represent a color image described by hue, saturation, and value image planes. * The minimum sample value for each HSV plane represents a minimum value of each vector. This * value may be used only when Samples per Pixel (0028,0002) has a value of 3. * * ARGB = Pixel data represent a color image described by red, green, blue, and alpha image planes. * The minimum sample value for each RGB plane represents minimum intensity of the color. The * alpha plane is passed through Palette Color Lookup Tables. If the alpha pixel value is greater than * 0, the red, green, and blue lookup table values override the red, green, and blue, pixel plane colors. * This value may be used only when Samples per Pixel (0028,0002) has a value of 4. * * CMYK = Pixel data represent a color image described by cyan, magenta, yellow, and black image * planes. The minimum sample value for each CMYK plane represents a minimum intensity of the * color. This value may be used only when Samples per Pixel (0028,0002) has a value of 4. * */ static const char *PIStrings[] = { "UNKNOWN", "MONOCHROME1 ", "MONOCHROME2 ", "PALETTE COLOR ", "RGB ", "HSV ", "ARGB", "CMYK", "YBR_FULL", "YBR_FULL_422", "YBR_PARTIAL_422 ", "YBR_PARTIAL_420 ", "YBR_ICT ", "YBR_RCT ", nullptr }; const char *PhotometricInterpretation::GetPIString(PIType pi) { //assert( pi < PhotometricInterpretation::PI_END ); return PIStrings[pi]; } PhotometricInterpretation::PIType PhotometricInterpretation::GetPIType(const char *inputpi) { if( !inputpi ) return PI_END; // The following code allows use to handle whitespace and invalid padding: CodeString codestring = inputpi; CSComp cs = codestring.GetAsString(); const char *pi = cs.c_str(); for( unsigned int i = 1; PIStrings[i] != nullptr; ++i ) { if( strcmp(pi, PIStrings[i]) == 0 ) { return PIType(i); } } // Ouch ! We did not find anything, that's pretty bad, let's hope that // the toolkit which wrote the image is buggy and tolerate \0 padded ASCII // string // warning this piece of code will do MONOCHROME -> MONOCHROME1 static const unsigned int n = sizeof(PIStrings) / sizeof(*PIStrings) - 1; size_t len = strlen(pi); if( pi[len-1] == ' ' ) len--; for( unsigned int i = 1; i < n; ++i ) { if( strncmp(pi, PIStrings[i], len ) == 0 ) { gdcmDebugMacro( "PhotometricInterpretation was found: [" << pi << "], but is invalid. It should be padded with a space" ); return PIType(i); } } //assert(0); return PI_END; } bool PhotometricInterpretation::IsRetired(PIType pi) { return pi == HSV || pi == ARGB || pi == CMYK; } unsigned short PhotometricInterpretation::GetSamplesPerPixel() const { if ( PIField == UNKNOWN ) return 0; else if( PIField == MONOCHROME1 || PIField == MONOCHROME2 || PIField == PALETTE_COLOR ) { return 1; } else if( PIField == ARGB || PIField == CMYK ) { return 4; } else { assert( PIField != PI_END ); assert( //PIField == PALETTE_COLOR PIField == RGB || PIField == HSV //|| PIField == ARGB //|| PIField == CMYK || PIField == YBR_FULL || PIField == YBR_FULL_422 || PIField == YBR_PARTIAL_422 || PIField == YBR_PARTIAL_420 || PIField == YBR_ICT || PIField == YBR_RCT ); return 3; } } bool PhotometricInterpretation::IsLossy() const { return !IsLossless(); } bool PhotometricInterpretation::IsLossless() const { switch ( PIField ) { case MONOCHROME1: /* technically MPEG-2 is lossy however the PI is set to MONOCHROME2 */ case MONOCHROME2: case PALETTE_COLOR: case RGB: case HSV: case ARGB: case CMYK: case YBR_FULL: case YBR_RCT: return true; case YBR_FULL_422: case YBR_PARTIAL_422: case YBR_PARTIAL_420: case YBR_ICT: return false; default: assert(0); return false; } assert( 0 ); // technically one should not reach here, unless UNKNOWN ... return false; } const char *PhotometricInterpretation::GetString() const { return PhotometricInterpretation::GetPIString( PIField ); } bool PhotometricInterpretation::IsSameColorSpace( PhotometricInterpretation const &pi ) const { if( PIField == pi ) return true; // else if( PIField == RGB || PIField == YBR_RCT || PIField == YBR_ICT ) { if( pi == RGB || pi == YBR_RCT || pi == YBR_ICT ) return true; } if( PIField == YBR_FULL || PIField == YBR_FULL_422 ) { if( pi == YBR_FULL || pi == YBR_FULL_422 ) return true; } return false; } //PhotometricInterpretation::PIType PhotometricInterpretation::GetEquivalent(TransferSyntax const &ts) //{ // // A.8.5.4 Multi-frame True Color SC Image IOD Content Constraints // if( PIField == RGB ) // { // if( ts == TransferSyntax:: // } // return PIField; //} // } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPhotometricInterpretation.h000066400000000000000000000054001412732066400267420ustar00rootroot00000000000000/*========================================================================= 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 GDCMPHOTOMETRICINTERPRETATION_H #define GDCMPHOTOMETRICINTERPRETATION_H #include "gdcmTypes.h" #include namespace gdcm { class TransferSyntax; /** * \brief Class to represent an PhotometricInterpretation */ class GDCM_EXPORT PhotometricInterpretation { public: typedef enum { UNKNOWN = 0, MONOCHROME1, MONOCHROME2, PALETTE_COLOR, RGB, HSV, ARGB, // retired CMYK, YBR_FULL, YBR_FULL_422, YBR_PARTIAL_422, YBR_PARTIAL_420, YBR_ICT, YBR_RCT, // PALETTE_COLOR ? //MONOCHROME = MONOCHROME1 | MONOCHROME2, //COLOR = RGB | HSV | ARGB | CMYK | YBR_FULL | YBR_FULL_422 | YBR_PARTIAL_422 | YBR_PARTIAL_420 | YBR_ICT | YBR_RCT, PI_END // Helpful for internal implementation } PIType; // PhotometricInterpretationType PhotometricInterpretation(PIType pi = UNKNOWN):PIField(pi) {} static const char *GetPIString(PIType pi); const char *GetString() const; // You need to make sure end of string is \0 static PIType GetPIType(const char *pi); static bool IsRetired(PIType pi); bool IsLossy() const; bool IsLossless() const; /// return the value for Sample Per Pixel associated with a particular Photometric Interpretation unsigned short GetSamplesPerPixel() const; // TODO // not all PhotometricInterpretation are allowed for compressed Transfer // syntax // static bool IsAllowedForCompressedTS(PIType pi); friend std::ostream& operator<<(std::ostream& os, const PhotometricInterpretation& pi); operator PIType () const { return PIField; } PIType GetType () const { return PIField; } // Will return whether current PhotometricInterpretation is the same Color Space as input: // eg. RGB and YBR_RCT are bool IsSameColorSpace( PhotometricInterpretation const &pi ) const; //static PIType GetEquivalent(TransferSyntax const &ts); private: PIType PIField; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream& os, const PhotometricInterpretation &val) { const char *s = PhotometricInterpretation::GetPIString(val.PIField); os << (s ? s : ""); return os; } } // end namespace gdcm #endif //GDCMPHOTOMETRICINTERPRETATION_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPixelFormat.cxx000066400000000000000000000162761412732066400243370ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPixelFormat.h" #include "gdcmTrace.h" #include "gdcmTransferSyntax.h" #include namespace gdcm { static const char *ScalarTypeStrings[] = { "UINT8", "INT8", "UINT12", "INT12", "UINT16", "INT16", "UINT32", "INT32", "UINT64", "INT64", "FLOAT16", "FLOAT32", "FLOAT64", "SINGLEBIT", "UNKNOWN", nullptr, }; PixelFormat::PixelFormat(ScalarType st) { SamplesPerPixel = 1; SetScalarType( st ); } unsigned short PixelFormat::GetSamplesPerPixel() const { // \postcondition assert( SamplesPerPixel == 1 || SamplesPerPixel == 3 || SamplesPerPixel == 4 ); return SamplesPerPixel; } void PixelFormat::SetScalarType(ScalarType st) { SamplesPerPixel = 1; switch(st) { case PixelFormat::UINT8: BitsAllocated = 8; PixelRepresentation = 0; break; case PixelFormat::INT8: BitsAllocated = 8; PixelRepresentation = 1; break; case PixelFormat::UINT12: BitsAllocated = 12; PixelRepresentation = 0; break; case PixelFormat::INT12: BitsAllocated = 12; PixelRepresentation = 1; break; case PixelFormat::UINT16: BitsAllocated = 16; PixelRepresentation = 0; break; case PixelFormat::INT16: BitsAllocated = 16; PixelRepresentation = 1; break; case PixelFormat::UINT32: BitsAllocated = 32; PixelRepresentation = 0; break; case PixelFormat::INT32: BitsAllocated = 32; PixelRepresentation = 1; break; case PixelFormat::UINT64: BitsAllocated = 64; PixelRepresentation = 0; break; case PixelFormat::INT64: BitsAllocated = 64; PixelRepresentation = 1; break; case PixelFormat::FLOAT16: BitsAllocated = 16; // secret code: PixelRepresentation = 2; break; case PixelFormat::FLOAT32: BitsAllocated = 32; // secret code: PixelRepresentation = 3; break; case PixelFormat::FLOAT64: BitsAllocated = 64; // secret code: PixelRepresentation = 4; break; case PixelFormat::SINGLEBIT: BitsAllocated = 1; PixelRepresentation = 0; break; case PixelFormat::UNKNOWN: BitsAllocated = 0; PixelRepresentation = 0; break; default: assert(0); break; } BitsStored = BitsAllocated; HighBit = (uint16_t)(BitsStored - 1); } PixelFormat::ScalarType PixelFormat::GetScalarType() const { ScalarType type = PixelFormat::UNKNOWN; gdcmAssertAlwaysMacro( BitsStored <= BitsAllocated ); switch( BitsAllocated ) { case 0: type = PixelFormat::UNKNOWN; break; case 1: type = PixelFormat::SINGLEBIT; break; case 8: type = PixelFormat::UINT8; break; case 12: type = PixelFormat::UINT12; break; case 16: type = PixelFormat::UINT16; break; case 32: type = PixelFormat::UINT32; break; case 64: type = PixelFormat::UINT64; break; case 24: gdcmDebugMacro( "This is illegal in DICOM, assuming a RGB image" ); type = PixelFormat::UINT8; break; default: gdcmErrorMacro( "I have never seen this before BitsAllocated " << BitsAllocated ); type = PixelFormat::UNKNOWN; } if( type != PixelFormat::UNKNOWN ) { if( PixelRepresentation == 0 ) { // all set ! } else if( PixelRepresentation == 1 ) { assert( type <= INT64 ); // That's why you need to order properly type in ScalarType type = ScalarType(int(type)+1); } else if( PixelRepresentation == 2 ) { assert( BitsAllocated == 16 ); return FLOAT16; } else if( PixelRepresentation == 3 ) { assert( BitsAllocated == 32 ); return FLOAT32; } else if( PixelRepresentation == 4 ) { assert( BitsAllocated == 64 ); return FLOAT64; } else { gdcmAssertAlwaysMacro(0); } } return type; } const char *PixelFormat::GetScalarTypeAsString() const { return ScalarTypeStrings[GetScalarType()]; } uint8_t PixelFormat::GetPixelSize() const { uint8_t pixelsize = (uint8_t)(BitsAllocated / 8); if( BitsAllocated == 12 ) { pixelsize = 2; // fake a short value } else { assert( !(BitsAllocated % 8) ); } pixelsize *= SamplesPerPixel; return pixelsize; } int64_t PixelFormat::GetMin() const { assert( BitsAllocated ); // cannot be unknown if( BitsStored <= 32 ) { if( PixelRepresentation == 1 ) { return (int64_t)(~(((1ull << BitsStored) - 1) >> 1)); } else if( PixelRepresentation == 0 ) { return 0; } } // else gdcmAssertAlwaysMacro( 0 ); // throw "PixelFormat bad representation"; } int64_t PixelFormat::GetMax() const { assert( BitsAllocated ); // cannot be unknown if( BitsStored <= 32 ) { if( PixelRepresentation == 1 ) { return (int64_t)(((1ull << BitsStored) - 1) >> 1); } else if( PixelRepresentation == 0 ) { return (int64_t)((1ull << BitsStored) - 1); } } // else gdcmAssertAlwaysMacro( 0 ); // throw "PixelFormat bad representation"; } bool PixelFormat::IsValid() const { if( PixelRepresentation != 0 && PixelRepresentation != 1 ) { return false; } if( BitsAllocated < BitsStored ) return false; if( BitsAllocated < HighBit ) return false; if( BitsStored > 32 ) return false; return true; } bool PixelFormat::Validate() { if( !IsValid() ) return false; //assert( BitsStored >= HighBit ); // DigitexAlpha_no_7FE0.dcm assert( PixelRepresentation == 0 || PixelRepresentation == 1 ); assert( SamplesPerPixel == 1 || SamplesPerPixel == 3 || SamplesPerPixel == 4 ); if ( BitsStored == 0 ) { gdcmDebugMacro( "Bits Stored is 0. Setting is to max value" ); BitsStored = BitsAllocated; } if ( BitsAllocated == 24 ) { gdcmDebugMacro( "ACR-NEMA way of storing RGB data. Updating" ); if( BitsStored == 24 && HighBit == 23 && SamplesPerPixel == 1 ) { BitsAllocated = 8; BitsStored = 8; HighBit = 7; SamplesPerPixel = 3; return true; } // all other case, simply give up return false; } return true; } void PixelFormat::Print(std::ostream &os) const { os << "SamplesPerPixel :" << SamplesPerPixel << "\n"; os << "BitsAllocated :" << BitsAllocated << "\n"; os << "BitsStored :" << BitsStored << "\n"; os << "HighBit :" << HighBit << "\n"; os << "PixelRepresentation:" << PixelRepresentation << "\n"; os << "ScalarType found :" << GetScalarTypeAsString() << "\n"; } bool PixelFormat::IsCompatible(const TransferSyntax & ts ) const { if( ts == TransferSyntax::JPEGBaselineProcess1 && BitsAllocated != 8 ) return false; // FIXME are we missing any ? return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPixelFormat.h000066400000000000000000000167631412732066400237650ustar00rootroot00000000000000/*========================================================================= 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 GDCMPIXELFORMAT_H #define GDCMPIXELFORMAT_H #include "gdcmTypes.h" #include #include namespace gdcm { class TransferSyntax; /** * \brief PixelFormat * \details * By default the Pixel Type will be instantiated with the following * parameters: * - SamplesPerPixel : 1 * - BitsAllocated : 8 * - BitsStored : 8 * - HighBit : 7 * - PixelRepresentation : 0 * * Fundamentally PixelFormat is very close to what DICOM allows. It will be * very hard to extend this class for the upcoming DICOM standard where * Floating 32 and 64bits will be allowed. * * It is also very hard for this class to fully support 64bits integer type * (see GetMin / GetMax signature restricted to 64bits signed). */ 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) typedef enum { UINT8, INT8, UINT12, INT12, UINT16, INT16, UINT32, // For some DICOM files (RT or SC) INT32, // " " UINT64, // Needed when input is 32bits + intercept/slope (incomplete support) INT64, // " " FLOAT16, // sure why not... FLOAT32, // good ol' 'float' FLOAT64, // aka 'double' SINGLEBIT, // bool / monochrome UNKNOWN // aka BitsAllocated == 0 && PixelRepresentation == 0 } ScalarType; // default cstor: PixelFormat () : PixelFormat(1, 8, 8, 7, 0) {} explicit PixelFormat ( unsigned short samplesperpixel, unsigned short bitsallocated = 8, unsigned short bitsstored = 8, unsigned short highbit = 7, unsigned short pixelrepresentation = 0 ) : SamplesPerPixel(samplesperpixel), BitsAllocated(bitsallocated), BitsStored(bitsstored), HighBit(highbit), PixelRepresentation(pixelrepresentation) {} // helper, for the common case PixelFormat(ScalarType st); // For transparency of use operator ScalarType() const { return GetScalarType(); } /// Samples Per Pixel see (0028,0002) US Samples Per Pixel /// DICOM - only allows 1, 3 and 4 as valid value. Other value are undefined behavior. unsigned short GetSamplesPerPixel() const; void SetSamplesPerPixel(unsigned short spp) { gdcmAssertMacro( spp <= 4 ); SamplesPerPixel = spp; assert( SamplesPerPixel == 1 || SamplesPerPixel == 3 || SamplesPerPixel == 4 ); } /// BitsAllocated see Tag (0028,0100) US Bits Allocated unsigned short GetBitsAllocated() const { return BitsAllocated; } void SetBitsAllocated(unsigned short ba) { if( ba ) { switch( ba ) { /* some devices (FUJIFILM CR + MONO1) incorrectly set BitsAllocated/BitsStored * as bitmask instead of value. Do what they mean instead of what they say. */ case 0xffff: ba = 16; break; case 0x0fff: ba = 12; break; case 0x00ff: ba = 8; break; } BitsAllocated = ba; BitsStored = ba; HighBit = (unsigned short)(ba - 1); } else // Make the PixelFormat as UNKNOWN { BitsAllocated = 0; PixelRepresentation = 0; } } /// BitsStored see Tag (0028,0101) US Bits Stored unsigned short GetBitsStored() const { assert( BitsStored <= BitsAllocated ); return BitsStored; } void SetBitsStored(unsigned short bs) { switch( bs ) { /* see SetBitsAllocated for explanation */ case 0xffff: bs = 16; break; case 0x0fff: bs = 12; break; case 0x00ff: bs = 8; break; } if( bs <= BitsAllocated && bs ) { BitsStored = bs; SetHighBit( (unsigned short) (bs - 1) ); } } /// HighBit see Tag (0028,0102) US High Bit unsigned short GetHighBit() const { assert( HighBit < BitsStored ); return HighBit; } void SetHighBit(unsigned short hb) { switch( hb ) { /* broken implementations that use bitmask for BitsAllocated/Stored * nonetheless use (BitsStored-1) for HighBit. correct for this here. */ case 0xfffe: hb = 15; break; case 0x0ffe: hb = 11; break; case 0x00fe: hb = 7; break; } if( hb < BitsStored ) HighBit = hb; } /// PixelRepresentation: 0 or 1, see Tag (0028,0103) US Pixel Representation unsigned short GetPixelRepresentation() const { return (unsigned short)(PixelRepresentation ? 1 : 0); } void SetPixelRepresentation(unsigned short pr) { PixelRepresentation = (unsigned short)(pr ? 1 : 0); } /// ScalarType does not take into account the sample per pixel ScalarType GetScalarType() const; /// Set PixelFormat based only on the ScalarType /// \warning: You need to call SetScalarType *before* SetSamplesPerPixel void SetScalarType(ScalarType st); const char *GetScalarTypeAsString() const; /// return the size of the pixel /// This is the number of words it would take to store one pixel /// \warning the return value takes into account the SamplesPerPixel /// \warning in the rare case when BitsAllocated == 12, the function /// assume word padding and value returned will be identical as if BitsAllocated == 16 uint8_t GetPixelSize() const; /// Print void Print(std::ostream &os) const; /// return the min possible of the pixel int64_t GetMin() const; /// return the max possible of the pixel int64_t GetMax() const; /// return IsValid bool IsValid() const; bool operator==(ScalarType st) const { return GetScalarType() == st; } bool operator!=(ScalarType st) const { return GetScalarType() != st; } bool operator==(const PixelFormat &pf) const { return SamplesPerPixel == pf.SamplesPerPixel && BitsAllocated == pf.BitsAllocated && BitsStored == pf.BitsStored && HighBit == pf.HighBit && PixelRepresentation == pf.PixelRepresentation; } bool operator!=(const PixelFormat &pf) const { return SamplesPerPixel != pf.SamplesPerPixel || BitsAllocated != pf.BitsAllocated || BitsStored != pf.BitsStored || HighBit != pf.HighBit || PixelRepresentation != pf.PixelRepresentation; } bool IsCompatible(const TransferSyntax & ts ) const; protected: /// When image with 24/24/23 was read, need to validate bool Validate(); private: // D 0028|0002 [US] [Samples per Pixel] [1] unsigned short SamplesPerPixel; // D 0028|0100 [US] [Bits Allocated] [8] unsigned short BitsAllocated; // D 0028|0101 [US] [Bits Stored] [8] unsigned short BitsStored; // D 0028|0102 [US] [High Bit] [7] unsigned short HighBit; // D 0028|0103 [US] [Pixel Representation] [0] unsigned short PixelRepresentation; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const PixelFormat &pf) { pf.Print( os ); return os; } } // end namespace gdcm #endif //GDCMPIXELFORMAT_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPixmap.cxx000066400000000000000000000053001412732066400233250ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPixmap.h" namespace gdcm { /* * PICKER-16-MONO2-Nested_icon.dcm: (0088,0200) SQ (Sequence with undefined length #=1) # u/l, 1 PixmapSequence (fffe,e000) na (Item with undefined length #=10) # u/l, 1 Item (0028,0002) US 1 # 2, 1 SamplesPerPixel (0028,0004) CS [MONOCHROME2] # 12, 1 PhotometricInterpretation (0028,0010) US 64 # 2, 1 Rows (0028,0011) US 64 # 2, 1 Columns (0028,0034) IS [1\1] # 4, 2 PixelAspectRatio (0028,0100) US 8 # 2, 1 BitsAllocated (0028,0101) US 8 # 2, 1 BitsStored (0028,0102) US 7 # 2, 1 HighBit (0028,0103) US 0 # 2, 1 PixelRepresentation (7fe0,0010) OW 0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000... # 4096, 1 PixelData (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem */ Pixmap::Pixmap():Overlays(),Curves(),Icon(new IconImage) {} Pixmap::~Pixmap() = default; bool Pixmap::AreOverlaysInPixelData() const { int total = 0; std::vector::const_iterator it = Overlays.begin(); for(; it != Overlays.end(); ++it) { total += (int)it->IsInPixelData(); } assert( total == (int)GetNumberOfOverlays() || !total ); return total != 0; } bool Pixmap::UnusedBitsPresentInPixelData() const { const PixelFormat &pf = GetPixelFormat(); unsigned short ba = pf.GetBitsAllocated(); unsigned short bs = pf.GetBitsStored(); return ba != bs; } void Pixmap::Print(std::ostream &os) const { Bitmap::Print(os); for( std::vector::const_iterator it = Overlays.begin(); it != Overlays.end(); ++it) { it->Print( os ); } for( std::vector::const_iterator it = Curves.begin(); it != Curves.end(); ++it) { it->Print( os ); } } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPixmap.h000066400000000000000000000046651412732066400227670ustar00rootroot00000000000000/*========================================================================= 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 GDCMPIXMAP_H #define GDCMPIXMAP_H #include "gdcmBitmap.h" #include "gdcmCurve.h" #include "gdcmIconImage.h" #include "gdcmOverlay.h" namespace gdcm { /** * \brief Pixmap class * \details A bitmap based image. Used as parent for both IconImage and the main Pixel Data Image * It does not contains any World Space information (IPP, IOP) * * \see PixmapReader */ class GDCM_EXPORT Pixmap : public Bitmap { public: Pixmap(); ~Pixmap() override; void Print(std::ostream &) const override; /// returns if Overlays are stored in the unused bit of the pixel data: bool AreOverlaysInPixelData() const override; /// returns if there are unused bits in the pixel data bool UnusedBitsPresentInPixelData() const override; /// Curve: group 50xx Curve& GetCurve(size_t i = 0) { assert( i < Curves.size() ); return Curves[i]; } const Curve& GetCurve(size_t i = 0) const { assert( i < Curves.size() ); return Curves[i]; } size_t GetNumberOfCurves() const { return Curves.size(); } void SetNumberOfCurves(size_t n) { Curves.resize(n); } /// Overlay: group 60xx Overlay& GetOverlay(size_t i = 0) { assert( i < Overlays.size() ); return Overlays[i]; } const Overlay& GetOverlay(size_t i = 0) const { assert( i < Overlays.size() ); return Overlays[i]; } size_t GetNumberOfOverlays() const { return Overlays.size(); } void SetNumberOfOverlays(size_t n) { Overlays.resize(n); } void RemoveOverlay(size_t i) { assert( i < Overlays.size() ); Overlays.erase( Overlays.begin() + i ); } /// Set/Get Icon Image const IconImage &GetIconImage() const { return *Icon; } IconImage &GetIconImage() { return *Icon; } void SetIconImage(IconImage const &ii) { Icon = ii; } //private: protected: std::vector Overlays; std::vector Curves; SmartPointer Icon; }; } // end namespace gdcm #endif //GDCMPIXMAP_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPixmapReader.cxx000066400000000000000000001401121412732066400244510ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPixmapReader.h" #include "gdcmExplicitDataElement.h" #include "gdcmImplicitDataElement.h" #include "gdcmValue.h" #include "gdcmFileMetaInformation.h" #include "gdcmElement.h" #include "gdcmPhotometricInterpretation.h" #include "gdcmSegmentedPaletteColorLookupTable.h" #include "gdcmTransferSyntax.h" #include "gdcmLookupTable.h" #include "gdcmAttribute.h" #include "gdcmIconImage.h" #include "gdcmPrivateTag.h" #include "gdcmJPEGCodec.h" #include "gdcmImageHelper.h" namespace gdcm { PixmapReader::PixmapReader():PixelData(new Pixmap) { } PixmapReader::~PixmapReader() = default; const Pixmap& PixmapReader::GetPixmap() const { return *PixelData; } Pixmap& PixmapReader::GetPixmap() { return *PixelData; } //void PixmapReader::SetPixmap(Pixmap const &img) //{ // PixelData = img; //} bool PixmapReader::Read() { if( !Reader::Read() ) { // cemra_bug/IM-0001-0066.dcm // will return from the parser with an error // but a partial Pixel Data can be seen return false; } const FileMetaInformation &header = F->GetHeader(); const DataSet &ds = F->GetDataSet(); const TransferSyntax &ts = header.GetDataSetTransferSyntax(); // Need to set the type of image we are dealing with: PixelData->SetTransferSyntax( ts ); bool res = false; /* Does it really make sense to check for Media Storage SOP Class UID? * I need then to check consistency with 0008 0016 Instance SOP Class UID * ... I don't think there is an end. * I'd rather go the old way check a bunch of tags (From Image Plane * Module). */ MediaStorage ms = header.GetMediaStorage(); bool isImage = MediaStorage::IsImage( ms ); if( isImage ) { // I cannot leave this here, since ELSCINT1 / LOSSLESS RICE declares CT Image Storage, // when in fact this is a private Media Storage (no Pixel Data element) //assert( ds.FindDataElement( Tag(0x7fe0,0x0010 ) ) ); assert( ts != TransferSyntax::TS_END && ms != MediaStorage::MS_END ); // Good it's the easy case. It's declared as an Image: //PixelData->SetCompressionFromTransferSyntax( ts ); res = ReadImage(ms); } //else if( ms == MediaStorage::MRSpectroscopyStorage ) // { // res = ReadImage(ms); // } else { MediaStorage ms2 = ds.GetMediaStorage(); //assert( !ds.FindDataElement( Tag(0x7fe0,0x0010 ) ) ); if( ms == MediaStorage::MediaStorageDirectoryStorage && ms2 == MediaStorage::MS_END ) { gdcmDebugMacro( "DICOM file is not an Image file but a : " << MediaStorage::GetMSString(ms) << " SOP Class UID" ); res = false; } else if( ms == ms2 && ms != MediaStorage::MS_END ) { gdcmDebugMacro( "DICOM file is not an Image file but a : " << MediaStorage::GetMSString(ms) << " SOP Class UID" ); res = false; } else { if( ms2 != MediaStorage::MS_END ) { bool isImage2 = MediaStorage::IsImage( ms2 ); if( isImage2 ) { gdcmDebugMacro( "After all it might be a DICOM file " "(Mallinckrodt-like)" ); //PixelData->SetCompressionFromTransferSyntax( ts ); //PixelData->SetCompressionType( Compression::RAW ); res = ReadImage(ms2); } else { ms2.SetFromFile( *F ); if( MediaStorage::IsImage( ms2 ) ) { res = ReadImage(ms2); } else { gdcmDebugMacro( "DICOM file is not an Image file but a : " << MediaStorage::GetMSString(ms2) << " SOP Class UID" ); res = false; } } } else if( ts == TransferSyntax::ImplicitVRBigEndianACRNEMA || header.IsEmpty() ) { // Those transfer syntax have a high probability of being ACR NEMA gdcmDebugMacro( "Looks like an ACR-NEMA file" ); // Hopefully all ACR-NEMA are RAW: //PixelData->SetCompressionType( Compression::RAW ); res = ReadACRNEMAImage(); } else // there is a Unknown Media Storage Syntax { assert( ts != TransferSyntax::TS_END && ms == MediaStorage::MS_END ); // god damit I don't know what to do... gdcmWarningMacro( "Attempting to read this file as a DICOM file" "\nDesperate attempt" ); MediaStorage ms3; ms3.SetFromFile( GetFile() ); if( ms3 != MediaStorage::MS_END ) { res = ReadImage(ms3); } else { // Giving up res = false; } } } } //if(res) PixelData->Print( std::cout ); return res; } // PICKER-16-MONO2-Nested_icon.dcm static void DoIconImage(const DataSet& rootds, Pixmap& image) { const Tag ticonimage(0x0088,0x0200); IconImage &pixeldata = image.GetIconImage(); if( rootds.FindDataElement( ticonimage ) ) { const DataElement &iconimagesq = rootds.GetDataElement( ticonimage ); //const SequenceOfItems* sq = iconimagesq.GetSequenceOfItems(); SmartPointer sq = iconimagesq.GetValueAsSQ(); // Is SQ empty ? if( !sq || sq->IsEmpty() ) return; SequenceOfItems::ConstIterator it = sq->Begin(); const DataSet &ds = it->GetNestedDataSet(); // D 0028|0011 [US] [Columns] [512] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0011) ); Attribute<0x0028,0x0011> at = { 0 }; at.SetFromDataSet( ds ); pixeldata.SetDimension(0, at.GetValue() ); } // D 0028|0010 [US] [Rows] [512] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0010) ); Attribute<0x0028,0x0010> at = { 0 }; at.SetFromDataSet( ds ); pixeldata.SetDimension(1, at.GetValue() ); } PixelFormat pf; // D 0028|0100 [US] [Bits Allocated] [16] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0100) ); Attribute<0x0028,0x0100> at = { 0 }; at.SetFromDataSet( ds ); pf.SetBitsAllocated( at.GetValue() ); } // D 0028|0101 [US] [Bits Stored] [12] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0101) ); Attribute<0x0028,0x0101> at = { 0 }; at.SetFromDataSet( ds ); pf.SetBitsStored( at.GetValue() ); } // D 0028|0102 [US] [High Bit] [11] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0102) ); Attribute<0x0028,0x0102> at = { 0 }; at.SetFromDataSet( ds ); pf.SetHighBit( at.GetValue() ); } // D 0028|0103 [US] [Pixel Representation] [0] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0103) ); Attribute<0x0028,0x0103> at = { 0 }; at.SetFromDataSet( ds ); pf.SetPixelRepresentation( at.GetValue() ); } // (0028,0002) US 1 # 2, 1 SamplesPerPixel { //if( ds.FindDataElement( Tag(0x0028, 0x0002) ) ) { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0002) ); Attribute<0x0028,0x0002> at = { 1 }; at.SetFromDataSet( ds ); pf.SetSamplesPerPixel( at.GetValue() ); } // else pf will default to 1... } pixeldata.SetPixelFormat( pf ); // D 0028|0004 [CS] [Photometric Interpretation] [MONOCHROME2 ] const Tag tphotometricinterpretation(0x0028, 0x0004); PhotometricInterpretation pi = PhotometricInterpretation::MONOCHROME2; if( ds.FindDataElement( tphotometricinterpretation ) ) { const ByteValue *photometricinterpretation = ds.GetDataElement( tphotometricinterpretation ).GetByteValue(); std::string photometricinterpretation_str( photometricinterpretation->GetPointer(), photometricinterpretation->GetLength() ); pi = PhotometricInterpretation::GetPIType( photometricinterpretation_str.c_str()); } assert( pi != PhotometricInterpretation::UNKNOWN); pixeldata.SetPhotometricInterpretation( pi ); // if ( pi == PhotometricInterpretation::PALETTE_COLOR ) { SmartPointer lut = new LookupTable; const Tag testseglut(0x0028, (0x1221 + 0)); if( ds.FindDataElement( testseglut ) ) { assert(0 && "Please report this image"); lut = new SegmentedPaletteColorLookupTable; } //SmartPointer lut = new SegmentedPaletteColorLookupTable; lut->Allocate( pf.GetBitsAllocated() ); // for each red, green, blue: for(int i=0; i<3; ++i) { // (0028,1101) US 0\0\16 // (0028,1102) US 0\0\16 // (0028,1103) US 0\0\16 const Tag tdescriptor(0x0028, (uint16_t)(0x1101 + i)); //const Tag tdescriptor(0x0028, 0x3002); Element el_us3; // Now pass the byte array to a DICOMizer: el_us3.SetFromDataElement( ds[tdescriptor] ); //.GetValue() ); lut->InitializeLUT( LookupTable::LookupTableType(i), el_us3[0], el_us3[1], el_us3[2] ); // (0028,1201) OW // (0028,1202) OW // (0028,1203) OW const Tag tlut(0x0028, (uint16_t)(0x1201 + i)); //const Tag tlut(0x0028, 0x3006); // Segmented LUT // (0028,1221) OW // (0028,1222) OW // (0028,1223) OW const Tag seglut(0x0028, (uint16_t)(0x1221 + i)); if( ds.FindDataElement( tlut ) ) { const ByteValue *lut_raw = ds.GetDataElement( tlut ).GetByteValue(); assert( lut_raw ); // LookupTableType::RED == 0 lut->SetLUT( LookupTable::LookupTableType(i), (const unsigned char*)lut_raw->GetPointer(), lut_raw->GetLength() ); //assert( pf.GetBitsAllocated() == el_us3.GetValue(2) ); unsigned long check = (el_us3.GetValue(0) ? el_us3.GetValue(0) : 65536) * el_us3.GetValue(2) / 8; assert( check == lut_raw->GetLength() || 2 * check == lut_raw->GetLength() || check + 1 == lut_raw->GetLength() ); (void)check; } else if( ds.FindDataElement( seglut ) ) { const ByteValue *lut_raw = ds.GetDataElement( seglut ).GetByteValue(); assert( lut_raw ); lut->SetLUT( LookupTable::LookupTableType(i), (const unsigned char*)lut_raw->GetPointer(), lut_raw->GetLength() ); //assert( pf.GetBitsAllocated() == el_us3.GetValue(2) ); //unsigned long check = // (el_us3.GetValue(0) ? el_us3.GetValue(0) : 65536) // * el_us3.GetValue(2) / 8; //assert( check == lut_raw->GetLength() ); (void)check; } else { gdcmWarningMacro( "Icon Sequence is incomplete. Giving up" ); pixeldata.Clear(); return; } } pixeldata.SetLUT(*lut); } const Tag tpixeldata = Tag(0x7fe0, 0x0010); if( !ds.FindDataElement( tpixeldata ) ) { gdcmWarningMacro( "Icon Sequence is incomplete. Giving up" ); pixeldata.Clear(); return; } const DataElement& de = ds.GetDataElement( tpixeldata ); pixeldata.SetDataElement( de ); // Pass TransferSyntax: // Warning This is legal for the Icon to be uncompress in a compressed image // We need to set the appropriate TS here: const ByteValue *bv = de.GetByteValue(); if( bv ) pixeldata.SetTransferSyntax( TransferSyntax::ImplicitVRLittleEndian ); else pixeldata.SetTransferSyntax( image.GetTransferSyntax() ); } } // GE_DLX-8-MONO2-Multiframe.dcm static void DoCurves(const DataSet& ds, Pixmap& pixeldata) { unsigned int numcurves; if( (numcurves = Curve::GetNumberOfCurves( ds )) ) { pixeldata.SetNumberOfCurves( numcurves ); Tag curve(0x5000,0x0000); bool finished = false; unsigned int idxcurves = 0; while( !finished ) { const DataElement &de = ds.FindNextDataElement( curve ); // Are we done: if( de.GetTag().GetGroup() > 0x50FF ) // last possible curve curve { finished = true; } else if( de.GetTag().IsPrivate() ) // GEMS owns some 0x5003 { // Move on to the next public one: curve.SetGroup( (uint16_t)(de.GetTag().GetGroup() + 1) ); curve.SetElement( 0 ); } else { // Yay! this is an curve element Curve &ov = pixeldata.GetCurve(idxcurves); ++idxcurves; // move on to the next one curve = de.GetTag(); uint16_t currentcurve = curve.GetGroup(); assert( !(currentcurve % 2) ); // 0x6001 is not an curve... // Now loop on all element from this current group: DataElement de2 = de; while( de2.GetTag().GetGroup() == currentcurve ) { ov.Update(de2); curve.SetElement( (uint16_t)(de2.GetTag().GetElement() + 1) ); de2 = ds.FindNextDataElement( curve ); // Next element: //curve.SetElement( curve.GetElement() + 1 ); } // If we exit the loop we have pass the current curve and potentially point to the next one: //curve.SetElement( curve.GetElement() + 1 ); //ov.Print( std::cout ); } } //std::cout << "Num of curves: " << numcurves << std::endl; assert( idxcurves == numcurves ); } } static unsigned int GetNumberOfOverlaysInternal(DataSet const & ds, std::vector & overlaylist) { Tag overlay(0x6000,0x0000); // First possible overlay bool finished = false; unsigned int numoverlays = 0; while( !finished ) { const DataElement &de = ds.FindNextDataElement( overlay ); if( de.GetTag().GetGroup() > 0x60FF ) // last possible curve { finished = true; } else if( de.GetTag().IsPrivate() ) { // Move on to the next public one: overlay.SetGroup( (uint16_t)(de.GetTag().GetGroup() + 1) ); overlay.SetElement( 0 ); // reset just in case... } else { // Yeah this is a potential overlay element, let's check this is not a broken LEADTOOL image, // or prova0001.dcm: // (5000,0000) UL 0 # 4, 1 GenericGroupLength // (6000,0000) UL 0 # 4, 1 GenericGroupLength // (6001,0000) UL 28 # 4, 1 PrivateGroupLength // (6001,0010) LT [PAPYRUS 3.0] # 12, 1 PrivateCreator // (6001,1001) LT (no value available) # 0, 0 Unknown Tag & Data /* * FIXME: * In order to support : gdcmData/SIEMENS_GBS_III-16-ACR_NEMA_1.acr * gdcmDataExtra/gdcmSampleData/images_of_interest/XA_GE_JPEG_02_with_Overlays.dcm * I cannot simply check for overlay_group,3000 this would not work * I would need a strong euristick */ // Store found tag in overlay: overlay = de.GetTag(); // heuristic based on either the Overlay Data or the Col/Row info Tag toverlaydata(overlay.GetGroup(),0x3000 ); Tag toverlayrows(overlay.GetGroup(),0x0010 ); Tag toverlaycols(overlay.GetGroup(),0x0011 ); Tag toverlaybitpos(overlay.GetGroup(),0x0102 ); if( ds.FindDataElement( toverlaydata ) ) { // ok so far so good... const DataElement& overlaydata = ds.GetDataElement( toverlaydata ); //const DataElement& overlaydata = ds.GetDataElement(Tag(overlay.GetGroup(),0x0010)); if( !overlaydata.IsEmpty() ) { ++numoverlays; overlaylist.push_back( overlay.GetGroup() ); } } else if( ds.FindDataElement( toverlayrows ) && ds.FindDataElement( toverlaycols ) && ds.FindDataElement( toverlaybitpos ) ) { // Overlay Pixel are in Unused Pixel assert( !ds.FindDataElement( toverlaydata ) ); const DataElement& overlayrows = ds.GetDataElement( toverlayrows ); const DataElement& overlaycols = ds.GetDataElement( toverlaycols ); assert( ds.FindDataElement( toverlaybitpos ) ); const DataElement& overlaybitpos = ds.GetDataElement( toverlaybitpos ); if( !overlayrows.IsEmpty() && !overlaycols.IsEmpty() && !overlaybitpos.IsEmpty() ) { ++numoverlays; overlaylist.push_back( overlay.GetGroup() ); } } // Move on to the next possible one: overlay.SetGroup( (uint16_t)(overlay.GetGroup() + 2) ); // reset to element 0x0 just in case... overlay.SetElement( 0 ); } } // at most one out of two : assert( numoverlays < 0x00ff / 2 ); // PS 3.3 - 2004: // C.9.2 Overlay plane module // Each Overlay Plane is one bit deep. Sixteen separate Overlay Planes may be associated with an // Image or exist as Standalone Overlays in a Series assert( numoverlays <= 16 ); assert( numoverlays == overlaylist.size() ); return numoverlays; } static bool DoOverlays(const DataSet& ds, Pixmap& pixeldata) { unsigned int numoverlays; std::vector overlaylist; std::vector updateoverlayinfo; if( (numoverlays = GetNumberOfOverlaysInternal( ds, overlaylist )) ) { updateoverlayinfo.resize(numoverlays, false); pixeldata.SetNumberOfOverlays( numoverlays ); for( unsigned int idxoverlays = 0; idxoverlays < numoverlays; ++idxoverlays ) { Overlay &ov = pixeldata.GetOverlay(idxoverlays); uint16_t currentoverlay = overlaylist[idxoverlays]; Tag overlay(0x6000,0x0000); overlay.SetGroup( currentoverlay ); const DataElement &de = ds.FindNextDataElement( overlay ); assert( !(currentoverlay % 2) ); // 0x6001 is not an overlay... // Now loop on all element from this current group: DataElement de2 = de; while( de2.GetTag().GetGroup() == currentoverlay ) { ov.Update(de2); overlay.SetElement( (uint16_t)(de2.GetTag().GetElement() + 1) ); de2 = ds.FindNextDataElement( overlay ); } // Let's decode it: std::ostringstream unpack; ov.Decompress( unpack ); std::string s = unpack.str(); //size_t l = s.size(); // The following line will fail with images like XA_GE_JPEG_02_with_Overlays.dcm // since the overlays are stored in the unused bit of the PixelData if( !ov.IsEmpty() ) { //assert( unpack.str().size() / 8 == ((ov.GetRows() * ov.GetColumns()) + 7 ) / 8 ); assert( ov.IsInPixelData( ) == false ); } else if( pixeldata.GetPixelFormat().GetSamplesPerPixel() == 1 ) { assert( ov.IsEmpty() ); gdcmDebugMacro( "This image does not contains Overlay in the 0x60xx tags. " << "Instead the overlay is stored in the unused bit of the Pixel Data." << std::endl ); ov.IsInPixelData( true ); // make sure Overlay is valid if( ov.GetBitsAllocated() != pixeldata.GetPixelFormat().GetBitsAllocated() ) { gdcmWarningMacro( "Bits Allocated are wrong. Correcting." ); ov.SetBitsAllocated( pixeldata.GetPixelFormat().GetBitsAllocated() ); } if( !ov.GrabOverlayFromPixelData(ds) ) { gdcmWarningMacro( "Could not extract Overlay from Pixel Data" ); //throw Exception("TODO: Could not extract Overlay Data"); } updateoverlayinfo[idxoverlays] = true; } else { // http://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.9.2.html // Overlay data stored in unused bit planes of Pixel Data (7FE0,0010) // with Samples Per Pixel (0028,0002) of 1 was previously described in // DICOM. gdcmWarningMacro( "Overlay was found, while PI is: " << pixeldata.GetPhotometricInterpretation() << " skipping."); } } //std::cout << "Num of Overlays: " << numoverlays << std::endl; } // Now is good time to do some cleanup (eg. DX_GE_FALCON_SNOWY-VOI.dcm). const PixelFormat &pf = pixeldata.GetPixelFormat(); // Yes I am using a call in the for() loop, because I internally modify the // number of overlays: for( size_t ov_idx = pixeldata.GetNumberOfOverlays(); ov_idx != 0; --ov_idx ) { size_t ov = ov_idx - 1; const Overlay& o = pixeldata.GetOverlay(ov); if( o.IsInPixelData() ) { unsigned short obp = o.GetBitPosition(); if( obp < pf.GetBitsStored() ) { pixeldata.RemoveOverlay( ov ); updateoverlayinfo.erase( updateoverlayinfo.begin() + ov ); gdcmWarningMacro( "Invalid BitPosition: " << obp << " for overlay #" << ov << " removing it." ); } else if( obp > pf.GetBitsAllocated() ) { pixeldata.RemoveOverlay( ov ); updateoverlayinfo.erase( updateoverlayinfo.begin() + ov ); gdcmWarningMacro( "Invalid BitPosition: " << obp << " for overlay #" << ov << " removing it." ); } } } for( size_t ov = 0; ov < pixeldata.GetNumberOfOverlays() && updateoverlayinfo[ov] ; ++ov ) { Overlay& o = pixeldata.GetOverlay(ov); // We need to update information if( o.GetBitsAllocated() == 16 ) { o.SetBitsAllocated( 1 ); o.SetBitPosition( 0 ); } else { gdcmErrorMacro( "Overlay #" << ov << " is not supported" ); return false; } } return true; } bool PixmapReader::ReadImage(MediaStorage const &ms) { return ReadImageInternal(ms); } bool PixmapReader::ReadImageInternal(MediaStorage const &ms, bool handlepixeldata ) { const DataSet &ds = F->GetDataSet(); std::string conversion; bool isacrnema = false; const Tag trecognitioncode(0x0008,0x0010); if( ds.FindDataElement( trecognitioncode ) && !ds.GetDataElement( trecognitioncode ).IsEmpty() ) { // PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm // PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm gdcmDebugMacro( "Mixture of ACR NEMA and DICOM file" ); isacrnema = true; const char *str = ds.GetDataElement( trecognitioncode ).GetByteValue()->GetPointer(); assert( strncmp( str, "ACR-NEMA", strlen( "ACR-NEMA" ) ) == 0 || strncmp( str, "ACRNEMA", strlen( "ACRNEMA" ) ) == 0 || strncmp( str, "MIPS 2.0", strlen( "MIPS 2.0" ) ) == 0 ); (void)str;//warning removal } std::vector vdims = ImageHelper::GetDimensionsValue(*F); unsigned int numberofframes = vdims[2]; // What should I do when numberofframes == 0 ? if( numberofframes > 1 ) { PixelData->SetNumberOfDimensions(3); PixelData->SetDimension(2, numberofframes ); } else { gdcmDebugMacro( "NumberOfFrames was specified with a value of: " << numberofframes ); PixelData->SetNumberOfDimensions(2); } // 2. What are the col & rows: PixelData->SetDimension(0, vdims[0] ); PixelData->SetDimension(1, vdims[1] ); // 3. Pixel Format ? PixelFormat pf; // D 0028|0002 [US] [Samples per Pixel] [1] { Attribute<0x0028,0x0002> at = { 1 }; // By default assume 1 Samples Per Pixel at.SetFromDataSet( ds ); pf.SetSamplesPerPixel( at.GetValue() ); } if( ms == MediaStorage::MRSpectroscopyStorage ) { pf.SetScalarType( PixelFormat::FLOAT32 ); } else { assert( MediaStorage::IsImage( ms ) ); // D 0028|0100 [US] [Bits Allocated] [16] //pf.SetBitsAllocated( // ReadUSFromTag( Tag(0x0028, 0x0100), ss, conversion ) ); { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0100) ); Attribute<0x0028,0x0100> at = { 0 }; at.SetFromDataSet( ds ); pf.SetBitsAllocated( at.GetValue() ); //assert( at.GetValue() == ReadUSFromTag( Tag(0x0028, 0x0100), ss, conversion ) ); } // D 0028|0101 [US] [Bits Stored] [12] //pf.SetBitsStored( // ReadUSFromTag( Tag(0x0028, 0x0101), ss, conversion ) ); { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0101) ); Attribute<0x0028,0x0101> at = { 0 }; at.SetFromDataSet( ds ); pf.SetBitsStored( at.GetValue() ); //assert( at.GetValue() == ReadUSFromTag( Tag(0x0028, 0x0101), ss, conversion ) ); } // D 0028|0102 [US] [High Bit] [11] //pf.SetHighBit( // ReadUSFromTag( Tag(0x0028, 0x0102), ss, conversion ) ); { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0102) ); Attribute<0x0028,0x0102> at = { 0 }; at.SetFromDataSet( ds ); pf.SetHighBit( at.GetValue() ); //assert( at.GetValue() == ReadUSFromTag( Tag(0x0028, 0x0102), ss, conversion ) ); } // D 0028|0103 [US] [Pixel Representation] [0] //Tag tpixelrep(0x0028, 0x0103); //if( ds.FindDataElement( tpixelrep ) && !ds.GetDataElement( tpixelrep ).IsEmpty() ) { //pf.SetPixelRepresentation( // ReadUSFromTag( Tag(0x0028, 0x0103), ss, conversion ) ); //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0103) ); Attribute<0x0028,0x0103> at = { 0 }; at.SetFromDataSet( ds ); pf.SetPixelRepresentation( at.GetValue() ); //assert( at.GetValue() == ReadUSFromTag( Tag(0x0028, 0x0103), ss, conversion ) ); } // else // { // gdcmWarningMacro( "Pixel Representation was not found. Default to Unsigned Pixel Representation" ); // pf.SetPixelRepresentation( 0 ); // } } // 5. Photometric Interpretation // D 0028|0004 [CS] [Photometric Interpretation] [MONOCHROME2 ] const Tag tphotometricinterpretation(0x0028, 0x0004); const ByteValue *photometricinterpretation = ImageHelper::GetPointerFromElement( tphotometricinterpretation, *F ); PhotometricInterpretation pi = PhotometricInterpretation::UNKNOWN; if( photometricinterpretation ) { std::string photometricinterpretation_str( photometricinterpretation->GetPointer(), photometricinterpretation->GetLength() ); pi = PhotometricInterpretation::GetPIType( photometricinterpretation_str.c_str() ); // http://www.dominator.com/assets/003/5278.pdf // JPEG 2000 lossless YUV_RCT if( pi == PhotometricInterpretation::PI_END ) { gdcmWarningMacro( "Discarding suspicious PhotometricInterpretation found: " << photometricinterpretation_str ); } } // try again harder: if( !photometricinterpretation || pi == PhotometricInterpretation::PI_END ) { if( pf.GetSamplesPerPixel() == 1 ) { gdcmWarningMacro( "No PhotometricInterpretation found, default to MONOCHROME2" ); pi = PhotometricInterpretation::MONOCHROME2; } else if( pf.GetSamplesPerPixel() == 3 ) { gdcmWarningMacro( "No PhotometricInterpretation found, default to RGB" ); pi = PhotometricInterpretation::RGB; } else if( pf.GetSamplesPerPixel() == 4 ) { gdcmWarningMacro( "No PhotometricInterpretation found, default to ARGB" ); pi = PhotometricInterpretation::ARGB; } else { gdcmWarningMacro( "Impossible value for Samples Per Pixel: " << pf.GetSamplesPerPixel() ); return false; } } assert( pi != PhotometricInterpretation::PI_END ); if( !pf.GetSamplesPerPixel() || (pi.GetSamplesPerPixel() != pf.GetSamplesPerPixel()) ) { if( pi != PhotometricInterpretation::UNKNOWN ) { pf.SetSamplesPerPixel( pi.GetSamplesPerPixel() ); } else if ( isacrnema ) { assert ( pf.GetSamplesPerPixel() == 0 ); assert ( pi == PhotometricInterpretation::UNKNOWN ); pf.SetSamplesPerPixel( 1 ); pi = PhotometricInterpretation::MONOCHROME2; } else { gdcmWarningMacro( "Cannot recognize image type. Does not looks like" "ACR-NEMA and is missing both Sample Per Pixel AND PhotometricInterpretation." "Please report" ); return false; } } assert ( pf.GetSamplesPerPixel() != 0 ); // Very important to set the PixelFormat here before PlanarConfiguration PixelData->SetPixelFormat( pf ); pf = PixelData->GetPixelFormat(); if( !pf.IsValid() ) { return false; } if( pi == PhotometricInterpretation::UNKNOWN ) return false; PixelData->SetPhotometricInterpretation( pi ); // 4. Planar Configuration // D 0028|0006 [US] [Planar Configuration] [1] const Tag planarconfiguration = Tag(0x0028, 0x0006); // FIXME: Whatif planaconfiguration is send in a grayscale image... it would be empty... // well hopefully :( if( ds.FindDataElement( planarconfiguration ) && !ds.GetDataElement( planarconfiguration ).IsEmpty() ) { const DataElement& de = ds.GetDataElement( planarconfiguration ); Attribute<0x0028,0x0006> at = { 0 }; at.SetFromDataElement( de ); //unsigned int pc = ReadUSFromTag( planarconfiguration, ss, conversion ); unsigned int pc = at.GetValue(); if( pc && PixelData->GetPixelFormat().GetSamplesPerPixel() != 3 ) { gdcmDebugMacro( "Cannot have PlanarConfiguration=1, when Sample Per Pixel != 3" ); pc = 0; } PixelData->SetPlanarConfiguration( pc ); } // Do the Palette Color: // 1. Modality LUT Sequence bool modlut = ds.FindDataElement(Tag(0x0028,0x3000) ); if( modlut ) { gdcmWarningMacro( "Modality LUT (0028,3000) are not handled. Image will not be displayed properly" ); } // 2. LUTData (0028,3006) // technically I do not need to warn about LUTData since either modality lut XOR VOI LUT need to // be sent to require a LUT Data... bool lutdata = ds.FindDataElement(Tag(0x0028,0x3006) ); if( lutdata ) { gdcmWarningMacro( "LUT Data (0028,3006) are not handled. Image will not be displayed properly" ); } // 3. VOILUTSequence (0028,3010) bool voilut = ds.FindDataElement(Tag(0x0028,0x3010) ); if( voilut ) { gdcmWarningMacro( "VOI LUT (0028,3010) are not handled. Image will not be displayed properly" ); } // (0028,0120) US 32767 # 2, 1 PixelPaddingValue bool pixelpaddingvalue = ds.FindDataElement(Tag(0x0028,0x0120)); // PS 3.3 - 2008 / C.7.5.1.1.2 Pixel Padding Value and Pixel Padding Range Limit if(pixelpaddingvalue) { // Technically if Pixel Padding Value is 0 on MONOCHROME2 image, then appearance should be fine... bool vizissue = true; if( pf.GetPixelRepresentation() == 0 ) { Element ppv; if( !ds.GetDataElement(Tag(0x0028,0x0120) ).IsEmpty() ) { ppv.SetFromDataElement( ds.GetDataElement(Tag(0x0028,0x0120)) ); //.GetValue() ); if( pi == PhotometricInterpretation::MONOCHROME2 && ppv.GetValue() == 0 ) { vizissue = false; } } } else if( pf.GetPixelRepresentation() == 1 ) { gdcmDebugMacro( "TODO" ); } // test if there is any viz issue: if( vizissue ) { gdcmDebugMacro( "Pixel Padding Value (0028,0120) is not handled. Image will not be displayed properly" ); } } // 4. Palette Color Lookup Table Descriptor if ( pi == PhotometricInterpretation::PALETTE_COLOR ) { //const DataElement& modlutsq = ds.GetDataElement( Tag(0x0028,0x3000) ); //const SequenceOfItems* sq = modlutsq.GetSequenceOfItems(); //SequenceOfItems::ConstIterator it = sq->Begin(); //const DataSet &ds = it->GetNestedDataSet(); SmartPointer lut = new LookupTable; const Tag testseglut(0x0028, (0x1221 + 0)); if( ds.FindDataElement( testseglut ) ) { lut = new SegmentedPaletteColorLookupTable; } //SmartPointer lut = new SegmentedPaletteColorLookupTable; lut->Allocate( pf.GetBitsAllocated() ); // for each red, green, blue: for(int i=0; i<3; ++i) { // (0028,1101) US 0\0\16 // (0028,1102) US 0\0\16 // (0028,1103) US 0\0\16 const Tag tdescriptor(0x0028, (uint16_t)(0x1101 + i)); //const Tag tdescriptor(0x0028, 0x3002); Element el_us3 = {{ 0, 0, 0}}; // Now pass the byte array to a DICOMizer: el_us3.SetFromDataElement( ds[tdescriptor] ); //.GetValue() ); lut->InitializeLUT( LookupTable::LookupTableType(i), el_us3[0], el_us3[1], el_us3[2] ); // (0028,1201) OW // (0028,1202) OW // (0028,1203) OW const Tag tlut(0x0028, (uint16_t)(0x1201 + i)); //const Tag tlut(0x0028, 0x3006); // Segmented LUT // (0028,1221) OW // (0028,1222) OW // (0028,1223) OW const Tag seglut(0x0028, (uint16_t)(0x1221 + i)); if( ds.FindDataElement( tlut ) ) { const ByteValue *lut_raw = ds.GetDataElement( tlut ).GetByteValue(); if( lut_raw ) { // LookupTableType::RED == 0 lut->SetLUT( LookupTable::LookupTableType(i), (const unsigned char*)lut_raw->GetPointer(), lut_raw->GetLength() ); //assert( pf.GetBitsAllocated() == el_us3.GetValue(2) ); } else { lut->Clear(); } unsigned long check = (el_us3.GetValue(0) ? el_us3.GetValue(0) : 65536) * el_us3.GetValue(2) / 8; assert( !lut->Initialized() || check == lut_raw->GetLength() ); (void)check; } else if( ds.FindDataElement( seglut ) ) { const ByteValue *lut_raw = ds.GetDataElement( seglut ).GetByteValue(); if( lut_raw ) { lut->SetLUT( LookupTable::LookupTableType(i), (const unsigned char*)lut_raw->GetPointer(), lut_raw->GetLength() ); //assert( pf.GetBitsAllocated() == el_us3.GetValue(2) ); } else { lut->Clear(); } //unsigned long check = // (el_us3.GetValue(0) ? el_us3.GetValue(0) : 65536) // * el_us3.GetValue(2) / 8; //assert( check == lut_raw->GetLength() ); (void)check; } else { gdcmAssertAlwaysMacro(0); } } if( ! lut->Initialized() ) return false; PixelData->SetLUT(*lut); } // TODO //assert( pi.GetSamplesPerPixel() == pf.GetSamplesPerPixel() ); // 5.5 Do IconImage if any assert( PixelData->GetIconImage().IsEmpty() ); DoIconImage(ds, *PixelData); // 6. Do the Curves if any DoCurves(ds, *PixelData); // 7. Do the Overlays if any if( !DoOverlays(ds, *PixelData) ) { return false; } // 8. Do the PixelData if( handlepixeldata ) { if( ms == MediaStorage::MRSpectroscopyStorage ) { const Tag spectdata = Tag(0x5600, 0x0020); if( !ds.FindDataElement( spectdata ) ) { gdcmWarningMacro( "No Spectroscopy Data Found" ); return false; } const DataElement& xde = ds.GetDataElement( spectdata ); //bool need = PixelData->GetTransferSyntax() == TransferSyntax::ImplicitVRBigEndianPrivateGE; //PixelData->SetNeedByteSwap( need ); PixelData->SetDataElement( xde ); } else { const Tag pixeldata = Tag(0x7fe0, 0x0010); if( !ds.FindDataElement( pixeldata ) ) { gdcmWarningMacro( "No Pixel Data Found" ); return false; } const DataElement& xde = ds.GetDataElement( pixeldata ); bool need = PixelData->GetTransferSyntax() == TransferSyntax::ImplicitVRBigEndianPrivateGE; PixelData->SetNeedByteSwap( need ); PixelData->SetDataElement( xde ); if( PixelData->GetTransferSyntax().IsEncapsulated() && PixelData->GetDataElement().GetByteValue() ) { // Pixel Data attribute is not encapsulated, let's check for simple user error const ByteValue *bv = PixelData->GetDataElement().GetByteValue(); if( bv->GetLength() == PixelData->GetBufferLength() || bv->GetLength() == PixelData->GetBufferLength() + 1 ) { gdcmWarningMacro( "Pixel Data was found to be raw. Fixing invalid Transfer Syntax: " << PixelData->GetTransferSyntax() ); PixelData->SetTransferSyntax( TransferSyntax::ExplicitVRLittleEndian ); } } // FIXME: // We should check that when PixelData is RAW that Col * Dim == PixelData->GetLength() //PixelFormat guesspf = PixelFormat->GuessPixelFormat(); } const unsigned int *dims = PixelData->GetDimensions(); if( dims[0] == 0 || dims[1] == 0 ) { // Pseudo-declared JPEG SC image storage. Let's fix col/row/pf/pi JPEGCodec jpeg; if( jpeg.CanDecode( PixelData->GetTransferSyntax() ) ) { std::stringstream ss; const DataElement &de = PixelData->GetDataElement(); //const ByteValue *bv = de.GetByteValue(); const SequenceOfFragments *sqf = de.GetSequenceOfFragments(); if( !sqf ) { // TODO: It would be nice to recognize file such as JPEGDefinedLengthSequenceOfFragments.dcm gdcmDebugMacro( "File is declared as JPEG compressed but does not contains Fragments explicitly." ); return false; } sqf->WriteBuffer( ss ); //std::string s( bv->GetPointer(), bv->GetLength() ); //is.str( s ); PixelFormat jpegpf ( PixelFormat::UINT8 ); // usual guess... jpeg.SetPixelFormat( jpegpf ); TransferSyntax ts; bool b = jpeg.GetHeaderInfo( ss, ts ); if( b ) { std::vector v(3); v[0] = PixelData->GetDimensions()[0]; v[1] = PixelData->GetDimensions()[1]; v[2] = PixelData->GetDimensions()[2]; assert( jpeg.GetDimensions()[0] ); assert( jpeg.GetDimensions()[1] ); v[0] = jpeg.GetDimensions()[0]; v[1] = jpeg.GetDimensions()[1]; PixelData->SetDimensions( &v[0] ); //PixelData->SetPixelFormat( jpeg.GetPixelFormat() ); // need to handle carefully if( PixelData->GetPixelFormat().GetSamplesPerPixel() != jpeg.GetPixelFormat().GetSamplesPerPixel() ) { gdcmDebugMacro( "Fix samples per pixel." ); PixelData->GetPixelFormat().SetSamplesPerPixel( jpeg.GetPixelFormat().GetSamplesPerPixel() ); } //PixelData->SetPhotometricInterpretation( jpeg.GetPhotometricInterpretation() ); if( PixelData->GetPhotometricInterpretation().GetSamplesPerPixel() != jpeg.GetPhotometricInterpretation().GetSamplesPerPixel() ) { gdcmDebugMacro( "Fix photometric interpretation." ); PixelData->SetPhotometricInterpretation( jpeg.GetPhotometricInterpretation() ); } assert( PixelData->IsTransferSyntaxCompatible( ts ) ); } else { gdcmDebugMacro( "Columns or Row was found to be 0. Cannot compute dimension." ); return false; } } else { gdcmDebugMacro( "Columns or Row was found to be 0. Cannot compute dimension." ); return false; } } } // Let's be smart when computing the lossyflag (0028,2110) // LossyImageCompression Attribute<0x0028,0x2110> licat; bool lossyflag = false; bool haslossyflag = false; if( ds.FindDataElement( licat.GetTag() ) ) { haslossyflag = true; licat.SetFromDataSet( ds ); // could be empty const CSComp & v = licat.GetValue(); lossyflag = atoi( v.c_str() ) == 1; // Note: technically one can decompress into uncompressed form (eg. // Implicit Little Endian) an input JPEG Lossy. So we need to check // the attribute LossyImageCompression value: PixelData->SetLossyFlag(lossyflag); } // Two cases: // - DataSet did not specify the lossyflag // - DataSet specify it to be 0, but there is still a chance it could be wrong: // execute computation of lossy flag eny time the TS is encapsulated so as to // update the correct PixelFormat as early as possible and not during // decompression in case of mismatch: if( (!haslossyflag || !lossyflag) || PixelData->GetTransferSyntax().IsEncapsulated() ) { PixelData->ComputeLossyFlag(); if( PixelData->IsLossy() && (!lossyflag && haslossyflag ) ) { // We always prefer the setting from the stream... gdcmWarningMacro( "DataSet set LossyFlag to 0, while Codec made the stream lossy" ); } // Make sure to combine DICOM info + pixel data bitstream: PixelData->SetLossyFlag( PixelData->IsLossy() || lossyflag); } return true; } bool PixmapReader::ReadACRNEMAImage() { const DataSet &ds = F->GetDataSet(); std::stringstream ss; std::string conversion; // Ok we have the dataset let's feed the Image (PixelData) // 1. First find how many dimensions there is: // D 0028|0005 [SS] [Image Dimensions (RET)] [2] const Tag timagedimensions = Tag(0x0028, 0x0005); if( ds.FindDataElement( timagedimensions ) ) { const DataElement& de0 = ds.GetDataElement( timagedimensions ); unsigned short imagedimensions = 0; if( de0.GetVR() == VR::SS ) { // Data/SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm 0028,0005 is SS Element el0 = { 0 }; el0.SetFromDataElement( de0 ); imagedimensions = el0.GetValue(); } else { Attribute<0x0028,0x0005> at0 = { 0 }; at0.SetFromDataElement( de0 ); assert( at0.GetNumberOfValues() == 1 ); imagedimensions = at0.GetValue(); } //assert( imagedimensions == ReadSSFromTag( timagedimensions, ss, conversion ) ); if ( imagedimensions == 3 ) { PixelData->SetNumberOfDimensions(3); // D 0028|0012 [US] [Planes] [262] const DataElement& de1 = ds.GetDataElement( Tag(0x0028, 0x0012) ); Attribute<0x0028,0x0012> at1 = { 0 }; at1.SetFromDataElement( de1 ); assert( at1.GetNumberOfValues() == 1 ); PixelData->SetDimension(2, at1.GetValue() ); //assert( at.GetValue() == ReadUSFromTag( Tag(0x0028, 0x0012), ss, conversion ) ); } else if ( imagedimensions == 2 ) { PixelData->SetNumberOfDimensions(2); } else { gdcmErrorMacro( "Unhandled Image Dimensions: " << imagedimensions ); return false; } } else { gdcmWarningMacro( "Attempting a guess for the number of dimensions" ); PixelData->SetNumberOfDimensions( 2 ); } // 2. What are the col & rows: // D 0028|0011 [US] [Columns] [512] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0011) ); Attribute<0x0028,0x0011> at = { 0 }; at.SetFromDataSet( ds ); PixelData->SetDimension(0, at.GetValue() ); //assert( at.GetValue() == ReadUSFromTag( Tag(0x0028, 0x0011), ss, conversion ) ); } // D 0028|0010 [US] [Rows] [512] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0010) ); Attribute<0x0028,0x0010> at = { 0 }; at.SetFromDataSet( ds ); PixelData->SetDimension(1, at.GetValue() ); //assert( at.GetValue() == ReadUSFromTag( Tag(0x0028, 0x0010), ss, conversion ) ); } // This is the definition of an ACR NEMA image: // D 0008|0010 [LO] [Recognition Code (RET)] [ACR-NEMA 2.0] // LIBIDO compatible code: // D 0008|0010 [LO] [Recognition Code (RET)] [ACRNEMA_LIBIDO_1.1] const Tag trecognitioncode(0x0008,0x0010); if( ds.FindDataElement( trecognitioncode ) && !ds.GetDataElement( trecognitioncode ).IsEmpty() ) { const ByteValue *libido = ds.GetDataElement(trecognitioncode).GetByteValue(); assert( libido ); std::string libido_str( libido->GetPointer(), libido->GetLength() ); assert( libido_str != "CANRME_AILIBOD1_1." ); if( strcmp(libido_str.c_str() , "ACRNEMA_LIBIDO_1.1") == 0 || strcmp(libido_str.c_str() , "ACRNEMA_LIBIDO_1.0") == 0 ) { // Swap Columns & Rows // assert( PixelData->GetNumberOfDimensions() == 2 ); const unsigned int *dims = PixelData->GetDimensions(); unsigned int tmp = dims[0]; PixelData->SetDimension(0, dims[1] ); PixelData->SetDimension(1, tmp ); } else { assert( libido_str == "ACR-NEMA 2.0" || libido_str == "ACR-NEMA 1.0" ); } } else { gdcmWarningMacro( "Reading as ACR NEMA an image which does not look likes ACR NEMA" ); // File: acc-max.dcm is it ACR or DICOM ? // assert(0); } // 3. Pixel Format ? PixelFormat pf; // D 0028|0100 [US] [Bits Allocated] [16] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0100) ); Attribute<0x0028,0x0100> at = { 0 }; at.SetFromDataSet( ds ); pf.SetBitsAllocated( at.GetValue() ); //assert( at.GetValue() == ReadUSFromTag( Tag(0x0028, 0x0100), ss, conversion ) ); } // D 0028|0101 [US] [Bits Stored] [12] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0101) ); Attribute<0x0028,0x0101> at = { 0 }; at.SetFromDataSet( ds ); pf.SetBitsStored( at.GetValue() ); //assert( at.GetValue() == ReadUSFromTag( Tag(0x0028, 0x0101), ss, conversion ) ); } // D 0028|0102 [US] [High Bit] [11] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0102) ); Attribute<0x0028,0x0102> at = { 0 }; at.SetFromDataSet( ds ); pf.SetHighBit( at.GetValue() ); //assert( at.GetValue() == ReadUSFromTag( Tag(0x0028, 0x0102), ss, conversion ) ); } // D 0028|0103 [US] [Pixel Representation] [0] { //const DataElement& de = ds.GetDataElement( Tag(0x0028, 0x0103) ); Attribute<0x0028,0x0103> at = { 0 }; at.SetFromDataSet( ds ); pf.SetPixelRepresentation( at.GetValue() ); //assert( at.GetValue() == ReadUSFromTag( Tag(0x0028, 0x0103), ss, conversion ) ); } PixelData->SetPixelFormat( pf ); // 4. Do the Curves/Overlays if any DoCurves(ds, *PixelData); // Pay attention that pf.GetSamplesPerPixel() may equal 1 (eg. LIBIDO-24-ACR_NEMA-Rectangle.dcm) DoOverlays(ds, *PixelData); // 5. Do the PixelData const Tag pixeldata = Tag(0x7fe0, 0x0010); if( !ds.FindDataElement( pixeldata ) ) { gdcmWarningMacro( "No Pixel Data Found" ); return false; } const DataElement& de = ds.GetDataElement( pixeldata ); if ( de.GetVR() == VR::OW ) { //assert(0); //PixelData->SetNeedByteSwap(true); } PixelData->SetDataElement( de ); // There is no such thing as Photometric Interpretation and // Planar Configuration in ACR NEMA so let's default to something ... PixelData->SetPhotometricInterpretation( PhotometricInterpretation::MONOCHROME2 ); PixelData->SetPlanarConfiguration(0); const Tag planarconfiguration(0x0028, 0x0006); if( ds.FindDataElement( planarconfiguration ) && !ds.GetDataElement( planarconfiguration ).IsEmpty() ) { //const DataElement& de = ds.GetDataElement( planarconfiguration ); Attribute<0x0028,0x0006> at = { 0 }; at.SetFromDataSet( ds ); //unsigned int pc = ReadUSFromTag( planarconfiguration, ss, conversion ); unsigned int pc = at.GetValue(); if( pc && PixelData->GetPixelFormat().GetSamplesPerPixel() != 3 ) { gdcmDebugMacro( "Cannot have PlanarConfiguration=1, when Sample Per Pixel != 3" ); pc = 0; } PixelData->SetPlanarConfiguration( pc ); } const Tag tphotometricinterpretation(0x0028, 0x0004); // Some funny ACR NEMA file have PhotometricInterpretation ... if( ds.FindDataElement( tphotometricinterpretation ) && !ds.GetDataElement( tphotometricinterpretation ).IsEmpty() ) { const ByteValue *photometricinterpretation = ds.GetDataElement( tphotometricinterpretation ).GetByteValue(); assert( photometricinterpretation ); std::string photometricinterpretation_str( photometricinterpretation->GetPointer(), photometricinterpretation->GetLength() ); PhotometricInterpretation pi( PhotometricInterpretation::GetPIType( photometricinterpretation_str.c_str())); PixelData->SetPhotometricInterpretation( pi ); } else { // Wild guess: if( PixelData->GetPixelFormat().GetSamplesPerPixel() == 1 ) { assert( PixelData->GetPhotometricInterpretation() == PhotometricInterpretation::MONOCHROME2 ); // No need... //PixelData->SetPhotometricInterpretation( PhotometricInterpretation::MONOCHROME2 ); } else if( PixelData->GetPixelFormat().GetSamplesPerPixel() == 3 ) { // LIBIDO-24-ACR_NEMA-Rectangle.dcm PixelData->SetPhotometricInterpretation( PhotometricInterpretation::RGB ); } else if( PixelData->GetPixelFormat().GetSamplesPerPixel() == 4 ) { PixelData->SetPhotometricInterpretation( PhotometricInterpretation::ARGB ); } else { gdcmErrorMacro( "Cannot handle Samples Per Pixel=" << PixelData->GetPixelFormat().GetSamplesPerPixel() ); return false; } } return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPixmapReader.h000066400000000000000000000040621412732066400241010ustar00rootroot00000000000000/*========================================================================= 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 GDCMPIXMAPREADER_H #define GDCMPIXMAPREADER_H #include "gdcmReader.h" #include "gdcmPixmap.h" namespace gdcm { 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 * they impact the rendering or the image * * See PS 3.3-2008, Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES for the list of * attribute that belong to what gdcm calls a 'Pixmap' * * \warning the API ReadUpToTag and ReadSelectedTag * * \see Pixmap */ class GDCM_EXPORT PixmapReader : public Reader { public: PixmapReader(); ~PixmapReader() override; //needs to be virtual to ensure lack of memory leaks /// Read the DICOM image. There are two reason for failure: /// 1. The input filename is not DICOM /// 2. The input DICOM file does not contains an Pixmap. bool Read() override; // Following methods are valid only after a call to 'Read' /// Return the read image (need to call Read() first) const Pixmap& GetPixmap() const; Pixmap& GetPixmap(); //void SetPixamp(Pixmap const &pix); protected: bool ReadImageInternal(MediaStorage const &ms, bool handlepixeldata = true); virtual bool ReadImage(MediaStorage const &ms); virtual bool ReadACRNEMAImage(); SmartPointer PixelData; }; /** * \example StandardizeFiles.cs * This is a C++ example on how to use PixmapReader */ } // end namespace gdcm #endif //GDCMPIXMAPREADER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPixmapToPixmapFilter.cxx000066400000000000000000000020101412732066400261500ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPixmapToPixmapFilter.h" #include "gdcmPixmap.h" namespace gdcm { PixmapToPixmapFilter::PixmapToPixmapFilter() = default; Pixmap &PixmapToPixmapFilter::GetInput() { return dynamic_cast(*Input); } const Pixmap &PixmapToPixmapFilter::GetOutput() const { return dynamic_cast(*Output); } const Pixmap &PixmapToPixmapFilter::GetOutputAsPixmap() const { return dynamic_cast(*Output); } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPixmapToPixmapFilter.h000066400000000000000000000022461412732066400256100ustar00rootroot00000000000000/*========================================================================= 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 GDCMPIXMAPTOPIXMAPFILTER_H #define GDCMPIXMAPTOPIXMAPFILTER_H #include "gdcmBitmapToBitmapFilter.h" namespace gdcm { class Pixmap; /** * \brief PixmapToPixmapFilter class * \details Super class for all filter taking an image and producing an output image */ class GDCM_EXPORT PixmapToPixmapFilter : public BitmapToBitmapFilter { public: PixmapToPixmapFilter(); ~PixmapToPixmapFilter() = default; Pixmap &GetInput(); /// Get Output image const Pixmap &GetOutput() const; // SWIG/Java hack: const Pixmap &GetOutputAsPixmap() const; }; } // end namespace gdcm #endif //GDCMPIXMAPTOPIXMAPFILTER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPixmapWriter.cxx000066400000000000000000000704151412732066400245330ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPixmapWriter.h" #include "gdcmImageHelper.h" #include "gdcmTrace.h" #include "gdcmDataSet.h" #include "gdcmDataElement.h" #include "gdcmAttribute.h" #include "gdcmUIDGenerator.h" #include "gdcmSystem.h" #include "gdcmPixmap.h" #include "gdcmLookupTable.h" #include "gdcmItem.h" #include "gdcmSequenceOfItems.h" namespace gdcm { PixmapWriter::PixmapWriter():PixelData(new Pixmap) { } PixmapWriter::~PixmapWriter() = default; void PixmapWriter::SetPixmap(Pixmap const &img) { PixelData = img; } void PixmapWriter::DoIconImage(DataSet & rootds, Pixmap const & image) { //const Tag ticonimage(0x0088,0x0200); const IconImage &icon = image.GetIconImage(); if( !icon.IsEmpty() ) { //DataElement iconimagesq = rootds.GetDataElement( ticonimage ); //iconimagesq.SetTag( ticonimage ); DataElement iconimagesq; iconimagesq.SetTag( Attribute<0x0088,0x0200>::GetTag() ); iconimagesq.SetVR( VR::SQ ); SmartPointer sq = new SequenceOfItems; sq->SetLengthToUndefined(); DataSet ds; //SequenceOfItems* sq = iconimagesq.GetSequenceOfItems(); //// Is SQ empty ? //if( !sq ) return; //SequenceOfItems::Iterator it = sq->Begin(); //DataSet &ds = it->GetNestedDataSet(); // col & rows: Attribute<0x0028, 0x0011> columns; columns.SetValue( (uint16_t)icon.GetDimension(0) ); ds.Insert( columns.GetAsDataElement() ); Attribute<0x0028, 0x0010> rows; rows.SetValue( (uint16_t)icon.GetDimension(1) ); ds.Insert( rows.GetAsDataElement() ); PixelFormat pf = icon.GetPixelFormat(); Attribute<0x0028, 0x0100> bitsallocated; bitsallocated.SetValue( pf.GetBitsAllocated() ); ds.Replace( bitsallocated.GetAsDataElement() ); Attribute<0x0028, 0x0101> bitsstored; bitsstored.SetValue( pf.GetBitsStored() ); ds.Replace( bitsstored.GetAsDataElement() ); Attribute<0x0028, 0x0102> highbit; highbit.SetValue( pf.GetHighBit() ); ds.Replace( highbit.GetAsDataElement() ); Attribute<0x0028, 0x0103> pixelrepresentation; pixelrepresentation.SetValue( pf.GetPixelRepresentation() ); ds.Replace( pixelrepresentation.GetAsDataElement() ); Attribute<0x0028, 0x0002> samplesperpixel; samplesperpixel.SetValue( pf.GetSamplesPerPixel() ); ds.Replace( samplesperpixel.GetAsDataElement() ); if( pf.GetSamplesPerPixel() != 1 ) { Attribute<0x0028, 0x0006> planarconf; planarconf.SetValue( (uint16_t)icon.GetPlanarConfiguration() ); ds.Replace( planarconf.GetAsDataElement() ); } PhotometricInterpretation pi = icon.GetPhotometricInterpretation(); Attribute<0x0028,0x0004> piat; const char *pistr = PhotometricInterpretation::GetPIString(pi); { DataElement de( Tag(0x0028, 0x0004 ) ); VL::Type strlenPistr = (VL::Type)strlen(pistr); de.SetByteValue( pistr, strlenPistr ); de.SetVR( piat.GetVR() ); ds.Replace( de ); } if ( pi == PhotometricInterpretation::PALETTE_COLOR ) { const LookupTable &lut = icon.GetLUT(); assert( (pf.GetBitsAllocated() == 8 && pf.GetPixelRepresentation() == 0) || (pf.GetBitsAllocated() == 16 && pf.GetPixelRepresentation() == 0) ); // lut descriptor: // (0028,1101) US 256\0\16 # 6, 3 RedPaletteColorLookupTableDescriptor // (0028,1102) US 256\0\16 # 6, 3 GreenPaletteColorLookupTableDescriptor // (0028,1103) US 256\0\16 # 6, 3 BluePaletteColorLookupTableDescriptor // lut data: unsigned short length, subscript, bitsize; //unsigned short rawlut8[256]; std::vector rawlut8; rawlut8.resize(256); //unsigned short rawlut16[65536]; std::vector rawlut16; unsigned short *rawlut = &rawlut8[0]; unsigned int lutlen = 256; if( pf.GetBitsAllocated() == 16 ) { rawlut16.resize(65536); rawlut = &rawlut16[0]; lutlen = 65536; } unsigned int l; // FIXME: should I really clear rawlut each time ? // RED memset(rawlut,0,lutlen*2); lut.GetLUT(LookupTable::RED, (unsigned char*)rawlut, l); DataElement redde( Tag(0x0028, 0x1201) ); redde.SetVR( VR::OW ); redde.SetByteValue( (char*)rawlut, l); ds.Replace( redde ); // descriptor: Attribute<0x0028, 0x1101, VR::US, VM::VM3> reddesc; lut.GetLUTDescriptor(LookupTable::RED, length, subscript, bitsize); reddesc.SetValue(length,0); reddesc.SetValue(subscript,1); reddesc.SetValue(bitsize,2); ds.Replace( reddesc.GetAsDataElement() ); // GREEN memset(rawlut,0,lutlen*2); lut.GetLUT(LookupTable::GREEN, (unsigned char*)rawlut, l); DataElement greende( Tag(0x0028, 0x1202) ); greende.SetVR( VR::OW ); greende.SetByteValue( (char*)rawlut, l); ds.Replace( greende ); // descriptor: Attribute<0x0028, 0x1102, VR::US, VM::VM3> greendesc; lut.GetLUTDescriptor(LookupTable::GREEN, length, subscript, bitsize); greendesc.SetValue(length,0); greendesc.SetValue(subscript,1); greendesc.SetValue(bitsize,2); ds.Replace( greendesc.GetAsDataElement() ); // BLUE memset(rawlut,0,lutlen*2); lut.GetLUT(LookupTable::BLUE, (unsigned char*)rawlut, l); DataElement bluede( Tag(0x0028, 0x1203) ); bluede.SetVR( VR::OW ); bluede.SetByteValue( (char*)rawlut, l); ds.Replace( bluede ); // descriptor: Attribute<0x0028, 0x1103, VR::US, VM::VM3> bluedesc; lut.GetLUTDescriptor(LookupTable::BLUE, length, subscript, bitsize); bluedesc.SetValue(length,0); bluedesc.SetValue(subscript,1); bluedesc.SetValue(bitsize,2); ds.Replace( bluedesc.GetAsDataElement() ); } { // Pixel Data DataElement de( Tag(0x7fe0,0x0010) ); const Value &v = icon.GetDataElement().GetValue(); de.SetValue( v ); const ByteValue *bv = de.GetByteValue(); const TransferSyntax &ts = icon.GetTransferSyntax(); assert( ts.IsExplicit() || ts.IsImplicit() ); VL vl; if( bv ) { // if ts is explicit -> set VR vl = bv->GetLength(); } else { // if ts is explicit -> set VR vl.SetToUndefined(); } if( ts.IsExplicit() ) { switch ( pf.GetBitsAllocated() ) { case 8: de.SetVR( VR::OB ); break; //case 12: case 16: case 32: de.SetVR( VR::OW ); break; default: assert( 0 && "should not happen" ); break; } } else { de.SetVR( VR::OB ); } de.SetVL( vl ); ds.Replace( de ); } Item item; item.SetNestedDataSet( ds ); sq->AddItem( item ); iconimagesq.SetValue( *sq ); rootds.Replace( iconimagesq ); } } bool PixmapWriter::PrepareWrite( MediaStorage const & ref_ms ) { File& file = GetFile(); DataSet& ds = file.GetDataSet(); FileMetaInformation &fmi_orig = file.GetHeader(); const TransferSyntax &ts_orig = fmi_orig.GetDataSetTransferSyntax(); const PhotometricInterpretation pi_orig = ImageHelper::GetPhotometricInterpretationValue(file); // col & rows: #if 0 Attribute<0x0028, 0x0011> columns; columns.SetValue( (uint16_t)PixelData->GetDimension(0) ); ds.Replace( columns.GetAsDataElement() ); Attribute<0x0028, 0x0010> rows; rows.SetValue( (uint16_t)PixelData->GetDimension(1) ); ds.Replace( rows.GetAsDataElement() ); // (0028,0008) IS [12] # 2, 1 NumberOfFrames const Tag tnumberofframes = Tag(0x0028, 0x0008); if( PixelData->GetNumberOfDimensions() == 3 ) { Attribute<0x0028, 0x0008> numberofframes; assert( PixelData->GetDimension(2) >= 1 ); numberofframes.SetValue( PixelData->GetDimension(2) ); ds.Replace( numberofframes.GetAsDataElement() ); } else if( ds.FindDataElement(tnumberofframes) ) // Remove Number Of Frames { assert( PixelData->GetNumberOfDimensions() == 2 ); assert( PixelData->GetDimension(2) == 1 ); ds.Remove( tnumberofframes ); } #endif PixelFormat pf = PixelData->GetPixelFormat(); if ( !pf.IsValid() ) { gdcmWarningMacro( "Pixel format is not valid: " << pf ); return false; } PhotometricInterpretation pi = PixelData->GetPhotometricInterpretation(); if( pi.GetSamplesPerPixel() != pf.GetSamplesPerPixel() ) { gdcmWarningMacro( "Photometric Interpretation and Pixel format are not compatible: " << pi.GetSamplesPerPixel() << " vs " << pf.GetSamplesPerPixel() ); return false; } { assert( pi != PhotometricInterpretation::UNKNOWN ); const char *pistr = PhotometricInterpretation::GetPIString(pi); DataElement de( Tag(0x0028, 0x0004 ) ); VL::Type strlenPistr = (VL::Type)strlen(pistr); de.SetByteValue( pistr, strlenPistr ); de.SetVR( Attribute<0x0028,0x0004>::GetVR() ); ds.Replace( de ); } // Pixel Format : // (0028,0100) US 8 # 2, 1 BitsAllocated // (0028,0101) US 8 # 2, 1 BitsStored // (0028,0102) US 7 # 2, 1 HighBit // (0028,0103) US 0 # 2, 1 PixelRepresentation Attribute<0x0028, 0x0100> bitsallocated; bitsallocated.SetValue( pf.GetBitsAllocated() ); ds.Replace( bitsallocated.GetAsDataElement() ); Attribute<0x0028, 0x0101> bitsstored; bitsstored.SetValue( pf.GetBitsStored() ); ds.Replace( bitsstored.GetAsDataElement() ); Attribute<0x0028, 0x0102> highbit; highbit.SetValue( pf.GetHighBit() ); ds.Replace( highbit.GetAsDataElement() ); Attribute<0x0028, 0x0103> pixelrepresentation; pixelrepresentation.SetValue( pf.GetPixelRepresentation() ); ds.Replace( pixelrepresentation.GetAsDataElement() ); Attribute<0x0028, 0x0002> samplesperpixel; samplesperpixel.SetValue( pf.GetSamplesPerPixel() ); ds.Replace( samplesperpixel.GetAsDataElement() ); if( pf.GetSamplesPerPixel() != 1 ) { Attribute<0x0028, 0x0006> planarconf; planarconf.SetValue( (uint16_t)PixelData->GetPlanarConfiguration() ); ds.Replace( planarconf.GetAsDataElement() ); } // PhotometricInterpretation // const Tag tphotometricinterpretation(0x0028, 0x0004); //if( !ds.FindDataElement( Tag(0x0028, 0x0004) ) ) { //if( pi == PhotometricInterpretation::RGB // || pi == PhotometricInterpretation::YBR_FULL ) // FIXME // { // Attribute<0x0028, 0x0006> planarconfiguration; // planarconfiguration.SetValue( PixelData->GetPlanarConfiguration() ); // ds.Replace( planarconfiguration.GetAsDataElement() ); // } //else if ( pi == PhotometricInterpretation::PALETTE_COLOR ) { const LookupTable &lut = PixelData->GetLUT(); assert( lut.Initialized() ); // assert( (pf.GetBitsAllocated() == 8 && pf.GetPixelRepresentation() == 0) // || (pf.GetBitsAllocated() == 16 && pf.GetPixelRepresentation() == 0) ); // lut descriptor: // (0028,1101) US 256\0\16 # 6, 3 RedPaletteColorLookupTableDescriptor // (0028,1102) US 256\0\16 # 6, 3 GreenPaletteColorLookupTableDescriptor // (0028,1103) US 256\0\16 # 6, 3 BluePaletteColorLookupTableDescriptor // lut data: unsigned short length, subscript, bitsize; unsigned short rawlut8[256]; unsigned short rawlut16[65536]; unsigned short *rawlut = rawlut8; unsigned int lutlen = 256; if( pf.GetBitsAllocated() == 16 ) { rawlut = rawlut16; lutlen = 65536; } unsigned int l; // FIXME: should I really clear rawlut each time ? // RED memset(rawlut,0,lutlen*2); lut.GetLUT(LookupTable::RED, (unsigned char*)rawlut, l); DataElement redde( Tag(0x0028, 0x1201) ); redde.SetVR( VR::OW ); redde.SetByteValue( (char*)rawlut, l); ds.Replace( redde ); // descriptor: Attribute<0x0028, 0x1101, VR::US, VM::VM3> reddesc; lut.GetLUTDescriptor(LookupTable::RED, length, subscript, bitsize); reddesc.SetValue(length,0); reddesc.SetValue(subscript,1); reddesc.SetValue(bitsize,2); ds.Replace( reddesc.GetAsDataElement() ); // GREEN memset(rawlut,0,lutlen*2); lut.GetLUT(LookupTable::GREEN, (unsigned char*)rawlut, l); DataElement greende( Tag(0x0028, 0x1202) ); greende.SetVR( VR::OW ); greende.SetByteValue( (char*)rawlut, l); ds.Replace( greende ); // descriptor: Attribute<0x0028, 0x1102, VR::US, VM::VM3> greendesc; lut.GetLUTDescriptor(LookupTable::GREEN, length, subscript, bitsize); greendesc.SetValue(length,0); greendesc.SetValue(subscript,1); greendesc.SetValue(bitsize,2); ds.Replace( greendesc.GetAsDataElement() ); // BLUE memset(rawlut,0,lutlen*2); lut.GetLUT(LookupTable::BLUE, (unsigned char*)rawlut, l); DataElement bluede( Tag(0x0028, 0x1203) ); bluede.SetVR( VR::OW ); bluede.SetByteValue( (char*)rawlut, l); ds.Replace( bluede ); // descriptor: Attribute<0x0028, 0x1103, VR::US, VM::VM3> bluedesc; lut.GetLUTDescriptor(LookupTable::BLUE, length, subscript, bitsize); bluedesc.SetValue(length,0); bluedesc.SetValue(subscript,1); bluedesc.SetValue(bitsize,2); ds.Replace( bluedesc.GetAsDataElement() ); } ds.Remove( Tag(0x0028, 0x1221) ); ds.Remove( Tag(0x0028, 0x1222) ); ds.Remove( Tag(0x0028, 0x1223) ); } // Cleanup LUT here since cannot be done within gdcm::ImageApplyLookupTable if( pi == PhotometricInterpretation::RGB ) { // usual tags: ds.Remove( Tag(0x0028, 0x1101) ); ds.Remove( Tag(0x0028, 0x1102) ); ds.Remove( Tag(0x0028, 0x1103) ); ds.Remove( Tag(0x0028, 0x1201) ); ds.Remove( Tag(0x0028, 0x1202) ); ds.Remove( Tag(0x0028, 0x1203) ); // Don't forget the segmented one: ds.Remove( Tag(0x0028, 0x1221) ); ds.Remove( Tag(0x0028, 0x1222) ); ds.Remove( Tag(0x0028, 0x1223) ); // PaletteColorLookupTableUID ?? ds.Remove( Tag(0x0028, 0x1199) ); } // Overlay Data 60xx SequenceOfItems::SizeType nOv = PixelData->GetNumberOfOverlays(); for(SequenceOfItems::SizeType ovidx = 0; ovidx < nOv; ++ovidx ) { // (6000,0010) US 484 # 2, 1 OverlayRows // (6000,0011) US 484 # 2, 1 OverlayColumns // (6000,0015) IS [1] # 2, 1 NumberOfFramesInOverlay // (6000,0022) LO [Siemens MedCom Object Graphics] # 30, 1 OverlayDescription // (6000,0040) CS [G] # 2, 1 OverlayType // (6000,0050) SS 1\1 # 4, 2 OverlayOrigin // (6000,0051) US 1 # 2, 1 ImageFrameOrigin // (6000,0100) US 1 # 2, 1 OverlayBitsAllocated // (6000,0102) US 0 # 2, 1 OverlayBitPosition // (6000,3000) OW 0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000\0000... # 29282, 1 OverlayData DataElement de; const Overlay &ov = PixelData->GetOverlay(ovidx); Attribute<0x6000,0x0010> overlayrows; overlayrows.SetValue( ov.GetRows() ); de = overlayrows.GetAsDataElement(); de.GetTag().SetGroup( ov.GetGroup() ); ds.Replace( de ); Attribute<0x6000,0x0011> overlaycolumns; overlaycolumns.SetValue( ov.GetColumns() ); de = overlaycolumns.GetAsDataElement(); de.GetTag().SetGroup( ov.GetGroup() ); ds.Replace( de ); if( ov.GetDescription() ) // Type 3 { Attribute<0x6000,0x0022> overlaydescription; overlaydescription.SetValue( ov.GetDescription() ); de = overlaydescription.GetAsDataElement(); de.GetTag().SetGroup( ov.GetGroup() ); ds.Replace( de ); } Attribute<0x6000,0x0040> overlaytype; // 'G' or 'R' overlaytype.SetValue( ov.GetType() ); de = overlaytype.GetAsDataElement(); de.GetTag().SetGroup( ov.GetGroup() ); ds.Replace( de ); Attribute<0x6000,0x0050> overlayorigin; overlayorigin.SetValues( ov.GetOrigin() ); de = overlayorigin.GetAsDataElement(); de.GetTag().SetGroup( ov.GetGroup() ); ds.Replace( de ); Attribute<0x6000,0x0100> overlaybitsallocated; overlaybitsallocated.SetValue( ov.GetBitsAllocated() ); de = overlaybitsallocated.GetAsDataElement(); de.GetTag().SetGroup( ov.GetGroup() ); ds.Replace( de ); Attribute<0x6000,0x0102> overlaybitposition; overlaybitposition.SetValue( ov.GetBitPosition() ); de = overlaybitposition.GetAsDataElement(); de.GetTag().SetGroup( ov.GetGroup() ); ds.Replace( de ); // FIXME: for now rewrite 'Overlay in pixel data' still in the pixel data element... //if( !ov.IsInPixelData() ) { const ByteValue & overlaydatabv = ov.GetOverlayData(); DataElement overlaydata( Tag(0x6000,0x3000) ); overlaydata.SetByteValue( overlaydatabv.GetPointer(), overlaydatabv.GetLength() ); overlaydata.SetVR( VR::OW ); // FIXME overlaydata.GetTag().SetGroup( ov.GetGroup() ); ds.Replace( overlaydata ); } } // Pixel Data DataElement depixdata( Tag(0x7fe0,0x0010) ); DataElement & pde = PixelData->GetDataElement(); const ByteValue *bvpixdata = nullptr; // Sometime advanced user may use a gdcm::ImageRegionReader to feed an empty gdcm::Image if( !pde.IsEmpty() ) { const Value &v = PixelData->GetDataElement().GetValue(); depixdata.SetValue( v ); bvpixdata = depixdata.GetByteValue(); } const TransferSyntax &ts = PixelData->GetTransferSyntax(); assert( ts.IsExplicit() || ts.IsImplicit() ); // It is perfectly ok to store a lossy image using a J2K (this is odd, but valid). // as long as your mark LossyImageCompression with value 1 #if 0 // if ts_orig is undefined we need to check ts of Pixel Data comply with itself if( ts_orig == TransferSyntax::TS_END ) { if( !ts.CanStoreLossy() && PixelData->IsLossy() ) { gdcmWarningMacro( "Sorry Pixel Data in encapsulated stream was found to be " "lossy while Transfer Syntax does not authorized that" ); return false; } // Obviously we could also be checking the contrary: trying to store a // lossless compressed JPEG file using a lossy JPEG (compatible) one. But I // do not believe this is an error in this case. } #endif if( /*ts.IsLossy() &&*/ PixelData->IsLossy() ) { Attribute<0x0028,0x2110> at1; Attribute<0x0028,0x2114> at3; if( ts_orig == TransferSyntax::TS_END ) { // Add the Lossy stuff: at1.SetValue( "01" ); ds.Replace( at1.GetAsDataElement() ); } else if( ts_orig.IsLossy() ) { // Add the Lossy stuff: at1.SetValue( "01" ); ds.Replace( at1.GetAsDataElement() ); /* The Defined Terms for Lossy Image Compression Method (0028,2114) are : ISO_10918_1 = JPEG Lossy Compression ISO_14495_1 = JPEG-LS Near-lossless Compression ISO_15444_1 = JPEG 2000 Irreversible Compression ISO_13818_2 = MPEG2 Compression */ if( ts_orig == TransferSyntax::JPEG2000 ) { static const CSComp newvalues2[] = {"ISO_15444_1"}; at3.SetValues( newvalues2, 1 ); } else if( ts_orig == TransferSyntax::JPEGLSNearLossless ) { static const CSComp newvalues2[] = {"ISO_14495_1"}; at3.SetValues( newvalues2, 1 ); } else if ( ts_orig == TransferSyntax::JPEGBaselineProcess1 || ts_orig == TransferSyntax::JPEGExtendedProcess2_4 || ts_orig == TransferSyntax::JPEGExtendedProcess3_5 || ts_orig == TransferSyntax::JPEGSpectralSelectionProcess6_8 || ts_orig == TransferSyntax::JPEGFullProgressionProcess10_12 ) { static const CSComp newvalues2[] = {"ISO_10918_1"}; at3.SetValues( newvalues2, 1 ); } else { gdcmErrorMacro( "Pixel Data is lossy but I cannot find the original transfer syntax" ); return false; } ds.Replace( at3.GetAsDataElement() ); } else { if( ds.FindDataElement( at1.GetTag() ) ) { at1.Set( ds ); if( atoi(at1.GetValue().c_str()) != 1 ) { gdcmDebugMacro( "Fixing invalid value for LossyImageCompression: " << at1.GetValue() ); at1.SetValue( "01" ); ds.Replace( at1.GetAsDataElement() ); } } else { if( pi_orig == PhotometricInterpretation::YBR_FULL_422 ) { at1.SetValue( "01" ); ds.Replace( at1.GetAsDataElement() ); static const CSComp newvalues2[] = {"ISO_10918_1"}; at3.SetValues( newvalues2, 1 ); ds.Replace( at3.GetAsDataElement() ); } else { gdcmErrorMacro( "Unhandled Lossy flag for Pixel Data" ); return false; } } } } VL vl; if( bvpixdata ) { // if ts is explicit -> set VR vl = bvpixdata->GetLength(); } else { // if ts is explicit -> set VR vl.SetToUndefined(); } if( ts.IsExplicit() ) { switch ( pf.GetBitsAllocated() ) { case 1: case 8: depixdata.SetVR( VR::OB ); break; case 12: case 16: case 32: if( depixdata.GetSequenceOfFragments() ) depixdata.SetVR( VR::OB ); else depixdata.SetVR( VR::OW ); break; default: assert( 0 && "should not happen" ); break; } } else { depixdata.SetVR( VR::OB ); } depixdata.SetVL( vl ); // Advanced user may have passed an empty image if( !pde.IsEmpty() ) { ds.Replace( depixdata ); } // Do Icon Image DoIconImage(ds, GetPixmap()); MediaStorage ms = ref_ms; // Most SOP Class support 2D, but let's make sure that 3D is ok: if( PixelData->GetNumberOfDimensions() > 2 ) { if( ms.GetModalityDimension() < PixelData->GetNumberOfDimensions() ) { // input was specified with SC, but the Number of Frame is > 1. Fix that: ms = ImageHelper::ComputeMediaStorageFromModality( ms.GetModality(), PixelData->GetNumberOfDimensions(), PixelData->GetPixelFormat(), PixelData->GetPhotometricInterpretation(), 0, 1 ); if( ms.GetModalityDimension() < PixelData->GetNumberOfDimensions() ) { gdcmErrorMacro( "Problem with NumberOfDimensions and MediaStorage" ); return false; } } } // if we reach here somethnig went really wrong in previous step. Let's make // it a hard failure gdcmAssertAlwaysMacro( ms != MediaStorage::MS_END ); const char* msstr = MediaStorage::GetMSString(ms); if( !ds.FindDataElement( Tag(0x0008, 0x0016) ) ) { DataElement de( Tag(0x0008, 0x0016 ) ); VL::Type strlenMsstr = (VL::Type)strlen(msstr); de.SetByteValue( msstr, strlenMsstr); de.SetVR( Attribute<0x0008, 0x0016>::GetVR() ); ds.Insert( de ); } else { const ByteValue *bv = ds.GetDataElement( Tag(0x0008,0x0016) ).GetByteValue(); if( !bv ) { gdcmErrorMacro( "Cannot be empty" ); return false; } if( strncmp( bv->GetPointer(), msstr, bv->GetLength() ) != 0 ) { DataElement de = ds.GetDataElement( Tag(0x0008,0x0016) ); VL::Type strlenMsstr = (VL::Type) strlen(msstr); de.SetByteValue( msstr, strlenMsstr ); ds.Replace( de ); } else { assert( bv->GetLength() == strlen( msstr ) || bv->GetLength() == strlen(msstr) + 1 ); } } ImageHelper::SetDimensionsValue(file, *PixelData); // UIDs: // (0008,0018) UI [1.3.6.1.4.1.5962.1.1.1.1.3.20040826185059.5457] # 46, 1 SOPInstanceUID // (0020,000d) UI [1.3.6.1.4.1.5962.1.2.1.20040826185059.5457] # 42, 1 StudyInstanceUID // (0020,000e) UI [1.3.6.1.4.1.5962.1.3.1.1.20040826185059.5457] # 44, 1 SeriesInstanceUID UIDGenerator uid; // Be careful with the SOP Instance UID: if( ds.FindDataElement( Tag(0x0008, 0x0018) ) && false ) { // We are coming from a real DICOM image, we need to reference it... const Tag tsourceImageSequence(0x0008,0x2112); SmartPointer sq; if( ds.FindDataElement( tsourceImageSequence ) ) { DataElement &de = const_cast(ds.GetDataElement( tsourceImageSequence )); de.SetVLToUndefined(); // For now if( de.IsEmpty() ) { sq = new SequenceOfItems; de.SetValue( *sq ); } sq = de.GetValueAsSQ(); } else { sq = new SequenceOfItems; } sq->SetLengthToUndefined(); Item item; //( /*Tag(0xfffe,0xe000)*/ ); //DataSet sourceimageds; // (0008,1150) UI =MRImageStorage # 26, 1 ReferencedSOPClassUID // (0008,1155) UI [1.3.6.1.4.17434.1.1.5.2.1160650698.1160650698.0] # 48, 1 ReferencedSOPInstanceUID DataElement referencedSOPClassUID = ds.GetDataElement( Tag(0x0008,0x0016) ); referencedSOPClassUID.SetTag( Tag(0x0008,0x1150 ) ); DataElement referencedSOPInstanceUID = ds.GetDataElement( Tag(0x0008,0x0018) ); referencedSOPInstanceUID.SetTag( Tag(0x0008,0x1155) ); //item.SetNestedDataSet( sourceimageds ); item.SetVLToUndefined(); item.InsertDataElement( referencedSOPClassUID ); item.InsertDataElement( referencedSOPInstanceUID ); sq->AddItem( item ); if( !ds.FindDataElement( tsourceImageSequence ) ) { DataElement de( tsourceImageSequence ); de.SetVR( VR::SQ ); de.SetValue( *sq ); de.SetVLToUndefined(); //std::cout << de << std::endl; ds.Insert( de ); } } { const char *sop = uid.Generate(); DataElement de( Tag(0x0008,0x0018) ); VL::Type strlenSOP = (VL::Type) strlen(sop); de.SetByteValue( sop, strlenSOP ); de.SetVR( Attribute<0x0008, 0x0018>::GetVR() ); ds.ReplaceEmpty( de ); } // Are we on a particular Study ? If not create a new UID if( !ds.FindDataElement( Tag(0x0020, 0x000d) ) ) { const char *study = uid.Generate(); DataElement de( Tag(0x0020,0x000d) ); VL::Type strlenStudy= (VL::Type)strlen(study); de.SetByteValue( study, strlenStudy ); de.SetVR( Attribute<0x0020, 0x000d>::GetVR() ); ds.ReplaceEmpty( de ); } // Are we on a particular Series ? If not create a new UID if( !ds.FindDataElement( Tag(0x0020, 0x000e) ) ) { const char *series = uid.Generate(); DataElement de( Tag(0x0020,0x000e) ); VL::Type strlenSeries= (VL::Type)strlen(series); de.SetByteValue( series, strlenSeries ); de.SetVR( Attribute<0x0020, 0x000e>::GetVR() ); ds.ReplaceEmpty( de ); } FileMetaInformation &fmi = file.GetHeader(); if( GetCheckFileMetaInformation() ) { fmi.Clear(); //assert( ts == TransferSyntax::ImplicitVRLittleEndian ); { const char *tsuid = TransferSyntax::GetTSString( ts ); DataElement de( Tag(0x0002,0x0010) ); VL::Type strlenTSUID = (VL::Type)strlen(tsuid); de.SetByteValue( tsuid, strlenTSUID ); de.SetVR( Attribute<0x0002, 0x0010>::GetVR() ); fmi.Replace( de ); fmi.SetDataSetTransferSyntax(ts); } fmi.FillFromDataSet( ds ); } else { Attribute<0x0002,0x0010> at; at.SetFromDataSet( fmi ); const char *tsuid = TransferSyntax::GetTSString( ts ); UIComp tsui = at.GetValue(); if( tsui != tsuid ) { gdcmErrorMacro( "Incompatible TransferSyntax." ); return false; } } return true; } bool PixmapWriter::Write() { MediaStorage ms; if( !ms.SetFromFile( GetFile() ) ) { // Let's fix some old ACR-NAME stuff: ms = ImageHelper::ComputeMediaStorageFromModality( ms.GetModality(), PixelData->GetNumberOfDimensions(), PixelData->GetPixelFormat(), PixelData->GetPhotometricInterpretation(), 0, 1 ); } if( !PrepareWrite( ms ) ) return false; assert( Stream ); if( !Writer::Write() ) { return false; } return true; } void PixmapWriter::SetImage(Pixmap const &img) { PixelData = img; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPixmapWriter.h000066400000000000000000000040071412732066400241520ustar00rootroot00000000000000/*========================================================================= 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 GDCMPIXMAPWRITER_H #define GDCMPIXMAPWRITER_H #include "gdcmWriter.h" #include "gdcmPixmap.h" namespace gdcm { class StreamImageWriter; class Pixmap; /** * \brief PixmapWriter * \details This class will takes two inputs: * 1. The DICOM DataSet * 2. The Image input * It will override any info from the Image over the DataSet. * * For instance when one read in a lossy compressed image and write out as unencapsulated * (ie implicitly lossless) then some attribute are definitely needed to mark this * dataset as Lossy (typically 0028,2114) */ class GDCM_EXPORT PixmapWriter : public Writer { public: PixmapWriter(); ~PixmapWriter() override; const Pixmap& GetPixmap() const { return *PixelData; } Pixmap& GetPixmap() { return *PixelData; } // FIXME void SetPixmap(Pixmap const &img); /// Set/Get Pixmap to be written /// It will overwrite anything Pixmap infos found in DataSet /// (see parent class to see how to pass dataset) virtual const Pixmap& GetImage() const { return *PixelData; } virtual Pixmap& GetImage() { return *PixelData; } // FIXME virtual void SetImage(Pixmap const &img); /// Write bool Write() override; // Execute() protected: void DoIconImage(DataSet & ds, Pixmap const & image); bool PrepareWrite( MediaStorage const & refms ); SmartPointer PixelData; }; /** * \example StandardizeFiles.cs * This is a C++ example on how to use PixmapWriter */ } // end namespace gdcm #endif //GDCMPIXMAPWRITER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPrinter.cxx000066400000000000000000001000461412732066400235150ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPrinter.h" #include "gdcmSequenceOfItems.h" #include "gdcmSequenceOfFragments.h" #include "gdcmDict.h" #include "gdcmDicts.h" #include "gdcmGroupDict.h" #include "gdcmVR.h" #include "gdcmVM.h" #include "gdcmElement.h" #include "gdcmGlobal.h" #include "gdcmAttribute.h" #include "gdcmDataSetHelper.h" #include "gdcmDataSet.h" #include // for typeid #define gdcm_terminal_vt100_normal "\33[0m" #define gdcm_terminal_vt100_bold "\33[1m" #define gdcm_terminal_vt100_underline "\33[4m" #define gdcm_terminal_vt100_blink "\33[5m" #define gdcm_terminal_vt100_inverse "\33[7m" #define gdcm_terminal_vt100_foreground_black "\33[30m" #define gdcm_terminal_vt100_foreground_red "\33[31m" #define gdcm_terminal_vt100_foreground_green "\33[32m" #define gdcm_terminal_vt100_foreground_yellow "\33[33m" #define gdcm_terminal_vt100_foreground_blue "\33[34m" #define gdcm_terminal_vt100_foreground_magenta "\33[35m" #define gdcm_terminal_vt100_foreground_cyan "\33[36m" #define gdcm_terminal_vt100_foreground_white "\33[37m" #define gdcm_terminal_vt100_background_black "\33[40m" #define gdcm_terminal_vt100_background_red "\33[41m" #define gdcm_terminal_vt100_background_green "\33[42m" #define gdcm_terminal_vt100_background_yellow "\33[43m" #define gdcm_terminal_vt100_background_blue "\33[44m" #define gdcm_terminal_vt100_background_magenta "\33[45m" #define gdcm_terminal_vt100_background_cyan "\33[46m" #define gdcm_terminal_vt100_background_white "\33[47m" static const char * GDCM_TERMINAL_VT100_NORMAL = ""; static const char * GDCM_TERMINAL_VT100_BOLD = ""; static const char * GDCM_TERMINAL_VT100_UNDERLINE = ""; static const char * GDCM_TERMINAL_VT100_BLINK = ""; static const char * GDCM_TERMINAL_VT100_INVERSE = ""; static const char * GDCM_TERMINAL_VT100_FOREGROUND_BLACK = ""; static const char * GDCM_TERMINAL_VT100_FOREGROUND_RED = ""; static const char * GDCM_TERMINAL_VT100_FOREGROUND_GREEN = ""; static const char * GDCM_TERMINAL_VT100_FOREGROUND_YELLOW = ""; static const char * GDCM_TERMINAL_VT100_FOREGROUND_BLUE = ""; static const char * GDCM_TERMINAL_VT100_FOREGROUND_MAGENTA = ""; static const char * GDCM_TERMINAL_VT100_FOREGROUND_CYAN = ""; static const char * GDCM_TERMINAL_VT100_FOREGROUND_WHITE = ""; static const char * GDCM_TERMINAL_VT100_BACKGROUND_BLACK = ""; static const char * GDCM_TERMINAL_VT100_BACKGROUND_RED = ""; static const char * GDCM_TERMINAL_VT100_BACKGROUND_GREEN = ""; static const char * GDCM_TERMINAL_VT100_BACKGROUND_YELLOW = ""; static const char * GDCM_TERMINAL_VT100_BACKGROUND_BLUE = ""; static const char * GDCM_TERMINAL_VT100_BACKGROUND_MAGENTA = ""; static const char * GDCM_TERMINAL_VT100_BACKGROUND_CYAN = ""; static const char * GDCM_TERMINAL_VT100_BACKGROUND_WHITE = ""; namespace gdcm { //----------------------------------------------------------------------------- Printer::Printer():PrintStyle(Printer::VERBOSE_STYLE),F(nullptr) { MaxPrintLength = 0x100; // Need to be %2 } //----------------------------------------------------------------------------- Printer::~Printer() = default; void Printer::SetColor(bool c) { if( c ) { GDCM_TERMINAL_VT100_NORMAL = gdcm_terminal_vt100_normal ; GDCM_TERMINAL_VT100_BOLD = gdcm_terminal_vt100_bold ; GDCM_TERMINAL_VT100_UNDERLINE = gdcm_terminal_vt100_underline ; GDCM_TERMINAL_VT100_BLINK = gdcm_terminal_vt100_blink ; GDCM_TERMINAL_VT100_INVERSE = gdcm_terminal_vt100_inverse ; GDCM_TERMINAL_VT100_FOREGROUND_BLACK = gdcm_terminal_vt100_foreground_black ; GDCM_TERMINAL_VT100_FOREGROUND_RED = gdcm_terminal_vt100_foreground_red ; GDCM_TERMINAL_VT100_FOREGROUND_GREEN = gdcm_terminal_vt100_foreground_green ; GDCM_TERMINAL_VT100_FOREGROUND_YELLOW = gdcm_terminal_vt100_foreground_yellow ; GDCM_TERMINAL_VT100_FOREGROUND_BLUE = gdcm_terminal_vt100_foreground_blue ; GDCM_TERMINAL_VT100_FOREGROUND_MAGENTA = gdcm_terminal_vt100_foreground_magenta ; GDCM_TERMINAL_VT100_FOREGROUND_CYAN = gdcm_terminal_vt100_foreground_cyan ; GDCM_TERMINAL_VT100_FOREGROUND_WHITE = gdcm_terminal_vt100_foreground_white ; GDCM_TERMINAL_VT100_BACKGROUND_BLACK = gdcm_terminal_vt100_background_black ; GDCM_TERMINAL_VT100_BACKGROUND_RED = gdcm_terminal_vt100_background_red ; GDCM_TERMINAL_VT100_BACKGROUND_GREEN = gdcm_terminal_vt100_background_green ; GDCM_TERMINAL_VT100_BACKGROUND_YELLOW = gdcm_terminal_vt100_background_yellow ; GDCM_TERMINAL_VT100_BACKGROUND_BLUE = gdcm_terminal_vt100_background_blue ; GDCM_TERMINAL_VT100_BACKGROUND_MAGENTA = gdcm_terminal_vt100_background_magenta ; GDCM_TERMINAL_VT100_BACKGROUND_CYAN = gdcm_terminal_vt100_background_cyan ; GDCM_TERMINAL_VT100_BACKGROUND_WHITE = gdcm_terminal_vt100_background_white ; } else { GDCM_TERMINAL_VT100_NORMAL = ""; GDCM_TERMINAL_VT100_BOLD = ""; GDCM_TERMINAL_VT100_UNDERLINE = ""; GDCM_TERMINAL_VT100_BLINK = ""; GDCM_TERMINAL_VT100_INVERSE = ""; GDCM_TERMINAL_VT100_FOREGROUND_BLACK = ""; GDCM_TERMINAL_VT100_FOREGROUND_RED = ""; GDCM_TERMINAL_VT100_FOREGROUND_GREEN = ""; GDCM_TERMINAL_VT100_FOREGROUND_YELLOW = ""; GDCM_TERMINAL_VT100_FOREGROUND_BLUE = ""; GDCM_TERMINAL_VT100_FOREGROUND_MAGENTA = ""; GDCM_TERMINAL_VT100_FOREGROUND_CYAN = ""; GDCM_TERMINAL_VT100_FOREGROUND_WHITE = ""; GDCM_TERMINAL_VT100_BACKGROUND_BLACK = ""; GDCM_TERMINAL_VT100_BACKGROUND_RED = ""; GDCM_TERMINAL_VT100_BACKGROUND_GREEN = ""; GDCM_TERMINAL_VT100_BACKGROUND_YELLOW = ""; GDCM_TERMINAL_VT100_BACKGROUND_BLUE = ""; GDCM_TERMINAL_VT100_BACKGROUND_MAGENTA = ""; GDCM_TERMINAL_VT100_BACKGROUND_CYAN = ""; GDCM_TERMINAL_VT100_BACKGROUND_WHITE = ""; } } void PrintValue(VR::VRType const &vr, VM const &vm, const Value &v); template inline char *bswap(char *out, const char *in, size_t length) { assert( !(length % sizeof(T)) ); assert( out != in ); for(size_t i = 0; i < length; i+=2) { //const char copy = in[i]; out[i] = in[i+1]; out[i+1] = in[i]; } return out; } //----------------------------------------------------------------------------- /* void Printer::PrintElement(std::ostream& os, const ImplicitDataElement &ide, DictEntry const &entry) { const Tag &t = _val.GetTag(); const uint32_t vl = _val.GetVL(); _os << t; if ( printVR ) { //_os << " (VR=" << VR::GetVRString(dictVR) << ")"; _os << " " << VR::GetVRString(dictVR) << " "; } //_os << "\tVL=" << std::dec << vl << "\tValueField=["; if( _val.GetVL() ) { // FIXME FIXME: // value could dereference a NULL pointer in case of 0 length... const Value& value = _val.GetValue(); if( dictVR != VR::INVALID && VR::IsBinary(dictVR) ) { PrintValue(dictVR, vm, value); } else { _os << "[" << value << "]"; } } //_os << "]"; _os << "\t\t"; _os << "#" << std::setw(4) << std::setfill(' ') << std::dec << vl << ", 1 "; } */ // = reinterpret_cast< const Element& > ( array ); // os.flush(); // memcpy( (void*)(&e), array, e.GetLength() * sizeof( VRToType::Type) ); // bswap::Type>( (char*)(&e), array, e.GetLength() * sizeof( VRToType::Type) ); #define PrinterTemplateSubCase1n(type,rep) \ case VM::rep: \ {Element e; \ /*assert( VM::rep == VM::VM1_n );*/ \ e.SetArray( (const VRToType::Type *)array, length, true ); \ e.Print( os ); }\ break; #define PrinterTemplateSubCase(type,rep) \ case VM::rep: \ {Element e; \ /*assert( bv.GetLength() == VMToLength::Length * sizeof( VRToType::Type) ); */ \ assert( bv.GetLength() == e.GetLength() * sizeof( VRToType::Type) ); \ memcpy( (void*)(&e), array, e.GetLength() * sizeof( VRToType::Type) ); \ e.Print( os ); }\ break; #define PrinterTemplateSub(type) \ switch(vm) { \ PrinterTemplateSubCase(type, VM1) \ PrinterTemplateSubCase(type, VM2) \ PrinterTemplateSubCase(type, VM3) \ PrinterTemplateSubCase(type, VM4) \ PrinterTemplateSubCase(type, VM5) \ PrinterTemplateSubCase(type, VM6) \ PrinterTemplateSubCase(type, VM24) \ PrinterTemplateSubCase1n(type, VM1_n) \ default: assert(0); } #define PrinterTemplateSub2(type) \ switch(vm) { \ PrinterTemplateSubCase1n(type, VM1) \ default: assert(0); } #define PrinterTemplateCase(type) \ case VR::type: \ PrinterTemplateSub(type) \ break; #define PrinterTemplateCase2(type) \ case VR::type: \ PrinterTemplateSub2(type) \ break; #define PrinterTemplate() \ switch(vr) { \ PrinterTemplateCase(AE) \ PrinterTemplateCase(AS) \ PrinterTemplateCase(AT) \ PrinterTemplateCase(CS) \ PrinterTemplateCase(DA) \ PrinterTemplateCase(DS) \ PrinterTemplateCase(DT) \ PrinterTemplateCase(FL) \ PrinterTemplateCase(FD) \ PrinterTemplateCase(IS) \ PrinterTemplateCase(LO) \ PrinterTemplateCase(LT) \ PrinterTemplateCase2(OB) \ PrinterTemplateCase(OF) \ PrinterTemplateCase2(OW) \ PrinterTemplateCase(PN) \ PrinterTemplateCase(SH) \ PrinterTemplateCase(SL) \ PrinterTemplateCase(SQ) \ PrinterTemplateCase(SS) \ PrinterTemplateCase(ST) \ PrinterTemplateCase(TM) \ PrinterTemplateCase(UI) \ PrinterTemplateCase(UL) \ PrinterTemplateCase(UN) \ PrinterTemplateCase(US) \ PrinterTemplateCase(UT) \ default: assert(0); } void PrintValue(VR::VRType const &vr, VM const &vm, const Value &v) { try { const ByteValue &bv = dynamic_cast(v); const void *array = bv.GetVoidPointer(); const VL &length = bv.GetLength(); //unsigned short val = *(unsigned short*)(array); std::ostream &os = std::cout; // Big phat MACRO: PrinterTemplate() } catch(...) { // Indeed a SequenceOfFragments is not handle ... std::cerr << "Problem in PrintValue" << std::endl; } } //----------------------------------------------------------------------------- #if 0 void Printer::PrintDataSet(std::ostream& os, const DataSet &ds) { //ImplicitDataElement de; Printer::PrintStyles pstyle = is.GetPrintStyle(); (void)pstyle; bool printVR = true; //is.GetPrintVR(); std::ostream &_os = std::cout; //static const Dicts dicts; //const Dict &d = dicts.GetPublicDict(); static const Dict d; static const GroupDict gd; try { //while( is.Read(de) ) DataSet::ConstIterator it = ds.Begin(); for( ; it != ds.End(); ++it ) { const ImplicitDataElement &de = *it; const Tag &t = de.GetTag(); const DictEntry &entry = d.GetDictEntry(de.GetTag()); // Use VR from dictionary VR::VRType vr = entry.GetVR(); VM::VMType vm = entry.GetVM(); if( /*de.GetTag().GetGroup()%2 &&*/ de.GetTag().GetElement() == 0 ) { assert( vr == VR::INVALID || vr == VR::UL ); assert( vm == VM::VM0 || vm == VM::VM1 ); vr = VR::UL; vm = VM::VM1; } if( vr == VR::INVALID || VR::IsBinary(vr) || VR::IsASCII( vr ) ) { // TODO: FIXME FIXME FIXME if ( de.GetTag().GetElement() == 0x0 ) { if( vr == VR::INVALID ) // not found { vr = VR::UL; // this is a group length (VR=UL,VM=1) } } if( vr == VR::INVALID && entry.GetVR() != VR::INVALID ) { vr = entry.GetVR(); } // TODO FIXME FIXME FIXME // Data Element (7FE0,0010) Pixel Data has the Value Representation // OW and shall be encoded in Little Endian. //VM::VMType vm = VM::VM1; if( t == Tag(0x7fe0,0x0010) ) { assert( vr == VR::OB_OW ); vr = VR::OW; //vm = VM::VM1_n; } // RETIRED: // See PS 3.5 - 2004 // Data Element (50xx,3000) Curve Data has the Value Representation OB // with its component points (n-tuples) having the Value Representation // specified in Data Value Representation (50xx,0103). // The component points shall be encoded in Little Endian. else if( t == Tag(0x5004,0x3000) ) // FIXME { assert( vr == VR::OB_OW ); vr = VR::OB; } // Value of pixels not present in the native image added to an image // to pad to rectangular format. See C.7.5.1.1.2 for further explanation. // Note: The Value Representation of this Attribute is determined // by the value of Pixel Representation (0028,0103). if( vr == VR::US_SS ) { if( t == Tag(0x0028,0x0120) // Pixel Padding Value || t == Tag(0x0028,0x0106) // Smallest Image Pixel Value || t == Tag(0x0028,0x0107) // Largest Image Pixel Value || t == Tag(0x0028,0x0108) // Smallest Pixel Value in Series || t == Tag(0x0028,0x0109) // Largest Pixel Value in Series || t == Tag(0x0028,0x1101) // Red Palette Color Lookup Table Descriptor || t == Tag(0x0028,0x1102) // Green Palette Color Lookup Table Descriptor || t == Tag(0x0028,0x1103) // Blue Palette Color Lookup Table Descriptor ) { // TODO It would be nice to have a TagToVR<0x0028,0x0103>::VRType // and TagToVM<0x0028,0x0103>::VMType ... // to be able to have an independent Standard from implementation :) const ImplicitDataElement &pixel_rep = ds.GetDataElement( Tag(0x0028, 0x0103) ); const Value &value = pixel_rep.GetValue(); const ByteValue &bv = static_cast(value); // FIXME: unsigned short pixel_rep_value = *(unsigned short*)(bv.GetPointer()); assert( pixel_rep_value == 0x0 || pixel_rep_value == 0x1 ); vr = pixel_rep_value ? VR::SS : VR::US; } else { assert(0); } } PrintImplicitDataElement(_os, de, printVR, vr /*entry.GetVR()*/, vm); } else { assert(0); const Value& val = de.GetValue(); _os << de.GetTag(); if ( printVR ) { //_os << " ?VR=" << vr; _os << " " << vr; } //_os << "\tVL=" << std::dec << de.GetVL() << "\tValueField=["; _os << "\t" << std::dec << de.GetVL() << "\tValueField=["; // Use super class of the template stuff //Attribute af; //// Last minute check, is it a Group Length: //af.SetVR(vr); //af.SetVM(vm); //af.SetLength( val.GetLength() ); //std::istringstream iss; //iss.str( std::string( val.GetPointer(), val.GetLength() ) ); //af.Read( iss ); //af.Print( _os ); _os << "]"; } if( de.GetTag().GetElement() == 0x0 ) { _os << "\t\t" << gd.GetName(de.GetTag().GetGroup() ) << " " << entry.GetName() << std::endl; } else { // _os.flush(); // std::streampos pos = _os.tellp(); // streambuf *s = _os.rdbuf(); //int pos = _os.str().size(); _os << " " << entry.GetName() << std::endl; } } } catch(std::exception &e) { std::cerr << "Exception:" << typeid(e).name() << std::endl; } } #endif // TODO / FIXME // SIEMENS_GBS_III-16-ACR_NEMA_1.acr is a tough kid: 0009,1131 is supposed to be VR::UL, but // there are only two bytes... #define StringFilterCase(type) \ case VR::type: \ { \ Element el; \ if( !de.IsEmpty() ) { \ el.Set( de.GetValue() ); \ if( el.GetLength() ) { \ os << "" << el.GetValue(); \ long l = std::min( (long) el.GetLength(), (long) (MaxPrintLength / VR::GetLength(VR::type)) ); \ for(long i = 1; i < l; ++i) os << "\\" << el.GetValue((unsigned int)i); \ os << ""; } \ else { if( de.IsEmpty() ) os << GDCM_TERMINAL_VT100_INVERSE << "(no value)" << GDCM_TERMINAL_VT100_NORMAL; \ else os << GDCM_TERMINAL_VT100_INVERSE << GDCM_TERMINAL_VT100_FOREGROUND_RED << "(VR=" << refvr << " is incompatible with length)" << GDCM_TERMINAL_VT100_NORMAL; } } \ else { assert( de.IsEmpty()); os << GDCM_TERMINAL_VT100_INVERSE << "(no value)" << GDCM_TERMINAL_VT100_NORMAL; } \ } break VR Printer::PrintDataElement(std::ostringstream &os, const Dicts &dicts, const DataSet & ds, const DataElement &de, std::ostream &out, std::string const & indent ) { const ByteValue *bv = de.GetByteValue(); const SequenceOfItems *sqi = nullptr; //de.GetSequenceOfItems(); const SequenceOfFragments *sqf = de.GetSequenceOfFragments(); std::string strowner; const char *owner = nullptr; const Tag& t = de.GetTag(); if( t.IsPrivate() && !t.IsPrivateCreator() ) { strowner = ds.GetPrivateCreator(t); owner = strowner.c_str(); } const DictEntry &entry = dicts.GetDictEntry(t,owner); const VR &vr = entry.GetVR(); const VM &vm = entry.GetVM(); const char *name = entry.GetName(); bool retired = entry.GetRetired(); //if( t.IsPrivate() ) assert( retired == false ); const VR &vr_read = de.GetVR(); const VL &vl_read = de.GetVL(); os << indent; // first thing do the shift ! os << t << " "; os << vr_read << " "; //VR refvr = GetRefVR(dicts, de); VR refvr; // always prefer the vr from the file: if( vr_read == VR::INVALID ) { refvr = vr; } else if ( vr_read == VR::UN && vr != VR::INVALID ) // File is explicit, but still prefer vr from dict when UN { refvr = vr; } else // cool the file is Explicit ! { refvr = vr_read; } if( vr.IsDual() ) // Always check { refvr = DataSetHelper::ComputeVR(*F,ds, t); } assert( refvr != VR::US_SS ); assert( refvr != VR::OB_OW ); if( !de.IsEmpty() ) { const Value &value = de.GetValue(); if( dynamic_cast( &value ) ) { sqi = de.GetValueAsSQ(); refvr = VR::SQ; assert( refvr == VR::SQ ); } #if 0 else if( vr == VR::SQ && vr_read != VR::SQ ) { sqi = de.GetValueAsSQ(); refvr = VR::SQ; assert( refvr == VR::SQ ); } #endif } if( (vr_read == VR::INVALID || vr_read == VR::UN ) && vl_read.IsUndefined() ) { assert( refvr == VR::SQ ); } // if( vr_read == VR::SQ || vr_read == VR::UN ) // { // sqi = de.GetValueAsSQ(); // } if( vr != VR::INVALID && (!vr.Compatible( vr_read ) || vr_read == VR::INVALID || vr_read == VR::UN || vr_read != refvr ) ) { assert( vr != VR::INVALID ); // FIXME : if terminal supports it: print in red/green ! os << GDCM_TERMINAL_VT100_FOREGROUND_GREEN; if( vr == VR::US_SS || vr == VR::OB_OW ) { os << "(" << vr << " => " << refvr << ") "; } else { os << "(" << vr << ") "; } os << GDCM_TERMINAL_VT100_NORMAL; } else if( sqi /*de.GetSequenceOfItems()*/ && refvr == VR::INVALID ) { // when vr == VR::INVALID and vr_read is also VR::INVALID, we have a seldom case where we can guess // the vr // eg. CD1/647662/647663/6471066 has a SQ at (2001,9000) os << GDCM_TERMINAL_VT100_FOREGROUND_GREEN; os << "(SQ) "; os << GDCM_TERMINAL_VT100_NORMAL; assert( refvr == VR::INVALID ); refvr = VR::SQ; } // Print Value now: if( refvr & VR::VRASCII ) { assert( !sqi && !sqf ); if( bv ) { VL l = std::min( bv->GetLength(), MaxPrintLength ); os << "["; if( bv->IsPrintable(l) ) { bv->PrintASCII(os,l); } else { os << GDCM_TERMINAL_VT100_INVERSE; os << GDCM_TERMINAL_VT100_FOREGROUND_RED; bv->PrintASCII(os,l); os << GDCM_TERMINAL_VT100_NORMAL; } os << "]"; } else { assert( de.IsEmpty() ); os << GDCM_TERMINAL_VT100_INVERSE; os << "(no value)"; os << GDCM_TERMINAL_VT100_NORMAL; } } else { assert( refvr & VR::VRBINARY || (vr == VR::INVALID && refvr == VR::INVALID) ); //std::ostringstream os; std::string s; switch(refvr) { StringFilterCase(AT); StringFilterCase(FL); StringFilterCase(FD); //StringFilterCase(OB); StringFilterCase(OD); StringFilterCase(OF); //StringFilterCase(OW); StringFilterCase(SL); //StringFilterCase(SQ); StringFilterCase(SS); StringFilterCase(UL); //StringFilterCase(UN); StringFilterCase(US); //StringFilterCase(UT); StringFilterCase(SV); StringFilterCase(UV); case VR::OB: case VR::OW: case VR::OL: case VR::OV: case VR::OB_OW: case VR::UN: case VR::US_OW: // TODO: check with ModalityLUT.dcm case VR::US_SS_OW: // TODO: check with ModalityLUT.dcm /* VR::US_SS_OW: undefined_length_un_vr.dcm GDCMFakeJPEG.dcm PhilipsWith15Overlays.dcm */ { if ( bv ) { //VL l = std::min( bv->GetLength(), MaxPrintLength ); //VL l = std::min( (int)bv->GetLength(), 0xF ); //int width = (vr == VR::OW ? 4 : 2); //os << std::hex << std::setw( width ) << std::setfill('0'); bv->PrintHex(os, MaxPrintLength / 4); //os << std::dec; } else if ( sqf ) { assert( t == Tag(0x7fe0,0x0010) ); //os << *sqf; } else if ( sqi ) { // gdcmDataExtra/gdcmSampleData/images_of_interest/illegal_UN_stands_for_SQ.dcm gdcmErrorMacro( "Should not happen: VR=UN but contains a SQ" ); //os << *sqi; } else { assert( !sqi && !sqf ); assert( de.IsEmpty() ); os << GDCM_TERMINAL_VT100_INVERSE << "(no value)" << GDCM_TERMINAL_VT100_NORMAL; } } break; case VR::US_SS: // impossible... assert( refvr != VR::US_SS ); break; case VR::SQ: if( !sqi /*!de.GetSequenceOfItems()*/ && !de.IsEmpty() && de.GetValue().GetLength() ) { // This case is insane, this is an implicit file, with a defined length SQ. // Since this is a private element there is no way to guess that, and to // make it even worse the binary blob does not start with item start... // Bug_Philips_ItemTag_3F3F.dcm //os << GDCM_TERMINAL_VT100_BACKGROUND_RED; //bv->PrintHex(os, MaxPrintLength / 4); //os << GDCM_TERMINAL_VT100_NORMAL; } else { if( vl_read.IsUndefined() ) { os << "(Sequence with undefined length)"; } else { os << "(Sequence with defined length)"; } } break; // Let's be a little more helpful and try to print anyway when possible: case VR::INVALID: { if( bv ) { VL l = std::min( bv->GetLength(), MaxPrintLength ); if( bv->IsPrintable(l) ) { os << "["; bv->PrintASCII(os,l); os << "]"; } else if( t == Tag(0xfffe,0xe000) ) bv->PrintHex(os, MaxPrintLength / 8); else { os << GDCM_TERMINAL_VT100_INVERSE; // << "(non-printable character found)" bv->PrintHex(os, MaxPrintLength / 8); os << GDCM_TERMINAL_VT100_NORMAL; } } else { assert( !sqi && !sqf ); assert( de.IsEmpty() ); os << GDCM_TERMINAL_VT100_INVERSE << "(no value)" << GDCM_TERMINAL_VT100_NORMAL; } } break; /* ASCII are treated elsewhere but we do not want to use default: here to get warnings */ /* hopefully compiler is smart and remove dead switch/case */ case VR::AE: case VR::AS: case VR::CS: case VR::DA: case VR::DS: case VR::DT: case VR::IS: case VR::LO: case VR::LT: case VR::PN: case VR::SH: case VR::ST: case VR::TM: case VR::UC: case VR::UI: case VR::UR: case VR::UT: /* others */ case VR::VL16: case VR::VL32: case VR::VRASCII: case VR::VRBINARY: case VR::VR_VM1: case VR::VRALL: case VR::VR_END: assert(0); break; } os << s; } out.width(57); out << std::left << os.str(); // There is something wrong going on when doing terminal color stuff // Let's add a couple of space to be nicer... if( os.str().find( GDCM_TERMINAL_VT100_NORMAL ) != std::string::npos ) { out << " "; } os.str( "" ); // Extra info (not in the file) os << " # "; // Append the VL if( vl_read.IsUndefined() ) { os << "u/l"; } else { os << std::dec << vl_read; } if( vl_read.IsOdd() ) { os << GDCM_TERMINAL_VT100_FOREGROUND_GREEN; os << " (" << (vl_read + 1) << ")"; os << GDCM_TERMINAL_VT100_NORMAL; } os << ","; // Append the VM if( vm != VM::VM0 ) { os << vm; } else { os << GDCM_TERMINAL_VT100_FOREGROUND_RED; os << "?"; os << GDCM_TERMINAL_VT100_NORMAL; } VM guessvm = VM::VM0; if( refvr & VR::VRASCII ) { assert( refvr != VR::INVALID ); assert( refvr & VR::VRASCII ); if( bv ) { size_t count = VM::GetNumberOfElementsFromArray(bv->GetPointer(), bv->GetLength()); guessvm = VM::GetVMTypeFromLength(count, 1); // hackish... } } else if( refvr & VR::VRBINARY ) { assert( refvr != VR::INVALID ); assert( refvr & VR::VRBINARY ); if( refvr & VR::OB_OW || refvr == VR::OD || refvr == VR::OF || refvr == VR::SQ ) { guessvm = VM::VM1; } else if ( refvr == VR::UN && sqi ) { // This is a SQ / UN guessvm = VM::VM1; } else if( bv ) { guessvm = VM::GetVMTypeFromLength(bv->GetLength(), refvr.GetSize() ); } else { if( de.IsEmpty() ) guessvm = VM::VM0; else assert( 0 && "Impossible" ); } } else if( refvr == VR::INVALID ) { refvr = VR::UN; guessvm = VM::VM1; } else { // Burst into flames ! assert( 0 && "Impossible happen" ); } if( !vm.Compatible( guessvm ) ) { os << GDCM_TERMINAL_VT100_FOREGROUND_RED; os << " (" << guessvm << ") "; os << GDCM_TERMINAL_VT100_NORMAL; } // Append the name now: if( name && *name ) { // No owner case ! if( t.IsPrivate() && (owner == nullptr || *owner == 0 ) && !t.IsPrivateCreator() ) { os << GDCM_TERMINAL_VT100_FOREGROUND_RED; os << " " << name; os << GDCM_TERMINAL_VT100_NORMAL; } // 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; os << GDCM_TERMINAL_VT100_NORMAL; } else { os << GDCM_TERMINAL_VT100_BOLD; os << " " << name; os << GDCM_TERMINAL_VT100_NORMAL; } } else { os << GDCM_TERMINAL_VT100_FOREGROUND_RED; if( t.IsPublic() ) { // What ? A public element that we do not know about !!! os << GDCM_TERMINAL_VT100_BLINK; } os << " GDCM:UNKNOWN"; // Special keyword os << GDCM_TERMINAL_VT100_NORMAL; } os << "\n"; return refvr; } void Printer::PrintSQ(const SequenceOfItems *sqi, std::ostream & os, std::string const & indent) { if( !sqi ) return; SequenceOfItems::ItemVector::const_iterator it = sqi->Items.begin(); for(; it != sqi->Items.end(); ++it) { const Item &item = *it; const DataSet &ds = item.GetNestedDataSet(); const DataElement &deitem = item; std::string nextindent = indent + " "; os << nextindent << deitem.GetTag(); os << " "; os << "na"; //deitem.GetVR(); os << " "; if( deitem.GetVL().IsUndefined() ) { os << "(Item with undefined length)"; } else { os << "(Item with defined length)"; } os << "\n"; PrintDataSet(ds, os, nextindent + " "); if( deitem.GetVL().IsUndefined() ) { const Tag itemDelItem(0xfffe,0xe00d); os << nextindent << itemDelItem << "\n"; } } if( sqi->GetLength().IsUndefined() ) { const Tag seqDelItem(0xfffe,0xe0dd); os << indent << seqDelItem << "\n"; } } void Printer::PrintDataSet(const DataSet &ds, std::ostream &out, std::string const & indent ) { const Global& g = GlobalInstance; const Dicts &dicts = g.GetDicts(); const Dict &d = dicts.GetPublicDict(); (void)d; DataSet::ConstIterator it = ds.Begin(); for( ; it != ds.End(); ++it ) { const DataElement &de = *it; //const ByteValue *bv = de.GetByteValue(); const SequenceOfFragments *sqf = de.GetSequenceOfFragments(); std::ostringstream os; VR refvr = PrintDataElement(os, dicts, ds, de, out, indent); if( refvr == VR::SQ /*|| sqi*/ ) { //SmartPointer sqi2 = DataSetHelper::ComputeSQFromByteValue( *F, ds, de.GetTag() ); SmartPointer sqi2 = de.GetValueAsSQ(); // may throw PrintSQ(sqi2, os, indent); /* const SequenceOfItems *sqi = de.GetSequenceOfItems(); if( sqi ) // empty SQ ? { assert( sqi ); PrintSQ(sqi, os, indent); } else { if( !de.IsEmpty() ) { // Ok so far we know: // 1. VR is SQ sqi == NULL // 2. DataElement is not empty ... // => This is a VR:UN or Implicit SQ with defined length. // let's try to interpret this sequence SequenceOfItems *sqi2 = DataSetHelper::ComputeSQFromByteValue( *F, ds, de.GetTag() ); if(sqi2) PrintSQ(sqi2, os, indent); delete sqi2; } } */ } else if ( sqf ) { std::string nextindent = indent + " "; const BasicOffsetTable & table = sqf->GetTable(); //os << nextindent << table.GetTag() << "\n"; PrintDataElement(os,dicts,ds,table,out,nextindent); size_t numfrag = sqf->GetNumberOfFragments(); for(size_t i = 0; i < numfrag; ++i) { const Fragment& frag = sqf->GetFragment(i); //os << nextindent<< frag << "\n"; PrintDataElement(os,dicts,ds,frag,out,nextindent); } const Tag seqDelItem(0xfffe,0xe0dd); VL zero = 0; os << /*nextindent <<*/ seqDelItem; os << " " << zero << "\n"; } else { // This is a byte value, so it should have been already treated } out << os.str(); } } //----------------------------------------------------------------------------- void DumpDataSet(const DataSet &ds, std::ostream &os ) { DataSet::ConstIterator it = ds.Begin(); for( ; it != ds.End(); ++it ) { const DataElement &de = *it; const Tag& t = de.GetTag(); (void)t; const VR& vr = de.GetVR(); (void)vr; os << de << std::endl; //if( VR::IsASCII( vr ) ) // { // } } } //----------------------------------------------------------------------------- void Printer::Print(std::ostream& os) { os << "# Dicom-File-Format\n"; os << "\n"; os << "# Dicom-Meta-Information-Header\n"; os << "# Used TransferSyntax: \n"; const FileMetaInformation &meta = F->GetHeader(); if( PrintStyle == VERBOSE_STYLE ) PrintDataSet(meta, os); else if (PrintStyle == CONDENSED_STYLE ) DumpDataSet(meta, os); os << "\n# Dicom-Data-Set\n"; os << "# Used TransferSyntax: "; const TransferSyntax &metats = meta.GetDataSetTransferSyntax(); os << metats; os << std::endl; const DataSet &ds = F->GetDataSet(); if( PrintStyle == VERBOSE_STYLE ) PrintDataSet(ds, os); else if (PrintStyle == CONDENSED_STYLE ) DumpDataSet(ds, os); } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmPrinter.h000066400000000000000000000055361412732066400231520ustar00rootroot00000000000000/*========================================================================= 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 GDCMPRINTER_H #define GDCMPRINTER_H // TODO Class to implement printing // Since DICOM does printing ? // Also I would like to encapsulate the IsCharacterPrintable thing // (to avoid printing \0 and other weird characters) // \todo I still need to implement skipping of group (shadow) // need to implement longer field to read /* * Output: * For ASCII: * Typically will look like: * [ORIGINAL\PRIMARY\OTHER] * If a non printable character is found: RED and INVERSE is used: * [ .] * * when the VR is not found (file or dict), we check if we can print the output: * on success ASCII mode is used, on failure the output is printed a series of bytes * * Special case when the data element is empty: * INVERSE << (no value) * * retired public element are printed in red and underline * unknown private element are printed in RED followed by 'UNKNOWN' * * Correct VR is printed in green just after the found VR * * length of data element is printed in bytes, followed by the VM, a green VM is appended * if this is not compatible */ #include "gdcmFile.h" #include "gdcmDataElement.h" namespace gdcm { class DataSet; class DictEntry; class Dicts; /** * \brief Printer class */ // It's a sink there is no output class GDCM_EXPORT Printer { public: Printer(); ~Printer(); /// Set file void SetFile(File const &f) { F = &f; } /// Set color mode or not void SetColor(bool c); typedef enum { VERBOSE_STYLE = 0, // GDCM Legacy VERBOSE one CONDENSED_STYLE, // // Ok I am missing voc here ...better naming would be nice XML, // CXX } PrintStyles; /// Set PrintStyle value void SetStyle(PrintStyles ps) { PrintStyle = ps; } /// Get PrintStyle value PrintStyles GetPrintStyle() const { return PrintStyle; } /// Print void Print(std::ostream& os); /// Print an individual dataset void PrintDataSet(const DataSet &ds, std::ostream& os, const std::string &s = ""); protected: VR PrintDataElement(std::ostringstream & os, const Dicts &dicts, const DataSet & ds, const DataElement &de, std::ostream &out, std::string const & indent ); void PrintSQ(const SequenceOfItems *sqi, std::ostream & os, std::string const & indent); PrintStyles PrintStyle; const File *F; VL MaxPrintLength; }; } // end namespace gdcm #endif //GDCMPRINTER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmRAWCodec.cxx000066400000000000000000000140301412732066400234560ustar00rootroot00000000000000/*========================================================================= 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 "gdcmRAWCodec.h" #include "gdcmTransferSyntax.h" #include "gdcmByteSwap.txx" #include "gdcmDataElement.h" #include "gdcmSequenceOfFragments.h" #include "gdcmUnpacker12Bits.h" #include #include #include namespace gdcm { class RAWInternals { public: }; RAWCodec::RAWCodec() { Internals = new RAWInternals; } RAWCodec::~RAWCodec() { delete Internals; } bool RAWCodec::CanCode(TransferSyntax const &ts) const { return ts == TransferSyntax::ImplicitVRLittleEndian || ts == TransferSyntax::ExplicitVRLittleEndian || ts == TransferSyntax::ExplicitVRBigEndian || ts == TransferSyntax::ImplicitVRBigEndianPrivateGE || ts == TransferSyntax::DeflatedExplicitVRLittleEndian; } bool RAWCodec::CanDecode(TransferSyntax const &ts) const { return ts == TransferSyntax::ImplicitVRLittleEndian || ts == TransferSyntax::ExplicitVRLittleEndian || ts == TransferSyntax::ExplicitVRBigEndian || ts == TransferSyntax::ImplicitVRBigEndianPrivateGE || ts == TransferSyntax::DeflatedExplicitVRLittleEndian; } bool RAWCodec::Code(DataElement const &in, DataElement &out) { out = in; //assert(0); return true; } bool RAWCodec::DecodeBytes(const char* inBytes, size_t inBufferLength, char* outBytes, size_t inOutBufferLength) { // First let's see if we can do a fast-path: if( !NeedByteSwap && !RequestPaddedCompositePixelCode && PI != PhotometricInterpretation::YBR_FULL_422 && /*!PlanarConfiguration &&*/ !RequestPlanarConfiguration && GetPixelFormat().GetBitsAllocated() != 12 && !NeedOverlayCleanup ) { assert( !NeedOverlayCleanup ); assert( PI != PhotometricInterpretation::YBR_PARTIAL_422 ); assert( PI != PhotometricInterpretation::YBR_PARTIAL_420 ); assert( PI != PhotometricInterpretation::YBR_ICT ); assert( this->GetPixelFormat() != PixelFormat::UINT12 ); assert( this->GetPixelFormat() != PixelFormat::INT12 ); // DermaColorLossLess.dcm //assert(inBufferLength == inOutBufferLength || inBufferLength == inOutBufferLength + 1); // What if the user request a subportion of the image: // this happen in the case of MOSAIC image, where we are only interested in the non-zero // pixel of the tiled image. // removal of this assert also solve an issue with: SIEMENS_GBS_III-16-ACR_NEMA_1.acr // where we need to discard trailing pixel data bytes. if( inOutBufferLength <= inBufferLength ) { memcpy(outBytes, inBytes, inOutBufferLength); } else { gdcmWarningMacro( "Requesting too much data. Truncating result" ); memcpy(outBytes, inBytes, inBufferLength); } return true; } // else assert( inBytes ); assert( outBytes ); std::stringstream is; is.write(inBytes, inBufferLength); std::stringstream os; bool r = DecodeByStreams(is, os); assert( r ); if(!r) return false; std::string str = os.str(); //std::string::size_type check = str.size();//unused if( this->GetPixelFormat() == PixelFormat::UINT12 || this->GetPixelFormat() == PixelFormat::INT12 ) { size_t len = str.size() * 16 / 12; char * copy = new char[len]; bool b = Unpacker12Bits::Unpack(copy, &str[0], str.size() ); (void)b; assert( b ); assert (len == inOutBufferLength); assert(inOutBufferLength == len); memcpy(outBytes, copy, len); delete[] copy; this->GetPixelFormat().SetBitsAllocated( 16 ); } else { // DermaColorLossLess.dcm //assert (check == inOutBufferLength || check == inOutBufferLength + 1); // problem with: SIEMENS_GBS_III-16-ACR_NEMA_1.acr memcpy(outBytes, str.c_str(), inOutBufferLength); } return r; } bool RAWCodec::Decode(DataElement const &in, DataElement &out) { // First let's see if we can do a fast-path: if( !NeedByteSwap && !RequestPaddedCompositePixelCode && PI == PhotometricInterpretation::MONOCHROME2 && !PlanarConfiguration && !RequestPlanarConfiguration && GetPixelFormat().GetBitsAllocated() != 12 && !NeedOverlayCleanup ) { assert( this->GetPixelFormat() != PixelFormat::UINT12 ); assert( this->GetPixelFormat() != PixelFormat::INT12 ); out = in; return true; } // else const ByteValue *bv = in.GetByteValue(); assert( bv ); std::stringstream is; is.write(bv->GetPointer(), bv->GetLength()); std::stringstream os; bool r = DecodeByStreams(is, os); if(!r) return false; assert( r ); std::string str = os.str(); //std::string::size_type check = str.size(); out = in; if( this->GetPixelFormat() == PixelFormat::UINT12 || this->GetPixelFormat() == PixelFormat::INT12 ) { 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() ); assert( b ); (void)b; VL::Type lenSize = (VL::Type)len; out.SetByteValue( copy, lenSize ); delete[] copy; this->GetPixelFormat().SetBitsAllocated( 16 ); } else { VL::Type strSize = (VL::Type) str.size(); out.SetByteValue( &str[0], strSize); } return r; } bool RAWCodec::DecodeByStreams(std::istream &is, std::ostream &os) { bool r = ImageCodec::DecodeByStreams(is, os); return r; } bool RAWCodec::GetHeaderInfo(std::istream &, TransferSyntax &ts) { ts = TransferSyntax::ExplicitVRLittleEndian; if( NeedByteSwap ) { ts = TransferSyntax::ImplicitVRBigEndianPrivateGE; } return true; } ImageCodec * RAWCodec::Clone() const { return nullptr; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmRAWCodec.h000066400000000000000000000030141412732066400231030ustar00rootroot00000000000000/*========================================================================= 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 GDCMRAWCODEC_H #define GDCMRAWCODEC_H #include "gdcmImageCodec.h" namespace gdcm { class RAWInternals; /** * \brief RAWCodec class */ class GDCM_EXPORT RAWCodec : public ImageCodec { public: RAWCodec(); ~RAWCodec() override; bool CanCode(TransferSyntax const &ts) const override; bool CanDecode(TransferSyntax const &ts) const override; bool Decode(DataElement const &is, DataElement &os) override; bool Code(DataElement const &in, DataElement &out) override; bool GetHeaderInfo(std::istream &is, TransferSyntax &ts) override; ImageCodec * Clone() const override; /// Used by the ImageStreamReader-- converts a read in /// buffer into one with the proper encodings. bool DecodeBytes(const char* inBytes, size_t inBufferLength, char* outBytes, size_t inOutBufferLength); protected: bool DecodeByStreams(std::istream &is, std::ostream &os) override; private: RAWInternals *Internals; }; } // end namespace gdcm #endif // GDCMRAWCODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmRLECodec.cxx000066400000000000000000000720441412732066400234600ustar00rootroot00000000000000/*========================================================================= 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 "gdcmRLECodec.h" #include "gdcmTransferSyntax.h" #include "gdcmTrace.h" #include "gdcmByteSwap.txx" #include "gdcmDataElement.h" #include "gdcmSequenceOfFragments.h" #include "gdcmSmartPointer.h" #include "gdcmSwapper.h" #include #include // req C++11 #include // ptrdiff_t fix #include #include namespace gdcm { // TODO ideally this code should be in utilities for ease of reuse class RLEHeader { public: uint32_t NumSegments; uint32_t Offset[15]; void Print(std::ostream &os) { os << "NumSegments:" << NumSegments << "\n"; for(int i=0; i<15; ++i) { os << i << ":" << Offset[i] << "\n"; } } }; class RLEFrame { public: bool Read(std::istream &is) { // read Header (64 bytes) is.read((char*)(&Header), sizeof(uint32_t)*16); assert( sizeof(uint32_t)*16 == 64 ); assert( sizeof(RLEHeader) == 64 ); SwapperNoOp::SwapArray((uint32_t*)&Header,16); uint32_t numSegments = Header.NumSegments; if( numSegments >= 1 ) { if( Header.Offset[0] != 64 ) return false; } // We just check that we are indeed at the proper position start+64 return true; } void Print(std::ostream &os) { Header.Print(os); } //private: RLEHeader Header; std::vector Bytes; }; class RLEInternals { public: RLEFrame Frame; std::vector SegmentLength; }; RLECodec::RLECodec() { Internals = new RLEInternals; Length = 0; BufferLength = 0; } RLECodec::~RLECodec() { delete Internals; } bool RLECodec::CanDecode(TransferSyntax const &ts) const { return ts == TransferSyntax::RLELossless; } bool RLECodec::CanCode(TransferSyntax const &ts) const { return ts == TransferSyntax::RLELossless; } /* G.3 THE RLE ALGORITHM The RLE algorithm described in this section is used to compress Byte Segments into RLE Segments. There is a one-to-one correspondence between Byte Segments and RLE Segments. Each RLE segment must be an even number of bytes or padded at its end with zero to make it even. G.3.1 The RLE encoder A sequence of identical bytes (Replicate Run) is encoded as a two-byte code: < -count + 1 > , where count = the number of bytes in the run, and 2 <= count <= 128 and a non-repetitive sequence of bytes (Literal Run) is encoded as: < count - 1 > , where count = number of bytes in the sequence, and 1 <= count <= 128. The value of -128 may not be used to prefix a byte value. Note: It is common to encode a 2-byte repeat run as a Replicate Run except when preceded and followed by a Literal Run, in which case it's best to merge the three runs into a Literal Run. Three-byte repeats shall be encoded as Replicate Runs. Each row of the image shall be encoded separately and not cross a row boundary. */ inline int count_identical_bytes(const char *start, size_t len) { assert( len ); #if 0 const char *p = start + 1; const unsigned int cmin = std::min(128u,len); const char *end = start + cmin; while( p < end && *p == *start ) { ++p; } return p - start; #else const char ref = start[0]; unsigned int count = 1; // start at one; make unsigned for comparison const size_t cmin = std::min((size_t)128,len); while( count < cmin && start[count] == ref ) { //std::cerr << "count/len:" << count << "," << len << std::endl; ++count; } assert( /*2 <= count && */ count <= 128 ); // remove post condition as it will be our return error code assert( count >= 1 ); return count; #endif } inline int count_nonrepetitive_bytes(const char *start, size_t len) { /* * TODO: * I need a special handling when there is only a one repetition that break the Literal run... Note: It is common to encode a 2-byte repeat run as a Replicate Run except when preceded and followed by a Literal Run, in which case it's best to merge the three runs into a Literal Run. */ assert( len ); #if 0 const char *prev = start; const char *p = start + 1; const unsigned int cmin = std::min(128u,len); const char *end = start + cmin; while( p < end && *p != *prev ) { ++prev; ++p; } return p - start; #else unsigned int count = 1; const size_t cmin = std::min((size_t)128,len); #if 0 // TODO: this version that handles the note still does not work... while( count < cmin ) { if ( start[count] != start[count-1] ) { // Special case: if( count + 1 < cmin && start[count] != start[count+1] ) { continue; } break; } ++count; } #else #if 1 // This version properly encode: 0 1 1 0 as: 3 0 1 1 0 ... for( count = 1; count < cmin; ++count ) { if( start[count] == start[count-1] ) { if( count + 1 < cmin && start[count] != start[count+1] ) { continue; } --count;//Note that count can go negative, or wrapped if unsigned! break; } } #else // This version does not handle 0 1 1 0 as specified in the note in the DICOM standard while( count < cmin && start[count] != start[count-1] ) { ++count; } #endif #endif assert( 1 <= count && count <= 128 ); return count; #endif } /* return output length */ ptrdiff_t rle_encode(char *output, size_t outputlength, const char *input, size_t inputlength) { char *pout = output; const char *pin = input; size_t length = inputlength; while( pin != input + inputlength ) { assert( length <= inputlength ); assert( pin <= input + inputlength ); int count = count_identical_bytes(pin, length); if( count > 1 ) /* or 2 ? */ { // repeat case: // // Test first we are allowed to write two bytes: if( pout + 1 + 1 > output + outputlength ) return -1; *pout = (char)(-count + 1); assert( /**pout != -128 &&*/ 1 - *pout == count ); assert( *pout <= -1 && *pout >= -127 ); ++pout; *pout = *pin; ++pout; } else { // non repeat case: // ok need to compute non-repeat: count = count_nonrepetitive_bytes(pin, length); // first test we are allowed to write 1 + count bytes in the output buffer: if( pout + count + 1 > output + outputlength ) return -1; *pout = (char)(count - 1); assert( *pout != -128 && *pout+1 == count ); assert( *pout >= 0 ); ++pout; memcpy(pout, pin, count); pout += count; } // count byte where read, move pin to new position: pin += count; // compute remaining length: assert( count <= (int)length ); length -= count; } return pout - output; } template bool DoInvertPlanarConfiguration(T *output, const T *input, uint32_t inputlength) { const T *r = input+0; const T *g = input+1; const T *b = input+2; uint32_t length = (inputlength / 3) * 3; // remove the 0 padding assert( length == inputlength || length == inputlength - 1 ); assert( length % 3 == 0 ); uint32_t plane_length = length / 3; T *pout = output; // copy red plane: while( pout != output + plane_length * 1 ) { *pout++ = *r; r += 3; } assert( r == input + length ); // copy green plane: assert( pout == output + plane_length ); while( pout != output + plane_length * 2 ) { *pout++ = *g; g += 3; } assert( g == input + length + 1); // copy blue plane: assert( pout == output + 2*plane_length ); while( pout != output + plane_length * 3 ) { *pout++ = *b; b += 3; } assert( b == input + length + 2); assert ( pout == output + length ); return true; } bool RLECodec::Code(DataElement const &in, DataElement &out) { const unsigned int *dims = this->GetDimensions(); const unsigned int n = 256*256; char *outbuf; // At most we are encoding a single row at a time, so we would be very unlucky // if the row *after* compression would not fit in 256*256 bytes... char small_buffer[n]; outbuf = small_buffer; // Create a Sequence Of Fragments: SmartPointer sq = new SequenceOfFragments; const Tag itemStart(0xfffe, 0xe000); //sq->GetTable().SetTag( itemStart ); // FIXME ? Is this compulsory ? //const char dummy[4] = {}; //sq->GetTable().SetByteValue( dummy, sizeof(dummy) ); const ByteValue *bv = in.GetByteValue(); assert( bv ); const char *input = bv->GetPointer(); unsigned long bvl = bv->GetLength(); unsigned long image_len = bvl / dims[2]; // If 16bits, need to do the padded composite... char *buffer = nullptr; // if rgb (3 comp) need to the planar configuration char *bufferrgb = nullptr; if( GetPixelFormat().GetBitsAllocated() > 8 ) { //RequestPaddedCompositePixelCode = true; buffer = new char [ image_len ]; } if ( GetPhotometricInterpretation() == PhotometricInterpretation::RGB || GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL || GetPhotometricInterpretation() == PhotometricInterpretation::YBR_RCT || GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL_422 ) { bufferrgb = new char [ image_len ]; } unsigned int MaxNumSegments = 1; if( GetPixelFormat().GetBitsAllocated() == 8 ) { MaxNumSegments *= 1; } else if( GetPixelFormat().GetBitsAllocated() == 16 ) { MaxNumSegments *= 2; } else if( GetPixelFormat().GetBitsAllocated() == 32 ) { MaxNumSegments *= 4; } else { delete[] buffer; delete[] bufferrgb; return false; } if( GetPhotometricInterpretation() == PhotometricInterpretation::RGB || GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL || GetPhotometricInterpretation() == PhotometricInterpretation::YBR_RCT || GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL_422 ) { MaxNumSegments *= 3; } assert( GetPixelFormat().GetBitsAllocated() == 8 || GetPixelFormat().GetBitsAllocated() == 16 || GetPixelFormat().GetBitsAllocated() == 32 ); if( GetPixelFormat().GetSamplesPerPixel() == 3 ) { assert( MaxNumSegments % 3 == 0 ); } RLEHeader header = { static_cast ( MaxNumSegments ), { 64 } }; // there cannot be any space in between the end of the RLE header and the start // of the first RLE segment // // Create a RLE Frame for each frame: for(unsigned int dim = 0; dim < dims[2]; ++dim) { // Within each frame, create the RLE Segments: // lets' try a simple scheme where each Segments is given an equal portion // of the input image. const char *ptr_img = input + dim * image_len; if( GetPlanarConfiguration() == 0 && GetPixelFormat().GetSamplesPerPixel() == 3 ) { if( GetPixelFormat().GetBitsAllocated() == 8 ) { DoInvertPlanarConfiguration(bufferrgb, ptr_img, (uint32_t)(image_len / sizeof(char))); } else if ( GetPixelFormat().GetBitsAllocated() == 16 ) { DoInvertPlanarConfiguration((short*)(void*)bufferrgb, (const short*)(const void*)ptr_img, (uint32_t)(image_len / sizeof(short))); } else /* ( GetPixelFormat().GetBitsAllocated() == 32 ) */ { assert( GetPixelFormat().GetBitsAllocated() == 32 ); DoInvertPlanarConfiguration( (int32_t*)(void*)bufferrgb, (const int32_t*)(const void*)ptr_img, (uint32_t)(image_len / sizeof(int32_t)) ); } ptr_img = bufferrgb; } if( GetPixelFormat().GetBitsAllocated() == 32 ) { assert( !(image_len % 4) ); //assert( image_len % 3 == 0 ); unsigned int div = GetPixelFormat().GetSamplesPerPixel(); for(unsigned int j = 0; j < div; ++j) { unsigned long iimage_len = image_len / div; char *ibuffer = buffer + j * iimage_len; const char *iptr_img = ptr_img + j * iimage_len; assert( iimage_len % 4 == 0 ); for(unsigned long i = 0; i < iimage_len/4; ++i) { #ifdef GDCM_WORDS_BIGENDIAN ibuffer[i] = iptr_img[4*i+0]; #else ibuffer[i] = iptr_img[4*i+3]; #endif } for(unsigned long i = 0; i < iimage_len/4; ++i) { #ifdef GDCM_WORDS_BIGENDIAN ibuffer[i+iimage_len/4] = iptr_img[4*i+1]; #else ibuffer[i+iimage_len/4] = iptr_img[4*i+2]; #endif } for(unsigned long i = 0; i < iimage_len/4; ++i) { #ifdef GDCM_WORDS_BIGENDIAN ibuffer[i+2*iimage_len/4] = iptr_img[4*i+2]; #else ibuffer[i+2*iimage_len/4] = iptr_img[4*i+1]; #endif } for(unsigned long i = 0; i < iimage_len/4; ++i) { #ifdef GDCM_WORDS_BIGENDIAN ibuffer[i+3*iimage_len/4] = iptr_img[4*i+3]; #else ibuffer[i+3*iimage_len/4] = iptr_img[4*i+0]; #endif } } ptr_img = buffer; } else if( GetPixelFormat().GetBitsAllocated() == 16 ) { assert( !(image_len % 2) ); //assert( image_len % 3 == 0 ); unsigned int div = GetPixelFormat().GetSamplesPerPixel(); for(unsigned int j = 0; j < div; ++j) { unsigned long iimage_len = image_len / div; char *ibuffer = buffer + j * iimage_len; const char *iptr_img = ptr_img + j * iimage_len; assert( iimage_len % 2 == 0 ); for(unsigned long i = 0; i < iimage_len/2; ++i) { #ifdef GDCM_WORDS_BIGENDIAN ibuffer[i] = iptr_img[2*i]; #else ibuffer[i] = iptr_img[2*i+1]; #endif } for(unsigned long i = 0; i < iimage_len/2; ++i) { #ifdef GDCM_WORDS_BIGENDIAN ibuffer[i+iimage_len/2] = iptr_img[2*i+1]; #else ibuffer[i+iimage_len/2] = iptr_img[2*i]; #endif } } ptr_img = buffer; } assert( image_len % MaxNumSegments == 0 ); const size_t input_seg_length = image_len / MaxNumSegments; std::string datastr; for(unsigned int seg = 0; seg < MaxNumSegments; ++seg ) { size_t partition = input_seg_length; const char *ptr = ptr_img + seg * input_seg_length; assert( ptr < ptr_img + image_len ); if( seg == MaxNumSegments - 1 ) { partition += image_len % MaxNumSegments; assert( (MaxNumSegments-1) * input_seg_length + partition == (size_t)image_len ); } assert( partition == input_seg_length ); std::stringstream data; assert( partition % dims[1] == 0 ); size_t length = 0; // Do not cross row boundary: for(unsigned int y = 0; y < dims[1]; ++y) { ptrdiff_t llength = rle_encode(outbuf, n, ptr + y*dims[0], partition / dims[1] /*image_len*/); if( llength < 0 ) { gdcmErrorMacro( "RLE compressor error" ); delete[] buffer; delete[] bufferrgb; return false; } assert( llength ); data.write((char*)outbuf, llength); length += llength; } // update header header.Offset[1+seg] = (uint32_t)(header.Offset[seg] + length); assert( data.str().size() == length ); datastr += data.str(); } header.Offset[MaxNumSegments] = 0; std::stringstream os; //header.Print( std::cout ); os.write((char*)&header,sizeof(header)); std::string str = os.str() + datastr; assert( str.size() ); Fragment frag; //frag.SetTag( itemStart ); VL::Type strSize = (VL::Type)str.size(); frag.SetByteValue( &str[0], strSize ); sq->AddFragment( frag ); } out.SetValue( *sq ); delete[] buffer; delete[] bufferrgb; return true; } // G.3.2 The RLE decoder // Pseudo code for the RLE decoder is shown below: // Loop until the number of output bytes equals the uncompressed segment size // Read the next source byte into n // If n> =0 and n <= 127 then // output the next n+1 bytes literally // Elseif n <= - 1 and n >= -127 then // output the next byte -n+1 times // Elseif n = - 128 then // output nothing // Endif // Endloop size_t RLECodec::DecodeFragment(Fragment const & frag, char *buffer, size_t llen) { std::stringstream is; const ByteValue &bv = dynamic_cast(frag.GetValue()); size_t bv_len = bv.GetLength(); char *mybuffer = new char[bv_len]; bv.GetBuffer(mybuffer, bv.GetLength()); is.write(mybuffer, bv.GetLength()); delete[] mybuffer; std::stringstream os; SetLength( (unsigned long)llen ); #if !defined(NDEBUG) const unsigned int * const dimensions = this->GetDimensions(); const PixelFormat & pf = this->GetPixelFormat(); assert( llen == dimensions[0] * dimensions[1] * pf.GetPixelSize() ); #endif bool r = DecodeByStreams(is, os); if( !r ) return 0; (void)r; //warning removal std::streampos p = is.tellg(); // http://groups.google.com/group/microsoft.public.vc.stl/browse_thread/thread/96740930d0e4e6b8 if( !!is ) { // Indeed the length of the RLE stream has been padded with a \0 // which is discarded std::streamoff check = bv.GetLength() - p; // check == 2 for gdcmDataExtra/gdcmSampleData/US_DataSet/GE_US/2929J686-breaker //assert( check == 0 || check == 1 || check == 2 ); if( check ) { gdcmDebugMacro( "tiny offset detected in between RLE segments: " << check ); } } else { // ALOKA_SSD-8-MONO2-RLE-SQ.dcm gdcmWarningMacro( "Bad RLE stream" ); } std::string::size_type check = os.str().size(); // If the following assert fail expect big troubles: memcpy(buffer, os.str().c_str(), check); // pos += check; return check; } bool RLECodec::Decode(DataElement const &in, DataElement &out) { if( NumberOfDimensions == 2 ) { out = in; const SequenceOfFragments *sf = in.GetSequenceOfFragments(); if( !sf ) return false; unsigned long len = GetBufferLength(); std::stringstream is; sf->WriteBuffer( is ); SetLength( len ); std::stringstream os; bool r = DecodeByStreams(is, os); if( !r ) { gdcmErrorMacro( "DecodeByStreams failure." ); return false; } std::string str = os.str(); std::string::size_type check = str.size(); assert( check == len ); VL::Type checkCast = (VL::Type)check; out.SetByteValue( &str[0], checkCast ); return true; } else if ( NumberOfDimensions == 3 ) { out = in; const SequenceOfFragments *sf = in.GetSequenceOfFragments(); if( !sf ) return false; const unsigned long len = GetBufferLength(); unsigned long pos = 0; // Each RLE Frame store a 2D frame. len is the 3d length const size_t nframes = sf->GetNumberOfFragments(); const size_t zdim = Dimensions[2]; if( nframes != zdim ) { gdcmErrorMacro( "Invalid number of fragments: " << nframes << " should be: " << zdim ); return false; } char *buffer = new char[len]; const std::size_t llen = len / nframes; // assert( GetNumberOfDimensions() == 2 // || GetDimension(2) == sf->GetNumberOfFragments() ); bool corruption = false; for(unsigned int i = 0; i < nframes; ++i) { const Fragment &frag = sf->GetFragment(i); const size_t check = DecodeFragment(frag, buffer + pos, llen); (void)check; if( check != llen ) { gdcmDebugMacro( "RLE pb with frag: " << i ); corruption = true; } pos += (unsigned long)llen; } if( !corruption ) assert( pos == len ); out.SetByteValue( buffer, (uint32_t)len ); delete[] buffer; return !corruption; } return false; } bool RLECodec::DecodeExtent( char *buffer, unsigned int xmin, unsigned int xmax, unsigned int ymin, unsigned int ymax, unsigned int zmin, unsigned int zmax, std::istream & is ) { std::stringstream tmpos; BasicOffsetTable bot; bot.Read( is ); //std::cout << bot << std::endl; const unsigned int * dimensions = this->GetDimensions(); const PixelFormat & pf = this->GetPixelFormat(); assert( pf.GetBitsAllocated() % 8 == 0 ); assert( pf != PixelFormat::SINGLEBIT ); assert( pf != PixelFormat::UINT12 && pf != PixelFormat::INT12 ); // skip std::stringstream os; Fragment frag; for( unsigned int z = 0; z < zmin; ++z ) { frag.ReadPreValue(is); std::streamoff off = frag.GetVL(); is.seekg( off, std::ios::cur ); } for( unsigned int z = zmin; z <= zmax; ++z ) { frag.ReadPreValue(is); std::streampos start = is.tellg(); SetLength( dimensions[0] * dimensions[1] * pf.GetPixelSize() ); const bool r = DecodeByStreams(is, os); (void)r; if( !r ) return false; assert( r ); // handle DICOM padding std::streampos end = is.tellg(); size_t numberOfReadBytes = (size_t)(end - start); if( numberOfReadBytes > frag.GetVL() ) { // Special handling for ALOKA_SSD-8-MONO2-RLE-SQ.dcm size_t diff = numberOfReadBytes - frag.GetVL(); assert( diff == 1 ); os.seekp( 0 - (int)diff, std::ios::cur ); os.put( 0 ); end = (size_t)end - 1; } assert( end - start == frag.GetVL() || (size_t)(end - start) + 1 == frag.GetVL() ); // sync is (rle16loo.dcm) if( (end - start) % 2 == 1 ) { is.get(); } } // for each z os.seekg(0, std::ios::beg ); assert( os.good() ); std::istream *theStream = &os; unsigned int rowsize = xmax - xmin + 1; unsigned int colsize = ymax - ymin + 1; unsigned int bytesPerPixel = pf.GetPixelSize(); std::vector buffer1; buffer1.resize( rowsize*bytesPerPixel ); char *tmpBuffer1 = &buffer1[0]; unsigned int y, z; std::streamoff theOffset; for (z = zmin; z <= zmax; ++z) { for (y = ymin; y <= ymax; ++y) { theStream->seekg(std::ios::beg); theOffset = 0 + ((z-zmin)*dimensions[1]*dimensions[0] + y*dimensions[0] + xmin)*bytesPerPixel; theStream->seekg(theOffset); theStream->read(tmpBuffer1, rowsize*bytesPerPixel); memcpy(&(buffer[((z-zmin)*rowsize*colsize + (y-ymin)*rowsize)*bytesPerPixel]), tmpBuffer1, rowsize*bytesPerPixel); } } return true; } bool RLECodec::DecodeByStreamsCommon(std::istream &, std::ostream &) { return false; } bool RLECodec::DecodeByStreams(std::istream &is, std::ostream &os) { std::streampos start = is.tellg(); // FIXME: Do some stupid work: char dummy_buffer[256]; std::stringstream tmpos; RLEFrame &frame = Internals->Frame; if( !frame.Read(is) ) return false; unsigned long numSegments = frame.Header.NumSegments; unsigned long numberOfReadBytes = 0; unsigned long length = Length; assert( length ); // Special case: assert( GetPixelFormat().GetBitsAllocated() == 32 || GetPixelFormat().GetBitsAllocated() == 16 || GetPixelFormat().GetBitsAllocated() == 8 ); if( GetPixelFormat().GetBitsAllocated() > 8 ) { RequestPaddedCompositePixelCode = true; } assert( GetPixelFormat().GetSamplesPerPixel() == 3 || GetPixelFormat().GetSamplesPerPixel() == 1 ); // A footnote: // RLE *by definition* with more than one component will have applied the // Planar Configuration because it simply does not make sense to do it // otherwise. So implicitly RLE is indeed PlanarConfiguration == 1. However // when the image says: "hey I am PlanarConfiguration = 0 AND RLE", then // apply the PlanarConfiguration internally so that people don't get lost // Because GDCM internally set PlanarConfiguration == 0 by default, even if // the Attribute is not sent, it will still default to 0 and we will be // consistent with ourselves... if( GetPixelFormat().GetSamplesPerPixel() == 3 && GetPlanarConfiguration() == 0 ) { RequestPlanarConfiguration = true; } length /= numSegments; for(unsigned long i = 0; i= 0 /*&& byte <= 127*/ ) /* 2nd is always true */ { is.read( dummy_buffer, byte+1 ); //assert( is.good() ); // impossible because ALOKA_SSD-8-MONO2-RLE-SQ.dc numberOfReadBytes += byte+1; numOutBytes += byte+ 1; tmpos.write( dummy_buffer, byte+1 ); } else if( byte <= -1 && byte >= -127 ) { char nextByte; is.read( &nextByte, 1); numberOfReadBytes += 1; memset(dummy_buffer, nextByte, -byte + 1); numOutBytes += -byte + 1; tmpos.write( dummy_buffer, -byte+1 ); } else /* byte == -128 */ { assert( byte == -128 ); } //assert( numberOfReadBytes + frame.Header.Offset[i] - is.tellg() + start == 0); } if( numOutBytes != length ) return false; } return ImageCodec::DecodeByStreams(tmpos,os); } bool RLECodec::GetHeaderInfo(std::istream &is, TransferSyntax &ts) { RLEFrame frame; if( !frame.Read(is) ) return false; // numsegments = num_comp * bpp / 8; // numsegments >0 && numsegments <= 12 uint32_t bytespercomp = frame.Header.NumSegments; if( frame.Header.NumSegments % 3 == 0 ) { PI = PhotometricInterpretation::RGB; PlanarConfiguration = 1; this->PF.SetSamplesPerPixel( 3 ); bytespercomp /= 3; } else { PI = PhotometricInterpretation::MONOCHROME2; this->PF.SetSamplesPerPixel( 1 ); } this->PF.SetBitsAllocated( bytespercomp * 8 ); ts = TransferSyntax::RLELossless; return true; } ImageCodec * RLECodec::Clone() const { return new RLECodec; } bool RLECodec::StartEncode( std::ostream & ) { return true; } bool RLECodec::IsRowEncoder() { return false; } bool RLECodec::IsFrameEncoder() { return true; } class memsrc : public ::rle::source { public: memsrc( const char * data, size_t datalen ):ptr(data),cur(data),len(datalen) { } int read( char * out, int l ) override { memcpy( out, cur, l ); cur += l; assert( cur <= ptr + len ); return l; } streampos_t tell() override { assert( cur <= ptr + len ); return (streampos_t)(cur - ptr); } bool seek(streampos_t pos) override { cur = ptr + pos; assert( cur <= ptr + len && cur >= ptr ); return true; } bool eof() override { assert( cur <= ptr + len ); return cur == ptr + len; } memsrc * clone() override { memsrc * ret = new memsrc( ptr, len ); return ret; } private: const char * ptr; const char * cur; size_t len; }; bool RLECodec::AppendRowEncode( std::ostream & os, const char * data, size_t datalen) { (void)os; (void)data; (void)datalen; assert(0); return false; } class streamdest : public rle::dest { public: streamdest( std::ostream & os ):stream(os) { start = os.tellp(); } int write( const char * in, int len ) override { stream.write(in, len ); return len; } bool seek( streampos_t abs_pos ) override { stream.seekp( abs_pos + start ); return true; } private: std::ostream & stream; std::streampos start; }; bool RLECodec::AppendFrameEncode( std::ostream & out, const char * data, size_t datalen ) { try { const PixelFormat & pf = this->GetPixelFormat(); unsigned int pc = this->GetPlanarConfiguration(); bool isLittleEndian = !this->GetNeedByteSwap(); rle::pixel_info pi((unsigned char)pf.GetSamplesPerPixel(), (unsigned char)(pf.GetBitsAllocated())); const unsigned int * dimensions = this->GetDimensions(); rle::image_info ii(dimensions[0], dimensions[1], pi, pc ? true : false, isLittleEndian); const int h = dimensions[1]; memsrc src( data, datalen ); rle::rle_encoder re(src, ii); streamdest fd( out ); if( !re.write_header( fd ) ) { gdcmErrorMacro( "could not write header" ); return false; } for( int y = 0; y < h; ++y ) { const int ret = re.encode_row( fd ); if( ret < 0 ) { gdcmErrorMacro( "problem at row: " << y ); return false; } } } catch( std::exception & ) { gdcmErrorMacro( "invalid compression params (not supported for now)." ); return false; } return true; } bool RLECodec::StopEncode( std::ostream & ) { return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmRLECodec.h000066400000000000000000000052051412732066400231000ustar00rootroot00000000000000/*========================================================================= 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 GDCMRLECODEC_H #define GDCMRLECODEC_H #include "gdcmImageCodec.h" namespace gdcm { class Fragment; class RLEInternals; /** * \brief Class to do RLE * \note * ANSI X3.9 * A.4.2 RLE Compression * Annex G defines a RLE Compression Transfer Syntax. This transfer Syntax is * identified by the UID value "1.2.840.10008.1.2.5". If the object allows * multi-frame images in the pixel data field, then each frame shall be encoded * separately. Each frame shall be encoded in one and only one Fragment (see PS * 3.5.8.2). * */ class GDCM_EXPORT RLECodec : public ImageCodec { friend class ImageRegionReader; public: RLECodec(); ~RLECodec() override; bool CanCode(TransferSyntax const &ts) const override; bool CanDecode(TransferSyntax const &ts) const override; bool Decode(DataElement const &is, DataElement &os) override; unsigned long GetBufferLength() const { return BufferLength; } void SetBufferLength(unsigned long l) { BufferLength = l; } bool Code(DataElement const &in, DataElement &out) override; bool GetHeaderInfo(std::istream &is, TransferSyntax &ts) override; ImageCodec * Clone() const override; protected: bool DecodeExtent( char *buffer, unsigned int XMin, unsigned int XMax, unsigned int YMin, unsigned int YMax, unsigned int ZMin, unsigned int ZMax, std::istream & is ); bool DecodeByStreams(std::istream &is, std::ostream &os) override; public: void SetLength(unsigned long l) { Length = l; } protected: bool StartEncode( std::ostream & ) override; bool IsRowEncoder() override; bool IsFrameEncoder() override; bool AppendRowEncode( std::ostream & out, const char * data, size_t datalen ) override; bool AppendFrameEncode( std::ostream & out, const char * data, size_t datalen ) override; bool StopEncode( std::ostream & ) override; private: bool DecodeByStreamsCommon(std::istream &is, std::ostream &os); RLEInternals *Internals; unsigned long Length; unsigned long BufferLength; size_t DecodeFragment(Fragment const & frag, char *buffer, size_t llen); }; } // end namespace gdcm #endif //GDCMRLECODEC_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmRescaler.cxx000066400000000000000000000411751412732066400236410ustar00rootroot00000000000000/*========================================================================= 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 "gdcmRescaler.h" #include #include // std::max #include // abort #include // memcpy #include // std::lround namespace gdcm { // parameter 'size' is in bytes template void RescaleFunction(TOut *out, const TIn *in, double intercept, double slope, size_t size) { size /= sizeof(TIn); for(size_t i = 0; i != size; ++i) { // Implementation detail: // The rescale function does not add the usual +0.5 to do the proper integer type // cast, since TOut is expected to be floating point type whenever it would occur out[i] = (TOut)(slope * in[i] + intercept); //assert( out[i] == (TOut)(slope * in[i] + intercept) ); // will really slow down stuff... //assert( in[i] == (TIn)(((double)out[i] - intercept) / slope + 0.5) ); // For image such as: gdcmData/MR16BitsAllocated_8BitsStored.dcm, the following line will not work: // Indeed the pixel declares itself as 16/8/7 with pixel representation of 1. In this case // anything outside the range [-127,128] is required to be discarded ! //assert( (TIn)out[i] == in[i] ); } } // no such thing as partial specialization of function in c++ // so instead use this trick: template struct FImpl; template void InverseRescaleFunction(TOut *out, const TIn *in, double intercept, double slope, size_t size) { FImpl::InverseRescaleFunction(out,in,intercept,slope,size); } // users, don't touch this! template struct FImpl { // parameter 'size' is in bytes // TODO: add template parameter for intercept/slope so that we can have specialized instantiation // when 1. both are int, 2. slope is 1, 3. intercept is 0 // Detail: casting from float to int is soooo slow static void InverseRescaleFunction( TOut *out, const TIn *in, double intercept, double slope, size_t size) // users, go ahead and specialize this { // If you read the code down below you'll see a specialized function for float, thus // if we reach here it pretty much means slope/intercept were integer type assert( intercept == (int)intercept ); assert( slope == (int)slope ); size /= sizeof(TIn); for(size_t i = 0; i != size; ++i) { // '+ 0.5' trick is NOT needed for image such as: gdcmData/D_CLUNIE_CT1_J2KI.dcm out[i] = (TOut)(((double)in[i] - intercept) / slope ); } } }; // http://stackoverflow.com/questions/485525/round-for-float-in-c // http://en.cppreference.com/w/c/numeric/math/round template < typename T > static inline T round_impl(const double d) { // round() is C99, std::round() is C++11 return (T)std::lround(d); } template struct FImpl { static void InverseRescaleFunction(TOut *out, const float *in, double intercept, double slope, size_t size) { size /= sizeof(float); for(size_t i = 0; i != size; ++i) { // '+ 0.5' trick is needed for instance for : gdcmData/MR-MONO2-12-shoulder.dcm // well known trick of adding 0.5 after a floating point type operation to properly find the // closest integer that will represent the transformation // TOut in this case is integer type, while input is floating point type out[i] = round_impl(((double)in[i] - intercept) / slope); //assert( out[i] == (TOut)(((double)in[i] - intercept) / slope ) ); } } }; template struct FImpl { static void InverseRescaleFunction(TOut *out, const double *in, double intercept, double slope, size_t size) { size /= sizeof(double); for(size_t i = 0; i != size; ++i) { // '+ 0.5' trick is needed for instance for : gdcmData/MR-MONO2-12-shoulder.dcm // well known trick of adding 0.5 after a floating point type operation to properly find the // closest integer that will represent the transformation // TOut in this case is integer type, while input is floating point type out[i] = round_impl(((double)in[i] - intercept) / slope); //assert( out[i] == (TOut)(((double)in[i] - intercept) / slope ) ); } } }; static inline PixelFormat::ScalarType ComputeBestFit(const PixelFormat &pf, double intercept, double slope) { PixelFormat::ScalarType st = PixelFormat::UNKNOWN; assert( slope == (int)slope && intercept == (int)intercept); assert( pf.GetMin() <= pf.GetMax() ); const double pfmin = slope >= 0. ? (double)pf.GetMin() : (double)pf.GetMax(); const double pfmax = slope >= 0. ? (double)pf.GetMax() : (double)pf.GetMin(); const double min = slope * pfmin + intercept; const double max = slope * pfmax + intercept; assert( min <= max ); assert( min == (int64_t)min && max == (int64_t)max ); if( min >= 0 ) // unsigned { if( max <= std::numeric_limits::max() ) { st = PixelFormat::UINT8; } else if( max <= std::numeric_limits::max() ) { st = PixelFormat::UINT16; } else if( max <= std::numeric_limits::max() ) { st = PixelFormat::UINT32; } else if( max <= static_cast(std::numeric_limits::max()) ) { // very large value in Rescale Slope ? return PixelFormat::FLOAT64; } else { gdcmErrorMacro( "Unhandled Pixel Format" ); return st; } } else { if( max <= std::numeric_limits::max() && min >= std::numeric_limits::min() ) { st = PixelFormat::INT8; } else if( max <= std::numeric_limits::max() && min >= std::numeric_limits::min() ) { st = PixelFormat::INT16; } else if( max <= std::numeric_limits::max() && min >= std::numeric_limits::min() ) { st = PixelFormat::INT32; } else if( max <= static_cast(std::numeric_limits::max()) && min >= static_cast(std::numeric_limits::min() ) ) { // very large value in Rescale Slope ? return PixelFormat::FLOAT64; } else { gdcmErrorMacro( "Unhandled Pixel Format" ); return st; } } // postcondition: assert( min >= PixelFormat(st).GetMin() ); assert( max <= PixelFormat(st).GetMax() ); assert( st != PixelFormat::UNKNOWN ); return st; } PixelFormat::ScalarType Rescaler::ComputeInterceptSlopePixelType() { assert( PF != PixelFormat::UNKNOWN ); if( PF.GetSamplesPerPixel() != 1 ) { gdcmErrorMacro( "Sample Per Pixel is required to be 1" ); return PF; } PixelFormat::ScalarType output = PixelFormat::UNKNOWN; if( PF == PixelFormat::SINGLEBIT ) return PixelFormat::SINGLEBIT; if( Slope != (int)Slope || Intercept != (int)Intercept) { //assert( PF != PixelFormat::INT8 && PF != PixelFormat::UINT8 ); // Is there any Object that have Rescale on char ? assert( PF != PixelFormat::SINGLEBIT ); return PixelFormat::FLOAT64; } //if( PF.IsValid() ) { const double intercept = Intercept; const double slope = Slope; output = ComputeBestFit (PF,intercept,slope); } return output; } template void Rescaler::RescaleFunctionIntoBestFit(char *out8, const TIn *in, size_t n) { double intercept = Intercept; double slope = Slope; PixelFormat::ScalarType output = ComputeInterceptSlopePixelType(); void *out = out8; if( UseTargetPixelType ) { output = TargetScalarType; } switch(output) { case PixelFormat::SINGLEBIT: assert(0); break; case PixelFormat::UINT8: RescaleFunction((uint8_t*)out,in,intercept,slope,n); break; case PixelFormat::INT8: RescaleFunction((int8_t*)out,in,intercept,slope,n); break; case PixelFormat::UINT16: RescaleFunction((uint16_t*)out,in,intercept,slope,n); break; case PixelFormat::INT16: RescaleFunction((int16_t*)out,in,intercept,slope,n); break; case PixelFormat::UINT32: RescaleFunction((uint32_t*)out,in,intercept,slope,n); break; case PixelFormat::INT32: RescaleFunction((int32_t*)out,in,intercept,slope,n); break; case PixelFormat::FLOAT32: RescaleFunction((float*)out,in,intercept,slope,n); break; case PixelFormat::FLOAT64: RescaleFunction((double*)out,in,intercept,slope,n); break; default: assert(0); break; } } template void Rescaler::InverseRescaleFunctionIntoBestFit(char *out8, const TIn *in, size_t n) { const double intercept = Intercept; const double slope = Slope; PixelFormat output = ComputePixelTypeFromMinMax(); void *out = out8; switch(output) { case PixelFormat::SINGLEBIT: assert(0); break; case PixelFormat::UINT8: InverseRescaleFunction((uint8_t*)out,in,intercept,slope,n); break; case PixelFormat::INT8: InverseRescaleFunction((int8_t*)out,in,intercept,slope,n); break; case PixelFormat::UINT16: InverseRescaleFunction((uint16_t*)out,in,intercept,slope,n); break; case PixelFormat::INT16: InverseRescaleFunction((int16_t*)out,in,intercept,slope,n); break; case PixelFormat::UINT32: InverseRescaleFunction((uint32_t*)out,in,intercept,slope,n); break; case PixelFormat::INT32: InverseRescaleFunction((int32_t*)out,in,intercept,slope,n); break; default: assert(0); break; } } bool Rescaler::InverseRescale(char *out, const char *in8, size_t n) { bool fastpath = true; const void* in = in8; switch(PF) { case PixelFormat::FLOAT32: case PixelFormat::FLOAT64: fastpath = false; break; default: ; } // fast path: if( fastpath && (Slope == 1 && Intercept == 0) ) { memcpy(out,in,n); return true; } // check if we are dealing with floating point type if( Slope != (int)Slope || Intercept != (int)Intercept) { // need to rescale as double (64bits) as slope/intercept are 64bits //assert(0); } // else integral type switch(PF) { case PixelFormat::UINT8: InverseRescaleFunctionIntoBestFit(out,(const uint8_t*)in,n); break; case PixelFormat::INT8: InverseRescaleFunctionIntoBestFit(out,(const int8_t*)in,n); break; case PixelFormat::UINT16: InverseRescaleFunctionIntoBestFit(out,(const uint16_t*)in,n); break; case PixelFormat::INT16: InverseRescaleFunctionIntoBestFit(out,(const int16_t*)in,n); break; case PixelFormat::UINT32: InverseRescaleFunctionIntoBestFit(out,(const uint32_t*)in,n); break; case PixelFormat::INT32: InverseRescaleFunctionIntoBestFit(out,(const int32_t*)in,n); break; case PixelFormat::FLOAT32: assert( sizeof(float) == 32 / 8 ); InverseRescaleFunctionIntoBestFit(out,(const float*)in,n); break; case PixelFormat::FLOAT64: assert( sizeof(double) == 64 / 8 ); InverseRescaleFunctionIntoBestFit(out,(const double*)in,n); break; default: assert(0); break; } return true; } bool Rescaler::Rescale(char *out, const char *in8, size_t n) { const void *in = in8; if( UseTargetPixelType == false ) { // fast path: if( Slope == 1 && Intercept == 0 ) { memcpy(out,in,n); return true; } // check if we are dealing with floating point type if( Slope != (int)Slope || Intercept != (int)Intercept) { // need to rescale as float (32bits) as slope/intercept are 32bits } } // else integral type switch(PF) { case PixelFormat::SINGLEBIT: memcpy(out,in,n); break; case PixelFormat::UINT8: RescaleFunctionIntoBestFit(out,(const uint8_t*)in,n); break; case PixelFormat::INT8: RescaleFunctionIntoBestFit(out,(const int8_t*)in,n); break; case PixelFormat::UINT12: case PixelFormat::UINT16: RescaleFunctionIntoBestFit(out,(const uint16_t*)in,n); break; case PixelFormat::INT12: case PixelFormat::INT16: RescaleFunctionIntoBestFit(out,(const int16_t*)in,n); break; case PixelFormat::UINT32: RescaleFunctionIntoBestFit(out,(const uint32_t*)in,n); break; case PixelFormat::INT32: RescaleFunctionIntoBestFit(out,(const int32_t*)in,n); break; default: gdcmErrorMacro( "Unhandled: " << PF ); assert(0); break; } return true; } static PixelFormat ComputeInverseBestFitFromMinMax(/*const PixelFormat &pf,*/ double intercept, double slope, double _min, double _max) { PixelFormat st = PixelFormat::UNKNOWN; //assert( slope == (int)slope && intercept == (int)intercept); assert( _min <= _max ); double dmin = (_min - intercept ) / slope; double dmax = (_max - intercept ) / slope; if( slope < 0 ) { dmin = (_max - intercept ) / slope; dmax = (_min - intercept ) / slope; } assert( dmin <= dmax ); assert( dmax <= static_cast(std::numeric_limits::max() ) ); assert( dmin >= static_cast(std::numeric_limits::min() ) ); /* * Tricky: what happen in the case where floating point approximate dmax as: 65535.000244081035 * Take for instance: _max = 64527, intercept = -1024, slope = 1.000244140625 * => dmax = 65535.000244081035 * thus we must always make sure to cast to an integer first. */ int64_t min = (int64_t)dmin; int64_t max = (int64_t)dmax; int log2max = 0; if( min >= 0 ) // unsigned { if( max <= std::numeric_limits::max() ) { st = PixelFormat::UINT8; } else if( max <= std::numeric_limits::max() ) { st = PixelFormat::UINT16; } else if( max <= std::numeric_limits::max() ) { st = PixelFormat::UINT32; } else { gdcmAssertAlwaysMacro(0); } int64_t max2 = max; // make a copy while (max2 >>= 1) ++log2max; // need + 1 in case max == 4095 => 12bits stored required st.SetBitsStored( (unsigned short)(log2max + 1) ); } else { if( max <= std::numeric_limits::max() && min >= std::numeric_limits::min() ) { st = PixelFormat::INT8; } else if( max <= std::numeric_limits::max() && min >= std::numeric_limits::min() ) { st = PixelFormat::INT16; } else if( max <= std::numeric_limits::max() && min >= std::numeric_limits::min() ) { st = PixelFormat::INT32; } else { gdcmAssertAlwaysMacro(0); } assert( min < 0 ); #if 0 int log2min = 0; int64_t min2 = -min; // make a copy int64_t max2 = max; // make a copy while (min2 >>= 1) ++log2min; while (max2 >>= 1) ++log2max; const int64_t bs = std::max( log2min, log2max ) + 1 + 1 /* 2 complement */; #else int64_t max2 = max - min; // make a copy while (max2 >>= 1) ++log2max; const int64_t bs = log2max + 1; #endif assert( bs <= st.GetBitsAllocated() ); st.SetBitsStored( (unsigned short)bs ); } // postcondition: assert( min >= PixelFormat(st).GetMin() ); assert( max <= PixelFormat(st).GetMax() ); assert( st != PixelFormat::UNKNOWN ); assert( st != PixelFormat::FLOAT32 && st != PixelFormat::FLOAT16 && st != PixelFormat::FLOAT64 ); return st; } void Rescaler::SetMinMaxForPixelType(double min, double max) { if( min < max ) { ScalarRangeMin = min; ScalarRangeMax = max; } else { gdcmWarningMacro( "Min > Max. Correcting" ); ScalarRangeMin = max; ScalarRangeMax = min; } } PixelFormat Rescaler::ComputePixelTypeFromMinMax() { assert( PF != PixelFormat::UNKNOWN ); const double intercept = Intercept; const double slope = Slope; const PixelFormat output = ComputeInverseBestFitFromMinMax (/*PF,*/intercept,slope,ScalarRangeMin,ScalarRangeMax); assert( output != PixelFormat::UNKNOWN && output >= PixelFormat::UINT8 && output <= PixelFormat::INT32 ); return output; } void Rescaler::SetTargetPixelType( PixelFormat const & targetpf ) { TargetScalarType = targetpf.GetScalarType(); } void Rescaler::SetUseTargetPixelType(bool b) { UseTargetPixelType = b; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmRescaler.h000066400000000000000000000111131412732066400232530ustar00rootroot00000000000000/*========================================================================= 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 GDCMRESCALER_H #define GDCMRESCALER_H #include "gdcmTypes.h" #include "gdcmPixelFormat.h" namespace gdcm { /** * \brief Rescale class * \details This class is meant to apply the linear transform of Stored Pixel Value to * Real World Value. * This is mostly found in CT or PET dataset, where the value are stored using * one type, but need to be converted to another scale using a linear * transform. * There are basically two cases: * In CT: the linear transform is generally integer based. E.g. the Stored * Pixel Type is unsigned short 12bits, but to get Hounsfield unit, one need to * apply the linear transform: * \f[ * RWV = 1. * SV - 1024 * \f] * So the best scalar to store the Real World Value will be 16 bits signed * type. * * In PET: the linear transform is generally floating point based. * Since the dynamic range can be quite high, the Rescale Slope / Rescale * Intercept can be changing throughout the Series. So it is important to read * all linear transform and deduce the best Pixel Type only at the end (when * all the images to be read have been parsed). * * \warning Internally any time a floating point value is found either in the * Rescale Slope or the Rescale Intercept it is assumed that the best matching * output pixel type is FLOAT64 (in previous implementation it was FLOAT32). * Because VR:DS is closer to a 64bits floating point type FLOAT64 is thus a * best matching pixel type for the floating point transformation. * * Example: Let say input is FLOAT64, and we want UINT16 as output, we would do: * *\code Rescaler ir; ir.SetIntercept( 0 ); ir.SetSlope( 5.6789 ); ir.SetPixelFormat( FLOAT64 ); ir.SetMinMaxForPixelType( ((PixelFormat)UINT16).GetMin(), ((PixelFormat)UINT16).GetMax() ); ir.InverseRescale(output,input,numberofbytes ); \endcode * * \note handle floating point transformation back and forth to integer * properly (no loss) * * \see Unpacker12Bits */ class GDCM_EXPORT Rescaler { public: Rescaler():Intercept(0),Slope(1),PF(PixelFormat::UNKNOWN),TargetScalarType(PixelFormat::UNKNOWN), ScalarRangeMin(0), ScalarRangeMax(0), UseTargetPixelType(false) {} ~Rescaler() = default; /// Direct transform bool Rescale(char *out, const char *in, size_t n); /// Inverse transform bool InverseRescale(char *out, const char *in, size_t n); /// Set Intercept: used for both direct&inverse transformation void SetIntercept(double i) { Intercept = i; } double GetIntercept() const { return Intercept; } /// Set Slope: user for both direct&inverse transformation void SetSlope(double s) { Slope = s; } double GetSlope() const { return Slope; } /// 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 void SetTargetPixelType( PixelFormat const & targetst ); /// Override default behavior of Rescale void SetUseTargetPixelType(bool b); /// Set Pixel Format of input data void SetPixelFormat(PixelFormat const & pf) { PF = pf; } /// Compute the Pixel Format of the output data /// Used for direct transformation PixelFormat::ScalarType ComputeInterceptSlopePixelType(); /// Set target interval for output data. A best match will be computed (if possible) /// Used for inverse transformation void SetMinMaxForPixelType(double min, double max); /// Compute the Pixel Format of the output data /// Used for inverse transformation PixelFormat ComputePixelTypeFromMinMax(); protected: template void RescaleFunctionIntoBestFit(char *out, const TIn *in, size_t n); template void InverseRescaleFunctionIntoBestFit(char *out, const TIn *in, size_t n); private: double Intercept; // 0028,1052 double Slope; // 0028,1053 PixelFormat PF; PixelFormat::ScalarType TargetScalarType; double ScalarRangeMin; double ScalarRangeMax; bool UseTargetPixelType; }; } // end namespace gdcm #endif //GDCMRESCALER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmScanner.cxx000066400000000000000000000316451412732066400234730ustar00rootroot00000000000000/*========================================================================= 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 "gdcmScanner.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 { Scanner::~Scanner() = default; void Scanner::ClearTags() { Tags.clear(); } void Scanner::ClearSkipTags() { SkipTags.clear(); } void Scanner::AddSkipTag( Tag const & t ) { SkipTags.insert( t ); assert(0); // This is NOT implemented for now } // Warning: API is passing a public tag (no way to specify private tag) void Scanner::AddPrivateTag( PrivateTag const & t ) { static const Global &g = GlobalInstance; static const Dicts &dicts = g.GetDicts(); const DictEntry &entry = dicts.GetDictEntry( t ); //std::cout << "Debug: " << entry << std::endl; // 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 ); } } void Scanner::AddTag( Tag const & t ) { 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 ) { Tags.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" ); Tags.insert( t ); } } bool Scanner::Scan( Directory::FilenamesType const & filenames ) { this->InvokeEvent( StartEvent() ); // Is there at least one tag ? if( !Tags.empty() || !PrivateTags.empty() ) { //if( filenames.empty() ) return true; // Prepare hash table: Mappings.clear(); Mappings[""]; // 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; if( !Tags.empty() ) { TagsType::const_reverse_iterator it1 = Tags.rbegin(); const Tag & publiclast = *it1; last = publiclast; } if( !PrivateTags.empty() ) { PrivateTagsType::const_reverse_iterator pit1 = PrivateTags.rbegin(); Tag privatelast = *pit1; 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() ); Scanner::ProcessPublicTag(sf, filename); //Scanner::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 Scanner::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"; //const FilenameToValue &mapping = Mappings[*tag]; if( Mappings.find(filename) != Mappings.end() ) { const TagToValue &mapping = GetMapping(filename); TagToValue::const_iterator it = mapping.begin(); for( ; it != mapping.end(); ++it) { const Tag & 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; //if( tag == Tag(0x0020,0x000d) // Study Instance UID : UI // || tag == Tag(0x0020,0x0052) // // || tag == Tag(0x0020,0x000e) ) // Series Instance UID : UI // { // return true; // } return false; } void Scanner::PrintTable( std::ostream & os ) const { Directory::FilenamesType::const_iterator file = Filenames.begin(); for(; file != Filenames.end(); ++file) { const char *filename = file->c_str(); assert( filename && *filename ); os << '"' << filename << '"' << "\t"; TagsType::const_iterator tag = Tags.begin(); const TagToValue &mapping = GetMapping(filename); for( ; tag != Tags.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"; } os << "\n"; } } Scanner::TagToValue const & Scanner::GetMapping(const char *filename) const { // assert( Mappings.find(filename) != Mappings.end() ); assert( filename && *filename ); if( Mappings.find(filename) != Mappings.end() ) return Mappings.find(filename)->second; return Mappings.find("")->second; // dummy file could not be found } bool Scanner::IsKey( const char * filename ) const { /* // std::find on contiguous array will operate in 0(n) which is way too slow, assume user is not too dumb... Directory::FilenamesType::const_iterator it = std::find(Filenames.begin(), Filenames.end(), filename); if( it == Filenames.end() ) { gdcmErrorMacro( "The file: " << filename << " was not scanned" ); return false; } */ // Look for the file in Mappings table: assert( filename && *filename ); MappingType::const_iterator it2 = Mappings.find(filename); return it2 != Mappings.end(); } Directory::FilenamesType Scanner::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* Scanner::GetValue(const char *filename, Tag const &t) const { // \precondition assert( Tags.find( t ) != Tags.end() ); TagToValue const &ftv = GetMapping(filename); if( ftv.find(t) != ftv.end() ) { return ftv.find(t)->second; } return nullptr; } const char *Scanner::GetFilenameFromTagToValue(Tag const &t, const char *valueref) const { const char *filenameref = nullptr; if( valueref ) { Directory::FilenamesType::const_iterator file = Filenames.begin(); size_t len = strlen( valueref ); if( len && valueref[ len - 1 ] == ' ' ) { --len; } for(; file != Filenames.end() && !filenameref; ++file) { const char *filename = file->c_str(); const char * value = GetValue(filename, t); if( value && strncmp(value, valueref, len ) == 0 ) { 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 Scanner::GetAllFilenamesFromTagToValue(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 = GetValue(filename, t); const std::string value_str = String<>::Trim( value ); if( value_str == valueref_str ) { theReturn.push_back( filename ); } } } return theReturn; } Scanner::TagToValue const & Scanner::GetMappingFromTagToValue(Tag const &t, const char *valueref) const { return GetMapping( GetFilenameFromTagToValue(t, valueref) ); } Scanner::ValuesType Scanner::GetValues(Tag const &t) const { ValuesType vt; Directory::FilenamesType::const_iterator file = Filenames.begin(); for(; file != Filenames.end(); ++file) { const char *filename = file->c_str(); TagToValue const &ttv = GetMapping(filename); if( ttv.find(t) != ttv.end() ) { vt.insert( ttv.find(t)->second ); } } return vt; } Directory::FilenamesType Scanner::GetOrderedValues(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(); TagToValue const &ttv = GetMapping(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; } void Scanner::ProcessPublicTag(StringFilter &sf, const char *filename) { assert( filename ); TagToValue &mapping = Mappings[filename]; const File& file = sf.GetFile(); const FileMetaInformation & header = file.GetHeader(); const DataSet & ds = file.GetDataSet(); TagsType::const_iterator tag = Tags.begin(); for( ; tag != Tags.end(); ++tag ) { if( tag->GetGroup() == 0x2 ) { if( header.FindDataElement( *tag ) ) { //std::string s; DataElement const & de = header.GetDataElement( *tag ); //const ByteValue *bv = de.GetByteValue(); ////assert( VR::IsASCII( vr ) ); //if( bv ) // Hum, should I store an empty string or what ? // { // s = std::string( bv->GetPointer(), bv->GetLength() ); // s.resize( std::min( s.size(), strlen( s.c_str() ) ) ); // } 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( TagToValue::value_type(*tag, value)); } } else { if( ds.FindDataElement( *tag ) ) { //std::string s; DataElement const & de = ds.GetDataElement( *tag ); //const ByteValue *bv = de.GetByteValue(); ////assert( VR::IsASCII( vr ) ); //if( bv ) // Hum, should I store an empty string or what ? // { // s = std::string( bv->GetPointer(), bv->GetLength() ); // s.resize( std::min( s.size(), strlen( s.c_str() ) ) ); // } 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( TagToValue::value_type(*tag, value)); } } } // end for } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmScanner.h000066400000000000000000000166071412732066400231210ustar00rootroot00000000000000/*========================================================================= 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 GDCMSCANNER_H #define GDCMSCANNER_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 Scanner * \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 Scanner : public Subject { friend std::ostream& operator<<(std::ostream &_os, const Scanner &s); public: Scanner():Values(),Filenames(),Mappings() {} ~Scanner() 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 (hold 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 TagToValue; //typedef std::map TagToValue; //StringMap; //typedef TagToStringMap TagToValue; typedef TagToValue::value_type TagToValueValueType; /// Add a tag that will need to be read. Those are root level tags void AddTag( Tag const & t ); void ClearTags(); // Work in progress do not use: void AddPrivateTag( PrivateTag const & t ); /// Add a tag that will need to be skipped. Those are root level skip tags void AddSkipTag( Tag const & t ); void ClearSkipTags(); /// Start the scan ! bool Scan( Directory::FilenamesType const & filenames ); Directory::FilenamesType const &GetFilenames() const { return Filenames; } /// Print result void Print( std::ostream & os ) const override; void PrintTable( std::ostream & os ) 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 GetValues(Tag const &t) 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 GetOrderedValues(Tag const &t) 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 MappingType; typedef MappingType::const_iterator ConstIterator; ConstIterator Begin() const { return Mappings.begin(); } ConstIterator End() const { return Mappings.end(); } /// Mappings are the mapping from a particular tag to the map, mapping filename to value: MappingType const & GetMappings() const { return Mappings; } /// Get the std::map mapping filenames to value for file 'filename' TagToValue const & GetMapping(const char *filename) const; /// Will loop over all files and return the first file where value match the reference value /// 'valueref' const char *GetFilenameFromTagToValue(Tag const &t, 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 GetAllFilenamesFromTagToValue(Tag const &t, const char *valueref) const; /// See GetFilenameFromTagToValue(). This is simply GetFilenameFromTagToValue followed // by a call to GetMapping() TagToValue const & GetMappingFromTagToValue(Tag const &t, 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* GetValue(const char *filename, Tag const &t) const; /// for wrapped language: instantiate a reference counted object static SmartPointer New() { return new Scanner; } protected: void ProcessPublicTag(StringFilter &sf, const char *filename); private: // struct to store all uniq tags in ascending order: typedef std::set< Tag > TagsType; typedef std::set< PrivateTag > PrivateTagsType; std::set< Tag > Tags; std::set< PrivateTag > PrivateTags; std::set< Tag > SkipTags; ValuesType Values; Directory::FilenamesType Filenames; // Main struct that will hold all mapping: MappingType Mappings; double Progress; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const Scanner &s) { s.Print( os ); return os; } #if defined(SWIGPYTHON) || defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPHP) /* * HACK: I need this temp class to be able to manipulate a std::map from python, * swig does not support wrapping of simple class like std::map... */ class SWIGTagToValue { public: SWIGTagToValue(Scanner::TagToValue const &t2v):Internal(t2v),it(t2v.begin()) {} const Scanner::TagToValueValueType& GetCurrent() const { return *it; } const Tag& GetCurrentTag() const { return it->first; } const char *GetCurrentValue() const { return it->second; } void Start() { it = Internal.begin(); } bool IsAtEnd() const { return it == Internal.end(); } void Next() { ++it; } private: const Scanner::TagToValue& Internal; Scanner::TagToValue::const_iterator it; }; #endif /* SWIG */ /** * \example ScanDirectory.cs * This is a C# example on how to use Scanner */ } // end namespace gdcm #endif //GDCMSCANNER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSegment.cxx000066400000000000000000000130401412732066400234710ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSegment.h" #include "gdcmCodeString.h" #include namespace gdcm { static const char * ALGOTypeStrings[] = { "AUTOMATIC", "SEMIAUTOMATIC", "MANUAL", nullptr }; const char * Segment::GetALGOTypeString(ALGOType type) { assert( type <= ALGOType_END ); return ALGOTypeStrings[(int)type]; } Segment::ALGOType Segment::GetALGOType(const char * type) { if(!type) return ALGOType_END; // Delete possible space as last character String<> str( type ); str.Trim(); std::string strClearStr = str.Trim(); const char * strClear = strClearStr.c_str(); for(unsigned int i = 0; ALGOTypeStrings[i] != nullptr; ++i) { if( strcmp(strClear, ALGOTypeStrings[i]) == 0 ) { return (ALGOType)i; } } // Ouch ! We did not find anything, that's pretty bad, let's hope that // the toolkit which wrote the image is buggy and tolerate space padded binary // string CodeString codestring = strClear; std::string cs = codestring.GetAsString(); for(unsigned int i = 0; ALGOTypeStrings[i] != nullptr; ++i) { if( strcmp(cs.c_str(), ALGOTypeStrings[i]) == 0 ) { return (ALGOType)i; } } return ALGOType_END; } Segment::Segment(): SegmentNumber(0), SegmentLabel(""), SegmentDescription(""), AnatomicRegion(), AnatomicRegionModifiers(), PropertyCategory(), PropertyType(), PropertyTypeModifiers(), SegmentAlgorithmType(ALGOType_END), SegmentAlgorithmName(""), SurfaceCount(0), Surfaces() { } Segment::~Segment() = default; unsigned short Segment::GetSegmentNumber() const { return SegmentNumber; } void Segment::SetSegmentNumber(const unsigned short num) { SegmentNumber = num; } const char * Segment::GetSegmentLabel() const { return SegmentLabel.c_str(); } void Segment::SetSegmentLabel(const char * label) { SegmentLabel = label; } const char * Segment::GetSegmentDescription() const { return SegmentDescription.c_str(); } void Segment::SetSegmentDescription(const char * description) { SegmentDescription = description; } SegmentHelper::BasicCodedEntry const & Segment::GetAnatomicRegion() const { return AnatomicRegion; } SegmentHelper::BasicCodedEntry & Segment::GetAnatomicRegion() { return AnatomicRegion; } void Segment::SetAnatomicRegion(SegmentHelper::BasicCodedEntry const & BSE) { AnatomicRegion.CV = BSE.CV; AnatomicRegion.CSD = BSE.CSD; AnatomicRegion.CM = BSE.CM; } Segment::BasicCodedEntryVector const & Segment::GetAnatomicRegionModifiers() const { return AnatomicRegionModifiers; } Segment::BasicCodedEntryVector & Segment::GetAnatomicRegionModifiers() { return AnatomicRegionModifiers; } void Segment::SetAnatomicRegionModifiers(BasicCodedEntryVector const & BSEV) { AnatomicRegionModifiers = BSEV; } SegmentHelper::BasicCodedEntry const & Segment::GetPropertyCategory() const { return PropertyCategory; } SegmentHelper::BasicCodedEntry & Segment::GetPropertyCategory() { return PropertyCategory; } void Segment::SetPropertyCategory(SegmentHelper::BasicCodedEntry const & BSE) { PropertyCategory.CV = BSE.CV; PropertyCategory.CSD = BSE.CSD; PropertyCategory.CM = BSE.CM; } SegmentHelper::BasicCodedEntry const & Segment::GetPropertyType() const { return PropertyType; } SegmentHelper::BasicCodedEntry & Segment::GetPropertyType() { return PropertyType; } void Segment::SetPropertyType(SegmentHelper::BasicCodedEntry const & BSE) { PropertyType.CV = BSE.CV; PropertyType.CSD = BSE.CSD; PropertyType.CM = BSE.CM; } Segment::BasicCodedEntryVector const & Segment::GetPropertyTypeModifiers() const { return PropertyTypeModifiers; } Segment::BasicCodedEntryVector & Segment::GetPropertyTypeModifiers() { return PropertyTypeModifiers; } void Segment::SetPropertyTypeModifiers(BasicCodedEntryVector const & BSEV) { PropertyTypeModifiers = BSEV; } Segment::ALGOType Segment::GetSegmentAlgorithmType() const { return SegmentAlgorithmType; } void Segment::SetSegmentAlgorithmType(Segment::ALGOType type) { assert(type <= ALGOType_END); SegmentAlgorithmType = type; } void Segment::SetSegmentAlgorithmType(const char * typeStr) { SetSegmentAlgorithmType( GetALGOType(typeStr) ); } const char * Segment::GetSegmentAlgorithmName() const { return SegmentAlgorithmName.c_str(); } void Segment::SetSegmentAlgorithmName(const char * name) { SegmentAlgorithmName = name; } void Segment::ComputeSurfaceCount() { SurfaceCount = (unsigned long)Surfaces.size(); } unsigned long Segment::GetSurfaceCount() { if (SurfaceCount == 0) { ComputeSurfaceCount(); } return SurfaceCount; } void Segment::SetSurfaceCount(const unsigned long nb) { SurfaceCount = nb; } Segment::SurfaceVector const & Segment::GetSurfaces() const { return Surfaces; } Segment::SurfaceVector & Segment::GetSurfaces() { return Surfaces; } SmartPointer< Surface > Segment::GetSurface(const unsigned int idx /*= 0*/) const { assert( idx < SurfaceCount ); return Surfaces[idx]; } void Segment::AddSurface(SmartPointer< Surface > surface) { Surfaces.push_back(surface); } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSegment.h000066400000000000000000000102731412732066400231230ustar00rootroot00000000000000/*========================================================================= 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 GDCMSEGMENT_H #define GDCMSEGMENT_H #include #include #include #include "gdcmSegmentHelper.h" namespace gdcm { /** * \brief This class defines a segment. * \details It mainly contains attributes of group 0x0062. * In addition, it can be associated with surface. * * \see PS 3.3 C.8.20.2 and C.8.23 */ class GDCM_EXPORT Segment : public Object { public: typedef std::vector< SmartPointer< Surface > > SurfaceVector; typedef std::vector< SegmentHelper::BasicCodedEntry > BasicCodedEntryVector; typedef enum { AUTOMATIC = 0, SEMIAUTOMATIC, MANUAL, ALGOType_END } ALGOType; static const char * GetALGOTypeString(ALGOType type); static ALGOType GetALGOType(const char * type); Segment(); ~Segment() override; //** Segment getters/setters **// unsigned short GetSegmentNumber() const; void SetSegmentNumber(const unsigned short num); const char * GetSegmentLabel() const; void SetSegmentLabel(const char * label); const char * GetSegmentDescription() const; void SetSegmentDescription(const char * description); SegmentHelper::BasicCodedEntry const & GetAnatomicRegion() const; SegmentHelper::BasicCodedEntry & GetAnatomicRegion(); void SetAnatomicRegion(SegmentHelper::BasicCodedEntry const & BSE); BasicCodedEntryVector const & GetAnatomicRegionModifiers() const; BasicCodedEntryVector & GetAnatomicRegionModifiers(); void SetAnatomicRegionModifiers(BasicCodedEntryVector const & BSEV); SegmentHelper::BasicCodedEntry const & GetPropertyCategory() const; SegmentHelper::BasicCodedEntry & GetPropertyCategory(); void SetPropertyCategory(SegmentHelper::BasicCodedEntry const & BSE); SegmentHelper::BasicCodedEntry const & GetPropertyType() const; SegmentHelper::BasicCodedEntry & GetPropertyType(); void SetPropertyType(SegmentHelper::BasicCodedEntry const & BSE); BasicCodedEntryVector const & GetPropertyTypeModifiers() const; BasicCodedEntryVector & GetPropertyTypeModifiers(); void SetPropertyTypeModifiers(BasicCodedEntryVector const & BSEV); ALGOType GetSegmentAlgorithmType() const; void SetSegmentAlgorithmType(ALGOType type); void SetSegmentAlgorithmType(const char * typeStr); const char * GetSegmentAlgorithmName() const; void SetSegmentAlgorithmName(const char * name); //** Surface getters/setters **// unsigned long GetSurfaceCount(); void SetSurfaceCount(const unsigned long nb); SurfaceVector const & GetSurfaces() const; SurfaceVector & GetSurfaces(); SmartPointer< Surface > GetSurface(const unsigned int idx = 0) const; void AddSurface(SmartPointer< Surface > surface); protected : //** Segment members **// //0062 0004 US 1 Segment Number unsigned short SegmentNumber; //0062 0005 LO 1 Segment Label std::string SegmentLabel; //0062 0006 ST 1 Segment Description std::string SegmentDescription; // General Anatomic Region SegmentHelper::BasicCodedEntry AnatomicRegion; // General Anatomic Region Modifier BasicCodedEntryVector AnatomicRegionModifiers; // Property Category Code SegmentHelper::BasicCodedEntry PropertyCategory; // Property Type Code SegmentHelper::BasicCodedEntry PropertyType; // Property Type Modifier Code BasicCodedEntryVector PropertyTypeModifiers; //0062 0008 CS 1 Segment Algorithm Type ALGOType SegmentAlgorithmType; //0062 0009 LO 1 Segment Algorithm Name std::string SegmentAlgorithmName; //** Surface members **// //0066 002a UL 1 Surface Count unsigned long SurfaceCount; SurfaceVector Surfaces; private : void ComputeSurfaceCount(); }; } #endif // GDCMSEGMENT_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSegmentHelper.cxx000066400000000000000000000020111412732066400246250ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSegmentHelper.h" namespace gdcm { namespace SegmentHelper { bool BasicCodedEntry::IsEmpty(const bool checkOptionalAttributes/* = false*/) const { bool res = true; if (!CV.empty() && !CSD.empty() && !CM.empty()) { if (checkOptionalAttributes) { if (!CSV.empty()) { res = false; } } else { res = false; } } return res; } } // end of SegmentHelper namespace } // end of gdcm namespace GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSegmentHelper.h000066400000000000000000000042631412732066400242650ustar00rootroot00000000000000/*========================================================================= 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 GDCMSEGMENTHELPER_H #define GDCMSEGMENTHELPER_H #include "gdcmTypes.h" #include namespace gdcm { namespace SegmentHelper { /** * \brief This structure defines a basic coded entry with all of its attributes. * * \see PS 3.3 section 8.8. */ struct GDCM_EXPORT BasicCodedEntry { /** * \brief Constructor. */ BasicCodedEntry(): CV(""), CSD(""), CSV(""), CM("") {} /** * \brief constructor which defines type 1 attributes. */ BasicCodedEntry(const char * a_CV, const char * a_CSD, const char * a_CM): CV(a_CV), CSD(a_CSD), CSV(""), CM(a_CM) {} /** * \brief constructor which defines attributes. */ BasicCodedEntry(const char * a_CV, const char * a_CSD, const char * a_CSV, const char * a_CM): CV(a_CV), CSD(a_CSD), CSV(a_CSV), CM(a_CM) {} /** * \brief Check if each attributes of the basic coded entry is defined. * * \param checkOptionalAttributes Check also type 1C attributes. */ bool IsEmpty(const bool checkOptionalAttributes = false) const; //** Members **// // 0008 0100 1 Code Value std::string CV; /// Code Value attribute // 0008 0102 1 Coding Scheme Designator std::string CSD; /// Coding Scheme Designator attribute // 0008 0103 1C Coding Scheme Version std::string CSV; /// Coding Scheme Version attribute // 0008 0104 1 Code Meaning std::string CM; /// Code Meaning attribute }; } // end of SegmentHelper namespace } // end of gdcm namespace #endif // GDCMSEGMENTHELPER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSegmentReader.cxx000066400000000000000000000261051412732066400246220ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSegmentReader.h" #include "gdcmMediaStorage.h" #include "gdcmAttribute.h" #include "gdcmString.h" namespace gdcm { SegmentReader::SegmentReader() = default; SegmentReader::~SegmentReader() = default; const SegmentReader::SegmentVector SegmentReader::GetSegments() const { return const_cast(this)->GetSegments(); } SegmentReader::SegmentVector SegmentReader::GetSegments() { SegmentVector res; // Make a segment vector from map with no duplicate. SegmentMap::const_iterator itMap = Segments.begin(); SegmentMap::const_iterator itMapEnd = Segments.end(); if (itMap != itMapEnd) { // Add first segment res.push_back(itMap->second); itMap++; // Search and add only different segments SegmentVector::const_iterator itVec; SegmentVector::const_iterator itVecEnd; for (; itMap != itMapEnd; itMap++) { itVec = res.begin(); itVecEnd = res.end(); // if res is a list, remove this line while (itVec != itVecEnd && itMap->second != *itVec) itVec++; if (itVec == itVecEnd) res.push_back(itMap->second); } } return res; } //unsigned int SegmentReader::GetNumberOfSegments() //{ // return GetSegments().size(); //} bool SegmentReader::Read() { bool res = false; // Read a file if( !Reader::Read() ) { return res; } // Read Segments from file const FileMetaInformation & header = F->GetHeader(); MediaStorage ms = header.GetMediaStorage(); if( ms == MediaStorage::SegmentationStorage || ms == MediaStorage::SurfaceSegmentationStorage ) { res = ReadSegments(); } else { const char * modality = ms.GetModality(); const DataSet & dsRoot = F->GetDataSet(); if (modality != nullptr) { // Check modality String<> modalityStr( modality ); if ( modalityStr.Trim() == "SEG" ) { res = ReadSegments(); } else if (dsRoot.FindDataElement( Tag(0x0062, 0x0002) )) { // Try to find Segment Sequence res = ReadSegments(); } } else if (dsRoot.FindDataElement( Tag(0x0062, 0x0002) )) { // Try to find Segment Sequence res = ReadSegments(); } } return res; } bool SegmentReader::ReadSegments() { bool res = false; const DataSet & ds = F->GetDataSet(); // Segment Sequence const Tag segmentSQTag(0x0062, 0x0002); if (ds.FindDataElement(segmentSQTag)) { SmartPointer< SequenceOfItems > segmentSQ = ds.GetDataElement(segmentSQTag).GetValueAsSQ(); const size_t numberOfSegments = segmentSQ->GetNumberOfItems(); if ( numberOfSegments == 0) { gdcmErrorMacro( "No segment found" ); return false; } for (unsigned int i = 1; i <= numberOfSegments; ++i) { if ( !ReadSegment( segmentSQ->GetItem(i), i ) ) { gdcmWarningMacro( "Segment "< sequence = dataset.GetDataElement(tag).GetValueAsSQ(); SequenceOfItems::Iterator it = sequence->Begin(); for(; it != sequence->End(); ++it) { const Item & item = *it; const DataSet & itemDataSet = item.GetNestedDataSet(); SegmentHelper::BasicCodedEntry entry; // Code Value (Type 1C) Attribute<0x0008, 0x0100> codeValueAttribute; codeValueAttribute.SetFromDataSet(itemDataSet); entry.CV = codeValueAttribute.GetValue(); // Coding Scheme Designator (Type 1C) Attribute<0x0008, 0x0102> codingSchemeDesignatorAttribute; codingSchemeDesignatorAttribute.SetFromDataSet(itemDataSet); entry.CSD = codingSchemeDesignatorAttribute.GetValue(); // Coding Scheme Version (Type 1C) Attribute<0x0008, 0x0103> codingSchemeVersionAttribute; codingSchemeVersionAttribute.SetFromDataSet(itemDataSet); entry.CSV = codingSchemeVersionAttribute.GetValue(); // Code Meaning (Type 1) Attribute<0x0008, 0x0104> codeMeaningAttribute; codeMeaningAttribute.SetFromDataSet(itemDataSet); entry.CM = codeMeaningAttribute.GetValue(); result.push_back(entry); } } return result; } bool SegmentReader::ReadSegment(const Item & segmentItem, const unsigned int idx) { SmartPointer< Segment > segment = new Segment; const DataSet & rootDs = GetFile().GetDataSet(); const DataSet & segmentDS = segmentItem.GetNestedDataSet(); // Segment Number const Tag segmentNumberTag(0x0062, 0x0004); if (segmentDS.FindDataElement( segmentNumberTag ) && !segmentDS.GetDataElement( segmentNumberTag ).IsEmpty() ) { Attribute<0x0062, 0x0004> segmentNumberAt; segmentNumberAt.SetFromDataSet( segmentDS ); segment->SetSegmentNumber( segmentNumberAt.GetValue() ); } else { segment->SetSegmentNumber( (unsigned short)idx ); } // Segment Label Attribute<0x0062, 0x0005> segmentLabelAt; segmentLabelAt.SetFromDataSet( segmentDS ); segment->SetSegmentLabel( segmentLabelAt.GetValue() ); // Segment Description Attribute<0x0062, 0x0006> segmentDescriptionAt; segmentDescriptionAt.SetFromDataSet( segmentDS ); segment->SetSegmentDescription( segmentDescriptionAt.GetValue() ); // Segment Algorithm Type Attribute<0x0062, 0x0008> segmentAlgoType; segmentAlgoType.SetFromDataSet( segmentDS ); segment->SetSegmentAlgorithmType( segmentAlgoType.GetValue() ); // Surface Count Attribute<0x0066, 0x002A> surfaceCountAt; surfaceCountAt.SetFromDataSet( segmentDS ); const unsigned long surfaceCount = surfaceCountAt.GetValue(); segment->SetSurfaceCount( surfaceCount ); // Check if there is a Surface Segmentation Module if (surfaceCount > 0 || rootDs.FindDataElement(Tag(0x0066, 0x0002))) { //Basic Coded Entries in each sequences Segment::BasicCodedEntryVector basicCodedEntries; // Anatomic Region Sequence (Type 3) basicCodedEntries = readCodeSequenceMacroAttributes(Tag(0x0008, 0x2218), segmentDS); if(!basicCodedEntries.empty()) { segment->SetAnatomicRegion(basicCodedEntries[0]); // Only a single Item is permitted in this Sequence if(basicCodedEntries.size() > 1) { gdcmWarningMacro("Only a single Item is permitted in Anatomic Region Sequence, other items will be ignored"); } SmartPointer sequence = segmentDS.GetDataElement(Tag(0x0008, 0x2218)).GetValueAsSQ(); Item& item = sequence->GetItem(1); DataSet& itemDataSet = item.GetNestedDataSet(); // Anatomic Region Modifier Sequence (Type 3) basicCodedEntries = readCodeSequenceMacroAttributes(Tag(0x0008, 0x2220), itemDataSet); if(!basicCodedEntries.empty()) { segment->SetAnatomicRegionModifiers(basicCodedEntries); } } // Segmented Property Category Code Sequence (Type 1) basicCodedEntries = readCodeSequenceMacroAttributes(Tag(0x0062, 0x0003), segmentDS); if(!basicCodedEntries.empty()) { segment->SetPropertyCategory(basicCodedEntries[0]); // Only a single Item shall be included in this Sequence if(basicCodedEntries.size() > 1) { gdcmWarningMacro("Only a single Item shall be included in Segmented Property Category Code Sequence, other items will be ignored"); } } else { gdcmWarningMacro("No Item have been found in Segmented Property Category Code Sequence."); } // Segmented Property Type Code Sequence (Type 1) basicCodedEntries = readCodeSequenceMacroAttributes(Tag(0x0062, 0x000F), segmentDS); if(!basicCodedEntries.empty()) { segment->SetPropertyType(basicCodedEntries[0]); // Only a single Item shall be included in this Sequence if(basicCodedEntries.size() > 1) { gdcmWarningMacro("Only a single Item shall be included in Segmented Property Type Code Sequence, other items will be ignored"); } SmartPointer sequence = segmentDS.GetDataElement(Tag(0x0062, 0x000F)).GetValueAsSQ(); Item& item = sequence->GetItem(1); DataSet& itemDataSet = item.GetNestedDataSet(); // Segmented Property Type Modifier Sequence (Type 3) basicCodedEntries = readCodeSequenceMacroAttributes(Tag(0x0062, 0x0011), itemDataSet); if(!basicCodedEntries.empty()) { segment->SetPropertyTypeModifiers(basicCodedEntries); } } else { gdcmWarningMacro("No Item have been found in Segmented Property Type Code Sequence."); } // Referenced Surface Sequence const Tag refSurfaceSQTag(0x0066, 0x002B); if (segmentDS.FindDataElement(refSurfaceSQTag)) { SmartPointer< SequenceOfItems > refSurfaceSQ = segmentDS.GetDataElement(refSurfaceSQTag).GetValueAsSQ(); // Index each surface of a segment SequenceOfItems::ConstIterator itRefSurface = refSurfaceSQ->Begin(); SequenceOfItems::ConstIterator itEndRefSurface = refSurfaceSQ->End(); unsigned long numberOfSurfaces = 0; for (; itRefSurface != itEndRefSurface; itRefSurface++) { const DataSet & refSurfaceDS = itRefSurface->GetNestedDataSet(); // Referenced Surface Number Attribute<0x0066, 0x002C> refSurfaceNumberAt; refSurfaceNumberAt.SetFromDataSet( refSurfaceDS ); unsigned long refSurfaceNumber; if ( !refSurfaceNumberAt.GetAsDataElement().IsEmpty() ) { refSurfaceNumber = refSurfaceNumberAt.GetValue(); } else { refSurfaceNumber = idx; } // Index the segment with its referenced surface number Segments[refSurfaceNumber] = segment; // Compute number of items // (can not use GetNumberOfItems because of it returns a unsigned int) ++numberOfSurfaces; } // Set surface count corresponding to number of items if ( numberOfSurfaces != surfaceCount) { segment->SetSurfaceCount( numberOfSurfaces ); // Is it the right thing to do? } } else {// Index the segment with item number Segments[idx] = segment; } } else { // If is not a surface segmentation storage // Segment Algorithm Name Attribute<0x0062, 0x0009> segmentAlgoName; segmentAlgoName.SetFromDataSet( segmentDS ); segment->SetSegmentAlgorithmName( segmentAlgoName.GetValue() ); // Index the segment with item number Segments[idx] = segment; } return true; } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSegmentReader.h000066400000000000000000000031311412732066400242410ustar00rootroot00000000000000/*========================================================================= 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 GDCMSEGMENTREADER_H #define GDCMSEGMENTREADER_H #include #include #include namespace gdcm { /** * \brief This class defines a segment reader. * \details It reads attributes of group 0x0062. * * \see PS 3.3 C.8.20.2 and C.8.23 */ class GDCM_EXPORT SegmentReader : public Reader { public: typedef std::vector< SmartPointer< Segment > > SegmentVector; SegmentReader(); ~SegmentReader() override; /// Read bool Read() override; // Set to protected ? //** Segment getters/setters **// const SegmentVector GetSegments() const; SegmentVector GetSegments(); // unsigned int GetNumberOfSegments(); protected: typedef std::map< unsigned long, SmartPointer< Segment > > SegmentMap; bool ReadSegments(); bool ReadSegment(const Item & segmentItem, const unsigned int idx); SegmentMap Segments; // The key value is item number (in segment sequence) // or the surface number (for a surface segmentation). }; } #endif // GDCMSEGMENTREADER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSegmentWriter.cxx000066400000000000000000000324021412732066400246710ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSegmentWriter.h" #include "gdcmAttribute.h" namespace gdcm { SegmentWriter::SegmentWriter() = default; SegmentWriter::~SegmentWriter() = default; unsigned int SegmentWriter::GetNumberOfSegments() const { return (unsigned int)Segments.size(); } void SegmentWriter::SetNumberOfSegments(const unsigned int size) { Segments.resize(size); } const SegmentWriter::SegmentVector & SegmentWriter::GetSegments() const { return Segments; } SegmentWriter::SegmentVector & SegmentWriter::GetSegments() { return Segments; } SmartPointer< Segment > SegmentWriter::GetSegment(const unsigned int idx /*= 0*/) const { assert( idx < Segments.size() ); return Segments[idx]; } void SegmentWriter::AddSegment(SmartPointer< Segment > segment) { Segments.push_back(segment); } void SegmentWriter::SetSegments(SegmentVector & segments) { Segments = segments; } void writeCodeSequenceMacroAttributes(const SegmentHelper::BasicCodedEntry & entry, const Tag & tag, DataSet & dataset, bool severalItemsAllowed) { SmartPointer sequence; // If the sequence does not exist, we create it if(!dataset.FindDataElement(tag)) { sequence = new SequenceOfItems(); DataElement dataElement( tag ); dataElement.SetVR( VR::SQ ); dataElement.SetValue(*sequence); dataElement.SetVLToUndefined(); dataset.Insert(dataElement); } // Retrieve the sequence from the dataset sequence = dataset.GetDataElement(tag).GetValueAsSQ(); // Check if an item is already present in the sequence if (!severalItemsAllowed && sequence->GetNumberOfItems() > 0) { // Obviously the user has already added an item to the sequence // Let's assume the user knows what he does return; } // Fill the Sequence sequence->SetLengthToUndefined(); Item item; item.SetVLToUndefined(); DataSet & itemDataSet = item.GetNestedDataSet(); // Code Sequence Macro Attributes { // Code Value (Type 1C) Attribute<0x0008, 0x0100> codeValueAttribute; codeValueAttribute.SetValue(entry.CV); itemDataSet.Replace(codeValueAttribute.GetAsDataElement()); // Coding Scheme Designator (Type 1C) Attribute<0x0008, 0x0102> codingSchemeDesignatorAttribute; codingSchemeDesignatorAttribute.SetValue(entry.CSD); itemDataSet.Replace(codingSchemeDesignatorAttribute.GetAsDataElement()); // Coding Scheme Version (Type 1C) if(!entry.CSV.empty()) { Attribute<0x0008, 0x0103> codingSchemeVersionAttribute; codingSchemeVersionAttribute.SetValue(entry.CSV); itemDataSet.Replace(codingSchemeVersionAttribute.GetAsDataElement()); } // Code Meaning (Type 1) Attribute<0x0008, 0x0104> codeMeaningAttribute; codeMeaningAttribute.SetValue(entry.CM); itemDataSet.Replace(codeMeaningAttribute.GetAsDataElement()); } sequence->AddItem(item); } void writeCodeSequenceMacroAttributes(const Segment::BasicCodedEntryVector & entries, const Tag & tag, DataSet & dataset) { Segment::BasicCodedEntryVector::const_iterator it = entries.begin(); for(; it != entries.end(); ++it) { writeCodeSequenceMacroAttributes(*it, tag, dataset, true); } } bool SegmentWriter::PrepareWrite() { File & file = GetFile(); DataSet & ds = file.GetDataSet(); // Segment Sequence SmartPointer segmentsSQ; if( !ds.FindDataElement( Tag(0x0062, 0x0002) ) ) { segmentsSQ = new SequenceOfItems; DataElement detmp( Tag(0x0062, 0x0002) ); detmp.SetVR( VR::SQ ); detmp.SetValue( *segmentsSQ ); detmp.SetVLToUndefined(); ds.Insert( detmp ); } segmentsSQ = ds.GetDataElement( Tag(0x0062, 0x0002) ).GetValueAsSQ(); segmentsSQ->SetLengthToUndefined(); { // Fill the Segment Sequence const unsigned int numberOfSegments = this->GetNumberOfSegments(); assert( numberOfSegments ); const size_t nbItems = segmentsSQ->GetNumberOfItems(); if (nbItems < numberOfSegments) { const size_t diff = numberOfSegments - nbItems; const size_t nbOfItemToMake = (diff > 0?diff:0); for(unsigned int i = 1; i <= nbOfItemToMake; ++i) { Item item; item.SetVLToUndefined(); segmentsSQ->AddItem(item); } } } // else Should I remove items? std::vector< SmartPointer< Segment > >::const_iterator it0 = Segments.begin(); std::vector< SmartPointer< Segment > >::const_iterator it0End = Segments.end(); unsigned int itemNumber = 1; unsigned long surfaceNumber = 1; for (; it0 != it0End; it0++) { SmartPointer< Segment > segment = *it0; assert( segment ); Item & segmentItem = segmentsSQ->GetItem(itemNumber); DataSet & segmentDS = segmentItem.GetNestedDataSet(); // Segment Number (Type 1) Attribute<0x0062, 0x0004> segmentNumberAt; unsigned short segmentNumber = segment->GetSegmentNumber(); if (segmentNumber == 0) segmentNumber = (unsigned short)itemNumber; segmentNumberAt.SetValue( segmentNumber ); segmentDS.Replace( segmentNumberAt.GetAsDataElement() ); // Segment Label (Type 1) const char * segmentLabel = segment->GetSegmentLabel(); if ( strcmp(segmentLabel, "") != 0 ) { gdcmWarningMacro("No segment label specified"); } Attribute<0x0062, 0x0005> segmentLabelAt; segmentLabelAt.SetValue( segmentLabel ); segmentDS.Replace( segmentLabelAt.GetAsDataElement() ); // Segment Description (Type 3) const char * segmentDescription = segment->GetSegmentDescription(); if ( strcmp(segmentDescription, "") != 0 ) { Attribute<0x0062, 0x0006> segmentDescriptionAt; segmentDescriptionAt.SetValue( segmentDescription ); segmentDS.Replace( segmentDescriptionAt.GetAsDataElement() ); } // Segment Algorithm Type (Type 1) const char * segmentAlgorithmType = Segment::GetALGOTypeString( segment->GetSegmentAlgorithmType() ); if ( segmentAlgorithmType == nullptr ) { gdcmWarningMacro("No segment algorithm type specified"); Attribute<0x0062, 0x0008> segmentAlgorithmTypeAt; segmentAlgorithmTypeAt.SetValue( "" ); segmentDS.Replace( segmentAlgorithmTypeAt.GetAsDataElement() ); } else { Attribute<0x0062, 0x0008> segmentAlgorithmTypeAt; segmentAlgorithmTypeAt.SetValue( segmentAlgorithmType ); segmentDS.Replace( segmentAlgorithmTypeAt.GetAsDataElement() ); } // General Anatomy Optional Macro Attributes { // Anatomic Region Sequence (Type 3) - Only a single Item allowed const SegmentHelper::BasicCodedEntry & anatomicRegion = segment->GetAnatomicRegion(); if(!anatomicRegion.IsEmpty()) { writeCodeSequenceMacroAttributes(anatomicRegion, Tag(0x0008, 0x2218), segmentDS, false); // Anatomic Region Modifier Sequence (Type 3) const Segment::BasicCodedEntryVector & anatomicRegionModifiers = segment->GetAnatomicRegionModifiers(); if(!anatomicRegionModifiers.empty()) { SmartPointer sequence = segmentDS.GetDataElement(Tag(0x0008, 0x2218)).GetValueAsSQ(); Item& item = sequence->GetItem(1); DataSet& itemDataSet = item.GetNestedDataSet(); writeCodeSequenceMacroAttributes(anatomicRegionModifiers, Tag(0x0008, 0x2220), itemDataSet); } } } // Segmented Property Category Code Sequence (Type 1) - Only a single Item allowed const SegmentHelper::BasicCodedEntry & propertyCategory = segment->GetPropertyCategory(); if(propertyCategory.IsEmpty()) { gdcmWarningMacro("The property category is not specified or incomplete"); } writeCodeSequenceMacroAttributes(propertyCategory, Tag(0x0062, 0x0003), segmentDS, false); // Segmented Property Type Code Sequence (Type 1) - Only a single Item allowed const SegmentHelper::BasicCodedEntry & propertyType = segment->GetPropertyType(); if(propertyType.IsEmpty()) { gdcmWarningMacro("The property type is not specified or incomplete"); } writeCodeSequenceMacroAttributes(propertyType, Tag(0x0062, 0x000F), segmentDS, false); // Segmented Property Type Modifier Code Sequence (Type 3) const Segment::BasicCodedEntryVector & propertyTypeModifiers = segment->GetPropertyTypeModifiers(); if(!propertyTypeModifiers.empty()) { SmartPointer sequence = segmentDS.GetDataElement(Tag(0x0062, 0x000F)).GetValueAsSQ(); Item& item = sequence->GetItem(1); DataSet& itemDataSet = item.GetNestedDataSet(); writeCodeSequenceMacroAttributes(propertyTypeModifiers, Tag(0x0062, 0x0011), itemDataSet); } //***** Surface segmentation *****// const unsigned long surfaceCount = segment->GetSurfaceCount(); if (surfaceCount > 0) { // Surface Count Attribute<0x0066, 0x002A> surfaceCountAt; surfaceCountAt.SetValue( (unsigned int)surfaceCount ); segmentDS.Replace( surfaceCountAt.GetAsDataElement() ); //***** Referenced Surface Sequence *****// SmartPointer segmentsRefSQ; if( !segmentDS.FindDataElement( Tag(0x0066, 0x002B) ) ) { segmentsRefSQ = new SequenceOfItems; DataElement detmp( Tag(0x0066, 0x002B) ); detmp.SetVR( VR::SQ ); detmp.SetValue( *segmentsRefSQ ); detmp.SetVLToUndefined(); segmentDS.Insert( detmp ); } segmentsRefSQ = segmentDS.GetDataElement( Tag(0x0066, 0x002B) ).GetValueAsSQ(); segmentsRefSQ->SetLengthToUndefined(); // Fill the Segment Surface Generation Algorithm Identification Sequence const size_t nbItems = segmentsRefSQ->GetNumberOfItems(); if (nbItems < surfaceCount) { const size_t diff = surfaceCount - nbItems; const size_t nbOfItemToMake = (diff > 0?diff:0); for(unsigned int i = 1; i <= nbOfItemToMake; ++i) { Item item; item.SetVLToUndefined(); segmentsRefSQ->AddItem(item); } } // else Should I remove items? std::vector< SmartPointer< Surface > > surfaces = segment->GetSurfaces(); std::vector< SmartPointer< Surface > >::const_iterator it = surfaces.begin(); std::vector< SmartPointer< Surface > >::const_iterator itEnd = surfaces.end(); unsigned int itemSurfaceNumber = 1; for (; it != itEnd; it++) { SmartPointer< Surface > surface = *it; Item & segmentsRefItem = segmentsRefSQ->GetItem( itemSurfaceNumber++ ); DataSet & segmentsRefDS = segmentsRefItem.GetNestedDataSet(); // Referenced Surface Number Attribute<0x0066, 0x002C> refSurfaceNumberAt; unsigned long refSurfaceNumber = surface->GetSurfaceNumber(); if (refSurfaceNumber == 0) { refSurfaceNumber = surfaceNumber++; surface->SetSurfaceNumber( refSurfaceNumber ); } refSurfaceNumberAt.SetValue( (unsigned int)refSurfaceNumber ); segmentsRefDS.Replace( refSurfaceNumberAt.GetAsDataElement() ); //***** Segment Surface Source Instance Sequence *****// { // SmartPointer surfaceSourceSQ; // if( !segmentsRefDS.FindDataElement( Tag(0x0066, 0x002E) ) ) // { // surfaceSourceSQ = new SequenceOfItems; // DataElement detmp( Tag(0x0066, 0x002E) ); // detmp.SetVR( VR::SQ ); // detmp.SetValue( *surfaceSourceSQ ); // detmp.SetVLToUndefined(); // segmentsRefDS.Insert( detmp ); // } // surfaceSourceSQ = segmentsRefDS.GetDataElement( Tag(0x0066, 0x002E) ).GetValueAsSQ(); // surfaceSourceSQ->SetLengthToUndefined(); //NOTE: If surfaces are derived from image, include 'Image SOP Instance Reference Macro' PS 3.3 Table C.10-3. // How to know it? } } } else { // Segment Algorithm Name (Type 1) const char * segmentAlgorithmName = segment->GetSegmentAlgorithmName(); if ( strcmp(segmentAlgorithmName, "") != 0 ) { gdcmWarningMacro("No segment algorithm name specified"); } Attribute<0x0062, 0x0009> segmentAlgorithmNameAt; segmentAlgorithmNameAt.SetValue( segmentAlgorithmName ); segmentDS.Replace( segmentAlgorithmNameAt.GetAsDataElement() ); } ++itemNumber; } return true; } bool SegmentWriter::Write() { if( !PrepareWrite() ) { return false; } assert( Stream ); if( !Writer::Write() ) { return false; } return true; } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSegmentWriter.h000066400000000000000000000030401412732066400243120ustar00rootroot00000000000000/*========================================================================= 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 GDCMSEGMENTWRITER_H #define GDCMSEGMENTWRITER_H #include #include namespace gdcm { /** * \brief This class defines a segment writer. * \details It writes attributes of group 0x0062. * * \see PS 3.3 C.8.20.2 and C.8.23 */ class GDCM_EXPORT SegmentWriter : public Writer { public: typedef std::vector< SmartPointer< Segment > > SegmentVector; SegmentWriter(); ~SegmentWriter() override; /// Write bool Write() override; // Set to protected ? //** Segment getters/setters **// unsigned int GetNumberOfSegments() const; void SetNumberOfSegments(const unsigned int size); const SegmentVector & GetSegments() const; SegmentVector & GetSegments(); SmartPointer< Segment > GetSegment(const unsigned int idx = 0) const; void AddSegment(SmartPointer< Segment > segment); void SetSegments(SegmentVector & segments); protected: bool PrepareWrite(); SegmentVector Segments; }; } #endif // GDCMSEGMENTWRITER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSegmentedPaletteColorLookupTable.cxx000066400000000000000000000166541412732066400305000ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSegmentedPaletteColorLookupTable.h" #include "gdcmDataSet.h" // http://blog.goo.ne.jp/satomi_takeo/e/3643e5249b2a9650f9e10ef1c830e8b8 // #include #include #include #include #include namespace gdcm { // abstract class for segment. template class Segment { public: virtual ~Segment() = default; using SegmentMap = std::map; virtual bool Expand(const SegmentMap& instances, std::vector& expanded) const = 0; const EntryType* First() const { return _first; } const EntryType* Last() const { return _last; } struct ToMap { std::pair< typename SegmentMap::key_type, typename SegmentMap::mapped_type > operator()(const Segment* segment) const { return std::make_pair(segment->First(), segment); } }; protected: Segment(const EntryType* first, const EntryType* last) { _first = first; _last = last; } const EntryType* _first; const EntryType* _last; }; // discrete segment (opcode = 0) template class DiscreteSegment : public Segment { public: using SegmentMap = typename Segment::SegmentMap; DiscreteSegment(const EntryType* first) : Segment(first, first+2+*(first+1)) {} bool Expand(const SegmentMap&, std::vector& expanded) const override { std::copy(this->_first + 2, this->_last, std::back_inserter(expanded)); return true; } }; // linear segment (opcode = 1) template class LinearSegment : public Segment { public: using SegmentMap = typename Segment::SegmentMap; LinearSegment(const EntryType* first) : Segment(first, first+3) {} bool Expand(const SegmentMap&, std::vector& expanded) const override { if ( expanded.empty() ) { // linear segment can't be the first segment. return false; } EntryType length = *(this->_first + 1); EntryType y0 = expanded.back(); EntryType y1 = *(this->_first + 2); double y01 = y1 - y0; for ( EntryType i = 0; i (y0) + (static_cast(i)/static_cast(length)) * y01; EntryType value_int = static_cast(value_float + 0.5); expanded.push_back(value_int); } return true; } }; // indirect segment (opcode = 2) template class IndirectSegment : public Segment { public: using SegmentMap = typename Segment::SegmentMap; IndirectSegment(const EntryType* first) : Segment(first, first+2+4/sizeof(EntryType)) {} bool Expand(const SegmentMap& instances, std::vector& expanded) const override { if ( instances.empty() ) { // some other segments are required as references. return false; } const EntryType* first_segment = instances.begin()->first; const unsigned short* pOffset = reinterpret_cast(this->_first + 2); unsigned long offsetBytes = (*pOffset) | (static_cast(*(pOffset + 1)) << 16); const EntryType* copied_part_head = first_segment + offsetBytes / sizeof(EntryType); typename SegmentMap::const_iterator ppHeadSeg = instances.find(copied_part_head); if ( ppHeadSeg == instances.end() ) { // referred segment not found return false; } EntryType nNumCopies = *(this->_first + 1); typename SegmentMap::const_iterator ppSeg = ppHeadSeg; while ( std::distance(ppHeadSeg, ppSeg) second->Expand(instances, expanded); ++ppSeg; } return true; } }; template void ExpandPalette(const EntryType* raw_values, uint32_t length, std::vector& palette) { using SegmentList = std::deque *>; SegmentList segments; const EntryType* raw_seg = raw_values; while ( (std::distance(raw_values, raw_seg) * sizeof(EntryType)) * segment = nullptr; if ( *raw_seg == 0 ) { segment = new DiscreteSegment(raw_seg); } else if ( *raw_seg == 1 ) { segment = new LinearSegment(raw_seg); } else if ( *raw_seg == 2 ) { segment = new IndirectSegment(raw_seg); } if ( segment ) { segments.push_back(segment); raw_seg = segment->Last(); } else { // invalid opcode break; } } typename Segment::SegmentMap instances; std::transform(segments.begin(), segments.end(), std::inserter(instances, instances.end()), typename Segment::ToMap()); typename SegmentList::iterator ppSeg = segments.begin(); typename SegmentList::iterator endOfSegments = segments.end(); for ( ; ppSeg != endOfSegments; ++ppSeg ) { (*ppSeg)->Expand(instances, palette); } ppSeg = segments.begin(); for ( ; ppSeg != endOfSegments; ++ppSeg ) { delete *ppSeg; } } SegmentedPaletteColorLookupTable::SegmentedPaletteColorLookupTable() = default; SegmentedPaletteColorLookupTable::~SegmentedPaletteColorLookupTable() = default; void SegmentedPaletteColorLookupTable::SetLUT(LookupTableType type, const unsigned char *array, unsigned int length) { if( BitSample == 8 ) { assert(0); // TODO } else if( BitSample == 16 ) { const uint16_t *array16 = (const uint16_t*)(const void*)array; const uint16_t *segment_values = array16; std::vector palette; unsigned int num_entries = GetLUTLength(type); palette.reserve(num_entries); assert( length % 2 == 0 ); // 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)); } } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSegmentedPaletteColorLookupTable.h000066400000000000000000000022721412732066400301140ustar00rootroot00000000000000/*========================================================================= 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 GDCMSEGMENTEDPALETTECOLORLOOKUPTABLE_H #define GDCMSEGMENTEDPALETTECOLORLOOKUPTABLE_H #include "gdcmLookupTable.h" namespace gdcm { /** * \brief SegmentedPaletteColorLookupTable class */ class GDCM_EXPORT SegmentedPaletteColorLookupTable : public LookupTable { public: SegmentedPaletteColorLookupTable(); ~SegmentedPaletteColorLookupTable() override; void Print(std::ostream &) const override {} /// Initialize a SegmentedPaletteColorLookupTable void SetLUT(LookupTableType type, const unsigned char *array, unsigned int length) override; }; } // end namespace gdcm #endif //GDCMSEGMENTEDPALETTECOLORLOOKUPTABLE_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSerieHelper.cxx000066400000000000000000000333531412732066400243070ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSerieHelper.h" #include "gdcmStringFilter.h" #include "gdcmDirectory.h" #include "gdcmIPPSorter.h" #include "gdcmImageReader.h" #include "gdcmImageHelper.h" #include "gdcmAttribute.h" #include "gdcmTrace.h" namespace gdcm { SerieHelper::SerieHelper() { Trace::WarningOff(); UseSeriesDetails = false; Clear(); UserLessThanFunction = nullptr; DirectOrder = true; //LoadMode = 0; } SerieHelper::~SerieHelper() { Clear(); } void SerieHelper::AddRestriction(uint16_t group, uint16_t elem, std::string const &value, int op) { Rule r; r.group = group; r.elem = elem; r.value = value; r.op = op; Restrictions.push_back( r ); } void SerieHelper::AddRestriction(const std::string & tag) { Tag t; t.ReadFromPipeSeparatedString(tag.c_str()); AddRestriction( Tag(t.GetGroup(), t.GetElement()) ); } void SerieHelper::AddRestriction(const Tag& tag) { Rule r; r.group = tag.GetGroup(); r.elem = tag.GetElement(); Refine.push_back( r ); } void SerieHelper::SetUseSeriesDetails( bool useSeriesDetails ) { UseSeriesDetails = useSeriesDetails; } void SerieHelper::CreateDefaultUniqueSeriesIdentifier() { // If the user requests, additional information can be appended // to the SeriesUID to further differentiate volumes in the DICOM // objects being processed. // 0020 0011 Series Number // A scout scan prior to a CT volume scan can share the same // SeriesUID, but they will sometimes have a different Series Number AddRestriction( Tag(0x0020, 0x0011) ); // 0018 0024 Sequence Name // For T1-map and phase-contrast MRA, the different flip angles and // directions are only distinguished by the Sequence Name AddRestriction( Tag(0x0018, 0x0024) ); // 0018 0050 Slice Thickness // On some CT systems, scout scans and subsequence volume scans will // have the same SeriesUID and Series Number - YET the slice // thickness will differ from the scout slice and the volume slices. AddRestriction( Tag(0x0018, 0x0050) ); // 0028 0010 Rows // If the 2D images in a sequence don't have the same number of rows, // then it is difficult to reconstruct them into a 3D volume. AddRestriction( Tag(0x0028, 0x0010)); // 0028 0011 Columns // If the 2D images in a sequence don't have the same number of columns, // then it is difficult to reconstruct them into a 3D volume. AddRestriction( Tag(0x0028, 0x0011)); } void SerieHelper::Clear() { // For all the 'Single SerieUID' Filesets that may already exist FileList *l = GetFirstSingleSerieUIDFileSet(); while (l) { // For all the File of a File set for (FileList::iterator it = l->begin(); it != l->end(); ++it) { //delete *it; // remove each entry } l->clear(); delete l; // remove the container l = GetNextSingleSerieUIDFileSet(); } // Need to clear that too: SingleSerieUIDFileSetHT.clear(); } void SerieHelper::SetDirectory(std::string const &dir, bool recursive) { Directory dirList; unsigned int nfiles = dirList.Load(dir, recursive); (void)nfiles; Directory::FilenamesType const &filenames = dirList.GetFilenames(); for( Directory::FilenamesType::const_iterator it = filenames.begin(); it != filenames.end(); ++it) { AddFileName( *it ); } } void SerieHelper::AddFileName(std::string const &filename) { // Only accept DICOM file containing Image (Pixel Data element): ImageReader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { gdcmWarningMacro("Could not read file: " << filename ); } else { SmartPointer f = new FileWithName( reader.GetFile() ); f->filename = filename; (void)AddFile( *f /*reader.GetFile()*/ ); // discard return value } } static bool CompareDicomString(const std::string &s1, const char *s2, int op) { // s2 is the string from the DICOM reference e.g. : 'MONOCHROME1' std::string s1_even = s1; //Never change input parameter std::string s2_even = /*DicomString(*/ s2 ; assert( s2_even.size() % 2 == 0 ); if ( s1_even[s1_even.size()-1] == ' ' ) { s1_even[s1_even.size()-1] = '\0'; //replace space character by null } switch (op) { case GDCM_EQUAL : return s1_even == s2_even; case GDCM_DIFFERENT : return s1_even != s2_even; case GDCM_GREATER : return s1_even > s2_even; case GDCM_GREATEROREQUAL : return s1_even >= s2_even; case GDCM_LESS : return s1_even < s2_even; case GDCM_LESSOREQUAL : return s1_even <= s2_even; default : gdcmDebugMacro(" Wrong operator : " << op); return false; } } bool SerieHelper::AddFile(FileWithName &header) { StringFilter sf; sf.SetFile( header ); int allrules = 1; // First step the user has defined a set of rules for the DICOM // he is looking for. // make sure the file correspond to his set of rules: std::string s; for(SerieRestrictions::iterator it2 = Restrictions.begin(); it2 != Restrictions.end(); ++it2) { const Rule &r = *it2; //s = header->GetEntryValue( r.group, r.elem ); s = sf.ToString( Tag(r.group,r.elem) ); if ( !CompareDicomString(s, r.value.c_str(), r.op) ) { // Argh ! This rule is unmatched; let's just quit allrules = 0; break; } } if ( allrules ) // all rules are respected: { // All right! we have a found a DICOM that matches the user expectation. // Let's add it to the specific 'id' which by default is uid (Series UID) // but can be `refined` by user with more parameter (see AddRestriction(g,e)) std::string id = CreateUniqueSeriesIdentifier( &header ); // if id == GDCM_UNFOUND then consistently we should find GDCM_UNFOUND // no need here to do anything special if ( SingleSerieUIDFileSetHT.count(id) == 0 ) { gdcmDebugMacro(" New Series UID :[" << id << "]"); // create a std::list in 'id' position SingleSerieUIDFileSetHT[id] = new FileList; } // Current Series UID and DICOM header seems to match add the file: SingleSerieUIDFileSetHT[id]->push_back( header ); } else { // one rule not matched, tell user: return false; } return true; } FileList *SerieHelper::GetFirstSingleSerieUIDFileSet() { ItFileSetHt = SingleSerieUIDFileSetHT.begin(); if ( ItFileSetHt != SingleSerieUIDFileSetHT.end() ) return ItFileSetHt->second; return nullptr; } FileList *SerieHelper::GetNextSingleSerieUIDFileSet() { //gdcmAssertMacro (ItFileSetHt != SingleSerieUIDFileSetHT.end()); ++ItFileSetHt; if ( ItFileSetHt != SingleSerieUIDFileSetHT.end() ) return ItFileSetHt->second; return nullptr; } bool SerieHelper::UserOrdering(FileList *fileList) { std::sort(fileList->begin(), fileList->end(), SerieHelper::UserLessThanFunction); if (!DirectOrder) { std::reverse(fileList->begin(), fileList->end()); } return true; } namespace details { bool MyFileNameSortPredicate(const SmartPointer& d1, const SmartPointer& d2) { return d1->filename < d2->filename; } bool MyInstanceSortPredicate(const SmartPointer& d1, const SmartPointer& d2) { Attribute<0x0020,0x0013> instancenumber1; Attribute<0x0020,0x0013> instancenumber2; const DataSet& ds1 = d1->GetDataSet(); instancenumber1.SetFromDataSet( ds1 ); const DataSet& ds2 = d2->GetDataSet(); instancenumber2.SetFromDataSet( ds2 ); return instancenumber1.GetValue() < instancenumber2.GetValue(); } } bool SerieHelper::FileNameOrdering( FileList *fileList ) { std::sort(fileList->begin(), fileList->end(), details::MyFileNameSortPredicate); return true; } bool SerieHelper::ImageNumberOrdering( FileList *fileList ) { Attribute<0x0020,0x0013> instancenumber; std::set instancenumbers; for ( FileList::const_iterator it = fileList->begin(); it != fileList->end(); ++it ) { instancenumber.SetValue( -1 ); const DataSet& ds = (*it)->GetDataSet(); instancenumber.SetFromDataSet( ds ); int in = instancenumber.GetValue(); instancenumbers.insert( in ); } if( instancenumbers.size() == fileList->size() ) { std::sort(fileList->begin(), fileList->end(), details::MyInstanceSortPredicate); return true; } return false; } bool SerieHelper::ImagePositionPatientOrdering( FileList *fileList ) { //iop is calculated based on the file file std::vector cosines; double normal[3] = {}; std::vector ipp; double dist; double min = 0, max = 0; bool first = true; std::multimap > distmultimap; // Use a multimap to sort the distances from 0,0,0 for ( FileList::const_iterator it = fileList->begin(); it != fileList->end(); ++it ) { if ( first ) { //(*it)->GetImageOrientationPatient( cosines ); cosines = ImageHelper::GetDirectionCosinesValue( **it ); // You only have to do this once for all slices in the volume. Next, // for each slice, calculate the distance along the slice normal // using the IPP ("Image Position Patient") tag. // ("dist" is initialized to zero before reading the first slice) : normal[0] = cosines[1]*cosines[5] - cosines[2]*cosines[4]; normal[1] = cosines[2]*cosines[3] - cosines[0]*cosines[5]; normal[2] = cosines[0]*cosines[4] - cosines[1]*cosines[3]; ipp = ImageHelper::GetOriginValue( **it ); //ipp[0] = (*it)->GetXOrigin(); //ipp[1] = (*it)->GetYOrigin(); //ipp[2] = (*it)->GetZOrigin(); dist = 0; for ( int i = 0; i < 3; ++i ) { dist += normal[i]*ipp[i]; } distmultimap.insert(std::pair >(dist, *it)); max = min = dist; first = false; } else { ipp = ImageHelper::GetOriginValue( **it ); //ipp[0] = (*it)->GetXOrigin(); //ipp[1] = (*it)->GetYOrigin(); //ipp[2] = (*it)->GetZOrigin(); dist = 0; for ( int i = 0; i < 3; ++i ) { dist += normal[i]*ipp[i]; } distmultimap.insert(std::pair >(dist, *it)); min = (min < dist) ? min : dist; max = (max > dist) ? max : dist; } } // Find out if min/max are coherent if ( min == max ) { gdcmWarningMacro("Looks like all images have the exact same image position" << ". No PositionPatientOrdering sort performed" ); return false; } // Check to see if image shares a common position bool ok = true; for (std::multimap >::iterator it2 = distmultimap.begin(); it2 != distmultimap.end(); ++it2) { if (distmultimap.count((*it2).first) != 1) { gdcmErrorMacro("File: " //<< ((*it2).second->GetFileName()) << " Distance: " << (*it2).first << " position is not unique"); ok = false; } } if (!ok) { return false; } fileList->clear(); // doesn't delete list elements, only nodes if (DirectOrder) { for (std::multimap >::iterator it3 = distmultimap.begin(); it3 != distmultimap.end(); ++it3) { fileList->push_back( (*it3).second ); } } else // user asked for reverse order { std::multimap >::const_iterator it4; it4 = distmultimap.end(); do { it4--; fileList->push_back( (*it4).second ); } while (it4 != distmultimap.begin() ); } distmultimap.clear(); return true; } void SerieHelper::OrderFileList(FileList *fileSet) { IPPSorter ipps; if ( SerieHelper::UserLessThanFunction ) { UserOrdering( fileSet ); return; } else if ( ImagePositionPatientOrdering( fileSet ) ) { return ; } else if ( ImageNumberOrdering(fileSet ) ) { return ; } else { FileNameOrdering(fileSet ); } } std::string SerieHelper::CreateUniqueSeriesIdentifier( File * inFile ) { StringFilter sf; sf.SetFile( *inFile ); if( true /*inFile->IsReadable()*/ ) { // 0020 000e UI REL Series Instance UID //std::string uid = inFile->GetEntryValue (0x0020, 0x000e); std::string uid = sf.ToString( Tag(0x0020, 0x000e) ); std::string id = uid.c_str(); if(UseSeriesDetails) { for(SerieRestrictions::iterator it2 = Refine.begin(); it2 != Refine.end(); ++it2) { const Rule &r = *it2; //std::string s = inFile->GetEntryValue( r.group, r.elem ); std::string s = sf.ToString( Tag(r.group, r.elem) ); //if( s == GDCM_UNFOUND ) // { // s = ""; // } if( id == uid && !s.empty() ) { id += "."; // add separator } id += s; } } // Eliminate non-alnum characters, including whitespace... // that may have been introduced by concats. for(size_t i=0; i= 'a' && id[i] <= 'z') || (id[i] >= '0' && id[i] <= '9') || (id[i] >= 'A' && id[i] <= 'Z'))) { id.erase(i, 1); } } return id; } else // Could not open inFile { gdcmWarningMacro("Could not parse series info."); std::string id = "GDCM_UNFOUND"; //GDCM_UNFOUND; return id; } } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSerieHelper.h000066400000000000000000000061431412732066400237310ustar00rootroot00000000000000/*========================================================================= 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 GDCMSERIEHELPER_H #define GDCMSERIEHELPER_H #include "gdcmTag.h" #include "gdcmSmartPointer.h" #include "gdcmFile.h" #include #include #include namespace gdcm { enum CompOperators { GDCM_EQUAL = 0, GDCM_DIFFERENT, GDCM_GREATER, GDCM_GREATEROREQUAL, GDCM_LESS, GDCM_LESSOREQUAL }; enum LodModeType { LD_ALL = 0x00000000, LD_NOSEQ = 0x00000001, LD_NOSHADOW = 0x00000002, LD_NOSHADOWSEQ = 0x00000004 }; /** * \brief FileWithName * * \details * Backward only class do not use in newer code */ class GDCM_EXPORT FileWithName : public File { public: FileWithName(File &f):File(f),filename(){} std::string filename; }; typedef std::vector< SmartPointer > FileList; typedef bool (*BOOL_FUNCTION_PFILE_PFILE_POINTER)(File *, File *); class Scanner; /** * \brief SerieHelper * DO NOT USE this class, it is only a temporary solution for ITK migration from GDCM 1.x to GDCM 2.x * It will disappear soon, you've been warned. * * Instead see ImageHelper or IPPSorter */ class GDCM_EXPORT SerieHelper { public: SerieHelper(); ~SerieHelper(); void Clear(); void SetLoadMode (int ) {} void SetDirectory(std::string const &dir, bool recursive=false); void AddRestriction(const std::string & tag); void SetUseSeriesDetails( bool useSeriesDetails ); void CreateDefaultUniqueSeriesIdentifier(); FileList *GetFirstSingleSerieUIDFileSet(); FileList *GetNextSingleSerieUIDFileSet(); std::string CreateUniqueSeriesIdentifier( File * inFile ); void OrderFileList(FileList *fileSet); void AddRestriction(uint16_t group, uint16_t elem, std::string const &value, int op); protected: bool UserOrdering(FileList *fileSet); void AddFileName(std::string const &filename); bool AddFile(FileWithName &header); void AddRestriction(const Tag& tag); bool ImagePositionPatientOrdering(FileList *fileSet); bool ImageNumberOrdering( FileList *fileList ); bool FileNameOrdering( FileList *fileList ); using Rule = struct RuleStructure{ uint16_t group; uint16_t elem; std::string value; int op; }; typedef std::vector SerieRestrictions; typedef std::map SingleSerieUIDFileSetmap; SingleSerieUIDFileSetmap SingleSerieUIDFileSetHT; SingleSerieUIDFileSetmap::iterator ItFileSetHt; private: SerieRestrictions Restrictions; SerieRestrictions Refine; bool UseSeriesDetails; bool DirectOrder; BOOL_FUNCTION_PFILE_PFILE_POINTER UserLessThanFunction; }; // backward compat } // end namespace gdcm #endif //GDCMSERIEHELPER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSimpleSubjectWatcher.cxx000066400000000000000000000137621412732066400261710ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSimpleSubjectWatcher.h" #include "gdcmEvent.h" #include "gdcmAnonymizeEvent.h" #include "gdcmDataSetEvent.h" #include "gdcmProgressEvent.h" #include "gdcmFileNameEvent.h" namespace gdcm { SimpleSubjectWatcher::SimpleSubjectWatcher(Subject *s, const char *comment):m_Subject(s),m_Comment(comment) { // Create a series of commands m_StartFilterCommand = SimpleCommandType::New(); m_EndFilterCommand = SimpleCommandType::New(); m_ProgressFilterCommand = CommandType::New(); m_FileNameFilterCommand = CommandType::New(); m_IterationFilterCommand = SimpleCommandType::New(); m_AbortFilterCommand = SimpleCommandType::New(); m_AnonymizeFilterCommand = CommandType::New(); m_DataSetFilterCommand = CommandType::New(); m_DataFilterCommand = CommandType::New(); // Assign the callbacks m_StartFilterCommand->SetCallbackFunction(this, &SimpleSubjectWatcher::StartFilter); m_EndFilterCommand->SetCallbackFunction(this, &SimpleSubjectWatcher::EndFilter); m_ProgressFilterCommand->SetCallbackFunction(this, &SimpleSubjectWatcher::ShowProgress); m_FileNameFilterCommand->SetCallbackFunction(this, &SimpleSubjectWatcher::ShowFileName); m_IterationFilterCommand->SetCallbackFunction(this, &SimpleSubjectWatcher::ShowIteration); m_AbortFilterCommand->SetCallbackFunction(this, &SimpleSubjectWatcher::ShowAbort); m_AnonymizeFilterCommand->SetCallbackFunction(this, &SimpleSubjectWatcher::ShowAnonymization); m_DataSetFilterCommand->SetCallbackFunction(this, &SimpleSubjectWatcher::ShowDataSet); m_DataFilterCommand->SetCallbackFunction(this, &SimpleSubjectWatcher::ShowData); // Add the commands as observers m_StartTag = m_Subject->AddObserver(StartEvent(), m_StartFilterCommand); m_EndTag = m_Subject->AddObserver(EndEvent(), m_EndFilterCommand); m_ProgressTag = m_Subject->AddObserver(ProgressEvent(), m_ProgressFilterCommand); m_FileNameTag = m_Subject->AddObserver(FileNameEvent(), m_FileNameFilterCommand); m_IterationTag = m_Subject->AddObserver(IterationEvent(), m_IterationFilterCommand); m_AbortTag = m_Subject->AddObserver(AbortEvent(), m_AbortFilterCommand); m_AnonymizeTag = m_Subject->AddObserver(AnonymizeEvent(), m_AnonymizeFilterCommand); m_DataSetTag = m_Subject->AddObserver(DataSetEvent(), m_DataSetFilterCommand); m_DataTag = m_Subject->AddObserver(DataEvent(), m_DataFilterCommand); m_TestAbort = false; } SimpleSubjectWatcher::~SimpleSubjectWatcher() { // Remove any observers we have on the old process object if (m_Subject) { if (m_StartFilterCommand) { m_Subject->RemoveObserver(m_StartTag); } if (m_EndFilterCommand) { m_Subject->RemoveObserver(m_EndTag); } if (m_ProgressFilterCommand) { m_Subject->RemoveObserver(m_ProgressTag); } if (m_FileNameFilterCommand) { m_Subject->RemoveObserver(m_FileNameTag); } if (m_IterationFilterCommand) { m_Subject->RemoveObserver(m_IterationTag); } if (m_AbortFilterCommand) { m_Subject->RemoveObserver(m_AbortTag); } if (m_AnonymizeFilterCommand) { m_Subject->RemoveObserver(m_AnonymizeTag); } if (m_DataFilterCommand) { m_Subject->RemoveObserver(m_DataTag); } if (m_DataSetFilterCommand) { m_Subject->RemoveObserver(m_DataSetTag); } } } void SimpleSubjectWatcher::StartFilter() { std::cout << "Start" << std::endl; } void SimpleSubjectWatcher::EndFilter() { std::cout << "End" << std::endl; } void SimpleSubjectWatcher::ShowProgress(Subject *caller, const Event &evt) { const ProgressEvent &pe = dynamic_cast(evt); (void)caller; if( !m_Comment.empty() ) std::cout << "(" << m_Comment << ") "; std::cout << "Progress: " << pe.GetProgress() << std::endl; } void SimpleSubjectWatcher::ShowFileName(Subject *caller, const Event &evt) { const FileNameEvent &pe = dynamic_cast(evt); (void)caller; if( !m_Comment.empty() ) std::cout << "(" << m_Comment << ") "; std::cout << "FileName: " << pe.GetFileName() << std::endl; } void SimpleSubjectWatcher::ShowIteration() { std::cout << "Iteration" << std::endl; } void SimpleSubjectWatcher::ShowAbort() { std::cout << "Abort" << std::endl; } void SimpleSubjectWatcher::ShowAnonymization(Subject *caller, const Event &evt) { const AnonymizeEvent &ae = dynamic_cast(evt); (void)caller; std::cout << "AnonymizeEvent: " << ae.GetTag() << std::endl; } void SimpleSubjectWatcher::ShowData(Subject *caller, const Event &evt) { const DataEvent &ae = dynamic_cast(evt); (void)caller; std::cout << "DataEvent: " << ae.GetDataLength() << std::endl; } void SimpleSubjectWatcher::ShowDataSet(Subject *caller, const Event &evt) { const DataSetEvent &ae = dynamic_cast(evt); (void)caller; std::cout << "DataSetEvent: \n"; std::cout << ae.GetDataSet() << std::endl; } void SimpleSubjectWatcher::TestAbortOn() { m_TestAbort = true; } void SimpleSubjectWatcher::TestAbortOff() { m_TestAbort = false; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSimpleSubjectWatcher.h000066400000000000000000000056101412732066400256070ustar00rootroot00000000000000/*========================================================================= 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 GDCMSIMPLESUBJECTWATCHER_H #define GDCMSIMPLESUBJECTWATCHER_H #include "gdcmSubject.h" #include "gdcmCommand.h" #include "gdcmSmartPointer.h" #include "gdcmAnonymizeEvent.h" #include "gdcmDataEvent.h" namespace gdcm { //----------------------------------------------------------------------------- class Event; /** * \brief SimpleSubjectWatcher * \details This is a typical Subject Watcher class. It will observe all events. */ class GDCM_EXPORT SimpleSubjectWatcher { public: SimpleSubjectWatcher(Subject * s, const char *comment = ""); virtual ~SimpleSubjectWatcher(); SimpleSubjectWatcher(const SimpleSubjectWatcher&) = delete; void operator=(const SimpleSubjectWatcher&) = delete; protected: virtual void StartFilter(); virtual void EndFilter(); virtual void ShowProgress(Subject *caller, const Event &evt); virtual void ShowFileName(Subject *caller, const Event &evt); virtual void ShowIteration(); virtual void ShowAnonymization(Subject *caller, const Event &evt); virtual void ShowDataSet(Subject *caller, const Event &evt); virtual void ShowData(Subject *caller, const Event &evt); virtual void ShowAbort(); protected: // Custom API used for internal Testing do not use ! void TestAbortOn(); void TestAbortOff(); private: SmartPointer m_Subject; std::string m_Comment; typedef SimpleMemberCommand SimpleCommandType; typedef MemberCommand CommandType; SmartPointer m_StartFilterCommand; SmartPointer m_EndFilterCommand; SmartPointer m_ProgressFilterCommand; SmartPointer m_FileNameFilterCommand; SmartPointer m_IterationFilterCommand; SmartPointer m_AbortFilterCommand; SmartPointer m_AnonymizeFilterCommand; SmartPointer m_DataFilterCommand; SmartPointer m_DataSetFilterCommand; unsigned long m_StartTag; unsigned long m_EndTag; unsigned long m_ProgressTag; unsigned long m_FileNameTag; unsigned long m_IterationTag; unsigned long m_AbortTag; unsigned long m_AnonymizeTag; unsigned long m_DataTag; unsigned long m_DataSetTag; bool m_TestAbort; }; } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMSIMPLESUBJECTWATCHER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSorter.cxx000066400000000000000000000104751412732066400233560ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSorter.h" #include "gdcmElement.h" #include "gdcmSerieHelper.h" #include "gdcmFile.h" #include "gdcmReader.h" #include #include #include namespace gdcm { Sorter::Sorter() { SortFunc = nullptr; TagsToRead = std::set(); } Sorter::~Sorter() = default; void Sorter::SetTagsToRead( std::set const & tags ) { TagsToRead = tags; } void Sorter::SetSortFunction( SortFunction f ) { SortFunc = f; } namespace { class SortFunctor { public: bool operator() (File const *file1, File const *file2) { return (SortFunc)(file1->GetDataSet(), file2->GetDataSet()); } Sorter::SortFunction SortFunc; SortFunctor() { SortFunc = nullptr; } SortFunctor(SortFunctor const &sf) { SortFunc = sf.SortFunc; } void operator=(Sorter::SortFunction sf) { SortFunc = sf; } }; } bool Sorter::StableSort(std::vector const & filenames) { // BUG: I cannot clear Filenames since input filenames could also be the output of ourself... // Filenames.clear(); if( filenames.empty() || !SortFunc ) { Filenames.clear(); return true; } std::vector< SmartPointer > filelist; filelist.resize( filenames.size() ); std::vector< SmartPointer >::iterator it2 = filelist.begin(); for( Directory::FilenamesType::const_iterator it = filenames.begin(); it != filenames.end() && it2 != filelist.end(); ++it, ++it2) { Reader reader; reader.SetFileName( it->c_str() ); SmartPointer &f = *it2; bool readWasSuccessful = TagsToRead.empty() ? reader.Read() : reader.ReadSelectedTags(TagsToRead); if (readWasSuccessful) { f = new FileWithName( reader.GetFile() ); f->filename = *it; } else { gdcmErrorMacro( "File could not be read: " << it->c_str() ); return false; } } SortFunctor sf; sf = Sorter::SortFunc; std::stable_sort( filelist.begin(), filelist.end(), sf); Filenames.clear(); // cleanup any previous call for(it2 = filelist.begin(); it2 != filelist.end(); ++it2 ) { SmartPointer const & f = *it2; Filenames.push_back( f->filename ); } return true; } bool Sorter::Sort(std::vector const & filenames) { (void)filenames; Filenames.clear(); if( filenames.empty() || !SortFunc ) return true; std::vector< SmartPointer > filelist; filelist.resize( filenames.size() ); std::vector< SmartPointer >::iterator it2 = filelist.begin(); for( Directory::FilenamesType::const_iterator it = filenames.begin(); it != filenames.end() && it2 != filelist.end(); ++it, ++it2) { Reader reader; reader.SetFileName( it->c_str() ); SmartPointer &f = *it2; bool readWasSuccessful = TagsToRead.empty() ? reader.Read() : reader.ReadSelectedTags(TagsToRead); if (readWasSuccessful) { f = new FileWithName( reader.GetFile() ); f->filename = *it; } else { gdcmErrorMacro( "File could not be read: " << it->c_str() ); return false; } } //std::sort( filelist.begin(), filelist.end(), Sorter::SortFunc); SortFunctor sf; sf = Sorter::SortFunc; std::sort( filelist.begin(), filelist.end(), sf); for(it2 = filelist.begin(); it2 != filelist.end(); ++it2 ) { SmartPointer const & f = *it2; Filenames.push_back( f->filename ); } return true; } bool Sorter::AddSelect( Tag const &tag, const char *value ) { Selection.insert( SelectionMap::value_type(tag,value) ); return true; } void Sorter::Print( std::ostream &os) const { std::vector::const_iterator it = Filenames.begin(); for( ; it != Filenames.end(); ++it) { os << *it < #include #include #include namespace gdcm { class DataSet; /** * \brief Sorter * \details General class to do sorting using a custom function * You simply need to provide a function of type: Sorter::SortFunction * * \warning implementation details. For now there is no cache mechanism. Which means * that every time you call Sort, all files specified as input parameter are *read* * * \see Scanner */ class GDCM_EXPORT Sorter { friend std::ostream& operator<<(std::ostream &_os, const Sorter &s); public: Sorter(); virtual ~Sorter(); /// Typically the output of Directory::GetFilenames() virtual bool Sort(std::vector const & filenames); /// Return the list of filenames as sorted by the specific algorithm used. /// Empty by default (before Sort() is called) const std::vector &GetFilenames() const { return Filenames; } /// Print void Print(std::ostream &os) const; /// UNSUPPORTED FOR NOW bool AddSelect( Tag const &tag, const char *value ); /// Specify a set of tags to be read in during the sort procedure. /// By default this set is empty, in which case the entire image, /// including pixel data, is read in. void SetTagsToRead( std::set const & tags ); /// Set the sort function which compares one dataset to the other typedef bool (*SortFunction)(DataSet const &, DataSet const &); void SetSortFunction( SortFunction f ); virtual bool StableSort(std::vector const & filenames); protected: std::vector Filenames; typedef std::map SelectionMap; std::map Selection; SortFunction SortFunc; std::set TagsToRead; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const Sorter &s) { s.Print( os ); return os; } } // end namespace gdcm #endif //GDCMSORTER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSpacing.cxx000066400000000000000000000070741412732066400234650ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSpacing.h" 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 * http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/fracToBaseK.html * http://docs.sun.com/source/806-3568/ncg_goldberg.html */ /* ** find rational approximation to given real number ** David Eppstein / UC Irvine / 8 Aug 1993 ** ** With corrections from Arno Formella, May 2008 ** ** usage: a.out r d ** r is real number to approx ** d is the maximum denominator allowed ** ** based on the theory of continued fractions ** if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...))) ** then best approximation is found by truncating this series ** (with some adjustments in the last term). ** ** Note the fraction can be recovered as the first column of the matrix ** ( a1 1 ) ( a2 1 ) ( a3 1 ) ... ** ( 1 0 ) ( 1 0 ) ( 1 0 ) ** Instead of keeping the sequence of continued fraction terms, ** we just keep the last partial product of these matrices. */ // return error double frap(double frac[2], double startx, double maxden = 10 ) { long m[2][2]; double x; long ai; x = startx; /* initialize matrix */ m[0][0] = m[1][1] = 1; m[0][1] = m[1][0] = 0; /* loop finding terms until denom gets too big */ while (m[1][0] * ( ai = (long)x ) + m[1][1] <= maxden) { long t; t = m[0][0] * ai + m[0][1]; m[0][1] = m[0][0]; m[0][0] = t; t = m[1][0] * ai + m[1][1]; m[1][1] = m[1][0]; m[1][0] = t; if(x==(double)ai) break; // AF: division by zero x = 1/(x - (double) ai); if(x>(double)0x7FFFFFFF) break; // AF: representation failure } /* now remaining x is between 0 and 1/ai */ /* approx as either 0 or 1/m where m is max that will fit in maxden */ /* first try zero */ //printf("%ld/%ld, error = %e\n", m[0][0], m[1][0], // startx - ((double) m[0][0] / (double) m[1][0])); frac[0] = (double)m[0][0]; frac[1] = (double)m[1][0]; const double error = startx - ((double) m[0][0] / (double) m[1][0]); /* now try other possibility */ ai = ((long)maxden - m[1][1]) / m[1][0]; m[0][0] = m[0][0] * ai + m[0][1]; m[1][0] = m[1][0] * ai + m[1][1]; //printf("%ld/%ld, error = %e\n", m[0][0], m[1][0], // startx - ((double) m[0][0] / (double) m[1][0])); const double error2 = startx - ((double) m[0][0] / (double) m[1][0]); assert( fabs(error) < fabs(error2) ); (void)error2; return error; } Attribute<0x28,0x34> Spacing::ComputePixelAspectRatioFromPixelSpacing(const Attribute<0x28,0x30>& pixelspacing) { Attribute<0x28,0x34> pixelaspectratio; const double ratio = pixelspacing[0] / pixelspacing[1]; // double value = 2.5; // double integral_part; // double frac_part = modf(value, &integral_part); double frac[2]; double error = frap(frac, ratio); (void)error; pixelaspectratio[0] = static_cast(frac[0]); pixelaspectratio[1] = static_cast(frac[1]); return pixelaspectratio; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSpacing.h000066400000000000000000000120621412732066400231030ustar00rootroot00000000000000/*========================================================================= 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 GDCMSPACING_H #define GDCMSPACING_H #include "gdcmTypes.h" #include "gdcmAttribute.h" namespace gdcm { /** It all began with a mail to WG6: Subject: Imager Pixel Spacing vs Pixel Spacing Body: [Apologies for the duplicate post, namely to David Clunie & OFFIS team] I have been trying to understand CP-586 in the following two cases: On the one hand: - DISCIMG/IMAGES/CRIMAGE taken from http://dclunie.com/images/pixelspacingtestimages.zip And on the other hand: - http://gdcm.sourceforge.net/thingies/cr_pixelspacing.dcm If I understand correctly the CP, one is required to use Pixel Spacing for measurement ('true size' print) instead of Imager Pixel Spacing, since the two attributes are present and Pixel Spacing is different from Imager Pixel Spacing. If this is correct, then the test data DISCIMG/IMAGES/CRIMAGE is incorrect. If this is incorrect (ie. I need to use Imager Pixel Spacing), then the display of cr_pixelspacing.dcm for measurement will be incorrect. Could someone please let me know what am I missing here? I could not find any information in any header that would allow me to differentiate those. Thank you for your time, Ref: http://lists.nema.org/scripts/lyris.pl?sub=488573&id=400720477 */ /** * \brief Class for Spacing * \details * See PS 3.3-2008, Table C.7-11b IMAGE PIXEL MACRO ATTRIBUTES Ratio of the vertical size and horizontal size of the pixels in the image specified by a pair of integer values where the first value is the vertical pixel size, and the second value is the horizontal pixel size. Required if the aspect ratio values do not have a ratio of 1:1 and the physical pixel spacing is not specified by Pixel Spacing (0028,0030), or Imager Pixel Spacing (0018,1164) or Nominal Scanned Pixel Spacing (0018,2010), either for the entire Image or per-frame in a Functional Group Macro. See C.7.6.3.1.7. PS 3.3-2008 10.7.1.3 Pixel Spacing Value Order and Valid Values All pixel spacing related attributes shall have non-zero values, except when there is only a single row or column or pixel of data present, in which case the corresponding value may be zero. Ref: http://gdcm.sourceforge.net/wiki/index.php/Imager_Pixel_Spacing */ class GDCM_EXPORT Spacing { public : Spacing(); ~Spacing(); // Here are the list of spacing we support: // (0018,0088) DS [1.500000] # 8,1 Spacing Between Slices // (0018,1164) DS [0.5\0.5 ] # 8,2 Imager Pixel Spacing // (0018,2010) DS [0.664062\0.664062 ] # 18,2 Nominal Scanned Pixel Spacing // (0018,7022) DS [0.125\0.125 ] # 12,2 Detector Element Spacing // (0028,0030) DS [0.25\0.25 ] # 10,2 Pixel Spacing // > (0028,0a02) CS [FIDUCIAL] # 8,1 Pixel Spacing Calibration Type // > (0028,0a04) LO [Used fiducial ] # 14,1 Pixel Spacing Calibration Description // (0028,0034) IS [4\3 ] # 4,2 Pixel Aspect Ratio // (3002,0011) DS [0.8\0.8 ] # 8,2 Image Plane Pixel Spacing // Here is the list of Spacing we do not support: // // // // // // // // // typedef enum { DETECTOR = 0, // (0018,1164) Imager Pixel Spacing MAGNIFIED, // (0018,1114) (IHE Mammo) CALIBRATED, // (0028,0030) Pixel Spacing -> (0028,0a04) Pixel Spacing Calibration Description UNKNOWN } SpacingType; static Attribute<0x28,0x34> ComputePixelAspectRatioFromPixelSpacing(const Attribute<0x28,0x30>& pixelspacing); }; } // end namespace gdcm //----------------------------------------------------------------------------- #endif //GDCMSPACING_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSpectroscopy.cxx000066400000000000000000000011451412732066400245670ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSpectroscopy.h" namespace gdcm {} GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSpectroscopy.h000066400000000000000000000015001412732066400242070ustar00rootroot00000000000000/*========================================================================= 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 GDCMSPECTROSCOPY_H #define GDCMSPECTROSCOPY_H #include "gdcmFile.h" namespace gdcm { /** * \brief Spectroscopy class */ class GDCM_EXPORT Spectroscopy { public: Spectroscopy() = default; private: }; } // end namespace gdcm #endif //GDCMSPECTROSCOPY_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.cxx000066400000000000000000000312161412732066400254710ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSplitMosaicFilter.h" #include "gdcmCSAHeader.h" #include "gdcmAttribute.h" #include "gdcmImageHelper.h" #include "gdcmDirectionCosines.h" #include namespace gdcm { SplitMosaicFilter::SplitMosaicFilter():F(new File),I(new Image) {} SplitMosaicFilter::~SplitMosaicFilter() = default; namespace details { /* * gdcmDataExtra/gdcmSampleData/images_of_interest/MR-sonata-3D-as-Tile.dcm */ 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 y = 0; y < outputdims[1]; ++y) { for(unsigned int z = 0; z < outputdims[2]; ++z) { const size_t outputidx = x + y*outputdims[0] + z*outputdims[0]*outputdims[1]; const size_t inputidx = (x + (z%square)*outputdims[0]) + (y + (z/square)*outputdims[1])*inputdims[0]; output[ outputidx ] = input[ inputidx ]; } } } return true; } 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 y = 0; y < outputdims[1]; ++y) { for(unsigned int z = 0; z < outputdims[2]; ++z) { 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]) + (y + (z/square)*outputdims[1])*inputdims[0]; output[ outputidx ] = input[ inputidx ]; } } } return true; } } void SplitMosaicFilter::SetImage(const Image& image) { I = image; } bool SplitMosaicFilter::GetAcquisitionSize(unsigned int size[2], DataSet const & ds) { bool found = true; /* Dimensions of the acquired frequency /phase data before reconstruction. Multi-valued: frequency rows\frequency columns\phase rows\phase columns. */ Attribute<0x0018, 0x1310> acquisitionMatrix; acquisitionMatrix.SetFromDataSet( ds ); const unsigned short *pMat = acquisitionMatrix.GetValues(); /* The axis of phase encoding with respect to the image. Enumerated Values: ROW phase encoded in rows. COL phase encoded in columns. */ Attribute<0x0018, 0x1312> inPlanePhaseEncodingDirection; inPlanePhaseEncodingDirection.SetFromDataSet( ds ); CSComp val = inPlanePhaseEncodingDirection.GetValue(); std::string dir = val.Trim(); // http://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.8.3.html if( dir == "COL" ) { /* pay attention that size is: { columns , rows } */ // [256\0\0\134] size[0] = pMat[3]; size[1] = pMat[0]; } else if( dir == "ROW" ) { // [0\512\213\0] size[0] = pMat[1]; size[1] = pMat[2]; } else { size[0] = size[1] = 0; } found = size[0] && size[1]; return found; } unsigned int SplitMosaicFilter::GetNumberOfImagesInMosaic( File const & file ) { unsigned int numberOfImagesInMosaic = 0; DataSet const &ds = file.GetDataSet(); CSAHeader csa; const PrivateTag &t1 = csa.GetCSAImageHeaderInfoTag(); if( csa.LoadFromDataElement( ds.GetDataElement( t1 ) ) ) { if( csa.FindCSAElementByName( "NumberOfImagesInMosaic" ) ) { const CSAElement &csael4 = csa.GetCSAElementByName( "NumberOfImagesInMosaic" ); if( !csael4.IsEmpty() ) { Element el4 = {{ 0 }}; el4.Set( csael4.GetValue() ); numberOfImagesInMosaic = el4.GetValue(); } } } // try harder: if( !numberOfImagesInMosaic ) { // Some weird anonymizer remove the private creator but leave the actual element. // oh well, let try harder: // (0019,100a) US 72 # 2,1 NumberOfImagesInMosaic PrivateTag t2 (0x0019,0x0a, "SIEMENS MR HEADER"); if( ds.FindDataElement( t2 ) ) { const DataElement &de = ds.GetDataElement( t2 ); const ByteValue * bv = de.GetByteValue(); if( bv ) { Element el1 = {{0}}; std::istringstream is; is.str( std::string( bv->GetPointer(), bv->GetLength() ) ); el1.Read( is ); numberOfImagesInMosaic = el1.GetValue(); } } } std::vector colrow = ImageHelper::GetDimensionsValue( file ); // try super harder. Pay attention that trailing black image cannot be removed here. if( !numberOfImagesInMosaic ) { unsigned int mosaicSize[2]; if( GetAcquisitionSize(mosaicSize, ds) ) { if( colrow[0] % mosaicSize[0] == 0 && colrow[1] % mosaicSize[1] == 0 ) { numberOfImagesInMosaic = colrow[0] / mosaicSize[0] * colrow[1] / mosaicSize[1]; // MultiFrame will contain trailing empty slices: gdcmWarningMacro( "NumberOfImagesInMosaic was not found. Volume will be padded with black image." ); } else { // assume interpolation: unsigned int mosSize = std::max( mosaicSize[0], mosaicSize[1] ); if( colrow[0] % mosSize == 0 && colrow[1] % mosSize == 0 ) { gdcmDebugMacro( "Matrix Acquisition does not match exactly. Using max value." ); numberOfImagesInMosaic = colrow[0] / mosSize * colrow[1] / mosSize; // MultiFrame will contain trailing empty slices: gdcmWarningMacro( "NumberOfImagesInMosaic was not found. Volume will be padded with black image." ); } else { gdcmErrorMacro( "NumberOfImagesInMosaic cannot be computed from Img Acq: " << mosaicSize[0] << "," << mosaicSize[1] ); } } } } return numberOfImagesInMosaic; } bool SplitMosaicFilter::ComputeMOSAICDimensions( unsigned int dims[3] ) { unsigned int numberOfImagesInMosaic = GetNumberOfImagesInMosaic( GetFile() ); if( !numberOfImagesInMosaic ) { gdcmErrorMacro( "Could not find/compute NumberOfImagesInMosaic" ); return false; } std::vector colrow = ImageHelper::GetDimensionsValue( GetFile() ); dims[0] = colrow[0]; dims[1] = colrow[1]; const unsigned int div = (unsigned int )ceil(sqrt( (double)numberOfImagesInMosaic ) ); dims[0] /= div; dims[1] /= div; dims[2] = numberOfImagesInMosaic; return true; } bool SplitMosaicFilter::ComputeMOSAICSliceNormal( double slicenormalvector[3], bool & inverted ) { CSAHeader csa; DataSet& ds = GetFile().GetDataSet(); double normal[3]; bool snvfound = false; const PrivateTag &t1 = csa.GetCSAImageHeaderInfoTag(); static const char snvstr[] = "SliceNormalVector"; if( csa.LoadFromDataElement( ds.GetDataElement( t1 ) ) ) { if( csa.FindCSAElementByName( snvstr ) ) { const CSAElement &snv_csa = csa.GetCSAElementByName( snvstr ); if( !snv_csa.IsEmpty() ) { const ByteValue * bv = snv_csa.GetByteValue(); const std::string str(bv->GetPointer(), bv->GetLength()); std::istringstream is; is.str( str ); char sep; double *snv = normal; if( is >> snv[0] >> sep >> snv[1] >> sep >> snv[2] ) { snvfound = true; } } } } if( snvfound ) { Attribute<0x20,0x37> iop; iop.SetFromDataSet( ds ); DirectionCosines dc( iop.GetValues() ); double z[3]; dc.Cross (z); const double snv_dot = dc.Dot( normal, z ); if( fabs(1. - snv_dot) < 1e-6 ) { gdcmDebugMacro("Same direction"); inverted = false; } else if( fabs(-1. - snv_dot) < 1e-6 ) { gdcmWarningMacro("SliceNormalVector is opposite direction"); inverted = true; } else { gdcmErrorMacro( "Unexpected normal for SliceNormalVector, dot is: " << snv_dot ); return false; } } for( int i = 0; i < 3; ++i) slicenormalvector[i] = normal[i]; return snvfound; } bool SplitMosaicFilter::ComputeMOSAICSlicePosition( double pos[3], bool ) { CSAHeader csa; DataSet& ds = GetFile().GetDataSet(); MrProtocol mrprot; if( !csa.GetMrProtocol(ds, mrprot) ) return false; MrProtocol::SliceArray sa; bool b = mrprot.GetSliceArray(sa); if( !b ) return false; size_t size = sa.Slices.size(); if( !size ) return false; #if 0 { double z[3]; for( int i = 0; i < size; ++i ) { MrProtocol::Slice & slice = sa.Slices[i]; MrProtocol::Vector3 & p = slice.Position; z[0] = p.dSag; z[1] = p.dCor; z[2] = p.dTra; const double snv_dot = DirectionCosines::Dot( slicenormalvector, z ); if( (1. - snv_dot) < 1e-6 ) { gdcmErrorMacro("Invalid direction found"); return false; } } } #endif size_t index = 0; MrProtocol::Slice & slice = sa.Slices[index]; MrProtocol::Vector3 & p = slice.Position; pos[0] = p.dSag; pos[1] = p.dCor; pos[2] = p.dTra; return true; } bool SplitMosaicFilter::Split() { bool success = true; DataSet& ds = GetFile().GetDataSet(); unsigned int dims[3] = {0,0,0}; if( ! ComputeMOSAICDimensions( dims ) ) { return false; } const unsigned int div = (unsigned int )ceil(sqrt( (double)dims[2]) ); bool inverted; double normal[3]; bool hasOriginCSA = true; bool hasNormalCSA = true; if( !ComputeMOSAICSliceNormal( normal, inverted ) ) { gdcmDebugMacro( "Normal will not be accurate" ); hasNormalCSA = false; } (void)hasNormalCSA; double origin[3]; if( !ComputeMOSAICSlicePosition( origin, inverted ) ) { gdcmWarningMacro( "Origin will not be accurate" ); hasOriginCSA = false; } const Image &inputimage = GetImage(); if( inputimage.GetPixelFormat() != PixelFormat::UINT16 ) { gdcmErrorMacro( "Expecting UINT16 PixelFormat" ); return false; } unsigned long l = inputimage.GetBufferLength(); std::vector buf; buf.resize(l); inputimage.GetBuffer( &buf[0] ); DataElement pixeldata( Tag(0x7fe0,0x0010) ); std::vector outbuf; outbuf.resize(l); bool b; if( inverted ) { b = details::reorganize_mosaic_invert( (unsigned short*)(void*)&buf[0], inputimage.GetDimensions(), div, dims, (unsigned short*)(void*)&outbuf[0] ); } else { b = details::reorganize_mosaic( (unsigned short*)(void*)&buf[0], inputimage.GetDimensions(), div, dims, (unsigned short*)(void*)&outbuf[0] ); } if( !b ) return false; VL::Type outbufSize = (VL::Type)outbuf.size(); pixeldata.SetByteValue( &outbuf[0], outbufSize ); Image &image = GetImage(); const TransferSyntax &ts = image.GetTransferSyntax(); if( ts.IsExplicit() ) { image.SetTransferSyntax( TransferSyntax::ExplicitVRLittleEndian ); } else { image.SetTransferSyntax( TransferSyntax::ImplicitVRLittleEndian ); } image.SetNumberOfDimensions( 3 ); image.SetDimension(0, dims[0] ); image.SetDimension(1, dims[1] ); image.SetDimension(2, dims[2] ); // Fix origin (direction is ok since we reorganize the tiles): if( hasOriginCSA ) image.SetOrigin( origin ); PhotometricInterpretation pi; pi = PhotometricInterpretation::MONOCHROME2; image.SetDataElement( pixeldata ); // Second part need to fix the Media Storage, now that this is not a single slice anymore MediaStorage ms = MediaStorage::SecondaryCaptureImageStorage; ms.SetFromFile( GetFile() ); if( ms == MediaStorage::MRImageStorage ) { // Ok make it a MediaStorage::EnhancedMRImageStorage // ms = MediaStorage::EnhancedMRImageStorage; // // // Remove old MRImageStorage attribute then: // ds.Remove( Tag(0x0020,0x0032) ); // Image Position (Patient) // ds.Remove( Tag(0x0020,0x0037) ); // Image Orientation (Patient) // ds.Remove( Tag(0x0028,0x1052) ); // Rescale Intercept // ds.Remove( Tag(0x0028,0x1053) ); // Rescale Slope // ds.Remove( Tag(0x0028,0x1054) ); // Rescale Type } else { gdcmDebugMacro( "Expecting MRImageStorage" ); return false; } DataElement de( Tag(0x0008, 0x0016) ); const char* msstr = MediaStorage::GetMSString(ms); VL::Type strlenMsstr = (VL::Type)strlen(msstr); de.SetByteValue( msstr, strlenMsstr ); de.SetVR( Attribute<0x0008, 0x0016>::GetVR() ); ds.Replace( de ); return success; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.h000066400000000000000000000055111412732066400251150ustar00rootroot00000000000000/*========================================================================= 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 GDCMSPLITMOSAICFILTER_H #define GDCMSPLITMOSAICFILTER_H #include "gdcmFile.h" #include "gdcmImage.h" namespace gdcm { /* * Everything done in this code is for the sole purpose of writing interoperable * software under Sect. 1201 (f) Reverse Engineering exception of the DMCA. * If you believe anything in this code violates any law or any of your rights, * please contact us (gdcm-developers@lists.sourceforge.net) so that we can * find a solution. */ /** * \brief SplitMosaicFilter class * \details Class to reshuffle bytes for a SIEMENS Mosaic image * Siemens CSA Image Header * CSA:= Common Siemens Architecture, sometimes also known as Common syngo Architecture * * \warning when private attributes are not found, the acquisition matrix is * used to compute the NumberOfImagesInMosaic. This means trailing black slices * will be considered in the volume (instead of discarded). * CSA 0029,1010 is needed for correct NumberOfImagesInMosaic * CSA 0029,1020 is needed to compute the correct origin * without above info default are taken (may not be accurate). */ class GDCM_EXPORT SplitMosaicFilter { public: SplitMosaicFilter(); ~SplitMosaicFilter(); /// Split the SIEMENS MOSAIC image bool Split(); /// Compute the new dimensions according to private information /// stored in the MOSAIC header. bool ComputeMOSAICDimensions(unsigned int dims[3]); /// Extract the value for SliceNormalVector (CSA header) bool ComputeMOSAICSliceNormal( double dims[3], bool & inverted ); /// Extract the value for ImagePositionPatient (requires inverted flag) bool ComputeMOSAICSlicePosition( double pos[3], bool inverted ); void SetImage(const Image& image); const Image &GetImage() const { return *I; } Image &GetImage() { return *I; } void SetFile(const File& f) { F = f; } File &GetFile() { return *F; } const File &GetFile() const { return *F; } /// Get the Acquisition Matrix (non zero value): static bool GetAcquisitionSize(unsigned int size[2], DataSet const & ds); /// Return the value for NumberOfImagesInMosaic, or compute it from Acquisition Size static unsigned int GetNumberOfImagesInMosaic( File const & file ); protected: private: SmartPointer F; SmartPointer I; }; } // end namespace gdcm #endif //GDCMSPLITMOSAICFILTER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmStreamImageReader.cxx000066400000000000000000000404331412732066400254160ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmStreamImageReader.h" #include "gdcmImage.h" #include "gdcmMediaStorage.h" #include "gdcmImageHelper.h" #include "gdcmRAWCodec.h" #include "gdcmJPEGLSCodec.h" #include namespace gdcm { //see http://stackoverflow.com/questions/1448467/initializing-a-c-stdistringstream-from-an-in-memory-buffer/1449527#1449527 struct OneShotReadBuf : public std::streambuf { OneShotReadBuf(void* s, std::size_t n){ char* cast = (char*)s; setg(cast, cast, cast+n); } }; StreamImageReader::StreamImageReader() { //set these values to be the opposite ends of possible, //so that if the extent is not defined, read can fail properly. mXMin = mYMin = mZMin = std::numeric_limits::max(); mXMax = mYMax = mZMax = std::numeric_limits::min(); } StreamImageReader::~StreamImageReader() = default; /// One of either SetFileName or SetStream must be called prior /// to any other functions. void StreamImageReader::SetFileName(const char* inFileName) { mReader.SetFileName(inFileName); } void StreamImageReader::SetStream(std::istream& inStream) { mReader.SetStream(inStream); } std::vector StreamImageReader::GetDimensionsValueForResolution( unsigned int res ) { std::vector extent(3); File &file_t = mReader.GetFile(); DataSet &ds_t = file_t.GetDataSet(); const DataElement &seq = ds_t.GetDataElement( Tag(0x0048,0x0200) ); SmartPointer sqi = seq.GetValueAsSQ(); Item &itemL = sqi->GetItem(res); DataSet &subds_L = itemL.GetNestedDataSet(); const DataElement &brrL = subds_L.GetDataElement( Tag(0x0048,0x0202) ); Element elL1; elL1.SetFromDataElement( brrL ); extent[0] = elL1.GetValue(0); extent[1] = elL1.GetValue(1); extent[2] = res; return extent; } /// Defines an image extent for the Read function. /// DICOM states that an image can have no more than 2^16 pixels per edge (as of 2009) /// In this case, the pixel extents ignore the direction cosines entirely, and /// assumes that the origin of the image is at location 0,0 (regardless of the definition /// in space per the tags). So, if the first 100 pixels of the first row are to be read in, /// this function should be called with DefinePixelExtent(0, 100, 0, 1), regardless /// of pixel size or orientation. void StreamImageReader::DefinePixelExtent(uint16_t inXMin, uint16_t inXMax, uint16_t inYMin, uint16_t inYMax, uint16_t inZMin, uint16_t inZMax){ mXMin = inXMin; mYMin = inYMin; mXMax = inXMax; mYMax = inYMax; mZMin = inZMin; mZMax = inZMax; } /// Paying attention to the pixel format and so forth, define the proper buffer length for the user. /// The return amount is in bytes. /// If the return is 0, then that means that the pixel extent was not defined prior uint32_t StreamImageReader::DefineProperBufferLength() const { if (mXMax < mXMin || mYMax < mYMin || mZMax < mZMin) return 0; PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(mReader.GetFile()); //unsigned short samplesPerPixel = pixelInfo.GetSamplesPerPixel(); int bytesPerPixel = pixelInfo.GetPixelSize(); return (mYMax - mYMin)*(mXMax - mXMin)*(mZMax - mZMin)*bytesPerPixel; } /// Read the DICOM image. There are two reason for failure: /// 1. The extent is not set /// 2. The output buffer is not set /// This method has been implemented to look similar to the metaimageio in itk bool StreamImageReader::Read(char* inReadBuffer, const std::size_t& inBufferLength) { //need to have some kind of extent defined. if (mXMin > mXMax || mYMin > mYMax || mZMin > mZMax) { return false; //for now } // OneShotReadBuf osrb(inReadBuffer, inBufferLength); // std::ostream ostr(&osrb); //put the codec interpretation here // return ReadImageSubregionRAW(ostr); //just do memcpys instead of doing this stream shenanigans return ReadImageSubregionRAW(inReadBuffer, inBufferLength); } /** Read a particular subregion, using the stored mFileOffset as the beginning of the stream. This class reads uncompressed data; other subclasses will reimplement this function for compression. Assumes that the given buffer is the size in bytes returned from DefineProperBufferLength. */ bool StreamImageReader::ReadImageSubregionRAW(char* inReadBuffer, const std::size_t& inBufferLength) { //assumes that the file is organized in row-major format, with each row rastering across assert( mFileOffset != -1 ); (void)inBufferLength; int y, z; std::streamoff theOffset; //need to get the pixel size information //should that come from the header? //most likely that's a tag in the header std::vector extent = ImageHelper::GetDimensionsValue(mReader.GetFile()); PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(mReader.GetFile()); //unsigned short samplesPerPixel = pixelInfo.GetSamplesPerPixel(); int bytesPerPixel = pixelInfo.GetPixelSize(); int SubRowSize = mXMax - mXMin; int SubColSize = mYMax - mYMin; //set up the codec prior to resetting the file, just in case that affects the way that //files are handled by the ImageHelper const FileMetaInformation &header = mReader.GetFile().GetHeader(); const TransferSyntax &ts = header.GetDataSetTransferSyntax(); bool needbyteswap = (ts == TransferSyntax::ImplicitVRBigEndianPrivateGE); RAWCodec theCodec; if( !theCodec.CanDecode(ts) ) { JPEGLSCodec theJpegLSCodec; if (!theJpegLSCodec.CanDecode(ts)) { gdcmDebugMacro( "Raw Codec cannot decode this file by streaming." ); return false; } else { //read in the entire file for jpegls //right now, it needs to be read entirely off of disk first //kind of a shame, but it's the way it is now mReader.Read(); } } theCodec.SetNeedByteSwap( needbyteswap ); theCodec.SetDimensions(ImageHelper::GetDimensionsValue(mReader.GetFile())); theCodec.SetPlanarConfiguration( ImageHelper::GetPlanarConfigurationValue(mReader.GetFile())); theCodec.SetPhotometricInterpretation( ImageHelper::GetPhotometricInterpretationValue(mReader.GetFile())); //how do I handle byte swapping here? where is it set? //have to reset the stream to the proper position //first, reopen the stream,then the loop should set the right position //mReader.SetFileName(mReader.GetFileName().c_str()); std::istream* theStream = mReader.GetStreamPtr();//probably going to need a copy of this //to ensure thread safety; if the stream ptr handler gets used simultaneously by different threads, //that would be BAD //tmpBuffer is for a single raster char* tmpBuffer = new char[SubRowSize*bytesPerPixel]; char* tmpBuffer2 = new char[SubRowSize*bytesPerPixel]; try { for (z = mZMin; z < mZMax; ++z) { #if 0 theStream->seekg(std::ios::beg); if(mFileOffset1 == 0) { mFileOffset1 = mFileOffset; for(int j = 1; j<=z; j++) { std::vector extent = GetDimensionsValueForResolution(j); mFileOffset1 = mFileOffset1 + (int)((extent[1])*(extent[0])*bytesPerPixel); mFileOffset1 = mFileOffset1 + 4*sizeof(uint16_t); } } else { mFileOffset1 = mFileOffset; } std::vector extent = GetDimensionsValueForResolution(z+1); #endif for (y = mYMin; y < mYMax; ++y) { #if 0 theOffset = mFileOffset1 + (y*(int)(extent[0]) + mXMin)*bytesPerPixel; #else theStream->seekg(std::ios::beg); theOffset = mFileOffset + (z * (int)(extent[1]*extent[0]) + y*(int)extent[0] + mXMin)*bytesPerPixel; #endif theStream->seekg(theOffset); theStream->read(tmpBuffer, SubRowSize*bytesPerPixel); //now, convert that buffer. if (!theCodec.DecodeBytes(tmpBuffer, SubRowSize*bytesPerPixel, tmpBuffer2, SubRowSize*bytesPerPixel)) { delete [] tmpBuffer; delete [] tmpBuffer2; return false; } //this next line may require a bit of finagling... //std::copy(tmpBuffer2, &(tmpBuffer2[SubRowSize*bytesPerPixel]), std::ostream_iterator(os)); //make sure to have a test that will test different x, y, and z mins and maxes memcpy(&(inReadBuffer[((z-mZMin)*SubRowSize*SubColSize + (y-mYMin)*SubRowSize)// + mXMin)//shouldn't need mXMin *bytesPerPixel]), tmpBuffer2, SubRowSize*bytesPerPixel); } #if 0 if((mYMax == extent[1]) && (mXMax == extent[0])) { mFileOffset1 = mFileOffset1 + (int)((extent[1])*(extent[0])*bytesPerPixel) + 4*sizeof(uint16_t); } #endif } #if 0 mFileOffset = mFileOffset1; #endif } catch (std::exception & ex) { (void)ex; gdcmWarningMacro( "Failed to read with ex:" << ex.what() ); delete [] tmpBuffer; delete [] tmpBuffer2; return false; } catch (...) { gdcmWarningMacro( "Failed to read with unknown error." ); delete [] tmpBuffer; delete [] tmpBuffer2; return false; } delete [] tmpBuffer; delete [] tmpBuffer2; return true; } /** This class reads via the jpegls codec. Due to limitations in that codec, the entire file must be read into memory before a subregion can be decoded. */ bool StreamImageReader::ReadImageSubregionJpegLS(char* inReadBuffer, const std::size_t& inBufferLength) { //assumes that the file is organized in row-major format, with each row rastering across //don't need to get all the other stuff (ie, the file offset) since we have to read it all in anyway //set up the codec prior to resetting the file, just in case that affects the way that //files are handled by the ImageHelper const FileMetaInformation &header = mReader.GetFile().GetHeader(); const TransferSyntax &ts = header.GetDataSetTransferSyntax(); bool needbyteswap = (ts == TransferSyntax::ImplicitVRBigEndianPrivateGE); JPEGLSCodec theCodec; if (!theCodec.CanDecode(ts)) { gdcmDebugMacro( "JpegLS cannot read this." ); return false; } //read in the entire file for jpegls //right now, it needs to be read entirely off of disk first //kind of a shame, but it's the way it is now mReader.Read(); theCodec.SetNeedByteSwap( needbyteswap ); theCodec.SetDimensions(ImageHelper::GetDimensionsValue(mReader.GetFile())); theCodec.SetPlanarConfiguration(ImageHelper::GetPlanarConfigurationValue(mReader.GetFile())); theCodec.SetPhotometricInterpretation(ImageHelper::GetPhotometricInterpretationValue(mReader.GetFile())); try { DataSet ds = mReader.GetFile().GetDataSet(); Tag thePixelDataTag(0x7fe0, 0x0010); DataElement de = ds.GetDataElement(thePixelDataTag); theCodec.Decode(de, inReadBuffer, inBufferLength, mXMin, mXMax, mYMin, mYMax, mZMin, mZMax); } catch (std::exception & ex){ (void)ex; gdcmWarningMacro( "Failed to read with ex:" << ex.what() ); return false; } catch (...){ gdcmWarningMacro( "Failed to read with unknown error." ); return false; } return true; } /// Set the spacing and dimension information for the set filename. /// returns false if the file is not initialized or not an image, /// with the pixel 0x7fe0, 0x0010 tag. bool StreamImageReader::ReadImageInformation() { //read up to the point in the stream where the pixel information tag is //store that location and keep the rest of the data as the header information dataset std::set theSkipTags; Tag thePixelDataTag(0x7fe0, 0x0010);//must be LESS than the pixel information tag, 0x7fe0,0x0010 //otherwise, it'll read that tag as well. //make a reader object in readimageinformation //call read up to tag //then create data structures from that dataset that's been read-up-to theSkipTags.insert(thePixelDataTag); try { //ok, need to read up until I know what kind of endianness i'm dealing with? if (!mReader.ReadUpToTag(thePixelDataTag, theSkipTags)) { gdcmWarningMacro("Failed to read tags in the gdcm stream image reader."); return false; } #if 0 std::streampos shift = 4*sizeof(uint16_t)+2*sizeof(uint32_t); mFileOffset = mReader.GetStreamPtr()->tellg()+ shift; mFileOffset1 = 0; #else mFileOffset = mReader.GetStreamPtr()->tellg(); #endif } catch(std::exception & ex) { (void)ex; gdcmWarningMacro( "Failed to read with ex:" << ex.what() ); return false; } catch(...) { gdcmWarningMacro( "Failed to read with unknown error" ); return false; } // eg. ELSCINT1_PMSCT_RLE1.dcm if( mFileOffset == -1 ) return false; // postcondition assert( mFileOffset != -1 ); const File &file_t = mReader.GetFile(); const DataSet &ds_t = file_t.GetDataSet(); MediaStorage ms; ms.SetFromFile(file_t); if( ms == MediaStorage::VLWholeSlideMicroscopyImageStorage ) { if( !ds_t.FindDataElement( Tag(0x0048,0x0200) ) ) { gdcmWarningMacro( "error occurred in WSI File read" ); return false; } DataElement seq = ds_t.GetDataElement( Tag(0x0048,0x0200) ); SmartPointer sqi = seq.GetValueAsSQ(); SequenceOfItems::SizeType s = sqi->GetNumberOfItems(); Item itemL = sqi->GetItem(1); DataSet &subds_L = itemL.GetNestedDataSet(); if( !subds_L.FindDataElement( Tag(0x0008,0x1160) ) ) { gdcmWarningMacro( "Error occurred during WSI File Read" ); return false; } DataElement rfnL = subds_L.GetDataElement( Tag(0x0008,0x1160) ); Element elL; elL.SetFromDataElement( rfnL ); if( !subds_L.FindDataElement( Tag(0x0048,0x0202) ) ) { gdcmWarningMacro( "Error During WSI File Read" ); return false; } DataElement brrL = subds_L.GetDataElement( Tag(0x0048,0x0202) ); Element elL1; elL1.SetFromDataElement( brrL ); Item itemH = sqi->GetItem(s); DataSet &subds_H = itemH.GetNestedDataSet(); if( !subds_H.FindDataElement( Tag(0x0008,0x1160) ) ) { gdcmWarningMacro( "Error occurred during WSI File Read" ); return false; } DataElement rfnH = subds_H.GetDataElement( Tag(0x0008,0x1160) ); Element elH; elH.SetFromDataElement( rfnH ); if( !subds_H.FindDataElement( Tag(0x0048,0x0202) ) ) { gdcmWarningMacro( "Error During WSI File Read" ); return false; } DataElement brrH = subds_H.GetDataElement( Tag(0x0048,0x0202) ); Element elH1; elH1.SetFromDataElement( brrH ); } return true; } bool StreamImageReader::CanReadImage() const { //this is the check to ensure that ReadImageInformation was read in properly if (mFileOffset == -1) { return false; } const FileMetaInformation &header = mReader.GetFile().GetHeader(); const TransferSyntax &ts = header.GetDataSetTransferSyntax(); //bool needbyteswap = (ts == TransferSyntax::ImplicitVRBigEndianPrivateGE); RAWCodec theCodec; bool canDecodeRaw = theCodec.CanDecode(ts); if (!canDecodeRaw) return false; std::vector extent = ImageHelper::GetDimensionsValue(mReader.GetFile()); if (extent.empty()) return false; //should not happen with current GetDimensionsValue implementation //but just in case... if (extent[0] == 0 || extent[1] == 0) return false; return true; } /// Returns the dataset read by ReadImageInformation /// Couple this with the ImageHelper to get statistics about the image, /// like pixel extent, to be able to initialize buffers for reading File const &StreamImageReader::GetFile() const { if (mFileOffset > 0) { /// mFileOffset1 = 0; return mReader.GetFile(); } else { assert(0); return mReader.GetFile(); } } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmStreamImageReader.h000066400000000000000000000126251412732066400250450ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMSTREAMIMAGEREADER_H #define GDCMSTREAMIMAGEREADER_H #include "gdcmReader.h" namespace gdcm { class MediaStorage; /** * \brief StreamImageReader * \note its role is to convert the DICOM DataSet into a Image * representation via an ITK streaming (ie, multithreaded) interface * Image is different from Pixmap has it has a position and a direction in * Space. * Currently, this class is thread safe in that it can read a single extent * in a single thread. Multiple versions can be used for multiple extents/threads. * * \see Image */ class GDCM_EXPORT StreamImageReader { public: StreamImageReader(); virtual ~StreamImageReader(); /// One of either SetFileName or SetStream must be called prior /// to any other functions. These initialize an internal Reader class /// to be able to get non-pixel image information. void SetFileName(const char* inFileName); void SetStream(std::istream& inStream); std::vector GetDimensionsValueForResolution( unsigned int ); /// Defines an image extent for the Read function. /// DICOM states that an image can have no more than 2^16 pixels per edge (as of 2009) /// In this case, the pixel extents ignore the direction cosines entirely, and /// assumes that the origin of the image is at location 0,0 (regardless of the definition /// in space per the tags). So, if the first 100 pixels of the first row are to be read in, /// this function should be called with DefinePixelExtent(0, 100, 0, 1), regardless /// of pixel size or orientation. void DefinePixelExtent(uint16_t inXMin, uint16_t inXMax, uint16_t inYMin, uint16_t inYMax, uint16_t inZMin = 0, uint16_t inZMax = 1); /// Paying attention to the pixel format and so forth, define the proper buffer length for the user. /// The return amount is in bytes. Call this function to determine the size of the char* buffer /// that will need to be passed in to ReadImageSubregion(). /// If the return is 0, then that means that the pixel extent was not defined prior uint32_t DefineProperBufferLength() const; /// Read the DICOM image. There are three reasons for failure: /// 1. The extent is not set /// 2. the conversion from char* to std::ostream (internally) fails /// 3. the given buffer isn't large enough to accommodate the desired pixel extent. /// This method has been implemented to look similar to the metaimageio in itk /// MUST have an extent defined, or else Read will return false. /// If no particular extent is required, use ImageReader instead. bool Read(char* inReadBuffer, const std::size_t& inBufferLength); /// Only RAW images are currently readable by the stream reader. As more /// streaming codecs are added, then this function will be updated to reflect /// those changes. Calling this function prior to reading will ensure that /// only streamable files are streamed. Make sure to call ReadImageInformation /// prior to calling this function. bool CanReadImage() const; /// Set the spacing and dimension information for the set filename. /// returns false if the file is not initialized or not an image, /// with the pixel (7fe0,0010) tag. virtual bool ReadImageInformation(); /// Returns the dataset read by ReadImageInformation /// Couple this with the ImageHelper to get statistics about the image, /// like pixel extent, to be able to initialize buffers for reading File const & GetFile() const; protected: private: //contains a reader for being able to ReadUpToTag //however, we don't want the user to be able to call Read //either directly or via a parent class call, so we hide the reader in here. Reader mReader; std::streamoff mFileOffset; //the file offset for getting header information #if 0 std::streamoff mFileOffset1; #endif DataSet mHeaderInformation; //all the non-pixel information //for thread safety, these should not be stored here, but should be used //for every read subregion operation. uint16_t mXMin, mYMin, mXMax, mYMax, mZMin, mZMax; /// Using the min, max, etc set by DefinePixelExtent, this will fill the given buffer /// Make sure to call DefinePixelExtent and to initialize the buffer with the /// amount given by DefineProperBufferLength prior to calling this. /// reads by the RAW codec; other codecs are added once implemented bool ReadImageSubregionRAW(char* inReadBuffer, const std::size_t& inBufferLength); /// Reads the file via JpegLS. The JpegLS codec, as of this writing, requires that the /// entire file be read in in order to decode a subregion, so that's what's done here. bool ReadImageSubregionJpegLS(char* inReadBuffer, const std::size_t& inBufferLength); }; } // end namespace gdcm #endif //GDCMSTREAMIMAGEREADER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmStreamImageWriter.cxx000066400000000000000000000414751412732066400254770ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmStreamImageWriter.h" #include "gdcmTag.h" #include "gdcmMediaStorage.h" #include #include "gdcmImageHelper.h" #include "gdcmRAWCodec.h" namespace gdcm { StreamImageWriter::StreamImageWriter():mspFile(new File) { //set these values to be the opposite ends of possible, //so that if the extent is not defined, read can fail properly. mXMin = mYMin = mZMin = std::numeric_limits::max(); mXMax = mYMax = mZMax = std::numeric_limits::min(); mElementOffsets = 0; mElementOffsets1 = 0; } StreamImageWriter::~StreamImageWriter() { } /// One of either SetFileName or SetStream must be called prior /// to any other functions. void StreamImageWriter::SetFileName(const char* inFileName){ mWriter.SetFileName(inFileName); mElementOffsets = 0;//changing to a new file, should make sure that we're starting again } void StreamImageWriter::SetStream(std::ostream& inStream){ mWriter.SetStream(inStream); } /// Defines an image extent for the Read function. /// DICOM states that an image can have no more than 2^16 pixels per edge (as of 2009) /// In this case, the pixel extents ignore the direction cosines entirely, and /// assumes that the origin of the image is at location 0,0 (regardless of the definition /// in space per the tags). So, if the first 100 pixels of the first row are to be read in, /// this function should be called with DefinePixelExtent(0, 100, 0, 1), regardless /// of pixel size or orientation. void StreamImageWriter::DefinePixelExtent(uint16_t inXMin, uint16_t inXMax, uint16_t inYMin, uint16_t inYMax, uint16_t inZMin, uint16_t inZMax){ mXMin = inXMin; mYMin = inYMin; mXMax = inXMax; mYMax = inYMax; mZMin = inZMin; mZMax = inZMax; } /// Read the DICOM image. There are two reason for failure: /// 1. The extent is not set /// 2. The output buffer is not set /// This method has been implemented to look similar to the metaimageio in itk bool StreamImageWriter::Write(void* inReadBuffer, const std::size_t& inBufferLength){ //need to have some kind of extent defined. if (mXMin > mXMax || mYMin > mYMax || mZMin > mZMax) return false; //for now // OneShotReadBuf osrb(inReadBuffer, inBufferLength); // std::ostream ostr(&osrb); //put the codec interpretation here // return ReadImageSubregionRAW(ostr); //just do memcpys instead of doing this stream shenanigans return WriteImageSubregionRAW((char*)inReadBuffer, inBufferLength); } /// Paying attention to the pixel format and so forth, define the proper buffer length for the user. /// The return amount is in bytes. /// If the return is 0, then that means that the pixel extent was not defined prior /// this return is for RAW inputs which are then encoded by the writer, but are used /// to ensure that the writer gets the proper buffer size uint32_t StreamImageWriter::DefineProperBufferLength() { if (mXMax < mXMin || mYMax < mYMin || mZMax < mZMin) return 0; PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(mWriter.GetFile()); //unsigned short samplesPerPixel = pixelInfo.GetSamplesPerPixel(); int bytesPerPixel = pixelInfo.GetPixelSize(); return (mYMax - mYMin)*(mXMax - mXMin)*(mZMax - mZMin)*bytesPerPixel; } /// when writing a raw file, we know the full extent, and can just write the first /// 12 bytes out (the tag, the VR, and the size) /// when we do compressed files, we'll do it in chunks, as described in /// 2009-3, part 5, Annex A, section 4. /// Pass the raw codec so that in the rare case of a bigendian explicit raw, /// the first 12 bytes written out should still be kosher. /// returns -1 if there's any failure, or the complete offset (12 bytes) /// if it works. Those 12 bytes are then added to the position in order to determine /// where to write. int StreamImageWriter::WriteRawHeader(RAWCodec* inCodec, std::ostream* inStream) { //if this is the first time writing the file out, then //the first few header bytes need to be written out; the tags, the length, etc //that information is found at 2009, section 5, annex A, table 4-1 and 4-2 //for now, just writing out straight raw, which means that the first 12 bytes are //07fe, 0010, OB, 00, 32 bit length //and must be written in little endian (for now-- could do big endian raw, but not atm) //so, we set those 12 bytes up, send them through the codec, and then write them directly to disk //because this is raw, we know exactly the size that will be written. So, let's do that. if(mElementOffsets == 0) { uint16_t firstTag = 0x7fe0; uint16_t secondTag = 0x0010; //uint16_t thirdTag = 0x4f42; uint16_t thirdTag = 0x424f; // OB uint16_t fourthTag = 0x0000; //uint16_t fourthTag = 0x0000; uint32_t fifthTag = 0xffffffff; uint16_t sixthTag = 0xfffe; uint16_t seventhTag = 0xe000; uint32_t eightthTag = 0x00000000; const int theBufferSize = 4*sizeof(uint16_t)+sizeof(uint32_t)+2*sizeof(uint16_t)+sizeof(uint32_t); char* tmpBuffer1 = new char[theBufferSize]; memcpy(&(tmpBuffer1[0]), &firstTag, sizeof(uint16_t)); memcpy(&(tmpBuffer1[sizeof(uint16_t)]), &secondTag, sizeof(uint16_t)); memcpy(&(tmpBuffer1[2*sizeof(uint16_t)]), &thirdTag, sizeof(uint16_t)); memcpy(&(tmpBuffer1[3*sizeof(uint16_t)]), &fourthTag, sizeof(uint16_t)); //Addition by Manoj memcpy(&(tmpBuffer1[4*sizeof(uint16_t)]), &fifthTag, sizeof(uint32_t));// Data Element Length 4 bytes // Basic OffSet Tabl with No Item Value memcpy(&(tmpBuffer1[4*sizeof(uint16_t)+sizeof(uint32_t)]), &sixthTag, sizeof(uint16_t)); //fffe memcpy(&(tmpBuffer1[5*sizeof(uint16_t)+sizeof(uint32_t)]), &seventhTag, sizeof(uint16_t));//e000 memcpy(&(tmpBuffer1[6*sizeof(uint16_t)+sizeof(uint32_t)]), &eightthTag, sizeof(uint32_t));//00000000H assert( inStream && *inStream && !inStream->eof() && inStream->good() ); inStream->write(tmpBuffer1, theBufferSize); inStream->flush(); assert( inStream && *inStream ); } uint16_t NinthTag = 0xfffe; uint16_t TenthTag = 0xe000; std::vector extent = ImageHelper::GetDimensionsValue(mWriter.GetFile()); PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(mWriter.GetFile()); int bytesPerPixel = pixelInfo.GetPixelSize(); uint32_t sizeTag = extent[0]*extent[1]*extent[2]*bytesPerPixel; const int theBufferSize1 = 2*sizeof(uint16_t)+sizeof(uint32_t); char* tmpBuffer3 = new char[theBufferSize1]; char* tmpBuffer4 = new char[theBufferSize1]; // std::streamoff theOffset; try { //First Fragment (Single Frame) of Pixel Data memcpy(&(tmpBuffer3[0]), &NinthTag, sizeof(uint16_t)); //fffe memcpy(&(tmpBuffer3[sizeof(uint16_t)]), &TenthTag, sizeof(uint16_t)); //e000 memcpy(&(tmpBuffer3[2*sizeof(uint16_t)]), &sizeTag, sizeof(uint32_t));//Item Length //run that through the codec if (!inCodec->DecodeBytes(tmpBuffer3, theBufferSize1, tmpBuffer4, theBufferSize1)){ delete [] tmpBuffer3; gdcmErrorMacro( "Problems in Header" ); delete [] tmpBuffer4; return -1; } //write that chunk to the end of the file, ie, this function //requires that it be called with a stream in append mode // inStream->seekp(std::ios::beg); // theOffset = mFileOffset; // inStream->seekp(theOffset); assert( inStream && *inStream && !inStream->eof() && inStream->good() ); inStream->write(tmpBuffer4, theBufferSize1); inStream->flush(); assert( inStream && *inStream ); } catch(...){ delete [] tmpBuffer3; delete [] tmpBuffer4; return -1; } delete [] tmpBuffer3; delete [] tmpBuffer4; return sizeTag; } /** Read a particular subregion, using the stored mFileOffset as the beginning of the stream. This class reads uncompressed data; other subclasses will reimplement this function for compression. Assumes that the given buffer is the size in bytes returned from DefineProperBufferLength. */ bool StreamImageWriter::WriteImageSubregionRAW(char* inWriteBuffer, const std::size_t& inBufferLength) { (void)inBufferLength; //assumes that the file is organized in row-major format, with each row rastering across // assert( mFileOffset != -1 ); int y, z; // std::streamoff theOffset; //need to get the pixel size information //should that come from the header? //most likely that's a tag in the header std::vector extent = ImageHelper::GetDimensionsValue(mWriter.GetFile()); PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(mWriter.GetFile()); //unsigned short samplesPerPixel = pixelInfo.GetSamplesPerPixel(); int bytesPerPixel = pixelInfo.GetPixelSize(); int SubRowSize = mXMax - mXMin; int SubColSize = mYMax - mYMin; //set up the codec prior to resetting the file, just in case that affects the way that //files are handled by the ImageHelper const FileMetaInformation &header = mWriter.GetFile().GetHeader(); const TransferSyntax &ts = header.GetDataSetTransferSyntax(); bool needbyteswap = (ts == TransferSyntax::ImplicitVRBigEndianPrivateGE); RAWCodec theCodec; if( !theCodec.CanDecode(ts) || ts == TransferSyntax::ExplicitVRBigEndian) { gdcmErrorMacro( "Only RAW for now" ); return false; } theCodec.SetNeedByteSwap( needbyteswap ); theCodec.SetDimensions(ImageHelper::GetDimensionsValue(mWriter.GetFile())); theCodec.SetPlanarConfiguration( ImageHelper::GetPlanarConfigurationValue(mWriter.GetFile())); theCodec.SetPhotometricInterpretation( ImageHelper::GetPhotometricInterpretationValue(mWriter.GetFile())); //how do I handle byte swapping here? where is it set? //have to reset the stream to the proper position //first, reopen the stream,then the loop should set the right position //MM: you have to reopen the stream, by default, the writer closes it each time it writes. // mWriter.SetFileName(mWriter.GetFileName().c_str(), true);//open in file append mode std::ostream* theStream = mWriter.GetStreamPtr();//probably going to need a copy of this //to ensure thread safety; if the stream ptr handler gets used simultaneously by different threads, //that would be BAD //tmpBuffer is for a single raster assert( theStream && *theStream ); char* tmpBuffer = new char[SubRowSize*bytesPerPixel]; char* tmpBuffer2 = new char[SubRowSize*bytesPerPixel]; try { if (mElementOffsets == 0 || mElementOffsets1 ==0 ){ mElementOffsets = WriteRawHeader(&theCodec, theStream); mElementOffsets1 = mElementOffsets; } if (mElementOffsets < 0){//something broke during writing gdcmErrorMacro( "Broke" ); delete [] tmpBuffer; delete [] tmpBuffer2; return false; } //only need to seek to the location once, and then write sequentially //may be trickier with compressed images, but should work for RAW // theStream->seekp(std::ios::end); //seeking to the end should be sufficient, if we're guaranteed to get chunks in order // theOffset = mFileOffset + (mZMin * (int)(extent[1]*extent[0]) + mYMin*(int)extent[0] + mXMin)*bytesPerPixel + mElementOffsets; // theStream->seekp(mElementOffsets); for (z = mZMin; z < mZMax; ++z){ for (y = mYMin; y < mYMax; ++y){ //this next line may require a bit of finagling... //std::copy(tmpBuffer2, &(tmpBuffer2[SubRowSize*bytesPerPixel]), std::ostream_iterator(os)); //make sure to have a test that will test different x, y, and z mins and maxes memcpy(tmpBuffer, &(inWriteBuffer[((z-mZMin)*SubRowSize*SubColSize + (y-mYMin)*SubRowSize)// + mXMin)//shouldn't need mXMin *bytesPerPixel]), SubRowSize*bytesPerPixel); if (!theCodec.DecodeBytes(tmpBuffer, SubRowSize*bytesPerPixel, tmpBuffer2, SubRowSize*bytesPerPixel)){ delete [] tmpBuffer; delete [] tmpBuffer2; return false; } //should be appending //assert( theStream && *theStream && !theStream->eof() && theStream->good() ); theStream->write(tmpBuffer2, SubRowSize*bytesPerPixel); theStream->flush(); //assert( theStream && *theStream ); } } } catch (std::exception & ex){ (void)ex; gdcmWarningMacro( "Failed to write with ex:" << ex.what() ); delete [] tmpBuffer; delete [] tmpBuffer2; return false; } catch (...){ gdcmWarningMacro( "Failed to write with unknown error." ); delete [] tmpBuffer; delete [] tmpBuffer2; return false; } delete [] tmpBuffer; delete [] tmpBuffer2; return true; } /// Set the spacing and dimension information for the set filename. /// returns false if the file is not initialized or not an image, /// with the pixel 0x7fe0, 0x0010 tag. bool StreamImageWriter::WriteImageInformation(){ //ok, the writer has a file in it, and so we place the dataset that we're given into //the file File &mFile = *mspFile; mWriter.SetFile(mFile); mElementOffsets = 0;//changing to a new file, should make sure that we're starting again //filename needs to be set prior to this function try { //question! is this file a copy of the file that was given in, or a reference? mFile.GetDataSet().Remove( Tag(0x7fe0,0x0010) ); // FIXME assert( !mFile.GetDataSet().FindDataElement( Tag(0x7fe0,0x0010) ) ); if( !mWriter.Write() )//should write everything BUT the image tag. right? { //assert( 0 );//this assert fires when the image is not writeable, ie, doesn't have //tags 2,3 and 8,18 //if the writer can't write, then this should return false. return false; } //this is where to start writing zeros for the image. //BUT! do we know here if it's compressed for writing out? If so, shouldn't that require forcing //the datasets to be presented sequentially? //at this point, we should be at the end of the dataset, and the pointer should be set to eof //which is good, because otherwise, we have a problem (write is inherited, and I can't easily //do the trick where I return the stream location //no longer really using the mFileLocation anyway, because always appending. /* mWriter.SetFileName(mWriter.GetFileName().c_str());//MM: we must call setfilename in order to open //the stream. Otherwise, the position information will be wrong. std::ostream* theStreamPtr = mWriter.GetStreamPtr(); theStreamPtr->seekp(std::ios::end); mFileOffset = theStreamPtr->tellp(); std::ofstream* theFileStreamPtr = dynamic_cast(theStreamPtr); if (theFileStreamPtr!= NULL){ theFileStreamPtr->close(); } */ } catch(std::exception & ex) { (void)ex; gdcmWarningMacro( "Failed to write with ex:" << ex.what() ); } catch(...) { gdcmWarningMacro( "Failed to write with unknown error" ); } // eg. ELSCINT1_PMSCT_RLE1.dcm // if( mFileOffset == -1 ) return false; // postcondition // assert( mFileOffset != -1 ); return true; } //this function determines if a file can even be written using the streaming writer //unlike the reader, can be called before WriteImageInformation, but must be called //after SetFile. bool StreamImageWriter::CanWriteFile() const { File &mFile = *mspFile; if (mspFile == NULL) { return false; } bool hasTag23 = mFile.GetDataSet().FindDataElement(Tag(0x02,0x03)); bool hasTag818 = mFile.GetDataSet().FindDataElement(Tag(0x08,0x18)); if (!hasTag23 && !hasTag818){ // std::cout << "It is good"; return false; //need both tags to be able to write out to disk } const FileMetaInformation &header = mFile.GetHeader(); const TransferSyntax &ts = header.GetDataSetTransferSyntax(); //std::cout<< ts; RAWCodec theCodec; // bool canDecodeWithRaw = !theCodec.CanDecode(ts); bool canDecodeWithRaw = theCodec.CanDecode(ts); if (!canDecodeWithRaw) { //std::cout << "It is not good"; return false; } return true; } /// Set the image information to be written to disk that is everything but /// the pixel information. Copies the data into a new dataset, except for the pixel element ///This way, writing the image information will just write everything else. void StreamImageWriter::SetFile(const File& inFile) { mspFile = inFile; File &mFile = *mspFile; mWriter.SetFile(mFile); mElementOffsets1 = 0; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmStreamImageWriter.h000066400000000000000000000143051412732066400251140ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMSTREAMIMAGEWRITER_H #define GDCMSTREAMIMAGEWRITER_H #include "gdcmWriter.h" #include #include "gdcmDataSet.h" namespace gdcm { class MediaStorage; class RAWCodec; /** * \brief StreamImageReader * \note its role is to convert the DICOM DataSet into a Image * representation via an ITK streaming (ie, multithreaded) interface * Image is different from Pixmap has it has a position and a direction in * Space. * Currently, this class is threadsafe in that it can read a single extent * in a single thread. Multiple versions can be used for multiple extents/threads. * * \see Image */ class GDCM_EXPORT StreamImageWriter { public: StreamImageWriter(); virtual ~StreamImageWriter(); /// One of either SetFileName or SetStream must be called prior /// to any other functions. These initialize an internal Reader class /// to be able to get non-pixel image information. void SetFileName(const char* inFileName); void SetStream(std::ostream& inStream); /// Defines an image extent for the Read function. /// DICOM states that an image can have no more than 2^16 pixels per edge (as of 2009) /// In this case, the pixel extents ignore the direction cosines entirely, and /// assumes that the origin of the image is at location 0,0 (regardless of the definition /// in space per the tags). So, if the first 100 pixels of the first row are to be read in, /// this function should be called with DefinePixelExtent(0, 100, 0, 1), regardless /// of pixel size or orientation. /// 15 nov 2010: added z dimension, defaults to being 1 plane large void DefinePixelExtent(uint16_t inXMin, uint16_t inXMax, uint16_t inYMin, uint16_t inYMax, uint16_t inZMin = 0, uint16_t inZMax = 1); /// Paying attention to the pixel format and so forth, define the proper buffer length for the user. /// The return amount is in bytes. /// If the return is 0, then that means that the pixel extent was not defined prior /// this return is for RAW inputs which are then encoded by the writer, but are used /// to ensure that the writer gets the proper buffer size uint32_t DefineProperBufferLength(); /// Read the DICOM image. There are three reasons for failure: /// 1. The extent is not set /// 2. the conversion from void* to std::ostream (internally) fails /// 3. the given buffer isn't large enough to accommodate the desired pixel extent. /// This method has been implemented to look similar to the metaimageio in itk /// MUST have an extent defined, or else Read will return false. /// If no particular extent is required, use ImageReader instead. bool Write(void* inWriteBuffer, const std::size_t& inBufferLength); /// Write the header information to disk, and a bunch of zeros for the actual pixel information /// Of course, if we're doing a non-compressed format, that works /// but if it's compressed, we have to force the ordering of chunks that are written. virtual bool WriteImageInformation(); /// This function determines if a file can even be written using the streaming writer /// unlike the reader, can be called before WriteImageInformation, but must be called /// after SetFile. bool CanWriteFile() const; /// Set the image information to be written to disk that is everything but /// the pixel information: (7fe0,0010) PixelData void SetFile(const File& inFile); protected: //contains the PrepareWrite function, which will get the given dataset ready //for writing to disk by manufacturing the header information. //note that if there is a pixel element in the given dataset, that will be removed //during the copy, so that the imagewriter can write everything else out Writer mWriter; //is the offset necessary if we always append? //std::streamoff mFileOffset; //the fileoffset for getting header information SmartPointer mspFile; //all the non-pixel information //for thread safety, these should not be stored here, but should be used //for every read subregion operation. uint16_t mXMin, mYMin, mXMax, mYMax, mZMin, mZMax; /// Using the min, max, etc set by DefinePixelExtent, this will fill the given buffer /// Make sure to call DefinePixelExtent and to initialize the buffer with the /// amount given by DefineProperBufferLength prior to calling this. /// reads by the RAW codec; other codecs are added once implemented //virtual bool ReadImageSubregionRAW(std::ostream& os); virtual bool WriteImageSubregionRAW(char* inWriteBuffer, const std::size_t& inBufferLength); /// when writing a raw file, we know the full extent, and can just write the first /// 12 bytes out (the tag, the VR, and the size) /// when we do compressed files, we'll do it in chunks, as described in /// 2009-3, part 5, Annex A, section 4. /// Pass the raw codec so that in the rare case of a bigendian explicit raw, /// the first 12 bytes written out should still be kosher. /// returns -1 if there's any failure, or the complete offset (12 bytes) /// if it works. Those 12 bytes are then added to the position in order to determine /// where to write. int WriteRawHeader(RAWCodec* inCodec, std::ostream* inStream); /// The result of WriteRawHeader (or another header, when that's implemented) /// This result is saved so that the first N bytes aren't constantly being /// rewritten for each chunk that's passed in. /// For compressed data, the offset table will require rewrites of data. int mElementOffsets; int mElementOffsets1; }; } // end namespace gdcm #endif //GDCMSTREAMIMAGEWRITER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmStrictScanner.cxx000066400000000000000000000326451412732066400246650ustar00rootroot00000000000000/*========================================================================= 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 "gdcmStrictScanner.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 { StrictScanner::~StrictScanner() = default; void StrictScanner::ClearTags() { Tags.clear(); } void StrictScanner::ClearSkipTags() { SkipTags.clear(); } void StrictScanner::AddSkipTag( Tag const & t ) { SkipTags.insert( t ); assert(0); // This is NOT implemented for now } // Warning: API is passing a public tag (no way to specify private tag) void StrictScanner::AddPrivateTag( PrivateTag const & t ) { static const Global &g = GlobalInstance; static const Dicts &dicts = g.GetDicts(); const DictEntry &entry = dicts.GetDictEntry( t ); //std::cout << "Debug: " << entry << std::endl; // 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 ); } } void StrictScanner::AddTag( Tag const & t ) { 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 ) { Tags.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" ); Tags.insert( t ); } } // see gdcmReader.strict.cxx bool StrictReadUpToTag( const char * filename, Tag const & last, std::set const & skiptags ); bool StrictScanner::Scan( Directory::FilenamesType const & filenames ) { this->InvokeEvent( StartEvent() ); // Is there at least one tag ? if( !Tags.empty() || !PrivateTags.empty() ) { //if( filenames.empty() ) return true; // Prepare hash table: Mappings.clear(); Mappings[""]; // 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; if( !Tags.empty() ) { TagsType::const_reverse_iterator it1 = Tags.rbegin(); const Tag & publiclast = *it1; last = publiclast; } if( !PrivateTags.empty() ) { PrivateTagsType::const_reverse_iterator pit1 = PrivateTags.rbegin(); Tag privatelast = *pit1; 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() ); StrictScanner::ProcessPublicTag(sf, filename); //StrictScanner::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 StrictScanner::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"; //const FilenameToValue &mapping = Mappings[*tag]; if( Mappings.find(filename) != Mappings.end() ) { const TagToValue &mapping = GetMapping(filename); TagToValue::const_iterator it = mapping.begin(); for( ; it != mapping.end(); ++it) { const Tag & 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; //if( tag == Tag(0x0020,0x000d) // Study Instance UID : UI // || tag == Tag(0x0020,0x0052) // // || tag == Tag(0x0020,0x000e) ) // Series Instance UID : UI // { // return true; // } return false; } void StrictScanner::PrintTable( std::ostream & os ) const { Directory::FilenamesType::const_iterator file = Filenames.begin(); for(; file != Filenames.end(); ++file) { const char *filename = file->c_str(); assert( filename && *filename ); os << '"' << filename << '"' << "\t"; TagsType::const_iterator tag = Tags.begin(); const TagToValue &mapping = GetMapping(filename); for( ; tag != Tags.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"; } os << "\n"; } } StrictScanner::TagToValue const & StrictScanner::GetMapping(const char *filename) const { // assert( Mappings.find(filename) != Mappings.end() ); assert( filename && *filename ); if( Mappings.find(filename) != Mappings.end() ) return Mappings.find(filename)->second; return Mappings.find("")->second; // dummy file could not be found } bool StrictScanner::IsKey( const char * filename ) const { /* // std::find on contiguous array will operate in 0(n) which is way too slow, assume user is not too dumb... Directory::FilenamesType::const_iterator it = std::find(Filenames.begin(), Filenames.end(), filename); if( it == Filenames.end() ) { gdcmErrorMacro( "The file: " << filename << " was not scanned" ); return false; } */ // Look for the file in Mappings table: assert( filename && *filename ); MappingType::const_iterator it2 = Mappings.find(filename); return it2 != Mappings.end(); } Directory::FilenamesType StrictScanner::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* StrictScanner::GetValue(const char *filename, Tag const &t) const { // \precondition assert( Tags.find( t ) != Tags.end() ); TagToValue const &ftv = GetMapping(filename); if( ftv.find(t) != ftv.end() ) { return ftv.find(t)->second; } return nullptr; } const char *StrictScanner::GetFilenameFromTagToValue(Tag const &t, const char *valueref) const { const char *filenameref = nullptr; if( valueref ) { Directory::FilenamesType::const_iterator file = Filenames.begin(); size_t len = strlen( valueref ); if( len && valueref[ len - 1 ] == ' ' ) { --len; } for(; file != Filenames.end() && !filenameref; ++file) { const char *filename = file->c_str(); const char * value = GetValue(filename, t); if( value && strncmp(value, valueref, len ) == 0 ) { 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 StrictScanner::GetAllFilenamesFromTagToValue(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 = GetValue(filename, t); const std::string value_str = String<>::Trim( value ); if( value_str == valueref_str ) { theReturn.push_back( filename ); } } } return theReturn; } StrictScanner::TagToValue const & StrictScanner::GetMappingFromTagToValue(Tag const &t, const char *valueref) const { return GetMapping( GetFilenameFromTagToValue(t, valueref) ); } StrictScanner::ValuesType StrictScanner::GetValues(Tag const &t) const { ValuesType vt; Directory::FilenamesType::const_iterator file = Filenames.begin(); for(; file != Filenames.end(); ++file) { const char *filename = file->c_str(); TagToValue const &ttv = GetMapping(filename); if( ttv.find(t) != ttv.end() ) { vt.insert( ttv.find(t)->second ); } } return vt; } Directory::FilenamesType StrictScanner::GetOrderedValues(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(); TagToValue const &ttv = GetMapping(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; } void StrictScanner::ProcessPublicTag(StringFilter &sf, const char *filename) { assert( filename ); TagToValue &mapping = Mappings[filename]; const File& file = sf.GetFile(); const FileMetaInformation & header = file.GetHeader(); const DataSet & ds = file.GetDataSet(); TagsType::const_iterator tag = Tags.begin(); for( ; tag != Tags.end(); ++tag ) { if( tag->GetGroup() == 0x2 ) { if( header.FindDataElement( *tag ) ) { //std::string s; DataElement const & de = header.GetDataElement( *tag ); //const ByteValue *bv = de.GetByteValue(); ////assert( VR::IsASCII( vr ) ); //if( bv ) // Hum, should I store an empty string or what ? // { // s = std::string( bv->GetPointer(), bv->GetLength() ); // s.resize( std::min( s.size(), strlen( s.c_str() ) ) ); // } 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( TagToValue::value_type(*tag, value)); } } else { if( ds.FindDataElement( *tag ) ) { //std::string s; DataElement const & de = ds.GetDataElement( *tag ); //const ByteValue *bv = de.GetByteValue(); ////assert( VR::IsASCII( vr ) ); //if( bv ) // Hum, should I store an empty string or what ? // { // s = std::string( bv->GetPointer(), bv->GetLength() ); // s.resize( std::min( s.size(), strlen( s.c_str() ) ) ); // } 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( TagToValue::value_type(*tag, value)); } } } // end for } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmStrictScanner.h000066400000000000000000000151551412732066400243070ustar00rootroot00000000000000/*========================================================================= 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 GDCMSTRICTSCANNER_H #define GDCMSTRICTSCANNER_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 StrictScanner * \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 StrictScanner : public Subject { friend std::ostream& operator<<(std::ostream &_os, const StrictScanner &s); public: StrictScanner():Values(),Filenames(),Mappings() {} ~StrictScanner() 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 (hold 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 TagToValue; //typedef std::map TagToValue; //StringMap; //typedef TagToStringMap TagToValue; typedef TagToValue::value_type TagToValueValueType; /// Add a tag that will need to be read. Those are root level skip tags void AddTag( Tag const & t ); void ClearTags(); // Work in progress do not use: void AddPrivateTag( PrivateTag const & t ); /// Add a tag that will need to be skipped. Those are root level skip tags void AddSkipTag( Tag const & t ); void ClearSkipTags(); /// Start the scan ! bool Scan( Directory::FilenamesType const & filenames ); Directory::FilenamesType const &GetFilenames() const { return Filenames; } /// Print result void Print( std::ostream & os ) const override; void PrintTable( std::ostream & os ) 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 GetValues(Tag const &t) 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 GetOrderedValues(Tag const &t) 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 MappingType; typedef MappingType::const_iterator ConstIterator; ConstIterator Begin() const { return Mappings.begin(); } ConstIterator End() const { return Mappings.end(); } /// Mappings are the mapping from a particular tag to the map, mapping filename to value: MappingType const & GetMappings() const { return Mappings; } /// Get the std::map mapping filenames to value for file 'filename' TagToValue const & GetMapping(const char *filename) const; /// Will loop over all files and return the first file where value match the reference value /// 'valueref' const char *GetFilenameFromTagToValue(Tag const &t, 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 GetAllFilenamesFromTagToValue(Tag const &t, const char *valueref) const; /// See GetFilenameFromTagToValue(). This is simply GetFilenameFromTagToValue followed // by a call to GetMapping() TagToValue const & GetMappingFromTagToValue(Tag const &t, 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* GetValue(const char *filename, Tag const &t) const; /// for wrapped language: instantiate a reference counted object static SmartPointer New() { return new StrictScanner; } protected: void ProcessPublicTag(StringFilter &sf, const char *filename); private: // struct to store all uniq tags in ascending order: typedef std::set< Tag > TagsType; typedef std::set< PrivateTag > PrivateTagsType; std::set< Tag > Tags; std::set< PrivateTag > PrivateTags; std::set< Tag > SkipTags; ValuesType Values; Directory::FilenamesType Filenames; // Main struct that will hold all mapping: MappingType Mappings; double Progress; }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const StrictScanner &s) { s.Print( os ); return os; } } // end namespace gdcm #endif //GDCMSTRICTSCANNER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmStringFilter.cxx000066400000000000000000000364061412732066400245160ustar00rootroot00000000000000/*========================================================================= 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 "gdcmStringFilter.h" #include "gdcmGlobal.h" #include "gdcmElement.h" #include "gdcmByteValue.h" #include "gdcmAttribute.h" #include "gdcmDataSetHelper.h" #include // strtok namespace gdcm { //----------------------------------------------------------------------------- StringFilter::StringFilter():F(new File) { } //----------------------------------------------------------------------------- StringFilter::~StringFilter() = default; void StringFilter::SetDicts(const Dicts &dicts) { (void)dicts; assert(0); // FIXME } std::string StringFilter::ToString(const Tag& t) const { return ToStringPair(t).second; } std::string StringFilter::ToString(const PrivateTag& privTag) const { const DataSet &ds = GetFile().GetDataSet(); const DataElement &de = ds.GetDataElement(privTag); return ToStringPair(de).second; } std::string StringFilter::ToString(const DataElement& de) const { return ToStringPair(de).second; } /* std::string StringFilter::ToMIME64(const Tag& t) const { return ToStringPair(t).second; // base64 streams have to be a multiple of 4 bytes long int encodedLengthEstimate = 2 * bv->GetLength(); encodedLengthEstimate = ((encodedLengthEstimate / 4) + 1) * 4; char *bin = new char[encodedLengthEstimate]; unsigned int encodedLengthActual = static_cast( itksysBase64_Encode( (const unsigned char *) bv->GetPointer(), static_cast< unsigned long>( bv->GetLength() ), (unsigned char *) bin, static_cast< int >( 0 ) )); std::string encodedValue(bin, encodedLengthActual); } */ #define StringFilterCase(type) \ case VR::type: \ { \ Element el; \ if( !de.IsEmpty() ) { \ el.Set( de.GetValue() ); \ if( el.GetLength() ) { \ os << el.GetValue(); \ for(unsigned int i = 1; i < el.GetLength(); ++i) os << "\\" << el.GetValue(i); \ retvalue = os.str(); } } \ } break std::pair StringFilter::ToStringPair(const Tag& t) const { if( t.GetGroup() == 0x2 ) { const FileMetaInformation &header = GetFile().GetHeader(); return ToStringPair(t, header); } else { const DataSet &ds = GetFile().GetDataSet(); return ToStringPair(t, ds); } } std::pair StringFilter::ToStringPair(const DataElement& de) const { const Tag & t = de.GetTag(); if( t.GetGroup() == 0x2 ) { const FileMetaInformation &header = GetFile().GetHeader(); return ToStringPairInternal(de, header); } else { const DataSet &ds = GetFile().GetDataSet(); return ToStringPairInternal(de, ds); } } bool StringFilter::ExecuteQuery(std::string const & query_const, std::string &value ) const { // if( t.GetGroup() == 0x2 ) // { // const FileMetaInformation &header = GetFile().GetHeader(); // return ToStringPair(query_const, header); // } // else { const DataSet &ds = GetFile().GetDataSet(); return ExecuteQuery(query_const, ds, value); } } bool StringFilter::ExecuteQuery(std::string const & query_const, DataSet const &ds, std::string &retvalue ) const { //std::pair ret; static Global &g = Global::GetInstance(); static const Dicts &dicts = g.GetDicts(); static const Dict &pubdict = dicts.GetPublicDict(); char *query = strdup( query_const.c_str() ); const char delim[] = "/"; const char subdelim[] = "[]@='"; char *str1, *str2, *token, *subtoken; char *saveptr1= nullptr, *saveptr2; int j; //bool dicomnativemodel = false;//unused const DataSet *curds = nullptr; const DataElement *curde = nullptr; Tag t; int state = 0; SmartPointer sqi; for (j = 1, str1 = query; state >= 0 ; j++, 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) { subtoken = System::StrTokR(str2, subdelim, &saveptr2); if (subtoken == nullptr) break; //printf(" --> %s\n", subtoken); subtokens.emplace_back(subtoken ); } if( subtokens[0] == "DicomNativeModel" ) { // move to next state assert( state == 0 ); state = 1; curds = &ds; } else if( subtokens[0] == "DicomAttribute" ) { if( state != 1 ) { state = -1; break; } assert( subtokens[1] == "keyword" ); const char *k = subtokens[2].c_str(); /*const DictEntry &dictentry = */pubdict.GetDictEntryByKeyword(k, t); if( !curds->FindDataElement( t ) ) { state = -1; break; } curde = &curds->GetDataElement( t ); } else if( subtokens[0] == "Item" ) { assert( state == 1 ); assert( curde ); assert( subtokens[1] == "number" ); sqi = curde->GetValueAsSQ(); if( !sqi ) { state = -1; break; } Item const &item = sqi->GetItem( atoi( subtokens[2].c_str() ) ); curds = &item.GetNestedDataSet(); } else if( subtokens[0] == "Value" ) { assert( state == 1 ); // move to next state state = 2; assert( subtokens[1] == "number" ); #if !defined(NDEBUG) const ByteValue * const bv = curde->GetByteValue(); (void)bv; assert( bv ); //bv->Print( std::cout << std::endl ); #endif } else { assert( subtokens.size() ); gdcmDebugMacro( "Unhandled token: " << subtokens[0] ); state = -1; } } if( state != 2 ) { free( query ); return false; } free( query ); const DataElement &de = *curde; const DictEntry &entry = pubdict.GetDictEntry(de.GetTag()); const VR &vr_read = de.GetVR(); const VR &vr_dict = entry.GetVR(); if( vr_dict == VR::INVALID ) { // FIXME This is a public element we do not support... return false; } VR vr; // always prefer the vr from the file: if( vr_read == VR::INVALID ) { vr = vr_dict; } else if ( vr_read == VR::UN && vr_dict != VR::INVALID ) // File is explicit, but still prefer vr from dict when UN { vr = vr_dict; } else // cool the file is Explicit ! { vr = vr_read; } if( vr.IsDual() ) // This mean vr was read from a dict entry: { vr = DataSetHelper::ComputeVR(*F,ds, t); } if( vr == VR::UN ) { // this element is not known... return false; } assert( vr != VR::UN && vr != VR::INVALID ); //ret.first = entry.GetName(); if( VR::IsASCII( vr ) ) { assert( vr & VR::VRASCII ); const ByteValue *bv = de.GetByteValue(); if( de.GetVL() ) { assert( bv /*|| bv->IsEmpty()*/ ); retvalue = std::string( bv->GetPointer(), bv->GetLength() ); // Let's remove any trailing \0 : retvalue.resize( std::min( retvalue.size(), strlen( retvalue.c_str() ) ) ); // strlen is guarantee to be lower or equal to ::size() } else { //assert( bv == NULL ); retvalue = ""; // ?? } } else { assert( vr & VR::VRBINARY ); const ByteValue *bv = de.GetByteValue(); if( bv ) { //VM::VMType vm = entry.GetVM();//!!mmr-- can I remove this, or will it mess with the stream? //assert( vm == VM::VM1 ); if( vr.IsDual() ) // This mean vr was read from a dict entry: { vr = DataSetHelper::ComputeVR(GetFile(),ds, t); } std::ostringstream os; switch(vr) { StringFilterCase(AT); StringFilterCase(FL); StringFilterCase(FD); //StringFilterCase(OB); StringFilterCase(OF); //StringFilterCase(OW); StringFilterCase(SL); //StringFilterCase(SQ); StringFilterCase(SS); StringFilterCase(UL); //StringFilterCase(UN); StringFilterCase(US); StringFilterCase(UT); case VR::UN: case VR::US_SS: assert(0); break; case VR::OB: case VR::OW: case VR::OB_OW: case VR::SQ: gdcmWarningMacro( "Unhandled: " << vr << " for tag " << de.GetTag() ); retvalue = ""; break; default: assert(0); break; } } } return true; } std::pair StringFilter::ToStringPair(const Tag& t, DataSet const &ds) const { std::pair ret; if( !ds.FindDataElement(t) ) { gdcmDebugMacro( "DataSet does not contains tag:" ); return ret; } const DataElement &de = ds.GetDataElement( t ); ret = ToStringPairInternal( de, ds ); return ret; } std::pair StringFilter::ToStringPairInternal(const DataElement& de, DataSet const &ds) const { std::pair ret; const Global &g = GlobalInstance; const Dicts &dicts = g.GetDicts(); if( ds.IsEmpty() ) { gdcmDebugMacro( "DataSet is empty or does not contains tag:" ); return ret; } //assert( de.GetTag().IsPublic() ); std::string strowner; const char *owner = nullptr; const Tag &t = de.GetTag(); if( t.IsPrivate() && !t.IsPrivateCreator() ) { strowner = ds.GetPrivateCreator(t); owner = strowner.c_str(); } const DictEntry &entry = dicts.GetDictEntry(de.GetTag(), owner); const VR &vr_read = de.GetVR(); const VR &vr_dict = entry.GetVR(); VR vr; // always prefer the vr from the file: if( vr_read == VR::INVALID && vr_dict != VR::INVALID ) { vr = vr_dict; } else if ( vr_read == VR::UN && vr_dict != VR::INVALID ) // File is explicit, but still prefer vr from dict when UN { vr = vr_dict; } else // cool the file is Explicit ! { vr = vr_read; } if( vr == VR::INVALID ) { // FIXME This is a public element we do not support... gdcmDebugMacro( "DataElement does not specify the VR." ); return ret; } if( vr.IsDual() ) // This mean vr was read from a dict entry: { vr = DataSetHelper::ComputeVR(*F,ds, t); } if( vr == VR::UN ) { // this element is not known... return ret; } assert( vr != VR::UN && vr != VR::INVALID ); //std::cerr << "Found " << vr << " for " << de.GetTag() << std::endl; ret.first = entry.GetName(); if( VR::IsASCII( vr ) ) { assert( vr & VR::VRASCII ); const ByteValue *bv = de.GetByteValue(); if( de.GetVL() ) { assert( bv /*|| bv->IsEmpty()*/ ); ret.second = std::string( bv->GetPointer(), bv->GetLength() ); // Let's remove any trailing \0 : ret.second.resize( std::min( ret.second.size(), strlen( ret.second.c_str() ) ) ); // strlen is guarantee to be lower or equal to ::size() } else { //assert( bv == NULL ); ret.second = ""; // ?? } } else { assert( vr & VR::VRBINARY ); const ByteValue *bv = de.GetByteValue(); if( bv ) { //VM::VMType vm = entry.GetVM();//!!mmr-- can I remove this, or will it mess with the stream? //assert( vm == VM::VM1 ); if( vr.IsDual() ) // This mean vr was read from a dict entry: { vr = DataSetHelper::ComputeVR(GetFile(),ds, t); } std::ostringstream os; std::string retvalue; switch(vr) { StringFilterCase(AT); StringFilterCase(FL); StringFilterCase(FD); //StringFilterCase(OB); StringFilterCase(OF); //StringFilterCase(OW); StringFilterCase(SL); //StringFilterCase(SQ); StringFilterCase(SS); StringFilterCase(UL); //StringFilterCase(UN); StringFilterCase(US); StringFilterCase(UT); case VR::UN: case VR::US_SS: assert(0); break; case VR::OB: case VR::OW: case VR::OB_OW: case VR::SQ: gdcmWarningMacro( "Unhandled: " << vr << " for tag " << de.GetTag() ); ret.second = ""; break; default: assert(0); break; } ret.second = retvalue; } } return ret; } #define FromStringFilterCase(type) \ case VR::type: \ { \ Element el; \ /* el.ReadComputeLength( is ); */ \ el.SetLength( vl ); \ for(unsigned int i = 0; i < vm.GetLength(); ++i) \ { \ if(i) is.get(); \ is >> el.GetValue(i); \ } \ el.Write(os); \ } \ break #if 0 static inline size_t count_backslash(const char *s, size_t len) { assert( s ); size_t c = 0; for(size_t i = 0; i < len; ++i, ++s) { if( *s == '\\' ) { ++c; } } return c; } #endif std::string StringFilter::FromString(const Tag&t, const char * value, size_t len) { if( !value || !len ) return ""; const Global &g = GlobalInstance; const Dicts &dicts = g.GetDicts(); std::string strowner; const char *owner = nullptr; const DataSet &ds = GetFile().GetDataSet(); if( t.IsPrivate() && !t.IsPrivateCreator() ) { strowner = ds.GetPrivateCreator(t); owner = strowner.c_str(); } const DictEntry &entry = dicts.GetDictEntry(t, owner); const VM &vm = entry.GetVM(); //const VR &vr = entry.GetVR(); const DataElement &de = ds.GetDataElement( t ); const VR &vr_read = de.GetVR(); const VR &vr_dict = entry.GetVR(); VR vr; // always prefer the vr from the file: if( vr_read == VR::INVALID ) { vr = vr_dict; } else if ( vr_read == VR::UN && vr_dict != VR::INVALID ) // File is explicit, but still prefer vr from dict when UN { vr = vr_dict; } else // cool the file is Explicit ! { vr = vr_read; } if( vr.IsDual() ) // This mean vr was read from a dict entry: { vr = DataSetHelper::ComputeVR(*F,ds, t); } if( vr == VR::UN ) { // this element is not known... //return ret; } std::string s(value,value+len); if( VR::IsASCII( vr ) ) { return s; } VL::Type castLen = (VL::Type)len; size_t count = VM::GetNumberOfElementsFromArray(value, castLen); VL vl = vm.GetLength() * vr.GetSizeof(); if( vm.GetLength() == 0 ) { // VM1_n vl = (VL)( count * vr.GetSizeof()); #if !defined(NDEBUG) VM check = VM::GetVMTypeFromLength(count, 1); if( vm != VM::VM0 ) assert( vm.Compatible( check ) ); #endif } std::istringstream is; is.str( s ); std::ostringstream os; switch(vr) { FromStringFilterCase(AT); FromStringFilterCase(FL); FromStringFilterCase(FD); //FromStringFilterCase(OB); FromStringFilterCase(OF); //FromStringFilterCase(OW); FromStringFilterCase(SL); //FromStringFilterCase(SQ); FromStringFilterCase(SS); FromStringFilterCase(UL); //FromStringFilterCase(UN); FromStringFilterCase(US); default: gdcmErrorMacro( "Not implemented" ); assert(0); } return os.str(); } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmStringFilter.h000066400000000000000000000055251412732066400241410ustar00rootroot00000000000000/*========================================================================= 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 GDCMSTRINGFILTER_H #define GDCMSTRINGFILTER_H #include "gdcmDataElement.h" #include "gdcmDicts.h" #include "gdcmFile.h" namespace gdcm { /** * \brief StringFilter * \details StringFilter is the class that make gdcm2.x looks more like gdcm1 and transform the binary blob * contained in a DataElement into a string, typically this is a nice feature to have for wrapped language */ class GDCM_EXPORT StringFilter { public: StringFilter(); ~StringFilter(); /// void UseDictAlways(bool) {} /// Allow user to pass in there own dicts void SetDicts(const Dicts &dicts); /// Convert to string the ByteValue contained in a DataElement. The /// DataElement must be coming from the actual DataSet associated with File /// (see SetFile). std::string ToString(const DataElement& de) const; /// Directly from a Tag: std::string ToString(const Tag& t) const; std::string ToString(const PrivateTag& t) const; /// Convert to string the ByteValue contained in a DataElement /// the returned elements are: /// pair.first : the name as found in the dictionary of DataElement /// pari.second : the value encoded into a string (US,UL...) are properly converted std::pair ToStringPair(const DataElement& de) const; /// Directly from a Tag: std::pair ToStringPair(const Tag& t) const; /// Convert to string the char array defined by the pair (value,len) std::string FromString(const Tag&t, const char * value, size_t len); /// Set/Get File void SetFile(const File& f) { F = f; } File &GetFile() { return *F; } const File &GetFile() const { return *F; } /// 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 bool ExecuteQuery(std::string const &query, std::string & value) const; protected: std::pair ToStringPair(const Tag& t, DataSet const &ds) const; bool ExecuteQuery(std::string const &query, DataSet const &ds, std::string & value) const; private: std::pair ToStringPairInternal(const DataElement& de, DataSet const &ds) const; SmartPointer F; }; } // end namespace gdcm #endif //GDCMSTRINGFILTER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSurface.cxx000066400000000000000000000272041412732066400234660ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSurface.h" #include "gdcmCodeString.h" #include "gdcmString.h" #include namespace gdcm { static const char * STATESStrings[] = { "NO", "YES", "UNKNOWN", nullptr }; const char * Surface::GetSTATESString(STATES state) { assert( state <= STATES_END ); return STATESStrings[(int)state]; } Surface::STATES Surface::GetSTATES(const char * state) { if(!state) return STATES_END; // Delete possible space as last character String<> str( state ); str.Trim(); std::string stateClearStr = str.Trim(); const char * stateClear = stateClearStr.c_str(); for(unsigned int i = 0; STATESStrings[i] != nullptr; ++i) { if( strcmp(stateClear, STATESStrings[i]) == 0 ) { return (STATES)i; } } // Ouch ! We did not find anything, that's pretty bad, let's hope that // the toolkit which wrote the image is buggy and tolerate space padded binary // string CodeString codestring = stateClear; std::string cs = codestring.GetAsString(); for(unsigned int i = 0; STATESStrings[i] != nullptr; ++i) { if( strcmp(cs.c_str(), STATESStrings[i]) == 0 ) { return (STATES)i; } } return STATES_END; } static const char * VIEWStrings[] = { "SURFACE", "WIREFRAME", "POINTS", nullptr }; const char * Surface::GetVIEWTypeString(VIEWType type) { assert( type <= VIEWType_END ); return VIEWStrings[(int)type]; } Surface::VIEWType Surface::GetVIEWType(const char * type) { if(!type) return VIEWType_END; // Delete possible space as last character String<> str( type ); str.Trim(); std::string typeClearStr = str.Trim(); const char * typeClear = typeClearStr.c_str(); for(unsigned int i = 0; VIEWStrings[i] != nullptr; ++i) { if( strcmp(typeClear, VIEWStrings[i]) == 0 ) { return (VIEWType)i; } } // Ouch ! We did not find anything, that's pretty bad, let's hope that // the toolkit which wrote the image is buggy and tolerate space padded binary // string CodeString codestring = typeClear; std::string cs = codestring.GetAsString(); for(unsigned int i = 0; VIEWStrings[i] != nullptr; ++i) { if( strcmp(cs.c_str(), VIEWStrings[i]) == 0 ) { return (VIEWType)i; } } return VIEWType_END; } Surface::Surface(): SurfaceNumber(0), SurfaceComments(""), SurfaceProcessing(false), SurfaceProcessingRatio(1.), SurfaceProcessingDescription(""), ProcessingAlgorithm(), RecommendedDisplayGrayscaleValue(0), RecommendedPresentationOpacity(1), RecommendedPresentationType(SURFACE), FiniteVolume(UNKNOWN), Manifold(UNKNOWN), AlgorithmFamily(), AlgorithmVersion(""), AlgorithmName(""), NumberOfSurfacePoints(0), PointCoordinatesData(), PointPositionAccuracy(nullptr), MeanPointDistance(0), MaximumPointDistance(0), PointsBoundingBoxCoordinates(nullptr), AxisOfRotation(nullptr), CenterOfRotation(nullptr), NumberOfVectors(0), VectorDimensionality(0), VectorAccuracy(nullptr), VectorCoordinateData(), Primitive(new MeshPrimitive) { RecommendedDisplayCIELabValue[0] = 0; RecommendedDisplayCIELabValue[1] = 0; RecommendedDisplayCIELabValue[2] = 0; } Surface::~Surface() { if (PointPositionAccuracy != nullptr) delete PointPositionAccuracy; if (PointsBoundingBoxCoordinates != nullptr) delete PointsBoundingBoxCoordinates; if (AxisOfRotation != nullptr) delete AxisOfRotation; if (CenterOfRotation != nullptr) delete CenterOfRotation; if (VectorAccuracy != nullptr) delete VectorAccuracy; } unsigned short Surface::GetRecommendedDisplayGrayscaleValue() const { return RecommendedDisplayGrayscaleValue; } void Surface::SetRecommendedDisplayGrayscaleValue(const unsigned short vl) { RecommendedDisplayGrayscaleValue = vl; } const unsigned short * Surface::GetRecommendedDisplayCIELabValue() const { return &RecommendedDisplayCIELabValue[0]; } unsigned short Surface::GetRecommendedDisplayCIELabValue(const unsigned int idx) const { assert( idx < 3 ); return RecommendedDisplayCIELabValue[idx]; } void Surface::SetRecommendedDisplayCIELabValue(const unsigned short vl[3]) { RecommendedDisplayCIELabValue[0] = vl[0]; RecommendedDisplayCIELabValue[1] = vl[1]; RecommendedDisplayCIELabValue[2] = vl[2]; } void Surface::SetRecommendedDisplayCIELabValue(const unsigned short vl, const unsigned int idx/* = 0*/) { assert( idx < 3 ); RecommendedDisplayCIELabValue[idx] = vl; } void Surface::SetRecommendedDisplayCIELabValue(const std::vector< unsigned short > & vl) { assert( vl.size() > 2 ); RecommendedDisplayCIELabValue[0] = vl[0]; RecommendedDisplayCIELabValue[1] = vl[1]; RecommendedDisplayCIELabValue[2] = vl[2]; } float Surface::GetRecommendedPresentationOpacity() const { return RecommendedPresentationOpacity; } void Surface::SetRecommendedPresentationOpacity(float opacity) { if( (0 <= opacity) && (opacity <= 1) ) { RecommendedPresentationOpacity = opacity; } //else keep default value : 1 } Surface::VIEWType Surface::GetRecommendedPresentationType() const { return RecommendedPresentationType; } void Surface::SetRecommendedPresentationType(VIEWType type) { if( type < VIEWType_END) { RecommendedPresentationType = type; } } unsigned long Surface::GetSurfaceNumber() const { return SurfaceNumber; } void Surface::SetSurfaceNumber(const unsigned long nb) { SurfaceNumber = nb; } const char * Surface::GetSurfaceComments() const { return SurfaceComments.c_str(); } void Surface::SetSurfaceComments(const char * comment) { SurfaceComments = comment; } bool Surface::GetSurfaceProcessing() const { return SurfaceProcessing; } void Surface::SetSurfaceProcessing(bool b) { SurfaceProcessing = b; } float Surface::GetSurfaceProcessingRatio() const { return SurfaceProcessingRatio; } void Surface::SetSurfaceProcessingRatio(const float ratio) { SurfaceProcessingRatio = ratio; } const char * Surface::GetSurfaceProcessingDescription() const { return SurfaceProcessingDescription.c_str(); } void Surface::SetSurfaceProcessingDescription(const char * description) { SurfaceProcessingDescription = description; } SegmentHelper::BasicCodedEntry const & Surface::GetProcessingAlgorithm() const { return ProcessingAlgorithm; } SegmentHelper::BasicCodedEntry & Surface::GetProcessingAlgorithm() { return ProcessingAlgorithm; } void Surface::SetProcessingAlgorithm(SegmentHelper::BasicCodedEntry const & BSE) { ProcessingAlgorithm.CV = BSE.CV; ProcessingAlgorithm.CSD = BSE.CSD; ProcessingAlgorithm.CM = BSE.CM; } Surface::STATES Surface::GetFiniteVolume() const { return FiniteVolume; } void Surface::SetFiniteVolume(STATES state) { assert( state < STATES_END ); FiniteVolume = state; } Surface::STATES Surface::GetManifold() const { return Manifold; } void Surface::SetManifold(STATES state) { assert( state < STATES_END ); Manifold = state; } SegmentHelper::BasicCodedEntry const & Surface::GetAlgorithmFamily() const { return AlgorithmFamily; } SegmentHelper::BasicCodedEntry & Surface::GetAlgorithmFamily() { return AlgorithmFamily; } void Surface::SetAlgorithmFamily(SegmentHelper::BasicCodedEntry const & BSE) { AlgorithmFamily.CV = BSE.CV; AlgorithmFamily.CSD = BSE.CSD; AlgorithmFamily.CM = BSE.CM; } const char * Surface::GetAlgorithmVersion() const { return AlgorithmVersion.c_str(); } void Surface::SetAlgorithmVersion(const char * str) { AlgorithmVersion = str; } const char * Surface::GetAlgorithmName() const { return AlgorithmName.c_str(); } void Surface::SetAlgorithmName(const char * str) { AlgorithmName = str; } unsigned long Surface::GetNumberOfSurfacePoints() const { return NumberOfSurfacePoints; } void Surface::SetNumberOfSurfacePoints(const unsigned long nb) { NumberOfSurfacePoints = nb; } const DataElement & Surface::GetPointCoordinatesData() const { return PointCoordinatesData; } DataElement & Surface::GetPointCoordinatesData() { return PointCoordinatesData; } void Surface::SetPointCoordinatesData(DataElement const & de) { PointCoordinatesData = de; } const float * Surface::GetPointPositionAccuracy() const { return PointPositionAccuracy; } void Surface::SetPointPositionAccuracy(const float * accuracies) { assert(accuracies); if (PointPositionAccuracy == nullptr) PointPositionAccuracy = new float[3]; PointPositionAccuracy[0] = accuracies[0]; PointPositionAccuracy[1] = accuracies[1]; PointPositionAccuracy[2] = accuracies[2]; } float Surface::GetMeanPointDistance() const { return MeanPointDistance; } void Surface::SetMeanPointDistance(float average) { MeanPointDistance = average; } float Surface::GetMaximumPointDistance() const { return MaximumPointDistance; } void Surface::SetMaximumPointDistance(float maximum) { MaximumPointDistance = maximum; } const float * Surface::GetPointsBoundingBoxCoordinates() const { return PointsBoundingBoxCoordinates; } void Surface::SetPointsBoundingBoxCoordinates(const float * coordinates) { assert(coordinates); if (PointsBoundingBoxCoordinates == nullptr) PointsBoundingBoxCoordinates = new float[6]; PointsBoundingBoxCoordinates[0] = coordinates[0]; PointsBoundingBoxCoordinates[1] = coordinates[1]; PointsBoundingBoxCoordinates[2] = coordinates[2]; PointsBoundingBoxCoordinates[3] = coordinates[3]; PointsBoundingBoxCoordinates[4] = coordinates[4]; PointsBoundingBoxCoordinates[5] = coordinates[5]; } const float * Surface::GetAxisOfRotation() const { return AxisOfRotation; } void Surface::SetAxisOfRotation(const float * axis) { assert(axis); if (AxisOfRotation == nullptr) AxisOfRotation = new float[3]; AxisOfRotation[0] = axis[0]; AxisOfRotation[1] = axis[1]; AxisOfRotation[2] = axis[2]; } const float * Surface::GetCenterOfRotation() const { return CenterOfRotation; } void Surface::SetCenterOfRotation(const float * center) { assert(center); if (CenterOfRotation == nullptr) CenterOfRotation = new float[3]; CenterOfRotation[0] = center[0]; CenterOfRotation[1] = center[1]; CenterOfRotation[2] = center[2]; } unsigned long Surface::GetNumberOfVectors() const { return NumberOfVectors; } void Surface::SetNumberOfVectors(const unsigned long nb) { NumberOfVectors = nb; } unsigned short Surface::GetVectorDimensionality() const { return VectorDimensionality; } void Surface::SetVectorDimensionality(const unsigned short dim) { VectorDimensionality = dim; } const float * Surface::GetVectorAccuracy() const { return VectorAccuracy; } void Surface::SetVectorAccuracy(const float * accuracy) { assert(accuracy); if (VectorAccuracy == nullptr) VectorAccuracy = new float[ VectorDimensionality ]; for (unsigned int i = 0; i < VectorDimensionality; ++i) VectorAccuracy[i] = accuracy[i]; } const DataElement & Surface::GetVectorCoordinateData() const { return VectorCoordinateData; } DataElement & Surface::GetVectorCoordinateData() { return VectorCoordinateData; } void Surface::SetVectorCoordinateData(DataElement const & de) { VectorCoordinateData = de; } MeshPrimitive const & Surface::GetMeshPrimitive() const { return *Primitive; } MeshPrimitive & Surface::GetMeshPrimitive() { return *Primitive; } void Surface::SetMeshPrimitive(MeshPrimitive & mp) { Primitive = mp; } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSurface.h000066400000000000000000000171471412732066400231200ustar00rootroot00000000000000/*========================================================================= 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 GDCMSURFACE_H #define GDCMSURFACE_H #include #include #include #include "gdcmSegmentHelper.h" // for BasicCodedEntry namespace gdcm { /** * \brief This class defines a SURFACE IE. * \details This members are taken from required surface mesh module attributes. * * \see PS 3.3 A.1.2.18 , A.57 and C.27 */ class GDCM_EXPORT Surface : public Object { public: typedef enum { NO = 0, YES, UNKNOWN, STATES_END } STATES; static const char * GetSTATESString(STATES state); static STATES GetSTATES(const char * state); /** * \brief Enumeration for Recommended Presentation Type * * \see Tag(0x0066, 0x000D) and PS 3.3 C.27.1.1.3 */ typedef enum { SURFACE = 0, WIREFRAME, POINTS, VIEWType_END } VIEWType; static const char * GetVIEWTypeString(VIEWType type); static VIEWType GetVIEWType(const char * type); Surface(); ~Surface() override; //** Common getters/setters **// unsigned long GetSurfaceNumber() const; void SetSurfaceNumber(const unsigned long nb); const char * GetSurfaceComments() const; void SetSurfaceComments(const char * comment); bool GetSurfaceProcessing() const; void SetSurfaceProcessing(bool b); float GetSurfaceProcessingRatio() const; void SetSurfaceProcessingRatio(const float ratio); const char * GetSurfaceProcessingDescription() const; void SetSurfaceProcessingDescription(const char * description); SegmentHelper::BasicCodedEntry const & GetProcessingAlgorithm() const; SegmentHelper::BasicCodedEntry & GetProcessingAlgorithm(); void SetProcessingAlgorithm(SegmentHelper::BasicCodedEntry const & BSE); unsigned short GetRecommendedDisplayGrayscaleValue() const; void SetRecommendedDisplayGrayscaleValue(const unsigned short vl); const unsigned short * GetRecommendedDisplayCIELabValue() const; unsigned short GetRecommendedDisplayCIELabValue(const unsigned int idx) const; void SetRecommendedDisplayCIELabValue(const unsigned short vl[3]); void SetRecommendedDisplayCIELabValue(const unsigned short vl, const unsigned int idx = 0); void SetRecommendedDisplayCIELabValue(const std::vector< unsigned short > & vl); float GetRecommendedPresentationOpacity() const; void SetRecommendedPresentationOpacity(const float opacity); VIEWType GetRecommendedPresentationType() const; void SetRecommendedPresentationType(VIEWType type); STATES GetFiniteVolume() const; void SetFiniteVolume(STATES state); STATES GetManifold() const; void SetManifold(STATES state); SegmentHelper::BasicCodedEntry const & GetAlgorithmFamily() const; SegmentHelper::BasicCodedEntry & GetAlgorithmFamily(); void SetAlgorithmFamily(SegmentHelper::BasicCodedEntry const & BSE); const char * GetAlgorithmVersion() const; void SetAlgorithmVersion(const char * str); const char * GetAlgorithmName() const; void SetAlgorithmName(const char * str); //** Points getters/setters **// unsigned long GetNumberOfSurfacePoints() const; void SetNumberOfSurfacePoints(const unsigned long nb); const DataElement & GetPointCoordinatesData() const; DataElement & GetPointCoordinatesData(); void SetPointCoordinatesData(DataElement const & de); /** * \note Pointer is null if undefined */ const float * GetPointPositionAccuracy() const; void SetPointPositionAccuracy(const float * accuracies); float GetMeanPointDistance() const; void SetMeanPointDistance(float average); float GetMaximumPointDistance() const; void SetMaximumPointDistance(float maximum); /** * \note Pointer is null if undefined */ const float * GetPointsBoundingBoxCoordinates() const; void SetPointsBoundingBoxCoordinates(const float * coordinates); /** * \note Pointer is null if undefined */ const float * GetAxisOfRotation() const; void SetAxisOfRotation(const float * axis); /** * \note Pointer is null if undefined */ const float * GetCenterOfRotation() const; void SetCenterOfRotation(const float * center); //** Vectors getters/setters **// unsigned long GetNumberOfVectors() const; void SetNumberOfVectors(const unsigned long nb); unsigned short GetVectorDimensionality() const; void SetVectorDimensionality(const unsigned short dim); const float * GetVectorAccuracy() const; void SetVectorAccuracy(const float * accuracy); const DataElement & GetVectorCoordinateData() const; DataElement & GetVectorCoordinateData(); void SetVectorCoordinateData(DataElement const & de); //** Primitive getters/setters **// MeshPrimitive const & GetMeshPrimitive() const; MeshPrimitive & GetMeshPrimitive(); void SetMeshPrimitive(MeshPrimitive & mp); private: //** Common members **// //0066 0003 UL 1 Surface Number unsigned long SurfaceNumber; //0066 0004 LT 1 Surface Comments std::string SurfaceComments; //0066 0009 CS 1 Surface Processing bool SurfaceProcessing; //0066 000a FL 1 Surface Processing Ratio float SurfaceProcessingRatio; //0066 000b LO 1 Surface Processing Description std::string SurfaceProcessingDescription; // Processing Algorithm Code SegmentHelper::BasicCodedEntry ProcessingAlgorithm; //0062 000c US 1 Recommended Display Grayscale Value unsigned short RecommendedDisplayGrayscaleValue; //0062 000d US 3 Recommended Display CIELab Value unsigned short RecommendedDisplayCIELabValue[3]; // 0066 000c FL 1 Recommended Presentation Opacity float RecommendedPresentationOpacity; // 0066 000d CS 1 Recommended Presentation Type VIEWType RecommendedPresentationType; //0066 000e CS 1 Finite Volume STATES FiniteVolume; //0066 0010 CS 1 Manifold STATES Manifold; // Algorithm Family Code SegmentHelper::BasicCodedEntry AlgorithmFamily; //0066 0031 LO 1 Algorithm Version std::string AlgorithmVersion; //0066 0032 LT 1 Algorithm Parameters //0066 0036 LO 1 Algorithm Name std::string AlgorithmName; //** Point members **// //0066 0015 UL 1 Number of Surface Points unsigned long NumberOfSurfacePoints; //0066 0016 OF 1 Point Coordinates Data DataElement PointCoordinatesData; //0066 0017 FL 3 Point Position Accuracy float * PointPositionAccuracy; //0066 0018 FL 1 Mean Point Distance float MeanPointDistance; //0066 0019 FL 1 Maximum Point Distance float MaximumPointDistance; //0066 001a FL 6 Points Bounding Box Coordinates float * PointsBoundingBoxCoordinates; //0066 001b FL 3 Axis of Rotation float * AxisOfRotation; //0066 001c FL 3 Center of Rotation float * CenterOfRotation; //** Normal members **// //0066 001e UL 1 Number of Vectors unsigned long NumberOfVectors; //0066 001f US 1 Vector Dimensionality unsigned short VectorDimensionality; //0066 0020 FL 1-n Vector Accuracy float * VectorAccuracy; //0066 0021 OF 1 Vector Coordinate Data DataElement VectorCoordinateData; //** Primitive members **// SmartPointer< MeshPrimitive > Primitive; }; } #endif // GDCMSURFACE_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSurfaceHelper.cxx000066400000000000000000000104301412732066400246170ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSurfaceHelper.h" #include namespace gdcm { std::vector< float > SurfaceHelper::RGBToXYZ(const std::vector & RGB) { std::vector< float > XYZ(3); float tmp[3]; tmp[0] = RGB[0]; tmp[1] = RGB[1]; tmp[2] = RGB[2]; const float A = 1.0f / 12.92f; const float B = 1.0f / 1.055f; if ( tmp[0] > 0.04045f ) tmp[0] = powf( ( tmp[0] + 0.055f ) * B, 2.4f); else tmp[0] *= A; if ( tmp[1] > 0.04045f ) tmp[1] = powf( ( tmp[1] + 0.055f ) * B, 2.4f); else tmp[1] *= A; if ( tmp[2] > 0.04045f ) tmp[2] = powf( ( tmp[2] + 0.055f ) * B, 2.4f); else tmp[2] *= A; tmp[0] *= 100; tmp[1] *= 100; tmp[2] *= 100; //Observer. = 2°, Illuminant = D65 XYZ[0] = (tmp[0] * 0.4124f + tmp[1] * 0.3576f + tmp[2] * 0.1805f); XYZ[1] = (tmp[0] * 0.2126f + tmp[1] * 0.7152f + tmp[2] * 0.0722f); XYZ[2] = (tmp[0] * 0.0193f + tmp[1] * 0.1192f + tmp[2] * 0.9505f); return XYZ; } std::vector< float > SurfaceHelper::XYZToRGB(const std::vector & XYZ) { std::vector< float > RGB(3); float tmp[3]; tmp[0] = XYZ[0]; tmp[1] = XYZ[1]; tmp[2] = XYZ[2]; // Divide by 100 tmp[0] *= 0.01f; //X from 0 to 95.047 (Observer = 2°, Illuminant = D65) tmp[1] *= 0.01f; //Y from 0 to 100.000 tmp[2] *= 0.01f; //Z from 0 to 108.883 RGB[0] = (tmp[0] * 3.2406f + tmp[1] * -1.5372f + tmp[2] * -0.4986f); RGB[1] = (tmp[0] * -0.9689f + tmp[1] * 1.8758f + tmp[2] * 0.0415f); RGB[2] = (tmp[0] * 0.0557f + tmp[1] * -0.2040f + tmp[2] * 1.0570f); const float A = 1.0f / 2.4f; if ( RGB[0] > 0.0031308f ) RGB[0] = 1.055f * powf( RGB[0], A) - 0.055f; else RGB[0] *= 12.92f; if ( RGB[1] > 0.0031308f ) RGB[1] = 1.055f * powf( RGB[1], A) - 0.055f; else RGB[1] *= 12.92f; if ( RGB[2] > 0.0031308f ) RGB[2] = 1.055f * powf( RGB[2], A) - 0.055f; else RGB[2] *= 12.92f; return RGB; } std::vector< float > SurfaceHelper::XYZToCIELab(const std::vector & XYZ) { std::vector< float > CIELab(3); float tmp[3]; tmp[0] = (XYZ[0] / 95.047f); //ref_X = 95.047 Observer= 2°, Illuminant= D65 tmp[1] = (XYZ[1] * 0.01f); //ref_Y = 100.000 tmp[2] = (XYZ[2] / 108.883f); //ref_Z = 108.883 const float A = 1.0f / 3.0f; const float B = 16.0f / 116.0f; if ( tmp[0] > 0.008856f ) tmp[0] = powf(tmp[0], A); else tmp[0] = (7.787f * tmp[0] + B); if ( tmp[1] > 0.008856f ) tmp[1] = powf(tmp[1], A); else tmp[1] = (7.787f * tmp[1] + B); if ( tmp[2] > 0.008856f ) tmp[2] = powf(tmp[2], A); else tmp[2] = (7.787f * tmp[2] + B); CIELab[0] = ( 116 * tmp[1] ) - 16; CIELab[1] = 500 * ( tmp[0] - tmp[1] ); CIELab[2] = 200 * ( tmp[1] - tmp[2] ); return CIELab; } std::vector< float > SurfaceHelper::CIELabToXYZ(const std::vector & CIELab) { std::vector< float > XYZ(3); float tmp[3]; tmp[1] = (( CIELab[0] + 16 ) / 116.0f); tmp[0] = (CIELab[1] * 0.002f + tmp[1]); tmp[2] = (tmp[1] - CIELab[2] * 0.005f); // Compute t const float A = tmp[0]*tmp[0]*tmp[0]; const float B = tmp[1]*tmp[1]*tmp[1]; const float C = tmp[2]*tmp[2]*tmp[2]; const float D = 16.0f / 116.0f; // Compute f(t) if ( B > 0.008856f) tmp[1] = B; else tmp[1] = ( tmp[1] - D ) / 7.787f; if ( A > 0.008856f) tmp[0] = A; else tmp[0] = ( tmp[0] - D ) / 7.787f; if ( C > 0.008856f) tmp[2] = C; else tmp[2] = ( tmp[2] - D ) / 7.787f; XYZ[0] = (tmp[0] * 95.047f); //ref_X = 95.047 Observer= 2°, Illuminant= D65 XYZ[1] = (tmp[1] * 100.0f); //ref_Y = 100.000 XYZ[2] = (tmp[2] * 108.883f); //ref_Z = 108.883 return XYZ; } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSurfaceHelper.h000066400000000000000000000145001412732066400242460ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2017 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 GDCMSURFACEHELPER_H #define GDCMSURFACEHELPER_H #include "gdcmTypes.h" // for GDCM_EXPORT #include #include namespace gdcm { /** * \brief SurfaceHelper * \details Helper class for Surface object */ class GDCM_EXPORT SurfaceHelper { public: typedef std::vector< unsigned short > ColorArray; /** * \brief Convert a RGB color into DICOM grayscale (ready to write). * * \see PS 3.3 C.27.1 tag(0062,000C) * * \param RGB RGB array. * \param rangeMax Max value of the RGB range. * * \tparam T Type of RGB components. * \tparam U Type of rangeMax value. */ template static unsigned short RGBToRecommendedDisplayGrayscale(const std::vector & RGB, const U rangeMax = 255); /** * \brief Convert a RGB color into DICOM CIE-Lab (ready to write). * * \see PS 3.3 C.10.7.1.1 * * \param RGB RGB array. * \param rangeMax Max value of the RGB range. * * \tparam T Type of RGB components. * \tparam U Type of rangeMax value. */ template static ColorArray RGBToRecommendedDisplayCIELab(const std::vector & RGB, const U rangeMax = 255); /** * \brief Convert a DICOM CIE-Lab (after reading) color into RGB. * * \see PS 3.3 C.10.7.1.1 * * \param CIELab DICOM CIE-Lab array. * \param rangeMax Max value of the RGB range. * * \tparam T Type of CIELab components. * \tparam U Type of rangeMax value. */ template static std::vector RecommendedDisplayCIELabToRGB(const ColorArray & CIELab, const U rangeMax = 255); /** * \brief Convert a DICOM CIE-Lab (after reading) color into RGB. * * \see PS 3.3 C.10.7.1.1 * * \param CIELab DICOM CIE-Lab array. * \param rangeMax Max value of the RGB range. * * \tparam U Type of rangeMax value. */ template static std::vector RecommendedDisplayCIELabToRGB(const ColorArray & CIELab, const U rangeMax = 255); private: static std::vector< float > RGBToXYZ(const std::vector & RGB); static std::vector< float > XYZToRGB(const std::vector & XYZ); static std::vector< float > XYZToCIELab(const std::vector & XYZ); static std::vector< float > CIELabToXYZ(const std::vector & CIELab); }; template unsigned short SurfaceHelper::RGBToRecommendedDisplayGrayscale(const std::vector & RGB, const U rangeMax/* = 255*/) { assert(RGB.size() > 2); unsigned short Grayscale = 0; const float inverseRangeMax = 1.0f / (float) rangeMax; // 0xFFFF "=" 255 "=" white Grayscale = (unsigned short) ((0.2989 * RGB[0] + 0.5870 * RGB[1] + 0.1140 * RGB[2]) * inverseRangeMax // Convert to range 0-1 * 0xFFFF); // Convert to range 0x0000-0xFFFF return Grayscale; } template SurfaceHelper::ColorArray SurfaceHelper::RGBToRecommendedDisplayCIELab(const std::vector & RGB, const U rangeMax/* = 255*/) { assert(RGB.size() > 2); ColorArray CIELab(3); std::vector tmp(3); // Convert to range 0-1 const float inverseRangeMax = 1.0f / (float) rangeMax; tmp[0] = (float) (RGB[0] * inverseRangeMax); tmp[1] = (float) (RGB[1] * inverseRangeMax); tmp[2] = (float) (RGB[2] * inverseRangeMax); tmp = SurfaceHelper::XYZToCIELab( SurfaceHelper::RGBToXYZ( tmp ) ); // Convert to range 0x0000-0xFFFF // 0xFFFF "=" 127, 0x8080 "=" 0, 0x0000 "=" -128 CIELab[0] = (unsigned short) ( 0xFFFF * (tmp[0]*0.01f)); if(tmp[1] >= -128 && tmp[1] <= 0) { CIELab[1] = (unsigned short)(((float)(0x8080)/128.0f)*tmp[1] + ((float)0x8080)); } else if(tmp[1] <= 127 && tmp[1] > 0) { CIELab[1] = (unsigned short)(((float)(0xFFFF - 0x8080)/127.0f)*tmp[1] + (float)(0x8080)); } if(tmp[2] >= -128 && tmp[2] <= 0) { CIELab[2] = (unsigned short)(((float)0x8080/128.0f)*tmp[2] + ((float)0x8080)); } else if(tmp[2] <= 127 && tmp[2] > 0) { CIELab[2] = (unsigned short)(((float)(0xFFFF - 0x8080)/127.0f)*tmp[2] + (float)(0x8080)); } return CIELab; } template std::vector SurfaceHelper::RecommendedDisplayCIELabToRGB(const ColorArray & CIELab, const U rangeMax/* = 255*/) { assert(CIELab.size() > 2); std::vector RGB(3); std::vector tmp(3); // Convert to range 0-1 tmp[0] = 100.0f*CIELab[0] /(float)(0xFFFF); if(CIELab[1] <= 0x8080) { tmp[1] = (float)(((CIELab[1] - 0x8080) * 128.0f)/(float)0x8080); } else { tmp[1] = (float)((CIELab[1]-0x8080)*127.0f / (float)(0xFFFF - 0x8080)); } if(CIELab[2] <= 0x8080) { tmp[2] = (float)(((CIELab[2] - 0x8080) * 128.0f)/(float)0x8080); } else { tmp[2] = (float)((CIELab[2]-0x8080)*127.0f / (float)(0XFFFF - 0x8080)); } tmp = SurfaceHelper::XYZToRGB( SurfaceHelper::CIELabToXYZ( tmp ) ); // Convert to range 0-rangeMax RGB[0] = (T) (tmp[0] * rangeMax); RGB[1] = (T) (tmp[1] * rangeMax); RGB[2] = (T) (tmp[2] * rangeMax); return RGB; } template std::vector SurfaceHelper::RecommendedDisplayCIELabToRGB(const ColorArray & CIELab, const U rangeMax/* = 255*/) { return RecommendedDisplayCIELabToRGB(CIELab, rangeMax); } } // end namespace gdcm #endif // GDCMSURFACEHELPER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSurfaceReader.cxx000066400000000000000000000561751412732066400246220ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSurfaceReader.h" #include "gdcmMediaStorage.h" #include "gdcmAttribute.h" #include "gdcmString.h" namespace gdcm { SurfaceReader::SurfaceReader() = default; SurfaceReader::~SurfaceReader() = default; unsigned long SurfaceReader::GetNumberOfSurfaces() const { return (unsigned long)Segments.size(); } bool SurfaceReader::Read() { bool res = false; if (!SegmentReader::Read()) { return res; } const FileMetaInformation & header = F->GetHeader(); MediaStorage ms = header.GetMediaStorage(); if( ms == MediaStorage::SurfaceSegmentationStorage ) { res = ReadSurfaces(); } else { // Try to find Surface Sequence const DataSet & dsRoot = F->GetDataSet(); if (dsRoot.FindDataElement( Tag(0x0066, 0x0002) )) { res = ReadSurfaces(); } } return res; } bool SurfaceReader::ReadSurfaces() { bool res = false; const DataSet & ds = F->GetDataSet(); // Surface Sequence const Tag surfaceSQTag(0x0066, 0x0002); if (ds.FindDataElement(surfaceSQTag)) { SmartPointer< SequenceOfItems > surfaceSQ = ds.GetDataElement(surfaceSQTag).GetValueAsSQ(); if ( surfaceSQ->GetNumberOfItems() == 0) { gdcmErrorMacro( "No surface found" ); return false; } SequenceOfItems::ConstIterator itSurface = surfaceSQ->Begin(); SequenceOfItems::ConstIterator itEndSurface = surfaceSQ->End(); unsigned long idxItem = 1; for (; itSurface != itEndSurface; itSurface++) { if ( !ReadSurface( *itSurface, idxItem ) ) { gdcmWarningMacro( "Surface "< surface = new Surface; const DataSet & surfacesDS = surfaceItem.GetNestedDataSet(); // Recommended Display Grayscale Value Attribute<0x0062, 0x000C> recommendedDisplayGrayscaleValue; recommendedDisplayGrayscaleValue.SetFromDataSet( surfacesDS ); surface->SetRecommendedDisplayGrayscaleValue( recommendedDisplayGrayscaleValue.GetValue() ); // Recommended Display CIELab Value Attribute<0x0062, 0x000D> recommendedDisplayCIELabValue; recommendedDisplayCIELabValue.SetFromDataSet( surfacesDS ); const unsigned short * array = recommendedDisplayCIELabValue.GetValues(); unsigned short CIELavValue[3] = {0, 0, 0}; unsigned int i = 0; while (array != nullptr && i < 3) CIELavValue[i++] = *(array++); surface->SetRecommendedDisplayCIELabValue( CIELavValue ); // Surface Number Attribute<0x0066, 0x0003> surfaceNumberAt; surfaceNumberAt.SetFromDataSet( surfacesDS ); unsigned long surfaceNumber = idx; if ( !surfaceNumberAt.GetAsDataElement().IsEmpty() ) { surfaceNumber = surfaceNumberAt.GetValue(); } surface->SetSurfaceNumber( surfaceNumber ); // Surface Comments Attribute<0x0066, 0x0004> surfaceComments; surfaceComments.SetFromDataSet( surfacesDS ); surface->SetSurfaceComments( surfaceComments.GetValue() ); // Surface Processing Attribute<0x0066, 0x0009> surfaceProcessingAt; surfaceProcessingAt.SetFromDataSet( surfacesDS ); String<> surfaceProcessingStr( surfaceProcessingAt.GetValue() ); bool surfaceProcessing; if (surfaceProcessingStr.Trim() == "YES") surfaceProcessing = true; else surfaceProcessing = false; surface->SetSurfaceProcessing( surfaceProcessing ); if (surfaceProcessing) { // Surface Processing Ratio Attribute<0x0066, 0x000A> surfaceProcessingRatioAt; surfaceProcessingRatioAt.SetFromDataSet( surfacesDS ); surface->SetSurfaceProcessingRatio( surfaceProcessingRatioAt.GetValue() ); // Surface Processing Description Attribute<0x0066, 0x000B> surfaceProcessingDescriptionAt; surfaceProcessingDescriptionAt.SetFromDataSet( surfacesDS ); surface->SetSurfaceProcessingDescription( surfaceProcessingDescriptionAt.GetValue() ); //***** Surface Processing Algorithm Identification Sequence *****// if( surfacesDS.FindDataElement( Tag(0x0066, 0x0035) ) ) { SmartPointer processingAlgoSQ = surfacesDS.GetDataElement( Tag(0x0066, 0x0035) ).GetValueAsSQ(); if (processingAlgoSQ->GetNumberOfItems() > 0) // Only one item (type 1) { const Item & processingAlgoItem = processingAlgoSQ->GetItem(1); const DataSet & processingAlgoDS = processingAlgoItem.GetNestedDataSet(); //***** Algorithm Family Code Sequence *****// if( processingAlgoDS.FindDataElement( Tag(0x0066, 0x002F) ) ) { SmartPointer algoFamilySQ = processingAlgoDS.GetDataElement( Tag(0x0066, 0x002F) ).GetValueAsSQ(); if (algoFamilySQ->GetNumberOfItems() > 0) // Only one item (type 1) { const Item & algoFamilyItem = algoFamilySQ->GetItem(1); const DataSet & algoFamilyDS = algoFamilyItem.GetNestedDataSet(); //***** CODE SEQUENCE MACRO ATTRIBUTES *****// SegmentHelper::BasicCodedEntry & processingAlgo = surface->GetProcessingAlgorithm(); // Code Value (Type 1) Attribute<0x0008, 0x0100> codeValueAt; codeValueAt.SetFromDataSet( algoFamilyDS ); processingAlgo.CV = codeValueAt.GetValue(); // Coding Scheme (Type 1) Attribute<0x0008, 0x0102> codingSchemeAt; codingSchemeAt.SetFromDataSet( algoFamilyDS ); processingAlgo.CSD = codingSchemeAt.GetValue(); // Code Meaning (Type 1) Attribute<0x0008, 0x0104> codeMeaningAt; codeMeaningAt.SetFromDataSet( algoFamilyDS ); processingAlgo.CM = codeMeaningAt.GetValue(); } } } } } // Recommended Presentation Opacity Attribute<0x0066, 0x000C> recommendedPresentationOpacity; recommendedPresentationOpacity.SetFromDataSet( surfacesDS ); surface->SetRecommendedPresentationOpacity( recommendedPresentationOpacity.GetValue() ); // Recommended Presentation Type Attribute<0x0066, 0x000D> recommendedPresentationType; recommendedPresentationType.SetFromDataSet( surfacesDS ); surface->SetRecommendedPresentationType( Surface::GetVIEWType( recommendedPresentationType.GetValue() ) ); // Finite Volume Attribute<0x0066, 0x000E> finiteVolumeAt; finiteVolumeAt.SetFromDataSet( surfacesDS ); Surface::STATES finiteVolume = Surface::GetSTATES( finiteVolumeAt.GetValue() ); if ( finiteVolume == Surface::STATES_END) finiteVolume = Surface::UNKNOWN; surface->SetFiniteVolume( finiteVolume ); // Manifold Attribute<0x0066, 0x0010> manifoldAt; manifoldAt.SetFromDataSet( surfacesDS ); Surface::STATES manifold = Surface::GetSTATES( manifoldAt.GetValue() ); if ( manifold == Surface::STATES_END ) manifold = Surface::UNKNOWN; surface->SetManifold( manifold ); //***** Surface Points Sequence ******// if ( !ReadPointMacro(surface, surfacesDS) ) return false; //***** Surface Points Normals Sequence ******// const Tag surfaceNormalsSQTag(0x0066, 0x0012); if ( surfacesDS.FindDataElement(surfaceNormalsSQTag)) { SmartPointer< SequenceOfItems > surfaceNormalsSQ = surfacesDS.GetDataElement(surfaceNormalsSQTag).GetValueAsSQ(); if ( surfaceNormalsSQ->GetNumberOfItems() > 0) // One Item shall be permitted { const DataSet & surfaceNormalsDS = surfaceNormalsSQ->GetItem(1).GetNestedDataSet(); // Number of Vectors Attribute<0x0066, 0x001E> numberOfVectors; numberOfVectors.SetFromDataSet( surfaceNormalsDS ); surface->SetNumberOfVectors( numberOfVectors.GetValue() ); // Vector Dimensionality Attribute<0x0066, 0x001F> vectorDimensionality; vectorDimensionality.SetFromDataSet( surfaceNormalsDS ); surface->SetVectorDimensionality( vectorDimensionality.GetValue() ); // Vector Accuracy (Type 3) const Tag vectorAccuracyTag = Tag(0x0066, 0x0020); if ( surfaceNormalsDS.FindDataElement( vectorAccuracyTag ) ) { const DataElement & vectorAccuracyDE = surfaceNormalsDS.GetDataElement( vectorAccuracyTag ); if ( !vectorAccuracyDE.IsEmpty() ) { Attribute<0x0066, 0x0020> vectorAccuracyAt; vectorAccuracyAt.SetFromDataElement( vectorAccuracyDE ); surface->SetVectorAccuracy( vectorAccuracyAt.GetValues() ); } } const Tag vectorCoordDataTag = Tag(0x0066, 0x0021); if( surfaceNormalsDS.FindDataElement( vectorCoordDataTag ) ) { const DataElement & de = surfaceNormalsDS.GetDataElement( vectorCoordDataTag ); surface->SetVectorCoordinateData( de ); } else { gdcmWarningMacro( "No Vector Coordinate Data Found" ); return false; } } else { gdcmWarningMacro( "Surface Point Normals Sequence empty" ); // return false; } } //***** Surface Mesh Primitives Sequence ******// const Tag surfacePrimitivesSQTag(0x0066, 0x0013); if ( !surfacesDS.FindDataElement(surfacePrimitivesSQTag)) { gdcmWarningMacro( "No Surface Mesh Primitives Sequence Found" ); return false; } SmartPointer< SequenceOfItems > surfacePrimitivesSQ = surfacesDS.GetDataElement(surfacePrimitivesSQTag).GetValueAsSQ(); if ( surfacePrimitivesSQ->GetNumberOfItems() < 1) // One Item shall be permitted { gdcmWarningMacro( "Surface Mesh Primitives Sequence empty" ); return false; } SmartPointer< MeshPrimitive > meshPrimitive = new MeshPrimitive; DataSet & surfacePrimitivesDS = surfacePrimitivesSQ->GetItem(1).GetNestedDataSet(); Tag typedTag; // Long Triangle Point Index List if (surfacePrimitivesDS.FindDataElement( Tag(0x0066, 0x0041) )) { typedTag = Tag(0x0066, 0x0041); meshPrimitive->SetPrimitiveType( MeshPrimitive::TRIANGLE ); } // Long Edge Point Index List else if (surfacePrimitivesDS.FindDataElement( Tag(0x0066, 0x0042)) ) { typedTag = Tag(0x0066, 0x0042); meshPrimitive->SetPrimitiveType( MeshPrimitive::EDGE ); } // Long Vertex Point Index List else if (surfacePrimitivesDS.FindDataElement( Tag(0x0066, 0x0043)) ) { typedTag = Tag(0x0066, 0x0043); meshPrimitive->SetPrimitiveType( MeshPrimitive::VERTEX ); } // RETIRED Triangle Point Index List else if (surfacePrimitivesDS.FindDataElement( Tag(0x0066, 0x0023) )) { typedTag = Tag(0x0066, 0x0023); meshPrimitive->SetPrimitiveType( MeshPrimitive::TRIANGLE ); gdcmErrorMacro("Retrieving primitive data from retired tag 'Triangle Point Index List' (0066,0023)"); } // RETIRED Edge Point Index List else if (surfacePrimitivesDS.FindDataElement( Tag(0x0066, 0x0024)) ) { typedTag = Tag(0x0066, 0x0024); meshPrimitive->SetPrimitiveType( MeshPrimitive::EDGE ); gdcmErrorMacro("Retrieving primitive data from retired tag 'Edge Point Index List' (0066,0024)"); } // RETIRED Vertex Point Index List else if (surfacePrimitivesDS.FindDataElement( Tag(0x0066, 0x0025)) ) { typedTag = Tag(0x0066, 0x0025); meshPrimitive->SetPrimitiveType( MeshPrimitive::VERTEX ); gdcmErrorMacro("Retrieving primitive data from retired tag 'Vertex Point Index List' (0066,0025)"); } else { SmartPointer< SequenceOfItems > typedSQ; if (surfacePrimitivesDS.FindDataElement(Tag(0x0066, 0x0026))) { SmartPointer< SequenceOfItems > sequence = surfacePrimitivesDS.GetDataElement( Tag(0x0066, 0x0026) ).GetValueAsSQ(); if(sequence->GetNumberOfItems() > 0) { typedSQ = sequence; meshPrimitive->SetPrimitiveType( MeshPrimitive::TRIANGLE_STRIP ); } } if(!typedSQ && surfacePrimitivesDS.FindDataElement( Tag(0x0066, 0x0027)) ) { SmartPointer< SequenceOfItems > sequence = surfacePrimitivesDS.GetDataElement( Tag(0x0066, 0x0027) ).GetValueAsSQ(); if(sequence->GetNumberOfItems() > 0) { typedSQ = sequence; meshPrimitive->SetPrimitiveType( MeshPrimitive::TRIANGLE_FAN ); } } if (!typedSQ && surfacePrimitivesDS.FindDataElement( Tag(0x0066, 0x0028)) ) { SmartPointer< SequenceOfItems > sequence = surfacePrimitivesDS.GetDataElement( Tag(0x0066, 0x0028) ).GetValueAsSQ(); if(sequence->GetNumberOfItems() > 0) { typedSQ = sequence; meshPrimitive->SetPrimitiveType( MeshPrimitive::LINE ); } } if (!typedSQ && surfacePrimitivesDS.FindDataElement( Tag(0x0066, 0x0034)) ) { SmartPointer< SequenceOfItems > sequence = surfacePrimitivesDS.GetDataElement( Tag(0x0066, 0x0034) ).GetValueAsSQ(); if(sequence->GetNumberOfItems() > 0) { typedSQ = sequence; meshPrimitive->SetPrimitiveType( MeshPrimitive::FACET ); } } if(!typedSQ) { gdcmErrorMacro( "Unknown surface mesh primitives type" ); return false; } if (typedSQ->GetNumberOfItems() > 0) { const size_t nbItems = typedSQ->GetNumberOfItems(); MeshPrimitive::PrimitivesData & primitivesData= meshPrimitive->GetPrimitivesData(); primitivesData.reserve( nbItems ); SequenceOfItems::ConstIterator it = typedSQ->Begin(); SequenceOfItems::ConstIterator itEnd= typedSQ->End(); for (; it != itEnd; it++) { const DataSet & typedPrimitivesDS = it->GetNestedDataSet(); // Primitive Sequence if ( typedPrimitivesDS.FindDataElement( Tag(0x0066, 0x0040)) ) { meshPrimitive->AddPrimitiveData( typedPrimitivesDS.GetDataElement( Tag(0x0066, 0x0040)) ); } // RETIRED Primitive Sequence else if ( typedPrimitivesDS.FindDataElement( Tag(0x0066, 0x0029)) ) { meshPrimitive->AddPrimitiveData( typedPrimitivesDS.GetDataElement( Tag(0x0066, 0x0029)) ); gdcmErrorMacro("Retrieving primitive data from retired tag 'Primitive Point Index List' (0066,0029)"); } else { gdcmWarningMacro( "Missing Primitive Point Index List" ); return false; } } } else { gdcmWarningMacro( "Mesh Primitive typed Sequence empty" ); return false; } } if (typedTag.GetElementTag() != 0) { const DataElement & meshPrimitiveData = surfacePrimitivesDS.GetDataElement( typedTag ); meshPrimitive->SetPrimitiveData( meshPrimitiveData ); } else { gdcmWarningMacro( "No typed Point Index List found" ); return false; } // Get the appropriated segment SmartPointer< Segment > segment = Segments[surfaceNumber]; //***** Segment Sequence *****// SmartPointer segmentsSQ = F->GetDataSet().GetDataElement( Tag(0x0062, 0x0002) ).GetValueAsSQ(); SequenceOfItems::ConstIterator itSegment = segmentsSQ->Begin(); SequenceOfItems::ConstIterator itEndSegment = segmentsSQ->End(); bool findItem = false; while( !findItem && itSegment != itEndSegment ) { const DataSet & segmentDS = itSegment->GetNestedDataSet(); //***** Referenced Surface Sequence *****// SmartPointer refSurfaceSQ = segmentDS.GetDataElement( Tag(0x0066, 0x002B) ).GetValueAsSQ(); SequenceOfItems::ConstIterator itRefSurface = refSurfaceSQ->Begin(); SequenceOfItems::ConstIterator itEndRefSurface = refSurfaceSQ->End(); while( !findItem && itRefSurface != itEndRefSurface ) { const DataSet & refSurfaceDS = itRefSurface->GetNestedDataSet(); // Referenced Surface Number Attribute<0x0066, 0x002C> refSurfaceNumberAt; refSurfaceNumberAt.SetFromDataSet( refSurfaceDS ); unsigned long refSurfaceNumber; if ( !refSurfaceNumberAt.GetAsDataElement().IsEmpty() ) { refSurfaceNumber = refSurfaceNumberAt.GetValue(); } else { refSurfaceNumber = idx; } if (refSurfaceNumber == surfaceNumber) { findItem = true; //***** Segment Surface Generation Algorithm Identification Sequence *****// if( refSurfaceDS.FindDataElement( Tag(0x0066, 0x002D) ) ) { SmartPointer algoSQ = refSurfaceDS.GetDataElement( Tag(0x0066, 0x002D) ).GetValueAsSQ(); if (algoSQ->GetNumberOfItems() > 0) // Only one item is a type 1 { const Item & algoItem = algoSQ->GetItem(1); const DataSet & algoDS = algoItem.GetNestedDataSet(); //***** Algorithm Family Code Sequence *****// if( algoDS.FindDataElement( Tag(0x0066, 0x002F) ) ) { SmartPointer algoFamilySQ = algoDS.GetDataElement( Tag(0x0066, 0x002F) ).GetValueAsSQ(); if (algoFamilySQ->GetNumberOfItems() > 0) // Only one item is a type 1 { const Item & algoFamilyItem = algoFamilySQ->GetItem(1); const DataSet & algoFamilyDS = algoFamilyItem.GetNestedDataSet(); //***** CODE SEQUENCE MACRO ATTRIBUTES *****// SegmentHelper::BasicCodedEntry & algoFamily = surface->GetAlgorithmFamily(); // Code Value (Type 1) Attribute<0x0008, 0x0100> codeValueAt; codeValueAt.SetFromDataSet( algoFamilyDS ); algoFamily.CV = codeValueAt.GetValue(); // Coding Scheme (Type 1) Attribute<0x0008, 0x0102> codingSchemeAt; codingSchemeAt.SetFromDataSet( algoFamilyDS ); algoFamily.CSD = codingSchemeAt.GetValue(); // Code Meaning (Type 1) Attribute<0x0008, 0x0104> codeMeaningAt; codeMeaningAt.SetFromDataSet( algoFamilyDS ); algoFamily.CM = codeMeaningAt.GetValue(); } } // Algorithm Version Attribute<0x0066, 0x0031> algoVersionAt; algoVersionAt.SetFromDataSet( algoDS ); surface->SetAlgorithmVersion( algoVersionAt.GetValue() ); // Algorithm Name Attribute<0x0066, 0x0036> algoNameAt; algoNameAt.SetFromDataSet( algoDS ); surface->SetAlgorithmName( algoNameAt.GetValue() ); } } // else assert? return false? gdcmWarning? } itRefSurface++; } itSegment++; } // Add a MeshPrimitive to the surface surface->SetMeshPrimitive( *meshPrimitive ); // Add surface to the appropriated segment segment->AddSurface(surface); return true; } bool SurfaceReader::ReadPointMacro(SmartPointer< Surface > surface, const DataSet & surfaceDS) { //***** Surface Points Sequence ******// const Tag surfacePointsSQTag(0x0066, 0x0011); if ( !surfaceDS.FindDataElement(surfacePointsSQTag)) { gdcmWarningMacro( "No Surface Point Sequence Found" ); return false; } SmartPointer< SequenceOfItems > surfacePointsSQ = surfaceDS.GetDataElement(surfacePointsSQTag).GetValueAsSQ(); if ( surfacePointsSQ->GetNumberOfItems() == 0) // One Item shall be permitted { gdcmWarningMacro( "Surface Point Sequence empty" ); return false; } const DataSet & surfacePointsDS = surfacePointsSQ->GetItem(1).GetNestedDataSet(); const Tag pointCoordDataTag = Tag(0x0066, 0x0016); if( !surfacePointsDS.FindDataElement( pointCoordDataTag ) ) { gdcmWarningMacro( "No Point Coordinates Data Found" ); return false; } const DataElement & pointCoordDataDe = surfacePointsDS.GetDataElement( pointCoordDataTag ); surface->SetPointCoordinatesData( pointCoordDataDe ); // Number of Surface Points const Tag numberOfSurfacePointsTag = Tag(0x0066, 0x0015); if (surfacePointsDS.FindDataElement( numberOfSurfacePointsTag ) && !surfacePointsDS.GetDataElement( numberOfSurfacePointsTag ).IsEmpty() ) { Attribute<0x0066, 0x0015> numberOfSurfacePointsAt; numberOfSurfacePointsAt.SetFromDataSet( surfacePointsDS ); surface->SetNumberOfSurfacePoints( numberOfSurfacePointsAt.GetValue() ); } else { const unsigned long numberOfSurfacePoints = (unsigned long) ( pointCoordDataDe.GetVL().GetLength() / (VR::GetLength(VR::OF) * 3) ); surface->SetNumberOfSurfacePoints( numberOfSurfacePoints ); } // Point Position Accuracy (Type 3) const Tag pointPositionAccuracyTag = Tag(0x0066, 0x0017); if (surfacePointsDS.FindDataElement( pointPositionAccuracyTag ) && !surfacePointsDS.GetDataElement( pointPositionAccuracyTag ).IsEmpty() ) { Attribute<0x0066, 0x0017> pointPositionAccuracyAt; pointPositionAccuracyAt.SetFromDataSet( surfacePointsDS ); surface->SetPointPositionAccuracy( pointPositionAccuracyAt.GetValues() ); } // Mean Point Distance (Type 3) const Tag meanPointDistanceTag = Tag(0x0066, 0x0018); if (surfacePointsDS.FindDataElement( meanPointDistanceTag ) && !surfacePointsDS.GetDataElement( meanPointDistanceTag ).IsEmpty() ) { Attribute<0x0066, 0x0018> meanPointDistanceAt; meanPointDistanceAt.SetFromDataSet( surfacePointsDS ); surface->SetMeanPointDistance( meanPointDistanceAt.GetValue() ); } // Maximum Point Distance (Type 3) const Tag maximumPointDistanceTag = Tag(0x0066, 0x0019); if (surfacePointsDS.FindDataElement( maximumPointDistanceTag ) && !surfacePointsDS.GetDataElement( maximumPointDistanceTag ).IsEmpty() ) { Attribute<0x0066, 0x0019> maximumPointDistanceAt; maximumPointDistanceAt.SetFromDataSet( surfacePointsDS ); surface->SetMaximumPointDistance( maximumPointDistanceAt.GetValue() ); } // Point Bounding Box Coordinates (Type 3) const Tag pointsBoundingBoxCoordinatesTag = Tag(0x0066, 0x001a); if (surfacePointsDS.FindDataElement( pointsBoundingBoxCoordinatesTag ) && !surfacePointsDS.GetDataElement( pointsBoundingBoxCoordinatesTag ).IsEmpty() ) { Attribute<0x0066, 0x001a> pointsBoundingBoxCoordinatesAt; pointsBoundingBoxCoordinatesAt.SetFromDataSet( surfacePointsDS ); surface->SetPointsBoundingBoxCoordinates( pointsBoundingBoxCoordinatesAt.GetValues() ); } // Axis of Rotation (Type 3) const Tag axisOfRotationTag = Tag(0x0066, 0x001b); if (surfacePointsDS.FindDataElement( axisOfRotationTag ) && !surfacePointsDS.GetDataElement( axisOfRotationTag ).IsEmpty() ) { Attribute<0x0066, 0x001b> axisOfRotationAt; axisOfRotationAt.SetFromDataSet( surfacePointsDS ); surface->SetAxisOfRotation( axisOfRotationAt.GetValues() ); } // Center of Rotation (Type 3) const Tag centerOfRotationTag = Tag(0x0066, 0x001c); if (surfacePointsDS.FindDataElement( centerOfRotationTag ) && !surfacePointsDS.GetDataElement( centerOfRotationTag ).IsEmpty() ) { Attribute<0x0066, 0x001c> centerOfRotationAt; centerOfRotationAt.SetFromDataSet( surfacePointsDS ); surface->SetAxisOfRotation( centerOfRotationAt.GetValues() ); } return true; } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSurfaceReader.h000066400000000000000000000024241412732066400242330ustar00rootroot00000000000000/*========================================================================= 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 GDCMSURFACEREADER_H #define GDCMSURFACEREADER_H #include #include namespace gdcm { /** * \brief This class defines a SURFACE IE reader. * \details It reads surface mesh module attributes. * * \see PS 3.3 A.1.2.18 , A.57 and C.27 */ class GDCM_EXPORT SurfaceReader : public SegmentReader { public: SurfaceReader(); ~SurfaceReader() override; /// Read bool Read() override; unsigned long GetNumberOfSurfaces() const; protected: bool ReadSurfaces(); bool ReadSurface(const Item & surfaceItem, const unsigned long idx); bool ReadPointMacro(SmartPointer< Surface > surface, const DataSet & surfaceDS); }; } #endif // GDCMSURFACEREADER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSurfaceWriter.cxx000066400000000000000000001126321412732066400246630ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSurfaceWriter.h" #include "gdcmAttribute.h" #include "gdcmUIDGenerator.h" namespace gdcm { SurfaceWriter::SurfaceWriter(): NumberOfSurfaces(0) { } SurfaceWriter::~SurfaceWriter() = default; void SurfaceWriter::ComputeNumberOfSurfaces() { std::vector< SmartPointer< Segment > >::const_iterator it = Segments.begin(); std::vector< SmartPointer< Segment > >::const_iterator itEnd = Segments.end(); for (; it != itEnd; it++) { NumberOfSurfaces += (*it)->GetSurfaceCount(); } } unsigned long SurfaceWriter::GetNumberOfSurfaces() { if (NumberOfSurfaces == 0) { ComputeNumberOfSurfaces(); } return NumberOfSurfaces; } void SurfaceWriter::SetNumberOfSurfaces(const unsigned long nb) { NumberOfSurfaces = nb; } bool SurfaceWriter::PrepareWrite() { if( !SegmentWriter::PrepareWrite() ) { return false; } File & file = GetFile(); DataSet & ds = file.GetDataSet(); FileMetaInformation & fmi = file.GetHeader(); const TransferSyntax & ts = fmi.GetDataSetTransferSyntax(); assert( ts.IsExplicit() || ts.IsImplicit() ); // Number Of Surface const unsigned long nbSurfaces = this->GetNumberOfSurfaces(); if (nbSurfaces == 0) { gdcmErrorMacro( "No surface to write" ); return false; } Attribute<0x0066, 0x0001> numberOfSurfaces; numberOfSurfaces.SetValue( (unsigned int)nbSurfaces ); ds.Replace( numberOfSurfaces.GetAsDataElement() ); // Surface Sequence SmartPointer surfacesSQ; if( !ds.FindDataElement( Tag(0x0066, 0x0002) ) ) { surfacesSQ = new SequenceOfItems; DataElement detmp( Tag(0x0066, 0x0002) ); detmp.SetVR( VR::SQ ); detmp.SetValue( *surfacesSQ ); detmp.SetVLToUndefined(); ds.Insert( detmp ); } surfacesSQ = ds.GetDataElement( Tag(0x0066, 0x0002) ).GetValueAsSQ(); surfacesSQ->SetLengthToUndefined(); // Fill the Surface Sequence { const size_t nbItems = surfacesSQ->GetNumberOfItems(); if (nbItems < nbSurfaces) { const size_t diff = nbSurfaces - nbItems; const size_t nbOfItemToMake = (diff > 0?diff:0); for(unsigned int i = 1; i <= nbOfItemToMake; ++i) { Item item; item.SetVLToUndefined(); surfacesSQ->AddItem(item); } } } // else Should I remove items? std::vector< SmartPointer< Segment > > segments = this->GetSegments(); std::vector< SmartPointer< Segment > >::const_iterator it0 = segments.begin(); std::vector< SmartPointer< Segment > >::const_iterator it0End = segments.end(); unsigned int numSegment= 1; unsigned int numSurface= 1; for (; it0 != it0End; it0++) { SmartPointer< Segment > segment = *it0; assert( segment ); std::vector< SmartPointer< Surface > > surfaces = segment->GetSurfaces(); std::vector< SmartPointer< Surface > >::const_iterator it1 = surfaces.begin(); std::vector< SmartPointer< Surface > >::const_iterator it1End = surfaces.end(); for (; it1 != it1End; it1++) { SmartPointer< Surface > surface = *it1; assert( surface ); Item & surfaceItem = surfacesSQ->GetItem( numSurface ); DataSet & surfaceDS = surfaceItem.GetNestedDataSet(); // Recommended Display Grayscale Value Attribute<0x0062, 0x000C> recommendedDisplayGrayscaleValue; recommendedDisplayGrayscaleValue.SetValue( surface->GetRecommendedDisplayGrayscaleValue() ); surfaceDS.Replace( recommendedDisplayGrayscaleValue.GetAsDataElement() ); // Recommended Display CIELab Value Attribute<0x0062, 0x000D> recommendedDisplayCIELabValue; recommendedDisplayCIELabValue.SetValues( surface->GetRecommendedDisplayCIELabValue(), 3 ); surfaceDS.Replace( recommendedDisplayCIELabValue.GetAsDataElement() ); // Surface Number (Type 1) Attribute<0x0066, 0x0003> surfaceNumberAt; unsigned long surfaceNumber = surface->GetSurfaceNumber(); if (surfaceNumber == 0) surfaceNumber = numSurface; surfaceNumberAt.SetValue( (unsigned int)surfaceNumber ); surfaceDS.Replace( surfaceNumberAt.GetAsDataElement() ); // Surface Comments (Type 3) const char * surfaceComments = surface->GetSurfaceComments(); if (strcmp(surfaceComments, "") != 0) { Attribute<0x0066, 0x0004> surfaceCommentsAt; surfaceCommentsAt.SetValue( surfaceComments ); surfaceDS.Replace( surfaceCommentsAt.GetAsDataElement() ); } // Surface Processing const bool surfaceProcessing = surface->GetSurfaceProcessing(); Attribute<0x0066, 0x0009> surfaceProcessingAt; surfaceProcessingAt.SetValue( (surfaceProcessing ? "YES" : "NO") ); surfaceDS.Replace( surfaceProcessingAt.GetAsDataElement() ); if (surfaceProcessing) { Attribute<0x0066, 0x000A> surfaceProcessingRatioAt; surfaceProcessingRatioAt.SetValue( surface->GetSurfaceProcessingRatio() ); surfaceDS.Replace( surfaceProcessingRatioAt.GetAsDataElement() ); const char * surfaceProcessingDescription = surface->GetSurfaceProcessingDescription(); if (strcmp(surfaceProcessingDescription, "") != 0) { Attribute<0x0066, 0x000B> surfaceProcessingDescriptionAt; surfaceProcessingDescriptionAt.SetValue( surfaceProcessingDescription ); surfaceDS.Replace( surfaceProcessingDescriptionAt.GetAsDataElement() ); } //***** Surface Processing Algorithm Identification Sequence *****// { SmartPointer processingAlgoIdSQ; const Tag processingAlgoIdTag(0x0066, 0x0035); if( !surfaceDS.FindDataElement( processingAlgoIdTag ) ) { processingAlgoIdSQ = new SequenceOfItems; DataElement detmp( processingAlgoIdTag ); detmp.SetVR( VR::SQ ); detmp.SetValue( *processingAlgoIdSQ ); detmp.SetVLToUndefined(); surfaceDS.Insert( detmp ); } processingAlgoIdSQ = surfaceDS.GetDataElement( processingAlgoIdTag ).GetValueAsSQ(); processingAlgoIdSQ->SetLengthToUndefined(); if (processingAlgoIdSQ->GetNumberOfItems() < 1) // One item shall be permitted { Item item; item.SetVLToUndefined(); processingAlgoIdSQ->AddItem(item); } Item & processingAlgoIdItem = processingAlgoIdSQ->GetItem(1); DataSet & processingAlgoIdDS = processingAlgoIdItem.GetNestedDataSet(); //***** Algorithm Family Code Sequence *****// //See: PS.3.3 Table 8.8-1 and PS 3.16 Context ID 7162 { const SegmentHelper::BasicCodedEntry & processingAlgo = surface->GetProcessingAlgorithm(); if (processingAlgo.IsEmpty()) { gdcmWarningMacro("Surface processing algorithm family not specified or incomplete"); } SmartPointer algoFamilyCodeSQ; const Tag algoFamilyCodeTag(0x0066, 0x002F); if( !processingAlgoIdDS.FindDataElement( algoFamilyCodeTag ) ) { algoFamilyCodeSQ = new SequenceOfItems; DataElement detmp( algoFamilyCodeTag ); detmp.SetVR( VR::SQ ); detmp.SetValue( *algoFamilyCodeSQ ); detmp.SetVLToUndefined(); processingAlgoIdDS.Insert( detmp ); } algoFamilyCodeSQ = processingAlgoIdDS.GetDataElement( algoFamilyCodeTag ).GetValueAsSQ(); algoFamilyCodeSQ->SetLengthToUndefined(); // Fill the Algorithm Family Code Sequence if (algoFamilyCodeSQ->GetNumberOfItems() < 1) { Item item; item.SetVLToUndefined(); algoFamilyCodeSQ->AddItem(item); } Item & algoFamilyCodeItem = algoFamilyCodeSQ->GetItem(1); DataSet & algoFamilyCodeDS = algoFamilyCodeItem.GetNestedDataSet(); //***** CODE SEQUENCE MACRO ATTRIBUTES *****// { // Code Value (Type 1) Attribute<0x0008, 0x0100> codeValueAt; codeValueAt.SetValue( processingAlgo.CV ); algoFamilyCodeDS.Replace( codeValueAt.GetAsDataElement() ); // Coding Scheme (Type 1) Attribute<0x0008, 0x0102> codingSchemeAt; codingSchemeAt.SetValue( processingAlgo.CSD ); algoFamilyCodeDS.Replace( codingSchemeAt.GetAsDataElement() ); // Code Meaning (Type 1) Attribute<0x0008, 0x0104> codeMeaningAt; codeMeaningAt.SetValue( processingAlgo.CM ); algoFamilyCodeDS.Replace( codeMeaningAt.GetAsDataElement() ); } } } } // Presentation Opacity Attribute<0x0066, 0x000C> presentationOpacity; presentationOpacity.SetValue( surface->GetRecommendedPresentationOpacity() ); surfaceDS.Replace( presentationOpacity.GetAsDataElement() ); // Presentation Type Attribute<0x0066, 0x000D> presentationType; const char * reconmmendedPresentationType = Surface::GetVIEWTypeString( surface->GetRecommendedPresentationType() ); if (reconmmendedPresentationType != nullptr) presentationType.SetValue( reconmmendedPresentationType ); else presentationType.SetValue( Surface::GetVIEWTypeString(Surface::SURFACE) ); // Is it the right thing to do? surfaceDS.Replace( presentationType.GetAsDataElement() ); // Finite Volume Attribute<0x0066, 0x000E> finiteVolumeAt; Surface::STATES finiteVolume = surface->GetFiniteVolume(); if (finiteVolume == Surface::STATES_END) finiteVolume = Surface::UNKNOWN; finiteVolumeAt.SetValue( Surface::GetSTATESString( finiteVolume ) ); surfaceDS.Replace( finiteVolumeAt.GetAsDataElement() ); // Manifold Attribute<0x0066, 0x0010> manifoldAt; Surface::STATES manifold = surface->GetManifold(); if (manifold == Surface::STATES_END) manifold = Surface::UNKNOWN; manifoldAt.SetValue( Surface::GetSTATESString( manifold ) ); surfaceDS.Replace( manifoldAt.GetAsDataElement() ); //****** Surface Points *****// // (0066,0011) SQ (Sequence with undefined length #=1) # u/l, 1 Surface Points Sequence // (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item // (0066,0015) UL # 0, 1 Number Of Surface Points // (0066,0016) OW # 0, 1 Point Coordinates Data // (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem // (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem if ( !PrepareWritePointMacro(surface, surfaceDS, ts) ) return false; //****** Surface Points Normals *****// // (0066,0012) SQ (Sequence with undefined length #=1) # u/l, 1 Surface Points Sequence // (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item // (0066,001e) UL # 0, 1 Number of Vectors // (0066,001f) US # 0, 1 Vector Dimensionality // (0066,0021) OF # 0, 1_n Vector Coordinate Data // (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem // (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem const unsigned long numberofvectors = surface->GetNumberOfVectors(); SmartPointer< MeshPrimitive > meshPrimitive = surface->GetMeshPrimitive(); const MeshPrimitive::MPType primitiveType = meshPrimitive->GetPrimitiveType(); if (numberofvectors > 0 && primitiveType != MeshPrimitive::TRIANGLE_STRIP && primitiveType != MeshPrimitive::TRIANGLE_FAN) { SmartPointer surfacePointsNormalsSQ; if( !surfaceDS.FindDataElement( Tag(0x0066, 0x0012) ) ) { surfacePointsNormalsSQ = new SequenceOfItems; DataElement detmp( Tag(0x0066, 0x0012) ); detmp.SetVR( VR::SQ ); detmp.SetValue( *surfacePointsNormalsSQ ); detmp.SetVLToUndefined(); surfaceDS.Insert( detmp ); } surfacePointsNormalsSQ = surfaceDS.GetDataElement( Tag(0x0066, 0x0012) ).GetValueAsSQ(); surfacePointsNormalsSQ->SetLengthToUndefined(); if (surfacePointsNormalsSQ->GetNumberOfItems() < 1) // One item shall be permitted { Item item; item.SetVLToUndefined(); surfacePointsNormalsSQ->AddItem(item); } Item & surfacePointsNormalsItem = surfacePointsNormalsSQ->GetItem(1); DataSet & surfacePointsNormalsDS = surfacePointsNormalsItem.GetNestedDataSet(); // Number of Vectors Attribute<0x0066, 0x001E> numberOfVectors; numberOfVectors.SetValue( (unsigned int)surface->GetNumberOfVectors() ); surfacePointsNormalsDS.Replace( numberOfVectors.GetAsDataElement() ); // Vector Dimensionality Attribute<0x0066, 0x001F> vectorDimensionalityAt; unsigned short vectorDimensionality = surface->GetVectorDimensionality(); assert( vectorDimensionality ); vectorDimensionalityAt.SetValue( vectorDimensionality ); surfacePointsNormalsDS.Replace( vectorDimensionalityAt.GetAsDataElement() ); // Vector Accuracy (Type 3) Attribute<0x0066, 0x0020> vectorAccuracyAt; const float * vectorAccuracy = surface->GetVectorAccuracy(); if (vectorAccuracy != nullptr) { vectorAccuracyAt.SetValues( vectorAccuracy, vectorDimensionality ); surfacePointsNormalsDS.Replace( vectorAccuracyAt.GetAsDataElement() ); } // Vector Coordinate Data DataElement vectorCoordDataDE( Tag(0x0066, 0x0021) ); vectorCoordDataDE.SetVR( VR::OF ); const Value & vectorCoordinateDataValue = surface->GetVectorCoordinateData().GetValue(); vectorCoordDataDE.SetValue( vectorCoordinateDataValue ); const ByteValue *bv = vectorCoordDataDE.GetByteValue(); VL vl; if ( bv ) vl = bv->GetLength(); else vl.SetToUndefined(); vectorCoordDataDE.SetVL( vl ); if ( ts.IsExplicit() ) vectorCoordDataDE.SetVR( VR::OF ); surfacePointsNormalsDS.Replace( vectorCoordDataDE ); } else if (numberofvectors > 0) { gdcmWarningMacro("Triangle strip or fan have no surface points normals"); } //****** Surface Mesh Primitives *****// // Two exemples : // (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 // (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem // (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem // // OR // // (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,0026) SQ (Sequence with undefined length #=1) # u/l, 1 // Triangle Strip Sequence // (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item // (0066,0040) OL # 0, 1 // Long Primitive Point Index List // (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem // ... // (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item // (0066,0040) OL # 0, 1 // Long Primitive Point Index List // (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem // (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem // (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem // (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem // Surface Mesh Primitives Sequence { SmartPointer surfaceMeshPrimitivesSQ; if( !surfaceDS.FindDataElement( Tag(0x0066, 0x0013) ) ) { surfaceMeshPrimitivesSQ = new SequenceOfItems; DataElement detmp( Tag(0x0066, 0x0013) ); detmp.SetVR( VR::SQ ); detmp.SetValue( *surfaceMeshPrimitivesSQ ); detmp.SetVLToUndefined(); surfaceDS.Insert( detmp ); } surfaceMeshPrimitivesSQ = surfaceDS.GetDataElement( Tag(0x0066, 0x0013) ).GetValueAsSQ(); surfaceMeshPrimitivesSQ->SetLengthToUndefined(); if (surfaceMeshPrimitivesSQ->GetNumberOfItems() < 1) // One itme shall be permitted { Item item; item.SetVLToUndefined(); surfaceMeshPrimitivesSQ->AddItem(item); } Item & surfaceMeshPrimitivesItem = surfaceMeshPrimitivesSQ->GetItem(1); DataSet & surfaceMeshPrimitivesDS = surfaceMeshPrimitivesItem.GetNestedDataSet(); //***** Handle "Typed" Point Index List *****// bool insertInSQ = false; // Primitive Point Index List Tag typedPrimitiveTag; typedPrimitiveTag.SetGroup(0x0066); DataSet & pointIndexListDS0 = surfaceMeshPrimitivesDS; switch (primitiveType) { case MeshPrimitive::VERTEX: // Long Vertex Point Index List typedPrimitiveTag.SetElement(0x0043); break; case MeshPrimitive::EDGE: // Long Edge Point Index List typedPrimitiveTag.SetElement(0x0042); break; case MeshPrimitive::TRIANGLE: // Long Triangle Point Index List typedPrimitiveTag.SetElement(0x0041); break; case MeshPrimitive::TRIANGLE_STRIP: case MeshPrimitive::TRIANGLE_FAN: case MeshPrimitive::LINE: case MeshPrimitive::FACET: // Long Primitive Point Index List typedPrimitiveTag.SetElement(0x0040); insertInSQ = true; break; default: gdcmErrorMacro( "Unknown surface mesh primitives type" ); return false; } if (insertInSQ) { // Handled "complex" mesh primitives Tag typedSequenceTag; typedSequenceTag.SetGroup(0x0066); switch (primitiveType) { case MeshPrimitive::TRIANGLE_STRIP: // Triangle Strip Sequence typedSequenceTag.SetElement(0x0026); break; case MeshPrimitive::TRIANGLE_FAN: // Triangle Fan Sequence typedSequenceTag.SetElement(0x0027); break; case MeshPrimitive::LINE: // Line Sequence typedSequenceTag.SetElement(0x0028); break; case MeshPrimitive::FACET: // Facet Sequence typedSequenceTag.SetElement(0x0034); break; default: gdcmErrorMacro( "Unknown surface mesh primitives type" ); return false; } // "Typed" Sequence SmartPointer typedSequenceSQ; if( !surfaceMeshPrimitivesDS.FindDataElement( typedSequenceTag ) ) { typedSequenceSQ = new SequenceOfItems; DataElement detmp( typedSequenceTag ); detmp.SetVR( VR::SQ ); detmp.SetValue( *typedSequenceSQ ); detmp.SetVLToUndefined(); surfaceMeshPrimitivesDS.Insert( detmp ); } typedSequenceSQ = surfaceMeshPrimitivesDS.GetDataElement( typedSequenceTag ).GetValueAsSQ(); typedSequenceSQ->SetLengthToUndefined(); // Fill the Segment Sequence const unsigned int numberOfPrimitives = meshPrimitive->GetNumberOfPrimitivesData(); assert( numberOfPrimitives ); const size_t nbItems = typedSequenceSQ->GetNumberOfItems(); if (nbItems < numberOfPrimitives) { const size_t diff = numberOfPrimitives - nbItems; const size_t nbOfItemToMake = (diff > 0?diff:0); for(unsigned int i = 1; i <= nbOfItemToMake; ++i) { Item item; item.SetVLToUndefined(); typedSequenceSQ->AddItem(item); } } // else Should I remove items? const MeshPrimitive::PrimitivesData & primitivesData= meshPrimitive->GetPrimitivesData(); MeshPrimitive::PrimitivesData::const_iterator it = primitivesData.begin(); MeshPrimitive::PrimitivesData::const_iterator itEnd = primitivesData.end(); unsigned int i = 1; for (; it != itEnd; it++) { Item & typedSequenceItem = typedSequenceSQ->GetItem(i++); DataSet & pointIndexListDS = typedSequenceItem.GetNestedDataSet(); // "Typed" Point Index List DataElement typedPointIndexListDE( typedPrimitiveTag ); const Value & pointIndexListValue = it->GetValue(); typedPointIndexListDE.SetValue( pointIndexListValue ); const ByteValue * pointIndexListBV = typedPointIndexListDE.GetByteValue(); VL pointIndexListVL; if( pointIndexListBV ) { pointIndexListVL = pointIndexListBV->GetLength(); } else { pointIndexListVL.SetToUndefined(); } typedPointIndexListDE.SetVL( pointIndexListVL ); if ( ts.IsExplicit() ) typedPointIndexListDE.SetVR( VR::OL ); pointIndexListDS.Replace( typedPointIndexListDE ); } } else { // Handled "simple" mesh primitives // "Typed" Point Index List DataElement typedPointIndexListDE( typedPrimitiveTag ); const Value & pointIndexListValue = meshPrimitive->GetPrimitiveData().GetValue(); typedPointIndexListDE.SetValue( pointIndexListValue ); const ByteValue * pointIndexListBV = typedPointIndexListDE.GetByteValue(); VL pointIndexListVL; if ( pointIndexListBV ) pointIndexListVL = pointIndexListBV->GetLength(); else pointIndexListVL.SetToUndefined(); typedPointIndexListDE.SetVL( pointIndexListVL ); if ( ts.IsExplicit() ) typedPointIndexListDE.SetVR( VR::OL ); pointIndexListDS0.Replace( typedPointIndexListDE ); } //***** Add empty values in unused but required tags (Type 2) *****// DataElement emptyOLDE; emptyOLDE.SetVLToUndefined(); emptyOLDE.SetVR( VR::OL ); SmartPointer emptyValueOW = new ByteValue; emptyOLDE.SetValue(*emptyValueOW); // Long Vertex Point Index List ( Type 2 ) Tag vertexPointIndexListTag(0x0066, 0x0043); if( !surfaceMeshPrimitivesDS.FindDataElement( vertexPointIndexListTag ) ) { emptyOLDE.SetTag( vertexPointIndexListTag ); surfaceMeshPrimitivesDS.Insert( emptyOLDE ); } // Long Edge Point Index List ( Type 2 ) Tag edgePointIndexListTag(0x0066, 0x0042); if( !surfaceMeshPrimitivesDS.FindDataElement( edgePointIndexListTag ) ) { emptyOLDE.SetTag( edgePointIndexListTag ); surfaceMeshPrimitivesDS.Insert( emptyOLDE ); } // Long Triangle Point Index List ( Type 2 ) Tag trianglePointIndexListTag(0x0066, 0x0041); if( !surfaceMeshPrimitivesDS.FindDataElement( trianglePointIndexListTag ) ) { emptyOLDE.SetTag( trianglePointIndexListTag ); surfaceMeshPrimitivesDS.Insert( emptyOLDE ); } DataElement emptySQDE; emptySQDE.SetVLToUndefined(); emptySQDE.SetVR( VR::SQ ); SmartPointer emptySequenceSQ = new SequenceOfItems; emptySQDE.SetValue(*emptySequenceSQ); // Triangle Strip Sequence ( Type 2 ) Tag triangleStripSequenceTag(0x0066, 0x0026); if( !surfaceMeshPrimitivesDS.FindDataElement( triangleStripSequenceTag ) ) { emptySQDE.SetTag( triangleStripSequenceTag ); surfaceMeshPrimitivesDS.Insert( emptySQDE ); } // Triangle Fan Sequence ( Type 2 ) Tag triangleFanSequenceTag(0x0066, 0x0027); if( !surfaceMeshPrimitivesDS.FindDataElement( triangleFanSequenceTag ) ) { emptySQDE.SetTag( triangleFanSequenceTag ); surfaceMeshPrimitivesDS.Insert( emptySQDE ); } // Line Sequence ( Type 2 ) Tag lineSequenceTag(0x0066, 0x0028); if( !surfaceMeshPrimitivesDS.FindDataElement( lineSequenceTag ) ) { emptySQDE.SetTag( lineSequenceTag ); surfaceMeshPrimitivesDS.Insert( emptySQDE ); } // Facet Sequence ( Type 2 ) Tag facetSequenceTag(0x0066, 0x0034); if( !surfaceMeshPrimitivesDS.FindDataElement( facetSequenceTag ) ) { emptySQDE.SetTag( facetSequenceTag ); surfaceMeshPrimitivesDS.Insert( emptySQDE ); } } ++numSurface; } //***** Segment Sequence *****// SmartPointer segmentsSQ = ds.GetDataElement( Tag(0x0062, 0x0002) ).GetValueAsSQ(); Item & segmentIt = segmentsSQ->GetItem( numSegment++ ); DataSet & segmentDS = segmentIt.GetNestedDataSet(); //***** Referenced Surface Sequence *****// SmartPointer refSurfaceSQ = segmentDS.GetDataElement( Tag(0x0066, 0x002B) ).GetValueAsSQ(); SequenceOfItems::Iterator itRefSurface = refSurfaceSQ->Begin(); SequenceOfItems::Iterator itEndRefSurface = refSurfaceSQ->End(); unsigned int idxSurface = 0; for (; itRefSurface != itEndRefSurface; itRefSurface++) { DataSet & refSurfaceDS = itRefSurface->GetNestedDataSet(); SmartPointer< Surface > surface = segment->GetSurface( idxSurface++ ); //***** Segment Surface Generation Algorithm Identification Sequence *****// { SmartPointer segmentsAlgoIdSQ; const Tag segmentsAlgoIdTag(0x0066, 0x002D); if( !refSurfaceDS.FindDataElement( segmentsAlgoIdTag ) ) { segmentsAlgoIdSQ = new SequenceOfItems; DataElement detmp( segmentsAlgoIdTag ); detmp.SetVR( VR::SQ ); detmp.SetValue( *segmentsAlgoIdSQ ); detmp.SetVLToUndefined(); refSurfaceDS.Insert( detmp ); } segmentsAlgoIdSQ = refSurfaceDS.GetDataElement( segmentsAlgoIdTag ).GetValueAsSQ(); segmentsAlgoIdSQ->SetLengthToUndefined(); if (segmentsAlgoIdSQ->GetNumberOfItems() < 1) { Item item; item.SetVLToUndefined(); segmentsAlgoIdSQ->AddItem(item); } Item & segmentsAlgoIdItem = segmentsAlgoIdSQ->GetItem(1); DataSet & segmentsAlgoIdDS = segmentsAlgoIdItem.GetNestedDataSet(); //***** Algorithm Family Code Sequence *****// //See: PS.3.3 Table 8.8-1 and PS 3.16 Context ID 7162 const SegmentHelper::BasicCodedEntry & algoFamily = surface->GetAlgorithmFamily(); if (algoFamily.IsEmpty()) { gdcmWarningMacro("Segment surface generation algorithm family not specified or incomplete"); } SmartPointer algoFamilyCodeSQ; const Tag algoFamilyCodeTag(0x0066, 0x002F); if( !segmentsAlgoIdDS.FindDataElement( algoFamilyCodeTag ) ) { algoFamilyCodeSQ = new SequenceOfItems; DataElement detmp( algoFamilyCodeTag ); detmp.SetVR( VR::SQ ); detmp.SetValue( *algoFamilyCodeSQ ); detmp.SetVLToUndefined(); segmentsAlgoIdDS.Insert( detmp ); } algoFamilyCodeSQ = segmentsAlgoIdDS.GetDataElement( algoFamilyCodeTag ).GetValueAsSQ(); algoFamilyCodeSQ->SetLengthToUndefined(); // Fill the Algorithm Family Code Sequence if (algoFamilyCodeSQ->GetNumberOfItems() < 1) { Item item; item.SetVLToUndefined(); algoFamilyCodeSQ->AddItem(item); } Item & algoFamilyCodeItem = algoFamilyCodeSQ->GetItem(1); DataSet & algoFamilyCodeDS = algoFamilyCodeItem.GetNestedDataSet(); //***** CODE SEQUENCE MACRO ATTRIBUTES *****// { // Code Value (Type 1) Attribute<0x0008, 0x0100> codeValueAt; codeValueAt.SetValue( algoFamily.CV ); algoFamilyCodeDS.Replace( codeValueAt.GetAsDataElement() ); // Coding Scheme (Type 1) Attribute<0x0008, 0x0102> codingSchemeAt; codingSchemeAt.SetValue( algoFamily.CSD ); algoFamilyCodeDS.Replace( codingSchemeAt.GetAsDataElement() ); // Code Meaning (Type 1) Attribute<0x0008, 0x0104> codeMeaningAt; codeMeaningAt.SetValue( algoFamily.CM ); algoFamilyCodeDS.Replace( codeMeaningAt.GetAsDataElement() ); } // Algorithm Version const char * algorithmVersion = surface->GetAlgorithmVersion(); if (strcmp(algorithmVersion, "") != 0) { gdcmWarningMacro("No algorithm version specified"); } Attribute<0x0066, 0x0031> algorithmVersionAt; algorithmVersionAt.SetValue( algorithmVersion ); segmentsAlgoIdDS.Replace( algorithmVersionAt.GetAsDataElement() ); // Algorithm Name const char * algorithmName = surface->GetAlgorithmName(); if (strcmp(algorithmName, "") != 0) { gdcmWarningMacro("No algorithm name specified"); } Attribute<0x0066, 0x0036> algorithmNameAt; algorithmNameAt.SetValue( algorithmName ); segmentsAlgoIdDS.Replace( algorithmNameAt.GetAsDataElement() ); } } } //** Complete the file **// // Is SOP Class UID defined? if( !ds.FindDataElement( Tag(0x0008, 0x0016) ) ) { const char * SOPClassUID = MediaStorage::GetMSString(MediaStorage::SurfaceSegmentationStorage); DataElement de( Tag(0x0008, 0x0016) ); VL::Type strlenSOPClassUID= (VL::Type)strlen(SOPClassUID); de.SetByteValue( SOPClassUID, strlenSOPClassUID ); de.SetVR( Attribute<0x0008, 0x0016>::GetVR() ); ds.ReplaceEmpty( de ); } // Is SOP Instance UID defined? if( !ds.FindDataElement( Tag(0x0008, 0x0018) ) ) { UIDGenerator UIDgen; UIDgen.SetRoot( MediaStorage::GetMSString(MediaStorage::SurfaceSegmentationStorage) ); const char * SOPInstanceUID = UIDgen.Generate(); DataElement de( Tag(0x0008, 0x0018) ); VL::Type strlenSOPInstanceUID= (VL::Type)strlen(SOPInstanceUID); de.SetByteValue( SOPInstanceUID, strlenSOPInstanceUID ); de.SetVR( Attribute<0x0008, 0x0018>::GetVR() ); ds.ReplaceEmpty( de ); } fmi.Clear(); { const char *tsuid = TransferSyntax::GetTSString( ts ); DataElement de( Tag(0x0002,0x0010) ); VL::Type strlenTSUID = (VL::Type)strlen(tsuid); de.SetByteValue( tsuid, strlenTSUID ); de.SetVR( Attribute<0x0002, 0x0010>::GetVR() ); fmi.Replace( de ); fmi.SetDataSetTransferSyntax(ts); } fmi.FillFromDataSet( ds ); return true; } bool SurfaceWriter::Write() { if( !PrepareWrite() ) { return false; } assert( Stream ); if( !Writer::Write() ) { return false; } return true; } bool SurfaceWriter::PrepareWritePointMacro(SmartPointer< Surface > surface, DataSet & surfaceDS, const TransferSyntax & ts) { //****** Surface Points *****// // (0066,0011) SQ (Sequence with undefined length #=1) # u/l, 1 Surface Points Sequence // (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item // (0066,0015) UL # 0, 1 Number Of Surface Points // (0066,0016) OW # 0, 1 Point Coordinates Data // (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem // (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem //***** Surface Points Sequence *****// { SmartPointer surfacePointsSq; if( !surfaceDS.FindDataElement( Tag(0x0066, 0x0011) ) ) { surfacePointsSq = new SequenceOfItems; DataElement detmp( Tag(0x0066, 0x0011) ); detmp.SetVR( VR::SQ ); detmp.SetValue( *surfacePointsSq ); detmp.SetVLToUndefined(); surfaceDS.Insert( detmp ); } surfacePointsSq = surfaceDS.GetDataElement( Tag(0x0066, 0x0011) ).GetValueAsSQ(); surfacePointsSq->SetLengthToUndefined(); if (surfacePointsSq->GetNumberOfItems() < 1) // One item shall be permitted { Item item; item.SetVLToUndefined(); surfacePointsSq->AddItem(item); } Item & surfacePointsItem = surfacePointsSq->GetItem(1); DataSet & surfacePointsDs = surfacePointsItem.GetNestedDataSet(); // Point Coordinates Data DataElement pointCoordDataDE( Tag(0x0066, 0x0016) ); const Value & pointCoordinateDataValue = surface->GetPointCoordinatesData().GetValue(); pointCoordDataDE.SetValue( pointCoordinateDataValue ); const ByteValue *bv = pointCoordDataDE.GetByteValue(); VL vl; if ( bv ) vl = bv->GetLength(); else vl.SetToUndefined(); pointCoordDataDE.SetVL( vl ); if ( ts.IsExplicit() ) pointCoordDataDE.SetVR( VR::OF ); surfacePointsDs.Replace( pointCoordDataDE ); // Number Of Surface Points Attribute<0x0066, 0x0015> numberOfSurfacePointsAt; unsigned long numberOfSurfacePoints = surface->GetNumberOfSurfacePoints(); if (numberOfSurfacePoints == 0) numberOfSurfacePoints = bv->GetLength() / (VR::GetLength(VR::OF) * 3); numberOfSurfacePointsAt.SetValue( (unsigned int)numberOfSurfacePoints ); surfacePointsDs.Replace( numberOfSurfacePointsAt.GetAsDataElement() ); // Point Position Accuracy (Type 3) Attribute<0x0066, 0x0017> pointPositionAccuracyAt; const float * pointPositionAccuracy = surface->GetPointPositionAccuracy(); if (pointPositionAccuracy != nullptr) { pointPositionAccuracyAt.SetValues( pointPositionAccuracy ); surfacePointsDs.Replace( pointPositionAccuracyAt.GetAsDataElement() ); } // Mean Point Distance (Type 3) Attribute<0x0066, 0x0018> meanPointDistanceAt; float meanPointDistance = surface->GetMeanPointDistance(); if (meanPointDistance != 0) // FIXME: user can specified 0 value { meanPointDistanceAt.SetValue( meanPointDistance ); surfacePointsDs.Replace( meanPointDistanceAt.GetAsDataElement() ); } // Maximum Point Distance (Type 3) Attribute<0x0066, 0x0019> maximumPointDistanceAt; float maximumPointDistance = surface->GetMaximumPointDistance(); if (maximumPointDistance != 0) // FIXME: user can specified 0 value { maximumPointDistanceAt.SetValue( maximumPointDistance ); surfacePointsDs.Replace( maximumPointDistanceAt.GetAsDataElement() ); } // Point Bounding Box Coordinates (Type 3) Attribute<0x0066, 0x001a> pointsBoundingBoxCoordinatesAt; const float * pointsBoundingBoxCoordinates = surface->GetPointsBoundingBoxCoordinates(); if (pointsBoundingBoxCoordinates != nullptr) { pointsBoundingBoxCoordinatesAt.SetValues( pointsBoundingBoxCoordinates ); surfacePointsDs.Replace( pointsBoundingBoxCoordinatesAt.GetAsDataElement() ); } // Axis of Rotation (Type 3) Attribute<0x0066, 0x001b> axisOfRotationAt; const float * axisOfRotation = surface->GetAxisOfRotation(); if (axisOfRotation != nullptr) { axisOfRotationAt.SetValues( axisOfRotation ); surfacePointsDs.Replace( axisOfRotationAt.GetAsDataElement() ); } // Center of Rotation (Type 3) Attribute<0x0066, 0x001c> centerOfRotationAt; const float * centerOfRotation = surface->GetCenterOfRotation(); if (centerOfRotation != nullptr) { centerOfRotationAt.SetValues( centerOfRotation ); surfacePointsDs.Replace( centerOfRotationAt.GetAsDataElement() ); } return true; } } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmSurfaceWriter.h000066400000000000000000000032001412732066400242760ustar00rootroot00000000000000/*========================================================================= 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 GDCMSURFACEWRITER_H #define GDCMSURFACEWRITER_H #include #include namespace gdcm { /** * \brief This class defines a SURFACE IE writer. * \details It writes surface mesh module attributes. * * \see PS 3.3 A.1.2.18 , A.57 and C.27 */ class GDCM_EXPORT SurfaceWriter : public SegmentWriter { public: SurfaceWriter(); ~SurfaceWriter() override; // const Surface & GetSurface() const { return *SurfaceData; } // Surface & GetSurface() { return *SurfaceData; } // void SetSurface(Surface const & segment); /// Write bool Write() override; // Execute() unsigned long GetNumberOfSurfaces(); void SetNumberOfSurfaces(const unsigned long nb); protected: bool PrepareWrite(); void ComputeNumberOfSurfaces(); bool PrepareWritePointMacro(SmartPointer< Surface > surface, DataSet & surfaceDS, const TransferSyntax & ts); //0066 0001 UL 1 Number of Surfaces unsigned long NumberOfSurfaces; }; } #endif // GDCMSURFACEWRITER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmTagPath.cxx000066400000000000000000000057411412732066400234300ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTagPath.h" #include "gdcmTag.h" #include #include // strlen #include // abort #include // sscanf namespace gdcm { /* * Implementation detail: a tag path is simply a vector. * with the following convention: * First tag is a valid tag, * Second tag is an item number (or 0) * Third tag is a valid tag * ... * and so on an so forth */ TagPath::TagPath():Path() { } TagPath::~TagPath() = default; void TagPath::Print(std::ostream &os) const { unsigned int flip = 0; std::vector::const_iterator it = Path.begin(); for(; it != Path.end(); ++it) { if( flip % 2 == 0 ) { os << *it << "/"; } else // item number { // assert( it->GetElementTag() < 255 ); // how many item max can we have ? os << it->GetElementTag() << "/"; } ++flip; } } bool TagPath::IsValid(const char *path) { TagPath tp; return tp.ConstructFromString(path); } bool TagPath::ConstructFromTagList(Tag const *l, unsigned int n) { //Path = std::vector(l,l+n); Path.clear(); for(unsigned int i = 0; i < n; ++i) { Path.push_back( l[i] ); if( i+1 < n ) { Path.emplace_back(0 ); } } return true; } bool TagPath::ConstructFromString(const char *path) { Path.clear(); if(!path) return false; unsigned int flip = 0; size_t pos = 0; const size_t len = strlen(path); if(!len) return false; // Need to start with a / if( path[pos] == '/' ) { ++pos; } else { return false; } while( pos != len ) { Tag t; if( flip % 2 == 0 ) { if( t.ReadFromCommaSeparatedString( path+pos ) ) { pos += 4 + 4 + 1; Path.push_back( t ); } else { return false; } } else { unsigned int value = 0; if( path[pos] == '*' ) { t.SetElementTag( 0 ); pos++; Path.push_back( t ); } else if( sscanf(path+pos, "%d/", &value) == 1 ) { } } ++flip; if( pos != len && path[pos] == '/' ) ++pos; //else assert(0); } return true; } bool TagPath::Push(Tag const & t) { if( Path.size() % 2 == 0 ) { Path.push_back( t ); return true; } return false; } bool TagPath::Push(unsigned int itemnum) { if( Path.size() % 2 == 1 ) { Path.emplace_back(itemnum ); return true; } return false; } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmTagPath.h000066400000000000000000000027231412732066400230520ustar00rootroot00000000000000/*========================================================================= 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 GDCMTAGPATH_H #define GDCMTAGPATH_H #include "gdcmTag.h" #include namespace gdcm { /** * \brief class to handle a path of tag. * \details * Any Resemblance to Existing XPath is Purely Coincidental * ftp://medical.nema.org/medical/dicom/supps/sup118_pc.pdf */ class GDCM_EXPORT TagPath { public: TagPath(); ~TagPath(); void Print(std::ostream &) const; /// "/0018,0018/"... /// No space allowed, comma is use to separate tag group /// from tag element and slash is used to separate tag /// return false if invalid bool ConstructFromString(const char *path); /// Return if path is valid or not static bool IsValid(const char *path); /// Construct from a list of tags bool ConstructFromTagList(Tag const *l, unsigned int n); bool Push(Tag const & t); bool Push(unsigned int itemnum); private: std::vector Path; }; } // end namespace gdcm #endif //GDCMTAGPATH_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmUIDGenerator.cxx000066400000000000000000000172151412732066400243670ustar00rootroot00000000000000/*========================================================================= 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 "gdcmUIDGenerator.h" #include "gdcmTrace.h" #include "gdcmSystem.h" #include #include // FIXME... #if defined(_WIN32) || defined(__CYGWIN__) #define HAVE_UUIDCREATE #else #define HAVE_UUID_GENERATE #endif #ifdef HAVE_UUID_GENERATE #include "gdcm_uuid.h" #endif #ifdef GDCM_HAVE_RPC_H #include #endif namespace gdcm { /* * This is just plain bad luck. GDCM UID root is 26 byte long * And all implementation of the DCE UUID (Theodore Y. Ts'o) * are based on a uint128_t (unsigned char [16]). Which * means that converted to a base 10 number they require at * least 39 bytes to fit in memory, since the highest possible * number is 256**16 - 1 = 340282366920938463463374607431768211455 * Unfortunately root + '.' + suffix should be at most 64 bytes * * So to get a full UUID implementation as per RFC 4122 * http://www.ietf.org/rfc/rfc4122.txt we need a shorter * root... * */ const char UIDGenerator::GDCM_UID[] = "1.2.826.0.1.3680043.2.1143"; std::string UIDGenerator::Root = GetGDCMUID(); // The following contains the *encoded* hardware address (not the raw as in ipconfig/ifconfig) std::string UIDGenerator::EncodedHardwareAddress; // = System::GetHardwareAddress(); const char *UIDGenerator::GetRoot() { return Root.c_str(); } void UIDGenerator::SetRoot(const char * root) { assert( IsValid( root ) ); Root = root; } const char *UIDGenerator::GetGDCMUID() { return GDCM_UID; } /* * http://www.isthe.com/chongo/tech/comp/fnv/ */ #define FNV1_64_INIT ((uint64_t)0xcbf29ce484222325ULL) struct fnv_hash { static uint64_t hash(const char* pBuffer, size_t nByteLen) { uint64_t nHashVal = FNV1_64_INIT, nMagicPrime = 0x00000100000001b3ULL; const unsigned char* pFirst = ( const unsigned char* )( pBuffer ), * pLast = pFirst + nByteLen; while( pFirst < pLast ) { nHashVal ^= *pFirst++; nHashVal *= nMagicPrime; } return nHashVal; } }; /* Implementation note: You cannot set a root of more than 26 bytes (which should already enough for most people). Since implementation is only playing with the first 8bits of the upper */ const char* UIDGenerator::Generate() { Unique = GetRoot(); // We choose here a value of 26 so that we can still have 37 bytes free to // set the suffix part which is sufficient to store a 2^(128-8+1)-1 number if( Unique.empty() || Unique.size() > 62 ) // 62 is simply the highest possible limit { // I cannot go any further... return nullptr; } unsigned char uuid[16]; bool r = UIDGenerator::GenerateUUID(uuid); // This should only happen in some obscure cases. Since the creation of UUID failed // I should try to go any further and make sure the user's computer crash and burn // right away if( !r ) return nullptr; char randbytesbuf[64]; size_t len = System::EncodeBytes(randbytesbuf, uuid, sizeof(uuid)); assert( len < 64 ); // programmer error Unique += "."; // This dot is compulsory to separate root from suffix if( Unique.size() + len > 64 ) { 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]; unsigned int i = 0; while( ( Unique.size() + len > 64 ) && i < 8 ) { x[7-i] = false; uuid[idx] = (unsigned char)x.to_ulong(); len = System::EncodeBytes(randbytesbuf, uuid, sizeof(uuid)); ++i; } if( ( Unique.size() + len > 64 ) && i == 8 ) { // too bad only reducing the 8 bits from uuid[idx] was not enough, // let's set to zero the following bits... idx++; } else { // cool we found enough to stop found = true; } } if( !found ) { // Technically this could only happen when root has a length >= 64 ... is it // even remotely possible ? gdcmWarningMacro( "Root is too long for current implementation" ); return nullptr; } } // can now safely use randbytesbuf as is, no need to truncate any more: Unique += randbytesbuf; assert( IsValid( Unique.c_str() ) ); return Unique.c_str(); } /* return true on success */ bool UIDGenerator::GenerateUUID(unsigned char *uuid_data) { #if defined(HAVE_UUID_GENERATE) uuid_t g; uuid_generate(g); memcpy(uuid_data, g, sizeof(uuid_t)); #elif defined(HAVE_UUID_CREATE) uint32_t rv; uuid_t g; uuid_create(&g, &rv); if (rv != uuid_s_ok) return false; memcpy(uuid_data, &g, sizeof(uuid_t)); #elif defined(HAVE_UUIDCREATE) if (FAILED(UuidCreate((UUID *)uuid_data))) { return false; } #else #error should not happen #endif return true; } bool UIDGenerator::IsValid(const char *uid_) { /* 9.1 UID ENCODING RULES The DICOM UID encoding rules are defined as follows: - Each component of a UID is a number and shall consist of one or more digits. The first digit of each component shall not be zero unless the component is a single digit. Note: Registration authorities may distribute components with non-significant leading zeroes. The leading zeroes should be ignored when being encoded (ie. 00029 would be encoded 29). - Each component numeric value shall be encoded using the characters 0-9 of the Basic G0 Set of the International Reference Version of ISO 646:1990 (the DICOM default character repertoire). - Components shall be separated by the character "." (2EH). - If ending on an odd byte boundary, except when used for network negotiation (See PS 3.8), one trailing NULL (00H), as a padding character, shall follow the last component in order to align the UID on an even byte boundary. - UID's, shall not exceed 64 total characters, including the digits of each component, separators between components, and the NULL (00H) padding character if needed. */ /* * FIXME: This is not clear in the standard, but I believe a trailing '.' is not allowed since * this is considered as a separator for components */ if( !uid_ ) return false; std::string uid = uid_; if( uid.size() > 64 || uid.empty() ) { return false; } if( uid[0] == '.' || uid[uid.size()-1] == '.' ) // important to do that first { return false; } if( uid.size() < 3 ) return false; if( uid[0] == '0' && uid[1] != '.' ) return false; std::string::size_type i = 0; for(; i < uid.size(); ++i) { if( uid[i] == '.' ) // if test is true we are guarantee that next char is valid (see previous check) { // check that next character is neither '0' (except single number) not '.' if( uid[i+1] == '.' ) { return false; } else if( uid[i+1] == '0' ) // character is guarantee to exist since '.' is not last char { // Need to check first if we are not at the end of string if( i+2 != uid.size() && uid[i+2] != '.' ) { return false; } } } else if ( !isdigit( (unsigned char)uid[i] ) ) { return false; } } // no error found ! return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmUIDGenerator.h000066400000000000000000000066431412732066400240170ustar00rootroot00000000000000/*========================================================================= 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 GDCMUIDGENERATOR_H #define GDCMUIDGENERATOR_H #include "gdcmTypes.h" 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, * otherwise the UID Generator will simply forget the value and create a new UID. */ class GDCM_EXPORT UIDGenerator { public: /// By default the root of a UID is a GDCM Root... UIDGenerator():Unique() {} // Function to override the GDCM root with a user one: // WARNING: This need to be a valid root, otherwise call will fail // Implementation note. According to DICOM standard PS 3.5, Section 9 : // Unique Identifiers (UIDs), we have: /* ... The portion of the UID uniquely identifies an organization, (i.e., manufacturer, research organization, NEMA, etc.), and is composed of a number of numeric components as defined by ISO 8824. The portion of the UID is also composed of a number of numeric components, and shall be unique within the scope of the . This implies that the organization identified in the is responsible for guaranteeing uniqueness by providing registration policies. These policies shall guarantee uniqueness for all UID's created by that organization. Unlike the , which may be common for UID's in an organization, the shall take different unique values between different UID's that identify different objects. ... */ /// The current implementation in GDCM make use of the UUID implementation (RFC 4122) and has been /// 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. static void SetRoot(const char * root); static const char *GetRoot(); /// Internally uses a std::string, so two calls have the same pointer ! /// save into a std::string /// In summary do not write code like that: /// const char *uid1 = uid.Generate(); /// const char *uid2 = uid.Generate(); /// since uid1 == uid2 const char* Generate(); /// Find out if the string is a valid UID or not /// \todo: Move that in DataStructureAndEncoding (see FileMetaInformation::CheckFileMetaInformation) static bool IsValid(const char *uid); /// Return the default (GDCM) root UID: static const char *GetGDCMUID(); // who would want that in the public API ?? protected: static bool GenerateUUID(unsigned char *uuid_data); private: static const char GDCM_UID[]; static std::string Root; static std::string EncodedHardwareAddress; std::string Unique; // Buffer }; } // end namespace gdcm #endif //GDCMUIDGENERATOR_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmUUIDGenerator.cxx000066400000000000000000000046321412732066400245130ustar00rootroot00000000000000/*========================================================================= 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 "gdcmUUIDGenerator.h" #include "gdcmTrace.h" #include "gdcmSystem.h" #include // memcpy // FIXME... #if defined(_WIN32) || defined(__CYGWIN__) #define HAVE_UUIDCREATE #else #define HAVE_UUID_GENERATE #endif #ifdef HAVE_UUID_GENERATE #include "gdcm_uuid.h" #endif #ifdef GDCM_HAVE_RPC_H #include #endif namespace gdcm { const char* UUIDGenerator::Generate() { Unique.resize( 36 ); char *uuid_data = &Unique[0]; #if defined(HAVE_UUID_GENERATE) assert( sizeof(uuid_t) == 16 ); uuid_t g; uuid_generate(g); uuid_unparse(g, uuid_data); #elif defined(HAVE_UUID_CREATE) uint32_t rv; uuid_t g; uuid_create(&g, &rv); if (rv != uuid_s_ok) return NULL; uuid_to_string(&g, &uuid_data, &rv); if (rv != uuid_s_ok) return NULL; #elif defined(HAVE_UUIDCREATE) UUID uuid; UuidCreate(&uuid); unsigned char * str = 0; UuidToString(&uuid, &str); Unique = (char*)str; RpcStringFree(&str); #else #error should not happen #endif assert( IsValid( Unique.c_str() ) ); return Unique.c_str(); } bool UUIDGenerator::IsValid(const char *suid) { if( !suid ) return false; #if defined(HAVE_UUID_GENERATE) uuid_t uu; // technically the specification wants char* input not const char*: // this makes compilation fails otherwise on OpenIndiana: int res = uuid_parse((const char*)suid, uu); if( res ) return false; #elif defined(HAVE_UUID_CREATE) // http://www.freebsd.org/cgi/man.cgi?query=uuid_create uint32_t status; uuid_t uuid; uuid_from_string(suid, &uuid, &status); if( status != uuid_s_ok ) return false; #elif defined(HAVE_UUIDCREATE) // http://msdn.microsoft.com/en-us/library/windows/desktop/aa379336(v=vs.85).aspx UUID uuid; if (FAILED(UuidFromString((unsigned char*)suid, &uuid))) { return false; } #else #error should not happen #endif // no error found ! return true; } } // end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmUUIDGenerator.h000066400000000000000000000020461412732066400241350ustar00rootroot00000000000000/*========================================================================= 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 GDCMUUIDGENERATOR_H #define GDCMUUIDGENERATOR_H #include "gdcmTypes.h" namespace gdcm { /** * \brief Class for generating unique UUID * \details generate DCE 1.1 uid */ class GDCM_EXPORT UUIDGenerator { public: /// Return the generated uuid /// NOT THREAD SAFE const char* Generate(); /// Find out if the string is a valid UUID or not static bool IsValid(const char *uid); private: std::string Unique; // Buffer }; } // end namespace gdcm #endif //GDCMUUIDGENERATOR_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmValidate.cxx000066400000000000000000000026101412732066400236210ustar00rootroot00000000000000/*========================================================================= 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 "gdcmValidate.h" namespace gdcm { //----------------------------------------------------------------------------- Validate::Validate():F(nullptr) { } //----------------------------------------------------------------------------- Validate::~Validate() = default; //----------------------------------------------------------------------------- void Validate::Validation() { if(!F) return; V.GetHeader().SetPreamble( F->GetHeader().GetPreamble() ); //FileMetaInformation &fmi = F.GetHeader(); FileMetaInformation fmi( F->GetHeader() ); fmi.FillFromDataSet( F->GetDataSet() ); std::cout << "Validation" << std::endl; //std::cout << fmi << std::endl; //std::cout << fmi.GetDataElement( Tag(0x0002, 0x0002) ) << std::endl; V.SetHeader( fmi ); V.SetDataSet( F->GetDataSet() ); //std::cout << V.GetHeader() << std::endl; } } GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmValidate.h000066400000000000000000000017151412732066400232530ustar00rootroot00000000000000/*========================================================================= 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 GDCMVALIDATE_H #define GDCMVALIDATE_H #include "gdcmFile.h" namespace gdcm { /** * \brief Validate class */ class GDCM_EXPORT Validate { public: Validate(); ~Validate(); void SetFile(File const &f) { F = &f; } const File& GetValidatedFile() { return V; } void Validation(); protected: const File *F; File V; // Validated file }; } // end namespace gdcm #endif //GDCMVALIDATE_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmWaveform.cxx000066400000000000000000000011411412732066400236540ustar00rootroot00000000000000/*========================================================================= 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 "gdcmWaveform.h" namespace gdcm {} GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmWaveform.h000066400000000000000000000014501412732066400233040ustar00rootroot00000000000000/*========================================================================= 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 GDCMWAVEFORM_H #define GDCMWAVEFORM_H #include "gdcmFile.h" namespace gdcm { /** * \brief Waveform class */ class GDCM_EXPORT Waveform { public: Waveform() = default; private: }; } // end namespace gdcm #endif //GDCMWAVEFORM_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmXMLPrinter.cxx000066400000000000000000000373571412732066400241140ustar00rootroot00000000000000/*========================================================================= 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 "gdcmXMLPrinter.h" #include "gdcmSequenceOfItems.h" #include "gdcmSequenceOfFragments.h" #include "gdcmDict.h" #include "gdcmDicts.h" #include "gdcmGroupDict.h" #include "gdcmVR.h" #include "gdcmVM.h" #include "gdcmElement.h" #include "gdcmGlobal.h" #include "gdcmAttribute.h" #include "gdcmDataSetHelper.h" #include "gdcmUUIDGenerator.h" #include "gdcmDataSet.h" #include namespace gdcm { //----------------------------------------------------------------------------- XMLPrinter::XMLPrinter():PrintStyle(XMLPrinter::OnlyUUID),F(nullptr) { } //----------------------------------------------------------------------------- XMLPrinter::~XMLPrinter() = default; // Carried forward from Printer Class // SIEMENS_GBS_III-16-ACR_NEMA_1.acr is a tough kid: 0009,1131 is supposed to be VR::UL, but // there are only two bytes... VR XMLPrinter::PrintDataElement(std::ostream &os, const Dicts &dicts, const DataSet & ds, const DataElement &de, const TransferSyntax & ts) { const ByteValue *bv = de.GetByteValue(); const SequenceOfItems *sqi = nullptr; const SequenceOfFragments *sqf = de.GetSequenceOfFragments(); std::string strowner; const char *owner = nullptr; const Tag& t = de.GetTag(); UUIDGenerator UIDgen; if( t.IsPrivate() && !t.IsPrivateCreator() ) { strowner = ds.GetPrivateCreator(t); owner = strowner.c_str(); } const DictEntry &entry = dicts.GetDictEntry(t,owner); const VR &vr = entry.GetVR(); const VM &vm = entry.GetVM(); (void)vm; const char *name = entry.GetKeyword(); bool retired = entry.GetRetired(); const VR &vr_read = de.GetVR(); const VL &vl_read = de.GetVL(); //Printing Tag os << " tag = \"" << std::uppercase << std::hex << std::setw(4) << std::setfill('0') << t.GetGroup() << std::setw(4) << t.GetElement() << std::nouppercase <<"\"" << std::dec; //Printing Private Creator if( owner && *owner ) { os << " privateCreator = \"" << owner << "\" "; } VR refvr; // Prefer the vr from the file: if( vr_read == VR::INVALID ) { refvr = vr; } else if ( vr_read == VR::UN && vr != VR::INVALID ) // File is explicit, but still prefer vr from dict when UN { refvr = vr; } else // The file is Explicit ! { refvr = vr_read; } if( refvr.IsDual() ) // This means vr was read from a dict entry: { refvr = DataSetHelper::ComputeVR(*F,ds, t); } //as DataSetHelper would have been called assert( refvr != VR::US_SS ); assert( refvr != VR::OB_OW ); if( !de.IsEmpty() ) { const Value &value = de.GetValue(); if( dynamic_cast( &value ) ) { sqi = de.GetValueAsSQ(); refvr = VR::SQ; assert( refvr == VR::SQ ); } #if 0 else if( vr == VR::SQ && vr_read != VR::SQ ) { sqi = de.GetValueAsSQ(); refvr = VR::SQ; assert( refvr == VR::SQ ); } #endif } if( (vr_read == VR::INVALID || vr_read == VR::UN ) && vl_read.IsUndefined() ) { assert( refvr == VR::SQ ); } // if( vr_read == VR::SQ || vr_read == VR::UN ) // { // sqi = de.GetValueAsSQ(); // } if( vr != VR::INVALID && (!vr.Compatible( vr_read ) || vr_read == VR::INVALID || vr_read == VR::UN ) ) { assert( vr != VR::INVALID ); /* No need as we will save only the VR to which it is stored by GDCM in the XML file if( vr == VR::US_SS || vr == VR::OB_OW ) { os << "(" << vr << " => " << refvr << ") "; } else { os << "(" << vr << ") "; } */ } else if( sqi /*de.GetSequenceOfItems()*/ && refvr == VR::INVALID ) { // when vr == VR::INVALID and vr_read is also VR::INVALID, we have a seldom case where we can guess // the vr // eg. CD1/647662/647663/6471066 has a SQ at (2001,9000) assert( refvr == VR::INVALID ); refvr = VR::SQ; } if(refvr == VR::INVALID) refvr = VR::UN; // Printing the VR -- Value Representation os << " vr = \"" << refvr << "\" "; // Add the keyword attribute : if( t.IsPublic()) { if( name && *name ) { os <<"keyword = \""; /* No owner */ if( t.IsPrivate() && (owner == nullptr || *owner == 0 ) && !t.IsPrivateCreator() ) { //os << name; //os = PrintXML_char(os,name); } /* retired element */ else if( retired ) { assert( t.IsPublic() || t.GetElement() == 0x0 ); // Is there such thing as private and retired element ? //os << name; //os = PrintXML_char(os,name); } /* Public element */ else { //os << name; //os = PrintXML_char(os,name); } char c; for (; (*name)!='\0'; name++) { c = *name; if(c == '&') os << "&"; else if(c == '<') os << "<"; else if(c == '>') os << ">"; else if(c == '\'') os << "'"; else if(c == '\"') os << """; else os << c; } os << "\""; } else { if( t.IsPublic() ) { gdcmWarningMacro( "An unknown public element."); } // os << ""; // Special keyword } } os << ">\n"; #define StringFilterCase(type) \ case VR::type: \ { \ Element el; \ if( !de.IsEmpty() ) { \ el.Set( de.GetValue() ); \ if( el.GetLength() ) { \ os << "" ;os << "" << el.GetValue();os << "\n"; \ const uint32_t l = (uint32_t)el.GetLength(); \ for(uint32_t i = 1; i < l; ++i) \ { \ os << "" ;\ os << el.GetValue(i);os << "\n";} \ } \ else { if( de.IsEmpty() ) \ {} } } \ else { assert( de.IsEmpty()); } \ } break // Print Value now: //Handle PN first, acc. to Standard if(refvr == VR::PN) { if( bv ) { bv->PrintPNXML(os); //new function to print each value in new child tag } else { assert( de.IsEmpty() ); } } else if( refvr & VR::VRASCII ) { //assert( !sqi && !sqf); assert(!sqi); if( bv ) { bv->PrintASCIIXML(os); //new function to print each value in new child tag } else { assert( de.IsEmpty() ); } } else { assert( refvr & VR::VRBINARY || (vr == VR::INVALID && refvr == VR::INVALID) ); std::string s; switch(refvr) { StringFilterCase(AT); StringFilterCase(FL); StringFilterCase(FD); StringFilterCase(OD); StringFilterCase(OF); StringFilterCase(SL); StringFilterCase(SS); StringFilterCase(UL); StringFilterCase(US); StringFilterCase(SV); StringFilterCase(UV); case VR::OB: case VR::OW: case VR::OL: case VR::OV: case VR::OB_OW: case VR::UN: case VR::US_OW: case VR::US_SS_OW: { if ( bv ) { if(PrintStyle) { bv->PrintHexXML(os); } else { if(bv->GetLength()) { const char *suid = UIDgen.Generate(); os << "\n"; HandleBulkData( suid, ts, bv->GetPointer(), bv->GetLength() ); } } } else if ( sqf ) { assert( t == Tag(0x7fe0,0x0010) ); } else if ( sqi ) { gdcmErrorMacro( "Should not happen: VR=UN but contains a SQ" ); } else { assert( !sqi && !sqf ); assert( de.IsEmpty() ); } } break; case VR::US_SS: assert( refvr != VR::US_SS ); break; case VR::SQ://The below info need not be printed into the XML infoset acc. to the standard if( !sqi && !de.IsEmpty() && de.GetValue().GetLength() ) { } else { if( vl_read.IsUndefined() ) { //os << "(Sequence with undefined length)"; } else { //os << "(Sequence with defined length)"; } } break; case VR::INVALID: if( bv ) { if(PrintStyle) bv->PrintHexXML(os); else { if(bv->GetLength()) { const char *suid = UIDgen.Generate(); os << "\n"; HandleBulkData( suid, ts, bv->GetPointer(), bv->GetLength() ); } } } else { assert( !sqi && !sqf ); assert( de.IsEmpty() ); } break; /* ASCII are treated elsewhere but we do not want to use default: here to get warnings */ /* hopefully compiler is smart and remove dead switch/case */ case VR::AE: case VR::AS: case VR::CS: case VR::DA: case VR::DS: case VR::DT: case VR::IS: case VR::LO: case VR::LT: case VR::PN: case VR::SH: case VR::ST: case VR::TM: case VR::UC: case VR::UI: case VR::UR: case VR::UT: /* others */ case VR::VL16: case VR::VL32: case VR::VRASCII: case VR::VRBINARY: case VR::VR_VM1: case VR::VRALL: case VR::VR_END: assert(0 && "No Match! Impossible!!"); break; } } //os << "\n"; return refvr; } void XMLPrinter::PrintSQ(const SequenceOfItems *sqi, const TransferSyntax & ts, std::ostream & os) { if( !sqi ) return; int noItems = 1; SequenceOfItems::ItemVector::const_iterator it = sqi->Items.begin(); for(; it != sqi->Items.end(); ++it) { const Item &item = *it; const DataSet &ds = item.GetNestedDataSet(); //const DataElement &deitem = item; /* os << "> 8) << "\" "; os << " VR = \"UN\" keyword = "; if( deitem.GetVL().IsUndefined() ) { os << "\"ItemWithUndefinedLength\""; } else { os << "\"ItemWithDefinedLength\""; } os << ">\n"; */ os << "\n"; PrintDataSet(ds, ts, os); /* if( deitem.GetVL().IsUndefined() ) { os << "\n"; } os << "\n\n"; */ os << "\n"; } /* if( sqi->GetLength().IsUndefined() ) { os << "\n"; } */ } void XMLPrinter::PrintDataSet(const DataSet &ds, const TransferSyntax & ts, std::ostream &os) { const Global& g = GlobalInstance; const Dicts &dicts = g.GetDicts(); const Dict &d = dicts.GetPublicDict(); (void)d; DataSet::ConstIterator it = ds.Begin(); UUIDGenerator UIDgen; for( ; it != ds.End(); ++it ) { const DataElement &de = *it; const SequenceOfFragments *sqf = de.GetSequenceOfFragments(); os << " sqi2 = de.GetValueAsSQ(); PrintSQ(sqi2, ts, os); } else if ( sqf ) { /*I have appended all fragments into one by calling the GetBuffer method in gdcmSequenceOfFragments which does not write the Table to the buffer. It is slightly buggy as the size returns includes that of the table. Should I get the Table size and subtract it? Or should I append the table as well in the BulkData?? */ unsigned long size = sqf->ComputeByteLength(); char *bulkData = new char [size]; if(sqf->GetBuffer(bulkData, size)) { if(size) { const char *suid = UIDgen.Generate(); os << "\n"; HandleBulkData( suid, ts, bulkData, size); } } /* const BasicOffsetTable & table = sqf->GetTable(); const ByteValue *bv = table.GetByteValue(); if(bv->GetLength()) { const char *suid = UIDgen.Generate(); os << "\n"; HandleBulkData( suid, ts, bv->GetPointer(), bv->GetLength() ); } unsigned int numfrag = sqf->GetNumberOfFragments(); for(unsigned int i = 0; i < numfrag; i++) { const Fragment& frag = sqf->GetFragment(i); const ByteValue *bv = frag.GetByteValue(); if(bv->GetLength()) { const char *suid = UIDgen.Generate(); os << "\n"; HandleBulkData( suid, ts, bv->GetPointer(), bv->GetLength() ); } } */ delete[] bulkData; } else { // This is a byte value, so it should have been already treated. } os << "\n"; } } /*------------------------------------------------------------------------------------------------------------------------------------------------*/ void XMLPrinter::Print(std::ostream& os) { /* XML Meta Info */ const Tag CharacterEncoding(0x0008,0x0005); const DataSet &ds = F->GetDataSet(); const FileMetaInformation &header = F->GetHeader(); const TransferSyntax &ts = header.GetDataSetTransferSyntax(); os << R"( at; at.SetFromDataElement( de ); const char* EncodingFromFile = at.GetValue(0); if (!strcmp(EncodingFromFile,"ISO_IR 6")) os << "UTF-8"; else if (!strcmp(EncodingFromFile,"ISO_IR 192")) os << "UTF-8"; else if (!strcmp(EncodingFromFile,"ISO_IR 100")) os << "ISO-8859-1"; else if (!strcmp(EncodingFromFile,"ISO_IR 101")) os << "ISO-8859-2"; else if (!strcmp(EncodingFromFile,"ISO_IR 109")) os << "ISO-8859-3"; else if (!strcmp(EncodingFromFile,"ISO_IR 110")) os << "ISO-8859-4"; else if (!strcmp(EncodingFromFile,"ISO_IR 148")) os << "ISO-8859-9"; else if (!strcmp(EncodingFromFile,"ISO_IR 144")) os << "ISO-8859-5"; else if (!strcmp(EncodingFromFile,"ISO_IR 127")) os << "ISO-8859-6"; else if (!strcmp(EncodingFromFile,"ISO_IR 126")) os << "ISO-8859-7"; else if (!strcmp(EncodingFromFile,"ISO_IR 138")) os << "ISO-8859-8"; else os << "UTF-8"; os << "\"?>\n"; } else { os << "UTF-8\"?>\n\n"; } } else { os << "UTF-8\"?>\n\n"; } os << "\n"; PrintDataSet(ds, ts, os); os << ""; } // Drop BulkData by default. // Application programmer can override this mechanism. void XMLPrinter::HandleBulkData(const char *uuid, const TransferSyntax & ts, const char *bulkdata, size_t bulklen) { (void)ts; (void)uuid; (void)bulkdata; (void)bulklen; } }//end namespace gdcm GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcmXMLPrinter.h000066400000000000000000000070441412732066400235270ustar00rootroot00000000000000/*========================================================================= 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 GDCMXMLPRINTER_H #define GDCMXMLPRINTER_H /* The Normative version of the XML Schema for the Native DICOM Model follows: start = element NativeDicomModel { DicomDataSet } # A DICOM Data Set is as defined in PS3.5. It does not appear # as an XML Element, since it does not appear in the binary encoded # DICOM objects. It exists here merely as a documentation aid. DicomDataSet = DicomAttribute* DicomAttribute = element DicomAttribute { Tag, VR, Keyword?, PrivateCreator?, ( BulkData | Value+ | Item+ | PersonName+ )? } BulkData = element BulkData{ UUID } Value = element Value { Number, xsd:string } Item = element Item { Number, DicomDataSet } PersonName = element PersonName { Number, element SingleByte { NameComponents }?, element Ideographic { NameComponents }?, element Phonetic { NameComponents }? } NameComponents = element FamilyName {xsd:string}?, element GivenName {xsd:string}?, element MiddleName {xsd:string}?, element NamePrefix {xsd:string}?, element NameSuffix {xsd:string}? # keyword is the attribute tag from PS3.6 # (derived from the DICOM Attribute's name) Keyword = attribute keyword { xsd:token } # canonical XML definition of Hex, with lowercase letters disallowed Tag = attribute tag { xsd:string{ minLength="8" maxLength="8" pattern="[0-9A-F]{8}" } } VR = attribute vr { "AE" | "AS" | "AT"| "CS" | "DA" | "DS" | "DT" | "FL" | "FD" | "IS" | "LO" | "LT" | "OB" | "OF" | "OW" | "PN" | "SH" | "SL" | "SQ" | "SS" | "ST" | "TM" | "UI" | "UL" | "UN" | "US" | "UT" } PrivateCreator = attribute privateCreator{ xsd:string } UUID = attribute uuid { xsd:string } Number = attribute number { xsd:positiveInteger } */ #include "gdcmFile.h" #include "gdcmDataElement.h" namespace gdcm { class DataSet; class DictEntry; class Dicts; class GDCM_EXPORT XMLPrinter { public: XMLPrinter(); virtual ~XMLPrinter(); // Set file void SetFile(File const &f) { F = &f; } typedef enum { OnlyUUID = 0 , LOADBULKDATA = 1 } PrintStyles; // Set PrintStyle value void SetStyle(PrintStyles ps) { PrintStyle = ps; } // Get PrintStyle value PrintStyles GetPrintStyle() const { return PrintStyle; } // Print void Print(std::ostream& os); // Print an individual dataset void PrintDataSet(const DataSet &ds, const TransferSyntax & ts, std::ostream& os); //void PrintUID(std::ostream &os); /// Virtual function mechanism to allow application programmer to /// override the default mechanism for BulkData handling. By default /// GDCM will simply discard the BulkData and only write the UUID virtual void HandleBulkData(const char *uuid, const TransferSyntax &ts, const char *bulkdata, size_t bulklen); protected: VR PrintDataElement(std::ostream &os, const Dicts &dicts, const DataSet & ds, const DataElement &de, const TransferSyntax & ts); void PrintSQ(const SequenceOfItems *sqi, const TransferSyntax & ts, std::ostream &os); PrintStyles PrintStyle; const File *F; }; } // end namespace gdcm #endif //GDCMXMLPRINTER_H GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcm_j2k.h000066400000000000000000000370161412732066400223520ustar00rootroot00000000000000/* * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium * Copyright (c) 2002-2007, Professor Benoit Macq * Copyright (c) 2001-2003, David Janssens * Copyright (c) 2002-2003, Yannick Verschueren * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2006-2007, Parvatha Elangovan * All rights reserved. * * 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, this list of conditions and the following disclaimer. * 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. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef GDCM_J2K_H #define GDCM_J2K_H /** @file j2k.h @brief The JPEG-2000 Codestream Reader/Writer (J2K) The functions in J2K.C have for goal to read/write the several parts of the codestream: markers and data. */ /** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */ /*@{*/ #define J2K_CP_CSTY_PRT 0x01 #define J2K_CP_CSTY_SOP 0x02 #define J2K_CP_CSTY_EPH 0x04 #define J2K_CCP_CSTY_PRT 0x01 #define J2K_CCP_CBLKSTY_LAZY 0x01 #define J2K_CCP_CBLKSTY_RESET 0x02 #define J2K_CCP_CBLKSTY_TERMALL 0x04 #define J2K_CCP_CBLKSTY_VSC 0x08 #define J2K_CCP_CBLKSTY_PTERM 0x10 #define J2K_CCP_CBLKSTY_SEGSYM 0x20 #define J2K_CCP_QNTSTY_NOQNT 0 #define J2K_CCP_QNTSTY_SIQNT 1 #define J2K_CCP_QNTSTY_SEQNT 2 /* ----------------------------------------------------------------------- */ #define J2K_MS_SOC 0xff4f /**< SOC marker value */ #define J2K_MS_SOT 0xff90 /**< SOT marker value */ #define J2K_MS_SOD 0xff93 /**< SOD marker value */ #define J2K_MS_EOC 0xffd9 /**< EOC marker value */ #define J2K_MS_SIZ 0xff51 /**< SIZ marker value */ #define J2K_MS_COD 0xff52 /**< COD marker value */ #define J2K_MS_COC 0xff53 /**< COC marker value */ #define J2K_MS_RGN 0xff5e /**< RGN marker value */ #define J2K_MS_QCD 0xff5c /**< QCD marker value */ #define J2K_MS_QCC 0xff5d /**< QCC marker value */ #define J2K_MS_POC 0xff5f /**< POC marker value */ #define J2K_MS_TLM 0xff55 /**< TLM marker value */ #define J2K_MS_PLM 0xff57 /**< PLM marker value */ #define J2K_MS_PLT 0xff58 /**< PLT marker value */ #define J2K_MS_PPM 0xff60 /**< PPM marker value */ #define J2K_MS_PPT 0xff61 /**< PPT marker value */ #define J2K_MS_SOP 0xff91 /**< SOP marker value */ #define J2K_MS_EPH 0xff92 /**< EPH marker value */ #define J2K_MS_CRG 0xff63 /**< CRG marker value */ #define J2K_MS_COM 0xff64 /**< COM marker value */ /* UniPG>> */ #ifdef USE_JPWL #define J2K_MS_EPC 0xff68 /**< EPC marker value (Part 11: JPEG 2000 for Wireless) */ #define J2K_MS_EPB 0xff66 /**< EPB marker value (Part 11: JPEG 2000 for Wireless) */ #define J2K_MS_ESD 0xff67 /**< ESD marker value (Part 11: JPEG 2000 for Wireless) */ #define J2K_MS_RED 0xff69 /**< RED marker value (Part 11: JPEG 2000 for Wireless) */ #endif /* USE_JPWL */ #ifdef USE_JPSEC #define J2K_MS_SEC 0xff65 /**< SEC marker value (Part 8: Secure JPEG 2000) */ #define J2K_MS_INSEC 0xff94 /**< INSEC marker value (Part 8: Secure JPEG 2000) */ #endif /* USE_JPSEC */ /* < there was a PPT marker for the present tile */ int ppt; /** used in case of multiple marker PPT (number of info already stored) */ int ppt_store; /** ppmbug1 */ int ppt_len; /** add fixed_quality */ float distoratio[100]; /** tile-component coding parameters */ opj_tccp_t *tccps; } opj_tcp_t; /** Coding parameters */ typedef struct opj_cp { /** Digital cinema profile*/ OPJ_CINEMA_MODE cinema; /** Maximum rate for each component. If == 0, component size limitation is not considered */ int max_comp_size; /** Size of the image in bits*/ int img_size; /** Rsiz*/ OPJ_RSIZ_CAPABILITIES rsiz; /** Enabling Tile part generation*/ char tp_on; /** Flag determining tile part generation*/ char tp_flag; /** Position of tile part flag in progression order*/ int tp_pos; /** allocation by rate/distortion */ int disto_alloc; /** allocation by fixed layer */ int fixed_alloc; /** add fixed_quality */ int fixed_quality; /** if != 0, then original dimension divided by 2^(reduce); if == 0 or not used, image is decoded to the full resolution */ int reduce; /** if != 0, then only the first "layer" layers are decoded; if == 0 or not used, all the quality layers are decoded */ int layer; /** if == NO_LIMITATION, decode entire codestream; if == LIMIT_TO_MAIN_HEADER then only decode the main header */ OPJ_LIMIT_DECODING limit_decoding; /** XTOsiz */ int tx0; /** YTOsiz */ int ty0; /** XTsiz */ int tdx; /** YTsiz */ int tdy; /** comment for coding */ char *comment; /** number of tiles in width */ int tw; /** number of tiles in height */ int th; /** ID number of the tiles present in the codestream */ int *tileno; /** size of the vector tileno */ int tileno_size; /** packet header store there for futur use in t2_decode_packet */ unsigned char *ppm_data; /** pointer remaining on the first byte of the first header if ppm is used */ unsigned char *ppm_data_first; /** if ppm == 1 --> there was a PPM marker for the present tile */ int ppm; /** use in case of multiple marker PPM (number of info already store) */ int ppm_store; /** use in case of multiple marker PPM (case on non-finished previous info) */ int ppm_previous; /** ppmbug1 */ int ppm_len; /** tile coding parameters */ opj_tcp_t *tcps; /** fixed layer */ int *matrice; /* UniPG>> */ #ifdef USE_JPWL /** enables writing of EPC in MH, thus activating JPWL */ bool epc_on; /** enables writing of EPB, in case of activated JPWL */ bool epb_on; /** enables writing of ESD, in case of activated JPWL */ bool esd_on; /** enables writing of informative techniques of ESD, in case of activated JPWL */ bool info_on; /** enables writing of RED, in case of activated JPWL */ bool red_on; /** error protection method for MH (0,1,16,32,37-128) */ int hprot_MH; /** tile number of header protection specification (>=0) */ int hprot_TPH_tileno[JPWL_MAX_NO_TILESPECS]; /** error protection methods for TPHs (0,1,16,32,37-128) */ int hprot_TPH[JPWL_MAX_NO_TILESPECS]; /** tile number of packet protection specification (>=0) */ int pprot_tileno[JPWL_MAX_NO_PACKSPECS]; /** packet number of packet protection specification (>=0) */ int pprot_packno[JPWL_MAX_NO_PACKSPECS]; /** error protection methods for packets (0,1,16,32,37-128) */ int pprot[JPWL_MAX_NO_PACKSPECS]; /** enables writing of ESD, (0/2/4 bytes) */ int sens_size; /** sensitivity addressing size (0=auto/2/4 bytes) */ int sens_addr; /** sensitivity range (0-3) */ int sens_range; /** sensitivity method for MH (-1,0-7) */ int sens_MH; /** tile number of sensitivity specification (>=0) */ int sens_TPH_tileno[JPWL_MAX_NO_TILESPECS]; /** sensitivity methods for TPHs (-1,0-7) */ int sens_TPH[JPWL_MAX_NO_TILESPECS]; /** enables JPWL correction at the decoder */ bool correct; /** expected number of components at the decoder */ int exp_comps; /** maximum number of tiles at the decoder */ int max_tiles; #endif /* USE_JPWL */ /* <cp. @param j2k J2K decompressor handle @param parameters decompression parameters */ void j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters); /** Decode an image from a JPEG-2000 codestream @param j2k J2K decompressor handle @param cio Input buffer stream @param cstr_info Codestream information structure if required, NULL otherwise @return Returns a decoded image if successful, returns NULL otherwise */ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *cstr_info); /** Decode an image form a JPT-stream (JPEG 2000, JPIP) @param j2k J2K decompressor handle @param cio Input buffer stream @param cstr_info Codestream information structure if required, NULL otherwise @return Returns a decoded image if successful, returns NULL otherwise */ opj_image_t* j2k_decode_jpt_stream(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *cstr_info); /** Creates a J2K compression structure @param cinfo Codec context info @return Returns a handle to a J2K compressor if successful, returns NULL otherwise */ opj_j2k_t* j2k_create_compress(opj_common_ptr cinfo); /** Destroy a J2K compressor handle @param j2k J2K compressor handle to destroy */ void j2k_destroy_compress(opj_j2k_t *j2k); /** Setup the encoder parameters using the current image and using user parameters. Coding parameters are returned in j2k->cp. @param j2k J2K compressor handle @param parameters compression parameters @param image input filled image */ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_t *image); /** Converts an enum type progression order to string type */ char *j2k_convert_progression_order(OPJ_PROG_ORDER prg_order); /** Encode an image into a JPEG-2000 codestream @param j2k J2K compressor handle @param cio Output buffer stream @param image Image to encode @param cstr_info Codestream information structure if required, NULL otherwise @return Returns true if successful, returns false otherwise */ bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info); /* ----------------------------------------------------------------------- */ /*@}*/ /*@}*/ #endif /* GDCM_J2K_H */ GDCM-3.0.10/Source/MediaStorageAndFileFormat/gdcm_jp2.h000066400000000000000000000134601412732066400223540ustar00rootroot00000000000000/* * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium * Copyright (c) 2002-2007, Professor Benoit Macq * Copyright (c) 2002-2003, Yannick Verschueren * Copyright (c) 2005, Herve Drolon, FreeImage Team * All rights reserved. * * 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, this list of conditions and the following disclaimer. * 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. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef GDCM_JP2_H #define GDCM_JP2_H /** @file jp2.h @brief The JPEG-2000 file format Reader/Writer (JP2) */ /** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */ /*@{*/ #define JPIP_JPIP 0x6a706970 #define JP2_JP 0x6a502020 /**< JPEG 2000 signature box */ #define JP2_FTYP 0x66747970 /**< File type box */ #define JP2_JP2H 0x6a703268 /**< JP2 header box */ #define JP2_IHDR 0x69686472 /**< Image header box */ #define JP2_COLR 0x636f6c72 /**< Colour specification box */ #define JP2_JP2C 0x6a703263 /**< Contiguous codestream box */ #define JP2_URL 0x75726c20 /**< URL box */ #define JP2_DBTL 0x6474626c /**< ??? */ #define JP2_BPCC 0x62706363 /**< Bits per component box */ #define JP2_JP2 0x6a703220 /**< File type fields */ /* ----------------------------------------------------------------------- */ /** JP2 component */ typedef struct opj_jp2_comps { int depth; int sgnd; int bpcc; } opj_jp2_comps_t; /** JPEG-2000 file format reader/writer */ typedef struct opj_jp2 { /** codec context */ opj_common_ptr cinfo; /** handle to the J2K codec */ opj_j2k_t *j2k; unsigned int w; unsigned int h; unsigned int numcomps; unsigned int bpc; unsigned int C; unsigned int UnkC; unsigned int IPR; unsigned int meth; unsigned int approx; unsigned int enumcs; unsigned int precedence; unsigned int brand; unsigned int minversion; unsigned int numcl; unsigned int *cl; opj_jp2_comps_t *comps; unsigned int j2k_codestream_offset; unsigned int j2k_codestream_length; } opj_jp2_t; /** JP2 Box */ typedef struct opj_jp2_box { int length; int type; int init_pos; } opj_jp2_box_t; /** @name Exported functions */ /*@{*/ /* ----------------------------------------------------------------------- */ /** Write the JP2H box - JP2 Header box (used in MJ2) @param jp2 JP2 handle @param cio Output buffer stream */ void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio); /** Read the JP2H box - JP2 Header box (used in MJ2) @param jp2 JP2 handle @param cio Input buffer stream @return Returns true if successful, returns false otherwise */ bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio); /** Creates a JP2 decompression structure @param cinfo Codec context info @return Returns a handle to a JP2 decompressor if successful, returns NULL otherwise */ opj_jp2_t* jp2_create_decompress(opj_common_ptr cinfo); /** Destroy a JP2 decompressor handle @param jp2 JP2 decompressor handle to destroy */ void jp2_destroy_decompress(opj_jp2_t *jp2); /** Setup the decoder decoding parameters using user parameters. Decoding parameters are returned in jp2->j2k->cp. @param jp2 JP2 decompressor handle @param parameters decompression parameters */ void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters); /** Decode an image from a JPEG-2000 file stream @param jp2 JP2 decompressor handle @param cio Input buffer stream @param cstr_info Codestream information structure if required, NULL otherwise @return Returns a decoded image if successful, returns NULL otherwise */ opj_image_t* jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, opj_codestream_info_t *cstr_info); /** Creates a JP2 compression structure @param cinfo Codec context info @return Returns a handle to a JP2 compressor if successful, returns NULL otherwise */ opj_jp2_t* jp2_create_compress(opj_common_ptr cinfo); /** Destroy a JP2 compressor handle @param jp2 JP2 compressor handle to destroy */ void jp2_destroy_compress(opj_jp2_t *jp2); /** Setup the encoder parameters using the current image and using user parameters. Coding parameters are returned in jp2->j2k->cp. @param jp2 JP2 compressor handle @param parameters compression parameters @param image input filled image */ void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_t *image); /** Encode an image into a JPEG-2000 file stream @param jp2 JP2 compressor handle @param cio Output buffer stream @param image Image to encode @param cstr_info Codestream information structure if required, NULL otherwise @return Returns true if successful, returns false otherwise */ bool jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info); /* ----------------------------------------------------------------------- */ /*@}*/ /*@}*/ #endif /* GDCM_JP2_H */ GDCM-3.0.10/Source/MessageExchangeDefinition/000077500000000000000000000000001412732066400206125ustar00rootroot00000000000000GDCM-3.0.10/Source/MessageExchangeDefinition/CMakeLists.txt000066400000000000000000000061371412732066400233610ustar00rootroot00000000000000# Add the include paths include_directories( "${GDCM_BINARY_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition" "${GDCM_SOURCE_DIR}/Source/DataDictionary" "${GDCM_SOURCE_DIR}/Source/InformationObjectDefinition" "${GDCM_SOURCE_DIR}/Source/MediaStorageAndFileFormat" "${GDCM_BINARY_DIR}/Testing/Source/Data" "${GDCM_SOURCE_DIR}/Testing/Source/Data" "${GDCM_SOURCE_DIR}/Utilities" ) if(NOT GDCM_USE_SYSTEM_SOCKETXX) include_directories( "${GDCM_SOURCE_DIR}/Utilities/socketxx" "${GDCM_SOURCE_DIR}/Utilities/socketxx/socket++" # local.h "${GDCM_BINARY_DIR}/Utilities/socketxx/socket++" # config.h ) endif() set(MessageExchangeDefinition_SRCS gdcmAAbortPDU.cxx gdcmAAssociateACPDU.cxx gdcmAAssociateRJPDU.cxx gdcmAAssociateRQPDU.cxx gdcmAbstractSyntax.cxx gdcmApplicationContext.cxx gdcmAReleaseRPPDU.cxx gdcmAReleaseRQPDU.cxx gdcmARTIMTimer.cxx gdcmAsynchronousOperationsWindowSub.cxx gdcmBaseQuery.cxx gdcmBaseRootQuery.cxx gdcmCEchoMessages.cxx gdcmCFindMessages.cxx gdcmCMoveMessages.cxx gdcmCommandDataSet.cxx gdcmCompositeMessageFactory.cxx gdcmCompositeNetworkFunctions.cxx gdcmCStoreMessages.cxx gdcmFindPatientRootQuery.cxx gdcmFindStudyRootQuery.cxx gdcmImplementationClassUIDSub.cxx gdcmImplementationUIDSub.cxx gdcmImplementationVersionNameSub.cxx gdcmMaximumLengthSub.cxx gdcmModalityPerformedProcedureStepCreateQuery.cxx gdcmModalityPerformedProcedureStepSetQuery.cxx gdcmMovePatientRootQuery.cxx gdcmMoveStudyRootQuery.cxx gdcmNActionMessages.cxx gdcmNCreateMessages.cxx gdcmNDeleteMessages.cxx gdcmNEventReportMessages.cxx gdcmNGetMessages.cxx gdcmNormalizedMessageFactory.cxx gdcmNormalizedNetworkFunctions.cxx gdcmNSetMessages.cxx gdcmPDataTFPDU.cxx gdcmPDUFactory.cxx gdcmPresentationContext.cxx gdcmPresentationContextAC.cxx gdcmPresentationContextGenerator.cxx gdcmPresentationContextRQ.cxx gdcmPresentationDataValue.cxx gdcmQueryBase.cxx gdcmQueryFactory.cxx gdcmQueryImage.cxx gdcmQueryPatient.cxx gdcmQuerySeries.cxx gdcmQueryStudy.cxx gdcmRoleSelectionSub.cxx gdcmServiceClassApplicationInformation.cxx gdcmServiceClassUser.cxx gdcmSOPClassExtendedNegociationSub.cxx gdcmTransferSyntaxSub.cxx gdcmULActionAA.cxx gdcmULActionAE.cxx gdcmULActionAR.cxx gdcmULActionDT.cxx gdcmULBasicCallback.cxx gdcmULConnection.cxx gdcmULConnectionInfo.cxx gdcmULConnectionManager.cxx gdcmULTransitionTable.cxx gdcmULWritingCallback.cxx gdcmUserInformation.cxx gdcmWLMFindQuery.cxx ) add_library(gdcmMEXD ${MessageExchangeDefinition_SRCS}) target_link_libraries(gdcmMEXD LINK_PRIVATE gdcmMSFF gdcmDICT gdcmDSED gdcmIOD) if(GDCM_USE_SYSTEM_SOCKETXX) target_link_libraries(gdcmMEXD LINK_PRIVATE socket++) else() target_link_libraries(gdcmMEXD LINK_PRIVATE socketxx) endif() if(WIN32) target_link_libraries(gdcmMEXD LINK_PRIVATE ws2_32) endif() set_target_properties(gdcmMEXD PROPERTIES ${GDCM_LIBRARY_PROPERTIES}) # libs install_library(gdcmMEXD) # PDB install_pdb(gdcmMEXD) # include files install_includes("*.h") GDCM-3.0.10/Source/MessageExchangeDefinition/README.txt000066400000000000000000000024401412732066400223100ustar00rootroot00000000000000Part 3.7 / Part 3.8 The DICOM UL protocol consists of seven Protocol Data Units: a) A-ASSOCIATE-RQ PDU b) A-ASSOCIATE-AC PDU c) A-ASSOCIATE-RJ PDU d) P-DATA-TF PDU e) A-RELEASE-RQ PDU f) A-RELEASE-RP PDU g) A-ABORT PDU The encoding of the DICOM UL PDUs is defined as follows (Big Endian byte ordering): Note: The Big Endian byte ordering has been chosen for consistency with the OSI and TCP/IP environment. This pertains to the DICOM UL PDU headers only. The encoding of the PDV message fragments is defined by the Transfer Syntax negotiated at association establishment. a) Each PDU type shall consist of one or more bytes that when represented, are numbered sequentially, with byte 1 being the lowest byte number. b) Each byte within the PDU shall consist of eight bits that, when represented, are numbered 7 to 0, where bit 0 is the low order bit. c) When consecutive bytes are used to represent a string of characters, the lowest byte numbers represent the first character. d) When consecutive bytes are used to represent a binary number, the lower byte number has the most significant value. e) The lowest byte number is placed first in the transport service data flow. f) An overview of the PDUs is shown in Figures 9-1 and 9-2. The detailed structure of each PDU is specified in the following sections. GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAAbortPDU.cxx000066400000000000000000000103341412732066400237130ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAAbortPDU.h" #include "gdcmSwapper.h" namespace gdcm { namespace network { const uint8_t AAbortPDU::ItemType = 0x7; // PDUType ? const uint8_t AAbortPDU::Reserved2 = 0x0; const uint8_t AAbortPDU::Reserved7 = 0x0; const uint8_t AAbortPDU::Reserved8 = 0x0; /* This Source field shall contain an integer value encoded as an unsigned binary number. One of the following values shall be used: 0 - DICOM UL service-user (initiated abort) 1 - reserved 2 - DICOM UL service-provider (initiated abort) */ /* This field shall contain an integer value encoded as an unsigned binary number. If the Source field has the value (2) “DICOM UL service-provider,” it shall take one of the following: 0 - reason-not-specified 1 - unrecognized-PDU 2 - unexpected-PDU 3 - reserved 4 - unrecognized-PDU parameter 5 - unexpected-PDU parameter 6 - invalid-PDU-parameter value If the Source field has the value (0) “DICOM UL service-user,” this reason field shall not be significant. It shall be sent with a value 00H but not tested to this value when received. Note: The reserved fields are used to preserve symmetry with OSI ACSE/Presentation Services and Protocol. */ AAbortPDU::AAbortPDU() { ItemLength = 0; Source = 0; Reason = 0; ItemLength = (uint32_t)Size() - 6; assert( (ItemLength + 4 + 1 + 1) == Size() ); } std::istream &AAbortPDU::Read(std::istream &is) { //uint8_t itemtype = 0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2 = 0; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint32_t itemlength = ItemLength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; uint8_t reserved7 = 0; is.read( (char*)&reserved7, sizeof(Reserved7) ); uint8_t reserved8 = 0; is.read( (char*)&reserved8, sizeof(Reserved8) ); uint8_t source = 0; is.read( (char*)&source, sizeof(Source) ); Source = source; uint8_t reason = 0; is.read( (char*)&reason, sizeof(Reason) ); Reason = reason; assert( (ItemLength + 4 + 1 + 1) == Size() ); return is; } const std::ostream &AAbortPDU::Write(std::ostream &os) const { return os; } size_t AAbortPDU::Size() const { size_t ret = 0; ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); ret += sizeof(Reserved7); ret += sizeof(Reserved8); ret += sizeof(Source); ret += sizeof(Reason); return ret; } namespace { static const char *PrintSourceAsString( uint8_t source ) { // See PS 3.8-2011 Table 9-26 A-ABORT PDU FIELDS switch( source ) { case 0x0: return "DICOM UL service-user (initiated abort)"; case 0x1: return "reserved"; case 0x2: return "DICOM UL service-provider (initiated abort)"; } // Conquest DICOM 1.14.17c, return '3' as source value: return "BOGUS SCP IMPLEMENTATION, REPORT UPSTREAM"; } static const char *PrintReasonAsString( uint8_t reason ) { switch( reason ) { case 0x0: return "reason-not-specified"; case 0x1: return "unrecognized-PDU"; case 0x2: return "unexpected-PDU"; case 0x3: return "reserved"; case 0x4: return "unrecognized-PDU parameter"; case 0x5: return "unexpected-PDU parameter"; case 0x6: return "invalid-PDU-parameter value"; } assert( 0 ); return nullptr; } } void AAbortPDU::Print(std::ostream &os) const { os << "PDULength: " << ItemLength << std::endl; os << "Source: " << PrintSourceAsString( Source ) << std::endl; os << "Reason: " << PrintReasonAsString( Reason ) << std::endl; } void AAbortPDU::SetSource(const uint8_t s) { Source = s; } void AAbortPDU::SetReason(const uint8_t r) { Reason = r; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAAbortPDU.h000066400000000000000000000027461412732066400233500ustar00rootroot00000000000000/*========================================================================= 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 GDCMAABORTPDU_H #define GDCMAABORTPDU_H #include "gdcmTypes.h" #include "gdcmBasePDU.h" namespace gdcm { namespace network { /** * \brief AAbortPDU * \details Table 9-26 A-ABORT PDU FIELDS */ class GDCM_EXPORT AAbortPDU : public BasePDU { public: AAbortPDU(); std::istream &Read(std::istream &is) override; const std::ostream &Write(std::ostream &os) const override; /// \internal Compute Size size_t Size() const override; void Print(std::ostream &os) const override; bool IsLastFragment() const override { return true; } void SetSource(const uint8_t s); void SetReason(const uint8_t r); private: static const uint8_t ItemType; // PDUType ? static const uint8_t Reserved2; uint32_t ItemLength; // PDU Length static const uint8_t Reserved7; static const uint8_t Reserved8; uint8_t Source; uint8_t Reason; // diag }; } // end namespace network } // end namespace gdcm #endif //GDCMAABORTPDU_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAAssociateACPDU.cxx000066400000000000000000000215161412732066400247670ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAAssociateACPDU.h" #include "gdcmSwapper.h" #include "gdcmAAssociateRQPDU.h" namespace gdcm { namespace network { const uint8_t AAssociateACPDU::ItemType = 0x02; // PDUType ? const uint8_t AAssociateACPDU::Reserved2 = 0x00; const uint16_t AAssociateACPDU::ProtocolVersion = 0x01; // big endian const uint16_t AAssociateACPDU::Reserved9_10 = 0x0000; //const uint8_t AAssociateACPDU::Reserved11_26[16] = { }; //const uint8_t AAssociateACPDU::Reserved27_42[16] = { }; //const uint8_t AAssociateACPDU::Reserved43_74[32] = { }; AAssociateACPDU::AAssociateACPDU() { PDULength = 0; // len of memset(Reserved11_26, ' ', sizeof(Reserved11_26)); memset(Reserved27_42, ' ', sizeof(Reserved27_42)); memset(Reserved43_74, ' ', sizeof(Reserved43_74)); PDULength = (uint32_t)(Size() - 6); } void AAssociateACPDU::SetCalledAETitle(const char calledaetitle[16]) { //size_t len = strlen( calledaetitle ); //assert( len <= 16 ); // since forwarded from AA-RQ no reason to be invalid memcpy(Reserved11_26, calledaetitle, 16 ); } void AAssociateACPDU::SetCallingAETitle(const char callingaetitle[16]) { //size_t len = strlen( callingaetitle ); //assert( len <= 16 ); // since forwarded from AA-RQ no reason to be invalid memcpy(Reserved27_42, callingaetitle, 16 ); } std::istream &AAssociateACPDU::Read(std::istream &is) { //uint8_t itemtype = 0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); assert( is.good() ); uint8_t reserved2; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint32_t pdulength = 0; is.read( (char*)&pdulength, sizeof(PDULength) ); SwapperDoOp::SwapArray(&pdulength,1); PDULength = pdulength; uint16_t protocolversion; is.read( (char*)&protocolversion, sizeof(ProtocolVersion) ); SwapperDoOp::SwapArray(&protocolversion,1); if( protocolversion != ProtocolVersion ) { gdcmErrorMacro( "Improper Protocol Version: " << protocolversion ); } uint16_t reserved9_10; is.read( (char*)&reserved9_10, sizeof(Reserved9_10) ); SwapperDoOp::SwapArray(&reserved9_10,1); char reserved11_26[16]; memset( reserved11_26, 0, sizeof(reserved11_26)); is.read( (char*)&reserved11_26, sizeof(Reserved11_26) ); // called memcpy( Reserved11_26, reserved11_26, sizeof(Reserved11_26) ); char reserved27_42[16]; memset( reserved27_42, 0, sizeof(reserved27_42)); is.read( (char*)&reserved27_42, sizeof(Reserved27_42) ); // calling memcpy( Reserved27_42, reserved27_42, sizeof(Reserved27_42) ); uint8_t reserved43_74[32]; memset( reserved43_74, 0, sizeof(reserved43_74)); is.read( (char*)&reserved43_74, sizeof(Reserved43_74) ); // 0 (32 times) memcpy( Reserved43_74, reserved43_74, sizeof(Reserved43_74) ); uint8_t itemtype2 = 0x0; size_t curlen = 0; while( curlen + 68 < PDULength ) { is.read( (char*)&itemtype2, sizeof(ItemType) ); switch ( itemtype2 ) { case 0x10: // ApplicationContext ItemType AppContext.Read( is ); curlen += AppContext.Size(); break; case 0x21: // PresentationContextAC ItemType { PresentationContextAC pcac; pcac.Read( is ); PresContextAC.push_back( pcac ); curlen += pcac.Size(); } break; case 0x50: // UserInformation ItemType UserInfo.Read( is ); curlen += UserInfo.Size(); break; default: gdcmErrorMacro( "Unknown ItemType: " << std::hex << (int) itemtype2 ); curlen = PDULength; // make sure to exit break; } // WARNING: I cannot simply call Size() since UserInfo is initialized with GDCM // own parameter, this will bias the computation. Instead compute relative // length of remaining bytes to read. //curlen = Size(); } assert( curlen + 68 == PDULength ); assert( PDULength + 4 + 1 + 1 == Size() ); return is; } const std::ostream &AAssociateACPDU::Write(std::ostream &os) const { os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); //os.write( (const char*)&PDULength, sizeof(PDULength) ); uint32_t copy = PDULength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(PDULength) ); uint16_t protocolversion = ProtocolVersion; SwapperDoOp::SwapArray(&protocolversion,1); os.write( (const char*)&protocolversion, sizeof(ProtocolVersion) ); os.write( (const char*)&Reserved9_10, sizeof(Reserved9_10) ); os.write( (const char*)&Reserved11_26, sizeof(Reserved11_26) ); //const char calling[] = "ANY-SCP "; //os.write( calling, 16 ); os.write( (const char*)&Reserved27_42, sizeof(Reserved27_42) ); //const char called[] = "STORESCU "; //const char called[] = "ECHOSCU "; //os.write( called, 16 ); os.write( (const char*)&Reserved43_74, sizeof(Reserved43_74) ); AppContext.Write( os ); gdcmAssertAlwaysMacro( PresContextAC.size() ); std::vector::const_iterator it = PresContextAC.begin(); for( ; it != PresContextAC.end(); ++it ) { it->Write( os ); } UserInfo.Write( os ); assert( PDULength + 4 + 1 + 1 == Size() ); return os; } size_t AAssociateACPDU::Size() const { size_t ret = 0; ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(PDULength); ret += sizeof(ProtocolVersion); ret += sizeof(Reserved9_10); ret += sizeof(Reserved11_26); ret += sizeof(Reserved27_42); ret += sizeof(Reserved43_74); ret += AppContext.Size(); std::vector::const_iterator it = PresContextAC.begin(); for( ; it != PresContextAC.end(); ++it ) { ret += it->Size(); } ret += UserInfo.Size(); return ret; } void AAssociateACPDU::AddPresentationContextAC( PresentationContextAC const &pcac ) { PresContextAC.push_back( pcac ); PDULength = (uint32_t)(Size() - 6); assert( PDULength + 4 + 1 + 1 == Size() ); } void AAssociateACPDU::Print(std::ostream &os) const { os << "ProtocolVersion: " << std::hex << ProtocolVersion << std::dec << std::endl; os << "Reserved9_10: " << std::hex << Reserved9_10 << std::dec << std::endl; os << "Reserved11_26: [" << std::string(Reserved11_26,sizeof(Reserved11_26)) << "]" << std::endl; os << "Reserved27_42: [" << std::string(Reserved27_42,sizeof(Reserved27_42)) << "]" << std::endl; /*os << "Reserved43_74: [" << std::string(Reserved43_74,sizeof(Reserved43_74)) << "]" << std::endl;*/ os << "Application Context Name: "; AppContext.Print( os ); os << "List of PresentationContextAC: " << std::endl; std::vector::const_iterator it = PresContextAC.begin(); for( ; it != PresContextAC.end(); ++it ) { it->Print(os); } os << "User Information: "; UserInfo.Print( os ); } void AAssociateACPDU::InitFromRQ( AAssociateRQPDU const & rqpdu ) { // Table 9-17 ASSOCIATE-AC PDU fields // This reserved field shall be sent with a value identical to the value // received in the same field of the A-ASSOCIATE-RQ PDU const std::string called = rqpdu.GetCalledAETitle(); SetCalledAETitle( rqpdu.GetCalledAETitle().c_str() ); const std::string calling = rqpdu.GetCallingAETitle(); SetCallingAETitle( rqpdu.GetCallingAETitle().c_str() ); const std::string reserved = rqpdu.GetReserved43_74(); memcpy( Reserved43_74, reserved.c_str(), sizeof(Reserved43_74) ); assert( ProtocolVersion == 0x01 ); assert( Reserved9_10 == 0x0 ); assert( memcmp( Reserved11_26, called.c_str(), sizeof( Reserved11_26) ) == 0 ); assert( memcmp( Reserved27_42, calling.c_str(), sizeof(Reserved27_42) ) == 0 ); assert( memcmp( Reserved43_74, reserved.c_str(), sizeof(Reserved43_74) ) == 0 ); } void AAssociateACPDU::InitSimple( AAssociateRQPDU const & rqpdu ) { TransferSyntaxSub ts1; ts1.SetNameFromUID( UIDs::ImplicitVRLittleEndianDefaultTransferSyntaxforDICOM ); assert( rqpdu.GetNumberOfPresentationContext() ); for( unsigned int index = 0; index < rqpdu.GetNumberOfPresentationContext(); index++ ) { // FIXME / HARDCODED We only ever accept Little Endian // FIXME we should check : // rqpdu.GetAbstractSyntax() contains LittleEndian PresentationContextAC pcac1; PresentationContextRQ const &pc = rqpdu.GetPresentationContext(index); uint8_t id = pc.GetPresentationContextID(); pcac1.SetPresentationContextID( id ); // DCMTK MR pcac1.SetTransferSyntax( ts1 ); AddPresentationContextAC( pcac1 ); } } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAAssociateACPDU.h000066400000000000000000000064141412732066400244140ustar00rootroot00000000000000/*========================================================================= 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 GDCMAASSOCIATEACPDU_H #define GDCMAASSOCIATEACPDU_H #include "gdcmTypes.h" #include "gdcmApplicationContext.h" #include "gdcmPresentationContextAC.h" #include "gdcmUserInformation.h" #include "gdcmBasePDU.h" #include namespace gdcm { namespace network { class AAssociateRQPDU; /** * \brief AAssociateACPDU * \details Table 9-17 * ASSOCIATE-AC PDU fields */ class AAssociateACPDU : public BasePDU { public: AAssociateACPDU(); std::istream &Read(std::istream &is) override; const std::ostream &Write(std::ostream &os) const override; void AddPresentationContextAC( PresentationContextAC const &pcac ); typedef std::vector::size_type SizeType; const PresentationContextAC &GetPresentationContextAC( SizeType i ) { assert( !PresContextAC.empty() && i < PresContextAC.size() ); return PresContextAC[i]; } SizeType GetNumberOfPresentationContextAC() const { return PresContextAC.size(); } const UserInformation &GetUserInformation() const { return UserInfo; } SizeType Size() const override; void Print(std::ostream &os) const override; bool IsLastFragment() const override { return true; } void InitFromRQ( AAssociateRQPDU const & rqpdu ); protected: friend class AAssociateRQPDU; void SetCalledAETitle(const char calledaetitle[16]); void SetCallingAETitle(const char callingaetitle[16]); private: void InitSimple( AAssociateRQPDU const & rqpdu ); private: static const uint8_t ItemType; // PDUType ? static const uint8_t Reserved2; uint32_t PDULength; // len of static const uint16_t ProtocolVersion; static const uint16_t Reserved9_10; // This reserved field shall be sent with a value identical to the value // received in the same field of the A-ASSOCIATE-RQ PDU, but its value // shall not be tested when received. char Reserved11_26[16]; // This reserved field shall be sent with a value identical to the value // received in the same field of the A-ASSOCIATE-RQ PDU, but its value // shall not be tested when received. char Reserved27_42[16]; // This reserved field shall be sent with a value identical to the value // received in the same field of the A-ASSOCIATE-RQ PDU, but its value // shall not be tested when received. char Reserved43_74[32]; /* 75-xxx Variable items This variable field shall contain the following items: one Application Context Item, one or more Presentation Context Item(s) and one User Information Item. For a complete description of these items see Sections 7.1.1.2, 7.1.1.14, and 7.1.1.6. */ ApplicationContext AppContext; std::vector PresContextAC; UserInformation UserInfo; }; } // end namespace network } // end namespace gdcm #endif //GDCMAASSOCIATEACPDU_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAAssociateRJPDU.cxx000066400000000000000000000073501412732066400250170ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAAssociateRJPDU.h" #include "gdcmSwapper.h" namespace gdcm { namespace network { const uint8_t AAssociateRJPDU::ItemType = 0x03; // PDUType ? const uint8_t AAssociateRJPDU::Reserved2 = 0x00; const uint8_t AAssociateRJPDU::Reserved8 = 0x00; AAssociateRJPDU::AAssociateRJPDU() { ItemLength = 0; Result = 0; Source = 0; Reason = 0; // diag ? } std::istream &AAssociateRJPDU::Read(std::istream &is) { //uint8_t itemtype = 0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2; is >> reserved2; uint32_t itemlength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; uint8_t reserved8; is >> reserved8; uint8_t result; is >> result; Result = result; uint8_t source; is >> source; Source = source; uint8_t reason; is >> reason; Reason = reason; //assert( ItemLength + 4 + 1 + 1 == Size() ); return is; } const std::ostream &AAssociateRJPDU::Write(std::ostream &os) const { return os; } namespace { static const char *PrintResultAsString( uint8_t result ) { switch( result ) { case 0x1: return "rejected-permanent"; case 0x2: return "rejected-transient"; } assert( 0 ); return nullptr; } static const char *PrintSourceAsString( uint8_t source ) { switch( source ) { case 0x0: return "DICOM UL service-user"; case 0x1: return "DICOM UL service-provider (ACSE related function)"; case 0x2: return "DICOM UL service-provider (Presentation related function)"; } assert( 0 ); return nullptr; } static const char *PrintReasonAsString( uint8_t source, uint8_t reason ) { switch( source ) { case 0x1: switch( reason ) { case 0x1: return "1 - no-reason-given"; case 0x2: return "2 - application-context-name-not-supported"; case 0x3: return "3 - calling-AE-title-not-recognized"; case 0x4: case 0x5: case 0x6: return "4-6 - reserved"; case 0x7: return "7 - called-AE-title-not-recognized"; case 0x8: case 0x9: case 0xa: return "8-10 - reserved"; } break; case 0x2: switch( reason ) { case 0x1: return "no-reason-given"; case 0x2: return "protocol-version-not-supported"; } break; case 0x3: switch( reason ) { case 0x0: return "0 - reserved"; case 0x1: return "1 - temporary-congestion"; case 0x2: return "2 - local-limit-exceeded"; case 0x3: case 0x4: case 0x5: case 0x6: case 0x7: return "3-7 - reserved"; } } assert( 0 ); return nullptr; } } void AAssociateRJPDU::Print(std::ostream &os) const { os << "PDULength: " << ItemLength << std::endl; os << "Result: " << PrintResultAsString( Result ) << std::endl; os << "Source: " << PrintSourceAsString( Source ) << std::endl; os << "Reason: " << PrintReasonAsString( Source, Reason ) << std::endl; } size_t AAssociateRJPDU::Size() const{ return sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint32_t)+ sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint8_t); } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAAssociateRJPDU.h000066400000000000000000000026231412732066400244420ustar00rootroot00000000000000/*========================================================================= 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 GDCMAASSOCIATERJPDU_H #define GDCMAASSOCIATERJPDU_H #include "gdcmTypes.h" #include "gdcmBasePDU.h" namespace gdcm { namespace network { /** * \brief AAssociateRJPDU * \details Table 9-21 * ASSOCIATE-RJ PDU FIELDS */ class AAssociateRJPDU : public BasePDU { public: AAssociateRJPDU(); std::istream &Read(std::istream &is) override; const std::ostream &Write(std::ostream &os) const override; void Print(std::ostream &os) const override; size_t Size() const override; bool IsLastFragment() const override { return true; } private: static const uint8_t ItemType; // PDUType ? static const uint8_t Reserved2; uint32_t ItemLength; // PDU Length ? static const uint8_t Reserved8; uint8_t Result; uint8_t Source; uint8_t Reason; // diag ? }; } // end namespace network } // end namespace gdcm #endif //GDCMAASSOCIATERJPDU_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAAssociateRQPDU.cxx000066400000000000000000000225021412732066400250220ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAAssociateRQPDU.h" #include "gdcmSwapper.h" #include "gdcmAAssociateACPDU.h" #include #include namespace gdcm { /* 9.3.2 A-ASSOCIATE-RQ PDU STRUCTURE An A-ASSOCIATE-RQ PDU shall be made of a sequence of mandatory fields followed by a variable length field. Table 9-11 shows the sequence of the mandatory fields. The variable field shall consist of one Application Context Item, one or more Presentation Context Items, and one User Information Item. Sub-Items shall exist for the Presentation Context and User Information Items. */ namespace network { const uint8_t AAssociateRQPDU::ItemType = 0x1; // PDUType ? const uint8_t AAssociateRQPDU::Reserved2 = 0x0; const uint16_t AAssociateRQPDU::ProtocolVersion = 0x1; // big - endian ? const uint16_t AAssociateRQPDU::Reserved9_10 = 0x0; //const uint8_t AAssociateRQPDU::Reserved43_74[32] = {}; AAssociateRQPDU::AAssociateRQPDU() { memset(CalledAETitle, ' ', sizeof(CalledAETitle)); //const char called[] = "ANY-SCP"; //strncpy(CalledAETitle, called, strlen(called) ); memset(CallingAETitle, ' ', sizeof(CallingAETitle)); //const char calling[] = "ECHOSCU"; //strncpy(CallingAETitle, calling, strlen(calling) ); memset(Reserved43_74, 0x0, sizeof(Reserved43_74)); //SetCallingAETitle( "MOVESCU" ); ItemLength = (uint32_t)Size() - 6; assert( (ItemLength + 4 + 1 + 1) == Size() ); } std::istream &AAssociateRQPDU::Read(std::istream &is) { //uint8_t itemtype = 0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2; is >> reserved2; uint32_t itemlength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; uint16_t protocolversion; is.read( (char*)&protocolversion, sizeof(ProtocolVersion) ); SwapperDoOp::SwapArray(&protocolversion,1); if( protocolversion != ProtocolVersion ) { gdcmWarningMacro( "ProtocolVersion is: " << protocolversion ); } uint16_t reserved9_10; is.read( (char*)&reserved9_10, sizeof(Reserved9_10) ); SwapperDoOp::SwapArray(&reserved9_10,1); //char calledaetitle[16]; is.read( (char*)&CalledAETitle, sizeof(CalledAETitle) ); // called //char callingaetitle[16]; is.read( (char*)&CallingAETitle, sizeof(CallingAETitle) ); // calling uint8_t reserved43_74[32] = { }; is.read( (char*)&reserved43_74, sizeof(Reserved43_74) ); // 0 (32 times) memcpy( Reserved43_74, reserved43_74, sizeof(Reserved43_74) ); uint8_t itemtype2 = 0x0; size_t curlen = 0; while( curlen + 68 < ItemLength ) { is.read( (char*)&itemtype2, sizeof(ItemType) ); switch ( itemtype2 ) { case 0x10: // ApplicationContext ItemType AppContext.Read( is ); curlen += AppContext.Size(); break; case 0x20: // PresentationContextRQ ItemType { PresentationContextRQ pc; pc.Read( is ); PresContext.push_back( pc ); curlen += pc.Size(); } break; case 0x50: // UserInformation ItemType UserInfo.Read( is ); curlen += UserInfo.Size(); break; default: gdcmErrorMacro( "Unknown ItemType: " << std::hex << (int) itemtype2 ); curlen = ItemLength; // make sure to exit break; } // WARNING: I cannot simply call Size() since UserInfo is initialized with GDCM // own parameter, this will bias the computation. Instead compute relative // length of remaining bytes to read. //curlen = Size(); } assert( curlen + 68 == ItemLength ); assert( ItemLength + 4 + 1 + 1 == Size() ); return is; } const std::ostream &AAssociateRQPDU::Write(std::ostream &os) const { assert( ItemLength + 4 + 1 + 1 == Size() ); #if 0 // Need to check all context Id are ordered ? and odd number ? std::vector::const_iterator it = PresContext.begin(); for( ; it != PresContext.end(); ++it) { it->Write(os); } #endif os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); uint32_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); uint16_t protocolversion = ProtocolVersion; SwapperDoOp::SwapArray(&protocolversion,1); os.write( (const char*)&protocolversion, sizeof(ProtocolVersion) ); os.write( (const char*)&Reserved9_10, sizeof(Reserved9_10) ); assert( AAssociateRQPDU::IsAETitleValid(CalledAETitle) ); os.write( CalledAETitle, 16 ); assert( AAssociateRQPDU::IsAETitleValid(CallingAETitle) ); os.write( CallingAETitle, 16 ); os.write( (const char*)&Reserved43_74, sizeof(Reserved43_74) ); AppContext.Write(os); std::vector::const_iterator it = PresContext.begin(); for( ; it != PresContext.end(); ++it) { it->Write(os); } UserInfo.Write(os); return os; } size_t AAssociateRQPDU::Size() const { size_t ret = 0; ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); ret += sizeof(ProtocolVersion); ret += sizeof(Reserved9_10); ret += sizeof(CalledAETitle); ret += sizeof(CallingAETitle); ret += sizeof(Reserved43_74); ret += AppContext.Size(); std::vector::const_iterator it = PresContext.begin(); for( ; it != PresContext.end(); ++it) { ret += it->Size(); } ret += UserInfo.Size(); return ret; } bool AAssociateRQPDU::IsAETitleValid(const char title[16]) { if(!title) return false; #if 0 std::string s ( title, 16 ); // check no \0 : //size_t len = strlen( s.c_str() ); // FIXME: // if( len != 16 ) return false; std::locale loc; std::string str = s; for (size_t i=0; i < str.size(); ++i) { str[i] = std::toupper(str[i],loc); } if( str != s ) return false; #else const size_t reallen = strlen( title ); std::string s ( title, std::min(reallen, (size_t)16) ); // check no \0 : size_t len = strlen( s.c_str() ); char OnlySpaces[16]; memset(OnlySpaces, ' ', sizeof(OnlySpaces)); if( strncmp( title, OnlySpaces, len ) == 0 ) { return false; } #endif return true; } void AAssociateRQPDU::AddPresentationContext( PresentationContextRQ const &pc ) { PresContext.push_back( pc ); ItemLength = (uint32_t)Size() - 6; assert( (ItemLength + 4 + 1 + 1) == Size() ); } void AAssociateRQPDU::SetCalledAETitle(const char calledaetitle[16]) { assert( AAssociateRQPDU::IsAETitleValid(calledaetitle) ); size_t len = strlen( calledaetitle ); if( len <= 16 ) { memset(CalledAETitle, ' ', sizeof(CalledAETitle)); memcpy(CalledAETitle, calledaetitle, len ); } // FIXME Need to check upper case // FIXME cannot set to only whitespaces } void AAssociateRQPDU::SetCallingAETitle(const char callingaetitle[16]) { assert( AAssociateRQPDU::IsAETitleValid(callingaetitle) ); size_t len = strlen( callingaetitle ); if( len <= 16 ) { memset(CallingAETitle, ' ', sizeof(CallingAETitle)); memcpy(CallingAETitle, callingaetitle, len ); } // FIXME Need to check upper case // FIXME cannot set to only whitespaces } std::string AAssociateRQPDU::GetReserved43_74() const { return std::string(Reserved43_74,32); } void AAssociateRQPDU::Print(std::ostream &os) const { //static const uint8_t ItemType; // PDUType ? //static const uint8_t Reserved2; //uint32_t ItemLength; // PDU Length //static const uint16_t ProtocolVersion; //static const uint16_t Reserved9_10; os << "CalledAETitle: "; os << GetCalledAETitle() << std::endl; os << "CallingAETitle: "; os << GetCallingAETitle() << std::endl; //static const uint8_t Reserved43_74[32]; // { 0 } os << "ApplicationContext: "; AppContext.Print( os ); os << std::endl; //std::vector PresContext; os << "PresentationContext(s): "; std::vector::const_iterator it = PresContext.begin(); for( ; it != PresContext.end(); ++it) { it->Print( os << std::endl ); } os << "UserInformation: "; UserInfo.Print( os ); os << std::endl; } const PresentationContextRQ *AAssociateRQPDU::GetPresentationContextByID(uint8_t id) const { std::vector::const_iterator it = PresContext.begin(); for( ; it != PresContext.end(); ++it) { if( it->GetPresentationContextID() == id ) { return &*it; } } return nullptr; } const PresentationContextRQ *AAssociateRQPDU::GetPresentationContextByAbstractSyntax(AbstractSyntax const & as ) const { std::vector::const_iterator it = PresContext.begin(); for( ; it != PresContext.end(); ++it) { if( it->GetAbstractSyntax() == as ) { return &*it; } } return nullptr; } void AAssociateRQPDU::SetUserInformation( UserInformation const & ui ) { UserInfo = ui; ItemLength = (uint32_t)Size() - 6; assert( (ItemLength + 4 + 1 + 1) == Size() ); } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAAssociateRQPDU.h000066400000000000000000000127141412732066400244530ustar00rootroot00000000000000/*========================================================================= 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 GDCMAASSOCIATERQPDU_H #define GDCMAASSOCIATERQPDU_H #include "gdcmTypes.h" #include "gdcmVR.h" // AEComp #include "gdcmApplicationContext.h" #include "gdcmPresentationContextRQ.h" #include "gdcmUserInformation.h" #include "gdcmBasePDU.h" namespace gdcm { namespace network { class AAssociateACPDU; /** * \brief AAssociateRQPDU * \details Table 9-11 ASSOCIATE-RQ PDU fields */ class AAssociateRQPDU : public BasePDU { public: AAssociateRQPDU(); std::istream &Read(std::istream &is) override; const std::ostream &Write(std::ostream &os) const override; size_t Size() const override; void AddPresentationContext( PresentationContextRQ const &pc ); /// Set the Called AE Title void SetCalledAETitle(const char calledaetitle[16]); std::string GetCalledAETitle() const { return std::string(CalledAETitle,16); } /// Set the Calling AE Title void SetCallingAETitle(const char callingaetitle[16]); std::string GetCallingAETitle() const { return std::string(CallingAETitle,16); } /// Check whether or not the \param title is a valid AE title static bool IsAETitleValid(const char title[16]); /// This function will initialize an AAssociateACPDU from /// the fields in the AAssociateRQPDU structure //void InitFromRQ( AAssociateACPDU & acpdu ); void Print(std::ostream &os) const override; AAssociateRQPDU(const AAssociateRQPDU &pdu):BasePDU(pdu) { assert( 0 ); } //this function fails to compile on windows. // AAssociateRQPDU &operator=(const AAssociateRQPDU &_val) // { // assert( 0 ); // } typedef std::vector::size_type SizeType; SizeType GetNumberOfPresentationContext() const { return PresContext.size(); } PresentationContextRQ const &GetPresentationContext(SizeType i) const { assert( !PresContext.empty() && i < PresContext.size() ); return PresContext[i]; } typedef std::vector PresentationContextArrayType; PresentationContextArrayType const &GetPresentationContexts() { return PresContext; } const PresentationContextRQ *GetPresentationContextByID(uint8_t i) const; const PresentationContextRQ *GetPresentationContextByAbstractSyntax(AbstractSyntax const & absyn ) const; bool IsLastFragment() const override { return true; } const UserInformation & GetUserInformation() const { return UserInfo; } void SetUserInformation( UserInformation const & ui ); protected: friend class AAssociateACPDU; std::string GetReserved43_74() const; private: // 1 PDU-type 01H static const uint8_t ItemType; // PDUType ? // 2 Reserved This reserved field shall be sent with a value 00H but not tested to this value when received. static const uint8_t Reserved2; /* 3-6 PDU-length This PDU-length shall be the number of bytes from the first byte of the following field to the last byte of the variable field. It shall be encoded as an unsigned binary number */ uint32_t ItemLength; // PDU Length /* 7-8 Protocol-version This two byte field shall use one bit to identify each version of the DICOM UL protocol supported by the calling end-system. This is Version 1 and shall be identified with bit 0 set. A receiver of this PDU implementing only this version of the DICOM UL protocol shall only test that bit 0 is set. */ static const uint16_t ProtocolVersion; /* 9-10 Reserved This reserved field shall be sent with a value 0000H but not tested to this value when received. */ static const uint16_t Reserved9_10; /* 11-26 Called-AE-title Destination DICOM Application Name. It shall be encoded as 16 characters as defined by the ISO 646:1990-Basic G0 Set with leading and trailing spaces (20H) being non-significant. The value made of 16 spaces (20H) meaning "no Application Name specified" shall not be used. For a complete description of the use of this field, see Section 7.1.1.4. */ char CalledAETitle[16]; /* 27-42 Calling-AE-title Source DICOM Application Name. It shall be encoded as 16 characters as defined by the ISO 646:1990-Basic G0 Set with leading and trailing spaces (20H) being non-significant. The value made of 16 spaces (20H) meaning "no Application Name specified" shall not be used. For a complete description of the use of this field, see Section 7.1.1.3. */ char CallingAETitle[16]; /* 43-74 Reserved This reserved field shall be sent with a value 00H for all bytes but not tested to this value when received */ char Reserved43_74[32]; // { 0 } /* 75-xxx Variable items This variable field shall contain the following items: one Application Context Item, one or more Presentation Context Items and one User Information Item. For a complete description of the use of these items see Sections 7.1.1.2, 7.1.1.13, and 7.1.1.6. */ ApplicationContext AppContext; std::vector PresContext; UserInformation UserInfo; }; } // end namespace network } // end namespace gdcm #endif //GDCMAASSOCIATERQPDU_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmARTIMTimer.cxx000066400000000000000000000044331412732066400240520ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /* This file contains the code for the ARTIM timer. Basically, the ARTIM timer will just get the wall time when it's started, and then can be queried for the current time, and then can be stopped (ie, the start time reset). Because we're trying to do this without threading, we should be able to 'start' the ARTIM timer by this mechanism, and then when waiting for a particular response, tight loop that with sleep calls and determinations of when the ARTIM timer has reached its peak. As such, this isn't a strict 'timer' in the traditional sense of the word, but more of a time keeper. */ #include "gdcmARTIMTimer.h" #include "gdcmSystem.h" namespace gdcm { namespace network { //initiates the start and timeout at -1; ARTIMTimer::ARTIMTimer(){ mStartTime = 0; mTimeOut = 0; } double ARTIMTimer::GetCurrentTime() const{ return 0; //platform-specific timing functions go here... } void ARTIMTimer::Start(){ mStartTime = GetCurrentTime(); } void ARTIMTimer::SetTimeout(double inTimeOut){ mTimeOut = inTimeOut; } double ARTIMTimer::GetTimeout() const{ return mTimeOut; } double ARTIMTimer::GetElapsedTime() const{ if (mStartTime > 0){ return GetCurrentTime() - mStartTime; } else { return -1; //not started yet } } bool ARTIMTimer::GetHasExpired() const{ double theElapsed = GetElapsedTime(); if (theElapsed > 0){ return theElapsed > mTimeOut; } else { return false; //not started yet } } void ARTIMTimer::Stop() { mStartTime = -1;//stop the timer by resetting it. } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmARTIMTimer.h000066400000000000000000000047261412732066400235040ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMARTIMTIMER_H #define GDCMARTIMTIMER_H namespace gdcm { namespace network{ /** \brief ARTIMTimer * \details This file contains the code for the ARTIM timer. * * Basically, the ARTIM timer will just get the wall time when it's started, * and then can be queried for the current time, and then can be stopped (ie, * the start time reset). * * Because we're trying to do this without threading, we should be able to 'start' the * ARTIM timer by this mechanism, and then when waiting for a particular response, tight * loop that with sleep calls and determinations of when the ARTIM timer has reached its * peak. As such, this isn't a strict 'timer' in the traditional sense of the word, * but more of a time keeper. * * There can be only one ARTIM timer per connection. */ class ARTIMTimer { private: double mStartTime; //ms timing should be good enough, but there are also //high-resolution timing options. Those return doubles. For now, //go with integer timing solutions based on milliseconds (DWORD on windows), //but leave as doubles to ease transitions to other timing methods. double mTimeOut; //once GetCurrentTime() -mStartTime > mTimeout, GetHasExpired returns true. double GetCurrentTime() const;//a platform-specific implementation of getting the //current time. public: ARTIMTimer(); //initiates the start and timeout at -1; void Start(); //'start' the timer by getting the current wall time void Stop();//'stop' the timer by resetting the 'start' to -1; void SetTimeout(double inTimeout); double GetTimeout() const; double GetElapsedTime() const; bool GetHasExpired() const; }; } } #endif //GDCMARTIMTIMER_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAReleaseRPPDU.cxx000066400000000000000000000043131412732066400244660ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAReleaseRPPDU.h" #include "gdcmSwapper.h" namespace gdcm { namespace network { const uint8_t AReleaseRPPDU::ItemType = 0x6; // PDUType ? const uint8_t AReleaseRPPDU::Reserved2 = 0x0; const uint32_t AReleaseRPPDU::Reserved7_10 = 0x0; AReleaseRPPDU::AReleaseRPPDU() { ItemLength = (uint32_t)(Size() - 6); // PDU Length assert( ItemLength + 6 == Size() ); } std::istream &AReleaseRPPDU::Read(std::istream &is) { //uint8_t itemtype = 0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2 = 0; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint32_t itemlength = ItemLength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; uint32_t reserved7_10; is.read( (char*)&reserved7_10, sizeof(Reserved7_10) ); assert( ItemLength + 6 == Size() ); return is; } const std::ostream &AReleaseRPPDU::Write(std::ostream &os) const { os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); uint32_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); os.write( (const char*)&Reserved7_10, sizeof(Reserved7_10) ); assert( ItemLength + 6 == Size() ); return os; } size_t AReleaseRPPDU::Size() const { size_t ret = 0; ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); // len of ret += sizeof(Reserved7_10); return ret; } void AReleaseRPPDU::Print(std::ostream &os) const { os << "PDULength: " << ItemLength << std::endl; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAReleaseRPPDU.h000066400000000000000000000025111412732066400241110ustar00rootroot00000000000000/*========================================================================= 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 GDCMARELEASERPPDU_H #define GDCMARELEASERPPDU_H #include "gdcmTypes.h" #include "gdcmBasePDU.h" namespace gdcm { namespace network { /** * \brief AReleaseRPPDU * \details Table 9-25 * A-RELEASE-RP PDU fields */ class AReleaseRPPDU : public BasePDU { public: AReleaseRPPDU(); std::istream &Read(std::istream &is) override; const std::ostream &Write(std::ostream &os) const override; size_t Size() const override; void Print(std::ostream &os) const override; bool IsLastFragment() const override { return true; } private: static const uint8_t ItemType; // PDUType ? static const uint8_t Reserved2; uint32_t ItemLength; // PDU Length static const uint32_t Reserved7_10; }; } // end namespace network } // end namespace gdcm #endif //GDCMARELEASERPPDU_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAReleaseRQPDU.cxx000066400000000000000000000043341412732066400244720ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAReleaseRQPDU.h" #include "gdcmSwapper.h" namespace gdcm { namespace network { const uint8_t AReleaseRQPDU::ItemType = 0x5; // PDUType ? const uint8_t AReleaseRQPDU::Reserved2 = 0x0; const uint32_t AReleaseRQPDU::Reserved7_10 = 0x0; AReleaseRQPDU::AReleaseRQPDU() { ItemLength = (uint32_t)(Size() - 6); // PDU Length assert( ItemLength + 6 == Size() ); } std::istream &AReleaseRQPDU::Read(std::istream &is) { //uint8_t itemtype = 0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2 = 0; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint32_t itemlength = ItemLength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; uint32_t reserved7_10; is.read( (char*)&reserved7_10, sizeof(Reserved7_10) ); assert( ItemLength + 6 == Size() ); return is; } const std::ostream &AReleaseRQPDU::Write(std::ostream &os) const { os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); uint32_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); os.write( (const char*)&Reserved7_10, sizeof(Reserved7_10) ); assert( ItemLength + 6 == Size() ); return os; } size_t AReleaseRQPDU::Size() const { size_t ret = 0; ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); // len of ret += sizeof(Reserved7_10); return ret; } void AReleaseRQPDU::Print(std::ostream &os) const { os << "AReleaseRQ PDU printing not implemented yet" << std::endl; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAReleaseRQPDU.h000066400000000000000000000025111412732066400241120ustar00rootroot00000000000000/*========================================================================= 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 GDCMARELEASERQPDU_H #define GDCMARELEASERQPDU_H #include "gdcmTypes.h" #include "gdcmBasePDU.h" namespace gdcm { namespace network { /** * \brief AReleaseRQPDU * \details Table 9-24 * A-RELEASE-RQ PDU FIELDS */ class AReleaseRQPDU : public BasePDU { public: AReleaseRQPDU(); std::istream &Read(std::istream &is) override; const std::ostream &Write(std::ostream &os) const override; size_t Size() const override; void Print(std::ostream &os) const override; bool IsLastFragment() const override { return true; } private: static const uint8_t ItemType; // PDUType ? static const uint8_t Reserved2; uint32_t ItemLength; // PDU Length static const uint32_t Reserved7_10; }; } // end namespace network } // end namespace gdcm #endif //GDCMARELEASERQPDU_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAbstractSyntax.cxx000066400000000000000000000063211412732066400251450ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAbstractSyntax.h" #include "gdcmSwapper.h" #include namespace gdcm { namespace network { const uint8_t AbstractSyntax::ItemType = 0x30; const uint8_t AbstractSyntax::Reserved2 = 0x00; AbstractSyntax::AbstractSyntax() { //UpdateName ( "1.2.840.10008.1.1" ); // Verification SOP Class ItemLength = 0; } std::istream &AbstractSyntax::Read(std::istream &is) { uint8_t itemtype = 0x0; is.read( (char*)&itemtype, sizeof(ItemType) ); assert( itemtype == ItemType ); uint8_t reserved2; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint16_t itemlength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; char name[256]; assert( itemlength < 256 ); is.read( name, itemlength ); Name = std::string(name,itemlength); return is; } const std::ostream &AbstractSyntax::Write(std::ostream &os) const { os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); //os.write( (const char*)&ItemLength, sizeof(ItemLength) ); uint16_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); os.write( Name.c_str(), Name.size() ); return os; } size_t AbstractSyntax::Size() const { size_t ret = 0; assert( Name.size() == ItemLength ); ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); ret += ItemLength; assert(ret <= (size_t)std::numeric_limits::max); assert(ret >= 4); return ret; } void AbstractSyntax::UpdateName( const char *name ) { if( name ) { UIDs uids; bool b = uids.SetFromUID( name ); if( b ) { Name = name; size_t lenTemp = Name.size(); assert(lenTemp < (size_t)std::numeric_limits::max); ItemLength = (uint16_t)lenTemp; assert( (size_t)ItemLength + 4 == Size() ); return; } } gdcmErrorMacro( "Invalid Name: " << name ); throw "Invalid Name"; } void AbstractSyntax::SetNameFromUID( UIDs::TSName tsname ) { const char *name = UIDs::GetUIDString( tsname ); UpdateName( name ); } //void AbstractSyntax::SetNameFromUIDString( const std::string& inUIDName ) //{ // const char *name = inUIDName.c_str(); // UpdateName( name ); //} void AbstractSyntax::Print(std::ostream &os) const { os << Name << std::endl; } DataElement AbstractSyntax::GetAsDataElement() const { DataElement de( Tag(0x0,0x2) ); de.SetVR( VR::UI ); std::string suid; suid = Name; if( suid.size() % 2 ) suid.push_back( 0 ); de.SetByteValue( suid.c_str(), (uint32_t)suid.size() ); return de; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAbstractSyntax.h000066400000000000000000000034341412732066400245740ustar00rootroot00000000000000/*========================================================================= 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 GDCMABSTRACTSYNTAX_H #define GDCMABSTRACTSYNTAX_H #include "gdcmTypes.h" #include "gdcmUIDs.h" #include "gdcmDataElement.h" namespace gdcm { namespace network { /** * \brief AbstractSyntax * \details Table 9-14 * ABSTRACT SYNTAX SUB-ITEM FIELDS */ class AbstractSyntax { public: AbstractSyntax(); std::istream &Read(std::istream &is); const std::ostream &Write(std::ostream &os) const; void SetName( const char *name ) { UpdateName( name ); } const char *GetName() const { return Name.c_str(); } // accept a UIDs::TSType also... void SetNameFromUID( UIDs::TSName tsname ); //now that the PresentationContext messes around with UIDs and returns a string //use that string as well. //void SetNameFromUIDString( const std::string& inUIDName ); size_t Size() const; void Print(std::ostream &os) const; bool operator==(const AbstractSyntax & as) const { return Name == as.Name; } DataElement GetAsDataElement() const; private: void UpdateName( const char *name ); static const uint8_t ItemType; static const uint8_t Reserved2; uint16_t ItemLength; // len of std::string /*AbstractSyntax*/ Name; // UID }; } // end namespace network } // end namespace gdcm #endif //GDCMABSTRACTSYNTAX_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmApplicationContext.cxx000066400000000000000000000051071412732066400260040ustar00rootroot00000000000000/*========================================================================= 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 "gdcmApplicationContext.h" #include "gdcmSwapper.h" #include namespace gdcm { namespace network { const uint8_t ApplicationContext::ItemType = 0x10; const uint8_t ApplicationContext::Reserved2 = 0x00; // PS 3.7 - 2011 // A.2.1 DICOM Registered Application Context Names static const char DICOMApplicationContextName[] = "1.2.840.10008.3.1.1.1"; ApplicationContext::ApplicationContext() { UpdateName( DICOMApplicationContextName ); } std::istream &ApplicationContext::Read(std::istream &is) { //uint8_t itemtype = 0x0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2 = 0x0; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint16_t itemlength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; char name[256]; assert( itemlength < 256 ); is.read( name, ItemLength ); Name = std::string(name,itemlength); assert( Name == DICOMApplicationContextName ); return is; } const std::ostream &ApplicationContext::Write(std::ostream &os) const { os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); uint16_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); assert( Name == DICOMApplicationContextName ); os.write( Name.c_str(), Name.size() ); return os; } size_t ApplicationContext::Size() const { size_t ret = 0; assert( Name.size() == ItemLength ); ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); ret += ItemLength; return ret; } void ApplicationContext::UpdateName( const char *name ) { if( name ) { Name = name; assert( Name.size() < std::numeric_limits::max() ); ItemLength = (uint16_t)Name.size(); assert( (size_t)ItemLength + 4 == Size() ); } } void ApplicationContext::Print(std::ostream &os) const { os << Name << std::endl; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmApplicationContext.h000066400000000000000000000030761412732066400254340ustar00rootroot00000000000000/*========================================================================= 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 GDCMAPPLICATIONCONTEXT_H #define GDCMAPPLICATIONCONTEXT_H #include "gdcmTypes.h" namespace gdcm { namespace network { /** * \brief ApplicationContext * \details Table 9-12 * APPLICATION CONTEXT ITEM FIELDS * \todo * Looks like Application Context can only be 64 bytes at max (see Figure 9-1 / PS 3.8 - 2009 ) */ class ApplicationContext { public: ApplicationContext(); std::istream &Read(std::istream &is); const std::ostream &Write(std::ostream &os) const; void SetName( const char *name ) { UpdateName( name ); } const char *GetName() const { return Name.c_str(); } size_t Size() const; //static const uint8_t GetItemType() { return ItemType; } void Print(std::ostream &os) const; private: void UpdateName( const char *name ); static const uint8_t ItemType; static const uint8_t Reserved2; uint16_t ItemLength; // len of application context name std::string /*ApplicationContext*/ Name; // UID }; } // end namespace network } // end namespace gdcm #endif //GDCMAPPLICATIONCONTEXT_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAsynchronousOperationsWindowSub.cxx000066400000000000000000000067071412732066400306040ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAsynchronousOperationsWindowSub.h" #include "gdcmFileMetaInformation.h" #include "gdcmSwapper.h" namespace gdcm { namespace network { const uint8_t AsynchronousOperationsWindowSub::ItemType = 0x53; const uint8_t AsynchronousOperationsWindowSub::Reserved2 = 0x00; AsynchronousOperationsWindowSub::AsynchronousOperationsWindowSub() { ItemLength = 0; MaximumNumberOperationsInvoked = 0; MaximumNumberOperationsPerformed = 0; ItemLength = (uint16_t)(Size() - 4); assert( (size_t)ItemLength + 4 == Size() ); } std::istream &AsynchronousOperationsWindowSub::Read(std::istream &is) { //uint8_t itemtype = 0x0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint16_t itemlength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; uint16_t maximumnumberoperationsinvoked; is.read( (char*)&maximumnumberoperationsinvoked, sizeof(MaximumNumberOperationsInvoked) ); SwapperDoOp::SwapArray(&maximumnumberoperationsinvoked,1); MaximumNumberOperationsInvoked = maximumnumberoperationsinvoked; uint16_t maximumnumberoperationsperformed; is.read( (char*)&maximumnumberoperationsperformed, sizeof(MaximumNumberOperationsPerformed) ); SwapperDoOp::SwapArray(&maximumnumberoperationsperformed,1); MaximumNumberOperationsPerformed = maximumnumberoperationsperformed; return is; } const std::ostream &AsynchronousOperationsWindowSub::Write(std::ostream &os) const { os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); //os.write( (const char*)&ItemLength, sizeof(ItemLength) ); uint16_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); uint16_t maximumnumberoperationsinvoked = MaximumNumberOperationsInvoked; SwapperDoOp::SwapArray(&maximumnumberoperationsinvoked,1); os.write( (const char*)&maximumnumberoperationsinvoked, sizeof(MaximumNumberOperationsInvoked) ); uint16_t maximumnumberoperationsperformed = MaximumNumberOperationsPerformed; SwapperDoOp::SwapArray(&maximumnumberoperationsperformed,1); os.write( (const char*)&maximumnumberoperationsperformed, sizeof(MaximumNumberOperationsPerformed) ); return os; } size_t AsynchronousOperationsWindowSub::Size() const { size_t ret = 0; ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); ret += sizeof(MaximumNumberOperationsInvoked); ret += sizeof(MaximumNumberOperationsPerformed); return ret; } void AsynchronousOperationsWindowSub::Print(std::ostream &os) const { os << "MaximumNumberOperationsInvoked: " << MaximumNumberOperationsInvoked << std::endl; os << "MaximumNumberOperationsPerformed: " << MaximumNumberOperationsPerformed << std::endl; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmAsynchronousOperationsWindowSub.h000066400000000000000000000025771412732066400302320ustar00rootroot00000000000000/*========================================================================= 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 GDCMASYNCHRONOUSOPERATIONSWINDOWSUB_H #define GDCMASYNCHRONOUSOPERATIONSWINDOWSUB_H #include "gdcmTypes.h" namespace gdcm { namespace network { /** * \brief AsynchronousOperationsWindowSub * \details PS 3.7 * Table D.3-7 * ASYNCHRONOUS OPERATIONS WINDOW SUB-ITEM FIELDS * (A-ASSOCIATE-RQ) */ class AsynchronousOperationsWindowSub { public: AsynchronousOperationsWindowSub(); std::istream &Read(std::istream &is); const std::ostream &Write(std::ostream &os) const; size_t Size() const; void Print(std::ostream &os) const; private: static const uint8_t ItemType; static const uint8_t Reserved2; uint16_t ItemLength; uint16_t MaximumNumberOperationsInvoked; uint16_t MaximumNumberOperationsPerformed; }; } // end namespace network } // end namespace gdcm #endif // GDCMASYNCHRONOUSOPERATIONSWINDOWSUB_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmBaseCompositeMessage.h000066400000000000000000000046051412732066400256650ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMBASECOMPOSITEMESSSAGE_H #define GDCMBASECOMPOSITEMESSSAGE_H #include "gdcmPresentationDataValue.h" #include "gdcmBaseRootQuery.h" #include namespace gdcm { namespace network { class ULConnection; /** * \brief BaseCompositeMessage * \details The Composite events described in section 3.7-2009 of the DICOM standard all * use their own messages. These messages are constructed using Presentation * Data Values, from section 3.8-2009 of the standard, and then fill in * appropriate values in their datasets. * * So, for the five composites: * \li C-ECHO * \li C-FIND * \li C-MOVE * \li C-GET * \li C-STORE * there are a series of messages. However, all of these messages are obtained * as part of a PDataPDU, and all have to be placed there. Therefore, since * they all have shared functionality and construction tropes, that will be put * into a base class. Further, the base class will be then returned by the * factory class, gdcmCompositePDUFactory. * * This is an abstract class. It cannot be instantiated on its own. */ class BaseCompositeMessage { public: virtual ~BaseCompositeMessage() = default; //construct the appropriate pdv and dataset for this message //for instance, setting tag 0x0,0x100 to the appropriate value //the pdv, as described in Annex E of 3.8-2009, is the first byte //of the message (the MessageHeader), and then the subsequent dataset //that describes the operation. virtual std::vector ConstructPDV(const ULConnection &inConnection, const BaseRootQuery * inRootQuery) = 0; }; } } #endif //BASECOMPOSITEMESSSAGE_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmBaseNormalizedMessage.h000066400000000000000000000043461412732066400260310ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 GDCMBASENORMALIZEDMESSSAGE_H #define GDCMBASENORMALIZEDMESSSAGE_H #include "gdcmPresentationDataValue.h" #include "gdcmBaseQuery.h" #include namespace gdcm { namespace network { class ULConnection; /** * \brief BaseNormalizedMessage * \details The Normalized events described in section 3.7-2011 of the DICOM standard all * use their own messages. These messages are constructed using Presentation * Data Values, from section 3.8-2011 of the standard, and then fill in * appropriate values in their datasets. * * So, for the five normalized: * \li N-ACTION * \li N-CREATE * \li N-DELETE * \li N-EVENT * \li N-GET * \li N-SET * there are a series of messages. However, all of these messages are obtained * as part of a PDataPDU, and all have to be placed there. Therefore, since * they all have shared functionality and construction tropes, that will be put * into a base class. Further, the base class will be then returned by the * factory class, gdcmNormalizedMessageFactory.h. * * This is an abstract class. It cannot be instantiated on its own. */ class BaseNormalizedMessage { public: virtual ~BaseNormalizedMessage() = default; //construct the appropriate pdv and dataset for this message //for instance, setting tag 0x0,0x100 to the appropriate value //the pdv, as described in Annex E of 3.8-2009, is the first byte //of the message (the MessageHeader), and then the subsequent dataset //that describes the operation. virtual std::vector ConstructPDV( const ULConnection &inConnection, const BaseQuery * inQuery) = 0; }; } } #endif //GDCMBASENORMALIZEDMESSSAGE_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmBasePDU.h000066400000000000000000000037111412732066400230430ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMBASEPDU_H #define GDCMBASEPDU_H #include "gdcmTypes.h" namespace gdcm { namespace network { /** * \brief BasePDU * \details base class for PDUs * * all PDUs start with the first ten bytes as specified: * 01 PDU type * 02 reserved * 3-6 PDU Length (unsigned) * 7-10 variable * * on some, 7-10 are split (7-8 as protocol version in Associate-RQ, for instance, * while associate-rj splits those four bytes differently). * * Also common to all the PDUs is their ability to read and write to a stream. * * So, let's just get them all bunched together into one (abstract) class, shall we? * * Why? * 1) so that the ULEvent can have the PDU stored in it, since the event takes PDUs and not * other class structures (other class structures get converted into PDUs) * 2) to make reading PDUs in the event loop cleaner */ class BasePDU { public: virtual ~BasePDU() = default; virtual std::istream &Read(std::istream &is) = 0; virtual const std::ostream &Write(std::ostream &os) const = 0; virtual size_t Size() const = 0; virtual void Print(std::ostream &os) const = 0; virtual bool IsLastFragment() const = 0; }; } // end namespace network } // end namespace gdcm #endif // GDCMBASEPDU_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmBaseQuery.cxx000066400000000000000000000215621412732066400240770ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /* contains: a baseclass which will produce a dataset for c-find and c-move with patient root This class contains the functionality used in patient c-find and c-move queries. StudyRootQuery derives from this class. Namely: 1) list all tags associated with a particular query type 2) produce a query dataset via tag association Eventually, it can be used to validate a particular dataset type. The dataset held by this object (or, really, one of its derivates) should be passed to a c-find or c-move query. */ #include "gdcmBaseQuery.h" #include "gdcmQueryBase.h" #include "gdcmDataElement.h" #include "gdcmTag.h" #include "gdcmDict.h" #include "gdcmDictEntry.h" #include "gdcmDicts.h" #include "gdcmGlobal.h" #include "gdcmAttribute.h" #include "gdcmWriter.h" #include "gdcmPrinter.h" #include namespace gdcm { BaseQuery::BaseQuery() { //nothing to do, really } BaseQuery::~BaseQuery() { //nothing to do, really } void BaseQuery::SetSearchParameter(const Tag& inTag, const DictEntry& inDictEntry, const std::string& inValue) { //borrowed this code from anonymization; not sure if it's correct, though. DataElement de; de.SetTag( inTag ); const VR &vr = inDictEntry.GetVR(); if( vr.IsDual() ) { if( vr == VR::US_SS ) { de.SetVR( VR::US ); } else if( vr == VR::US_OW ) { de.SetVR( VR::OW ); } else if( vr == VR::US_SS_OW ) { de.SetVR( VR::OW ); } else if( vr == VR::OB_OW ) { de.SetVR( VR::OB ); } } else { de.SetVR( vr ); } std::string thePaddedValue = inValue; if (thePaddedValue.length() % 2 ){ thePaddedValue.push_back(' '); } assert(thePaddedValue.length() < std::numeric_limits::max()); de.SetByteValue(thePaddedValue.c_str(), (uint32_t)thePaddedValue.length()); //Replace any existing values mDataSet.Replace(de); } void BaseQuery::SetSearchParameter(const Tag& inTag, const std::string& inValue){ //IF WE WANTED, we could validate the incoming tag as belonging to our set of tags. //but we will not. static const Global &g = Global::GetInstance(); static const Dicts &dicts = g.GetDicts(); static const Dict &pubdict = dicts.GetPublicDict(); const DictEntry &dictentry = pubdict.GetDictEntry(inTag); SetSearchParameter(inTag, dictentry, inValue); } void BaseQuery::SetSearchParameter(const std::string& inKeyword, const std::string& inValue){ static const Global &g = Global::GetInstance(); static const Dicts &dicts = g.GetDicts(); static const Dict &pubdict = dicts.GetPublicDict(); Tag theTag; const DictEntry &dictentry = pubdict.GetDictEntryByName(inKeyword.c_str(), theTag); SetSearchParameter(theTag, dictentry, inValue); } const std::ostream &BaseQuery::WriteHelpFile(std::ostream &os) { // TODO //mash all the query types into a vector for ease-of-use //std::vector theQueries; //std::vector::const_iterator qtor; //std::vector theTags; //std::vector::iterator ttor; //static const Global &g = Global::GetInstance(); //static const Dicts &dicts = g.GetDicts(); //static const Dict &pubdict = dicts.GetPublicDict(); //os << "The following tags must be supported by a C-FIND/C-MOVE " << mHelpDescription << ": " << std::endl; //for (qtor = theQueries.begin(); qtor < theQueries.end(); qtor++){ // os << "Level: " << (*qtor)->GetName() << std::endl; // theTags = (*qtor)->GetRequiredTags(mRootType); // for (ttor = theTags.begin(); ttor < theTags.end(); ttor++){ // const DictEntry &dictentry = pubdict.GetDictEntry(*ttor); // os << "Keyword: " << dictentry.GetKeyword() << " Tag: " << *ttor << std::endl; // } // os << std::endl; //} //os << std::endl; //os << "The following tags are unique at each level of a " << mHelpDescription << ": " << std::endl; //for (qtor = theQueries.begin(); qtor < theQueries.end(); qtor++){ // os << "Level: " << (*qtor)->GetName() << std::endl; // theTags = (*qtor)->GetUniqueTags(mRootType); // for (ttor = theTags.begin(); ttor < theTags.end(); ttor++){ // const DictEntry &dictentry = pubdict.GetDictEntry(*ttor); // os << "Keyword: " << dictentry.GetKeyword() << " Tag: " << *ttor << std::endl; // } // os << std::endl; //} //os << std::endl; //os << "The following tags are optional at each level of a " << mHelpDescription << ": " << std::endl; //for (qtor = theQueries.begin(); qtor < theQueries.end(); qtor++){ // os << "Level: " << (*qtor)->GetName() << std::endl; // theTags = (*qtor)->GetOptionalTags(mRootType); // for (ttor = theTags.begin(); ttor < theTags.end(); ttor++){ // const DictEntry &dictentry = pubdict.GetDictEntry(*ttor); // os << "Keyword: " << dictentry.GetKeyword() << " Tag: " << *ttor << std::endl; // } // os << std::endl; //} os << std::endl; return os; } bool BaseQuery::WriteQuery(const std::string& inFileName) { Writer writer; writer.SetCheckFileMetaInformation( false ); writer.GetFile().GetHeader().SetDataSetTransferSyntax( TransferSyntax::ImplicitVRLittleEndian ); writer.GetFile().SetDataSet( GetQueryDataSet() ); writer.SetFileName( inFileName.c_str() ); if( !writer.Write() ) { gdcmWarningMacro( "Could not write: " << inFileName ); return false; } return true; } DataSet const & BaseQuery::GetQueryDataSet() const { return mDataSet; } DataSet & BaseQuery::GetQueryDataSet() { return mDataSet; } void BaseQuery::AddQueryDataSet(const DataSet & ds) { // Cannot use std::set::insert in case a unique key was added (eg. 10,20 with an empty // value). The user defined value for 10,20 in ds would not be taken into account DataSet::ConstIterator it = ds.Begin(); for( ; it != ds.End(); ++it ) { mDataSet.Replace( *it ); } } void BaseQuery::Print(std::ostream &os) const { UIDs::TSName asuid = GetAbstractSyntaxUID(); const char *asname = UIDs::GetUIDName( asuid ); os << "===================== OUTGOING DIMSE MESSAGE ====================" << std::endl; os << "Affected SOP Class UID :" << asname << std::endl; os << "======================= END DIMSE MESSAGE =======================" << std::endl; os << "Find SCU Request Identifiers:" << std::endl; os << "# Dicom-Data-Set" << std::endl; os << "# Used TransferSyntax: Unknown Transfer Syntax" << std::endl; Printer p; p.PrintDataSet( mDataSet, os ); } bool BaseQuery::ValidDataSet( const DataSet & dataSetToValid, const DataSet & dataSetReference ) const { bool theReturn = true ; DataSet::ConstIterator itor; for (itor = dataSetReference.Begin(); itor != dataSetReference.End(); itor++) { if ( dataSetToValid.FindDataElement( itor->GetTag() ) ) { SmartPointer pSqi = dataSetToValid.GetDataElement( itor->GetTag() ).GetValueAsSQ(); SmartPointer pSqiRef = pSqi ? itor->GetValueAsSQ() : nullptr ; if ( pSqi && pSqiRef ) { if( pSqi->GetNumberOfItems() < pSqiRef->GetNumberOfItems() ) { gdcmErrorMacro( "DataSet to valid has less Items " << pSqi->GetNumberOfItems() << " for sequence : " << itor->GetTag() << " than valid one " << pSqiRef->GetNumberOfItems() ); theReturn = false ; break ; } SequenceOfItems::SizeType indexOfItem ; for ( indexOfItem = 1 ; indexOfItem <= pSqiRef->GetNumberOfItems(); indexOfItem++ ) { const Item & currentReferenceItem = pSqiRef->GetItem( indexOfItem ); const Item & currentItemToValid = pSqi->GetItem( indexOfItem ); // now valid subDataSet theReturn &= ValidDataSet( currentItemToValid.GetNestedDataSet(), currentReferenceItem.GetNestedDataSet() ); if ( !theReturn ) break ; } } else // tag is found its not a sequence so it's ok theReturn &= true ; } else { gdcmErrorMacro( "You must have this tag : " << itor->GetTag() << " in your query dataset. "); theReturn = false ; break ; } } return theReturn ; } } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmBaseQuery.h000066400000000000000000000052451412732066400235240ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMBASEQUERY_H #define GDCMBASEQUERY_H #include "gdcmDataSet.h" #include "gdcmUIDs.h" #include "gdcmObject.h" namespace gdcm { class QueryFactory; class DictEntry; enum ENQueryType { eCreateMMPS = 0, eSetMMPS }; /** * \brief BaseQuery * \details contains: a baseclass which will produce a dataset for all dimse messages * * */ class GDCM_EXPORT BaseQuery : public Object { //these four classes contain the required, unique, and optional tags from the standard. //used both to list the tags as well as to validate a dataset, if ever we were to do so. protected: DataSet mDataSet; friend class QueryFactory; BaseQuery(); std::string mSopInstanceUID; void SetSearchParameter(const Tag& inTag, const DictEntry& inDictEntry, const std::string& inValue); bool ValidDataSet( const DataSet & dataSetToValid, const DataSet & dataSetReference ) const ; public: ~BaseQuery() override; void SetSearchParameter(const Tag& inTag, const std::string& inValue); void SetSearchParameter(const std::string& inKeyword, const std::string& inValue); const std::ostream &WriteHelpFile(std::ostream &os); //this function allows writing of the query to disk for storing for future use //virtual in case it needs to be overridden //returns false if the operation failed bool WriteQuery(const std::string& inFileName); /// Set/Get the internal representation of the query as a DataSet DataSet const & GetQueryDataSet() const; DataSet & GetQueryDataSet(); void AddQueryDataSet(const DataSet & ds); virtual bool ValidateQuery( bool inStrict = true ) const = 0; virtual UIDs::TSName GetAbstractSyntaxUID() const = 0; std::string GetSOPInstanceUID() const { return mSopInstanceUID ; } void SetSOPInstanceUID( const std::string & iSopInstanceUID ) { mSopInstanceUID = iSopInstanceUID ; } void Print(std::ostream &os) const override; }; } // end namespace gdcm #endif //GDCMBASEROOTQUERY_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmBaseRootQuery.cxx000066400000000000000000000063501412732066400247410ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /* contains: a baseclass which will produce a dataset for c-find and c-move with patient root This class contains the functionality used in patient c-find and c-move queries. StudyRootQuery derives from this class. Namely: 1) list all tags associated with a particular query type 2) produce a query dataset via tag association Eventually, it can be used to validate a particular dataset type. The dataset held by this object (or, really, one of its derivates) should be passed to a c-find or c-move query. */ #include "gdcmBaseRootQuery.h" #include "gdcmDataElement.h" #include "gdcmTag.h" #include "gdcmDict.h" #include "gdcmDictEntry.h" #include "gdcmDicts.h" #include "gdcmGlobal.h" #include "gdcmAttribute.h" #include "gdcmWriter.h" #include "gdcmPrinter.h" #include namespace gdcm { BaseRootQuery::BaseRootQuery() : BaseQuery() { //nothing to do, really } BaseRootQuery::~BaseRootQuery() { //nothing to do, really } static const char *QueryLevelStrings[] = { "PATIENT ", "STUDY ", "SERIES", "IMAGE ", }; const char *BaseRootQuery::GetQueryLevelString( EQueryLevel ql ) { return QueryLevelStrings[ ql ]; } int BaseRootQuery::GetQueryLevelFromString( const char * str ) { if( str ) { const std::string s = str; static const int n = sizeof( QueryLevelStrings ) / sizeof( *QueryLevelStrings ); for( int i = 0; i < n; ++i ) { if( s == QueryLevelStrings[ i ] ) { return i; } } } return -1; // FIXME never use it as valid enum } QueryBase * BaseRootQuery::Construct( ERootType inRootType, EQueryLevel qlevel ) { QueryBase* qb = nullptr; // Check no new extension: assert( inRootType == ePatientRootType || inRootType == eStudyRootType ); if( qlevel == ePatient ) { if( inRootType == ePatientRootType ) { qb = new QueryPatient; } } else if( qlevel == eStudy ) { qb = new QueryStudy; } else if( qlevel == eSeries ) { qb = new QuerySeries; } else if( qlevel == eImage ) { qb = new QueryImage; } return qb; } EQueryLevel BaseRootQuery::GetQueryLevelFromQueryRoot( ERootType roottype ) { EQueryLevel level = ePatient; switch( roottype ) { case ePatientRootType: level = ePatient; break; case eStudyRootType: level = eStudy; break; } assert( level == eStudy || level == ePatient ); return level; } } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmBaseRootQuery.h000066400000000000000000000105031412732066400243610ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMBASEROOTQUERY_H #define GDCMBASEROOTQUERY_H #include "gdcmDataSet.h" #include "gdcmUIDs.h" #include "gdcmBaseQuery.h" #include "gdcmQueryPatient.h" #include "gdcmQueryStudy.h" #include "gdcmQuerySeries.h" #include "gdcmQueryImage.h" namespace gdcm { class QueryFactory; class DictEntry; enum EQueryLevel { // -1 is reserved do not use ePatient = 0, eStudy = 1, eSeries = 2, eImage = 3 }; enum EQueryType { eFind= 0, eMove, eWLMFind }; /** * \brief BaseRootQuery * \details contains: a baseclass which will produce a dataset for c-find and c-move * with patient/study root * * This class contains the functionality used in patient c-find and c-move * queries. PatientRootQuery and StudyRootQuery derive from this class. * * Namely: * 1) list all tags associated with a particular query type * 2) produce a query dataset via tag association * * Eventually, it can be used to validate a particular dataset type. * * The dataset held by this object (or, really, one of its derivates) should be * passed to a c-find or c-move query. */ class GDCM_EXPORT BaseRootQuery : public BaseQuery { //these four classes contain the required, unique, and optional tags from the standard. //used both to list the tags as well as to validate a dataset, if ever we were to do so. protected: QueryPatient mPatient; QueryStudy mStudy; QuerySeries mSeries; QueryImage mImage; friend class QueryFactory; BaseRootQuery(); ERootType mRootType; //set in construction, and it's something else in the study root type std::string mHelpDescription; //used when generating the help output public: ~BaseRootQuery() override; ///this function will return all tags at a given query level, so that ///they maybe selected for searching. The boolean forFind is true ///if the query is a find query, or false for a move query. virtual std::vector GetTagListByLevel(const EQueryLevel& inQueryLevel) = 0; /// this function sets tag 8,52 to the appropriate value based on query level /// also fills in the right unique tags, as per the standard's requirements /// should allow for connection with dcmtk virtual void InitializeDataSet(const EQueryLevel& inQueryLevel) = 0; ///have to be able to ensure that ///0x8,0x52 is set (which will be true if InitializeDataSet is called...) ///that the level is appropriate (ie, not setting PATIENT for a study query ///that the tags in the query match the right level (either required, unique, optional) ///by default, this function checks to see if the query is for finding, which is more ///permissive than for moving. For moving, only the unique tags are allowed. ///10 Jan 2011: adding in the 'strict' mode. ///according to the standard (at least, how I've read it), only tags for a particular ///level should be allowed in a particular query (ie, just series level tags in a series ///level query). However, it seems that dcm4chee doesn't share that interpretation. ///So, if 'inStrict' is false, then tags from the current level and all higher levels ///are now considered valid. So, if you're doing a non-strict series-level query, ///tags from the patient and study level can be passed along as well. bool ValidateQuery( bool inStrict = true ) const override = 0; static const char *GetQueryLevelString( EQueryLevel ql ); static int GetQueryLevelFromString( const char * str ); static QueryBase * Construct(ERootType inRootType, EQueryLevel qlevel); EQueryLevel GetQueryLevelFromQueryRoot( ERootType roottype ); }; } // end namespace gdcm #endif //GDCMBASEROOTQUERY_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmCEchoMessages.cxx000066400000000000000000000046441412732066400246520ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /* this file defines the messages for the cecho action 5 oct 2010 mmr */ #include "gdcmCEchoMessages.h" #include "gdcmUIDs.h" #include "gdcmAttribute.h" #include "gdcmImplicitDataElement.h" #include "gdcmPresentationContextRQ.h" #include "gdcmCommandDataSet.h" #include "gdcmULConnection.h" namespace gdcm{ namespace network{ std::vector CEchoRQ::ConstructPDV( const ULConnection &inConnection, const BaseRootQuery* inRootQuery) { (void)inRootQuery; PresentationDataValue thePDV; PresentationContextRQ pc( UIDs::VerificationSOPClass ); thePDV.SetPresentationContextID( inConnection.GetPresentationContextIDFromPresentationContext(pc) ); thePDV.SetCommand(true); thePDV.SetLastFragment(true); //ignore incoming data set, make your own CommandDataSet ds; ds.Insert( pc.GetAbstractSyntax().GetAsDataElement() ); { Attribute<0x0,0x100> at = { 48 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x110> at = { 1 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x800> at = { 257 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x0> at = { 0 }; unsigned int glen = ds.GetLength(); assert( (glen % 2) == 0 ); at.SetValue( glen ); ds.Insert( at.GetAsDataElement() ); } thePDV.SetDataSet(ds); //!!!Mathieu, I assume you'll want to fix this std::vector thePDVs; thePDVs.push_back(thePDV); return thePDVs; } std::vector CEchoRSP::ConstructPDVByDataSet(const DataSet* inDataSet){ std::vector thePDV; (void)inDataSet; assert( 0 && "TODO" ); return thePDV; } }//namespace network }//namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmCEchoMessages.h000066400000000000000000000027161412732066400242750ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMCECHOMESSAGES_H #define GDCMCECHOMESSAGES_H #include "gdcmBaseCompositeMessage.h" namespace gdcm{ namespace network{ class ULConnection; /** * \brief CEchoRQ * \details this file defines the messages for the cecho action */ class CEchoRQ : public BaseCompositeMessage { public: std::vector ConstructPDV(const ULConnection &inConnection, const BaseRootQuery* inRootQuery) override; }; /** * \brief CEchoRSP * this file defines the messages for the cecho action */ class CEchoRSP : public BaseCompositeMessage { public: std::vector ConstructPDVByDataSet(const DataSet* inDataSet); }; } } #endif // GDCMCECHOMESSAGES_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmCFindMessages.cxx000066400000000000000000000072121412732066400246460ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /* this file defines the messages for the cfind action 5 oct 2010 mmr */ #include "gdcmCFindMessages.h" #include "gdcmUIDs.h" #include "gdcmAttribute.h" #include "gdcmImplicitDataElement.h" #include "gdcmPresentationContextRQ.h" #include "gdcmCommandDataSet.h" #include "gdcmULConnection.h" namespace gdcm{ namespace network{ std::vector CFindRQ::ConstructPDV( const ULConnection &inConnection, const BaseRootQuery* inRootQuery) { std::vector thePDVs; PresentationDataValue thePDV; #if 0 int contextID = ePatientRootQueryRetrieveInformationModelFIND; const char *uid = UIDs::GetUIDString( UIDs::PatientRootQueryRetrieveInformationModelFIND ); std::string suid = uid; if (dynamic_cast(inRootQuery)!=NULL) { contextID = eStudyRootQueryRetrieveInformationModelFIND; const char *uid2 = UIDs::GetUIDString( UIDs::StudyRootQueryRetrieveInformationModelFIND ); suid = uid2; } thePDV.SetPresentationContextID(contextID);//could it be 5, if the server does study? #else PresentationContextRQ pc( inRootQuery->GetAbstractSyntaxUID() ); uint8_t presidx = inConnection.GetPresentationContextIDFromPresentationContext(pc); if( !presidx ) { // try harder: PresentationContextRQ pc2( inRootQuery->GetAbstractSyntaxUID(), UIDs::ExplicitVRLittleEndian); presidx = inConnection.GetPresentationContextIDFromPresentationContext(pc2); if( !presidx ) { gdcmErrorMacro( "Could not find Pres Cont ID" ); return thePDVs; } } thePDV.SetPresentationContextID( presidx ); #endif thePDV.SetCommand(true); thePDV.SetLastFragment(true); //ignore incoming data set, make your own CommandDataSet ds; ds.Insert( pc.GetAbstractSyntax().GetAsDataElement() ); { Attribute<0x0,0x100> at = { 32 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x110> at = { 1 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x700> at = { 2 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x800> at = { 1 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x0> at = { 0 }; unsigned int glen = ds.GetLength(); assert( (glen % 2) == 0 ); at.SetValue( glen ); ds.Insert( at.GetAsDataElement() ); } thePDV.SetDataSet(ds); thePDVs.push_back(thePDV); thePDV.SetDataSet(inRootQuery->GetQueryDataSet()); thePDV.SetMessageHeader( 2 ); thePDVs.push_back(thePDV); return thePDVs; } std::vector CFindRSP::ConstructPDVByDataSet(const DataSet* inDataSet){ std::vector thePDV; (void)inDataSet; assert( 0 && "TODO" ); return thePDV; } std::vector CFindCancelRQ::ConstructPDVByDataSet(const DataSet* inDataSet){ std::vector thePDV; (void)inDataSet; assert( 0 && "TODO" ); return thePDV; } }//namespace network }//namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmCFindMessages.h000066400000000000000000000032241412732066400242720ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMCFINDMESSAGES_H #define GDCMCFINDMESSAGES_H #include "gdcmBaseCompositeMessage.h" #include "gdcmBaseRootQuery.h" namespace gdcm { namespace network { /** * \brief CFindRQ * \details this file defines the messages for the cfind action */ class CFindRQ : public BaseCompositeMessage { public: std::vector ConstructPDV(const ULConnection &inConnection, const BaseRootQuery* inRootQuery) override; }; /** * \brief CFindRSP * this file defines the messages for the cfind action */ class CFindRSP : public BaseCompositeMessage { public: std::vector ConstructPDVByDataSet(const DataSet* inDataSet); }; /** * \brief CFindCancelRQ * this file defines the messages for the cfind action */ class CFindCancelRQ : public BaseCompositeMessage { public: std::vector ConstructPDVByDataSet(const DataSet* inDataSet); }; } } #endif GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmCMoveMessages.cxx000066400000000000000000000077741412732066400247110ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmCMoveMessages.h" #include "gdcmUIDs.h" #include "gdcmAttribute.h" #include "gdcmImplicitDataElement.h" #include "gdcmCommandDataSet.h" #include "gdcmPresentationContextRQ.h" #include "gdcmULConnection.h" #include "gdcmAAssociateRQPDU.h" namespace gdcm{ namespace network{ std::vector CMoveRQ::ConstructPDV( const ULConnection &inConnection, const BaseRootQuery* inRootQuery) { std::vector thePDVs; PresentationContextRQ pc( inRootQuery->GetAbstractSyntaxUID() ); { PresentationDataValue thePDV; #if 0 int contextID = ePatientRootQueryRetrieveInformationModelMOVE; const char *uid = UIDs::GetUIDString( UIDs::PatientRootQueryRetrieveInformationModelMOVE ); std::string suid = uid; if (dynamic_cast(inRootQuery)!=NULL) { contextID = eStudyRootQueryRetrieveInformationModelMOVE; const char *uid2 = UIDs::GetUIDString( UIDs::StudyRootQueryRetrieveInformationModelMOVE ); suid = uid2; } thePDV.SetPresentationContextID(contextID);//could it be 5, if the server does study? #else thePDV.SetPresentationContextID( inConnection.GetPresentationContextIDFromPresentationContext(pc) ); #endif thePDV.SetCommand(true); thePDV.SetLastFragment(true); //ignore incoming data set, make your own CommandDataSet ds; ds.Insert( pc.GetAbstractSyntax().GetAsDataElement() ); { Attribute<0x0,0x100> at = { 33 };//0021H, as per the spec ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x110> at = { 1 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x600> at = { "" }; const char *calling = inConnection.GetConnectionInfo().GetCallingAETitle(); assert( AAssociateRQPDU::IsAETitleValid( calling ) ); at.SetValue( calling ); ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x700> at = { 0 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x800> at = { 1 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x0> at = { 0 }; unsigned int glen = ds.GetLength(); assert( (glen % 2) == 0 ); at.SetValue( glen ); ds.Insert( at.GetAsDataElement() ); } thePDV.SetDataSet(ds); thePDVs.push_back(thePDV); } { PresentationDataValue thePDV; thePDV.SetPresentationContextID( inConnection.GetPresentationContextIDFromPresentationContext(pc) ); //thePDV.SetBlob( sub ); thePDV.SetDataSet(inRootQuery->GetQueryDataSet()); thePDV.SetMessageHeader( 2 ); thePDVs.push_back(thePDV); } return thePDVs; } //this is a private function, should not be callable //but if you manage to do call it, return a blank dataset. std::vector CMoveRQ::ConstructPDVByDataSet(const DataSet* inDataSet){ std::vector thePDVs; (void)inDataSet; assert( 0 && "TODO" ); return thePDVs; } std::vector CMoveRSP::ConstructPDVByDataSet(const DataSet* inDataSet){ std::vector thePDV; (void)inDataSet; assert( 0 && "TODO" ); return thePDV; } std::vector CMoveCancelRq::ConstructPDVByDataSet(const DataSet* inDataSet){ std::vector thePDV; (void)inDataSet; assert( 0 && "TODO" ); return thePDV; } }//namespace network }//namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmCMoveMessages.h000066400000000000000000000035701412732066400243240ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMCMOVEMESSAGES_H #define GDCMCMOVEMESSAGES_H #include "gdcmBaseCompositeMessage.h" #include "gdcmBaseRootQuery.h" namespace gdcm{ namespace network{ class ULConnection; /** * \brief CMoveRQ * \details this file defines the messages for the cmove action */ class CMoveRQ : public BaseCompositeMessage { //this class will fulfill the inheritance, //but additional information is needed by cmovd //namely, the root type or the calling AE-TITLE std::vector ConstructPDVByDataSet(const DataSet* inDataSet); public: std::vector ConstructPDV( const ULConnection &inConnection, const BaseRootQuery* inRootQuery) override; }; /** * \brief CMoveRSP * this file defines the messages for the cmove action */ class CMoveRSP : public BaseCompositeMessage { public: std::vector ConstructPDVByDataSet(const DataSet* inDataSet); }; class CMoveCancelRq : public BaseCompositeMessage { public: std::vector ConstructPDVByDataSet(const DataSet* inDataSet); }; } } #endif GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmCStoreMessages.cxx000066400000000000000000000244701412732066400250670ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmCStoreMessages.h" #include "gdcmUIDs.h" #include "gdcmAttribute.h" #include "gdcmFile.h" #include "gdcmImplicitDataElement.h" #include "gdcmPresentationContextRQ.h" #include "gdcmCommandDataSet.h" #include "gdcmBasePDU.h" #include "gdcmPDataTFPDU.h" #include "gdcmMediaStorage.h" #include "gdcmULConnection.h" #include "gdcmWriter.h" #include namespace gdcm{ class DataSetWriter : public Writer { public: DataSetWriter() { SetWriteDataSetOnly( true ); } }; namespace network{ std::vector CStoreRQ::ConstructPDV( const ULConnection &inConnection, File const & file, bool writeDataSet /*=true*/ ) { const DataSet* inDataSet = &file.GetDataSet(); std::vector thePDVs; PresentationContextRQ pc( UIDs::VerificationSOPClass ); uint8_t prescontid; { assert( inDataSet ); PresentationDataValue thePDV; #if 0 std::string UIDString; thePDV.SetPresentationContextID( PresentationContextRQ::AssignPresentationContextID(*inDataSet, UIDString)); #else { MediaStorage mst; if (!mst.SetFromDataSet(*inDataSet)) { throw Exception("Missing MediaStorage"); } UIDs uid; uid.SetFromUID( MediaStorage::GetMSString(mst) ); //as.SetNameFromUID( uid ); pc.GetAbstractSyntax().SetName( uid.GetString() ); } // prescontid = inConnection.GetPresentationContextIDFromAbstractSyntax(as); // thePDV.SetPresentationContextID( prescontid ); #endif thePDV.SetCommand(true); thePDV.SetLastFragment(true); //ignore incoming data set, make your own CommandDataSet ds; { DataElement de( Tag(0x0,0x2) ); de.SetVR( VR::UI ); if( !inDataSet->FindDataElement( Tag(0x0008, 0x0016) ) || inDataSet->GetDataElement( Tag(0x0008, 0x0016) ).IsEmpty() ) { throw Exception("Missing SOP Class UID"); } const DataElement& msclass = inDataSet->GetDataElement( Tag(0x0008, 0x0016) ); const char *uid = msclass.GetByteValue()->GetPointer(); assert( uid ); std::string suid = std::string(uid, msclass.GetByteValue()->GetLength()); // self check // const PresentationContextAC * pc = inConnection.GetPresentationContextACByID(prescontid); // assert( pc ); // TransferSyntaxSub const &tssub = pc->GetTransferSyntax(); const TransferSyntax & fmits = file.GetHeader().GetDataSetTransferSyntax(); const char *tsuidvalue = fmits.GetString(); // TransferSyntaxSub tssub; // tssub.SetName( tsuidvalue ); pc.GetTransferSyntax(0).SetName( tsuidvalue ); std::string tsuid = fmits.GetString(); prescontid = inConnection.GetPresentationContextIDFromPresentationContext(pc); // prescontid cannot possibly be unknown since we are only looking in our own // AAssociateRQPDU assert( prescontid != 0 ); const PresentationContextRQ * rqpc = inConnection.GetPresentationContextRQByID(prescontid); assert( rqpc ); // Now let's see if this best matching PresentationContextRQ can be found in the AC // section of the AAssociateACPDU const PresentationContextAC * acpc = inConnection.GetPresentationContextACByID(prescontid); // the following make sure that the accepted Presentation Context match the actual encoding // of the current File // ADV: technically we could use an explicit VR encoded dataset and send it over // an implicit TS accepted Transfer syntax. However thing do not interchange well // so we really need a filter to check whether conversion is ok or not. if( acpc == nullptr ) { // Technically we should fallback to something else. Anyway lets' give up // and hope the user will convert the encapsulated stream to something else... throw Exception("Server side refuse our proposed PC."); } TransferSyntaxSub const & actssub = acpc->GetTransferSyntax(); assert( rqpc->GetNumberOfTransferSyntaxes() == 1 ); // TODO FIXME TransferSyntaxSub const & rqtssub = rqpc->GetTransferSyntax(0); if( !(actssub == rqtssub) ) { gdcmDebugMacro( "Faulty Presentation Context : " << (int)acpc->GetPresentationContextID() ); throw Exception("Server side refuse our proposed PC for context id" ); } #if 0 // For some reason using a dcmtk 3.5.4 server. The PresCont even if refused returned // filled with the default Implicit Little Endian. So make sure TS matches TransferSyntaxSub const & actssub = acpc->GetTransferSyntax(); TransferSyntaxSub const & dummy0 = pc.GetTransferSyntax(0); if( !(actssub == pc.GetTransferSyntax(0)) ) { gdcmDebugMacro( "Faulty Presentation Context : " << (int)acpc->GetPresentationContextID() ); throw Exception("Server side refuse our proposed PC for context id" ); } #endif thePDV.SetPresentationContextID( prescontid ); assert(suid.size() < std::numeric_limits::max()); de.SetByteValue( suid.c_str(), (uint32_t)suid.size() ); ds.Insert( de ); } { assert( inDataSet->FindDataElement( Tag(0x0008, 0x0018) ) ); const DataElement& msinst = inDataSet->GetDataElement( Tag(0x0008, 0x0018) ); std::string suid; DataElement de( Tag(0x0,0x1000) ); de.SetVR( VR::UI ); if( !msinst.IsEmpty() ) { const ByteValue* bv = msinst.GetByteValue(); if( bv ) { const char *uid = bv->GetPointer(); assert( uid ); suid = std::string(uid, bv->GetLength() ); assert(suid.size() < std::numeric_limits::max()); } } de.SetByteValue( suid.c_str(), (uint32_t)suid.size() ); ds.Insert( de ); } { Attribute<0x0,0x100> at = { 1 }; ds.Insert( at.GetAsDataElement() ); } static uint32_t messageid = 1; { Attribute<0x0,0x110> at = { 0 }; at.SetValue( (unsigned short)messageid++ ); assert( messageid < std::numeric_limits::max()); ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x700> at = { 2 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x800> at = { 1 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x0> at = { 0 }; unsigned int glen = ds.GetLength(); assert( (glen % 2) == 0 ); at.SetValue( glen ); ds.Insert( at.GetAsDataElement() ); } thePDV.SetDataSet(ds); //!!!Mathieu, I assume you'll want to fix this thePDVs.push_back(thePDV); } if( !writeDataSet ) return thePDVs ; // now let's chunk'ate the dataset: { std::stringstream ss; #if 0 inDataSet->Write( ss ); #else DataSetWriter writer; writer.SetStream( ss ); writer.SetFile( file ); writer.Write(); #endif std::string ds_copy = ss.str(); // E: 0006:0308 DUL Illegal PDU Length 16390. Max expected 16384 //const size_t maxpdu = 16384 - 6; size_t maxpdu = 16378; maxpdu = inConnection.GetMaxPDUSize() - 6; size_t len = ds_copy.size(); const char *begin = ds_copy.c_str(); const char *end = begin + len; const char *cur = begin; while( cur < end ) { size_t remaining = std::min( maxpdu , (size_t)(end - cur) ); std::string sub( cur, remaining ); PresentationDataValue thePDV; std::string UIDString; thePDV.SetPresentationContextID( prescontid ); thePDV.SetBlob( sub ); cur += remaining; if( cur < end ) thePDV.SetMessageHeader( 0 ); else { assert( cur == end ); thePDV.SetMessageHeader( 2 ); } thePDVs.push_back(thePDV); } } return thePDVs; } //private hack std::vector CStoreRQ::ConstructPDV( const ULConnection &inConnection, const BaseRootQuery* inRootQuery) { std::vector thePDVs; (void)inRootQuery; (void)inConnection; assert( 0 && "TODO" ); return thePDVs; } //private hack std::vector CStoreRSP::ConstructPDV(const ULConnection &, const BaseRootQuery* inRootQuery) { std::vector thePDVs; (void)inRootQuery; assert( 0 && "TODO" ); return thePDVs; } std::vector CStoreRSP::ConstructPDV(const DataSet* inDataSet, const BasePDU* inPDU){ std::vector thePDVs; ///should be passed the received dataset, ie, the cstorerq, so that ///the cstorersp contains the appropriate SOP instance UIDs. CommandDataSet ds; uint32_t theMessageID = 0; Attribute<0x0,0x0110> at3 = { 0 }; at3.SetFromDataSet( *inDataSet ); theMessageID = at3.GetValue(); const DataElement &de1 = inDataSet->GetDataElement( Tag( 0x0000,0x0002 ) ); const DataElement &de2 = inDataSet->GetDataElement( Tag( 0x0000,0x1000 ) ); //pass back the instance UIDs in the response ds.Insert(de1); ds.Insert(de2); //code is from the presentationdatavalue::myinit2 { // Command Field Attribute<0x0,0x100> at = { 32769 }; ds.Insert( at.GetAsDataElement() ); } { // Message ID Being Responded To Attribute<0x0,0x120> at = { 1 }; at.SetValue( (unsigned short)theMessageID ); ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x800> at = { 257 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x900> at = { 0 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x0> at = { 0 }; unsigned int glen = ds.GetLength(); assert( (glen % 2) == 0 ); at.SetValue( glen ); ds.Insert( at.GetAsDataElement() ); } PresentationDataValue pdv; // FIXME // how do we retrieve the actual PresID from the AAssociate? const PDataTFPDU* theDataPDU = dynamic_cast(inPDU); assert (theDataPDU); uint8_t thePDVValue; PresentationDataValue const &input_pdv = theDataPDU->GetPresentationDataValue(0); thePDVValue = input_pdv.GetPresentationContextID(); pdv.SetPresentationContextID( thePDVValue ); pdv.SetDataSet(ds); pdv.SetMessageHeader(3); thePDVs.push_back(pdv); return thePDVs; } }//namespace network }//namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmCStoreMessages.h000066400000000000000000000034671412732066400245170ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMCSTOREMESSAGES_H #define GDCMCSTOREMESSAGES_H #include "gdcmBaseCompositeMessage.h" namespace gdcm{ class File; namespace network{ class BasePDU; /** * \brief CStoreRQ * \details this file defines the messages for the cecho action */ class CStoreRQ : public BaseCompositeMessage { std::vector ConstructPDV(const ULConnection &inConnection, const BaseRootQuery* inRootQuery) override;//to fulfill the virtual contract public: std::vector ConstructPDV(const ULConnection &inConnection, const File& file, bool writeDataSet = true ); }; /** * \brief CStoreRSP * this file defines the messages for the cecho action */ class CStoreRSP : public BaseCompositeMessage { std::vector ConstructPDV(const ULConnection &inConnection, const BaseRootQuery* inRootQuery) override;//to fulfill the virtual contract public: std::vector ConstructPDV(const DataSet* inDataSet, const BasePDU* inPC); }; } } #endif // GDCMCSTOREMESSAGES_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmCommandDataSet.cxx000066400000000000000000000017341412732066400250220ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCommandDataSet.h" #include "gdcmVR.h" #include "gdcmImplicitDataElement.h" #include "gdcmTag.h" namespace gdcm { std::istream &CommandDataSet::Read(std::istream &is) { this->DataSet::Read(is); return is; } std::ostream &CommandDataSet::Write(std::ostream &os) const { this->DataSet::Write(os); return os; } } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmCommandDataSet.h000066400000000000000000000033311412732066400244420ustar00rootroot00000000000000/*========================================================================= 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 GDCMCOMMANDDATASET_H #define GDCMCOMMANDDATASET_H #include "gdcmDataSet.h" #include "gdcmDataElement.h" namespace gdcm { /** * \brief Class to represent a Command DataSet * * \see DataSet */ class GDCM_EXPORT CommandDataSet : public DataSet { public: CommandDataSet() = default; ~CommandDataSet() = default; friend std::ostream &operator<<(std::ostream &_os, const CommandDataSet &_val); // FIXME: no virtual function means: duplicate code... void Insert(const DataElement& de) { if( de.GetTag().GetGroup() == 0x0000 ) { InsertDataElement( de ); } else { gdcmErrorMacro( "Cannot add element with group != 0x0000 in the command dataset : " << de ); } } void Replace(const DataElement& de) { Remove(de.GetTag()); Insert(de); } /// Read std::istream &Read(std::istream &is); /// Write std::ostream &Write(std::ostream &os) const; protected: }; //----------------------------------------------------------------------------- inline std::ostream& operator<<(std::ostream &os, const CommandDataSet &val) { val.Print( os ); return os; } } // end namespace gdcm #endif //GDCMFILEMETAINFORMATION_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmCompositeMessageFactory.cxx000066400000000000000000000050431412732066400267720ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /* This class constructs PDataPDUs, but that have been specifically constructed for the composite DICOM services (C-Echo, C-Find, C-Get, C-Move, and C-Store). It will also handle parsing the incoming data to determine which of the CompositePDUs the incoming data is, and so therefore allowing the scu to determine what to do with incoming data (if acting as a storescp server, for instance). name and date: 4 oct 2010 mmr */ #include "gdcmCompositeMessageFactory.h" #include "gdcmCEchoMessages.h" #include "gdcmCStoreMessages.h" #include "gdcmCFindMessages.h" #include "gdcmCMoveMessages.h" #include "gdcmBaseRootQuery.h" namespace gdcm { namespace network { std::vector CompositeMessageFactory::ConstructCEchoRQ(const ULConnection& inConnection) { CEchoRQ theEchoRQ; return theEchoRQ.ConstructPDV(inConnection,nullptr); } std::vector CompositeMessageFactory::ConstructCStoreRQ(const ULConnection& inConnection, const File &file, bool writeDataSet /*= true*/ ) { CStoreRQ theStoreRQ; return theStoreRQ.ConstructPDV( inConnection, file, writeDataSet ); } std::vector CompositeMessageFactory::ConstructCStoreRSP(const DataSet *inDataSet, const BasePDU* inPDU) { CStoreRSP theStoreRSP; return theStoreRSP.ConstructPDV(inDataSet, inPDU); } std::vector CompositeMessageFactory::ConstructCFindRQ(const ULConnection& inConnection, const BaseRootQuery* inRootQuery) { CFindRQ theFindRQ; return theFindRQ.ConstructPDV(inConnection, inRootQuery); } std::vector CompositeMessageFactory::ConstructCMoveRQ(const ULConnection& inConnection, const BaseRootQuery* inRootQuery) { CMoveRQ theMoveRQ; return theMoveRQ.ConstructPDV(inConnection, inRootQuery); } } } GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmCompositeMessageFactory.h000066400000000000000000000046541412732066400264260ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMCOMPOSITEMESSAGEFACTORY_H #define GDCMCOMPOSITEMESSAGEFACTORY_H #include "gdcmPresentationDataValue.h" #include "gdcmULConnection.h" namespace gdcm { class BaseRootQuery; class File; namespace network { class BasePDU; /** * \brief CompositeMessageFactory * \details This class constructs PDataPDUs, but that have been specifically constructed for the * composite DICOM services (C-Echo, C-Find, C-Get, C-Move, and C-Store). It will also handle * parsing the incoming data to determine which of the CompositePDUs the incoming data is, and * so therefore allowing the scu to determine what to do with incoming data (if acting as * a storescp server, for instance). */ class CompositeMessageFactory { public: //the echo request only needs a properly constructed PDV. //find, move, etc, may need something more robust, but since those are //easily placed into the appropriate pdatapdu in the pdufactory, //this approach without a base class (but done internally) is useful. static std::vector ConstructCEchoRQ(const ULConnection& inConnection); static std::vector ConstructCStoreRQ(const ULConnection& inConnection,const File &file, bool writeDataSet = true ); static std::vector ConstructCStoreRSP(const DataSet *inDataSet, const BasePDU* inPC); static std::vector ConstructCFindRQ(const ULConnection& inConnection, const BaseRootQuery* inRootQuery); static std::vector ConstructCMoveRQ(const ULConnection& inConnection, const BaseRootQuery* inRootQuery); }; } } #endif // GDCMCOMPOSITEMESSAGEFACTORY_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmCompositeNetworkFunctions.cxx000066400000000000000000000355601412732066400274070ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmCompositeNetworkFunctions.h" #include #include "gdcmReader.h" #include "gdcmPrinter.h" #include "gdcmAttribute.h" #include "gdcmULConnectionManager.h" #include "gdcmULConnection.h" #include "gdcmDataSet.h" #include "gdcmVersion.h" #include "gdcmGlobal.h" #include "gdcmSystem.h" #include "gdcmUIDGenerator.h" #include "gdcmWriter.h" #include "gdcmSimpleSubjectWatcher.h" #include "gdcmProgressEvent.h" #include "gdcmQueryFactory.h" #include "gdcmULWritingCallback.h" #include "gdcmULBasicCallback.h" #include "gdcmPresentationContextGenerator.h" namespace gdcm { // Execute like this: // gdcmscu --echo www.dicomserver.co.uk 11112 bool CompositeNetworkFunctions::CEcho(const char *remote, uint16_t portno, const char *aetitle, const char *call) { if( !remote ) return false; if( !aetitle ) { aetitle = "GDCMSCU"; } if( !call ) { call = "ANY-SCP"; } // Generate the PresentationContext array from the echo UID: PresentationContextGenerator generator; if( !generator.GenerateFromUID( UIDs::VerificationSOPClass ) ) { gdcmErrorMacro( "Failed to generate pres context." ); return false; } network::ULConnectionManager theManager; if (!theManager.EstablishConnection(aetitle, call, remote, 0, portno, 1000, generator.GetPresentationContexts() )) { gdcmErrorMacro( "Failed to establish connection." ); return false; } std::vector theValues1 = theManager.SendEcho(); //should print _something_ to let the user know of success, if they ask for something //other than a return code. if (Trace::GetDebugFlag()) { DataSet ds = network::PresentationDataValue::ConcatenatePDVBlobs(theValues1); Printer thePrinter; thePrinter.PrintDataSet(ds, Trace::GetStream()); } theManager.BreakConnection(-1);//wait for a while for the connection to break, ie, infinite // Check the Success Status DataSet ds = network::PresentationDataValue::ConcatenatePDVBlobs( theValues1 ); Attribute<0x0,0x0900> at; if( ds.FindDataElement( at.GetTag() ) ) { at.SetFromDataSet( ds ); if( at.GetValue() != 0 ) { gdcmErrorMacro( "Wrong value for Status (C-ECHO)" ); return false; } return true; } gdcmDebugMacro( "Empty return on C-ECHO (no Status)" ); return false; } // this function will take command line options and construct a cmove query from them // returns NULL if the query could not be constructed. // note that the caller is responsible for deleting the constructed query. // used to build both a move and a find query (true for inMove if it's move, false if it's find) BaseRootQuery* CompositeNetworkFunctions::ConstructQuery( ERootType inRootType, EQueryLevel inQueryLevel, const KeyValuePairArrayType& keys, EQueryType queryType /*= eFind*/ ) { KeyValuePairArrayType::const_iterator it = keys.begin(); DataSet ds; for(; it != keys.end(); ++it) { DataElement de( it->first ); const std::string &s = it->second; de.SetByteValue ( s.c_str(), (uint32_t)s.size() ); ds.Insert( de ); } return CompositeNetworkFunctions::ConstructQuery( inRootType, inQueryLevel, ds, queryType); } BaseRootQuery* CompositeNetworkFunctions::ConstructQuery( ERootType inRootType, EQueryLevel inQueryLevel, const DataSet& ds, EQueryType queryType /*= eFind*/ ) { BaseRootQuery* outQuery = nullptr; if( queryType == eMove ) outQuery = QueryFactory::ProduceQuery(inRootType, eMove, inQueryLevel); else if( queryType == eFind ) outQuery = QueryFactory::ProduceQuery(inRootType, eFind, inQueryLevel); else if( queryType == eWLMFind ) outQuery = QueryFactory::ProduceQuery(inRootType, eWLMFind, inQueryLevel); if (!outQuery) { gdcmErrorMacro( "Specify the query" ); return nullptr; } outQuery->AddQueryDataSet(ds); // setup the special character set std::vector inCharSetType; inCharSetType.push_back( QueryFactory::GetCharacterFromCurrentLocale() ); DataElement de = QueryFactory::ProduceCharacterSetDataElement(inCharSetType); std::string param ( de.GetByteValue()->GetPointer(), de.GetByteValue()->GetLength() ); outQuery->SetSearchParameter(de.GetTag(), param ); // Print info: if (Trace::GetDebugFlag()) { outQuery->Print( Trace::GetStream() ); } return outQuery; } //note that pointer to the base root query-- the caller must instantiated and delete bool CompositeNetworkFunctions::CMove( const char *remote, uint16_t portno, const BaseRootQuery* query, uint16_t portscp, const char *aetitle, const char *call, const char* outputdir) { if( !remote ) return false; if( !aetitle ) { aetitle = "GDCMSCU"; } if( !call ) { call = "ANY-SCP"; } /* movescu -v -d --aetitle GDCMDASH3 --call GDCM_STORE --patient --key * 8,52=IMAGE --key 8,18=1.3.12.2.1107.5.8.1.123456789.199507271758050707765 * dicom.example.com 11112 --key 10,20 +P 5677 * --key 20,d=1.3.12.2.1107.5.8.1.123456789.199507271758050705910 * --key 20,e=1.3.12.2.1107.5.8.1.123456789.199507271758050706635 */ if (!outputdir || !*outputdir) { outputdir = "."; } // Generate the PresentationContext array from the query UID: PresentationContextGenerator generator; if( !generator.GenerateFromUID( query->GetAbstractSyntaxUID() ) ) { gdcmErrorMacro( "Failed to generate pres context." ); return false; } network::ULConnectionManager theManager; if (!theManager.EstablishConnectionMove(aetitle, call, remote, 0, portno, 1000, portscp, generator.GetPresentationContexts())) { gdcmErrorMacro( "Failed to establish connection." ); return false; } network::ULWritingCallback theCallback; theCallback.SetDirectory(outputdir); bool ret = theManager.SendMove( query, &theCallback ); if( !ret ) return false; ret = theManager.BreakConnection(-1);//wait for a while for the connection to break, ie, infinite return ret; } //note that pointer to the base root query-- the caller must instantiated and delete bool CompositeNetworkFunctions::CFind( const char *remote, uint16_t portno, const BaseRootQuery* query, std::vector &retDataSets, const char *aetitle, const char *call ) { if( !remote ) return false; if( !aetitle ) { aetitle = "GDCMSCU"; } if( !call ) { call = "ANY-SCP"; } // $ findscu -v -d --aetitle ACME1 --call ACME_STORE -P -k 0010,0010="X*" // dhcp-67-183 5678 patqry.dcm // Add a query: // Generate the PresentationContext array from the query UID: PresentationContextGenerator generator; if( !generator.GenerateFromUID( query->GetAbstractSyntaxUID() ) ) { gdcmErrorMacro( "Failed to generate pres context." ); return false; } network::ULConnectionManager theManager; if (!theManager.EstablishConnection(aetitle, call, remote, 0, portno, 1000, generator.GetPresentationContexts())) { gdcmErrorMacro( "Failed to establish connection." ); return false; } std::vector theDataSets; std::vector theResponses; //theDataSets = theManager.SendFind( query ); network::ULBasicCallback theCallback; theManager.SendFind(query, &theCallback); theDataSets = theCallback.GetDataSets(); theResponses = theCallback.GetResponses(); bool ret = false; // by default an error if( theResponses.empty() ) { gdcmErrorMacro( "Failed to GetResponses." ); return false; } assert( theResponses.size() >= 1 ); // take the last one: const DataSet &ds = theResponses[ theResponses.size() - 1 ]; // FIXME assert ( ds.FindDataElement(Tag(0x0, 0x0900)) ); Attribute<0x0,0x0900> at; at.SetFromDataSet( ds ); // Table CC.2.8-2 //C-FIND RESPONSE STATUS VALUES const uint16_t theVal = at.GetValue(); switch( theVal ) { case 0x0: // Matching is complete - No final Identifier is supplied. gdcmDebugMacro( "C-Find was successful." ); // Append the new DataSet to the ret one: retDataSets.insert( retDataSets.end(), theDataSets.begin(), theDataSets.end() ); ret = true; break; case 0xA900: // Identifier Does Not Match SOP Class { Attribute<0x0,0x0901> errormsg; errormsg.SetFromDataSet( ds ); gdcm::Tag const & t = errormsg.GetValue(); gdcmErrorMacro( "Offending Element: " << t ); (void)t; } break; case 0xA700: // Refused: Out of Resources { Attribute<0x0,0x0902> errormsg; errormsg.SetFromDataSet( ds ); const char *themsg = errormsg.GetValue(); assert( themsg ); (void)themsg; gdcmErrorMacro( "Response Status: [" << themsg << "]" ); } break; case 0x0122: // SOP Class not Supported gdcmErrorMacro( "SOP Class not Supported" ); break; case 0xfe00: // Matching terminated due to Cancel request gdcmErrorMacro( "Matching terminated due to Cancel request" ); break; default: { if( theVal >= 0xC000 && theVal <= 0xCFFF ) // Unable to process { Attribute<0x0,0x0902> errormsg; errormsg.SetFromDataSet( ds ); const char *themsg = errormsg.GetValue(); assert( themsg ); (void)themsg; gdcmErrorMacro( "Response Status: " << themsg ); } } } theManager.BreakConnection(-1);//wait for a while for the connection to break, ie, infinite return ret; } class MyWatcher : public SimpleSubjectWatcher { size_t nfiles; double progress; size_t index; double refprogress; public: MyWatcher(Subject * s, const char *comment = "", size_t n = 1):SimpleSubjectWatcher(s,comment),nfiles(n),progress(0),index(0),refprogress(0){} void ShowIteration() override { index++; assert( index <= nfiles ); refprogress = progress; } void ShowProgress(Subject *caller, const Event &evt) override { const ProgressEvent &pe = dynamic_cast(evt); (void)caller; progress = refprogress + (1. / (double)nfiles ) * pe.GetProgress(); // std::cout << "Progress: " << progress << " " << pe.GetProgress() << std::endl; } void ShowDataSet(Subject *, const Event &) override {} }; bool CompositeNetworkFunctions::CStore( const char *remote, uint16_t portno, const Directory::FilenamesType& filenames, const char *aetitle, const char *call) { if( !remote ) return false; // TODO AE-TITLE are more restrictive than that ! if( !aetitle ) { aetitle = "GDCMSCU"; } if( !call ) { call = "ANY-SCP"; } SmartPointer ps = new network::ULConnectionManager; network::ULConnectionManager &theManager = *ps; Directory::FilenamesType const &files = filenames; //SimpleSubjectWatcher watcher(ps, "cstore"); MyWatcher watcher(ps, "cstore", files.size() ); // Generate the PresentationContext array from the File-Set: PresentationContextGenerator generator; if( !generator.GenerateFromFilenames(filenames) ) { gdcmErrorMacro( "Failed to generate pres context." ); return false; } if (!theManager.EstablishConnection(aetitle, call, remote, 0, portno, 1000, generator.GetPresentationContexts() )) { gdcmErrorMacro( "Failed to establish connection." ); return false; } const char *fn = ""; // FIXME bool ret = true; // by default no error try { for( size_t i = 0; i < files.size(); ++i ) { const std::string & filename = files[i]; fn = filename.c_str(); assert( fn && *fn ); (void)fn; Reader reader; reader.SetFileName( filename.c_str() ); gdcmDebugMacro( "Processing: " << filename ); if( !reader.Read() ) { gdcmErrorMacro( "Could not read: " << filename ); return false; } const File &file = reader.GetFile(); std::vector theDataSets; theDataSets = theManager.SendStore( file ); if( theDataSets.empty() ) { gdcmErrorMacro( "Could not C-STORE: " << filename ); return false; } assert( theDataSets.size() == 1 ); const DataSet &ds = theDataSets[0]; assert ( ds.FindDataElement(Tag(0x0, 0x0900)) ); DataElement const & de = ds.GetDataElement(Tag(0x0,0x0900)); Attribute<0x0,0x0900> at; at.SetFromDataElement( de ); // PS 3.4 - 2011 // Table W.4-1 C-STORE RESPONSE STATUS VALUES const uint16_t theVal = at.GetValue(); // http://dicom.nema.org/medical/dicom/current/output/chtml/part07/chapter_C.html if( theVal == 0x0 ) // Success { gdcmDebugMacro( "C-Store of file " << filename << " was successful." ); } else if ( theVal == 0x0001 || (theVal & 0xf000) == 0xb000 ) // Warning { gdcmWarningMacro( "C-Store of file " << filename << " had a warning." ); } else if ( (theVal & 0xf000) == 0xa000 || (theVal & 0xf000) == 0xc000 ) // Failure //case 0xA700: //case 0xA900: //case 0xC000: { // TODO: value from 0901 ? gdcmErrorMacro( "C-Store of file " << filename << " was a failure." ); Attribute<0x0,0x0902> errormsg; errormsg.SetFromDataSet( ds ); const char *themsg = errormsg.GetValue(); assert( themsg ); (void)themsg; gdcmErrorMacro( "Response Status: " << themsg ); ret = false; // at least one file was not sent correctly } else gdcmWarningMacro( "Unhandle error code: " << theVal ); theManager.InvokeEvent( IterationEvent() ); } } catch ( Exception &e ) { (void)e; //to avoid unreferenced variable warning on release // If you reach here this is basically because GDCM does not support encoding other // than raw transfer syntx (Little Endian Explicit/Implicit...) theManager.BreakConnection(-1);//wait for a while for the connection to break, ie, infinite gdcmErrorMacro( "C-Store of file " << fn << " was unsuccessful, aborting. " ); (void)fn; gdcmErrorMacro( "Error was " << e.what() ); return false; } catch (...) { theManager.BreakConnection(-1);//wait for a while for the connection to break, ie, infinite gdcmErrorMacro( "C-Store of file " << fn << " was unsuccessful, aborting. " ); return false; } theManager.BreakConnection(-1);//wait for a while for the connection to break, ie, infinite return ret; } } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmCompositeNetworkFunctions.h000066400000000000000000000135511412732066400270300ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMCOMPOSITENETWORKFUNCTIONS_H #define GDCMCOMPOSITENETWORKFUNCTIONS_H #include "gdcmDirectory.h" #include "gdcmBaseRootQuery.h" // EQueryLevel / EQueryType #include #include namespace gdcm { /** * \brief Composite Network Functions * \details These functions provide a generic API to the DICOM functions implemented in * GDCM. * Advanced users can use this code as a template for building their own * versions of these functions (for instance, to provide progress bars or some * other way of handling returned query information), but for most users, these * functions should be sufficient to interface with a PACS to a local machine. * Note that these functions are not contained within a static class or some * other class-style interface, because multiple connections can be * instantiated in the same program. The DICOM standard is much more function * oriented rather than class oriented in this instance, so the design of this * API reflects that functional approach. * These functions implements the following SCU operations: * \li C-ECHO SCU * \li C-FIND SCU * \li C-STORE SCU * \li C-MOVE SCU (+internal C-STORE SCP) */ class GDCM_EXPORT CompositeNetworkFunctions { public: /// The most basic network function. Use this function to ensure that the /// remote server is responding on the given IP and port number as expected. /// \param aetitle when not set will default to 'GDCMSCU' /// \param call when not set will default to 'ANY-SCP' /// \warning This is an error to set remote to NULL or portno to 0 /// \return true if it worked. static bool CEcho( const char *remote, uint16_t portno, const char *aetitle = nullptr, const char *call = nullptr ); typedef std::pair KeyValuePairType; typedef std::vector< KeyValuePairType > KeyValuePairArrayType; /// This function will take a list of strings and tags and fill in a query that /// can be used for either CFind or CMove (depending on the input boolean /// \param inMove). /// Note that the caller is responsible for deleting the constructed query. /// This function is used to build both a move and a find query /// (true for inMove if it's move, false if it's find) static BaseRootQuery* ConstructQuery(ERootType inRootType, EQueryLevel inQueryLevel, const DataSet& queryds, EQueryType queryType = eFind ); /// \deprecated static BaseRootQuery* ConstructQuery(ERootType inRootType, EQueryLevel inQueryLevel, const KeyValuePairArrayType& keys, EQueryType queryType = eFind ); /// This function will use the provided query to get files from a remote server. /// NOTE that this functionality is essentially equivalent to C-GET in the /// DICOM standard; however, C-GET has been deprecated, so this function /// allows for the user to ask a remote server for files matching a query and /// return them to the local machine. /// Files will be written to the given output directory. /// If the operation succeeds, the function returns true. /// This function is a prime candidate for being overwritten by expert users; /// if the datasets should remain in memory, for instance, that behavior can /// be changed by creating a user-level version of this function. /// \param aetitle when not set will default to 'GDCMSCU' /// \param call when not set will default to 'ANY-SCP' /// This is an error to set remote to NULL or portno to 0 /// when \param outputdir is not set default to current dir ('.') /// \return true if it worked. static bool CMove( const char *remote, uint16_t portno, const BaseRootQuery* query, uint16_t portscp, const char *aetitle = nullptr, const char *call = nullptr, const char *outputdir = nullptr); /// This function will use the provided query to determine what files a remote /// server contains that match the query strings. The return is a vector of /// datasets that contain tags as reported by the server. If the dataset is /// empty, then it is possible that an error condition was encountered; in /// which case, the user should monitor the error and warning streams. /// \param aetitle when not set will default to 'GDCMSCU' /// \param call when not set will default to 'ANY-SCP' /// \warning This is an error to set remote to NULL or portno to 0 /// \return true if it worked. static bool CFind( const char *remote, uint16_t portno, const BaseRootQuery* query, std::vector &retDataSets, const char *aetitle = nullptr, const char *call = nullptr ); /// This function will place the provided files into the remote server. /// The function returns true if it worked for all files. /// \warning the server side can refuse an association on a given file /// \param aetitle when not set will default to 'GDCMSCU' /// \param call when not set will default to 'ANY-SCP' /// \warning This is an error to set remote to NULL or portno to 0 /// \return true if it worked for all files static bool CStore( const char *remote, uint16_t portno, const Directory::FilenamesType & filenames, const char *aetitle = nullptr, const char *call = nullptr); }; } // end namespace gdcm #endif // GDCMCOMPOSITENETWORKFUNCTIONS_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmDIMSE.h000066400000000000000000000051631412732066400224640ustar00rootroot00000000000000/*========================================================================= 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 GDCMDIMSE_H #define GDCMDIMSE_H #include "gdcmTypes.h" namespace gdcm { namespace network { /** * \brief DIMSE * \details PS 3.7 - 2009 * Annex E Command Dictionary (Normative) * E.1 REGISTRY OF DICOM COMMAND ELEMENTS * Table E.1-1 * COMMAND FIELDS (PART 1) */ class DIMSE { public: typedef enum { C_STORE_RQ = 0x0001, C_STORE_RSP = 0x8001, C_GET_RQ = 0x0010, C_GET_RSP = 0x8010, C_FIND_RQ = 0x0020, C_FIND_RSP = 0x8020, C_MOVE_RQ = 0x0021, C_MOVE_RSP = 0x8021, C_ECHO_RQ = 0x0030, C_ECHO_RSP = 0x8030, N_EVENT_REPORT_RQ = 0x0100, N_EVENT_REPORT_RSP = 0x8100, N_GET_RQ = 0x0110, N_GET_RSP = 0x8110, N_SET_RQ = 0x0120, N_SET_RSP = 0x8120, N_ACTION_RQ = 0x0130, N_ACTION_RSP = 0x8130, N_CREATE_RQ = 0x0140, N_CREATE_RSP = 0x8140, N_DELETE_RQ = 0x0150, N_DELETE_RSP = 0x8150, C_CANCEL_RQ = 0x0FFF } CommandTypes; }; /* 9.1.5.1 C-ECHO parameters Table 9.1-5 C-ECHO PARAMETERS */ class CEchoRQ { public: uint16_t MessageID; /* M */ UIComp AffectedSOPClassUID; /* M */ }; class CEchoRSP { public: /* Message ID M U Message ID Being Responded To  M Affected SOP Class UID M U(=) Status  M */ }; /** PS 3.4 - 2009 Table B.2-1 C-STORE STATUS */ class CFind { /* Failure Refused: Out of Resources A700 (0000,0902) Identifier does not match SOP Class A900 (0000,0901) (0000,0902) Unable to process Cxxx (0000,0901) (0000,0902) Cancel Matching terminated due to Cancel request FE00 None Success Matching is complete – No final Identifier is supplied. 0000 None Pending Matches are continuing – Current Match is supplied and any Optional Keys were supported in the same manner as Required Keys. FF00 Identifier Matches are continuing – Warning that one or more Optional Keys were not supported for existence and/or matching for this Identifier. FF01 Identifier */ }; } // end namespace network } // end namespace gdcm #endif //GDCMDIMSE_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmFindPatientRootQuery.cxx000066400000000000000000000210001412732066400262610ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFindPatientRootQuery.h" #include "gdcmAttribute.h" #include namespace gdcm { FindPatientRootQuery::FindPatientRootQuery() { mRootType = ePatientRootType; mHelpDescription = "Patient-level root query"; } void FindPatientRootQuery::InitializeDataSet(const EQueryLevel& inQueryLevel) { switch (inQueryLevel) { case ePatient: { Attribute<0x8,0x52> at1 = { "PATIENT " }; mDataSet.Insert( at1.GetAsDataElement() ); } break; case eStudy: { Attribute<0x8,0x52> at1 = { "STUDY " }; mDataSet.Insert( at1.GetAsDataElement() ); Attribute<0x10,0x20> PatientLevel = { "" }; mDataSet.Insert( PatientLevel.GetAsDataElement() ); } break; case eSeries: { Attribute<0x8,0x52> at1 = { "SERIES" }; mDataSet.Insert( at1.GetAsDataElement() ); Attribute<0x10,0x20> PatientLevel = { "" }; mDataSet.Insert( PatientLevel.GetAsDataElement() ); Attribute<0x20, 0xd> Studylevel = { "" }; mDataSet.Insert( Studylevel.GetAsDataElement() ); } break; case eImage: { Attribute<0x8,0x52> at1 = { "IMAGE " }; mDataSet.Insert( at1.GetAsDataElement() ); Attribute<0x10,0x20> PatientLevel = { "" }; mDataSet.Insert( PatientLevel.GetAsDataElement() ); Attribute<0x20, 0xd> Studylevel = { "" }; mDataSet.Insert( Studylevel.GetAsDataElement() ); Attribute<0x20, 0xe> SeriesLevel = { "" }; mDataSet.Insert( SeriesLevel.GetAsDataElement() ); } break; } } std::vector FindPatientRootQuery::GetTagListByLevel(const EQueryLevel& inQueryLevel) { switch (inQueryLevel) { case ePatient: return mPatient.GetAllTags(ePatientRootType); case eStudy: return mStudy.GetAllTags(ePatientRootType); case eSeries: // default: return mSeries.GetAllTags(ePatientRootType); case eImage: return mImage.GetAllTags(ePatientRootType); default: //have to return _something_ if a query level isn't given assert(0); { std::vector empty; return empty; } } } bool FindPatientRootQuery::ValidateQuery(bool inStrict) const { //if it's empty, it's not useful const DataSet &ds = GetQueryDataSet(); if (ds.Size() == 0) { if (inStrict) { gdcmWarningMacro( "Empty DataSet in ValidateQuery" ); } return false; } //search for 0x8,0x52 Attribute<0x0008, 0x0052> level; level.SetFromDataSet( ds ); const std::string & theVal = level.GetValue(); const int ilevel = BaseRootQuery::GetQueryLevelFromString( theVal.c_str() ); if( ilevel == -1 ) { gdcmWarningMacro( "Invalid Level" ); return false; } bool theReturn = true; // requirement is that tag should belong to { opttags U requiredtags } && at // least one tag from { requiredtags } std::vector tags; // Optional+Required (at same level) std::vector hiertags; // Unique + Unique level above (Hierarchical Search) if (inStrict) { QueryBase* qb = BaseRootQuery::Construct( ePatientRootType, (EQueryLevel)ilevel ); if (qb == nullptr) { gdcmWarningMacro( "Invalid Query" ); return false; } std::vector opttags = qb->GetOptionalTags(ePatientRootType); tags.insert( tags.begin(), opttags.begin(), opttags.end() ); std::vector reqtags = qb->GetRequiredTags(ePatientRootType); tags.insert( tags.begin(), reqtags.begin(), reqtags.end() ); hiertags = qb->GetHierachicalSearchTags(ePatientRootType); tags.insert( tags.begin(), hiertags.begin(), hiertags.end() ); delete qb; } else { QueryBase* qb = nullptr; if (strcmp(theVal.c_str(), "PATIENT ") == 0) { //make sure remaining tags are somewhere in the list of required, unique, or optional tags std::vector tagGroup; qb = new QueryPatient(); tagGroup = qb->GetAllTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; } else if (strcmp(theVal.c_str(), "STUDY ") == 0) { //make sure remaining tags are somewhere in the list of required, unique, or optional tags std::vector tagGroup; qb = new QueryPatient(); tagGroup = qb->GetAllTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QueryStudy(); tagGroup = qb->GetAllTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; } else if (strcmp(theVal.c_str(), "SERIES") == 0) { //make sure remaining tags are somewhere in the list of required, unique, or optional tags std::vector tagGroup; qb = new QueryPatient(); tagGroup = qb->GetAllTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QueryStudy(); tagGroup = qb->GetAllTags(eStudyRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QuerySeries(); tagGroup = qb->GetAllTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; } else if (strcmp(theVal.c_str(), "IMAGE ") == 0 ) { //make sure remaining tags are somewhere in the list of required, unique, or optional tags std::vector tagGroup; qb = new QueryPatient(); tagGroup = qb->GetAllTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QueryStudy(); tagGroup = qb->GetAllTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QuerySeries(); tagGroup = qb->GetAllTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QueryImage(); tagGroup = qb->GetAllTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; } if (tags.empty()) { gdcmWarningMacro( "Invalid Level" ); return false; } } //all the tags in the dataset should be in that tag list //otherwise, it's not valid //also, while the level tag must be present, and the language tag can be //present (but does not have to be), some other tag must show up as well //so, have two counts: 1 for tags that are found, 1 for tags that are not //if there are no found tags, then the query is invalid //if there is one improper tag found, then the query is invalid DataSet::ConstIterator itor; Attribute<0x0008, 0x0005> language; if( inStrict ) { unsigned int thePresentTagCount = 0; for (itor = ds.Begin(); itor != ds.End(); itor++) { Tag t = itor->GetTag(); if (t == level.GetTag()) continue; if (t == language.GetTag()) continue; assert( !tags.empty() ); if (std::find(tags.begin(), tags.end(), t) == tags.end()) { //check to see if it's a language tag, 8,5, and if it is, ignore if it's one //of the possible language tag values //well, for now, just allow it if it's present. gdcmWarningMacro( "You have an extra tag: " << t ); theReturn = false; break; } else { // Ok this tags is in Unique/Required or Optional, need to check // if it is in Required/Unique now: //std::copy( hiertags.begin(), hiertags.end(), // std::ostream_iterator( std::cout, "," ) ); if (std::find(hiertags.begin(), hiertags.end(), t) != hiertags.end()) { gdcmDebugMacro( "Found at least one key: " << t ); thePresentTagCount++; } } } if( thePresentTagCount != hiertags.size() ) { gdcmWarningMacro( "Missing Key found (within the hierarchical search ones)" ); theReturn = false; } } return theReturn; } UIDs::TSName FindPatientRootQuery::GetAbstractSyntaxUID() const { return UIDs::PatientRootQueryRetrieveInformationModelFIND; } } GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmFindPatientRootQuery.h000066400000000000000000000023621412732066400257200ustar00rootroot00000000000000/*========================================================================= 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 GDCMFINDPATIENTROOTQUERY_H #define GDCMFINDPATIENTROOTQUERY_H #include "gdcmBaseRootQuery.h" namespace gdcm { /** * \brief PatientRootQuery * \details contains: the class which will produce a dataset for c-find with patient root */ class GDCM_EXPORT FindPatientRootQuery : public BaseRootQuery { friend class QueryFactory; public: FindPatientRootQuery(); void InitializeDataSet(const EQueryLevel& inQueryLevel) override; std::vector GetTagListByLevel(const EQueryLevel& inQueryLevel) override; bool ValidateQuery(bool inStrict = true) const override; UIDs::TSName GetAbstractSyntaxUID() const override; }; } // end namespace gdcm #endif // GDCMFINDPATIENTROOTQUERY_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmFindStudyRootQuery.cxx000066400000000000000000000173571412732066400260110ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFindStudyRootQuery.h" #include "gdcmAttribute.h" #include "gdcmDataSet.h" #include #include namespace gdcm { FindStudyRootQuery::FindStudyRootQuery() { mRootType = eStudyRootType; mHelpDescription = "Study-level root query"; } void FindStudyRootQuery::InitializeDataSet(const EQueryLevel& inQueryLevel) { switch (inQueryLevel) { case eStudy: { Attribute<0x8,0x52> at1 = { "STUDY " }; mDataSet.Insert( at1.GetAsDataElement() ); } break; case eSeries: { Attribute<0x8,0x52> at1 = { "SERIES" }; mDataSet.Insert( at1.GetAsDataElement() ); Attribute<0x20, 0xd> Studylevel = { "" }; mDataSet.Insert( Studylevel.GetAsDataElement() ); } default: // ePatient break; case eImage: { Attribute<0x8,0x52> at1 = { "IMAGE " }; mDataSet.Insert( at1.GetAsDataElement() ); Attribute<0x20, 0xd> Studylevel = { "" }; mDataSet.Insert( Studylevel.GetAsDataElement() ); Attribute<0x20, 0xe> SeriesLevel = { "" }; mDataSet.Insert( SeriesLevel.GetAsDataElement() ); } break; } } std::vector FindStudyRootQuery::GetTagListByLevel(const EQueryLevel& inQueryLevel) { switch (inQueryLevel) { case ePatient: return mPatient.GetAllTags(eStudyRootType); case eStudy: return mStudy.GetAllTags(eStudyRootType); case eSeries: // default: return mSeries.GetAllTags(eStudyRootType); case eImage: return mImage.GetAllTags(eStudyRootType); default: //have to return _something_ if a query level isn't given assert(0); { std::vector empty; return empty; } } } /* PS 3.4- 2011 C.4.1.2.1 Baseline Behavior of SCU The Identifier contained in a C-FIND request shall contain a single value in the Unique Key Attribute for each level above the Query/Retrieve level. No Required or Optional Keys shall be specified which are associated with levels above the Query/Retrieve level. */ bool FindStudyRootQuery::ValidateQuery(bool inStrict) const { //if it's empty, it's not useful const DataSet & ds = GetQueryDataSet(); if (ds.Size() == 0) { if (inStrict) { gdcmWarningMacro( "Empty DataSet in ValidateQuery" ); } return false; } //search for 0x8,0x52 Attribute<0x0008, 0x0052> level; level.SetFromDataSet( ds ); const std::string & theVal = level.GetValue(); const int ilevel = BaseRootQuery::GetQueryLevelFromString( theVal.c_str() ); if( ilevel == -1 ) { gdcmWarningMacro( "Invalid Level" ); return false; } bool theReturn = true; // requirement is that tag should belong to { opttags U requiredtags } && at // least one tag from { requiredtags } std::vector tags; // Optional+Required (at same level) std::vector hiertags; // Unique + Unique level above (Hierarchical Search) if (inStrict) { QueryBase* qb = BaseRootQuery::Construct( eStudyRootType, (EQueryLevel)ilevel ); if (qb == nullptr) { gdcmWarningMacro( "Invalid Query" ); return false; } std::vector opttags = qb->GetOptionalTags(eStudyRootType); tags.insert( tags.begin(), opttags.begin(), opttags.end() ); std::vector reqtags = qb->GetRequiredTags(eStudyRootType); tags.insert( tags.begin(), reqtags.begin(), reqtags.end() ); hiertags = qb->GetHierachicalSearchTags(eStudyRootType); tags.insert( tags.begin(), hiertags.begin(), hiertags.end() ); delete qb; } else //include all previous levels (ie, series gets study, image gets series and study) { QueryBase* qb = nullptr; if (strcmp(theVal.c_str(), "STUDY ") == 0) { //make sure remaining tags are somewhere in the list of required, unique, or optional tags std::vector tagGroup; qb = new QueryStudy(); tagGroup = qb->GetAllTags(eStudyRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; } if (strcmp(theVal.c_str(), "SERIES") == 0) { //make sure remaining tags are somewhere in the list of required, unique, or optional tags std::vector tagGroup; qb = new QueryStudy(); tagGroup = qb->GetAllTags(eStudyRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QuerySeries(); tagGroup = qb->GetAllTags(eStudyRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; } if (strcmp(theVal.c_str(), "IMAGE ") == 0 ) { //make sure remaining tags are somewhere in the list of required, unique, or optional tags std::vector tagGroup; qb = new QueryStudy(); tagGroup = qb->GetAllTags(eStudyRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QuerySeries(); tagGroup = qb->GetAllTags(eStudyRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QueryImage(); tagGroup = qb->GetAllTags(eStudyRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; } if (tags.empty()) { gdcmWarningMacro( "Invalid Level" ); return false; } } //all the tags in the dataset should be in that tag list //otherwise, it's not valid //also, while the level tag must be present, and the language tag can be //present (but does not have to be), some other tag must show up as well //so, have two counts: 1 for tags that are found, 1 for tags that are not //if there are no found tags, then the query is invalid //if there is one improper tag found, then the query is invalid DataSet::ConstIterator itor; Attribute<0x0008, 0x0005> language; if( inStrict ) { unsigned int thePresentTagCount = 0; for (itor = ds.Begin(); itor != ds.End(); itor++) { const Tag & t = itor->GetTag(); if (t == level.GetTag()) continue; if (t == language.GetTag()) continue; if (std::find(tags.begin(), tags.end(), t) == tags.end()) { //check to see if it's a language tag, 8,5, and if it is, ignore if it's one //of the possible language tag values //well, for now, just allow it if it's present. gdcmWarningMacro( "You have an extra tag: " << t ); theReturn = false; break; } else { // Ok this tags is in Unique/Required or Optional, need to check // if it is in Required/Unique now: //std::copy( hiertags.begin(), hiertags.end(), // std::ostream_iterator( std::cout, "," ) ); if (std::find(hiertags.begin(), hiertags.end(), t) != hiertags.end()) { gdcmDebugMacro( "Found at least one key: " << t ); thePresentTagCount++; } } } if( thePresentTagCount != hiertags.size() ) { assert( !hiertags.empty() ); gdcmWarningMacro( "Missing Key found (within the hierarchical search ones): " << hiertags[0] ); gdcmDebugMacro( "Current DataSet is: " << ds ); theReturn = false; } } return theReturn; } UIDs::TSName FindStudyRootQuery::GetAbstractSyntaxUID() const { return UIDs::StudyRootQueryRetrieveInformationModelFIND; } } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmFindStudyRootQuery.h000066400000000000000000000027131412732066400254240ustar00rootroot00000000000000/*========================================================================= 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 GDCMFINDSTUDYROOTQUERY_H #define GDCMFINDSTUDYROOTQUERY_H #include "gdcmBaseRootQuery.h" namespace gdcm { /** * \brief FindStudyRootQuery * \details contains: the class which will produce a dataset for C-FIND with study root */ class GDCM_EXPORT FindStudyRootQuery : public BaseRootQuery { friend class QueryFactory; public: FindStudyRootQuery(); void InitializeDataSet(const EQueryLevel& inQueryLevel) override; std::vector GetTagListByLevel(const EQueryLevel& inQueryLevel) override; /// have to be able to ensure that (0008,0052) is set /// that the level is appropriate (ie, not setting PATIENT for a study query /// that the tags in the query match the right level (either required, unique, optional) bool ValidateQuery(bool inStrict = true) const override; UIDs::TSName GetAbstractSyntaxUID() const override; }; } // end namespace gdcm #endif // GDCMFINDSTUDYROOTQUERY_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmImplementationClassUIDSub.cxx000066400000000000000000000050131412732066400271570ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImplementationClassUIDSub.h" #include "gdcmFileMetaInformation.h" #include "gdcmSwapper.h" namespace gdcm { namespace network { const uint8_t ImplementationClassUIDSub::ItemType = 0x52; const uint8_t ImplementationClassUIDSub::Reserved2 = 0x00; ImplementationClassUIDSub::ImplementationClassUIDSub() { ImplementationClassUID = FileMetaInformation::GetImplementationClassUID(); ItemLength = (uint16_t)ImplementationClassUID.size(); assert( (size_t)ItemLength + 4 == Size() ); } std::istream &ImplementationClassUIDSub::Read(std::istream &is) { //uint8_t itemtype = 0x0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint16_t itemlength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; char name[256]; assert( itemlength < 256 ); is.read( name, itemlength ); ImplementationClassUID = std::string(name, itemlength); assert( (size_t)ItemLength + 4 == Size() ); return is; } const std::ostream &ImplementationClassUIDSub::Write(std::ostream &os) const { os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); //os.write( (const char*)&ItemLength, sizeof(ItemLength) ); uint16_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); os.write( ImplementationClassUID.c_str(), ImplementationClassUID.size() ); return os; } size_t ImplementationClassUIDSub::Size() const { size_t ret = 0; assert( ImplementationClassUID.size() == ItemLength ); ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); ret += ItemLength; return ret; } void ImplementationClassUIDSub::Print(std::ostream &os) const { os << "ImplementationClassUID: " << ImplementationClassUID << std::endl; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmImplementationClassUIDSub.h000066400000000000000000000024271412732066400266120ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMPLEMENTATIONCLASSUIDSUB_H #define GDCMIMPLEMENTATIONCLASSUIDSUB_H #include "gdcmTypes.h" namespace gdcm { namespace network { /** * \brief ImplementationClassUIDSub * \details PS 3.7 * Table D.3-1 * IMPLEMENTATION CLASS UID SUB-ITEM FIELDS (A-ASSOCIATE-RQ) */ class ImplementationClassUIDSub { public: ImplementationClassUIDSub(); std::istream &Read(std::istream &is); const std::ostream &Write(std::ostream &os) const; size_t Size() const; void Print(std::ostream &os) const; private: static const uint8_t ItemType; static const uint8_t Reserved2; uint16_t ItemLength; std::string ImplementationClassUID; }; } // end namespace network } // end namespace gdcm #endif //GDCMMAXIMUMLENGTHSUB_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmImplementationUIDSub.cxx000066400000000000000000000024011412732066400261670ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImplementationUIDSub.h" namespace gdcm { namespace network { const uint8_t ImplementationUIDSub::ItemType = 0x52; const uint8_t ImplementationUIDSub::Reserved2 = 0x00; ImplementationUIDSub::ImplementationUIDSub() { ImplementationClassUID = "FOO"; ItemLength = (uint16_t)ImplementationClassUID.size(); } const std::ostream &ImplementationUIDSub::Write(std::ostream &os) const { os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); os.write( (const char*)&ItemLength, sizeof(ItemLength) ); os.write( ImplementationClassUID.c_str(), ImplementationClassUID.size() ); return os; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmImplementationUIDSub.h000066400000000000000000000022221412732066400256150ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMPLEMENTATIONUIDSUB_H #define GDCMIMPLEMENTATIONUIDSUB_H #include "gdcmTypes.h" namespace gdcm { namespace network { /** * \brief ImplementationUIDSub * \details Table D.3-2 * IMPLEMENTATION UID SUB-ITEM FIELDS (A-ASSOCIATE-AC) */ class GDCM_EXPORT ImplementationUIDSub { public: ImplementationUIDSub(); const std::ostream &Write(std::ostream &os) const; private: static const uint8_t ItemType; static const uint8_t Reserved2; uint16_t ItemLength; std::string ImplementationClassUID; }; } // end namespace network } // end namespace gdcm #endif //GDCMMAXIMUMLENGTHSUB_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmImplementationVersionNameSub.cxx000066400000000000000000000050221412732066400277760ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImplementationVersionNameSub.h" #include "gdcmFileMetaInformation.h" #include "gdcmSwapper.h" namespace gdcm { namespace network { const uint8_t ImplementationVersionNameSub::ItemType = 0x55; const uint8_t ImplementationVersionNameSub::Reserved2 = 0x00; ImplementationVersionNameSub::ImplementationVersionNameSub() { ImplementationVersionName = FileMetaInformation::GetImplementationVersionName(); ItemLength = (uint16_t)ImplementationVersionName.size(); assert( (size_t)ItemLength + 4 == Size() ); } std::istream &ImplementationVersionNameSub::Read(std::istream &is) { //uint8_t itemtype = 0x0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint16_t itemlength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; char name[256]; assert( itemlength < 256 ); is.read( name, itemlength ); ImplementationVersionName = std::string(name,itemlength); return is; } const std::ostream &ImplementationVersionNameSub::Write(std::ostream &os) const { os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); //os.write( (const char*)&ItemLength, sizeof(ItemLength) ); uint16_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); os.write( ImplementationVersionName.c_str(), ImplementationVersionName.size() ); return os; } size_t ImplementationVersionNameSub::Size() const { size_t ret = 0; assert( ImplementationVersionName.size() == ItemLength ); ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); ret += ItemLength; return ret; } void ImplementationVersionNameSub::Print(std::ostream &os) const { os << "ImplementationVersionName: " << ImplementationVersionName << std::endl; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmImplementationVersionNameSub.h000066400000000000000000000024411412732066400274250ustar00rootroot00000000000000/*========================================================================= 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 GDCMIMPLEMENTATIONVERSIONNAMESUB_H #define GDCMIMPLEMENTATIONVERSIONNAMESUB_H #include "gdcmTypes.h" namespace gdcm { namespace network { /** * \brief ImplementationVersionNameSub * \details Table D.3-3 * IMPLEMENTATION VERSION NAME SUB-ITEM FIELDS (A-ASSOCIATE-RQ) */ class ImplementationVersionNameSub { public: ImplementationVersionNameSub(); std::istream &Read(std::istream &is); const std::ostream &Write(std::ostream &os) const; size_t Size() const; void Print(std::ostream &os) const; private: static const uint8_t ItemType; static const uint8_t Reserved2; uint16_t ItemLength; std::string ImplementationVersionName; }; } // end namespace network } // end namespace gdcm #endif //GDCMMAXIMUMLENGTHSUB_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmMaximumLengthSub.cxx000066400000000000000000000050351412732066400254250ustar00rootroot00000000000000/*========================================================================= 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 "gdcmMaximumLengthSub.h" #include "gdcmSwapper.h" namespace gdcm { namespace network { const uint8_t MaximumLengthSub::ItemType = 0x51; const uint8_t MaximumLengthSub::Reserved2 = 0x00; MaximumLengthSub::MaximumLengthSub() { ItemLength = 0x4; MaximumLength = 0x4000; assert( (size_t)ItemLength + 4 == Size() ); } std::istream &MaximumLengthSub::Read(std::istream &is) { //uint8_t itemtype = 0x0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint16_t itemlength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; uint32_t maximumlength; is.read( (char*)&maximumlength, sizeof(MaximumLength) ); SwapperDoOp::SwapArray(&maximumlength,1); MaximumLength = maximumlength; // 16384 == max possible (0x4000) return is; } const std::ostream &MaximumLengthSub::Write(std::ostream &os) const { os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); //os.write( (const char*)&ItemLength, sizeof(ItemLength) ); { uint16_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); } //os.write( (const char*)&MaximumLength, sizeof(MaximumLength) ); { uint32_t copy = MaximumLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(MaximumLength) ); } return os; } size_t MaximumLengthSub::Size() const { size_t ret = 0; ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); ret += sizeof(MaximumLength); return ret; } void MaximumLengthSub::Print(std::ostream &os) const { os << "MaximumLength: " << MaximumLength << std::endl; } void MaximumLengthSub::SetMaximumLength(uint32_t maximumlength) { MaximumLength = maximumlength; MaximumLength -= (maximumlength % 2); } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmMaximumLengthSub.h000066400000000000000000000026231412732066400250520ustar00rootroot00000000000000/*========================================================================= 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 GDCMMAXIMUMLENGTHSUB_H #define GDCMMAXIMUMLENGTHSUB_H #include "gdcmTypes.h" namespace gdcm { namespace network { /** * \brief MaximumLengthSub * \details Annex D * Table D.1-1 * MAXIMUM LENGTH SUB-ITEM FIELDS (A-ASSOCIATE-RQ) * * or * * Table D.1-2 * Maximum length sub-item fields (A-ASSOCIATE-AC) */ class MaximumLengthSub { public: MaximumLengthSub(); std::istream &Read(std::istream &is); const std::ostream &Write(std::ostream &os) const; size_t Size() const; uint32_t GetMaximumLength() const { return MaximumLength; } void SetMaximumLength(uint32_t maximumlength); void Print(std::ostream &os) const; private: static const uint8_t ItemType; static const uint8_t Reserved2; uint16_t ItemLength; uint32_t MaximumLength; }; } // end namespace network } // end namespace gdcm #endif //GDCMMAXIMUMLENGTHSUB_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmModalityPerformedProcedureStepCreateQuery.cxx000066400000000000000000000142501412732066400325000ustar00rootroot00000000000000/*========================================================================= 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 "gdcmModalityPerformedProcedureStepCreateQuery.h" #include "gdcmAttribute.h" #include "gdcmSequenceOfItems.h" #include namespace gdcm { ModalityPerformedProcedureStepCreateQuery::ModalityPerformedProcedureStepCreateQuery( const std::string & iSopInstanceUID ) { mSopInstanceUID = iSopInstanceUID ; } bool ModalityPerformedProcedureStepCreateQuery::ValidateQuery(bool inStrict ) const { //if it's empty, it's not useful const DataSet &ds = GetQueryDataSet(); if (ds.Size() == 0) { if (inStrict) { gdcmWarningMacro( "Empty DataSet in ValidateQuery" ); } return false; } gdcm::DataSet requiredDataSet = GetRequiredDataSet(); bool theReturn = ValidDataSet( ds, requiredDataSet ) ; return theReturn; } UIDs::TSName ModalityPerformedProcedureStepCreateQuery::GetAbstractSyntaxUID() const { return UIDs::ModalityPerformedProcedureStepSOPClass; } gdcm::DataSet ModalityPerformedProcedureStepCreateQuery::GetRequiredDataSet() const { gdcm::DataSet validDataSet ; gdcm::DataElement ScheduledStepAttributeSequence( Tag(0x0040,0x0270), 0xFFFFFFFF, VR::SQ ); gdcm::SmartPointer sqItemList = new gdcm::SequenceOfItems(); ScheduledStepAttributeSequence.SetValue( *sqItemList ); validDataSet.Insert( ScheduledStepAttributeSequence ); gdcm::Item & ScheduledStepAttributeSequenceItem = sqItemList->AddNewUndefinedLengthItem(); gdcm::Attribute<0x0020,0x000D> StudyInstanceUID; ScheduledStepAttributeSequenceItem.GetNestedDataSet().Insert( StudyInstanceUID.GetAsDataElement() ); sqItemList = new gdcm::SequenceOfItems(); gdcm::DataElement ReferencedStudySequence( Tag(0x0008,0x1110), 0xFFFFFFFF, VR::SQ ); ReferencedStudySequence.SetValue( *sqItemList ); ScheduledStepAttributeSequenceItem.GetNestedDataSet().Insert( ReferencedStudySequence ); gdcm::Attribute<0x0008,0x0050> AccessionNumber; ScheduledStepAttributeSequenceItem.GetNestedDataSet().Insert( AccessionNumber.GetAsDataElement() ); gdcm::Attribute<0x0040,0x1001> RequestedProcedureID; ScheduledStepAttributeSequenceItem.GetNestedDataSet().Insert( RequestedProcedureID.GetAsDataElement() ); gdcm::Attribute<0x0032,0x1060> RequestedProcedureDescription; ScheduledStepAttributeSequenceItem.GetNestedDataSet().Insert( RequestedProcedureDescription.GetAsDataElement() ); gdcm::Attribute<0x0040,0x0009> ScheduledProcedureStepID; ScheduledStepAttributeSequenceItem.GetNestedDataSet().Insert( ScheduledProcedureStepID.GetAsDataElement() ); gdcm::Attribute<0x0040,0x0007> ScheduledProcedureStepDescription; ScheduledStepAttributeSequenceItem.GetNestedDataSet().Insert( ScheduledProcedureStepDescription.GetAsDataElement() ); sqItemList = new gdcm::SequenceOfItems(); gdcm::DataElement ScheduledProtocolCodeSequence( Tag(0x0040,0x0008), 0xFFFFFFFF, VR::SQ ); ScheduledProtocolCodeSequence.SetValue( *sqItemList ); ScheduledStepAttributeSequenceItem.GetNestedDataSet().Insert( ScheduledProtocolCodeSequence ); gdcm::Attribute<0x0010,0x0010> PatientsName; validDataSet.Insert( PatientsName.GetAsDataElement() ); gdcm::Attribute<0x0010,0x0020> PatientID ; validDataSet.Insert( PatientID.GetAsDataElement() ); gdcm::Attribute<0x0010,0x0030> PatientsBirthDate ; validDataSet.Insert( PatientsBirthDate.GetAsDataElement() ); gdcm::Attribute<0x0010,0x0040> PatientsSex ; validDataSet.Insert( PatientsSex.GetAsDataElement() ); gdcm::DataElement ReferencedPatientSequence( Tag(0x0008,0x1120), 0xFFFFFFFF, VR::SQ ); validDataSet.Insert( ReferencedPatientSequence ); gdcm::Attribute<0x0040,0x0253> PerformedProcedureStepID ; validDataSet.Insert( PerformedProcedureStepID.GetAsDataElement() ); gdcm::Attribute<0x0040,0x0241> PerformedStationAETitle ; validDataSet.Insert( PerformedStationAETitle.GetAsDataElement() ); gdcm::Attribute<0x0040,0x0242> PerformedStationName ; validDataSet.Insert( PerformedStationName.GetAsDataElement() ); gdcm::Attribute<0x0040,0x0243> PerformedLocation ; validDataSet.Insert( PerformedLocation.GetAsDataElement() ); gdcm::Attribute<0x0040,0x0244> PerformedProcedureStepStartDate ; validDataSet.Insert( PerformedProcedureStepStartDate.GetAsDataElement() ); gdcm::Attribute<0x0040,0x0245> PerformedProcedureStepStartTime ; validDataSet.Insert( PerformedProcedureStepStartTime.GetAsDataElement() ); gdcm::Attribute<0x0040,0x0252> PerformedProcedureStepStatus ; validDataSet.Insert( PerformedProcedureStepStatus.GetAsDataElement() ); gdcm::Attribute<0x0040,0x0254> PerformedProcedureStepDescription ; validDataSet.Insert( PerformedProcedureStepDescription.GetAsDataElement() ); gdcm::Attribute<0x0040,0x0255> PerformedProcedureTypeDescription ; validDataSet.Insert( PerformedProcedureTypeDescription.GetAsDataElement() ); gdcm::DataElement ProcedureCodeSequence( Tag(0x0008,0x1032), 0xFFFFFFFF, VR::SQ ); validDataSet.Insert( ProcedureCodeSequence ); gdcm::Attribute<0x0040,0x0250> PerformedProcedureStepEndDate ; validDataSet.Insert( PerformedProcedureStepEndDate.GetAsDataElement() ); gdcm::Attribute<0x0040,0x0251> PerformedProcedureStepEndTime ; validDataSet.Insert( PerformedProcedureStepEndTime.GetAsDataElement() ); gdcm::Attribute<0x0008,0x0060> Modality ; validDataSet.Insert( Modality.GetAsDataElement() ); gdcm::Attribute<0x0020,0x0010> StudyID ; validDataSet.Insert( StudyID.GetAsDataElement() ); gdcm::DataElement PerformedProtocolCodeSequence( Tag(0x0040,0x0260), 0xFFFFFFFF, VR::SQ ); validDataSet.Insert( PerformedProtocolCodeSequence ); gdcm::DataElement PerformedSeriesSequence( Tag(0x0040,0x0340), 0xFFFFFFFF, VR::SQ ); validDataSet.Insert( PerformedSeriesSequence ); return validDataSet ; } } GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmModalityPerformedProcedureStepCreateQuery.h000066400000000000000000000025061412732066400321260ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 GDCMMODALITYPERFORMEDPROCEDURESTEPCREATEQUERY_H #define GDCMMODALITYPERFORMEDPROCEDURESTEPCREATEQUERY_H #include "gdcmBaseQuery.h" namespace gdcm { /** * \brief ModalityPerformedProcedureStepCreateQuery * \details contains: the class which will produce a dataset for n-create for Modality Performed Procedure Step sop class */ class GDCM_EXPORT ModalityPerformedProcedureStepCreateQuery : public BaseQuery{ friend class QueryFactory; public: ModalityPerformedProcedureStepCreateQuery( const std::string & iSopInstanceUID ); gdcm::DataSet GetRequiredDataSet() const; bool ValidateQuery(bool inStrict = true) const override; UIDs::TSName GetAbstractSyntaxUID() const override; }; } // end namespace gdcm #endif // GDCMMODALITYPERFORMEDPROCEDURESTEPCREATEQUERY_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmModalityPerformedProcedureStepSetQuery.cxx000066400000000000000000000042501412732066400320270ustar00rootroot00000000000000/*========================================================================= 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 "gdcmModalityPerformedProcedureStepSetQuery.h" #include "gdcmAttribute.h" #include "gdcmSequenceOfItems.h" #include namespace gdcm { ModalityPerformedProcedureStepSetQuery::ModalityPerformedProcedureStepSetQuery( const std::string & iSopInstanceUID ) { mSopInstanceUID = iSopInstanceUID ; } bool ModalityPerformedProcedureStepSetQuery::ValidateQuery(bool inStrict ) const { //if it's empty, it's not useful const DataSet &ds = GetQueryDataSet(); if (ds.Size() == 0) { if (inStrict) { gdcmWarningMacro( "Empty DataSet in ValidateQuery" ); } return false; } gdcm::DataSet requiredDataSet = GetRequiredDataSet(); bool theReturn = ValidDataSet( ds, requiredDataSet ) ; return theReturn; } UIDs::TSName ModalityPerformedProcedureStepSetQuery::GetAbstractSyntaxUID() const { return UIDs::ModalityPerformedProcedureStepSOPClass; } gdcm::DataSet ModalityPerformedProcedureStepSetQuery::GetRequiredDataSet() const { gdcm::DataSet validDataSet ; gdcm::Attribute<0x0040,0x0252> PerformingPhysiciansName ; validDataSet.Insert( PerformingPhysiciansName.GetAsDataElement() ); gdcm::Attribute<0x0020,0x000E> SeriesInstanceUID ; validDataSet.Insert( SeriesInstanceUID.GetAsDataElement() ); gdcm::DataElement ReferencedImageSequence( Tag(0x0008,0x1140), 0xFFFFFFFF, VR::SQ ); validDataSet.Insert( ReferencedImageSequence ); gdcm::DataElement ReferencedNonImageCompositeSOPInstanceSequence( Tag(0x0040,0x0220), 0xFFFFFFFF, VR::SQ ); validDataSet.Insert( ReferencedNonImageCompositeSOPInstanceSequence ); return validDataSet ; } } GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmModalityPerformedProcedureStepSetQuery.h000066400000000000000000000024611412732066400314560ustar00rootroot00000000000000/*========================================================================= 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 GDCMMODALITYPERFORMEDPROCEDURESTEPSETQUERY_H #define GDCMMODALITYPERFORMEDPROCEDURESTEPSETQUERY_H #include "gdcmBaseQuery.h" namespace gdcm { /** * \brief ModalityPerformedProcedureStepSetQuery * \details contains: the class which will produce a dataset for n-set for Modality Performed Procedure Step sop class */ class GDCM_EXPORT ModalityPerformedProcedureStepSetQuery : public BaseQuery{ friend class QueryFactory; public: ModalityPerformedProcedureStepSetQuery( const std::string & iSopInstanceUID ); gdcm::DataSet GetRequiredDataSet() const; bool ValidateQuery(bool inStrict = true) const override; UIDs::TSName GetAbstractSyntaxUID() const override; }; } // end namespace gdcm #endif // GDCMMODALITYPERFORMEDPROCEDURESTEPSETQUERY_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmMovePatientRootQuery.cxx000066400000000000000000000212431412732066400263200ustar00rootroot00000000000000/*========================================================================= 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 "gdcmMovePatientRootQuery.h" #include "gdcmAttribute.h" #include namespace gdcm { MovePatientRootQuery::MovePatientRootQuery() { mRootType = ePatientRootType; mHelpDescription = "Patient-level root query"; } void MovePatientRootQuery::InitializeDataSet(const EQueryLevel& inQueryLevel) { switch (inQueryLevel) { case ePatient: { Attribute<0x8,0x52> at1 = { "PATIENT " }; mDataSet.Insert( at1.GetAsDataElement() ); } break; case eStudy: { Attribute<0x8,0x52> at1 = { "STUDY " }; mDataSet.Insert( at1.GetAsDataElement() ); Attribute<0x10,0x20> PatientLevel = { "" }; mDataSet.Insert( PatientLevel.GetAsDataElement() ); } break; case eSeries: { Attribute<0x8,0x52> at1 = { "SERIES" }; mDataSet.Insert( at1.GetAsDataElement() ); Attribute<0x10,0x20> PatientLevel = { "" }; mDataSet.Insert( PatientLevel.GetAsDataElement() ); Attribute<0x20, 0xd> Studylevel = { "" }; mDataSet.Insert( Studylevel.GetAsDataElement() ); } break; case eImage: { Attribute<0x8,0x52> at1 = { "IMAGE " }; mDataSet.Insert( at1.GetAsDataElement() ); Attribute<0x10,0x20> PatientLevel = { "" }; mDataSet.Insert( PatientLevel.GetAsDataElement() ); Attribute<0x20, 0xd> Studylevel = { "" }; mDataSet.Insert( Studylevel.GetAsDataElement() ); Attribute<0x20, 0xe> SeriesLevel = { "" }; mDataSet.Insert( SeriesLevel.GetAsDataElement() ); } break; } } std::vector MovePatientRootQuery::GetTagListByLevel(const EQueryLevel& inQueryLevel) { switch (inQueryLevel) { case ePatient: return mPatient.GetUniqueTags(ePatientRootType); case eStudy: return mStudy.GetUniqueTags(ePatientRootType); case eSeries: // default: return mSeries.GetUniqueTags(ePatientRootType); case eImage: return mImage.GetUniqueTags(ePatientRootType); default: //have to return _something_ if a query level isn't given assert(0); { std::vector empty; return empty; } } } bool MovePatientRootQuery::ValidateQuery(bool inStrict) const { //if it's empty, it's not useful const DataSet &ds = GetQueryDataSet(); if (ds.Size() == 0) { if (inStrict) { gdcmWarningMacro( "Empty DataSet in ValidateQuery" ); } return false; } // search for 0x8,0x52 Attribute<0x0008, 0x0052> level; level.SetFromDataSet( ds ); const std::string theVal = level.GetValue(); const int ilevel = BaseRootQuery::GetQueryLevelFromString( theVal.c_str() ); if( ilevel == -1 ) { gdcmWarningMacro( "Invalid Level" ); return false; } bool theReturn = true; // requirement is that tag should belong to { opttags U requiredtags } && at // least one tag from { requiredtags } std::vector tags; // Optional+Required (at same level) std::vector hiertags; // Unique + Unique level above (Hierarchical Search) if (inStrict) { QueryBase* qb = BaseRootQuery::Construct( ePatientRootType, (EQueryLevel)ilevel ); if (qb == nullptr) { gdcmWarningMacro( "Invalid Query" ); return false; } std::vector opttags = qb->GetOptionalTags(ePatientRootType); tags.insert( tags.begin(), opttags.begin(), opttags.end() ); std::vector reqtags = qb->GetRequiredTags(ePatientRootType); tags.insert( tags.begin(), reqtags.begin(), reqtags.end() ); hiertags = qb->GetHierachicalSearchTags(ePatientRootType); tags.insert( tags.begin(), hiertags.begin(), hiertags.end() ); delete qb; } else //include all previous levels (ie, series gets study and patient, image gets series, study, and patient) { QueryBase* qb = nullptr; if (strcmp(theVal.c_str(), "PATIENT ") == 0) { //make sure remaining tags are somewhere in the list of required, unique, or optional tags std::vector tagGroup; qb = new QueryPatient(); tagGroup = qb->GetUniqueTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; } else if (strcmp(theVal.c_str(), "STUDY ") == 0) { //make sure remaining tags are somewhere in the list of required, unique, or optional tags std::vector tagGroup; qb = new QueryPatient(); tagGroup = qb->GetUniqueTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QueryStudy(); tagGroup = qb->GetUniqueTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; } else if (strcmp(theVal.c_str(), "SERIES") == 0) { //make sure remaining tags are somewhere in the list of required, unique, or optional tags std::vector tagGroup; qb = new QueryPatient(); tagGroup = qb->GetUniqueTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QueryStudy(); tagGroup = qb->GetUniqueTags(eStudyRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QuerySeries(); tagGroup = qb->GetUniqueTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; } else if (strcmp(theVal.c_str(), "IMAGE ") == 0) { //make sure remaining tags are somewhere in the list of required, unique, or optional tags std::vector tagGroup; qb = new QueryPatient(); tagGroup = qb->GetUniqueTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QueryStudy(); tagGroup = qb->GetUniqueTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QuerySeries(); tagGroup = qb->GetUniqueTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QueryImage(); tagGroup = qb->GetUniqueTags(ePatientRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; } if (tags.empty()) { gdcmWarningMacro( "Invalid Level" ); return false; } } //all the tags in the dataset should be in that tag list //otherwise, it's not valid //also, while the level tag must be present, and the language tag can be //present (but does not have to be), some other tag must show up as well //so, have two counts: 1 for tags that are found, 1 for tags that are not //if there are no found tags, then the query is invalid //if there is one improper tag found, then the query is invalid DataSet::ConstIterator itor; Attribute<0x0008, 0x0005> language; if( inStrict ) { unsigned int thePresentTagCount = 0; for (itor = ds.Begin(); itor != ds.End(); itor++) { const Tag &t = itor->GetTag(); if (t == level.GetTag()) continue; if (t == language.GetTag()) continue; assert( !tags.empty() ); if (std::find(tags.begin(), tags.end(), t) == tags.end()) { //check to see if it's a language tag, 8,5, and if it is, ignore if it's one //of the possible language tag values //well, for now, just allow it if it's present. gdcmWarningMacro( "You have an extra tag: " << t ); theReturn = false; break; } else { // Ok this tags is in Unique/Required or Optional, need to check // if it is in Required/Unique now: //std::copy( hiertags.begin(), hiertags.end(), // std::ostream_iterator( std::cout, "," ) ); if (std::find(hiertags.begin(), hiertags.end(), t) != hiertags.end()) { gdcmDebugMacro( "Found at least one key: " << t ); thePresentTagCount++; } } } if( thePresentTagCount != hiertags.size() ) { gdcmWarningMacro( "Missing Key found (within the hierarchical search ones)" ); theReturn = false; } } return theReturn; } UIDs::TSName MovePatientRootQuery::GetAbstractSyntaxUID() const { return UIDs::PatientRootQueryRetrieveInformationModelMOVE; } } GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmMovePatientRootQuery.h000066400000000000000000000023761412732066400257530ustar00rootroot00000000000000/*========================================================================= 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 GDCMMOVEPATIENTROOTQUERY_H #define GDCMMOVEPATIENTROOTQUERY_H #include "gdcmFindPatientRootQuery.h" namespace gdcm { /** * \brief MovePatientRootQuery * \details contains: the class which will produce a dataset for c-move with patient root */ class GDCM_EXPORT MovePatientRootQuery : public BaseRootQuery { friend class QueryFactory; public: MovePatientRootQuery(); void InitializeDataSet(const EQueryLevel& inQueryLevel) override; std::vector GetTagListByLevel(const EQueryLevel& inQueryLevel) override; bool ValidateQuery(bool inStrict = true) const override; UIDs::TSName GetAbstractSyntaxUID() const override; }; } // end namespace gdcm #endif // GDCMMOVEPATIENTROOTQUERY_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmMoveStudyRootQuery.cxx000066400000000000000000000165731412732066400260360ustar00rootroot00000000000000/*========================================================================= 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 "gdcmMoveStudyRootQuery.h" #include "gdcmAttribute.h" #include "gdcmDataSet.h" #include namespace gdcm { MoveStudyRootQuery::MoveStudyRootQuery() { mRootType = eStudyRootType; mHelpDescription = "Study-level root query"; } void MoveStudyRootQuery::InitializeDataSet(const EQueryLevel& inQueryLevel) { switch (inQueryLevel) { case eStudy: { Attribute<0x8,0x52> at1 = { "STUDY " }; mDataSet.Insert( at1.GetAsDataElement() ); } break; case eSeries: { Attribute<0x8,0x52> at1 = { "SERIES" }; mDataSet.Insert( at1.GetAsDataElement() ); Attribute<0x20, 0xd> Studylevel = { "" };// make it blank mDataSet.Insert( Studylevel.GetAsDataElement() ); } default: break; case eImage: { Attribute<0x8,0x52> at1 = { "IMAGE " }; mDataSet.Insert( at1.GetAsDataElement() ); Attribute<0x20, 0xd> Studylevel = { "" };// make it blank mDataSet.Insert( Studylevel.GetAsDataElement() ); Attribute<0x20, 0xe> SeriesLevel = { "" };// make it blank mDataSet.Insert( SeriesLevel.GetAsDataElement() ); } break; } } std::vector MoveStudyRootQuery::GetTagListByLevel(const EQueryLevel& inQueryLevel) { switch (inQueryLevel) { case ePatient: return mPatient.GetUniqueTags(eStudyRootType); case eStudy: return mStudy.GetUniqueTags(eStudyRootType); case eSeries: // default: return mSeries.GetUniqueTags(eStudyRootType); case eImage: return mImage.GetUniqueTags(eStudyRootType); default: //have to return _something_ if a query level isn't given assert(0); { std::vector empty; return empty; } } } bool MoveStudyRootQuery::ValidateQuery(bool inStrict) const { //if it's empty, it's not useful const DataSet &ds = GetQueryDataSet(); if (ds.Size() == 0) { if (inStrict) { gdcmWarningMacro( "Empty DataSet in ValidateQuery" ); } return false; } //search for 0x8,0x52 Attribute<0x0008, 0x0052> level; level.SetFromDataElement( ds.GetDataElement( level.GetTag() ) ); const std::string theVal = level.GetValue(); const int ilevel = BaseRootQuery::GetQueryLevelFromString( theVal.c_str() ); if( ilevel == -1 ) { gdcmWarningMacro( "Invalid Level" ); return false; } bool theReturn = true; // requirement is that tag should belong to { opttags U requiredtags } && at // least one tag from { requiredtags } std::vector tags; // Optional+Required (at same level) std::vector hiertags; // Unique + Unique level above (Hierarchical Search) if (inStrict) { QueryBase* qb = BaseRootQuery::Construct( eStudyRootType, (EQueryLevel)ilevel ); if (qb == nullptr) { gdcmWarningMacro( "Invalid Query" ); return false; } std::vector opttags = qb->GetOptionalTags(eStudyRootType); tags.insert( tags.begin(), opttags.begin(), opttags.end() ); std::vector reqtags = qb->GetRequiredTags(eStudyRootType); tags.insert( tags.begin(), reqtags.begin(), reqtags.end() ); hiertags = qb->GetHierachicalSearchTags(eStudyRootType); tags.insert( tags.begin(), hiertags.begin(), hiertags.end() ); delete qb; } else //include all previous levels (ie, series gets study, image gets series and study) { QueryBase* qb = nullptr; if (strcmp(theVal.c_str(), "STUDY ") == 0) { //make sure remaining tags are somewhere in the list of required, unique, or optional tags std::vector tagGroup; qb = new QueryStudy(); tagGroup = qb->GetUniqueTags(eStudyRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; } if (strcmp(theVal.c_str(), "SERIES") == 0) { //make sure remaining tags are somewhere in the list of required, unique, or optional tags std::vector tagGroup; qb = new QueryStudy(); tagGroup = qb->GetUniqueTags(eStudyRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QuerySeries(); tagGroup = qb->GetUniqueTags(eStudyRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; } if (strcmp(theVal.c_str(), "IMAGE ") == 0) { //make sure remaining tags are somewhere in the list of required, unique, or optional tags std::vector tagGroup; qb = new QueryStudy(); tagGroup = qb->GetUniqueTags(eStudyRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QuerySeries(); tagGroup = qb->GetUniqueTags(eStudyRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; qb = new QueryImage(); tagGroup = qb->GetUniqueTags(eStudyRootType); tags.insert(tags.end(), tagGroup.begin(), tagGroup.end()); delete qb; } if (tags.empty()) { gdcmWarningMacro( "Invalid Level" ); return false; } } //all the tags in the dataset should be in that tag list //otherwise, it's not valid //also, while the level tag must be present, and the language tag can be //present (but does not have to be), some other tag must show up as well //so, have two counts: 1 for tags that are found, 1 for tags that are not //if there are no found tags, then the query is invalid //if there is one improper tag found, then the query is invalid DataSet::ConstIterator itor; Attribute<0x0008, 0x0005> language; if( inStrict ) { unsigned int thePresentTagCount = 0; for (itor = ds.Begin(); itor != ds.End(); itor++) { Tag t = itor->GetTag(); if (t == level.GetTag()) continue; if (t == language.GetTag()) continue; if (std::find(tags.begin(), tags.end(), t) == tags.end()) { //check to see if it's a language tag, 8,5, and if it is, ignore if it's one //of the possible language tag values //well, for now, just allow it if it's present. gdcmWarningMacro( "You have an extra tag: " << t ); theReturn = false; break; } else { // Ok this tags is in Unique/Required or Optional, need to check // if it is in Required/Unique now: //std::copy( hiertags.begin(), hiertags.end(), // std::ostream_iterator( std::cout, "," ) ); if (std::find(hiertags.begin(), hiertags.end(), t) != hiertags.end()) { gdcmDebugMacro( "Found at least one key: " << t ); thePresentTagCount++; } } } if( thePresentTagCount != hiertags.size() ) { gdcmWarningMacro( "Missing Key found (within the hierarchical search ones)" ); theReturn = false; } } return theReturn; } UIDs::TSName MoveStudyRootQuery::GetAbstractSyntaxUID() const { return UIDs::StudyRootQueryRetrieveInformationModelMOVE; } } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmMoveStudyRootQuery.h000066400000000000000000000023521412732066400254510ustar00rootroot00000000000000/*========================================================================= 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 GDCMMOVESTUDYROOTQUERY_H #define GDCMMOVESTUDYROOTQUERY_H #include "gdcmBaseRootQuery.h" namespace gdcm { /** * \brief MoveStudyRootQuery * \details contains: the class which will produce a dataset for C-MOVE with study root */ class GDCM_EXPORT MoveStudyRootQuery : public BaseRootQuery { friend class QueryFactory; public: MoveStudyRootQuery(); void InitializeDataSet(const EQueryLevel& inQueryLevel) override; std::vector GetTagListByLevel(const EQueryLevel& inQueryLevel) override; bool ValidateQuery(bool inStrict = true) const override; UIDs::TSName GetAbstractSyntaxUID() const override; }; } // end namespace gdcm #endif // GDCMMOVESTUDYROOTQUERY_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNActionMessages.cxx000066400000000000000000000025611412732066400252200ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 "gdcmNActionMessages.h" #include "gdcmUIDs.h" #include "gdcmAttribute.h" #include "gdcmImplicitDataElement.h" #include "gdcmPresentationContextRQ.h" #include "gdcmCommandDataSet.h" #include "gdcmULConnection.h" namespace gdcm{ namespace network{ std::vector NActionRQ::ConstructPDV( const ULConnection &inConnection, const BaseQuery* inQuery) { std::vector thePDV; (void)inConnection; (void)inQuery; assert( 0 && "TODO" ); return thePDV; } std::vector NActionRSP::ConstructPDVByDataSet(const DataSet* inDataSet){ std::vector thePDV; (void)inDataSet; assert( 0 && "TODO" ); return thePDV; } }//namespace network }//namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNActionMessages.h000066400000000000000000000024351412732066400246450ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 GDCMCNACTIONMESSAGES_H #define GDCMCNACTIONMESSAGES_H #include "gdcmBaseNormalizedMessage.h" namespace gdcm{ namespace network{ class ULConnection; /** * \brief NActionRQ * \details this file defines the messages for the NAction action */ class NActionRQ : public BaseNormalizedMessage { public: std::vector ConstructPDV(const ULConnection &inConnection, const BaseQuery* inQuery) override; }; /** * \brief NActionRSP * this file defines the messages for the NAction action */ class NActionRSP : public BaseNormalizedMessage { public: std::vector ConstructPDVByDataSet(const DataSet* inDataSet); }; } } #endif // GDCMCNACTIONMESSAGES_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNCreateMessages.cxx000066400000000000000000000056701412732066400252120ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 "gdcmNCreateMessages.h" #include "gdcmUIDs.h" #include "gdcmAttribute.h" #include "gdcmImplicitDataElement.h" #include "gdcmPresentationContextRQ.h" #include "gdcmCommandDataSet.h" #include "gdcmULConnection.h" namespace gdcm{ namespace network{ std::vector NCreateRQ::ConstructPDV( const ULConnection &inConnection, const BaseQuery* inQuery) { std::vector thePDVs; PresentationDataValue thePDV; PresentationContextRQ pc( inQuery->GetAbstractSyntaxUID() ); uint8_t presidx = inConnection.GetPresentationContextIDFromPresentationContext(pc); if( !presidx ) { // try harder: PresentationContextRQ pc2( inQuery->GetAbstractSyntaxUID(), UIDs::ExplicitVRLittleEndian); presidx = inConnection.GetPresentationContextIDFromPresentationContext(pc2); if( !presidx ) { gdcmErrorMacro( "Could not find Pres Cont ID" ); return thePDVs; } } thePDV.SetPresentationContextID( presidx ); thePDV.SetCommand(true); thePDV.SetLastFragment(true); //ignore incoming data set, make your own CommandDataSet ds; ds.Insert( pc.GetAbstractSyntax().GetAsDataElement() ); { Attribute<0x0,0x100> at = { 0x0140 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x110> at = { 1 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x800> at = { 1 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x1000> at = { inQuery->GetSOPInstanceUID() }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x0> at = { 0 }; unsigned int glen = ds.GetLength(); assert( (glen % 2) == 0 ); at.SetValue( glen ); ds.Insert( at.GetAsDataElement() ); } thePDV.SetDataSet(ds); thePDVs.push_back(thePDV); thePDV.SetDataSet(inQuery->GetQueryDataSet()); thePDV.SetMessageHeader( 2 ); thePDVs.push_back(thePDV); return thePDVs; } std::vector NCreateRSP::ConstructPDVByDataSet(const DataSet* inDataSet){ std::vector thePDV; (void)inDataSet; assert( 0 && "TODO" ); return thePDV; } }//namespace network }//namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNCreateMessages.h000066400000000000000000000024351412732066400246330ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 GDCMCNCREATEMESSAGES_H #define GDCMCNCREATEMESSAGES_H #include "gdcmBaseNormalizedMessage.h" namespace gdcm{ namespace network{ class ULConnection; /** * \brief NCreateRQ * \details this file defines the messages for the ncreate action */ class NCreateRQ : public BaseNormalizedMessage { public: std::vector ConstructPDV(const ULConnection &inConnection, const BaseQuery* inQuery) override; }; /** * \brief NCreateRSP * this file defines the messages for the ncreate action */ class NCreateRSP : public BaseNormalizedMessage { public: std::vector ConstructPDVByDataSet(const DataSet* inDataSet); }; } } #endif // GDCMCNCREATEMESSAGES_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNDeleteMessages.cxx000066400000000000000000000025611412732066400252050ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 "gdcmNDeleteMessages.h" #include "gdcmUIDs.h" #include "gdcmAttribute.h" #include "gdcmImplicitDataElement.h" #include "gdcmPresentationContextRQ.h" #include "gdcmCommandDataSet.h" #include "gdcmULConnection.h" namespace gdcm{ namespace network{ std::vector NDeleteRQ::ConstructPDV( const ULConnection &inConnection, const BaseQuery* inQuery) { std::vector thePDV; (void)inConnection; (void)inQuery; assert( 0 && "TODO" ); return thePDV; } std::vector NDeleteRSP::ConstructPDVByDataSet(const DataSet* inDataSet){ std::vector thePDV; (void)inDataSet; assert( 0 && "TODO" ); return thePDV; } }//namespace network }//namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNDeleteMessages.h000066400000000000000000000024351412732066400246320ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 GDCMCNDELETEMESSAGES_H #define GDCMCNDELETEMESSAGES_H #include "gdcmBaseNormalizedMessage.h" namespace gdcm{ namespace network{ class ULConnection; /** * \brief NDeleteRQ * \details this file defines the messages for the ndelete action */ class NDeleteRQ : public BaseNormalizedMessage { public: std::vector ConstructPDV(const ULConnection &inConnection, const BaseQuery* inQuery) override; }; /** * \brief NDeleteRSP * this file defines the messages for the ndelete action */ class NDeleteRSP : public BaseNormalizedMessage { public: std::vector ConstructPDVByDataSet(const DataSet* inDataSet); }; } } #endif // GDCMCNDELETEMESSAGES_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNEventReportMessages.cxx000066400000000000000000000027201412732066400262550ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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. =========================================================================*/ /* this file defines the messages for the neventreport action 5 oct 2010 mmr */ #include "gdcmNEventReportMessages.h" #include "gdcmUIDs.h" #include "gdcmAttribute.h" #include "gdcmImplicitDataElement.h" #include "gdcmPresentationContextRQ.h" #include "gdcmCommandDataSet.h" #include "gdcmULConnection.h" namespace gdcm{ namespace network{ std::vector NEventReportRQ::ConstructPDV( const ULConnection &inConnection, const BaseQuery* inQuery) { std::vector thePDV; (void)inConnection; (void)inQuery; assert( 0 && "TODO" ); return thePDV; } std::vector NEventReportRSP::ConstructPDVByDataSet(const DataSet* inDataSet){ std::vector thePDV; (void)inDataSet; assert( 0 && "TODO" ); return thePDV; } }//namespace network }//namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNEventReportMessages.h000066400000000000000000000025121412732066400257010ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 GDCMCNEVENTREPORTMESSAGES_H #define GDCMCNEVENTREPORTMESSAGES_H #include "gdcmBaseNormalizedMessage.h" namespace gdcm{ namespace network{ class ULConnection; /** * \brief NEventReportRQ * \details this file defines the messages for the neventreport action */ class NEventReportRQ : public BaseNormalizedMessage { public: std::vector ConstructPDV(const ULConnection &inConnection, const BaseQuery* inQuery) override; }; /** * \brief NEventReportRSP * this file defines the messages for the neventreport action */ class NEventReportRSP : public BaseNormalizedMessage { public: std::vector ConstructPDVByDataSet(const DataSet* inDataSet); }; } } #endif // GDCMCNEVENTREPORTMESSAGES_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNGetMessages.cxx000066400000000000000000000025501412732066400245200ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 "gdcmNGetMessages.h" #include "gdcmUIDs.h" #include "gdcmAttribute.h" #include "gdcmImplicitDataElement.h" #include "gdcmPresentationContextRQ.h" #include "gdcmCommandDataSet.h" #include "gdcmULConnection.h" namespace gdcm{ namespace network{ std::vector NGetRQ::ConstructPDV( const ULConnection &inConnection, const BaseQuery* inQuery) { std::vector thePDV; (void)inConnection; (void)inQuery; assert( 0 && "TODO" ); return thePDV; } std::vector NGetRSP::ConstructPDVByDataSet(const DataSet* inDataSet){ std::vector thePDV; (void)inDataSet; assert( 0 && "TODO" ); return thePDV; } }//namespace network }//namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNGetMessages.h000066400000000000000000000024021412732066400241410ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 GDCMCNGETMESSAGES_H #define GDCMCNGETMESSAGES_H #include "gdcmBaseNormalizedMessage.h" namespace gdcm{ namespace network{ class ULConnection; /** * \brief NGetRQ * \details this file defines the messages for the nget action */ class NGetRQ : public BaseNormalizedMessage { public: std::vector ConstructPDV(const ULConnection &inConnection, const BaseQuery* inQuery) override; }; /** * \brief NGetRSP * this file defines the messages for the nget action */ class NGetRSP : public BaseNormalizedMessage { public: std::vector ConstructPDVByDataSet(const DataSet* inDataSet); }; } } #endif // GDCMCNGETMESSAGES_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNSetMessages.cxx000066400000000000000000000052641412732066400245410ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 "gdcmNSetMessages.h" #include "gdcmUIDs.h" #include "gdcmAttribute.h" #include "gdcmImplicitDataElement.h" #include "gdcmPresentationContextRQ.h" #include "gdcmCommandDataSet.h" #include "gdcmULConnection.h" namespace gdcm{ namespace network{ std::vector NSetRQ::ConstructPDV( const ULConnection &inConnection, const BaseQuery* inQuery) { std::vector thePDVs; PresentationDataValue thePDV; PresentationContextRQ pc( inQuery->GetAbstractSyntaxUID() ); uint8_t presidx = inConnection.GetPresentationContextIDFromPresentationContext(pc); if( !presidx ) { // try harder: PresentationContextRQ pc2( inQuery->GetAbstractSyntaxUID(), UIDs::ExplicitVRLittleEndian); presidx = inConnection.GetPresentationContextIDFromPresentationContext(pc2); if( !presidx ) { gdcmErrorMacro( "Could not find Pres Cont ID" ); return thePDVs; } } thePDV.SetPresentationContextID( presidx ); thePDV.SetCommand(true); thePDV.SetLastFragment(true); //ignore incoming data set, make your own CommandDataSet ds; ds.Insert( pc.GetAbstractSyntax().GetAsDataElement() ); { Attribute<0x0,0x100> at = { 0x0120 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x110> at = { 1 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x800> at = { 1 }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x1001> at = { inQuery->GetSOPInstanceUID() }; ds.Insert( at.GetAsDataElement() ); } { Attribute<0x0,0x0> at = { 0 }; unsigned int glen = ds.GetLength(); assert( (glen % 2) == 0 ); at.SetValue( glen ); ds.Insert( at.GetAsDataElement() ); } thePDV.SetDataSet(ds); thePDVs.push_back(thePDV); thePDV.SetDataSet(inQuery->GetQueryDataSet()); thePDV.SetMessageHeader( 2 ); thePDVs.push_back(thePDV); return thePDVs; } std::vector NSetRSP::ConstructPDVByDataSet(const DataSet* inDataSet){ std::vector thePDV; (void)inDataSet; assert( 0 && "TODO" ); return thePDV; } }//namespace network }//namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNSetMessages.h000066400000000000000000000024021412732066400241550ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 GDCMCNSETMESSAGES_H #define GDCMCNSETMESSAGES_H #include "gdcmBaseNormalizedMessage.h" namespace gdcm{ namespace network{ class ULConnection; /** * \brief NSetRQ * \details this file defines the messages for the nset action */ class NSetRQ : public BaseNormalizedMessage { public: std::vector ConstructPDV(const ULConnection &inConnection, const BaseQuery* inQuery) override; }; /** * \brief NSetRSP * this file defines the messages for the nset action */ class NSetRSP : public BaseNormalizedMessage { public: std::vector ConstructPDVByDataSet(const DataSet* inDataSet); }; } } #endif // GDCMCNSETMESSAGES_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNetworkEvents.h000066400000000000000000000036761412732066400244500ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /* The NetworkEvents enumeration defines the inputs into the state of the network connection. These inputs can come either from user input or input from other things on the socket, ie, responses from the peer or ARTIM timeouts. Note that this enumeration is not 'power of two', like the states, because you can't have multiple simultaneous events. Multiple state outputs in transition tables, however, is possible. */ #ifndef GDCMNETWORKEVENTS_H #define GDCMNETWORKEVENTS_H namespace gdcm { namespace network{ typedef enum { eAASSOCIATERequestLocalUser = 0, eTransportConnConfirmLocal, eASSOCIATE_ACPDUreceived, eASSOCIATE_RJPDUreceived, eTransportConnIndicLocal, eAASSOCIATE_RQPDUreceived, eAASSOCIATEresponseAccept, eAASSOCIATEresponseReject, ePDATArequest, ePDATATFPDU, eARELEASERequest, eARELEASE_RQPDUReceivedOpen, eARELEASE_RPPDUReceived, eARELEASEResponse, eAABORTRequest, eAABORTPDUReceivedOpen, eTransportConnectionClosed, eARTIMTimerExpired, eUnrecognizedPDUReceived, eEventDoesNotExist } EEventID; const int cMaxEventID = eEventDoesNotExist; } } #endif //NETWORKEVENTS_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNetworkStateID.h000066400000000000000000000052641412732066400244740ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMNETWORKSTATEID_H #define GDCMNETWORKSTATEID_H namespace gdcm { namespace network { /** * Each network connection will be in a particular state at any given time. * Those states have IDs as described in the standard ps3.8-2009, roughly 1-13. * This enumeration lists those states. The actual ULState class will contain more information * about transitions to other states. * * name and date: 16 sept 2010 mmr */ enum EStateID { eStaDoesNotExist = 0, eSta1Idle = 1, eSta2Open = 2, eSta3WaitLocalAssoc = 4, eSta4LocalAssocDone = 8, eSta5WaitRemoteAssoc = 16, eSta6TransferReady = 32, eSta7WaitRelease = 64, eSta8WaitLocalRelease = 128, eSta9ReleaseCollisionRqLocal = 256, eSta10ReleaseCollisionAc = 512, eSta11ReleaseCollisionRq = 1024, eSta12ReleaseCollisionAcLocal = 2048, eSta13AwaitingClose = 4096 }; const int cMaxStateID = 13; //the transition table is built on state indices //this function will produce the index from the power-of-two EStateID inline int GetStateIndex(EStateID inState){ switch (inState){ case eStaDoesNotExist: default: return -1; case eSta1Idle: return 0; case eSta2Open: return 1; case eSta3WaitLocalAssoc: return 2; case eSta4LocalAssocDone: return 3; case eSta5WaitRemoteAssoc: return 4; case eSta6TransferReady: return 5; case eSta7WaitRelease: return 6; case eSta8WaitLocalRelease: return 7; case eSta9ReleaseCollisionRqLocal: return 8; case eSta10ReleaseCollisionAc: return 9; case eSta11ReleaseCollisionRq: return 10; case eSta12ReleaseCollisionAcLocal: return 11; case eSta13AwaitingClose: return 12; } } } } #endif //GDCMNETWORKSTATEID_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNormalizedMessageFactory.cxx000066400000000000000000000053331412732066400271360ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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. =========================================================================*/ /* This class constructs PDataPDUs, but that have been specifically constructed for the Normalized DICOM services (N-EventReport, N-Get, N-Set, N-Action, N-Create, N-Delete). It will also handle parsing the incoming data to determine which of the NormalizedPDUs the incoming data is, and so therefore allowing the scu to determine what to do with incoming data (if acting as a storescp server, for instance). */ #include "gdcmNormalizedMessageFactory.h" #include "gdcmBaseQuery.h" #include "gdcmNActionMessages.h" #include "gdcmNCreateMessages.h" #include "gdcmNDeleteMessages.h" #include "gdcmNEventReportMessages.h" #include "gdcmNGetMessages.h" #include "gdcmNSetMessages.h" namespace gdcm { namespace network { std::vector NormalizedMessageFactory::ConstructNEventReport (const ULConnection& inConnection, const BaseQuery* inQuery) { NEventReportRQ theNEventReportRQ; return theNEventReportRQ.ConstructPDV(inConnection, inQuery); } std::vector NormalizedMessageFactory::ConstructNGet (const ULConnection& inConnection, const BaseQuery* inQuery) { NGetRQ theNGetRQ; return theNGetRQ.ConstructPDV(inConnection, inQuery); } std::vector NormalizedMessageFactory::ConstructNSet (const ULConnection& inConnection, const BaseQuery* inQuery) { NSetRQ theNSetRQ; return theNSetRQ.ConstructPDV(inConnection, inQuery); } std::vector NormalizedMessageFactory::ConstructNAction (const ULConnection& inConnection, const BaseQuery* inQuery) { NActionRQ theNActionRQ; return theNActionRQ.ConstructPDV(inConnection, inQuery); } std::vector NormalizedMessageFactory::ConstructNCreate (const ULConnection& inConnection, const BaseQuery* inQuery) { NCreateRQ theNCreate; return theNCreate.ConstructPDV(inConnection, inQuery); } std::vector NormalizedMessageFactory::ConstructNDelete (const ULConnection& inConnection, const BaseQuery* inQuery) { NDeleteRQ theNDeleteRQ; return theNDeleteRQ.ConstructPDV(inConnection, inQuery); } } } GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNormalizedMessageFactory.h000066400000000000000000000032211412732066400265550ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 GDCMNORMALIZEDMESSAGEFACTORY_H #define GDCMNORMALIZEDMESSAGEFACTORY_H #include "gdcmPresentationDataValue.h" #include "gdcmULConnection.h" namespace gdcm { class BaseQuery; class File; namespace network { class BasePDU; class NormalizedMessageFactory { public: static std::vector ConstructNEventReport (const ULConnection& inConnection, const BaseQuery* inQuery); static std::vector ConstructNGet (const ULConnection& inConnection, const BaseQuery* inQuery); static std::vector ConstructNSet (const ULConnection& inConnection, const BaseQuery* inQuery); static std::vector ConstructNAction (const ULConnection& inConnection, const BaseQuery* inQuery); static std::vector ConstructNCreate (const ULConnection& inConnection, const BaseQuery* inQuery); static std::vector ConstructNDelete (const ULConnection& inConnection, const BaseQuery* inQuery); }; } } #endif // GDCMNORMALIZEDMESSAGEFACTORY_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNormalizedNetworkFunctions.cxx000066400000000000000000000231141412732066400275410ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 "gdcmNormalizedNetworkFunctions.h" #include #include "gdcmReader.h" #include "gdcmPrinter.h" #include "gdcmAttribute.h" #include "gdcmULConnectionManager.h" #include "gdcmULConnection.h" #include "gdcmDataSet.h" #include "gdcmVersion.h" #include "gdcmGlobal.h" #include "gdcmSystem.h" #include "gdcmUIDGenerator.h" #include "gdcmWriter.h" #include "gdcmSimpleSubjectWatcher.h" #include "gdcmProgressEvent.h" #include "gdcmQueryFactory.h" #include "gdcmULWritingCallback.h" #include "gdcmULBasicCallback.h" #include "gdcmPresentationContextGenerator.h" namespace gdcm { BaseQuery* NormalizedNetworkFunctions::ConstructQuery( const std::string & sopInstanceUID, const DataSet& queryds, ENQueryType queryType /*= eMMPS*/ ) { BaseQuery* outQuery = nullptr ; if( queryType == eCreateMMPS || queryType == eSetMMPS ) outQuery = QueryFactory::ProduceQuery( sopInstanceUID, queryType ); if (!outQuery) { gdcmErrorMacro( "Specify the query" ); return nullptr; } outQuery->AddQueryDataSet(queryds); // setup the special character set std::vector inCharSetType; inCharSetType.push_back( QueryFactory::GetCharacterFromCurrentLocale() ); DataElement de = QueryFactory::ProduceCharacterSetDataElement(inCharSetType); std::string param ( de.GetByteValue()->GetPointer(), de.GetByteValue()->GetLength() ); outQuery->SetSearchParameter(de.GetTag(), param ); // Print info: if (Trace::GetDebugFlag()) { outQuery->Print( Trace::GetStream() ); } return outQuery; } bool NormalizedNetworkFunctions::NEventReport( const char *remote, uint16_t portno, const BaseQuery* query, std::vector &retDataSets, const char *aetitle, const char *call ) { (void)remote; (void)portno; (void)query; (void)retDataSets; (void)aetitle; (void)call; return false ; } bool NormalizedNetworkFunctions::NGet( const char *remote, uint16_t portno, const BaseQuery* query, std::vector &retDataSets, const char *aetitle, const char *call ) { (void)remote; (void)portno; (void)query; (void)retDataSets; (void)aetitle; (void)call; return false ; } bool NormalizedNetworkFunctions::NSet( const char *remote, uint16_t portno, const BaseQuery* query, std::vector &retDataSets, const char *aetitle, const char *call ) { if( !remote ) return false; if( !aetitle ) { aetitle = "GDCMSCU"; } if( !call ) { call = "ANY-SCP"; } // $ findscu -v -d --aetitle ACME1 --call ACME_STORE -P -k 0010,0010="X*" // dhcp-67-183 5678 patqry.dcm // Add a query: // Generate the PresentationContext array from the query UID: PresentationContextGenerator generator; if( !generator.GenerateFromUID( query->GetAbstractSyntaxUID() ) ) { gdcmErrorMacro( "Failed to generate pres context." ); return false; } network::ULConnectionManager theManager; if (!theManager.EstablishConnection(aetitle, call, remote, 0, portno, 1000, generator.GetPresentationContexts())) { gdcmErrorMacro( "Failed to establish connection." ); return false; } std::vector theDataSets; std::vector theResponses; network::ULBasicCallback theCallback; theManager.SendNSet(query, &theCallback); theDataSets = theCallback.GetDataSets(); theResponses = theCallback.GetResponses(); bool ret = false; // by default an error if( theResponses.empty() ) { gdcmErrorMacro( "Failed to GetResponses." ); return false; } assert( theResponses.size() >= 1 ); // take the last one: const DataSet &ds = theResponses[ theResponses.size() - 1 ]; // FIXME assert ( ds.FindDataElement(Tag(0x0, 0x0900)) ); Attribute<0x0,0x0900> at; at.SetFromDataSet( ds ); // Table CC.2.1-2 // STATUS VALUES const uint16_t theVal = at.GetValue(); switch( theVal ) { case 0x0: gdcmDebugMacro( "The requested modification of the attribute values is performed." ); // Append the new DataSet to the ret one: retDataSets.insert( retDataSets.end(), theDataSets.begin(), theDataSets.end() ); ret = true; break; case 0x1: { gdcmWarningMacro( "Requested optional Attributes are not supported." ); } break; case 0xB305: { gdcmWarningMacro( "The UPS is already in the requested state of COMPLETED" ); } break; case 0xC310: { gdcmErrorMacro( "Refused: The UPS is not in the \"IN PROGRESS\" state " ); } break; case 0xC301: { gdcmErrorMacro( "Refused: The correct Transaction UID was not provided " ); } break; case 0xC300: { gdcmErrorMacro( "Refused: The UPS may no longer be updated " ); } break; case 0xC307: { gdcmErrorMacro( "Specified SOP Instance UID does not exist or is not a UPS Instance managed by this SCP " ); } break; default: break ; } theManager.BreakConnection(-1);//wait for a while for the connection to break, ie, infinite return ret; } bool NormalizedNetworkFunctions::NAction( const char *remote, uint16_t portno, const BaseQuery* query, std::vector &retDataSets, const char *aetitle, const char *call ) { (void)remote; (void)portno; (void)query; (void)retDataSets; (void)aetitle; (void)call; return false ; } bool NormalizedNetworkFunctions::NCreate( const char *remote, uint16_t portno, BaseQuery* query, std::vector &retDataSets, const char *aetitle, const char *call ) { if( !remote ) return false; if( !aetitle ) { aetitle = "GDCMSCU"; } if( !call ) { call = "ANY-SCP"; } // $ findscu -v -d --aetitle ACME1 --call ACME_STORE -P -k 0010,0010="X*" // dhcp-67-183 5678 patqry.dcm // Add a query: // Generate the PresentationContext array from the query UID: PresentationContextGenerator generator; if( !generator.GenerateFromUID( query->GetAbstractSyntaxUID() ) ) { gdcmErrorMacro( "Failed to generate pres context." ); return false; } network::ULConnectionManager theManager; if (!theManager.EstablishConnection(aetitle, call, remote, 0, portno, 1000, generator.GetPresentationContexts())) { gdcmErrorMacro( "Failed to establish connection." ); return false; } std::vector theDataSets; std::vector theResponses; //theDataSets = theManager.SendFind( query ); network::ULBasicCallback theCallback; theManager.SendNCreate(query, &theCallback); theDataSets = theCallback.GetDataSets(); theResponses = theCallback.GetResponses(); bool ret = false; // by default an error if( theResponses.empty() ) { gdcmErrorMacro( "Failed to GetResponses." ); return false; } assert( theResponses.size() >= 1 ); // take the last one: const DataSet &ds = theResponses[ theResponses.size() - 1 ]; // FIXME assert ( ds.FindDataElement(Tag(0x0, 0x0900)) ); Attribute<0x0,0x0900> at; at.SetFromDataSet( ds ); // Table CC.2.1-2 // STATUS VALUES const uint16_t theVal = at.GetValue(); switch( theVal ) { case 0x0: // The requested state change was performed gdcmDebugMacro( "The requested state change was performed." ); // Append the new DataSet to the ret one: retDataSets.insert( retDataSets.end(), theDataSets.begin(), theDataSets.end() ); { Attribute<0x0000,0x1000> sopInstanceUIDAt; sopInstanceUIDAt.SetFromDataSet( ds ); query->SetSOPInstanceUID( sopInstanceUIDAt.GetValue() ); } ret = true; break; case 0xB304: // The UPS is already in the requested state of CANCELED { gdcmWarningMacro( "Offending Element: The UPS is already in the requested state of CANCELED" ); } break; case 0xB306: // The UPS is already in the requested state of COMPLETED { gdcmWarningMacro( "The UPS is already in the requested state of COMPLETED" ); } break; case 0xC300: { gdcmErrorMacro( "Refused: The UPS may no longer be updated " ); } break; case 0xC301: { gdcmErrorMacro( "Refused: The correct Transaction UID was not provided " ); } break; case 0xC302: { gdcmErrorMacro( "Refused: The UPS is already IN PROGRESS " ); } break; case 0xC303: { gdcmErrorMacro( "Refused: The UPS may only become SCHEDULED via NCREATE, not N-SET or N-ACTION " ); } break; case 0xC304: { gdcmErrorMacro( "Refused: The UPS has not met final state requirements for the requested state change " ); } break; case 0xC307: { gdcmErrorMacro( "Specified SOP Instance UID does not exist or is not a UPS Instance managed by this SCP " ); } break; case 0xC310: { gdcmErrorMacro( "Refused: The UPS is not yet in the \"IN PROGRESS\" state " ); } break; default: break ; } theManager.BreakConnection(-1);//wait for a while for the connection to break, ie, infinite return ret; } bool NormalizedNetworkFunctions::NDelete( const char *remote, uint16_t portno, const BaseQuery* query, std::vector &retDataSets, const char *aetitle, const char *call ) { (void)remote; (void)portno; (void)query; (void)retDataSets; (void)aetitle; (void)call; return false ; } } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmNormalizedNetworkFunctions.h000066400000000000000000000060361412732066400271720ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2014 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 GDCMNORMALIZEDNETWORKFUNCTIONS_H #define GDCMNORMALIZEDNETWORKFUNCTIONS_H #include "gdcmDirectory.h" #include "gdcmBaseQuery.h" // EQueryLevel / EQueryType #include #include namespace gdcm { /** * \brief Normalized Network Functions * \details These functions provide a generic API to the DICOM functions implemented in * GDCM. * Advanced users can use this code as a template for building their own * versions of these functions (for instance, to provide progress bars or some * other way of handling returned query information), but for most users, these * functions should be sufficient to interface with a PACS to a local machine. * Note that these functions are not contained within a static class or some * other class-style interface, because multiple connections can be * instantiated in the same program. The DICOM standard is much more function * oriented rather than class oriented in this instance, so the design of this * API reflects that functional approach. * These functions implements the following SCU operations: * \li N-EVENT-REPORT * \li N-GET * \li N-SET * \li N-ACTION * \li N-CREATE * \li N-DELETE */ class GDCM_EXPORT NormalizedNetworkFunctions { public: static BaseQuery* ConstructQuery( const std::string & sopInstanceUID, const DataSet& queryds, ENQueryType queryType = eCreateMMPS ); static bool NEventReport( const char *remote, uint16_t portno, const BaseQuery* query, std::vector &retDataSets, const char *aetitle, const char *call ); static bool NGet( const char *remote, uint16_t portno, const BaseQuery* query, std::vector &retDataSets, const char *aetitle, const char *call ); static bool NSet( const char *remote, uint16_t portno, const BaseQuery* query, std::vector &retDataSets, const char *aetitle, const char *call ); static bool NAction( const char *remote, uint16_t portno, const BaseQuery* query, std::vector &retDataSets, const char *aetitle, const char *call ); static bool NCreate( const char *remote, uint16_t portno, BaseQuery* query, std::vector &retDataSets, const char *aetitle, const char *call ); static bool NDelete( const char *remote, uint16_t portno, const BaseQuery* query, std::vector &retDataSets, const char *aetitle, const char *call ); }; } // end namespace gdcm #endif // GDCMCOMPOSITENETWORKFUNCTIONS_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmPDUFactory.cxx000066400000000000000000000270071412732066400241570ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /* basically, given an initial byte, construct the appropriate PDU. 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 class to construct specific instances of PDUs, and return the BasePDU class. */ #include "gdcmPDUFactory.h" #include "gdcmAAbortPDU.h" #include "gdcmAAssociateACPDU.h" #include "gdcmAAssociateRJPDU.h" #include "gdcmAAssociateRQPDU.h" #include "gdcmAReleaseRPPDU.h" #include "gdcmAReleaseRQPDU.h" #include "gdcmPDataTFPDU.h" #include "gdcmCompositeMessageFactory.h" #include "gdcmNormalizedMessageFactory.h" #include "gdcmBaseRootQuery.h" #include "gdcmBasePDU.h" namespace gdcm { namespace network { //eventually needs to be smartpointer'd BasePDU* PDUFactory::ConstructPDU(uint8_t itemtype) { BasePDU* thePDU = nullptr; switch (itemtype) { case 0x01: thePDU = new AAssociateRQPDU; break; case 0x02: thePDU = new AAssociateACPDU; break; case 0x03: thePDU = new AAssociateRJPDU; break; case 0x04: thePDU = new PDataTFPDU; break; case 0x05: thePDU = new AReleaseRQPDU; break; case 0x06: thePDU = new AReleaseRPPDU; break; case 0x07: thePDU = new AAbortPDU; break; //default is that the PDU remains null } if( !thePDU ) { gdcmErrorMacro( "Could not construct PDU for itemtype: " << (int)itemtype ); } return thePDU; } //determine which event was received by the PDU type EEventID PDUFactory::DetermineEventByPDU(const BasePDU* inPDU) { if(inPDU) { const AAssociateRQPDU* theAAssociateRQPDU = dynamic_cast(inPDU); if (theAAssociateRQPDU != nullptr) { return eAASSOCIATE_RQPDUreceived; } const AAssociateACPDU* theAAssociateACPDU = dynamic_cast(inPDU); if (theAAssociateACPDU != nullptr) { return eASSOCIATE_ACPDUreceived; } const AAssociateRJPDU* theAAssociateRJPDU = dynamic_cast(inPDU); if (theAAssociateRJPDU != nullptr) { return eASSOCIATE_RJPDUreceived; } const PDataTFPDU* thePDataTFPDU = dynamic_cast(inPDU); if (thePDataTFPDU != nullptr) { /// const PresentationDataValue &pdv = thePDataTFPDU->GetPresentationDataValue(0); (void)pdv; #if 0 int mh = pdv.GetMessageHeader(); if( mh == 3 ) { // E.2 MESSAGE CONTROL HEADER ENCODING // If bit 1 is set to 1, the following fragment shall contain the last // fragment of a Message Data Set or of a Message Command. std::cout << "This was the last fragment of the message data set" << std::endl; } #endif return ePDATATFPDU; } const AReleaseRQPDU* theAReleaseRQPDU = dynamic_cast(inPDU); if (theAReleaseRQPDU != nullptr) { return eARELEASE_RQPDUReceivedOpen; } const AReleaseRPPDU* theAReleaseRPPDU = dynamic_cast(inPDU); if (theAReleaseRPPDU != nullptr) { return eARELEASE_RPPDUReceived; } const AAbortPDU* theAAbortPDU = dynamic_cast(inPDU); if (theAAbortPDU != nullptr) { return eAABORTPDUReceivedOpen; } } return eEventDoesNotExist; } BasePDU* PDUFactory::ConstructReleasePDU() { AReleaseRQPDU* theAReleaseRQPDU = new AReleaseRQPDU(); return theAReleaseRQPDU; } BasePDU* PDUFactory::ConstructAbortPDU() { AAbortPDU* theAAbortPDU = new AAbortPDU(); return theAAbortPDU; } std::vector PDUFactory::CreateCEchoPDU(const ULConnection& inConnection) { std::vector pdv = CompositeMessageFactory::ConstructCEchoRQ(inConnection); std::vector::iterator pdvItor; std::vector outVector; for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++) { PDataTFPDU* thePDataTFPDU = new PDataTFPDU(); thePDataTFPDU->AddPresentationDataValue( *pdvItor ); outVector.push_back(thePDataTFPDU); } return outVector; } std::vector PDUFactory::CreateCMovePDU(const ULConnection& inConnection, const BaseRootQuery* inRootQuery) { std::vector pdv = CompositeMessageFactory::ConstructCMoveRQ(inConnection, inRootQuery ); std::vector::iterator pdvItor; std::vector outVector; for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++) { PDataTFPDU* thePDataTFPDU = new PDataTFPDU(); thePDataTFPDU->AddPresentationDataValue( *pdvItor ); outVector.push_back(thePDataTFPDU); } return outVector; } std::vector PDUFactory::CreateCStoreRQPDU(const ULConnection& inConnection, const File& file, bool writeDataSet /*= true*/ ) { std::vector pdv = CompositeMessageFactory::ConstructCStoreRQ(inConnection, file, writeDataSet ); std::vector::iterator pdvItor; std::vector outVector; for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++) { PDataTFPDU* thePDataTFPDU = new PDataTFPDU; thePDataTFPDU->AddPresentationDataValue( *pdvItor ); outVector.push_back(thePDataTFPDU); } return outVector; } std::vector PDUFactory::CreateCStoreRSPPDU(const DataSet* inDataSet, const BasePDU* inPDU) { std::vector pdv = CompositeMessageFactory::ConstructCStoreRSP(inDataSet, inPDU ); std::vector::iterator pdvItor; std::vector outVector; for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++) { PDataTFPDU* thePDataTFPDU = new PDataTFPDU; thePDataTFPDU->AddPresentationDataValue( *pdvItor ); outVector.push_back(thePDataTFPDU); } return outVector; } std::vector PDUFactory::CreateCFindPDU(const ULConnection& inConnection, const BaseRootQuery* inRootQuery) { //still have to build this! std::vector pdv = CompositeMessageFactory::ConstructCFindRQ(inConnection, inRootQuery ); std::vector::iterator pdvItor; std::vector outVector; for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++) { PDataTFPDU* thePDataTFPDU = new PDataTFPDU(); thePDataTFPDU->AddPresentationDataValue( *pdvItor ); outVector.push_back(thePDataTFPDU); } return outVector; } std::vector PDUFactory::CreateNEventReportPDU (const ULConnection& inConnection, const BaseQuery *inQuery) { //still have to build this! std::vector pdv = NormalizedMessageFactory::ConstructNEventReport(inConnection, inQuery ); std::vector::iterator pdvItor; std::vector outVector; for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++) { PDataTFPDU* thePDataTFPDU = new PDataTFPDU(); thePDataTFPDU->AddPresentationDataValue( *pdvItor ); outVector.push_back(thePDataTFPDU); } return outVector; } std::vector PDUFactory::CreateNGetPDU (const ULConnection& inConnection, const BaseQuery *inQuery) { //still have to build this! std::vector pdv = NormalizedMessageFactory::ConstructNGet(inConnection, inQuery ); std::vector::iterator pdvItor; std::vector outVector; for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++) { PDataTFPDU* thePDataTFPDU = new PDataTFPDU(); thePDataTFPDU->AddPresentationDataValue( *pdvItor ); outVector.push_back(thePDataTFPDU); } return outVector; } std::vector PDUFactory::CreateNSetPDU (const ULConnection& inConnection, const BaseQuery *inQuery) { //still have to build this! std::vector pdv = NormalizedMessageFactory::ConstructNSet(inConnection, inQuery ); std::vector::iterator pdvItor; std::vector outVector; for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++) { PDataTFPDU* thePDataTFPDU = new PDataTFPDU(); thePDataTFPDU->AddPresentationDataValue( *pdvItor ); outVector.push_back(thePDataTFPDU); } return outVector; } std::vector PDUFactory::CreateNActionPDU (const ULConnection& inConnection, const BaseQuery *inQuery) { //still have to build this! std::vector pdv = NormalizedMessageFactory::ConstructNAction(inConnection, inQuery ); std::vector::iterator pdvItor; std::vector outVector; for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++) { PDataTFPDU* thePDataTFPDU = new PDataTFPDU(); thePDataTFPDU->AddPresentationDataValue( *pdvItor ); outVector.push_back(thePDataTFPDU); } return outVector; } std::vector PDUFactory::CreateNCreatePDU (const ULConnection& inConnection, const BaseQuery *inQuery) { //still have to build this! std::vector pdv = NormalizedMessageFactory::ConstructNCreate(inConnection, inQuery ); std::vector::iterator pdvItor; std::vector outVector; for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++) { PDataTFPDU* thePDataTFPDU = new PDataTFPDU(); thePDataTFPDU->AddPresentationDataValue( *pdvItor ); outVector.push_back(thePDataTFPDU); } return outVector; } std::vector PDUFactory::CreateNDeletePDU (const ULConnection& inConnection, const BaseQuery *inQuery) { //still have to build this! std::vector pdv = NormalizedMessageFactory::ConstructNDelete(inConnection, inQuery ); std::vector::iterator pdvItor; std::vector outVector; for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++) { PDataTFPDU* thePDataTFPDU = new PDataTFPDU(); thePDataTFPDU->AddPresentationDataValue( *pdvItor ); outVector.push_back(thePDataTFPDU); } return outVector; } //given data pdus, produce the presentation data values stored within. //all operations have these as the payload of the data sending operation //however, echo does not have a dataset in the pdv. std::vector PDUFactory::GetPDVs(const std::vector & inDataPDUs) { std::vector::const_iterator itor; std::vector outPDVs; for (itor = inDataPDUs.begin(); itor < inDataPDUs.end(); itor++) { PDataTFPDU* thePDataTFPDU = dynamic_cast(*itor); if (thePDataTFPDU == nullptr) { assert(0); //shouldn't really get here. return outPDVs; //just stop now, no longer with data pdus. } size_t theNumPDVsinPDU = thePDataTFPDU->GetNumberOfPresentationDataValues(); for (size_t i = 0; i < theNumPDVsinPDU; i++) { outPDVs.push_back(thePDataTFPDU->GetPresentationDataValue(i)); } } return outPDVs; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmPDUFactory.h000066400000000000000000000066271412732066400236110ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMPDUFACTORY_H #define GDCMPDUFACTORY_H #include "gdcmTypes.h" #include "gdcmNetworkEvents.h" #include "gdcmULConnection.h" #include "gdcmPresentationDataValue.h" namespace gdcm{ class BaseRootQuery; class BaseQuery; class File; namespace network{ class BasePDU; /** * \brief PDUFactory basically, given an initial byte, construct the * \details appropriate PDU. This way, the event loop doesn't have to know about all * the different PDU types. */ class PDUFactory { public: static BasePDU* ConstructPDU(uint8_t itemtype);//eventually needs to be smartpointer'd static EEventID DetermineEventByPDU(const BasePDU* inPDU); static BasePDU* ConstructReleasePDU(); static BasePDU* ConstructAbortPDU(); //these are the composite PDU construction methods for the PDataPDUs. //basically, builds a pdatapdu, and then puts the appropriate information in //for the appropriate composite service (c-echo, c-find, c-store, c-get, c-move) //the connection is necessary to construct the stream of PDVs that will //be then placed into the vector of PDUs static std::vector CreateCEchoPDU(const ULConnection& inConnection); static std::vector CreateCStoreRQPDU(const ULConnection& inConnection, const File &file, bool writeDataSet = true ); static std::vector CreateCStoreRSPPDU(const DataSet *inDataSet, const BasePDU* inPC); static std::vector CreateCFindPDU(const ULConnection& inConnection, const BaseRootQuery* inRootQuery); static std::vector CreateCMovePDU(const ULConnection& inConnection, const BaseRootQuery* inRootQuery); static std::vector CreateNEventReportPDU (const ULConnection& inConnection, const BaseQuery *inQuery); static std::vector CreateNGetPDU (const ULConnection& inConnection, const BaseQuery *inQuery); static std::vector CreateNSetPDU (const ULConnection& inConnection, const BaseQuery *inQuery); static std::vector CreateNActionPDU (const ULConnection& inConnection, const BaseQuery *inQuery); static std::vector CreateNCreatePDU (const ULConnection& inConnection, const BaseQuery *inQuery); static std::vector CreateNDeletePDU (const ULConnection& inConnection, const BaseQuery *inQuery); //given data pdus, produce the presentation data values stored within. //all operations have these as the payload of the data sending operation //however, echo does not have a dataset in the pdv. static std::vector GetPDVs(const std::vector & inDataPDUs); }; } } #endif //GDCMPDUFACTORY_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmPDataTFPDU.cxx000066400000000000000000000071611412732066400237720ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPDataTFPDU.h" #include "gdcmSwapper.h" namespace gdcm { namespace network { const uint8_t PDataTFPDU::ItemType = 0x04; // PDUType ? const uint8_t PDataTFPDU::Reserved2 = 0x00; PDataTFPDU::PDataTFPDU() { assert(Size() < std::numeric_limits::max()); ItemLength = (uint32_t)Size() - 6; assert( (ItemLength + 4 + 1 + 1) == Size() ); } std::istream &PDataTFPDU::Read(std::istream &is) { //uint8_t itemtype = 0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2 = 0; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint32_t itemlength = ItemLength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; size_t curlen = 0; while( curlen < ItemLength ) { PresentationDataValue pdv; pdv.Read( is ); V.push_back( pdv ); curlen += pdv.Size(); } assert( curlen == ItemLength ); assert( (ItemLength + 4 + 1 + 1) == Size() ); return is; } std::istream &PDataTFPDU::ReadInto(std::istream &is, std::ostream &os) { uint8_t itemtype = 0; is.read( (char*)&itemtype, sizeof(ItemType) ); assert( itemtype == ItemType ); uint8_t reserved2 = 0; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint32_t itemlength = ItemLength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; size_t curlen = 0; while( curlen < ItemLength ) { PresentationDataValue pdv; pdv.ReadInto( is, os ); V.push_back( pdv ); curlen += pdv.Size(); } assert( curlen == ItemLength ); assert( (ItemLength + 4 + 1 + 1) == Size() ); return is; } const std::ostream &PDataTFPDU::Write(std::ostream &os) const { assert( (ItemLength + 4 + 1 + 1) == Size() ); os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); //os.write( (const char*)&ItemLength, sizeof(ItemLength) ); uint32_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); std::vector::const_iterator it = V.begin(); for( ; it != V.end(); ++it ) { it->Write( os ); } return os; } size_t PDataTFPDU::Size() const { size_t ret = 0; ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); std::vector::const_iterator it = V.begin(); for( ; it != V.end(); ++it ) { ret += it->Size( ); } return ret; } void PDataTFPDU::Print(std::ostream &os) const { //static const uint8_t ItemType; // PDUType ? //static const uint8_t Reserved2; os << "ItemLength: " << ItemLength << std::endl; // PDU Length ? os << "PresentationDataValue: " << std::endl; std::vector::const_iterator it = V.begin(); for( ; it != V.end(); ++it ) { it->Print( os ); } os << std::endl; } bool PDataTFPDU::IsLastFragment() const { if (V.empty()) return true; return V[V.size()-1].GetIsLastFragment(); } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmPDataTFPDU.h000066400000000000000000000036751412732066400234250ustar00rootroot00000000000000/*========================================================================= 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 GDCMPDATATFPDU_H #define GDCMPDATATFPDU_H #include "gdcmTypes.h" #include "gdcmPresentationDataValue.h" #include "gdcmBasePDU.h" #include namespace gdcm { namespace network { /** * \brief PDataTFPDU * \details Table 9-22 * P-DATA-TF PDU FIELDS */ class GDCM_EXPORT PDataTFPDU : public BasePDU { public: PDataTFPDU(); std::istream &Read(std::istream &is) override; const std::ostream &Write(std::ostream &os) const override; /// \internal Compute Size size_t Size() const override; void AddPresentationDataValue( PresentationDataValue const &pdv ) { V.push_back( pdv ); assert(Size() < std::numeric_limits::max()); ItemLength = (uint32_t)Size() - 6; } typedef std::vector::size_type SizeType; PresentationDataValue const &GetPresentationDataValue(SizeType i) const { assert( !V.empty() && i < V.size() ); return V[i]; } SizeType GetNumberOfPresentationDataValues() const { return V.size(); } void Print(std::ostream &os) const override; bool IsLastFragment() const override; protected: std::istream &ReadInto(std::istream &is, std::ostream &os); private: static const uint8_t ItemType; // PDUType ? static const uint8_t Reserved2; uint32_t ItemLength; // PDU Length ? std::vector V; }; } // end namespace network } // end namespace gdcm #endif //GDCMPDATATFPDU_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmPresentationContext.cxx000066400000000000000000000032241412732066400262120ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPresentationContext.h" #include "gdcmUIDs.h" #include "gdcmAttribute.h" #include "gdcmMediaStorage.h" #include "gdcmTransferSyntax.h" #include namespace gdcm { PresentationContext::PresentationContext( ) { ID = 0x01; } PresentationContext::PresentationContext( UIDs::TSName asname, UIDs::TSName tsname ) { ID = 0x01; const char *asnamestr = UIDs::GetUIDString( asname ); AbstractSyntax = asnamestr; const char *tsnamestr = UIDs::GetUIDString( tsname ); AddTransferSyntax( tsnamestr ); } void PresentationContext::AddTransferSyntax( const char *tsstr ) { TransferSyntaxes.emplace_back(tsstr ); } void PresentationContext::SetPresentationContextID( uint8_t id ) { assert( id ); ID = id; } uint8_t PresentationContext::GetPresentationContextID() const { return ID; } void PresentationContext::Print(std::ostream &os) const { os << "AbstractSyntax:" << AbstractSyntax << std::endl; std::vector::const_iterator it = TransferSyntaxes.begin(); for( ; it != TransferSyntaxes.end(); ++it ) { os << *it << std::endl; } } } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmPresentationContext.h000066400000000000000000000043321412732066400256400ustar00rootroot00000000000000/*========================================================================= 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 GDCMPRESENTATIONCONTEXT_H #define GDCMPRESENTATIONCONTEXT_H #include "gdcmTypes.h" #include "gdcmUIDs.h" #include namespace gdcm { /** * \brief PresentationContext * \see PresentationContextAC PresentationContextRQ */ class GDCM_EXPORT PresentationContext { public: PresentationContext(); /// Initialize Presentation Context with AbstractSyntax set to asname /// and with a single TransferSyntax set to tsname (default to Implicit VR /// LittleEndian when not specified ). PresentationContext( UIDs::TSName asname, UIDs::TSName tsname = UIDs::ImplicitVRLittleEndianDefaultTransferSyntaxforDICOM ); void SetAbstractSyntax( const char *absyn ) { AbstractSyntax = absyn; } const char *GetAbstractSyntax() const { return AbstractSyntax.c_str(); } void AddTransferSyntax( const char *tsstr ); typedef std::vector TransferSyntaxArrayType; typedef TransferSyntaxArrayType::size_type SizeType; const char *GetTransferSyntax(SizeType i) const { return TransferSyntaxes[i].c_str(); } SizeType GetNumberOfTransferSyntaxes() const { return TransferSyntaxes.size(); } void SetPresentationContextID( uint8_t id ); uint8_t GetPresentationContextID() const; void Print(std::ostream &os) const; bool operator==(const PresentationContext & pc) const { assert( TransferSyntaxes.size() == 1 ); // TODO assert( pc.TransferSyntaxes.size() == 1 ); return AbstractSyntax == pc.AbstractSyntax && TransferSyntaxes == pc.TransferSyntaxes; } protected : std::string AbstractSyntax; std::vector TransferSyntaxes; uint8_t /*PresentationContext*/ID; }; } // end namespace gdcm #endif //GDCMPRESENTATIONCONTEXT_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmPresentationContextAC.cxx000066400000000000000000000065041412732066400264220ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPresentationContextAC.h" #include "gdcmSwapper.h" #include namespace gdcm { namespace network { const uint8_t PresentationContextAC::ItemType = 0x21; const uint8_t PresentationContextAC::Reserved2 = 0x00; const uint8_t PresentationContextAC::Reserved6 = 0x00; const uint8_t PresentationContextAC::Reserved8 = 0x00; PresentationContextAC::PresentationContextAC() { ID = 1; // odd [1-255] Result = 0; ItemLength = 8; assert( (size_t)ItemLength + 4 == Size() ); } std::istream &PresentationContextAC::Read(std::istream &is) { //uint8_t itemtype = 0x0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint16_t itemlength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; uint8_t id; is.read( (char*)&id, sizeof(ID) ); ID = id; uint8_t reserved6; is.read( (char*)&reserved6, sizeof(Reserved6) ); uint8_t result; is.read( (char*)&result, sizeof(Result) ); Result = result; // 0-4 uint8_t reserved8; is.read( (char*)&reserved8, sizeof(Reserved6) ); SubItems.Read( is ); assert( (size_t)ItemLength + 4 == Size() ); return is; } const std::ostream &PresentationContextAC::Write(std::ostream &os) const { os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); //os.write( (const char*)&ItemLength, sizeof(ItemLength) ); uint16_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); os.write( (const char*)&ID, sizeof(ID) ); os.write( (const char*)&Reserved6, sizeof(Reserved6) ); os.write( (const char*)&Result, sizeof(Result) ); os.write( (const char*)&Reserved8, sizeof(Reserved8) ); SubItems.Write(os); assert( (size_t)ItemLength + 4 == Size() ); return os; } size_t PresentationContextAC::Size() const { size_t ret = 0; ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); ret += sizeof(ID); ret += sizeof(Reserved6); ret += sizeof(Result); ret += sizeof(Reserved8); ret += SubItems.Size(); assert(ret <= (size_t)std::numeric_limits::max); assert(ret >= 4); return ret; } void PresentationContextAC::SetTransferSyntax( TransferSyntaxSub const &ts ) { SubItems = ts; ItemLength = (uint16_t)(Size() - 4); assert( (size_t)ItemLength + 4 == Size() ); } void PresentationContextAC::Print(std::ostream &os) const { os << "ID: " << (int)ID << std::endl; os << "Result: " << (int)Result << std::endl; os << "TransferSyntax: "; SubItems.Print( os ); } void PresentationContextAC::SetPresentationContextID( uint8_t id ) { ID = id; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmPresentationContextAC.h000066400000000000000000000034301412732066400260420ustar00rootroot00000000000000/*========================================================================= 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 GDCMPRESENTATIONCONTEXTAC_H #define GDCMPRESENTATIONCONTEXTAC_H #include "gdcmTypes.h" #include "gdcmTransferSyntaxSub.h" namespace gdcm { namespace network { /** * \brief PresentationContextAC * \details Table 9-18 * PRESENTATION CONTEXT ITEM FIELDS * \see PresentationContext */ class PresentationContextAC { public: PresentationContextAC(); std::istream &Read(std::istream &is); const std::ostream &Write(std::ostream &os) const; size_t Size() const; void SetTransferSyntax( TransferSyntaxSub const &ts ); void SetPresentationContextID( uint8_t id ); void Print(std::ostream &os) const; uint8_t GetPresentationContextID() const { return ID; } TransferSyntaxSub const & GetTransferSyntax() const { return SubItems; } void SetReason( uint8_t r ) { Result = r; } uint8_t GetReason() const { return Result; } private: static const uint8_t ItemType; static const uint8_t Reserved2; uint16_t ItemLength; // len of last transfer syntax uint8_t /*PresentationContext*/ID; static const uint8_t Reserved6; uint8_t /*Reason*/Result; static const uint8_t Reserved8; TransferSyntaxSub SubItems; }; } // end namespace network } // end namespace gdcm #endif //GDCMPRESENTATIONCONTEXTAC_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmPresentationContextGenerator.cxx000066400000000000000000000123451412732066400300650ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPresentationContextGenerator.h" #include "gdcmReader.h" #include "gdcmTransferSyntax.h" #include // std::find namespace gdcm { std::string PresentationContextGenerator::DefaultTransferSyntax = "1.2.840.10008.1.2"; const char *PresentationContextGenerator::GetDefaultTransferSyntax() const { return DefaultTransferSyntax.c_str(); } void PresentationContextGenerator::SetDefaultTransferSyntax( const TransferSyntax &ts ) { DefaultTransferSyntax = ts.GetString(); } PresentationContextGenerator::PresentationContextGenerator() = default; //bool PresentationContextGenerator::GenerateFromQuery(BaseRootQuery *query) //{ //} bool PresentationContextGenerator::GenerateFromUID(UIDs::TSName asname) { PresContext.clear(); const char *asnamestr = UIDs::GetUIDString( asname ); const char *tsnamestr = GetDefaultTransferSyntax(); // There is a special case for MOVE operations. Need to have alternate FIND operations if( asname == UIDs::PatientRootQueryRetrieveInformationModelMOVE ) { const char *asnamestr0 = UIDs::GetUIDString( UIDs::PatientRootQueryRetrieveInformationModelFIND ); AddPresentationContext( asnamestr0, tsnamestr ); } else if( asname == UIDs::StudyRootQueryRetrieveInformationModelMOVE ) { const char *asnamestr0 = UIDs::GetUIDString( UIDs::StudyRootQueryRetrieveInformationModelFIND ); AddPresentationContext( asnamestr0, tsnamestr ); } // Always set the *MOVE after the *FIND one AddPresentationContext( asnamestr, tsnamestr ); return true; } bool PresentationContextGenerator::AddFromFile(const File &file) { Tag sopclass(0x8,0x16); DataSet const & ds = file.GetDataSet(); if( ds.FindDataElement( sopclass ) ) { // by design gdcmscu will not send/retrieve a dataset that cannot be read // this should not be too restricitive const TransferSyntax &fmits = file.GetHeader().GetDataSetTransferSyntax(); const char *tsuidvalue = fmits.GetString(); const DataElement &tsde = ds.GetDataElement( sopclass ); // Passing pointer directly. We do not try to analyze what Media Storage // it is. We should be able to support to send/receive unknown media storage const ByteValue *bv = tsde.GetByteValue(); std::string buffer( bv->GetPointer(), bv->GetLength() ); const char *sopclassvalue = buffer.c_str(); AddPresentationContext( sopclassvalue, tsuidvalue ); return true; } return false; } bool PresentationContextGenerator::GenerateFromFilenames(const Directory::FilenamesType &filenames) { PresContext.clear(); // By design GDCM C-STORE implementation only setup the association for any dataset we are // about to send. This is therefore very important to gather all possible SOP Class // we are about to send otherwise the other end will simply disconnect us // this imply that C-STORE will refuse any DataSet without SOP Class or SOP Instances Tag tsuid(0x2,0x10); Tag mediasopclass(0x2,0x2); Tag sopclass(0x8,0x16); Directory::FilenamesType::const_iterator file = filenames.begin(); std::set skiptags; for(; file != filenames.end(); ++file) { // I cannot use gdcm::Scanner as I need the TS of the file. When the file // only contains the DataSet I cannot know if this is Explicit or Implicit // Instead re-use the lower level bricks of gdcm::Scanner here: const char *fn = file->c_str(); Reader reader; reader.SetFileName( fn ); // NOTE: There is a small overhead right here: what if we are sending Deflated // TS encoded file. We should not need to read up to tag 8,16 ... if( reader.ReadUpToTag( sopclass, skiptags ) ) { AddFromFile( reader.GetFile() ); } else { gdcmErrorMacro( "Could not read: " << fn ); } } return true; } bool PresentationContextGenerator::AddPresentationContext( const char *as, const char * ts ) { // \precondition assert( as ); assert( ts ); SizeType n = PresContext.size(); PresentationContext pc; pc.SetAbstractSyntax( as ); SizeType idn = 2*n + 1; assert( idn <= std::numeric_limits::max() ); pc.SetPresentationContextID( (uint8_t)idn ); pc.AddTransferSyntax( ts ); PresentationContextArrayType::const_iterator it = std::find( PresContext.begin(), PresContext.end(), pc ); // default mode it to only append when pc is not present already: // warning dcmtk 3.5.4 will segfault if no PresentationContext is found // (fixed in 3.6.0) if( it == PresContext.end() ) { PresContext.push_back( pc ); } return true; } void PresentationContextGenerator::SetMergeModeToAbstractSyntax() { } void PresentationContextGenerator::SetMergeModeToTransferSyntax() { assert( 0 && "TODO" ); } } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmPresentationContextGenerator.h000066400000000000000000000074551412732066400275200ustar00rootroot00000000000000/*========================================================================= 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 GDCMPRESENTATIONCONTEXTGENERATOR_H #define GDCMPRESENTATIONCONTEXTGENERATOR_H #include "gdcmDirectory.h" #include "gdcmPresentationContext.h" namespace gdcm { class TransferSyntax; class File; /** * \brief PresentationContextGenerator * \details This class is responsible for generating the proper PresentationContext that * will be used in subsequent operation during a DICOM Query/Retrieve * association. The step of the association is very sensible as special care * need to be taken to explicitly define what instance are going to be send * and how they are encoded. * * For example a PresentationContext will express that negotiation requires * that CT Image Storage are send using JPEG Lossless, while US Image Storage * are sent using RLE Transfer Syntax. * * Two very different API are exposed one which will always default to little * endian transfer syntax see GenerateFromUID() * This API is used for C-ECHO, C-FIND and C-MOVE (SCU). * Another API: GenerateFromFilenames() is used for C-STORE (SCU) as it will * loop over all filenames argument to detect the actual encoding. and * therefore find the proper encoding to be used. * * Two modes are available. The default mode (SetMergeModeToAbstractSyntax) * append PresentationContext (one AbstractSyntax and one TransferSyntax), as * long a they are different. Eg MR Image Storage/JPEG2000 and MR Image * Storage/JPEGLossless would be considered different. the other mode * SetMergeModeToTransferSyntax merge any new TransferSyntax to the already * existing PresentationContext in order to re-use the same AbstractSyntax. * * \see PresentationContext */ class GDCM_EXPORT PresentationContextGenerator { public: PresentationContextGenerator(); // Set MergeMode // Default mode, each pair AbstractSyntax/TransferSyntax are only merged when // exactly identical void SetMergeModeToAbstractSyntax(); // Set MergeMode // Merge is done on a per AbstractSyntax basis. Any new TransferSyntax for a // given AbstractSyntax is merge to the existing PresentationContext referring // to that AbstractSyntax void SetMergeModeToTransferSyntax(); /// Generate the PresentationContext array from a UID (eg. VerificationSOPClass) bool GenerateFromUID(UIDs::TSName asname); /// Generate the PresentationContext array from a File-Set. File specified needs to /// be valid DICOM files. /// Used for C-STORE operations bool GenerateFromFilenames(const Directory::FilenamesType &files); /// Add a single PresentationContext from a single File. Call multiple times when /// dealing with multiple files. bool AddFromFile(const File &file); typedef std::vector PresentationContextArrayType; typedef PresentationContextArrayType::size_type SizeType; PresentationContextArrayType const &GetPresentationContexts() { return PresContext; } /// Not implemented for now. GDCM internally uses Implicit Little Endian void SetDefaultTransferSyntax( const TransferSyntax &ts ); protected: bool AddPresentationContext( const char *absyn, const char *ts ); const char *GetDefaultTransferSyntax() const; private: std::vector PresContext; static std::string DefaultTransferSyntax; }; } // end namespace gdcm #endif //GDCMPRESENTATIONCONTEXTGENERATOR_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmPresentationContextRQ.cxx000066400000000000000000000131501412732066400264540ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPresentationContextRQ.h" #include "gdcmPresentationContext.h" #include "gdcmUIDs.h" #include "gdcmSwapper.h" #include "gdcmAttribute.h" #include "gdcmGlobal.h" #include "gdcmMediaStorage.h" #include namespace gdcm { namespace network { const uint8_t PresentationContextRQ::ItemType = 0x20; const uint8_t PresentationContextRQ::Reserved2 = 0x00; const uint8_t PresentationContextRQ::Reserved6 = 0x00; const uint8_t PresentationContextRQ::Reserved7 = 0x00; const uint8_t PresentationContextRQ::Reserved8 = 0x00; PresentationContextRQ::PresentationContextRQ() { ID = 0x01; ItemLength = 8; assert( (size_t)ItemLength + 4 == Size() ); } PresentationContextRQ::PresentationContextRQ( UIDs::TSName asname, UIDs::TSName tsname ) { ID = 0x01; AbstractSyntax as; as.SetNameFromUID( asname ); SetAbstractSyntax( as ); TransferSyntaxSub ts; ts.SetNameFromUID( tsname ); assert( TransferSyntaxes.empty() ); AddTransferSyntax( ts ); } std::istream &PresentationContextRQ::Read(std::istream &is) { //uint8_t itemtype = 0x0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint16_t itemlength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; uint8_t id; is.read( (char*)&id, sizeof(ID) ); ID = id; uint8_t reserved6; is.read( (char*)&reserved6, sizeof(Reserved6) ); uint8_t reserved7; is.read( (char*)&reserved7, sizeof(Reserved7) ); // assert( reserved7 == 0 ); //no need for this assert--'This reserved field shall be sent with a value 00H but not tested to this value when received.' uint8_t reserved8; is.read( (char*)&reserved8, sizeof(Reserved6) ); SubItems.Read( is ); size_t curlen = 0; size_t offset = SubItems.Size() + 4; while( curlen + offset < ItemLength ) { TransferSyntaxSub ts; ts.Read( is ); TransferSyntaxes.push_back( ts ); curlen += ts.Size(); } assert( curlen + offset == ItemLength ); assert( (size_t)ItemLength + 4 == Size() ); return is; } const std::ostream &PresentationContextRQ::Write(std::ostream &os) const { assert( (size_t)ItemLength + 4 == Size() ); os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); uint16_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); os.write( (const char*)&ID, sizeof(ID) ); os.write( (const char*)&Reserved6, sizeof(Reserved6) ); os.write( (const char*)&Reserved7, sizeof(Reserved7) ); os.write( (const char*)&Reserved8, sizeof(Reserved8) ); SubItems.Write(os); std::vector::const_iterator it = TransferSyntaxes.begin(); for( ; it != TransferSyntaxes.end(); ++it ) { it->Write( os ); } return os; } size_t PresentationContextRQ::Size() const { size_t ret = 0; ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); ret += sizeof(ID); ret += sizeof(Reserved6); ret += sizeof(Reserved7); ret += sizeof(Reserved8); ret += SubItems.Size(); std::vector::const_iterator it = TransferSyntaxes.begin(); for( ; it != TransferSyntaxes.end(); ++it ) { ret += it->Size(); } assert(ret <= (size_t)std::numeric_limits::max); assert(ret >= 4); return ret; } void PresentationContextRQ::SetAbstractSyntax( AbstractSyntax const & as ) { SubItems = as; ItemLength = (uint16_t)(Size() - 4); assert( (size_t)ItemLength + 4 == Size() ); } void PresentationContextRQ::AddTransferSyntax( TransferSyntaxSub const &ts ) { TransferSyntaxes.push_back( ts ); ItemLength = (uint16_t)(Size() - 4); assert( (size_t)ItemLength + 4 == Size() ); } void PresentationContextRQ::SetPresentationContextID( uint8_t id ) { assert( id ); ID = id; } uint8_t PresentationContextRQ::GetPresentationContextID() const { return ID; } void PresentationContextRQ::Print(std::ostream &os) const { //static const uint8_t ItemType; //static const uint8_t Reserved2; os << "ItemLength: " << ItemLength << std::endl; // len of last transfer syntax os << "PresentationContext ID: " << (int)ID << std::endl; //static const uint8_t Reserved6; //static const uint8_t Reserved7; //static const uint8_t Reserved8; SubItems.Print( os ); std::vector::const_iterator it = TransferSyntaxes.begin(); for( ; it != TransferSyntaxes.end(); ++it ) { it->Print( os ); } } PresentationContextRQ::PresentationContextRQ(const PresentationContext & in) { AbstractSyntax as; as.SetName( in.GetAbstractSyntax() ); SetAbstractSyntax( as ); size_t n = in.GetNumberOfTransferSyntaxes(); TransferSyntaxes.clear(); for( size_t j = 0; j < n; ++j ) { TransferSyntaxSub ts; ts.SetName( in.GetTransferSyntax(j) ); AddTransferSyntax( ts ); } SetPresentationContextID( in.GetPresentationContextID() ); assert( GetNumberOfTransferSyntaxes() == in.GetNumberOfTransferSyntaxes() ); } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmPresentationContextRQ.h000066400000000000000000000062711412732066400261070ustar00rootroot00000000000000/*========================================================================= 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 GDCMPRESENTATIONCONTEXTRQ_H #define GDCMPRESENTATIONCONTEXTRQ_H #include "gdcmTypes.h" #include "gdcmAbstractSyntax.h" #include "gdcmTransferSyntaxSub.h" #include "gdcmDataSet.h" namespace gdcm { class PresentationContext; namespace network { /** * \brief PresentationContextRQ * \details Table 9-13 * PRESENTATION CONTEXT ITEM FIELDS * \see PresentationContextAC */ class GDCM_EXPORT PresentationContextRQ { public: PresentationContextRQ(); /// Initialize Presentation Context with AbstractSyntax set to asname /// and with a single TransferSyntax set to tsname (dfault to Implicit VR /// LittleEndian when not specified ). PresentationContextRQ( UIDs::TSName asname, UIDs::TSName tsname = UIDs::ImplicitVRLittleEndianDefaultTransferSyntaxforDICOM ); std::istream &Read(std::istream &is); const std::ostream &Write(std::ostream &os) const; size_t Size() const; void SetAbstractSyntax( AbstractSyntax const & absyn ); AbstractSyntax const &GetAbstractSyntax() const { return SubItems; } AbstractSyntax &GetAbstractSyntax() { return SubItems; } void AddTransferSyntax( TransferSyntaxSub const &ts ); typedef std::vector::size_type SizeType; TransferSyntaxSub const & GetTransferSyntax(SizeType i) const { return TransferSyntaxes[i]; } TransferSyntaxSub & GetTransferSyntax(SizeType i) { return TransferSyntaxes[i]; } std::vector const & GetTransferSyntaxes() const {return TransferSyntaxes; } SizeType GetNumberOfTransferSyntaxes() const { return TransferSyntaxes.size(); } void SetPresentationContextID( uint8_t id ); uint8_t GetPresentationContextID() const; void Print(std::ostream &os) const; bool operator==(const PresentationContextRQ & pc) const { assert( TransferSyntaxes.size() == 1 ); // TODO assert( pc.TransferSyntaxes.size() == 1 ); return SubItems == pc.SubItems && TransferSyntaxes == pc.TransferSyntaxes; } PresentationContextRQ(const PresentationContext & pc); private: static const uint8_t ItemType; static const uint8_t Reserved2; uint16_t ItemLength; // len of last transfer syntax uint8_t /*PresentationContext*/ID; static const uint8_t Reserved6; static const uint8_t Reserved7; static const uint8_t Reserved8; /* This variable field shall contain the following sub-items: one Abstract Syntax and one or more Transfer Syntax(es). For a complete description of the use and encoding of these sub-items see Sections 9.3.2.2.1 and 9.3.2.2.2. */ AbstractSyntax SubItems; std::vector TransferSyntaxes; }; } // end namespace network } // end namespace gdcm #endif //GDCMPRESENTATIONCONTEXTRQ_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmPresentationDataValue.cxx000066400000000000000000000163401412732066400264370ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPresentationDataValue.h" #include "gdcmSwapper.h" #include "gdcmFile.h" #include "gdcmAttribute.h" #include "gdcmCommandDataSet.h" #include "gdcmPrinter.h" #include namespace gdcm { namespace network { PresentationDataValue::PresentationDataValue() { MessageHeader = 0; PresentationContextID = 0; //MUST BE SET BY THE CALLER! // postcondition assert(Size() < std::numeric_limits::max()); ItemLength = (uint32_t)Size() - 4; assert (ItemLength + 4 == Size() ); } std::istream &PresentationDataValue::Read(std::istream &is) { uint32_t itemlength = ItemLength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; is.read( (char*)&PresentationContextID, sizeof(PresentationContextID) ); uint8_t mh; is.read( (char*)&mh, 1 ); MessageHeader = mh; if ( MessageHeader > 3 ) { gdcmDebugMacro( "Bizarre MessageHeader: " << MessageHeader ); } assert( ItemLength > 2 ); uint32_t vl = ItemLength - 2; Blob.resize( vl ); is.read( &Blob[0], vl ); assert (ItemLength + 4 == Size() ); return is; } std::istream &PresentationDataValue::ReadInto(std::istream &is, std::ostream &os) { uint32_t itemlength = ItemLength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; is.read( (char*)&PresentationContextID, sizeof(PresentationContextID) ); uint8_t mh; is.read( (char*)&mh, 1 ); MessageHeader = mh; if ( MessageHeader > 3 ) { gdcmDebugMacro( "Bizarre MessageHeader: " << MessageHeader ); } assert( ItemLength > 2 ); uint32_t vl = ItemLength - 2; Blob.resize( vl ); is.read( &Blob[0], vl ); os.write( &Blob[0], vl ); assert (ItemLength + 4 == Size() ); return is; } const std::ostream &PresentationDataValue::Write(std::ostream &os) const { uint32_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); assert( os.good() ); os.write( (const char*)&PresentationContextID, sizeof(PresentationContextID) ); assert( os.good() ); assert( MessageHeader <= 3 ); uint8_t t = MessageHeader; os.write( (const char*)&t, 1 ); assert( os.good() ); os.write( Blob.c_str(), Blob.size() ); assert( Blob.size() == ItemLength - 2 ); assert (ItemLength + 4 == Size() ); return os; } size_t PresentationDataValue::Size() const { size_t ret = 0; ret += sizeof(ItemLength); ret += sizeof(PresentationContextID); ret += sizeof(MessageHeader); // MESSAGE CONTROL HEADER ENCODING ret += Blob.size(); return ret; } void PresentationDataValue::SetBlob(const std::string & partialblob) { assert( !partialblob.empty() ); Blob = partialblob; assert(Size() < std::numeric_limits::max()); ItemLength = (uint32_t)Size() - 4; assert (ItemLength + 4 == Size() ); } void PresentationDataValue::SetDataSet(const DataSet & ds) { std::stringstream ss; //!!FIXME-- have to make sure that the transfer syntax is known and accounted for! ds.Write( ss ); SetBlob( ss.str() ); } const std::string &PresentationDataValue::GetBlob() const { return Blob; } //should only be one data set per chunk of pdvs. So, only return one; the //loop that gets the results from the scp will be clever and only enter this function //when the pdu has its 'last bit' set to true (ie, when all the pdvs can be sent in at once, //but the are all part of the same data set) DataSet PresentationDataValue::ConcatenatePDVBlobs(const std::vector& inPDVs) { //size_t s = inPDVs.size(); std::string theEntireBuffer;//could do it as streams. but apparently, std isn't letting me std::vector::const_iterator itor; for (itor = inPDVs.begin(); itor < inPDVs.end(); itor++){ const std::string & theBlobString = itor->GetBlob(); theEntireBuffer.insert(theEntireBuffer.end(), theBlobString.begin(), theBlobString.end()); } DataSet outDataSet; std::stringstream ss; ss.str( theEntireBuffer ); #if 0 char fn[512]; static int i = 0; sprintf( fn, "/tmp/debugimp%d", i++ ); std::ofstream d( fn, std::ios::binary ); d.write( theEntireBuffer.c_str(), theEntireBuffer.size() ); d.close(); #endif outDataSet.Read( ss ); //outDataSet.Read( ss ); return outDataSet; } DataSet PresentationDataValue::ConcatenatePDVBlobsAsExplicit(const std::vector& inPDVs) { #if 0 std::stringstream ss; std::vector::const_iterator itor; for (itor = inPDVs.begin(); itor < inPDVs.end(); itor++) { const std::string & theBlobString = itor->GetBlob(); ss.write( &theBlobString[0], theBlobString.size() ); } #else std::string theEntireBuffer;//could do it as streams. but apparently, std isn't letting me std::vector::const_iterator itor; for (itor = inPDVs.begin(); itor < inPDVs.end(); itor++){ const std::string & theBlobString = itor->GetBlob(); theEntireBuffer.insert(theEntireBuffer.end(), theBlobString.begin(), theBlobString.end()); } std::stringstream ss; ss.str( theEntireBuffer ); #endif #if 0 char fn[512]; static int i = 0; sprintf( fn, "/tmp/debugex%d", i++ ); std::ofstream d( fn, std::ios::binary ); d.write( theEntireBuffer.c_str(), theEntireBuffer.size() ); d.close(); #endif DataSet outDataSet; //outDataSet.Read( ss ); VL length = (uint32_t)theEntireBuffer.size(); //gdcm::Trace::DebugOn(); outDataSet.ReadWithLength( ss, length ); return outDataSet; } void PresentationDataValue::Print(std::ostream &os) const { os << "ItemLength: " << ItemLength << std::endl; os << "PresentationContextID: " << (int)PresentationContextID << std::endl; os << "MessageHeader: " << (int)MessageHeader << std::endl; std::vector thePDVs; thePDVs.push_back(*this); DataSet ds = ConcatenatePDVBlobs(thePDVs); Printer thePrinter; thePrinter.PrintDataSet(ds, os); } void PresentationDataValue::SetCommand(bool inCommand) { const uint8_t flipped = ~1; if (inCommand) { MessageHeader |= 1; } else { MessageHeader &= flipped; } } void PresentationDataValue::SetLastFragment(bool inLast) { const uint8_t flipped = ~2; if (inLast) { MessageHeader |= 2; } else { MessageHeader &= flipped;//set the second field to zero } } bool PresentationDataValue::GetIsCommand() const { return (MessageHeader & 1) == 1; } bool PresentationDataValue::GetIsLastFragment() const { return (MessageHeader & 2) == 2; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmPresentationDataValue.h000066400000000000000000000053151412732066400260640ustar00rootroot00000000000000/*========================================================================= 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 GDCMPRESENTATIONDATAVALUE_H #define GDCMPRESENTATIONDATAVALUE_H #include "gdcmTypes.h" #include namespace gdcm { class DataSet; namespace network { /** * \brief PresentationDataValue * \details Table 9-23 * PRESENTATION-DATA-VALUE ITEM FIELDS */ class GDCM_EXPORT PresentationDataValue { public: PresentationDataValue(); std::istream &Read(std::istream &is); std::istream &ReadInto(std::istream &is, std::ostream &os); const std::ostream &Write(std::ostream &os) const; /// \internal Compute Size size_t Size() const; /// Set DataSet. Write DataSet in implicit. /// \warning size of dataset should be below maxpdusize void SetDataSet(const DataSet & ds); void SetBlob(const std::string & partialblob); const std::string &GetBlob() const; uint8_t GetPresentationContextID() const { return PresentationContextID; } void SetPresentationContextID(uint8_t id) { assert( id ); PresentationContextID = id; } uint8_t GetMessageHeader() const { assert( MessageHeader <= 0x3 ); return MessageHeader; } // E.2 MESSAGE CONTROL HEADER ENCODING // Only the first two bits are considered void SetMessageHeader(uint8_t messageheader) { MessageHeader = messageheader; assert( MessageHeader <= 0x3 ); } //flip the least significant bit of the message header to 1 //if this is a command, else set it to 0. void SetCommand(bool inCommand); void SetLastFragment(bool inLast);//set to true if this is the last PDV of a set bool GetIsCommand() const; bool GetIsLastFragment() const; void Print(std::ostream &os) const; //NOTE that the PDVs have to be given in the order in which they were received! //also note that a dataset may be across multiple PDVs /// \warning DataSet will be read as Implicit Little Endian TS static DataSet ConcatenatePDVBlobs(const std::vector& inPDVs); static DataSet ConcatenatePDVBlobsAsExplicit(const std::vector& inPDVs); private: uint32_t ItemLength; uint8_t PresentationContextID; uint8_t MessageHeader; std::string Blob; }; } // end namespace network } // end namespace gdcm #endif //GDCMPRESENTATIONDATAVALUE_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmQueryBase.cxx000066400000000000000000000025071412732066400240750ustar00rootroot00000000000000/*========================================================================= 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 "gdcmQueryBase.h" #include "gdcmBaseRootQuery.h" namespace gdcm { std::vector QueryBase::GetAllTags(const ERootType& inRootType) const { std::vector theReturn = GetRequiredTags(inRootType); std::vector theNext = GetUniqueTags(inRootType); theReturn.insert(theReturn.end(), theNext.begin(), theNext.end()); theNext = GetOptionalTags(inRootType); theReturn.insert(theReturn.end(), theNext.begin(), theNext.end()); return theReturn; } std::vector QueryBase::GetAllRequiredTags(const ERootType& inRootType) const { std::vector theReturn = GetRequiredTags(inRootType); std::vector theNext = GetUniqueTags(inRootType); theReturn.insert(theReturn.end(), theNext.begin(), theNext.end()); return theReturn; } } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmQueryBase.h000066400000000000000000000067351412732066400235310ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMQUERYBASE_H #define GDCMQUERYBASE_H #include "gdcmTag.h" #include "gdcmDataElement.h" #include namespace gdcm { enum ERootType { ePatientRootType, eStudyRootType }; /** * \brief QueryBase * \details contains: the base class for constructing a query dataset for a C-FIND and a * C-MOVE * * There are four levels of C-FIND and C-MOVE query: * \li Patient * \li Study * \li Series * \li Image * * Each one has its own required and optional tags. This class provides an * interface for getting those tags. This is an interface class. * * See 3.4 C 6.1 and 3.4 C 6.2 for the patient and study root query types. * These sections define the tags allowed by a particular query. The caller * must pass in which root type they want, patient or study. A third root type, * Modality Worklist Query, isn't yet supported. * * This class (or rather it's derived classes) will be held in the RootQuery * types. These query types actually make the dataset, and will use this * dataset to list the required, unique, and optional tags for each type of * query. This design is somewhat overly complicated, but is kept so that if we * ever wanted to try to guess the query type from the given tags, we could do * so. */ class GDCM_EXPORT QueryBase { public: virtual ~QueryBase() = default; virtual std::vector GetRequiredTags(const ERootType& inRootType) const = 0; virtual std::vector GetUniqueTags(const ERootType& inRootType) const = 0; virtual std::vector GetOptionalTags(const ERootType& inRootType) const = 0; // C.4.1.2.1 Baseline Behavior of SCU // All C-FIND SCUs shall be capable of generating query requests which // meet the requirements of the Hierarchical Search. // The Identifier contained in a C-FIND request shall contain a single // value in the Unique Key Attribute for each level above the // Query/Retrieve level. No Required or Optional Keys shall be // specified which are associated with levels above the Query/Retrieve // level. /// Return all Unique Key for a particular Query Root type (from the same level and above). virtual std::vector GetHierachicalSearchTags(const ERootType& inRootType) const = 0; /// In order to validate a query dataset, just check for the presence /// of a tag, not it's requirement level in the spec std::vector GetAllTags(const ERootType& inRootType) const; /// In order to validate a query dataset we need to check that there /// exists at least one required (or unique) key std::vector GetAllRequiredTags(const ERootType& inRootType) const; virtual const char * GetName() const = 0; virtual DataElement GetQueryLevel() const = 0; }; } #endif //GDCMQUERYBASE_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmQueryFactory.cxx000066400000000000000000000206421412732066400246320ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmQueryFactory.h" #include "gdcmFindPatientRootQuery.h" #include "gdcmMovePatientRootQuery.h" #include "gdcmFindStudyRootQuery.h" #include "gdcmMoveStudyRootQuery.h" #include "gdcmWLMFindQuery.h" #include "gdcmModalityPerformedProcedureStepCreateQuery.h" #include "gdcmModalityPerformedProcedureStepSetQuery.h" #include namespace gdcm { BaseQuery* QueryFactory::ProduceQuery( const std::string & sopInstanceUID, ENQueryType inQueryType ) { BaseQuery* theReturn = nullptr; switch (inQueryType) { case eCreateMMPS : theReturn = new ModalityPerformedProcedureStepCreateQuery( sopInstanceUID ); break; case eSetMMPS : theReturn = new ModalityPerformedProcedureStepSetQuery( sopInstanceUID ); break; } return theReturn; } BaseRootQuery* QueryFactory::ProduceQuery(ERootType inRootType, EQueryType inQueryType, EQueryLevel inQueryLevel) { BaseRootQuery* theReturn = nullptr; switch (inQueryType) { case eFind: switch (inRootType) { case ePatientRootType: theReturn = new FindPatientRootQuery(); break; case eStudyRootType: if (inQueryLevel != ePatient) theReturn = new FindStudyRootQuery(); break; } break; case eMove: switch (inRootType) { case ePatientRootType: theReturn = new MovePatientRootQuery(); break; case eStudyRootType: if (inQueryLevel != ePatient) theReturn = new MoveStudyRootQuery(); break; } break; case eWLMFind: theReturn = new WLMFindQuery(); break; } if( theReturn ) theReturn->InitializeDataSet(inQueryLevel); return theReturn; } /* LATIN1 ISO 8859-1 LATIN2 ISO 8859-2 LATIN3 ISO 8859-3 LATIN4 ISO 8859-4 ISO_8859_5 ISO 8859-5 Latin/Cyrillic ISO_8859_6 ISO 8859-6 Latin/Arabic ISO_8859_7 ISO 8859-7 Latin/Greek ISO_8859_8 ISO 8859-8 Latin/Hebrew LATIN5 ISO 8859-9 LATIN6 ISO 8859-10 LATIN7 ISO 8859-13 LATIN8 ISO 8859-14 LATIN9 ISO 8859-15 LATIN10 ISO 8859-16 */ ECharSet QueryFactory::GetCharacterFromCurrentLocale() { const char *charset = System::GetLocaleCharset(); if( charset ) { // UTF-8 (this is the default for UNIX): if( strcmp( charset, "UTF-8" ) == 0 ) return eUTF8; // US-ASCII, simply return latin1 else if( strcmp( charset, "US-ASCII" ) == 0 ) return eLatin1; else if( strcmp( charset, "ANSI_X3.4-1968" ) == 0 ) return eLatin1; // Latin-1 else if( strcmp( charset, "ISO-8859-1" ) == 0 ) return eLatin1; else if( strcmp( charset, "ISO-8859-2" ) == 0 ) return eLatin2; else if( strcmp( charset, "ISO-8859-3" ) == 0 ) return eLatin3; else if( strcmp( charset, "ISO-8859-4" ) == 0 ) return eLatin4; else if( strcmp( charset, "ISO-8859-5" ) == 0 ) return eCyrillic; else if( strcmp( charset, "ISO-8859-6" ) == 0 ) return eArabic; else if( strcmp( charset, "ISO-8859-7" ) == 0 ) return eGreek; else if( strcmp( charset, "ISO-8859-8" ) == 0 ) return eHebrew; else if( strcmp( charset, "ISO-8859-9" ) == 0 ) return eLatin5; // else if( strcmp( charset, "EUC-JP" ) == 0 ) return eJapanese; else if( strcmp( charset, "TIS-620" ) == 0 ) return eThai; else if( strcmp( charset, "EUC-JP" ) == 0 ) return eJapaneseKanjiMultibyte; else if( strcmp( charset, "EUC-JP" ) == 0 ) return eJapaneseSupplementaryKanjiMultibyte; else if( strcmp( charset, "EUC-KR" ) == 0 ) return eKoreanHangulHanjaMultibyte; //else if( strcmp( charset, "UTF-8" ) == 0 ) return eUTF8; else if( strcmp( charset, "GB18030" ) == 0 ) return eGB18030; gdcmWarningMacro( "Problem mapping Locale Charset: " << charset ); } gdcmWarningMacro( "Default to Latin-1" ); return eLatin1; } ///This function will produce the appropriate dataelement given a list of charsets. ///The first charset will be used directly, while the second and subsequent ///will be prepended with "ISO2022 ". Redundant character sets are not permitted, ///so if they are encountered, they will just be skipped. ///if UTF8 or GB18030 is used, no subsequent character sets will be used DataElement QueryFactory::ProduceCharacterSetDataElement(const std::vector& inCharSetType) { DataElement theReturn; //use the 'visited' array to make sure that if a redundant character set is entered, //it's skipped rather than produce a malformed tag. bool visited[eGB18030+1]; memset(visited, 0, (eGB18030+1)*sizeof(bool)); if (inCharSetType.empty()) return theReturn; std::vector::const_iterator itor; std::string theOutputString; for (itor = inCharSetType.begin(); itor < inCharSetType.end(); itor++) { if (itor > inCharSetType.begin()) { theOutputString += "ISO 2022 "; } else { theOutputString += "ISO_IR "; } if (visited[*itor]) continue; switch (*itor) { default: case eLatin1: theOutputString += "100"; break; case eLatin2: theOutputString += "101"; break; case eLatin3: theOutputString += "109"; break; case eLatin4: theOutputString += "110"; break; case eCyrillic: theOutputString += "144"; break; case eArabic: theOutputString += "127"; break; case eGreek: theOutputString += "126"; break; case eHebrew: theOutputString += "138"; break; case eLatin5: theOutputString += "148"; break; case eJapanese: theOutputString += "13"; break; case eThai: theOutputString += "166"; break; case eJapaneseKanjiMultibyte: theOutputString += "87"; break; case eJapaneseSupplementaryKanjiMultibyte: theOutputString += "159"; break; case eKoreanHangulHanjaMultibyte: theOutputString += "149"; break; //for the next two, they are only valid if they are //the only ones that appear case eUTF8: theOutputString = "ISO_IR 192"; itor = inCharSetType.end() - 1; //stop the loop break; case eGB18030: theOutputString = "GB13080"; itor = inCharSetType.end() - 1; //stop the loop break; } if (itor < (inCharSetType.end()-1)) { theOutputString += "\\"; // the following code will not work for UTF-8 and eGB18030 assert( itor < inCharSetType.end() ); visited[*itor] = true; } } if( theOutputString.size() % 2 ) theOutputString.push_back( ' ' ); // no \0 ! theReturn.SetByteValue(theOutputString.c_str(), (uint32_t)theOutputString.length()); theReturn.SetTag(Tag(0x0008, 0x0005)); return theReturn; } void QueryFactory::ListCharSets(std::ostream& os) { os << "The following character sets are supported by GDCM Network Queries." << std::endl; os << "The number in the parenthesis is the index to select." << std::endl; os << "Note that multiple selections are possible." << std::endl; os << "Latin1 (0): This is the default if nothing is specified." <& inCharSetType); /// This function will return the corresponding ECharSet associated with the /// current locale of the running system (based on the value of locale() ). static ECharSet GetCharacterFromCurrentLocale(); /// List all possible CharSet static void ListCharSets(std::ostream& os); }; } // end namespace gdcm #endif // GDCMQUERYFACTORY_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmQueryImage.cxx000066400000000000000000000056411412732066400242470ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /* contains: class to construct an image-based query for c-find and c-move note that at the series and image levels, there is no distinction between the root query types. */ #include "gdcmQueryImage.h" #include "gdcmQueryPatient.h" #include "gdcmQueryStudy.h" #include "gdcmQuerySeries.h" #include "gdcmAttribute.h" namespace gdcm { std::vector QueryImage::GetRequiredTags(const ERootType& ) const { std::vector theReturn;//see 3.4 C.6.1.1.5 theReturn.emplace_back(0x0020, 0x0013); return theReturn; } std::vector QueryImage::GetUniqueTags(const ERootType& ) const { std::vector theReturn;//see 3.4 C.6.1.1.5 theReturn.emplace_back(0x0008, 0x0018); return theReturn; } std::vector QueryImage::GetOptionalTags(const ERootType& ) const { std::vector theReturn;//see 3.4 C.6.1.1.5 theReturn.emplace_back(0x0008, 0x0016);//SOP class UID //theReturn.push_back(Tag(0x0008, 0x3001));//alternate representation theReturn.emplace_back(0x0008, 0x001A);//related General SOP Class UID //sequence tags, not including for now //theReturn.push_back(Tag(0x0040, 0xA504)); //theReturn.push_back(Tag(0x0040, 0x0512)); //theReturn.push_back(Tag(0x0040, 0x0560)); return theReturn; } std::vector QueryImage::GetHierachicalSearchTags(const ERootType& inRootType) const { std::vector tags; if( inRootType == ePatientRootType ) { QueryPatient qp; tags = qp.GetUniqueTags(inRootType); } // add study level QueryStudy qst; std::vector qsttags = qst.GetUniqueTags(inRootType); tags.insert(tags.end(), qsttags.begin(), qsttags.end()); // add series level QuerySeries qse; std::vector qsetags = qse.GetUniqueTags(inRootType); tags.insert(tags.end(), qsetags.begin(), qsetags.end()); // add image level std::vector utags = GetUniqueTags(inRootType); tags.insert(tags.end(), utags.begin(), utags.end()); return tags; } DataElement QueryImage::GetQueryLevel() const { const Attribute<0x0008, 0x0052> level = { "IMAGE " }; return level.GetAsDataElement(); } static const char QueryImageString[] = "Composite Object Instance (Image)"; const char *QueryImage::GetName() const { return QueryImageString; } } GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmQueryImage.h000066400000000000000000000027611412732066400236740ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMQUERYIMAGE_H #define GDCMQUERYIMAGE_H #include "gdcmQueryBase.h" #include "gdcmDataSet.h" namespace gdcm { /** * \brief QueryImage * \details contains: class to construct an image-based query for C-FIND and C-MOVE */ class GDCM_EXPORT QueryImage : public QueryBase { public: std::vector GetRequiredTags(const ERootType& inRootType) const override; std::vector GetUniqueTags(const ERootType& inRootType) const override; std::vector GetOptionalTags(const ERootType& inRootType) const override; std::vector GetHierachicalSearchTags(const ERootType& inRootType) const override; const char * GetName() const override; DataElement GetQueryLevel() const override; }; } // end namespace gdcm #endif // GDCMQUERYIMAGE_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmQueryPatient.cxx000066400000000000000000000060061412732066400246250ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ //note that at the series and image levels, there is no distinction between //the root query types. #include "gdcmQueryPatient.h" #include "gdcmAttribute.h" namespace gdcm { std::vector QueryPatient::GetRequiredTags(const ERootType& inRootType) const { std::vector theReturn;//see 3.4 C.6.1.1.2 switch (inRootType) { case ePatientRootType: default: theReturn.emplace_back(0x0010, 0x0010); break; case eStudyRootType: //do nothing break; } return theReturn; } std::vector QueryPatient::GetUniqueTags(const ERootType& inRootType) const { std::vector theReturn;//see 3.4 C.6.1.1.2 switch (inRootType) { case ePatientRootType: default: theReturn.emplace_back(0x0010, 0x0020); break; case eStudyRootType: //do nothing break; } return theReturn; } std::vector QueryPatient::GetHierachicalSearchTags(const ERootType& inRootType) const { assert( inRootType == ePatientRootType ); std::vector tags; // Patient is always toplevel ! // just return Required and Unique std::vector utags = GetUniqueTags(inRootType); tags.insert(tags.end(), utags.begin(), utags.end()); return tags; } std::vector QueryPatient::GetOptionalTags(const ERootType& inRootType) const { std::vector theReturn;//see 3.4 C.6.1.1.2 switch (inRootType){ case ePatientRootType: default: theReturn.emplace_back(0x0010, 0x0021); theReturn.emplace_back(0x0008, 0x1120); theReturn.emplace_back(0x0010, 0x0030); theReturn.emplace_back(0x0010, 0x0032); theReturn.emplace_back(0x0010, 0x0040); theReturn.emplace_back(0x0010, 0x1000); theReturn.emplace_back(0x0010, 0x1001); theReturn.emplace_back(0x0010, 0x2160); theReturn.emplace_back(0x0010, 0x4000); theReturn.emplace_back(0x0020, 0x1200); theReturn.emplace_back(0x0020, 0x1202); theReturn.emplace_back(0x0020, 0x1204); break; case eStudyRootType: //do nothing break; } return theReturn; } DataElement QueryPatient::GetQueryLevel() const { const Attribute<0x0008, 0x0052> level = { "PATIENT " }; return level.GetAsDataElement(); } static const char QueryPatientString[] = "Patient"; const char * QueryPatient::GetName() const { return QueryPatientString; } } GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmQueryPatient.h000066400000000000000000000027411412732066400242540ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMQUERYPATIENT_H #define GDCMQUERYPATIENT_H #include "gdcmQueryBase.h" namespace gdcm { /** * \brief QueryPatient * \details contains: class to construct a patient-based query for c-find and c-move */ class GDCM_EXPORT QueryPatient : public QueryBase { public: std::vector GetRequiredTags(const ERootType& inRootType) const override; std::vector GetUniqueTags(const ERootType& inRootType) const override; std::vector GetOptionalTags(const ERootType& inRootType) const override; std::vector GetHierachicalSearchTags(const ERootType& inRootType) const override; const char * GetName() const override; DataElement GetQueryLevel() const override; }; } // end namespace gdcm #endif //GDCMQUERYPATIENT_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmQuerySeries.cxx000066400000000000000000000045351412732066400244600ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ //note that at the series and image levels, there is no distinction between //the root query types. #include "gdcmQuerySeries.h" #include "gdcmQueryPatient.h" #include "gdcmQueryStudy.h" #include "gdcmAttribute.h" namespace gdcm { std::vector QuerySeries::GetRequiredTags(const ERootType& ) const { std::vector theReturn;//see 3.4 C.6.1.1.4 theReturn.emplace_back(0x0008, 0x0060); theReturn.emplace_back(0x0020, 0x0011); return theReturn; } std::vector QuerySeries::GetUniqueTags(const ERootType& ) const { std::vector theReturn;//see 3.4 C.6.1.1.4 theReturn.emplace_back(0x0020, 0x000E); return theReturn; } std::vector QuerySeries::GetOptionalTags(const ERootType& ) const { std::vector theReturn;//see 3.4 C.6.1.1.4 theReturn.emplace_back(0x0020, 0x1209); return theReturn; } std::vector QuerySeries::GetHierachicalSearchTags(const ERootType& inRootType) const { std::vector tags; if( inRootType == ePatientRootType ) { QueryPatient qp; tags = qp.GetUniqueTags(inRootType); } // add study level QueryStudy qs; std::vector qstags = qs.GetUniqueTags(inRootType); tags.insert(tags.end(), qstags.begin(), qstags.end()); // add series level std::vector utags = GetUniqueTags(inRootType); tags.insert(tags.end(), utags.begin(), utags.end()); return tags; } DataElement QuerySeries::GetQueryLevel() const { const Attribute<0x0008, 0x0052> level = { "SERIES" }; return level.GetAsDataElement(); } static const char QuerySeriesString[] = "Series"; const char * QuerySeries::GetName() const { return QuerySeriesString; } } GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmQuerySeries.h000066400000000000000000000027331412732066400241030ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMQUERYSERIES_H #define GDCMQUERYSERIES_H #include "gdcmQueryBase.h" namespace gdcm { /** * \brief QuerySeries * \details contains: class to construct a series-based query for c-find and c-move */ class GDCM_EXPORT QuerySeries : public QueryBase { public: std::vector GetRequiredTags(const ERootType& inRootType) const override; std::vector GetUniqueTags(const ERootType& inRootType) const override; std::vector GetOptionalTags(const ERootType& inRootType) const override; std::vector GetHierachicalSearchTags(const ERootType& inRootType) const override; const char * GetName() const override; DataElement GetQueryLevel() const override; }; } // end namespace gdcm #endif //GDCMQUERYSERIES_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmQueryStudy.cxx000066400000000000000000000112141412732066400243260ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ //note that at the series and image levels, there is no distinction between //the root query types. #include "gdcmQueryStudy.h" #include "gdcmQueryPatient.h" #include "gdcmAttribute.h" namespace gdcm { std::vector QueryStudy::GetRequiredTags(const ERootType& inRootType) const { std::vector theReturn;//see 3.4 C.6.1.1.3 switch (inRootType){ case ePatientRootType: default: theReturn.emplace_back(0x0008, 0x0020); theReturn.emplace_back(0x0008, 0x0030); theReturn.emplace_back(0x0008, 0x0050); theReturn.emplace_back(0x0020, 0x0010); break; case eStudyRootType: theReturn.emplace_back(0x0008, 0x0020); theReturn.emplace_back(0x0008, 0x0030); theReturn.emplace_back(0x0008, 0x0050); theReturn.emplace_back(0x0010, 0x0010); theReturn.emplace_back(0x0010, 0x0020); theReturn.emplace_back(0x0020, 0x0010); break; } return theReturn; } std::vector QueryStudy::GetUniqueTags(const ERootType& ) const { std::vector theReturn;//see 3.4 C.6.2.1.2 theReturn.emplace_back(0x0020, 0x000d); return theReturn; } std::vector QueryStudy::GetOptionalTags(const ERootType& inRootType) const { std::vector theReturn;//see 3.4 C.6.1.1.3 switch (inRootType) { case ePatientRootType: default: theReturn.emplace_back(0x0008, 0x0061); theReturn.emplace_back(0x0008, 0x0062); theReturn.emplace_back(0x0008, 0x0090); theReturn.emplace_back(0x0008, 0x1030); theReturn.emplace_back(0x0008, 0x1032); theReturn.emplace_back(0x0008, 0x1060); theReturn.emplace_back(0x0008, 0x1080); theReturn.emplace_back(0x0008, 0x1110); theReturn.emplace_back(0x0010, 0x1010); theReturn.emplace_back(0x0010, 0x1020); theReturn.emplace_back(0x0010, 0x1030); theReturn.emplace_back(0x0010, 0x2180); theReturn.emplace_back(0x0010, 0x21B0); theReturn.emplace_back(0x0020, 0x1070); theReturn.emplace_back(0x0020, 0x1206); theReturn.emplace_back(0x0020, 0x1208); break; case eStudyRootType: theReturn.emplace_back(0x0008, 0x0061); theReturn.emplace_back(0x0008, 0x0062); theReturn.emplace_back(0x0008, 0x0090); theReturn.emplace_back(0x0008, 0x1030); theReturn.emplace_back(0x0008, 0x1032); theReturn.emplace_back(0x0008, 0x1060); theReturn.emplace_back(0x0008, 0x1080); theReturn.emplace_back(0x0008, 0x1110); theReturn.emplace_back(0x0008, 0x1120); theReturn.emplace_back(0x0010, 0x0021); theReturn.emplace_back(0x0010, 0x0030); theReturn.emplace_back(0x0010, 0x0032); theReturn.emplace_back(0x0010, 0x0040); theReturn.emplace_back(0x0010, 0x1000); theReturn.emplace_back(0x0010, 0x1001); theReturn.emplace_back(0x0010, 0x1010); theReturn.emplace_back(0x0010, 0x1020); theReturn.emplace_back(0x0010, 0x1030); theReturn.emplace_back(0x0010, 0x2160); theReturn.emplace_back(0x0010, 0x2180); theReturn.emplace_back(0x0010, 0x21B0); theReturn.emplace_back(0x0010, 0x4000); theReturn.emplace_back(0x0020, 0x1070); theReturn.emplace_back(0x0020, 0x1200); theReturn.emplace_back(0x0020, 0x1202); theReturn.emplace_back(0x0020, 0x1204); theReturn.emplace_back(0x0020, 0x1206); theReturn.emplace_back(0x0020, 0x1208); break; } return theReturn; } std::vector QueryStudy::GetHierachicalSearchTags(const ERootType& inRootType) const { std::vector tags; if( inRootType == ePatientRootType ) { QueryPatient qp; tags = qp.GetUniqueTags(inRootType); } // add study level std::vector utags = GetUniqueTags(inRootType); tags.insert(tags.end(), utags.begin(), utags.end()); return tags; } DataElement QueryStudy::GetQueryLevel() const { const Attribute<0x0008, 0x0052> level = { "STUDY " }; return level.GetAsDataElement(); } static const char QueryStudyString[] = "Study"; const char * QueryStudy::GetName() const { return QueryStudyString; } } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmQueryStudy.h000066400000000000000000000027261412732066400237630ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMQUERYSTUDY_H #define GDCMQUERYSTUDY_H #include "gdcmQueryBase.h" namespace gdcm { /** * \brief QueryStudy.h * \details contains: class to construct a study-based query for C-FIND and C-MOVE */ class GDCM_EXPORT QueryStudy : public QueryBase { public: std::vector GetRequiredTags(const ERootType& inRootType) const override; std::vector GetUniqueTags(const ERootType& inRootType) const override; std::vector GetOptionalTags(const ERootType& inRootType) const override; std::vector GetHierachicalSearchTags(const ERootType& inRootType) const override; const char *GetName() const override; DataElement GetQueryLevel() const override; }; } // end namespace gdcm #endif //GDCMQUERYSTUDY_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmRoleSelectionSub.cxx000066400000000000000000000104051412732066400254120ustar00rootroot00000000000000/*========================================================================= 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 "gdcmRoleSelectionSub.h" #include "gdcmFileMetaInformation.h" #include "gdcmSwapper.h" namespace gdcm { namespace network { const uint8_t RoleSelectionSub::ItemType = 0x54; const uint8_t RoleSelectionSub::Reserved2 = 0x00; RoleSelectionSub::RoleSelectionSub() { ItemLength = 0; UIDLength = 0; SCURole = 0; SCPRole = 0; ItemLength = (uint16_t)(Size() - 4); assert( (size_t)ItemLength + 4 == Size() ); } std::istream &RoleSelectionSub::Read(std::istream &is) { //uint8_t itemtype = 0x0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint16_t itemlength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; uint16_t uidlength; is.read( (char*)&uidlength, sizeof(UIDLength) ); SwapperDoOp::SwapArray(&uidlength,1); UIDLength = uidlength; char name[256]; assert( uidlength < 256 ); is.read( name, uidlength ); Name = std::string(name,uidlength); uint8_t scurole; is.read( (char*)&scurole, sizeof(SCURole) ); SCURole = scurole; uint8_t scprole; is.read( (char*)&scprole, sizeof(SCPRole) ); SCPRole = scprole; assert( (size_t)ItemLength + 4 == Size() ); return is; } const std::ostream &RoleSelectionSub::Write(std::ostream &os) const { assert( (size_t)ItemLength + 4 == Size() ); os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); //os.write( (const char*)&ItemLength, sizeof(ItemLength) ); uint16_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); assert( ItemLength > UIDLength ); uint16_t uidlength = UIDLength; SwapperDoOp::SwapArray(&uidlength,1); os.write( (const char*)&uidlength, sizeof(UIDLength) ); assert( (size_t)UIDLength == Name.size() ); os.write( Name.c_str(), Name.size() ); uint8_t scurole = SCURole; assert( scurole == 0 || scurole == 1 ); os.write( (const char*)&scurole, sizeof(SCURole) ); uint8_t scprole = SCPRole; assert( scprole == 0 || scprole == 1 ); os.write( (const char*)&scprole, sizeof(SCPRole) ); return os; } size_t RoleSelectionSub::Size() const { size_t ret = 0; ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); ret += sizeof(UIDLength); assert( Name.size() == UIDLength ); ret += UIDLength; ret += sizeof(SCURole); ret += sizeof(SCPRole); return ret; } /* SCU-role This byte field shall contain the SCU-role as defined for the Association-requester in Section D.3.3.4. It shall be encoded as an unsigned binary and shall use one of the following values: 0 - non support of the SCU role 1 - support of the SCU role SCP-role This byte field shall contain the SCP-role as defined for the Association-requester in Section D.3.3.4. It shall be encoded as an unsigned binary and shall use one of the following values: 0 - non support of the SCP role 1 - support of the SCP role. */ void RoleSelectionSub::SetTuple(const char *uid, uint8_t scurole, uint8_t scprole) { if( uid ) { Name = uid; UIDLength = (uint16_t)strlen( uid ); assert( (size_t)UIDLength == Name.size() ); SCURole = scurole % 2; SCPRole = scprole % 2; ItemLength = (uint16_t)(Size() - 4); } // post condition assert( (size_t)ItemLength + 4 == Size() ); } void RoleSelectionSub::Print(std::ostream &os) const { os << "SOP-class-uid" << Name << std::endl; os << "SCURole: " << (int)SCURole << std::endl; os << "SCPRole: " << (int)SCPRole << std::endl; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmRoleSelectionSub.h000066400000000000000000000025601412732066400250420ustar00rootroot00000000000000/*========================================================================= 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 GDCMROLESELECTIONSUB_H #define GDCMROLESELECTIONSUB_H #include "gdcmTypes.h" namespace gdcm { namespace network { /** * \brief RoleSelectionSub * \details PS 3.7 * Table D.3-9 * SCP/SCU ROLE SELECTION SUB-ITEM FIELDS (A-ASSOCIATE-RQ) */ class RoleSelectionSub { public: RoleSelectionSub(); std::istream &Read(std::istream &is); const std::ostream &Write(std::ostream &os) const; size_t Size() const; void Print(std::ostream &os) const; void SetTuple(const char *uid, uint8_t scurole, uint8_t scprole); private: static const uint8_t ItemType; static const uint8_t Reserved2; uint16_t ItemLength; uint16_t UIDLength; std::string /*SOP-class-uid*/ Name; // UID uint8_t SCURole; uint8_t SCPRole; }; } // end namespace network } // end namespace gdcm #endif // GDCMROLESELECTIONSUB_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmSOPClassExtendedNegociationSub.cxx000066400000000000000000000070011412732066400301310ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSOPClassExtendedNegociationSub.h" #include "gdcmFileMetaInformation.h" #include "gdcmSwapper.h" namespace gdcm { namespace network { const uint8_t SOPClassExtendedNegociationSub::ItemType = 0x56; const uint8_t SOPClassExtendedNegociationSub::Reserved2 = 0x00; SOPClassExtendedNegociationSub::SOPClassExtendedNegociationSub() { ItemLength = 0; UIDLength = 0; ItemLength = (uint16_t)(Size() - 4); assert( (size_t)ItemLength + 4 == Size() ); } std::istream &SOPClassExtendedNegociationSub::Read(std::istream &is) { //uint8_t itemtype = 0x0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint16_t itemlength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; uint16_t uidlength; is.read( (char*)&uidlength, sizeof(UIDLength) ); SwapperDoOp::SwapArray(&uidlength,1); UIDLength = uidlength; char name[256]; assert( uidlength < 256 ); is.read( name, uidlength ); Name = std::string(name,uidlength); assert( uidlength < ItemLength ); uint16_t bloblength = (uint16_t)(ItemLength - 2 - uidlength); assert( bloblength == 6 ); (void)bloblength; SCAI.Read( is ); return is; } const std::ostream &SOPClassExtendedNegociationSub::Write(std::ostream &os) const { os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); //os.write( (const char*)&ItemLength, sizeof(ItemLength) ); uint16_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); uint16_t uidlength = UIDLength; SwapperDoOp::SwapArray(&uidlength,1); os.write( (const char*)&uidlength, sizeof(UIDLength) ); os.write( Name.c_str(), Name.size() ); SCAI.Write( os ); return os; } size_t SOPClassExtendedNegociationSub::Size() const { size_t ret = 0; ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); ret += sizeof(UIDLength); ret += UIDLength; ret += SCAI.Size(); return ret; } void SOPClassExtendedNegociationSub::Print(std::ostream &os) const { os << "SOP-class-uid: " << Name << std::endl; // UID os << "Service-class-application-information:"; SCAI.Print( os ); #if 0 const char *beg = Blob.c_str(); const char *end = beg + Blob.size(); for( const char *p = beg; p != end; ++p ) { if ( p != beg ) os << " "; os << "0x" << (int)*p; } os << "]" << std::endl; #endif } void SOPClassExtendedNegociationSub::SetTuple(const char *uid, uint8_t levelofsupport, uint8_t levelofdigitalsig, uint8_t elementcoercion) { if( uid ) { Name = uid; UIDLength = (uint16_t)strlen( uid ); SCAI.SetTuple( levelofsupport, levelofdigitalsig, elementcoercion); ItemLength = (uint16_t)(Size() - 4); } // post condition assert( (size_t)ItemLength + 4 == Size() ); } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmSOPClassExtendedNegociationSub.h000066400000000000000000000031021412732066400275540ustar00rootroot00000000000000/*========================================================================= 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 GDCMSOPCLASSEXTENDEDNEGOCIATIONSUB_H #define GDCMSOPCLASSEXTENDEDNEGOCIATIONSUB_H #include "gdcmServiceClassApplicationInformation.h" namespace gdcm { namespace network { /** * \brief SOPClassExtendedNegociationSub * \details PS 3.7 * Table D.3-11 * SOP CLASS EXTENDED NEGOTIATION SUB-ITEM FIELDS * (A-ASSOCIATE-RQ and A-ASSOCIATE-AC) */ class SOPClassExtendedNegociationSub { public: SOPClassExtendedNegociationSub(); std::istream &Read(std::istream &is); const std::ostream &Write(std::ostream &os) const; size_t Size() const; void Print(std::ostream &os) const; void SetTuple(const char *uid, uint8_t levelofsupport = 3, uint8_t levelofdigitalsig = 0, uint8_t elementcoercion = 2); private: static const uint8_t ItemType; static const uint8_t Reserved2; uint16_t ItemLength; uint16_t UIDLength; std::string /*SOP-class-uid*/ Name; // UID ServiceClassApplicationInformation SCAI; }; } // end namespace network } // end namespace gdcm #endif // GDCMSOPCLASSEXTENDEDNEGOCIATIONSUB_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmServiceClassApplicationInformation.cxx000066400000000000000000000103711412732066400311530ustar00rootroot00000000000000/*========================================================================= 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 "gdcmServiceClassApplicationInformation.h" namespace gdcm { namespace network { ServiceClassApplicationInformation::ServiceClassApplicationInformation() { InternalArray[0] = 3; // Level of Support InternalArray[1] = 0; // Reserved InternalArray[2] = 0; // Level of Digital Signature support InternalArray[3] = 0; // Reserved InternalArray[4] = 2; // Element coercion InternalArray[5] = 0; // Reserved } std::istream &ServiceClassApplicationInformation::Read(std::istream &is) { is.read( (char*)InternalArray, sizeof(InternalArray) ); return is; } const std::ostream &ServiceClassApplicationInformation::Write(std::ostream &os) const { assert( InternalArray[0] < 4 ); assert( InternalArray[1] == 0 ); assert( InternalArray[2] < 4 ); assert( InternalArray[3] == 0 ); assert( InternalArray[4] < 3 ); assert( InternalArray[5] == 0 ); os.write( (const char*)InternalArray, sizeof(InternalArray) ); return os; } size_t ServiceClassApplicationInformation::Size() const { assert( sizeof(InternalArray) == 6 ); return 6; } void ServiceClassApplicationInformation::Print(std::ostream &os) const { os << "ServiceClassApplicationInformation: " << std::endl; os << " Level of Support: " << (int)InternalArray[0] << std::endl; os << " Level of Digital Signature support: " << (int)InternalArray[2] << std::endl; os << " Element coercion: " << (int)InternalArray[4] << std::endl; } /* Level of support This byte field defines the supported storage level of the Association-acceptor. It shall be encoded as an unsigned binary integer and shall use one of the following values: 0 - level 0 SCP 1 - level 1 SCP 2 - level 2 SCP 3 - N/A - Association-acceptor is SCU only If extended negotiation is not supported, no assumptions shall be made by the Association- requester about the capabilities of the Association- acceptor based upon this extended negotiation. Level of Digital A Level 2 SCP may further define its behavior in this Signature support byte field. 0 – The signature level is unspecified, the AE is an SCU only, or the AE is not a level 2 SCP 1 – signature level 1 2 – signature level 2 3 – signature level 3 If extended negotiation is not supported, no assumptions shall be made by the Association- requester about the capabilities of the Association- acceptor based upon this extended negotiation. Element Coercion This byte field defines whether the Association-acceptor may coerce Data Elements. It shall be encoded as an unsigned binary integer and shall use one of the following values: 0 - does not coerce any Data Element 1 - may coerce Data Elements 2 - N/A - Association-acceptor is SCU only If extended negotiation is not supported, no assumptions shall be made by the Association- requester about the capabilities of the Association- acceptor based upon this extended negotiation. */ void ServiceClassApplicationInformation::SetTuple(uint8_t levelofsupport, uint8_t levelofdigitalsig, uint8_t elementcoercion) { if( levelofsupport < 4 ) InternalArray[0] = levelofsupport; if( levelofdigitalsig < 4 ) InternalArray[2] = levelofdigitalsig; if( elementcoercion < 3 ) InternalArray[4] = elementcoercion; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmServiceClassApplicationInformation.h000066400000000000000000000024421412732066400306000ustar00rootroot00000000000000/*========================================================================= 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 GDCMSERVICECLASSAPPLICATIONINFORMATION_H #define GDCMSERVICECLASSAPPLICATIONINFORMATION_H #include "gdcmTypes.h" namespace gdcm { namespace network { /** * \details PS 3.4 * Table B.3-1 * SERVICE-CLASS-APPLICATION-INFORMATION (A-ASSOCIATE-RQ) */ class ServiceClassApplicationInformation { public: ServiceClassApplicationInformation(); std::istream &Read(std::istream &is); const std::ostream &Write(std::ostream &os) const; size_t Size() const; void SetTuple(uint8_t levelofsupport, uint8_t levelofdigitalsig, uint8_t elementcoercion); void Print(std::ostream &os) const; private: uint8_t InternalArray[6]; }; } // end namespace network } // end namespace gdcm #endif //GDCMSERVICECLASSAPPLICATIONINFORMATION_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmServiceClassUser.cxx000066400000000000000000001235471412732066400254320ustar00rootroot00000000000000/*========================================================================= 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 "gdcmServiceClassUser.h" #include "gdcmULTransitionTable.h" #include "gdcmULConnection.h" #include "gdcmULConnectionInfo.h" #include "gdcmPresentationContextAC.h" #include "gdcmPresentationDataValue.h" #include "gdcmULConnectionCallback.h" #include "gdcmULBasicCallback.h" #include "gdcmPDUFactory.h" #include "gdcmAttribute.h" #include "gdcmULWritingCallback.h" #include "gdcmPrinter.h" // FIXME #include "gdcmReader.h" // FIXME namespace gdcm { static const char GDCM_AETITLE[] = "GDCMSCU"; using namespace network; class ServiceClassUserInternals { public: ULConnection* mConnection{nullptr}; ULConnection* mSecondaryConnection{nullptr}; ULTransitionTable mTransitions; std::string hostname; int port; int portscp; std::string aetitle; std::string calledaetitle; double timeout; ServiceClassUserInternals()= default; ~ServiceClassUserInternals(){ delete mConnection; delete mSecondaryConnection; } }; ServiceClassUser::ServiceClassUser() { Internals = new ServiceClassUserInternals; Internals->hostname = "localhost"; Internals->port = 104; Internals->portscp = 104; Internals->aetitle = GDCM_AETITLE; Internals->calledaetitle = "ANY-SCP"; Internals->timeout = 10; } ServiceClassUser::~ServiceClassUser() { delete Internals; } void ServiceClassUser::SetPresentationContexts(std::vector const & pcs) { if( Internals->mConnection ) { Internals->mConnection->SetPresentationContexts(pcs); } } bool ServiceClassUser::IsPresentationContextAccepted(const PresentationContext& pc) const { bool found = false; const std::vector &acceptedContexts = Internals->mConnection->GetAcceptedPresentationContexts(); std::vector::const_iterator itor; uint8_t contextID = pc.GetPresentationContextID(); for (itor = acceptedContexts.begin(); itor != acceptedContexts.end() && !found; itor++) { if (contextID == itor->GetPresentationContextID()) found = true; } return found; } bool ServiceClassUser::InitializeConnection() { UserInformation userInfo; ULConnectionInfo connectInfo; if (Internals->aetitle.size() > 16) { return false; } if (Internals->calledaetitle.size() > 16) { return false; } if (!Internals->port) { return false; } if (Internals->hostname.empty()) { return false; } if (!connectInfo.Initialize(userInfo, Internals->calledaetitle.c_str(), Internals->aetitle.c_str(), 0, Internals->port, Internals->hostname)) { return false; } ULConnection* mConnection = Internals->mConnection; if (mConnection) { delete mConnection; } Internals->mConnection = new ULConnection(connectInfo); Internals->mConnection->GetTimer().SetTimeout(Internals->timeout); return true; } bool ServiceClassUser::StartAssociation() { // need to make sure no cached PresContAC are around: Internals->mConnection->GetAcceptedPresentationContexts().clear(); if( Internals->mConnection->GetPresentationContexts().empty() ) { return false; } ULEvent theEvent(eAASSOCIATERequestLocalUser, nullptr); network::EStateID theState = RunEventLoop(theEvent, Internals->mConnection, nullptr, false); if(theState != eSta6TransferReady) { std::vector const & thePDUs = theEvent.GetPDUs(); for( std::vector::const_iterator itor = thePDUs.begin(); itor != thePDUs.end(); itor++) { assert(*itor); if (*itor == nullptr) continue; //can have a nulled pdu, apparently (*itor)->Print(Trace::GetErrorStream()); } } return theState == eSta6TransferReady; } bool ServiceClassUser::StopAssociation() { ULConnection* mConnection = Internals->mConnection; BasePDU* thePDU = PDUFactory::ConstructReleasePDU(); ULEvent theEvent(eARELEASERequest, thePDU); EStateID theState = RunEventLoop(theEvent, mConnection, nullptr, false); return theState == eSta1Idle; } void ServiceClassUser::SetTimeout(double t) { Internals->timeout = t; } double ServiceClassUser::GetTimeout() const { return Internals->timeout; } void ServiceClassUser::SetCalledAETitle(const char *aetitle) { if( aetitle ) Internals->calledaetitle = aetitle; } void ServiceClassUser::SetAETitle(const char *aetitle) { if( aetitle ) Internals->aetitle = aetitle; } const char *ServiceClassUser::GetCalledAETitle() const { return Internals->calledaetitle.c_str(); } const char *ServiceClassUser::GetAETitle() const { return Internals->aetitle.c_str(); } void ServiceClassUser::SetHostname( const char *hostname ) { if( hostname ) Internals->hostname = hostname; } void ServiceClassUser::SetPort( uint16_t port ) { Internals->port = port; } void ServiceClassUser::SetPortSCP( uint16_t portscp ) { Internals->portscp = portscp; } bool ServiceClassUser::SendEcho() { ULConnection* mConnection = Internals->mConnection; std::vector theDataPDU = PDUFactory::CreateCEchoPDU(*mConnection); ULEvent theEvent(ePDATArequest, theDataPDU); EStateID theState = RunEventLoop(theEvent, mConnection, nullptr, false); return theState == eSta6TransferReady; } bool ServiceClassUser::SendStore(const char *filename) { if( !filename ) return false; Reader reader; reader.SetFileName( filename ); bool b = reader.Read(); if( !b ) { gdcmDebugMacro( "Could not read: " << filename ); return false; } const File & file = reader.GetFile(); return SendStore( file ); } bool ServiceClassUser::SendStore(DataSet const &ds) { SmartPointer file = new File; file->SetDataSet( ds ); file->GetHeader().SetDataSetTransferSyntax( TransferSyntax::ImplicitVRLittleEndian ); file->GetHeader().FillFromDataSet( ds ); return SendStore(*file); } bool ServiceClassUser::SendStore(File const &file) { ULConnection* mConnection = Internals->mConnection; std::vector theDataPDU; try { theDataPDU = PDUFactory::CreateCStoreRQPDU(*mConnection, file); } catch ( std::exception &ex ) { (void)ex; //to avoid unreferenced variable warning on release gdcmErrorMacro( "Could not C-STORE: " << ex.what() ); return false; } network::ULBasicCallback theCallback; network::ULConnectionCallback* inCallback = &theCallback; ULEvent theEvent(ePDATArequest, theDataPDU); EStateID stateid = RunEventLoop(theEvent, mConnection, inCallback, false); assert( stateid == eSta6TransferReady ); (void)stateid; std::vector const &theDataSets = theCallback.GetResponses(); bool ret = true; assert( theDataSets.size() == 1 ); const DataSet &ds = theDataSets[0]; assert ( ds.FindDataElement(Tag(0x0, 0x0900)) ); DataElement const & de = ds.GetDataElement(Tag(0x0,0x0900)); Attribute<0x0,0x0900> at; at.SetFromDataElement( de ); // PS 3.4 - 2011 // Table W.4-1 C-STORE RESPONSE STATUS VALUES const uint16_t theVal = at.GetValue(); switch( theVal ) { case 0x0: gdcmDebugMacro( "C-Store of file was successful." ); break; case 0xA700: case 0xA900: case 0xC000: { // TODO: value from 0901 ? gdcmErrorMacro( "C-Store of file was a failure." ); Attribute<0x0,0x0902> errormsg; errormsg.SetFromDataSet( ds ); const char *themsg = errormsg.GetValue(); assert( themsg ); (void)themsg; gdcmErrorMacro( "Response Status: " << themsg ); ret = false; // at least one file was not sent correctly } break; default: gdcmErrorMacro( "Unhandle error code: " << theVal ); gdcmAssertAlwaysMacro( 0 ); } return ret; } bool ServiceClassUser::SendFind(const BaseRootQuery* query, std::vector &retDataSets) { ULConnection* mConnection = Internals->mConnection; network::ULBasicCallback theCallback; network::ULConnectionCallback* inCallback = &theCallback; std::vector theDataPDU = PDUFactory::CreateCFindPDU( *mConnection, query); ULEvent theEvent(ePDATArequest, theDataPDU); RunEventLoop(theEvent, mConnection, inCallback, false); std::vector const & theDataSets = theCallback.GetDataSets(); std::vector const & theResponses = theCallback.GetResponses(); bool ret = false; // by default an error assert( theResponses.size() >= 1 ); // take the last one: const DataSet &ds = theResponses[ theResponses.size() - 1 ]; // FIXME assert ( ds.FindDataElement(Tag(0x0, 0x0900)) ); Attribute<0x0,0x0900> at; at.SetFromDataSet( ds ); // Table CC.2.8-2 //C-FIND RESPONSE STATUS VALUES const uint16_t theVal = at.GetValue(); switch( theVal ) { case 0x0: // Matching is complete - No final Identifier is supplied. gdcmDebugMacro( "C-Find was successful." ); // Append the new DataSet to the ret one: retDataSets.insert( retDataSets.end(), theDataSets.begin(), theDataSets.end() ); ret = true; break; case 0xA900: // Identifier Does Not Match SOP Class { Attribute<0x0,0x0901> errormsg; if( ds.FindDataElement( errormsg.GetTag() ) ) { errormsg.SetFromDataSet( ds ); gdcm::Tag const & t = errormsg.GetValue(); gdcmErrorMacro( "Offending Element: " << t ); (void)t; } else { gdcmErrorMacro( "Offending Element ??" ); } } break; case 0xA700: // Refused: Out of Resources { Attribute<0x0,0x0902> errormsg; errormsg.SetFromDataSet( ds ); const char *themsg = errormsg.GetValue(); assert( themsg ); (void)themsg; gdcmErrorMacro( "Response Status: [" << themsg << "]" ); } break; case 0x0122: // SOP Class not Supported gdcmErrorMacro( "SOP Class not Supported" ); break; case 0xfe00: // Matching terminated due to Cancel request gdcmErrorMacro( "Matching terminated due to Cancel request" ); break; default: { if( theVal >= 0xC000 && theVal <= 0xCFFF ) // Unable to process { Attribute<0x0,0x0902> errormsg; errormsg.SetFromDataSet( ds ); const char *themsg = errormsg.GetValue(); assert( themsg ); (void)themsg; gdcmErrorMacro( "Response Status: " << themsg ); } } } return ret; } bool ServiceClassUser::SendMove(const BaseRootQuery* query, const char *outputdir) { UserInformation userInfo2; ULConnectionInfo connectInfo2; if (!connectInfo2.Initialize(userInfo2, Internals->aetitle.c_str(), Internals->calledaetitle.c_str(), 0, Internals->portscp, Internals->hostname)) { return false; } // let's start the secondary connection ULConnection* mSecondaryConnection = Internals->mSecondaryConnection; if (mSecondaryConnection) { delete mSecondaryConnection; } Internals->mSecondaryConnection = new ULConnection(connectInfo2); Internals->mSecondaryConnection->GetTimer().SetTimeout(Internals->timeout); ULConnection* mConnection = Internals->mConnection; network::ULWritingCallback theCallback; theCallback.SetDirectory(outputdir); network::ULConnectionCallback* inCallback = &theCallback; std::vector theDataPDU = PDUFactory::CreateCMovePDU( *mConnection, query ); ULEvent theEvent(ePDATArequest, theDataPDU); EStateID stateid = RunMoveEventLoop(theEvent, inCallback); if( stateid != gdcm::network::eSta6TransferReady ) { return false; } return true; } bool ServiceClassUser::SendMove(const BaseRootQuery* query, std::vector &retDataSets) { UserInformation userInfo2; ULConnectionInfo connectInfo2; if (!connectInfo2.Initialize(userInfo2, Internals->aetitle.c_str(), Internals->calledaetitle.c_str(), 0, Internals->portscp, Internals->hostname)) { return false; } // let's start the secondary connection ULConnection* mSecondaryConnection = Internals->mSecondaryConnection; if (mSecondaryConnection) { delete mSecondaryConnection; } Internals->mSecondaryConnection = new ULConnection(connectInfo2); Internals->mSecondaryConnection->GetTimer().SetTimeout(Internals->timeout); ULConnection* mConnection = Internals->mConnection; network::ULBasicCallback theCallback; network::ULConnectionCallback* inCallback = &theCallback; std::vector theDataPDU = PDUFactory::CreateCMovePDU( *mConnection, query ); ULEvent theEvent(ePDATArequest, theDataPDU); EStateID stateid = RunMoveEventLoop(theEvent, inCallback); if( stateid != gdcm::network::eSta6TransferReady ) { return false; } std::vector const & theDataSets = theCallback.GetDataSets(); retDataSets.insert( retDataSets.end(), theDataSets.begin(), theDataSets.end() ); return true; } bool ServiceClassUser::SendMove(const BaseRootQuery* query, std::vector &retFiles) { (void)query; (void)retFiles; assert( 0 && "unimplemented do not use" ); return false; } //event handler loop. //will just keep running until the current event is nonexistent. //at which point, it will return the current state of the connection //to do this, execute an event, and then see if there's a response on the //incoming connection (with a reasonable amount of timeout). //if no response, assume that the connection is broken. //if there's a response, then yay. //note that this is the ARTIM timeout event EStateID ServiceClassUser::RunEventLoop(network::ULEvent& currentEvent, network::ULConnection* inWhichConnection, network::ULConnectionCallback* inCallback, const bool& startWaiting = false) { EStateID theState = eStaDoesNotExist; bool waitingForEvent = startWaiting;//overwritten if not starting waiting, but if waiting, then wait EEventID raisedEvent; bool receivingData = false; //bool justWaiting = startWaiting; //not sure justwaiting is useful; for now, go back to waiting for event //when receiving data from a find, etc, then justWaiting is true and only receiving is done //eventually, could add cancel into the mix... but that would be through a callback or something similar do { raisedEvent = eEventDoesNotExist; if (!waitingForEvent){//justWaiting){ Internals->mTransitions.HandleEvent(this, currentEvent, *inWhichConnection, waitingForEvent, raisedEvent); //this gathering of the state is for scus that have just sent out a request theState = inWhichConnection->GetState(); } std::istream &is = *inWhichConnection->GetProtocol(); //std::ostream &os = *inWhichConnection->GetProtocol(); BasePDU* theFirstPDU = nullptr;// the first pdu read in during this event loop, //used to make sure the presentation context ID is correct //read the connection, as that's an event as well. //waiting for an object to come back across the connection, so that it can get handled. //ie, accept, reject, timeout, etc. //of course, if the connection is down, just leave the loop. //also leave the loop if nothing's waiting. //use the PDUFactory to create the appropriate pdu, which has its own //internal mechanisms for handling itself (but will, of course, be put inside the event object). //but, and here's the important thing, only read on the socket when we should. std::vector incomingPDUs; if (waitingForEvent){ while (waitingForEvent){//loop for reading in the events that come down the wire uint8_t itemtype = 0x0; try { is.read( (char*)&itemtype, 1 ); //what happens if nothing's read? theFirstPDU = PDUFactory::ConstructPDU(itemtype); if (theFirstPDU != nullptr){ incomingPDUs.push_back(theFirstPDU); theFirstPDU->Read(is); gdcmDebugMacro("PDU code: " << static_cast(itemtype) << std::endl); if (Trace::GetDebugFlag()) { theFirstPDU->Print(Trace::GetStream()); } if (theFirstPDU->IsLastFragment()) waitingForEvent = false; } else { waitingForEvent = false; //because no PDU means not waiting anymore } } catch (...) { //handle the exception, which is basically that nothing came in over the pipe. assert( 0 ); } } //now, we have to figure out the event that just happened based on the PDU that was received. //this state gathering is for scps, especially the cstore for cmove. theState = inWhichConnection->GetState(); if (!incomingPDUs.empty()){ currentEvent.SetEvent(PDUFactory::DetermineEventByPDU(incomingPDUs[0])); currentEvent.SetPDU(incomingPDUs); //here's the scp handling code if (Internals->mConnection->GetTimer().GetHasExpired()){ currentEvent.SetEvent(eARTIMTimerExpired); } switch(currentEvent.GetEvent()){ case ePDATATFPDU: { //if (theState == eSta6TransferReady){//ie, finished the transitions //with find, the results now come down the wire. //the pdu we already have from the event will tell us how many to expect. uint32_t pendingDE1, pendingDE2, success, theVal; pendingDE1 = 0xff01; pendingDE2 = 0xff00; success = 0x0000; theVal = pendingDE1; uint32_t theCommandCode = 0;//for now, a nothing value DataSet theRSP = PresentationDataValue::ConcatenatePDVBlobs( PDUFactory::GetPDVs(currentEvent.GetPDUs())); if (inCallback) { inCallback->HandleResponse(theRSP); } if (theRSP.FindDataElement(Tag(0x0, 0x0900))){ DataElement de = theRSP.GetDataElement(Tag(0x0,0x0900)); Attribute<0x0,0x0900> at; at.SetFromDataElement( de ); theVal = at.GetValues()[0]; //if theVal is Pending or Success, then we need to enter the loop below, //because we need the data PDUs. //so, the loop below is a do/while loop; there should be at least a second packet //with the dataset, even if the status is 'success' //success == 0000H } if (Trace::GetDebugFlag()) { Printer thePrinter; thePrinter.PrintDataSet(theRSP, Trace::GetStream()); } //check to see if this is a cstorerq if (theRSP.FindDataElement(Tag(0x0, 0x0100))) { DataElement de2 = theRSP.GetDataElement(Tag(0x0,0x0100)); Attribute<0x0,0x0100> at2; at2.SetFromDataElement( de2 ); theCommandCode = at2.GetValues()[0]; } if (theVal != pendingDE1 && theVal != pendingDE2 && theVal != success) { //check for other error fields const ByteValue *err1 = nullptr, *err2 = nullptr; gdcmErrorMacro( "Transfer failed with code " << theVal << std::endl); switch (theVal){ case 0xA701: gdcmErrorMacro( "Refused: Out of Resources Unable to calculate number of matches" << std::endl); break; case 0xA702: gdcmErrorMacro( "Refused: Out of Resources Unable to perform sub-operations" << std::endl); break; case 0xA801: gdcmErrorMacro( "Refused: Move Destination unknown" << std::endl); break; case 0xA900: gdcmErrorMacro( "Identifier does not match SOP Class" << std::endl); break; case 0xAA00: gdcmErrorMacro( "None of the frames requested were found in the SOP Instance" << std::endl); break; case 0xAA01: gdcmErrorMacro( "Unable to create new object for this SOP class" << std::endl); break; case 0xAA02: gdcmErrorMacro( "Unable to extract frames" << std::endl); break; case 0xAA03: gdcmErrorMacro( "Time-based request received for a non-time-based original SOP Instance. " << std::endl); break; case 0xAA04: gdcmErrorMacro( "Invalid Request" << std::endl); break; case 0xFE00: gdcmErrorMacro( "Sub-operations terminated due to Cancel Indication" << std::endl); break; case 0xB000: gdcmErrorMacro( "Sub-operations Complete One or more Failures or Warnings" << std::endl); break; default: gdcmErrorMacro( "Unable to process" << std::endl); break; } if (theRSP.FindDataElement(Tag(0x0,0x0901))){ DataElement de = theRSP.GetDataElement(Tag(0x0,0x0901)); err1 = de.GetByteValue(); gdcmErrorMacro( " Tag 0x0,0x901 reported as " << *err1 << std::endl); (void)err1; } if (theRSP.FindDataElement(Tag(0x0,0x0902))){ DataElement de = theRSP.GetDataElement(Tag(0x0,0x0902)); err2 = de.GetByteValue(); gdcmErrorMacro( " Tag 0x0,0x902 reported as " << *err2 << std::endl); (void)err2; } } receivingData = false; //justWaiting = false; if (theVal == pendingDE1 || theVal == pendingDE2) { receivingData = true; //wait for more data as more PDUs (findrsps, for instance) //justWaiting = true; waitingForEvent = true; } if (theVal == pendingDE1 || theVal == pendingDE2 /*|| theVal == success*/){//keep looping if we haven't succeeded or failed; these are the values for 'pending' //first, dynamically cast that pdu in the event //should be a data pdu //then, look for tag 0x0,0x900 //only add datasets that are _not_ part of the network response std::vector final; std::vector theData; BasePDU* thePDU;//outside the loop for the do/while stopping condition bool interrupted = false; do { uint8_t itemtype = 0x0; is.read( (char*)&itemtype, 1 ); //what happens if nothing's read? thePDU = PDUFactory::ConstructPDU(itemtype); if (itemtype != 0x4 && thePDU != nullptr){ //ie, not a pdatapdu std::vector interruptingPDUs; interruptingPDUs.push_back(thePDU); currentEvent.SetEvent(PDUFactory::DetermineEventByPDU(interruptingPDUs[0])); currentEvent.SetPDU(interruptingPDUs); interrupted= true; break; } if (thePDU != nullptr){ // FIXME: How do I find out how many PData we are receiving ? // This is needed for proper progress report thePDU->Read(is); theData.push_back(thePDU); } else{ break; } //!!!need to handle incoming PDUs that are not data, ie, an abort } while(!thePDU->IsLastFragment()); if (!interrupted){//ie, if the remote server didn't hang up DataSet theCompleteFindResponse = PresentationDataValue::ConcatenatePDVBlobs(PDUFactory::GetPDVs(theData)); //note that it's the responsibility of the event to delete the PDU in theFindRSP for (size_t i = 0; i < theData.size(); i++) { delete theData[i]; } //outDataSet.push_back(theCompleteFindResponse); if (inCallback) { inCallback->HandleDataSet(theCompleteFindResponse); } // DataSetEvent dse( &theCompleteFindResponse ); // this->InvokeEvent( dse ); if (theCommandCode == 1){//if we're doing cstore scp stuff, send information back along the connection. std::vector theCStoreRSPPDU = PDUFactory::CreateCStoreRSPPDU(&theRSP, theFirstPDU);//pass NULL for C-Echo //send them directly back over the connection //ideall, should go through the transition table, but we know this should work //and it won't change the state (unless something breaks?, but then an exception should throw) std::vector::iterator itor; for (itor = theCStoreRSPPDU.begin(); itor < theCStoreRSPPDU.end(); itor++){ (*itor)->Write(*inWhichConnection->GetProtocol()); } inWhichConnection->GetProtocol()->flush(); // FIXME added MM / Oct 30 2010 //AReleaseRPPDU rel; //rel.Write( *inWhichConnection->GetProtocol() ); //inWhichConnection->GetProtocol()->flush(); receivingData = false; //gotta get data on the other connection for a cmove } } } } break; case eARELEASERequest://process this via the transition table waitingForEvent = false; break; case eARELEASE_RQPDUReceivedOpen://process this via the transition table waitingForEvent = false; receivingData = true; //to continue the loop to process the release break; case eAABORTRequest: waitingForEvent = false; inWhichConnection->StopProtocol(); break; case eASSOCIATE_ACPDUreceived: default: waitingForEvent = false; break; } } //} else { // raisedEvent = eEventDoesNotExist; // waitingForEvent = false; //} } else { currentEvent.SetEvent(raisedEvent);//actions that cause transitions in the state table //locally just raise local events that will therefore cause the trigger to be pulled. } } while (currentEvent.GetEvent() != eEventDoesNotExist && theState != eStaDoesNotExist && theState != eSta13AwaitingClose && theState != eSta1Idle && (theState != eSta6TransferReady || (theState == eSta6TransferReady && receivingData ))); //stop when the AE is done, or when ready to transfer data (ie, the next PDU should be sent in), //or when the connection is idle after a disconnection. //or, if in state 6 and receiving data, until all data is received. return theState; } EStateID ServiceClassUser::RunMoveEventLoop(ULEvent& currentEvent, ULConnectionCallback* inCallback){ EStateID theState = eStaDoesNotExist; bool waitingForEvent; EEventID raisedEvent; bool receivingData = false; bool justWaiting = false; //when receiving data from a find, etc, then justWaiting is true and only receiving is done //eventually, could add cancel into the mix... but that would be through a callback or something similar do { if (!justWaiting){ Internals->mTransitions.HandleEvent(this,currentEvent, *Internals->mConnection, waitingForEvent, raisedEvent); } theState = Internals->mConnection->GetState(); std::istream &is = *Internals->mConnection->GetProtocol(); //std::ostream &os = *mConnection->GetProtocol(); //When doing a C-MOVE we receive the Requested DataSet over //another channel (technically this is send to an SCP) //in our case we use another port to receive it. EStateID theCStoreStateID = eSta6TransferReady; bool secondConnectionEstablished = false; if (Internals->mSecondaryConnection->GetProtocol() == nullptr){ //establish the connection //can fail if is_readready doesn't return true, ie, the connection //wasn't opened on the other side because the other side isn't sending data yet //for whatever reason (maybe there's nothing to get?) try { secondConnectionEstablished = Internals->mSecondaryConnection->InitializeIncomingConnection(); } catch ( std::exception & e ) { gdcmErrorMacro( "Error 2nd connection:" << e.what() ); (void)e; } catch ( ... ) { assert( 0 ); } } if (secondConnectionEstablished && (Internals->mSecondaryConnection->GetState()== eSta1Idle || Internals->mSecondaryConnection->GetState() == eSta2Open)){ ULEvent theCStoreEvent(eEventDoesNotExist, nullptr);//have to fill this in, we're in passive mode now theCStoreStateID = RunEventLoop(theCStoreEvent, Internals->mSecondaryConnection, inCallback, true); } //just as for the regular event loop, but we have to alternate between the connections. //it may be that nothing comes back over the is connection, but lots over the //isSCP connection. So, if is fails, meh. But if isSCP fails, that's not so meh. //we care only about the datasets coming back from isSCP, ultimately, though the datasets //from is will contain progress info. std::vector incomingPDUs; if (waitingForEvent){ while (waitingForEvent) {//loop for reading in the events that come down the wire uint8_t itemtype = 0x0; is.read( (char*)&itemtype, 1 ); BasePDU* thePDU = PDUFactory::ConstructPDU(itemtype); if (thePDU != nullptr) { incomingPDUs.push_back(thePDU); thePDU->Read(is); gdcmDebugMacro("PDU code: " << static_cast(itemtype) << std::endl); if (Trace::GetDebugFlag()) { thePDU->Print(Trace::GetStream()); } if (thePDU->IsLastFragment()) waitingForEvent = false; } else { waitingForEvent = false; //because no PDU means not waiting anymore } } //now, we have to figure out the event that just happened based on the PDU that was received. if (!incomingPDUs.empty()) { currentEvent.SetEvent(PDUFactory::DetermineEventByPDU(incomingPDUs[0])); currentEvent.SetPDU(incomingPDUs); if (Internals->mConnection->GetTimer().GetHasExpired()) { currentEvent.SetEvent(eARTIMTimerExpired); } if (theState == eSta6TransferReady){//ie, finished the transitions //with find, the results now come down the wire. //the pdu we already have from the event will tell us how many to expect. uint32_t pendingDE1, pendingDE2, success, theVal; pendingDE1 = 0xff01; pendingDE2 = 0xff00; success = 0x0000; theVal = pendingDE1; uint32_t theNumLeft = 0; // the number of pending sub operations left. //so here's the thing: dcmtk responds with 'success' as it first cmove rsp //which is retarded and, I think, wrong. However, dcm4chee responds with 'pending' //so, we look either for pending, or for the number of operations left // (tag 0000, 1020) if the value is success, and that number should be 0. DataSet theRSP = PresentationDataValue::ConcatenatePDVBlobs(PDUFactory::GetPDVs(currentEvent.GetPDUs())); if (Trace::GetDebugFlag()){ Printer thePrinter; thePrinter.PrintDataSet(theRSP, Trace::GetStream()); } if (theRSP.FindDataElement(Tag(0x0, 0x0900))){ DataElement de = theRSP.GetDataElement(Tag(0x0,0x0900)); Attribute<0x0,0x0900> at; at.SetFromDataElement( de ); theVal = at.GetValues()[0]; //if theVal is Pending or Success, then we need to enter the loop below, //because we need the data PDUs. //so, the loop below is a do/while loop; there should be at least a second packet //with the dataset, even if the status is 'success' //success == 0000H } uint32_t theCommandCode = 0; if (theRSP.FindDataElement(Tag(0x0,0x0100))){ DataElement de = theRSP.GetDataElement(Tag(0x0,0x0100)); Attribute<0x0,0x0100> at; at.SetFromDataElement( de ); theCommandCode = at.GetValues()[0]; } if (theRSP.FindDataElement(Tag(0x0, 0x1020))){ DataElement de = theRSP.GetDataElement(Tag(0x0,0x1020)); Attribute<0x0,0x1020> at; at.SetFromDataElement( de ); theNumLeft = at.GetValues()[0]; //if theVal is Pending or Success, then we need to enter the loop below, //because we need the data PDUs. //so, the loop below is a do/while loop; there should be at least a second packet //with the dataset, even if the status is 'success' //success == 0000H } if (theVal != pendingDE1 && theVal != pendingDE2 && theVal != success){ //check for other error fields const ByteValue *err1 = nullptr, *err2 = nullptr; gdcmErrorMacro( "Transfer failed with code " << theVal << std::endl); switch (theVal){ case 0xA701: gdcmErrorMacro( "Refused: Out of Resources Unable to calculate number of matches" << std::endl); break; case 0xA702: gdcmErrorMacro( "Refused: Out of Resources Unable to perform sub-operations" << std::endl); break; case 0xA801: gdcmErrorMacro( "Refused: Move Destination unknown" << std::endl); break; case 0xA900: gdcmErrorMacro( "Identifier does not match SOP Class" << std::endl); break; case 0xAA00: gdcmErrorMacro( "None of the frames requested were found in the SOP Instance" << std::endl); break; case 0xAA01: gdcmErrorMacro( "Unable to create new object for this SOP class" << std::endl); break; case 0xAA02: gdcmErrorMacro( "Unable to extract frames" << std::endl); break; case 0xAA03: gdcmErrorMacro( "Time-based request received for a non-time-based original SOP Instance. " << std::endl); break; case 0xAA04: gdcmErrorMacro( "Invalid Request" << std::endl); break; case 0xFE00: gdcmErrorMacro( "Sub-operations terminated due to Cancel Indication" << std::endl); break; case 0xB000: gdcmErrorMacro( "Sub-operations Complete One or more Failures or Warnings" << std::endl); break; default: gdcmErrorMacro( "Unable to process" << std::endl); break; } if (theRSP.FindDataElement(Tag(0x0,0x0901))){ DataElement de = theRSP.GetDataElement(Tag(0x0,0x0901)); err1 = de.GetByteValue(); gdcmErrorMacro( " Tag 0x0,0x901 reported as " << *err1 << std::endl); (void)err1; } if (theRSP.FindDataElement(Tag(0x0,0x0902))){ DataElement de = theRSP.GetDataElement(Tag(0x0,0x0902)); err2 = de.GetByteValue(); gdcmErrorMacro( " Tag 0x0,0x902 reported as " << *err2 << std::endl); (void)err2; } } receivingData = false; justWaiting = false; if (theVal == pendingDE1 || theVal == pendingDE2 || (theVal == success && theNumLeft != 0)) { receivingData = true; //wait for more data as more PDUs (findrsps, for instance) justWaiting = true; waitingForEvent = true; //ok, if we're pending, then let's open the cstorescp connection here //(if it's not already open), and then from here start a storescp event loop. //just don't listen to the cmove event loop until this is done. //could cause a pileup on the main connection, I suppose. //could also report the progress here, if we liked. if (theCommandCode == 0x8021){//cmove response, so prep the retrieval loop on the back connection bool dataSetCountIncremented = true;//false once the number of incoming datasets doesn't change. if (Internals->mSecondaryConnection->GetProtocol() == nullptr){ //establish the connection //can fail if is_readready doesn't return true, ie, the connection //wasn't opened on the other side because the other side isn't sending data yet //for whatever reason (maybe there's nothing to get?) secondConnectionEstablished = Internals->mSecondaryConnection->InitializeIncomingConnection(); if (secondConnectionEstablished && (Internals->mSecondaryConnection->GetState()== eSta1Idle || Internals->mSecondaryConnection->GetState() == eSta2Open)){ ULEvent theCStoreEvent(eEventDoesNotExist, nullptr);//have to fill this in, we're in passive mode now theCStoreStateID = RunEventLoop(theCStoreEvent, Internals->mSecondaryConnection, inCallback, true); } else {//something broke, can't establish secondary move connection here gdcmErrorMacro( "Unable to establish secondary connection with server, aborting." << std::endl); return eStaDoesNotExist; } } if (secondConnectionEstablished){ while (theCStoreStateID == eSta6TransferReady && dataSetCountIncremented){ ULEvent theCStoreEvent(eEventDoesNotExist, nullptr);//have to fill this in, we're in passive mode now //now, get data from across the network theCStoreStateID = RunEventLoop(theCStoreEvent, Internals->mSecondaryConnection, inCallback, true); if (inCallback){ dataSetCountIncremented = true; inCallback->ResetHandledDataSet(); } else { dataSetCountIncremented = false; } } } //force the abort from our side // ULEvent theCStoreEvent(eAABORTRequest, NULL);//have to fill this in, we're in passive mode now // theCStoreStateID = RunEventLoop(theCStoreEvent, outDataSet, mSecondaryConnection, true); } else {//not dealing with cmove progress updates, apparently //keep looping if we haven't succeeded or failed; these are the values for 'pending' //first, dynamically cast that pdu in the event //should be a data pdu //then, look for tag 0x0,0x900 //only add datasets that are _not_ part of the network response std::vector final; std::vector theData; BasePDU* thePDU;//outside the loop for the do/while stopping condition bool interrupted = false; do { uint8_t itemtype = 0x0; is.read( (char*)&itemtype, 1 ); //what happens if nothing's read? thePDU = PDUFactory::ConstructPDU(itemtype); if (itemtype != 0x4 && thePDU != nullptr){ //ie, not a pdatapdu std::vector interruptingPDUs; currentEvent.SetEvent(PDUFactory::DetermineEventByPDU(interruptingPDUs[0])); currentEvent.SetPDU(interruptingPDUs); interrupted= true; break; } if (thePDU != nullptr){ thePDU->Read(is); theData.push_back(thePDU); } else{ break; } //!!!need to handle incoming PDUs that are not data, ie, an abort } while(/*!is.eof() &&*/ !thePDU->IsLastFragment()); if (!interrupted){//ie, if the remote server didn't hang up DataSet theCompleteFindResponse = PresentationDataValue::ConcatenatePDVBlobs(PDUFactory::GetPDVs(theData)); //note that it's the responsibility of the event to delete the PDU in theFindRSP for (size_t i = 0; i < theData.size(); i++){ delete theData[i]; } //outDataSet.push_back(theCompleteFindResponse); if (inCallback){ inCallback->HandleDataSet(theCompleteFindResponse); } } } } } } else { raisedEvent = eEventDoesNotExist; waitingForEvent = false; } } else { currentEvent.SetEvent(raisedEvent);//actions that cause transitions in the state table //locally just raise local events that will therefore cause the trigger to be pulled. } } while (currentEvent.GetEvent() != eEventDoesNotExist && theState != eStaDoesNotExist && theState != eSta13AwaitingClose && theState != eSta1Idle && (theState != eSta6TransferReady || (theState == eSta6TransferReady && receivingData ))); //stop when the AE is done, or when ready to transfer data (ie, the next PDU should be sent in), //or when the connection is idle after a disconnection. //or, if in state 6 and receiving data, until all data is received. return theState; } } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmServiceClassUser.h000066400000000000000000000077201412732066400250510ustar00rootroot00000000000000/*========================================================================= 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 GDCMSERVICECLASSUSER_H #define GDCMSERVICECLASSUSER_H #include "gdcmSubject.h" #include "gdcmPresentationContext.h" #include "gdcmFile.h" #include "gdcmNetworkStateID.h" // EStateID namespace gdcm { class ServiceClassUserInternals; class BaseRootQuery; namespace network{ class ULEvent; class ULConnection; class ULConnectionCallback; } /** * \brief ServiceClassUser */ class GDCM_EXPORT ServiceClassUser : public Subject { public: /// Construct a SCU with default: /// - hostname = localhost /// - port = 104 ServiceClassUser(); ~ServiceClassUser() override; ServiceClassUser(const ServiceClassUser&) = delete; void operator=(const ServiceClassUser &) = delete; /// Set the name of the called hostname (hostname or IP address) void SetHostname( const char *hostname ); /// Set port of remote host (called application) void SetPort( uint16_t port ); /// Set the port for any incoming C-STORE-SCP operation (typically in a return of C-MOVE) void SetPortSCP( uint16_t portscp ); /// set calling ae title void SetAETitle(const char *aetitle); const char *GetAETitle() const; /// set called ae title void SetCalledAETitle(const char *aetitle); const char *GetCalledAETitle() const; /// set/get Timeout void SetTimeout(double t); double GetTimeout() const; /// Will try to connect /// This will setup the actual timeout used during the whole connection time. Need to call /// SetTimeout first bool InitializeConnection(); /// Set the Presentation Context used for the Association void SetPresentationContexts(std::vector const & pcs); /// Return if the passed in presentation was accepted during association negotiation. bool IsPresentationContextAccepted(const PresentationContext& pc) const; /// Start the association. Need to call SetPresentationContexts before bool StartAssociation(); /// Stop the running association bool StopAssociation(); /// C-ECHO bool SendEcho(); /// Execute a C-STORE on file on disk, named filename bool SendStore(const char *filename); /// Execute a C-STORE on a File, the transfer syntax used for the query is based on the /// file. bool SendStore(File const &file); /// Execute a C-STORE on a DataSet, the transfer syntax used will be Implicit bool SendStore(DataSet const &ds); /// C-FIND a query, return result are in retDatasets bool SendFind(const BaseRootQuery* query, std::vector &retDatasets); /// Execute a C-MOVE, based on query, return files are written in outputdir bool SendMove(const BaseRootQuery* query, const char *outputdir); /// Execute a C-MOVE, based on query, returned dataset are Implicit bool SendMove(const BaseRootQuery* query, std::vector &retDatasets); /// Execute a C-MOVE, based on query, returned Files are stored in vector bool SendMove(const BaseRootQuery* query, std::vector &retFile); /// for wrapped language: instantiate a reference counted object static SmartPointer New() { return new ServiceClassUser; } private: network::EStateID RunEventLoop(network::ULEvent& inEvent, network::ULConnection* inWhichConnection, network::ULConnectionCallback* inCallback, const bool& startWaiting); network::EStateID RunMoveEventLoop(network::ULEvent& inEvent, network::ULConnectionCallback* inCallback); private: ServiceClassUserInternals *Internals; }; } // end namespace gdcm #endif // GDCMSERVICECLASSUSER_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmTransferSyntaxSub.cxx000066400000000000000000000057641412732066400256520ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTransferSyntaxSub.h" #include "gdcmSwapper.h" #include namespace gdcm { namespace network { const uint8_t TransferSyntaxSub::ItemType = 0x40; const uint8_t TransferSyntaxSub::Reserved2 = 0x00; TransferSyntaxSub::TransferSyntaxSub() { //UpdateName( "1.2.840.10008.1.1" ); ItemLength = 0; } void TransferSyntaxSub::SetName( const char *name ) { if( name ) { Name = name; assert( Name.size() <= std::numeric_limits::max() ); ItemLength = (uint16_t)Name.size(); } } std::istream &TransferSyntaxSub::Read(std::istream &is) { uint8_t itemtype = 0xf; is.read( (char*)&itemtype, sizeof(ItemType) ); assert( itemtype == ItemType ); uint8_t reserved2; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint16_t itemlength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; char name[256]; assert( itemlength < 256 ); is.read( name, itemlength ); Name = std::string(name,itemlength); return is; } const std::ostream &TransferSyntaxSub::Write(std::ostream &os) const { os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); //os.write( (const char*)&ItemLength, sizeof(ItemLength) ); uint16_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); assert( Name.size() < 256 ); os.write( Name.c_str(), Name.size() ); return os; } size_t TransferSyntaxSub::Size() const { size_t ret = 0; assert( Name.size() == ItemLength ); ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); ret += ItemLength; return ret; } void TransferSyntaxSub::UpdateName( const char *name ) { if( name ) { UIDs uids; bool b = uids.SetFromUID( name ); if( b ) { Name = name; ItemLength = (uint16_t)Name.size(); assert( (size_t)ItemLength + 4 == Size() ); return; } } gdcmErrorMacro( "Invalid Name: " << name ); throw "Invalid Name"; } void TransferSyntaxSub::SetNameFromUID( UIDs::TSName tsname ) { const char *name = UIDs::GetUIDString( tsname ); UpdateName( name ); } void TransferSyntaxSub::Print(std::ostream &os) const { os << "Name: " << Name; UIDs uids; if( uids.SetFromUID( Name.c_str() ) ) { os << " (" << uids.GetName() << ")" << std::endl; } os << std::endl; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmTransferSyntaxSub.h000066400000000000000000000032351412732066400252660ustar00rootroot00000000000000/*========================================================================= 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 GDCMTRANSFERSYNTAXSUB_H #define GDCMTRANSFERSYNTAXSUB_H #include "gdcmTypes.h" #include "gdcmTransferSyntax.h" #include "gdcmUIDs.h" namespace gdcm { namespace network { /** * \brief TransferSyntaxSub * \details Table 9-15 * TRANSFER SYNTAX SUB-ITEM FIELDS * * TODO what is the goal of : * * Table 9-19 * TRANSFER SYNTAX SUB-ITEM FIELDS */ class TransferSyntaxSub { public: TransferSyntaxSub(); void SetName( const char *name ); const char *GetName() const { return Name.c_str(); } // accept a UIDs::TSType also... void SetNameFromUID( UIDs::TSName tsname ); std::istream &Read(std::istream &is); const std::ostream &Write(std::ostream &os) const; size_t Size() const; void Print(std::ostream &os) const; bool operator==(const TransferSyntaxSub & ts) const { return Name == ts.Name; } private: void UpdateName( const char *name ); static const uint8_t ItemType; static const uint8_t Reserved2; uint16_t ItemLength; // len of std::string /*TransferSyntaxSub*/ Name; // UID }; } // end namespace network } // end namespace gdcm #endif //GDCMTRANSFERSYNTAXSUB_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULAction.h000066400000000000000000000066161412732066400233050ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMULACTION_H #define GDCMULACTION_H #include "gdcmNetworkStateID.h" #include "gdcmULEvent.h" #include "gdcmULConnection.h" namespace gdcm { class Subject; namespace network { /** * \brief ULAction * \details A ULConnection in a given ULState can perform certain ULActions. This base class * provides the interface for running those ULActions on a given ULConnection. * * Essentially, the ULConnectionManager will take this object, determined from the current * ULState of the ULConnection, and pass the ULConnection object to the ULAction. The ULAction * will then invoke whatever necessary commands are required by a given action. * * The result of a ULAction is a ULEvent (ie, what happened as a result of the action). * * This ULEvent is passed to the ULState, so that the transition to the next state can occur. * * Actions are associated with Payloads -- be those filestreams, AETitles to establish connections, * whatever. The actual parameters that the user will pass via an action will come through * a Payload object, which should, in itself, be some gdcm-based object (but not all objects can * be payloads; sending a single dataelement as a payload isn't meaningful). As such, each action * has its own particular payload. * * For the sake of keeping files together, both the particular payload class and the action class * will be defined in the same header file. Payloads should JUST be data (or streams), NO METHODS. * * Some actions perform changes that should raise events on the local system, and some * actions perform changes that will require waiting for events from the remote system. * * Therefore, this base action has been modified so that those events are set by each action. * When the event loop runs an action, it will then test to see if a local event was raised by the * action, and if so, perform the appropriate subsequent action. If the action requires waiting * for a response from the remote system, then the event loop will sit there (presumably with the * ARTIM timer running) and wait for a response from the remote system. Once a response is * obtained, then the the rest of the state transitions can happen. * */ class ULAction { protected: public: ULAction() = default; //make sure destructors are virtual to avoid memory leaks virtual ~ULAction() = default; //cannot copy a ULAction ULAction(const ULAction& inAction) = delete; void operator=(const ULAction&) = delete; virtual EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) = 0; }; } } #endif // GDCMULACTION_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULActionAA.cxx000066400000000000000000000065241412732066400240600ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /* This file contains the implementation for the classes for the AA Actions, Association Abort Related Actions (Table 9-9 of ps 3.8-2009). Since each class is essentially a placeholder for a function pointer, I'm breaking with having each class have its own file for the sake of brevity of the number of files. */ #include "gdcmULActionAA.h" #include "gdcmARTIMTimer.h" #include "gdcmAAbortPDU.h" #include namespace gdcm { namespace network { //Send A-ABORT PDU (service-user source) and start (or restart if already started) ARTIM timer EStateID ULActionAA1::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& , EEventID& ){ AAbortPDU thePDU; thePDU.Write(*inConnection.GetProtocol()); inConnection.GetTimer().Start(); return eSta13AwaitingClose; } //Stop ARTIM timer if running. Close transport connection. EStateID ULActionAA2::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& , EEventID& ){ inConnection.GetTimer().Stop(); inConnection.StopProtocol(); return eSta1Idle; } //If (service-user initiated abort) //- issue A-ABORT indication and close transport connection //otherwise (service-provider initiated abort): //- issue A-P-ABORT indication and close transport connection EStateID ULActionAA3::PerformAction(Subject *, ULEvent& , ULConnection& , bool& , EEventID& ){ return eSta1Idle; } //Issue A-P-ABORT indication primitive EStateID ULActionAA4::PerformAction(Subject *, ULEvent& , ULConnection& , bool& , EEventID& ){ return eSta1Idle; } //Stop ARTIM timer EStateID ULActionAA5::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& , EEventID& ){ inConnection.GetTimer().Stop(); return eSta1Idle; } //Ignore PDU EStateID ULActionAA6::PerformAction(Subject *, ULEvent& , ULConnection& , bool& , EEventID& ){ //do nothing, I guess. return eSta13AwaitingClose; } //Send A-ABORT PDU EStateID ULActionAA7::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& , EEventID& ){ AAbortPDU thePDU;//for now, use Matheiu's default values thePDU.Write(*inConnection.GetProtocol()); return eSta13AwaitingClose; } //Send A-ABORT PDU (service-provider source), issue an A-P-ABORT indication, and start ARTIM timer EStateID ULActionAA8::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& , EEventID& ){ AAbortPDU thePDU;//for now, use Matheiu's default values thePDU.Write(*inConnection.GetProtocol()); inConnection.GetTimer().Start(); return eSta13AwaitingClose; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULActionAA.h000066400000000000000000000073451412732066400235070ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMULACTIONAA_H #define GDCMULACTIONAA_H #include "gdcmULAction.h" /** This header defines the classes for the AA Actions, Association Abort Related Actions (Table 9-9 of ps 3.8-2009). Since each class is essentially a placeholder for a function pointer, I'm breaking with having each class have its own file for the sake of brevity of the number of files. */ namespace gdcm { namespace network { //Send A-ABORT PDU (service-user source) and start (or restart if already started) ARTIM timer //Next State: eSta13AwaitingClose class ULActionAA1 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Stop ARTIM timer if running. Close transport connection. //Next State: eSta1Idle class ULActionAA2 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //If (service-user initiated abort) //- issue A-ABORT indication and close transport connection //otherwise (service-provider initiated abort): //- issue A-P-ABORT indication and close transport connection //Next State: eSta1Idle class ULActionAA3 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Issue A-P-ABORT indication primitive //Next State: eSta1Idle class ULActionAA4 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Stop ARTIM timer //Next State: eSta1Idle class ULActionAA5 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Ignore PDU //Next State: eSta13AwaitingClose class ULActionAA6 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Send A-ABORT PDU //Next State: eSta13AwaitingClose class ULActionAA7 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Send A-ABORT PDU (service-provider source), issue an A-P-ABORT indication, and start ARTIM timer //Next State: eSta13AwaitingClose class ULActionAA8 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; } } #endif // GDCMULACTIONAA_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULActionAE.cxx000066400000000000000000000232671412732066400240670ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /* This file contains the implementation for the classes for the AE Actions, Association Establishment Related Actions (Table 9-6 of ps 3.8-2009). Since each class is essentially a placeholder for a function pointer, I'm breaking with having each class have its own file for the sake of brevity of the number of files. */ #include "gdcmULActionAE.h" #include "gdcmARTIMTimer.h" #include "gdcmAAssociateRQPDU.h" #include "gdcmAAssociateACPDU.h" #include "gdcmAAssociateRJPDU.h" #include //for setting up the local socket namespace gdcm { namespace network { //Issue TRANSPORT CONNECT request primitive to local transport service. EStateID ULActionAE1::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent){ //opening a local socket outWaitingForEvent = false; if (!inConnection.InitializeConnection()) { outRaisedEvent = eEventDoesNotExist; return eSta1Idle; } else { outRaisedEvent = eTransportConnConfirmLocal; } return eSta4LocalAssocDone; } //Send A-ASSOCIATE-RQ-PDU EStateID ULActionAE2::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) { AAssociateRQPDU thePDU; thePDU.SetCallingAETitle( inConnection.GetConnectionInfo().GetCallingAETitle() ); thePDU.SetCalledAETitle( inConnection.GetConnectionInfo().GetCalledAETitle() ); //the presentation context is now defined when the connection is first //desired to be established. The connection proposes these different //presentation contexts. ideally, we could refine it further to a particular //presentation context, but if the server supports many and we support many, //then an arbitrary decision can be made. std::vector const & thePCS = inConnection.GetPresentationContexts(); std::vector::const_iterator itor; for (itor = thePCS.begin(); itor < thePCS.end(); itor++) { thePDU.AddPresentationContext(*itor); } thePDU.Write(*inConnection.GetProtocol()); inConnection.GetProtocol()->flush(); outWaitingForEvent = true; outRaisedEvent = eEventDoesNotExist; return eSta5WaitRemoteAssoc; } //Issue A-ASSOCIATE confirmation (accept) primitive // NOTE: A-ASSOCIATE is NOT A-ASSOCIATE-AC // PS 3.7 / Annex D for A-ASSOCIATE definition EStateID ULActionAE3::PerformAction(Subject *, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent){ // Mark please check this junk: assert(!inEvent.GetPDUs().empty()); AAssociateACPDU* acpdu; acpdu = dynamic_cast(inEvent.GetPDUs()[0]); assert( acpdu ); uint32_t maxpdu = acpdu->GetUserInformation().GetMaximumLengthSub().GetMaximumLength(); inConnection.SetMaxPDUSize(maxpdu); // once again duplicate AAssociateACPDU vs ULConnection for( unsigned int index = 0; index < acpdu->GetNumberOfPresentationContextAC(); index++ ){ PresentationContextAC const &pc = acpdu->GetPresentationContextAC(index); inConnection.AddAcceptedPresentationContext(pc); } outWaitingForEvent = false; outRaisedEvent = eEventDoesNotExist;//no event is raised, //wait for the user to try to send some data. return eSta6TransferReady; } //Issue A-ASSOCIATE confirmation (reject) primitive and close transport connection EStateID ULActionAE4::PerformAction(Subject *, ULEvent& , ULConnection& , bool& outWaitingForEvent, EEventID& outRaisedEvent){ outWaitingForEvent = false; outRaisedEvent = eASSOCIATE_RJPDUreceived; return eSta1Idle; } //Issue Transport connection response primitive, start ARTIM timer EStateID ULActionAE5::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent){ //issue response primitive; have to set that up inConnection.GetTimer().Start(); outWaitingForEvent = false; outRaisedEvent = eTransportConnConfirmLocal; return eSta2Open; } //Stop ARTIM timer and if A-ASSOCIATE-RQ acceptable by service-provider: //- issue A-ASSOCIATE indication primitive //Next state: eSta3WaitLocalAssoc //otherwise: //- issue A-ASSOCIATE-RJ-PDU and start ARTIM timer //Next state: eSta13AwaitingClose EStateID ULActionAE6::PerformAction(Subject *, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent){ // we are in a C-MOVE inConnection.GetTimer().Stop(); //have to determine 'acceptability' //this is more server side than client, so it's a bit empty now //we have one server type, a store scp started on a cmove //so, it's defined as acceptable. bool acceptable = true;//for now, always accept if (inEvent.GetPDUs().empty()){ 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; if (acceptable){ rqpdu = dynamic_cast(inEvent.GetPDUs()[0]); if (rqpdu == nullptr){ acceptable = false; } } if (acceptable){ outWaitingForEvent = false;//not waiting, now want to get the //sending of data underway. Have to get info now outRaisedEvent = eAASSOCIATEresponseAccept; TransferSyntaxSub ts1; ts1.SetNameFromUID( UIDs::ImplicitVRLittleEndianDefaultTransferSyntaxforDICOM ); AAssociateACPDU acpdu; assert( rqpdu->GetNumberOfPresentationContext() ); for( unsigned int index = 0; index < rqpdu->GetNumberOfPresentationContext(); index++ ) { // FIXME / HARDCODED We only ever accept Little Endian // FIXME we should check : // rqpdu.GetAbstractSyntax() contains LittleEndian PresentationContextAC pcac1; PresentationContextRQ const &pc = rqpdu->GetPresentationContext(index); //add the presentation context back into the connection, //so later functions will know what's allowed on this connection // BOGUS (MM): //inConnection.AddAcceptedPresentationContext(pc); const uint8_t id = pc.GetPresentationContextID(); std::vector const & tsSet = pc.GetTransferSyntaxes(); std::vector::const_iterator tsitor; // PS 3.8 Table 9-18 PRESENTATION CONTEXT ITEM FIELDS uint8_t result = 4; // transfer-syntaxes-not-supported (provider rejection) for (tsitor = tsSet.begin(); tsitor < tsSet.end(); tsitor++) { //gdcmDebugMacro( "Checking: [" << tsitor->GetName() << "] vs [" << ts1.GetName() << "]" << std::endl ); if (strcmp(tsitor->GetName(), ts1.GetName()) == 0 ) { result = 0; // 0 - acceptance inConnection.SetCStoreTransferSyntax( ts1 ); pcac1.SetTransferSyntax( ts1 ); } } if( result ) { gdcmWarningMacro( "Could not find Implicit or Explicit Little Endian in Response. Giving another try" ); // Okay little endian implicit was not found, this happen sometimes, for eg with DVTk, let's be nice and accept also Explicit TransferSyntaxSub ts2; ts2.SetNameFromUID( UIDs::ExplicitVRLittleEndian ); for (tsitor = tsSet.begin(); tsitor < tsSet.end(); tsitor++) { //gdcmDebugMacro( "Checking: [" << tsitor->GetName() << "] vs [" << ts1.GetName() << "]" << std::endl ); if (strcmp(tsitor->GetName(), ts2.GetName()) == 0 ) { result = 0; // 0 - acceptance inConnection.SetCStoreTransferSyntax( ts2 ); pcac1.SetTransferSyntax( ts2 ); } } } if( result ) { gdcmErrorMacro( "Could not find Implicit or Explicit Little Endian in Response. Giving up" ); } pcac1.SetPresentationContextID( id ); pcac1.SetReason( result ); acpdu.AddPresentationContextAC( pcac1 ); } assert( acpdu.GetNumberOfPresentationContextAC() ); // Init AE-Titles: acpdu.InitFromRQ( *rqpdu ); acpdu.Write( *inConnection.GetProtocol() ); inConnection.GetProtocol()->flush(); return eSta3WaitLocalAssoc; } else { outWaitingForEvent = false; outRaisedEvent = eAASSOCIATEresponseReject; AAssociateRJPDU thePDU; thePDU.Write(*inConnection.GetProtocol()); inConnection.GetProtocol()->flush(); inConnection.GetTimer().Stop(); return eSta13AwaitingClose; } } //Send A-ASSOCIATE-AC PDU EStateID ULActionAE7::PerformAction(Subject *, ULEvent& , ULConnection& , bool& outWaitingForEvent, EEventID& outRaisedEvent) { outWaitingForEvent = true; outRaisedEvent = eEventDoesNotExist; return eSta6TransferReady; } //Send A-ASSOCIATE-RJ PDU and start ARTIM timer EStateID ULActionAE8::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) { AAssociateRJPDU thePDU; thePDU.Write(*inConnection.GetProtocol()); inConnection.GetTimer().Start(); outWaitingForEvent = false; outRaisedEvent = eAASSOCIATEresponseReject; return eSta13AwaitingClose; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULActionAE.h000066400000000000000000000074041412732066400235070ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMULACTIONAE_H #define GDCMULACTIONAE_H #include "gdcmULAction.h" /** This header defines the classes for the AE Actions, Association Establishment Related Actions (Table 9-6 of ps 3.8-2009). Since each class is essentially a placeholder for a function pointer, I'm breaking with having each class have its own file for the sake of brevity of the number of files. */ namespace gdcm { namespace network { //Issue TRANSPORT CONNECT request primitive to local transport service. class ULActionAE1 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Send A-ASSOCIATE-RQ-PDU //Next State: eSta5WaitRemoteAssoc class ULActionAE2 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Issue A-ASSOCIATE confirmation (accept) primitive //Next State: eSta6TransferReady class ULActionAE3 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Issue A-ASSOCIATE confirmation (reject) primitive and close transport connection //Next State: eSta1Idle class ULActionAE4 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Issue Transport connection response primitive, start ARTIM timer //Next State: eSta2Open class ULActionAE5 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Stop ARTIM timer and if A-ASSOCIATE-RQ acceptable by service-provider: //- issue A-ASSOCIATE indication primitive //Next state: eSta3WaitLocalAssoc //otherwise: //- issue A-ASSOCIATE-RJ-PDU and start ARTIM timer //Next state: eSta13AwaitingClose class ULActionAE6 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Send A-ASSOCIATE-AC PDU //Next State: eSta6TransferReady class ULActionAE7 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Send A-ASSOCIATE-RJ PDU and start ARTIM timer //Next State: eSta13AwaitingClose class ULActionAE8 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; } } #endif // GDCMULACTIONAE_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULActionAR.cxx000066400000000000000000000122121412732066400240700ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /* This file contains the implementation for the classes for the AR Actions, Association Release Related Actions (Table 9-8 of ps 3.8-2009). Since each class is essentially a placeholder for a function pointer, I'm breaking with having each class have its own file for the sake of brevity of the number of files. */ #include "gdcmULActionAR.h" #include "gdcmARTIMTimer.h" #include "gdcmAReleaseRQPDU.h" #include "gdcmAReleaseRPPDU.h" #include "gdcmPDataTFPDU.h" namespace gdcm { namespace network { //Send A-RELEASE-RQ-PDU EStateID ULActionAR1::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& outWaitingForEvent, EEventID& ){ AReleaseRQPDU thePDU;//for now, use Matheiu's default values thePDU.Write(*inConnection.GetProtocol()); inConnection.GetProtocol()->flush(); // important outWaitingForEvent = true; return eSta7WaitRelease; } //Issue A-RELEASE indication primitive EStateID ULActionAR2::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent){ outWaitingForEvent = false; outRaisedEvent = eARELEASERequest;//here's the primitive being sent //this is very stupid. //the A-release indication primitive is given to determine whether or not the //server wants to send an a-release, an a-abort, or a pdata pdu. //we just want to send an a-release. //therefore, this function will directly send the release. //ar8 does the same thing, but so far, we have not had that collision yet. AReleaseRPPDU thePDU;//for now, use Matheiu's default values thePDU.Write(*inConnection.GetProtocol()); inConnection.GetProtocol()->flush(); //if we hadn't actually just performed the primitive right here, we should be in sta8 //as it is, we should be in sta13 // return eSta8WaitLocalRelease; return eSta13AwaitingClose; } //Issue A-RELEASE confirmation primitive, and close transport connection EStateID ULActionAR3::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent){ outWaitingForEvent = false; outRaisedEvent = eARELEASERequest; inConnection.StopProtocol(); return eSta1Idle; } //Issue A-RELEASE-RP PDU and start ARTIM timer EStateID ULActionAR4::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent){ AReleaseRPPDU thePDU;//for now, use Matheiu's default values thePDU.Write(*inConnection.GetProtocol()); inConnection.GetProtocol()->flush(); inConnection.GetTimer().Start(); outWaitingForEvent = false; outRaisedEvent = eARELEASERequest; return eSta13AwaitingClose; } //Stop ARTIM timer EStateID ULActionAR5::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& , EEventID& ){ inConnection.GetTimer().Stop(); return eSta1Idle; } //Issue P-DATA indication EStateID ULActionAR6::PerformAction(Subject *, ULEvent& , ULConnection& , bool& outWaitingForEvent, EEventID& outRaisedEvent){ outWaitingForEvent = true; outRaisedEvent = eEventDoesNotExist; return eSta7WaitRelease; } //Issue P-DATA-TF PDU EStateID ULActionAR7::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& , EEventID& ){ assert(0); PDataTFPDU thePDU;//for now, use Matheiu's default values thePDU.Write(*inConnection.GetProtocol()); inConnection.GetProtocol()->flush(); return eSta8WaitLocalRelease; } //Issue A-RELEASE indication (release collision): //- If association-requestor, next state is eSta9ReleaseCollisionRqLocal //- if not, next state is eSta10ReleaseCollisionAc EStateID ULActionAR8::PerformAction(Subject *, ULEvent& , ULConnection& , bool& , EEventID& ){ assert(0); return eSta10ReleaseCollisionAc; } //Send A-RELEASE-RP PDU EStateID ULActionAR9::PerformAction(Subject *, ULEvent& , ULConnection& inConnection, bool& outWaitingForEvent, EEventID& ){ AReleaseRPPDU thePDU;//for now, use Matheiu's default values thePDU.Write(*inConnection.GetProtocol()); inConnection.GetProtocol()->flush(); outWaitingForEvent = true; return eSta11ReleaseCollisionRq; } //Issue A-RELEASE confirmation primitive EStateID ULActionAR10::PerformAction(Subject *, ULEvent& , ULConnection& , bool& outWaitingForEvent, EEventID& outRaisedEvent){ outWaitingForEvent = false; outRaisedEvent = eARELEASEResponse; return eSta12ReleaseCollisionAcLocal; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULActionAR.h000066400000000000000000000102531412732066400235200ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMULACTIONAR_H #define GDCMULACTIONAR_H #include "gdcmULAction.h" /** This header defines the classes for the AR Actions, Association Release Related Actions (Table 9-8 of ps 3.8-2009). Since each class is essentially a placeholder for a function pointer, I'm breaking with having each class have its own file for the sake of brevity of the number of files. */ namespace gdcm { namespace network { //Send A-RELEASE-RQ-PDU //Next State: eSta7WaitRelease class ULActionAR1 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Issue A-RELEASE indication primitive //Next State: eSta8WaitLocalRelease class ULActionAR2 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Issue A-RELEASE confirmation primitive, and close transport connection //Next State: eSta1Idle class ULActionAR3 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Issue A-RELEASE-RP PDU and start ARTIM timer //Next State: eSta13AwaitingClose class ULActionAR4 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Stop ARTIM timer //Next State: eSta1Idle class ULActionAR5 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Issue P-Data indication //Next State: eSta7WaitRelease class ULActionAR6 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Issue P-DATA-TF PDU //Next State: eSta8WaitLocalRelease class ULActionAR7 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Issue A-RELEASE indication (release collision): //- If association-requestor, next state is eSta9ReleaseCollisionRqLocal //- if not, next state is eSta10ReleaseCollisionAc class ULActionAR8 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Send A-RELEASE-RP PDU //Next State: eSta11ReleaseCollisionRq class ULActionAR9 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Issue A-RELEASE confirmation primitive //Next State: eSta12ReleaseCollisionAcLocal class ULActionAR10 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; } } #endif // GDCMULACTIONAR_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULActionDT.cxx000066400000000000000000000217011412732066400241000ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /* This file contains the implementation for the classes for the DT Actions, Data Transfer Related Actions (Table 9-8 of ps 3.8-2009). Since each class is essentially a placeholder for a function pointer, I'm breaking with having each class have its own file for the sake of brevity of the number of files. */ #include "gdcmULActionDT.h" #include "gdcmARTIMTimer.h" #include "gdcmPDataTFPDU.h" #include "gdcmPDataTFPDU.h" #include "gdcmAttribute.h" #include "gdcmProgressEvent.h" #include "gdcmFile.h" #include "gdcmDataSet.h" #include "gdcmAReleaseRPPDU.h" #include "gdcmAAssociateRQPDU.h" #include "gdcmAAssociateACPDU.h" #include "gdcmAReleaseRQPDU.h" #include "gdcmSubject.h" #include //for setting up the local socket namespace gdcm { namespace network { #if USE_PROCESS_INPUT static void process_input(iosockinet& sio) { uint8_t itemtype = 0x0; sio.read( (char*)&itemtype, 1 ); assert( itemtype == 0x1 ); AAssociateRQPDU rqpdu; //rqpdu.SetCallingAETitle( "MOTESCU" ); rqpdu.Read( sio ); rqpdu.Print( std::cout ); //std::cout << "done AAssociateRQPDU !" << std::endl; TransferSyntaxSub ts1; ts1.SetNameFromUID( UIDs::ImplicitVRLittleEndianDefaultTransferSyntaxforDICOM ); AAssociateACPDU acpdu; for( unsigned int index = 0; index < rqpdu.GetNumberOfPresentationContext(); index++ ) { // FIXME / HARDCODED We only ever accept Little Endian // FIXME we should check : // rqpdu.GetAbstractSyntax() contains LittleENdian PresentationContextAC pcac1; PresentationContext const &pc = rqpdu.GetPresentationContext(index); uint8_t id = pc.GetPresentationContextID(); pcac1.SetPresentationContextID( id ); pcac1.SetTransferSyntax( ts1 ); acpdu.AddPresentationContextAC( pcac1 ); } acpdu.Write( sio ); sio.flush(); //std::cout << "done AAssociateACPDU !" << std::endl; sio.read( (char*)&itemtype, 1 ); assert( itemtype == 0x4 ); PDataTFPDU pdata; pdata.Read( sio ); pdata.Print( std::cout ); // pick the first one: size_t n = pdata.GetNumPDVs(); assert( n == 1 ); PresentationDataValue const &input_pdv = pdata.GetPresentationDataValue(0); //std::cout << "done PDataTFPDU 1!" << std::endl; uint8_t messageheader; messageheader = input_pdv.GetMessageHeader(); //std::cout << "Start with MessageHeader : " << (int)messageheader << std::endl; Attribute<0x0,0x800> at = { 0 }; //at.SetFromDataSet( input_pdv.GetDataSet() ); unsigned short commanddatasettype = at.GetValue(); //std::cout << "CommandDataSetType: " << at.GetValue() << std::endl; assert( messageheader == 3 ); // C-STORE if( commanddatasettype == 0 ) { std::ofstream out( "movescu.dcm", std::ios::binary ); int i = 0; do { PDataTFPDU pdata2; pdata2.ReadInto( sio, out ); //pdata2.Print( std::cout ); size_t n2 = pdata.GetNumPDVs(); assert( n2 == 1 ); PresentationDataValue const &pdv = pdata2.GetPresentationDataValue(0); messageheader = pdv.GetMessageHeader(); //std::cout << "---------------- done PDataTFPDU: " << i << std::endl; //std::cout << "---------------- done MessageHeader: " << (int)messageheader << std::endl; ++i; } while( messageheader == 0 ); assert( messageheader == 2 ); // end of data out.close(); PresentationDataValue pdv; pdv.SetPresentationContextID( input_pdv.GetPresentationContextID() ); std::vector inpdvs; inpdvs.push_back( input_pdv ); DataSet ds1 = PresentationDataValue::ConcatenatePDVBlobs( inpdvs ); const DataElement &de1 = ds1.GetDataElement( Tag( 0x0000,0x0002 ) ); const ByteValue *bv1 = de1.GetByteValue(); std::string s1( bv1->GetPointer(), bv1->GetLength() ); const DataElement &de2 = ds1.GetDataElement( Tag( 0x0000,0x1000 ) ); const ByteValue *bv2 = de2.GetByteValue(); std::string s2( bv2->GetPointer(), bv2->GetLength() ); //pdv.MyInit2( s1.c_str(), s2.c_str() ); //std::cout << "Compare:" << std::endl; //input_pdv.Print( std::cout ); //std::cout << "To:" << std::endl; //pdv.Print( std::cout ); PDataTFPDU pdata4; pdata4.AddPresentationDataValue( pdv ); pdata4.Write( sio ); //sio.flush(); } //sio.read( (char*)&itemtype, 1 ); //assert( itemtype == 0x4 ); //AReleaseRQPDU rel0; //rel0.Read( sio ); // send release: AReleaseRPPDU rel; rel.Write( sio ); sio.flush(); //std::cout << "done AReleaseRPPDU!" << std::endl; AReleaseRPPDU rel2; //rel2.Write( sio ); //sio.flush(); } #endif //USE_PROCESS_INPUT //Send P-DATA-TF PDU EStateID ULActionDT1::PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) { std::vector theDataPDUs = inEvent.GetPDUs(); std::vector::const_iterator itor = theDataPDUs.begin(); //they can all be sent at once because of the structure in 3.8 7.6-- pdata //does not wait for a response. double Progress = 0; const double progresstick = 1. / (double)theDataPDUs.size(); for (itor = theDataPDUs.begin(); itor < theDataPDUs.end(); itor++) { PDataTFPDU* dataPDU = dynamic_cast(*itor); if (dataPDU == nullptr) { throw Exception("Data sending event PDU malformed."); } dataPDU->Write(*inConnection.GetProtocol()); Progress += progresstick; ProgressEvent pe; pe.SetProgress( Progress ); s->InvokeEvent( pe ); //if( !inConnection.GetProtocol()->good() ); // { // throw new Exception("Protocol is not good."); // return eStaDoesNotExist; // } inConnection.GetProtocol()->flush(); } std::istream * pStream = inEvent.GetIStream() ; if ( pStream ) { PDataTFPDU* dataPDU = dynamic_cast(theDataPDUs[0]); if (dataPDU == nullptr) { throw Exception("Data sending event PDU malformed."); } uint8_t prescontid = dataPDU->GetPresentationDataValue(0).GetPresentationContextID(); size_t maxpdu = 16378; maxpdu = inConnection.GetMaxPDUSize() - 6; pStream->seekg( 0, std::ios::beg ); pStream->seekg( 0, std::ios::end ); std::streampos len = pStream->tellg(); char * contents = new char [maxpdu]; std::streampos cur = inEvent.GetDataSetPos() ; pStream->seekg( cur ); PresentationDataValue thePDV; PDataTFPDU basePDU ; while( cur < len ) { size_t remaining = std::min( maxpdu , (size_t)(len - cur) ); pStream->read( contents, remaining ); std::string sub( contents, remaining ); std::string UIDString; thePDV.SetPresentationContextID( prescontid ); thePDV.SetBlob( sub ); if( remaining == maxpdu ) thePDV.SetMessageHeader( 0 ); else thePDV.SetMessageHeader( 2 ); cur += remaining; basePDU = PDataTFPDU(); basePDU.AddPresentationDataValue( thePDV ); basePDU.Write(*inConnection.GetProtocol()); Progress += progresstick; ProgressEvent pe; pe.SetProgress( Progress ); s->InvokeEvent( pe ); //if( !inConnection.GetProtocol()->good() ); // { // throw new Exception("Protocol is not good."); // return eStaDoesNotExist; // } inConnection.GetProtocol()->flush(); } delete [] contents ; } // When doing a C-MOVE we receive the Requested DataSet over // another channel (technically this is send to an SCP) // in our case we use another port to receive it. #if USE_PROCESS_INPUT //wait for the user to try to send some data. sockinetbuf sin (sockbuf::sock_stream); sin.bind( 5677 ); //std::cout << "localhost = " << sin.localhost() << std::endl // << "localport = " << sin.localport() << std::endl; sin.listen(); // for(;;) { iosockinet s (sin.accept()); process_input(s); } #endif outWaitingForEvent = true;//wait for a response that the data got there. outRaisedEvent = ePDATArequest; return eSta6TransferReady; } //Send P-DATA indication primitive //for now, does nothing, stops the event loop EStateID ULActionDT2::PerformAction(Subject *, ULEvent& , ULConnection& , bool& outWaitingForEvent, EEventID& outRaisedEvent) { outWaitingForEvent = false; outRaisedEvent = ePDATArequest; return eSta6TransferReady; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULActionDT.h000066400000000000000000000033561412732066400235330ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMULACTIONDT_H #define GDCMULACTIONDT_H #include "gdcmULAction.h" /** This header defines the classes for the DT Actions, Data Transfer Related Actions (Table 9-8 of ps 3.8-2009). Since each class is essentially a placeholder for a function pointer, I'm breaking with having each class have its own file for the sake of brevity of the number of files. */ namespace gdcm { namespace network { //Send P-DATA-TF PDU //Next state: eSta6TransferReady class ULActionDT1 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; //Send P-DATA indication primitive //Next state: eSta6TransferReady class ULActionDT2 : public ULAction { public: EStateID PerformAction(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) override; }; } } #endif // GDCMULACTIONDT_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULBasicCallback.cxx000066400000000000000000000024111412732066400250660ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmULBasicCallback.h" namespace gdcm { namespace network { void ULBasicCallback::HandleDataSet(const DataSet& inDataSet) { mDataSets.push_back(inDataSet); DataSetHandled(); } std::vector const & ULBasicCallback::GetDataSets() const { return mDataSets; } void ULBasicCallback::HandleResponse(const DataSet& inDataSet) { mResponses.push_back(inDataSet); } std::vector const & ULBasicCallback::GetResponses() const { return mResponses; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULBasicCallback.h000066400000000000000000000040461412732066400245210ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMULCONNECTIONBASICCALLBACK_H #define GDCMULCONNECTIONBASICCALLBACK_H #include "gdcmULConnectionCallback.h" #include "gdcmDataSet.h" #include namespace gdcm { namespace network { /** * \brief ULBasicCallback * \details This is the most basic of callbacks for how the ULConnectionManager handles * incoming datasets. DataSets are just concatenated to the mDataSets vector, * and the result can be pulled out of the vector by later code. * Alternatives to this method include progress updates, saving to disk, etc. * This class is NOT THREAD SAFE. Access the dataset vector after the * entire set of datasets has been returned by the ULConnectionManager. */ class GDCM_EXPORT ULBasicCallback : public ULConnectionCallback { std::vector mDataSets; std::vector mResponses; public: ULBasicCallback() = default; ~ULBasicCallback() override = default; //empty, for later inheritance void HandleDataSet(const DataSet& inDataSet) override; void HandleResponse(const DataSet& inDataSet) override; std::vector const & GetDataSets() const; std::vector const & GetResponses() const; }; } // end namespace network } // end namespace gdcm #endif // GDCMULCONNECTIONBASICCALLBACK_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULConnection.cxx000066400000000000000000000223011412732066400245270ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmULConnection.h" #include // std::find #include namespace gdcm { namespace network { ULConnection::ULConnection(const ULConnectionInfo& inConnectInfo) { mCurrentState = eSta1Idle; mSocket = nullptr; mEcho = nullptr; mInfo = inConnectInfo; TransferSyntaxSub ts1; ts1.SetNameFromUID( UIDs::ImplicitVRLittleEndianDefaultTransferSyntaxforDICOM ); SetCStoreTransferSyntax( ts1 ); } ULConnection::~ULConnection() { if (mEcho != nullptr) { delete mEcho; mEcho = nullptr; } if (mSocket != nullptr) { delete mSocket; mSocket = nullptr; } } EStateID ULConnection::GetState() const { return mCurrentState; } void ULConnection::SetState(const EStateID& inState) { mCurrentState = inState; } //echo* ULConnection::GetProtocol(){ std::iostream* ULConnection::GetProtocol() { if (mEcho) { return mEcho; } //be careful-- the socket doesn't get removed when the protocol is stopped, //because then subsequent cstores will break. if (mSocket) { return mSocket; } return nullptr; } ARTIMTimer& ULConnection::GetTimer() { return mTimer; } const ULConnectionInfo &ULConnection::GetConnectionInfo() const { return mInfo; } void ULConnection::SetMaxPDUSize(uint32_t inSize) { mMaxPDUSize = inSize; } uint32_t ULConnection::GetMaxPDUSize() const { return mMaxPDUSize; } std::vector const & ULConnection::GetPresentationContexts() const { return mPresentationContexts; } void ULConnection::SetPresentationContexts( const std::vector& inContexts) { mPresentationContexts.clear(); for( size_t i = 0; i < inContexts.size(); ++i ) { PresentationContext const &in = inContexts[i]; mPresentationContexts.emplace_back(in ); } } void ULConnection::SetPresentationContexts( const std::vector& inContexts) { mPresentationContexts = inContexts; } std::vector & ULConnection::GetAcceptedPresentationContexts() { return mAcceptedPresentationContexts; } std::vector const & ULConnection::GetAcceptedPresentationContexts() const { return mAcceptedPresentationContexts; } void ULConnection::AddAcceptedPresentationContext(const PresentationContextAC& inPC) { mAcceptedPresentationContexts.push_back(inPC); } //given a particular data element, presumably the SOP class, //find the presentation context for that SOP //NOT YET IMPLEMENTED PresentationContextRQ ULConnection::FindContext(const DataElement& ) const { PresentationContextRQ empty; assert( 0 && "TODO" ); return empty; } bool ULConnection::InitializeConnection() { try { echo* p = new echo(protocol::tcp); if (GetConnectionInfo().GetCalledIPPort() == 0) { if (!GetConnectionInfo().GetCalledComputerName().empty()) (*p)->connect(GetConnectionInfo().GetCalledComputerName().c_str()); else (*p)->connect(GetConnectionInfo().GetCalledIPAddress()); } else { if (!GetConnectionInfo().GetCalledComputerName().empty()) (*p)->connect(GetConnectionInfo().GetCalledComputerName().c_str(), GetConnectionInfo().GetCalledIPPort()); } //make sure to convert timeouts to platform appropriate values. (*p)->recvtimeout((int)GetTimer().GetTimeout()); (*p)->sendtimeout((int)GetTimer().GetTimeout()); if (mEcho != nullptr) { delete mEcho; mEcho = nullptr; } if (mSocket != nullptr) { delete mSocket; mSocket = nullptr; } mEcho = p; } catch ( sockerr &err ) { (void)err; //to avoid unreferenced variable warning on release gdcmWarningMacro( "Unable to open connection with exception " << err.what() << std::endl ); return false; } catch (std::exception& ex) { (void)ex; //to avoid unreferenced variable warning on release //unable to establish connection, so break off. gdcmWarningMacro( "Unable to open connection with exception " << ex.what() << std::endl ); return false; } return true; } bool ULConnection::InitializeIncomingConnection() { try { if (mEcho != nullptr) { delete mEcho; mEcho = nullptr; } if (mSocket != nullptr) { delete mSocket; mSocket = nullptr; } sockinetbuf sin (sockbuf::sock_stream); // http://hea-www.harvard.edu/~fine/Tech/addrinuse.html int val = 1; sin.setopt( SO_REUSEADDR, &val, sizeof(val) ); sin.bind( mInfo.GetCalledIPPort() ); //int theRecvTimeout = sin.recvtimeout(60);//(int)GetTimer().GetTimeout()); //int theSendTimeout = sin.sendtimeout(60);//(int)GetTimer().GetTimeout()); sin.listen(); //sin.debug( true ); if (sin.is_readready(60, 0)) { mSocket = new iosockinet(sin.accept()); } else { gdcmDebugMacro( "Call to is_readready failed" ); SetState(eStaDoesNotExist); return false; //no connection here, so have to initialize later. } SetState(eSta2Open); /* if (mSocket != NULL){ delete mSocket; } mSocket = new protocol(); sockinetaddr theAddy(GetConnectionInfo().GetCalledComputerName().c_str(), GetConnectionInfo().GetCalledIPPort()); mSocket->rdbuf()->connect(theAddy); mSocket->rdbuf()->recvtimeout((int)GetTimer().GetTimeout()); mSocket->rdbuf()->sendtimeout((int)GetTimer().GetTimeout()); */ } catch (sockerr& ex) { //unable to establish connection, so break off. (void)ex; //to avoid unreferenced variable warning on release gdcmErrorMacro("Unable to open connection with exception " << ex.what() << " and " << ex.operation() << " on port: " << mInfo.GetCalledIPPort() << std::endl); return false; } catch (std::exception& ex) { //unable to establish connection, so break off. (void)ex; //to avoid unreferenced variable warning on release gdcmErrorMacro("Unable to open connection with exception " << ex.what() << std::endl); return false; } return true; } void ULConnection::StopProtocol() { if (mEcho != nullptr) { delete mEcho; mEcho = nullptr; SetState(eSta1Idle); } else { //don't actually kill the connection, just kill the association. //this is just for a cstorescp initialized by a cmove SetState(eSta2Open); } } const PresentationContextRQ *ULConnection::GetPresentationContextRQByID(uint8_t id) const { // one day ULConnection will actually use a AAssociateRQPDU as internal implementation // for now duplicate code from AAssociateRQPDU::GetPresentationContextFromAbstractSyntax std::vector::const_iterator it = mPresentationContexts.begin(); for( ; it != mPresentationContexts.end(); ++it) { if( it->GetPresentationContextID() == id ) { return &*it; } } return nullptr; } const PresentationContextAC *ULConnection::GetPresentationContextACByID(uint8_t id) const { // one day ULConnection will actually use a AAssociateRQPDU as internal implementation // for now duplicate code from AAssociateRQPDU::GetPresentationContextFromAbstractSyntax std::vector::const_iterator it = mAcceptedPresentationContexts.begin(); for( ; it != mAcceptedPresentationContexts.end(); ++it) { if( it->GetPresentationContextID() == id ) { return &*it; } } return nullptr; } uint8_t ULConnection::GetPresentationContextIDFromPresentationContext(PresentationContextRQ const & pc) const { // one day ULConnection will actually use a AAssociateRQPDU as internal implementation // for now duplicate code from AAssociateRQPDU::GetPresentationContextIDFromAbstractSyntax uint8_t ret = 0; std::vector::const_iterator it = std::find( mPresentationContexts.begin(), mPresentationContexts.end(), pc ); if( it != mPresentationContexts.end() ) { ret = it->GetPresentationContextID(); } assert( ret ); return ret; } void ULConnection::SetCStoreTransferSyntax( TransferSyntaxSub const & ts ) { cstorets = ts; } TransferSyntaxSub const & ULConnection::GetCStoreTransferSyntax( ) const { TransferSyntaxSub ts1; ts1.SetNameFromUID( UIDs::ImplicitVRLittleEndianDefaultTransferSyntaxforDICOM ); TransferSyntaxSub ts2; ts2.SetNameFromUID( UIDs::ExplicitVRLittleEndian ); assert( strcmp(cstorets.GetName(), ts1.GetName()) == 0 || strcmp(cstorets.GetName(), ts2.GetName()) == 0 ); return cstorets; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULConnection.h000066400000000000000000000124441412732066400241630ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMULCONNECTION_H #define GDCMULCONNECTION_H #include "gdcmNetworkStateID.h" #include "gdcmARTIMTimer.h" #include "gdcmULConnectionInfo.h" #include "gdcmPresentationContextRQ.h" #include "gdcmDataElement.h" #include "gdcmPresentationContextAC.h" #include "gdcmPresentationContext.h" class iosockinet; class echo; namespace gdcm{ namespace network{ /** * \brief ULConnection * \details This is the class that contains the socket to another machine, and passes * data through itself, as well as maintaining a sense of state. * * The ULConnectionManager tells the ULConnection what data can actually be * sent. * * This class is done this way so that it can be eventually be replaced with a * ULSecureConnection, if such a protocol is warranted, so that all data that * passes through can be managed through a secure connection. For now, this * class provides a simple pass-through mechanism to the socket itself. * * So, for instance, a gdcm object will be passes to this object, and it will * then get passed along the connection, if that connection is in the proper * state to do so. * * For right now, this class is not directly intended to be inherited from, but * the potential for future ULSecureConnection warrants the addition, rather * than having everything be managed from within the ULConnectionManager (or * this class) without a wrapper. * */ class GDCM_EXPORT ULConnection { ULConnectionInfo mInfo; //this is a dirty dirty hack //but to establish an outgoing connection (scu), we need the echo service //to establish incoming, we just need a port and localhost, so an iosockinet works while an //echo would fail (probably because one already exists) echo* mEcho; iosockinet* mSocket;//of the three protocols offered by socket++-- echo, smtp, and ftp-- //echo most closely matches what the DICOM standard describes as a network connection ARTIMTimer mTimer; EStateID mCurrentState; std::vector mPresentationContexts; //this is our list of presentation contexts of what we can send uint32_t mMaxPDUSize; std::vector mAcceptedPresentationContexts;//these come back from the server //and tell us what can be sent over this connection TransferSyntaxSub cstorets; friend class ULActionAE6; void SetCStoreTransferSyntax( TransferSyntaxSub const & ts ); friend class ULConnectionManager; TransferSyntaxSub const & GetCStoreTransferSyntax( ) const; public: ULConnection(const ULConnectionInfo& inUserInformation); //destructors are virtual to prevent memory leaks by inherited classes virtual ~ULConnection(); EStateID GetState() const; void SetState(const EStateID& inState);//must be able to update state... //echo* GetProtocol(); std::iostream* GetProtocol(); void StopProtocol(); ARTIMTimer& GetTimer(); const ULConnectionInfo &GetConnectionInfo() const; //when the connection is first associated, the connection is told //the max packet/PDU size and the way in which to present data //(presentation contexts, etc). Store that here. void SetMaxPDUSize(uint32_t inSize); uint32_t GetMaxPDUSize() const; const PresentationContextAC *GetPresentationContextACByID(uint8_t id) const; const PresentationContextRQ *GetPresentationContextRQByID(uint8_t id) const; /// return 0 upon error uint8_t GetPresentationContextIDFromPresentationContext(PresentationContextRQ const & pc) const; std::vector const & GetPresentationContexts() const; void SetPresentationContexts(const std::vector& inContexts); void SetPresentationContexts(const std::vector& inContexts); //given a particular data element, presumably the SOP class, //find the presentation context for that SOP //NOT YET IMPLEMENTED PresentationContextRQ FindContext(const DataElement& de) const; std::vector const & GetAcceptedPresentationContexts() const; std::vector & GetAcceptedPresentationContexts(); void AddAcceptedPresentationContext(const PresentationContextAC& inPC); /// used to establish scu connections bool InitializeConnection(); /// used to establish scp connections bool InitializeIncomingConnection(); ULConnection(const ULConnection&) = delete; void operator=(const ULConnection&) = delete; }; } } #endif // ULCONNECTION_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULConnectionCallback.h000066400000000000000000000047301412732066400255770ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMULCONNECTIONCALLBACK_H #define GDCMULCONNECTIONCALLBACK_H #include "gdcmTypes.h" //to be able to export the class namespace gdcm { class DataSet; namespace network { ///When a dataset comes back from a query/move/etc, the result can either be ///stored entirely in memory, or could be stored on disk. This class provides ///a mechanism to indicate what the ULConnectionManager should do with datasets ///that are produced through query results. ///The ULConnectionManager will call the HandleDataSet function during the course ///of receiving datasets. Particular implementations should fill in what that ///function does, including updating progress, etc. ///NOTE: since cmove requires that multiple event loops be employed, ///the callback function MUST set mHandledDataSet to true. ///otherwise, the cmove event loop handler will not know data was received, and ///proceed to end the loop prematurely. class GDCM_EXPORT ULConnectionCallback { bool mHandledDataSet; protected: bool mImplicit; //inherited callbacks MUST call this function for the cmove loop to work properly void DataSetHandled() { mHandledDataSet = true; } public: ULConnectionCallback():mHandledDataSet(false),mImplicit(true){} virtual ~ULConnectionCallback() = default; //placeholder for inherited objects virtual void HandleDataSet(const DataSet& inDataSet) = 0; virtual void HandleResponse(const DataSet& inDataSet) = 0; bool DataSetHandles() const { return mHandledDataSet; } void ResetHandledDataSet() { mHandledDataSet = false; } void SetImplicitFlag( const bool imp ) { mImplicit = imp; } }; } } #endif //GDCMULCONNECTIONCALLBACK_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULConnectionInfo.cxx000066400000000000000000000071461412732066400253550ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ //this class contains all the information about a particular connection //as established by the user. That is, it's: // User Information // Calling AE Title // Called AE Title // IP address/computer name // IP Port //A connection must be established with this information, that's subsequently //placed into various primitives for actual communication. #include "gdcmULConnectionInfo.h" #include "gdcmAAssociateRQPDU.h" #include //for setting up the local socket #if defined(_WIN32) #else #include #include #include #include #endif namespace gdcm { namespace network { ULConnectionInfo::ULConnectionInfo() = default; //it is possible to misinitialize this object, so //have it return false if something breaks (ie, given AEs are bigger than 16 characters, //no name or IP address). bool ULConnectionInfo::Initialize(UserInformation const & inUserInformation, const char *inCalledAETitle, const char *inCallingAETitle, unsigned long inCalledIPAddress, int inCalledIPPort, std::string inCalledComputerName) { if (inCalledIPAddress == 0 && inCalledComputerName.empty()){ return false; } assert( inCalledAETitle ); assert( inCallingAETitle ); assert( AAssociateRQPDU::IsAETitleValid( inCalledAETitle ) ); assert( AAssociateRQPDU::IsAETitleValid( inCallingAETitle ) ); const size_t lcalled = strlen( inCalledAETitle ); const size_t lcalling = strlen( inCallingAETitle ); mCalledAETitle = std::string(inCalledAETitle, lcalled > 16 ? 16 : lcalled ); mCallingAETitle = std::string(inCallingAETitle, lcalling > 16 ? 16 : lcalling ); mCalledComputerName = inCalledComputerName; mCalledIPPort = inCalledIPPort; mCalledIPAddress = inCalledIPAddress; //test to see if the given computer name is actually an IP address if (mCalledIPAddress == 0 && !mCalledComputerName.empty()){ mCalledIPAddress = inet_addr(mCalledComputerName.c_str()); // if (mCalledIPAddress != 0) // mCalledComputerName = ""; } //mUserInformation = inUserInformation; (void)inUserInformation; return true; } //UserInformation ULConnectionInfo::GetUserInformation() const{ // return mUserInformation; //} const char* ULConnectionInfo::GetCalledAETitle() const{ return mCalledAETitle.c_str(); } const char* ULConnectionInfo::GetCallingAETitle() const{ return mCallingAETitle.c_str(); } unsigned long ULConnectionInfo::GetCalledIPAddress() const{ return mCalledIPAddress; } int ULConnectionInfo::GetCalledIPPort() const{ return mCalledIPPort; } std::string ULConnectionInfo::GetCalledComputerName() const{ return mCalledComputerName; } void ULConnectionInfo::SetMaxPDULength(unsigned long inMaxPDULength){ mMaxPDULength = inMaxPDULength; } unsigned long ULConnectionInfo::GetMaxPDULength() const{ return mMaxPDULength; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULConnectionInfo.h000066400000000000000000000051631412732066400247770ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMULCONNECTIONINFO_H #define GDCMULCONNECTIONINFO_H #include "gdcmUserInformation.h" #include namespace gdcm{ namespace network { /** * \brief ULConnectionInfo * \details this class contains all the information about a particular connection * as established by the user. That is, it's: * User Information * Calling AE Title * Called AE Title * IP address/computer name * IP Port * A connection must be established with this information, that's subsequently * placed into various primitives for actual communication. */ class ULConnectionInfo { UserInformation mUserInformation; std::string mCalledAETitle; std::string mCallingAETitle; unsigned long mCalledIPAddress; int mCalledIPPort; std::string mCalledComputerName; //either the IP or the name has to be filled in unsigned long mMaxPDULength; public: ULConnectionInfo(); //it is possible to misinitialize this object, so //have it return false if something breaks (ie, given AEs are bigger than 16 characters, //no name or IP address). bool Initialize(UserInformation const &inUserInformation, const char *inCalledAETitle, const char *inCallingAETitle, unsigned long inCalledIPAddress, int inCalledIPPort, std::string inCalledComputerName); //UserInformation GetUserInformation() const; const char* GetCalledAETitle() const; const char* GetCallingAETitle() const; unsigned long GetCalledIPAddress() const; int GetCalledIPPort() const; std::string GetCalledComputerName() const; //CStore needs to know the max pdu length, so the value gets initialized //when a cstore connection is established (but not for the others). void SetMaxPDULength(unsigned long inMaxPDULength); unsigned long GetMaxPDULength() const; }; } } #endif //GDCMULCONNECTIONINFO_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULConnectionManager.cxx000066400000000000000000001461351412732066400260360ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmULConnectionManager.h" #include "gdcmUserInformation.h" #include "gdcmULEvent.h" #include "gdcmPDUFactory.h" #include "gdcmReader.h" #include "gdcmAAssociateRQPDU.h" #include "gdcmAttribute.h" #include "gdcmBaseRootQuery.h" #include "gdcmDataSetEvent.h" #include "gdcmAReleaseRPPDU.h" #include "gdcmULBasicCallback.h" #include #include //for setting up the local socket #include "gdcmTrace.h" #include "gdcmPrinter.h" namespace gdcm { namespace network { ULConnectionManager::ULConnectionManager() { mConnection = nullptr; mSecondaryConnection = nullptr; } ULConnectionManager::~ULConnectionManager() { if (mConnection != nullptr) { delete mConnection; mConnection = nullptr; } if (mSecondaryConnection != nullptr) { delete mSecondaryConnection; mSecondaryConnection = nullptr; } } bool ULConnectionManager::EstablishConnection(const std::string& inAETitle, const std::string& inConnectAETitle, const std::string& inComputerName, long inIPAddress, unsigned short inConnectPort, double inTimeout, std::vector const & pcVector) { //generate a ULConnectionInfo object UserInformation userInfo; ULConnectionInfo connectInfo; if (inConnectAETitle.size() > 16) return false;//too long an AETitle, probably need better failure message if (inAETitle.size() > 16) return false; //as above if (!connectInfo.Initialize(userInfo, inConnectAETitle.c_str(), inAETitle.c_str(), inIPAddress, inConnectPort, inComputerName)) { return false; } if (mConnection != nullptr) { 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. // if one push_pack // (1, Secondary) // (1, Verification) // Then the last one is preferred (DCMTK 3.5.5) // The following only works for C-STORE / C-ECHO // however it does not make much sense to add a lot of abstract syntax // when doing only C-ECHO. // FIXME is there a way to know here if we are in C-ECHO ? //there is now! //the presentation context will now be part of the connection, so that this //initialization for the association-rq will use parameters from the connection #if 0 AbstractSyntax as; std::vector pcVector; PresentationContextRQ pc; TransferSyntaxSub ts; ts.SetNameFromUID( UIDs::ImplicitVRLittleEndianDefaultTransferSyntaxforDICOM ); pc.AddTransferSyntax( ts ); ts.SetNameFromUID( UIDs::ExplicitVRLittleEndian ); //ts.SetNameFromUID( UIDs::JPEGLosslessNonHierarchicalFirstOrderPredictionProcess14SelectionValue1DefaultTransferSyntaxforLosslessJPEGImageCompression); //pc.AddTransferSyntax( ts ); // we do not support explicit (mm) switch (inConnectionType){ case eEcho: pc.SetPresentationContextID( eVerificationSOPClass ); as.SetNameFromUID( UIDs::VerificationSOPClass ); pc.SetAbstractSyntax( as ); pcVector.push_back(pc); break; case eFind: pc.SetPresentationContextID( ePatientRootQueryRetrieveInformationModelFIND ); as.SetNameFromUID( UIDs::PatientRootQueryRetrieveInformationModelFIND ); pc.SetAbstractSyntax( as ); pcVector.push_back(pc); pc.SetPresentationContextID(eStudyRootQueryRetrieveInformationModelFIND ); as.SetNameFromUID( UIDs::StudyRootQueryRetrieveInformationModelFIND ); pc.SetAbstractSyntax( as ); pcVector.push_back(pc); pc.SetPresentationContextID( ePatientStudyOnlyQueryRetrieveInformationModelFINDRetired ); as.SetNameFromUID( UIDs::PatientStudyOnlyQueryRetrieveInformationModelFINDRetired ); pc.SetAbstractSyntax( as ); pcVector.push_back(pc); pc.SetPresentationContextID( eModalityWorklistInformationModelFIND ); as.SetNameFromUID( UIDs::ModalityWorklistInformationModelFIND ); pc.SetAbstractSyntax( as ); pcVector.push_back(pc); pc.SetPresentationContextID( eGeneralPurposeWorklistInformationModelFIND ); as.SetNameFromUID( UIDs::GeneralPurposeWorklistInformationModelFIND ); pc.SetAbstractSyntax( as ); pcVector.push_back(pc); break; //our spec does not require C-GET support // case eGet: // break; /* case eMove: // should we also send stuff from FIND ? // E: Move PresCtx but no Find (accepting for now) pc.SetPresentationContextID( ePatientRootQueryRetrieveInformationModelFIND ); as.SetNameFromUID( UIDs::PatientRootQueryRetrieveInformationModelFIND ); pc.SetAbstractSyntax( as ); pcVector.push_back(pc); // move pc.SetPresentationContextID( ePatientRootQueryRetrieveInformationModelMOVE ); as.SetNameFromUID( UIDs::PatientRootQueryRetrieveInformationModelMOVE ); pc.SetAbstractSyntax( as ); pcVector.push_back(pc); pc.SetPresentationContextID( eStudyRootQueryRetrieveInformationModelFIND ); as.SetNameFromUID( UIDs::StudyRootQueryRetrieveInformationModelFIND ); pc.SetAbstractSyntax( as ); pcVector.push_back(pc); pc.SetPresentationContextID( eStudyRootQueryRetrieveInformationModelMOVE ); as.SetNameFromUID( UIDs::StudyRootQueryRetrieveInformationModelMOVE ); pc.SetAbstractSyntax( as ); pcVector.push_back(pc); break;*/ case eStore: std::string uidName; pc.SetPresentationContextID( PresentationContextRQ::AssignPresentationContextID(inDS, uidName) ); if (pc.GetPresentationContextID() != eVerificationSOPClass){ as.SetNameFromUIDString( uidName ); pc.SetAbstractSyntax( as ); pcVector.push_back(pc); } break; } if (pcVector.empty()){ gdcmWarningMacro("Unable to establish presentation context; ensure that dataset has tags 0x8,0x16 and 0x8,0x18 defined." <SetPresentationContexts(pcVector); //now, try to establish a connection by starting the transition table and the event loop. //here's the thing //if there's nothing on the event loop, assume that it's done & the function can exit. //otherwise, keep rolling the event loop ULEvent theEvent(eAASSOCIATERequestLocalUser, nullptr); //no callback, assume that no data is transferred back, because there shouldn't be any EStateID theState = RunEventLoop(theEvent, mConnection, nullptr, false); if(theState != eSta6TransferReady) { std::vector const & thePDUs = theEvent.GetPDUs(); for( std::vector::const_iterator itor = thePDUs.begin(); itor != thePDUs.end(); itor++) { //assert(*itor); if (*itor == nullptr) continue; //can have a nulled pdu, apparently (*itor)->Print(Trace::GetErrorStream()); } } else if (Trace::GetDebugFlag()) { std::vector const & thePDUs = theEvent.GetPDUs(); for( std::vector::const_iterator itor = thePDUs.begin(); itor != thePDUs.end(); itor++) { assert(*itor); if (*itor == nullptr) continue; //can have a nulled pdu, apparently (*itor)->Print(Trace::GetDebugStream()); } } return (theState == eSta6TransferReady);//ie, finished the transitions } /// returns true for above reasons, but contains the special 'move' port bool ULConnectionManager::EstablishConnectionMove(const std::string& inAETitle, const std::string& inConnectAETitle, const std::string& inComputerName, long inIPAddress, uint16_t inConnectPort, double inTimeout, uint16_t inReturnPort, std::vector const & pcVector) { gdcmDebugMacro( "Start EstablishConnectionMove" ); //generate a ULConnectionInfo object UserInformation userInfo; ULConnectionInfo connectInfo; if (inConnectAETitle.size() > 16) return false;//too long an AETitle, probably need better failure message if (inAETitle.size() > 16) return false; //as above if (!connectInfo.Initialize(userInfo,inAETitle.c_str(), inConnectAETitle.c_str(), inIPAddress, inReturnPort, inComputerName)) { gdcmDebugMacro( "Could not Initialize connectInfo" ); return false; } gdcmDebugMacro( "SCP: First connection established on port " << inReturnPort ); if (mSecondaryConnection != nullptr) { gdcmDebugMacro( "delete mSecondaryConnection" ); delete mSecondaryConnection; } mSecondaryConnection = new ULConnection(connectInfo); mSecondaryConnection->GetTimer().SetTimeout(inTimeout); //generate a ULConnectionInfo object UserInformation userInfo2; ULConnectionInfo connectInfo2; if (inConnectAETitle.size() > 16) return false;//too long an AETitle, probably need better failure message if (inAETitle.size() > 16) return false; //as above if (!connectInfo2.Initialize(userInfo2, inConnectAETitle.c_str(), inAETitle.c_str(), inIPAddress, inConnectPort, inComputerName)) { gdcmDebugMacro( "Could not Initialize connectInfo2" ); return false; } gdcmDebugMacro( "SCU: Second connection established on port " << inConnectPort ); if (mConnection!= nullptr) { gdcmDebugMacro( "delete mConnection" ); delete mConnection; } mConnection = new ULConnection(connectInfo2); mConnection->GetTimer().SetTimeout(inTimeout); // Warning PresentationContextID is important // this is a sort of uniq key used by the recevier. Eg. // if one push_pack // (1, Secondary) // (1, Verification) // Then the last one is preferred (DCMTK 3.5.5) // The following only works for C-STORE / C-ECHO // however it does not make much sense to add a lot of abstract syntax // when doing only C-ECHO. // FIXME is there a way to know here if we are in C-ECHO ? //there is now! //the presentation context will now be part of the connection, so that this //initialization for the association-rq will use parameters from the connection AbstractSyntax as; #if 0 std::vector pcVector; PresentationContextRQ pc; TransferSyntaxSub ts; ts.SetNameFromUID( UIDs::ImplicitVRLittleEndianDefaultTransferSyntaxforDICOM ); pc.AddTransferSyntax( ts ); ts.SetNameFromUID( UIDs::ExplicitVRLittleEndian ); //pc.AddTransferSyntax( ts ); // we do not support explicit (mm) // should we also send stuff from FIND ? // E: Move PresCtx but no Find (accepting for now) pc.SetPresentationContextID( ePatientRootQueryRetrieveInformationModelFIND ); as.SetNameFromUID( UIDs::PatientRootQueryRetrieveInformationModelFIND ); pc.SetAbstractSyntax( as ); pcVector.push_back(pc); // move pc.SetPresentationContextID( ePatientRootQueryRetrieveInformationModelMOVE ); as.SetNameFromUID( UIDs::PatientRootQueryRetrieveInformationModelMOVE ); pc.SetAbstractSyntax( as ); pcVector.push_back(pc); pc.SetPresentationContextID( eStudyRootQueryRetrieveInformationModelFIND ); as.SetNameFromUID( UIDs::StudyRootQueryRetrieveInformationModelFIND ); pc.SetAbstractSyntax( as ); pcVector.push_back(pc); pc.SetPresentationContextID( eStudyRootQueryRetrieveInformationModelMOVE ); as.SetNameFromUID( UIDs::StudyRootQueryRetrieveInformationModelMOVE ); pc.SetAbstractSyntax( as ); pcVector.push_back(pc); #endif mConnection->SetPresentationContexts(pcVector); //now, try to establish a connection by starting the transition table and the event loop. //here's the thing //if there's nothing on the event loop, assume that it's done & the function can exit. //otherwise, keep rolling the event loop ULEvent theEvent(eAASSOCIATERequestLocalUser, nullptr); std::vector empty; //No data should be returned when connections are established EStateID theState = RunEventLoop(theEvent, mConnection, nullptr, false); if (Trace::GetDebugFlag()) { std::vector thePDUs = theEvent.GetPDUs(); std::vector::iterator itor; for (itor = thePDUs.begin(); itor != thePDUs.end(); itor++) { if (*itor == NULL) continue; //can have a nulled pdu, apparently (*itor)->Print(Trace::GetStream()); } } return (theState == eSta6TransferReady);//ie, finished the transitions } //send the Data PDU associated with Echo (ie, a default DataPDU) //this lets the user confirm that the connection is alive. //the user should look to cout to see the response of the echo command std::vector ULConnectionManager::SendEcho(){ std::vector theDataPDU = PDUFactory::CreateCEchoPDU(*mConnection);//pass NULL for C-Echo ULEvent theEvent(ePDATArequest, theDataPDU); EStateID theState = RunEventLoop(theEvent, mConnection, nullptr, false); //theEvent should contain the PDU for the echo! if (theState == eSta6TransferReady){//ie, finished the transitions return PDUFactory::GetPDVs(theEvent.GetPDUs()); } else { std::vector empty; return empty; } } std::vector ULConnectionManager::SendMove(const BaseRootQuery* inRootQuery) { ULBasicCallback theCallback; SendMove(inRootQuery, &theCallback); return theCallback.GetDataSets(); } bool ULConnectionManager::SendMove(const BaseRootQuery* inRootQuery, ULConnectionCallback* inCallback) { if (mConnection == nullptr) { gdcmErrorMacro( "mConnection is NULL" ); return false; } std::vector theDataPDU = PDUFactory::CreateCMovePDU( *mConnection, inRootQuery ); ULEvent theEvent(ePDATArequest, theDataPDU); EStateID stateid = RunMoveEventLoop(theEvent, inCallback); gdcmDebugMacro( "Final StateID: " << (int) stateid ); return stateid == gdcm::network::eSta6TransferReady; } std::vector ULConnectionManager::SendFind(const BaseRootQuery* inRootQuery) { ULBasicCallback theCallback; SendFind(inRootQuery, &theCallback); return theCallback.GetDataSets(); } void ULConnectionManager::SendFind(const BaseRootQuery* inRootQuery, ULConnectionCallback* inCallback) { if (mConnection == nullptr) { return; } std::vector theDataPDU = PDUFactory::CreateCFindPDU( *mConnection, inRootQuery ); ULEvent theEvent(ePDATArequest, theDataPDU); RunEventLoop(theEvent, mConnection, inCallback, false); } std::vector ULConnectionManager::SendStore(const File &file, std::istream * pStream /*= NULL*/, std::streampos dataSetOffset/*=0*/ ) { ULBasicCallback theCallback; SendStore(file, &theCallback, pStream, dataSetOffset ); return theCallback.GetResponses(); } void ULConnectionManager::SendStore(const File & file, ULConnectionCallback* inCallback, std::istream * pStream /*= NULL*/, std::streampos dataSetOffset/*=0*/ ) { if (mConnection == nullptr) { return; } bool writeDataSet = pStream == nullptr ; std::vector theDataPDU = PDUFactory::CreateCStoreRQPDU(*mConnection, file, writeDataSet); const DataSet* inDataSet = &file.GetDataSet(); DataSetEvent dse( inDataSet ); this->InvokeEvent( dse ); ULEvent theEvent(ePDATArequest, theDataPDU, pStream, dataSetOffset ); EStateID theState = RunEventLoop(theEvent, mConnection, inCallback, false); assert( theState == eSta6TransferReady || theState == eStaDoesNotExist ); (void)theState; } std::vector ULConnectionManager::SendNEventReport (const BaseQuery* inQuery) { ULBasicCallback theCallback; SendNEventReport(inQuery, &theCallback); return theCallback.GetDataSets(); } void ULConnectionManager::SendNEventReport (const BaseQuery* inQuery, ULConnectionCallback* inCallback) { if (mConnection == nullptr) { return; } std::vector theDataPDU = PDUFactory::CreateNEventReportPDU( *mConnection, inQuery ); ULEvent theEvent(ePDATArequest, theDataPDU); RunEventLoop(theEvent, mConnection, inCallback, false); } std::vector ULConnectionManager::SendNGet (const BaseQuery* inQuery) { ULBasicCallback theCallback; SendNGet(inQuery, &theCallback); return theCallback.GetDataSets(); } void ULConnectionManager::SendNGet (const BaseQuery* inQuery, ULConnectionCallback* inCallback) { if (mConnection == nullptr) { return; } std::vector theDataPDU = PDUFactory::CreateNGetPDU( *mConnection, inQuery ); ULEvent theEvent(ePDATArequest, theDataPDU); RunEventLoop(theEvent, mConnection, inCallback, false); } std::vector ULConnectionManager::SendNSet (const BaseQuery* inQuery) { ULBasicCallback theCallback; SendNSet(inQuery, &theCallback); return theCallback.GetDataSets(); } void ULConnectionManager::SendNSet (const BaseQuery* inQuery, ULConnectionCallback* inCallback) { if (mConnection == nullptr) { return; } std::vector theDataPDU = PDUFactory::CreateNSetPDU( *mConnection, inQuery ); ULEvent theEvent(ePDATArequest, theDataPDU); RunEventLoop(theEvent, mConnection, inCallback, false); } std::vector ULConnectionManager::SendNAction (const BaseQuery* inQuery) { ULBasicCallback theCallback; SendNAction(inQuery, &theCallback); return theCallback.GetDataSets(); } void ULConnectionManager::SendNAction (const BaseQuery* inQuery, ULConnectionCallback* inCallback) { if (mConnection == nullptr) { return; } std::vector theDataPDU = PDUFactory::CreateNActionPDU( *mConnection, inQuery ); ULEvent theEvent(ePDATArequest, theDataPDU); RunEventLoop(theEvent, mConnection, inCallback, false); } std::vector ULConnectionManager::SendNCreate (const BaseQuery* inQuery) { ULBasicCallback theCallback; SendNCreate(inQuery, &theCallback); return theCallback.GetDataSets(); } void ULConnectionManager::SendNCreate (const BaseQuery* inQuery, ULConnectionCallback* inCallback) { if (mConnection == nullptr) { return; } std::vector theDataPDU = PDUFactory::CreateNCreatePDU( *mConnection, inQuery ); ULEvent theEvent(ePDATArequest, theDataPDU); RunEventLoop(theEvent, mConnection, inCallback, false); } std::vector ULConnectionManager::SendNDelete (const BaseQuery* inQuery) { ULBasicCallback theCallback; SendNDelete(inQuery, &theCallback); return theCallback.GetDataSets(); } void ULConnectionManager::SendNDelete (const BaseQuery* inQuery, ULConnectionCallback* inCallback) { if (mConnection == nullptr) { return; } std::vector theDataPDU = PDUFactory::CreateNDeletePDU( *mConnection, inQuery ); ULEvent theEvent(ePDATArequest, theDataPDU); RunEventLoop(theEvent, mConnection, inCallback, false); } bool ULConnectionManager::BreakConnection(const double& inTimeOut){ std::vector theResult; if (mConnection == nullptr){ return false; } BasePDU* thePDU = PDUFactory::ConstructReleasePDU(); ULEvent theEvent(eARELEASERequest, thePDU); mConnection->GetTimer().SetTimeout(inTimeOut); //assume no data coming back when dying, no need for callback EStateID theState = RunEventLoop(theEvent, mConnection, nullptr, false); return (theState == eSta1Idle);//ie, finished the transitions } void ULConnectionManager::BreakConnectionNow(){ BasePDU* thePDU = PDUFactory::ConstructAbortPDU(); ULEvent theEvent(eAABORTRequest, thePDU); //assume no data coming back when dying, no need for callback EStateID theState = RunEventLoop(theEvent, mConnection, nullptr, false); (void)theState; } //event handler loop for move-- will interweave the two event loops, //one for storescp and the other for movescu. Perhaps complicated, but //avoids starting a second process. EStateID ULConnectionManager::RunMoveEventLoop(ULEvent& currentEvent, ULConnectionCallback* inCallback){ gdcmDebugMacro( "Start RunMoveEventLoop" ); EStateID theState = eStaDoesNotExist; bool waitingForEvent; EEventID raisedEvent; bool receivingData = false; bool justWaiting = false; //when receiving data from a find, etc, then justWaiting is true and only receiving is done //eventually, could add cancel into the mix... but that would be through a callback or something similar do { gdcmDebugMacro( "Before mTransitions.HandleEvent" ); if (!justWaiting){ mTransitions.HandleEvent(this,currentEvent, *mConnection, waitingForEvent, raisedEvent); } theState = mConnection->GetState(); std::istream &is = *mConnection->GetProtocol(); //std::ostream &os = *mConnection->GetProtocol(); //When doing a C-MOVE we receive the Requested DataSet over //another channel (technically this is send to an SCP) //in our case we use another port to receive it. EStateID theCStoreStateID = eSta6TransferReady; bool secondConnectionEstablished = false; gdcmDebugMacro( "Before mSecondaryConnection.GetProtocol" ); if (mSecondaryConnection->GetProtocol() == nullptr){ //establish the connection //can fail if is_readready doesn't return true, ie, the connection //wasn't opened on the other side because the other side isn't sending data yet //for whatever reason (maybe there's nothing to get?) gdcmDebugMacro( "Before mSecondaryConnection.InitializeIncomingConnection" ); secondConnectionEstablished = mSecondaryConnection->InitializeIncomingConnection(); } gdcmDebugMacro( "After mSecondaryConnection.InitializeIncomingConnection: " << "secondConnectionEstablished=" << secondConnectionEstablished << " GetState() =" << (int)mSecondaryConnection->GetState() ); if (!secondConnectionEstablished ) { gdcmErrorMacro( "Could not establish 2nd connection" ); //return eStaDoesNotExist; } if (secondConnectionEstablished && (mSecondaryConnection->GetState()== eSta1Idle || mSecondaryConnection->GetState() == eSta2Open)){ ULEvent theCStoreEvent(eEventDoesNotExist, nullptr);//have to fill this in, we're in passive mode now theCStoreStateID = RunEventLoop(theCStoreEvent, mSecondaryConnection, inCallback, true); } gdcmDebugMacro( "After mSecondaryConnection / RunEventLoop: " << (int)theCStoreStateID ); //just as for the regular event loop, but we have to alternate between the connections. //it may be that nothing comes back over the is connection, but lots over the //isSCP connection. So, if is fails, meh. But if isSCP fails, that's not so meh. //we care only about the datasets coming back from isSCP, ultimately, though the datasets //from is will contain progress info. std::vector incomingPDUs; if (waitingForEvent){ while (waitingForEvent) {//loop for reading in the events that come down the wire uint8_t itemtype = 0x0; gdcmDebugMacro( "Waiting for ItemType (#2)" ); is.read( (char*)&itemtype, 1 ); BasePDU* thePDU = PDUFactory::ConstructPDU(itemtype); if (thePDU != nullptr) { incomingPDUs.push_back(thePDU); thePDU->Read(is); gdcmDebugMacro("PDU code: " << static_cast(itemtype) << std::endl); if (Trace::GetDebugFlag()) { thePDU->Print(Trace::GetStream()); } if (thePDU->IsLastFragment()) waitingForEvent = false; } else { waitingForEvent = false; //because no PDU means not waiting anymore } } //now, we have to figure out the event that just happened based on the PDU that was received. if (!incomingPDUs.empty()) { currentEvent.SetEvent(PDUFactory::DetermineEventByPDU(incomingPDUs[0])); currentEvent.SetPDU(incomingPDUs); if (mConnection->GetTimer().GetHasExpired()) { currentEvent.SetEvent(eARTIMTimerExpired); } if (theState == eSta6TransferReady){//ie, finished the transitions //with find, the results now come down the wire. //the pdu we already have from the event will tell us how many to expect. uint32_t pendingDE1, pendingDE2, success, theVal; pendingDE1 = 0xff01; pendingDE2 = 0xff00; success = 0x0000; theVal = pendingDE1; uint32_t theNumLeft = 0; // the number of pending sub operations left. //so here's the thing: dcmtk responds with 'success' as it first cmove rsp //which is retarded and, I think, wrong. However, dcm4chee responds with 'pending' //so, we look either for pending, or for the number of operations left // (tag 0000, 1020) if the value is success, and that number should be 0. DataSet theRSP = PresentationDataValue::ConcatenatePDVBlobs(PDUFactory::GetPDVs(currentEvent.GetPDUs())); if (Trace::GetDebugFlag()) { Printer thePrinter; Trace::GetStream() << "Response: " << std::endl; thePrinter.PrintDataSet(theRSP, Trace::GetStream()); Trace::GetStream() << std::endl; } if (theRSP.FindDataElement(Tag(0x0, 0x0800))){ DataElement const & de = theRSP.GetDataElement(Tag(0x0,0x0800)); Attribute<0x0,0x0800> at; at.SetFromDataElement( de ); unsigned short datasettype = at.GetValue(); assert( datasettype == 0x0101 || datasettype == 0x1 ); (void)datasettype; } if (theRSP.FindDataElement(Tag(0x0, 0x0900))){ DataElement const & de = theRSP.GetDataElement(Tag(0x0,0x0900)); Attribute<0x0,0x0900> at; at.SetFromDataElement( de ); theVal = at.GetValues()[0]; //if theVal is Pending or Success, then we need to enter the loop below, //because we need the data PDUs. //so, the loop below is a do/while loop; there should be at least a second packet //with the dataset, even if the status is 'success' //success == 0000H } uint32_t theCommandCode = 0; if (theRSP.FindDataElement(Tag(0x0,0x0100))){ DataElement const & de = theRSP.GetDataElement(Tag(0x0,0x0100)); Attribute<0x0,0x0100> at; at.SetFromDataElement( de ); theCommandCode = at.GetValues()[0]; } if (theRSP.FindDataElement(Tag(0x0, 0x1020))){ DataElement de = theRSP.GetDataElement(Tag(0x0,0x1020)); Attribute<0x0,0x1020> at; at.SetFromDataElement( de ); theNumLeft = at.GetValues()[0]; //if theVal is Pending or Success, then we need to enter the loop below, //because we need the data PDUs. //so, the loop below is a do/while loop; there should be at least a second packet //with the dataset, even if the status is 'success' //success == 0000H } if (theVal != pendingDE1 && theVal != pendingDE2 && theVal != success){ //check for other error fields const ByteValue *err1 = nullptr, *err2 = nullptr; gdcmErrorMacro( "Transfer failed with code " << theVal << std::endl); switch (theVal){ case 0xA701: gdcmErrorMacro( "Refused: Out of Resources Unable to calculate number of matches" << std::endl); break; case 0xA702: gdcmErrorMacro( "Refused: Out of Resources Unable to perform sub-operations" << std::endl); break; case 0xA801: gdcmErrorMacro( "Refused: Move Destination unknown" << std::endl); break; case 0xA900: gdcmErrorMacro( "Identifier does not match SOP Class" << std::endl); break; case 0xAA00: gdcmErrorMacro( "None of the frames requested were found in the SOP Instance" << std::endl); break; case 0xAA01: gdcmErrorMacro( "Unable to create new object for this SOP class" << std::endl); break; case 0xAA02: gdcmErrorMacro( "Unable to extract frames" << std::endl); break; case 0xAA03: gdcmErrorMacro( "Time-based request received for a non-time-based original SOP Instance. " << std::endl); break; case 0xAA04: gdcmErrorMacro( "Invalid Request" << std::endl); break; case 0xFE00: gdcmErrorMacro( "Sub-operations terminated due to Cancel Indication" << std::endl); break; case 0xB000: gdcmErrorMacro( "Sub-operations Complete One or more Failures or Warnings" << std::endl); break; default: gdcmErrorMacro( "Unable to process" << std::endl); break; } if (theRSP.FindDataElement(Tag(0x0,0x0901))){ DataElement de = theRSP.GetDataElement(Tag(0x0,0x0901)); err1 = de.GetByteValue(); gdcmErrorMacro( " Tag 0x0,0x901 reported as " << *err1 << std::endl); (void)err1; } if (theRSP.FindDataElement(Tag(0x0,0x0902))){ DataElement de = theRSP.GetDataElement(Tag(0x0,0x0902)); err2 = de.GetByteValue(); gdcmErrorMacro( " Tag 0x0,0x902 reported as " << *err2 << std::endl); (void)err2; } } receivingData = false; justWaiting = false; if (theVal == pendingDE1 || theVal == pendingDE2 || (theVal == success && theNumLeft != 0)) { receivingData = true; //wait for more data as more PDUs (findrsps, for instance) justWaiting = true; waitingForEvent = true; //ok, if we're pending, then let's open the cstorescp connection here //(if it's not already open), and then from here start a storescp event loop. //just don't listen to the cmove event loop until this is done. //could cause a pileup on the main connection, I suppose. //could also report the progress here, if we liked. if (theCommandCode == 0x8021){//cmove response, so prep the retrieval loop on the back connection bool dataSetCountIncremented = true;//false once the number of incoming datasets doesn't change. if (mSecondaryConnection->GetProtocol() == nullptr){ //establish the connection //can fail if is_readready doesn't return true, ie, the connection //wasn't opened on the other side because the other side isn't sending data yet //for whatever reason (maybe there's nothing to get?) secondConnectionEstablished = mSecondaryConnection->InitializeIncomingConnection(); if (secondConnectionEstablished && (mSecondaryConnection->GetState()== eSta1Idle || mSecondaryConnection->GetState() == eSta2Open)){ ULEvent theCStoreEvent(eEventDoesNotExist, nullptr);//have to fill this in, we're in passive mode now theCStoreStateID = RunEventLoop(theCStoreEvent, mSecondaryConnection, inCallback, true); } else {//something broke, can't establish secondary move connection here gdcmErrorMacro( "Unable to establish secondary connection with server, aborting." << std::endl); return eStaDoesNotExist; } } if (secondConnectionEstablished){ while (theCStoreStateID == eSta6TransferReady && dataSetCountIncremented){ ULEvent theCStoreEvent(eEventDoesNotExist, nullptr);//have to fill this in, we're in passive mode now //now, get data from across the network theCStoreStateID = RunEventLoop(theCStoreEvent, mSecondaryConnection, inCallback, true); if (inCallback){ dataSetCountIncremented = true; inCallback->ResetHandledDataSet(); } else { dataSetCountIncremented = false; } } } //force the abort from our side // ULEvent theCStoreEvent(eAABORTRequest, NULL);//have to fill this in, we're in passive mode now // theCStoreStateID = RunEventLoop(theCStoreEvent, outDataSet, mSecondaryConnection, true); } else {//not dealing with cmove progress updates, apparently //keep looping if we haven't succeeded or failed; these are the values for 'pending' //first, dynamically cast that pdu in the event //should be a data pdu //then, look for tag 0x0,0x900 //only add datasets that are _not_ part of the network response std::vector final; std::vector theData; BasePDU* thePDU;//outside the loop for the do/while stopping condition bool interrupted = false; do { uint8_t itemtype = 0x0; is.read( (char*)&itemtype, 1 ); //what happens if nothing's read? thePDU = PDUFactory::ConstructPDU(itemtype); if (itemtype != 0x4 && thePDU != nullptr){ //ie, not a pdatapdu std::vector interruptingPDUs; currentEvent.SetEvent(PDUFactory::DetermineEventByPDU(interruptingPDUs[0])); currentEvent.SetPDU(interruptingPDUs); interrupted= true; break; } if (thePDU != nullptr){ thePDU->Read(is); theData.push_back(thePDU); } else{ break; } //!!!need to handle incoming PDUs that are not data, ie, an abort } while(/*!is.eof() &&*/ !thePDU->IsLastFragment()); if (!interrupted){//ie, if the remote server didn't hang up DataSet theCompleteFindResponse = PresentationDataValue::ConcatenatePDVBlobs(PDUFactory::GetPDVs(theData)); //note that it's the responsibility of the event to delete the PDU in theFindRSP for (size_t i = 0; i < theData.size(); i++){ delete theData[i]; } //outDataSet.push_back(theCompleteFindResponse); if (inCallback){ inCallback->HandleDataSet(theCompleteFindResponse); } } } } } } else { raisedEvent = eEventDoesNotExist; waitingForEvent = false; } } else { currentEvent.SetEvent(raisedEvent);//actions that cause transitions in the state table //locally just raise local events that will therefore cause the trigger to be pulled. } } while (currentEvent.GetEvent() != eEventDoesNotExist && theState != eStaDoesNotExist && theState != eSta13AwaitingClose && theState != eSta1Idle && (theState != eSta6TransferReady || (theState == eSta6TransferReady && receivingData ))); //stop when the AE is done, or when ready to transfer data (ie, the next PDU should be sent in), //or when the connection is idle after a disconnection. //or, if in state 6 and receiving data, until all data is received. return theState; } //event handler loop. //will just keep running until the current event is nonexistent. //at which point, it will return the current state of the connection //to do this, execute an event, and then see if there's a response on the //incoming connection (with a reasonable amount of timeout). //if no response, assume that the connection is broken. //if there's a response, then yay. //note that this is the ARTIM timeout event EStateID ULConnectionManager::RunEventLoop(ULEvent& currentEvent, ULConnection* inWhichConnection, ULConnectionCallback* inCallback, const bool& startWaiting = false){ gdcmDebugMacro( "Start RunEventLoop" ); EStateID theState = eStaDoesNotExist; bool waitingForEvent = startWaiting;//overwritten if not starting waiting, but if waiting, then wait EEventID raisedEvent; bool receivingData = false; //bool justWaiting = startWaiting; //not sure justwaiting is useful; for now, go back to waiting for event //when receiving data from a find, etc, then justWaiting is true and only receiving is done //eventually, could add cancel into the mix... but that would be through a callback or something similar do { gdcmDebugMacro( "Before mTransitions.HandleEvent #2" ); raisedEvent = eEventDoesNotExist; if (!waitingForEvent){//justWaiting){ mTransitions.HandleEvent(this, currentEvent, *inWhichConnection, waitingForEvent, raisedEvent); //this gathering of the state is for scus that have just sent out a request theState = inWhichConnection->GetState(); } std::istream * tempProtocolStream = inWhichConnection->GetProtocol(); if(tempProtocolStream == nullptr) { throw Exception("ProtocolStream as nullptr is invalid"); } std::istream &is = *tempProtocolStream; //std::ostream &os = *inWhichConnection->GetProtocol(); BasePDU* theFirstPDU = nullptr;// the first pdu read in during this event loop, //used to make sure the presentation context ID is correct //read the connection, as that's an event as well. //waiting for an object to come back across the connection, so that it can get handled. //ie, accept, reject, timeout, etc. //of course, if the connection is down, just leave the loop. //also leave the loop if nothing's waiting. //use the PDUFactory to create the appropriate pdu, which has its own //internal mechanisms for handling itself (but will, of course, be put inside the event object). //but, and here's the important thing, only read on the socket when we should. std::vector incomingPDUs; if (waitingForEvent){ while (waitingForEvent){//loop for reading in the events that come down the wire uint8_t itemtype = 0x0; try { gdcmDebugMacro( "Waiting for ItemType" ); is.read( (char*)&itemtype, 1 ); gdcmDebugMacro( "Received ItemType #" << (int)itemtype ); //what happens if nothing's read? theFirstPDU = PDUFactory::ConstructPDU(itemtype); if (theFirstPDU != nullptr){ incomingPDUs.push_back(theFirstPDU); theFirstPDU->Read(is); gdcmDebugMacro("PDU code: " << static_cast(itemtype) << std::endl); if (Trace::GetDebugFlag()) { theFirstPDU->Print(Trace::GetStream()); } if (theFirstPDU->IsLastFragment()) waitingForEvent = false; } else { gdcmDebugMacro( "NULL theFirstPDU for ItemType" << (int)itemtype ); waitingForEvent = false; //because no PDU means not waiting anymore return eStaDoesNotExist; } } catch (...) { //handle the exception, which is basically that nothing came in over the pipe. gdcmAssertAlwaysMacro( 0 ); } } //now, we have to figure out the event that just happened based on the PDU that was received. //this state gathering is for scps, especially the cstore for cmove. theState = inWhichConnection->GetState(); if (!incomingPDUs.empty()){ currentEvent.SetEvent(PDUFactory::DetermineEventByPDU(incomingPDUs[0])); currentEvent.SetPDU(incomingPDUs); //here's the scp handling code if (mConnection->GetTimer().GetHasExpired()){ currentEvent.SetEvent(eARTIMTimerExpired); } switch(currentEvent.GetEvent()){ case ePDATATFPDU: { //if (theState == eSta6TransferReady){//ie, finished the transitions //with find, the results now come down the wire. //the pdu we already have from the event will tell us how many to expect. uint32_t pendingDE1, pendingDE2, success, theVal; pendingDE1 = 0xff01; pendingDE2 = 0xff00; success = 0x0000; theVal = pendingDE1; uint32_t theCommandCode = 0;//for now, a nothing value DataSet theRSP = PresentationDataValue::ConcatenatePDVBlobs( PDUFactory::GetPDVs(currentEvent.GetPDUs())); if (inCallback) { inCallback->HandleResponse(theRSP); } if (theRSP.FindDataElement(Tag(0x0, 0x0900))){ DataElement de = theRSP.GetDataElement(Tag(0x0,0x0900)); Attribute<0x0,0x0900> at; at.SetFromDataElement( de ); theVal = at.GetValues()[0]; //if theVal is Pending or Success, then we need to enter the loop below, //because we need the data PDUs. //so, the loop below is a do/while loop; there should be at least a second packet //with the dataset, even if the status is 'success' //success == 0000H } if (Trace::GetDebugFlag()) { Printer thePrinter; thePrinter.PrintDataSet(theRSP, Trace::GetStream()); } //check to see if this is a cstorerq if (theRSP.FindDataElement(Tag(0x0, 0x0100))) { DataElement de2 = theRSP.GetDataElement(Tag(0x0,0x0100)); Attribute<0x0,0x0100> at2; at2.SetFromDataElement( de2 ); theCommandCode = at2.GetValues()[0]; } if (theVal != pendingDE1 && theVal != pendingDE2 && theVal != success) { //check for other error fields const ByteValue *err1 = nullptr, *err2 = nullptr; gdcmErrorMacro( "Transfer failed with code " << theVal << std::endl); switch (theVal){ case 0xA701: gdcmErrorMacro( "Refused: Out of Resources Unable to calculate number of matches" << std::endl); break; case 0xA702: gdcmErrorMacro( "Refused: Out of Resources Unable to perform sub-operations" << std::endl); break; case 0xA801: gdcmErrorMacro( "Refused: Move Destination unknown" << std::endl); break; case 0xA900: gdcmErrorMacro( "Identifier does not match SOP Class" << std::endl); break; case 0xAA00: gdcmErrorMacro( "None of the frames requested were found in the SOP Instance" << std::endl); break; case 0xAA01: gdcmErrorMacro( "Unable to create new object for this SOP class" << std::endl); break; case 0xAA02: gdcmErrorMacro( "Unable to extract frames" << std::endl); break; case 0xAA03: gdcmErrorMacro( "Time-based request received for a non-time-based original SOP Instance. " << std::endl); break; case 0xAA04: gdcmErrorMacro( "Invalid Request" << std::endl); break; case 0xFE00: gdcmErrorMacro( "Sub-operations terminated due to Cancel Indication" << std::endl); break; case 0xB000: gdcmErrorMacro( "Sub-operations Complete One or more Failures or Warnings" << std::endl); break; default: gdcmErrorMacro( "Unable to process" << std::endl); break; } if (theRSP.FindDataElement(Tag(0x0,0x0901))){ DataElement de = theRSP.GetDataElement(Tag(0x0,0x0901)); err1 = de.GetByteValue(); gdcmErrorMacro( " Tag 0x0,0x901 reported as " << *err1 << std::endl); (void)err1; } if (theRSP.FindDataElement(Tag(0x0,0x0902))){ DataElement de = theRSP.GetDataElement(Tag(0x0,0x0902)); err2 = de.GetByteValue(); gdcmErrorMacro( " Tag 0x0,0x902 reported as " << *err2 << std::endl); (void)err2; } } receivingData = false; //justWaiting = false; if (theVal == pendingDE1 || theVal == pendingDE2) { receivingData = true; //wait for more data as more PDUs (findrsps, for instance) //justWaiting = true; waitingForEvent = true; } if (theVal == pendingDE1 || theVal == pendingDE2 /*|| theVal == success*/){//keep looping if we haven't succeeded or failed; these are the values for 'pending' //first, dynamically cast that pdu in the event //should be a data pdu //then, look for tag 0x0,0x900 //only add datasets that are _not_ part of the network response std::vector final; std::vector theData; BasePDU* thePDU;//outside the loop for the do/while stopping condition bool interrupted = false; do { uint8_t itemtype = 0x0; is.read( (char*)&itemtype, 1 ); //what happens if nothing's read? thePDU = PDUFactory::ConstructPDU(itemtype); if (itemtype != 0x4 && thePDU != nullptr){ //ie, not a pdatapdu std::vector interruptingPDUs; interruptingPDUs.push_back(thePDU); currentEvent.SetEvent(PDUFactory::DetermineEventByPDU(interruptingPDUs[0])); currentEvent.SetPDU(interruptingPDUs); interrupted= true; break; } if (thePDU != nullptr){ thePDU->Read(is); theData.push_back(thePDU); } else{ break; } //!!!need to handle incoming PDUs that are not data, ie, an abort } while(!thePDU->IsLastFragment()); if (!interrupted){//ie, if the remote server didn't hang up bool useimplicit = true; TransferSyntaxSub ts1; ts1.SetNameFromUID( UIDs::ImplicitVRLittleEndianDefaultTransferSyntaxforDICOM ); if( mSecondaryConnection ) { const TransferSyntaxSub & ts_ = mSecondaryConnection->GetCStoreTransferSyntax(); if( strcmp(ts_.GetName(), ts1.GetName()) != 0) { useimplicit = false; } } DataSet theCompleteFindResponse; if( useimplicit ) { inCallback->SetImplicitFlag(true); theCompleteFindResponse = PresentationDataValue::ConcatenatePDVBlobs(PDUFactory::GetPDVs(theData)); } else { inCallback->SetImplicitFlag(false); theCompleteFindResponse = PresentationDataValue::ConcatenatePDVBlobsAsExplicit(PDUFactory::GetPDVs(theData)); } //note that it's the responsibility of the event to delete the PDU in theFindRSP for (size_t i = 0; i < theData.size(); i++) { delete theData[i]; } assert(inCallback); { inCallback->HandleDataSet(theCompleteFindResponse); } // DataSetEvent dse( &theCompleteFindResponse ); // this->InvokeEvent( dse ); if (theCommandCode == 1){//if we're doing cstore scp stuff, send information back along the connection. std::vector theCStoreRSPPDU = PDUFactory::CreateCStoreRSPPDU(&theRSP, theFirstPDU);//pass NULL for C-Echo //send them directly back over the connection //ideall, should go through the transition table, but we know this should work //and it won't change the state (unless something breaks?, but then an exception should throw) std::vector::iterator itor; for (itor = theCStoreRSPPDU.begin(); itor < theCStoreRSPPDU.end(); itor++){ (*itor)->Write(*inWhichConnection->GetProtocol()); } inWhichConnection->GetProtocol()->flush(); // FIXME added MM / Oct 30 2010 //AReleaseRPPDU rel; //rel.Write( *inWhichConnection->GetProtocol() ); //inWhichConnection->GetProtocol()->flush(); receivingData = false; //gotta get data on the other connection for a cmove // cleanup for (itor = theCStoreRSPPDU.begin(); itor < theCStoreRSPPDU.end(); itor++){ delete *itor; } } } } } break; case eARELEASERequest://process this via the transition table waitingForEvent = false; break; case eARELEASE_RQPDUReceivedOpen://process this via the transition table waitingForEvent = false; receivingData = true; //to continue the loop to process the release break; case eAABORTPDUReceivedOpen: raisedEvent = eEventDoesNotExist; theState = eStaDoesNotExist; /* fall through */ case eAABORTRequest: waitingForEvent = false; inWhichConnection->StopProtocol(); break; case eASSOCIATE_ACPDUreceived: default: waitingForEvent = false; break; } } //} else { // raisedEvent = eEventDoesNotExist; // waitingForEvent = false; //} } else { currentEvent.SetEvent(raisedEvent);//actions that cause transitions in the state table //locally just raise local events that will therefore cause the trigger to be pulled. } } while (currentEvent.GetEvent() != eEventDoesNotExist && theState != eStaDoesNotExist && theState != eSta13AwaitingClose && theState != eSta1Idle && (theState != eSta6TransferReady || (theState == eSta6TransferReady && receivingData ))); //stop when the AE is done, or when ready to transfer data (ie, the next PDU should be sent in), //or when the connection is idle after a disconnection. //or, if in state 6 and receiving data, until all data is received. return theState; } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULConnectionManager.h000066400000000000000000000156721412732066400254640ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMULCONNECTIONMANAGER_H #define GDCMULCONNECTIONMANAGER_H #include "gdcmULTransitionTable.h" #include "gdcmULConnection.h" #include "gdcmULConnectionInfo.h" #include "gdcmPresentationDataValue.h" #include "gdcmULConnectionCallback.h" #include "gdcmSubject.h" #include "gdcmPresentationContext.h" namespace gdcm { class File; class BaseRootQuery; class BaseQuery; namespace network { /** * \brief ULConnectionManager * \details The ULConnectionManager performs actions on the ULConnection given inputs * from the user and from the state of what's going on around the connection * (ie, timeouts of the ARTIM timer, responses from the peer across the * connection, etc). * * Its inputs are ULEvents, and it performs ULActions. */ class GDCM_EXPORT ULConnectionManager : public Subject { protected: ULConnection* mConnection; ULConnection* mSecondaryConnection; ULTransitionTable mTransitions; //no copying ULConnectionManager(const ULConnectionManager& inCM); //event handler loop. //will just keep running until the current event is nonexistent. //at which point, it will return the current state of the connection //this starts by initiating an action, but can be put into a passive mode //for a cmove/cstore combination by setting startWaiting to true EStateID RunEventLoop(ULEvent& inEvent, ULConnection* inWhichConnection, ULConnectionCallback* inCallback, const bool& startWaiting); //like the above, but will manage the event loop for a move event (which //is basically two simultaneous connections interwoven, one inbound and //the other outbound. Note, for instance, that cmoversp's can be sent back //during the other connection's operation. EStateID RunMoveEventLoop(ULEvent& inEvent, ULConnectionCallback* inCallback); public: ULConnectionManager(); ~ULConnectionManager() override; // NOTE: (MM) The following two functions are difficults to use, therefore marking // them as internal for now. // \internal /// returns true if a connection of the given AETitle (ie, 'this' program) /// is able to connect to the given AETitle and Port in a certain amount of /// time providing the connection type will establish the proper exchange /// syntax with a server; if a different functionality is required, a /// different connection should be established. /// returns false if the connection type is 'move'-- have to give a return /// port for move to work as specified. bool EstablishConnection(const std::string& inAETitle, const std::string& inConnectAETitle, const std::string& inComputerName, long inIPAddress, uint16_t inConnectPort, double inTimeout, std::vector const & pcVector ); /// returns true for above reasons, but contains the special 'move' port /// \internal bool EstablishConnectionMove(const std::string& inAETitle, const std::string& inConnectAETitle, const std::string& inComputerName, long inIPAddress, uint16_t inConnectPort, double inTimeout, uint16_t inReturnPort, std::vector const & pcVector); // \endinternal //bool ReestablishConnection(const EConnectionType& inConnectionType, // const DataSet& inDS); //allows for a connection to be broken, but waits for an acknowledgement //of the breaking for a certain amount of time. Returns true of the //other side acknowledges the break bool BreakConnection(const double& inTimeout); //severs the connection, if it's open, without waiting for any kind of response. //typically done if the program is going down. void BreakConnectionNow(); //This function will send a given piece of data //across the network connection. It will return true if the //sending worked, false otherwise. //note that sending is asynchronous; as such, there's //also a 'receive' option, but that requires a callback function. //bool SendData(); //send the Data PDU associated with Echo (ie, a default DataPDU) //this lets the user confirm that the connection is alive. //the user should look to cout to see the response of the echo command //returns the PresentationDataValue that was returned by the remote //host. Note that the PDV can be uninitialized, which would indicate failure. //Echo does not use a callback for results. std::vector SendEcho(); // \internal // API will change... std::vector SendStore(const File &file, std::istream * pStream = nullptr, std::streampos dataSetOffset = 0 ); std::vector SendFind(const BaseRootQuery* inRootQuery); std::vector SendMove(const BaseRootQuery* inRootQuery); std::vector SendNEventReport (const BaseQuery* inQuery); std::vector SendNGet (const BaseQuery* inQuery); std::vector SendNSet (const BaseQuery* inQuery); std::vector SendNAction (const BaseQuery* inQuery); std::vector SendNCreate (const BaseQuery* inQuery); std::vector SendNDelete (const BaseQuery* inQuery); // \endinternal ///callback based API void SendStore(const File & file, ULConnectionCallback* inCallback, std::istream * pStream = nullptr , std::streampos dataSetOffset = 0 ); void SendFind(const BaseRootQuery* inRootQuery, ULConnectionCallback* inCallback); /// return false upon error bool SendMove(const BaseRootQuery* inRootQuery, ULConnectionCallback* inCallback); void SendNEventReport (const BaseQuery* inQuery, ULConnectionCallback* inCallback); void SendNGet (const BaseQuery* inQuery, ULConnectionCallback* inCallback); void SendNSet (const BaseQuery* inQuery, ULConnectionCallback* inCallback); void SendNAction (const BaseQuery* inQuery, ULConnectionCallback* inCallback); void SendNCreate (const BaseQuery* inQuery, ULConnectionCallback* inCallback); void SendNDelete (const BaseQuery* inQuery, ULConnectionCallback* inCallback); }; } } #endif // GDCMULCONNECTIONMANAGER_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULEvent.h000066400000000000000000000052101412732066400231360ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMULEVENT_H #define GDCMULEVENT_H #include "gdcmNetworkStateID.h" #include "gdcmNetworkEvents.h" #include "gdcmBasePDU.h" #include namespace gdcm { namespace network { /** * \brief ULEvent * \details base class for network events. * * An event consists of the event ID and the data associated with that event. * * Note that once a PDU is created, it is now the responsibility of the associated event to destroy it! */ class ULEvent { EEventID mEvent; std::vector mBasePDU; std::istream * m_pStream ; std::streampos m_posDataSet ; void DeletePDUVector(){ std::vector::iterator baseItor; for (baseItor = mBasePDU.begin(); baseItor < mBasePDU.end(); baseItor++){ if (*baseItor != NULL){ delete *baseItor; *baseItor = NULL; } } } public: ULEvent(const EEventID& inEventID, std::vector inBasePDU, std::istream * iStream = nullptr, std::streampos posDataSet = 0 ){ mEvent = inEventID; mBasePDU = inBasePDU; m_pStream = iStream ; m_posDataSet = posDataSet ; } ULEvent(const EEventID& inEventID, BasePDU* inBasePDU, std::istream * iStream = nullptr, std::streampos posDataSet = 0 ){ mEvent = inEventID; mBasePDU.push_back(inBasePDU); m_pStream = iStream ; m_posDataSet = posDataSet ; } ~ULEvent(){ DeletePDUVector(); } EEventID GetEvent() const { return mEvent; } std::vector const & GetPDUs() const { return mBasePDU; } std::istream * GetIStream() const { return m_pStream; } std::streampos GetDataSetPos() const { return m_posDataSet; } void SetEvent(const EEventID& inEvent) { mEvent = inEvent; } void SetPDU(std::vector const & inPDU) { DeletePDUVector(); mBasePDU = inPDU; } }; } } #endif //GDCMULEVENT_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULTransitionTable.cxx000066400000000000000000000516571412732066400255520ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /* * This file is the implementation of the ULTransitionTable class, including * the actual event handling as well as the construction of the table itself. */ #include "gdcmULTransitionTable.h" #include "gdcmULActionAA.h" #include "gdcmULActionAE.h" #include "gdcmULActionAR.h" #include "gdcmULActionDT.h" namespace gdcm { namespace network { //construct the table ULTransitionTable::ULTransitionTable() { //row 1 // A-ASSOCIATE Request (local user) mTable[eAASSOCIATERequestLocalUser].transitions[GetStateIndex(eSta1Idle)] = Transition::MakeNew(eSta4LocalAssocDone, new ULActionAE1()); //row 2 // Transport Conn. Confirmn (local transport service) mTable[eTransportConnConfirmLocal].transitions[GetStateIndex(eSta4LocalAssocDone)] = Transition::MakeNew(eSta5WaitRemoteAssoc, new ULActionAE2()); //row 3 // A-ASSOCIATE-AC PDU (received on transport connection) mTable[eASSOCIATE_ACPDUreceived].transitions[GetStateIndex(eSta2Open)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA1()); mTable[eASSOCIATE_ACPDUreceived].transitions[GetStateIndex(eSta3WaitLocalAssoc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_ACPDUreceived].transitions[GetStateIndex(eSta5WaitRemoteAssoc)] = Transition::MakeNew(eSta6TransferReady, new ULActionAE3()); mTable[eASSOCIATE_ACPDUreceived].transitions[GetStateIndex(eSta6TransferReady)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_ACPDUreceived].transitions[GetStateIndex(eSta7WaitRelease)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_ACPDUreceived].transitions[GetStateIndex(eSta8WaitLocalRelease)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_ACPDUreceived].transitions[GetStateIndex(eSta9ReleaseCollisionRqLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_ACPDUreceived].transitions[GetStateIndex(eSta10ReleaseCollisionAc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_ACPDUreceived].transitions[GetStateIndex(eSta11ReleaseCollisionRq)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_ACPDUreceived].transitions[GetStateIndex(eSta12ReleaseCollisionAcLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_ACPDUreceived].transitions[GetStateIndex(eSta13AwaitingClose)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA6()); //row 4 // A-ASSOCIATE-RJ PDU (received on transport connection) mTable[eASSOCIATE_RJPDUreceived].transitions[GetStateIndex(eSta2Open)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA1()); mTable[eASSOCIATE_RJPDUreceived].transitions[GetStateIndex(eSta3WaitLocalAssoc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_RJPDUreceived].transitions[GetStateIndex(eSta5WaitRemoteAssoc)] = Transition::MakeNew(eSta1Idle, new ULActionAE4()); mTable[eASSOCIATE_RJPDUreceived].transitions[GetStateIndex(eSta6TransferReady)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_RJPDUreceived].transitions[GetStateIndex(eSta7WaitRelease)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_RJPDUreceived].transitions[GetStateIndex(eSta8WaitLocalRelease)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_RJPDUreceived].transitions[GetStateIndex(eSta9ReleaseCollisionRqLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_RJPDUreceived].transitions[GetStateIndex(eSta10ReleaseCollisionAc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_RJPDUreceived].transitions[GetStateIndex(eSta11ReleaseCollisionRq)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_RJPDUreceived].transitions[GetStateIndex(eSta12ReleaseCollisionAcLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eASSOCIATE_RJPDUreceived].transitions[GetStateIndex(eSta13AwaitingClose)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA6()); //row 5 // Transport Connection Indication (local transport service) mTable[eTransportConnIndicLocal].transitions[GetStateIndex(eSta1Idle)] = Transition::MakeNew(eSta2Open, new ULActionAE5()); //row 6 // A-ASSOCIATE-RQ PDU (received on transport connection) mTable[eAASSOCIATE_RQPDUreceived].transitions[GetStateIndex(eSta2Open)] = Transition::MakeNew(eSta3WaitLocalAssoc | eSta13AwaitingClose, new ULActionAE6()); mTable[eAASSOCIATE_RQPDUreceived].transitions[GetStateIndex(eSta3WaitLocalAssoc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eAASSOCIATE_RQPDUreceived].transitions[GetStateIndex(eSta5WaitRemoteAssoc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eAASSOCIATE_RQPDUreceived].transitions[GetStateIndex(eSta6TransferReady)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eAASSOCIATE_RQPDUreceived].transitions[GetStateIndex(eSta7WaitRelease)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eAASSOCIATE_RQPDUreceived].transitions[GetStateIndex(eSta8WaitLocalRelease)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eAASSOCIATE_RQPDUreceived].transitions[GetStateIndex(eSta9ReleaseCollisionRqLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eAASSOCIATE_RQPDUreceived].transitions[GetStateIndex(eSta10ReleaseCollisionAc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eAASSOCIATE_RQPDUreceived].transitions[GetStateIndex(eSta11ReleaseCollisionRq)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eAASSOCIATE_RQPDUreceived].transitions[GetStateIndex(eSta12ReleaseCollisionAcLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eAASSOCIATE_RQPDUreceived].transitions[GetStateIndex(eSta13AwaitingClose)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA7()); //row 7 // A-ASSOCIATE response primitive (accept) mTable[eAASSOCIATEresponseAccept].transitions[GetStateIndex(eSta3WaitLocalAssoc)] = Transition::MakeNew(eSta7WaitRelease, new ULActionAE7()); //row 8 // A-ASSOCIATE response primitive (reject) mTable[eAASSOCIATEresponseReject].transitions[GetStateIndex(eSta3WaitLocalAssoc)] = Transition::MakeNew(eSta7WaitRelease, new ULActionAE7()); //Row 9 // P-DATA request primitive mTable[ePDATArequest].transitions[GetStateIndex(eSta6TransferReady)] = Transition::MakeNew(eSta6TransferReady, new ULActionDT1()); mTable[ePDATArequest].transitions[GetStateIndex(eSta8WaitLocalRelease)] = Transition::MakeNew(eSta8WaitLocalRelease, new ULActionAR7()); //row 10 // P-DATA-TF PDU mTable[ePDATATFPDU].transitions[GetStateIndex(eSta2Open)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA1()); mTable[ePDATATFPDU].transitions[GetStateIndex(eSta3WaitLocalAssoc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[ePDATATFPDU].transitions[GetStateIndex(eSta5WaitRemoteAssoc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[ePDATATFPDU].transitions[GetStateIndex(eSta6TransferReady)] = Transition::MakeNew(eSta6TransferReady, new ULActionDT2()); mTable[ePDATATFPDU].transitions[GetStateIndex(eSta7WaitRelease)] = Transition::MakeNew(eSta7WaitRelease, new ULActionAR6()); mTable[ePDATATFPDU].transitions[GetStateIndex(eSta8WaitLocalRelease)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[ePDATATFPDU].transitions[GetStateIndex(eSta9ReleaseCollisionRqLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[ePDATATFPDU].transitions[GetStateIndex(eSta10ReleaseCollisionAc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[ePDATATFPDU].transitions[GetStateIndex(eSta11ReleaseCollisionRq)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[ePDATATFPDU].transitions[GetStateIndex(eSta12ReleaseCollisionAcLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[ePDATATFPDU].transitions[GetStateIndex(eSta13AwaitingClose)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA6()); //row 11 // A-RELEASE Request primitive mTable[eARELEASERequest].transitions[GetStateIndex(eSta6TransferReady)] = Transition::MakeNew(eSta7WaitRelease, new ULActionAR1()); //row 12 // A-RELEASE-RQ PDU (received on open transport connection) mTable[eARELEASE_RQPDUReceivedOpen].transitions[GetStateIndex(eSta2Open)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA1()); mTable[eARELEASE_RQPDUReceivedOpen].transitions[GetStateIndex(eSta3WaitLocalAssoc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eARELEASE_RQPDUReceivedOpen].transitions[GetStateIndex(eSta5WaitRemoteAssoc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eARELEASE_RQPDUReceivedOpen].transitions[GetStateIndex(eSta6TransferReady)] = Transition::MakeNew(eSta8WaitLocalRelease, new ULActionAR2()); mTable[eARELEASE_RQPDUReceivedOpen].transitions[GetStateIndex(eSta7WaitRelease)] = Transition::MakeNew(eSta9ReleaseCollisionRqLocal | eSta10ReleaseCollisionAc, new ULActionAR8()); mTable[eARELEASE_RQPDUReceivedOpen].transitions[GetStateIndex(eSta8WaitLocalRelease)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eARELEASE_RQPDUReceivedOpen].transitions[GetStateIndex(eSta9ReleaseCollisionRqLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eARELEASE_RQPDUReceivedOpen].transitions[GetStateIndex(eSta10ReleaseCollisionAc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eARELEASE_RQPDUReceivedOpen].transitions[GetStateIndex(eSta11ReleaseCollisionRq)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eARELEASE_RQPDUReceivedOpen].transitions[GetStateIndex(eSta12ReleaseCollisionAcLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eARELEASE_RQPDUReceivedOpen].transitions[GetStateIndex(eSta13AwaitingClose)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA6()); //row 13 // A-RELEASE-RP PDU (received on transport connection) mTable[eARELEASE_RPPDUReceived].transitions[GetStateIndex(eSta2Open)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA1()); mTable[eARELEASE_RPPDUReceived].transitions[GetStateIndex(eSta3WaitLocalAssoc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eARELEASE_RPPDUReceived].transitions[GetStateIndex(eSta5WaitRemoteAssoc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eARELEASE_RPPDUReceived].transitions[GetStateIndex(eSta6TransferReady)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eARELEASE_RPPDUReceived].transitions[GetStateIndex(eSta7WaitRelease)] = Transition::MakeNew(eSta1Idle, new ULActionAR3()); mTable[eARELEASE_RPPDUReceived].transitions[GetStateIndex(eSta8WaitLocalRelease)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eARELEASE_RPPDUReceived].transitions[GetStateIndex(eSta9ReleaseCollisionRqLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eARELEASE_RPPDUReceived].transitions[GetStateIndex(eSta10ReleaseCollisionAc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eARELEASE_RPPDUReceived].transitions[GetStateIndex(eSta11ReleaseCollisionRq)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eARELEASE_RPPDUReceived].transitions[GetStateIndex(eSta12ReleaseCollisionAcLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eARELEASE_RPPDUReceived].transitions[GetStateIndex(eSta13AwaitingClose)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA6()); // Row 14 // A-RELEASE Response primitive mTable[eARELEASEResponse].transitions[GetStateIndex(eSta8WaitLocalRelease)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAR4()); mTable[eARELEASEResponse].transitions[GetStateIndex(eSta9ReleaseCollisionRqLocal)] = Transition::MakeNew(eSta11ReleaseCollisionRq, new ULActionAR9); mTable[eARELEASEResponse].transitions[GetStateIndex(eSta12ReleaseCollisionAcLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAR4()); // row 15 // A-ABORT Request primitive mTable[eAABORTRequest].transitions[GetStateIndex(eSta3WaitLocalAssoc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA1()); mTable[eAABORTRequest].transitions[GetStateIndex(eSta4LocalAssocDone)] = Transition::MakeNew(eSta1Idle, new ULActionAA2()); mTable[eAABORTRequest].transitions[GetStateIndex(eSta5WaitRemoteAssoc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA1()); mTable[eAABORTRequest].transitions[GetStateIndex(eSta6TransferReady)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA1()); mTable[eAABORTRequest].transitions[GetStateIndex(eSta7WaitRelease)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA1()); mTable[eAABORTRequest].transitions[GetStateIndex(eSta8WaitLocalRelease)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA1()); mTable[eAABORTRequest].transitions[GetStateIndex(eSta9ReleaseCollisionRqLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA1()); mTable[eAABORTRequest].transitions[GetStateIndex(eSta10ReleaseCollisionAc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA1()); mTable[eAABORTRequest].transitions[GetStateIndex(eSta11ReleaseCollisionRq)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA1()); mTable[eAABORTRequest].transitions[GetStateIndex(eSta12ReleaseCollisionAcLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA1()); // row 16 // A-ABORT PDU (received on open transport connection) mTable[eAABORTPDUReceivedOpen].transitions[GetStateIndex(eSta2Open)] = Transition::MakeNew(eSta1Idle, new ULActionAA2()); mTable[eAABORTPDUReceivedOpen].transitions[GetStateIndex(eSta3WaitLocalAssoc)] = Transition::MakeNew(eSta1Idle, new ULActionAA3()); mTable[eAABORTPDUReceivedOpen].transitions[GetStateIndex(eSta5WaitRemoteAssoc)] = Transition::MakeNew(eSta1Idle, new ULActionAA3()); mTable[eAABORTPDUReceivedOpen].transitions[GetStateIndex(eSta6TransferReady)] = Transition::MakeNew(eSta1Idle, new ULActionAA3()); mTable[eAABORTPDUReceivedOpen].transitions[GetStateIndex(eSta7WaitRelease)] = Transition::MakeNew(eSta1Idle, new ULActionAA3()); mTable[eAABORTPDUReceivedOpen].transitions[GetStateIndex(eSta8WaitLocalRelease)] = Transition::MakeNew(eSta1Idle, new ULActionAA3()); mTable[eAABORTPDUReceivedOpen].transitions[GetStateIndex(eSta9ReleaseCollisionRqLocal)] = Transition::MakeNew(eSta1Idle, new ULActionAA3()); mTable[eAABORTPDUReceivedOpen].transitions[GetStateIndex(eSta10ReleaseCollisionAc)] = Transition::MakeNew(eSta1Idle, new ULActionAA3()); mTable[eAABORTPDUReceivedOpen].transitions[GetStateIndex(eSta11ReleaseCollisionRq)] = Transition::MakeNew(eSta1Idle, new ULActionAA3()); mTable[eAABORTPDUReceivedOpen].transitions[GetStateIndex(eSta12ReleaseCollisionAcLocal)] = Transition::MakeNew(eSta1Idle, new ULActionAA3()); mTable[eAABORTPDUReceivedOpen].transitions[GetStateIndex(eSta13AwaitingClose)] = Transition::MakeNew(eSta1Idle, new ULActionAA2()); //row 17 // Transport connection closed indication (local transport service), mTable[eTransportConnectionClosed].transitions[GetStateIndex(eSta2Open)] = Transition::MakeNew(eSta1Idle, new ULActionAA5()); mTable[eTransportConnectionClosed].transitions[GetStateIndex(eSta3WaitLocalAssoc)] = Transition::MakeNew(eSta1Idle, new ULActionAA4()); mTable[eTransportConnectionClosed].transitions[GetStateIndex(eSta4LocalAssocDone)] = Transition::MakeNew(eSta1Idle, new ULActionAA4()); mTable[eTransportConnectionClosed].transitions[GetStateIndex(eSta5WaitRemoteAssoc)] = Transition::MakeNew(eSta1Idle, new ULActionAA4()); mTable[eTransportConnectionClosed].transitions[GetStateIndex(eSta6TransferReady)] = Transition::MakeNew(eSta1Idle, new ULActionAA4()); mTable[eTransportConnectionClosed].transitions[GetStateIndex(eSta7WaitRelease)] = Transition::MakeNew(eSta1Idle, new ULActionAA4()); mTable[eTransportConnectionClosed].transitions[GetStateIndex(eSta8WaitLocalRelease)] = Transition::MakeNew(eSta1Idle, new ULActionAA4()); mTable[eTransportConnectionClosed].transitions[GetStateIndex(eSta9ReleaseCollisionRqLocal)] = Transition::MakeNew(eSta1Idle, new ULActionAA4()); mTable[eTransportConnectionClosed].transitions[GetStateIndex(eSta10ReleaseCollisionAc)] = Transition::MakeNew(eSta1Idle, new ULActionAA4()); mTable[eTransportConnectionClosed].transitions[GetStateIndex(eSta11ReleaseCollisionRq)] = Transition::MakeNew(eSta1Idle, new ULActionAA4()); mTable[eTransportConnectionClosed].transitions[GetStateIndex(eSta12ReleaseCollisionAcLocal)] = Transition::MakeNew(eSta1Idle, new ULActionAA4()); mTable[eTransportConnectionClosed].transitions[GetStateIndex(eSta13AwaitingClose)] = Transition::MakeNew(eSta1Idle, new ULActionAA5()); //row 18 // ARTIM timer expired (Association reject/release timer), mTable[eARTIMTimerExpired].transitions[GetStateIndex(eSta2Open)] = Transition::MakeNew(eSta1Idle, new ULActionAA2()); mTable[eARTIMTimerExpired].transitions[GetStateIndex(eSta13AwaitingClose)] = Transition::MakeNew(eSta1Idle, new ULActionAA2()); //row 19 // Unrecognized or invalid PDU received mTable[eUnrecognizedPDUReceived].transitions[GetStateIndex(eSta3WaitLocalAssoc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA1()); mTable[eUnrecognizedPDUReceived].transitions[GetStateIndex(eSta13AwaitingClose)] = Transition::MakeNew(eSta1Idle, new ULActionAA8()); mTable[eUnrecognizedPDUReceived].transitions[GetStateIndex(eSta5WaitRemoteAssoc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eUnrecognizedPDUReceived].transitions[GetStateIndex(eSta6TransferReady)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eUnrecognizedPDUReceived].transitions[GetStateIndex(eSta7WaitRelease)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eUnrecognizedPDUReceived].transitions[GetStateIndex(eSta8WaitLocalRelease)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eUnrecognizedPDUReceived].transitions[GetStateIndex(eSta9ReleaseCollisionRqLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eUnrecognizedPDUReceived].transitions[GetStateIndex(eSta10ReleaseCollisionAc)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eUnrecognizedPDUReceived].transitions[GetStateIndex(eSta11ReleaseCollisionRq)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA8()); mTable[eUnrecognizedPDUReceived].transitions[GetStateIndex(eSta12ReleaseCollisionAcLocal)] = Transition::MakeNew(eSta13AwaitingClose, new ULActionAA7()); } //given the event and the state of the connection, call the appropriate action void ULTransitionTable::HandleEvent(Subject *s, ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) const{ //first, find the Event EEventID eventID = inEvent.GetEvent(); if (eventID < eEventDoesNotExist) { //make sure that the event exists //have to convert the state ID into an index int stateIndex = GetStateIndex(inConnection.GetState()); if (stateIndex >= 0 && stateIndex < cMaxStateID) { if ( mTable[eventID].transitions[stateIndex] ) { if (mTable[eventID].transitions[stateIndex]->mAction != nullptr) { gdcmDebugMacro( "Process: Event:" << (int)eventID << ", State:" << stateIndex ); inConnection.SetState(mTable[eventID].transitions[stateIndex]->mAction-> PerformAction(s,inEvent, inConnection, outWaitingForEvent, outRaisedEvent)); } } else { gdcmDebugMacro( "Transition failed (NULL) for event:" << (int)eventID << ", State:" << stateIndex ); } } } } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULTransitionTable.h000066400000000000000000000067401412732066400251700ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMULTRANSITIONTABLE_H #define GDCMULTRANSITIONTABLE_H #include "gdcmNetworkStateID.h" #include "gdcmNetworkEvents.h" #include "gdcmULAction.h" #include // NULL namespace gdcm { class Subject; namespace network{ class ULConnection; class ULAction; class ULEvent; //The transition dictates the action that should be taken from the start state to the end state struct Transition { int mEnd; ULAction* mAction; Transition(){ mEnd = eStaDoesNotExist; mAction = nullptr; } ~Transition(){ if (mAction != nullptr){ delete mAction; mAction = nullptr; } } Transition(int inEndState, ULAction* inAction){ mEnd = inEndState; mAction = inAction; } static Transition* MakeNew(int inEndState, ULAction* inAction){ return new Transition(inEndState, inAction); } }; //used to define a row in table 9-10 of 3.8 2009 //the transition table is events, then state, //then the transition itself (which has the event //and start state implied by their starting locations) //don't need to store the event; that's implicitly defined in the Table itself by location class TableRow{ public: TableRow() { for(int stateIndex = 0; stateIndex < cMaxStateID; ++stateIndex) { transitions[stateIndex] = nullptr; } } ~TableRow() { for(int stateIndex = 0; stateIndex < cMaxStateID; ++stateIndex) { Transition *t = transitions[stateIndex]; delete t; } } Transition *transitions[cMaxStateID]; //copy constructor for stl additions into the transition table below. }; /** * \brief ULTransitionTable * The transition table of all the ULEvents, new ULActions, and ULStates. * * Based roughly on the solutions in player2.cpp in the boost examples and this * so question: * http://stackoverflow.com/questions/1647631/c-state-machine-design * * The transition table is constructed of TableRows. Each row is based on an * event, and an event handler in the TransitionTable object takes a given * event, and then finds the given row. * * Then, given the current state of the connection, determines the appropriate * action to take and then the state to transition to next. * */ class ULTransitionTable { private: TableRow mTable[cMaxEventID]; public: ULTransitionTable(); void HandleEvent(Subject*s,ULEvent& inEvent, ULConnection& inConnection, bool& outWaitingForEvent, EEventID& outRaisedEvent) const; void PrintTable() const; //so that the table can be printed and verified against the DICOM standard }; } } #endif // GDCMULTRANSITIONTABLE_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULWritingCallback.cxx000066400000000000000000000046371412732066400255040ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmULWritingCallback.h" #include "gdcmFile.h" #include "gdcmWriter.h" namespace gdcm { namespace network { // writes the data set to disk immediately, rather than keeping it memory. // could have potential timing issues if datasets come over the network faster than // they can be written, which could be the case on very fast connections with slow disks void ULWritingCallback::HandleDataSet(const DataSet& inDataSet) { if (inDataSet.FindDataElement(Tag(0x0008,0x0018)) && !inDataSet.GetDataElement(Tag(0x0008,0x0018)).IsEmpty() ) { const DataElement &de = inDataSet.GetDataElement(Tag(0x0008,0x0018)); const ByteValue *bv = de.GetByteValue(); const std::string sopclassuid_str( bv->GetPointer(), bv->GetLength() ); Writer w; std::string theLoc = mDirectoryName + "/" + sopclassuid_str.c_str() + ".dcm"; w.SetFileName(theLoc.c_str()); File &f = w.GetFile(); f.SetDataSet(inDataSet); FileMetaInformation &fmi = f.GetHeader(); if( mImplicit ) fmi.SetDataSetTransferSyntax( TransferSyntax::ImplicitVRLittleEndian ); else fmi.SetDataSetTransferSyntax( TransferSyntax::ExplicitVRLittleEndian ); w.SetCheckFileMetaInformation( true ); if (!w.Write()) { gdcmErrorMacro("Failed to write " << sopclassuid_str.c_str() << std::endl); } else { gdcmDebugMacro( "Wrote " << sopclassuid_str.c_str() << " to disk. " << std::endl); } } else { gdcmErrorMacro( "Failed to write data set, could not find tag 0x0008, 0x0018" << std::endl); } DataSetHandled(); } void ULWritingCallback::HandleResponse(const DataSet& ) { } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmULWritingCallback.h000066400000000000000000000034761412732066400251310ustar00rootroot00000000000000/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef GDCMULCONNECTIONWRITINGCALLBACK_H #define GDCMULCONNECTIONWRITINGCALLBACK_H #include "gdcmULConnectionCallback.h" namespace gdcm { class DataSet; namespace network { /* \brief ULWritingCallback * \details This is the most basic of callbacks for how the ULConnectionManager handles * incoming datasets. DataSets are immediately written to disk as soon as they * are received. NOTE that if the incoming connection is faster than the disk * writing speed, this callback could cause some pileups! */ class GDCM_EXPORT ULWritingCallback : public ULConnectionCallback { std::string mDirectoryName; public: ULWritingCallback() = default; ~ULWritingCallback() override = default; //empty, for later inheritance ///provide the directory into which all files are written. void SetDirectory(const std::string& inDirectoryName) { mDirectoryName = inDirectoryName; } void HandleDataSet(const DataSet& inDataSet) override; void HandleResponse(const DataSet& inDataSet) override; }; } // end namespace network } // end namespace gdcm #endif //GDCMULCONNECTIONWRITINGCALLBACK_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmUserInformation.cxx000066400000000000000000000200271412732066400253160ustar00rootroot00000000000000/*========================================================================= 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 "gdcmUserInformation.h" #include "gdcmSwapper.h" #include "gdcmAsynchronousOperationsWindowSub.h" #include "gdcmRoleSelectionSub.h" #include "gdcmSOPClassExtendedNegociationSub.h" #include namespace gdcm { namespace network { const uint8_t UserInformation::ItemType = 0x50; const uint8_t UserInformation::Reserved2 = 0x00; struct RoleSelectionSubItems { void Print(std::ostream &os) const { std::vector::const_iterator it = RSSArray.begin(); for( ; it != RSSArray.end(); ++it ) { it->Print(os); } } const std::ostream &Write(std::ostream &os) const { std::vector::const_iterator it = RSSArray.begin(); for( ; it != RSSArray.end(); ++it ) { it->Write(os); } return os; } void AddTuple(const char *uid, uint8_t scurole, uint8_t scprole) { RoleSelectionSub rss; rss.SetTuple( uid, scurole, scprole ); RSSArray.push_back( rss ); } bool Empty() const { return RSSArray.empty(); } size_t Size() const { size_t s = 0; std::vector::const_iterator it = RSSArray.begin(); for( ; it != RSSArray.end(); ++it ) { s += it->Size(); } return s; } std::vector RSSArray; }; struct SOPClassExtendedNegociationSubItems { void Print(std::ostream &os) const { std::vector::const_iterator it = SOPCENSArray.begin(); for( ; it != SOPCENSArray.end(); ++it ) { it->Print(os); } } const std::ostream &Write(std::ostream &os) const { std::vector::const_iterator it = SOPCENSArray.begin(); for( ; it != SOPCENSArray.end(); ++it ) { it->Write(os); } return os; } void AddDefault(const char *uid) { SOPClassExtendedNegociationSub sub; sub.SetTuple( uid ); SOPCENSArray.push_back( sub ); } bool Empty() const { return SOPCENSArray.empty(); } size_t Size() const { size_t s = 0; std::vector::const_iterator it = SOPCENSArray.begin(); for( ; it != SOPCENSArray.end(); ++it ) { s += it->Size(); } return s; } std::vector SOPCENSArray; }; UserInformation::UserInformation() { AOWS = nullptr; RSSI = new RoleSelectionSubItems; SOPCENSI = new SOPClassExtendedNegociationSubItems; #if 0 RSSI->AddTuple("1.2.840.10008.5.1.4.1.1.2", 1, 1); // DEBUG RSSI->AddTuple("1.2.840.10008.5.1.4.1.1.4", 1, 1); // DEBUG RSSI->AddTuple("1.2.840.10008.5.1.4.1.1.7", 1, 1); // DEBUG SOPCENSI->AddDefault("1.2.840.10008.5.1.4.1.1.2"); // DEBUG SOPCENSI->AddDefault("1.2.840.10008.5.1.4.1.1.4"); // DEBUG SOPCENSI->AddDefault("1.2.840.10008.5.1.4.1.1.7"); // DEBUG #endif size_t t0 = MLS.Size(); size_t t1 = ICUID.Size(); size_t t2 = 0; //AOWS.Size(); size_t t3 = IVNS.Size(); ItemLength = (uint16_t)(t0 + t1 + t2 + t3); #if 0 if( !RSSI->Empty() ) ItemLength += RSSI->Size(); if( !SOPCENSI->Empty() ) ItemLength += SOPCENSI->Size(); #endif assert( (size_t)ItemLength + 4 == Size() ); } UserInformation::~UserInformation() { delete AOWS; delete SOPCENSI; delete RSSI; } std::istream &UserInformation::Read(std::istream &is) { //uint8_t itemtype = 0x0; //is.read( (char*)&itemtype, sizeof(ItemType) ); //assert( itemtype == ItemType ); uint8_t reserved2; is.read( (char*)&reserved2, sizeof(Reserved2) ); uint16_t itemlength; is.read( (char*)&itemlength, sizeof(ItemLength) ); SwapperDoOp::SwapArray(&itemlength,1); ItemLength = itemlength; uint8_t itemtype2 = 0x0; size_t curlen = 0; #if 0 RSSI->RSSArray.clear(); // DEBUG SOPCENSI->SOPCENSArray.clear(); // DEBUG #endif while( curlen < ItemLength ) { is.read( (char*)&itemtype2, sizeof(ItemType) ); switch ( itemtype2 ) { case 0x51: // MaximumLengthSub MLS.Read( is ); curlen += MLS.Size(); break; case 0x52: // ImplementationClassUIDSub ICUID.Read(is); curlen += ICUID.Size(); break; case 0x53: // AsynchronousOperationsWindowSub assert( !AOWS ); AOWS = new AsynchronousOperationsWindowSub; AOWS->Read( is ); curlen += AOWS->Size(); break; case 0x54: // RoleSelectionSub assert( RSSI ); { RoleSelectionSub rss; rss.Read( is ); curlen += rss.Size(); RSSI->RSSArray.push_back( rss ); } break; case 0x55: // ImplementationVersionNameSub IVNS.Read( is ); curlen += IVNS.Size(); break; case 0x56: // SOPClassExtendedNegociationSub assert( SOPCENSI ); { SOPClassExtendedNegociationSub sopcens; sopcens.Read( is ); curlen += sopcens.Size(); SOPCENSI->SOPCENSArray.push_back( sopcens ); } break; default: gdcmErrorMacro( "Unknown ItemType: " << std::hex << (int) itemtype2 ); curlen = ItemLength; // make sure to exit assert(0); break; } } assert( curlen == ItemLength ); assert( (size_t)ItemLength + 4 == Size() ); return is; } const std::ostream &UserInformation::Write(std::ostream &os) const { assert( (size_t)ItemLength + 4 == Size() ); os.write( (const char*)&ItemType, sizeof(ItemType) ); os.write( (const char*)&Reserved2, sizeof(Reserved2) ); uint16_t copy = ItemLength; SwapperDoOp::SwapArray(©,1); os.write( (const char*)©, sizeof(ItemLength) ); MLS.Write(os); ICUID.Write(os); if( AOWS ) { AOWS->Write(os); } if( !RSSI->Empty() ) { RSSI->Write(os); } IVNS.Write(os); if( !SOPCENSI->Empty() ) { SOPCENSI->Write(os); } assert( (size_t)ItemLength + 4 == Size() ); return os; } size_t UserInformation::Size() const { size_t ret = 0; ret += sizeof(ItemType); ret += sizeof(Reserved2); ret += sizeof(ItemLength); // len of ret += MLS.Size(); ret += ICUID.Size(); if( AOWS ) ret += AOWS->Size(); if( !RSSI->Empty() ) ret += RSSI->Size(); ret += IVNS.Size(); if( !SOPCENSI->Empty() ) ret += SOPCENSI->Size(); return ret; } void UserInformation::Print(std::ostream &os) const { os << "MaximumLengthSub: "; MLS.Print( os ); os << "ImplementationClassUIDSub: "; ICUID.Print( os ); if( AOWS ) { os << "AsynchronousOperationsWindowSub: "; AOWS->Print( os ); } if( !RSSI->Empty() ) { os << "RoleSelectionSub: "; RSSI->Print( os ); } os << "ImplementationVersionNameSub: "; IVNS.Print( os ); if( !SOPCENSI->Empty() ) { os << "SOPClassExtendedNegociationSub: "; SOPCENSI->Print( os ); } os << std::endl; } UserInformation &UserInformation::operator=(const UserInformation& ui) { ItemLength = ui.ItemLength; MLS = ui.MLS; ICUID = ui.ICUID; if( ui.AOWS ) { delete AOWS; AOWS = new AsynchronousOperationsWindowSub; *AOWS = *ui.AOWS; } *RSSI = *ui.RSSI; *SOPCENSI = *ui.SOPCENSI; IVNS = ui.IVNS; assert( (size_t)ItemLength + 4 == Size() ); return *this; } void UserInformation::AddRoleSelectionSub( RoleSelectionSub const & rss ) { RSSI->RSSArray.push_back( rss ); ItemLength = (uint16_t)(Size() - 4); assert( (size_t)ItemLength + 4 == Size() ); } void UserInformation::AddSOPClassExtendedNegociationSub( SOPClassExtendedNegociationSub const & sopcens ) { SOPCENSI->SOPCENSArray.push_back( sopcens ); ItemLength = (uint16_t)(Size() - 4); assert( (size_t)ItemLength + 4 == Size() ); } } // end namespace network } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmUserInformation.h000066400000000000000000000042171412732066400247460ustar00rootroot00000000000000/*========================================================================= 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 GDCMUSERINFORMATION_H #define GDCMUSERINFORMATION_H #include "gdcmTypes.h" #include "gdcmMaximumLengthSub.h" #include "gdcmImplementationVersionNameSub.h" #include "gdcmImplementationClassUIDSub.h" namespace gdcm { namespace network { class AsynchronousOperationsWindowSub; class RoleSelectionSub; struct RoleSelectionSubItems; class SOPClassExtendedNegociationSub; struct SOPClassExtendedNegociationSubItems; /** * \brief UserInformation * \details Table 9-16 * USER INFORMATION ITEM FIELDS * * TODO what is the goal of : * * Table 9-20 * USER INFORMATION ITEM FIELDS */ class UserInformation { public: UserInformation(); ~UserInformation(); std::istream &Read(std::istream &is); const std::ostream &Write(std::ostream &os) const; size_t Size() const; void Print(std::ostream &os) const; const MaximumLengthSub &GetMaximumLengthSub() const { return MLS; } MaximumLengthSub &GetMaximumLengthSub() { return MLS; } void AddRoleSelectionSub( RoleSelectionSub const & r ); void AddSOPClassExtendedNegociationSub( SOPClassExtendedNegociationSub const & s ); private: static const uint8_t ItemType; static const uint8_t Reserved2; uint16_t ItemLength; // len of MaximumLengthSub MLS; ImplementationClassUIDSub ICUID; AsynchronousOperationsWindowSub *AOWS; RoleSelectionSubItems *RSSI; SOPClassExtendedNegociationSubItems *SOPCENSI; ImplementationVersionNameSub IVNS; public: UserInformation(const UserInformation&) = delete; UserInformation &operator=(const UserInformation&); }; } // end namespace network } // end namespace gdcm #endif //GDCMUSERINFORMATION_H GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmWLMFindQuery.cxx000066400000000000000000000061341412732066400244630ustar00rootroot00000000000000/*========================================================================= 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 "gdcmWLMFindQuery.h" #include "gdcmAttribute.h" #include "gdcmSequenceOfItems.h" namespace gdcm { WLMFindQuery::WLMFindQuery() { mRootType = ePatientRootType; mHelpDescription = "Modality Worklist query"; } void WLMFindQuery::InitializeDataSet(const EQueryLevel& inQueryLevel) { // no level so no tags to add (void)inQueryLevel; } std::vector WLMFindQuery::GetTagListByLevel(const EQueryLevel& inQueryLevel) { // no level so no tags std::vector tags ; (void)inQueryLevel; return tags; } bool WLMFindQuery::ValidateQuery(bool inStrict) const { //if it's empty, it's not useful (void)inStrict; 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 bool theReturn = true ; DataSet validDs = GetValidDataSet(); theReturn &= ValidDataSet( ds, validDs ); return theReturn ; } UIDs::TSName WLMFindQuery::GetAbstractSyntaxUID() const { return UIDs::ModalityWorklistInformationModelFIND; } DataSet WLMFindQuery::GetValidDataSet() const { DataSet validDataSet ; Attribute<0x10,0x10> PatientName; validDataSet.Insert( PatientName.GetAsDataElement() ); Attribute<0x10,0x20> PatientId; validDataSet.Insert( PatientId.GetAsDataElement() ); gdcm::SmartPointer sqItemList = new gdcm::SequenceOfItems(); gdcm::DataElement scheduledProcedureStepSequence; scheduledProcedureStepSequence.SetTag( Tag(0x40,0x0100) ); scheduledProcedureStepSequence.SetVR( gdcm::VR::SQ ); scheduledProcedureStepSequence.SetValue( *sqItemList ); scheduledProcedureStepSequence.SetVLToUndefined(); validDataSet.Insert( scheduledProcedureStepSequence ); // Item Separator gdcm::Item item; //( Tag(0xfffe,0xe000) ); item.SetVLToUndefined(); Attribute<0x8,0x60> Modality ; item.GetNestedDataSet().Insert( Modality.GetAsDataElement() ); Attribute<0x40,0x1, VR::AE, VM::VM1> ScheduledStationAETitle ; item.GetNestedDataSet().Insert( ScheduledStationAETitle.GetAsDataElement() ); Attribute<0x40,0x2> ScheduledProcedureStepStartDate; item.GetNestedDataSet().Insert( ScheduledProcedureStepStartDate.GetAsDataElement() ); Attribute<0x40,0x3> ScheduledProcedureStepStartTime ; item.GetNestedDataSet().Insert( ScheduledProcedureStepStartTime.GetAsDataElement() ); Attribute<0x40,0x6> ScheduledPerformingPhysiciansName ; item.GetNestedDataSet().Insert( ScheduledPerformingPhysiciansName.GetAsDataElement() ); sqItemList->AddItem( item ); return validDataSet; } } // end namespace gdcm GDCM-3.0.10/Source/MessageExchangeDefinition/gdcmWLMFindQuery.h000066400000000000000000000024601412732066400241060ustar00rootroot00000000000000/*========================================================================= 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 GDCMWLMFindQuery_H #define GDCMWLMFindQuery_H #include "gdcmBaseRootQuery.h" namespace gdcm { /** * \brief PatientRootQuery * \details contains: the class which will produce a dataset for c-find with patient root */ class GDCM_EXPORT WLMFindQuery : public BaseRootQuery { friend class QueryFactory; public: WLMFindQuery(); // no sense here void InitializeDataSet(const EQueryLevel& inQueryLevel) override; std::vector GetTagListByLevel(const EQueryLevel& inQueryLevel) override; // validate query has required tag bool ValidateQuery(bool inStrict = true) const override; UIDs::TSName GetAbstractSyntaxUID() const override; protected : DataSet GetValidDataSet() const; }; } // end namespace gdcm #endif // GDCMWLMFindQuery_H GDCM-3.0.10/TODO000066400000000000000000000524171412732066400130130ustar00rootroot00000000000000PrepGroupName.cxx does not handle Pixel Data group name since it has a space in the name... ----------------------------------------------------------------------- gdcmDictPrinter allowed me to find bug in dclunie tool: gems.tpl:(0043,001b) VERS="GEM" VR="SS" VM="1" Owner="GEMS_PARM_01" ----------------------------------------------------------------------- dcmtk is confused: (0028,0034) IS [ 185\185] # 8, 1 Pixel Aspect Ratio ----------------------------------------------------------------------- Offer mapping from UID to Manufacturer: eg. 1.3.12.2.1107 -> SIEMENS ----------------------------------------------------------------------- > We use a Philips ENVISOR machine to do Cardiac TOE Echo. We are about > to produce a CD of some of the Echo loops. Can anyone suggest a good > DICOM to AVI converted for Echo loops. we have implemented a tool called "dcm2avi" that can be used for this purpose. Please send an email to dicom/at/offis/dot/de in case you are interested in an evaluation version of this program. ----------------------------------------------------------------------- from sup58_ft2.doc >CTDIvol (0018,9445) 2C Computed Tomography Dose Index (CTDIvol), im mGy according to IEC 60601-2-44, Ed.2.1 (Clause 29.1.103.4), The Volume CTDIvol. It describes the average dose for this frame for the selected CT conditions of operation. ----------------------------------------------------------------------- Calling dcmodify [1][2] with option --erase-tag should do what you want. ----------------------------------------------------------------------- You should be able to say: this file is a ACR NEMA read it ! So the wizard should be bypass and the discovery step can be skipped. ----------------------------------------------------------------------- Need to handle image rotation/flip (0070,0041) CS [Y] # 2, 1 ImageHorizontalFlip (0070,0042) US 270 # 2, 1 ImageRotation ----------------------------------------------------------------------- Parsing SQ can actually double the time to read a file /images/test_DCEMRI/04-004-4/MR-20070129/Perfusion/Perfusion_205_ ----------------------------------------------------------------------- The NEMA Enhanced CT and MR multi-frame test sets contain a couple of images that have Supplemental Palette Color LUTs. See: "ftp://medical.nema.org/medical/dicom/Multiframe/" and in particular: CT0012 CT0013 CT0014 GFUNCST2 MRVPWCB2 ----------------------------------------------------------------------- Wrong Private element in dcmtk: (0009,1227) TM [210959.000000] # 14, 1 LastMoveTime I found: diction.pfl:Table Zero Time,0009,SIEMENS CM VA0 CMS,27,TM,1 ----------------------------------------------------------------------- Make File Meta Information configurable from CMake ----------------------------------------------------------------------- Add progress to gdcmscanner ----------------------------------------------------------------------- FIX the reading of 3F3F SQ in: Bug_Philips_ItemTag_3F3F ----------------------------------------------------------------------- gdcm does not read the associated data in RT Object file - RTImage and RTDose. For RTImage pixel spacing is in 3002,0011 and position of upper left corner is in 3002,0012. ----------------------------------------------------------------------- Extract Mosaic as 3D volume: afni.nimh.nih.gov/pub/dist/doc/misc/DICOM/data/From_TomRoss/20021009-1-Toms_fMri/4-ep2d_bold_moco_ax3x3-192/image-00002-000042.IMA ----------------------------------------------------------------------- Correctly display: PHANTOM.MR.CARDIO_COEUR_S_QUENCE_DE_REP_RAGE.9.257.2008.03.20.14.53.25.578125.43151705.IMA ----------------------------------------------------------------------- TODO: need a gdcm::ExtractOverlayFromPixelDataFilter to rewrite a gdcm::Image ----------------------------------------------------------------------- Provide operator() == for String (should discard length, space char...) ----------------------------------------------------------------------- Should handle old Date format (with - separator) ----------------------------------------------------------------------- vtkMedicalImageProp user defined value should be written back to disk -> TODO: SQ will be difficult to handle ----------------------------------------------------------------------- Filter should use OpenMP ? ----------------------------------------------------------------------- GDCMFakeJPEG should be detected (at least a warning ----------------------------------------------------------------------- Hum, looks like vs 2007+1 can be used to redistribute binaries: http://www.microsoft.com/express/support/faq/ # Can I use Express Editions for commercial use? Yes, there are no licensing restrictions for applications built using Visual Studio Express Editions. Some random links: http://blogs.msdn.com/nikolad/archive/2006/04/11/Download-location-for-VCRedist.aspx http://blogs.msdn.com/vcblog/archive/2007/10/12/how-to-redistribute-the-visual-c-libraries-with-your-application.aspx ----------------------------------------------------------------------- TODO: /home/mmalaterre/Creatis/gdcmDataExtra/gdcmSampleData/images_of_interest/ITK-GDCM-1.2.2.saysExplicitVR-butIsImplicitVR.dcm ----------------------------------------------------------------------- ZSpacing for RTDoseStorage is not handled properly: bin/gdcmvtkGDCMTests TestvtkGDCMImageWriter BogugsItemAndSequenceLengthCorrected.dcm ----------------------------------------------------------------------- There are still some subtle issues with Enhanced modality: * what if frames are not order according to IPP ? * what is the intercept/slope are not constant throughout the frames ? ----------------------------------------------------------------------- Add support for namelink packaging ----------------------------------------------------------------------- Need a MediaStorage::IsRetired / UIDs::IsRetired ----------------------------------------------------------------------- What if: (0018,0084) DS [ 63.89.73.30] # 10,1 Imaging Frequency ----------------------------------------------------------------------- play with imageplanewdg / Orthoplanewidget http://www.itk.org/pipermail/insight-users/2006-January/016463.html ----------------------------------------------------------------------- window level in Enhanced objects is not handled ----------------------------------------------------------------------- wow cpack is finally documented: http://www.itk.org/Wiki/CMake:Component_Install_With_CPack ----------------------------------------------------------------------- TODO: gdcmData/GDCMPrinterDisplayUNasSQ.dcm ----------------------------------------------------------------------- http://mlblog.osdir.com/programming.swig/2003-02/msg00053.html ----------------------------------------------------------------------- doxygen is pretty advanced for this project: http://sourceforge.net/projects/od1n/ ----------------------------------------------------------------------- STL-based (non-validating) XML Parser http://www.codeguru.com/cpp/i-n/internet/xml/article.php/c3451/ ----------------------------------------------------------------------- There is subttle bug in the Part3 support: A sequence of identification numbers or codes used to identify the patient, which may or may not be human readable, and may or may not have been obtained from an implanted or attached device such as an RFID or barcode. If present, shall contain one or more items. An identification number or code used to identify the patient. Identifier of the Assigning Authority that issued the Patient ID. The type of identifier in this item. Defined Terms: TEXT RFID BARCODE Note: The identifier is coded as a string regardless of the type, not as a binary value. What this means is that 10,22 is Type 1 only within sequence 10,1002 ----------------------------------------------------------------------- Yet another brain dead philips DICOM image: gdcmDataExtra/gdcmBreakers/Unexpected-Sequence-Terminator/images/Philips-Intera_Unexpected_Sequence_Terminator_1.dcm (2005,e005) DS (CS) [75.0] # 4,1 Synergy Reconstruction Type ... (2005,e030) FL 79.9997\0 # 8,1 (2) ? ----------------------------------------------------------------------- Thread with Philips BigEndian/LittleEndian inversion http://www.creatis.insa-lyon.fr/pipermail/dcmlib/2004-November/000898.html ----------------------------------------------------------------------- Looks like ELSCINT1 is doing a group xx for element: {0x6003,0x0010,"ELSCINT1",VR::CS,VM::VM1,"Text Overlay Flag",false }, need to repeat for: {0x6005,0x0010,"ELSCINT1",VR::CS,VM::VM1,"Text Overlay Flag",false }, and so and so forth... ----------------------------------------------------------------------- SIEMENS MrProt / IDEA / Numaris stuff: apt-get source minc-tools conversion/dcm2mnc/dicom_to_minc.c ./conversion/dcm2mnc/siemens_to_dicom.c ./conversion/dcm2mnc/siemens_header_defs.h http://www.nmr.mgh.harvard.edu/~greve/dicom-unpack http://atonal.ucdavis.edu/matlab/fmri/spm5/spm_dicom_convert.m ----------------------------------------------------------------------- cmake export() might be helpful to cleanup cmakelists.txt ----------------------------------------------------------------------- BasicOffsetTable is never computed... ----------------------------------------------------------------------- Need a gdcm::DataSetToPythonDict class ----------------------------------------------------------------------- Need a gdcm::ApplyRuleFilter class where Addrule: void AddRule( void(*func)(DataElement &de) ) where void func(DataElement &de) { if( de.IsPrivate() ) { ds.Remove( de ); } } ----------------------------------------------------------------------- Fix the UseGDCM. So that user can do: FIND_PACKAGE(GDCM REQUIRED) INCLUDE( ${GDCM_USE_FILE} ) ADD_EXECUTABLE(bla bla.cxx) TARGET_LIBK_LIBRARIES(bla vtkgdcm) ----------------------------------------------------------------------- http://www.4bitterguys.com/phpBB2/viewtopic.php?t=7426 http://www.data-compression.info/ABC/index.htm http://www.geocities.com/truth_out_there/additionalinfo.html ----------------------------------------------------------------------- FIX data dict, missing bunch of old acr nema stuff ----------------------------------------------------------------------- Create a toplevel main gdcmswig.i to avoid code duplication for C# and python ----------------------------------------------------------------------- This is a SC, with Pixel Spacing and Rescale Slope/Intercept gdcmData/WeirdOverlayThingy.dcm Using gdcm2vtk will loose everything... ----------------------------------------------------------------------- C# has some sort of compilation in XML to construct the documentation... to investigate ----------------------------------------------------------------------- RegionOfInterestImageFilter is the streaming interface for ITKIO ----------------------------------------------------------------------- http://www.stack.nl/~dimitri/doxygen/external.html with tag file from: http://www.vtk.org/doc/release/5.2/ or: http://www.vtk.org/doc/nightly/ ----------------------------------------------------------------------- TODO: explicit TS for: LUTDATA_implicit_OW.dcm ----------------------------------------------------------------------- Fix gdcm::Sorter::SetSortFunction for wrapped language ----------------------------------------------------------------------- Add more siemens stuff from: dicom_to_minc.c apt-get source minc ----------------------------------------------------------------------- file meta header does not check for valid of imp class uid Need to be UIDGenerator::IsValid ----------------------------------------------------------------------- Bug gdcmconv should properly autorecompute explicit length for: BogusItemLengthImplicitPrivateAtt.dcm ----------------------------------------------------------------------- gdcmconv --squeeze to squeeze extra space (trailing) ----------------------------------------------------------------------- gdcmimg /usr/share/VTKData/Data/beach.jpg out.dcm gdcmraw out.dcm out.jpg -> out.jpg still contains the JFIF marker (color space...) ----------------------------------------------------------------------- BUG: SERIOUS gdcm does not allow creation of such file dcmcjpeg +fs 100 GE_DLX-8-MONO2-Multiframe.dcm /tmp/jpeg3.dcm tricky for jpeg 2000 ----------------------------------------------------------------------- Following same bug: need to fix gdcmconv --split 65536 for multiframe also need to check BasicOffset is properly discarded ----------------------------------------------------------------------- Can I handle SetImageFormat (invalid) properly ? eg. vtkImageData is single comp but ImageFormat=RGB ... ----------------------------------------------------------------------- FIXME: gdcmconv --deflated gdcmDataExtra/gdcmNonImageData/c15-5.dcm out.dcm could not read: gdcmDataExtra/gdcmNonImageData/c15-5.dcm ----------------------------------------------------------------------- Technically nothing prevent someone from using JPegcompress on PDF object So gdcm::ImageChangeTransferSyntax should let non-image pass ----------------------------------------------------------------------- Add support for invalid SC generated from ITK/gdcm 1.2.4 ----------------------------------------------------------------------- When converting an Enhanced CT, IOP is moved from root dataset to Sharedgroups but original attribute is kept (should be removed) same goes for WindowLevel, Rescale ... ----------------------------------------------------------------------- old SC and numberOfFrames > 1: ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm ----------------------------------------------------------------------- TODO: try to handle: gdcmData/gdcm-CR-DCMTK-16-NonSamplePerPix.dcm ----------------------------------------------------------------------- OPJ_LIMIT_DECODING to parse header only ----------------------------------------------------------------------- check volume_to_jp3d/ jp3d_to_volume to handle JPEG2000 Part 2 ----------------------------------------------------------------------- Write a gdcm2jp2 that would be cool ? Need to handle PALETTE_COLOR in JP2 palettetized (PCLR) There is only one problem with slope/rescale -> float ----------------------------------------------------------------------- Private tags extracted from private DCS is cool, but one would also need Defined terms, that would be *very* cool ! ----------------------------------------------------------------------- Amicas JP2 to DICOM: http://www.mikekristofferson.com/misc/mri/amicas-patients/ ----------------------------------------------------------------------- Prepare a DICOM file with VR:UN element with Value Length odd ... what is the padding then ? ----------------------------------------------------------------------- Add example of JPC (redundancy 3D volume / J2K) ----------------------------------------------------------------------- Create a PDF Storage class with a trailing Pixel Data element to test broken DICOM implementation ----------------------------------------------------------------------- Prepare a Basic Pixel Spacing Calibration example but with SC SOP so that we have Nominal Scanned Pixel Spacing case... ----------------------------------------------------------------------- I think there is a bug in ByteValue::SetByte. What if byte buffer is 0xfffffffe long ? internally I ++ the length, which would make it an undefined length. ----------------------------------------------------------------------- Get rid of polarssl now that OpenSSL completely replaces it ... I might even have to get rid of OpenSSL http://gdcm.sourceforge.net/wiki/index.php/Tools/openssl#Giving_up_on_OpenSSL ----------------------------------------------------------------------- gdcmdump map-uid-names ----------------------------------------------------------------------- +/* + * Windows _snprintf and _vsnprintf are not compatible to linux versions. + * Result value is not size of buffer needed, but -1 if no fit is possible. + * + * This function tries to 'fix' this by at least suggesting enlarging the + * size by 20. + */ -> polarssl ----------------------------------------------------------------------- Update charls for bug fix (16bits RGB still not working) ----------------------------------------------------------------------- vtkGDCMImageReader::GetDirectionCosines(uint i) ----------------------------------------------------------------------- http://blog.mozilla.com/nnethercote/2009/02/27/eliminating-undefined-values-with-valgrind-the-easy-way/ > And just think, if C++ warned about fields uninitialised by constructors, I think adding -Weffc++ to the CXXFLAGS should help about that. ----------------------------------------------------------------------- gdcmimg should strip the JFIF / JP2 markers ----------------------------------------------------------------------- TODO: to get rid of openssl on Win32 one could use the CryptoAPI: [Example C Program: Signing a Message and Verifying a Message Signature] http://msdn.microsoft.com/en-us/library/aa382372.aspx http://www.ureader.com/msg/16591281.aspx ----------------------------------------------------------------------- Fix gdcm::spacing before release CP-586 ----------------------------------------------------------------------- This is part of CPack's API. There is no API in the make system to use this feature. You have to run "make preinstall" to prepare the installation and then run "cmake -DCOMPONENT=Runtime -P cmake_install.cmake" to do the component-specific installation. ----------------------------------------------------------------------- vtkGDCMImageReader:: SetReferencedStudyUID() to allow creation of DERIVED / SECONDARY ----------------------------------------------------------------------- Make sure Overlay can reference original instance question: image is a reslice of original image, how do I map to original UID ? ----------------------------------------------------------------------- * There is a current limitation of not handling Referenced SOP Class UID / * Referenced SOP Instance UID simply because the gdcm::Scanner does not allow us * See PS 3.11 / Table D.3-2 STD-GEN Additional DICOMDIR Keys ----------------------------------------------------------------------- RTSTRUCT support http://www.nabble.com/How-to-load-sequence-items-td20622657.html Re: How to load sequence items ----------------------------------------------------------------------- # CPP check find_program(CPPCHECK_EXECUTABLE NAMES cppcheck DOC "cppcheck - static check tool") add_custom_target (cppcheck ${CPPCHECK_EXECUTABLE} -a -f -q ${GDCM_SOURCE_DIR}" COMMENT "Checking C++ code") ----------------------------------------------------------------------- Reduce excess linkage: http://wiki.mandriva.com/en/Development/Tasks/Packaging/Problems/Underlinking http://wiki.mandriva.com/en/Overlinking ----------------------------------------------------------------------- Generate doc for python automatically ----------------------------------------------------------------------- Display Shutter: It should not invert to white when radiologist invert lookup table ----------------------------------------------------------------------- Private Tags IMPAC http://www.varian.com/media/oncology/services_and_support/pdf/dicom/System_Server_8.2_8.5_8.6.pdf http://www.varian.com/media/oncology/services_and_support/pdf/dicom/System_Server_DCS.pdf ----------------------------------------------------------------------- http://www.w3.org/People/Bos/JPEG-XMP/ rdjpgxmp : extract XMP metadata from a JPEG file ----------------------------------------------------------------------- PDFParser: http://www.codeproject.com/kb/cpp/ExtractPDFText.aspx http://www.codeproject.com/KB/recipes/mgpdfreader.aspx passepartout-0.6› src› ps› pdfparser.ccC http://www.cocoabuilder.com/archive/cocoa/114723-pdf-meta-data.html#115418 http://blog.didierstevens.com/programs/pdf-tools/ http://sourceforge.net/projects/pdfsqueezer/develop ----------------------------------------------------------------------- FIX Iterator in gdcm::Dict ----------------------------------------------------------------------- Structured REport for Presentation ----------------------------------------------------------------------- WADO instead of DICOM protocol ----------------------------------------------------------------------- http://assimp.sourceforge.net/main_license.html ----------------------------------------------------------------------- Missing dict for: SIEMENS MED SP DXMG WH AWS 1 http://www.medical.siemens.com/siemens/en_GLOBAL/rg_marcom_FBAs/files/brochures/DICOM/sp_mammo/WH_AWS_VB30_dcs_ekl.pdf ----------------------------------------------------------------------- Other quantization algorithm: http://alpng.sourceforge.net/octree.html ----------------------------------------------------------------------- http://www.hitachimed.com/idc/groups/hitachimedical/documents/supportingdocumentpdf/poc_013216.pdf GDCM-3.0.10/Testing/000077500000000000000000000000001412732066400137275ustar00rootroot00000000000000GDCM-3.0.10/Testing/.NoDartCoverage000066400000000000000000000000471412732066400165740ustar00rootroot00000000000000# do not do coverage in this directory GDCM-3.0.10/Testing/CMakeLists.txt000066400000000000000000000040411412732066400164660ustar00rootroot00000000000000 find_package(DCMTK) find_package(DICOM3TOOLS) # Special CMake Module required when doing Python Testing if(GDCM_WRAP_PYTHON) include(${GDCM_SOURCE_DIR}/CMake/UsePythonTest.cmake) endif() # Special CMake Module required when doing Java Testing if(GDCM_WRAP_JAVA) include(${GDCM_SOURCE_DIR}/CMake/UseJavaTest.cmake) endif() # Special CMake Module required when doing C# Testing if(GDCM_WRAP_CSHARP) include(${GDCM_SOURCE_DIR}/CMake/UseCSharpTest.cmake) endif() add_subdirectory( Source ) #----------------------------------------------------------------------------- # Here is one cool test: you can pretty much test all configuration using # ctest...well except one, the case where a user set BUILD_TESTING=OFF # since this would deactivate the dashboard and would not submit...doh! # So instead let's create a test that would build gdcm with this option if(GDCM_TEST_BOOTSTRAP) add_test(BuildGDCM ${CMAKE_CTEST_COMMAND} --build-and-test ${GDCM_SOURCE_DIR} ${GDCM_BINARY_DIR}/GDCMLocal --build-two-config --build-generator ${CMAKE_GENERATOR} --build-makeprogram ${CMAKE_MAKE_PROGRAM} --build-project GDCMLOCAL --build-options -DGDCM_BUILD_TESTING:BOOL=OFF -DGDCM_BUILD_SHARED_LIBS:BOOL=ON -DGDCM_WRAP_PYTHON:BOOL=ON -DGDCM_WRAP_CSHARP:BOOL=ON -DGDCM_SUPPORT_BROKEN_IMPLEMENTATION:BOOL=OFF ) add_test(InstallGDCM ${CMAKE_CTEST_COMMAND} --build-and-test ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} --build-generator ${CMAKE_GENERATOR} --build-project GDCM --build-makeprogram ${CMAKE_MAKE_PROGRAM} --build-noclean --build-target install ) add_test(BuildStaticGDCM ${CMAKE_CTEST_COMMAND} --build-and-test ${GDCM_SOURCE_DIR} ${GDCM_BINARY_DIR}/GDCMLocal2 --build-two-config --build-generator ${CMAKE_GENERATOR} --build-makeprogram ${CMAKE_MAKE_PROGRAM} --build-project GDCMLOCAL2 --build-options -DGDCM_BUILD_TESTING:BOOL=ON -DGDCM_BUILD_SHARED_LIBS:BOOL=OFF -DGDCM_SUPPORT_BROKEN_IMPLEMENTATION:BOOL=OFF -DGDCM_LEGACY_REMOVE:BOOL=ON --test-command ${CMAKE_CTEST_COMMAND} ) endif() GDCM-3.0.10/Testing/Data/000077500000000000000000000000001412732066400146005ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/000077500000000000000000000000001412732066400151675ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/Attribute/000077500000000000000000000000001412732066400171325ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/Attribute/CMakeLists.txt000066400000000000000000000000001412732066400216600ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/CMakeLists.txt000066400000000000000000000015651412732066400177360ustar00rootroot00000000000000# All the tests # ADD_SUBDIRECTORY is required here to properly get the definition variables later on: add_subdirectory(Data) # Get the variables defined in Data add_subdirectory: get_directory_property(gdcm_data_dicomdir_filenames_glob DIRECTORY Data DEFINITION GDCM_DATA_DICOMDIR_FILENAMES_GLOB) get_directory_property(gdcm_data_image_filenames_glob DIRECTORY Data DEFINITION GDCM_DATA_IMAGE_FILENAMES_GLOB) get_directory_property(gdcm_data_filenames_glob DIRECTORY Data DEFINITION GDCM_DATA_FILENAMES_GLOB) get_directory_property(black_list_reader DIRECTORY Data DEFINITION BLACK_LIST_READER) add_subdirectory( Attribute ) add_subdirectory( Common ) add_subdirectory( DataDictionary ) add_subdirectory( DataStructureAndEncodingDefinition ) add_subdirectory( InformationObjectDefinition ) add_subdirectory( MediaStorageAndFileFormat ) add_subdirectory( MessageExchangeDefinition ) GDCM-3.0.10/Testing/Source/Common/000077500000000000000000000000001412732066400164175ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/Common/CMakeLists.txt000066400000000000000000000001171412732066400211560ustar00rootroot00000000000000add_subdirectory(Cxx) if(GDCM_WRAP_PYTHON) add_subdirectory(Python) endif() GDCM-3.0.10/Testing/Source/Common/Cxx/000077500000000000000000000000001412732066400171615ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/Common/Cxx/CMakeLists.txt000066400000000000000000000024511412732066400217230ustar00rootroot00000000000000# Define the tests for Common # Common set(Common_TEST_SRCS TestVersion.cxx TestCommand.cxx TestCryptographicMessageSyntax.cxx TestDummyValueGenerator.cxx TestASN1.cxx TestTesting.cxx TestSystem3.cxx TestSwapper.cxx TestByteSwap.cxx TestString1.cxx TestString2.cxx TestTerminal.cxx TestFilenameGenerator.cxx TestObject.cxx TestSmartPointer.cxx TestSwapCode.cxx TestSystem1.cxx TestSystem2.cxx TestTrace.cxx TestTypes.cxx TestUnpacker12Bits.cxx TestBase64.cxx TestLog2.cxx ) if(GDCM_DATA_ROOT) list(APPEND Common_TEST_SRCS TestDirectory.cxx TestFilename.cxx TestMD5.cxx ) if(GDCM_USE_SYSTEM_OPENSSL) list(APPEND Common_TEST_SRCS TestSHA1.cxx) endif() endif() # Add the include paths include_directories( "${GDCM_BINARY_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition" ) create_test_sourcelist(CommonTests gdcmCommonTests.cxx ${Common_TEST_SRCS} EXTRA_INCLUDE gdcmTestDriver.h ) add_executable(gdcmCommonTests ${CommonTests}) target_link_libraries(gdcmCommonTests gdcmCommon) # Loop over files and create executables foreach(name ${Common_TEST_SRCS}) get_filename_component(testname ${name} NAME_WE) add_test(NAME ${testname} COMMAND gdcmCommonTests ${testname}) endforeach() GDCM-3.0.10/Testing/Source/Common/Cxx/TestASN1.cxx000066400000000000000000000016071412732066400212530ustar00rootroot00000000000000/*========================================================================= 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 "gdcmASN1.h" struct MyASN1 : public gdcm::ASN1 { int TestPBKDF2() { return this->gdcm::ASN1::TestPBKDF2(); } }; int TestASN1(int argc, char *argv[]) { if( argc < 1 ) { return 1; } const char *filename = argv[1]; MyASN1 asn1; asn1.ParseDumpFile( filename ); asn1.TestPBKDF2(); return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestBase64.cxx000066400000000000000000000053751412732066400216030ustar00rootroot00000000000000/*========================================================================= 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 "gdcmBase64.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include int TestBase64(int , char *[]) { const char str[] = "GDCM Test Base64 Encoding"; //const char str64[] = "R0RDTSBUZXN0IEJhc2U2NCBFbmNvZGluZwA="; (contains trailing \0 ) const char str64[] = "R0RDTSBUZXN0IEJhc2U2NCBFbmNvZGluZw=="; //std::cout << "sizeof:" << sizeof(str) << std::endl; //std::cout << "strlen:" << strlen(str) << std::endl; const size_t l1 = gdcm::Base64::GetEncodeLength( str, strlen(str) ); if( l1 != 36 ) { std::cerr << "Fail 1: " << l1 << std::endl; return 1; } char buffer[256] = {}; if( l1 > sizeof(buffer) ) { std::cerr << "Fail 2" << std::endl; return 1; } size_t l2 = gdcm::Base64::Encode( buffer, sizeof(buffer), str, strlen(str) ); if( l2 == 0 ) { std::cerr << "Fail 3: " << l2 << std::endl; return 1; } if( strcmp( buffer, str64 ) != 0 ) { std::cerr << "Found: " << buffer << " instead of " << str64 << std::endl; return 1; } size_t lbuffer = strlen(buffer); if( lbuffer != l1 ) { std::cerr << "Fail 4" << std::endl; return 1; } const size_t l3 = gdcm::Base64::GetDecodeLength( buffer, l1 ); if( l3 != 25 ) { std::cerr << "Fail 5: " << l3 << std::endl; return 1; } if( l3 != sizeof(str) - 1 ) { std::cerr << "Fail 6" << std::endl; return 1; } char buffer2[256]; if( l3 > sizeof(buffer2) ) { std::cerr << "Fail 7" << std::endl; return 1; } const size_t l4 = gdcm::Base64::Decode( buffer2, sizeof(buffer2), buffer, l1); if( l4 == 0 ) { std::cerr << "Fail 8" << std::endl; return 1; } if( strncmp( str, buffer2, strlen(str) ) != 0 ) { std::cerr << "Fail 9: " << str << " vs " << buffer2 << std::endl; return 1; } const unsigned char bin[] = { 0x00, 0x00, 0xc8, 0x43 }; const char bin64[] = "AADIQw=="; const size_t l5 = gdcm::Base64::Decode( buffer2, sizeof(buffer2), bin64, strlen(bin64) ); if( l5 == 0 ) { std::cerr << "Fail 10" << std::endl; return 1; } if( memcmp( bin, buffer2, sizeof(bin) ) != 0 ) { std::cerr << "Fail 11" << std::endl; return 1; } return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestByteSwap.cxx000066400000000000000000000071641412732066400223130ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTypes.h" #include "gdcmSwapCode.h" #include "gdcmByteSwap.h" #include // memcpy int myfunc() { char vl_str[4]; const char raw[] = "\000\000\000\004"; memcpy(vl_str, raw, 4); uint32_t vl; gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem((uint32_t*)(&vl_str), gdcm::SwapCode::BigEndian, 1); memcpy(&vl, vl_str, 4); if( vl != 0x00000004 ) { std::cerr << std::hex << "vl: " << vl << std::endl; return 1; } gdcm::ByteSwap::SwapFromSwapCodeIntoSystem(vl, gdcm::SwapCode::LittleEndian); if( vl != 0x00000004 ) { std::cerr << std::hex << "vl: " << vl << std::endl; return 1; } gdcm::ByteSwap::SwapFromSwapCodeIntoSystem(vl, gdcm::SwapCode::BigEndian); if( vl != 0x4000000 ) { std::cerr << std::hex << "vl: " << vl << std::endl; return 1; } return 0; } int TestByteSwap(int , char *[]) { gdcm::SwapCode sc = gdcm::SwapCode::Unknown; if ( gdcm::ByteSwap::SystemIsBigEndian() ) { sc = gdcm::SwapCode::BigEndian; } else if ( gdcm::ByteSwap::SystemIsLittleEndian() ) { sc = gdcm::SwapCode::LittleEndian; } if( sc == gdcm::SwapCode::Unknown ) { std::cerr << "unk" << std::endl; return 1; } //std::cout << "sc: " << sc << std::endl; uint16_t t = 0x1234; gdcm::ByteSwap::SwapFromSwapCodeIntoSystem(t, sc); if( sc == gdcm::SwapCode::BigEndian ) { if( t != 0x3412 ) { std::cerr << std::hex << "t: " << t << std::endl; return 1; } // ok test pass rest value to old one t = 0x1234; } else if ( sc == gdcm::SwapCode::LittleEndian ) { if( t != 0x1234 ) { std::cerr << std::hex << "t: " << t << std::endl; return 1; } } union { char n[2]; uint16_t tn; } u16; memcpy(u16.n, &t, 2 ); gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem(&u16.tn, sc, 1); uint16_t tn = u16.tn; if( sc == gdcm::SwapCode::BigEndian ) { if( tn != 0x3412 ) { std::cerr << std::hex << "tn: " << tn << std::endl; return 1; } // ok test pass rest value to old one t = 0x1234; } else if ( sc == gdcm::SwapCode::LittleEndian ) { if( tn != 0x1234 ) { std::cerr << std::hex << "tn: " << tn << std::endl; return 1; } } gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem(&u16.tn, gdcm::SwapCode::BigEndian, 1); tn = u16.tn; if( sc == gdcm::SwapCode::LittleEndian ) { if( tn != 0x3412 ) { std::cerr << std::hex << "tn: " << tn << std::endl; return 1; } } else if ( sc == gdcm::SwapCode::BigEndian ) { if( tn != 0x1234 ) { std::cerr << std::hex << "tn: " << tn << std::endl; return 1; } } if( myfunc() ) { return 1; } uint16_t array[] = { 0x1234 }; gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem(array, gdcm::SwapCode::BigEndian,1); if ( array[0] != 0x3412 ) { std::cerr << std::hex << "array: " << array[0] << std::endl; return 1; } return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestCommand.cxx000066400000000000000000000020201412732066400221150ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCommand.h" #include "gdcmEvent.h" #include "gdcmSmartPointer.h" using gdcm::SmartPointer; struct Watcher {}; void foo(gdcm::Command *c) { c->Execute((gdcm::Subject*)nullptr, gdcm::AnyEvent() ); } int TestCommand(int , char *[]) { SmartPointer > mc = gdcm::MemberCommand::New(); foo(mc); SmartPointer > smc = gdcm::SimpleMemberCommand::New(); foo(smc); return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestCryptographicMessageSyntax.cxx000066400000000000000000000267431412732066400261130ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCryptoFactory.h" #include #include #include #include #include "gdcmFilename.h" #include "gdcmTesting.h" static bool LoadFile(const char * filename, char* & buffer, size_t & bufLen) { FILE * f = fopen(filename, "rb"); if (f == nullptr) { //gdcmErrorMacro("Couldn't open the file: " << filename); return false; } fseek(f, 0L, SEEK_END); long sz = ftell(f); rewind(f); buffer = new char[sz]; bufLen = sz; while (sz) sz -= (long)fread(buffer + bufLen - sz, sizeof(char), sz, f); return true; } static const gdcm::CryptographicMessageSyntax::CipherTypes ciphers[] = { gdcm::CryptographicMessageSyntax::AES128_CIPHER, gdcm::CryptographicMessageSyntax::AES192_CIPHER, gdcm::CryptographicMessageSyntax::AES256_CIPHER, gdcm::CryptographicMessageSyntax::DES3_CIPHER }; static std::pair cip2str_data[] = { std::make_pair(gdcm::CryptographicMessageSyntax::AES128_CIPHER, "AES128"), std::make_pair(gdcm::CryptographicMessageSyntax::AES192_CIPHER, "AES192"), std::make_pair(gdcm::CryptographicMessageSyntax::AES256_CIPHER, "AES256"), std::make_pair(gdcm::CryptographicMessageSyntax::DES3_CIPHER, "3DES") }; static std::map cip2str(cip2str_data, cip2str_data + sizeof cip2str_data / sizeof cip2str_data[0]); const char * const tstr = "12345"; const size_t tstr_l = strlen(tstr); #define BUFSZ 5000 bool TestCMSProvider(gdcm::CryptographicMessageSyntax& cms, const char * provName) { const std::string certpath = gdcm::Filename::Join(gdcm::Testing::GetSourceDirectory(), "/Testing/Source/Data/certificate.pem" ); const std::string keypath = gdcm::Filename::Join(gdcm::Testing::GetSourceDirectory(), "/Testing/Source/Data/privatekey.pem" ); const std::string encrypted_vector = gdcm::Filename::Join(gdcm::Testing::GetSourceDirectory(), "/Testing/Source/Data/encrypted_text" ); bool ret = true; for (unsigned int i = 0; i < 4; i++) { char encout[BUFSZ] = {0}, decout[BUFSZ] = {0}; size_t encoutlen = BUFSZ, decoutlen = BUFSZ; cms.SetCipherType(ciphers[i]); bool encryptSuccess = cms.Encrypt(encout, encoutlen, tstr, tstr_l); if (!encryptSuccess) { std::cerr << provName << " using " << cip2str[ciphers[i]] << ": encryption failed" << std::endl; ret = false; continue; } bool decryptSuccess = cms.Decrypt(decout, decoutlen, encout, encoutlen); if (!decryptSuccess) { std::cerr << provName << " using " << cip2str[ciphers[i]] << ": decryption failed" << std::endl; ret = false; continue; } if (decoutlen != tstr_l) { std::cerr << provName << " using " << cip2str[ciphers[i]] << ": decryted length different from original (" << decoutlen << " != " << tstr_l << ")" << std::endl; ret = false; continue; } if (memcmp(tstr, decout, tstr_l) != 0) { std::cerr << provName << " using " << cip2str[ciphers[i]] << ": decryted data different from original" << std::endl; ret = false; continue; } } return ret; } bool TestCMSVector(gdcm::CryptographicMessageSyntax& cms, const char * provName) { char decout[BUFSZ] = {0}; size_t decoutlen = BUFSZ; std::string encrypted_filename = gdcm::Filename::Join(gdcm::Testing::GetSourceDirectory(), "/Testing/Source/Data/encrypted_text" ); const char * tv_plaintext = "1234567890abcdefghijklmnopqrstuvwxyz"; size_t tv_plaintext_len = strlen(tv_plaintext); char * test_vector; // FIXME : should I delete test_vector ? size_t tvlen; if (!LoadFile(encrypted_filename.c_str(), test_vector, tvlen)) { std::cerr << "Couldn't load encrypted file: " << encrypted_filename << std::endl; return false; } bool decryptSuccess = cms.Decrypt(decout, decoutlen, test_vector, tvlen); if (!decryptSuccess) { std::cerr << provName << " test vector decryption failed" << std::endl; return false; } if (decoutlen != tv_plaintext_len) { std::cerr << provName << " test vector decryted length different from original (" << decoutlen << " != " << tstr_l << ")" << std::endl; return false; } if (memcmp(tv_plaintext, decout, tv_plaintext_len) != 0) { std::cerr << provName << " test vector decryted data different from original" << std::endl; return false; } return true; } bool TestCMSCompatibility(gdcm::CryptographicMessageSyntax& cms1, const char * provName1, gdcm::CryptographicMessageSyntax& cms2, const char * provName2) { const std::string encrypted_vector = gdcm::Filename::Join(gdcm::Testing::GetSourceDirectory(), "/Testing/Source/Data/encrypted_text" ); bool ret = true; for (int i = 0; i < 4; i++) { char encout[BUFSZ] = {0}, decout[BUFSZ] = {0}; size_t encoutlen = BUFSZ, decoutlen = BUFSZ; cms1.SetCipherType(ciphers[i]); cms2.SetCipherType(ciphers[i]); bool encryptSuccess = cms1.Encrypt(encout, encoutlen, tstr, tstr_l); if (!encryptSuccess) { std::cerr << provName1 << " & " << provName2 << " using " << cip2str[ciphers[i]] << ": encryption failed" << std::endl; ret = false; break; } bool decryptSuccess = cms2.Decrypt(decout, decoutlen, encout, encoutlen); if (!decryptSuccess) { std::cerr << provName1 << " & " << provName2 << " using " << cip2str[ciphers[i]] << ": decryption failed" << std::endl; ret = false; break; } if (decoutlen != tstr_l) { std::cerr << provName1 << " & " << provName2 << " using " << cip2str[ciphers[i]] << ": decryted length different from original (" << decoutlen << " != " << tstr_l << ")" << std::endl; ret = false; break; } if (memcmp(tstr, decout, tstr_l) != 0) { std::cerr << provName1 << " & " << provName2 << " using " << cip2str[ciphers[i]] << ": decryted data different from original" << std::endl; ret = false; break; } } /* char encout[BUFSZ] = {0}, decout[BUFSZ] = {0}; size_t encoutlen = BUFSZ, decoutlen = BUFSZ; for (int i = 0; i < 4; i++) { bool ret = true; char encout[BUFSZ] = {0}, decout[BUFSZ] = {0}; size_t encoutlen = BUFSZ, decoutlen = BUFSZ; cms1.SetCipherType(ciphers[i]); cms2.SetCipherType(ciphers[i]); //cms2.Encrypt(encout, encoutlen, tstr, tstr_l); //cms1.Decrypt(decout, decoutlen, encout, encoutlen); //assert(decoutlen == tstr_l); //assert(memcmp(tstr, decout, tstr_l) == 0); bool encryptSuccess = cms1.Encrypt(encout, encoutlen, tstr, tstr_l); if (!encryptSuccess) { std::cerr << provName1 << " & " << provName2 << " using " << cip2str[ciphers[i]] << ": encryption failed" << std::endl; ret = false; break; } bool decryptSuccess = cms2.Decrypt(decout, decoutlen, encout, encoutlen); if (!decryptSuccess) { std::cerr << provName1 << " & " << provName2 << " using " << cip2str[ciphers[i]] << ": decryption failed" << std::endl; ret = false; break; } if (decoutlen != tstr_l) { std::cerr << provName1 << " & " << provName2 << " using " << cip2str[ciphers[i]] << ": decryted length different from original (" << decoutlen << " != " << tstr_l << ")" << std::endl; ret = false; break; } if (memcmp(tstr, decout, tstr_l) != 0) { std::cerr << provName1 << " & " << provName2 << " using " << cip2str[ciphers[i]] << ": decryted data different from original" << std::endl; ret = false; break; } }*/ return ret; } int TestCryptographicMessageSyntax(int, char *[]) { std::string certpath = gdcm::Filename::Join(gdcm::Testing::GetSourceDirectory(), "/Testing/Source/Data/certificate.pem" ); std::string keypath = gdcm::Filename::Join(gdcm::Testing::GetSourceDirectory(), "/Testing/Source/Data/privatekey.pem" ); bool bret = true; //typedef std::tuple StringCMSPairType; std::vector availableCMS; std::vector availableCMSName; #ifdef GDCM_USE_SYSTEM_OPENSSL gdcm::CryptoFactory* osslp7 = gdcm::CryptoFactory::GetFactoryInstance(gdcm::CryptoFactory::OPENSSLP7); std::unique_ptr ocmsp7(osslp7->CreateCMSProvider()); ocmsp7->ParseKeyFile(keypath.c_str()); ocmsp7->ParseCertificateFile(certpath.c_str()); bret = TestCMSProvider(*ocmsp7, "OpenSSL PKCS7") && bret; bret = TestCMSVector(*ocmsp7, "OpenSSL PKCS7") && bret; availableCMS.push_back(ocmsp7.get()); availableCMSName.push_back("OpenSSL PKCS7"); #endif #ifdef GDCM_USE_SYSTEM_OPENSSL #ifdef GDCM_HAVE_CMS_RECIPIENT_PASSWORD gdcm::CryptoFactory* ossl = gdcm::CryptoFactory::GetFactoryInstance(gdcm::CryptoFactory::OPENSSL); std::unique_ptr ocms(ossl->CreateCMSProvider()); ocms->ParseKeyFile(keypath.c_str()); ocms->ParseCertificateFile(certpath.c_str()); bret = TestCMSProvider(*ocms, "OpenSSL CMS") && bret; bret = TestCMSVector(*ocms, "OpenSSL CMS") && bret; availableCMS.push_back(ocms.get()); availableCMSName.push_back("OpenSSL CMS"); #endif #endif #ifdef WIN32 gdcm::CryptoFactory* capi = gdcm::CryptoFactory::GetFactoryInstance(gdcm::CryptoFactory::CAPI); std::unique_ptr ccms(capi->CreateCMSProvider()); ccms->ParseCertificateFile(certpath.c_str()); ccms->ParseKeyFile(keypath.c_str()); bret = TestCMSProvider(*ccms, "CAPI") && bret; bret = TestCMSVector(*ccms, "CAPI") && bret; availableCMS.push_back(ccms.get()); availableCMSName.push_back("CAPI"); #endif for (size_t i = 0; i < availableCMS.size(); ++i) for (size_t j = i+1; j < availableCMS.size(); ++j) bret = TestCMSCompatibility(*availableCMS[i], availableCMSName[i].c_str(), *availableCMS[j], availableCMSName[j].c_str()) && bret; return (bret ? 0 : 1); } int TestPasswordBasedEncryption(int, char *[]) { const char *directory = gdcm::Testing::GetDataRoot(); std::string encrypted_dicomdir = gdcm::Filename::Join(directory, "/securedicomfileset/DICOMDIR" ); std::string encrypted_image = gdcm::Filename::Join(directory, "/securedicomfileset/IMAGES/IMAGE1" ); #ifdef GDCM_USE_SYSTEM_OPENSSL gdcm::CryptoFactory* ossl = gdcm::CryptoFactory::GetFactoryInstance(gdcm::CryptoFactory::OPENSSL); std::unique_ptr ocms(ossl->CreateCMSProvider()); ocms->SetPassword("password", strlen("password")); if (!TestCMSProvider(*ocms, "OpenSSL")) return 1; char decout[BUFSZ] = {0}; size_t decoutlen = BUFSZ; char * ddir = new char[5000]; size_t ddirlen = 5000; LoadFile(encrypted_dicomdir.c_str(), ddir, ddirlen); bool decryptSuccess = ocms->Decrypt(decout, decoutlen, ddir, ddirlen); if (!decryptSuccess) { std::cerr << "OpenSSL sample DICOMDIR decryption failed" << std::endl; return 1; } if (decoutlen == 0) { std::cerr << "OpenSSL sample DICOMDIR decrypted length == 0" << std::endl; return 1; } #endif return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestDirectory.cxx000066400000000000000000000034061412732066400225140ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDirectory.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include // atoi int TestOneDirectory(const char *path, bool recursive = false ) { if( !gdcm::System::FileIsDirectory(path) ) { std::cerr << path << " is not a directory" << std::endl; return 1; } gdcm::Directory d; d.Load( path, recursive ); //d.Print( std::cout ); if( d.GetToplevel() != path ) { std::cerr << d.GetToplevel() << " != " << path << std::endl; return 1; } gdcm::Directory::FilenamesType const &files = d.GetFilenames(); for(gdcm::Directory::FilenamesType::const_iterator it = files.begin(); it != files.end(); ++it ) { const char *filename = it->c_str(); if( !gdcm::System::FileExists(filename) ) { return 1; } } return 0; } int TestDirectory(int argc, char *argv[]) { int res = 0; if( argc > 1 ) { bool recursive = false; if ( argc > 2 ) { recursive = (atoi(argv[2]) > 0 ? true : false); } res += TestOneDirectory( argv[1], recursive); } else { const char *path = gdcm::Testing::GetDataRoot(); res += TestOneDirectory( path ); } //res += TestOneDirectory( "" ); return res; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestDummyValueGenerator.cxx000066400000000000000000000023411412732066400245040ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDummyValueGenerator.h" #include "gdcmTesting.h" int TestDummyValueGenerator(int , char *[]) { gdcm::DummyValueGenerator dvg; (void)dvg; const char patientid1[] = "hello"; const char patientid2[] = "hello "; // Because patientid1 & patientid2 are equivalent in DICOM we need to be able to generate // identical replacement value in case of de-identifier operation: const char *ptr1 = gdcm::DummyValueGenerator::Generate( patientid1 ); const char *ptr2 = gdcm::DummyValueGenerator::Generate( patientid2 ); if( !ptr1 || !ptr2 ) return 1; std::string str1 = ptr1; std::string str2 = ptr2; if( str1 != str2 ) { return 1; } return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestFilename.cxx000066400000000000000000000160371412732066400222740ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmTesting.h" #include #include #include // EXIT_FAILURE /*! * \test TestFilename * bla coucou */ int TestFilename(int argc, char *argv[]) { (void)argc;(void)argv; std::string path = "/gdcm/is/a/dicom/"; std::string name = "library.dcm"; std::string fullpath = path; fullpath += '/'; fullpath += name; gdcm::Filename f( fullpath.c_str() ); std::cout << f.GetPath() << std::endl; std::cout << f.GetName() << std::endl; std::cout << f.GetExtension() << std::endl; std::cout << f << std::endl; if( f.GetPath() != path ) { std::cerr << "Wrong path" << std::endl; return 1; } if( f.GetName() != name) { std::cerr << "Wrong name" << std::endl; return 1; } if( f.GetExtension() != std::string( ".dcm" ) ) { std::cerr << "Wrong extension" << std::endl; return 1; } // if( std::string( "/tmp/debug.dcm" ) != f ) // { // return 1; // } std::string dataroot = gdcm::Testing::GetDataRoot(); std::string current = dataroot + "/test.acr"; if( !gdcm::System::FileExists( current.c_str() ) ) { std::cerr << "File does not exist: " << current << std::endl; return 1; } std::cerr << "Current:" << current << std::endl; gdcm::Filename fn0(current.c_str()); std::cerr << fn0.GetPath() << std::endl; std::string current2 = fn0.GetPath(); current2 += "/./"; current2 += fn0.GetName(); std::cerr << current2 << std::endl; if( current2 == current ) { return 1; } gdcm::Filename fn2(current2.c_str()); if( !fn0.IsIdentical(fn2)) { return 1; } { const char *curprocfn = gdcm::System::GetCurrentProcessFileName(); if( curprocfn ) { gdcm::Filename fn( curprocfn ); std::string str = fn.GetPath(); std::cout << str << std::endl; } } { #ifdef GDCM_HAVE_WCHAR_IFSTREAM const wchar_t ifn[] = L"UnicodeFileName.dcm"; const wchar_t* fn = gdcm::Testing::GetTempFilenameW(ifn); std::ofstream outputFileStream( fn ); if ( ! outputFileStream.is_open() ) { std::cerr << "Failed to read UTF-16: " << fn << std::endl; return EXIT_FAILURE; } outputFileStream.close(); #else //char ifn2[] = "α.dcm"; //MM: I do not think this is legal C++... const char ifn2[] = "\xCE\xB1.dcm"; // this is the proper way to write it (portable) const char ifn1[] = { (char)0xCE, (char)0xB1, '.', 'd', 'c', 'm', 0}; // trailing NULL char std::string sfn1 = gdcm::Testing::GetTempFilename(ifn1); const char *csfn1 = sfn1.c_str(); std::string sfn2 = gdcm::Testing::GetTempFilename(ifn2); const char *csfn2 = sfn2.c_str(); std::ofstream outputFileStream( csfn1 ); if ( ! outputFileStream.is_open() ) { std::cerr << "Failed to create UTF-8 file: " << csfn1 << std::endl; return EXIT_FAILURE; } const char secret[]= "My_secret_pass_phrase"; outputFileStream << secret; outputFileStream.close(); if( !gdcm::System::FileExists(csfn1) ) { std::cerr << "File does not exist: " << csfn1 << std::endl; return EXIT_FAILURE; } // Now open version 2 (different encoding) std::ifstream inputFileStream( csfn2 ); if ( ! inputFileStream.is_open() ) { std::cerr << "Failed to open UTF-8 file: " << csfn2 << std::endl; return EXIT_FAILURE; } std::string ssecret; inputFileStream >> ssecret; inputFileStream.close(); if( ssecret != secret ) { std::cerr << "Found: " << ssecret << " should have been " << secret << std::endl; return EXIT_FAILURE; } if( !gdcm::System::RemoveFile(csfn1) ) { std::cerr << "Could not remove #1: " << csfn1 << std::endl; return EXIT_FAILURE; } // cannot remove twice the same file: if( gdcm::System::RemoveFile(csfn2) ) { std::cerr << "Could remove #2 a second time...seriously " << csfn2 << std::endl; return EXIT_FAILURE; } #endif } { //#define TESTLONGPATHNAMES #ifdef TESTLONGPATHNAMES //why are we testing this? This is the operating system's deal, not GDCM's. //GDCM is not responsible for long path names, and cannot fix this issue. //if we want to move this to a configuration option (ie, test for long pathnames), //then we can--otherwise, windows users should just beware of this issue. //This path limit has been the case since Windows 95, and is unlikely to change any time soon. // Apparently there is an issue with long pathanem i nWin32 system: // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath // The only way to work around the 260 byte limitation it appears as if we // have to deal with universal naming convention (UNC) path. const char subdir[] = "very/long/pathname/foobar/hello_world/toreproduceabugindpkg/pleaseconsider/" "very/long/pathname/foobar/hello_world/toreproduceabugindpkg/pleaseconsider/" "very/long/pathname/foobar/hello_world/toreproduceabugindpkg/pleaseconsider/" "very/long/pathname/foobar/hello_world/toreproduceabugindpkg/pleaseconsider/"; const char *directory_ = gdcm::Testing::GetTempDirectory(subdir); #ifdef _WIN32 gdcm::Filename mydir( directory_ ); std::string unc = "\\\\?\\";//on Windows, to use UNC, you need to: //a) append this string //b) use a network drive (ie, the gdcm file is made on a network drive) that //c) you have access to. //I don't think this is a good or useful test. mmr unc += mydir.ToWindowsSlashes(); const char *directory = unc.c_str(); #else const char *directory = directory_; #endif if( !gdcm::System::MakeDirectory(directory)) { std::cerr << "Failed to create directory with long path: " << directory << std::endl; return EXIT_FAILURE; } std::string sfn = gdcm::Testing::GetTempFilename( "dummy.dcm", subdir ); std::cerr << "Long path is: " << sfn.size() << std::endl; std::cerr << "Long path is: " << sfn << std::endl; if( sfn.size() > 260 ) { const char *fn = sfn.c_str(); // Should demontrate the issue std::ofstream outputFileStream( fn ); if ( ! outputFileStream.is_open() ) { std::cerr << "Failed to create file with long path: " << fn << std::endl; return EXIT_FAILURE; } outputFileStream.close(); if( !gdcm::System::FileExists(fn) ) { std::cerr << "File does not exist: " << fn << std::endl; return EXIT_FAILURE; } if( !gdcm::System::RemoveFile(fn) ) { std::cerr << "Could not remove: " << fn << std::endl; return EXIT_FAILURE; } } else { std::cerr << "seriously " << fn << std::endl; return EXIT_FAILURE; } #endif //TESTLONGPATHNAMES } return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestFilenameGenerator.cxx000066400000000000000000000020431412732066400241330ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFilenameGenerator.h" #include int TestFilenameGenerator(int , char *[]) { gdcm::FilenameGenerator fg; const char pattern[] = "/tmp/bla%01d"; const unsigned int nfiles = 11; fg.SetPattern( pattern ); fg.SetNumberOfFilenames( nfiles ); if( !fg.Generate() ) { std::cerr << "Could not generate" << std::endl; return 1; } for( unsigned int i = 0; i < nfiles; ++i ) { std::cout << fg.GetFilename( i ) << std::endl; } return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestLog2.cxx000066400000000000000000000016451412732066400213560ustar00rootroot00000000000000/*========================================================================= 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 static inline int log2( int n ) { int bits = 0; while (n > 0) { bits++; n >>= 1; } return bits; } int TestLog2(int , char *[]) { int v; v = log2(255); if( v != 8 ) return 1; v = log2(256); if( v != 9 ) return 1; v = log2(4095); if( v != 12 ) return 1; v = log2(4096); if( v != 13 ) return 1; return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestMD5.cxx000066400000000000000000000464541412732066400211470ustar00rootroot00000000000000/*========================================================================= 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 "gdcmMD5.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmTesting.h" #include #include // strcmp static const char * const gdcmMD5SumFiles[][2] = { { "f5ae1418f6ec07ae13522c18ff1e067a" , "00191113.dcm" }, { "c2fdbb35ba2a179939a8608e1320c7ac" , "012345.002.050.dcm" }, { "4b8bed2f8da2fa6a260764e62eb3731b" , "05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm" }, { "a01a44c67a88d5a98ecdc214e412c585" , "05148044-mr-siemens-avanto-syngo.dcm" }, { "7ddb7cc42cf3191a248a60f66661b380" , "3E768EB7.dcm" }, { "a0452c3bb9303ad8ebc7f8a166cc8190" , "ACUSON-24-YBR_FULL-RLE-b.dcm" }, { "916b12bdf36d60a0b0ae39451d86ddb4" , "ACUSON-24-YBR_FULL-RLE.dcm" }, { "a4d1faf3a3a4c8b0cdf8605ef0ab48b5" , "ALOKA_SSD-8-MONO2-RLE-SQ.dcm" }, { "00c78123ea2d8a9f1452f0da37383d85" , "BugGDCM2_UndefItemWrongVL.dcm" }, { "0b4cfdaebfa3944940bed290c0a29a5b" , "CR-MONO1-10-chest.dcm" }, { "d4f286ee295ac03856370e4ff0fe60a9" , "CT_16b_signed-UsedBits13.dcm" }, { "0e03332d250a8a1a5d3c0699b1cf6b1d" , "CT-MONO2-12-lomb-an2.acr" }, { "102528014fa6ff9758c76745090b7550" , "CT-MONO2-16-ankle.dcm" }, { "a21649de46e5f5609ef6e227999a1dc8" , "CT-MONO2-16-brain.dcm" }, { "56caa0050cd61dee0bfb41559dbd6a33" , "CT-MONO2-16-chest.dcm" }, { "5e8efa7ebe3a4c47c01a64f80b244b2c" , "CT-MONO2-16-ort.dcm" }, { "abe6a2e0b1a1d636b6a775291b44b7d0" , "CT-MONO2-8-abdo.dcm" }, { "442e1966eba2fd0eb8fab685c99cc388" , "CT-SIEMENS-Icone-With-PaletteColor.dcm" }, { "7dbc75bccddcb7177796c1fa3509ab09" , "CT-SIEMENS-MissingPixelDataInIconSQ.dcm" }, { "6155e751818ede1db17aa848d882beda" , "D_CLUNIE_CT1_J2KI.dcm" }, { "7e59d70ed013175815a6c8a498d481f1" , "D_CLUNIE_CT1_J2KR.dcm" }, { "073960e6c249b45bd6341e3397637478" , "D_CLUNIE_CT1_JPLL.dcm" }, { "53d722b71a881e386005ec3c83bd78a1" , "D_CLUNIE_CT1_RLE.dcm" }, { "8577a89b3906c01731641e177dda0f88" , "D_CLUNIE_CT2_JPLL.dcm" }, { "681c50b2a496cb5c2d7bb964108649d2" , "D_CLUNIE_CT2_RLE.dcm" }, { "64f39d9d812d999b689cb9dad069ed3a" , "D_CLUNIE_MR1_JPLL.dcm" }, { "c14fd84b399f305ddd71a547ecbaaa13" , "D_CLUNIE_MR1_JPLY.dcm" }, { "45346d785b6c3a8be12b271abb745b13" , "D_CLUNIE_MR1_RLE.dcm" }, { "82093a4fc15b10b791b3d884a1cdc9c6" , "D_CLUNIE_MR2_JPLL.dcm" }, { "43867bf684f5c8eb56e7595c76e02e7a" , "D_CLUNIE_MR2_JPLY.dcm" }, { "072779b40d39e704ec4c002226bdfceb" , "D_CLUNIE_MR2_RLE.dcm" }, { "60852d347647758175d8f65d2c81e7a6" , "D_CLUNIE_MR3_JPLL.dcm" }, { "8e60bb51feba032aa141385f48465ef8" , "D_CLUNIE_MR3_JPLY.dcm" }, { "cf1e84527b2a6095037a8c2cfe801335" , "D_CLUNIE_MR3_RLE.dcm" }, { "caa51957b182d1048f1077af1c3d99fb" , "D_CLUNIE_MR4_JPLL.dcm" }, { "810033c798a3168f051389e0a0a8bcb7" , "D_CLUNIE_MR4_JPLY.dcm" }, { "af6b015679b368bb0e066874730a5cb9" , "D_CLUNIE_MR4_RLE.dcm" }, { "9a1008f0b45537614523e1fc8dce1b37" , "D_CLUNIE_NM1_JPLL.dcm" }, { "dbd2aedf74ca7297ea213d7d19934bba" , "D_CLUNIE_NM1_JPLY.dcm" }, { "01b95bc55f4684d0d7f2cb990a4c870f" , "D_CLUNIE_NM1_RLE.dcm" }, { "510e107dc1ca40a577af88a20f71a0b4" , "D_CLUNIE_RG1_JPLL.dcm" }, { "418bef1f3e70cb02205999bce74fed8e" , "D_CLUNIE_RG1_RLE.dcm" }, { "7596cda97de4782951827104f616f7ea" , "D_CLUNIE_RG2_JPLL.dcm" }, { "f03d1b8dc233c8c902c9fb4800ec6fe2" , "D_CLUNIE_RG2_JPLY.dcm" }, { "2fbc6e918c2d4ad7115addf46d870e78" , "D_CLUNIE_RG2_RLE.dcm" }, { "9966b6dbec23248fb2b6da9e7769ba20" , "D_CLUNIE_RG3_JPLL.dcm" }, { "6867e0e4f8a1feb871a1ee8dcfac838e" , "D_CLUNIE_RG3_JPLY.dcm" }, { "4ed3c3920c7763b883c234bf8bf95662" , "D_CLUNIE_RG3_RLE.dcm" }, { "41dc2884a4f98d484da80c2bdb7e5fcc" , "D_CLUNIE_SC1_JPLY.dcm" }, { "ec344a1d113d5070cabebf17c0fa3330" , "D_CLUNIE_SC1_RLE.dcm" }, { "14f4e54540008a39b53725800962f703" , "D_CLUNIE_US1_RLE.dcm" }, { "44a550cd8bccba4f157dd825489a5e87" , "D_CLUNIE_VL1_RLE.dcm" }, { "f4274cbe83a3368d99ee8332421448fe" , "D_CLUNIE_VL2_RLE.dcm" }, { "ea3d6a0fe2a65244c285c31eac5066ab" , "D_CLUNIE_VL3_RLE.dcm" }, { "6452ff527ac71f780445cf5ff083b0af" , "D_CLUNIE_VL4_RLE.dcm" }, { "53be8cfa8cb9709c08732908bb37410a" , "D_CLUNIE_VL6_RLE.dcm" }, { "9178b1d061641464ecaf271fc4328948" , "D_CLUNIE_XA1_JPLL.dcm" }, { "1f050eec29d9eeed3d406570ea1b9168" , "D_CLUNIE_XA1_JPLY.dcm" }, { "99040c48b80d40d6f7d6eed6a3cbc824" , "D_CLUNIE_XA1_RLE.dcm" }, { "9cf394a4dde294fc740e7577529ba5ca" , "D_CLUNIE_CT1_JLSL.dcm" }, { "b4d14dc9e820e6f1cf17730833a0373a" , "D_CLUNIE_CT1_JLSN.dcm" }, { "de20088d529a3bb211933c2d3b7604aa" , "DCMTK_JPEGExt_12Bits.dcm" }, { "e959b1f056d40bb4b21d0cbff1f67310" , "DermaColorLossLess.dcm" }, { "dee54ccedfed2d4d5562b52a1a7a5cfc" , "DICOMDIR" }, { "81ba5ff6f512289c30efdc757c6de231" , "dicomdir_Acusson_WithPrivate_WithSR" }, { "7c75c6a8957298bd70bf9b51efd39da1" , "DICOMDIR_MR_B_VA12A" }, { "7339affc644067bbd4be9134b597c515" , "DICOMDIR-Philips-EasyVision-4200-Entries" }, { "de270e5b601d5f9e235ea651932b546c" , "dicomdir_Pms_With_heavy_embedded_sequence" }, { "1ef216d2a08420432172581e0b4b9ffa" , "dicomdir_Pms_WithVisit_WithPrivate_WithStudyComponents" }, { "19c0a3e4ba48de7b35f19013bf7ceaa7" , "dicomdir_With_embedded_icons" }, { "33e6ad84c695d0d2c8be46ae79cfb5be" , "DMCPACS_ExplicitImplicit_BogusIOP.dcm" }, { "e692180e794a05a284edc985728af12b" , "DX_GE_FALCON_SNOWY-VOI.dcm" }, { "4838485dda77a0ff1a51463e1742f1c1" , "DX_J2K_0Padding.dcm" }, { "16f951766461b7cf1ec318f53c396c3b" , "ELSCINT1_JP2vsJ2K.dcm" }, { "e1e3c870656147b186361ab2439379ae" , "ELSCINT1_LOSSLESS_RICE.dcm" }, { "c5a985457952a33a10c90139c5812e56" , "ELSCINT1_PMSCT_RLE1.dcm" }, { "f2429f2bf3d2d7951a358e94a848977b" , "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm" }, { "b92edb08527b520df5f624f6753fb47a" , "fffc0000UN.dcm" }, { "40cff8d72a15be2b91d3c972b5c8a481" , "FUJI-10-MONO1-ACR_NEMA_2.dcm" }, { "74fc5c1975c8c8277a2900a803e56260" , "gdcm-ACR-LibIDO.acr" }, { "bd4c340a9d225c16f1507dbc9013ff47" , "gdcm-CR-DCMTK-16-NonSamplePerPix.dcm" }, { "04528010e8679cd668ee3e89cb9b7058" , "gdcm-JPEG-Extended.dcm" }, { "95953bc725582368ac5ddac7eb73e73f" , "gdcm-JPEG-LossLess3a.dcm" }, { "f715e4b9f640ff3b3b98b87d10f81c36" , "gdcm-JPEG-LossLessThoravision.dcm" }, { "06fc6d07dc486b2cb87077ea74774220" , "gdcm-MR-PHILIPS-16-Multi-Seq.dcm" }, { "4b09787d27dbd36a02a0ae7d4d3abe16" , "gdcm-MR-PHILIPS-16-NonSquarePixels.dcm" }, { "765d1cae48ebac57f675193734f6477c" , "gdcm-MR-SIEMENS-16-2.acr" }, { "20e289bad9be67e22d179174f3bc1694" , "gdcm-US-ALOKA-16.dcm" }, { "64e2f50c3e3b9b7400f3f29e144b4a34" , "GE_CT_With_Private_compressed-icon.dcm" }, { "012993a90206a659e92f6af305889f0b" , "GE_DLX-8-MONO2-Multiframe.dcm" }, { "1bec471d81dcb3a39852c03d261c22cd" , "GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm" }, { "44f09f83983a2b45a6cd42deb1cbcf0a" , "GE_DLX-8-MONO2-PrivateSyntax.dcm" }, { "1ef5dca6cda8c21b01ff779e6aa67692" , "GE_GENESIS-16-MONO2-Uncompressed-UnusualVR.dcm" }, { "34483fff69d88d647a2edfd8d55210a3" , "GE_GENESIS-16-MONO2-WrongLengthItem.dcm" }, { "1a7c56cb02d6e742cc9c856a8ac182e3" , "GE_LOGIQBook-8-RGB-HugePreview.dcm" }, { "7285d6a7261889c33626310e1d581ef8" , "GE_MR_0025xx1bProtocolDataBlock.dcm" }, { "309d063fbe3bd73dad534e72de032f97" , "GE_RHAPSODE-16-MONO2-JPEG-Fragments.dcm" }, { "76d57d019a5af8cd5a7cd2afb1e40f4b" , "IM-0001-0066.dcm" }, { "b479bb01798444128d75d90d37cf8546" , "ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm" }, { "1bb147010022b15e021eabe0eae1a231" , "JDDICOM_Sample2.dcm" }, { "cd9afab2d9d31de0029bf4ed1995186c" , "JDDICOM_Sample2-dcmdjpeg.dcm" }, { "e4b43fa2fdb4dde13e2a7fd018323241" , "JPEG_LossyYBR.dcm" }, { "118dc6986862bf76326ba542813049d2" , "KODAK-12-MONO1-Odd_Terminated_Sequence.dcm" }, { "499661b964e8df08860655c8dcc17661" , "KODAK_CompressedIcon.dcm" }, { "21de4aa50000b4ed74e4531c2b1d0cc1" , "LEADTOOLS_FLOWERS-16-MONO2-JpegLossless.dcm" }, { "042ca0b7551bd96b501fbbdd4275342f" , "LEADTOOLS_FLOWERS-16-MONO2-RLE.dcm" }, { "31c7e4c1a2f39871b886c443c6376ba7" , "LEADTOOLS_FLOWERS-16-MONO2-Uncompressed.dcm" }, { "9f884f686020c37be9f41a617b9ec8e8" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossless.dcm" }, { "bc38dd9c27150dd3d67250830644e609" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm" }, { "32ad312f99c425b1631e6e05881e3e33" , "LEADTOOLS_FLOWERS-24-RGB-Uncompressed.dcm" }, { "82c2343f6f4b55bf6a31f6cc0f9cf83e" , "LEADTOOLS_FLOWERS-8-MONO2-JpegLossy.dcm" }, { "f78abbd1df9ef87ba21d805083d6e3b3" , "LEADTOOLS_FLOWERS-8-MONO2-RLE.dcm" }, { "afe156b36b3af19b6a889d640296c710" , "LEADTOOLS_FLOWERS-8-MONO2-Uncompressed.dcm" }, { "deaf5e62e2132996ebe759a438195f95" , "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm" }, { "6b04366e28facddd808b9ea149745309" , "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm" }, { "f1b63522a4d6ae89eb6bc728cebc14ff" , "libido1.0-vol.acr" }, { "b90b87245eddfcb53b26e61cfaa40fcc" , "LIBIDO-16-ACR_NEMA-Volume.dcm" }, { "454accc7d6688c0478461f575461c607" , "LIBIDO-24-ACR_NEMA-Rectangle.dcm" }, { "3d8ee51f870495bf22b7a51ba0661f90" , "LIBIDO-8-ACR_NEMA-Lena_128_128.acr" }, { "9c8b67c4205880f78347b751268af0fa" , "LJPEG_BuginGDCM12.dcm" }, { "335428b3dde0d390dbd8bb49f32c673c" , "MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm" }, { "abd7b36703f82e3b491e4b3b95cc1c43" , "MAROTECH_CT_JP2Lossy.dcm" }, { "63f178c91a573f13e28aabe8b7eaf1bd" , "MR-Brucker-CineTagging-NonSquarePixels.dcm" }, { "746a17465b70119264762ead8f1a6763" , "MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm" }, { "c87dd2eac7b55cb3eade01eaa373b4e3" , "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm" }, { "ca8cd1b0a7c64139919deba04dbddfc9" , "MR-MONO2-12-an2.acr" }, { "cb32c2e0c3f9c52939440d39f9fe7b4f" , "MR-MONO2-12-angio-an1.acr" }, { "fb0565a0a591ed83106e90d5b76e0cfe" , "MR-MONO2-12-shoulder.dcm" }, { "97d9f3dcc35e54478522ead748e24956" , "MR-MONO2-16-head.dcm" }, { "fc72513cfea2caf6035dd8910c53bb9a" , "MR-MONO2-8-16x-heart.dcm" }, { "1a2e4f0aa20448fdd7783ff938bf99e6" , "MR_Philips-Intera_BreaksNOSHADOW.dcm" }, { "aa07de9c01765602fe722e9ef2d8b92a" , "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm" }, { "a8091f92ae895c2ef70143487e29b7d3" , "MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm" }, { "5d893aee8147f12b975cde73abdb5d84" , "MR_Philips_Intera_PrivateSequenceImplicitVR.dcm" }, { "3bbffc4c87f4f5554fafad5f8a002552" , "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm" }, { "32f899e8f1506bc3fa155da22e9c8813" , "MR-SIEMENS-DICOM-WithOverlays.dcm" }, { "db7370f6d18ce7a9c8ab05179eb82cc6" , "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm" }, { "15ef679db745d4a3a59cab0456a82ace" , "MR_SIEMENS_forceLoad29-1010_29-1020.dcm" }, { "be2ce86e93fe5a0cc33c2351b6a4ac66" , "MR_Spectroscopy_SIEMENS_OF.dcm" }, { "473dd7ad8ec7c50dbd20470b525eb859" , "NM-MONO2-16-13x-heart.dcm" }, { "cc1dd93cd2e2fc19815b015663ea8e66" , "OT-MONO2-8-a7.dcm" }, { "61dfde4beae2ecd7fd4acc9cab412daa" , "OT-PAL-8-face.dcm" }, { "d97af0d265cee784f3fd6391f17cf8fd" , "PET-cardio-Multiframe-Papyrus.dcm" }, { "826226301791aaa2e1dfacb9f56775ae" , "PHILIPS_Brilliance_ExtraBytesInOverlay.dcm" }, { "fe35f6ff5e85392143c7216a9e4bc92d" , "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm" }, { "d6ea0b68da84829a1b4cbd07d7cf6ef5" , "PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm" }, { "cc8bbb35c017acd32ba29d20df12ac8b" , "PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm" }, { "f80468faedc918845fc31accc247125f" , "PHILIPS_Intera-16-MONO2-Uncompress.dcm" }, { "43469b245a5fbbea69db6ed9507a86e4" , "PICKER-16-MONO2-Nested_icon.dcm" }, { "2cd10ed50b409549a6a25c4feaa5a989" , "PICKER-16-MONO2-No_DicomV3_Preamble.dcm" }, { "9d4f1c087ababf655297bf2129c01911" , "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm" }, { "8e902a2371c37b9e6f636c3c53ef1f5c" , "RadBWLossLess.dcm" }, { "a0e664672011dab175f593bf61026ffc" , "rle16loo.dcm" }, { "f35d850d15021800175c585f856a8f54" , "rle16sti.dcm" }, { "148b28cb580e6f56d9adce46a985c692" , "SIEMENS-12-Jpeg_Process_2_4-Lossy-a.dcm" }, { "90336859a2e275900931d54c41fe033a" , "SIEMENS_CSA2.dcm" }, { "4b1498f0edd79cc0f5273f22a4e03615" , "SIEMENS_GBS_III-16-ACR_NEMA_1.acr" }, { "c54eb37190f783c79504554990761efd" , "SIEMENS_GBS_III-16-ACR_NEMA_1-ULis2Bytes.dcm" }, { "bf49f9fdab81e97482b8fe6f579bc3f7" , "SIEMENS_ImageLocationUN.dcm" }, { "765d1cae48ebac57f675193734f6477c" , "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm" }, { "6884e1143f2edf6188643e896e796463" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm" }, { "340b9006e47d48bd6d5abe5af628026b" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm" }, { "59cc16618e978026cff79e61e17174ec" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm" }, { "fde3a66d449ae3788b4c431fde7a7a50" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm" }, { "6facfeecd3c531b3a536064aa046fa9e" , "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm" }, { "ba687ec0b2e49f5eedd3e22573ba2094" , "SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm" }, { "7e00f1e50bd0bedc5db64dff0dea3848" , "SIEMENS_MAGNETOM-12-MONO2-VRUN.dcm" }, { "c80b1be0d50619955e54d81bca451a05" , "SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm" }, { "544a1fde6df0817ef03ad56f7ff539a8" , "SIEMENS-MR-RGB-16Bits.dcm" }, { "33f4765c31a5d2f61f4e3fa4571e2f88" , "SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs.acr" }, { "08443d1e07d98554a695c482ecba2014" , "SIEMENS_Sonata-12-MONO2-SQ.dcm" }, { "f49aeced38187d9d8502cf79fb690e0d" , "SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm" }, { "fd22f759b7dd4b8cccd64f5f5096887b" , "SignedShortLosslessBug.dcm" }, { "c8c3e1d395aa50795ca831e12051d9d0" , "simpleImageWithIcon.dcm" }, { "c634e9e559b61ea65d222a1d5c5a9d5e" , "test.acr" }, { "fc733f08120936e25cb11af6df6f65bf" , "TG18-CH-2k-01.dcm" }, { "47a35db3d33ab798e7b41449e22d1120" , "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm" }, { "d85505c6a7be835b482175fbed85ce98" , "TheralysGDCM120Bug.dcm" }, { "db53b838d4ed4aca22999d6c70558305" , "TOSHIBA_MRT150-16-MONO2-ACR_NEMA_2.dcm" }, { "b3bc682102873b761491839df5686adf" , "undefined_length_un_vr.dcm" }, { "98473e5af6a5694ae08d63780bcea96c" , "US-GE-4AICL142.dcm" }, { "1b12a27ca6075d55000d1d170949b789" , "US-IRAD-NoPreambleStartWith0003.dcm" }, { "44f97431146a33e320ae08fb7dc09a59" , "US-IRAD-NoPreambleStartWith0005.dcm" }, { "1006e4c95b63539608adf62060d7fc46" , "US-MONO2-8-8x-execho.dcm" }, { "83574afcb319337222472db44f91cbd8" , "US-PAL-8-10x-echo.dcm" }, { "0b3ae440e8dbb144205074a664228c1e" , "US-RGB-8-epicard.dcm" }, { "0ae1d92cc14706add796368622deaa26" , "US-RGB-8-esopecho.dcm" }, { "d23db052b02b2a2c510104486cdf40b2" , "XA-MONO2-8-12x-catheter.dcm" }, { "231bb6c25d482422745bb839d6f8610a" , "PHILIPS_GDCM12xBug2.dcm" }, { "e2558e4e01d937bfac33b7e0fb07b7b5" , "PHILIPS_GDCM12xBug.dcm" }, { "434c7aa1172ce3af0c306d9a2cb28c17" , "AMIInvalidPrivateDefinedLengthSQasUN.dcm" }, { "346ba438ade47d75c41e637858a419f8" , "OsirixFake16BitsStoredFakeSpacing.dcm" }, { "efe1ff2da3fc0bfcc5df834fa390d5cf" , "MR16BitsAllocated_8BitsStored.dcm" }, { "7900d059078278ad0387f7c4aaf2027d" , "JPEGDefinedLengthSequenceOfFragments.dcm" }, { "dacb240b2fc701416d80193ad18baad5" , "IM-0001-0066.CommandTag00.dcm" }, { "7f2f84d3adef913bb5531f583eceb004" , "UnexpectedSequenceDelimiterInFixedLengthSequence.dcm" }, { "f4bf27280aad0ff38d1fe3871a0a8afb" , "GDCMJ2K_TextGBR.dcm" }, { "f445a6dc674e2c12c14bf3583c6c3e6f" , "NM_Kakadu44_SOTmarkerincons.dcm" }, { "7c0c4eb0c73b4dc5b3a4d961653fc4e2" , "PhilipsInteraSeqTermInvLen.dcm" }, { "64528209839b0369c2da530249f4ca58" , "TOSHIBA_J2K_SIZ1_PixRep0.dcm" }, { "2498ca4aaf62991c8a1f629a804bfa44" , "TOSHIBA_J2K_OpenJPEGv2Regression.dcm" }, { "e4d559b6db04679b54bea40c763b09e4" , "TOSHIBA_J2K_SIZ0_PixRep1.dcm" }, { "58ab110be40303952e05d50e64823192" , "NM-PAL-16-PixRep1.dcm" }, { "deb7e4ee592efca5d475aaa6fab06459" , "MEDILABInvalidCP246_EVRLESQasUN.dcm" }, { "52f727de4f831ff2bae850fdd8b1413a" , "JPEGInvalidSecondFrag.dcm" }, { "027faefc8031768dad1afc100f7aee27" , "SC16BitsAllocated_8BitsStoredJ2K.dcm" }, { "f7c4fbb93b0347101e21e36f223b4d46" , "SC16BitsAllocated_8BitsStoredJPEG.dcm" }, { "af580e6202a240005a5a05adc5c691f2" , "SIEMENS_SYNGO-12-MONO2-LUTWrongLength512.dcm" }, { "236713383dd9d315415f3a5957707ad1" , "JPEGNote_empty.dcm" }, { "5b6f7f59dbefd679aa29e9082f100ff5" , "JPEGLS_CharLS_10742.dcm" }, { "66fe7d517941802364e7ad8dee7149e7" , "JPEGLosslessYBR_FULL_422.dcm" }, { "dcb4b29b7e0f0da441ab3e5cdcb506b4" , "JPEGNote_missing.dcm" }, { "2c30e74ee3db1895027932bb0566f54e" , "JPEGNote_bogus.dcm" }, { "c71a2cf95325395264c4dc6e15a898bd" , "RLEDebianBug816607Orig.dcm" }, { "e49c403278663d9739014ad1d57c276f" , "IllegalGroup2ImplicitTS.dcm" }, { "299df0175ea4d3ab1f02651f88ffe9f3" , "JPEG_LS_InvalidEscapeSequence_COM_padding.dcm" }, { "9add5fd3c83cc0946633e792f448f732" , "LengthOfItemLarger.dcm" }, { "b9fdef839a6b6ab33486bfd6b35de3a8" , "GE_MR_0025xx1bProtocolDataBlockXML.dcm" }, { "fd6ba97f247f5b8ef70f407f5c1b5f11" , "EmptyIcon_Bug417.dcm" }, { "271d71dde59c0cad76baab36c909a43a" , "EnhancedWithIPPPerFrameIOPShared.dcm" }, { "2fd5ad3e9265861be43b6a341314cc52" , "FUJI-ffff-MONO1-J2K.dcm" }, { "69648b9be35a621e9e5b447df656ab18" , "JPEGLosslessSeNonZero.dcm" }, { "c0ee318130c0fcf35b0f57670a8f1e0d" , "US-YBR_FULL_422-EVRLE.dcm" }, { "3d873e4c19bf5513959c6cc1a184e2df" , "Osirix10vs8BitsStored.dcm" }, { "5141fe286ad2e39259dac231e3d10b41" , "Bug_Siemens_PrivateIconNoItem.dcm" }, { "3155af485dc3f490cc9e212f95499615" , "HardcopyColor_YBR_RCT_J2K_PC1.dcm" }, { "ab93bd11ce0f48e2e9e1c700df160a30" , "PET-GE-dicomwrite-PixelDataSQUNv2.dcm" }, { nullptr, nullptr} }; int TestMD5Func(const char* filename, const char *md5ref, bool verbose = false) { if( !filename || !md5ref) return 1; if( verbose ) std::cout << "TestRead: " << filename << std::endl; const char *dataroot = gdcm::Testing::GetDataRoot(); std::string path = dataroot; path += "/"; path += filename; path = filename; char md5[2*16+1] = {}; bool b = gdcm::MD5::ComputeFile( path.c_str(), md5); if( !b ) { std::cerr << "Fail ComputeFile: " << path << std::endl; return 1; } if( strcmp( md5, md5ref) != 0 ) { std::cout << "Problem with: " << path << std::endl; std::cout << "Ref: " << md5ref << " vs " << md5 << std::endl; // Let's remove this buggy file: //std::cout << "Removing: " << path << std::endl; //gdcm::System::RemoveFile(path.c_str()); return 1; } return 0; } static const char *GetMD5Sum(const char *filename) { using md5pair = const char *const (*)[2]; const char *md5filename; md5pair md5filenames = gdcmMD5SumFiles; int i = 0; while( ( md5filename = md5filenames[i][1] ) ) { gdcm::Filename fn( filename ); if( strcmp( md5filename, fn.GetName() ) == 0 ) { return md5filenames[i][0]; } ++i; } std::cerr << "Missing Md5 for: " << filename << std::endl; return nullptr; } int TestMD5(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; const char *md5 = GetMD5Sum( filename ); return TestMD5Func(filename, md5, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { const char *md5 = GetMD5Sum( filename ); r += TestMD5Func( filename, md5 ); ++i; } return r; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestObject.cxx000066400000000000000000000012311412732066400217500ustar00rootroot00000000000000/*========================================================================= 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 "gdcmObject.h" int TestObject(int, char *[]) { gdcm::Object o; (void)o; return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestSHA1.cxx000066400000000000000000000511201412732066400212400ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSHA1.h" #include "gdcmFilename.h" #include "gdcmTrace.h" #include "gdcmTesting.h" #include #include // strcmp static const char * const gdcmSHA1SumFiles[][2] = { { "265465a2e3b204ab9a094f2de56bbec96d55ab74" , "00191113.dcm" }, { "ab316e51539a56053e216017c8445a246a978590" , "012345.002.050.dcm" }, { "750ff7a9df7a12c13f7149c514664db7c68c3125" , "05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm" }, { "4efeffa6a7b535df85dda198a26e074866b0ed88" , "05148044-mr-siemens-avanto-syngo.dcm" }, { "9d1e3fdf69f8d5b46105e4c259b3d84e7f281a45" , "3E768EB7.dcm" }, { "f08ff36b45cd50d4349f4c6c17a75b3f653bb11e" , "ACUSON-24-YBR_FULL-RLE-b.dcm" }, { "dac2ffa6ccf59f2d91e78f632e45b08d1537715c" , "ACUSON-24-YBR_FULL-RLE.dcm" }, { "cf749c5323866c343255805cf781ae87e6bb598a" , "ALOKA_SSD-8-MONO2-RLE-SQ.dcm" }, { "7202bfac6d4196aeb2655e879bc91e4dcf40a463" , "BugGDCM2_UndefItemWrongVL.dcm" }, { "1d227106140c2a24dbe8c6becd4649761dd117a2" , "CR-MONO1-10-chest.dcm" }, { "74e7de8b0f5903b8571294e2d8f960dc7329a0ca" , "CT_16b_signed-UsedBits13.dcm" }, { "c0e08333984692bcef149c946e23bb46e01b9b7c" , "CT-MONO2-12-lomb-an2.acr" }, { "594ce3215ca94f640fd7502d614651cc755a9d7e" , "CT-MONO2-16-ankle.dcm" }, { "ce0bd0c9635db3f04b4996648c1d41e10daffa77" , "CT-MONO2-16-brain.dcm" }, { "f9ad8311fa69835c55314e740ca55ab71e038c17" , "CT-MONO2-16-chest.dcm" }, { "507fdef01d9357dfb99981ae6c18ab88931271b5" , "CT-MONO2-16-ort.dcm" }, { "ad5c2b6d0816761d5f5dc1fcc83e44f3eea4666d" , "CT-MONO2-8-abdo.dcm" }, { "76e6ae295b326a46d37f1ad5056ee18b6ee3d6f2" , "CT-SIEMENS-Icone-With-PaletteColor.dcm" }, { "7bce2465ca918a5d2a9b8f9c6a9cce1b6b94b44b" , "CT-SIEMENS-MissingPixelDataInIconSQ.dcm" }, { "1b75f84318351449b5d841d094297d7975e8ac5b" , "D_CLUNIE_CT1_J2KI.dcm" }, { "1d40f08bf78a29e0729742ff5f5731477ab5a9ff" , "D_CLUNIE_CT1_J2KR.dcm" }, { "6f6027b38ec184af8cdf31077cd669bd35270ccb" , "D_CLUNIE_CT1_JPLL.dcm" }, { "3df887253b24f3296f078fc618e6a682cae4c1d6" , "D_CLUNIE_CT1_RLE.dcm" }, { "5336a791f09fe080688b5c1fad04691b39588978" , "D_CLUNIE_CT2_JPLL.dcm" }, { "37beaf412c74e435cfdf351cc95f02b62820e3ea" , "D_CLUNIE_CT2_RLE.dcm" }, { "fa118c4661e14878a9113032b6549dc7666b773b" , "D_CLUNIE_MR1_JPLL.dcm" }, { "f464c45fceb6f5dc234150064c1b7999cd0db2ff" , "D_CLUNIE_MR1_JPLY.dcm" }, { "4f6a484fd77238f8bc245fbfadc449cb3ec40a75" , "D_CLUNIE_MR1_RLE.dcm" }, { "111bed6926dbf4ad3f61bd9c95e36095475265a1" , "D_CLUNIE_MR2_JPLL.dcm" }, { "eec3ed081ec196e036d2cac9e0043bef1038665e" , "D_CLUNIE_MR2_JPLY.dcm" }, { "c2ab10273241fe18401f4584a42c76c5257219f0" , "D_CLUNIE_MR2_RLE.dcm" }, { "fb04e8143117a8ecdd9cece68c08d4ee3b3ed040" , "D_CLUNIE_MR3_JPLL.dcm" }, { "ef2d3fe28424e42963ca52f097b3d1309c95f43d" , "D_CLUNIE_MR3_JPLY.dcm" }, { "08dd62d2f452e145dea7905b64e43836504c8a2e" , "D_CLUNIE_MR3_RLE.dcm" }, { "e2fa66c4074e9f75b582eb6cf5261a6ac064c5cb" , "D_CLUNIE_MR4_JPLL.dcm" }, { "7426ae6aa6cb2f13138878a68183d69ed8d42b1e" , "D_CLUNIE_MR4_JPLY.dcm" }, { "2cf735f7ced248c20d4bd8af760523e8b1c88c44" , "D_CLUNIE_MR4_RLE.dcm" }, { "f0632988a652cf186a2c1199bb19389534617952" , "D_CLUNIE_NM1_JPLL.dcm" }, { "8e4a062c60bda83a7a118b505f9da29454eb77e1" , "D_CLUNIE_NM1_JPLY.dcm" }, { "0933067b799d0b4407e190e0b3a58f0e97c92371" , "D_CLUNIE_NM1_RLE.dcm" }, { "c72d14184a995b367682f42c3e3b62de7a5b4c7e" , "D_CLUNIE_RG1_JPLL.dcm" }, { "b71f33df55502266ca2f4966cd5fc88b2b766385" , "D_CLUNIE_RG1_RLE.dcm" }, { "8c337359cca8d2bf1002209589ff19699e530908" , "D_CLUNIE_RG2_JPLL.dcm" }, { "c6188f2ae06a55d596d4d6b4d914b404f7bf5786" , "D_CLUNIE_RG2_JPLY.dcm" }, { "5035a6298cf8590932605cb4bb10f128df971fcb" , "D_CLUNIE_RG2_RLE.dcm" }, { "d2a56de2e035095c3dea9be80878f9607c63728d" , "D_CLUNIE_RG3_JPLL.dcm" }, { "c90b8543259ca7189fa76201f864c2f32e6ebef3" , "D_CLUNIE_RG3_JPLY.dcm" }, { "eb417a88c6b3fe6c5768ab705990fc0d54558816" , "D_CLUNIE_RG3_RLE.dcm" }, { "8e27c853a156038e1f6daebb04f2c9059ebfbd82" , "D_CLUNIE_SC1_JPLY.dcm" }, { "6a6ca811ae87ae1ca4549f49724b58562eea714b" , "D_CLUNIE_SC1_RLE.dcm" }, { "94737b44e512c8b84e1fb880e04b0ae6f069bd96" , "D_CLUNIE_US1_RLE.dcm" }, { "6cc2ad34df402a9aa5c6a2c5436ff0e775a59768" , "D_CLUNIE_VL1_RLE.dcm" }, { "4432f4bba584c5bf93264050a0aef0237c8cc9a5" , "D_CLUNIE_VL2_RLE.dcm" }, { "c11e1487e94b332f32c041d7e8889d1fe91c2db6" , "D_CLUNIE_VL3_RLE.dcm" }, { "345bde73f67171cc6f90cd890d67108aa6039656" , "D_CLUNIE_VL4_RLE.dcm" }, { "e52694c1e9be0f4d1c44eab3ac44aa4225b593b0" , "D_CLUNIE_VL6_RLE.dcm" }, { "37bf802b1918f36fcf7c6fb89b40ee1da1124419" , "D_CLUNIE_XA1_JPLL.dcm" }, { "ff7b9c99731732b55bcff577037542689efe9c72" , "D_CLUNIE_XA1_JPLY.dcm" }, { "f384b5f1ae912d97e7784558d5519dc74b853f10" , "D_CLUNIE_XA1_RLE.dcm" }, { "cc3641d1f25549a0ee06d2a5e87081cf6c407bf0" , "D_CLUNIE_CT1_JLSL.dcm" }, { "ac9f4592e6cfad438de5c928b9e01591006683d8" , "D_CLUNIE_CT1_JLSN.dcm" }, { "cc72ee9f3e671321e231103eb562063078b67bf8" , "DCMTK_JPEGExt_12Bits.dcm" }, { "fb9da9ae84e5da97c992398ac0222fffafa028f6" , "DermaColorLossLess.dcm" }, { "6f53ebd046c0c39ad04b7aa3767ced2647b02c83" , "DICOMDIR" }, { "436f0de1319089bc203b699a6e64687a9b27fd8c" , "dicomdir_Acusson_WithPrivate_WithSR" }, { "3c73737e44852b9f30cc4fe4e8cc600cdf63ee0a" , "DICOMDIR_MR_B_VA12A" }, { "86687243468f6e8243081adbff3374c8fbeb1166" , "DICOMDIR-Philips-EasyVision-4200-Entries" }, { "623523dedebccddb38ab6fbb76e01c1458bd0d98" , "dicomdir_Pms_With_heavy_embedded_sequence" }, { "0c0c0b72d980a6675897fc50854c98176582e7d5" , "dicomdir_Pms_WithVisit_WithPrivate_WithStudyComponents" }, { "9a90f8c949d99f9e9e7523f442b8995bb2b2ae3d" , "dicomdir_With_embedded_icons" }, { "eb0b632f7feccde2b7d88d6a82f51857ef5de521" , "DMCPACS_ExplicitImplicit_BogusIOP.dcm" }, { "abb8fb269447e046fe10306e4e5f54fe988a0069" , "DX_GE_FALCON_SNOWY-VOI.dcm" }, { "861ff0760754f6ebb0056f52adcdcd60f0cd3bfa" , "DX_J2K_0Padding.dcm" }, { "8275a7e217807273fb0027a64f46cba8656f699a" , "ELSCINT1_JP2vsJ2K.dcm" }, { "399e80d60843e62b817322ba9e82278258f9a222" , "ELSCINT1_LOSSLESS_RICE.dcm" }, { "3598e59bf8ff6cb5217473f9f23ad763638a27e0" , "ELSCINT1_PMSCT_RLE1.dcm" }, { "3514c92127b0c78b63efce1fb6053e202da86d3f" , "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm" }, { "cc80ee94edf9b3d7fd4c1402b2c6ae99eb832685" , "fffc0000UN.dcm" }, { "374bf25ac4279a7458d848b595b23ed50580400b" , "FUJI-10-MONO1-ACR_NEMA_2.dcm" }, { "ada05095c6d64767af77eafeb2e6fc305f2ba2c8" , "gdcm-ACR-LibIDO.acr" }, { "f2d333278c7ebb985916011ecb808342205b9815" , "gdcm-CR-DCMTK-16-NonSamplePerPix.dcm" }, { "09f0d023545047704beb2fa8168bd7fadca845e2" , "gdcm-JPEG-Extended.dcm" }, { "70da750cb898c6510ba079a1e71b4869faf66dd7" , "gdcm-JPEG-LossLess3a.dcm" }, { "736c14572e7ee964d24b2b5c5b2a607ca50ebc05" , "gdcm-JPEG-LossLessThoravision.dcm" }, { "765541a6e32671891fc0787e69c4917c7166a77a" , "gdcm-MR-PHILIPS-16-Multi-Seq.dcm" }, { "b7d171ebfcb288ec44647f3000515f3683dfef50" , "gdcm-MR-PHILIPS-16-NonSquarePixels.dcm" }, { "6f1e68d6a8586862c31ac7d7a2d2c8d317865263" , "gdcm-MR-SIEMENS-16-2.acr" }, { "a525344659d1767787c6929bb2b080286106e881" , "gdcm-US-ALOKA-16.dcm" }, { "5b8c8d45b6c06f5d2fb90df6205606accfedfc6c" , "GE_CT_With_Private_compressed-icon.dcm" }, { "58c81390cbb3a033c0f1fe15760bd14d87ca8313" , "GE_DLX-8-MONO2-Multiframe.dcm" }, { "53b514276db021a5a8e26cddd3f09c43dad49747" , "GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm" }, { "86ae2ce4b9676110db10ebc6aaba1d49bfa26537" , "GE_DLX-8-MONO2-PrivateSyntax.dcm" }, { "34a42605c83313dbd6d0af4670c2dfabaf270319" , "GE_GENESIS-16-MONO2-Uncompressed-UnusualVR.dcm" }, { "a3f130a256fea9804cc2b9e05dedb4b3af517421" , "GE_GENESIS-16-MONO2-WrongLengthItem.dcm" }, { "da85472c37599dc02c83f2e4c24e3fd5a2617f92" , "GE_LOGIQBook-8-RGB-HugePreview.dcm" }, { "a47f7d0d1d40c213666ccc67d3ce83464a5fa9b8" , "GE_MR_0025xx1bProtocolDataBlock.dcm" }, { "36bcff2d268dbf8e92b296a9cd0894f5b4dcb5ed" , "GE_RHAPSODE-16-MONO2-JPEG-Fragments.dcm" }, { "f84803d8879bc0a461f03c39ec896704796d8376" , "IM-0001-0066.dcm" }, { "fb563954a0b3e8f521248cfac294233e85c517c9" , "ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm" }, { "5a21779c6db335b0f6a989c292b66e2d1939aaae" , "JDDICOM_Sample2.dcm" }, { "9f2559b3e74c09e04c1ccca0424f6bbb3480fe9e" , "JDDICOM_Sample2-dcmdjpeg.dcm" }, { "9af362dd8ba13c358b869ebaf9c70dd2c34a9b49" , "JPEG_LossyYBR.dcm" }, { "e99bd082c18b4f0a150737d5f1a18e00c6bb73d8" , "KODAK-12-MONO1-Odd_Terminated_Sequence.dcm" }, { "12fc320b12b35822da90155a2b92586f8ff4adf0" , "KODAK_CompressedIcon.dcm" }, { "3e554827c2110cd94ab29f65ea4bb8155ae11be8" , "LEADTOOLS_FLOWERS-16-MONO2-JpegLossless.dcm" }, { "1b8c958f48da2aaa1bbc085aec4410f5c2545875" , "LEADTOOLS_FLOWERS-16-MONO2-RLE.dcm" }, { "7be91a03cca70febe383fd4df821f5475cc02c8d" , "LEADTOOLS_FLOWERS-16-MONO2-Uncompressed.dcm" }, { "f6046930f93017ac0586f389d2f69cc47d139615" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossless.dcm" }, { "7de6449beccbeda52d95b027d24448abad1194bc" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm" }, { "6a8f88021d04488bf1d8f5160b49bc9245a5da2c" , "LEADTOOLS_FLOWERS-24-RGB-Uncompressed.dcm" }, { "d5b043ad7c367c4ac5156c8137125d481201f8b6" , "LEADTOOLS_FLOWERS-8-MONO2-JpegLossy.dcm" }, { "3f3d48adcbbe43cd88ec4dd38c0eabac1518cbb1" , "LEADTOOLS_FLOWERS-8-MONO2-RLE.dcm" }, { "a6e1d158e76362545a32d90adfdbc06d0a795aa8" , "LEADTOOLS_FLOWERS-8-MONO2-Uncompressed.dcm" }, { "53e1a8442e52b8e7fb0024f38a3ba47cd1557af4" , "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm" }, { "f1cf42d9fbd847f7bebaa2b2e05ad669401bceeb" , "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm" }, { "5c768b7fa2940546d9f3c49e76d8734ebae41b9b" , "libido1.0-vol.acr" }, { "fe7170c9acf67f99977f12ab41429e082bca4440" , "LIBIDO-16-ACR_NEMA-Volume.dcm" }, { "4d3d23112591bcbbf130e2d83768c59af69c6740" , "LIBIDO-24-ACR_NEMA-Rectangle.dcm" }, { "971bf05ef2a29cdddfb28279b73444fd5dedb046" , "LIBIDO-8-ACR_NEMA-Lena_128_128.acr" }, { "f6cf7fb8470a33f82beef9dcf55b7379464db068" , "LJPEG_BuginGDCM12.dcm" }, { "483032c54da529824e6d1f587dba9a9c5c6f4888" , "MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm" }, { "9033fd528b9008273cbb277f0adb21abe8a1d35a" , "MAROTECH_CT_JP2Lossy.dcm" }, { "88534f6f5c247a198b860108c4d3a5b5f7fb7048" , "MR-Brucker-CineTagging-NonSquarePixels.dcm" }, { "73817e417b440a961dfcc273eeae6007fc004f61" , "MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm" }, { "2f210cc06d8e05b762b8fd996ac730f2442b258a" , "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm" }, { "73eae004f6305c3ef10f710dd51ef750b7ced8ab" , "MR-MONO2-12-an2.acr" }, { "80cb279b9cfe4cd5f8209dc1fd81a0de789fb561" , "MR-MONO2-12-angio-an1.acr" }, { "30a35164282f20ffc38eeb4d0a94b74159f72a38" , "MR-MONO2-12-shoulder.dcm" }, { "c6376ebdfda8ca05bb3d2f2796b2f4ce4cf5417a" , "MR-MONO2-16-head.dcm" }, { "e4b6f0ea147335d048ef1cf271f1f8ea9b3a947a" , "MR-MONO2-8-16x-heart.dcm" }, { "482282eab5270a9b49da1fe52955029c90665318" , "MR_Philips-Intera_BreaksNOSHADOW.dcm" }, { "0edaefb39107ede69cbfef9fa5d646734859560a" , "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm" }, { "002496c378b8d74cde8034c8e64ac06278aaac64" , "MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm" }, { "7b32e317ab15df08cbc22e5c71c19be0236c4a71" , "MR_Philips_Intera_PrivateSequenceImplicitVR.dcm" }, { "d201a0399638b90dab2d147e8505b12dc3f22abf" , "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm" }, { "f86689b7eacfa0c477168f6d95e5f554ba9db2f6" , "MR-SIEMENS-DICOM-WithOverlays.dcm" }, { "4ca412d03202693ea4dbe5189681afb25341e7d7" , "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm" }, { "ddc7ed9fc533413dec8795c35c0dc45485a64422" , "MR_SIEMENS_forceLoad29-1010_29-1020.dcm" }, { "af658128f2acfb72b95892435a34d983194adb85" , "MR_Spectroscopy_SIEMENS_OF.dcm" }, { "a28aa38246dbce06692f5a977ca320cf26bb9260" , "NM-MONO2-16-13x-heart.dcm" }, { "5ca8093b12ff8c78875af95091a96965a94acb19" , "OT-MONO2-8-a7.dcm" }, { "9bf3ca1db0420baede3c257e9c102fe5d27a0554" , "OT-PAL-8-face.dcm" }, { "38a8505e4a5f4119c76636e6eaf754edff1e8122" , "PET-cardio-Multiframe-Papyrus.dcm" }, { "a011aaddce1295f42d9d8fbd14b1558ed04b0b6c" , "PHILIPS_Brilliance_ExtraBytesInOverlay.dcm" }, { "cd88e741f78d2267a7c8a83a0fb4b009fce706f8" , "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm" }, { "05fe55371a99bd6e233b4605eef8b47d5d21f243" , "PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm" }, { "09a07901bb4b6ca120648c3fa478a4172811b4db" , "PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm" }, { "d4a5ce137aac5d979a68b5a62593cf99096a485d" , "PHILIPS_Intera-16-MONO2-Uncompress.dcm" }, { "f64181bf0abfacf2853ce3eeb60149f2c3cf7507" , "PICKER-16-MONO2-Nested_icon.dcm" }, { "aef5bc2a2132e2c11a4f8fc5e1dd7655300d0c1f" , "PICKER-16-MONO2-No_DicomV3_Preamble.dcm" }, { "0fc0e0168128517472e3a4a69808331aaffe4bb5" , "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm" }, { "38e925d7c30ef5b0cf829ea520e271482ea89c7d" , "RadBWLossLess.dcm" }, { "7a57d75599fd8521210835f6506dd77204f16883" , "rle16loo.dcm" }, { "77d3e4e78f0452f4ebb0855fa367e19044014244" , "rle16sti.dcm" }, { "3d9e8bf00e3509fc7210a8a67c3d15622c03b15e" , "SIEMENS-12-Jpeg_Process_2_4-Lossy-a.dcm" }, { "292433a76c4ef0a8341c76b23d030950fbe7865a" , "SIEMENS_CSA2.dcm" }, { "b67eecea6c2099fa0bb0d558ad2fb281e0c14811" , "SIEMENS_GBS_III-16-ACR_NEMA_1.acr" }, { "89c6d755e1f183b18c3711ccce0bdb243d11f05c" , "SIEMENS_GBS_III-16-ACR_NEMA_1-ULis2Bytes.dcm" }, { "521b21eb0b5ec9ebb77de6d7730971a3d5ce5542" , "SIEMENS_ImageLocationUN.dcm" }, { "6f1e68d6a8586862c31ac7d7a2d2c8d317865263" , "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm" }, { "32da5e531a2df100b4a6bc5334c0128a7603c62f" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm" }, { "f7cf7f2d62113863f76580bac6a0465638ebd050" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm" }, { "8708d74b623b3317631a982b9c316c8521c1b220" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm" }, { "461959350160a422e7806a9e8201146b29a3a21f" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm" }, { "e5152fe2ada738f5b0c86af0858dc6d6b3ed9520" , "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm" }, { "bcba71eae5a0e3e43d836c410118e5992f6a6fb7" , "SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm" }, { "38284e6f4591418be8a572aaa190a86b9487ed6f" , "SIEMENS_MAGNETOM-12-MONO2-VRUN.dcm" }, { "61b1b8768cde82a51fa8f5238713d65f16aeff68" , "SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm" }, { "a3646e926f9b8dd6a536b95ab8a86ee35f74f612" , "SIEMENS-MR-RGB-16Bits.dcm" }, { "542213ababb9f3410be5516d28adece7ca9aa4ad" , "SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs.acr" }, { "6d08c8b6f34de509166fa4d1e456e12861ab86e7" , "SIEMENS_Sonata-12-MONO2-SQ.dcm" }, { "4204cf122c096365f7fa14009a4dd62c49e9e5cf" , "SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm" }, { "cd2c42d837702aab1f85de4dc000962dda1fe2f7" , "SignedShortLosslessBug.dcm" }, { "d6e3e55033bd06e8b3e67ef83168d7425cf63c2f" , "simpleImageWithIcon.dcm" }, { "55d4b449f51012c6bcad025a99eea672ba880a60" , "test.acr" }, { "918939283378898524dfa449fd9c9bc12b6dd189" , "TG18-CH-2k-01.dcm" }, { "d70be071b03866d8b561588588b9541ad4c370d7" , "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm" }, { "1f06affc50bfd1382efbf1960f5c601f79db841d" , "TheralysGDCM120Bug.dcm" }, { "16d9e8000e9b19dd3bdb36b3a829780aa43c8b74" , "TOSHIBA_MRT150-16-MONO2-ACR_NEMA_2.dcm" }, { "f188be58d7378e0949b0ee21ef72906ec1c7e236" , "undefined_length_un_vr.dcm" }, { "acf081a99759cef05711ec51d5da9e910396024d" , "US-GE-4AICL142.dcm" }, { "7330de615594148320e2f48a6aecb2e65607fa31" , "US-IRAD-NoPreambleStartWith0003.dcm" }, { "3ffd40a0aba42431d2b2deeed07013e66afb0328" , "US-IRAD-NoPreambleStartWith0005.dcm" }, { "035d7791c0fce801078854697fef86292a97eef1" , "US-MONO2-8-8x-execho.dcm" }, { "8e9ef1a7516ab9bc0fbe894e25c28c7d15dd848d" , "US-PAL-8-10x-echo.dcm" }, { "b401f77c8c78a82422baad6f6d42dcc275b7f0e0" , "US-RGB-8-epicard.dcm" }, { "f4368f3e10ebbd70fbe00c3d4b29d30df3adee85" , "US-RGB-8-esopecho.dcm" }, { "750f15609a6f442c0517173138e404894849b374" , "XA-MONO2-8-12x-catheter.dcm" }, { "cdc423e6abfb6fd678a3e65675cd5ce42f304b0d" , "PHILIPS_GDCM12xBug2.dcm" }, { "916938d82884fcb77a54dade49481e15049e50b6" , "PHILIPS_GDCM12xBug.dcm" }, { "0f058542379c201e26ef233a4b116862283bc81e" , "AMIInvalidPrivateDefinedLengthSQasUN.dcm" }, { "ec4a0d2ff24e9c2f3281b75c479914aff3215fb7" , "OsirixFake16BitsStoredFakeSpacing.dcm" }, { "27277c296a9703f22b2ef033ec326dd22b4bacc9" , "MR16BitsAllocated_8BitsStored.dcm" }, { "6260235b715af050f47494e098fcaa2ada3a11a5" , "JPEGDefinedLengthSequenceOfFragments.dcm" }, { "b1977dfddff0d88742bc6f6368d56eb9d3325dd9" , "IM-0001-0066.CommandTag00.dcm" }, { "f9d31313e26c335d26e4fd9126d88f1467425117" , "UnexpectedSequenceDelimiterInFixedLengthSequence.dcm" }, { "ac491044a7c69d3a365f31f163db3a4bf1085afa" , "GDCMJ2K_TextGBR.dcm" }, { "ed38be73d76c7a326012f86034c7472aa02d83ee" , "NM_Kakadu44_SOTmarkerincons.dcm" }, { "c06aae794ed5690ae82237f4f153ca7795ddd5b7" , "PhilipsInteraSeqTermInvLen.dcm" }, { "c14634b31dc52e4ed2b0c626aa61af4de207f6e4" , "TOSHIBA_J2K_SIZ1_PixRep0.dcm" }, { "bf68f33e0922508d6075f0893298d339d817aa86" , "TOSHIBA_J2K_OpenJPEGv2Regression.dcm" }, { "6d21ac7b5b4ad32b7d91750a70b574a732b679a7" , "TOSHIBA_J2K_SIZ0_PixRep1.dcm" }, { "94cadb9e79e0d04f3c212cf6fa069b3cf3f09a76" , "NM-PAL-16-PixRep1.dcm" }, { "156463350047cada3ec091396695d3f3ef660c9a" , "MEDILABInvalidCP246_EVRLESQasUN.dcm" }, { "9775e8206011b9d5cedfcba16946060cb047f826" , "JPEGInvalidSecondFrag.dcm" }, { "d17a34f8ae066048442ab5b110d43c412472ea7e" , "SC16BitsAllocated_8BitsStoredJ2K.dcm" }, { "71517fce6c32625f1051b72085cfceeee58bd164" , "SC16BitsAllocated_8BitsStoredJPEG.dcm" }, { "0d19e4a98265afc3c782db02bc64bd32124ed2f6" , "SIEMENS_SYNGO-12-MONO2-LUTWrongLength512.dcm" }, { "5cb6c554e80b552ea68cad05409dce4fe92b6dd7" , "IllegalGroup2ImplicitTS.dcm" }, { "031f8cb2cbbe7b5e524b1f79aef6674a66e7f390" , "JPEGLosslessYBR_FULL_422.dcm" }, { "4710e6cfd86c0d349c61b60ae69a684b246db3ff" , "JPEGNote_bogus.dcm" }, { "197e47b5afeeeb75eccafe04e5a1bb0af1a7957a" , "JPEGNote_empty.dcm" }, { "08828e913a7a1ebbc0129c42974b64ce702814b6" , "JPEGNote_missing.dcm" }, { "99c169688190a66100b61319eaeefb3db1936125" , "RLEDebianBug816607Orig.dcm" }, { "f18f91631b59f0242b5daca547878e4c5cbf6a5b" , "GE_MR_0025xx1bProtocolDataBlockXML.dcm" }, { "8c46efd571b33264d7c0bed14fb6dd0282330b92" , "JPEGLS_CharLS_10742.dcm" }, { "f52cac75e6371a8a9b70b2146811b52593cef774" , "EmptyIcon_Bug417.dcm" }, { "fbca7c76d8c290d6a07aff378526463185b391d0" , "EnhancedWithIPPPerFrameIOPShared.dcm" }, { "566387063a28df033d891ac48a42dbb3f6b6a65f" , "FUJI-ffff-MONO1-J2K.dcm" }, { "cb4be6eb5b38940067a1b74ca0360bbb8c66c449" , "JPEGLosslessSeNonZero.dcm" }, { "53137beb3f73345771ff853d670addd81e58906e" , "US-YBR_FULL_422-EVRLE.dcm" }, { "78088c2bfe34911c46476f5fd110c9e0d9813044" , "Osirix10vs8BitsStored.dcm" }, { "31f0556c75829dee3850414e166863220f9e03da" , "Bug_Siemens_PrivateIconNoItem.dcm" }, { "129b3cebd15fd1edb55c8fae75976501f2601dce" , "HardcopyColor_YBR_RCT_J2K_PC1.dcm" }, { "2ac195a776c8cb9f0e6eb2e297bd2bf37bb11697" , "PET-GE-dicomwrite-PixelDataSQUNv2.dcm" }, { NULL, NULL} }; int TestSHA1Func(const char* filename, const char *sha1ref, bool verbose = false) { if( !filename || !sha1ref) return 1; if( verbose ) std::cout << "TestRead: " << filename << std::endl; const char *dataroot = gdcm::Testing::GetDataRoot(); std::string path = dataroot; path += "/"; path += filename; path = filename; char sha1[2*20+1] = {}; bool b = gdcm::SHA1::ComputeFile( path.c_str(), sha1 ); if( !b ) { std::cerr << "Fail ComputeFile: " << path << std::endl; return 1; } if( strcmp( sha1, sha1ref) != 0 ) { std::cout << "Problem with: " << path << std::endl; std::cout << "Ref: " << sha1ref << " vs " << sha1 << std::endl; return 1; } return 0; } static const char *GetSHA1Sum(const char *filename) { typedef const char * const (*sha1pair)[2]; const char *sha1filename; sha1pair sha1filenames = gdcmSHA1SumFiles; int i = 0; while( ( sha1filename = sha1filenames[i][1] ) ) { gdcm::Filename fn( filename ); if( strcmp( sha1filename, fn.GetName() ) == 0 ) { return sha1filenames[i][0]; } ++i; } std::cerr << "Missing SHA1 for: " << filename << std::endl; return 0; } int TestSHA1(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; const char *sha1 = GetSHA1Sum( filename ); return TestSHA1Func(filename, sha1, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { const char *sha1 = GetSHA1Sum( filename ); r += TestSHA1Func( filename, sha1 ); ++i; } return r; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestSmartPointer.cxx000066400000000000000000000042631412732066400232010ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSmartPointer.h" #include "gdcmObject.h" #include using gdcm::Object; using gdcm::SmartPointer; class Foo : public Object { public: void foo() { // Does exist in Object as far as I know :) std::cout << "foo" << std::endl; } }; class Containter { public: Containter():Instance(nullptr) {} SmartPointer Instance; }; void Fill(SmartPointer &p) { SmartPointer in = new Foo; // p = in; Foo & rp = *in; p = &rp; } SmartPointer gf; SmartPointer TestReturn(int i) { static int n = 0; if( !n ) { ++n; gf = new Foo; } if( i == 0 ) { return gf; } else if( i == 1 ) { SmartPointer f = new Foo; return f; } else if( i == 2 ) { return new Foo; } return nullptr; } //class Object2 : public Foo {}; int TestSmartPointer(int, char *[]) { SmartPointer p = new Object; SmartPointer p2 = new Foo; p2->foo(); SmartPointer p3 = new Foo; //p3->foo(); // should not compile //std::cout << p << std::endl; //std::cout << p2 << std::endl; //std::cout << p3 << std::endl; if( p == p2 || p == p3 || p2 == p3 ) { return 1; } // SmartPointer SmartPointer p4 = p2; SmartPointer p5 = p3; // Pointer: SmartPointer p6 = &(*p2); SmartPointer p7; Fill(p7); Foo &foo = *p7; foo.foo(); Containter c1; Containter c2; c2 = c1; // TODO: //SmartPointer s = new Foo; //delete s; for(int i = 0; i < 5; ++i) { SmartPointer f = TestReturn(i); if( f ) { f->foo(); } } return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestString1.cxx000066400000000000000000000054071412732066400221020ustar00rootroot00000000000000/*========================================================================= 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 "gdcmString.h" #include using CSComp = gdcm::String<'\\', 64>; static void Print(CSComp v) { std::cout << v << std::endl; } int TestString1(int , char *[]) { { gdcm::String<'\\'> s = "coucou"; std::cout << s << std::endl; const char str[] = "WINDOW1\\WINDOW2\\WINDOW3"; //const size_t lenstr = strlen(str); gdcm::String<'\\'> ms1, ms2, ms3; std::stringstream ss; ss << str; ss >> ms1; ss.get(); // discard backslash std::cout << ms1 << std::endl; if( ms1 != "WINDOW1" ) return 1; ss >> ms2; ss.get(); std::cout << ms2 << std::endl; if( ms2 != "WINDOW2" ) return 1; ss >> ms3; ss.get(); std::cout << ms3 << std::endl; if( ms3 != "WINDOW3" ) return 1; // we are at the end: if( !!ss ) { std::cerr << "not at the end" << std::endl; return 1; } } { gdcm::String<'^'> s = "coucou"; std::cout << s << std::endl; const char str[] = "WINDOW1^WINDOW2^WINDOW3"; //const size_t lenstr = strlen(str); gdcm::String<'^'> ms1, ms2, ms3; std::stringstream ss; ss << str; ss >> ms1; ss.get(); // discard backslash std::cout << ms1 << std::endl; if( ms1 != "WINDOW1" ) return 1; ss >> ms2; ss.get(); std::cout << ms2 << std::endl; if( ms2 != "WINDOW2" ) return 1; ss >> ms3; ss.get(); std::cout << ms3 << std::endl; if( ms3 != "WINDOW3" ) return 1; // we are at the end: if( !!ss ) return 1; } { gdcm::String<> s = "coucou"; std::cout << s << std::endl; const char str[] = "WINDOW1^WINDOW2^WINDOW3"; //const size_t lenstr = strlen(str); gdcm::String<> ms1; std::stringstream ss; ss << str; ss >> ms1; std::cout << ms1 << std::endl; ss.get(); // discard \n if ( ms1 != str ) return 1; // we are at the end: if( !!ss ) return 1; } std::string privatecreator = " CREATOR SMS-AX "; std::cout << "[" << privatecreator << "]" << std::endl; privatecreator.erase(privatecreator.find_last_not_of(' ') + 1); std::cout << "[" << privatecreator << "]" << std::endl; static const CSComp values[] = {"DERIVED","SECONDARY"}; std::cout << values[0] << std::endl; Print( values[0] ); const char trim[] = "8 "; gdcm::String<> strim( trim ); std::cout << "|" << strim.Trim() << "|" << std::endl; return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestString2.cxx000066400000000000000000000030261412732066400220760ustar00rootroot00000000000000/*========================================================================= 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 "gdcmString.h" #include #include // strlen int TestString2(int , char *[]) { gdcm::String<> s1 = "coucou"; std::cout << s1 << " -> " << s1.size() << std::endl; gdcm::String<> s2 = "coucou!"; std::cout << s2 << " -> " << s2.size() << std::endl; gdcm::String<'\0',64,0> s3 = "coucou"; std::cout << s3.c_str() << " -> " << s3.size() << std::endl; gdcm::String<'\0',64,0> s4 = "coucou!"; std::cout << s4.c_str() << " -> " << s4.size() << std::endl; const char *s = "coucou!"; gdcm::String<'\0',64,0> s5( s, strlen(s) ); std::cout << s5.c_str() << " -> " << s5.size() << std::endl; std::string ss = "coucou!"; gdcm::String<'\0',64,0> s6( ss ); std::cout << s6.c_str() << " -> " << s6.size() << std::endl; gdcm::String<'\0',64,0> s7( ss, 1, 5 ); std::cout << s7.c_str() << " -> " << s7.size() << std::endl; gdcm::String<'\0',64,0> s8( ss, 1, 6 ); std::cout << s8.c_str() << " -> " << s8.size() << std::endl; return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestSwapCode.cxx000066400000000000000000000011771412732066400222600ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSwapCode.h" int TestSwapCode(int, char *[]) { return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestSwapper.cxx000066400000000000000000000021331412732066400221650ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSwapper.h" int TestSwapper(int argc, char *argv[]) { (void)argv; (void)argc; int res = 0; using testswapper = union { uint64_t v64; uint32_t v32[2]; uint16_t v16[4]; uint8_t v8[8]; }; testswapper t; for(uint_fast8_t i = 0; i < 8; ++i) t.v8[i] = i; testswapper val; val.v64 = gdcm::SwapperDoOp::Swap(t.v64); //for(int i = 0; i < 8; ++i) std::cout << (int)val.v8[i] << std::endl; for(int i = 0; i < 8; ++i) { if( val.v8[i] != 8 - i - 1) { ++res; } } return res; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestSystem1.cxx000066400000000000000000000267321412732066400221240ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSystem.h" #include "gdcmTesting.h" #include "gdcmFilename.h" #include #include #include // strlen #include int TestGetTimeOfDay() { time_t t = time(nullptr); char date[22]; if( !gdcm::System::GetCurrentDateTime(date) ) { std::cerr << "Error" << std::endl; return 1; } char time_date[22]; if( !gdcm::System::FormatDateTime(time_date, t) ) { std::cerr << "Error" << std::endl; return 1; } //std::cout << date << std::endl; //std::cout << time_date << std::endl; if ( strncmp( date, time_date, strlen("20090511172802.") ) != 0 ) { std::cerr << "Error" << std::endl; return 1; } return 0; } int TestMakeDirectory() { std::string tmpdir = gdcm::Testing::GetTempDirectory(); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() )) return 1; const char subpath[] = "TestSystem1"; std::string subdir = gdcm::Testing::GetTempDirectory(subpath); if( !gdcm::System::MakeDirectory( subdir.c_str() )) return 1; if( !gdcm::System::FileIsDirectory( subdir.c_str() )) return 1; const char multipath[] = "TestSystem42/another/dir"; std::string subdir2 = gdcm::Testing::GetTempDirectory(multipath); if( !gdcm::System::MakeDirectory( subdir2.c_str() )) return 1; if( !gdcm::System::FileIsDirectory( subdir2.c_str() )) return 1; return 0; } int TestSystem1(int, char *[]) { const char s1[] = "HELLO, wORLD !"; const char s2[] = "Hello, World !"; if( gdcm::System::StrCaseCmp(s1,s2) != 0 ) { return 1; } if( gdcm::System::StrNCaseCmp(s1,s2, strlen(s1)) != 0 ) { return 1; } const char s3[] = "Hello, World ! "; if( gdcm::System::StrCaseCmp(s1,s3) == 0 ) { return 1; } if( gdcm::System::StrNCaseCmp(s1,s3, strlen(s1)) != 0 ) { return 1; } if( gdcm::System::StrNCaseCmp(s1,s3, strlen(s3)) == 0 ) { return 1; } // struct stat { // off_t st_size; /* total size, in bytes */ // } //unsigned long size1 = sizeof(off_t); unsigned long size2 = sizeof(size_t); unsigned long size4 = sizeof(std::streamsize); #if 0 if( size1 > size2 ) { std::cerr << "size_t is not appropriate on this system" << std::endl; // fails on some macosx return 1; } unsigned long size3 = sizeof(uintmax_t); if( size2 != size3 ) { std::cerr << "size_t is diff from uintmax_t: " << size2 << " " << size3 << std::endl; return 1; } #endif if( size2 != size4 ) { std::cerr << "size_t is diff from std::streamsize: " << size2 << " " << size4 << std::endl; //return 1; } char datetime[22]; bool bres = gdcm::System::GetCurrentDateTime(datetime); if( !bres ) { std::cerr << "bres" << std::endl; return 1; } assert( datetime[21] == 0 ); std::cerr << datetime << std::endl; const char *cwd = gdcm::System::GetCWD(); std::cerr << "cwd:" << cwd << std::endl; // GDCM_EXECUTABLE_OUTPUT_PATH "/../" "/Testing/Source/Common/Cxx" /* * I can do this kind of testing here since I know testing: * - cannot be installed (no rule in cmakelists) * - they cannot be moved around since cmake is not relocatable * thus this is safe to assume that current process directory is actually the executable output * path as computed by cmake: * * TODO: there can be trailing slash... */ const char *path = gdcm::System::GetCurrentProcessFileName(); if( !path ) { std::cerr << "Missing implemnetation for GetCurrentProcessFileName" << std::endl; return 1; } gdcm::Filename fn( path ); //std::cerr << path << std::endl; if( strncmp(GDCM_EXECUTABLE_OUTPUT_PATH, fn.GetPath(), strlen(GDCM_EXECUTABLE_OUTPUT_PATH)) != 0 ) { std::cerr << GDCM_EXECUTABLE_OUTPUT_PATH << " != " << fn.GetPath() << std::endl; gdcm::Filename fn_debug1( GDCM_EXECUTABLE_OUTPUT_PATH ); gdcm::Filename fn_debug2( fn.GetPath() ); std::cerr << fn_debug1.GetFileName() << " , " << fn_debug2.GetFileName() << std::endl; std::cerr << std::boolalpha << fn_debug1.IsIdentical( fn_debug2 ) << std::endl; return 1; } // gdcmCommonTests const char exename[] = "gdcmCommonTests"; if( strncmp(exename, fn.GetName(), strlen(exename)) != 0 ) { std::cerr << exename << " != " << fn.GetName() << std::endl; return 1; } { char date[22]; if( !gdcm::System::GetCurrentDateTime( date ) ) { std::cerr << "GetCurrentDateTime: " << date << std::endl; return 1; } assert( date[21] == 0 ); time_t timep; long milliseconds; if( !gdcm::System::ParseDateTime(timep, milliseconds, date) ) { std::cerr << "Could not re-parse: " << date << std::endl; return 1; } char date2[22]; if( !gdcm::System::FormatDateTime(date2, timep, milliseconds) ) { return 1; } assert( date2[21] == 0 ); if( strcmp( date, date2 ) != 0 ) { std::cerr << "date1=" << date << std::endl; std::cerr << "date2=" << date2 << std::endl; return 1; } } // Skip millisecond this time: { char date[22+1]; if( !gdcm::System::GetCurrentDateTime( date ) ) { std::cerr << "GetCurrentDateTime: " << date << std::endl; return 1; } date[14] = 0; std::cout << date << std::endl; time_t timep; if( !gdcm::System::ParseDateTime(timep, date) ) { std::cerr << "ParseDateTime" << std::endl; return 1; } char date2[22+1]; date2[22] = 0; if( !gdcm::System::FormatDateTime(date2, timep) ) { std::cerr << "FormatDateTime" << std::endl; return 1; } // FormatDateTime always print millisecond, only compare the date up to the millisecond: if( strncmp( date, date2, strlen(date) ) != 0 ) { std::cerr << "date1=" << date << std::endl; std::cerr << "date2=" << date2 << std::endl; return 1; } } // Check some valid date { // YYYYMMDDHHMMSS.FFFFFF&ZZXX static const char *dates[] = { "2001", "200101", "20010102", "2001010203", "200101020304", "20010102030405", "20010102030405", "20010102030405.01", "20010102030405.0101", "20010102030405.010101", }; for(int i = 0; i < 10; ++i ) { const char *date = dates[i]; time_t timep; long milliseconds; if( !gdcm::System::ParseDateTime(timep, milliseconds, date) ) { std::cerr << "Should accept: " << date << std::endl; return 1; } } } // Check some invalid date { // YYYYMMDDHHMMSS.FFFFFF&ZZXX static const char *dates[] = { "200", "200121", "20010142", "2001010233", "200101020374", "20010102030485", "20010102030405.", "20010102030405-0000000", "20010102030405.0000001", "20010102030405.0000001", }; for(int i = 0; i < 10; ++i ) { const char *date = dates[i]; time_t timep; long milliseconds; if( gdcm::System::ParseDateTime(timep, milliseconds, date) ) { char buffer[22]; gdcm::System::FormatDateTime(buffer, timep, milliseconds); std::cerr << "Should not accept: " << date << std::endl; std::cerr << "rendered as: " << buffer << std::endl; return 1; } } } //const char long_str8[] = " 0123456789"; //long l = 0; //int n = sscanf( long_str8, "%8ld", &l ); //std::cout << "Long:" << l << std::endl; char hostname[255+1]; hostname[255] = 0; if( gdcm::System::GetHostName( hostname ) ) { std::cout << "Host:" << hostname << std::endl; } else { std::cerr << "cannot get Hostname" << std::endl; return 1; } //time_t t = gdcm::System::FileTime("/etc/debian_version"); //char date3[22]; //gdcm::System::FormatDateTime(date3, t); //std::cout << date3 << std::endl; std::cout << "Check dates:" << std::endl; const char fixed_date[] = "20090428172557.515500"; if( strlen( fixed_date ) != 21 ) { std::cerr << "fixed_date" << std::endl; return 1; } time_t fixed_timep; long fixed_milliseconds; if( !gdcm::System::ParseDateTime(fixed_timep, fixed_milliseconds, fixed_date) ) { std::cerr << "ParseDateTime" << std::endl; return 1; } if( fixed_milliseconds != 515500 ) { std::cerr << "fixed_milliseconds" << std::endl; return 1; } char fixed_date2[22]; if( !gdcm::System::FormatDateTime(fixed_date2, fixed_timep, fixed_milliseconds) ) { std::cerr << "FormatDateTime" << std::endl; return 1; } assert( fixed_date2[21] == 0 ); if( strcmp( fixed_date, fixed_date2 ) != 0 ) { std::cerr << "fixed_date | fixed_date2" << std::endl; return 1; } const char invalid_date1[] = "20090428172557."; if( gdcm::System::ParseDateTime(fixed_timep, fixed_milliseconds, invalid_date1) ) { std::cerr << "should reject:" << invalid_date1 << std::endl; return 1; } const char invalid_date2[] = "200"; if( gdcm::System::ParseDateTime(fixed_timep, fixed_milliseconds, invalid_date2) ) { std::cerr << "should reject:" << invalid_date2 << std::endl; return 1; } // const char invalid_date3[] = "17890714172557"; //if( gdcm::System::ParseDateTime(fixed_timep, fixed_milliseconds, invalid_date3) ) //{ //std::cerr << "should reject:" << invalid_date3 << std::endl; //char buffer[22]; //gdcm::System::FormatDateTime( buffer, fixed_timep, fixed_milliseconds ); //std::cerr << "Found" << buffer << std::endl; //return 1; //} // const char invalid_date4[] = "19891714172557"; //if( gdcm::System::ParseDateTime(fixed_timep, fixed_milliseconds, invalid_date4) ) //{ //std::cerr << "should reject:" << invalid_date4 << std::endl; //char buffer[22]; //gdcm::System::FormatDateTime( buffer, fixed_timep, fixed_milliseconds ); //std::cerr << "Found" << buffer << std::endl; // //return 1; //} // const char invalid_date5[] = "19890014172557"; //if( gdcm::System::ParseDateTime(fixed_timep, fixed_milliseconds, invalid_date5) ) //{ //std::cerr << "should reject:" << invalid_date5 << std::endl; //char buffer[22]; //gdcm::System::FormatDateTime( buffer, fixed_timep, fixed_milliseconds ); //std::cerr << "Found" << buffer << std::endl; // //return 1; //} const char valid_date1[] = "19890714172557"; if( !gdcm::System::ParseDateTime(fixed_timep, fixed_milliseconds, valid_date1) ) { std::cerr << "should accept:" << valid_date1 << std::endl; return 1; } std::cout << "End Check dates" << std::endl; int res = 0; res += TestGetTimeOfDay(); std::cout << "res = " << res << std::endl; res += TestMakeDirectory(); std::cout << "res = " << res << std::endl; const char * testfilesize = gdcm::Testing::GetTempFilename( "filesize.bin" ); if( gdcm::System::FileExists( testfilesize ) ) { gdcm::System::RemoveFile(testfilesize); } size_t ss1 = gdcm::System::FileSize( testfilesize ); if( ss1 != 0 ) { std::cerr << "found:" << ss1 << std::endl; ++res; } std::ofstream os( testfilesize, std::ios::binary ); const char coucou[] = "coucou"; os << coucou; os.flush(); os.close(); size_t ss2 = gdcm::System::FileSize( testfilesize ); if( ss2 != strlen( coucou ) ) { std::cerr << "found:" << ss2 << std::endl; res++; } const char *codeset = gdcm::System::GetLocaleCharset(); if( !codeset ) { std::cerr << "Could not find Charset on your system. Please report." << std::endl; res++; } return res; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestSystem2.cxx000066400000000000000000000030361412732066400221150ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSystem.h" #include "gdcmTesting.h" #define _FILE_OFFSET_BITS 64 #include static bool mybool; static size_t actualde; static bool check( const int64_t inslen ) { std::cerr << "check:" << inslen << std::endl; if( inslen < 0 ) return true; return false; } static bool append( size_t len ) { off_t newlen = (off_t)len; #if 1 newlen -= (off_t)actualde; return check( newlen ); #else return check( newlen - actualde ); #endif } int TestSystem2(int, char *[]) { const int soff = sizeof( off_t ); std::cerr << soff << std::endl; mybool = true; actualde = 26; off_t o0 = -1; off_t o1 = 0; //off_t o2 = 1; std::cerr << "t:" << o0 << std::endl; if( o0 > o1 ) { std::cerr << "Not a long value" << std::endl; return 1; } int val1 = 5; int val2 = 10; size_t size = 2; const off_t o = (off_t)size; if( !check( o + val1 - val2 ) ) { return 1; } if( !append( 2 ) ) { return 1; } return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestSystem3.cxx000066400000000000000000000032611412732066400221160ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSystem.h" #include "gdcmTesting.h" #include #include // strdup int TestSystem3(int, char *[]) { const char isostr[] = "\\ISO 2022 IR 13\\ISO 2022 IR 87"; const char delim[] = "\\"; char *token; { char *query = strdup( isostr ); char *str1; char *saveptr1; std::vector< std::string > v; for (str1 = query; ; str1 = nullptr) { token = gdcm::System::StrTokR(str1, delim, &saveptr1); if (token == nullptr) break; //std::cout << "[" << token << "]" << std::endl; v.emplace_back(token ); } free( query ); if( v.size() != 2 ) return 1; if( v[0] != "ISO 2022 IR 13" ) return 1; if( v[1] != "ISO 2022 IR 87" ) return 1; } { std::vector< std::string > v; char *string = strdup( isostr ); if(!string) return 1; char *copy = string; while ((token = gdcm::System::StrSep(&string, delim)) != nullptr) { //printf("token=%s\n", token); v.emplace_back(token ); } free( copy ); if( v.size() != 3 ) return 1; if( !v[0].empty() ) return 1; if( v[1] != "ISO 2022 IR 13" ) return 1; if( v[2] != "ISO 2022 IR 87" ) return 1; } return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestTerminal.cxx000066400000000000000000000054121412732066400223220ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTerminal.h" #include namespace term = gdcm::terminal; void TestAll() { std::cout << term::setattribute( term::bright ) << "bright" << std::endl; std::cout << term::setattribute( term::dim ) << "dim" << std::endl; std::cout << term::setattribute( term::underline ) << "underline" << std::endl; std::cout << term::setattribute( term::blink ) << "blink" << std::endl; std::cout << term::setattribute( term::reverse ) << "reverse" << std::endl; std::cout << term::setattribute( term::reset ) << "reset" << std::endl; std::cout << term::setfgcolor( term::black ) << "fg:black" << std::endl; std::cout << term::setfgcolor( term::red ) << "fg:red " << std::endl; std::cout << term::setfgcolor( term::green ) << "fg:green" << std::endl; std::cout << term::setfgcolor( term::yellow ) << "fg:yellow" << std::endl; std::cout << term::setfgcolor( term::blue ) << "fg:blue" << std::endl; std::cout << term::setfgcolor( term::magenta ) << "fg:magenta" << std::endl; std::cout << term::setfgcolor( term::cyan ) << "fg:cyan" << std::endl; std::cout << term::setfgcolor( term::white ) << "fg:white" << std::endl; std::cout << term::setattribute( term::reverse ) << term::setfgcolor( term::white ) << "fg:white" << std::endl; std::cout << term::setbgcolor( term::black ) << "bg:black" << std::endl; std::cout << term::setbgcolor( term::red ) << "bg:red " << std::endl; std::cout << term::setbgcolor( term::green ) << "bg:green" << std::endl; std::cout << term::setbgcolor( term::yellow ) << "bg:yellow" << std::endl; std::cout << term::setbgcolor( term::blue ) << "bg:blue" << std::endl; std::cout << term::setbgcolor( term::magenta ) << "bg:magenta" << std::endl; std::cout << term::setbgcolor( term::cyan ) << "bg:cyan" << std::endl; std::cout << term::setbgcolor( term::white ) << "bg:white" << std::endl; std::cout << term::setattribute( term::reset ) << "reset" << std::endl; //std::cerr << term::setbgcolor( term::blue ) << "cerr:bg:blue" << std::endl; } int TestTerminal(int , char *[]) { // Typically for WIN32 term::setmode( term::CONSOLE ); TestAll(); // For all *NIX // rxvt is WIN32 app, but is a VT100 compatible TERM term::setmode( term::VT100 ); TestAll(); return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestTesting.cxx000066400000000000000000000025011412732066400221600ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTesting.h" #include "gdcmSystem.h" int TestTesting(int , char *[]) { gdcm::Testing testing; testing.Print( std::cout ); const char *f = gdcm::Testing::GetFileName( 100000 ); if( f ) return 1; std::cout << "Num:" << gdcm::Testing::GetNumberOfFileNames() << std::endl; const char * const * md5 = gdcm::Testing::GetMD5DataImage( 100000 ); if( !md5 ) return 1; if( md5[0] || md5[1] ) return 1; const char * const *null = gdcm::Testing::GetMD5DataImage(1000000000u); if( null[0] != nullptr || null[1] != nullptr ) { return 1; } const char *tmp = gdcm::Testing::GetTempDirectory(); if( !gdcm::System::FileExists(tmp) ) { return 1; } if( !gdcm::System::FileIsDirectory(tmp) ) { return 1; } return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestTrace.cxx000066400000000000000000000057431412732066400216140ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTrace.h" #include int TestTrace(int, char *[]) { gdcm::Trace t; //initializes all macros to 'off' gdcmDebugMacro( "DebugKO" ); gdcmWarningMacro( "WarningKO" ); gdcmErrorMacro( "ErrorKO" ); // test the SetStream interface std::ostringstream useros; gdcm::Trace::SetStream( useros ); gdcmDebugMacro( "DebugOK_OFF" ); gdcmWarningMacro( "WarningOK_OFF" ); gdcmErrorMacro( "ErrorOK_OFF" ); gdcm::Trace::DebugOn(); gdcm::Trace::WarningOn(); gdcm::Trace::ErrorOn(); gdcmDebugMacro( "DebugOK_ON" ); gdcmWarningMacro( "WarningOK_ON" ); gdcmErrorMacro( "ErrorOK_ON" ); //in release mode, tracing just doesn't work any more, so this test isn't valid. #ifndef NDEBUG std::string result = useros.str(); if( result.find( "KO" ) != std::string::npos ) { std::cerr << result << std::endl; return 1; } if( result.find( "OFF" ) != std::string::npos ) { std::cerr << result << std::endl; return 1; } // opposite: if( result.find( "OK" ) == std::string::npos ) { std::cerr << result << std::endl; return 1; } if( result.find( "ON" ) == std::string::npos ) { std::cerr << result << std::endl; return 1; } #endif // Test Debug/Warning/Error interface: std::ostringstream debug; std::ostringstream warning; std::ostringstream error; gdcm::Trace::SetDebugStream( debug ); gdcm::Trace::SetWarningStream( warning ); gdcm::Trace::SetErrorStream( error ); gdcmDebugMacro( "Debug1234" ); gdcmWarningMacro( "Warning1234" ); gdcmErrorMacro( "Error1234" ); #ifndef NDEBUG std::string result1 = debug.str(); std::string result2 = warning.str(); std::string result3 = error.str(); if( result1.find( "Debug1234" ) == std::string::npos ) { std::cerr << result1 << std::endl; return 1; } if( result2.find( "Warning1234" ) == std::string::npos ) { std::cerr << result2 << std::endl; return 1; } if( result3.find( "Error1234" ) == std::string::npos ) { std::cerr << result3 << std::endl; return 1; } if( result1.find( "Warning1234" ) != std::string::npos ) { std::cerr << result1 << std::endl; return 1; } if( result2.find( "Error1234" ) != std::string::npos ) { std::cerr << result2 << std::endl; return 1; } if( result3.find( "Debug1234" ) != std::string::npos ) { std::cerr << result3 << std::endl; return 1; } #endif return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestTypes.cxx000066400000000000000000000020111412732066400216430ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTypes.h" int TestTypes(int argc, char *argv[]) { (void)argc; (void)argv; if( sizeof(int8_t) != 1 ) return 1; if( sizeof(int16_t) != 2 ) return 1; if( sizeof(int32_t) != 4 ) return 1; if( sizeof(uint8_t) != 1 ) return 1; if( sizeof(uint16_t) != 2 ) return 1; if( sizeof(uint32_t) != 4 ) return 1; if( sizeof(uint64_t) != 8 ) return 1; if( sizeof(float) != 4 ) return 1; if( sizeof(double) != 8 ) return 1; return 0; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestUnpacker12Bits.cxx000066400000000000000000000070371412732066400233110ustar00rootroot00000000000000/*========================================================================= 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 "gdcmUnpacker12Bits.h" #include #include #include #include int TestUnpacker12Bits(int, char *[]) { int res = 0; { const size_t len = (256 / 3 ) * 3; char *values = new char[len]; for( size_t i = 0; i < len; ++i) { values[i] = (char)i; } //const char values[] = {0, 1, 2}; //const size_t len = sizeof(values) / sizeof(*values); const size_t outlen = 16 * len / 12; char * output = new char[outlen]; bool b = gdcm::Unpacker12Bits::Unpack(output, values, len); if( b ) { std::set out; short * output_s = (short*)(void*)output; for( size_t i = 0; i < outlen / 2; ++i ) { const short &v = output_s[i]; // There is no way we can have values greater than a 12bits integer: if( v >= 4096 || v < 0 ) { std::cerr << "Too big:" << v << std::endl; res = 1; } // no duplicate possible std::pair< std::set::iterator, bool> p = out.insert( v ); if( p.second == false ) { std::cerr << "duplicate:" << v << std::endl; res = 1; } //std::cout << v << std::endl; } } else { res = 1; } delete[] values; delete[] output; } { const unsigned char values[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }; const size_t len = sizeof(values) / sizeof(*values); const size_t outlen = 16 * len / 12; char * output = new char[outlen]; bool b = gdcm::Unpacker12Bits::Unpack(output, (const char*)values, len); if (!b) res = 1; if( b ) { unsigned short * output_s = (unsigned short*)output; const unsigned short outputvalues[] = { 0x301, 0x452, 0x967, 0xab8 }; const size_t outputlen = sizeof(outputvalues) / sizeof(*outputvalues); assert( outlen / 2 == outputlen ); for(size_t i = 0; i < outputlen; ++i) { if( outputvalues[i] != output_s[i] ) { ++res; } } } delete[] output; } { const unsigned short input[] = { 0x301, 0x452, 0x967, 0xab8 }; unsigned char values[6] = {}; const unsigned char ref[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }; bool b = gdcm::Unpacker12Bits::Pack((char*)values, (const char*)input, 8); // 4 * sizeof(us) == 8 if(!b) { return 1; } for(size_t i = 0; i < 6; ++i) { if( values[i] != ref[i] ) { assert(0); ++res; } } } { //struct uint12_t { unsigned short v:12; }; std::vector v; for(uint16_t val = 0; val < 4096; ++val) { v.push_back( val ); } assert( v.size() == 4096 ); assert( v[0] == 0 ); const size_t outsize = 4096 / 2 * 3; unsigned char outvalues[outsize] = {}; gdcm::Unpacker12Bits::Pack( (char*)outvalues, (char*)&v[0], 4096 * sizeof(unsigned short) ); unsigned short outvalues2[4096] = {}; gdcm::Unpacker12Bits::Unpack( (char*)outvalues2, (char*)outvalues, outsize); for(uint16_t val = 0; val < 4096; ++val) { if( v[val] != outvalues2[val] ) { ++res; } } } return res; } GDCM-3.0.10/Testing/Source/Common/Cxx/TestVersion.cxx000066400000000000000000000020671412732066400221770ustar00rootroot00000000000000/*========================================================================= 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 "gdcmVersion.h" int TestVersion(int, char *[]) { // The following statements just test whether those functions are callable: const char *version = gdcm::Version::GetVersion(); (void)version; const int majorVersion = gdcm::Version::GetMajorVersion(); (void)majorVersion; const int minorVersion = gdcm::Version::GetMinorVersion(); (void)minorVersion; const int buildVersion = gdcm::Version::GetBuildVersion(); (void)buildVersion; gdcm::Version v; v.Print( std::cout ); return 0; } GDCM-3.0.10/Testing/Source/Common/Python/000077500000000000000000000000001412732066400177005ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/Common/Python/CMakeLists.txt000066400000000000000000000005361412732066400224440ustar00rootroot00000000000000# Define the tests for gdcm-python set(GDCM_PYTHON_TEST_SRCS TestTesting ) if(GDCM_DATA_ROOT) set(GDCM_PYTHON_TEST_SRCS ${GDCM_PYTHON_TEST_SRCS} TestDirectory ) endif() # Loop over files and create executables foreach(name ${GDCM_PYTHON_TEST_SRCS}) ADD_PYTHON_TEST(${name}Python ${name}.py ${GDCM_DATA_ROOT}/test.acr) endforeach() GDCM-3.0.10/Testing/Source/Common/Python/TestDirectory.py000066400000000000000000000016411412732066400230600ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import os,sys dir = gdcm.Directory() t = gdcm.Testing() dataroot = t.GetDataRoot() system = gdcm.System() if not system.FileIsDirectory(dataroot): sys.exit(1) nfiles = dir.Load(dataroot) if nfiles == 0: sys.exit(1) #print dir.GetFilenames() for file in dir.GetFilenames(): print(file) # Test succeed ? #sys.exit(success != 1) GDCM-3.0.10/Testing/Source/Common/Python/TestTesting.py000066400000000000000000000014631412732066400225330ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import os,sys t = gdcm.Testing() nfiles = t.GetNumberOfFileNames() print(nfiles) for i in range(0,nfiles): print(t.GetFileName(i)) print(t.GetFileName(10000)) print(t.GetDataRoot()) # Test succeed ? #sys.exit(success != 1) GDCM-3.0.10/Testing/Source/Data/000077500000000000000000000000001412732066400160405ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/Data/CMakeLists.txt000066400000000000000000000106451412732066400206060ustar00rootroot00000000000000#----------------------------------------------------------------------------- # We need to test the reading of all dicom images in the gdcmData directory # First parse this directory and extract all images set(GDCM_DATA_IMAGE_FILENAMES_GLOB_EXPR "${GDCM_DATA_ROOT}/*.acr" "${GDCM_DATA_ROOT}/*.nema" "${GDCM_DATA_ROOT}/*.dcm" ) set(GDCM_DATA_DICOMDIR_FILENAMES_GLOB_EXPR # Those files do not have any extension, special regex: "${GDCM_DATA_ROOT}/dicomdir*" ) # Case sensitive system: if(UNIX) set(GDCM_DATA_IMAGE_FILENAMES_GLOB_EXPR ${GDCM_DATA_IMAGE_FILENAMES_GLOB_EXPR} "${GDCM_DATA_ROOT}/*.DCM" ) set(GDCM_DATA_DICOMDIR_FILENAMES_GLOB_EXPR ${GDCM_DATA_DICOMDIR_FILENAMES_GLOB_EXPR} "${GDCM_DATA_ROOT}/DICOMDIR*" ) endif() # GLOB expression ! file(GLOB GDCM_DATA_IMAGE_FILENAMES_GLOB ${GDCM_DATA_IMAGE_FILENAMES_GLOB_EXPR} ) # Same for DICOMDIR: file(GLOB GDCM_DATA_DICOMDIR_FILENAMES_GLOB ${GDCM_DATA_DICOMDIR_FILENAMES_GLOB_EXPR} ) set(GDCM_DATA_FILENAMES_GLOB ${GDCM_DATA_IMAGE_FILENAMES_GLOB} ${GDCM_DATA_DICOMDIR_FILENAMES_GLOB} ) # List of images that are technically difficult to read # Hopefully we will soon be able to read them set(BLACK_LIST_READER # grrrrrr do not handle swapping correctly (implicit dataset are such a pain) LIBIDO-16-ACR_NEMA-Volume.dcm # Papyrus: PET-cardio-Multiframe-Papyrus.dcm # No way to read this image: ELSCINT1_LOSSLESS_RICE.dcm # SignedShortLossless has never really been supported anyway: SignedShortLosslessBug.dcm # Would need to process ALL Pixel Data element when decompressing: PET-GE-dicomwrite-PixelDataSQUNv3.dcm # Toshiba US Private Data Storage 1.2.392.200036.9116.7.8.1.1.1 TOSHIBA_MDW_HEADER.dcm # TODO, nasty: PhilipsLosslessRice.dcm # This file is incorrect IM-0001-0066.dcm # Problem with RLE SIEMENS_GBS_III-16-ACR_NEMA_1.acr SIEMENS_GBS_III-16-ACR_NEMA_1-ULis2Bytes.dcm # TestImageChangeTransferSyntax1 MR-MONO2-12-angio-an1.acr # Openjpeg / Part 2: lena512_rot90.j2k.dcm # Remove this one for now: LengthOfItemLarger.dcm # https://github.com/team-charls/charls/issues/16 JPEG_LS_InvalidEscapeSequence_COM_padding.dcm # MITRA_CORNELL MITRA_CORNELL.dcm # FIXME PET-GE-dicomwrite-PixelDataSQUN.dcm ) if(NOT GDCM_USE_PVRG) set(BLACK_LIST_READER # The following should really fails according to JPEG spec, IJG is failing and even when forcing # decompression using IJG output is different from PVRG... # Apparently pvrg likes it this way... # PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm ${BLACK_LIST_READER} PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm ) endif() if(GDCM_WORDS_BIGENDIAN) set(BLACK_LIST_READER ${BLACK_LIST_READER} MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm PHILIPS_Intera-16-MONO2-Uncompress.dcm SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm PICKER-16-MONO2-No_DicomV3_Preamble.dcm ) endif() if(NOT GDCM_SUPPORT_BROKEN_IMPLEMENTATION) set(BLACK_LIST_READER ${BLACK_LIST_READER} GE_GENESIS-16-MONO2-WrongLengthItem.dcm # can't read odd length PHILIPS_GDCM12xBug2.dcm # odd length KODAK-12-MONO1-Odd_Terminated_Sequence.dcmq # odd length PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm # odd length PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm # odd length BugGDCM2_UndefItemWrongVL.dcm # odd length THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm CT-SIEMENS-MissingPixelDataInIconSQ.dcm # odd length 00191113.dcm MR_Philips_Intera_PrivateSequenceImplicitVR.dcm PICKER-16-MONO2-Nested_icon.dcm PHILIPS_GDCM12xBug.dcm # odd length MR_Philips-Intera_BreaksNOSHADOW.dcm NM_Kakadu44_SOTmarkerincons.dcm MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm ) endif() set(GDCM_DATA_FILENAMES) set(GDCM_BLACK_LIST_READER_DATA_FILENAMES) foreach(filename ${GDCM_DATA_FILENAMES_GLOB}) get_filename_component(filename_name ${filename} NAME) string(REGEX MATCH ${filename_name} bad_dicom ${BLACK_LIST_READER}) if(NOT bad_dicom) set(GDCM_DATA_FILENAMES "${GDCM_DATA_FILENAMES}\n\"${filename}\",") else() set(GDCM_BLACK_LIST_READER_DATA_FILENAMES "${GDCM_BLACK_LIST_READER_DATA_FILENAMES}\n\"${filename}\",") endif() endforeach() # Populate GDCM_DATA_FILENAMES: configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/gdcmDataFileNames.cxx.in" "${CMAKE_CURRENT_BINARY_DIR}/gdcmDataFileNames.cxx" ) GDCM-3.0.10/Testing/Source/Data/NativeDICOM.rnc000066400000000000000000000051401412732066400205460ustar00rootroot00000000000000# PS 3.19-2011 # A.1.6 Schema # The Normative version of the XML Schema for the Native DICOM Model follows: default namespace="http://dicom.nema.org/PS3.19/models/NativeDICOM" # This schema was created as an intermediary, a means of describing # native binary encoded DICOM objects as XML Infosets, thus allowing # one to manipulate binary DICOM objects using familiar XML tools. # As such, the schema is designed to facilitate a simple, mechanical, # bi-directional translation between binary encoded DICOM and XML-like # constructs without constraints, and to simplify identifying portions # of a DICOM object using XPath statements. # # Since this schema has minimal type checking, it is neither intended # to be used for any operation that involves hand coding, nor to # describe a definitive, fully validating encoding of DICOM concepts # into XML, as what one might use, for example, in a robust XML # database system or in XML-based forms, though it may be used # as a means for translating binary DICOM Objects into such a form # (e.g. through an XSLT script). start = element NativeDicomModel { DicomDataSet } # A DICOM Data Set is as defined in PS3.5. It does not appear # as an XML Element, since it does not appear in the binary encoded # DICOM objects. It exists here merely as a documentation aid. DicomDataSet = DicomAttribute* DicomAttribute = element DicomAttribute { Tag, VR, Keyword?, PrivateCreator?, ( BulkData | Value+ | Item+ | PersonName+ )? } BulkData = element BulkData{ UUID } Value = element Value { Number, xsd:string } Item = element Item { Number, DicomDataSet } PersonName = element PersonName { Number, element SingleByte { NameComponents }?, element Ideographic { NameComponents }?, element Phonetic { NameComponents }? } NameComponents = element FamilyName {xsd:string}?, element GivenName {xsd:string}?, element MiddleName {xsd:string}?, element NamePrefix {xsd:string}?, element NameSuffix {xsd:string}? # keyword is the attribute tag from PS3.6 # (derived from the DICOM Attribute's name) Keyword = attribute keyword { xsd:token } # canonical XML definition of Hex, with lowercase letters disallowed Tag = attribute tag { xsd:string{ minLength="8" maxLength="8" pattern="[0-9A-F]{8}" } } VR = attribute vr { "AE" | "AS" | "AT" | "CS" | "DA" | "DS" | "DT" | "FL" | "FD" | "IS" | "LO" | "LT" | "OB" | "OF" | "OW" | "PN" | "SH" | "SL" | "SQ" | "SS" | "ST" | "TM" | "UI" | "UL" | "UN" | "US" | "UT" } PrivateCreator = attribute privateCreator{ xsd:string } UUID = attribute uuid { xsd:string } Number = attribute number { xsd:positiveInteger } GDCM-3.0.10/Testing/Source/Data/NativeDICOM.rng000066400000000000000000000126271412732066400205620ustar00rootroot00000000000000 8 8 [0-9A-F]{8} AE AS AT CS DA DS DT FL FD IS LO LT OB OF OW PN SH SL SQ SS ST TM UI UL UN US UT GDCM-3.0.10/Testing/Source/Data/QIDO-RS_examplesup166.json000066400000000000000000000134261412732066400225170ustar00rootroot00000000000000// The following example is a QIDO-RS SearchForStudies response consisting // of two matching studies, corresponding to the example QIDO-RS request: // GET http://qido.nema.org/studies?PatientID=12345&includefield=all&limit=2 [ { // Result 1 "SpecificCharacterSet": { "Tag": "00080005", "VR": "CS", "Value": [ "ISO_IR192" ] }, "StudyDate": { "Tag": "00080020", "VR": "DT", "Value": [ "20130409" ] }, "StudyTime": { "Tag": "00080030", "VR": "TM", "Value": [ "131600.0000" ] }, "AccessionNumber": { "Tag": "00080050", "VR": "SH", "Value": [ "11235813" ] }, "InstanceAvailability": { "Tag": "00080056", "VR": "CS", "Value": [ "ONLINE" ] }, "ModalitiesInStudy": { "Tag": "00080061", "VR": "CS", "Value": [ "CT", "PET" ] }, "ReferringPhysiciansName": { "Tag": "00080090", "VR": "PN", "PersonName": [ { "SingleByte": "^Bob^^Dr." } ] }, "00090010": { "Tag": "00090010", "VR": "LO", "Value": [ "Vendor A" ] }, "00091002": { "Tag": "00091002", "VR": "UN", "PrivateCreator": "Vendor A", "Value": [ "z0x9c8v7" ] }, "PatientName": { "Tag": "00100010", "VR": "PN", "PersonName": [ { "SingleByte": "Wang^XiaoDong", "Ideographic": "王^小東" } ] }, "PatientID": { "Tag": "00100020", "VR": "LO", "Value": [ "12345" ] }, "IssuerOfPatientID": { "Tag": "00100021", "VR": "LO", "Value": [ "Hospital A" ] }, "PatientsBirthDate": { "Tag": "00100030", "VR": "DT", "Value": [ "19670701" ] }, "PatientsSex": { "Tag": "00100040", "VR": "CS", "Value": [ "M" ] }, "OtherPatientIDsSequence": { "Tag": "00101002", "VR": "SQ", "Sequence": [ { "PatientID": { "Tag": "00100020", "VR": "LO", "Value": [ "54321" ] }, "IssuerOfPatientID": { "Tag": "00100021", "VR": "LO", "Value": [ "Hospital B" ] } }, { "PatientID": { "Tag": "00100020", "VR": "LO", "Value": [ "24680" ] }, "IssuerOfPatientID": { "Tag": "00100021", "VR": "LO", "Value": [ "Hospital C" ] } } ] }, "StudyID": { "Tag": "00200010", "VR": "SH", "Value": [ "11235813" ] }, "StudyInstanceUID": { "Tag": "0020000D", "VR": "UI", "Value": [ "1.2.392.200036.9116.2.2.2.1762893313.1029997326.945873" ] }, "NumberOfStudyRelatedSeries": { "Tag": "00201206", "VR": "IS", "Value": [ "4" ] }, "NumberOfStudyRelatedInstances": { "Tag": "00201208", "VR": "IS", "Value": [ "942" ] }, "RetrieveURL": { "Tag": "00081190", "VR": "UT", "Value": [ "http://wado.nema.org/studies/1.2.392.200036.9116.2.2.2.1762893313.1029997326.945873" ] } }, { // Result 2 "SpecificCharacterSet": { "Tag": "00080005", "VR": "CS", "Value": [ "ISO_IR192" ] }, "StudyDate": { "Tag": "00080020", "VR": "DT", "Value": [ "20130309" ] }, "StudyTime": { "Tag": "00080030", "VR": "TM", "Value": [ "111900.0000" ] }, "AccessionNumber": { "Tag": "00080050", "VR": "SH", "Value": [ "11235821" ] }, "InstanceAvailability": { "Tag": "00080056", "VR": "CS", "Value": [ "ONLINE" ] }, "ModalitiesInStudy": { "Tag": "00080061", "VR": "CS", "Value": [ "CT", "PET" ] }, "ReferringPhysiciansName": { "Tag": "00080090", "VR": "PN", "PersonName": [ { "SingleByte": "^Bob^^Dr." } ] }, "00090010": { "Tag": "00090010", "VR": "LO", "Value": [ "Vendor A" ] }, "00091002": { "Tag": "00091002", "VR": "UN", "PrivateCreator": "Modality Vendor A", "Value": [ "z0x9c8v7" ] }, "PatientName": { "Tag": "00100010", "VR": "PN", "PersonName": [ { "SingleByte": "Wang^XiaoDong", "Ideographic": "王^小東" } ] }, "PatientID": { "Tag": "00100020", "VR": "LO", "Value": [ "12345" ] }, "IssuerOfPatientID": { "Tag": "00100021", "VR": "LO", "Value": [ "Hospital A" ] }, "PatientsBirthDate": { "Tag": "00100030", "VR": "DT", "Value": [ "19670701" ] }, "PatientsSex": { "Tag": "00100040", "VR": "CS", "Value": [ "M" ] }, "OtherPatientIDsSequence": { "Tag": "00101002", "VR": "SQ", "Sequence": [ { "PatientID": { "Tag": "00100020", "VR": "LO", "Value": [ "54321" ] }, "IssuerOfPatientID": { "Tag": "00100021", "VR": "LO", "Value": [ "Hospital B" ] } }, { "PatientID": { "Tag": "00100020", "VR": "LO", "Value": [ "24680" ] }, "IssuerOfPatientID": { "Tag": "00100021", "VR": "LO", "Value": [ "Hospital C" ] } } ] }, "StudyID": { "Tag": "00200010", "VR": "SH", "Value": [ "11235821" ] }, "StudyInstanceUID": { "Tag": "0020000D", "VR": "UI", "Value": [ "1.2.392.200036.9116.2.2.2.2162893313.1029997326.945876" ] }, "NumberOfStudyRelatedSeries": { "Tag": "00201206", "VR": "IS", "Value": [ "5" ] }, "NumberOfStudyRelatedInstances": { "Tag": "00201208", "VR": "IS", "Value": [ "1123" ] }, "RetrieveURL": { "Tag": "00081190", "VR": "UT", "Value": [ "http://wado.nema.org/studies/1.2.392.200036.9116.2.2.2.2162893313.1029997326.945876" ] } } ] GDCM-3.0.10/Testing/Source/Data/certificate.pem000066400000000000000000000025021412732066400210240ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIDtTCCAp2gAwIBAgIJAKyWbYh4elG0MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX aWRnaXRzIFB0eSBMdGQwHhcNMDkwNDI3MDk1NzE1WhcNMTAwNDI3MDk1NzE1WjBF MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50 ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB CgKCAQEA4k5GEgO9mI5K2UuywuGxcO4xJdygQlpvL2IS9XEbXOWBEwJZx1tccfzC a929DCijlJE6/f5KBzDNPdLpPt3eyUKB3n7mOos7ATWEFCZgE7RWGRBhIfN2R9LD kLT2eaUhXDzsk7L1qmKPP9nSdAXoUB6sj0EmHrQQWIPEZwGcPcvMUhcUpjD/hnmC X6DAWHVCvE7vhbHntNYFwu1Bmau5ZY6Ywk5lQ/ZTfEYcRD1ZmUB2Wkzv4InvRc1z YbTBpL/Lkft1B9/A7+LzJJRHoNvHaMN5pRF2qFyZW3sb+bh8z8SC0oJNzIbrWZvW M9TEnQ8P+GCw4y68juSvlcLcBsoxCQIDAQABo4GnMIGkMB0GA1UdDgQWBBTNWfHq ZOUwrkeH39jLz0qgBV1LaDB1BgNVHSMEbjBsgBTNWfHqZOUwrkeH39jLz0qgBV1L aKFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAKyWbYh4elG0MAwGA1UdEwQF MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAMvT7rwSoHwOUMr1ZnjCYccuBsWND1Vt JvMzELX/IUs2f0BbDVZeyn1NC7VyoAOfvgJwLccK6v49p2J/SbBaAiixlgGAi670 V7VkwMaDKIAR/AEIbORwcRoogHYSft4to1kNcPmYOhiny2VFWSp3Fmoc/egU3Cbo pVH/ixjcCT7q/6MIuklnvULGSOajtE/+fz+KzlX8nZyD22oMk/TtxVsys8F0qWtZ HsGoXUY15xg+HjHcSCOBeU7pAglCyRCLyO3mhAgfE3o4T5HBp4opjfRGDaVd+uPj XRjzAZgfgLQAmiUixyCzzG8wDgpFVdoOcWQ9RcNnR9XgIw5Omas75so= -----END CERTIFICATE----- GDCM-3.0.10/Testing/Source/Data/encrypted_text000066400000000000000000000007311412732066400210250ustar00rootroot000000000000000 *H 01n0j0R0E1 0 UAU10U Some-State1!0U Internet Widgits Pty Ltd mxzQ0  *H 5"/}R Tp`vb V#a2zw\ȩ>@256DTm\kE|P8ݵÖUy95^t'/tKUWMbonϓT9&{^:*HH,9q,3ͰB$uoy;O#Uq?kwx+Fzm}v+fi EFk@ȥW?Jɷ3 d|<0K *H 0*H 3ٞ(91ͥͪMJ{߰qMz8-3H]?GDCM-3.0.10/Testing/Source/Data/gdcmDataFileNames.cxx.in000066400000000000000000000023221412732066400224600ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* Hardcode the path to GDCM_DATA_ROOT */ static const char GDCM_DATA_ROOT[] = "@GDCM_DATA_ROOT@"; static const char GDCM_DATA_EXTRA_ROOT[] = "@GDCM_DATA_EXTRA_ROOT@"; static const char GDCM_PIXEL_SPACING_DATA_ROOT[] = "@GDCM_PIXEL_SPACING_DATA_ROOT@"; /* Hardcode the path to GDCM_TEMP_DIRECTORY */ static const char GDCM_TEMP_DIRECTORY[] = "@GDCM_TEMP_DIRECTORY@"; static const char * const gdcmDataFileNames[] = { @GDCM_DATA_FILENAMES@ 0 }; static const char * const gdcmBlackListReaderDataFileNames[] = { @GDCM_BLACK_LIST_READER_DATA_FILENAMES@ 0 }; //const char * const gdcmBlackListWriterDataImages[] = { // @GDCM_BLACK_LIST_WRITER_DATA_IMAGES@ //0 }; GDCM-3.0.10/Testing/Source/Data/gdcmMD5DataBrokenImages.cxx000066400000000000000000000125531412732066400230730ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * See TestWriter */ // This is the full md5 of the rewritten file. The file was manually check // and is (should be) exactly what should have been written in the first place // test was done using dcmtk 3.5.4 / dicom3tools static const char * const gdcmMD5DataBrokenImages[][2] = { // file has some garbage at the end, replace with a trailing end item. { "e8ed75f5e13cc20e96ee716bcc78351b" , "gdcm-JPEG-LossLess3a.dcm" }, // size match // files are little endian implicit meta data header: { "8cb29ba0173c66e7adb4c54c6b0a5896" , "GE_DLX-8-MONO2-PrivateSyntax.dcm" }, { "ed93b34819bf2acbacefb510476e8d4a" , "PICKER-16-MONO2-No_DicomV3_Preamble.dcm" }, // stupidest file ever, 0x6 was sent in place of 0x4 ... sigh { "c8cce480eac80770a3c6e456c7d8d66f" , "SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm" }, // size match // big endian / little endian nightmare from PMS { "df0e01aae299317db1719e4de72b8937" , "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm" }, // size match and CheckbigEndian match => ok ! { "df632a3b5ca38340faa612a23b907ac4" , "PHILIPS_Intera-16-MONO2-Uncompress.dcm" }, // size match and CheckbigEndian match => ok ! { "6bf002815fad665392acab24f09caa5e" , "MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm" }, // size match and CheckbigEndian match => ok ! // little endian implicit meta header + a couple of attribute sent with correct, but odd length: { "e1b2956f781685fc9e46e0da26b8a0fd" , "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm" }, // name says it all. dcmtk does not support this. dicom3tools confirmed that dataset is compatible { "66a75503221ef32b0236cf9f78e169ff" , "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm" }, // size mismatch // item length are supposed to be 0, not FFFF... { "3cc629fa470efb114a14ca3909117eb8" , "SIEMENS-MR-RGB-16Bits.dcm" }, // size match { "0fb0cb12f2b038bbfe1014bbf2935026" , "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm" }, // size match // this is a private syntax from ge with a little endian dataset and big endian pixel data // FMI is little endian implicit, it also contained a couple of odd length attributes. // using dcmtk it looks like file are identical { "2d23a8d55425c88bdd5e90f866a11607" , "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm" }, // size mismatch // couple of weird stuff going on... dcdump confirmed dataset is identical in both file { "34abc36682a6e6ba22d7295931b39d85" , "DMCPACS_ExplicitImplicit_BogusIOP.dcm" }, // size mismatch // weird stuff going on. dcdump confirmed dataset are identical. dcmdump can read output, and size match. { "82fda19e1f2046a289fe1307b70510af" , "gdcm-MR-PHILIPS-16-Multi-Seq.dcm" }, // yet another stupidest ever bug, 0xd was replaced with 0xa ... don't ask { "a047110a3935dc0fdda24d3b9e4769af" , "GE_GENESIS-16-MONO2-WrongLengthItem.dcm" }, // size match // empty 16bits after VR should be 0 not garbage... { "6cded0f160edfab809cddfce2d562671" , "JDDICOM_Sample2.dcm" }, // size match // simple issue, last fragment is odd, simply need to pad (easy, should be handle by most implementation) { "6234a50361f02cb9a739755d63cdd673" , "00191113.dcm" }, // size mismatch (obviously) { "28f9d4114b0699630a77d027910e5e41" , "MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm" }, // serious bug from gdcm 1.2.0, where VR=UN would be written on 16bits length sigh... no toolkit will ever be able to deal with that thing (and should not anyway) { "50752239f24669697897c4b6542bc161" , "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm" }, // unordered dataset { "f221e76c6f0758877aa3cf13632480f4" , "dicomdir_Pms_WithVisit_WithPrivate_WithStudyComponents" }, // size match // frankenstein-type dicom file: // 1. Implicit encoding is used any time it is not known (most of the time, private element) // 2. > (0x2001,0x1068) SQ ? VR= VL=<0xffffffff> is sent twice (don't ask), second entry cannot be stored... // dcdump kindda show file are somewhat compatible. { "69ca7a4300967cf2841da34d7904c6c4" , "TheralysGDCM120Bug.dcm" }, // size mismatch // GDCM 1.0 generated file. At that time, VL for a start/end item delimiter would be set to 0xFFF... instead of 0x0 // dcmtk / dicom3tools do not seems to care about the value stored for VL, so does GDCM (now). // As a side note the FMI was set to Little Endian Implicit ... { "ddf83cd708e58021a633588927d55ab8" , "BugGDCM2_UndefItemWrongVL.dcm" }, // size mismatch { "cb43a6ad60b8eacf718687b82126f625" , "NM_Kakadu44_SOTmarkerincons.dcm" }, // item size mismatch // Item length are bogus (explicit length) { "1225ea0a03b93393f70c73be35e2619d" , "PhilipsInteraSeqTermInvLen.dcm" }, // Two Items in a single Frame JPEG compressed DICOM image: { "cd00658f54dbd2d2a9d02d64c6f6497e" , "JPEGInvalidSecondFrag.dcm" }, // VR is set to 'OX' { "5793021ffb7b3506ae22ae9329d67d29" , "Bug_Siemens_PrivateIconNoItem.dcm" }, { nullptr ,nullptr } }; GDCM-3.0.10/Testing/Source/Data/gdcmMD5DataImages.cxx000066400000000000000000001136011412732066400217260ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // See tst2md5 in GDCM/Utilities/md5 // // Another way to do it is: // // dcmdrle ACUSON-24-YBR_FULL-RLE.dcm bla.dcm // gdcmraw -i bla.dcm -o bla.raw // md5sum bla.raw // So this md5 checksum should match the one in dcmtk...hopefully :) // static const char * const gdcmMD5DataImages[][2] = { /* gdcm 512 512 4 8 1 */ { "bfff320d1b058e91b4819aa4560c16f7" , "00191113.dcm" }, /* gdcm 256 256 1 16 1 */ { "d594a5e2fde12f32b6633ca859b4d4a6" , "012345.002.050.dcm" }, /* gdcm 512 512 1 16 1 */ { "c68cf1c4ae59903930e334498389ea88" , "05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm" }, /* gdcm 448 336 1 16 1 */ { "a9d455ca171294fe56d29bf714f4f845" , "05119865-mr-siemens-avanto-syngo.dcm" }, /* gdcm 192 192 1 16 1 */ { "9acdd9969f5d0584ddd67e994f00b7c7" , "05148044-mr-siemens-avanto-syngo.dcm" }, /* gdcm 512 512 1 16 1 */ { "c3541091a3794753065022f4defc4343" , "3E768EB7.dcm" }, /* gdcm 768 576 40 8 3 */ { "6a796be399aefebc1479e924f6051d69" , "ACUSON-24-YBR_FULL_422-Jpeg_Baseline_1.dcm" }, /* gdcm 384 288 1 8 3 */ //{ "2a922d5c606354612bfdbece1421d863" , "ACUSON-24-YBR_FULL-RLE-b.dcm" }, //{ "22b32f23beb118f7b64c13bf04bc2809" , "ACUSON-24-YBR_FULL-RLE-b.dcm" }, { "22b32f23beb118f7b64c13bf04bc2809" , "ACUSON-24-YBR_FULL-RLE-b.dcm" }, /* gdcm 768 576 1 8 3 */ //{ "f9bb8a37acabdf8b0cfa4fd1b471e6aa" , "ACUSON-24-YBR_FULL-RLE.dcm" }, //{ "435c66f7e113d11d226d500294aae865" , "ACUSON-24-YBR_FULL-RLE.dcm" }, { "435c66f7e113d11d226d500294aae865" , "ACUSON-24-YBR_FULL-RLE.dcm" }, /* gdcm 768 576 25 8 3 */ { "e36350b0711fd34eb86c386164554679" , "ACUSON-8-YBR_FULL-JPEG-TrailingInfo.dcm" }, /* gdcm 608 420 1 8 1 */ { "7d8858e3419392b7f39a99fdc8028064" , "ALOKA_SSD-8-MONO2-RLE-SQ.dcm" }, /* gdcm 440 440 1 16 1 */ //{ "8acaa88edcc2c29d3be3ee373fbaed5e" , "CR-MONO1-10-chest.dcm" }, { "1f772b4849727a9750931b60d920436f" , "CR-MONO1-10-chest.dcm" }, /* gdcm 512 512 1 16 1 */ { "8c8b9d99ad12fb4d231182d4fc14c042" , "CT_16b_signed-UsedBits13.dcm" }, /* gdcm 512 512 1 16 1 */ { "160c0b4432cfab8d36531b5a3693ff3e" , "CT-MONO2-12-lomb-an2.acr" }, /* gdcm 512 512 1 16 1 */ { "90cca03ada67c6a1fcb48cfcc2b52eeb" , "CT-MONO2-16-ankle.dcm" }, /* gdcm 512 512 1 16 1 */ { "a6cf43e05087b6c31644c1d360701ff2" , "CT-MONO2-16-brain.dcm" }, /* gdcm 512 400 1 16 1 */ { "78bb9ea4b746ff2aa5559be567f95030" , "CT-MONO2-16-chest.dcm" }, /* gdcm 512 512 1 16 1 */ { "dcb3aa1defd85d93d69d445e3e9b3074" , "CT-MONO2-16-ort.dcm" }, /* gdcm 512 512 1 8 1 */ { "86d3e09a5858aa3844cb3be1b822a069" , "CT-MONO2-8-abdo.dcm" }, /* gdcm 512 614 1 16 1 */ { "3695d167c298646b877efccaeff92682" , "CT_Phillips_JPEG2K_Decompr_Problem.dcm" }, /* gdcm 512 512 1 16 1 */ { "3372195a35448b76daee682d23502090" , "CT-SIEMENS-Icone-With-PaletteColor.dcm" }, /* gdcm 512 512 1 16 1 */ { "05bbdbcc81081791f6f9f8a1ffa648c8" , "D_CLUNIE_CT1_J2KI.dcm" }, /* gdcm 512 512 1 16 1 */ { "f3a3d0e739e5f4fbeddd1452b81f4d89" , "D_CLUNIE_CT1_J2KR.dcm" }, /* gdcm 512 512 1 16 1 */ { "f3a3d0e739e5f4fbeddd1452b81f4d89" , "D_CLUNIE_CT1_JPLL.dcm" }, /* gdcm 512 512 1 16 1 */ { "f3a3d0e739e5f4fbeddd1452b81f4d89" , "D_CLUNIE_CT1_RLE.dcm" }, /* gdcm 512 512 1 16 1 */ { "2e389ddbfc1b29d55c52c97e7f2c6f9c" , "D_CLUNIE_CT2_JPLL.dcm" }, /* gdcm 512 512 1 16 1 */ { "2e389ddbfc1b29d55c52c97e7f2c6f9c" , "D_CLUNIE_CT2_RLE.dcm" }, /* gdcm 3064 4664 1 16 1 */ { "d9b97ad9199d429960123dcc1e74bdbc" , "D_CLUNIE_MG1_JPLL.dcm" }, /* gdcm 3064 4664 1 16 1 */ { "02742062fcad004500d73d7c61b9b9e6" , "D_CLUNIE_MG1_JPLY.dcm" }, /* gdcm 3064 4664 1 16 1 */ { "d9b97ad9199d429960123dcc1e74bdbc" , "D_CLUNIE_MG1_RLE.dcm" }, /* gdcm 512 512 1 16 1 */ { "7b7424e6115931c371f3c94c2f5d32d9" , "D_CLUNIE_MR1_JPLL.dcm" }, /* gdcm 512 512 1 16 1 */ { "2824e914ecae250a755a8a0bb1a7d4b1" , "D_CLUNIE_MR1_JPLY.dcm" }, /* gdcm 512 512 1 16 1 */ { "7b7424e6115931c371f3c94c2f5d32d9" , "D_CLUNIE_MR1_RLE.dcm" }, /* gdcm 1024 1024 1 16 1 */ { "a70676f0e60a58f55a5ac517ff662e7e" , "D_CLUNIE_MR2_JPLL.dcm" }, /* gdcm 1024 1024 1 16 1 */ { "981510df3a57e98141c7d192b45bd93f" , "D_CLUNIE_MR2_JPLY.dcm" }, /* gdcm 1024 1024 1 16 1 */ { "a70676f0e60a58f55a5ac517ff662e7e" , "D_CLUNIE_MR2_RLE.dcm" }, /* gdcm 512 512 1 16 1 */ { "fb03254fad02d2330d404225c3ea9b4e" , "D_CLUNIE_MR3_JPLL.dcm" }, /* gdcm 512 512 1 16 1 */ { "d7009808a147f59a9bdf58d5c5924ef2" , "D_CLUNIE_MR3_JPLY.dcm" }, /* gdcm 512 512 1 16 1 */ { "fb03254fad02d2330d404225c3ea9b4e" , "D_CLUNIE_MR3_RLE.dcm" }, /* gdcm 512 512 1 16 1 */ { "14fa2ae9f63742af6944edd4a61145e8" , "D_CLUNIE_MR4_JPLL.dcm" }, /* gdcm 512 512 1 16 1 */ { "a33ad864b49ae7daa59cfaabdf751976" , "D_CLUNIE_MR4_JPLY.dcm" }, /* gdcm 512 512 1 16 1 */ { "14fa2ae9f63742af6944edd4a61145e8" , "D_CLUNIE_MR4_RLE.dcm" }, /* gdcm 256 1024 1 16 1 */ { "6b5c1eff0ef65e36b0565f96507e96fd" , "D_CLUNIE_NM1_JPLL.dcm" }, /* gdcm 256 1024 1 16 1 */ { "812050a7fc53b5735f7740b60969cb6b" , "D_CLUNIE_NM1_JPLY.dcm" }, /* gdcm 256 1024 1 16 1 */ { "6b5c1eff0ef65e36b0565f96507e96fd" , "D_CLUNIE_NM1_RLE.dcm" }, /* gdcm 1841 1955 1 16 1 */ //{ "01518af70491372814fb056d536ffb7e" , "D_CLUNIE_RG1_JPLL.dcm" }, { "ae141f6fb91f63769a6adc572a942fb9" , "D_CLUNIE_RG1_JPLL.dcm" }, /* gdcm 1841 1955 1 16 1 */ //{ "01518af70491372814fb056d536ffb7e" , "D_CLUNIE_RG1_RLE.dcm" }, { "ae141f6fb91f63769a6adc572a942fb9" , "D_CLUNIE_RG1_RLE.dcm" }, /* gdcm 1760 2140 1 16 1 */ { "06900ee4323a91b7f5ffab8655e3c845" , "D_CLUNIE_RG2_JPLL.dcm" }, /* gdcm 1760 2140 1 16 1 */ { "27fa50d4cf6b31baa669e9746ce10f63" , "D_CLUNIE_RG2_JPLY.dcm" }, /* gdcm 1760 2140 1 16 1 */ { "06900ee4323a91b7f5ffab8655e3c845" , "D_CLUNIE_RG2_RLE.dcm" }, /* gdcm 1760 1760 1 16 1 */ //{ "6588b7b8e6e53b2276d919a053316153" , "D_CLUNIE_RG3_JPLL.dcm" }, { "e7c857ef7e6a2c81498297a072a0332e" , "D_CLUNIE_RG3_JPLL.dcm" }, /* gdcm 1760 1760 1 16 1 */ //{ "cb381c53172242404346b237bf741eb4" , "D_CLUNIE_RG3_JPLY.dcm" }, { "cc2968949ffbb6548288ffde7e5202e4" , "D_CLUNIE_RG3_JPLY.dcm" }, /* gdcm 1760 1760 1 16 1 */ //{ "6588b7b8e6e53b2276d919a053316153" , "D_CLUNIE_RG3_RLE.dcm" }, { "e7c857ef7e6a2c81498297a072a0332e" , "D_CLUNIE_RG3_RLE.dcm" }, /* gdcm 2048 2487 1 16 1 */ { "bd0cccbfd8db465c0af306ba0f482d72" , "D_CLUNIE_SC1_JPLL.dcm" }, /* gdcm 2048 2487 1 16 1 */ { "994a5abb70d3f5968672ce4970a9d4da" , "D_CLUNIE_SC1_JPLY.dcm" }, /* gdcm 2048 2487 1 16 1 */ { "bd0cccbfd8db465c0af306ba0f482d72" , "D_CLUNIE_SC1_RLE.dcm" }, /* gdcm 640 480 1 8 3 */ { "eb52dce9eed5ad677364baadf6144ac4" , "D_CLUNIE_US1_RLE.dcm" }, /* gdcm 756 486 1 8 3 */ { "b07e34ec35ba1be62ee7d4a404cf0b90" , "D_CLUNIE_VL1_RLE.dcm" }, /* gdcm 756 486 1 8 3 */ { "d215c88125359d34474a741d793c2215" , "D_CLUNIE_VL2_RLE.dcm" }, /* gdcm 756 486 1 8 3 */ { "65cd359ea4c6c13ca89b906215a4b762" , "D_CLUNIE_VL3_RLE.dcm" }, /* gdcm 2226 1868 1 8 3 */ { "e2fdf24d2c03dd0991b4f4e9d6e84ed6" , "D_CLUNIE_VL4_RLE.dcm" }, /* gdcm 2670 3340 1 8 3 */ { "0ed86ef35d1fb443e1b63c28afe84bd0" , "D_CLUNIE_VL5_RLE.dcm" }, /* gdcm 756 486 1 8 3 */ { "b825c0ed35c7c896fb707c14b534c233" , "D_CLUNIE_VL6_RLE.dcm" }, /* gdcm 1024 1024 1 16 1 */ { "6111657e6b01ec7b243d63f5dec6ec48" , "D_CLUNIE_XA1_JPLL.dcm" }, /* gdcm 1024 1024 1 16 1 */ { "51af0d83fe795f9c9544c20d0bbac11c" , "D_CLUNIE_XA1_JPLY.dcm" }, /* gdcm 1024 1024 1 16 1 */ { "6111657e6b01ec7b243d63f5dec6ec48" , "D_CLUNIE_XA1_RLE.dcm" }, /* gdcm 117 181 1 8 3 */ { "b4f442047a209a98af015c89b4a3c4ed" , "DermaColorLossLess.dcm" }, /* gdcm 1024 1024 1 16 1 */ { "0b4dff77726ccf037fa83c42cc186a98" , "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm" }, /* gdcm 512 512 1 16 1 */ { "6b92115ec7a394c4aaad74e88d7dbc98" , "FLAIR-wrong-group-length.dcm" }, /* gdcm 1670 2010 1 16 1 */ //{ "9ca80d44bfb1af2f96495fac4b57fa29" , "FUJI-10-MONO1-ACR_NEMA_2.dcm" }, { "da2415a1e58b4ca2e588d0de18274f60" , "FUJI-10-MONO1-ACR_NEMA_2.dcm" }, /* gdcm 512 301 1 8 1 */ { "59d9851ca0f214d57fdfd6a8c13bc91c" , "gdcm-ACR-LibIDO.acr" }, /* gdcm 750 750 1 8 1 */ { "73f20916abaea83abebe9135c365d81a" , "gdcm-CR-DCMTK-16-NonSamplePerPix.dcm" }, /* gdcm 512 512 1 16 1 */ { "f2c026beea9da0a78404f1299c4628bb" , "gdcm-JPEG-Extended-Allready_present.dcm" }, /* gdcm 512 512 1 16 1 */ { "f2c026beea9da0a78404f1299c4628bb" , "gdcm-JPEG-Extended.dcm" }, /* gdcm 512 512 1 16 1 */ { "ad67e448e8923c34f1e019c3395e616c" , "gdcm-JPEG-LossLess3a.dcm" }, /* gdcm 1876 2076 1 16 1 */ { "c15c1e18a0c41970fbded48b20e834a1" , "gdcm-JPEG-LossLessThoravision.dcm" }, /* gdcm 128 128 1 16 1 */ { "ad85be428c08ab4166347ef04bda9637" , "gdcm-MR-PHILIPS-16-Multi-Seq.dcm" }, /* gdcm 160 64 1 16 1 */ { "2f7f9ef80b49111c5a7cfdb60a97f523" , "gdcm-MR-PHILIPS-16-NonSquarePixels.dcm" }, /* gdcm 512 512 1 16 1 */ { "864e2c5d6acf5a371fe9eaa7ee0dcf5f" , "gdcm-MR-SIEMENS-16-2.acr" }, /* gdcm 640 480 1 16 1 */ { "f85ff02a143c426edc4b2f6b9a175305" , "gdcm-US-ALOKA-16.dcm" }, /* gdcm 512 512 1 16 1 */ { "80527e9c17a4a3d12d408e9a354f37f9" , "GE_CT_With_Private_compressed-icon.dcm" }, /* gdcm 512 512 67 8 1 */ { "b8bcbccd17b76a0f8e3d4c342f855f9f" , "GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm" }, /* gdcm 512 512 56 8 1 */ { "71e4ea61df4f7ada2955799c91f93e74" , "GE_DLX-8-MONO2-Multiframe.dcm" }, /* gdcm 512 512 54 8 1 */ { "51c998d3474c069b5703e98313258a1e" , "GE_DLX-8-MONO2-PrivateSyntax.dcm" }, /* gdcm 256 256 1 16 1 */ { "8ac7f7891fb4506e2cd3ae2f0f7e9f46" , "GE_GENESIS-16-MONO2-Uncompressed-UnusualVR.dcm" }, /* gdcm 256 256 1 16 1 */ { "1497fb9d7467b1eb36d5618e254aac76" , "GE_GENESIS-16-MONO2-WrongLengthItem.dcm" }, /* gdcm 640 480 1 8 3 */ { "13fd8c7e533a3d7199bb78de45710f5c" , "GE_LOGIQBook-8-RGB-HugePreview.dcm" }, /* gdcm 512 512 1 16 1 */ { "f3a3d0e739e5f4fbeddd1452b81f4d89" , "GE_RHAPSODE-16-MONO2-JPEG-Fragments.dcm" }, /* gdcm 1792 2392 1 16 1 */ //{ "821acfdb5d5ad9dc13275d3ad3827d43" , "KODAK-12-MONO1-Odd_Terminated_Sequence.dcm" }, { "c1ed06d39821a5fd65abc397982e2ac1" , "KODAK-12-MONO1-Odd_Terminated_Sequence.dcm" }, /* gdcm 800 535 1 16 1 */ { "70166425c4dca767e22d3f25f737922b" , "LEADTOOLS_FLOWERS-16-MONO2-JpegLossless.dcm" }, /* gdcm 800 535 1 16 1 */ { "70166425c4dca767e22d3f25f737922b" , "LEADTOOLS_FLOWERS-16-MONO2-RLE.dcm" }, /* gdcm 800 535 1 16 1 */ { "70166425c4dca767e22d3f25f737922b" , "LEADTOOLS_FLOWERS-16-MONO2-Uncompressed.dcm" }, /* gdcm 800 535 1 8 3 */ { "279e2b0363394a553ff8571cf3540c6c" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossless.dcm" }, /* gdcm 800 535 1 8 3 */ { "38c2784aa485733fef45b6517479a4f5" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm" }, /* gdcm 800 535 1 8 3 */ { "279e2b0363394a553ff8571cf3540c6c" , "LEADTOOLS_FLOWERS-24-RGB-Uncompressed.dcm" }, /* gdcm 800 535 1 8 1 */ { "fa08fec923f34e009ec89f77232e52ad" , "LEADTOOLS_FLOWERS-8-MONO2-JpegLossy.dcm" }, /* gdcm 800 535 1 8 1 */ { "3cd8bd92db17bff54e376885dfefdd8d" , "LEADTOOLS_FLOWERS-8-MONO2-RLE.dcm" }, /* gdcm 800 535 1 8 1 */ { "3cd8bd92db17bff54e376885dfefdd8d" , "LEADTOOLS_FLOWERS-8-MONO2-Uncompressed.dcm" }, /* gdcm 800 535 1 8 3 */ //{ "d613050ca0f9c924fb5282d140281fcc" , "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm" }, { "16e999d6afc5574bcb075f296c3bcbbc" , "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm" }, /* gdcm 800 535 1 8 3 */ //{ "d613050ca0f9c924fb5282d140281fcc" , "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm" }, { "16e999d6afc5574bcb075f296c3bcbbc" , "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm" }, /* duh ! This should be the exact same md5...if only the testing was a little * smarter */ { "d613050ca0f9c924fb5282d140281fcc" , "LEADTOOLS_FLOWERS-8-PAL-RAW.dcm" }, /* gdcm 50 50 262 16 1 */ { "ce1cc8ebb1efb86213d5912a1cfde843" , "LIBIDO-16-ACR_NEMA-Volume.dcm" }, /* gdcm 400 100 1 8 3 */ { "81a40454eec2b18f4331cfd1ba4e501e" , "LIBIDO-24-ACR_NEMA-Rectangle.dcm" }, /* gdcm 128 128 1 8 1 */ { "fc5db4e2e7fca8445342b83799ff16d8" , "LIBIDO-8-ACR_NEMA-Lena_128_128.acr" }, /* gdcm 512 512 1 16 1 */ { "b1476cacdd32216b3295d2a494af2945" , "MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm" }, /* gdcm 256 192 1 16 1 */ { "d9f47017de79e8755e4bc5d3c9146ebd" , "MR-Brucker-CineTagging-NonSquarePixels.dcm" }, /* gdcm 512 512 1 16 1 */ { "8fe67e8e1f849c1b61f59e70d2d53cf7" , "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm" }, /* gdcm 256 256 1 16 1 */ { "f54c7ea520ab3ec32b6303581ecd262f" , "MR-MONO2-12-an2.acr" }, /* gdcm 256 256 1 16 1 */ //{ "48345bccbd67f57b4c13060b6a9a0d35" , "MR-MONO2-12-angio-an1.acr" }, //{ "19cd553b53c8c35b8f2c20f27ed31d2d" , "MR-MONO2-12-angio-an1.acr" }, { "ae5c00b60a58849b19aaabfc6521eeed" , "MR-MONO2-12-angio-an1.acr" }, /* gdcm 1024 1024 1 16 1 */ { "a70676f0e60a58f55a5ac517ff662e7e" , "MR-MONO2-12-shoulder.dcm" }, /* gdcm 256 256 1 16 1 */ { "83be31fb5e5cee60dedaf485bf592ac3" , "MR-MONO2-16-head.dcm" }, /* gdcm 256 256 16 8 1 */ { "01db0d71100c47013e588082d5f39bab" , "MR-MONO2-8-16x-heart.dcm" }, /* gdcm 256 256 1 16 1 */ { "b606add66c681bbe674f972799c6d336" , "MR_Philips-Intera_BreaksNOSHADOW.dcm" }, /* gdcm 1024 1024 1 16 1 */ { "0b4dff77726ccf037fa83c42cc186a98" , "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm" }, /* gdcm 512 512 1 16 1 */ { "f69bca6228b0ca07d97ee11c0ab3b989" , "MR_Philips_Intera_PrivateSequenceImplicitVR.dcm" }, /* gdcm 1024 1024 1 16 1 */ { "0b4dff77726ccf037fa83c42cc186a98" , "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm" }, /* ?? */ { "7775ffdd374994b7dd029f45f198844f" , "MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm" }, /* gdcm 484 484 1 8 1 */ { "8b636107a6d8e6a6b3d1d7eed966d7a0" , "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm" }, /* gdcm 484 484 1 16 1 */ { "3027eda10630e5c845f456264dc65210" , "MR-SIEMENS-DICOM-WithOverlays.dcm" }, /* gdcm 128 128 1 16 1 */ { "6a925f871c58553f84ad24195e155c52" , "MR_SIEMENS_forceLoad29-1010_29-1020.dcm" }, /* gdcm 64 64 13 16 1 */ { "c83ef2159abef677229d3afd26f9e6a0" , "NM-MONO2-16-13x-heart.dcm" }, /* gdcm 512 512 1 8 1 */ { "a155c3004bb902ed3f2d78f482923b32" , "OT-MONO2-8-a7.dcm" }, /* gdcm 640 480 1 8 3 */ //{ "47715f0a5d5089268bbef6f83251a8ad" , "OT-PAL-8-face.dcm" }, { "d7c30d57af821b02c67103250a744235" , "OT-PAL-8-face.dcm" }, /* gdcm 512 512 1 16 1 */ //{ "4b0021efe5a675f24c82e1ff28a1e2eb" , "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm" }, { "d93d2f78d845c7a132489aab92eadd32" , "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm" }, /* gdcm 256 256 1 16 1 */ { "b78366162d9d43b2852d2637c5365c89" , "PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm" }, /* gdcm 256 256 1 16 1 */ { "4842ccbaac5b563ce915d2e21eb4c06e" , "PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm" }, /* gdcm 512 512 76 8 1 */ { "1f8951a6f8b599ad4ebc97efd7aab6be" , "PHILIPS_Integris_H-8-MONO2-Multiframe.dcm" }, /* gdcm 1024 1024 31 16 1 */ { "3d005cd3270c6d2562c2a8d9069c9295" , "PHILIPS_Integris_V-10-MONO2-Multiframe.dcm" }, /* gdcm 1024 1024 1 16 1 */ { "0b4dff77726ccf037fa83c42cc186a98" , "PHILIPS_Intera-16-MONO2-Uncompress.dcm" }, /* gdcm 512 512 1 16 1 */ { "6c9e477330d70d4a1360888121c7c3d3" , "PICKER-16-MONO2-Nested_icon.dcm" }, /* gdcm 512 512 1 16 1 */ { "5ea911b29f472f371d21f2da2fd6b016" , "PICKER-16-MONO2-No_DicomV3_Preamble.dcm" }, /* gdcm 512 512 1 16 1 */ { "498f80fd27882351b9a09e6ceef470bc" , "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm" }, /* gdcm 136 92 1 16 1 */ { "dbbf39ac11a39372b1e961f40ac6f62a" , "RadBWLossLess.dcm" }, /* gdcm 600 430 1 16 3 */ //{ "964ea27345a7004325896d34b257f289" , "rle16sti.dcm" }, { "f799773abbe36a1a8a3a881e27f8084d" , "rle16sti.dcm" }, /* gdcm 512 512 1 16 1 */ { "80527e9c17a4a3d12d408e9a354f37f9" , "ser002img00026.dcm" }, /* gdcm 512 512 1 16 1 */ { "7b55fd124331adde6276416678543048" , "SIEMENS-12-Jpeg_Process_2_4-Lossy-a.dcm" }, /* gdcm 256 256 1 16 1 */ { "ea24c09f475a4e9643e27f6d470edc67" , "SIEMENS_GBS_III-16-ACR_NEMA_1.acr" }, /* gdcm 512 512 1 16 1 */ { "864e2c5d6acf5a371fe9eaa7ee0dcf5f" , "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm" }, /* gdcm 128 128 1 16 1 */ { "a13466d96b2f068c4844240797069f13" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm" }, /* gdcm 128 128 1 16 1 */ { "73f5986082729c2661cdc8de81fd26d0" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm" }, /* gdcm 128 128 1 16 1 */ { "f932a194df62ec99aef676c563893496" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm" }, /* gdcm 128 128 1 16 1 */ { "b6e4780d8aa8c1d3642377a60a5302dd" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm" }, /* gdcm 512 512 1 16 1 */ { "4b426d4cd570bd4c998f3d19cfddfbb8" , "SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm" }, /* gdcm 192 256 1 16 3 */ { "faff9970b905458c0844400b5b869e25" , "SIEMENS-MR-RGB-16Bits.dcm" }, /* gdcm 512 512 1 16 1 */ { "7ccf7c7c4b2a5fa9d337ea8b01f75c42" , "SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs.acr" }, /* gdcm 192 192 1 16 1 */ { "a3009bc70444148c5ea2441a099f9dc6" , "SIEMENS_Sonata-12-MONO2-SQ.dcm" }, /* gdcm 256 208 1 16 1 */ { "017237320ccded3a367f07b44851788e" , "SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm" }, /* gdcm 512 512 1 8 1 */ { "f845c8f283d39a0204c325654493ba53" , "test.acr" }, /* gdcm 256 256 1 16 1 */ { "62c98e89a37c9a527d95d5ac3e2548b0" , "THERALYS-12-MONO2-Uncompressed-E_Film_Template.dcm" }, /* gdcm 256 256 1 16 1 */ { "0121cd64c3b9957f76dd338d27454bc6" , "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm" }, /* gdcm 512 512 1 16 1 */ { "09661bd8516aeb5a6f09239f9ca1b092" , "TOSHIBA_MRT150-16-MONO2-ACR_NEMA_2.dcm" }, /* gdcm 636 434 1 8 3 */ { "23ec8ed09e1ecc353c2e6436a1de6cb2" , "US-GE-4AICL142.dcm" }, /* gdcm 640 480 1 8 1 */ { "ba092234639594ee9091b46997532cce" , "US-IRAD-NoPreambleStartWith0003.dcm" }, /* gdcm 640 480 1 8 1 */ { "1bde104ba256fb73528c5d9a02e363d7" , "US-IRAD-NoPreambleStartWith0005.dcm" }, /* gdcm 128 120 8 8 1 */ { "bf63affde325b3fa81cd5a700f30bd5b" , "US-MONO2-8-8x-execho.dcm" }, /* gdcm 600 430 10 8 3 */ //{ "c70309b66045140b8e08c11aa319c0ab" , "US-PAL-8-10x-echo.dcm" }, { "1785f4d8af4717c17bfb78ba74c18ea5" , "US-PAL-8-10x-echo.dcm" }, /* gdcm 640 480 1 8 3 */ //{ "fe2d477d699e327be2d3d65eb76203e9" , "US-RGB-8-epicard.dcm" }, { "eb3433568c6b0cee90688ccf228ffc02" , "US-RGB-8-epicard.dcm" }, /* gdcm 256 120 1 8 3 */ { "4b350b9353a93c747917c7c3bf9b8f44" , "US-RGB-8-esopecho.dcm" }, /* gdcm 512 512 12 8 1 */ { "136eaf8f7d654bbb08741c201a945561" , "XA-MONO2-8-12x-catheter.dcm" }, // Those where added manually: // If you are lucky and the image is raw (MONOCHROME2) you simply need to // do (assuming you are under UNIX) // $ ./bin/gdcmraw -i 42166745.dcm -o bla.raw // $ md5sum bla.raw // For JPEG and RLE file, you need to check result against dcmtk (dcmdjpeg, // dcmdrle will help you). // Image1 & Image2 are crap, some kind of decompression went wrong // and PixelData is raw so not much you can do... { "1b0768a3518a6b6ed425c3c1d7a7ea3b" , "Image1.dcm" }, { "a41c7f4e75cf637ae8912f5c3cd2c69d" , "Image2.dcm" }, { "22c9be23446a7be61a90d3578f3c9739" , "deflate_image.dcm" }, { "d5681b156af55899835293286c57d887" , "brain.dcm" }, { "d4d365f0500f2ccff932317833d8804b" , "abdominal.dcm" }, { "138d9bd642c6f1cdc427ef6f99132677" , "ankle.dcm" }, { "ff8d450e47e8989478a1b6f19d0988cc" , "spine.dcm" }, { "c78c1721a5ac585a12cf9a52abc25d4c" , "42166745.dcm" }, { "d48ae6ccc815fd171169591a1048c5ed" , "JDDICOM_Sample4.dcm" }, { "63c45c2e73403af781d07ae02247654f" , "I20051107115955.dcm" }, { "938ac04374eadbe6ac4d7df80e5aa178" , "JDDICOM_Sample1.dcm" }, // This one can not be decompressed properly with dcmdjpeg. Until // they fix dcmdjpeg I'll assume decompression went right { "33aa469ec024188d692262d03e7108a0" , "JDDICOM_Sample2.dcm" }, // Same problem { "308b1b6fbc01df4dc3fb168830777cb1" , "JDDICOM_Sample3.dcm" }, // Same thing { "b8b5030261f92574227fe91902738558" , "JDDICOM_Sample5.dcm" }, // This one was computed from dcmtk, gdcm 1.x fails to read it... //{ "49ca8ad45fa7f24b0406a5a03ba8aff6" , "rle16loo.dcm" }, { "04b42f011bdcf56e8a22607cb715447c" , "rle16loo.dcm" }, // Name is poorly chosen since it's actually a Dicom Objects bug // Cannot only be read by gdcm 1.2.x { "f1436c1800ccbba8da82acb7f2dff29d" , "GE_JPEG-Broken.dcm" }, // For some reason the numbers gets funny { "73dd2a43ab7c2810714a8ea1079f3c38" , "10200901_8b_Palette_RLE_blinker.dcm" }, { "609ede096636ae804dbb0fb4d78be2c2" , "10200900_8b_Palette_RLE_blinker.dcm" }, { "ed6078d83f467f9eda5d8cd06f87080f" , "10200905_8b_Palette_RLE_blinker.dcm" }, // This is the same image as rle16loo ... { "49ca8ad45fa7f24b0406a5a03ba8aff6" , "rle16loop_16b_Palette_RLE.dcm" }, // dummy image, this is the same as US-IRAD-NoPreambleStartWith0005.dcm { "1bde104ba256fb73528c5d9a02e363d7" , "US.irad.27702.1.dcm"}, // ACR NEMA with a PhotometricInterpretation.. { "1e3acacba2ae92b52011804ebddbf5df" , "acc-max.dcm" }, { "d5037d66855c7815f55185b808e48750" , "Originale_015.dcm" }, { "bbca0e3e26acdd1ab4f6c4871810ac50" , "PETAt001_PT001.dcm" }, { "5a33e3a2cd414d734984c7a6a5a32a41" , "i0116.dcm" }, { "5a0ebe04ffe50d4373624e444093b855" , "eclipse_dose.dcm" }, { "c4e4589b884cfee49db81746cd18a41c" , "MRMN1786V1L.dcm" }, { "bc8f9791b75916e85c91e458cd1364a3" , "MRMN1786V1T.dcm" }, { "6cee5011d0dcce93d259d272eb94336f" , "MRMN1786V2L.dcm" }, { "793d177bd10188e66483ddc04cbca9e7" , "gdcm-CT-GE-16-GantryTilt.dcm" }, { "7db6d7da455d94ed1a3afda437c3f09e" , "MRMN1786V2T.dcm" }, // JPEG lossy: { "bea6e06fe30abd455288e35aaf47477d" , "angiograms.dcm" }, { "350aea8820dbbdbb15eabc88f3dd3b16" , "image09-bis.dcm" }, // The same as US-IRAD-NoPreambleStartWith0003.dcm { "ba092234639594ee9091b46997532cce" , "US.irad.28317.1.dcm" }, { "21a11f961726c81684be3241eb961819" , "PETAt001_PT204.dcm" }, { "23b5d0a918fb882c08c458c1507c39f7" , "SiemensIcon.dcm" }, { "0121cd64c3b9957f76dd338d27454bc6" , "RMI_Mattes_1_150_001_7_150_cEval0_038.dcm" }, { "350aea8820dbbdbb15eabc88f3dd3b16" , "image09.dcm" }, { "1bde104ba256fb73528c5d9a02e363d7" , "image12.dcm" }, { "417ca9bf1db40dd8656cfb6de0aef181" , "JPEGLosslessLongSQ.dcm" }, { "d5037d66855c7815f55185b808e48750" , "readWrite.dcm" }, // Visible Human written in DICOM with ITK-GDCM (1.2) { "e114252b9acf985cf53b06c39118a290" , "vhm.1001.dcm" }, { "0b4dff77726ccf037fa83c42cc186a98" , "MR_Philips_Intera_Kosher.dcm" }, { "f9d9898ad844a73c0656539388fec85c" , "0001.dcm" }, { "c4031c607b7312952bb560e55cbbb072" , "exp000.dcm" }, { "2bb620b2c516b66faeef7397d30b83f1" , "exp001.dcm" }, { "0dfbe8aa4c20b52e1b8bf3cb6cbdf193" , "RMI_Mattes_unevenLengthTags.dcm" }, // The famous Siemens 0029-1010/1020 { "6a925f871c58553f84ad24195e155c52" , "MR_forceLoad29-1010_29-1020.dcm" }, { "255769e6c9d8a161fce520c958c94de7" , "MR_Siemens_ShadowGroupsImplicitVR.dcm" }, { "5c25c435ecd8eeac124ab427668186de" , "01f7_7fdf.dcm" }, { "0dfbe8aa4c20b52e1b8bf3cb6cbdf193" , "RMI_Mattes_1_1_001_7_1_cEval0_000.dcm" }, { "620012cfec4ae2e6dd0137b2e16947d7" , "ElemZeroNotGroupLength.dcm" }, { "57994245238730f4b4c5eaed21c4144b" , "File000138.dcm" }, { "826b6bc1e36efda1b727b08248a71dd2" , "File000139.dcm" }, { "6b26a5561678b26aa2f21a68ea334819" , "SYNGORTImage.dcm" }, { "a198893279520631657781d47c4097b2" , "Implicit-0001.dcm" }, { "99540b33d088646b8e424a57afdccbe6" , "CT_PET001_CT001.dcm" }, { "343e27f0867b55af74b21a5ba55bd9cc" , "rattag.dcm" }, { "0038402afc09d44d3c75ed207171976b" , "i0002.dcm" }, { "0ad4eca25cc0f783bd60c07b2d73f8b0" , "fudd_post.dcm" }, { "b85ca0e38d91ba0ee3a97f9c709415ac" , "brain_001.dcm" }, { "f1436c1800ccbba8da82acb7f2dff29d" , "SignedShortLosslessBug.dcm" }, { "eb87ca4a01e55dc7a7f1c92f0aa31017" , "ATTMA002_DS.dcm" }, { "f17cf873a3c07f3d91dc88f34664bf0d" , "libido1.0-vol.acr" }, { "d2fab61e0fff8869e448d69951f1084d" , "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm" }, { "e0221ddcc9febdc3c266bb8cd0fcf14f" , "undefined_length_un_vr.dcm" }, { "a136e501bcd1b8ee0835981d2bc8dd87" , "fffc0000UN.dcm" }, { "33aa469ec024188d692262d03e7108a0" , "JDDICOM_Sample2-dcmdjpeg.dcm" }, // mismatch DICOM / JPEG { "d2fab61e0fff8869e448d69951f1084d" , "SIEMENS_MAGNETOM-12-MONO2-VRUN.dcm" }, { "fc5db4e2e7fca8445342b83799ff16d8" , "simpleImageWithIcon.dcm" }, // Following need to be proof checked: { "0b4dff77726ccf037fa83c42cc186a98" , "imp.dcm" }, { "eb5fc6c9e86a69c27b7208d72370a92d" , "Renal_Clearance.dcm" }, { "1b130fa646f8d6b3c14b9443b35c80b4" , "IM0046A0.dcm" }, { "8c00e7f797d8bb4a629ae1e4b08084b9" , "rvg_analysis.dcm" }, { "0d7c2f8714ed3c7dec8194c6e4b359c3" , "BRTUM001.dcm" }, { "e5dbfc8673ea25dd73c95f4df3353b10" , "3DDCM011.dcm" }, { "12150f9067ea72bc56c75d83c42c8108" , "MIRA.dcm" }, { "ae9a191c716dfda2651a147728910a89" , "NM.dcm" }, { "d4444bcca0ee13919f867e486a8f3553" , "QCpatternC-v1.dcm" }, { "ad85be428c08ab4166347ef04bda9637" , "gdcm-MR-PHILIPS-16-Multi-Seq-Correct.dcm" }, { "9c390fc010105325427e3ff29a9b186c" , "SIEMENS_ORIGINAL.dcm" }, { "0b4dff77726ccf037fa83c42cc186a98" , "venticles32004-11-09-08-55-57-6750000000.dcm" }, { "bfff320d1b058e91b4819aa4560c16f7" , "test.dcm" }, { "8c9666cef26a0cc76491a7a8a5239b85" , "Renal_Flow.dcm" }, { "f3a3d0e739e5f4fbeddd1452b81f4d89" , "dclunie.dcm" }, { "78dae0e2d9b7a124fe63300b6356ded4" , "Toshiba7005.dcm" }, { "8240955d1e4b72989f8f49549f1617b2" , "PhilipsWith15Overlays.dcm" }, { "3cd8bd92db17bff54e376885dfefdd8d" , "toto.dcm" }, { "14ad8ae28cc5e5e5dc4c4d010c291a7f" , "test20.dcm" }, { "e7408198028983cd6643a00fd7668c00" , "testacr-jpll.dcm" }, { "6633fb8bce0a648763e7ed2b7de1db5c" , "1_172.dcm" }, { "29cfe7038fae548abd4af4551b2a37cb" , "example.dcm" }, { "6b18e445fbc917e7d6f55b616f17d3e1" , "WrongVRFor00271033.dcm" }, { "0b4dff77726ccf037fa83c42cc186a98" , "ExplicitVRforPublicElementsImplicitVRforShadowElementsCorrected.dcm" }, { "9570a06da59988ff3a7271cdde14abf5" , "3DT1_5138_0077.dcm" }, { "20c5f63d65732703e3fffeb8d67c62ed" , "FluroWithDisplayShutter.dcm" }, { "92b62f22fc44b8563c19f5536d9e499f" , "fudd_ant.dcm" }, { "b92a22ef55d6a1fbd24a6a24a7a84a7f" , "yazhi.dcm" }, { "2b69286289543afc3be7df0400abb8fc" , "IM_0001.dcm" }, //{ "67d86e26740882586b6bf3fe7e09c831" , "PMMA-Treppe.dcm" }, { "287e002ebf84424fe66558b642c51bce" , "PMMA-Treppe.dcm" }, { "82a8d3398c98d23e1b34f5364f967287" , "PERFORM_T1_Symphony_VA25.dcm" }, //{ "00b4b3282855c96744355892caf9d310" , "Al-Treppe.dcm" }, { "2c0ccfeff0a6d4afd7929a672dec0cc0" , "Al-Treppe.dcm" }, { "f891eae2cdfecd578b2204ebbb93f606" , "ImplicitDeclaredAsExplicit.dcm" }, { "7ceb7886f9fbcb7ae979fdb6f1305414" , "CR-Preamble-NoMeta.dcm" }, { "d2fab61e0fff8869e448d69951f1084d" , "db318_MR_STN_stimulator_T2_TSE_TRA__20071005161618048_4.dcm" }, { "2b4d7fb6b039b43145f2766b2339c460" , "0019004_Baseline_IMG1.dcm" }, { "f02e48f4b7df2ff4855733febc92e4e6" , "SIEMENS_GBS_III-16-ACR_NEMA_1.acr.ovly.6002.dcm" }, { "6a34b606135c4cd1c31511164e2cb235" , "SIEMENS_GBS_III-16-ACR_NEMA_1.acr.ovly.6000.dcm" }, { "65f961aca90fb61952d723feec6dec89" , "SIEMENS_GBS_III-16-ACR_NEMA_1.acr.ovly.6006.dcm" }, { "fc137690ae436bb44a695fb2f1e49d85" , "SIEMENS_GBS_III-16-ACR_NEMA_1.acr.ovly.6004.dcm" }, // No tested: { "864e2c5d6acf5a371fe9eaa7ee0dcf5f" , "acr_image_with_non_printable_in_0051_1010.acr" }, { "7efed1c332c62ea34d5edad901081c36" , "mr_r_opptak000_20000925_t2.nema" }, { "d6995bd1d76eb36913c985c8397ff02d" , "mr_r_opptak000_20000925_t1.nema" }, { "dc549f804f1f59bfee245ddf100ee26b" , "SIEMENS-IncompletePixelData.dcm" }, { "51b7e83cdc569b8f355662d80bd7036d" , "20061119171007906.dcm" }, { "01db0d71100c47013e588082d5f39bab" , "MR0001.dcm" }, { "d9df75ff0394bb9a3753b625933d94fc" , "ModalityLUT.dcm" }, { "acd3f756192a9f0484c971db2869d70b" , "PublicElementsImplicitInExplicitDataSet.dcm" }, { "820575fcc05338f3e95296107d9ddf7a" , "MR3.dcm" }, { "3c6984afa2af4257565d8f622f7f5e5b" , "SIEMENS-JPEG-CorruptFragClean.dcm" }, { "cc2968949ffbb6548288ffde7e5202e4" , "D_CLUNIE_RG3_JPLY_dcmtk.dcm" }, { "83656f4989a2d4be8f9ad56d83a907f5" , "5decf5b5-6695-4557-867e-a1f97321cd80.dcm" }, { "92655f77a55eb9c316223b9e73d55800" , "PMS-IncompletePixelData.dcm" }, { "6a23c9f150a360381c8fbceb2277efc5" , "TOSHIBA-CurveData2.dcm" }, { "6ad75566935554fcc60ca35a003fba6d" , "IM_00003.dcm" }, { "ab7cab6e7b5f9043f8fa7c0ae3f1b282" , "19872890.dcm" }, { "48eb24e37d41faca8b629b3807c20d92" , "rm6_DICM.dcm" }, { "201c9761ed911ad12508248252f4ff16" , "T2*_1484_0009.dcm" }, { "90017033c3916259cad63615385a1d02" , "BogugsItemAndSequenceLength.dcm" }, { "b09dc714f6d56d29005996b3204eec25" , "TOSHIBA-CurveData1.dcm" }, { "5ed3d1de2a086ac7efd31a6f1463f129" , "SCIsMR.dcm" }, { "9bbb1d908401299e73e636ad5b19a225" , "Siemens_CT_Sensation64_has_VR_RT.dcm" }, { "13e41624a8b86c18ac257e3588f818ce" , "tst_ok.dcm" }, { "17f514732d5f7e9484ed33c35bddc930" , "ImplicitVRInExplicitDataSet.dcm" }, { "0826b8cc512a8e4d726c1c019af2eaf9" , "29627381.dcm" }, { "727383f164107aaa9ee6c2182f94b91d" , "1.2.752.24.6.1820537353.20080220145707750.8.1.dcm" }, { "5588652e673e745ad56441f5a26c2305" , "22484474.dcm" }, { "cf6fde116c90e4e56512b22004503d96" , "PHILIPS_PrivateSeqWithPublicElems.dcm" }, { "098bba76d4e75a3148c9b62aee35f950" , "GEMS-IncompletePixelData.dcm" }, { "1fe71a52a211d1a56cc49cdcb71c1dbb" , "IM03.dcm" }, { "b857b6cce2afd7033476526b89ed9678" , "TheralysGDCM1.dcm" }, { "e998bbfca8b892fd0955c95b6f1584ea" , "Theralys2048Thingy.dcm" }, { "0508d28682e209f87d28184ae10060bd" , "Compress_16bit_noPVRG.dcm" }, { "90017033c3916259cad63615385a1d02" , "BogugsItemAndSequenceLengthCorrected.dcm" }, { "51b7e83cdc569b8f355662d80bd7036d" , "debian_medcon_401529.dcm" }, { "51b7e83cdc569b8f355662d80bd7036d" , "BogusItemStartItemEnd.dcm" }, { "3c6984afa2af4257565d8f622f7f5e5b" , "SIEMENS-JPEG-CorruptFrag.dcm" }, { "192f5ebd4d8f6164a4142421408172b2" , "PhilipsByteSwapping.dcm" }, { "2438b8feef6c8f682b2f468aff4475e5" , "MismatchSOPClassUID.dcm" }, { "738092e703655b6ae22a907d9f9f0c9c" , "YBRisGray.dcm" }, { "635e947fc156c89a8d10ced8317ace82" , "2mAs.dcm" }, { "54d648704507de7cd6e4be12061a5fb2" , "OSIRIX_MONOCHROME2_BUG.dcm" }, { "1db40fc52b962c8b6823980fe9dad6d8" , "5mAs.dcm" }, { "1b130fa646f8d6b3c14b9443b35c80b4" , "IM0046A0_2.dcm" }, { "cdfb45de5ddad3e7e2b0053c848d0d2b" , "ImplicitVRInExplicitDataSet2.dcm" }, { "ec5c421832df7cc43801d038705cd2cf" , "OverlayPrivateDataInBetween.dcm" }, { "9a375c3b2a72a6ccf687250b17f646c9" , "ItemTerminatorVLnot0.dcm" }, { "5269176094127c6f106cbcf9dbdf55b0" , "I0000017.dcm" }, { "eb87ca4a01e55dc7a7f1c92f0aa31017" , "EmptyItemStarter.dcm" }, { "cae8f644373163cb3970999f7ac00fd3" , "169585.dcm" }, { "5ea911b29f472f371d21f2da2fd6b016" , "VRUNInMetaHeader.dcm" }, { "ad7b664eed26e95f790c24cdb3060fb9" , "IM000450.dcm" }, { "4f113f33863067b8ca8d560cb194da09" , "TOSHIBA-CurveData3.dcm" }, { "14fa2ae9f63742af6944edd4a61145e8" , "mrbrainR.dcm" }, { "ba17ae006314a097fef7a32fa1a624b0" , "c42g57hg64ca02.dcm" }, { "10047ec574a6401ad90606e63304de6e" , "0020.DCM" }, { "5184839806c9a9583fe192d43cede939" , "001005XA" }, { "5291e36a7d54d4c8e00d5765cd0b3d17" , "001007XA" }, { "a57df7bc23977977832f98bfb662cdb4" , "001003XA" }, { "b36329c27f359daede3205d7c57cccd1" , "001009XA" }, { "1d173a6f31e0e4dd1078adf3557774c7" , "001008XA" }, { "9b42aa4e5d3b5f889164b5a734b954b3" , "001010XA" }, { "87f72a961292c83f8a9230e8eefecc6b" , "001004XA" }, { "6c7a303d25b418988ef9a37c4315a746" , "001001XA" }, { "9dde002e4e99218891df5f98da56ec9d" , "001002XA" }, { "6c7a303d25b418988ef9a37c4315a746" , "001001XA.1" }, { "8891d44376bc53c7bd0d36d2b776cd9b" , "001006XA" }, { "a6d10a3de9499d8853c6667b82628e86" , "TOSHIBA-EnhancedCT.dcm" }, { "71b3b19571f5b9e7ec931071bf5157dd" , "CroppedArm.dcm" }, { "bab06b7112dbce4f528bab5c1b89abc1" , "Bug_Philips_ItemTag_3F3F.dcm" }, { "8d3a64a67b4d8d15561fb586fd0706ee" , "Nm.dcm" }, { "05392d4f7a0c05223eeb957ee60203a9" , "MergeCOM3_330_IM50.dcm" }, { "635c2dbedea549a89f88e959934ed93c" , "ELSCINT1_OW.dcm" }, { "594995a6eb12a565247cd98f967a378d" , "KONICA_VROX.dcm" }, { "1497b865a4c6ab73cd6797b8834baa9f" , "TheralysNoModalityNoObject.dcm" }, { "d1f8cbdb279d038e2674ec0907afffe1" , "gastrolateral.dcm" }, { "ea24c09f475a4e9643e27f6d470edc67" , "SIEMENS_GBS_III-16-ACR_NEMA_1-ULis2Bytes.dcm" }, { "ecd26fb1fa914918ff9292c4f7340050" , "MR00010001.dcm" }, { "c56567bbb8f1924d6c0c6fd8ca7f239d" , "006872.003.107.dcm" }, { "228e9af71b8ce00cae3066e3fdd3641f" , "SIEMENS_MONOCHROME2_LUT_MOCO.dcm" }, { "ef8c3435ee7a9b332976f2dc56833d3a" , "GENESIS_SIGNA-JPEG-CorruptFrag.dcm" }, // FIXME ! { "42a4f33eb34456e3e82f30d707c84870" , "DCMOBJ_IMG57.dcm" }, { "3a85617df95abbb63cd84a183515c697" , "image.acr" }, { "8c5a627c461688cfa5dc708a170c5eda" , "IM-0001-0001.dcm" }, { "ec87a838931d4d5d2e94a04644788a55" , "test_att.acr" }, { "0621954acd5815e0b4f7b65fcc6506b1" , "SIEMENS_ImageLocationUN.dcm" }, { "e1e34e81050d17b07a20c0e43c355187" , "GDCMFakeJPEG.dcm" }, { "ef9f915086db838334ddc656a10486f2" , "DMCPACS_ExplicitImplicit_BogusIOP.dcm" }, { "498f80fd27882351b9a09e6ceef470bc" , "ELSCINT1_GDCM12Bug.dcm" }, { "34b5c1ce40f09f0dbede87ebf3f6ed3c" , "korean_agfa_infinitt_2008-3.dcm" }, { "2c8b8ee9950582af472cf652005f07d4" , "c_vf1001.dcm" }, { "a1ea6633f17ef1e0d702cdd46434b393" , "MARTIN_ALBERT-20010502-2-1.nema" }, { "d85237c7ff838f5246643a027d3727ae" , "GDCMPrinterDisplayUNasSQ.dcm" }, { "2dbe2da7fbcf1bd73e2221e9cd4ad7ee" , "MissingPixelRepresentation.dcm" }, { "a3009bc70444148c5ea2441a099f9dc6" , "E00001S03I0015.dcm" }, { "afe5937be25ac657e48b1270b52e6d98" , "Martin.dcm" }, { "4d790e17ee35572d64e37c55dbc36725" , "MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm" }, { "93ddc0c3d642af60f55630232d2801ae" , "CT_Image_Storage_multiframe.dcm" }, { "6127740892542f23e37e6ab516b17caf" , "ELSCINT1_JP2vsJ2K.dcm" }, { "b620a57170941e26dfd07ff334c73cb4" , "GE_MR_0025xx1bProtocolDataBlock.dcm" }, { "4b5423b34ab4e104c222359a91448a5d" , "CT-SIEMENS-MissingPixelDataInIconSQ.dcm" }, { "79b8705f2e6c7464bd3e2fc7e1d3483b" , "KODAK_CompressedIcon.dcm" }, { "59071590099d21dd439896592338bf95" , "ima43.dcm" }, { "46bf12c412590767bb8cd7f0d53eaa87" , "TG18-CH-2k-01.dcm" }, { "9214cc4f62fbea873ffad88e1be877c5" , "LJPEG_BuginGDCM12.dcm" }, { "52607a16af1eaddbbc71c14d32e489d8" , "DX_J2K_0Padding.dcm" }, { "6af53848fe77feb56a12aba74dadea8e" , "TheralysGDCM120Bug.dcm" }, { "79b8705f2e6c7464bd3e2fc7e1d3483b" , "TestVRSQUN2.dcm" }, { "71e4ea61df4f7ada2955799c91f93e74" , "TestVRSQUN1.dcm" }, { "6396332b75b15bf30b1dd1cd0f212691" , "SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm" }, { "ba8dae4b43075c7e8562f5addf5f95c3" , "DX_GE_FALCON_SNOWY-VOI.dcm" }, { "d6fb1fb06318dd305a461db9c84cf825" , "JPEG_LossyYBR.dcm" }, { "43f33c06d56f239ce9ed5ca0d66a69d2" , "PHILIPS_Brilliance_ExtraBytesInOverlay.dcm" }, { "dae9d2e2b412646fd0a0f31dc2d17aa4" , "BugGDCM2_UndefItemWrongVL.dcm" }, { "62687f0a17e9c4153f18b55c8abfcef3" , "SIEMENS_CSA2.dcm" }, { "a02fa05065b3a93a391f820ac38bd9ee" , "MAROTECH_CT_JP2Lossy.dcm" }, { "8b5e38699887158c3defd47900a68fc5" , "ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm" }, { "c57035e2dac52e339b27e8c965251b3d" , "DCMTK_JPEGExt_12Bits.dcm" }, // checked with dcmdjpeg v3.5.4+ 2009-05-07 { "d7673c8575cb2765f8ae25aa3899c77e" , "PHILIPS_GDCM12xBug.dcm"}, { "a597540a79306be4710f4f04497fc23a" , "PHILIPS_GDCM12xBug2.dcm"}, { "1e8843c2d247f9e9e7a44c9c6de43f6d" , "multiframegrayscalewordscis.dcm" }, { "928b41468193f0eecaea216866bbe735" , "signedtruecoloroldsc.dcm" }, { "209bc9b02004a712f0436a1ca5e676b4" , "multiframesinglebitscis.dcm" }, { "c8698fa1ec0b227113f244954b8e88f4" , "multiframegrayscalebytescis.dcm" }, { "dce1513162a762bf43dcc3c9d5c5c3f7" , "multiframetruecolorscis.dcm" }, { "6bf95a48f366bdf8af3a198c7b723c77" , "SinglePrecisionSC.dcm" }, { "42cb593979fcc4630f965c31caaf4ec1" , "MR16BitsAllocated_8BitsStored.dcm" }, { "da153c2f438d6dd4277e0c6ad2aeae74" , "OsirixFake16BitsStoredFakeSpacing.dcm" }, { "1c485e1ac2b2bdbeeba14391b8c1e0c8" , "JPEGDefinedLengthSequenceOfFragments.dcm" }, { "ae1290d59c63b0c334a4834c5995fe45" , "AMIInvalidPrivateDefinedLengthSQasUN.dcm" }, { "f3a3d0e739e5f4fbeddd1452b81f4d89" , "D_CLUNIE_CT1_JLSL.dcm" }, { "5e9085c66976d2f5f9989d88bf7a90c4" , "D_CLUNIE_CT1_JLSN.dcm" }, { "9eb513314b2fcf25d895e18ffb2ead0b" , "UnexpectedSequenceDelimiterInFixedLengthSequence.dcm" }, { "fb8119f30ec32ff575789caa969180ca" , "IM-0001-0066.CommandTag00.dcm" }, { "6f26e552a1b71d386483118779d192ad" , "NM_Kakadu44_SOTmarkerincons.dcm" }, { "56238d3665ebdb0251d1161fb7f4edc6" , "GDCMJ2K_TextGBR.dcm" }, { "f8a1f4ce85b51527267e670a8aa0c308" , "PhilipsInteraSeqTermInvLen.dcm" }, // following 3 md5 computes with kdu_expand v6.3.1 { "d6347ed051d7b887bdaad1a91433c6ba" , "TOSHIBA_J2K_SIZ1_PixRep0.dcm" }, { "d6347ed051d7b887bdaad1a91433c6ba" , "TOSHIBA_J2K_SIZ0_PixRep1.dcm" }, { "94414d8b4300aa3d8cbe4475d34e8e54" , "TOSHIBA_J2K_OpenJPEGv2Regression.dcm" }, { "304f147752d46adfdcff71a30cd03d0a" , "NM-PAL-16-PixRep1.dcm" }, { "20b1e4de7b864d44fcd0dda1fc42402c" , "MEDILABInvalidCP246_EVRLESQasUN.dcm" }, // gdcmDataExtra: { "cb26bfacea534b5cd6881bc36520ecfc" , "US_512x512x2496_JPEG_BaseLine_Process_1.dcm" }, { "d40e2d27988f0c546b0daeb67fcbfba8" , "i32.XADC.7.215MegaBytes.dcm" }, { "c383b244fd43cb0a9db764b71cb59741" , "1.3.46.670589.7.5.10.80002138018.20001204.181556.9.1.1.dcm" }, { "f111ed4eea73f535261039d3f7b112e9" , "JPEGInvalidSecondFrag.dcm" }, // Computed with kakadu: { "a218fcee00e16d430f30ec7ebd4937dc" , "lena512_rot90.j2k.dcm" }, { "dbf83984984741c98205d77a947b442c" , "SC16BitsAllocated_8BitsStoredJ2K.dcm" }, { "f845c8f283d39a0204c325654493ba53" , "SC16BitsAllocated_8BitsStoredJPEG.dcm" }, { "4a5d8549791432b29948dd8ff63e2534" , "SIEMENS_SYNGO-12-MONO2-LUTWrongLength512.dcm" }, { "2c8630ae1bff925b258d98e742dfc632" , "JPEGLS_CharLS_10742.dcm" }, { "f666a95dde9ddfdec0cf9574a7985ae3" , "IllegalGroup2ImplicitTS.dcm" }, { "b85686dd3169b99725149abb00181254" , "RLEDebianBug816607Orig.dcm" }, { "464960d948dff0ded72b0380080f18a3" , "JPEGNote_empty.dcm" }, { "cdfb5dd0c999d88badeb00a16f96554f" , "JPEGLosslessYBR_FULL_422.dcm" }, { "464960d948dff0ded72b0380080f18a3" , "JPEGNote_missing.dcm" }, { "161e9fd986ea87adf2596e8e16641f11" , "JPEGNote_bogus.dcm" }, { "ad8f1164f0517ee150bf510d5dba5cc6" , "GE_MR_0025xx1bProtocolDataBlockXML.dcm" }, { "a0e0effa8d5638721b19e592acc11a4c" , "EmptyIcon_Bug417.dcm" }, { "2b64303085d747956bfdda2ee8cc33bc" , "EnhancedWithIPPPerFrameIOPShared.dcm" }, { "4ca2f3a88d21d941f6485a8d91f96e29" , "FUJI-ffff-MONO1-J2K.dcm" }, { "b9697e3615a841e4c04f45ede6923278" , "JPEGLosslessSeNonZero.dcm" }, { "5fcd7d6573cab16d2ef575bba878ec78" , "US-YBR_FULL_422-EVRLE.dcm" }, { "d62b4c13e8108671f1c66626c5bdee55" , "Osirix10vs8BitsStored.dcm" }, { "b7c6fb507da1b7a3f81f821a2e3eaf49" , "Bug_Siemens_PrivateIconNoItem.dcm" }, { "56238d3665ebdb0251d1161fb7f4edc6" , "HardcopyColor_YBR_RCT_J2K_PC1.dcm" }, { "5fe2b8742f05a0ba06d354f965266dbc" , "PET-GE-dicomwrite-PixelDataSQUNv2.dcm" }, /* Stopping condition */ { nullptr ,nullptr } }; GDCM-3.0.10/Testing/Source/Data/gdcmMediaStorageDataFiles.cxx000066400000000000000000000376251412732066400235550ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * gdcmscanner -d /path/to/gdcmData/ -t 8,16 -p */ static const char * const gdcmMediaStorageDataFiles[][2] = { { "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm","1.2.840.10008.5.1.4.1.1.7" }, { "SIEMENS_GBS_III-16-ACR_NEMA_1.acr", "1.2.840.10008.5.1.4.1.1.4"}, { "00191113.dcm","1.2.840.10008.5.1.4.1.1.12.1"}, { "SignedShortLosslessBug.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "gdcm-MR-PHILIPS-16-NonSquarePixels.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "ACUSON-24-YBR_FULL-RLE.dcm","1.2.840.10008.5.1.4.1.1.6.1"}, { "D_CLUNIE_VL2_RLE.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "MR_Philips-Intera_BreaksNOSHADOW.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "D_CLUNIE_MR2_JPLL.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "D_CLUNIE_XA1_JPLL.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "JPEG_LossyYBR.dcm","1.2.840.10008.5.1.4.1.1.6.1"}, { "ALOKA_SSD-8-MONO2-RLE-SQ.dcm","1.2.840.10008.5.1.4.1.1.6.1"}, { "PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "MR-MONO2-12-shoulder.dcm","1.2.840.10008.5.1.4.1.1.4"}, //{ "MR_SIEMENS_forceLoad29-1010_29-1020.README.txt (could not be read)}, //{ "ExplicitVRforPublicElementsImplicitVRforShadowElements.README.txt (could not be read)}, { "D_CLUNIE_RG3_JPLY.dcm","1.2.840.10008.5.1.4.1.1.1"}, { "SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs.acr","1.2.840.10008.5.1.4.1.1.2"}, { "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "DICOMDIR_MR_B_VA12A" , "1.2.840.10008.1.3.10" }, { "MR-MONO2-8-16x-heart.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "SIEMENS_ImageLocationUN.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "US-PAL-8-10x-echo.dcm","1.2.840.10008.5.1.4.1.1.3.1"}, { "PHILIPS_Brilliance_ExtraBytesInOverlay.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "MR-MONO2-12-an2.acr","1.2.840.10008.5.1.4.1.1.4"}, { "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "US-RGB-8-esopecho.dcm","1.2.840.10008.5.1.4.1.1.6"}, { "GE_RHAPSODE-16-MONO2-JPEG-Fragments.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "CT-SIEMENS-Icone-With-PaletteColor.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "gdcm-ACR-LibIDO.acr" , "1.2.840.10008.5.1.4.1.1.7"}, // COMPAT { "LEADTOOLS_FLOWERS-16-MONO2-Uncompressed.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "FUJI-10-MONO1-ACR_NEMA_2.dcm","1.2.840.10008.5.1.4.1.1.1"}, { "D_CLUNIE_CT1_RLE.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "undefined_length_un_vr.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "D_CLUNIE_MR4_JPLL.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "PET-cardio-Multiframe-Papyrus.dcm", "" }, { "dicomdir_Pms_WithVisit_WithPrivate_WithStudyComponents" , "1.2.840.10008.1.3.10"}, { "CT_16b_signed-UsedBits13.dcm","1.2.840.10008.5.1.4.1.1.2"}, //{ "TestAllEntryVerifyReference.txt (could not be read)}, { "DX_J2K_0Padding.dcm","1.2.840.10008.5.1.4.1.1.1.1"}, { "KODAK_CompressedIcon.dcm","1.2.840.10008.5.1.4.1.1.1"}, { "D_CLUNIE_CT2_JPLL.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "DermaColorLossLess.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "DICOMDIR" , "1.2.840.10008.1.3.10" }, { "LIBIDO-24-ACR_NEMA-Rectangle.dcm", "" }, { "GE_GENESIS-16-MONO2-Uncompressed-UnusualVR.dcm","1.2.840.10008.5.1.4.1.1.4"}, //{ "MR-SIEMENS-DICOM-WithOverlays.README.txt (could not be read)}, { "D_CLUNIE_NM1_JPLY.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "D_CLUNIE_CT1_J2KR.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "LEADTOOLS_FLOWERS-16-MONO2-RLE.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "US-RGB-8-epicard.dcm","1.2.840.10008.5.1.4.1.1.6.1"}, { "D_CLUNIE_MR3_RLE.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "test.acr" ,"1.2.840.10008.5.1.4.1.1.7"}, // COMPAT { "LEADTOOLS_FLOWERS-8-MONO2-Uncompressed.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "US-IRAD-NoPreambleStartWith0005.dcm","1.2.840.10008.5.1.4.1.1.6"}, { "D_CLUNIE_RG2_JPLL.dcm","1.2.840.10008.5.1.4.1.1.1"}, { "ELSCINT1_PMSCT_RLE1.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "DMCPACS_ExplicitImplicit_BogusIOP.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "LIBIDO-16-ACR_NEMA-Volume.dcm", "" }, //{ "Changelog (could not be read)}, //{ "ELSCINT1_LOSSLESS_RICE.txt (could not be read)}, { "MR-SIEMENS-DICOM-WithOverlays.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "JDDICOM_Sample2-dcmdjpeg.dcm", "" }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "D_CLUNIE_MR3_JPLY.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "TheralysGDCM120Bug.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "US-GE-4AICL142.dcm","1.2.840.10008.5.1.4.1.1.6.1"}, { "3E768EB7.dcm","1.2.840.10008.5.1.4.1.1.2"}, //{ "gdcm-MR-PHILIPS-16-Multi-Seq.README.txt (could not be read)}, { "SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "GE_MR_0025xx1bProtocolDataBlock.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "D_CLUNIE_SC1_JPLY.dcm","1.2.840.10008.5.1.4.1.1.7"}, //{ "imagesWithOverlays.README.txt (could not be read)}, { "CT-MONO2-16-chest.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "D_CLUNIE_MR4_RLE.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "gdcm-CR-DCMTK-16-NonSamplePerPix.dcm" , "" }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "ELSCINT1_JP2vsJ2K.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "D_CLUNIE_CT2_RLE.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "D_CLUNIE_MR2_RLE.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "OT-MONO2-8-a7.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "MR-MONO2-16-head.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "PICKER-16-MONO2-No_DicomV3_Preamble.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "gdcm-JPEG-Extended.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "MR-MONO2-12-angio-an1.acr", ""}, { "BugGDCM2_UndefItemWrongVL.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "D_CLUNIE_MR1_RLE.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "ELSCINT1_LOSSLESS_RICE.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "dicomdir_Pms_With_heavy_embedded_sequence" , "1.2.840.10008.1.3.10" }, { "PICKER-16-MONO2-Nested_icon.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "D_CLUNIE_VL4_RLE.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "D_CLUNIE_RG1_RLE.dcm","1.2.840.10008.5.1.4.1.1.1"}, { "JDDICOM_Sample2.dcm", "" }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "CT-MONO2-8-abdo.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "D_CLUNIE_SC1_RLE.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "LEADTOOLS_FLOWERS-24-RGB-JpegLossless.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "LIBIDO-8-ACR_NEMA-Lena_128_128.acr" , "" }, { "D_CLUNIE_RG3_JPLL.dcm","1.2.840.10008.5.1.4.1.1.1"}, { "SIEMENS_CSA2.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "SIEMENS_GBS_III-16-ACR_NEMA_1-ULis2Bytes.dcm", "" }, { "LJPEG_BuginGDCM12.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "CT-SIEMENS-MissingPixelDataInIconSQ.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "libido1.0-vol.acr" , "" }, { "MR_Spectroscopy_SIEMENS_OF.dcm","1.2.840.10008.5.1.4.1.1.4.2"}, { "GE_CT_With_Private_compressed-icon.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "D_CLUNIE_XA1_JPLY.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "012345.002.050.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "TOSHIBA_MRT150-16-MONO2-ACR_NEMA_2.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "LEADTOOLS_FLOWERS-8-MONO2-JpegLossy.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "gdcm-US-ALOKA-16.dcm","1.2.840.10008.5.1.4.1.1.6.1"}, { "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "D_CLUNIE_CT1_JPLL.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "rle16loo.dcm","1.2.840.10008.5.1.4.1.1.3.1"}, { "D_CLUNIE_US1_RLE.dcm","1.2.840.10008.5.1.4.1.1.6.1"}, { "LEADTOOLS_FLOWERS-8-MONO2-RLE.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "RadBWLossLess.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "dicomdir_Acusson_WithPrivate_WithSR" , "1.2.840.10008.1.3.10"}, { "D_CLUNIE_MR1_JPLY.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "GE_DLX-8-MONO2-PrivateSyntax.dcm","1.2.840.10008.5.1.4.1.1.12.1"}, { "gdcm-JPEG-LossLess3a.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "TG18-CH-2k-01.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "OT-PAL-8-face.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "D_CLUNIE_NM1_RLE.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "rle16sti.dcm","1.2.840.10008.5.1.4.1.1.6.1"}, { "GE_GENESIS-16-MONO2-WrongLengthItem.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "D_CLUNIE_CT1_J2KI.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "LEADTOOLS_FLOWERS-24-RGB-Uncompressed.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "D_CLUNIE_MR4_JPLY.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "D_CLUNIE_RG3_RLE.dcm","1.2.840.10008.5.1.4.1.1.1"}, { "SIEMENS-12-Jpeg_Process_2_4-Lossy-a.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "DICOMDIR-Philips-EasyVision-4200-Entries", "1.2.840.10008.1.3.10"}, { "CT-MONO2-16-brain.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "D_CLUNIE_RG2_JPLY.dcm","1.2.840.10008.5.1.4.1.1.1"}, { "MAROTECH_CT_JP2Lossy.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "D_CLUNIE_MR1_JPLL.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "dicomdir_With_embedded_icons", "1.2.840.10008.1.3.10"}, { "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm", "" }, { "MR_SIEMENS_forceLoad29-1010_29-1020.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "simpleImageWithIcon.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "D_CLUNIE_MR3_JPLL.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "D_CLUNIE_RG1_JPLL.dcm","1.2.840.10008.5.1.4.1.1.1"}, { "US-MONO2-8-8x-execho.dcm","1.2.840.10008.5.1.4.1.1.3"}, { "XA-MONO2-8-12x-catheter.dcm","1.2.840.10008.5.1.4.1.1.12.1"}, //{ "TheralysGDCM120Bug.README.txt (could not be read)}, { "GE_LOGIQBook-8-RGB-HugePreview.dcm","1.2.840.10008.5.1.4.1.1.7"}, //{ "MR_Philips_Intera_PrivateSequenceImplicitVR.README.txt (could not be read)}, { "gdcm-MR-SIEMENS-16-2.acr", ""}, { "gdcm-MR-PHILIPS-16-Multi-Seq.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "D_CLUNIE_XA1_RLE.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "NM-MONO2-16-13x-heart.dcm","1.2.840.10008.5.1.4.1.1.20"}, { "gdcm-JPEG-LossLessThoravision.dcm","1.2.840.10008.5.1.4.1.1.1"}, //{ "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.txt (could not be read)}, { "GE_DLX-8-MONO2-Multiframe.dcm","1.2.840.10008.5.1.4.1.1.12.1"}, { "PHILIPS_Intera-16-MONO2-Uncompress.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "D_CLUNIE_MR2_JPLY.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "05148044-mr-siemens-avanto-syngo.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "D_CLUNIE_VL3_RLE.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "D_CLUNIE_RG2_RLE.dcm","1.2.840.10008.5.1.4.1.1.1"}, { "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "KODAK-12-MONO1-Odd_Terminated_Sequence.dcm","1.2.840.10008.5.1.4.1.1.1"}, { "SIEMENS-MR-RGB-16Bits.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "CR-MONO1-10-chest.dcm","1.2.840.10008.5.1.4.1.1.1"}, { "DX_GE_FALCON_SNOWY-VOI.dcm","1.2.840.10008.5.1.4.1.1.1.1"}, { "US-IRAD-NoPreambleStartWith0003.dcm","1.2.840.10008.5.1.4.1.1.6"}, { "MR-Brucker-CineTagging-NonSquarePixels.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "D_CLUNIE_VL6_RLE.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "MR_Philips_Intera_PrivateSequenceImplicitVR.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "fffc0000UN.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "CT-MONO2-12-lomb-an2.acr" , "" }, { "SIEMENS_Sonata-12-MONO2-SQ.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "ACUSON-24-YBR_FULL-RLE-b.dcm","1.2.840.10008.5.1.4.1.1.6.1"}, { "CT-MONO2-16-ankle.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm","1.2.840.10008.5.1.4.1.1.12.1"}, { "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "CT-MONO2-16-ort.dcm","1.2.840.10008.5.1.4.1.1.2"}, { "LEADTOOLS_FLOWERS-16-MONO2-JpegLossless.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "D_CLUNIE_NM1_JPLL.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "D_CLUNIE_VL1_RLE.dcm","1.2.840.10008.5.1.4.1.1.7"}, { "IM-0001-0066.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "SIEMENS_MAGNETOM-12-MONO2-VRUN.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "PhilipsInteraSeqTermInvLen.dcm","1.2.840.10008.5.1.4.1.1.4"}, { "PHILIPS_GDCM12xBug.dcm" , "1.2.840.10008.5.1.4.1.1.4" }, { "OsirixFake16BitsStoredFakeSpacing.dcm", "1.2.840.10008.5.1.4.1.1.7" }, { "IM-0001-0066.CommandTag00.dcm", "1.2.840.10008.5.1.4.1.1.4" }, { "AMIInvalidPrivateDefinedLengthSQasUN.dcm" , "1.2.840.10008.5.1.4.1.1.4" }, { "GDCMJ2K_TextGBR.dcm" , "1.2.840.10008.5.1.4.1.1.7" }, { "MR16BitsAllocated_8BitsStored.dcm" , "1.2.840.10008.5.1.4.1.1.4" }, { "D_CLUNIE_CT1_JLSL.dcm", "1.2.840.10008.5.1.4.1.1.2" }, { "JPEGDefinedLengthSequenceOfFragments.dcm" , "1.2.840.10008.5.1.4.1.1.2" }, { "PHILIPS_GDCM12xBug2.dcm" , "1.2.840.10008.5.1.4.1.1.4" }, { "DCMTK_JPEGExt_12Bits.dcm" , "1.2.840.10008.5.1.4.1.1.7" }, { "UnexpectedSequenceDelimiterInFixedLengthSequence.dcm" , "1.2.840.10008.5.1.4.1.1.20" }, { "NM_Kakadu44_SOTmarkerincons.dcm" , "1.2.840.10008.5.1.4.1.1.1" }, { "D_CLUNIE_CT1_JLSN.dcm", "1.2.840.10008.5.1.4.1.1.2" }, { "TOSHIBA_J2K_SIZ1_PixRep0.dcm", "1.2.840.10008.5.1.4.1.1.2"}, { "TOSHIBA_J2K_SIZ0_PixRep1.dcm", "1.2.840.10008.5.1.4.1.1.2" }, { "TOSHIBA_J2K_OpenJPEGv2Regression.dcm", "1.2.840.10008.5.1.4.1.1.2" }, { "NM-PAL-16-PixRep1.dcm", "1.2.840.10008.5.1.4.1.1.20" }, { "MEDILABInvalidCP246_EVRLESQasUN.dcm", "1.2.840.10008.5.1.4.1.1.2" }, { "JPEGInvalidSecondFrag.dcm", "1.2.840.10008.5.1.4.1.1.2" }, { "ELSCINT1_PMSCT_RLE1_priv.dcm", "1.2.840.10008.5.1.4.1.1.2" }, { "unreadable.dcm", "1.2.840.10008.5.1.4.1.1.2" }, { "SC16BitsAllocated_8BitsStoredJPEG.dcm" , "1.2.840.10008.5.1.4.1.1.7" }, { "SC16BitsAllocated_8BitsStoredJ2K.dcm" , "1.2.840.10008.5.1.4.1.1.7" }, { "SIEMENS_SYNGO-12-MONO2-LUTWrongLength512.dcm" , "1.2.840.10008.5.1.4.1.1.4" }, { "JPEGNote_empty.dcm" , "1.2.840.10008.5.1.4.1.1.7" }, { "JPEGLS_CharLS_10742.dcm" , "1.2.840.10008.5.1.4.1.1.7" }, { "JPEGLosslessYBR_FULL_422.dcm" , "1.2.840.10008.5.1.4.1.1.7" }, { "JPEGNote_missing.dcm" , "1.2.840.10008.5.1.4.1.1.7" }, { "JPEGNote_bogus.dcm" , "1.2.840.10008.5.1.4.1.1.7" }, { "RLEDebianBug816607Orig.dcm" , "1.2.840.10008.5.1.4.1.1.7" }, { "IllegalGroup2ImplicitTS.dcm" , "1.2.840.10008.5.1.4.1.1.1" }, { "JPEG_LS_InvalidEscapeSequence_COM_padding.dcm" , "1.2.840.10008.5.1.4.1.1.7" }, { "LengthOfItemLarger.dcm" , "1.2.840.10008.5.1.4.1.1.4" }, { "GE_MR_0025xx1bProtocolDataBlockXML.dcm" , "1.2.840.10008.5.1.4.1.1.4" }, { "MITRA_CORNELL.dcm" , "1.2.840.10008.5.1.4.1.1.7" }, { "EmptyIcon_Bug417.dcm" , "1.2.840.10008.5.1.4.1.1.2" }, { "EnhancedWithIPPPerFrameIOPShared.dcm" , "1.2.840.10008.5.1.4.1.1.13.1.2" }, { "FUJI-ffff-MONO1-J2K.dcm" , "1.2.840.10008.5.1.4.1.1.1" }, { "JPEGLosslessSeNonZero.dcm" , "1.2.840.10008.5.1.4.1.1.7" }, { "US-YBR_FULL_422-EVRLE.dcm" , "1.2.840.10008.5.1.4.1.1.6.1" }, { "PET-GE-dicomwrite-PixelDataSQUN.dcm" , "1.2.840.10008.5.1.4.1.1.128" }, { "Osirix10vs8BitsStored.dcm" , "1.2.840.10008.5.1.4.1.1.4" }, { "Bug_Siemens_PrivateIconNoItem.dcm" , "1.2.840.10008.5.1.4.1.1.2" }, { "HardcopyColor_YBR_RCT_J2K_PC1.dcm" , "1.2.840.10008.5.1.1.30" }, { "PET-GE-dicomwrite-PixelDataSQUNv2.dcm" , "1.2.840.10008.5.1.4.1.1.128" }, { "PET-GE-dicomwrite-PixelDataSQUNv3.dcm" , "1.2.840.10008.5.1.4.1.1.128" }, /* Stopping condition */ { nullptr ,nullptr } }; GDCM-3.0.10/Testing/Source/Data/gdcmSelectedPrivateGroupOffsetDataFiles.cxx000066400000000000000000000235131412732066400264470ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * See TestReaderSelectedPrivateGroup */ #if 0 struct StreamOffset { const char *filename; std::streamoff offset; }; #endif static const StreamOffset gdcmSelectedPrivateGroupOffsetDataFiles[] = { { "gdcm-ACR-LibIDO.acr",50 }, { "test.acr",50 }, { "libido1.0-vol.acr",50 }, { "gdcm-MR-SIEMENS-16-2.acr",686 }, { "SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs.acr",686 }, { "MR-MONO2-12-an2.acr",546 }, { "LIBIDO-8-ACR_NEMA-Lena_128_128.acr",50 }, { "CT-MONO2-12-lomb-an2.acr",366 }, { "D_CLUNIE_CT1_J2KR.dcm",1178 }, { "TOSHIBA_J2K_SIZ0_PixRep1.dcm",746 }, { "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm",1796 }, { "LJPEG_BuginGDCM12.dcm",886 }, { "GE_MR_0025xx1bProtocolDataBlock.dcm",1146 }, { "LEADTOOLS_FLOWERS-8-MONO2-RLE.dcm",848 }, { "SIEMENS_ImageLocationUN.dcm",960 }, { "JPEGDefinedLengthSequenceOfFragments.dcm",1496 }, { "TOSHIBA_J2K_OpenJPEGv2Regression.dcm",748 }, { "MR-SIEMENS-DICOM-WithOverlays.dcm",1042 }, { "GDCMJ2K_TextGBR.dcm",534 }, { "rle16loo.dcm",524 }, { "GE_DLX-8-MONO2-Multiframe.dcm",780 }, { "SC16BitsAllocated_8BitsStoredJ2K.dcm",534 }, { "MR-MONO2-12-shoulder.dcm",674 }, { "GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm",794 }, { "SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm",1384 }, { "NM-MONO2-16-13x-heart.dcm",578 }, { "LEADTOOLS_FLOWERS-8-MONO2-Uncompressed.dcm",848 }, { "CT-MONO2-16-chest.dcm",838 }, { "D_CLUNIE_MR4_JPLY.dcm",1028 }, { "D_CLUNIE_SC1_JPLY.dcm",964 }, { "MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm",1302 }, { "D_CLUNIE_VL6_RLE.dcm",866 }, { "DX_J2K_0Padding.dcm",746 }, { "D_CLUNIE_XA1_RLE.dcm",800 }, { "PHILIPS_Intera-16-MONO2-Uncompress.dcm",1622 }, { "US-RGB-8-esopecho.dcm",598 }, { "GE_GENESIS-16-MONO2-WrongLengthItem.dcm",760 }, { "D_CLUNIE_MR3_JPLL.dcm",1200 }, { "SIEMENS-12-Jpeg_Process_2_4-Lossy-a.dcm",1252 }, { "D_CLUNIE_MR1_RLE.dcm",908 }, { "SIEMENS_CSA2.dcm",1260 }, { "gdcm-MR-PHILIPS-16-Multi-Seq.dcm",1354 }, { "GE_DLX-8-MONO2-PrivateSyntax.dcm",770 }, { "D_CLUNIE_MR2_JPLY.dcm",1030 }, { "DX_GE_FALCON_SNOWY-VOI.dcm",1152 }, { "AMIInvalidPrivateDefinedLengthSQasUN.dcm",1028 }, { "SC16BitsAllocated_8BitsStoredJPEG.dcm",606 }, { "OT-PAL-8-face.dcm",140 }, { "LEADTOOLS_FLOWERS-16-MONO2-RLE.dcm",848 }, { "TOSHIBA_J2K_SIZ1_PixRep0.dcm",762 }, { "D_CLUNIE_RG2_JPLL.dcm",1014 }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm",968 }, { "MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm",774 }, { "PHILIPS_GDCM12xBug2.dcm",1184 }, { "PICKER-16-MONO2-No_DicomV3_Preamble.dcm",496 }, { "MR_Spectroscopy_SIEMENS_OF.dcm",1372 }, { "ELSCINT1_JP2vsJ2K.dcm",680 }, { "US-PAL-8-10x-echo.dcm",496 }, { "OT-MONO2-8-a7.dcm",186 }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm",968 }, { "D_CLUNIE_NM1_JPLL.dcm",1406 }, { "D_CLUNIE_RG2_JPLY.dcm",1100 }, { "KODAK-12-MONO1-Odd_Terminated_Sequence.dcm",310 }, { "CT-MONO2-16-ort.dcm",784 }, { "D_CLUNIE_VL1_RLE.dcm",856 }, { "NM-PAL-16-PixRep1.dcm",820 }, { "ELSCINT1_PMSCT_RLE1.dcm",778 }, { "GE_GENESIS-16-MONO2-Uncompressed-UnusualVR.dcm",1012 }, { "D_CLUNIE_MR2_JPLL.dcm",944 }, { "GE_CT_With_Private_compressed-icon.dcm",1112 }, { "LEADTOOLS_FLOWERS-16-MONO2-JpegLossless.dcm",850 }, { "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm",1258 }, { "TOSHIBA_MRT150-16-MONO2-ACR_NEMA_2.dcm",400 }, { "simpleImageWithIcon.dcm",616 }, { "D_CLUNIE_CT1_JLSL.dcm",1162 }, { "US-IRAD-NoPreambleStartWith0005.dcm",684 }, { "TheralysGDCM120Bug.dcm",1964 }, { "SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm",1152 }, { "D_CLUNIE_NM1_RLE.dcm",1366 }, { "CR-MONO1-10-chest.dcm",298 }, { "ACUSON-24-YBR_FULL-RLE-b.dcm",822 }, { "TG18-CH-2k-01.dcm",1294 }, { "US-MONO2-8-8x-execho.dcm",630 }, { "GE_RHAPSODE-16-MONO2-JPEG-Fragments.dcm",1164 }, { "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm",753 }, { "MR_SIEMENS_forceLoad29-1010_29-1020.dcm",838 }, { "LEADTOOLS_FLOWERS-16-MONO2-Uncompressed.dcm",848 }, { "ACUSON-24-YBR_FULL-RLE.dcm",710 }, { "D_CLUNIE_MR1_JPLY.dcm",1036 }, { "D_CLUNIE_VL4_RLE.dcm",848 }, { "MR-MONO2-8-16x-heart.dcm",536 }, { "PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm",1060 }, { "D_CLUNIE_MR4_JPLL.dcm",942 }, { "LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm",850 }, { "D_CLUNIE_CT1_J2KI.dcm",1270 }, { "US-GE-4AICL142.dcm",688 }, { "CT-MONO2-16-ankle.dcm",750 }, { "LEADTOOLS_FLOWERS-24-RGB-JpegLossless.dcm",850 }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm",968 }, { "RadBWLossLess.dcm",542 }, { "DermaColorLossLess.dcm",542 }, { "D_CLUNIE_MR2_RLE.dcm",900 }, { "CT-SIEMENS-Icone-With-PaletteColor.dcm",1138 }, { "fffc0000UN.dcm",594 }, { "PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm",1340 }, { "BugGDCM2_UndefItemWrongVL.dcm",1466 }, { "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm",753 }, { "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm",1014 }, { "05148044-mr-siemens-avanto-syngo.dcm",1174 }, { "gdcm-JPEG-LossLessThoravision.dcm",954 }, { "D_CLUNIE_CT1_JPLL.dcm",1164 }, { "MR16BitsAllocated_8BitsStored.dcm",536 }, { "gdcm-CR-DCMTK-16-NonSamplePerPix.dcm",420 }, { "JDDICOM_Sample2-dcmdjpeg.dcm",464 }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm",968 }, { "gdcm-JPEG-Extended.dcm",1332 }, { "CT-SIEMENS-MissingPixelDataInIconSQ.dcm",922 }, { "LEADTOOLS_FLOWERS-8-MONO2-JpegLossy.dcm",850 }, { "CT-MONO2-16-brain.dcm",946 }, { "IM-0001-0066.CommandTag00.dcm",1472 }, { "SIEMENS_MAGNETOM-12-MONO2-VRUN.dcm",646 }, { "MAROTECH_CT_JP2Lossy.dcm",1244 }, { "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm",1236 }, { "D_CLUNIE_MR1_JPLL.dcm",952 }, { "D_CLUNIE_MR4_RLE.dcm",898 }, { "MEDILABInvalidCP246_EVRLESQasUN.dcm",1182 }, { "DCMTK_JPEGExt_12Bits.dcm",498 }, { "D_CLUNIE_RG2_RLE.dcm",966 }, { "05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm",1026 }, { "MR-Brucker-CineTagging-NonSquarePixels.dcm",652 }, { "ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm",590 }, { "D_CLUNIE_RG3_JPLL.dcm",988 }, { "00191113.dcm",536 }, { "PhilipsInteraSeqTermInvLen.dcm",922 }, { "MR_Philips_Intera_PrivateSequenceImplicitVR.dcm",1528 }, { "gdcm-JPEG-LossLess3a.dcm",1022 }, { "PHILIPS_Brilliance_ExtraBytesInOverlay.dcm",834 }, { "D_CLUNIE_RG3_JPLY.dcm",1074 }, { "PICKER-16-MONO2-Nested_icon.dcm",13296 }, { "LIBIDO-24-ACR_NEMA-Rectangle.dcm",50 }, { "SignedShortLosslessBug.dcm",794 }, { "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm",848 }, { "MR_Philips-Intera_BreaksNOSHADOW.dcm",1382 }, { "US-RGB-8-epicard.dcm",668 }, { "SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm",962 }, { "D_CLUNIE_VL2_RLE.dcm",854 }, { "3E768EB7.dcm",1282 }, { "012345.002.050.dcm",964 }, { "D_CLUNIE_CT1_JLSN.dcm",1260 }, { "PHILIPS_GDCM12xBug.dcm",1566 }, { "OsirixFake16BitsStoredFakeSpacing.dcm",664 }, { "CT_16b_signed-UsedBits13.dcm",1724 }, { "D_CLUNIE_CT2_RLE.dcm",922 }, { "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm",848 }, { "UnexpectedSequenceDelimiterInFixedLengthSequence.dcm",1310 }, { "rle16sti.dcm",520 }, { "D_CLUNIE_NM1_JPLY.dcm",1492 }, { "JDDICOM_Sample2.dcm",450 }, { "D_CLUNIE_RG1_RLE.dcm",1044 }, { "DMCPACS_ExplicitImplicit_BogusIOP.dcm",538 }, { "SIEMENS_Sonata-12-MONO2-SQ.dcm",1228 }, { "D_CLUNIE_XA1_JPLL.dcm",848 }, { "NM_Kakadu44_SOTmarkerincons.dcm",874 }, { "JPEG_LossyYBR.dcm",1142 }, { "gdcm-MR-PHILIPS-16-NonSquarePixels.dcm",772 }, { "D_CLUNIE_SC1_RLE.dcm",830 }, { "SIEMENS-MR-RGB-16Bits.dcm",1466 }, { "JPEGInvalidSecondFrag.dcm",1394 }, { "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm",1632 }, { "MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm",626 }, { "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm",686 }, { "LEADTOOLS_FLOWERS-24-RGB-Uncompressed.dcm",848 }, { "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm",1622 }, { "MR-MONO2-16-head.dcm",752 }, { "D_CLUNIE_XA1_JPLY.dcm",934 }, { "D_CLUNIE_CT2_JPLL.dcm",966 }, { "D_CLUNIE_RG3_RLE.dcm",934 }, { "ALOKA_SSD-8-MONO2-RLE-SQ.dcm",612 }, { "GE_LOGIQBook-8-RGB-HugePreview.dcm",742 }, { "gdcm-US-ALOKA-16.dcm",702 }, { "D_CLUNIE_US1_RLE.dcm",918 }, { "undefined_length_un_vr.dcm",1434 }, { "D_CLUNIE_MR3_JPLY.dcm",1286 }, { "D_CLUNIE_VL3_RLE.dcm",866 }, { "US-IRAD-NoPreambleStartWith0003.dcm",1504 }, { "CT-MONO2-8-abdo.dcm",422 }, { "FUJI-10-MONO1-ACR_NEMA_2.dcm",312 }, { "D_CLUNIE_MR3_RLE.dcm",1158 }, { "D_CLUNIE_CT1_RLE.dcm",1122 }, { "KODAK_CompressedIcon.dcm",890 }, { "D_CLUNIE_RG1_JPLL.dcm",1084 }, { "XA-MONO2-8-12x-catheter.dcm",644 }, { "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm",1314}, { "SIEMENS_SYNGO-12-MONO2-LUTWrongLength512.dcm", 1596 }, { "00191113.dcm",536 }, { "JPEGNote_empty.dcm", 482 }, { "JPEGLS_CharLS_10742.dcm", 532 }, { "JPEGLosslessYBR_FULL_422.dcm", 534 }, { "JPEGNote_missing.dcm", 406 }, { "JPEGNote_bogus.dcm", 482 }, { "RLEDebianBug816607Orig.dcm", 534 }, { "IllegalGroup2ImplicitTS.dcm", 1088 }, { "JPEG_LS_InvalidEscapeSequence_COM_padding.dcm", 534 }, { "LengthOfItemLarger.dcm", 1044 }, { "GE_MR_0025xx1bProtocolDataBlockXML.dcm",1358}, { "EmptyIcon_Bug417.dcm",1000}, { "EnhancedWithIPPPerFrameIOPShared.dcm",772}, { "FUJI-ffff-MONO1-J2K.dcm",982}, { "JPEGLosslessSeNonZero.dcm",530}, { "US-YBR_FULL_422-EVRLE.dcm",744}, { "Osirix10vs8BitsStored.dcm",1512}, { "Bug_Siemens_PrivateIconNoItem.dcm",1360}, { "HardcopyColor_YBR_RCT_J2K_PC1.dcm",1284}, { "PET-GE-dicomwrite-PixelDataSQUNv2.dcm",4620}, { "dicomdir_With_embedded_icons",7125212 }, { "dicomdir_Pms_WithVisit_WithPrivate_WithStudyComponents",37218 }, { "dicomdir_Acusson_WithPrivate_WithSR",3826 }, { "dicomdir_Pms_With_heavy_embedded_sequence",3003414 }, { "DICOMDIR-Philips-EasyVision-4200-Entries",1297194 }, { "DICOMDIR",1112434 }, { "DICOMDIR_MR_B_VA12A",14853880 }, /* Stopping condition */ { nullptr ,0 }, }; GDCM-3.0.10/Testing/Source/Data/gdcmSelectedTagsOffsetDataFiles.cxx000066400000000000000000000240421412732066400247140ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * See TestReaderSelectedTags */ #if 0 struct StreamOffset { const char *filename; std::streamoff offset; }; #endif static const StreamOffset gdcmSelectedTagsOffsetDataFiles[] = { { "SC16BitsAllocated_8BitsStoredJ2K.dcm", 752}, { "SC16BitsAllocated_8BitsStoredJPEG.dcm", 946}, { "CT-MONO2-12-lomb-an2.acr",1222 }, { "LIBIDO-8-ACR_NEMA-Lena_128_128.acr",174 }, { "MR-MONO2-12-an2.acr",1858 }, { "SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs.acr",5056 }, { "gdcm-ACR-LibIDO.acr",174 }, { "gdcm-MR-SIEMENS-16-2.acr",6044 }, { "libido1.0-vol.acr",162 }, { "test.acr",174 }, { "00191113.dcm",922 }, { "012345.002.050.dcm",9592 }, { "05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm",41936 }, { "05148044-mr-siemens-avanto-syngo.dcm",55872 }, { "3E768EB7.dcm",3222 }, { "ACUSON-24-YBR_FULL-RLE-b.dcm",2020 }, { "ACUSON-24-YBR_FULL-RLE.dcm",1908 }, { "ALOKA_SSD-8-MONO2-RLE-SQ.dcm",1386 }, { "AMIInvalidPrivateDefinedLengthSQasUN.dcm",12732 }, { "BugGDCM2_UndefItemWrongVL.dcm",9562 }, { "CR-MONO1-10-chest.dcm",768 }, { "CT-MONO2-16-ankle.dcm",1140 }, { "CT-MONO2-16-brain.dcm",1668 }, { "CT-MONO2-16-chest.dcm",1626 }, { "CT-MONO2-16-ort.dcm",1666 }, { "CT-MONO2-8-abdo.dcm",788 }, { "CT-SIEMENS-Icone-With-PaletteColor.dcm",8150 }, { "CT-SIEMENS-MissingPixelDataInIconSQ.dcm",20496 }, { "CT_16b_signed-UsedBits13.dcm",2574 }, { "DCMTK_JPEGExt_12Bits.dcm",784 }, { "DMCPACS_ExplicitImplicit_BogusIOP.dcm",20018 }, { "DX_GE_FALCON_SNOWY-VOI.dcm",104002 }, { "DX_J2K_0Padding.dcm",1482 }, { "D_CLUNIE_CT1_J2KI.dcm",6584 }, { "D_CLUNIE_CT1_J2KR.dcm",6484 }, { "D_CLUNIE_CT1_JLSL.dcm",6452 }, { "D_CLUNIE_CT1_JLSN.dcm",6566 }, { "D_CLUNIE_CT1_JPLL.dcm",6456 }, { "D_CLUNIE_CT1_RLE.dcm",6390 }, { "D_CLUNIE_CT2_JPLL.dcm",1744 }, { "D_CLUNIE_CT2_RLE.dcm",1676 }, { "D_CLUNIE_MR1_JPLL.dcm",1750 }, { "D_CLUNIE_MR1_JPLY.dcm",1836 }, { "D_CLUNIE_MR1_RLE.dcm",1682 }, { "D_CLUNIE_MR2_JPLL.dcm",1946 }, { "D_CLUNIE_MR2_JPLY.dcm",2034 }, { "D_CLUNIE_MR2_RLE.dcm",1878 }, { "D_CLUNIE_MR3_JPLL.dcm",9570 }, { "D_CLUNIE_MR3_JPLY.dcm",9658 }, { "D_CLUNIE_MR3_RLE.dcm",9504 }, { "D_CLUNIE_MR4_JPLL.dcm",1968 }, { "D_CLUNIE_MR4_JPLY.dcm",2056 }, { "D_CLUNIE_MR4_RLE.dcm",1900 }, { "D_CLUNIE_NM1_JPLL.dcm",2890 }, { "D_CLUNIE_NM1_JPLY.dcm",2978 }, { "D_CLUNIE_NM1_RLE.dcm",2826 }, { "D_CLUNIE_RG1_JPLL.dcm",1858 }, { "D_CLUNIE_RG1_RLE.dcm",1794 }, { "D_CLUNIE_RG2_JPLL.dcm",1444 }, { "D_CLUNIE_RG2_JPLY.dcm",1532 }, { "D_CLUNIE_RG2_RLE.dcm",1368 }, { "D_CLUNIE_RG3_JPLL.dcm",1514 }, { "D_CLUNIE_RG3_JPLY.dcm",1602 }, { "D_CLUNIE_RG3_RLE.dcm",1432 }, { "D_CLUNIE_SC1_JPLY.dcm",1340 }, { "D_CLUNIE_SC1_RLE.dcm",1176 }, { "D_CLUNIE_US1_RLE.dcm",1306 }, { "D_CLUNIE_VL1_RLE.dcm",1188 }, { "D_CLUNIE_VL2_RLE.dcm",1186 }, { "D_CLUNIE_VL3_RLE.dcm",1198 }, { "D_CLUNIE_VL4_RLE.dcm",1180 }, { "D_CLUNIE_VL6_RLE.dcm",1198 }, { "D_CLUNIE_XA1_JPLL.dcm",1192 }, { "D_CLUNIE_XA1_JPLY.dcm",1280 }, { "D_CLUNIE_XA1_RLE.dcm",1116 }, { "DermaColorLossLess.dcm",928 }, { "ELSCINT1_JP2vsJ2K.dcm",1808 }, { "ELSCINT1_PMSCT_RLE1.dcm",67912 }, { "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm",9534 }, { "FUJI-10-MONO1-ACR_NEMA_2.dcm",854 }, { "GDCMJ2K_TextGBR.dcm",758 }, { "GE_CT_With_Private_compressed-icon.dcm",10798 }, { "GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm",14126 }, { "GE_DLX-8-MONO2-Multiframe.dcm",4976 }, { "GE_DLX-8-MONO2-PrivateSyntax.dcm",2912 }, { "GE_GENESIS-16-MONO2-Uncompressed-UnusualVR.dcm",9654 }, { "GE_GENESIS-16-MONO2-WrongLengthItem.dcm",1922 }, { "GE_LOGIQBook-8-RGB-HugePreview.dcm",935596 }, { "GE_MR_0025xx1bProtocolDataBlock.dcm",11870 }, { "GE_RHAPSODE-16-MONO2-JPEG-Fragments.dcm",6456 }, { "IM-0001-0066.CommandTag00.dcm",3042 }, { "ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm",1132 }, { "JDDICOM_Sample2-dcmdjpeg.dcm",836 }, { "JDDICOM_Sample2.dcm",822 }, { "JPEGDefinedLengthSequenceOfFragments.dcm",2862 }, { "JPEG_LossyYBR.dcm",2366 }, { "KODAK-12-MONO1-Odd_Terminated_Sequence.dcm",9126 }, { "KODAK_CompressedIcon.dcm",8634 }, { "LEADTOOLS_FLOWERS-16-MONO2-JpegLossless.dcm",1932 }, { "LEADTOOLS_FLOWERS-16-MONO2-RLE.dcm",1930 }, { "LEADTOOLS_FLOWERS-16-MONO2-Uncompressed.dcm",1930 }, { "LEADTOOLS_FLOWERS-24-RGB-JpegLossless.dcm",1924 }, { "LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm",1924 }, { "LEADTOOLS_FLOWERS-24-RGB-Uncompressed.dcm",1922 }, { "LEADTOOLS_FLOWERS-8-MONO2-JpegLossy.dcm",1932 }, { "LEADTOOLS_FLOWERS-8-MONO2-RLE.dcm",1930 }, { "LEADTOOLS_FLOWERS-8-MONO2-Uncompressed.dcm",1930 }, { "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm",3526 }, { "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm",3526 }, { "LIBIDO-24-ACR_NEMA-Rectangle.dcm",174 }, { "LJPEG_BuginGDCM12.dcm",2236 }, { "MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm",1904 }, { "MAROTECH_CT_JP2Lossy.dcm",33844 }, { "MEDILABInvalidCP246_EVRLESQasUN.dcm",19162 }, { "MR-Brucker-CineTagging-NonSquarePixels.dcm",1530 }, { "MR-MONO2-12-shoulder.dcm",1568 }, { "MR-MONO2-16-head.dcm",1796 }, { "MR-MONO2-8-16x-heart.dcm",908 }, { "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm",42600 }, { "MR-SIEMENS-DICOM-WithOverlays.dcm",42404 }, { "MR16BitsAllocated_8BitsStored.dcm",928 }, { "MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm",7696 }, { "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm",20700 }, { "MR_Philips-Intera_BreaksNOSHADOW.dcm",7618 }, { "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm",9500 }, { "MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm",7512 }, { "MR_Philips_Intera_PrivateSequenceImplicitVR.dcm",7018 }, { "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm",9264 }, { "MR_SIEMENS_forceLoad29-1010_29-1020.dcm",60556 }, { "MR_Spectroscopy_SIEMENS_OF.dcm",2102344 }, { "NM-MONO2-16-13x-heart.dcm",1222 }, { "NM-PAL-16-PixRep1.dcm",4432 }, { "NM_Kakadu44_SOTmarkerincons.dcm",1564 }, { "OT-MONO2-8-a7.dcm",430 }, { "OT-PAL-8-face.dcm",1646 }, { "OsirixFake16BitsStoredFakeSpacing.dcm",1306 }, { "PHILIPS_Brilliance_ExtraBytesInOverlay.dcm",34538 }, { "PHILIPS_GDCM12xBug.dcm",9330 }, { "PHILIPS_GDCM12xBug2.dcm",9662 }, { "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm",5944 }, { "PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm",15366 }, { "PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm",6576 }, { "PHILIPS_Intera-16-MONO2-Uncompress.dcm",9264 }, { "PICKER-16-MONO2-Nested_icon.dcm",18220 }, { "PICKER-16-MONO2-No_DicomV3_Preamble.dcm",1398 }, { "PhilipsInteraSeqTermInvLen.dcm",7440 }, { "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm",14964 }, { "RadBWLossLess.dcm",930 }, { "SIEMENS-12-Jpeg_Process_2_4-Lossy-a.dcm",3032 }, { "SIEMENS-MR-RGB-16Bits.dcm",49840 }, { "SIEMENS_CSA2.dcm",104340 }, { "SIEMENS_ImageLocationUN.dcm",6336 }, { "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm",6044 }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm",6422 }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm",6422 }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm",6422 }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm",6422 }, { "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm",5158 }, { "SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm",5148 }, { "SIEMENS_MAGNETOM-12-MONO2-VRUN.dcm",5290 }, { "SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm",105714 }, { "SIEMENS_Sonata-12-MONO2-SQ.dcm",51792 }, { "SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm",25674 }, { "SignedShortLosslessBug.dcm",1772 }, { "TG18-CH-2k-01.dcm",2300 }, { "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm",1831 }, { "TOSHIBA_J2K_OpenJPEGv2Regression.dcm",2350 }, { "TOSHIBA_J2K_SIZ0_PixRep1.dcm",2334 }, { "TOSHIBA_J2K_SIZ1_PixRep0.dcm",2350 }, { "TOSHIBA_MRT150-16-MONO2-ACR_NEMA_2.dcm",1122 }, { "TheralysGDCM120Bug.dcm",8438 }, { "US-GE-4AICL142.dcm",14060 }, { "US-IRAD-NoPreambleStartWith0003.dcm",3322 }, { "US-IRAD-NoPreambleStartWith0005.dcm",2482 }, { "US-MONO2-8-8x-execho.dcm",964 }, { "US-PAL-8-10x-echo.dcm",2416 }, { "US-RGB-8-epicard.dcm",1000 }, { "US-RGB-8-esopecho.dcm",892 }, { "UnexpectedSequenceDelimiterInFixedLengthSequence.dcm",4178 }, { "XA-MONO2-8-12x-catheter.dcm",994 }, { "fffc0000UN.dcm",1142 }, { "gdcm-CR-DCMTK-16-NonSamplePerPix.dcm",728 }, { "gdcm-JPEG-Extended.dcm",2934 }, { "gdcm-JPEG-LossLess3a.dcm",2528 }, { "gdcm-JPEG-LossLessThoravision.dcm",3132 }, { "gdcm-MR-PHILIPS-16-Multi-Seq.dcm",35834 }, { "gdcm-MR-PHILIPS-16-NonSquarePixels.dcm",4998 }, { "gdcm-US-ALOKA-16.dcm",258732 }, { "rle16loo.dcm",394214 }, { "rle16sti.dcm",394158 }, { "simpleImageWithIcon.dcm",17466 }, { "undefined_length_un_vr.dcm",9156 }, { "JPEGInvalidSecondFrag.dcm",4788 }, { "lena512_rot90.j2k.dcm",756 }, { "ELSCINT1_PMSCT_RLE1_priv.dcm",298002 }, { "00191113.dcm",922 }, { "SIEMENS_SYNGO-12-MONO2-LUTWrongLength512.dcm", 48714 }, { "JPEGNote_empty.dcm", 704 }, { "JPEGLS_CharLS_10742.dcm", 748 }, { "JPEGLosslessYBR_FULL_422.dcm", 802 }, { "JPEGNote_missing.dcm", 596 }, { "JPEGNote_bogus.dcm", 722 }, { "RLEDebianBug816607Orig.dcm", 768 }, { "IllegalGroup2ImplicitTS.dcm", 2264 }, { "JPEG_LS_InvalidEscapeSequence_COM_padding.dcm", 752 }, { "LengthOfItemLarger.dcm", 12748 }, { "GE_MR_0025xx1bProtocolDataBlockXML.dcm",6462 }, { "EmptyIcon_Bug417.dcm",4470}, { "EnhancedWithIPPPerFrameIOPShared.dcm",23212}, { "FUJI-ffff-MONO1-J2K.dcm",2040}, { "JPEGLosslessSeNonZero.dcm",748}, { "US-YBR_FULL_422-EVRLE.dcm",1542}, { "Osirix10vs8BitsStored.dcm",73966}, { "Bug_Siemens_PrivateIconNoItem.dcm",12966}, { "HardcopyColor_YBR_RCT_J2K_PC1.dcm",2614}, { "PET-GE-dicomwrite-PixelDataSQUNv2.dcm",7706}, { "dicomdir_Acusson_WithPrivate_WithSR",3826 }, { "dicomdir_Pms_WithVisit_WithPrivate_WithStudyComponents",37218 }, { "dicomdir_Pms_With_heavy_embedded_sequence",3003414 }, { "dicomdir_With_embedded_icons",7125212 }, { "DICOMDIR",1112434 }, { "DICOMDIR-Philips-EasyVision-4200-Entries",1297194 }, { "DICOMDIR_MR_B_VA12A",14853880 }, /* Stopping condition */ { nullptr ,0 }, }; GDCM-3.0.10/Testing/Source/Data/gdcmStreamOffsetDataFiles.cxx000066400000000000000000000241311412732066400235770ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * See TestReaderUpToTag */ struct StreamOffset { const char *filename; std::streamoff offset; }; static const StreamOffset gdcmStreamOffsetDataFiles[] = { { "00191113.dcm",934 }, { "012345.002.050.dcm",9604 }, { "05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm",41948 }, { "05148044-mr-siemens-avanto-syngo.dcm",55884 }, { "3E768EB7.dcm",3234 }, { "ACUSON-24-YBR_FULL-RLE-b.dcm",2032 }, { "ACUSON-24-YBR_FULL-RLE.dcm",1920 }, { "ALOKA_SSD-8-MONO2-RLE-SQ.dcm",1398 }, { "AMIInvalidPrivateDefinedLengthSQasUN.dcm", 12744 }, { "BugGDCM2_UndefItemWrongVL.dcm",9570 }, { "CR-MONO1-10-chest.dcm",776 }, { "CT-MONO2-12-lomb-an2.acr",1230 }, { "CT-MONO2-16-ankle.dcm",1148 }, { "CT-MONO2-16-brain.dcm",1680 }, { "CT-MONO2-16-chest.dcm",1638 }, { "CT-MONO2-16-ort.dcm",1674 }, { "CT-MONO2-8-abdo.dcm",796 }, { "CT-SIEMENS-Icone-With-PaletteColor.dcm",8162 }, { "CT-SIEMENS-MissingPixelDataInIconSQ.dcm",20504 }, { "CT_16b_signed-UsedBits13.dcm",2582 }, { "DCMTK_JPEGExt_12Bits.dcm",796 }, { "DICOMDIR",1112434 }, { "DICOMDIR-Philips-EasyVision-4200-Entries",1297194 }, { "DICOMDIR_MR_B_VA12A", 14853880}, { "DMCPACS_ExplicitImplicit_BogusIOP.dcm",66618 }, { "DX_GE_FALCON_SNOWY-VOI.dcm",104014 }, { "DX_J2K_0Padding.dcm",1494 }, { "D_CLUNIE_CT1_J2KI.dcm",6596 }, { "D_CLUNIE_CT1_J2KR.dcm",6496 }, { "D_CLUNIE_CT1_JLSL.dcm", 6464 }, { "D_CLUNIE_CT1_JLSN.dcm", 6578 }, { "D_CLUNIE_CT1_JPLL.dcm",6468 }, { "D_CLUNIE_CT1_RLE.dcm",6402 }, { "D_CLUNIE_CT2_JPLL.dcm",1756 }, { "D_CLUNIE_CT2_RLE.dcm",1688 }, { "D_CLUNIE_MR1_JPLL.dcm",1762 }, { "D_CLUNIE_MR1_JPLY.dcm",1848 }, { "D_CLUNIE_MR1_RLE.dcm",1694 }, { "D_CLUNIE_MR2_JPLL.dcm",1958 }, { "D_CLUNIE_MR2_JPLY.dcm",2046 }, { "D_CLUNIE_MR2_RLE.dcm",1890 }, { "D_CLUNIE_MR3_JPLL.dcm",9582 }, { "D_CLUNIE_MR3_JPLY.dcm",9670 }, { "D_CLUNIE_MR3_RLE.dcm",9516 }, { "D_CLUNIE_MR4_JPLL.dcm",1980 }, { "D_CLUNIE_MR4_JPLY.dcm",2068 }, { "D_CLUNIE_MR4_RLE.dcm",1912 }, { "D_CLUNIE_NM1_JPLL.dcm",2902 }, { "D_CLUNIE_NM1_JPLY.dcm",2990 }, { "D_CLUNIE_NM1_RLE.dcm",2838 }, { "D_CLUNIE_RG1_JPLL.dcm",1870 }, { "D_CLUNIE_RG1_RLE.dcm",1806 }, { "D_CLUNIE_RG2_JPLL.dcm",1456 }, { "D_CLUNIE_RG2_JPLY.dcm",1544 }, { "D_CLUNIE_RG2_RLE.dcm",1380 }, { "D_CLUNIE_RG3_JPLL.dcm",1526 }, { "D_CLUNIE_RG3_JPLY.dcm",1614 }, { "D_CLUNIE_RG3_RLE.dcm",1444 }, { "D_CLUNIE_SC1_JPLY.dcm",1352 }, { "D_CLUNIE_SC1_RLE.dcm",1188 }, { "D_CLUNIE_US1_RLE.dcm",1318 }, { "D_CLUNIE_VL1_RLE.dcm",1200 }, { "D_CLUNIE_VL2_RLE.dcm",1198 }, { "D_CLUNIE_VL3_RLE.dcm",1210 }, { "D_CLUNIE_VL4_RLE.dcm",1192 }, { "D_CLUNIE_VL6_RLE.dcm",1210 }, { "D_CLUNIE_XA1_JPLL.dcm",1204 }, { "D_CLUNIE_XA1_JPLY.dcm",1292 }, { "D_CLUNIE_XA1_RLE.dcm",1128 }, { "DermaColorLossLess.dcm",940 }, { "ELSCINT1_JP2vsJ2K.dcm",1820 }, { "ELSCINT1_PMSCT_RLE1.dcm",67912 }, { "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm",9546 }, { "FUJI-10-MONO1-ACR_NEMA_2.dcm",862 }, { "GE_CT_With_Private_compressed-icon.dcm",10810 }, { "GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm",14138 }, { "GE_DLX-8-MONO2-Multiframe.dcm",4984 }, { "GE_DLX-8-MONO2-PrivateSyntax.dcm",2920 }, { "GE_GENESIS-16-MONO2-Uncompressed-UnusualVR.dcm",9666 }, { "GE_GENESIS-16-MONO2-WrongLengthItem.dcm",1930 }, { "GE_LOGIQBook-8-RGB-HugePreview.dcm",935608 }, { "GE_MR_0025xx1bProtocolDataBlock.dcm",11882 }, { "GE_RHAPSODE-16-MONO2-JPEG-Fragments.dcm",6468 }, { "ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm",1144 }, { "JDDICOM_Sample2-dcmdjpeg.dcm",848 }, { "JDDICOM_Sample2.dcm",834 }, { "JPEGDefinedLengthSequenceOfFragments.dcm",2874 }, { "JPEG_LossyYBR.dcm",2378 }, { "KODAK-12-MONO1-Odd_Terminated_Sequence.dcm",9134 }, { "KODAK_CompressedIcon.dcm",8646 }, { "LEADTOOLS_FLOWERS-16-MONO2-JpegLossless.dcm",1944 }, { "LEADTOOLS_FLOWERS-16-MONO2-RLE.dcm",1942 }, { "LEADTOOLS_FLOWERS-16-MONO2-Uncompressed.dcm",1942 }, { "LEADTOOLS_FLOWERS-24-RGB-JpegLossless.dcm",1936 }, { "LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm",1936 }, { "LEADTOOLS_FLOWERS-24-RGB-Uncompressed.dcm",1934 }, { "LEADTOOLS_FLOWERS-8-MONO2-JpegLossy.dcm",1944 }, { "LEADTOOLS_FLOWERS-8-MONO2-RLE.dcm",1942 }, { "LEADTOOLS_FLOWERS-8-MONO2-Uncompressed.dcm",1942 }, { "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm",3538 }, { "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm",3538 }, { "LIBIDO-8-ACR_NEMA-Lena_128_128.acr",182 }, { "LJPEG_BuginGDCM12.dcm",2248 }, { "MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm",1916 }, { "MAROTECH_CT_JP2Lossy.dcm",33856 }, { "MR-Brucker-CineTagging-NonSquarePixels.dcm",1542 }, { "MR-MONO2-12-an2.acr",1866 }, { "MR-MONO2-12-angio-an1.acr",650 }, { "MR-MONO2-12-shoulder.dcm",1580 }, { "MR-MONO2-16-head.dcm",1804 }, { "MR-MONO2-8-16x-heart.dcm",920 }, { "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm", 42612 }, { "MR-SIEMENS-DICOM-WithOverlays.dcm",42416 }, { "MR16BitsAllocated_8BitsStored.dcm",940 }, { "MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm",7704 }, { "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm",20712 }, { "MR_Philips-Intera_BreaksNOSHADOW.dcm",7626 }, { "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm",9508 }, { "MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm",7524 }, { "MR_Philips_Intera_PrivateSequenceImplicitVR.dcm",7026 }, { "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm",9276 }, { "MR_SIEMENS_forceLoad29-1010_29-1020.dcm",60564 }, { "MR_Spectroscopy_SIEMENS_OF.dcm",2102344 }, { "NM-MONO2-16-13x-heart.dcm",1234 }, { "OT-MONO2-8-a7.dcm",438 }, { "OT-PAL-8-face.dcm",1654 }, { "OsirixFake16BitsStoredFakeSpacing.dcm",1318 }, { "PHILIPS_Brilliance_ExtraBytesInOverlay.dcm",34550 }, { "PHILIPS_GDCM12xBug.dcm",9338 }, { "PHILIPS_GDCM12xBug2.dcm",9670 }, { "PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm",15378 }, { "PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm", 6584 }, { "PHILIPS_Intera-16-MONO2-Uncompress.dcm",9276 }, { "PICKER-16-MONO2-Nested_icon.dcm",18228 }, { "PICKER-16-MONO2-No_DicomV3_Preamble.dcm",1406 }, { "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm",14972 }, { "RadBWLossLess.dcm",942 }, { "SIEMENS-12-Jpeg_Process_2_4-Lossy-a.dcm",3044 }, { "SIEMENS-MR-RGB-16Bits.dcm",49852 }, { "SIEMENS_CSA2.dcm",104352 }, { "SIEMENS_ImageLocationUN.dcm",6348 }, { "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm",6052 }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm",6430 }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm",6430 }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm",6430 }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm",6430 }, { "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm",5170 }, { "SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm",5160 }, { "SIEMENS_MAGNETOM-12-MONO2-VRUN.dcm",5302 }, { "SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm",105726 }, { "SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs.acr",5064 }, { "SIEMENS_Sonata-12-MONO2-SQ.dcm",51804 }, { "SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm",25686 }, { "SignedShortLosslessBug.dcm",1784 }, { "TG18-CH-2k-01.dcm",2308 }, { "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm",1839 }, { "TOSHIBA_MRT150-16-MONO2-ACR_NEMA_2.dcm",1130 }, { "TheralysGDCM120Bug.dcm",8450 }, { "US-GE-4AICL142.dcm",14072 }, { "US-IRAD-NoPreambleStartWith0003.dcm",3330 }, { "US-IRAD-NoPreambleStartWith0005.dcm",2490 }, { "US-MONO2-8-8x-execho.dcm",976 }, { "US-PAL-8-10x-echo.dcm",2428 }, { "US-RGB-8-epicard.dcm",1012 }, { "US-RGB-8-esopecho.dcm",904 }, { "XA-MONO2-8-12x-catheter.dcm",1006 }, { "dicomdir_Acusson_WithPrivate_WithSR",3826 }, { "dicomdir_Pms_WithVisit_WithPrivate_WithStudyComponents",37218 }, { "dicomdir_Pms_With_heavy_embedded_sequence",3003414 }, { "dicomdir_With_embedded_icons", 7125212 }, { "fffc0000UN.dcm",1154 }, { "gdcm-ACR-LibIDO.acr",182 }, { "gdcm-CR-DCMTK-16-NonSamplePerPix.dcm",740 }, { "gdcm-JPEG-Extended.dcm",2946 }, { "gdcm-JPEG-LossLess3a.dcm",2540 }, { "gdcm-JPEG-LossLessThoravision.dcm",3144 }, { "gdcm-MR-PHILIPS-16-Multi-Seq.dcm",35846 }, { "gdcm-MR-PHILIPS-16-NonSquarePixels.dcm",5010 }, { "gdcm-MR-SIEMENS-16-2.acr",6052 }, { "gdcm-US-ALOKA-16.dcm",258740 }, { "libido1.0-vol.acr",170 }, { "rle16loo.dcm",394226 }, { "rle16sti.dcm",394170 }, { "simpleImageWithIcon.dcm",17478 }, { "test.acr",182 }, { "undefined_length_un_vr.dcm",9168 }, { "IM-0001-0066.CommandTag00.dcm", 3050 }, { "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm", 5956 }, { "UnexpectedSequenceDelimiterInFixedLengthSequence.dcm", 4190 }, { "GDCMJ2K_TextGBR.dcm", 770 }, { "NM_Kakadu44_SOTmarkerincons.dcm", 1576 }, { "PhilipsInteraSeqTermInvLen.dcm", 7452}, { "LIBIDO-24-ACR_NEMA-Rectangle.dcm", 182 }, { "TOSHIBA_J2K_SIZ1_PixRep0.dcm", 2362 }, { "TOSHIBA_J2K_OpenJPEGv2Regression.dcm", 2362 }, { "TOSHIBA_J2K_SIZ0_PixRep1.dcm", 2346 }, { "NM-PAL-16-PixRep1.dcm", 4444 }, { "MEDILABInvalidCP246_EVRLESQasUN.dcm", 19174 }, { "JPEGInvalidSecondFrag.dcm", 4800 }, { "lena512_rot90.j2k.dcm", 768 }, { "ELSCINT1_PMSCT_RLE1_priv.dcm", 298002 }, { "unreadable.dcm", 249230 }, { "SC16BitsAllocated_8BitsStoredJ2K.dcm", 764 }, { "SC16BitsAllocated_8BitsStoredJPEG.dcm", 958 }, { "SIEMENS_SYNGO-12-MONO2-LUTWrongLength512.dcm", 48726 }, { "JPEGNote_empty.dcm", 716 }, { "JPEGLS_CharLS_10742.dcm", 760 }, { "JPEGLosslessYBR_FULL_422.dcm", 814 }, { "JPEGNote_missing.dcm", 608 }, { "JPEGNote_bogus.dcm", 734 }, { "RLEDebianBug816607Orig.dcm", 780 }, { "IllegalGroup2ImplicitTS.dcm", 2272 }, { "JPEG_LS_InvalidEscapeSequence_COM_padding.dcm", 764 }, { "LengthOfItemLarger.dcm", 12748 }, { "GE_MR_0025xx1bProtocolDataBlockXML.dcm",6474 }, { "EmptyIcon_Bug417.dcm",4482 }, { "EnhancedWithIPPPerFrameIOPShared.dcm",23224 }, { "FUJI-ffff-MONO1-J2K.dcm",2052 }, { "JPEGLosslessSeNonZero.dcm",760 }, { "US-YBR_FULL_422-EVRLE.dcm",1554 }, { "Osirix10vs8BitsStored.dcm",73978 }, { "Bug_Siemens_PrivateIconNoItem.dcm",12978 }, { "HardcopyColor_YBR_RCT_J2K_PC1.dcm",2626 }, { "PET-GE-dicomwrite-PixelDataSQUNv2.dcm",7718 }, /* Stopping condition */ { nullptr ,0 }, }; GDCM-3.0.10/Testing/Source/Data/out.bin000066400000000000000000000007311412732066400173420ustar00rootroot000000000000000 *H 01n0j0R0E1 0 UAU10U Some-State1!0U Internet Widgits Pty Ltd mxzQ0  *H .iߨ3 GG{k!ٳ_.S#+mNq :HT;#7ū剋^J9v,JCc/Xq 4f"v}>Lϻq)#;d=Dc>s;J2İK< %\VSj6R9>0@HG߉=;BLsA&Ҟіac 뵘b|CjgaYpPBɩThH L+,9+0K *H 0*H 5q"aӀ(6crU@yuV 9b}z-N |GDCM-3.0.10/Testing/Source/Data/privatekey.pem000066400000000000000000000032171412732066400207310ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA4k5GEgO9mI5K2UuywuGxcO4xJdygQlpvL2IS9XEbXOWBEwJZ x1tccfzCa929DCijlJE6/f5KBzDNPdLpPt3eyUKB3n7mOos7ATWEFCZgE7RWGRBh IfN2R9LDkLT2eaUhXDzsk7L1qmKPP9nSdAXoUB6sj0EmHrQQWIPEZwGcPcvMUhcU pjD/hnmCX6DAWHVCvE7vhbHntNYFwu1Bmau5ZY6Ywk5lQ/ZTfEYcRD1ZmUB2Wkzv 4InvRc1zYbTBpL/Lkft1B9/A7+LzJJRHoNvHaMN5pRF2qFyZW3sb+bh8z8SC0oJN zIbrWZvWM9TEnQ8P+GCw4y68juSvlcLcBsoxCQIDAQABAoIBAQDW1ogewf5TvYHB F+P0rl3NX9K4puJdG41B5lEpQN9BKX+HlEu2vjzc2Z+Y10CJMmtYtybRyX5tpR6y +m8Dh43gcorntoDKQzMYyr1Ag83h5ul1kd8kZAR92tBdp+31PZaWAiB1dwdRYY+s hhUMoC8TIIug07BkpXx/C1iAkT7KSc4D2djWFbEOoAENykycM1Q+0dgumkZAO1C4 ZDjW4y6DBfbdS8+edgr/Qa3LbeF1uB7d23s4slCVs5h+J0IXVe4/LjrpRfXWUCQM 1YJDY3PVgZOhhnrhfUb0e0gMFAKinNPo7L4d5ZTp3pR5d5Rex1luhbv+E/ZTaLBL RZQWWTgBAoGBAPH5ob3RxQa7e+a1HkbfmP/vW5vBr1aa2hxqjU3UnKR6azoKCBgf +LWbkSAZ1dLhjgsL6M3585WvHDzJJuhLX+Rcd38D+eFz+YjOi6o721iiFJ4lNQPj qymWPwDiia+g1diVfo+3I/l9UPvaQdwkGqFtl6Waty1BSOIEC8/WXhlhAoGBAO9s JMVEvhrP26ve3iPcEwBD7CfAxiSgtZAOt8VxIq2p2BzWnRWysrC3vP8CKfuxG1/b 9cFehCQp0Q1PYRzvR/tmP3vcMh0e/mg1eMTLDjp3VFRTvi3OXsdbXNcV4eDfq0GA /Jp0s1nRBSxY7obQEoSBxPOyyn5zssOlC+D8MXCpAoGBAIegEJzxP4q3eQnlyHOX Dg2dnm4d0GYtY0T8H/lYyveRuhoM116WRPOdn2krseKCE/hzE2inyXTDcoNLh6g5 3ySDA2NI2j0YoOuiQTwIUrhKGF5Ponhsmloz4VpgnyW2c0Xy/L4Wu24yZDrVqYZ3 IgoLAC2NG1CdP/mWpPw4PgPhAoGAH4cIGIoC1pkEfk9sxSAXyHMpR9rUvMIE5qFp hbBuNpwk/zcrnE3ZxfeMBbCNQr2Bs0/NvtbpY7G1+6C2Uw8XVX2TYoYOe1M3gRV5 f8CVcRGBo1EbvABu7qWTRid1hR0u+gM4QEaZz3v8yGg1kL8ZkSVdgBHNJHWr1qOH Ous6v3ECgYBVMV9OpGZfqH9VFX+SLcKnGpL9DsrikDKwAvX0xS6VZJd8nqwpMEJW KtiKZqvrHaIlRSGJ6HLNP1wYd4YzHhQg2Y/AWaw1BioUa2ZmI4OS7oDJlTx0qw69 RBbyWY5Cys+DS17xTjp/bqX+DTZESpWuqNuOIQftE/8KETgh4VD9NQ== -----END RSA PRIVATE KEY----- GDCM-3.0.10/Testing/Source/Data/text000066400000000000000000000000441412732066400167450ustar00rootroot000000000000001234567890abcdefghijklmnopqrstuvwxyzGDCM-3.0.10/Testing/Source/DataDictionary/000077500000000000000000000000001412732066400200665ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/DataDictionary/CMakeLists.txt000066400000000000000000000001171412732066400226250ustar00rootroot00000000000000add_subdirectory(Cxx) if(GDCM_WRAP_PYTHON) add_subdirectory(Python) endif() GDCM-3.0.10/Testing/Source/DataDictionary/Cxx/000077500000000000000000000000001412732066400206305ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/DataDictionary/Cxx/CMakeLists.txt000066400000000000000000000016531412732066400233750ustar00rootroot00000000000000# Define the tests for Data Dictionary # DICT set(DICT_TEST_SRCS TestDictEntry.cxx TestDict.cxx TestGlobal.cxx TestUIDs.cxx TestDicts.cxx TestGroupDict.cxx TestTagToType.cxx TestSOPClassUIDToIOD.cxx TestTagKeywords.cxx ) # Add the include paths include_directories( "${GDCM_BINARY_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition" "${GDCM_SOURCE_DIR}/Source/DataDictionary" "${GDCM_SOURCE_DIR}/Source/InformationObjectDefinition" ) create_test_sourcelist(DICTTests gdcmDICTTests.cxx ${DICT_TEST_SRCS} EXTRA_INCLUDE gdcmTestDriver.h ) add_executable(gdcmDICTTests ${DICTTests}) target_link_libraries(gdcmDICTTests gdcmDICT gdcmMSFF) # Loop over files and create executables foreach(name ${DICT_TEST_SRCS}) get_filename_component(testname ${name} NAME_WE) add_test(NAME ${testname} COMMAND gdcmDICTTests ${testname}) endforeach() GDCM-3.0.10/Testing/Source/DataDictionary/Cxx/TestDict.cxx000066400000000000000000000012571412732066400231040ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDict.h" int TestDict(int, char *[]) { gdcm::Dict d; std::cerr << sizeof(d) << std::endl; return 0; } GDCM-3.0.10/Testing/Source/DataDictionary/Cxx/TestDictEntry.cxx000066400000000000000000000030371412732066400241240ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDictEntry.h" #include "gdcmDict.h" int TestDictEntry(int, char *[]) { //gdcm::DictEntry de(0,0,0,0); //std::cout << sizeof(de) << std::endl; //gdcm::PrivateDictEntry pde(0,0,0); //std::cout << sizeof(pde) << std::endl; gdcm::PrivateTag pt1(0,0,"bla"); gdcm::PrivateTag pt2(0,0,"foo"); gdcm::PrivateTag pt3(0,1,"bla"); gdcm::PrivateTag pt4(0,1,"foo"); if( ! (pt1 < pt2) ) { return 1; } if( ! (pt2 < pt3) ) { return 1; } if( ! (pt3 < pt4) ) { return 1; } if( ! (pt1 < pt3) ) { return 1; } if( ! (pt1 < pt4) ) { return 1; } if( ! (pt2 < pt3) ) { return 1; } if( ! (pt2 < pt4) ) { return 1; } if( pt4 < pt3 ) { return 1; } if( pt4 < pt2 ) { return 1; } if( pt4 < pt1 ) { return 1; } if( pt3 < pt2 ) { return 1; } if( pt3 < pt1 ) { return 1; } if( pt2 < pt1 ) { return 1; } return 0; } GDCM-3.0.10/Testing/Source/DataDictionary/Cxx/TestDicts.cxx000066400000000000000000000034101412732066400232600ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDicts.h" #include "gdcmGlobal.h" #include "gdcmDict.h" #include int TestDicts(int, char *[]) { gdcm::Dicts dicts; //const gdcm::Dict &d = dicts.GetPublicDict(); //std::cout << d << std::endl; const gdcm::Global& g = gdcm::GlobalInstance; // get the Part 6 dicts from it: const gdcm::Dicts &ds = g.GetDicts(); const gdcm::Dict &pub = ds.GetPublicDict(); gdcm::Dict::ConstIterator it = pub.Begin(); int ret = 0; std::set names; for( ; it != pub.End(); ++it) { const gdcm::Tag &t = it->first; const gdcm::DictEntry &de = it->second; // A couple of tests: if( t.GetElement() == 0x0 ) { // Check group length if( de.GetVR() != gdcm::VR::UL || de.GetVM() != gdcm::VM::VM1 ) { std::cerr << "Group length issue: Problem with tag: " << t << " " << de << std::endl; ++ret; } } // I need a test that check there is no duplicate name for data elements since python-gdcm // will rely on it if( names.count( de.GetName() ) != 0 ) { //std::cerr << "Name issue: Problem with tag: " << t << " " << de << std::endl; //++ret; } names.insert( de.GetName() ); } return ret; } GDCM-3.0.10/Testing/Source/DataDictionary/Cxx/TestGlobal.cxx000066400000000000000000000063171412732066400234230ustar00rootroot00000000000000/*========================================================================= 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 "gdcmGlobal.h" #include "gdcmDicts.h" #include "gdcmDict.h" #include "gdcmDefs.h" int TestGlobal(int, char *[]) { // case 1 // Get the global singleton: gdcm::Trace::DebugOn(); gdcm::Global& g = gdcm::Global::GetInstance(); if( !g.LoadResourcesFiles() ) { std::cerr << "Could not LoadResourcesFiles" << std::endl; return 1; } gdcm::Trace::DebugOff(); // get the Part 6 dicts from it: const gdcm::Dicts &ds = g.GetDicts(); const gdcm::Dict &pub = ds.GetPublicDict(); const gdcm::PrivateDict &priv = ds.GetPrivateDict(); // case 2 gdcm::Dicts dicts; const gdcm::Dict &d1 = dicts.GetPublicDict(); // case 3 gdcm::Dict d2; // This one will be empty: std::cout << "Empty dict:" << std::endl; std::cout << d1 << std::endl; if( !d1.IsEmpty() ) { return 1; } // This one will be empty: std::cout << "Empty dict:" << std::endl; std::cout << d2 << std::endl; if( !d2.IsEmpty() ) { return 1; } // This should should be filled in: std::cout << "Global pub dict:" << std::endl; //std::cout << pub << std::endl; if( pub.IsEmpty() ) { return 1; } // This should should be filled in: std::cout << "Global priv dict:" << std::endl; //std::cout << priv << std::endl; if( priv.IsEmpty() ) { return 1; } #if 0 // FIXME I do not understand what was wrong before... // I had to change the PrivateTag to use lower case to support this: const gdcm::DictEntry& de1 = priv.GetDictEntry( gdcm::PrivateTag(0x2001,0x0001,"Philips Imaging DD 001") ); std::cout << de1 << std::endl; const gdcm::DictEntry& de2 = priv.GetDictEntry( gdcm::PrivateTag(0x2001,0x0001,"PHILIPS IMAGING DD 001") ); std::cout << de2 << std::endl; if( &de1 != &de2 ) { return 1; } const gdcm::DictEntry& de3 = priv.GetDictEntry( gdcm::PrivateTag(0x2001,0x0003,"Philips Imaging DD 001") ); std::cout << de3 << std::endl; const gdcm::DictEntry& de4 = priv.GetDictEntry( gdcm::PrivateTag(0x2001,0x0003,"PHILIPS IMAGING DD 001") ); std::cout << de4 << std::endl; if( &de4 != &de3 ) { return 1; } #endif #if 0 const char *empty = ""; std::string s = empty; std::cout << s.empty() << std::endl; const gdcm::DictEntry& de = pub.GetDictEntry( gdcm::Tag(0x0028,0x0015) ); const char *v = de.GetName(); //assert( v ); std::cout << "TOTO:" << de << std::endl; #endif const gdcm::Defs &defs = g.GetDefs(); const gdcm::Modules &modules = defs.GetModules(); std::cout << modules << std::endl; const gdcm::Macros ¯os = defs.GetMacros(); std::cout << macros << std::endl; const gdcm::IODs &iods = defs.GetIODs(); std::cout << iods << std::endl; return 0; } GDCM-3.0.10/Testing/Source/DataDictionary/Cxx/TestGroupDict.cxx000066400000000000000000000013161412732066400241150ustar00rootroot00000000000000/*========================================================================= 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 "gdcmGroupDict.h" #include int TestGroupDict(int , char *[]) { gdcm::GroupDict gd; std::cout << gd << std::endl; return 0; } GDCM-3.0.10/Testing/Source/DataDictionary/Cxx/TestSOPClassUIDToIOD.cxx000066400000000000000000000031411412732066400250430ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSOPClassUIDToIOD.h" #include int TestSOPClassUIDToIOD(int, char *[]) { gdcm::SOPClassUIDToIOD::SOPClassUIDToIODType& s = gdcm::SOPClassUIDToIOD::GetSOPClassUIDToIOD(0); std::cout << s[0] << std::endl; if( std::string(s[0] ) != "1.2.840.10008.1.3.10" ) return 1; std::cout << s[1] << std::endl; if( std::string(s[1] ) != "Basic Directory IOD Modules" ) return 1; // points to { nullptr, nullptr }, hardcoded gdcm::SOPClassUIDToIOD::SOPClassUIDToIODType& s2 = gdcm::SOPClassUIDToIOD::GetSOPClassUIDToIOD(107); std::cout << ( s2[0] == nullptr ) << std::endl; if( !(s2[0] == nullptr) ) { std::cerr << s2[1] << std::endl; return 1; } if( !(s2[1] == nullptr) ) return 1; const char *sopclassuid = gdcm::SOPClassUIDToIOD::GetSOPClassUIDFromIOD( s[1] ); const char *iod = gdcm::SOPClassUIDToIOD::GetIODFromSOPClassUID( s[0] ); std::cout << sopclassuid << std::endl; std::cout << iod << std::endl; if( std::string(sopclassuid) != s[0] ) return 1; if( std::string(iod) != s[1] ) return 1; return 0; } GDCM-3.0.10/Testing/Source/DataDictionary/Cxx/TestTagKeywords.cxx000066400000000000000000000013741412732066400244640ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTagKeywords.h" int TestTagKeywords(int, char *[]) { gdcm::Keywords::FileMetaInformationVersion at1; (void)at1; if( at1.GetTag() != gdcm::Tag( 0x2, 0x1 ) ) return 1; return 0; } GDCM-3.0.10/Testing/Source/DataDictionary/Cxx/TestTagToType.cxx000066400000000000000000004742521412732066400241120ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc TestTagToType.xsl DICOMV3.xml > TestTagToType.cxx /*========================================================================= 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 "gdcmTagToType.h" int TestTagToType(int, char *[]) { gdcm::TagToType<0x0000,0x0000> x00000000; (void)x00000000; gdcm::TagToType<0x0000,0x0001> x00000001; (void)x00000001; gdcm::TagToType<0x0000,0x0002> x00000002; (void)x00000002; gdcm::TagToType<0x0000,0x0003> x00000003; (void)x00000003; gdcm::TagToType<0x0000,0x0010> x00000010; (void)x00000010; gdcm::TagToType<0x0000,0x0100> x00000100; (void)x00000100; gdcm::TagToType<0x0000,0x0110> x00000110; (void)x00000110; gdcm::TagToType<0x0000,0x0120> x00000120; (void)x00000120; gdcm::TagToType<0x0000,0x0200> x00000200; (void)x00000200; gdcm::TagToType<0x0000,0x0300> x00000300; (void)x00000300; gdcm::TagToType<0x0000,0x0400> x00000400; (void)x00000400; gdcm::TagToType<0x0000,0x0600> x00000600; (void)x00000600; gdcm::TagToType<0x0000,0x0700> x00000700; (void)x00000700; gdcm::TagToType<0x0000,0x0800> x00000800; (void)x00000800; gdcm::TagToType<0x0000,0x0850> x00000850; (void)x00000850; gdcm::TagToType<0x0000,0x0860> x00000860; (void)x00000860; gdcm::TagToType<0x0000,0x0900> x00000900; (void)x00000900; gdcm::TagToType<0x0000,0x0901> x00000901; (void)x00000901; gdcm::TagToType<0x0000,0x0902> x00000902; (void)x00000902; gdcm::TagToType<0x0000,0x0903> x00000903; (void)x00000903; gdcm::TagToType<0x0000,0x1000> x00001000; (void)x00001000; gdcm::TagToType<0x0000,0x1001> x00001001; (void)x00001001; gdcm::TagToType<0x0000,0x1002> x00001002; (void)x00001002; gdcm::TagToType<0x0000,0x1005> x00001005; (void)x00001005; gdcm::TagToType<0x0000,0x1008> x00001008; (void)x00001008; gdcm::TagToType<0x0000,0x1020> x00001020; (void)x00001020; gdcm::TagToType<0x0000,0x1021> x00001021; (void)x00001021; gdcm::TagToType<0x0000,0x1022> x00001022; (void)x00001022; gdcm::TagToType<0x0000,0x1023> x00001023; (void)x00001023; gdcm::TagToType<0x0000,0x1030> x00001030; (void)x00001030; gdcm::TagToType<0x0000,0x1031> x00001031; (void)x00001031; gdcm::TagToType<0x0000,0x4000> x00004000; (void)x00004000; gdcm::TagToType<0x0000,0x4010> x00004010; (void)x00004010; gdcm::TagToType<0x0000,0x5010> x00005010; (void)x00005010; gdcm::TagToType<0x0000,0x5020> x00005020; (void)x00005020; gdcm::TagToType<0x0000,0x5110> x00005110; (void)x00005110; gdcm::TagToType<0x0000,0x5120> x00005120; (void)x00005120; gdcm::TagToType<0x0000,0x5130> x00005130; (void)x00005130; gdcm::TagToType<0x0000,0x5140> x00005140; (void)x00005140; gdcm::TagToType<0x0000,0x5150> x00005150; (void)x00005150; gdcm::TagToType<0x0000,0x5160> x00005160; (void)x00005160; gdcm::TagToType<0x0000,0x5170> x00005170; (void)x00005170; gdcm::TagToType<0x0000,0x5180> x00005180; (void)x00005180; gdcm::TagToType<0x0000,0x5190> x00005190; (void)x00005190; gdcm::TagToType<0x0000,0x51a0> x000051a0; (void)x000051a0; gdcm::TagToType<0x0000,0x51b0> x000051b0; (void)x000051b0; gdcm::TagToType<0x0002,0x0000> x00020000; (void)x00020000; gdcm::TagToType<0x0002,0x0001> x00020001; (void)x00020001; gdcm::TagToType<0x0002,0x0002> x00020002; (void)x00020002; gdcm::TagToType<0x0002,0x0003> x00020003; (void)x00020003; gdcm::TagToType<0x0002,0x0010> x00020010; (void)x00020010; gdcm::TagToType<0x0002,0x0012> x00020012; (void)x00020012; gdcm::TagToType<0x0002,0x0013> x00020013; (void)x00020013; gdcm::TagToType<0x0002,0x0016> x00020016; (void)x00020016; gdcm::TagToType<0x0002,0x0100> x00020100; (void)x00020100; gdcm::TagToType<0x0002,0x0102> x00020102; (void)x00020102; gdcm::TagToType<0x0004,0x1130> x00041130; (void)x00041130; gdcm::TagToType<0x0004,0x1141> x00041141; (void)x00041141; gdcm::TagToType<0x0004,0x1142> x00041142; (void)x00041142; gdcm::TagToType<0x0004,0x1200> x00041200; (void)x00041200; gdcm::TagToType<0x0004,0x1202> x00041202; (void)x00041202; gdcm::TagToType<0x0004,0x1212> x00041212; (void)x00041212; gdcm::TagToType<0x0004,0x1220> x00041220; (void)x00041220; gdcm::TagToType<0x0004,0x1400> x00041400; (void)x00041400; gdcm::TagToType<0x0004,0x1410> x00041410; (void)x00041410; gdcm::TagToType<0x0004,0x1420> x00041420; (void)x00041420; gdcm::TagToType<0x0004,0x1430> x00041430; (void)x00041430; gdcm::TagToType<0x0004,0x1432> x00041432; (void)x00041432; gdcm::TagToType<0x0004,0x1500> x00041500; (void)x00041500; gdcm::TagToType<0x0004,0x1504> x00041504; (void)x00041504; gdcm::TagToType<0x0004,0x1510> x00041510; (void)x00041510; gdcm::TagToType<0x0004,0x1511> x00041511; (void)x00041511; gdcm::TagToType<0x0004,0x1512> x00041512; (void)x00041512; gdcm::TagToType<0x0004,0x151a> x0004151a; (void)x0004151a; gdcm::TagToType<0x0004,0x1600> x00041600; (void)x00041600; gdcm::TagToType<0x0008,0x0001> x00080001; (void)x00080001; gdcm::TagToType<0x0008,0x0005> x00080005; (void)x00080005; gdcm::TagToType<0x0008,0x0008> x00080008; (void)x00080008; gdcm::TagToType<0x0008,0x0010> x00080010; (void)x00080010; gdcm::TagToType<0x0008,0x0012> x00080012; (void)x00080012; gdcm::TagToType<0x0008,0x0013> x00080013; (void)x00080013; gdcm::TagToType<0x0008,0x0014> x00080014; (void)x00080014; gdcm::TagToType<0x0008,0x0016> x00080016; (void)x00080016; gdcm::TagToType<0x0008,0x0018> x00080018; (void)x00080018; gdcm::TagToType<0x0008,0x001a> x0008001a; (void)x0008001a; gdcm::TagToType<0x0008,0x001b> x0008001b; (void)x0008001b; gdcm::TagToType<0x0008,0x0020> x00080020; (void)x00080020; gdcm::TagToType<0x0008,0x0021> x00080021; (void)x00080021; gdcm::TagToType<0x0008,0x0022> x00080022; (void)x00080022; gdcm::TagToType<0x0008,0x0023> x00080023; (void)x00080023; gdcm::TagToType<0x0008,0x0024> x00080024; (void)x00080024; gdcm::TagToType<0x0008,0x0025> x00080025; (void)x00080025; gdcm::TagToType<0x0008,0x002a> x0008002a; (void)x0008002a; gdcm::TagToType<0x0008,0x0030> x00080030; (void)x00080030; gdcm::TagToType<0x0008,0x0031> x00080031; (void)x00080031; gdcm::TagToType<0x0008,0x0032> x00080032; (void)x00080032; gdcm::TagToType<0x0008,0x0033> x00080033; (void)x00080033; gdcm::TagToType<0x0008,0x0034> x00080034; (void)x00080034; gdcm::TagToType<0x0008,0x0035> x00080035; (void)x00080035; gdcm::TagToType<0x0008,0x0040> x00080040; (void)x00080040; gdcm::TagToType<0x0008,0x0041> x00080041; (void)x00080041; gdcm::TagToType<0x0008,0x0042> x00080042; (void)x00080042; gdcm::TagToType<0x0008,0x0050> x00080050; (void)x00080050; gdcm::TagToType<0x0008,0x0052> x00080052; (void)x00080052; gdcm::TagToType<0x0008,0x0054> x00080054; (void)x00080054; gdcm::TagToType<0x0008,0x0056> x00080056; (void)x00080056; gdcm::TagToType<0x0008,0x0058> x00080058; (void)x00080058; gdcm::TagToType<0x0008,0x0060> x00080060; (void)x00080060; gdcm::TagToType<0x0008,0x0061> x00080061; (void)x00080061; gdcm::TagToType<0x0008,0x0062> x00080062; (void)x00080062; gdcm::TagToType<0x0008,0x0064> x00080064; (void)x00080064; gdcm::TagToType<0x0008,0x0068> x00080068; (void)x00080068; gdcm::TagToType<0x0008,0x0070> x00080070; (void)x00080070; gdcm::TagToType<0x0008,0x0080> x00080080; (void)x00080080; gdcm::TagToType<0x0008,0x0081> x00080081; (void)x00080081; gdcm::TagToType<0x0008,0x0082> x00080082; (void)x00080082; gdcm::TagToType<0x0008,0x0090> x00080090; (void)x00080090; gdcm::TagToType<0x0008,0x0092> x00080092; (void)x00080092; gdcm::TagToType<0x0008,0x0094> x00080094; (void)x00080094; gdcm::TagToType<0x0008,0x0096> x00080096; (void)x00080096; gdcm::TagToType<0x0008,0x0100> x00080100; (void)x00080100; gdcm::TagToType<0x0008,0x0102> x00080102; (void)x00080102; gdcm::TagToType<0x0008,0x0103> x00080103; (void)x00080103; gdcm::TagToType<0x0008,0x0104> x00080104; (void)x00080104; gdcm::TagToType<0x0008,0x0105> x00080105; (void)x00080105; gdcm::TagToType<0x0008,0x0106> x00080106; (void)x00080106; gdcm::TagToType<0x0008,0x0107> x00080107; (void)x00080107; gdcm::TagToType<0x0008,0x010b> x0008010b; (void)x0008010b; gdcm::TagToType<0x0008,0x010c> x0008010c; (void)x0008010c; gdcm::TagToType<0x0008,0x010d> x0008010d; (void)x0008010d; gdcm::TagToType<0x0008,0x010f> x0008010f; (void)x0008010f; gdcm::TagToType<0x0008,0x0110> x00080110; (void)x00080110; gdcm::TagToType<0x0008,0x0112> x00080112; (void)x00080112; gdcm::TagToType<0x0008,0x0114> x00080114; (void)x00080114; gdcm::TagToType<0x0008,0x0115> x00080115; (void)x00080115; gdcm::TagToType<0x0008,0x0116> x00080116; (void)x00080116; gdcm::TagToType<0x0008,0x0201> x00080201; (void)x00080201; gdcm::TagToType<0x0008,0x1000> x00081000; (void)x00081000; gdcm::TagToType<0x0008,0x1010> x00081010; (void)x00081010; gdcm::TagToType<0x0008,0x1030> x00081030; (void)x00081030; gdcm::TagToType<0x0008,0x1032> x00081032; (void)x00081032; gdcm::TagToType<0x0008,0x103e> x0008103e; (void)x0008103e; gdcm::TagToType<0x0008,0x1040> x00081040; (void)x00081040; gdcm::TagToType<0x0008,0x1048> x00081048; (void)x00081048; gdcm::TagToType<0x0008,0x1049> x00081049; (void)x00081049; gdcm::TagToType<0x0008,0x1050> x00081050; (void)x00081050; gdcm::TagToType<0x0008,0x1052> x00081052; (void)x00081052; gdcm::TagToType<0x0008,0x1060> x00081060; (void)x00081060; gdcm::TagToType<0x0008,0x1062> x00081062; (void)x00081062; gdcm::TagToType<0x0008,0x1070> x00081070; (void)x00081070; gdcm::TagToType<0x0008,0x1072> x00081072; (void)x00081072; gdcm::TagToType<0x0008,0x1080> x00081080; (void)x00081080; gdcm::TagToType<0x0008,0x1084> x00081084; (void)x00081084; gdcm::TagToType<0x0008,0x1090> x00081090; (void)x00081090; gdcm::TagToType<0x0008,0x1100> x00081100; (void)x00081100; gdcm::TagToType<0x0008,0x1110> x00081110; (void)x00081110; gdcm::TagToType<0x0008,0x1111> x00081111; (void)x00081111; gdcm::TagToType<0x0008,0x1115> x00081115; (void)x00081115; gdcm::TagToType<0x0008,0x1120> x00081120; (void)x00081120; gdcm::TagToType<0x0008,0x1125> x00081125; (void)x00081125; gdcm::TagToType<0x0008,0x1130> x00081130; (void)x00081130; gdcm::TagToType<0x0008,0x113a> x0008113a; (void)x0008113a; gdcm::TagToType<0x0008,0x1140> x00081140; (void)x00081140; gdcm::TagToType<0x0008,0x1145> x00081145; (void)x00081145; gdcm::TagToType<0x0008,0x114a> x0008114a; (void)x0008114a; gdcm::TagToType<0x0008,0x114b> x0008114b; (void)x0008114b; gdcm::TagToType<0x0008,0x1150> x00081150; (void)x00081150; gdcm::TagToType<0x0008,0x1155> x00081155; (void)x00081155; gdcm::TagToType<0x0008,0x115a> x0008115a; (void)x0008115a; gdcm::TagToType<0x0008,0x1160> x00081160; (void)x00081160; gdcm::TagToType<0x0008,0x1195> x00081195; (void)x00081195; gdcm::TagToType<0x0008,0x1197> x00081197; (void)x00081197; gdcm::TagToType<0x0008,0x1198> x00081198; (void)x00081198; gdcm::TagToType<0x0008,0x1199> x00081199; (void)x00081199; gdcm::TagToType<0x0008,0x1200> x00081200; (void)x00081200; gdcm::TagToType<0x0008,0x1250> x00081250; (void)x00081250; gdcm::TagToType<0x0008,0x2110> x00082110; (void)x00082110; gdcm::TagToType<0x0008,0x2111> x00082111; (void)x00082111; gdcm::TagToType<0x0008,0x2112> x00082112; (void)x00082112; gdcm::TagToType<0x0008,0x2120> x00082120; (void)x00082120; gdcm::TagToType<0x0008,0x2122> x00082122; (void)x00082122; gdcm::TagToType<0x0008,0x2124> x00082124; (void)x00082124; gdcm::TagToType<0x0008,0x2127> x00082127; (void)x00082127; gdcm::TagToType<0x0008,0x2128> x00082128; (void)x00082128; gdcm::TagToType<0x0008,0x2129> x00082129; (void)x00082129; gdcm::TagToType<0x0008,0x212a> x0008212a; (void)x0008212a; gdcm::TagToType<0x0008,0x2130> x00082130; (void)x00082130; gdcm::TagToType<0x0008,0x2132> x00082132; (void)x00082132; gdcm::TagToType<0x0008,0x2142> x00082142; (void)x00082142; gdcm::TagToType<0x0008,0x2143> x00082143; (void)x00082143; gdcm::TagToType<0x0008,0x2144> x00082144; (void)x00082144; gdcm::TagToType<0x0008,0x2200> x00082200; (void)x00082200; gdcm::TagToType<0x0008,0x2204> x00082204; (void)x00082204; gdcm::TagToType<0x0008,0x2208> x00082208; (void)x00082208; gdcm::TagToType<0x0008,0x2218> x00082218; (void)x00082218; gdcm::TagToType<0x0008,0x2220> x00082220; (void)x00082220; gdcm::TagToType<0x0008,0x2228> x00082228; (void)x00082228; gdcm::TagToType<0x0008,0x2229> x00082229; (void)x00082229; gdcm::TagToType<0x0008,0x2230> x00082230; (void)x00082230; gdcm::TagToType<0x0008,0x2240> x00082240; (void)x00082240; gdcm::TagToType<0x0008,0x2242> x00082242; (void)x00082242; gdcm::TagToType<0x0008,0x2244> x00082244; (void)x00082244; gdcm::TagToType<0x0008,0x2246> x00082246; (void)x00082246; gdcm::TagToType<0x0008,0x2251> x00082251; (void)x00082251; gdcm::TagToType<0x0008,0x2253> x00082253; (void)x00082253; gdcm::TagToType<0x0008,0x2255> x00082255; (void)x00082255; gdcm::TagToType<0x0008,0x2256> x00082256; (void)x00082256; gdcm::TagToType<0x0008,0x2257> x00082257; (void)x00082257; gdcm::TagToType<0x0008,0x2258> x00082258; (void)x00082258; gdcm::TagToType<0x0008,0x2259> x00082259; (void)x00082259; gdcm::TagToType<0x0008,0x225a> x0008225a; (void)x0008225a; gdcm::TagToType<0x0008,0x225c> x0008225c; (void)x0008225c; gdcm::TagToType<0x0008,0x3001> x00083001; (void)x00083001; gdcm::TagToType<0x0008,0x3010> x00083010; (void)x00083010; gdcm::TagToType<0x0008,0x4000> x00084000; (void)x00084000; gdcm::TagToType<0x0008,0x9007> x00089007; (void)x00089007; gdcm::TagToType<0x0008,0x9092> x00089092; (void)x00089092; gdcm::TagToType<0x0008,0x9121> x00089121; (void)x00089121; gdcm::TagToType<0x0008,0x9123> x00089123; (void)x00089123; gdcm::TagToType<0x0008,0x9124> x00089124; (void)x00089124; gdcm::TagToType<0x0008,0x9154> x00089154; (void)x00089154; gdcm::TagToType<0x0008,0x9205> x00089205; (void)x00089205; gdcm::TagToType<0x0008,0x9206> x00089206; (void)x00089206; gdcm::TagToType<0x0008,0x9207> x00089207; (void)x00089207; gdcm::TagToType<0x0008,0x9208> x00089208; (void)x00089208; gdcm::TagToType<0x0008,0x9209> x00089209; (void)x00089209; gdcm::TagToType<0x0008,0x9215> x00089215; (void)x00089215; gdcm::TagToType<0x0008,0x9237> x00089237; (void)x00089237; gdcm::TagToType<0x0008,0x9410> x00089410; (void)x00089410; gdcm::TagToType<0x0008,0x9458> x00089458; (void)x00089458; gdcm::TagToType<0x0008,0x9459> x00089459; (void)x00089459; gdcm::TagToType<0x0008,0x9460> x00089460; (void)x00089460; gdcm::TagToType<0x0010,0x0010> x00100010; (void)x00100010; gdcm::TagToType<0x0010,0x0020> x00100020; (void)x00100020; gdcm::TagToType<0x0010,0x0021> x00100021; (void)x00100021; gdcm::TagToType<0x0010,0x0022> x00100022; (void)x00100022; gdcm::TagToType<0x0010,0x0030> x00100030; (void)x00100030; gdcm::TagToType<0x0010,0x0032> x00100032; (void)x00100032; gdcm::TagToType<0x0010,0x0040> x00100040; (void)x00100040; gdcm::TagToType<0x0010,0x0050> x00100050; (void)x00100050; gdcm::TagToType<0x0010,0x0101> x00100101; (void)x00100101; gdcm::TagToType<0x0010,0x0102> x00100102; (void)x00100102; gdcm::TagToType<0x0010,0x1000> x00101000; (void)x00101000; gdcm::TagToType<0x0010,0x1001> x00101001; (void)x00101001; gdcm::TagToType<0x0010,0x1002> x00101002; (void)x00101002; gdcm::TagToType<0x0010,0x1005> x00101005; (void)x00101005; gdcm::TagToType<0x0010,0x1010> x00101010; (void)x00101010; gdcm::TagToType<0x0010,0x1020> x00101020; (void)x00101020; gdcm::TagToType<0x0010,0x1030> x00101030; (void)x00101030; gdcm::TagToType<0x0010,0x1040> x00101040; (void)x00101040; gdcm::TagToType<0x0010,0x1050> x00101050; (void)x00101050; gdcm::TagToType<0x0010,0x1060> x00101060; (void)x00101060; gdcm::TagToType<0x0010,0x1080> x00101080; (void)x00101080; gdcm::TagToType<0x0010,0x1081> x00101081; (void)x00101081; gdcm::TagToType<0x0010,0x1090> x00101090; (void)x00101090; gdcm::TagToType<0x0010,0x2000> x00102000; (void)x00102000; gdcm::TagToType<0x0010,0x2110> x00102110; (void)x00102110; gdcm::TagToType<0x0010,0x2150> x00102150; (void)x00102150; gdcm::TagToType<0x0010,0x2152> x00102152; (void)x00102152; gdcm::TagToType<0x0010,0x2154> x00102154; (void)x00102154; gdcm::TagToType<0x0010,0x2160> x00102160; (void)x00102160; gdcm::TagToType<0x0010,0x2180> x00102180; (void)x00102180; gdcm::TagToType<0x0010,0x21a0> x001021a0; (void)x001021a0; gdcm::TagToType<0x0010,0x21b0> x001021b0; (void)x001021b0; gdcm::TagToType<0x0010,0x21c0> x001021c0; (void)x001021c0; gdcm::TagToType<0x0010,0x21d0> x001021d0; (void)x001021d0; gdcm::TagToType<0x0010,0x21f0> x001021f0; (void)x001021f0; gdcm::TagToType<0x0010,0x2201> x00102201; (void)x00102201; gdcm::TagToType<0x0010,0x2202> x00102202; (void)x00102202; gdcm::TagToType<0x0010,0x2203> x00102203; (void)x00102203; gdcm::TagToType<0x0010,0x2292> x00102292; (void)x00102292; gdcm::TagToType<0x0010,0x2293> x00102293; (void)x00102293; gdcm::TagToType<0x0010,0x2294> x00102294; (void)x00102294; gdcm::TagToType<0x0010,0x2295> x00102295; (void)x00102295; gdcm::TagToType<0x0010,0x2296> x00102296; (void)x00102296; gdcm::TagToType<0x0010,0x2297> x00102297; (void)x00102297; gdcm::TagToType<0x0010,0x2298> x00102298; (void)x00102298; gdcm::TagToType<0x0010,0x2299> x00102299; (void)x00102299; gdcm::TagToType<0x0010,0x4000> x00104000; (void)x00104000; gdcm::TagToType<0x0010,0x9431> x00109431; (void)x00109431; gdcm::TagToType<0x0012,0x0010> x00120010; (void)x00120010; gdcm::TagToType<0x0012,0x0020> x00120020; (void)x00120020; gdcm::TagToType<0x0012,0x0021> x00120021; (void)x00120021; gdcm::TagToType<0x0012,0x0030> x00120030; (void)x00120030; gdcm::TagToType<0x0012,0x0031> x00120031; (void)x00120031; gdcm::TagToType<0x0012,0x0040> x00120040; (void)x00120040; gdcm::TagToType<0x0012,0x0042> x00120042; (void)x00120042; gdcm::TagToType<0x0012,0x0050> x00120050; (void)x00120050; gdcm::TagToType<0x0012,0x0051> x00120051; (void)x00120051; gdcm::TagToType<0x0012,0x0060> x00120060; (void)x00120060; gdcm::TagToType<0x0012,0x0062> x00120062; (void)x00120062; gdcm::TagToType<0x0012,0x0063> x00120063; (void)x00120063; gdcm::TagToType<0x0012,0x0064> x00120064; (void)x00120064; gdcm::TagToType<0x0012,0x0071> x00120071; (void)x00120071; gdcm::TagToType<0x0012,0x0072> x00120072; (void)x00120072; gdcm::TagToType<0x0018,0x0010> x00180010; (void)x00180010; gdcm::TagToType<0x0018,0x0012> x00180012; (void)x00180012; gdcm::TagToType<0x0018,0x0014> x00180014; (void)x00180014; gdcm::TagToType<0x0018,0x0015> x00180015; (void)x00180015; gdcm::TagToType<0x0018,0x0020> x00180020; (void)x00180020; gdcm::TagToType<0x0018,0x0021> x00180021; (void)x00180021; gdcm::TagToType<0x0018,0x0022> x00180022; (void)x00180022; gdcm::TagToType<0x0018,0x0023> x00180023; (void)x00180023; gdcm::TagToType<0x0018,0x0024> x00180024; (void)x00180024; gdcm::TagToType<0x0018,0x0025> x00180025; (void)x00180025; gdcm::TagToType<0x0018,0x0026> x00180026; (void)x00180026; gdcm::TagToType<0x0018,0x0027> x00180027; (void)x00180027; gdcm::TagToType<0x0018,0x0028> x00180028; (void)x00180028; gdcm::TagToType<0x0018,0x0029> x00180029; (void)x00180029; gdcm::TagToType<0x0018,0x002a> x0018002a; (void)x0018002a; gdcm::TagToType<0x0018,0x0030> x00180030; (void)x00180030; gdcm::TagToType<0x0018,0x0031> x00180031; (void)x00180031; gdcm::TagToType<0x0018,0x0032> x00180032; (void)x00180032; gdcm::TagToType<0x0018,0x0033> x00180033; (void)x00180033; gdcm::TagToType<0x0018,0x0034> x00180034; (void)x00180034; gdcm::TagToType<0x0018,0x0035> x00180035; (void)x00180035; gdcm::TagToType<0x0018,0x0036> x00180036; (void)x00180036; gdcm::TagToType<0x0018,0x0037> x00180037; (void)x00180037; gdcm::TagToType<0x0018,0x0038> x00180038; (void)x00180038; gdcm::TagToType<0x0018,0x0039> x00180039; (void)x00180039; gdcm::TagToType<0x0018,0x003a> x0018003a; (void)x0018003a; gdcm::TagToType<0x0018,0x0040> x00180040; (void)x00180040; gdcm::TagToType<0x0018,0x0050> x00180050; (void)x00180050; gdcm::TagToType<0x0018,0x0060> x00180060; (void)x00180060; gdcm::TagToType<0x0018,0x0070> x00180070; (void)x00180070; gdcm::TagToType<0x0018,0x0071> x00180071; (void)x00180071; gdcm::TagToType<0x0018,0x0072> x00180072; (void)x00180072; gdcm::TagToType<0x0018,0x0073> x00180073; (void)x00180073; gdcm::TagToType<0x0018,0x0074> x00180074; (void)x00180074; gdcm::TagToType<0x0018,0x0075> x00180075; (void)x00180075; gdcm::TagToType<0x0018,0x0080> x00180080; (void)x00180080; gdcm::TagToType<0x0018,0x0081> x00180081; (void)x00180081; gdcm::TagToType<0x0018,0x0082> x00180082; (void)x00180082; gdcm::TagToType<0x0018,0x0083> x00180083; (void)x00180083; gdcm::TagToType<0x0018,0x0084> x00180084; (void)x00180084; gdcm::TagToType<0x0018,0x0085> x00180085; (void)x00180085; gdcm::TagToType<0x0018,0x0086> x00180086; (void)x00180086; gdcm::TagToType<0x0018,0x0087> x00180087; (void)x00180087; gdcm::TagToType<0x0018,0x0088> x00180088; (void)x00180088; gdcm::TagToType<0x0018,0x0089> x00180089; (void)x00180089; gdcm::TagToType<0x0018,0x0090> x00180090; (void)x00180090; gdcm::TagToType<0x0018,0x0091> x00180091; (void)x00180091; gdcm::TagToType<0x0018,0x0093> x00180093; (void)x00180093; gdcm::TagToType<0x0018,0x0094> x00180094; (void)x00180094; gdcm::TagToType<0x0018,0x0095> x00180095; (void)x00180095; gdcm::TagToType<0x0018,0x1000> x00181000; (void)x00181000; gdcm::TagToType<0x0018,0x1002> x00181002; (void)x00181002; gdcm::TagToType<0x0018,0x1003> x00181003; (void)x00181003; gdcm::TagToType<0x0018,0x1004> x00181004; (void)x00181004; gdcm::TagToType<0x0018,0x1005> x00181005; (void)x00181005; gdcm::TagToType<0x0018,0x1006> x00181006; (void)x00181006; gdcm::TagToType<0x0018,0x1007> x00181007; (void)x00181007; gdcm::TagToType<0x0018,0x1008> x00181008; (void)x00181008; gdcm::TagToType<0x0018,0x1010> x00181010; (void)x00181010; gdcm::TagToType<0x0018,0x1011> x00181011; (void)x00181011; gdcm::TagToType<0x0018,0x1012> x00181012; (void)x00181012; gdcm::TagToType<0x0018,0x1014> x00181014; (void)x00181014; gdcm::TagToType<0x0018,0x1016> x00181016; (void)x00181016; gdcm::TagToType<0x0018,0x1017> x00181017; (void)x00181017; gdcm::TagToType<0x0018,0x1018> x00181018; (void)x00181018; gdcm::TagToType<0x0018,0x1019> x00181019; (void)x00181019; gdcm::TagToType<0x0018,0x101a> x0018101a; (void)x0018101a; gdcm::TagToType<0x0018,0x101b> x0018101b; (void)x0018101b; gdcm::TagToType<0x0018,0x1020> x00181020; (void)x00181020; gdcm::TagToType<0x0018,0x1022> x00181022; (void)x00181022; gdcm::TagToType<0x0018,0x1023> x00181023; (void)x00181023; gdcm::TagToType<0x0018,0x1030> x00181030; (void)x00181030; gdcm::TagToType<0x0018,0x1040> x00181040; (void)x00181040; gdcm::TagToType<0x0018,0x1041> x00181041; (void)x00181041; gdcm::TagToType<0x0018,0x1042> x00181042; (void)x00181042; gdcm::TagToType<0x0018,0x1043> x00181043; (void)x00181043; gdcm::TagToType<0x0018,0x1044> x00181044; (void)x00181044; gdcm::TagToType<0x0018,0x1045> x00181045; (void)x00181045; gdcm::TagToType<0x0018,0x1046> x00181046; (void)x00181046; gdcm::TagToType<0x0018,0x1047> x00181047; (void)x00181047; gdcm::TagToType<0x0018,0x1048> x00181048; (void)x00181048; gdcm::TagToType<0x0018,0x1049> x00181049; (void)x00181049; gdcm::TagToType<0x0018,0x1050> x00181050; (void)x00181050; gdcm::TagToType<0x0018,0x1060> x00181060; (void)x00181060; gdcm::TagToType<0x0018,0x1061> x00181061; (void)x00181061; gdcm::TagToType<0x0018,0x1062> x00181062; (void)x00181062; gdcm::TagToType<0x0018,0x1063> x00181063; (void)x00181063; gdcm::TagToType<0x0018,0x1064> x00181064; (void)x00181064; gdcm::TagToType<0x0018,0x1065> x00181065; (void)x00181065; gdcm::TagToType<0x0018,0x1066> x00181066; (void)x00181066; gdcm::TagToType<0x0018,0x1067> x00181067; (void)x00181067; gdcm::TagToType<0x0018,0x1068> x00181068; (void)x00181068; gdcm::TagToType<0x0018,0x1069> x00181069; (void)x00181069; gdcm::TagToType<0x0018,0x106a> x0018106a; (void)x0018106a; gdcm::TagToType<0x0018,0x106c> x0018106c; (void)x0018106c; gdcm::TagToType<0x0018,0x106e> x0018106e; (void)x0018106e; gdcm::TagToType<0x0018,0x1070> x00181070; (void)x00181070; gdcm::TagToType<0x0018,0x1071> x00181071; (void)x00181071; gdcm::TagToType<0x0018,0x1072> x00181072; (void)x00181072; gdcm::TagToType<0x0018,0x1073> x00181073; (void)x00181073; gdcm::TagToType<0x0018,0x1074> x00181074; (void)x00181074; gdcm::TagToType<0x0018,0x1075> x00181075; (void)x00181075; gdcm::TagToType<0x0018,0x1076> x00181076; (void)x00181076; gdcm::TagToType<0x0018,0x1077> x00181077; (void)x00181077; gdcm::TagToType<0x0018,0x1078> x00181078; (void)x00181078; gdcm::TagToType<0x0018,0x1079> x00181079; (void)x00181079; gdcm::TagToType<0x0018,0x1080> x00181080; (void)x00181080; gdcm::TagToType<0x0018,0x1081> x00181081; (void)x00181081; gdcm::TagToType<0x0018,0x1082> x00181082; (void)x00181082; gdcm::TagToType<0x0018,0x1083> x00181083; (void)x00181083; gdcm::TagToType<0x0018,0x1084> x00181084; (void)x00181084; gdcm::TagToType<0x0018,0x1085> x00181085; (void)x00181085; gdcm::TagToType<0x0018,0x1086> x00181086; (void)x00181086; gdcm::TagToType<0x0018,0x1088> x00181088; (void)x00181088; gdcm::TagToType<0x0018,0x1090> x00181090; (void)x00181090; gdcm::TagToType<0x0018,0x1094> x00181094; (void)x00181094; gdcm::TagToType<0x0018,0x1100> x00181100; (void)x00181100; gdcm::TagToType<0x0018,0x1110> x00181110; (void)x00181110; gdcm::TagToType<0x0018,0x1111> x00181111; (void)x00181111; gdcm::TagToType<0x0018,0x1114> x00181114; (void)x00181114; gdcm::TagToType<0x0018,0x1120> x00181120; (void)x00181120; gdcm::TagToType<0x0018,0x1121> x00181121; (void)x00181121; gdcm::TagToType<0x0018,0x1130> x00181130; (void)x00181130; gdcm::TagToType<0x0018,0x1131> x00181131; (void)x00181131; gdcm::TagToType<0x0018,0x1134> x00181134; (void)x00181134; gdcm::TagToType<0x0018,0x1135> x00181135; (void)x00181135; gdcm::TagToType<0x0018,0x1136> x00181136; (void)x00181136; gdcm::TagToType<0x0018,0x1137> x00181137; (void)x00181137; gdcm::TagToType<0x0018,0x1138> x00181138; (void)x00181138; gdcm::TagToType<0x0018,0x113a> x0018113a; (void)x0018113a; gdcm::TagToType<0x0018,0x1140> x00181140; (void)x00181140; gdcm::TagToType<0x0018,0x1141> x00181141; (void)x00181141; gdcm::TagToType<0x0018,0x1142> x00181142; (void)x00181142; gdcm::TagToType<0x0018,0x1143> x00181143; (void)x00181143; gdcm::TagToType<0x0018,0x1144> x00181144; (void)x00181144; gdcm::TagToType<0x0018,0x1145> x00181145; (void)x00181145; gdcm::TagToType<0x0018,0x1146> x00181146; (void)x00181146; gdcm::TagToType<0x0018,0x1147> x00181147; (void)x00181147; gdcm::TagToType<0x0018,0x1149> x00181149; (void)x00181149; gdcm::TagToType<0x0018,0x1150> x00181150; (void)x00181150; gdcm::TagToType<0x0018,0x1151> x00181151; (void)x00181151; gdcm::TagToType<0x0018,0x1152> x00181152; (void)x00181152; gdcm::TagToType<0x0018,0x1153> x00181153; (void)x00181153; gdcm::TagToType<0x0018,0x1154> x00181154; (void)x00181154; gdcm::TagToType<0x0018,0x1155> x00181155; (void)x00181155; gdcm::TagToType<0x0018,0x1156> x00181156; (void)x00181156; gdcm::TagToType<0x0018,0x115a> x0018115a; (void)x0018115a; gdcm::TagToType<0x0018,0x115e> x0018115e; (void)x0018115e; gdcm::TagToType<0x0018,0x1160> x00181160; (void)x00181160; gdcm::TagToType<0x0018,0x1161> x00181161; (void)x00181161; gdcm::TagToType<0x0018,0x1162> x00181162; (void)x00181162; gdcm::TagToType<0x0018,0x1164> x00181164; (void)x00181164; gdcm::TagToType<0x0018,0x1166> x00181166; (void)x00181166; gdcm::TagToType<0x0018,0x1170> x00181170; (void)x00181170; gdcm::TagToType<0x0018,0x1180> x00181180; (void)x00181180; gdcm::TagToType<0x0018,0x1181> x00181181; (void)x00181181; gdcm::TagToType<0x0018,0x1182> x00181182; (void)x00181182; gdcm::TagToType<0x0018,0x1183> x00181183; (void)x00181183; gdcm::TagToType<0x0018,0x1184> x00181184; (void)x00181184; gdcm::TagToType<0x0018,0x1190> x00181190; (void)x00181190; gdcm::TagToType<0x0018,0x1191> x00181191; (void)x00181191; gdcm::TagToType<0x0018,0x11a0> x001811a0; (void)x001811a0; gdcm::TagToType<0x0018,0x11a2> x001811a2; (void)x001811a2; gdcm::TagToType<0x0018,0x1200> x00181200; (void)x00181200; gdcm::TagToType<0x0018,0x1201> x00181201; (void)x00181201; gdcm::TagToType<0x0018,0x1210> x00181210; (void)x00181210; gdcm::TagToType<0x0018,0x1240> x00181240; (void)x00181240; gdcm::TagToType<0x0018,0x1242> x00181242; (void)x00181242; gdcm::TagToType<0x0018,0x1243> x00181243; (void)x00181243; gdcm::TagToType<0x0018,0x1244> x00181244; (void)x00181244; gdcm::TagToType<0x0018,0x1250> x00181250; (void)x00181250; gdcm::TagToType<0x0018,0x1251> x00181251; (void)x00181251; gdcm::TagToType<0x0018,0x1260> x00181260; (void)x00181260; gdcm::TagToType<0x0018,0x1261> x00181261; (void)x00181261; gdcm::TagToType<0x0018,0x1300> x00181300; (void)x00181300; gdcm::TagToType<0x0018,0x1301> x00181301; (void)x00181301; gdcm::TagToType<0x0018,0x1302> x00181302; (void)x00181302; gdcm::TagToType<0x0018,0x1310> x00181310; (void)x00181310; gdcm::TagToType<0x0018,0x1312> x00181312; (void)x00181312; gdcm::TagToType<0x0018,0x1314> x00181314; (void)x00181314; gdcm::TagToType<0x0018,0x1315> x00181315; (void)x00181315; gdcm::TagToType<0x0018,0x1316> x00181316; (void)x00181316; gdcm::TagToType<0x0018,0x1318> x00181318; (void)x00181318; gdcm::TagToType<0x0018,0x1400> x00181400; (void)x00181400; gdcm::TagToType<0x0018,0x1401> x00181401; (void)x00181401; gdcm::TagToType<0x0018,0x1402> x00181402; (void)x00181402; gdcm::TagToType<0x0018,0x1403> x00181403; (void)x00181403; gdcm::TagToType<0x0018,0x1404> x00181404; (void)x00181404; gdcm::TagToType<0x0018,0x1405> x00181405; (void)x00181405; gdcm::TagToType<0x0018,0x1450> x00181450; (void)x00181450; gdcm::TagToType<0x0018,0x1460> x00181460; (void)x00181460; gdcm::TagToType<0x0018,0x1470> x00181470; (void)x00181470; gdcm::TagToType<0x0018,0x1480> x00181480; (void)x00181480; gdcm::TagToType<0x0018,0x1490> x00181490; (void)x00181490; gdcm::TagToType<0x0018,0x1491> x00181491; (void)x00181491; gdcm::TagToType<0x0018,0x1495> x00181495; (void)x00181495; gdcm::TagToType<0x0018,0x1500> x00181500; (void)x00181500; gdcm::TagToType<0x0018,0x1508> x00181508; (void)x00181508; gdcm::TagToType<0x0018,0x1510> x00181510; (void)x00181510; gdcm::TagToType<0x0018,0x1511> x00181511; (void)x00181511; gdcm::TagToType<0x0018,0x1520> x00181520; (void)x00181520; gdcm::TagToType<0x0018,0x1521> x00181521; (void)x00181521; gdcm::TagToType<0x0018,0x1530> x00181530; (void)x00181530; gdcm::TagToType<0x0018,0x1531> x00181531; (void)x00181531; gdcm::TagToType<0x0018,0x1600> x00181600; (void)x00181600; gdcm::TagToType<0x0018,0x1602> x00181602; (void)x00181602; gdcm::TagToType<0x0018,0x1604> x00181604; (void)x00181604; gdcm::TagToType<0x0018,0x1606> x00181606; (void)x00181606; gdcm::TagToType<0x0018,0x1608> x00181608; (void)x00181608; gdcm::TagToType<0x0018,0x1610> x00181610; (void)x00181610; gdcm::TagToType<0x0018,0x1612> x00181612; (void)x00181612; gdcm::TagToType<0x0018,0x1620> x00181620; (void)x00181620; gdcm::TagToType<0x0018,0x1622> x00181622; (void)x00181622; gdcm::TagToType<0x0018,0x1623> x00181623; (void)x00181623; gdcm::TagToType<0x0018,0x1624> x00181624; (void)x00181624; gdcm::TagToType<0x0018,0x1700> x00181700; (void)x00181700; gdcm::TagToType<0x0018,0x1702> x00181702; (void)x00181702; gdcm::TagToType<0x0018,0x1704> x00181704; (void)x00181704; gdcm::TagToType<0x0018,0x1706> x00181706; (void)x00181706; gdcm::TagToType<0x0018,0x1708> x00181708; (void)x00181708; gdcm::TagToType<0x0018,0x1710> x00181710; (void)x00181710; gdcm::TagToType<0x0018,0x1712> x00181712; (void)x00181712; gdcm::TagToType<0x0018,0x1720> x00181720; (void)x00181720; gdcm::TagToType<0x0018,0x1800> x00181800; (void)x00181800; gdcm::TagToType<0x0018,0x1801> x00181801; (void)x00181801; gdcm::TagToType<0x0018,0x1802> x00181802; (void)x00181802; gdcm::TagToType<0x0018,0x1803> x00181803; (void)x00181803; gdcm::TagToType<0x0018,0x2001> x00182001; (void)x00182001; gdcm::TagToType<0x0018,0x2002> x00182002; (void)x00182002; gdcm::TagToType<0x0018,0x2003> x00182003; (void)x00182003; gdcm::TagToType<0x0018,0x2004> x00182004; (void)x00182004; gdcm::TagToType<0x0018,0x2005> x00182005; (void)x00182005; gdcm::TagToType<0x0018,0x2006> x00182006; (void)x00182006; gdcm::TagToType<0x0018,0x2010> x00182010; (void)x00182010; gdcm::TagToType<0x0018,0x2020> x00182020; (void)x00182020; gdcm::TagToType<0x0018,0x2030> x00182030; (void)x00182030; gdcm::TagToType<0x0018,0x3100> x00183100; (void)x00183100; gdcm::TagToType<0x0018,0x3101> x00183101; (void)x00183101; gdcm::TagToType<0x0018,0x3102> x00183102; (void)x00183102; gdcm::TagToType<0x0018,0x3103> x00183103; (void)x00183103; gdcm::TagToType<0x0018,0x3104> x00183104; (void)x00183104; gdcm::TagToType<0x0018,0x3105> x00183105; (void)x00183105; gdcm::TagToType<0x0018,0x4000> x00184000; (void)x00184000; gdcm::TagToType<0x0018,0x5000> x00185000; (void)x00185000; gdcm::TagToType<0x0018,0x5010> x00185010; (void)x00185010; gdcm::TagToType<0x0018,0x5012> x00185012; (void)x00185012; gdcm::TagToType<0x0018,0x5020> x00185020; (void)x00185020; gdcm::TagToType<0x0018,0x5021> x00185021; (void)x00185021; gdcm::TagToType<0x0018,0x5022> x00185022; (void)x00185022; gdcm::TagToType<0x0018,0x5024> x00185024; (void)x00185024; gdcm::TagToType<0x0018,0x5026> x00185026; (void)x00185026; gdcm::TagToType<0x0018,0x5027> x00185027; (void)x00185027; gdcm::TagToType<0x0018,0x5028> x00185028; (void)x00185028; gdcm::TagToType<0x0018,0x5029> x00185029; (void)x00185029; gdcm::TagToType<0x0018,0x5030> x00185030; (void)x00185030; gdcm::TagToType<0x0018,0x5040> x00185040; (void)x00185040; gdcm::TagToType<0x0018,0x5050> x00185050; (void)x00185050; gdcm::TagToType<0x0018,0x5100> x00185100; (void)x00185100; gdcm::TagToType<0x0018,0x5101> x00185101; (void)x00185101; gdcm::TagToType<0x0018,0x5104> x00185104; (void)x00185104; gdcm::TagToType<0x0018,0x5210> x00185210; (void)x00185210; gdcm::TagToType<0x0018,0x5212> x00185212; (void)x00185212; gdcm::TagToType<0x0018,0x6000> x00186000; (void)x00186000; gdcm::TagToType<0x0018,0x6011> x00186011; (void)x00186011; gdcm::TagToType<0x0018,0x6012> x00186012; (void)x00186012; gdcm::TagToType<0x0018,0x6014> x00186014; (void)x00186014; gdcm::TagToType<0x0018,0x6016> x00186016; (void)x00186016; gdcm::TagToType<0x0018,0x6018> x00186018; (void)x00186018; gdcm::TagToType<0x0018,0x601a> x0018601a; (void)x0018601a; gdcm::TagToType<0x0018,0x601c> x0018601c; (void)x0018601c; gdcm::TagToType<0x0018,0x601e> x0018601e; (void)x0018601e; gdcm::TagToType<0x0018,0x6020> x00186020; (void)x00186020; gdcm::TagToType<0x0018,0x6022> x00186022; (void)x00186022; gdcm::TagToType<0x0018,0x6024> x00186024; (void)x00186024; gdcm::TagToType<0x0018,0x6026> x00186026; (void)x00186026; gdcm::TagToType<0x0018,0x6028> x00186028; (void)x00186028; gdcm::TagToType<0x0018,0x602a> x0018602a; (void)x0018602a; gdcm::TagToType<0x0018,0x602c> x0018602c; (void)x0018602c; gdcm::TagToType<0x0018,0x602e> x0018602e; (void)x0018602e; gdcm::TagToType<0x0018,0x6030> x00186030; (void)x00186030; gdcm::TagToType<0x0018,0x6031> x00186031; (void)x00186031; gdcm::TagToType<0x0018,0x6032> x00186032; (void)x00186032; gdcm::TagToType<0x0018,0x6034> x00186034; (void)x00186034; gdcm::TagToType<0x0018,0x6036> x00186036; (void)x00186036; gdcm::TagToType<0x0018,0x6038> x00186038; (void)x00186038; gdcm::TagToType<0x0018,0x6039> x00186039; (void)x00186039; gdcm::TagToType<0x0018,0x603a> x0018603a; (void)x0018603a; gdcm::TagToType<0x0018,0x603b> x0018603b; (void)x0018603b; gdcm::TagToType<0x0018,0x603c> x0018603c; (void)x0018603c; gdcm::TagToType<0x0018,0x603d> x0018603d; (void)x0018603d; gdcm::TagToType<0x0018,0x603e> x0018603e; (void)x0018603e; gdcm::TagToType<0x0018,0x603f> x0018603f; (void)x0018603f; gdcm::TagToType<0x0018,0x6040> x00186040; (void)x00186040; gdcm::TagToType<0x0018,0x6041> x00186041; (void)x00186041; gdcm::TagToType<0x0018,0x6042> x00186042; (void)x00186042; gdcm::TagToType<0x0018,0x6043> x00186043; (void)x00186043; gdcm::TagToType<0x0018,0x6044> x00186044; (void)x00186044; gdcm::TagToType<0x0018,0x6046> x00186046; (void)x00186046; gdcm::TagToType<0x0018,0x6048> x00186048; (void)x00186048; gdcm::TagToType<0x0018,0x604a> x0018604a; (void)x0018604a; gdcm::TagToType<0x0018,0x604c> x0018604c; (void)x0018604c; gdcm::TagToType<0x0018,0x604e> x0018604e; (void)x0018604e; gdcm::TagToType<0x0018,0x6050> x00186050; (void)x00186050; gdcm::TagToType<0x0018,0x6052> x00186052; (void)x00186052; gdcm::TagToType<0x0018,0x6054> x00186054; (void)x00186054; gdcm::TagToType<0x0018,0x6056> x00186056; (void)x00186056; gdcm::TagToType<0x0018,0x6058> x00186058; (void)x00186058; gdcm::TagToType<0x0018,0x605a> x0018605a; (void)x0018605a; gdcm::TagToType<0x0018,0x6060> x00186060; (void)x00186060; gdcm::TagToType<0x0018,0x7000> x00187000; (void)x00187000; gdcm::TagToType<0x0018,0x7001> x00187001; (void)x00187001; gdcm::TagToType<0x0018,0x7004> x00187004; (void)x00187004; gdcm::TagToType<0x0018,0x7005> x00187005; (void)x00187005; gdcm::TagToType<0x0018,0x7006> x00187006; (void)x00187006; gdcm::TagToType<0x0018,0x7008> x00187008; (void)x00187008; gdcm::TagToType<0x0018,0x700a> x0018700a; (void)x0018700a; gdcm::TagToType<0x0018,0x700c> x0018700c; (void)x0018700c; gdcm::TagToType<0x0018,0x700e> x0018700e; (void)x0018700e; gdcm::TagToType<0x0018,0x7010> x00187010; (void)x00187010; gdcm::TagToType<0x0018,0x7011> x00187011; (void)x00187011; gdcm::TagToType<0x0018,0x7012> x00187012; (void)x00187012; gdcm::TagToType<0x0018,0x7014> x00187014; (void)x00187014; gdcm::TagToType<0x0018,0x7016> x00187016; (void)x00187016; gdcm::TagToType<0x0018,0x701a> x0018701a; (void)x0018701a; gdcm::TagToType<0x0018,0x7020> x00187020; (void)x00187020; gdcm::TagToType<0x0018,0x7022> x00187022; (void)x00187022; gdcm::TagToType<0x0018,0x7024> x00187024; (void)x00187024; gdcm::TagToType<0x0018,0x7026> x00187026; (void)x00187026; gdcm::TagToType<0x0018,0x7028> x00187028; (void)x00187028; gdcm::TagToType<0x0018,0x702a> x0018702a; (void)x0018702a; gdcm::TagToType<0x0018,0x702b> x0018702b; (void)x0018702b; gdcm::TagToType<0x0018,0x7030> x00187030; (void)x00187030; gdcm::TagToType<0x0018,0x7032> x00187032; (void)x00187032; gdcm::TagToType<0x0018,0x7034> x00187034; (void)x00187034; gdcm::TagToType<0x0018,0x7040> x00187040; (void)x00187040; gdcm::TagToType<0x0018,0x7041> x00187041; (void)x00187041; gdcm::TagToType<0x0018,0x7042> x00187042; (void)x00187042; gdcm::TagToType<0x0018,0x7044> x00187044; (void)x00187044; gdcm::TagToType<0x0018,0x7046> x00187046; (void)x00187046; gdcm::TagToType<0x0018,0x7048> x00187048; (void)x00187048; gdcm::TagToType<0x0018,0x704c> x0018704c; (void)x0018704c; gdcm::TagToType<0x0018,0x7050> x00187050; (void)x00187050; gdcm::TagToType<0x0018,0x7052> x00187052; (void)x00187052; gdcm::TagToType<0x0018,0x7054> x00187054; (void)x00187054; gdcm::TagToType<0x0018,0x7060> x00187060; (void)x00187060; gdcm::TagToType<0x0018,0x7062> x00187062; (void)x00187062; gdcm::TagToType<0x0018,0x7064> x00187064; (void)x00187064; gdcm::TagToType<0x0018,0x7065> x00187065; (void)x00187065; gdcm::TagToType<0x0018,0x8150> x00188150; (void)x00188150; gdcm::TagToType<0x0018,0x8151> x00188151; (void)x00188151; gdcm::TagToType<0x0018,0x9004> x00189004; (void)x00189004; gdcm::TagToType<0x0018,0x9005> x00189005; (void)x00189005; gdcm::TagToType<0x0018,0x9006> x00189006; (void)x00189006; gdcm::TagToType<0x0018,0x9008> x00189008; (void)x00189008; gdcm::TagToType<0x0018,0x9009> x00189009; (void)x00189009; gdcm::TagToType<0x0018,0x9010> x00189010; (void)x00189010; gdcm::TagToType<0x0018,0x9011> x00189011; (void)x00189011; gdcm::TagToType<0x0018,0x9012> x00189012; (void)x00189012; gdcm::TagToType<0x0018,0x9014> x00189014; (void)x00189014; gdcm::TagToType<0x0018,0x9015> x00189015; (void)x00189015; gdcm::TagToType<0x0018,0x9016> x00189016; (void)x00189016; gdcm::TagToType<0x0018,0x9017> x00189017; (void)x00189017; gdcm::TagToType<0x0018,0x9018> x00189018; (void)x00189018; gdcm::TagToType<0x0018,0x9019> x00189019; (void)x00189019; gdcm::TagToType<0x0018,0x9020> x00189020; (void)x00189020; gdcm::TagToType<0x0018,0x9021> x00189021; (void)x00189021; gdcm::TagToType<0x0018,0x9022> x00189022; (void)x00189022; gdcm::TagToType<0x0018,0x9024> x00189024; (void)x00189024; gdcm::TagToType<0x0018,0x9025> x00189025; (void)x00189025; gdcm::TagToType<0x0018,0x9026> x00189026; (void)x00189026; gdcm::TagToType<0x0018,0x9027> x00189027; (void)x00189027; gdcm::TagToType<0x0018,0x9028> x00189028; (void)x00189028; gdcm::TagToType<0x0018,0x9029> x00189029; (void)x00189029; gdcm::TagToType<0x0018,0x9030> x00189030; (void)x00189030; gdcm::TagToType<0x0018,0x9032> x00189032; (void)x00189032; gdcm::TagToType<0x0018,0x9033> x00189033; (void)x00189033; gdcm::TagToType<0x0018,0x9034> x00189034; (void)x00189034; gdcm::TagToType<0x0018,0x9035> x00189035; (void)x00189035; gdcm::TagToType<0x0018,0x9036> x00189036; (void)x00189036; gdcm::TagToType<0x0018,0x9037> x00189037; (void)x00189037; gdcm::TagToType<0x0018,0x9041> x00189041; (void)x00189041; gdcm::TagToType<0x0018,0x9042> x00189042; (void)x00189042; gdcm::TagToType<0x0018,0x9043> x00189043; (void)x00189043; gdcm::TagToType<0x0018,0x9044> x00189044; (void)x00189044; gdcm::TagToType<0x0018,0x9045> x00189045; (void)x00189045; gdcm::TagToType<0x0018,0x9046> x00189046; (void)x00189046; gdcm::TagToType<0x0018,0x9047> x00189047; (void)x00189047; gdcm::TagToType<0x0018,0x9048> x00189048; (void)x00189048; gdcm::TagToType<0x0018,0x9049> x00189049; (void)x00189049; gdcm::TagToType<0x0018,0x9050> x00189050; (void)x00189050; gdcm::TagToType<0x0018,0x9051> x00189051; (void)x00189051; gdcm::TagToType<0x0018,0x9052> x00189052; (void)x00189052; gdcm::TagToType<0x0018,0x9053> x00189053; (void)x00189053; gdcm::TagToType<0x0018,0x9054> x00189054; (void)x00189054; gdcm::TagToType<0x0018,0x9058> x00189058; (void)x00189058; gdcm::TagToType<0x0018,0x9059> x00189059; (void)x00189059; gdcm::TagToType<0x0018,0x9060> x00189060; (void)x00189060; gdcm::TagToType<0x0018,0x9061> x00189061; (void)x00189061; gdcm::TagToType<0x0018,0x9062> x00189062; (void)x00189062; gdcm::TagToType<0x0018,0x9063> x00189063; (void)x00189063; gdcm::TagToType<0x0018,0x9064> x00189064; (void)x00189064; gdcm::TagToType<0x0018,0x9065> x00189065; (void)x00189065; gdcm::TagToType<0x0018,0x9066> x00189066; (void)x00189066; gdcm::TagToType<0x0018,0x9067> x00189067; (void)x00189067; gdcm::TagToType<0x0018,0x9069> x00189069; (void)x00189069; gdcm::TagToType<0x0018,0x9070> x00189070; (void)x00189070; gdcm::TagToType<0x0018,0x9073> x00189073; (void)x00189073; gdcm::TagToType<0x0018,0x9074> x00189074; (void)x00189074; gdcm::TagToType<0x0018,0x9075> x00189075; (void)x00189075; gdcm::TagToType<0x0018,0x9076> x00189076; (void)x00189076; gdcm::TagToType<0x0018,0x9077> x00189077; (void)x00189077; gdcm::TagToType<0x0018,0x9078> x00189078; (void)x00189078; gdcm::TagToType<0x0018,0x9079> x00189079; (void)x00189079; gdcm::TagToType<0x0018,0x9080> x00189080; (void)x00189080; gdcm::TagToType<0x0018,0x9081> x00189081; (void)x00189081; gdcm::TagToType<0x0018,0x9082> x00189082; (void)x00189082; gdcm::TagToType<0x0018,0x9083> x00189083; (void)x00189083; gdcm::TagToType<0x0018,0x9084> x00189084; (void)x00189084; gdcm::TagToType<0x0018,0x9085> x00189085; (void)x00189085; gdcm::TagToType<0x0018,0x9087> x00189087; (void)x00189087; gdcm::TagToType<0x0018,0x9089> x00189089; (void)x00189089; gdcm::TagToType<0x0018,0x9090> x00189090; (void)x00189090; gdcm::TagToType<0x0018,0x9091> x00189091; (void)x00189091; gdcm::TagToType<0x0018,0x9093> x00189093; (void)x00189093; gdcm::TagToType<0x0018,0x9094> x00189094; (void)x00189094; gdcm::TagToType<0x0018,0x9095> x00189095; (void)x00189095; gdcm::TagToType<0x0018,0x9096> x00189096; (void)x00189096; gdcm::TagToType<0x0018,0x9098> x00189098; (void)x00189098; gdcm::TagToType<0x0018,0x9100> x00189100; (void)x00189100; gdcm::TagToType<0x0018,0x9101> x00189101; (void)x00189101; gdcm::TagToType<0x0018,0x9103> x00189103; (void)x00189103; gdcm::TagToType<0x0018,0x9104> x00189104; (void)x00189104; gdcm::TagToType<0x0018,0x9105> x00189105; (void)x00189105; gdcm::TagToType<0x0018,0x9106> x00189106; (void)x00189106; gdcm::TagToType<0x0018,0x9107> x00189107; (void)x00189107; gdcm::TagToType<0x0018,0x9112> x00189112; (void)x00189112; gdcm::TagToType<0x0018,0x9114> x00189114; (void)x00189114; gdcm::TagToType<0x0018,0x9115> x00189115; (void)x00189115; gdcm::TagToType<0x0018,0x9117> x00189117; (void)x00189117; gdcm::TagToType<0x0018,0x9118> x00189118; (void)x00189118; gdcm::TagToType<0x0018,0x9119> x00189119; (void)x00189119; gdcm::TagToType<0x0018,0x9125> x00189125; (void)x00189125; gdcm::TagToType<0x0018,0x9126> x00189126; (void)x00189126; gdcm::TagToType<0x0018,0x9127> x00189127; (void)x00189127; gdcm::TagToType<0x0018,0x9147> x00189147; (void)x00189147; gdcm::TagToType<0x0018,0x9151> x00189151; (void)x00189151; gdcm::TagToType<0x0018,0x9152> x00189152; (void)x00189152; gdcm::TagToType<0x0018,0x9155> x00189155; (void)x00189155; gdcm::TagToType<0x0018,0x9159> x00189159; (void)x00189159; gdcm::TagToType<0x0018,0x9166> x00189166; (void)x00189166; gdcm::TagToType<0x0018,0x9168> x00189168; (void)x00189168; gdcm::TagToType<0x0018,0x9169> x00189169; (void)x00189169; gdcm::TagToType<0x0018,0x9170> x00189170; (void)x00189170; gdcm::TagToType<0x0018,0x9171> x00189171; (void)x00189171; gdcm::TagToType<0x0018,0x9172> x00189172; (void)x00189172; gdcm::TagToType<0x0018,0x9173> x00189173; (void)x00189173; gdcm::TagToType<0x0018,0x9174> x00189174; (void)x00189174; gdcm::TagToType<0x0018,0x9175> x00189175; (void)x00189175; gdcm::TagToType<0x0018,0x9176> x00189176; (void)x00189176; gdcm::TagToType<0x0018,0x9177> x00189177; (void)x00189177; gdcm::TagToType<0x0018,0x9178> x00189178; (void)x00189178; gdcm::TagToType<0x0018,0x9179> x00189179; (void)x00189179; gdcm::TagToType<0x0018,0x9180> x00189180; (void)x00189180; gdcm::TagToType<0x0018,0x9181> x00189181; (void)x00189181; gdcm::TagToType<0x0018,0x9182> x00189182; (void)x00189182; gdcm::TagToType<0x0018,0x9183> x00189183; (void)x00189183; gdcm::TagToType<0x0018,0x9184> x00189184; (void)x00189184; gdcm::TagToType<0x0018,0x9185> x00189185; (void)x00189185; gdcm::TagToType<0x0018,0x9186> x00189186; (void)x00189186; gdcm::TagToType<0x0018,0x9195> x00189195; (void)x00189195; gdcm::TagToType<0x0018,0x9196> x00189196; (void)x00189196; gdcm::TagToType<0x0018,0x9197> x00189197; (void)x00189197; gdcm::TagToType<0x0018,0x9198> x00189198; (void)x00189198; gdcm::TagToType<0x0018,0x9199> x00189199; (void)x00189199; gdcm::TagToType<0x0018,0x9200> x00189200; (void)x00189200; gdcm::TagToType<0x0018,0x9214> x00189214; (void)x00189214; gdcm::TagToType<0x0018,0x9217> x00189217; (void)x00189217; gdcm::TagToType<0x0018,0x9218> x00189218; (void)x00189218; gdcm::TagToType<0x0018,0x9219> x00189219; (void)x00189219; gdcm::TagToType<0x0018,0x9220> x00189220; (void)x00189220; gdcm::TagToType<0x0018,0x9226> x00189226; (void)x00189226; gdcm::TagToType<0x0018,0x9227> x00189227; (void)x00189227; gdcm::TagToType<0x0018,0x9231> x00189231; (void)x00189231; gdcm::TagToType<0x0018,0x9232> x00189232; (void)x00189232; gdcm::TagToType<0x0018,0x9234> x00189234; (void)x00189234; gdcm::TagToType<0x0018,0x9236> x00189236; (void)x00189236; gdcm::TagToType<0x0018,0x9239> x00189239; (void)x00189239; gdcm::TagToType<0x0018,0x9240> x00189240; (void)x00189240; gdcm::TagToType<0x0018,0x9241> x00189241; (void)x00189241; gdcm::TagToType<0x0018,0x9295> x00189295; (void)x00189295; gdcm::TagToType<0x0018,0x9296> x00189296; (void)x00189296; gdcm::TagToType<0x0018,0x9301> x00189301; (void)x00189301; gdcm::TagToType<0x0018,0x9302> x00189302; (void)x00189302; gdcm::TagToType<0x0018,0x9303> x00189303; (void)x00189303; gdcm::TagToType<0x0018,0x9304> x00189304; (void)x00189304; gdcm::TagToType<0x0018,0x9305> x00189305; (void)x00189305; gdcm::TagToType<0x0018,0x9306> x00189306; (void)x00189306; gdcm::TagToType<0x0018,0x9307> x00189307; (void)x00189307; gdcm::TagToType<0x0018,0x9308> x00189308; (void)x00189308; gdcm::TagToType<0x0018,0x9309> x00189309; (void)x00189309; gdcm::TagToType<0x0018,0x9310> x00189310; (void)x00189310; gdcm::TagToType<0x0018,0x9311> x00189311; (void)x00189311; gdcm::TagToType<0x0018,0x9312> x00189312; (void)x00189312; gdcm::TagToType<0x0018,0x9313> x00189313; (void)x00189313; gdcm::TagToType<0x0018,0x9314> x00189314; (void)x00189314; gdcm::TagToType<0x0018,0x9315> x00189315; (void)x00189315; gdcm::TagToType<0x0018,0x9316> x00189316; (void)x00189316; gdcm::TagToType<0x0018,0x9317> x00189317; (void)x00189317; gdcm::TagToType<0x0018,0x9318> x00189318; (void)x00189318; gdcm::TagToType<0x0018,0x9319> x00189319; (void)x00189319; gdcm::TagToType<0x0018,0x9320> x00189320; (void)x00189320; gdcm::TagToType<0x0018,0x9321> x00189321; (void)x00189321; gdcm::TagToType<0x0018,0x9322> x00189322; (void)x00189322; gdcm::TagToType<0x0018,0x9323> x00189323; (void)x00189323; gdcm::TagToType<0x0018,0x9324> x00189324; (void)x00189324; gdcm::TagToType<0x0018,0x9325> x00189325; (void)x00189325; gdcm::TagToType<0x0018,0x9326> x00189326; (void)x00189326; gdcm::TagToType<0x0018,0x9327> x00189327; (void)x00189327; gdcm::TagToType<0x0018,0x9328> x00189328; (void)x00189328; gdcm::TagToType<0x0018,0x9329> x00189329; (void)x00189329; gdcm::TagToType<0x0018,0x9330> x00189330; (void)x00189330; gdcm::TagToType<0x0018,0x9332> x00189332; (void)x00189332; gdcm::TagToType<0x0018,0x9333> x00189333; (void)x00189333; gdcm::TagToType<0x0018,0x9334> x00189334; (void)x00189334; gdcm::TagToType<0x0018,0x9335> x00189335; (void)x00189335; gdcm::TagToType<0x0018,0x9337> x00189337; (void)x00189337; gdcm::TagToType<0x0018,0x9338> x00189338; (void)x00189338; gdcm::TagToType<0x0018,0x9340> x00189340; (void)x00189340; gdcm::TagToType<0x0018,0x9341> x00189341; (void)x00189341; gdcm::TagToType<0x0018,0x9342> x00189342; (void)x00189342; gdcm::TagToType<0x0018,0x9343> x00189343; (void)x00189343; gdcm::TagToType<0x0018,0x9344> x00189344; (void)x00189344; gdcm::TagToType<0x0018,0x9345> x00189345; (void)x00189345; gdcm::TagToType<0x0018,0x9346> x00189346; (void)x00189346; gdcm::TagToType<0x0018,0x9351> x00189351; (void)x00189351; gdcm::TagToType<0x0018,0x9352> x00189352; (void)x00189352; gdcm::TagToType<0x0018,0x9360> x00189360; (void)x00189360; gdcm::TagToType<0x0018,0x9401> x00189401; (void)x00189401; gdcm::TagToType<0x0018,0x9402> x00189402; (void)x00189402; gdcm::TagToType<0x0018,0x9403> x00189403; (void)x00189403; gdcm::TagToType<0x0018,0x9404> x00189404; (void)x00189404; gdcm::TagToType<0x0018,0x9405> x00189405; (void)x00189405; gdcm::TagToType<0x0018,0x9406> x00189406; (void)x00189406; gdcm::TagToType<0x0018,0x9407> x00189407; (void)x00189407; gdcm::TagToType<0x0018,0x9412> x00189412; (void)x00189412; gdcm::TagToType<0x0018,0x9417> x00189417; (void)x00189417; gdcm::TagToType<0x0018,0x9420> x00189420; (void)x00189420; gdcm::TagToType<0x0018,0x9423> x00189423; (void)x00189423; gdcm::TagToType<0x0018,0x9424> x00189424; (void)x00189424; gdcm::TagToType<0x0018,0x9425> x00189425; (void)x00189425; gdcm::TagToType<0x0018,0x9426> x00189426; (void)x00189426; gdcm::TagToType<0x0018,0x9427> x00189427; (void)x00189427; gdcm::TagToType<0x0018,0x9428> x00189428; (void)x00189428; gdcm::TagToType<0x0018,0x9429> x00189429; (void)x00189429; gdcm::TagToType<0x0018,0x9430> x00189430; (void)x00189430; gdcm::TagToType<0x0018,0x9432> x00189432; (void)x00189432; gdcm::TagToType<0x0018,0x9433> x00189433; (void)x00189433; gdcm::TagToType<0x0018,0x9434> x00189434; (void)x00189434; gdcm::TagToType<0x0018,0x9435> x00189435; (void)x00189435; gdcm::TagToType<0x0018,0x9436> x00189436; (void)x00189436; gdcm::TagToType<0x0018,0x9437> x00189437; (void)x00189437; gdcm::TagToType<0x0018,0x9438> x00189438; (void)x00189438; gdcm::TagToType<0x0018,0x9439> x00189439; (void)x00189439; gdcm::TagToType<0x0018,0x9440> x00189440; (void)x00189440; gdcm::TagToType<0x0018,0x9441> x00189441; (void)x00189441; gdcm::TagToType<0x0018,0x9442> x00189442; (void)x00189442; gdcm::TagToType<0x0018,0x9447> x00189447; (void)x00189447; gdcm::TagToType<0x0018,0x9449> x00189449; (void)x00189449; gdcm::TagToType<0x0018,0x9451> x00189451; (void)x00189451; gdcm::TagToType<0x0018,0x9452> x00189452; (void)x00189452; gdcm::TagToType<0x0018,0x9455> x00189455; (void)x00189455; gdcm::TagToType<0x0018,0x9456> x00189456; (void)x00189456; gdcm::TagToType<0x0018,0x9457> x00189457; (void)x00189457; gdcm::TagToType<0x0018,0x9461> x00189461; (void)x00189461; gdcm::TagToType<0x0018,0x9462> x00189462; (void)x00189462; gdcm::TagToType<0x0018,0x9463> x00189463; (void)x00189463; gdcm::TagToType<0x0018,0x9464> x00189464; (void)x00189464; gdcm::TagToType<0x0018,0x9465> x00189465; (void)x00189465; gdcm::TagToType<0x0018,0x9466> x00189466; (void)x00189466; gdcm::TagToType<0x0018,0x9467> x00189467; (void)x00189467; gdcm::TagToType<0x0018,0x9468> x00189468; (void)x00189468; gdcm::TagToType<0x0018,0x9469> x00189469; (void)x00189469; gdcm::TagToType<0x0018,0x9470> x00189470; (void)x00189470; gdcm::TagToType<0x0018,0x9471> x00189471; (void)x00189471; gdcm::TagToType<0x0018,0x9472> x00189472; (void)x00189472; gdcm::TagToType<0x0018,0x9473> x00189473; (void)x00189473; gdcm::TagToType<0x0018,0x9474> x00189474; (void)x00189474; gdcm::TagToType<0x0018,0x9476> x00189476; (void)x00189476; gdcm::TagToType<0x0018,0x9477> x00189477; (void)x00189477; gdcm::TagToType<0x0018,0x9504> x00189504; (void)x00189504; gdcm::TagToType<0x0018,0x9506> x00189506; (void)x00189506; gdcm::TagToType<0x0018,0x9507> x00189507; (void)x00189507; gdcm::TagToType<0x0018,0x9508> x00189508; (void)x00189508; gdcm::TagToType<0x0018,0x9509> x00189509; (void)x00189509; gdcm::TagToType<0x0018,0x9510> x00189510; (void)x00189510; gdcm::TagToType<0x0018,0x9511> x00189511; (void)x00189511; gdcm::TagToType<0x0018,0x9514> x00189514; (void)x00189514; gdcm::TagToType<0x0018,0x9515> x00189515; (void)x00189515; gdcm::TagToType<0x0018,0x9516> x00189516; (void)x00189516; gdcm::TagToType<0x0018,0x9517> x00189517; (void)x00189517; gdcm::TagToType<0x0018,0x9524> x00189524; (void)x00189524; gdcm::TagToType<0x0018,0x9525> x00189525; (void)x00189525; gdcm::TagToType<0x0018,0x9526> x00189526; (void)x00189526; gdcm::TagToType<0x0018,0x9527> x00189527; (void)x00189527; gdcm::TagToType<0x0018,0x9528> x00189528; (void)x00189528; gdcm::TagToType<0x0018,0x9530> x00189530; (void)x00189530; gdcm::TagToType<0x0018,0x9531> x00189531; (void)x00189531; gdcm::TagToType<0x0018,0x9538> x00189538; (void)x00189538; gdcm::TagToType<0x0018,0x9601> x00189601; (void)x00189601; gdcm::TagToType<0x0018,0x9602> x00189602; (void)x00189602; gdcm::TagToType<0x0018,0x9603> x00189603; (void)x00189603; gdcm::TagToType<0x0018,0x9604> x00189604; (void)x00189604; gdcm::TagToType<0x0018,0x9605> x00189605; (void)x00189605; gdcm::TagToType<0x0018,0x9606> x00189606; (void)x00189606; gdcm::TagToType<0x0018,0x9607> x00189607; (void)x00189607; gdcm::TagToType<0x0018,0xa001> x0018a001; (void)x0018a001; gdcm::TagToType<0x0018,0xa002> x0018a002; (void)x0018a002; gdcm::TagToType<0x0018,0xa003> x0018a003; (void)x0018a003; gdcm::TagToType<0x0020,0x000d> x0020000d; (void)x0020000d; gdcm::TagToType<0x0020,0x000e> x0020000e; (void)x0020000e; gdcm::TagToType<0x0020,0x0010> x00200010; (void)x00200010; gdcm::TagToType<0x0020,0x0011> x00200011; (void)x00200011; gdcm::TagToType<0x0020,0x0012> x00200012; (void)x00200012; gdcm::TagToType<0x0020,0x0013> x00200013; (void)x00200013; gdcm::TagToType<0x0020,0x0014> x00200014; (void)x00200014; gdcm::TagToType<0x0020,0x0015> x00200015; (void)x00200015; gdcm::TagToType<0x0020,0x0016> x00200016; (void)x00200016; gdcm::TagToType<0x0020,0x0017> x00200017; (void)x00200017; gdcm::TagToType<0x0020,0x0018> x00200018; (void)x00200018; gdcm::TagToType<0x0020,0x0019> x00200019; (void)x00200019; gdcm::TagToType<0x0020,0x0020> x00200020; (void)x00200020; gdcm::TagToType<0x0020,0x0022> x00200022; (void)x00200022; gdcm::TagToType<0x0020,0x0024> x00200024; (void)x00200024; gdcm::TagToType<0x0020,0x0026> x00200026; (void)x00200026; gdcm::TagToType<0x0020,0x0030> x00200030; (void)x00200030; gdcm::TagToType<0x0020,0x0032> x00200032; (void)x00200032; gdcm::TagToType<0x0020,0x0035> x00200035; (void)x00200035; gdcm::TagToType<0x0020,0x0037> x00200037; (void)x00200037; gdcm::TagToType<0x0020,0x0050> x00200050; (void)x00200050; gdcm::TagToType<0x0020,0x0052> x00200052; (void)x00200052; gdcm::TagToType<0x0020,0x0060> x00200060; (void)x00200060; gdcm::TagToType<0x0020,0x0062> x00200062; (void)x00200062; gdcm::TagToType<0x0020,0x0070> x00200070; (void)x00200070; gdcm::TagToType<0x0020,0x0080> x00200080; (void)x00200080; gdcm::TagToType<0x0020,0x0100> x00200100; (void)x00200100; gdcm::TagToType<0x0020,0x0105> x00200105; (void)x00200105; gdcm::TagToType<0x0020,0x0110> x00200110; (void)x00200110; gdcm::TagToType<0x0020,0x0200> x00200200; (void)x00200200; gdcm::TagToType<0x0020,0x1000> x00201000; (void)x00201000; gdcm::TagToType<0x0020,0x1001> x00201001; (void)x00201001; gdcm::TagToType<0x0020,0x1002> x00201002; (void)x00201002; gdcm::TagToType<0x0020,0x1003> x00201003; (void)x00201003; gdcm::TagToType<0x0020,0x1004> x00201004; (void)x00201004; gdcm::TagToType<0x0020,0x1005> x00201005; (void)x00201005; gdcm::TagToType<0x0020,0x1020> x00201020; (void)x00201020; gdcm::TagToType<0x0020,0x1040> x00201040; (void)x00201040; gdcm::TagToType<0x0020,0x1041> x00201041; (void)x00201041; gdcm::TagToType<0x0020,0x1070> x00201070; (void)x00201070; gdcm::TagToType<0x0020,0x1200> x00201200; (void)x00201200; gdcm::TagToType<0x0020,0x1202> x00201202; (void)x00201202; gdcm::TagToType<0x0020,0x1204> x00201204; (void)x00201204; gdcm::TagToType<0x0020,0x1206> x00201206; (void)x00201206; gdcm::TagToType<0x0020,0x1208> x00201208; (void)x00201208; gdcm::TagToType<0x0020,0x1209> x00201209; (void)x00201209; gdcm::TagToType<0x0020,0x3401> x00203401; (void)x00203401; gdcm::TagToType<0x0020,0x3402> x00203402; (void)x00203402; gdcm::TagToType<0x0020,0x3403> x00203403; (void)x00203403; gdcm::TagToType<0x0020,0x3404> x00203404; (void)x00203404; gdcm::TagToType<0x0020,0x3405> x00203405; (void)x00203405; gdcm::TagToType<0x0020,0x3406> x00203406; (void)x00203406; gdcm::TagToType<0x0020,0x4000> x00204000; (void)x00204000; gdcm::TagToType<0x0020,0x5000> x00205000; (void)x00205000; gdcm::TagToType<0x0020,0x5002> x00205002; (void)x00205002; gdcm::TagToType<0x0020,0x9056> x00209056; (void)x00209056; gdcm::TagToType<0x0020,0x9057> x00209057; (void)x00209057; gdcm::TagToType<0x0020,0x9071> x00209071; (void)x00209071; gdcm::TagToType<0x0020,0x9072> x00209072; (void)x00209072; gdcm::TagToType<0x0020,0x9111> x00209111; (void)x00209111; gdcm::TagToType<0x0020,0x9113> x00209113; (void)x00209113; gdcm::TagToType<0x0020,0x9116> x00209116; (void)x00209116; gdcm::TagToType<0x0020,0x9128> x00209128; (void)x00209128; gdcm::TagToType<0x0020,0x9153> x00209153; (void)x00209153; gdcm::TagToType<0x0020,0x9156> x00209156; (void)x00209156; gdcm::TagToType<0x0020,0x9157> x00209157; (void)x00209157; gdcm::TagToType<0x0020,0x9158> x00209158; (void)x00209158; gdcm::TagToType<0x0020,0x9161> x00209161; (void)x00209161; gdcm::TagToType<0x0020,0x9162> x00209162; (void)x00209162; gdcm::TagToType<0x0020,0x9163> x00209163; (void)x00209163; gdcm::TagToType<0x0020,0x9164> x00209164; (void)x00209164; gdcm::TagToType<0x0020,0x9165> x00209165; (void)x00209165; gdcm::TagToType<0x0020,0x9167> x00209167; (void)x00209167; gdcm::TagToType<0x0020,0x9213> x00209213; (void)x00209213; gdcm::TagToType<0x0020,0x9221> x00209221; (void)x00209221; gdcm::TagToType<0x0020,0x9222> x00209222; (void)x00209222; gdcm::TagToType<0x0020,0x9228> x00209228; (void)x00209228; gdcm::TagToType<0x0020,0x9238> x00209238; (void)x00209238; gdcm::TagToType<0x0020,0x9241> x00209241; (void)x00209241; gdcm::TagToType<0x0020,0x9245> x00209245; (void)x00209245; gdcm::TagToType<0x0020,0x9246> x00209246; (void)x00209246; gdcm::TagToType<0x0020,0x9247> x00209247; (void)x00209247; gdcm::TagToType<0x0020,0x9248> x00209248; (void)x00209248; gdcm::TagToType<0x0020,0x9249> x00209249; (void)x00209249; gdcm::TagToType<0x0020,0x9250> x00209250; (void)x00209250; gdcm::TagToType<0x0020,0x9251> x00209251; (void)x00209251; gdcm::TagToType<0x0020,0x9252> x00209252; (void)x00209252; gdcm::TagToType<0x0020,0x9253> x00209253; (void)x00209253; gdcm::TagToType<0x0020,0x9254> x00209254; (void)x00209254; gdcm::TagToType<0x0020,0x9255> x00209255; (void)x00209255; gdcm::TagToType<0x0020,0x9256> x00209256; (void)x00209256; gdcm::TagToType<0x0020,0x9257> x00209257; (void)x00209257; gdcm::TagToType<0x0020,0x9421> x00209421; (void)x00209421; gdcm::TagToType<0x0020,0x9450> x00209450; (void)x00209450; gdcm::TagToType<0x0020,0x9453> x00209453; (void)x00209453; gdcm::TagToType<0x0020,0x9518> x00209518; (void)x00209518; gdcm::TagToType<0x0020,0x9529> x00209529; (void)x00209529; gdcm::TagToType<0x0020,0x9536> x00209536; (void)x00209536; gdcm::TagToType<0x0022,0x0001> x00220001; (void)x00220001; gdcm::TagToType<0x0022,0x0002> x00220002; (void)x00220002; gdcm::TagToType<0x0022,0x0003> x00220003; (void)x00220003; gdcm::TagToType<0x0022,0x0004> x00220004; (void)x00220004; gdcm::TagToType<0x0022,0x0005> x00220005; (void)x00220005; gdcm::TagToType<0x0022,0x0006> x00220006; (void)x00220006; gdcm::TagToType<0x0022,0x0007> x00220007; (void)x00220007; gdcm::TagToType<0x0022,0x0008> x00220008; (void)x00220008; gdcm::TagToType<0x0022,0x0009> x00220009; (void)x00220009; gdcm::TagToType<0x0022,0x000a> x0022000a; (void)x0022000a; gdcm::TagToType<0x0022,0x000b> x0022000b; (void)x0022000b; gdcm::TagToType<0x0022,0x000c> x0022000c; (void)x0022000c; gdcm::TagToType<0x0022,0x000d> x0022000d; (void)x0022000d; gdcm::TagToType<0x0022,0x000e> x0022000e; (void)x0022000e; gdcm::TagToType<0x0022,0x0010> x00220010; (void)x00220010; gdcm::TagToType<0x0022,0x0011> x00220011; (void)x00220011; gdcm::TagToType<0x0022,0x0012> x00220012; (void)x00220012; gdcm::TagToType<0x0022,0x0013> x00220013; (void)x00220013; gdcm::TagToType<0x0022,0x0014> x00220014; (void)x00220014; gdcm::TagToType<0x0022,0x0015> x00220015; (void)x00220015; gdcm::TagToType<0x0022,0x0016> x00220016; (void)x00220016; gdcm::TagToType<0x0022,0x0017> x00220017; (void)x00220017; gdcm::TagToType<0x0022,0x0018> x00220018; (void)x00220018; gdcm::TagToType<0x0022,0x0019> x00220019; (void)x00220019; gdcm::TagToType<0x0022,0x001a> x0022001a; (void)x0022001a; gdcm::TagToType<0x0022,0x001b> x0022001b; (void)x0022001b; gdcm::TagToType<0x0022,0x001c> x0022001c; (void)x0022001c; gdcm::TagToType<0x0022,0x001d> x0022001d; (void)x0022001d; gdcm::TagToType<0x0022,0x0020> x00220020; (void)x00220020; gdcm::TagToType<0x0022,0x0021> x00220021; (void)x00220021; gdcm::TagToType<0x0022,0x0022> x00220022; (void)x00220022; gdcm::TagToType<0x0022,0x0030> x00220030; (void)x00220030; gdcm::TagToType<0x0022,0x0031> x00220031; (void)x00220031; gdcm::TagToType<0x0022,0x0032> x00220032; (void)x00220032; gdcm::TagToType<0x0022,0x0035> x00220035; (void)x00220035; gdcm::TagToType<0x0022,0x0036> x00220036; (void)x00220036; gdcm::TagToType<0x0022,0x0037> x00220037; (void)x00220037; gdcm::TagToType<0x0022,0x0038> x00220038; (void)x00220038; gdcm::TagToType<0x0022,0x0039> x00220039; (void)x00220039; gdcm::TagToType<0x0022,0x0041> x00220041; (void)x00220041; gdcm::TagToType<0x0022,0x0042> x00220042; (void)x00220042; gdcm::TagToType<0x0022,0x0048> x00220048; (void)x00220048; gdcm::TagToType<0x0022,0x0049> x00220049; (void)x00220049; gdcm::TagToType<0x0022,0x004e> x0022004e; (void)x0022004e; gdcm::TagToType<0x0022,0x0055> x00220055; (void)x00220055; gdcm::TagToType<0x0022,0x0056> x00220056; (void)x00220056; gdcm::TagToType<0x0022,0x0057> x00220057; (void)x00220057; gdcm::TagToType<0x0022,0x0058> x00220058; (void)x00220058; gdcm::TagToType<0x0028,0x0002> x00280002; (void)x00280002; gdcm::TagToType<0x0028,0x0003> x00280003; (void)x00280003; gdcm::TagToType<0x0028,0x0004> x00280004; (void)x00280004; gdcm::TagToType<0x0028,0x0005> x00280005; (void)x00280005; gdcm::TagToType<0x0028,0x0006> x00280006; (void)x00280006; gdcm::TagToType<0x0028,0x0008> x00280008; (void)x00280008; gdcm::TagToType<0x0028,0x0009> x00280009; (void)x00280009; gdcm::TagToType<0x0028,0x000a> x0028000a; (void)x0028000a; gdcm::TagToType<0x0028,0x0010> x00280010; (void)x00280010; gdcm::TagToType<0x0028,0x0011> x00280011; (void)x00280011; gdcm::TagToType<0x0028,0x0012> x00280012; (void)x00280012; gdcm::TagToType<0x0028,0x0014> x00280014; (void)x00280014; gdcm::TagToType<0x0028,0x0030> x00280030; (void)x00280030; gdcm::TagToType<0x0028,0x0031> x00280031; (void)x00280031; gdcm::TagToType<0x0028,0x0032> x00280032; (void)x00280032; gdcm::TagToType<0x0028,0x0034> x00280034; (void)x00280034; gdcm::TagToType<0x0028,0x0040> x00280040; (void)x00280040; gdcm::TagToType<0x0028,0x0050> x00280050; (void)x00280050; gdcm::TagToType<0x0028,0x0051> x00280051; (void)x00280051; gdcm::TagToType<0x0028,0x005f> x0028005f; (void)x0028005f; gdcm::TagToType<0x0028,0x0060> x00280060; (void)x00280060; gdcm::TagToType<0x0028,0x0061> x00280061; (void)x00280061; gdcm::TagToType<0x0028,0x0062> x00280062; (void)x00280062; gdcm::TagToType<0x0028,0x0063> x00280063; (void)x00280063; gdcm::TagToType<0x0028,0x0065> x00280065; (void)x00280065; gdcm::TagToType<0x0028,0x0066> x00280066; (void)x00280066; gdcm::TagToType<0x0028,0x0068> x00280068; (void)x00280068; gdcm::TagToType<0x0028,0x0069> x00280069; (void)x00280069; gdcm::TagToType<0x0028,0x0070> x00280070; (void)x00280070; gdcm::TagToType<0x0028,0x0080> x00280080; (void)x00280080; gdcm::TagToType<0x0028,0x0081> x00280081; (void)x00280081; gdcm::TagToType<0x0028,0x0082> x00280082; (void)x00280082; gdcm::TagToType<0x0028,0x0090> x00280090; (void)x00280090; gdcm::TagToType<0x0028,0x0091> x00280091; (void)x00280091; gdcm::TagToType<0x0028,0x0092> x00280092; (void)x00280092; gdcm::TagToType<0x0028,0x0093> x00280093; (void)x00280093; gdcm::TagToType<0x0028,0x0094> x00280094; (void)x00280094; gdcm::TagToType<0x0028,0x0100> x00280100; (void)x00280100; gdcm::TagToType<0x0028,0x0101> x00280101; (void)x00280101; gdcm::TagToType<0x0028,0x0102> x00280102; (void)x00280102; gdcm::TagToType<0x0028,0x0103> x00280103; (void)x00280103; gdcm::TagToType<0x0028,0x0200> x00280200; (void)x00280200; gdcm::TagToType<0x0028,0x0300> x00280300; (void)x00280300; gdcm::TagToType<0x0028,0x0301> x00280301; (void)x00280301; gdcm::TagToType<0x0028,0x0400> x00280400; (void)x00280400; gdcm::TagToType<0x0028,0x0401> x00280401; (void)x00280401; gdcm::TagToType<0x0028,0x0402> x00280402; (void)x00280402; gdcm::TagToType<0x0028,0x0403> x00280403; (void)x00280403; gdcm::TagToType<0x0028,0x0404> x00280404; (void)x00280404; gdcm::TagToType<0x0028,0x0700> x00280700; (void)x00280700; gdcm::TagToType<0x0028,0x0701> x00280701; (void)x00280701; gdcm::TagToType<0x0028,0x0702> x00280702; (void)x00280702; gdcm::TagToType<0x0028,0x0710> x00280710; (void)x00280710; gdcm::TagToType<0x0028,0x0720> x00280720; (void)x00280720; gdcm::TagToType<0x0028,0x0721> x00280721; (void)x00280721; gdcm::TagToType<0x0028,0x0722> x00280722; (void)x00280722; gdcm::TagToType<0x0028,0x0730> x00280730; (void)x00280730; gdcm::TagToType<0x0028,0x0740> x00280740; (void)x00280740; gdcm::TagToType<0x0028,0x0a02> x00280a02; (void)x00280a02; gdcm::TagToType<0x0028,0x0a04> x00280a04; (void)x00280a04; gdcm::TagToType<0x0028,0x1040> x00281040; (void)x00281040; gdcm::TagToType<0x0028,0x1041> x00281041; (void)x00281041; gdcm::TagToType<0x0028,0x1050> x00281050; (void)x00281050; gdcm::TagToType<0x0028,0x1051> x00281051; (void)x00281051; gdcm::TagToType<0x0028,0x1052> x00281052; (void)x00281052; gdcm::TagToType<0x0028,0x1053> x00281053; (void)x00281053; gdcm::TagToType<0x0028,0x1054> x00281054; (void)x00281054; gdcm::TagToType<0x0028,0x1055> x00281055; (void)x00281055; gdcm::TagToType<0x0028,0x1056> x00281056; (void)x00281056; gdcm::TagToType<0x0028,0x1080> x00281080; (void)x00281080; gdcm::TagToType<0x0028,0x1090> x00281090; (void)x00281090; gdcm::TagToType<0x0028,0x1199> x00281199; (void)x00281199; gdcm::TagToType<0x0028,0x1201> x00281201; (void)x00281201; gdcm::TagToType<0x0028,0x1202> x00281202; (void)x00281202; gdcm::TagToType<0x0028,0x1203> x00281203; (void)x00281203; gdcm::TagToType<0x0028,0x1211> x00281211; (void)x00281211; gdcm::TagToType<0x0028,0x1212> x00281212; (void)x00281212; gdcm::TagToType<0x0028,0x1213> x00281213; (void)x00281213; gdcm::TagToType<0x0028,0x1214> x00281214; (void)x00281214; gdcm::TagToType<0x0028,0x1221> x00281221; (void)x00281221; gdcm::TagToType<0x0028,0x1222> x00281222; (void)x00281222; gdcm::TagToType<0x0028,0x1223> x00281223; (void)x00281223; gdcm::TagToType<0x0028,0x1300> x00281300; (void)x00281300; gdcm::TagToType<0x0028,0x1350> x00281350; (void)x00281350; gdcm::TagToType<0x0028,0x1351> x00281351; (void)x00281351; gdcm::TagToType<0x0028,0x1352> x00281352; (void)x00281352; gdcm::TagToType<0x0028,0x135a> x0028135a; (void)x0028135a; gdcm::TagToType<0x0028,0x2000> x00282000; (void)x00282000; gdcm::TagToType<0x0028,0x2110> x00282110; (void)x00282110; gdcm::TagToType<0x0028,0x2112> x00282112; (void)x00282112; gdcm::TagToType<0x0028,0x2114> x00282114; (void)x00282114; gdcm::TagToType<0x0028,0x3000> x00283000; (void)x00283000; gdcm::TagToType<0x0028,0x3003> x00283003; (void)x00283003; gdcm::TagToType<0x0028,0x3004> x00283004; (void)x00283004; gdcm::TagToType<0x0028,0x3010> x00283010; (void)x00283010; gdcm::TagToType<0x0028,0x3110> x00283110; (void)x00283110; gdcm::TagToType<0x0028,0x4000> x00284000; (void)x00284000; gdcm::TagToType<0x0028,0x5000> x00285000; (void)x00285000; gdcm::TagToType<0x0028,0x6010> x00286010; (void)x00286010; gdcm::TagToType<0x0028,0x6020> x00286020; (void)x00286020; gdcm::TagToType<0x0028,0x6022> x00286022; (void)x00286022; gdcm::TagToType<0x0028,0x6023> x00286023; (void)x00286023; gdcm::TagToType<0x0028,0x6030> x00286030; (void)x00286030; gdcm::TagToType<0x0028,0x6040> x00286040; (void)x00286040; gdcm::TagToType<0x0028,0x6100> x00286100; (void)x00286100; gdcm::TagToType<0x0028,0x6101> x00286101; (void)x00286101; gdcm::TagToType<0x0028,0x6102> x00286102; (void)x00286102; gdcm::TagToType<0x0028,0x6110> x00286110; (void)x00286110; gdcm::TagToType<0x0028,0x6112> x00286112; (void)x00286112; gdcm::TagToType<0x0028,0x6114> x00286114; (void)x00286114; gdcm::TagToType<0x0028,0x6120> x00286120; (void)x00286120; gdcm::TagToType<0x0028,0x6190> x00286190; (void)x00286190; gdcm::TagToType<0x0028,0x7fe0> x00287fe0; (void)x00287fe0; gdcm::TagToType<0x0028,0x9001> x00289001; (void)x00289001; gdcm::TagToType<0x0028,0x9002> x00289002; (void)x00289002; gdcm::TagToType<0x0028,0x9003> x00289003; (void)x00289003; gdcm::TagToType<0x0028,0x9099> x00289099; (void)x00289099; gdcm::TagToType<0x0028,0x9108> x00289108; (void)x00289108; gdcm::TagToType<0x0028,0x9110> x00289110; (void)x00289110; gdcm::TagToType<0x0028,0x9132> x00289132; (void)x00289132; gdcm::TagToType<0x0028,0x9145> x00289145; (void)x00289145; gdcm::TagToType<0x0028,0x9235> x00289235; (void)x00289235; gdcm::TagToType<0x0028,0x9411> x00289411; (void)x00289411; gdcm::TagToType<0x0028,0x9415> x00289415; (void)x00289415; gdcm::TagToType<0x0028,0x9416> x00289416; (void)x00289416; gdcm::TagToType<0x0028,0x9422> x00289422; (void)x00289422; gdcm::TagToType<0x0028,0x9443> x00289443; (void)x00289443; gdcm::TagToType<0x0028,0x9444> x00289444; (void)x00289444; gdcm::TagToType<0x0028,0x9445> x00289445; (void)x00289445; gdcm::TagToType<0x0028,0x9446> x00289446; (void)x00289446; gdcm::TagToType<0x0028,0x9454> x00289454; (void)x00289454; gdcm::TagToType<0x0028,0x9474> x00289474; (void)x00289474; gdcm::TagToType<0x0028,0x9520> x00289520; (void)x00289520; gdcm::TagToType<0x0028,0x9537> x00289537; (void)x00289537; gdcm::TagToType<0x0032,0x000a> x0032000a; (void)x0032000a; gdcm::TagToType<0x0032,0x000c> x0032000c; (void)x0032000c; gdcm::TagToType<0x0032,0x0012> x00320012; (void)x00320012; gdcm::TagToType<0x0032,0x0032> x00320032; (void)x00320032; gdcm::TagToType<0x0032,0x0033> x00320033; (void)x00320033; gdcm::TagToType<0x0032,0x0034> x00320034; (void)x00320034; gdcm::TagToType<0x0032,0x0035> x00320035; (void)x00320035; gdcm::TagToType<0x0032,0x1000> x00321000; (void)x00321000; gdcm::TagToType<0x0032,0x1001> x00321001; (void)x00321001; gdcm::TagToType<0x0032,0x1010> x00321010; (void)x00321010; gdcm::TagToType<0x0032,0x1011> x00321011; (void)x00321011; gdcm::TagToType<0x0032,0x1020> x00321020; (void)x00321020; gdcm::TagToType<0x0032,0x1021> x00321021; (void)x00321021; gdcm::TagToType<0x0032,0x1030> x00321030; (void)x00321030; gdcm::TagToType<0x0032,0x1031> x00321031; (void)x00321031; gdcm::TagToType<0x0032,0x1032> x00321032; (void)x00321032; gdcm::TagToType<0x0032,0x1033> x00321033; (void)x00321033; gdcm::TagToType<0x0032,0x1040> x00321040; (void)x00321040; gdcm::TagToType<0x0032,0x1041> x00321041; (void)x00321041; gdcm::TagToType<0x0032,0x1050> x00321050; (void)x00321050; gdcm::TagToType<0x0032,0x1051> x00321051; (void)x00321051; gdcm::TagToType<0x0032,0x1055> x00321055; (void)x00321055; gdcm::TagToType<0x0032,0x1060> x00321060; (void)x00321060; gdcm::TagToType<0x0032,0x1064> x00321064; (void)x00321064; gdcm::TagToType<0x0032,0x1070> x00321070; (void)x00321070; gdcm::TagToType<0x0032,0x4000> x00324000; (void)x00324000; gdcm::TagToType<0x0038,0x0004> x00380004; (void)x00380004; gdcm::TagToType<0x0038,0x0008> x00380008; (void)x00380008; gdcm::TagToType<0x0038,0x0010> x00380010; (void)x00380010; gdcm::TagToType<0x0038,0x0011> x00380011; (void)x00380011; gdcm::TagToType<0x0038,0x0016> x00380016; (void)x00380016; gdcm::TagToType<0x0038,0x001a> x0038001a; (void)x0038001a; gdcm::TagToType<0x0038,0x001b> x0038001b; (void)x0038001b; gdcm::TagToType<0x0038,0x001c> x0038001c; (void)x0038001c; gdcm::TagToType<0x0038,0x001d> x0038001d; (void)x0038001d; gdcm::TagToType<0x0038,0x001e> x0038001e; (void)x0038001e; gdcm::TagToType<0x0038,0x0020> x00380020; (void)x00380020; gdcm::TagToType<0x0038,0x0021> x00380021; (void)x00380021; gdcm::TagToType<0x0038,0x0030> x00380030; (void)x00380030; gdcm::TagToType<0x0038,0x0032> x00380032; (void)x00380032; gdcm::TagToType<0x0038,0x0040> x00380040; (void)x00380040; gdcm::TagToType<0x0038,0x0044> x00380044; (void)x00380044; gdcm::TagToType<0x0038,0x0050> x00380050; (void)x00380050; gdcm::TagToType<0x0038,0x0060> x00380060; (void)x00380060; gdcm::TagToType<0x0038,0x0061> x00380061; (void)x00380061; gdcm::TagToType<0x0038,0x0062> x00380062; (void)x00380062; gdcm::TagToType<0x0038,0x0100> x00380100; (void)x00380100; gdcm::TagToType<0x0038,0x0300> x00380300; (void)x00380300; gdcm::TagToType<0x0038,0x0400> x00380400; (void)x00380400; gdcm::TagToType<0x0038,0x0500> x00380500; (void)x00380500; gdcm::TagToType<0x0038,0x0502> x00380502; (void)x00380502; gdcm::TagToType<0x0038,0x4000> x00384000; (void)x00384000; gdcm::TagToType<0x003a,0x0004> x003a0004; (void)x003a0004; gdcm::TagToType<0x003a,0x0005> x003a0005; (void)x003a0005; gdcm::TagToType<0x003a,0x0010> x003a0010; (void)x003a0010; gdcm::TagToType<0x003a,0x001a> x003a001a; (void)x003a001a; gdcm::TagToType<0x003a,0x0020> x003a0020; (void)x003a0020; gdcm::TagToType<0x003a,0x0200> x003a0200; (void)x003a0200; gdcm::TagToType<0x003a,0x0202> x003a0202; (void)x003a0202; gdcm::TagToType<0x003a,0x0203> x003a0203; (void)x003a0203; gdcm::TagToType<0x003a,0x0205> x003a0205; (void)x003a0205; gdcm::TagToType<0x003a,0x0208> x003a0208; (void)x003a0208; gdcm::TagToType<0x003a,0x0209> x003a0209; (void)x003a0209; gdcm::TagToType<0x003a,0x020a> x003a020a; (void)x003a020a; gdcm::TagToType<0x003a,0x020c> x003a020c; (void)x003a020c; gdcm::TagToType<0x003a,0x0210> x003a0210; (void)x003a0210; gdcm::TagToType<0x003a,0x0211> x003a0211; (void)x003a0211; gdcm::TagToType<0x003a,0x0212> x003a0212; (void)x003a0212; gdcm::TagToType<0x003a,0x0213> x003a0213; (void)x003a0213; gdcm::TagToType<0x003a,0x0214> x003a0214; (void)x003a0214; gdcm::TagToType<0x003a,0x0215> x003a0215; (void)x003a0215; gdcm::TagToType<0x003a,0x0218> x003a0218; (void)x003a0218; gdcm::TagToType<0x003a,0x021a> x003a021a; (void)x003a021a; gdcm::TagToType<0x003a,0x0220> x003a0220; (void)x003a0220; gdcm::TagToType<0x003a,0x0221> x003a0221; (void)x003a0221; gdcm::TagToType<0x003a,0x0222> x003a0222; (void)x003a0222; gdcm::TagToType<0x003a,0x0223> x003a0223; (void)x003a0223; gdcm::TagToType<0x003a,0x0230> x003a0230; (void)x003a0230; gdcm::TagToType<0x003a,0x0231> x003a0231; (void)x003a0231; gdcm::TagToType<0x003a,0x0240> x003a0240; (void)x003a0240; gdcm::TagToType<0x003a,0x0241> x003a0241; (void)x003a0241; gdcm::TagToType<0x003a,0x0242> x003a0242; (void)x003a0242; gdcm::TagToType<0x003a,0x0244> x003a0244; (void)x003a0244; gdcm::TagToType<0x003a,0x0245> x003a0245; (void)x003a0245; gdcm::TagToType<0x003a,0x0246> x003a0246; (void)x003a0246; gdcm::TagToType<0x003a,0x0247> x003a0247; (void)x003a0247; gdcm::TagToType<0x003a,0x0248> x003a0248; (void)x003a0248; gdcm::TagToType<0x003a,0x0300> x003a0300; (void)x003a0300; gdcm::TagToType<0x003a,0x0301> x003a0301; (void)x003a0301; gdcm::TagToType<0x003a,0x0302> x003a0302; (void)x003a0302; gdcm::TagToType<0x0040,0x0001> x00400001; (void)x00400001; gdcm::TagToType<0x0040,0x0002> x00400002; (void)x00400002; gdcm::TagToType<0x0040,0x0003> x00400003; (void)x00400003; gdcm::TagToType<0x0040,0x0004> x00400004; (void)x00400004; gdcm::TagToType<0x0040,0x0005> x00400005; (void)x00400005; gdcm::TagToType<0x0040,0x0006> x00400006; (void)x00400006; gdcm::TagToType<0x0040,0x0007> x00400007; (void)x00400007; gdcm::TagToType<0x0040,0x0008> x00400008; (void)x00400008; gdcm::TagToType<0x0040,0x0009> x00400009; (void)x00400009; gdcm::TagToType<0x0040,0x000a> x0040000a; (void)x0040000a; gdcm::TagToType<0x0040,0x000b> x0040000b; (void)x0040000b; gdcm::TagToType<0x0040,0x0010> x00400010; (void)x00400010; gdcm::TagToType<0x0040,0x0011> x00400011; (void)x00400011; gdcm::TagToType<0x0040,0x0012> x00400012; (void)x00400012; gdcm::TagToType<0x0040,0x0020> x00400020; (void)x00400020; gdcm::TagToType<0x0040,0x0100> x00400100; (void)x00400100; gdcm::TagToType<0x0040,0x0220> x00400220; (void)x00400220; gdcm::TagToType<0x0040,0x0241> x00400241; (void)x00400241; gdcm::TagToType<0x0040,0x0242> x00400242; (void)x00400242; gdcm::TagToType<0x0040,0x0243> x00400243; (void)x00400243; gdcm::TagToType<0x0040,0x0244> x00400244; (void)x00400244; gdcm::TagToType<0x0040,0x0245> x00400245; (void)x00400245; gdcm::TagToType<0x0040,0x0250> x00400250; (void)x00400250; gdcm::TagToType<0x0040,0x0251> x00400251; (void)x00400251; gdcm::TagToType<0x0040,0x0252> x00400252; (void)x00400252; gdcm::TagToType<0x0040,0x0253> x00400253; (void)x00400253; gdcm::TagToType<0x0040,0x0254> x00400254; (void)x00400254; gdcm::TagToType<0x0040,0x0255> x00400255; (void)x00400255; gdcm::TagToType<0x0040,0x0260> x00400260; (void)x00400260; gdcm::TagToType<0x0040,0x0270> x00400270; (void)x00400270; gdcm::TagToType<0x0040,0x0275> x00400275; (void)x00400275; gdcm::TagToType<0x0040,0x0280> x00400280; (void)x00400280; gdcm::TagToType<0x0040,0x0281> x00400281; (void)x00400281; gdcm::TagToType<0x0040,0x0293> x00400293; (void)x00400293; gdcm::TagToType<0x0040,0x0294> x00400294; (void)x00400294; gdcm::TagToType<0x0040,0x0295> x00400295; (void)x00400295; gdcm::TagToType<0x0040,0x0296> x00400296; (void)x00400296; gdcm::TagToType<0x0040,0x0300> x00400300; (void)x00400300; gdcm::TagToType<0x0040,0x0301> x00400301; (void)x00400301; gdcm::TagToType<0x0040,0x0302> x00400302; (void)x00400302; gdcm::TagToType<0x0040,0x0303> x00400303; (void)x00400303; gdcm::TagToType<0x0040,0x0306> x00400306; (void)x00400306; gdcm::TagToType<0x0040,0x0307> x00400307; (void)x00400307; gdcm::TagToType<0x0040,0x030e> x0040030e; (void)x0040030e; gdcm::TagToType<0x0040,0x0310> x00400310; (void)x00400310; gdcm::TagToType<0x0040,0x0312> x00400312; (void)x00400312; gdcm::TagToType<0x0040,0x0314> x00400314; (void)x00400314; gdcm::TagToType<0x0040,0x0316> x00400316; (void)x00400316; gdcm::TagToType<0x0040,0x0318> x00400318; (void)x00400318; gdcm::TagToType<0x0040,0x0320> x00400320; (void)x00400320; gdcm::TagToType<0x0040,0x0321> x00400321; (void)x00400321; gdcm::TagToType<0x0040,0x0324> x00400324; (void)x00400324; gdcm::TagToType<0x0040,0x0330> x00400330; (void)x00400330; gdcm::TagToType<0x0040,0x0340> x00400340; (void)x00400340; gdcm::TagToType<0x0040,0x0400> x00400400; (void)x00400400; gdcm::TagToType<0x0040,0x0440> x00400440; (void)x00400440; gdcm::TagToType<0x0040,0x0441> x00400441; (void)x00400441; gdcm::TagToType<0x0040,0x050a> x0040050a; (void)x0040050a; gdcm::TagToType<0x0040,0x0550> x00400550; (void)x00400550; gdcm::TagToType<0x0040,0x0551> x00400551; (void)x00400551; gdcm::TagToType<0x0040,0x0552> x00400552; (void)x00400552; gdcm::TagToType<0x0040,0x0553> x00400553; (void)x00400553; gdcm::TagToType<0x0040,0x0555> x00400555; (void)x00400555; gdcm::TagToType<0x0040,0x0556> x00400556; (void)x00400556; gdcm::TagToType<0x0040,0x059a> x0040059a; (void)x0040059a; gdcm::TagToType<0x0040,0x06fa> x004006fa; (void)x004006fa; gdcm::TagToType<0x0040,0x071a> x0040071a; (void)x0040071a; gdcm::TagToType<0x0040,0x072a> x0040072a; (void)x0040072a; gdcm::TagToType<0x0040,0x073a> x0040073a; (void)x0040073a; gdcm::TagToType<0x0040,0x074a> x0040074a; (void)x0040074a; gdcm::TagToType<0x0040,0x08d8> x004008d8; (void)x004008d8; gdcm::TagToType<0x0040,0x08da> x004008da; (void)x004008da; gdcm::TagToType<0x0040,0x08ea> x004008ea; (void)x004008ea; gdcm::TagToType<0x0040,0x09f8> x004009f8; (void)x004009f8; gdcm::TagToType<0x0040,0x1001> x00401001; (void)x00401001; gdcm::TagToType<0x0040,0x1002> x00401002; (void)x00401002; gdcm::TagToType<0x0040,0x1003> x00401003; (void)x00401003; gdcm::TagToType<0x0040,0x1004> x00401004; (void)x00401004; gdcm::TagToType<0x0040,0x1005> x00401005; (void)x00401005; gdcm::TagToType<0x0040,0x1006> x00401006; (void)x00401006; gdcm::TagToType<0x0040,0x1007> x00401007; (void)x00401007; gdcm::TagToType<0x0040,0x1008> x00401008; (void)x00401008; gdcm::TagToType<0x0040,0x1009> x00401009; (void)x00401009; gdcm::TagToType<0x0040,0x100a> x0040100a; (void)x0040100a; gdcm::TagToType<0x0040,0x1010> x00401010; (void)x00401010; gdcm::TagToType<0x0040,0x1011> x00401011; (void)x00401011; gdcm::TagToType<0x0040,0x1101> x00401101; (void)x00401101; gdcm::TagToType<0x0040,0x1102> x00401102; (void)x00401102; gdcm::TagToType<0x0040,0x1103> x00401103; (void)x00401103; gdcm::TagToType<0x0040,0x1400> x00401400; (void)x00401400; gdcm::TagToType<0x0040,0x2001> x00402001; (void)x00402001; gdcm::TagToType<0x0040,0x2004> x00402004; (void)x00402004; gdcm::TagToType<0x0040,0x2005> x00402005; (void)x00402005; gdcm::TagToType<0x0040,0x2006> x00402006; (void)x00402006; gdcm::TagToType<0x0040,0x2007> x00402007; (void)x00402007; gdcm::TagToType<0x0040,0x2008> x00402008; (void)x00402008; gdcm::TagToType<0x0040,0x2009> x00402009; (void)x00402009; gdcm::TagToType<0x0040,0x2010> x00402010; (void)x00402010; gdcm::TagToType<0x0040,0x2016> x00402016; (void)x00402016; gdcm::TagToType<0x0040,0x2017> x00402017; (void)x00402017; gdcm::TagToType<0x0040,0x2400> x00402400; (void)x00402400; gdcm::TagToType<0x0040,0x3001> x00403001; (void)x00403001; gdcm::TagToType<0x0040,0x4001> x00404001; (void)x00404001; gdcm::TagToType<0x0040,0x4002> x00404002; (void)x00404002; gdcm::TagToType<0x0040,0x4003> x00404003; (void)x00404003; gdcm::TagToType<0x0040,0x4004> x00404004; (void)x00404004; gdcm::TagToType<0x0040,0x4005> x00404005; (void)x00404005; gdcm::TagToType<0x0040,0x4006> x00404006; (void)x00404006; gdcm::TagToType<0x0040,0x4007> x00404007; (void)x00404007; gdcm::TagToType<0x0040,0x4009> x00404009; (void)x00404009; gdcm::TagToType<0x0040,0x4010> x00404010; (void)x00404010; gdcm::TagToType<0x0040,0x4011> x00404011; (void)x00404011; gdcm::TagToType<0x0040,0x4015> x00404015; (void)x00404015; gdcm::TagToType<0x0040,0x4016> x00404016; (void)x00404016; gdcm::TagToType<0x0040,0x4018> x00404018; (void)x00404018; gdcm::TagToType<0x0040,0x4019> x00404019; (void)x00404019; gdcm::TagToType<0x0040,0x4020> x00404020; (void)x00404020; gdcm::TagToType<0x0040,0x4021> x00404021; (void)x00404021; gdcm::TagToType<0x0040,0x4022> x00404022; (void)x00404022; gdcm::TagToType<0x0040,0x4023> x00404023; (void)x00404023; gdcm::TagToType<0x0040,0x4025> x00404025; (void)x00404025; gdcm::TagToType<0x0040,0x4026> x00404026; (void)x00404026; gdcm::TagToType<0x0040,0x4027> x00404027; (void)x00404027; gdcm::TagToType<0x0040,0x4028> x00404028; (void)x00404028; gdcm::TagToType<0x0040,0x4029> x00404029; (void)x00404029; gdcm::TagToType<0x0040,0x4030> x00404030; (void)x00404030; gdcm::TagToType<0x0040,0x4031> x00404031; (void)x00404031; gdcm::TagToType<0x0040,0x4032> x00404032; (void)x00404032; gdcm::TagToType<0x0040,0x4033> x00404033; (void)x00404033; gdcm::TagToType<0x0040,0x4034> x00404034; (void)x00404034; gdcm::TagToType<0x0040,0x4035> x00404035; (void)x00404035; gdcm::TagToType<0x0040,0x4036> x00404036; (void)x00404036; gdcm::TagToType<0x0040,0x4037> x00404037; (void)x00404037; gdcm::TagToType<0x0040,0x8302> x00408302; (void)x00408302; gdcm::TagToType<0x0040,0x9094> x00409094; (void)x00409094; gdcm::TagToType<0x0040,0x9096> x00409096; (void)x00409096; gdcm::TagToType<0x0040,0x9098> x00409098; (void)x00409098; gdcm::TagToType<0x0040,0x9210> x00409210; (void)x00409210; gdcm::TagToType<0x0040,0x9212> x00409212; (void)x00409212; gdcm::TagToType<0x0040,0x9224> x00409224; (void)x00409224; gdcm::TagToType<0x0040,0x9225> x00409225; (void)x00409225; gdcm::TagToType<0x0040,0xa010> x0040a010; (void)x0040a010; gdcm::TagToType<0x0040,0xa027> x0040a027; (void)x0040a027; gdcm::TagToType<0x0040,0xa030> x0040a030; (void)x0040a030; gdcm::TagToType<0x0040,0xa032> x0040a032; (void)x0040a032; gdcm::TagToType<0x0040,0xa040> x0040a040; (void)x0040a040; gdcm::TagToType<0x0040,0xa043> x0040a043; (void)x0040a043; gdcm::TagToType<0x0040,0xa050> x0040a050; (void)x0040a050; gdcm::TagToType<0x0040,0xa073> x0040a073; (void)x0040a073; gdcm::TagToType<0x0040,0xa075> x0040a075; (void)x0040a075; gdcm::TagToType<0x0040,0xa078> x0040a078; (void)x0040a078; gdcm::TagToType<0x0040,0xa07a> x0040a07a; (void)x0040a07a; gdcm::TagToType<0x0040,0xa07c> x0040a07c; (void)x0040a07c; gdcm::TagToType<0x0040,0xa080> x0040a080; (void)x0040a080; gdcm::TagToType<0x0040,0xa082> x0040a082; (void)x0040a082; gdcm::TagToType<0x0040,0xa084> x0040a084; (void)x0040a084; gdcm::TagToType<0x0040,0xa088> x0040a088; (void)x0040a088; gdcm::TagToType<0x0040,0xa090> x0040a090; (void)x0040a090; gdcm::TagToType<0x0040,0xa0b0> x0040a0b0; (void)x0040a0b0; gdcm::TagToType<0x0040,0xa120> x0040a120; (void)x0040a120; gdcm::TagToType<0x0040,0xa121> x0040a121; (void)x0040a121; gdcm::TagToType<0x0040,0xa122> x0040a122; (void)x0040a122; gdcm::TagToType<0x0040,0xa123> x0040a123; (void)x0040a123; gdcm::TagToType<0x0040,0xa124> x0040a124; (void)x0040a124; gdcm::TagToType<0x0040,0xa130> x0040a130; (void)x0040a130; gdcm::TagToType<0x0040,0xa132> x0040a132; (void)x0040a132; gdcm::TagToType<0x0040,0xa136> x0040a136; (void)x0040a136; gdcm::TagToType<0x0040,0xa138> x0040a138; (void)x0040a138; gdcm::TagToType<0x0040,0xa13a> x0040a13a; (void)x0040a13a; gdcm::TagToType<0x0040,0xa160> x0040a160; (void)x0040a160; gdcm::TagToType<0x0040,0xa168> x0040a168; (void)x0040a168; gdcm::TagToType<0x0040,0xa170> x0040a170; (void)x0040a170; gdcm::TagToType<0x0040,0xa180> x0040a180; (void)x0040a180; gdcm::TagToType<0x0040,0xa195> x0040a195; (void)x0040a195; gdcm::TagToType<0x0040,0xa300> x0040a300; (void)x0040a300; gdcm::TagToType<0x0040,0xa301> x0040a301; (void)x0040a301; gdcm::TagToType<0x0040,0xa30a> x0040a30a; (void)x0040a30a; gdcm::TagToType<0x0040,0xa353> x0040a353; (void)x0040a353; gdcm::TagToType<0x0040,0xa354> x0040a354; (void)x0040a354; gdcm::TagToType<0x0040,0xa360> x0040a360; (void)x0040a360; gdcm::TagToType<0x0040,0xa370> x0040a370; (void)x0040a370; gdcm::TagToType<0x0040,0xa372> x0040a372; (void)x0040a372; gdcm::TagToType<0x0040,0xa375> x0040a375; (void)x0040a375; gdcm::TagToType<0x0040,0xa385> x0040a385; (void)x0040a385; gdcm::TagToType<0x0040,0xa390> x0040a390; (void)x0040a390; gdcm::TagToType<0x0040,0xa491> x0040a491; (void)x0040a491; gdcm::TagToType<0x0040,0xa492> x0040a492; (void)x0040a492; gdcm::TagToType<0x0040,0xa493> x0040a493; (void)x0040a493; gdcm::TagToType<0x0040,0xa494> x0040a494; (void)x0040a494; gdcm::TagToType<0x0040,0xa504> x0040a504; (void)x0040a504; gdcm::TagToType<0x0040,0xa525> x0040a525; (void)x0040a525; gdcm::TagToType<0x0040,0xa730> x0040a730; (void)x0040a730; gdcm::TagToType<0x0040,0xb020> x0040b020; (void)x0040b020; gdcm::TagToType<0x0040,0xdb00> x0040db00; (void)x0040db00; gdcm::TagToType<0x0040,0xdb06> x0040db06; (void)x0040db06; gdcm::TagToType<0x0040,0xdb07> x0040db07; (void)x0040db07; gdcm::TagToType<0x0040,0xdb0b> x0040db0b; (void)x0040db0b; gdcm::TagToType<0x0040,0xdb0c> x0040db0c; (void)x0040db0c; gdcm::TagToType<0x0040,0xdb0d> x0040db0d; (void)x0040db0d; gdcm::TagToType<0x0040,0xdb73> x0040db73; (void)x0040db73; gdcm::TagToType<0x0040,0xe001> x0040e001; (void)x0040e001; gdcm::TagToType<0x0040,0xe004> x0040e004; (void)x0040e004; gdcm::TagToType<0x0040,0xe006> x0040e006; (void)x0040e006; gdcm::TagToType<0x0040,0xe010> x0040e010; (void)x0040e010; gdcm::TagToType<0x0042,0x0010> x00420010; (void)x00420010; gdcm::TagToType<0x0042,0x0011> x00420011; (void)x00420011; gdcm::TagToType<0x0042,0x0012> x00420012; (void)x00420012; gdcm::TagToType<0x0042,0x0013> x00420013; (void)x00420013; gdcm::TagToType<0x0042,0x0014> x00420014; (void)x00420014; gdcm::TagToType<0x0044,0x0001> x00440001; (void)x00440001; gdcm::TagToType<0x0044,0x0002> x00440002; (void)x00440002; gdcm::TagToType<0x0044,0x0003> x00440003; (void)x00440003; gdcm::TagToType<0x0044,0x0004> x00440004; (void)x00440004; gdcm::TagToType<0x0044,0x0007> x00440007; (void)x00440007; gdcm::TagToType<0x0044,0x0008> x00440008; (void)x00440008; gdcm::TagToType<0x0044,0x0009> x00440009; (void)x00440009; gdcm::TagToType<0x0044,0x000a> x0044000a; (void)x0044000a; gdcm::TagToType<0x0044,0x000b> x0044000b; (void)x0044000b; gdcm::TagToType<0x0044,0x0010> x00440010; (void)x00440010; gdcm::TagToType<0x0044,0x0011> x00440011; (void)x00440011; gdcm::TagToType<0x0044,0x0012> x00440012; (void)x00440012; gdcm::TagToType<0x0044,0x0013> x00440013; (void)x00440013; gdcm::TagToType<0x0044,0x0019> x00440019; (void)x00440019; gdcm::TagToType<0x0050,0x0004> x00500004; (void)x00500004; gdcm::TagToType<0x0050,0x0010> x00500010; (void)x00500010; gdcm::TagToType<0x0050,0x0014> x00500014; (void)x00500014; gdcm::TagToType<0x0050,0x0016> x00500016; (void)x00500016; gdcm::TagToType<0x0050,0x0017> x00500017; (void)x00500017; gdcm::TagToType<0x0050,0x0018> x00500018; (void)x00500018; gdcm::TagToType<0x0050,0x0019> x00500019; (void)x00500019; gdcm::TagToType<0x0050,0x0020> x00500020; (void)x00500020; gdcm::TagToType<0x0054,0x0010> x00540010; (void)x00540010; gdcm::TagToType<0x0054,0x0011> x00540011; (void)x00540011; gdcm::TagToType<0x0054,0x0012> x00540012; (void)x00540012; gdcm::TagToType<0x0054,0x0013> x00540013; (void)x00540013; gdcm::TagToType<0x0054,0x0014> x00540014; (void)x00540014; gdcm::TagToType<0x0054,0x0015> x00540015; (void)x00540015; gdcm::TagToType<0x0054,0x0016> x00540016; (void)x00540016; gdcm::TagToType<0x0054,0x0017> x00540017; (void)x00540017; gdcm::TagToType<0x0054,0x0018> x00540018; (void)x00540018; gdcm::TagToType<0x0054,0x0020> x00540020; (void)x00540020; gdcm::TagToType<0x0054,0x0021> x00540021; (void)x00540021; gdcm::TagToType<0x0054,0x0022> x00540022; (void)x00540022; gdcm::TagToType<0x0054,0x0030> x00540030; (void)x00540030; gdcm::TagToType<0x0054,0x0031> x00540031; (void)x00540031; gdcm::TagToType<0x0054,0x0032> x00540032; (void)x00540032; gdcm::TagToType<0x0054,0x0033> x00540033; (void)x00540033; gdcm::TagToType<0x0054,0x0036> x00540036; (void)x00540036; gdcm::TagToType<0x0054,0x0038> x00540038; (void)x00540038; gdcm::TagToType<0x0054,0x0039> x00540039; (void)x00540039; gdcm::TagToType<0x0054,0x0050> x00540050; (void)x00540050; gdcm::TagToType<0x0054,0x0051> x00540051; (void)x00540051; gdcm::TagToType<0x0054,0x0052> x00540052; (void)x00540052; gdcm::TagToType<0x0054,0x0053> x00540053; (void)x00540053; gdcm::TagToType<0x0054,0x0060> x00540060; (void)x00540060; gdcm::TagToType<0x0054,0x0061> x00540061; (void)x00540061; gdcm::TagToType<0x0054,0x0062> x00540062; (void)x00540062; gdcm::TagToType<0x0054,0x0063> x00540063; (void)x00540063; gdcm::TagToType<0x0054,0x0070> x00540070; (void)x00540070; gdcm::TagToType<0x0054,0x0071> x00540071; (void)x00540071; gdcm::TagToType<0x0054,0x0072> x00540072; (void)x00540072; gdcm::TagToType<0x0054,0x0073> x00540073; (void)x00540073; gdcm::TagToType<0x0054,0x0080> x00540080; (void)x00540080; gdcm::TagToType<0x0054,0x0081> x00540081; (void)x00540081; gdcm::TagToType<0x0054,0x0090> x00540090; (void)x00540090; gdcm::TagToType<0x0054,0x0100> x00540100; (void)x00540100; gdcm::TagToType<0x0054,0x0101> x00540101; (void)x00540101; gdcm::TagToType<0x0054,0x0200> x00540200; (void)x00540200; gdcm::TagToType<0x0054,0x0202> x00540202; (void)x00540202; gdcm::TagToType<0x0054,0x0210> x00540210; (void)x00540210; gdcm::TagToType<0x0054,0x0211> x00540211; (void)x00540211; gdcm::TagToType<0x0054,0x0220> x00540220; (void)x00540220; gdcm::TagToType<0x0054,0x0222> x00540222; (void)x00540222; gdcm::TagToType<0x0054,0x0300> x00540300; (void)x00540300; gdcm::TagToType<0x0054,0x0302> x00540302; (void)x00540302; gdcm::TagToType<0x0054,0x0304> x00540304; (void)x00540304; gdcm::TagToType<0x0054,0x0306> x00540306; (void)x00540306; gdcm::TagToType<0x0054,0x0308> x00540308; (void)x00540308; gdcm::TagToType<0x0054,0x0400> x00540400; (void)x00540400; gdcm::TagToType<0x0054,0x0410> x00540410; (void)x00540410; gdcm::TagToType<0x0054,0x0412> x00540412; (void)x00540412; gdcm::TagToType<0x0054,0x0414> x00540414; (void)x00540414; gdcm::TagToType<0x0054,0x0500> x00540500; (void)x00540500; gdcm::TagToType<0x0054,0x1000> x00541000; (void)x00541000; gdcm::TagToType<0x0054,0x1001> x00541001; (void)x00541001; gdcm::TagToType<0x0054,0x1002> x00541002; (void)x00541002; gdcm::TagToType<0x0054,0x1004> x00541004; (void)x00541004; gdcm::TagToType<0x0054,0x1100> x00541100; (void)x00541100; gdcm::TagToType<0x0054,0x1101> x00541101; (void)x00541101; gdcm::TagToType<0x0054,0x1102> x00541102; (void)x00541102; gdcm::TagToType<0x0054,0x1103> x00541103; (void)x00541103; gdcm::TagToType<0x0054,0x1104> x00541104; (void)x00541104; gdcm::TagToType<0x0054,0x1105> x00541105; (void)x00541105; gdcm::TagToType<0x0054,0x1200> x00541200; (void)x00541200; gdcm::TagToType<0x0054,0x1201> x00541201; (void)x00541201; gdcm::TagToType<0x0054,0x1202> x00541202; (void)x00541202; gdcm::TagToType<0x0054,0x1203> x00541203; (void)x00541203; gdcm::TagToType<0x0054,0x1210> x00541210; (void)x00541210; gdcm::TagToType<0x0054,0x1220> x00541220; (void)x00541220; gdcm::TagToType<0x0054,0x1300> x00541300; (void)x00541300; gdcm::TagToType<0x0054,0x1310> x00541310; (void)x00541310; gdcm::TagToType<0x0054,0x1311> x00541311; (void)x00541311; gdcm::TagToType<0x0054,0x1320> x00541320; (void)x00541320; gdcm::TagToType<0x0054,0x1321> x00541321; (void)x00541321; gdcm::TagToType<0x0054,0x1322> x00541322; (void)x00541322; gdcm::TagToType<0x0054,0x1323> x00541323; (void)x00541323; gdcm::TagToType<0x0054,0x1324> x00541324; (void)x00541324; gdcm::TagToType<0x0054,0x1330> x00541330; (void)x00541330; gdcm::TagToType<0x0054,0x1400> x00541400; (void)x00541400; gdcm::TagToType<0x0054,0x1401> x00541401; (void)x00541401; gdcm::TagToType<0x0060,0x3000> x00603000; (void)x00603000; gdcm::TagToType<0x0060,0x3002> x00603002; (void)x00603002; gdcm::TagToType<0x0060,0x3008> x00603008; (void)x00603008; gdcm::TagToType<0x0060,0x3010> x00603010; (void)x00603010; gdcm::TagToType<0x0060,0x3020> x00603020; (void)x00603020; gdcm::TagToType<0x0062,0x0001> x00620001; (void)x00620001; gdcm::TagToType<0x0062,0x0002> x00620002; (void)x00620002; gdcm::TagToType<0x0062,0x0003> x00620003; (void)x00620003; gdcm::TagToType<0x0062,0x0004> x00620004; (void)x00620004; gdcm::TagToType<0x0062,0x0005> x00620005; (void)x00620005; gdcm::TagToType<0x0062,0x0006> x00620006; (void)x00620006; gdcm::TagToType<0x0062,0x0008> x00620008; (void)x00620008; gdcm::TagToType<0x0062,0x0009> x00620009; (void)x00620009; gdcm::TagToType<0x0062,0x000a> x0062000a; (void)x0062000a; gdcm::TagToType<0x0062,0x000b> x0062000b; (void)x0062000b; gdcm::TagToType<0x0062,0x000c> x0062000c; (void)x0062000c; gdcm::TagToType<0x0062,0x000d> x0062000d; (void)x0062000d; gdcm::TagToType<0x0062,0x000e> x0062000e; (void)x0062000e; gdcm::TagToType<0x0062,0x000f> x0062000f; (void)x0062000f; gdcm::TagToType<0x0062,0x0010> x00620010; (void)x00620010; gdcm::TagToType<0x0064,0x0002> x00640002; (void)x00640002; gdcm::TagToType<0x0064,0x0003> x00640003; (void)x00640003; gdcm::TagToType<0x0064,0x0005> x00640005; (void)x00640005; gdcm::TagToType<0x0064,0x0007> x00640007; (void)x00640007; gdcm::TagToType<0x0064,0x0008> x00640008; (void)x00640008; gdcm::TagToType<0x0064,0x0009> x00640009; (void)x00640009; gdcm::TagToType<0x0064,0x000f> x0064000f; (void)x0064000f; gdcm::TagToType<0x0064,0x0010> x00640010; (void)x00640010; gdcm::TagToType<0x0070,0x0001> x00700001; (void)x00700001; gdcm::TagToType<0x0070,0x0002> x00700002; (void)x00700002; gdcm::TagToType<0x0070,0x0003> x00700003; (void)x00700003; gdcm::TagToType<0x0070,0x0004> x00700004; (void)x00700004; gdcm::TagToType<0x0070,0x0005> x00700005; (void)x00700005; gdcm::TagToType<0x0070,0x0006> x00700006; (void)x00700006; gdcm::TagToType<0x0070,0x0008> x00700008; (void)x00700008; gdcm::TagToType<0x0070,0x0009> x00700009; (void)x00700009; gdcm::TagToType<0x0070,0x0010> x00700010; (void)x00700010; gdcm::TagToType<0x0070,0x0011> x00700011; (void)x00700011; gdcm::TagToType<0x0070,0x0012> x00700012; (void)x00700012; gdcm::TagToType<0x0070,0x0014> x00700014; (void)x00700014; gdcm::TagToType<0x0070,0x0015> x00700015; (void)x00700015; gdcm::TagToType<0x0070,0x0020> x00700020; (void)x00700020; gdcm::TagToType<0x0070,0x0021> x00700021; (void)x00700021; gdcm::TagToType<0x0070,0x0022> x00700022; (void)x00700022; gdcm::TagToType<0x0070,0x0023> x00700023; (void)x00700023; gdcm::TagToType<0x0070,0x0024> x00700024; (void)x00700024; gdcm::TagToType<0x0070,0x0040> x00700040; (void)x00700040; gdcm::TagToType<0x0070,0x0041> x00700041; (void)x00700041; gdcm::TagToType<0x0070,0x0042> x00700042; (void)x00700042; gdcm::TagToType<0x0070,0x0050> x00700050; (void)x00700050; gdcm::TagToType<0x0070,0x0051> x00700051; (void)x00700051; gdcm::TagToType<0x0070,0x0052> x00700052; (void)x00700052; gdcm::TagToType<0x0070,0x0053> x00700053; (void)x00700053; gdcm::TagToType<0x0070,0x005a> x0070005a; (void)x0070005a; gdcm::TagToType<0x0070,0x0060> x00700060; (void)x00700060; gdcm::TagToType<0x0070,0x0062> x00700062; (void)x00700062; gdcm::TagToType<0x0070,0x0066> x00700066; (void)x00700066; gdcm::TagToType<0x0070,0x0067> x00700067; (void)x00700067; gdcm::TagToType<0x0070,0x0068> x00700068; (void)x00700068; gdcm::TagToType<0x0070,0x0080> x00700080; (void)x00700080; gdcm::TagToType<0x0070,0x0081> x00700081; (void)x00700081; gdcm::TagToType<0x0070,0x0082> x00700082; (void)x00700082; gdcm::TagToType<0x0070,0x0083> x00700083; (void)x00700083; gdcm::TagToType<0x0070,0x0084> x00700084; (void)x00700084; gdcm::TagToType<0x0070,0x0086> x00700086; (void)x00700086; gdcm::TagToType<0x0070,0x0100> x00700100; (void)x00700100; gdcm::TagToType<0x0070,0x0101> x00700101; (void)x00700101; gdcm::TagToType<0x0070,0x0102> x00700102; (void)x00700102; gdcm::TagToType<0x0070,0x0103> x00700103; (void)x00700103; gdcm::TagToType<0x0070,0x0306> x00700306; (void)x00700306; gdcm::TagToType<0x0070,0x0308> x00700308; (void)x00700308; gdcm::TagToType<0x0070,0x0309> x00700309; (void)x00700309; gdcm::TagToType<0x0070,0x030a> x0070030a; (void)x0070030a; gdcm::TagToType<0x0070,0x030c> x0070030c; (void)x0070030c; gdcm::TagToType<0x0070,0x030d> x0070030d; (void)x0070030d; gdcm::TagToType<0x0070,0x030f> x0070030f; (void)x0070030f; gdcm::TagToType<0x0070,0x0310> x00700310; (void)x00700310; gdcm::TagToType<0x0070,0x0311> x00700311; (void)x00700311; gdcm::TagToType<0x0070,0x0312> x00700312; (void)x00700312; gdcm::TagToType<0x0070,0x0314> x00700314; (void)x00700314; gdcm::TagToType<0x0070,0x0318> x00700318; (void)x00700318; gdcm::TagToType<0x0070,0x031a> x0070031a; (void)x0070031a; gdcm::TagToType<0x0070,0x031c> x0070031c; (void)x0070031c; gdcm::TagToType<0x0070,0x031e> x0070031e; (void)x0070031e; gdcm::TagToType<0x0070,0x0401> x00700401; (void)x00700401; gdcm::TagToType<0x0070,0x0402> x00700402; (void)x00700402; gdcm::TagToType<0x0070,0x0403> x00700403; (void)x00700403; gdcm::TagToType<0x0070,0x0404> x00700404; (void)x00700404; gdcm::TagToType<0x0070,0x0405> x00700405; (void)x00700405; gdcm::TagToType<0x0072,0x0002> x00720002; (void)x00720002; gdcm::TagToType<0x0072,0x0004> x00720004; (void)x00720004; gdcm::TagToType<0x0072,0x0006> x00720006; (void)x00720006; gdcm::TagToType<0x0072,0x0008> x00720008; (void)x00720008; gdcm::TagToType<0x0072,0x000a> x0072000a; (void)x0072000a; gdcm::TagToType<0x0072,0x000c> x0072000c; (void)x0072000c; gdcm::TagToType<0x0072,0x000e> x0072000e; (void)x0072000e; gdcm::TagToType<0x0072,0x0010> x00720010; (void)x00720010; gdcm::TagToType<0x0072,0x0012> x00720012; (void)x00720012; gdcm::TagToType<0x0072,0x0014> x00720014; (void)x00720014; gdcm::TagToType<0x0072,0x0020> x00720020; (void)x00720020; gdcm::TagToType<0x0072,0x0022> x00720022; (void)x00720022; gdcm::TagToType<0x0072,0x0024> x00720024; (void)x00720024; gdcm::TagToType<0x0072,0x0026> x00720026; (void)x00720026; gdcm::TagToType<0x0072,0x0028> x00720028; (void)x00720028; gdcm::TagToType<0x0072,0x0030> x00720030; (void)x00720030; gdcm::TagToType<0x0072,0x0032> x00720032; (void)x00720032; gdcm::TagToType<0x0072,0x0034> x00720034; (void)x00720034; gdcm::TagToType<0x0072,0x0038> x00720038; (void)x00720038; gdcm::TagToType<0x0072,0x003a> x0072003a; (void)x0072003a; gdcm::TagToType<0x0072,0x003c> x0072003c; (void)x0072003c; gdcm::TagToType<0x0072,0x003e> x0072003e; (void)x0072003e; gdcm::TagToType<0x0072,0x0040> x00720040; (void)x00720040; gdcm::TagToType<0x0072,0x0050> x00720050; (void)x00720050; gdcm::TagToType<0x0072,0x0052> x00720052; (void)x00720052; gdcm::TagToType<0x0072,0x0054> x00720054; (void)x00720054; gdcm::TagToType<0x0072,0x0056> x00720056; (void)x00720056; gdcm::TagToType<0x0072,0x0060> x00720060; (void)x00720060; gdcm::TagToType<0x0072,0x0062> x00720062; (void)x00720062; gdcm::TagToType<0x0072,0x0064> x00720064; (void)x00720064; gdcm::TagToType<0x0072,0x0066> x00720066; (void)x00720066; gdcm::TagToType<0x0072,0x0068> x00720068; (void)x00720068; gdcm::TagToType<0x0072,0x006a> x0072006a; (void)x0072006a; gdcm::TagToType<0x0072,0x006c> x0072006c; (void)x0072006c; gdcm::TagToType<0x0072,0x006e> x0072006e; (void)x0072006e; gdcm::TagToType<0x0072,0x0070> x00720070; (void)x00720070; gdcm::TagToType<0x0072,0x0072> x00720072; (void)x00720072; gdcm::TagToType<0x0072,0x0074> x00720074; (void)x00720074; gdcm::TagToType<0x0072,0x0076> x00720076; (void)x00720076; gdcm::TagToType<0x0072,0x0078> x00720078; (void)x00720078; gdcm::TagToType<0x0072,0x007a> x0072007a; (void)x0072007a; gdcm::TagToType<0x0072,0x007c> x0072007c; (void)x0072007c; gdcm::TagToType<0x0072,0x007e> x0072007e; (void)x0072007e; gdcm::TagToType<0x0072,0x0080> x00720080; (void)x00720080; gdcm::TagToType<0x0072,0x0100> x00720100; (void)x00720100; gdcm::TagToType<0x0072,0x0102> x00720102; (void)x00720102; gdcm::TagToType<0x0072,0x0104> x00720104; (void)x00720104; gdcm::TagToType<0x0072,0x0106> x00720106; (void)x00720106; gdcm::TagToType<0x0072,0x0108> x00720108; (void)x00720108; gdcm::TagToType<0x0072,0x010a> x0072010a; (void)x0072010a; gdcm::TagToType<0x0072,0x010c> x0072010c; (void)x0072010c; gdcm::TagToType<0x0072,0x010e> x0072010e; (void)x0072010e; gdcm::TagToType<0x0072,0x0200> x00720200; (void)x00720200; gdcm::TagToType<0x0072,0x0202> x00720202; (void)x00720202; gdcm::TagToType<0x0072,0x0203> x00720203; (void)x00720203; gdcm::TagToType<0x0072,0x0204> x00720204; (void)x00720204; gdcm::TagToType<0x0072,0x0206> x00720206; (void)x00720206; gdcm::TagToType<0x0072,0x0208> x00720208; (void)x00720208; gdcm::TagToType<0x0072,0x0210> x00720210; (void)x00720210; gdcm::TagToType<0x0072,0x0212> x00720212; (void)x00720212; gdcm::TagToType<0x0072,0x0214> x00720214; (void)x00720214; gdcm::TagToType<0x0072,0x0216> x00720216; (void)x00720216; gdcm::TagToType<0x0072,0x0218> x00720218; (void)x00720218; gdcm::TagToType<0x0072,0x0300> x00720300; (void)x00720300; gdcm::TagToType<0x0072,0x0302> x00720302; (void)x00720302; gdcm::TagToType<0x0072,0x0304> x00720304; (void)x00720304; gdcm::TagToType<0x0072,0x0306> x00720306; (void)x00720306; gdcm::TagToType<0x0072,0x0308> x00720308; (void)x00720308; gdcm::TagToType<0x0072,0x0310> x00720310; (void)x00720310; gdcm::TagToType<0x0072,0x0312> x00720312; (void)x00720312; gdcm::TagToType<0x0072,0x0314> x00720314; (void)x00720314; gdcm::TagToType<0x0072,0x0316> x00720316; (void)x00720316; gdcm::TagToType<0x0072,0x0318> x00720318; (void)x00720318; gdcm::TagToType<0x0072,0x0320> x00720320; (void)x00720320; gdcm::TagToType<0x0072,0x0330> x00720330; (void)x00720330; gdcm::TagToType<0x0072,0x0400> x00720400; (void)x00720400; gdcm::TagToType<0x0072,0x0402> x00720402; (void)x00720402; gdcm::TagToType<0x0072,0x0404> x00720404; (void)x00720404; gdcm::TagToType<0x0072,0x0406> x00720406; (void)x00720406; gdcm::TagToType<0x0072,0x0500> x00720500; (void)x00720500; gdcm::TagToType<0x0072,0x0510> x00720510; (void)x00720510; gdcm::TagToType<0x0072,0x0512> x00720512; (void)x00720512; gdcm::TagToType<0x0072,0x0514> x00720514; (void)x00720514; gdcm::TagToType<0x0072,0x0516> x00720516; (void)x00720516; gdcm::TagToType<0x0072,0x0520> x00720520; (void)x00720520; gdcm::TagToType<0x0072,0x0600> x00720600; (void)x00720600; gdcm::TagToType<0x0072,0x0602> x00720602; (void)x00720602; gdcm::TagToType<0x0072,0x0604> x00720604; (void)x00720604; gdcm::TagToType<0x0072,0x0700> x00720700; (void)x00720700; gdcm::TagToType<0x0072,0x0702> x00720702; (void)x00720702; gdcm::TagToType<0x0072,0x0704> x00720704; (void)x00720704; gdcm::TagToType<0x0072,0x0706> x00720706; (void)x00720706; gdcm::TagToType<0x0072,0x0710> x00720710; (void)x00720710; gdcm::TagToType<0x0072,0x0712> x00720712; (void)x00720712; gdcm::TagToType<0x0072,0x0714> x00720714; (void)x00720714; gdcm::TagToType<0x0072,0x0716> x00720716; (void)x00720716; gdcm::TagToType<0x0072,0x0717> x00720717; (void)x00720717; gdcm::TagToType<0x0072,0x0718> x00720718; (void)x00720718; gdcm::TagToType<0x0074,0x1000> x00741000; (void)x00741000; gdcm::TagToType<0x0074,0x1002> x00741002; (void)x00741002; gdcm::TagToType<0x0074,0x1004> x00741004; (void)x00741004; gdcm::TagToType<0x0074,0x1006> x00741006; (void)x00741006; gdcm::TagToType<0x0074,0x1008> x00741008; (void)x00741008; gdcm::TagToType<0x0074,0x100a> x0074100a; (void)x0074100a; gdcm::TagToType<0x0074,0x100c> x0074100c; (void)x0074100c; gdcm::TagToType<0x0074,0x100e> x0074100e; (void)x0074100e; gdcm::TagToType<0x0074,0x1020> x00741020; (void)x00741020; gdcm::TagToType<0x0074,0x1022> x00741022; (void)x00741022; gdcm::TagToType<0x0074,0x1024> x00741024; (void)x00741024; gdcm::TagToType<0x0074,0x1030> x00741030; (void)x00741030; gdcm::TagToType<0x0074,0x1032> x00741032; (void)x00741032; gdcm::TagToType<0x0074,0x1034> x00741034; (void)x00741034; gdcm::TagToType<0x0074,0x1036> x00741036; (void)x00741036; gdcm::TagToType<0x0074,0x1038> x00741038; (void)x00741038; gdcm::TagToType<0x0074,0x103a> x0074103a; (void)x0074103a; gdcm::TagToType<0x0074,0x1040> x00741040; (void)x00741040; gdcm::TagToType<0x0074,0x1042> x00741042; (void)x00741042; gdcm::TagToType<0x0074,0x1044> x00741044; (void)x00741044; gdcm::TagToType<0x0074,0x1046> x00741046; (void)x00741046; gdcm::TagToType<0x0074,0x1048> x00741048; (void)x00741048; gdcm::TagToType<0x0074,0x104a> x0074104a; (void)x0074104a; gdcm::TagToType<0x0074,0x104c> x0074104c; (void)x0074104c; gdcm::TagToType<0x0074,0x104e> x0074104e; (void)x0074104e; gdcm::TagToType<0x0074,0x1050> x00741050; (void)x00741050; gdcm::TagToType<0x0074,0x1052> x00741052; (void)x00741052; gdcm::TagToType<0x0074,0x1054> x00741054; (void)x00741054; gdcm::TagToType<0x0074,0x1056> x00741056; (void)x00741056; gdcm::TagToType<0x0074,0x1200> x00741200; (void)x00741200; gdcm::TagToType<0x0074,0x1202> x00741202; (void)x00741202; gdcm::TagToType<0x0074,0x1204> x00741204; (void)x00741204; gdcm::TagToType<0x0074,0x1210> x00741210; (void)x00741210; gdcm::TagToType<0x0074,0x1212> x00741212; (void)x00741212; gdcm::TagToType<0x0074,0x1216> x00741216; (void)x00741216; gdcm::TagToType<0x0074,0x1220> x00741220; (void)x00741220; gdcm::TagToType<0x0074,0x1222> x00741222; (void)x00741222; gdcm::TagToType<0x0074,0x1230> x00741230; (void)x00741230; gdcm::TagToType<0x0074,0x1234> x00741234; (void)x00741234; gdcm::TagToType<0x0074,0x1236> x00741236; (void)x00741236; gdcm::TagToType<0x0074,0x1238> x00741238; (void)x00741238; gdcm::TagToType<0x0074,0x1242> x00741242; (void)x00741242; gdcm::TagToType<0x0074,0x1244> x00741244; (void)x00741244; gdcm::TagToType<0x0074,0x1246> x00741246; (void)x00741246; gdcm::TagToType<0x0088,0x0130> x00880130; (void)x00880130; gdcm::TagToType<0x0088,0x0140> x00880140; (void)x00880140; gdcm::TagToType<0x0088,0x0200> x00880200; (void)x00880200; gdcm::TagToType<0x0088,0x0904> x00880904; (void)x00880904; gdcm::TagToType<0x0088,0x0906> x00880906; (void)x00880906; gdcm::TagToType<0x0088,0x0910> x00880910; (void)x00880910; gdcm::TagToType<0x0088,0x0912> x00880912; (void)x00880912; gdcm::TagToType<0x0100,0x0410> x01000410; (void)x01000410; gdcm::TagToType<0x0100,0x0420> x01000420; (void)x01000420; gdcm::TagToType<0x0100,0x0424> x01000424; (void)x01000424; gdcm::TagToType<0x0100,0x0426> x01000426; (void)x01000426; gdcm::TagToType<0x0400,0x0005> x04000005; (void)x04000005; gdcm::TagToType<0x0400,0x0010> x04000010; (void)x04000010; gdcm::TagToType<0x0400,0x0015> x04000015; (void)x04000015; gdcm::TagToType<0x0400,0x0020> x04000020; (void)x04000020; gdcm::TagToType<0x0400,0x0100> x04000100; (void)x04000100; gdcm::TagToType<0x0400,0x0105> x04000105; (void)x04000105; gdcm::TagToType<0x0400,0x0110> x04000110; (void)x04000110; gdcm::TagToType<0x0400,0x0115> x04000115; (void)x04000115; gdcm::TagToType<0x0400,0x0120> x04000120; (void)x04000120; gdcm::TagToType<0x0400,0x0305> x04000305; (void)x04000305; gdcm::TagToType<0x0400,0x0310> x04000310; (void)x04000310; gdcm::TagToType<0x0400,0x0401> x04000401; (void)x04000401; gdcm::TagToType<0x0400,0x0402> x04000402; (void)x04000402; gdcm::TagToType<0x0400,0x0403> x04000403; (void)x04000403; gdcm::TagToType<0x0400,0x0404> x04000404; (void)x04000404; gdcm::TagToType<0x0400,0x0500> x04000500; (void)x04000500; gdcm::TagToType<0x0400,0x0510> x04000510; (void)x04000510; gdcm::TagToType<0x0400,0x0520> x04000520; (void)x04000520; gdcm::TagToType<0x0400,0x0550> x04000550; (void)x04000550; gdcm::TagToType<0x0400,0x0561> x04000561; (void)x04000561; gdcm::TagToType<0x0400,0x0562> x04000562; (void)x04000562; gdcm::TagToType<0x0400,0x0563> x04000563; (void)x04000563; gdcm::TagToType<0x0400,0x0564> x04000564; (void)x04000564; gdcm::TagToType<0x0400,0x0565> x04000565; (void)x04000565; gdcm::TagToType<0x2000,0x0010> x20000010; (void)x20000010; gdcm::TagToType<0x2000,0x001e> x2000001e; (void)x2000001e; gdcm::TagToType<0x2000,0x0020> x20000020; (void)x20000020; gdcm::TagToType<0x2000,0x0030> x20000030; (void)x20000030; gdcm::TagToType<0x2000,0x0040> x20000040; (void)x20000040; gdcm::TagToType<0x2000,0x0050> x20000050; (void)x20000050; gdcm::TagToType<0x2000,0x0060> x20000060; (void)x20000060; gdcm::TagToType<0x2000,0x0061> x20000061; (void)x20000061; gdcm::TagToType<0x2000,0x0062> x20000062; (void)x20000062; gdcm::TagToType<0x2000,0x0063> x20000063; (void)x20000063; gdcm::TagToType<0x2000,0x0065> x20000065; (void)x20000065; gdcm::TagToType<0x2000,0x0067> x20000067; (void)x20000067; gdcm::TagToType<0x2000,0x0069> x20000069; (void)x20000069; gdcm::TagToType<0x2000,0x006a> x2000006a; (void)x2000006a; gdcm::TagToType<0x2000,0x00a0> x200000a0; (void)x200000a0; gdcm::TagToType<0x2000,0x00a1> x200000a1; (void)x200000a1; gdcm::TagToType<0x2000,0x00a2> x200000a2; (void)x200000a2; gdcm::TagToType<0x2000,0x00a4> x200000a4; (void)x200000a4; gdcm::TagToType<0x2000,0x00a8> x200000a8; (void)x200000a8; gdcm::TagToType<0x2000,0x0500> x20000500; (void)x20000500; gdcm::TagToType<0x2000,0x0510> x20000510; (void)x20000510; gdcm::TagToType<0x2010,0x0010> x20100010; (void)x20100010; gdcm::TagToType<0x2010,0x0030> x20100030; (void)x20100030; gdcm::TagToType<0x2010,0x0040> x20100040; (void)x20100040; gdcm::TagToType<0x2010,0x0050> x20100050; (void)x20100050; gdcm::TagToType<0x2010,0x0052> x20100052; (void)x20100052; gdcm::TagToType<0x2010,0x0054> x20100054; (void)x20100054; gdcm::TagToType<0x2010,0x0060> x20100060; (void)x20100060; gdcm::TagToType<0x2010,0x0080> x20100080; (void)x20100080; gdcm::TagToType<0x2010,0x00a6> x201000a6; (void)x201000a6; gdcm::TagToType<0x2010,0x00a7> x201000a7; (void)x201000a7; gdcm::TagToType<0x2010,0x00a8> x201000a8; (void)x201000a8; gdcm::TagToType<0x2010,0x00a9> x201000a9; (void)x201000a9; gdcm::TagToType<0x2010,0x0100> x20100100; (void)x20100100; gdcm::TagToType<0x2010,0x0110> x20100110; (void)x20100110; gdcm::TagToType<0x2010,0x0120> x20100120; (void)x20100120; gdcm::TagToType<0x2010,0x0130> x20100130; (void)x20100130; gdcm::TagToType<0x2010,0x0140> x20100140; (void)x20100140; gdcm::TagToType<0x2010,0x0150> x20100150; (void)x20100150; gdcm::TagToType<0x2010,0x0152> x20100152; (void)x20100152; gdcm::TagToType<0x2010,0x0154> x20100154; (void)x20100154; gdcm::TagToType<0x2010,0x015e> x2010015e; (void)x2010015e; gdcm::TagToType<0x2010,0x0160> x20100160; (void)x20100160; gdcm::TagToType<0x2010,0x0376> x20100376; (void)x20100376; gdcm::TagToType<0x2010,0x0500> x20100500; (void)x20100500; gdcm::TagToType<0x2010,0x0510> x20100510; (void)x20100510; gdcm::TagToType<0x2010,0x0520> x20100520; (void)x20100520; gdcm::TagToType<0x2020,0x0010> x20200010; (void)x20200010; gdcm::TagToType<0x2020,0x0020> x20200020; (void)x20200020; gdcm::TagToType<0x2020,0x0030> x20200030; (void)x20200030; gdcm::TagToType<0x2020,0x0040> x20200040; (void)x20200040; gdcm::TagToType<0x2020,0x0050> x20200050; (void)x20200050; gdcm::TagToType<0x2020,0x00a0> x202000a0; (void)x202000a0; gdcm::TagToType<0x2020,0x00a2> x202000a2; (void)x202000a2; gdcm::TagToType<0x2020,0x0110> x20200110; (void)x20200110; gdcm::TagToType<0x2020,0x0111> x20200111; (void)x20200111; gdcm::TagToType<0x2020,0x0130> x20200130; (void)x20200130; gdcm::TagToType<0x2020,0x0140> x20200140; (void)x20200140; gdcm::TagToType<0x2030,0x0010> x20300010; (void)x20300010; gdcm::TagToType<0x2030,0x0020> x20300020; (void)x20300020; gdcm::TagToType<0x2040,0x0010> x20400010; (void)x20400010; gdcm::TagToType<0x2040,0x0011> x20400011; (void)x20400011; gdcm::TagToType<0x2040,0x0020> x20400020; (void)x20400020; gdcm::TagToType<0x2040,0x0060> x20400060; (void)x20400060; gdcm::TagToType<0x2040,0x0070> x20400070; (void)x20400070; gdcm::TagToType<0x2040,0x0072> x20400072; (void)x20400072; gdcm::TagToType<0x2040,0x0074> x20400074; (void)x20400074; gdcm::TagToType<0x2040,0x0080> x20400080; (void)x20400080; gdcm::TagToType<0x2040,0x0082> x20400082; (void)x20400082; gdcm::TagToType<0x2040,0x0090> x20400090; (void)x20400090; gdcm::TagToType<0x2040,0x0100> x20400100; (void)x20400100; gdcm::TagToType<0x2040,0x0500> x20400500; (void)x20400500; gdcm::TagToType<0x2050,0x0010> x20500010; (void)x20500010; gdcm::TagToType<0x2050,0x0020> x20500020; (void)x20500020; gdcm::TagToType<0x2050,0x0500> x20500500; (void)x20500500; gdcm::TagToType<0x2100,0x0010> x21000010; (void)x21000010; gdcm::TagToType<0x2100,0x0020> x21000020; (void)x21000020; gdcm::TagToType<0x2100,0x0030> x21000030; (void)x21000030; gdcm::TagToType<0x2100,0x0040> x21000040; (void)x21000040; gdcm::TagToType<0x2100,0x0050> x21000050; (void)x21000050; gdcm::TagToType<0x2100,0x0070> x21000070; (void)x21000070; gdcm::TagToType<0x2100,0x0140> x21000140; (void)x21000140; gdcm::TagToType<0x2100,0x0160> x21000160; (void)x21000160; gdcm::TagToType<0x2100,0x0170> x21000170; (void)x21000170; gdcm::TagToType<0x2100,0x0500> x21000500; (void)x21000500; gdcm::TagToType<0x2110,0x0010> x21100010; (void)x21100010; gdcm::TagToType<0x2110,0x0020> x21100020; (void)x21100020; gdcm::TagToType<0x2110,0x0030> x21100030; (void)x21100030; gdcm::TagToType<0x2110,0x0099> x21100099; (void)x21100099; gdcm::TagToType<0x2120,0x0010> x21200010; (void)x21200010; gdcm::TagToType<0x2120,0x0050> x21200050; (void)x21200050; gdcm::TagToType<0x2120,0x0070> x21200070; (void)x21200070; gdcm::TagToType<0x2130,0x0010> x21300010; (void)x21300010; gdcm::TagToType<0x2130,0x0015> x21300015; (void)x21300015; gdcm::TagToType<0x2130,0x0030> x21300030; (void)x21300030; gdcm::TagToType<0x2130,0x0040> x21300040; (void)x21300040; gdcm::TagToType<0x2130,0x0050> x21300050; (void)x21300050; gdcm::TagToType<0x2130,0x0060> x21300060; (void)x21300060; gdcm::TagToType<0x2130,0x0080> x21300080; (void)x21300080; gdcm::TagToType<0x2130,0x00a0> x213000a0; (void)x213000a0; gdcm::TagToType<0x2130,0x00c0> x213000c0; (void)x213000c0; gdcm::TagToType<0x2200,0x0001> x22000001; (void)x22000001; gdcm::TagToType<0x2200,0x0002> x22000002; (void)x22000002; gdcm::TagToType<0x2200,0x0003> x22000003; (void)x22000003; gdcm::TagToType<0x2200,0x0004> x22000004; (void)x22000004; gdcm::TagToType<0x2200,0x0005> x22000005; (void)x22000005; gdcm::TagToType<0x2200,0x0006> x22000006; (void)x22000006; gdcm::TagToType<0x2200,0x0007> x22000007; (void)x22000007; gdcm::TagToType<0x2200,0x0008> x22000008; (void)x22000008; gdcm::TagToType<0x2200,0x0009> x22000009; (void)x22000009; gdcm::TagToType<0x2200,0x000a> x2200000a; (void)x2200000a; gdcm::TagToType<0x2200,0x000b> x2200000b; (void)x2200000b; gdcm::TagToType<0x2200,0x000c> x2200000c; (void)x2200000c; gdcm::TagToType<0x2200,0x000d> x2200000d; (void)x2200000d; gdcm::TagToType<0x2200,0x000e> x2200000e; (void)x2200000e; gdcm::TagToType<0x2200,0x000f> x2200000f; (void)x2200000f; gdcm::TagToType<0x2200,0x0020> x22000020; (void)x22000020; gdcm::TagToType<0x3002,0x0002> x30020002; (void)x30020002; gdcm::TagToType<0x3002,0x0003> x30020003; (void)x30020003; gdcm::TagToType<0x3002,0x0004> x30020004; (void)x30020004; gdcm::TagToType<0x3002,0x000a> x3002000a; (void)x3002000a; gdcm::TagToType<0x3002,0x000c> x3002000c; (void)x3002000c; gdcm::TagToType<0x3002,0x000d> x3002000d; (void)x3002000d; gdcm::TagToType<0x3002,0x000e> x3002000e; (void)x3002000e; gdcm::TagToType<0x3002,0x0010> x30020010; (void)x30020010; gdcm::TagToType<0x3002,0x0011> x30020011; (void)x30020011; gdcm::TagToType<0x3002,0x0012> x30020012; (void)x30020012; gdcm::TagToType<0x3002,0x0020> x30020020; (void)x30020020; gdcm::TagToType<0x3002,0x0022> x30020022; (void)x30020022; gdcm::TagToType<0x3002,0x0024> x30020024; (void)x30020024; gdcm::TagToType<0x3002,0x0026> x30020026; (void)x30020026; gdcm::TagToType<0x3002,0x0028> x30020028; (void)x30020028; gdcm::TagToType<0x3002,0x0029> x30020029; (void)x30020029; gdcm::TagToType<0x3002,0x0030> x30020030; (void)x30020030; gdcm::TagToType<0x3002,0x0032> x30020032; (void)x30020032; gdcm::TagToType<0x3002,0x0034> x30020034; (void)x30020034; gdcm::TagToType<0x3002,0x0040> x30020040; (void)x30020040; gdcm::TagToType<0x3002,0x0041> x30020041; (void)x30020041; gdcm::TagToType<0x3002,0x0042> x30020042; (void)x30020042; gdcm::TagToType<0x3004,0x0001> x30040001; (void)x30040001; gdcm::TagToType<0x3004,0x0002> x30040002; (void)x30040002; gdcm::TagToType<0x3004,0x0004> x30040004; (void)x30040004; gdcm::TagToType<0x3004,0x0006> x30040006; (void)x30040006; gdcm::TagToType<0x3004,0x0008> x30040008; (void)x30040008; gdcm::TagToType<0x3004,0x000a> x3004000a; (void)x3004000a; gdcm::TagToType<0x3004,0x000c> x3004000c; (void)x3004000c; gdcm::TagToType<0x3004,0x000e> x3004000e; (void)x3004000e; gdcm::TagToType<0x3004,0x0010> x30040010; (void)x30040010; gdcm::TagToType<0x3004,0x0012> x30040012; (void)x30040012; gdcm::TagToType<0x3004,0x0014> x30040014; (void)x30040014; gdcm::TagToType<0x3004,0x0040> x30040040; (void)x30040040; gdcm::TagToType<0x3004,0x0042> x30040042; (void)x30040042; gdcm::TagToType<0x3004,0x0050> x30040050; (void)x30040050; gdcm::TagToType<0x3004,0x0052> x30040052; (void)x30040052; gdcm::TagToType<0x3004,0x0054> x30040054; (void)x30040054; gdcm::TagToType<0x3004,0x0056> x30040056; (void)x30040056; gdcm::TagToType<0x3004,0x0058> x30040058; (void)x30040058; gdcm::TagToType<0x3004,0x0060> x30040060; (void)x30040060; gdcm::TagToType<0x3004,0x0062> x30040062; (void)x30040062; gdcm::TagToType<0x3004,0x0070> x30040070; (void)x30040070; gdcm::TagToType<0x3004,0x0072> x30040072; (void)x30040072; gdcm::TagToType<0x3004,0x0074> x30040074; (void)x30040074; gdcm::TagToType<0x3006,0x0002> x30060002; (void)x30060002; gdcm::TagToType<0x3006,0x0004> x30060004; (void)x30060004; gdcm::TagToType<0x3006,0x0006> x30060006; (void)x30060006; gdcm::TagToType<0x3006,0x0008> x30060008; (void)x30060008; gdcm::TagToType<0x3006,0x0009> x30060009; (void)x30060009; gdcm::TagToType<0x3006,0x0010> x30060010; (void)x30060010; gdcm::TagToType<0x3006,0x0012> x30060012; (void)x30060012; gdcm::TagToType<0x3006,0x0014> x30060014; (void)x30060014; gdcm::TagToType<0x3006,0x0016> x30060016; (void)x30060016; gdcm::TagToType<0x3006,0x0020> x30060020; (void)x30060020; gdcm::TagToType<0x3006,0x0022> x30060022; (void)x30060022; gdcm::TagToType<0x3006,0x0024> x30060024; (void)x30060024; gdcm::TagToType<0x3006,0x0026> x30060026; (void)x30060026; gdcm::TagToType<0x3006,0x0028> x30060028; (void)x30060028; gdcm::TagToType<0x3006,0x002a> x3006002a; (void)x3006002a; gdcm::TagToType<0x3006,0x002c> x3006002c; (void)x3006002c; gdcm::TagToType<0x3006,0x0030> x30060030; (void)x30060030; gdcm::TagToType<0x3006,0x0033> x30060033; (void)x30060033; gdcm::TagToType<0x3006,0x0036> x30060036; (void)x30060036; gdcm::TagToType<0x3006,0x0038> x30060038; (void)x30060038; gdcm::TagToType<0x3006,0x0039> x30060039; (void)x30060039; gdcm::TagToType<0x3006,0x0040> x30060040; (void)x30060040; gdcm::TagToType<0x3006,0x0042> x30060042; (void)x30060042; gdcm::TagToType<0x3006,0x0044> x30060044; (void)x30060044; gdcm::TagToType<0x3006,0x0045> x30060045; (void)x30060045; gdcm::TagToType<0x3006,0x0046> x30060046; (void)x30060046; gdcm::TagToType<0x3006,0x0048> x30060048; (void)x30060048; gdcm::TagToType<0x3006,0x0049> x30060049; (void)x30060049; gdcm::TagToType<0x3006,0x0050> x30060050; (void)x30060050; gdcm::TagToType<0x3006,0x0080> x30060080; (void)x30060080; gdcm::TagToType<0x3006,0x0082> x30060082; (void)x30060082; gdcm::TagToType<0x3006,0x0084> x30060084; (void)x30060084; gdcm::TagToType<0x3006,0x0085> x30060085; (void)x30060085; gdcm::TagToType<0x3006,0x0086> x30060086; (void)x30060086; gdcm::TagToType<0x3006,0x0088> x30060088; (void)x30060088; gdcm::TagToType<0x3006,0x00a0> x300600a0; (void)x300600a0; gdcm::TagToType<0x3006,0x00a4> x300600a4; (void)x300600a4; gdcm::TagToType<0x3006,0x00a6> x300600a6; (void)x300600a6; gdcm::TagToType<0x3006,0x00b0> x300600b0; (void)x300600b0; gdcm::TagToType<0x3006,0x00b2> x300600b2; (void)x300600b2; gdcm::TagToType<0x3006,0x00b4> x300600b4; (void)x300600b4; gdcm::TagToType<0x3006,0x00b6> x300600b6; (void)x300600b6; gdcm::TagToType<0x3006,0x00b7> x300600b7; (void)x300600b7; gdcm::TagToType<0x3006,0x00b8> x300600b8; (void)x300600b8; gdcm::TagToType<0x3006,0x00c0> x300600c0; (void)x300600c0; gdcm::TagToType<0x3006,0x00c2> x300600c2; (void)x300600c2; gdcm::TagToType<0x3006,0x00c4> x300600c4; (void)x300600c4; gdcm::TagToType<0x3006,0x00c6> x300600c6; (void)x300600c6; gdcm::TagToType<0x3006,0x00c8> x300600c8; (void)x300600c8; gdcm::TagToType<0x3008,0x0010> x30080010; (void)x30080010; gdcm::TagToType<0x3008,0x0012> x30080012; (void)x30080012; gdcm::TagToType<0x3008,0x0014> x30080014; (void)x30080014; gdcm::TagToType<0x3008,0x0016> x30080016; (void)x30080016; gdcm::TagToType<0x3008,0x0020> x30080020; (void)x30080020; gdcm::TagToType<0x3008,0x0021> x30080021; (void)x30080021; gdcm::TagToType<0x3008,0x0022> x30080022; (void)x30080022; gdcm::TagToType<0x3008,0x0024> x30080024; (void)x30080024; gdcm::TagToType<0x3008,0x0025> x30080025; (void)x30080025; gdcm::TagToType<0x3008,0x002a> x3008002a; (void)x3008002a; gdcm::TagToType<0x3008,0x002b> x3008002b; (void)x3008002b; gdcm::TagToType<0x3008,0x002c> x3008002c; (void)x3008002c; gdcm::TagToType<0x3008,0x0030> x30080030; (void)x30080030; gdcm::TagToType<0x3008,0x0032> x30080032; (void)x30080032; gdcm::TagToType<0x3008,0x0033> x30080033; (void)x30080033; gdcm::TagToType<0x3008,0x0036> x30080036; (void)x30080036; gdcm::TagToType<0x3008,0x0037> x30080037; (void)x30080037; gdcm::TagToType<0x3008,0x003a> x3008003a; (void)x3008003a; gdcm::TagToType<0x3008,0x003b> x3008003b; (void)x3008003b; gdcm::TagToType<0x3008,0x0040> x30080040; (void)x30080040; gdcm::TagToType<0x3008,0x0041> x30080041; (void)x30080041; gdcm::TagToType<0x3008,0x0042> x30080042; (void)x30080042; gdcm::TagToType<0x3008,0x0044> x30080044; (void)x30080044; gdcm::TagToType<0x3008,0x0045> x30080045; (void)x30080045; gdcm::TagToType<0x3008,0x0046> x30080046; (void)x30080046; gdcm::TagToType<0x3008,0x0047> x30080047; (void)x30080047; gdcm::TagToType<0x3008,0x0048> x30080048; (void)x30080048; gdcm::TagToType<0x3008,0x0050> x30080050; (void)x30080050; gdcm::TagToType<0x3008,0x0052> x30080052; (void)x30080052; gdcm::TagToType<0x3008,0x0054> x30080054; (void)x30080054; gdcm::TagToType<0x3008,0x0056> x30080056; (void)x30080056; gdcm::TagToType<0x3008,0x005a> x3008005a; (void)x3008005a; gdcm::TagToType<0x3008,0x0060> x30080060; (void)x30080060; gdcm::TagToType<0x3008,0x0061> x30080061; (void)x30080061; gdcm::TagToType<0x3008,0x0062> x30080062; (void)x30080062; gdcm::TagToType<0x3008,0x0063> x30080063; (void)x30080063; gdcm::TagToType<0x3008,0x0064> x30080064; (void)x30080064; gdcm::TagToType<0x3008,0x0065> x30080065; (void)x30080065; gdcm::TagToType<0x3008,0x0066> x30080066; (void)x30080066; gdcm::TagToType<0x3008,0x0068> x30080068; (void)x30080068; gdcm::TagToType<0x3008,0x006a> x3008006a; (void)x3008006a; gdcm::TagToType<0x3008,0x0070> x30080070; (void)x30080070; gdcm::TagToType<0x3008,0x0072> x30080072; (void)x30080072; gdcm::TagToType<0x3008,0x0074> x30080074; (void)x30080074; gdcm::TagToType<0x3008,0x0076> x30080076; (void)x30080076; gdcm::TagToType<0x3008,0x0078> x30080078; (void)x30080078; gdcm::TagToType<0x3008,0x007a> x3008007a; (void)x3008007a; gdcm::TagToType<0x3008,0x0080> x30080080; (void)x30080080; gdcm::TagToType<0x3008,0x0082> x30080082; (void)x30080082; gdcm::TagToType<0x3008,0x0090> x30080090; (void)x30080090; gdcm::TagToType<0x3008,0x0092> x30080092; (void)x30080092; gdcm::TagToType<0x3008,0x00a0> x300800a0; (void)x300800a0; gdcm::TagToType<0x3008,0x00b0> x300800b0; (void)x300800b0; gdcm::TagToType<0x3008,0x00c0> x300800c0; (void)x300800c0; gdcm::TagToType<0x3008,0x00d0> x300800d0; (void)x300800d0; gdcm::TagToType<0x3008,0x00e0> x300800e0; (void)x300800e0; gdcm::TagToType<0x3008,0x00f0> x300800f0; (void)x300800f0; gdcm::TagToType<0x3008,0x00f2> x300800f2; (void)x300800f2; gdcm::TagToType<0x3008,0x00f4> x300800f4; (void)x300800f4; gdcm::TagToType<0x3008,0x00f6> x300800f6; (void)x300800f6; gdcm::TagToType<0x3008,0x0100> x30080100; (void)x30080100; gdcm::TagToType<0x3008,0x0105> x30080105; (void)x30080105; gdcm::TagToType<0x3008,0x0110> x30080110; (void)x30080110; gdcm::TagToType<0x3008,0x0116> x30080116; (void)x30080116; gdcm::TagToType<0x3008,0x0120> x30080120; (void)x30080120; gdcm::TagToType<0x3008,0x0122> x30080122; (void)x30080122; gdcm::TagToType<0x3008,0x0130> x30080130; (void)x30080130; gdcm::TagToType<0x3008,0x0132> x30080132; (void)x30080132; gdcm::TagToType<0x3008,0x0134> x30080134; (void)x30080134; gdcm::TagToType<0x3008,0x0136> x30080136; (void)x30080136; gdcm::TagToType<0x3008,0x0138> x30080138; (void)x30080138; gdcm::TagToType<0x3008,0x013a> x3008013a; (void)x3008013a; gdcm::TagToType<0x3008,0x013c> x3008013c; (void)x3008013c; gdcm::TagToType<0x3008,0x0140> x30080140; (void)x30080140; gdcm::TagToType<0x3008,0x0142> x30080142; (void)x30080142; gdcm::TagToType<0x3008,0x0150> x30080150; (void)x30080150; gdcm::TagToType<0x3008,0x0152> x30080152; (void)x30080152; gdcm::TagToType<0x3008,0x0160> x30080160; (void)x30080160; gdcm::TagToType<0x3008,0x0162> x30080162; (void)x30080162; gdcm::TagToType<0x3008,0x0164> x30080164; (void)x30080164; gdcm::TagToType<0x3008,0x0166> x30080166; (void)x30080166; gdcm::TagToType<0x3008,0x0168> x30080168; (void)x30080168; gdcm::TagToType<0x3008,0x0200> x30080200; (void)x30080200; gdcm::TagToType<0x3008,0x0202> x30080202; (void)x30080202; gdcm::TagToType<0x3008,0x0220> x30080220; (void)x30080220; gdcm::TagToType<0x3008,0x0223> x30080223; (void)x30080223; gdcm::TagToType<0x3008,0x0224> x30080224; (void)x30080224; gdcm::TagToType<0x3008,0x0230> x30080230; (void)x30080230; gdcm::TagToType<0x3008,0x0240> x30080240; (void)x30080240; gdcm::TagToType<0x3008,0x0250> x30080250; (void)x30080250; gdcm::TagToType<0x3008,0x0251> x30080251; (void)x30080251; gdcm::TagToType<0x300a,0x0002> x300a0002; (void)x300a0002; gdcm::TagToType<0x300a,0x0003> x300a0003; (void)x300a0003; gdcm::TagToType<0x300a,0x0004> x300a0004; (void)x300a0004; gdcm::TagToType<0x300a,0x0006> x300a0006; (void)x300a0006; gdcm::TagToType<0x300a,0x0007> x300a0007; (void)x300a0007; gdcm::TagToType<0x300a,0x0009> x300a0009; (void)x300a0009; gdcm::TagToType<0x300a,0x000a> x300a000a; (void)x300a000a; gdcm::TagToType<0x300a,0x000b> x300a000b; (void)x300a000b; gdcm::TagToType<0x300a,0x000c> x300a000c; (void)x300a000c; gdcm::TagToType<0x300a,0x000e> x300a000e; (void)x300a000e; gdcm::TagToType<0x300a,0x0010> x300a0010; (void)x300a0010; gdcm::TagToType<0x300a,0x0012> x300a0012; (void)x300a0012; gdcm::TagToType<0x300a,0x0013> x300a0013; (void)x300a0013; gdcm::TagToType<0x300a,0x0014> x300a0014; (void)x300a0014; gdcm::TagToType<0x300a,0x0015> x300a0015; (void)x300a0015; gdcm::TagToType<0x300a,0x0016> x300a0016; (void)x300a0016; gdcm::TagToType<0x300a,0x0018> x300a0018; (void)x300a0018; gdcm::TagToType<0x300a,0x001a> x300a001a; (void)x300a001a; gdcm::TagToType<0x300a,0x0020> x300a0020; (void)x300a0020; gdcm::TagToType<0x300a,0x0021> x300a0021; (void)x300a0021; gdcm::TagToType<0x300a,0x0022> x300a0022; (void)x300a0022; gdcm::TagToType<0x300a,0x0023> x300a0023; (void)x300a0023; gdcm::TagToType<0x300a,0x0025> x300a0025; (void)x300a0025; gdcm::TagToType<0x300a,0x0026> x300a0026; (void)x300a0026; gdcm::TagToType<0x300a,0x0027> x300a0027; (void)x300a0027; gdcm::TagToType<0x300a,0x0028> x300a0028; (void)x300a0028; gdcm::TagToType<0x300a,0x002a> x300a002a; (void)x300a002a; gdcm::TagToType<0x300a,0x002b> x300a002b; (void)x300a002b; gdcm::TagToType<0x300a,0x002c> x300a002c; (void)x300a002c; gdcm::TagToType<0x300a,0x002d> x300a002d; (void)x300a002d; gdcm::TagToType<0x300a,0x0040> x300a0040; (void)x300a0040; gdcm::TagToType<0x300a,0x0042> x300a0042; (void)x300a0042; gdcm::TagToType<0x300a,0x0043> x300a0043; (void)x300a0043; gdcm::TagToType<0x300a,0x0044> x300a0044; (void)x300a0044; gdcm::TagToType<0x300a,0x0046> x300a0046; (void)x300a0046; gdcm::TagToType<0x300a,0x0048> x300a0048; (void)x300a0048; gdcm::TagToType<0x300a,0x004a> x300a004a; (void)x300a004a; gdcm::TagToType<0x300a,0x004b> x300a004b; (void)x300a004b; gdcm::TagToType<0x300a,0x004c> x300a004c; (void)x300a004c; gdcm::TagToType<0x300a,0x004e> x300a004e; (void)x300a004e; gdcm::TagToType<0x300a,0x004f> x300a004f; (void)x300a004f; gdcm::TagToType<0x300a,0x0050> x300a0050; (void)x300a0050; gdcm::TagToType<0x300a,0x0051> x300a0051; (void)x300a0051; gdcm::TagToType<0x300a,0x0052> x300a0052; (void)x300a0052; gdcm::TagToType<0x300a,0x0053> x300a0053; (void)x300a0053; gdcm::TagToType<0x300a,0x0055> x300a0055; (void)x300a0055; gdcm::TagToType<0x300a,0x0070> x300a0070; (void)x300a0070; gdcm::TagToType<0x300a,0x0071> x300a0071; (void)x300a0071; gdcm::TagToType<0x300a,0x0072> x300a0072; (void)x300a0072; gdcm::TagToType<0x300a,0x0078> x300a0078; (void)x300a0078; gdcm::TagToType<0x300a,0x0079> x300a0079; (void)x300a0079; gdcm::TagToType<0x300a,0x007a> x300a007a; (void)x300a007a; gdcm::TagToType<0x300a,0x007b> x300a007b; (void)x300a007b; gdcm::TagToType<0x300a,0x0080> x300a0080; (void)x300a0080; gdcm::TagToType<0x300a,0x0082> x300a0082; (void)x300a0082; gdcm::TagToType<0x300a,0x0084> x300a0084; (void)x300a0084; gdcm::TagToType<0x300a,0x0086> x300a0086; (void)x300a0086; gdcm::TagToType<0x300a,0x0088> x300a0088; (void)x300a0088; gdcm::TagToType<0x300a,0x0089> x300a0089; (void)x300a0089; gdcm::TagToType<0x300a,0x008a> x300a008a; (void)x300a008a; gdcm::TagToType<0x300a,0x00a0> x300a00a0; (void)x300a00a0; gdcm::TagToType<0x300a,0x00a2> x300a00a2; (void)x300a00a2; gdcm::TagToType<0x300a,0x00a4> x300a00a4; (void)x300a00a4; gdcm::TagToType<0x300a,0x00b0> x300a00b0; (void)x300a00b0; gdcm::TagToType<0x300a,0x00b2> x300a00b2; (void)x300a00b2; gdcm::TagToType<0x300a,0x00b3> x300a00b3; (void)x300a00b3; gdcm::TagToType<0x300a,0x00b4> x300a00b4; (void)x300a00b4; gdcm::TagToType<0x300a,0x00b6> x300a00b6; (void)x300a00b6; gdcm::TagToType<0x300a,0x00b8> x300a00b8; (void)x300a00b8; gdcm::TagToType<0x300a,0x00ba> x300a00ba; (void)x300a00ba; gdcm::TagToType<0x300a,0x00bb> x300a00bb; (void)x300a00bb; gdcm::TagToType<0x300a,0x00bc> x300a00bc; (void)x300a00bc; gdcm::TagToType<0x300a,0x00be> x300a00be; (void)x300a00be; gdcm::TagToType<0x300a,0x00c0> x300a00c0; (void)x300a00c0; gdcm::TagToType<0x300a,0x00c2> x300a00c2; (void)x300a00c2; gdcm::TagToType<0x300a,0x00c3> x300a00c3; (void)x300a00c3; gdcm::TagToType<0x300a,0x00c4> x300a00c4; (void)x300a00c4; gdcm::TagToType<0x300a,0x00c6> x300a00c6; (void)x300a00c6; gdcm::TagToType<0x300a,0x00c7> x300a00c7; (void)x300a00c7; gdcm::TagToType<0x300a,0x00c8> x300a00c8; (void)x300a00c8; gdcm::TagToType<0x300a,0x00ca> x300a00ca; (void)x300a00ca; gdcm::TagToType<0x300a,0x00cc> x300a00cc; (void)x300a00cc; gdcm::TagToType<0x300a,0x00ce> x300a00ce; (void)x300a00ce; gdcm::TagToType<0x300a,0x00d0> x300a00d0; (void)x300a00d0; gdcm::TagToType<0x300a,0x00d1> x300a00d1; (void)x300a00d1; gdcm::TagToType<0x300a,0x00d2> x300a00d2; (void)x300a00d2; gdcm::TagToType<0x300a,0x00d3> x300a00d3; (void)x300a00d3; gdcm::TagToType<0x300a,0x00d4> x300a00d4; (void)x300a00d4; gdcm::TagToType<0x300a,0x00d5> x300a00d5; (void)x300a00d5; gdcm::TagToType<0x300a,0x00d6> x300a00d6; (void)x300a00d6; gdcm::TagToType<0x300a,0x00d7> x300a00d7; (void)x300a00d7; gdcm::TagToType<0x300a,0x00d8> x300a00d8; (void)x300a00d8; gdcm::TagToType<0x300a,0x00d9> x300a00d9; (void)x300a00d9; gdcm::TagToType<0x300a,0x00da> x300a00da; (void)x300a00da; gdcm::TagToType<0x300a,0x00db> x300a00db; (void)x300a00db; gdcm::TagToType<0x300a,0x00dc> x300a00dc; (void)x300a00dc; gdcm::TagToType<0x300a,0x00dd> x300a00dd; (void)x300a00dd; gdcm::TagToType<0x300a,0x00e0> x300a00e0; (void)x300a00e0; gdcm::TagToType<0x300a,0x00e1> x300a00e1; (void)x300a00e1; gdcm::TagToType<0x300a,0x00e2> x300a00e2; (void)x300a00e2; gdcm::TagToType<0x300a,0x00e3> x300a00e3; (void)x300a00e3; gdcm::TagToType<0x300a,0x00e4> x300a00e4; (void)x300a00e4; gdcm::TagToType<0x300a,0x00e5> x300a00e5; (void)x300a00e5; gdcm::TagToType<0x300a,0x00e6> x300a00e6; (void)x300a00e6; gdcm::TagToType<0x300a,0x00e7> x300a00e7; (void)x300a00e7; gdcm::TagToType<0x300a,0x00e8> x300a00e8; (void)x300a00e8; gdcm::TagToType<0x300a,0x00e9> x300a00e9; (void)x300a00e9; gdcm::TagToType<0x300a,0x00ea> x300a00ea; (void)x300a00ea; gdcm::TagToType<0x300a,0x00eb> x300a00eb; (void)x300a00eb; gdcm::TagToType<0x300a,0x00ec> x300a00ec; (void)x300a00ec; gdcm::TagToType<0x300a,0x00ed> x300a00ed; (void)x300a00ed; gdcm::TagToType<0x300a,0x00ee> x300a00ee; (void)x300a00ee; gdcm::TagToType<0x300a,0x00f0> x300a00f0; (void)x300a00f0; gdcm::TagToType<0x300a,0x00f2> x300a00f2; (void)x300a00f2; gdcm::TagToType<0x300a,0x00f3> x300a00f3; (void)x300a00f3; gdcm::TagToType<0x300a,0x00f4> x300a00f4; (void)x300a00f4; gdcm::TagToType<0x300a,0x00f5> x300a00f5; (void)x300a00f5; gdcm::TagToType<0x300a,0x00f6> x300a00f6; (void)x300a00f6; gdcm::TagToType<0x300a,0x00f7> x300a00f7; (void)x300a00f7; gdcm::TagToType<0x300a,0x00f8> x300a00f8; (void)x300a00f8; gdcm::TagToType<0x300a,0x00f9> x300a00f9; (void)x300a00f9; gdcm::TagToType<0x300a,0x00fa> x300a00fa; (void)x300a00fa; gdcm::TagToType<0x300a,0x00fb> x300a00fb; (void)x300a00fb; gdcm::TagToType<0x300a,0x00fc> x300a00fc; (void)x300a00fc; gdcm::TagToType<0x300a,0x00fe> x300a00fe; (void)x300a00fe; gdcm::TagToType<0x300a,0x0100> x300a0100; (void)x300a0100; gdcm::TagToType<0x300a,0x0102> x300a0102; (void)x300a0102; gdcm::TagToType<0x300a,0x0104> x300a0104; (void)x300a0104; gdcm::TagToType<0x300a,0x0106> x300a0106; (void)x300a0106; gdcm::TagToType<0x300a,0x0107> x300a0107; (void)x300a0107; gdcm::TagToType<0x300a,0x0108> x300a0108; (void)x300a0108; gdcm::TagToType<0x300a,0x0109> x300a0109; (void)x300a0109; gdcm::TagToType<0x300a,0x010a> x300a010a; (void)x300a010a; gdcm::TagToType<0x300a,0x010c> x300a010c; (void)x300a010c; gdcm::TagToType<0x300a,0x010e> x300a010e; (void)x300a010e; gdcm::TagToType<0x300a,0x0110> x300a0110; (void)x300a0110; gdcm::TagToType<0x300a,0x0111> x300a0111; (void)x300a0111; gdcm::TagToType<0x300a,0x0112> x300a0112; (void)x300a0112; gdcm::TagToType<0x300a,0x0114> x300a0114; (void)x300a0114; gdcm::TagToType<0x300a,0x0115> x300a0115; (void)x300a0115; gdcm::TagToType<0x300a,0x0116> x300a0116; (void)x300a0116; gdcm::TagToType<0x300a,0x0118> x300a0118; (void)x300a0118; gdcm::TagToType<0x300a,0x011a> x300a011a; (void)x300a011a; gdcm::TagToType<0x300a,0x011c> x300a011c; (void)x300a011c; gdcm::TagToType<0x300a,0x011e> x300a011e; (void)x300a011e; gdcm::TagToType<0x300a,0x011f> x300a011f; (void)x300a011f; gdcm::TagToType<0x300a,0x0120> x300a0120; (void)x300a0120; gdcm::TagToType<0x300a,0x0121> x300a0121; (void)x300a0121; gdcm::TagToType<0x300a,0x0122> x300a0122; (void)x300a0122; gdcm::TagToType<0x300a,0x0123> x300a0123; (void)x300a0123; gdcm::TagToType<0x300a,0x0124> x300a0124; (void)x300a0124; gdcm::TagToType<0x300a,0x0125> x300a0125; (void)x300a0125; gdcm::TagToType<0x300a,0x0126> x300a0126; (void)x300a0126; gdcm::TagToType<0x300a,0x0128> x300a0128; (void)x300a0128; gdcm::TagToType<0x300a,0x0129> x300a0129; (void)x300a0129; gdcm::TagToType<0x300a,0x012a> x300a012a; (void)x300a012a; gdcm::TagToType<0x300a,0x012c> x300a012c; (void)x300a012c; gdcm::TagToType<0x300a,0x012e> x300a012e; (void)x300a012e; gdcm::TagToType<0x300a,0x0130> x300a0130; (void)x300a0130; gdcm::TagToType<0x300a,0x0134> x300a0134; (void)x300a0134; gdcm::TagToType<0x300a,0x0140> x300a0140; (void)x300a0140; gdcm::TagToType<0x300a,0x0142> x300a0142; (void)x300a0142; gdcm::TagToType<0x300a,0x0144> x300a0144; (void)x300a0144; gdcm::TagToType<0x300a,0x0146> x300a0146; (void)x300a0146; gdcm::TagToType<0x300a,0x0148> x300a0148; (void)x300a0148; gdcm::TagToType<0x300a,0x014a> x300a014a; (void)x300a014a; gdcm::TagToType<0x300a,0x014c> x300a014c; (void)x300a014c; gdcm::TagToType<0x300a,0x014e> x300a014e; (void)x300a014e; gdcm::TagToType<0x300a,0x0180> x300a0180; (void)x300a0180; gdcm::TagToType<0x300a,0x0182> x300a0182; (void)x300a0182; gdcm::TagToType<0x300a,0x0183> x300a0183; (void)x300a0183; gdcm::TagToType<0x300a,0x0184> x300a0184; (void)x300a0184; gdcm::TagToType<0x300a,0x0190> x300a0190; (void)x300a0190; gdcm::TagToType<0x300a,0x0192> x300a0192; (void)x300a0192; gdcm::TagToType<0x300a,0x0194> x300a0194; (void)x300a0194; gdcm::TagToType<0x300a,0x0196> x300a0196; (void)x300a0196; gdcm::TagToType<0x300a,0x0198> x300a0198; (void)x300a0198; gdcm::TagToType<0x300a,0x0199> x300a0199; (void)x300a0199; gdcm::TagToType<0x300a,0x019a> x300a019a; (void)x300a019a; gdcm::TagToType<0x300a,0x01a0> x300a01a0; (void)x300a01a0; gdcm::TagToType<0x300a,0x01a2> x300a01a2; (void)x300a01a2; gdcm::TagToType<0x300a,0x01a4> x300a01a4; (void)x300a01a4; gdcm::TagToType<0x300a,0x01a6> x300a01a6; (void)x300a01a6; gdcm::TagToType<0x300a,0x01a8> x300a01a8; (void)x300a01a8; gdcm::TagToType<0x300a,0x01b0> x300a01b0; (void)x300a01b0; gdcm::TagToType<0x300a,0x01b2> x300a01b2; (void)x300a01b2; gdcm::TagToType<0x300a,0x01b4> x300a01b4; (void)x300a01b4; gdcm::TagToType<0x300a,0x01b6> x300a01b6; (void)x300a01b6; gdcm::TagToType<0x300a,0x01b8> x300a01b8; (void)x300a01b8; gdcm::TagToType<0x300a,0x01ba> x300a01ba; (void)x300a01ba; gdcm::TagToType<0x300a,0x01bc> x300a01bc; (void)x300a01bc; gdcm::TagToType<0x300a,0x01d0> x300a01d0; (void)x300a01d0; gdcm::TagToType<0x300a,0x01d2> x300a01d2; (void)x300a01d2; gdcm::TagToType<0x300a,0x01d4> x300a01d4; (void)x300a01d4; gdcm::TagToType<0x300a,0x01d6> x300a01d6; (void)x300a01d6; gdcm::TagToType<0x300a,0x0200> x300a0200; (void)x300a0200; gdcm::TagToType<0x300a,0x0202> x300a0202; (void)x300a0202; gdcm::TagToType<0x300a,0x0206> x300a0206; (void)x300a0206; gdcm::TagToType<0x300a,0x0210> x300a0210; (void)x300a0210; gdcm::TagToType<0x300a,0x0212> x300a0212; (void)x300a0212; gdcm::TagToType<0x300a,0x0214> x300a0214; (void)x300a0214; gdcm::TagToType<0x300a,0x0216> x300a0216; (void)x300a0216; gdcm::TagToType<0x300a,0x0218> x300a0218; (void)x300a0218; gdcm::TagToType<0x300a,0x021a> x300a021a; (void)x300a021a; gdcm::TagToType<0x300a,0x0222> x300a0222; (void)x300a0222; gdcm::TagToType<0x300a,0x0224> x300a0224; (void)x300a0224; gdcm::TagToType<0x300a,0x0226> x300a0226; (void)x300a0226; gdcm::TagToType<0x300a,0x0228> x300a0228; (void)x300a0228; gdcm::TagToType<0x300a,0x0229> x300a0229; (void)x300a0229; gdcm::TagToType<0x300a,0x022a> x300a022a; (void)x300a022a; gdcm::TagToType<0x300a,0x022b> x300a022b; (void)x300a022b; gdcm::TagToType<0x300a,0x022c> x300a022c; (void)x300a022c; gdcm::TagToType<0x300a,0x022e> x300a022e; (void)x300a022e; gdcm::TagToType<0x300a,0x0230> x300a0230; (void)x300a0230; gdcm::TagToType<0x300a,0x0232> x300a0232; (void)x300a0232; gdcm::TagToType<0x300a,0x0234> x300a0234; (void)x300a0234; gdcm::TagToType<0x300a,0x0236> x300a0236; (void)x300a0236; gdcm::TagToType<0x300a,0x0238> x300a0238; (void)x300a0238; gdcm::TagToType<0x300a,0x0240> x300a0240; (void)x300a0240; gdcm::TagToType<0x300a,0x0242> x300a0242; (void)x300a0242; gdcm::TagToType<0x300a,0x0244> x300a0244; (void)x300a0244; gdcm::TagToType<0x300a,0x0250> x300a0250; (void)x300a0250; gdcm::TagToType<0x300a,0x0260> x300a0260; (void)x300a0260; gdcm::TagToType<0x300a,0x0262> x300a0262; (void)x300a0262; gdcm::TagToType<0x300a,0x0263> x300a0263; (void)x300a0263; gdcm::TagToType<0x300a,0x0264> x300a0264; (void)x300a0264; gdcm::TagToType<0x300a,0x0266> x300a0266; (void)x300a0266; gdcm::TagToType<0x300a,0x026a> x300a026a; (void)x300a026a; gdcm::TagToType<0x300a,0x026c> x300a026c; (void)x300a026c; gdcm::TagToType<0x300a,0x0280> x300a0280; (void)x300a0280; gdcm::TagToType<0x300a,0x0282> x300a0282; (void)x300a0282; gdcm::TagToType<0x300a,0x0284> x300a0284; (void)x300a0284; gdcm::TagToType<0x300a,0x0286> x300a0286; (void)x300a0286; gdcm::TagToType<0x300a,0x0288> x300a0288; (void)x300a0288; gdcm::TagToType<0x300a,0x028a> x300a028a; (void)x300a028a; gdcm::TagToType<0x300a,0x028c> x300a028c; (void)x300a028c; gdcm::TagToType<0x300a,0x0290> x300a0290; (void)x300a0290; gdcm::TagToType<0x300a,0x0291> x300a0291; (void)x300a0291; gdcm::TagToType<0x300a,0x0292> x300a0292; (void)x300a0292; gdcm::TagToType<0x300a,0x0294> x300a0294; (void)x300a0294; gdcm::TagToType<0x300a,0x0296> x300a0296; (void)x300a0296; gdcm::TagToType<0x300a,0x0298> x300a0298; (void)x300a0298; gdcm::TagToType<0x300a,0x029c> x300a029c; (void)x300a029c; gdcm::TagToType<0x300a,0x029e> x300a029e; (void)x300a029e; gdcm::TagToType<0x300a,0x02a0> x300a02a0; (void)x300a02a0; gdcm::TagToType<0x300a,0x02a2> x300a02a2; (void)x300a02a2; gdcm::TagToType<0x300a,0x02a4> x300a02a4; (void)x300a02a4; gdcm::TagToType<0x300a,0x02b0> x300a02b0; (void)x300a02b0; gdcm::TagToType<0x300a,0x02b2> x300a02b2; (void)x300a02b2; gdcm::TagToType<0x300a,0x02b3> x300a02b3; (void)x300a02b3; gdcm::TagToType<0x300a,0x02b4> x300a02b4; (void)x300a02b4; gdcm::TagToType<0x300a,0x02b8> x300a02b8; (void)x300a02b8; gdcm::TagToType<0x300a,0x02ba> x300a02ba; (void)x300a02ba; gdcm::TagToType<0x300a,0x02c8> x300a02c8; (void)x300a02c8; gdcm::TagToType<0x300a,0x02d0> x300a02d0; (void)x300a02d0; gdcm::TagToType<0x300a,0x02d2> x300a02d2; (void)x300a02d2; gdcm::TagToType<0x300a,0x02d4> x300a02d4; (void)x300a02d4; gdcm::TagToType<0x300a,0x02d6> x300a02d6; (void)x300a02d6; gdcm::TagToType<0x300a,0x02e0> x300a02e0; (void)x300a02e0; gdcm::TagToType<0x300a,0x02e1> x300a02e1; (void)x300a02e1; gdcm::TagToType<0x300a,0x02e2> x300a02e2; (void)x300a02e2; gdcm::TagToType<0x300a,0x02e3> x300a02e3; (void)x300a02e3; gdcm::TagToType<0x300a,0x02e4> x300a02e4; (void)x300a02e4; gdcm::TagToType<0x300a,0x02e5> x300a02e5; (void)x300a02e5; gdcm::TagToType<0x300a,0x02e6> x300a02e6; (void)x300a02e6; gdcm::TagToType<0x300a,0x02e7> x300a02e7; (void)x300a02e7; gdcm::TagToType<0x300a,0x02e8> x300a02e8; (void)x300a02e8; gdcm::TagToType<0x300a,0x02ea> x300a02ea; (void)x300a02ea; gdcm::TagToType<0x300a,0x02eb> x300a02eb; (void)x300a02eb; gdcm::TagToType<0x300a,0x0302> x300a0302; (void)x300a0302; gdcm::TagToType<0x300a,0x0304> x300a0304; (void)x300a0304; gdcm::TagToType<0x300a,0x0306> x300a0306; (void)x300a0306; gdcm::TagToType<0x300a,0x0308> x300a0308; (void)x300a0308; gdcm::TagToType<0x300a,0x030a> x300a030a; (void)x300a030a; gdcm::TagToType<0x300a,0x030c> x300a030c; (void)x300a030c; gdcm::TagToType<0x300a,0x030d> x300a030d; (void)x300a030d; gdcm::TagToType<0x300a,0x030f> x300a030f; (void)x300a030f; gdcm::TagToType<0x300a,0x0312> x300a0312; (void)x300a0312; gdcm::TagToType<0x300a,0x0314> x300a0314; (void)x300a0314; gdcm::TagToType<0x300a,0x0316> x300a0316; (void)x300a0316; gdcm::TagToType<0x300a,0x0318> x300a0318; (void)x300a0318; gdcm::TagToType<0x300a,0x0320> x300a0320; (void)x300a0320; gdcm::TagToType<0x300a,0x0322> x300a0322; (void)x300a0322; gdcm::TagToType<0x300a,0x0330> x300a0330; (void)x300a0330; gdcm::TagToType<0x300a,0x0332> x300a0332; (void)x300a0332; gdcm::TagToType<0x300a,0x0334> x300a0334; (void)x300a0334; gdcm::TagToType<0x300a,0x0336> x300a0336; (void)x300a0336; gdcm::TagToType<0x300a,0x0338> x300a0338; (void)x300a0338; gdcm::TagToType<0x300a,0x033a> x300a033a; (void)x300a033a; gdcm::TagToType<0x300a,0x033c> x300a033c; (void)x300a033c; gdcm::TagToType<0x300a,0x0340> x300a0340; (void)x300a0340; gdcm::TagToType<0x300a,0x0342> x300a0342; (void)x300a0342; gdcm::TagToType<0x300a,0x0344> x300a0344; (void)x300a0344; gdcm::TagToType<0x300a,0x0346> x300a0346; (void)x300a0346; gdcm::TagToType<0x300a,0x0348> x300a0348; (void)x300a0348; gdcm::TagToType<0x300a,0x034a> x300a034a; (void)x300a034a; gdcm::TagToType<0x300a,0x034c> x300a034c; (void)x300a034c; gdcm::TagToType<0x300a,0x0350> x300a0350; (void)x300a0350; gdcm::TagToType<0x300a,0x0352> x300a0352; (void)x300a0352; gdcm::TagToType<0x300a,0x0354> x300a0354; (void)x300a0354; gdcm::TagToType<0x300a,0x0356> x300a0356; (void)x300a0356; gdcm::TagToType<0x300a,0x0358> x300a0358; (void)x300a0358; gdcm::TagToType<0x300a,0x035a> x300a035a; (void)x300a035a; gdcm::TagToType<0x300a,0x0360> x300a0360; (void)x300a0360; gdcm::TagToType<0x300a,0x0362> x300a0362; (void)x300a0362; gdcm::TagToType<0x300a,0x0364> x300a0364; (void)x300a0364; gdcm::TagToType<0x300a,0x0366> x300a0366; (void)x300a0366; gdcm::TagToType<0x300a,0x0370> x300a0370; (void)x300a0370; gdcm::TagToType<0x300a,0x0372> x300a0372; (void)x300a0372; gdcm::TagToType<0x300a,0x0374> x300a0374; (void)x300a0374; gdcm::TagToType<0x300a,0x0380> x300a0380; (void)x300a0380; gdcm::TagToType<0x300a,0x0382> x300a0382; (void)x300a0382; gdcm::TagToType<0x300a,0x0384> x300a0384; (void)x300a0384; gdcm::TagToType<0x300a,0x0386> x300a0386; (void)x300a0386; gdcm::TagToType<0x300a,0x0388> x300a0388; (void)x300a0388; gdcm::TagToType<0x300a,0x038a> x300a038a; (void)x300a038a; gdcm::TagToType<0x300a,0x0390> x300a0390; (void)x300a0390; gdcm::TagToType<0x300a,0x0392> x300a0392; (void)x300a0392; gdcm::TagToType<0x300a,0x0394> x300a0394; (void)x300a0394; gdcm::TagToType<0x300a,0x0396> x300a0396; (void)x300a0396; gdcm::TagToType<0x300a,0x0398> x300a0398; (void)x300a0398; gdcm::TagToType<0x300a,0x039a> x300a039a; (void)x300a039a; gdcm::TagToType<0x300a,0x03a0> x300a03a0; (void)x300a03a0; gdcm::TagToType<0x300a,0x03a2> x300a03a2; (void)x300a03a2; gdcm::TagToType<0x300a,0x03a4> x300a03a4; (void)x300a03a4; gdcm::TagToType<0x300a,0x03a6> x300a03a6; (void)x300a03a6; gdcm::TagToType<0x300a,0x03a8> x300a03a8; (void)x300a03a8; gdcm::TagToType<0x300a,0x03aa> x300a03aa; (void)x300a03aa; gdcm::TagToType<0x300a,0x03ac> x300a03ac; (void)x300a03ac; gdcm::TagToType<0x300a,0x0401> x300a0401; (void)x300a0401; gdcm::TagToType<0x300a,0x0402> x300a0402; (void)x300a0402; gdcm::TagToType<0x300a,0x0410> x300a0410; (void)x300a0410; gdcm::TagToType<0x300a,0x0412> x300a0412; (void)x300a0412; gdcm::TagToType<0x300a,0x0420> x300a0420; (void)x300a0420; gdcm::TagToType<0x300a,0x0421> x300a0421; (void)x300a0421; gdcm::TagToType<0x300a,0x0422> x300a0422; (void)x300a0422; gdcm::TagToType<0x300a,0x0423> x300a0423; (void)x300a0423; gdcm::TagToType<0x300a,0x0424> x300a0424; (void)x300a0424; gdcm::TagToType<0x300c,0x0002> x300c0002; (void)x300c0002; gdcm::TagToType<0x300c,0x0004> x300c0004; (void)x300c0004; gdcm::TagToType<0x300c,0x0006> x300c0006; (void)x300c0006; gdcm::TagToType<0x300c,0x0007> x300c0007; (void)x300c0007; gdcm::TagToType<0x300c,0x0008> x300c0008; (void)x300c0008; gdcm::TagToType<0x300c,0x0009> x300c0009; (void)x300c0009; gdcm::TagToType<0x300c,0x000a> x300c000a; (void)x300c000a; gdcm::TagToType<0x300c,0x000c> x300c000c; (void)x300c000c; gdcm::TagToType<0x300c,0x000e> x300c000e; (void)x300c000e; gdcm::TagToType<0x300c,0x0020> x300c0020; (void)x300c0020; gdcm::TagToType<0x300c,0x0022> x300c0022; (void)x300c0022; gdcm::TagToType<0x300c,0x0040> x300c0040; (void)x300c0040; gdcm::TagToType<0x300c,0x0042> x300c0042; (void)x300c0042; gdcm::TagToType<0x300c,0x0050> x300c0050; (void)x300c0050; gdcm::TagToType<0x300c,0x0051> x300c0051; (void)x300c0051; gdcm::TagToType<0x300c,0x0055> x300c0055; (void)x300c0055; gdcm::TagToType<0x300c,0x0060> x300c0060; (void)x300c0060; gdcm::TagToType<0x300c,0x006a> x300c006a; (void)x300c006a; gdcm::TagToType<0x300c,0x0080> x300c0080; (void)x300c0080; gdcm::TagToType<0x300c,0x00a0> x300c00a0; (void)x300c00a0; gdcm::TagToType<0x300c,0x00b0> x300c00b0; (void)x300c00b0; gdcm::TagToType<0x300c,0x00c0> x300c00c0; (void)x300c00c0; gdcm::TagToType<0x300c,0x00d0> x300c00d0; (void)x300c00d0; gdcm::TagToType<0x300c,0x00e0> x300c00e0; (void)x300c00e0; gdcm::TagToType<0x300c,0x00f0> x300c00f0; (void)x300c00f0; gdcm::TagToType<0x300c,0x00f2> x300c00f2; (void)x300c00f2; gdcm::TagToType<0x300c,0x00f4> x300c00f4; (void)x300c00f4; gdcm::TagToType<0x300c,0x00f6> x300c00f6; (void)x300c00f6; gdcm::TagToType<0x300c,0x0100> x300c0100; (void)x300c0100; gdcm::TagToType<0x300c,0x0102> x300c0102; (void)x300c0102; gdcm::TagToType<0x300c,0x0104> x300c0104; (void)x300c0104; gdcm::TagToType<0x300e,0x0002> x300e0002; (void)x300e0002; gdcm::TagToType<0x300e,0x0004> x300e0004; (void)x300e0004; gdcm::TagToType<0x300e,0x0005> x300e0005; (void)x300e0005; gdcm::TagToType<0x300e,0x0008> x300e0008; (void)x300e0008; gdcm::TagToType<0x4000,0x0010> x40000010; (void)x40000010; gdcm::TagToType<0x4000,0x4000> x40004000; (void)x40004000; gdcm::TagToType<0x4008,0x0040> x40080040; (void)x40080040; gdcm::TagToType<0x4008,0x0042> x40080042; (void)x40080042; gdcm::TagToType<0x4008,0x0050> x40080050; (void)x40080050; gdcm::TagToType<0x4008,0x0100> x40080100; (void)x40080100; gdcm::TagToType<0x4008,0x0101> x40080101; (void)x40080101; gdcm::TagToType<0x4008,0x0102> x40080102; (void)x40080102; gdcm::TagToType<0x4008,0x0103> x40080103; (void)x40080103; gdcm::TagToType<0x4008,0x0108> x40080108; (void)x40080108; gdcm::TagToType<0x4008,0x0109> x40080109; (void)x40080109; gdcm::TagToType<0x4008,0x010a> x4008010a; (void)x4008010a; gdcm::TagToType<0x4008,0x010b> x4008010b; (void)x4008010b; gdcm::TagToType<0x4008,0x010c> x4008010c; (void)x4008010c; gdcm::TagToType<0x4008,0x0111> x40080111; (void)x40080111; gdcm::TagToType<0x4008,0x0112> x40080112; (void)x40080112; gdcm::TagToType<0x4008,0x0113> x40080113; (void)x40080113; gdcm::TagToType<0x4008,0x0114> x40080114; (void)x40080114; gdcm::TagToType<0x4008,0x0115> x40080115; (void)x40080115; gdcm::TagToType<0x4008,0x0117> x40080117; (void)x40080117; gdcm::TagToType<0x4008,0x0118> x40080118; (void)x40080118; gdcm::TagToType<0x4008,0x0119> x40080119; (void)x40080119; gdcm::TagToType<0x4008,0x011a> x4008011a; (void)x4008011a; gdcm::TagToType<0x4008,0x0200> x40080200; (void)x40080200; gdcm::TagToType<0x4008,0x0202> x40080202; (void)x40080202; gdcm::TagToType<0x4008,0x0210> x40080210; (void)x40080210; gdcm::TagToType<0x4008,0x0212> x40080212; (void)x40080212; gdcm::TagToType<0x4008,0x0300> x40080300; (void)x40080300; gdcm::TagToType<0x4008,0x4000> x40084000; (void)x40084000; gdcm::TagToType<0x4ffe,0x0001> x4ffe0001; (void)x4ffe0001; gdcm::TagToType<0x5000,0x0005> x50000005; (void)x50000005; gdcm::TagToType<0x5000,0x0010> x50000010; (void)x50000010; gdcm::TagToType<0x5000,0x0020> x50000020; (void)x50000020; gdcm::TagToType<0x5000,0x0022> x50000022; (void)x50000022; gdcm::TagToType<0x5000,0x0030> x50000030; (void)x50000030; gdcm::TagToType<0x5000,0x0040> x50000040; (void)x50000040; gdcm::TagToType<0x5000,0x0103> x50000103; (void)x50000103; gdcm::TagToType<0x5000,0x0104> x50000104; (void)x50000104; gdcm::TagToType<0x5000,0x0105> x50000105; (void)x50000105; gdcm::TagToType<0x5000,0x0106> x50000106; (void)x50000106; gdcm::TagToType<0x5000,0x0110> x50000110; (void)x50000110; gdcm::TagToType<0x5000,0x0112> x50000112; (void)x50000112; gdcm::TagToType<0x5000,0x0114> x50000114; (void)x50000114; gdcm::TagToType<0x5000,0x1001> x50001001; (void)x50001001; gdcm::TagToType<0x5000,0x2000> x50002000; (void)x50002000; gdcm::TagToType<0x5000,0x2002> x50002002; (void)x50002002; gdcm::TagToType<0x5000,0x2004> x50002004; (void)x50002004; gdcm::TagToType<0x5000,0x2006> x50002006; (void)x50002006; gdcm::TagToType<0x5000,0x2008> x50002008; (void)x50002008; gdcm::TagToType<0x5000,0x200a> x5000200a; (void)x5000200a; gdcm::TagToType<0x5000,0x200e> x5000200e; (void)x5000200e; gdcm::TagToType<0x5000,0x2500> x50002500; (void)x50002500; gdcm::TagToType<0x5000,0x2600> x50002600; (void)x50002600; gdcm::TagToType<0x5000,0x2610> x50002610; (void)x50002610; gdcm::TagToType<0x5200,0x9229> x52009229; (void)x52009229; gdcm::TagToType<0x5200,0x9230> x52009230; (void)x52009230; gdcm::TagToType<0x5400,0x0100> x54000100; (void)x54000100; gdcm::TagToType<0x5400,0x1004> x54001004; (void)x54001004; gdcm::TagToType<0x5400,0x1006> x54001006; (void)x54001006; gdcm::TagToType<0x5600,0x0010> x56000010; (void)x56000010; gdcm::TagToType<0x5600,0x0020> x56000020; (void)x56000020; gdcm::TagToType<0x6000,0x0010> x60000010; (void)x60000010; gdcm::TagToType<0x6000,0x0011> x60000011; (void)x60000011; gdcm::TagToType<0x6000,0x0012> x60000012; (void)x60000012; gdcm::TagToType<0x6000,0x0015> x60000015; (void)x60000015; gdcm::TagToType<0x6000,0x0022> x60000022; (void)x60000022; gdcm::TagToType<0x6000,0x0040> x60000040; (void)x60000040; gdcm::TagToType<0x6000,0x0045> x60000045; (void)x60000045; gdcm::TagToType<0x6000,0x0050> x60000050; (void)x60000050; gdcm::TagToType<0x6000,0x0051> x60000051; (void)x60000051; gdcm::TagToType<0x6000,0x0052> x60000052; (void)x60000052; gdcm::TagToType<0x6000,0x0060> x60000060; (void)x60000060; gdcm::TagToType<0x6000,0x0061> x60000061; (void)x60000061; gdcm::TagToType<0x6000,0x0062> x60000062; (void)x60000062; gdcm::TagToType<0x6000,0x0063> x60000063; (void)x60000063; gdcm::TagToType<0x6000,0x0066> x60000066; (void)x60000066; gdcm::TagToType<0x6000,0x0068> x60000068; (void)x60000068; gdcm::TagToType<0x6000,0x0069> x60000069; (void)x60000069; gdcm::TagToType<0x6000,0x0100> x60000100; (void)x60000100; gdcm::TagToType<0x6000,0x0102> x60000102; (void)x60000102; gdcm::TagToType<0x6000,0x0110> x60000110; (void)x60000110; gdcm::TagToType<0x6000,0x0200> x60000200; (void)x60000200; gdcm::TagToType<0x6000,0x0800> x60000800; (void)x60000800; gdcm::TagToType<0x6000,0x0802> x60000802; (void)x60000802; gdcm::TagToType<0x6000,0x0803> x60000803; (void)x60000803; gdcm::TagToType<0x6000,0x0804> x60000804; (void)x60000804; gdcm::TagToType<0x6000,0x1001> x60001001; (void)x60001001; gdcm::TagToType<0x6000,0x1100> x60001100; (void)x60001100; gdcm::TagToType<0x6000,0x1101> x60001101; (void)x60001101; gdcm::TagToType<0x6000,0x1102> x60001102; (void)x60001102; gdcm::TagToType<0x6000,0x1103> x60001103; (void)x60001103; gdcm::TagToType<0x6000,0x1200> x60001200; (void)x60001200; gdcm::TagToType<0x6000,0x1201> x60001201; (void)x60001201; gdcm::TagToType<0x6000,0x1202> x60001202; (void)x60001202; gdcm::TagToType<0x6000,0x1203> x60001203; (void)x60001203; gdcm::TagToType<0x6000,0x1301> x60001301; (void)x60001301; gdcm::TagToType<0x6000,0x1302> x60001302; (void)x60001302; gdcm::TagToType<0x6000,0x1303> x60001303; (void)x60001303; gdcm::TagToType<0x6000,0x1500> x60001500; (void)x60001500; gdcm::TagToType<0x6000,0x4000> x60004000; (void)x60004000; gdcm::TagToType<0x7fe0,0x0020> x7fe00020; (void)x7fe00020; gdcm::TagToType<0x7fe0,0x0030> x7fe00030; (void)x7fe00030; gdcm::TagToType<0x7fe0,0x0040> x7fe00040; (void)x7fe00040; gdcm::TagToType<0x7f00,0x0011> x7f000011; (void)x7f000011; gdcm::TagToType<0x7f00,0x0020> x7f000020; (void)x7f000020; gdcm::TagToType<0x7f00,0x0030> x7f000030; (void)x7f000030; gdcm::TagToType<0x7f00,0x0040> x7f000040; (void)x7f000040; gdcm::TagToType<0xfffa,0xfffa> xfffafffa; (void)xfffafffa; gdcm::TagToType<0xfffc,0xfffc> xfffcfffc; (void)xfffcfffc; return 0; } GDCM-3.0.10/Testing/Source/DataDictionary/Cxx/TestTagToType.xsl000066400000000000000000000045131412732066400241030ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc TestTagToType.xsl DICOMV3.xml > TestTagToType.cxx /*========================================================================= 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 "gdcmTagToType.h" int TestTagToType(int, char *[]) { gdcm::TagToType<0x ,0x > ; (void) ; return 0; } GDCM-3.0.10/Testing/Source/DataDictionary/Cxx/TestUIDs.cxx000066400000000000000000000641041412732066400230250ustar00rootroot00000000000000/*========================================================================= 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 "gdcmUIDs.h" #include "gdcmTesting.h" #include #include // strcmp #include // strcmp // This list was retrieved from: // http://cardiacatlas.wiki.sourceforge.net/DICOM+Service+Class+Definitions // Hum...there is not a single difference, exact same number of white space... // apparently last modifier is 'solidether' // http://cardiacatlas.wiki.sourceforge.net/page/diff/DICOM+Service+Class+Definitions?v1=209104&v2=209124 // could this be that they copy/paste stuff from gdcm itself ? // how else could you explain the: // { "1.2.840.113543.6.6.1.3.10002","Unregistered (?) Philips3D" }, static const char * const sopclassuids[][2] = { { "1.2.840.10008.1.1","Verification SOP Class" }, { "1.2.840.10008.1.2","Implicit VR Little Endian: Default Transfer Syntax for DICOM" }, { "1.2.840.10008.1.2.1","Explicit VR Little Endian" }, { "1.2.840.10008.1.2.1.99","Deflated Explicit VR Little Endian" }, { "1.2.840.10008.1.2.2","Explicit VR Big Endian" }, { "1.2.840.10008.1.2.4.50","JPEG Baseline (Process 1): Default Transfer Syntax for Lossy JPEG 8 Bit Image Compression" }, { "1.2.840.10008.1.2.4.51","JPEG Extended (Process 2 & 4): Default Transfer Syntax for Lossy JPEG 12 Bit Image Compression (Process 4 only)" }, { "1.2.840.10008.1.2.4.52","JPEG Extended (Process 3 & 5)" }, { "1.2.840.10008.1.2.4.53","JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8)" }, { "1.2.840.10008.1.2.4.54","JPEG Spectral Selection, Non-Hierarchical (Process 7 & 9)" }, { "1.2.840.10008.1.2.4.55","JPEG Full Progression, Non-Hierarchical (Process 10 & 12)" }, { "1.2.840.10008.1.2.4.56","JPEG Full Progression, Non-Hierarchical (Process 11 & 13)" }, { "1.2.840.10008.1.2.4.57","JPEG Lossless, Non-Hierarchical (Process 14)" }, { "1.2.840.10008.1.2.4.58","JPEG Lossless, Non-Hierarchical (Process 15)" }, { "1.2.840.10008.1.2.4.59","JPEG Extended, Hierarchical (Process 16 & 18)" }, { "1.2.840.10008.1.2.4.60","JPEG Extended, Hierarchical (Process 17 & 19)" }, { "1.2.840.10008.1.2.4.61","JPEG Spectral Selection, Hierarchical (Process 20 & 22)" }, { "1.2.840.10008.1.2.4.62","JPEG Spectral Selection, Hierarchical (Process 21 & 23)" }, { "1.2.840.10008.1.2.4.63","JPEG Full Progression, Hierarchical (Process 24 & 26)" }, { "1.2.840.10008.1.2.4.64","JPEG Full Progression, Hierarchical (Process 25 & 27)" }, { "1.2.840.10008.1.2.4.65","JPEG Lossless, Hierarchical (Process 28)" }, { "1.2.840.10008.1.2.4.66","JPEG Lossless, Hierarchical (Process 29)" }, { "1.2.840.10008.1.2.4.70","JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1]): Default Transfer Syntax for Lossless JPEG Image Compression" }, { "1.2.840.10008.1.2.4.80","JPEG-LS Lossless Image Compression" }, { "1.2.840.10008.1.2.4.81","JPEG-LS Lossy (Near-Lossless) Image Compression" }, { "1.2.840.10008.1.2.4.90","JPEG 2000 Image Compression (Lossless Only)" }, { "1.2.840.10008.1.2.4.91","JPEG 2000 Image Compression" }, { "1.2.840.10008.1.2.4.92","JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)" }, { "1.2.840.10008.1.2.4.93","JPEG 2000 Part 2 Multi-component Image Compression" }, { "1.2.840.10008.1.2.4.94","JPIP Referenced" }, { "1.2.840.10008.1.2.4.95","JPIP Referenced Deflate" }, { "1.2.840.10008.1.2.4.100","MPEG2 Main Profile @ Main Level" }, { "1.2.840.10008.1.2.5","RLE Lossless" }, { "1.2.840.10008.1.2.6.1","RFC 2557 MIME encapsulation" }, { "1.2.840.10008.1.2.6.2","XML Encoding" }, { "1.2.840.10008.1.3.10","Media Storage Directory Storage" }, { "1.2.840.10008.1.4.1.1","Talairach Brain Atlas Frame of Reference" }, { "1.2.840.10008.1.4.1.2","SPM2 T1 Frame of Reference" }, { "1.2.840.10008.1.4.1.3","SPM2 T2 Frame of Reference" }, { "1.2.840.10008.1.4.1.4","SPM2 PD Frame of Reference" }, { "1.2.840.10008.1.4.1.5","SPM2 EPI Frame of Reference" }, { "1.2.840.10008.1.4.1.6","SPM2 FIL T1 Frame of Reference" }, { "1.2.840.10008.1.4.1.7","SPM2 PET Frame of Reference" }, { "1.2.840.10008.1.4.1.8","SPM2 TRANSM Frame of Reference" }, { "1.2.840.10008.1.4.1.9","SPM2 SPECT Frame of Reference" }, { "1.2.840.10008.1.4.1.10","SPM2 GRAY Frame of Reference" }, { "1.2.840.10008.1.4.1.11","SPM2 WHITE Frame of Reference" }, { "1.2.840.10008.1.4.1.12","SPM2 CSF Frame of Reference" }, { "1.2.840.10008.1.4.1.13","SPM2 BRAINMASK Frame of Reference" }, { "1.2.840.10008.1.4.1.14","SPM2 AVG305T1 Frame of Reference" }, { "1.2.840.10008.1.4.1.15","SPM2 AVG152T1 Frame of Reference" }, { "1.2.840.10008.1.4.1.16","SPM2 AVG152T2 Frame of Reference" }, { "1.2.840.10008.1.4.1.17","SPM2 AVG152PD Frame of Reference" }, { "1.2.840.10008.1.4.1.18","SPM2 SINGLESUBJT1 Frame of Reference" }, { "1.2.840.10008.1.4.2.1","ICBM 452 T1 Frame of Reference" }, { "1.2.840.10008.1.4.2.2","ICBM Single Subject MRI Frame of Reference" }, { "1.2.840.10008.1.9","Basic Study Content Notification SOP Class" }, { "1.2.840.10008.1.20.1","Storage Commitment Push Model SOP Class" }, { "1.2.840.10008.1.20.1.1","Storage Commitment Push Model SOP Instance" }, { "1.2.840.10008.1.20.2","Storage Commitment Pull Model SOP Class" }, { "1.2.840.10008.1.20.2.1","Storage Commitment Pull Model SOP Instance" }, { "1.2.840.10008.1.40","Procedural Event Logging SOP Class" }, { "1.2.840.10008.1.40.1","Procedural Event Logging SOP Instance" }, { "1.2.840.10008.1.42","Substance Administration Logging SOP Class" }, { "1.2.840.10008.1.42.1","Substance Administration Logging SOP Instance" }, { "1.2.840.10008.2.6.1","DICOM UID Registry" }, { "1.2.840.10008.2.16.4","DICOM Controlled Terminology" }, { "1.2.840.10008.3.1.1.1","DICOM Application Context Name" }, { "1.2.840.10008.3.1.2.1.1","Detached Patient Management SOP Class" }, { "1.2.840.10008.3.1.2.1.4","Detached Patient Management Meta SOP Class" }, { "1.2.840.10008.3.1.2.2.1","Detached Visit Management SOP Class" }, { "1.2.840.10008.3.1.2.3.1","Detached Study Management SOP Class" }, { "1.2.840.10008.3.1.2.3.2","Study Component Management SOP Class" }, { "1.2.840.10008.3.1.2.3.3","Modality Performed Procedure Step SOP Class" }, { "1.2.840.10008.3.1.2.3.4","Modality Performed Procedure Step Retrieve SOP Class" }, { "1.2.840.10008.3.1.2.3.5","Modality Performed Procedure Step Notification SOP Class" }, { "1.2.840.10008.3.1.2.5.1","Detached Results Management SOP Class" }, { "1.2.840.10008.3.1.2.5.4","Detached Results Management Meta SOP Class" }, { "1.2.840.10008.3.1.2.5.5","Detached Study Management Meta SOP Class" }, { "1.2.840.10008.3.1.2.6.1","Detached Interpretation Management SOP Class" }, { "1.2.840.10008.4.2","Storage Service Class" }, { "1.2.840.10008.5.1.1.1","Basic Film Session SOP Class" }, { "1.2.840.10008.5.1.1.2","Basic Film Box SOP Class" }, { "1.2.840.10008.5.1.1.4","Basic Grayscale Image Box SOP Class" }, { "1.2.840.10008.5.1.1.4.1","Basic Color Image Box SOP Class" }, { "1.2.840.10008.5.1.1.4.2","Referenced Image Box SOP Class" }, { "1.2.840.10008.5.1.1.9","Basic Grayscale Print Management Meta SOP Class" }, { "1.2.840.10008.5.1.1.9.1","Referenced Grayscale Print Management Meta SOP Class" }, { "1.2.840.10008.5.1.1.14","Print Job SOP Class" }, { "1.2.840.10008.5.1.1.15","Basic Annotation Box SOP Class" }, { "1.2.840.10008.5.1.1.16","Printer SOP Class" }, { "1.2.840.10008.5.1.1.16.376","Printer Configuration Retrieval SOP Class" }, { "1.2.840.10008.5.1.1.17","Printer SOP Instance" }, { "1.2.840.10008.5.1.1.17.376","Printer Configuration Retrieval SOP Instance" }, { "1.2.840.10008.5.1.1.18","Basic Color Print Management Meta SOP Class" }, { "1.2.840.10008.5.1.1.18.1","Referenced Color Print Management Meta SOP Class" }, { "1.2.840.10008.5.1.1.22","VOI LUT Box SOP Class" }, { "1.2.840.10008.5.1.1.23","Presentation LUT SOP Class" }, { "1.2.840.10008.5.1.1.24","Image Overlay Box SOP Class" }, { "1.2.840.10008.5.1.1.24.1","Basic Print Image Overlay Box SOP Class" }, { "1.2.840.10008.5.1.1.25","Print Queue SOP Instance" }, { "1.2.840.10008.5.1.1.26","Print Queue Management SOP Class" }, { "1.2.840.10008.5.1.1.27","Stored Print Storage SOP Class" }, { "1.2.840.10008.5.1.1.29","Hardcopy Grayscale Image Storage SOP Class" }, { "1.2.840.10008.5.1.1.30","Hardcopy Color Image Storage SOP Class" }, { "1.2.840.10008.5.1.1.31","Pull Print Request SOP Class" }, { "1.2.840.10008.5.1.1.32","Pull Stored Print Management Meta SOP Class" }, { "1.2.840.10008.5.1.1.33","Media Creation Management SOP Class UID" }, { "1.2.840.10008.5.1.4.1.1.1","Computed Radiography Image Storage" }, { "1.2.840.10008.5.1.4.1.1.1.1","Digital X-Ray Image Storage - For Presentation" }, { "1.2.840.10008.5.1.4.1.1.1.1.1","Digital X-Ray Image Storage - For Processing" }, { "1.2.840.10008.5.1.4.1.1.1.2","Digital Mammography X-Ray Image Storage - For Presentation" }, { "1.2.840.10008.5.1.4.1.1.1.2.1","Digital Mammography X-Ray Image Storage - For Processing" }, { "1.2.840.10008.5.1.4.1.1.1.3","Digital Intra-oral X-Ray Image Storage - For Presentation" }, { "1.2.840.10008.5.1.4.1.1.1.3.1","Digital Intra-oral X-Ray Image Storage - For Processing" }, { "1.2.840.10008.5.1.4.1.1.2","CT Image Storage" }, { "1.2.840.10008.5.1.4.1.1.2.1","Enhanced CT Image Storage" }, { "1.2.840.10008.5.1.4.1.1.3","Ultrasound Multi-frame Image Storage" }, { "1.2.840.10008.5.1.4.1.1.3.1","Ultrasound Multi-frame Image Storage" }, { "1.2.840.10008.5.1.4.1.1.4","MR Image Storage" }, { "1.2.840.10008.5.1.4.1.1.4.1","Enhanced MR Image Storage" }, { "1.2.840.10008.5.1.4.1.1.4.2","MR Spectroscopy Storage" }, { "1.2.840.10008.5.1.4.1.1.5","Nuclear Medicine Image Storage" }, { "1.2.840.10008.5.1.4.1.1.6","Ultrasound Image Storage" }, { "1.2.840.10008.5.1.4.1.1.6.1","Ultrasound Image Storage" }, { "1.2.840.10008.5.1.4.1.1.7","Secondary Capture Image Storage" }, { "1.2.840.10008.5.1.4.1.1.7.1","Multi-frame Single Bit Secondary Capture Image Storage" }, { "1.2.840.10008.5.1.4.1.1.7.2","Multi-frame Grayscale Byte Secondary Capture Image Storage" }, { "1.2.840.10008.5.1.4.1.1.7.3","Multi-frame Grayscale Word Secondary Capture Image Storage" }, { "1.2.840.10008.5.1.4.1.1.7.4","Multi-frame True Color Secondary Capture Image Storage" }, { "1.2.840.10008.5.1.4.1.1.8","Standalone Overlay Storage" }, { "1.2.840.10008.5.1.4.1.1.9","Standalone Curve Storage" }, { "1.2.840.10008.5.1.4.1.1.9.1","Waveform Storage - Trial" }, { "1.2.840.10008.5.1.4.1.1.9.1.1","12-lead ECG Waveform Storage" }, { "1.2.840.10008.5.1.4.1.1.9.1.2","General ECG Waveform Storage" }, { "1.2.840.10008.5.1.4.1.1.9.1.3","Ambulatory ECG Waveform Storage" }, { "1.2.840.10008.5.1.4.1.1.9.2.1","Hemodynamic Waveform Storage" }, { "1.2.840.10008.5.1.4.1.1.9.3.1","Cardiac Electrophysiology Waveform Storage" }, { "1.2.840.10008.5.1.4.1.1.9.4.1","Basic Voice Audio Waveform Storage" }, { "1.2.840.10008.5.1.4.1.1.10","Standalone Modality LUT Storage" }, { "1.2.840.10008.5.1.4.1.1.11","Standalone VOI LUT Storage" }, { "1.2.840.10008.5.1.4.1.1.11.1","Grayscale Softcopy Presentation State Storage SOP Class" }, { "1.2.840.10008.5.1.4.1.1.11.2","Color Softcopy Presentation State Storage SOP Class" }, { "1.2.840.10008.5.1.4.1.1.11.3","Pseudo-Color Softcopy Presentation State Storage SOP Class" }, { "1.2.840.10008.5.1.4.1.1.11.4","Blending Softcopy Presentation State Storage SOP Class" }, { "1.2.840.10008.5.1.4.1.1.12.1","X-Ray Angiographic Image Storage" }, { "1.2.840.10008.5.1.4.1.1.12.1.1","Enhanced XA Image Storage" }, { "1.2.840.10008.5.1.4.1.1.12.2","X-Ray Radiofluoroscopic Image Storage" }, { "1.2.840.10008.5.1.4.1.1.12.2.1","Enhanced XRF Image Storage" }, { "1.2.840.10008.5.1.4.1.1.13.1.1","X-Ray 3D Angiographic Image Storage" }, { "1.2.840.10008.5.1.4.1.1.13.1.2","X-Ray 3D Craniofacial Image Storage" }, { "1.2.840.10008.5.1.4.1.1.12.3","X-Ray Angiographic Bi-Plane Image Storage" }, { "1.2.840.10008.5.1.4.1.1.20","Nuclear Medicine Image Storage" }, { "1.2.840.10008.5.1.4.1.1.66","Raw Data Storage" }, { "1.2.840.10008.5.1.4.1.1.66.1","Spatial Registration Storage" }, { "1.2.840.10008.5.1.4.1.1.66.2","Spatial Fiducials Storage" }, { "1.2.840.10008.5.1.4.1.1.66.3","Deformable Spatial Registration Storage" }, { "1.2.840.10008.5.1.4.1.1.66.4","Segmentation Storage" }, { "1.2.840.10008.5.1.4.1.1.67","Real World Value Mapping Storage" }, { "1.2.840.10008.5.1.4.1.1.77.1","VL Image Storage - Trial" }, { "1.2.840.10008.5.1.4.1.1.77.2","VL Multi-frame Image Storage - Trial" }, { "1.2.840.10008.5.1.4.1.1.77.1.1","VL Endoscopic Image Storage" }, { "1.2.840.10008.5.1.4.1.1.77.1.1.1","Video Endoscopic Image Storage" }, { "1.2.840.10008.5.1.4.1.1.77.1.2","VL Microscopic Image Storage" }, { "1.2.840.10008.5.1.4.1.1.77.1.2.1","Video Microscopic Image Storage" }, { "1.2.840.10008.5.1.4.1.1.77.1.3","VL Slide-Coordinates Microscopic Image Storage" }, { "1.2.840.10008.5.1.4.1.1.77.1.4","VL Photographic Image Storage" }, { "1.2.840.10008.5.1.4.1.1.77.1.4.1","Video Photographic Image Storage" }, { "1.2.840.10008.5.1.4.1.1.77.1.5.1","Ophthalmic Photography 8 Bit Image Storage" }, { "1.2.840.10008.5.1.4.1.1.77.1.5.2","Ophthalmic Photography 16 Bit Image Storage" }, { "1.2.840.10008.5.1.4.1.1.77.1.5.3","Stereometric Relationship Storage" }, { "1.2.840.10008.5.1.4.1.1.77.1.5.4","Ophthalmic Tomography Image Storage" }, { "1.2.840.10008.5.1.4.1.1.88.1","Text SR Storage - Trial" }, { "1.2.840.10008.5.1.4.1.1.88.2","Audio SR Storage - Trial" }, { "1.2.840.10008.5.1.4.1.1.88.3","Detail SR Storage - Trial" }, { "1.2.840.10008.5.1.4.1.1.88.4","Comprehensive SR Storage - Trial" }, { "1.2.840.10008.5.1.4.1.1.88.11","Basic Text SR Storage" }, { "1.2.840.10008.5.1.4.1.1.88.22","Enhanced SR Storage" }, { "1.2.840.10008.5.1.4.1.1.88.33","Comprehensive SR Storage" }, { "1.2.840.10008.5.1.4.1.1.88.40","Procedure Log Storage" }, { "1.2.840.10008.5.1.4.1.1.88.50","Mammography CAD SR Storage" }, { "1.2.840.10008.5.1.4.1.1.88.59","Key Object Selection Document Storage" }, { "1.2.840.10008.5.1.4.1.1.88.65","Chest CAD SR Storage" }, { "1.2.840.10008.5.1.4.1.1.88.67","X-Ray Radiation Dose SR Storage" }, { "1.2.840.10008.5.1.4.1.1.104.1","Encapsulated PDF Storage" }, { "1.2.840.10008.5.1.4.1.1.104.2","Encapsulated CDA Storage" }, { "1.2.840.10008.5.1.4.1.1.128","Positron Emission Tomography Image Storage" }, { "1.2.840.10008.5.1.4.1.1.129","Standalone PET Curve Storage" }, { "1.2.840.10008.5.1.4.1.1.481.1","RT Image Storage" }, { "1.2.840.10008.5.1.4.1.1.481.2","RT Dose Storage" }, { "1.2.840.10008.5.1.4.1.1.481.3","RT Structure Set Storage" }, { "1.2.840.10008.5.1.4.1.1.481.4","RT Beams Treatment Record Storage" }, { "1.2.840.10008.5.1.4.1.1.481.5","RT Plan Storage" }, { "1.2.840.10008.5.1.4.1.1.481.6","RT Brachy Treatment Record Storage" }, { "1.2.840.10008.5.1.4.1.1.481.7","RT Treatment Summary Record Storage" }, { "1.2.840.10008.5.1.4.1.1.481.8","RT Ion Plan Storage" }, { "1.2.840.10008.5.1.4.1.1.481.9","RT Ion Beams Treatment Record Storage" }, { "1.2.840.10008.5.1.4.1.2.1.1","Patient Root Query/Retrieve Information Model - FIND" }, { "1.2.840.10008.5.1.4.1.2.1.2","Patient Root Query/Retrieve Information Model - MOVE" }, { "1.2.840.10008.5.1.4.1.2.1.3","Patient Root Query/Retrieve Information Model - GET" }, { "1.2.840.10008.5.1.4.1.2.2.1","Study Root Query/Retrieve Information Model - FIND" }, { "1.2.840.10008.5.1.4.1.2.2.2","Study Root Query/Retrieve Information Model - MOVE" }, { "1.2.840.10008.5.1.4.1.2.2.3","Study Root Query/Retrieve Information Model - GET" }, { "1.2.840.10008.5.1.4.1.2.3.1","Patient/Study Only Query/Retrieve Information Model - FIND" }, { "1.2.840.10008.5.1.4.1.2.3.2","Patient/Study Only Query/Retrieve Information Model - MOVE" }, { "1.2.840.10008.5.1.4.1.2.3.3","Patient/Study Only Query/Retrieve Information Model - GET" }, { "1.2.840.10008.5.1.4.31","Modality Worklist Information Model - FIND" }, { "1.2.840.10008.5.1.4.32.1","General Purpose Worklist Information Model - FIND" }, { "1.2.840.10008.5.1.4.32.2","General Purpose Scheduled Procedure Step SOP Class" }, { "1.2.840.10008.5.1.4.32.3","General Purpose Performed Procedure Step SOP Class" }, { "1.2.840.10008.5.1.4.32","General Purpose Worklist Management Meta SOP Class" }, { "1.2.840.10008.5.1.4.33","Instance Availability Notification SOP Class" }, { "1.2.840.10008.5.1.4.34.1","RT Beams Delivery Instruction Storage (Supplement 74 Frozen Draft)" }, { "1.2.840.10008.5.1.4.34.2","RT Conventional Machine Verification (Supplement 74 Frozen Draft)" }, { "1.2.840.10008.5.1.4.34.3","RT Ion Machine Verification (Supplement 74 Frozen Draft)" }, { "1.2.840.10008.5.1.4.34.4","Unified Worklist and Procedure Step Service Class" }, { "1.2.840.10008.5.1.4.34.4.1","Unified Procedure Step - Push SOP Class" }, { "1.2.840.10008.5.1.4.34.4.2","Unified Procedure Step - Watch SOP Class" }, { "1.2.840.10008.5.1.4.34.4.3","Unified Procedure Step - Pull SOP Class" }, { "1.2.840.10008.5.1.4.34.4.4","Unified Procedure Step - Event SOP Class" }, { "1.2.840.10008.5.1.4.34.5","Unified Worklist and Procedure Step SOP Instance" }, { "1.2.840.10008.5.1.4.37.1","General Relevant Patient Information Query" }, { "1.2.840.10008.5.1.4.37.2","Breast Imaging Relevant Patient Information Query" }, { "1.2.840.10008.5.1.4.37.3","Cardiac Relevant Patient Information Query" }, { "1.2.840.10008.5.1.4.38.1","Hanging Protocol Storage" }, { "1.2.840.10008.5.1.4.38.2","Hanging Protocol Information Model - FIND" }, { "1.2.840.10008.5.1.4.38.3","Hanging Protocol Information Model - MOVE" }, { "1.2.840.10008.5.1.4.41","Product Characteristics Query SOP Class" }, { "1.2.840.10008.5.1.4.42","Substance Approval Query SOP Class" }, { "1.2.840.10008.15.0.3.1","dicomDeviceName" }, { "1.2.840.10008.15.0.3.2","dicomDescription" }, { "1.2.840.10008.15.0.3.3","dicomManufacturer" }, { "1.2.840.10008.15.0.3.4","dicomManufacturerModelName" }, { "1.2.840.10008.15.0.3.5","dicomSoftwareVersion" }, { "1.2.840.10008.15.0.3.6","dicomVendorData" }, { "1.2.840.10008.15.0.3.7","dicomAETitle" }, { "1.2.840.10008.15.0.3.8","dicomNetworkConnectionReference" }, { "1.2.840.10008.15.0.3.9","dicomApplicationCluster" }, { "1.2.840.10008.15.0.3.10","dicomAssociationInitiator" }, { "1.2.840.10008.15.0.3.11","dicomAssociationAcceptor" }, { "1.2.840.10008.15.0.3.12","dicomHostname" }, { "1.2.840.10008.15.0.3.13","dicomPort" }, { "1.2.840.10008.15.0.3.14","dicomSOPClass" }, { "1.2.840.10008.15.0.3.15","dicomTransferRole" }, { "1.2.840.10008.15.0.3.16","dicomTransferSyntax" }, { "1.2.840.10008.15.0.3.17","dicomPrimaryDeviceType" }, { "1.2.840.10008.15.0.3.18","dicomRelatedDeviceReference" }, { "1.2.840.10008.15.0.3.19","dicomPreferredCalledAETitle" }, { "1.2.840.10008.15.0.3.20","dicomTLSCyphersuite" }, { "1.2.840.10008.15.0.3.21","dicomAuthorizedNodeCertificateReference" }, { "1.2.840.10008.15.0.3.22","dicomThisNodeCertificateReference" }, { "1.2.840.10008.15.0.3.23","dicomInstalled" }, { "1.2.840.10008.15.0.3.24","dicomStationName" }, { "1.2.840.10008.15.0.3.25","dicomDeviceSerialNumber" }, { "1.2.840.10008.15.0.3.26","dicomInstitutionName" }, { "1.2.840.10008.15.0.3.27","dicomInstitutionAddress" }, { "1.2.840.10008.15.0.3.28","dicomInstitutionDepartmentName" }, { "1.2.840.10008.15.0.3.29","dicomIssuerOfPatientID" }, { "1.2.840.10008.15.0.3.30","dicomPreferredCallingAETitle" }, { "1.2.840.10008.15.0.3.31","dicomSupportedCharacterSet" }, { "1.2.840.10008.15.0.4.1","dicomConfigurationRoot" }, { "1.2.840.10008.15.0.4.2","dicomDevicesRoot" }, { "1.2.840.10008.15.0.4.3","dicomUniqueAETitlesRegistryRoot" }, { "1.2.840.10008.15.0.4.4","dicomDevice" }, { "1.2.840.10008.15.0.4.5","dicomNetworkAE" }, { "1.2.840.10008.15.0.4.6","dicomNetworkConnection" }, { "1.2.840.10008.15.0.4.7","dicomUniqueAETitle" }, { "1.2.840.10008.15.0.4.8","dicomTransferCapability" }, { "1.2.840.113619.4.2","General Electric Magnetic Resonance Image Storage" }, { "1.2.840.113619.4.3","General Electric Computed Tomography Image Storage" }, { "1.3.12.2.1107.5.9.1","CSA Non-Image Storage" }, { "1.2.840.113619.4.26","GE Private 3D Model Storage" }, { "1.2.840.113619.4.30","GE Advance (PET) Raw Data Storage" }, { "2.16.840.1.113709.1.5.1","GEPACS_PRIVATE_IMS_INFO Storage" }, { "1.2.840.113543.6.6.1.3.10002","Unregistered (?) Philips3D" }, { "1.2.392.200036.9116.7.8.1.1.1","Toshiba Private Data Storage" }, { "1.2.840.113619.4.27","GE Nuclear Medicine private SOP Class" }, //{ "1.3.46.670589.11.0.0.12.1","Philips Private Gyroscan MR Spectrum" }, { "1.3.46.670589.11.0.0.12.1","Philips Private MR Spectrum Storage" }, //{ "1.3.46.670589.11.0.0.12.2","Philips Private Gyroscan MR Series Data" }, { "1.3.46.670589.11.0.0.12.2","Philips Private MR Series Data Storage" }, { "1.3.46.670589.2.3.1.1","Philips Private Specialized XA Image" }, { "1.3.46.670589.2.4.1.1","Philips Private CX Image Storage" }, { "1.3.46.670589.2.5.1.1","Philips iE33 private 3D Object Storage" }, { "1.3.46.670589.5.0.1","Philips Private Volume Storage" }, { "1.3.46.670589.5.0.1.1","Philips Private Volume Image Reference" }, { "1.3.46.670589.5.0.10","Philips Private MR Synthetic Image Storage" }, { "1.3.46.670589.5.0.11","Philips Private MR Cardio Analysis Storage" }, { "1.3.46.670589.5.0.11.1","Philips Private MR Cardio Analysis Data" }, { "1.3.46.670589.5.0.12","Philips Private CX Synthetic Image Storage" }, { "1.3.46.670589.5.0.13","Philips Private Perfusion Image Reference" }, { "1.3.46.670589.5.0.14","Philips Private Perfusion Analysis Data" }, { "1.3.46.670589.5.0.2","Philips Private 3D Object Storage" }, { "1.3.46.670589.5.0.2.1","Philips Private 3D Object 2 Storage" }, { "1.3.46.670589.5.0.3","Philips Private Surface Storage" }, { "1.3.46.670589.5.0.3.1","Philips Private Surface 2 Storage" }, { "1.3.46.670589.5.0.4","Philips Private Composite Object Storage" }, { "1.3.46.670589.5.0.7","Philips Private MR Cardio Profile" }, { "1.3.46.670589.5.0.8","Philips Private MR Cardio" }, { "1.3.46.670589.5.0.9","Philips Private CT Synthetic Image Storage" }, { "1.2.752.24.3.7.6","Sectra Compression (Private Syntax)" }, { "1.2.752.24.3.7.7","Sectra Compression LS (Private Syntax)" }, { "1.2.840.113619.5.2","Implicit VR Big Endian DLX (G.E Private)" }, { nullptr, nullptr} }; // Custom list: static const char * const sopclassuids2[] = { "1.2.840.10008.1.3.10", "1.2.840.10008.5.1.4.1.1.1", "1.2.840.10008.5.1.4.1.1.1.1", "1.2.840.10008.5.1.4.1.1.11.1", "1.2.840.10008.5.1.4.1.1.1.2", "1.2.840.10008.5.1.4.1.1.12.1", "1.2.840.10008.5.1.4.1.1.12.2", "1.2.840.10008.5.1.4.1.1.128", "1.2.840.10008.5.1.4.1.1.2", "1.2.840.10008.5.1.4.1.1.20", "1.2.840.10008.5.1.4.1.1.3.1", "1.2.840.10008.5.1.4.1.1.4", "1.2.840.10008.5.1.4.1.1.4.1", "1.2.840.10008.5.1.4.1.1.481.3", "1.2.840.10008.5.1.4.1.1.5", "1.2.840.10008.5.1.4.1.1.6", "1.2.840.10008.5.1.4.1.1.6.1", "1.2.840.10008.5.1.4.1.1.66", "1.2.840.10008.5.1.4.1.1.7", "1.2.840.10008.5.1.4.1.1.88.11", "1.2.840.10008.5.1.4.1.1.88.22", "1.2.840.10008.5.1.4.1.1.88.3", "1.2.840.10008.5.1.4.1.1.88.59", "1.2.840.10008.5.1.4.1.1.9", "1.2.840.10008.5.1.4.1.1.9.4.1", "1.2.840.10008.5.1.4.38.1", "1.2.840.113619.4.26", "1.3.12.2.1107.5.9.1", "1.3.46.670589.11.0.0.12.2", "1.3.46.670589.5.0.1", "1.3.46.670589.5.0.10", "1.3.46.670589.5.0.1.1", "1.3.46.670589.5.0.11", "1.3.46.670589.5.0.13", "1.3.46.670589.5.0.14", "1.3.46.670589.5.0.2", "1.3.46.670589.5.0.2.1", "1.3.46.670589.5.0.3", "1.3.46.670589.5.0.8", //"1.3.6.1.4.1.20468.1.10", // invalid nullptr }; int TestUIDs(int, char *[]) { const char* s0 = gdcm::UIDs::GetUIDString( 0 ); if(s0) return 1; // {"1.2.840.10008.5.1.4.1.1.2.1","Enhanced CT Image Storage"}, // uid_1_2_840_10008_5_1_4_1_1_2_1 = 117, // Enhanced CT Image Storage const char* s = gdcm::UIDs::GetUIDString( gdcm::UIDs::uid_1_2_840_10008_5_1_4_1_1_2_1 ); if(!s) return 1; std::cout << s << std::endl; const char* n = gdcm::UIDs::GetUIDName( gdcm::UIDs::uid_1_2_840_10008_5_1_4_1_1_2_1 ); if(!n) return 1; std::cout << n << std::endl; const char* s1 = gdcm::UIDs::GetUIDString( gdcm::UIDs::EnhancedCTImageStorage ); if(!s1) return 1; std::cout << s1 << std::endl; const char* n1 = gdcm::UIDs::GetUIDName( gdcm::UIDs::EnhancedCTImageStorage ); if(!n1) return 1; std::cout << n1 << std::endl; gdcm::UIDs uid; // valid: if( !uid.SetFromUID( "1.2.840.10008.5.1.4.1.1.2.1" ) ) { return 1; } std::cout << "This is : " << uid.GetName() << std::endl; std::cout << "This is : " << uid.GetString() << std::endl; std::cout << uid << std::endl; // invalid if( uid.SetFromUID( "prosper youpla boum c'est le roi du pain d'epices" ) ) { return 1; } if( uid.GetName() ) return 1; if( uid.SetFromUID( "1.2" ) ) { return 1; } if( uid.GetName() ) return 1; if( uid.SetFromUID( "" ) ) { return 1; } if( uid.GetName() ) return 1; // black box: if( uid.SetFromUID( nullptr ) ) { return 1; } if( uid.GetName() ) return 1; using mytype = const char *const (*)[2]; mytype sopclassuid = sopclassuids; while( *sopclassuid[0] ) { const char *uid_str = (*sopclassuid)[0]; const char *name_str = (*sopclassuid)[1]; //std::cout << uid_str << std::endl; if( !uid.SetFromUID( uid_str ) ) { std::cerr << "Invalid UID:" << uid_str << std::endl; return 1; } const char *name = uid.GetName(); if( !name ) { std::cerr << "problem with: " << uid_str << std::endl; return 1; } if( strcmp( name, name_str) != 0 ) { std::cerr << "Error: " << name << " vs " << name_str << std::endl; return 1; } ++sopclassuid; } std::cout << "Custom List:" << std::endl; const char * const *s2 = sopclassuids2; while( *s2 ) { const char *uid_str = *s2; if( !uid.SetFromUID( uid_str ) ) { std::cerr << "Invalid UID:" << uid_str << std::endl; return 1; } const char *name = uid.GetName(); if( !name ) { return 1; } //std::cout << uid_str << "," << name << std::endl; s2++; } // Print all std::cout << "All:" << std::endl; for(unsigned int i = 0; i < gdcm::UIDs::GetNumberOfTransferSyntaxStrings(); ++i) { //const char * const * str_pair = gdcm::UIDs::GetTransferSyntaxString(i); uid.SetFromUID( gdcm::UIDs::GetUIDString( i+1 ) ); //std::cout << uid << std::endl; if( !uid.GetName() || !uid.GetString() ) return 1; } return 0; } GDCM-3.0.10/Testing/Source/DataDictionary/Python/000077500000000000000000000000001412732066400213475ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/DataDictionary/Python/CMakeLists.txt000066400000000000000000000003611412732066400241070ustar00rootroot00000000000000# Define the tests for gdcm-python # gdcm-python set(GDCM_PYTHON_TEST_SRCS TestGlobal TestDict ) # Loop over files and create executables foreach(name ${GDCM_PYTHON_TEST_SRCS}) ADD_PYTHON_TEST(${name}Python ${name}.py) endforeach() GDCM-3.0.10/Testing/Source/DataDictionary/Python/TestDict.py000066400000000000000000000021701412732066400234440ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import os,sys if __name__ == "__main__": singleton = gdcm.Global.GetInstance() dicts = singleton.GetDicts() d = dicts.GetPublicDict() t = gdcm.Tag(0x0010,0x0010) keyword = d.GetKeywordFromTag( t ) if keyword != 'PatientName': sys.exit(1) print(keyword) p = d.GetDictEntryByKeyword( keyword ) if p[0].GetKeyword() != keyword: sys.exit(1) print(p[0].GetKeyword()) p = d.GetDictEntryByKeyword( 'foobar' ) undef = gdcm.Tag(0xffff,0xffff) if p[1] != undef: sys.exit(1) print(p[1]) # Test succeed ? sys.exit(0) GDCM-3.0.10/Testing/Source/DataDictionary/Python/TestGlobal.py000066400000000000000000000016661412732066400237720ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import os,sys if __name__ == "__main__": #gi = gdcm.GlobalInstance #print gi singleton = gdcm.Global.GetInstance() print(singleton) d = singleton.GetDicts() print(d) t = gdcm.Tag(0x0010,0x0010) entry = d.GetDictEntry( t ) print(entry) print(entry.GetName()) #print entry.GetVM() print(entry.GetVR()) # Test succeed ? sys.exit(0) GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/000077500000000000000000000000001412732066400240645ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/CMakeLists.txt000066400000000000000000000003061412732066400266230ustar00rootroot00000000000000# Always add_subdirectory(Cxx) if(GDCM_WRAP_PYTHON) add_subdirectory(Python) endif() if(GDCM_WRAP_CSHARP) add_subdirectory(Csharp) endif() if(GDCM_WRAP_JAVA) add_subdirectory(Java) endif() GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Csharp/000077500000000000000000000000001412732066400253045ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Csharp/CMakeLists.txt000066400000000000000000000020121412732066400300370ustar00rootroot00000000000000# C# MSFF tests set(DSED_TEST_SRCS TestReaderUnicode ) set(DEP) set_source_files_properties(${GDCM_LIBRARY_DIR}/gdcm-sharp.dll PROPERTIES GENERATED 1) foreach(test ${DSED_TEST_SRCS}) file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${test}.cs result) add_custom_command( OUTPUT ${GDCM_EXECUTABLE_DIR}/${test}.exe COMMAND ${CMAKE_CSHARP_COMPILER} "${CSC_PLATFORM_FLAG}" "/r:${GDCM_LIBRARY_DIR}/gdcm-sharp.dll" "/out:${GDCM_EXECUTABLE_DIR}/${test}.exe" ${result} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${test}.cs COMMENT "Create ${test}.exe" ) add_custom_target(gdcm_sharp_${test} DEPENDS ${GDCM_EXECUTABLE_DIR}/${test}.exe) add_dependencies(gdcm_sharp_${test} GDCMCSharp) list(APPEND DEP ${GDCM_EXECUTABLE_DIR}/${test}.exe) # add test if(GDCM_DATA_ROOT) ADD_CSHARP_TEST(Test${test}Csharp ${GDCM_EXECUTABLE_DIR}/${test}.exe) endif() endforeach() add_custom_target(gdcmDSEDTestsCsharp ALL DEPENDS ${DEP} COMMENT "building DSED C# tests" ) add_dependencies(gdcmDSEDTestsCsharp GDCMCSharp) GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Csharp/TestReaderUnicode.cs000066400000000000000000000047171412732066400312150ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ using System; using System.IO; using gdcm; public class TestReaderUnicode { public static void copyFile( string sourceFileName, string destFileName ) { System.IO.File.Copy (sourceFileName, destFileName); } public static void process(String template, String tmpdir, String targetname) { if(!PosixEmulation.FileIsDirectory( tmpdir ) ) { PosixEmulation.MakeDirectory( tmpdir ); } String filename = tmpdir + "/" + targetname; PosixEmulation.RemoveFile( filename ); try { copyFile(template, filename); } catch (IOException ex) { Console.WriteLine("Error copying: " + template + " to " + filename ); throw ex; } Reader reader = new Reader(); Console.WriteLine("Reading: " + filename ); reader.SetFileName( filename ); if ( !reader.Read() ) { throw new Exception("Could not read: " + filename ); } String reference = Testing.GetMediaStorageFromFile(template); if( reference == null || reference == "" ) { throw new Exception("Missing ref for: " + template); } MediaStorage ms = new MediaStorage(); ms.SetFromFile( reader.GetFile() ); if( ms.IsUndefined() ) { throw new Exception("ref is undefined for: " + filename + " should be " + reference ); } MediaStorage.MSType ref_mstype = MediaStorage.GetMSType( reference ); if( ms.GetMSType() != ref_mstype ) { throw new Exception("incompatible type: " + reference + " vs " + ms.GetString() + " for " + filename ); } } public static int Main(string[] args) { String dataroot = Testing.GetDataRoot(); String filename = dataroot + "/012345.002.050.dcm"; String subdir = "TestReaderUnicode"; String tmpdir = Testing.GetTempDirectory( subdir ); process(filename, tmpdir, "ascii.dcm" ); process(filename, tmpdir, "ê.dcm" ); process(filename, tmpdir, "А.dcm" ); return 0; } } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/000077500000000000000000000000001412732066400246265ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/CMakeLists.txt000066400000000000000000000060111412732066400273640ustar00rootroot00000000000000# Define the tests for Data Structure and Encoding Definitions # DSED set(DSED_TEST_SRCS TestAttribute.cxx TestCodeString.cxx TestAttribute1.cxx TestAttribute7.cxx #TestReadPatientName.cxx TestLO.cxx TestCSAElement.cxx #TestByteBuffer.cxx #TestByteValue.cxx TestPreamble.cxx TestReader.cxx #TestReader4.cxx # FIXME TestReaderUpToTag1.cxx TestReaderUpToTag2.cxx TestReaderSelectedTags.cxx TestReaderSelectedPrivateGroups.cxx TestReaderCanRead.cxx TestWriter.cxx TestWriter2.cxx TestCSAHeader.cxx TestByteSwapFilter.cxx TestBasicOffsetTable.cxx TestComposite.cxx TestDataElement.cxx TestDataSet.cxx #TestVRDS.cxx TestDS.cxx TestVRLT.cxx TestVRUI.cxx TestElement1.cxx #TestExplicitDataElement.cxx TestFile.cxx TestFileSet.cxx TestFragment.cxx #TestImplicitDataElement.cxx TestItem.cxx #TestParser.cxx TestSequenceOfFragments.cxx TestSequenceOfItems.cxx TestTag.cxx TestPrivateTag.cxx TestTransferSyntax.cxx TestMediaStorage.cxx TestVL.cxx TestVM.cxx TestVR.cxx #TestValue.cxx #TestTorture.cxx TestElement2.cxx TestElement4.cxx TestElement5.cxx TestElement6.cxx ) if(GDCM_TESTING_USE_LC_NUMERIC) # The test expect to be able to set fr as locale only turn if user # set the appropriate & hidden cmake variable set(DSED_TEST_SRCS ${DSED_TEST_SRCS} TestLCNumeric.cxx ) endif() if(GDCM_DATA_ROOT) set(DSED_TEST_SRCS ${DSED_TEST_SRCS} TestFileMetaInformation.cxx TestReader2.cxx TestAttribute8.cxx TestPDBHeader.cxx TestSequenceOfItems2.cxx TestSequenceOfItems3.cxx ) endif() if(GDCM_DATA_EXTRA_ROOT) set(DSED_TEST_SRCS ${DSED_TEST_SRCS} TestInvalidDICOMFiles.cxx ) endif() CHECK_INCLUDE_FILE("sys/mman.h" GDCM_HAVE_SYS_MMAN_H) # Need mmap if(GDCM_HAVE_SYS_MMAN_H) set(DSED_TEST_SRCS ${DSED_TEST_SRCS} TestReader3.cxx ) endif() option(SHARED_PTR "shared_ptr" OFF) mark_as_advanced(SHARED_PTR) if(SHARED_PTR) set(DSED_TEST_SRCS ${DSED_TEST_SRCS} TestCopyValue.cxx ) endif() # Add the include paths include_directories( "${GDCM_BINARY_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/DataDictionary" "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition" "${GDCM_BINARY_DIR}/Utilities/zlib" "${GDCM_SOURCE_DIR}/Utilities" ) create_test_sourcelist(DSEDTests gdcmDSEDTests.cxx ${DSED_TEST_SRCS} EXTRA_INCLUDE gdcmTestDriver.h ) add_executable(gdcmDSEDTests ${DSEDTests}) target_link_libraries(gdcmDSEDTests gdcmDSED) if(CMAKE_COMPILER_IS_GNUCXX AND MINGW) set_target_properties( gdcmDSEDTests PROPERTIES LINK_FLAGS "-Wl,--allow-multiple-definition") endif() # Loop over files and create executables foreach(name ${DSED_TEST_SRCS}) get_filename_component(testname ${name} NAME_WE) add_test(NAME ${testname} COMMAND gdcmDSEDTests ${testname}) endforeach() # FIXME #add_executable(TestAttribute2 TestAttribute2.cxx) #add_executable(TestAttribute3 TestAttribute3.cxx) #add_executable(TestAttribute4 TestAttribute4.cxx) #add_executable(TestAttribute5 TestAttribute5.cxx) GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestAttribute.cxx000066400000000000000000004713621412732066400301720ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc TestAttribute.xsl DICOMV3.xml > TestAttribute.cxx /*========================================================================= 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 "gdcmAttribute.h" int TestAttribute(int, char *[]) { gdcm::Attribute<0x0000,0x0000> a00000000; (void)a00000000; gdcm::Attribute<0x0000,0x0001> a00000001; (void)a00000001; gdcm::Attribute<0x0000,0x0002> a00000002; (void)a00000002; gdcm::Attribute<0x0000,0x0003> a00000003; (void)a00000003; gdcm::Attribute<0x0000,0x0010> a00000010; (void)a00000010; gdcm::Attribute<0x0000,0x0100> a00000100; (void)a00000100; gdcm::Attribute<0x0000,0x0110> a00000110; (void)a00000110; gdcm::Attribute<0x0000,0x0120> a00000120; (void)a00000120; gdcm::Attribute<0x0000,0x0200> a00000200; (void)a00000200; gdcm::Attribute<0x0000,0x0300> a00000300; (void)a00000300; gdcm::Attribute<0x0000,0x0400> a00000400; (void)a00000400; gdcm::Attribute<0x0000,0x0600> a00000600; (void)a00000600; gdcm::Attribute<0x0000,0x0700> a00000700; (void)a00000700; gdcm::Attribute<0x0000,0x0800> a00000800; (void)a00000800; gdcm::Attribute<0x0000,0x0850> a00000850; (void)a00000850; gdcm::Attribute<0x0000,0x0860> a00000860; (void)a00000860; gdcm::Attribute<0x0000,0x0900> a00000900; (void)a00000900; gdcm::Attribute<0x0000,0x0901> a00000901; (void)a00000901; gdcm::Attribute<0x0000,0x0902> a00000902; (void)a00000902; gdcm::Attribute<0x0000,0x0903> a00000903; (void)a00000903; gdcm::Attribute<0x0000,0x1000> a00001000; (void)a00001000; gdcm::Attribute<0x0000,0x1001> a00001001; (void)a00001001; gdcm::Attribute<0x0000,0x1002> a00001002; (void)a00001002; gdcm::Attribute<0x0000,0x1005> a00001005; (void)a00001005; gdcm::Attribute<0x0000,0x1008> a00001008; (void)a00001008; gdcm::Attribute<0x0000,0x1020> a00001020; (void)a00001020; gdcm::Attribute<0x0000,0x1021> a00001021; (void)a00001021; gdcm::Attribute<0x0000,0x1022> a00001022; (void)a00001022; gdcm::Attribute<0x0000,0x1023> a00001023; (void)a00001023; gdcm::Attribute<0x0000,0x1030> a00001030; (void)a00001030; gdcm::Attribute<0x0000,0x1031> a00001031; (void)a00001031; gdcm::Attribute<0x0000,0x4000> a00004000; (void)a00004000; gdcm::Attribute<0x0000,0x4010> a00004010; (void)a00004010; gdcm::Attribute<0x0000,0x5010> a00005010; (void)a00005010; gdcm::Attribute<0x0000,0x5020> a00005020; (void)a00005020; gdcm::Attribute<0x0000,0x5110> a00005110; (void)a00005110; gdcm::Attribute<0x0000,0x5120> a00005120; (void)a00005120; gdcm::Attribute<0x0000,0x5130> a00005130; (void)a00005130; gdcm::Attribute<0x0000,0x5140> a00005140; (void)a00005140; gdcm::Attribute<0x0000,0x5150> a00005150; (void)a00005150; gdcm::Attribute<0x0000,0x5160> a00005160; (void)a00005160; gdcm::Attribute<0x0000,0x5170> a00005170; (void)a00005170; gdcm::Attribute<0x0000,0x5180> a00005180; (void)a00005180; gdcm::Attribute<0x0000,0x5190> a00005190; (void)a00005190; gdcm::Attribute<0x0000,0x51a0> a000051a0; (void)a000051a0; gdcm::Attribute<0x0000,0x51b0> a000051b0; (void)a000051b0; gdcm::Attribute<0x0002,0x0000> a00020000; (void)a00020000; gdcm::Attribute<0x0002,0x0001> a00020001; (void)a00020001; gdcm::Attribute<0x0002,0x0002> a00020002; (void)a00020002; gdcm::Attribute<0x0002,0x0003> a00020003; (void)a00020003; gdcm::Attribute<0x0002,0x0010> a00020010; (void)a00020010; gdcm::Attribute<0x0002,0x0012> a00020012; (void)a00020012; gdcm::Attribute<0x0002,0x0013> a00020013; (void)a00020013; gdcm::Attribute<0x0002,0x0016> a00020016; (void)a00020016; gdcm::Attribute<0x0002,0x0100> a00020100; (void)a00020100; gdcm::Attribute<0x0002,0x0102> a00020102; (void)a00020102; gdcm::Attribute<0x0004,0x1130> a00041130; (void)a00041130; gdcm::Attribute<0x0004,0x1142> a00041142; (void)a00041142; gdcm::Attribute<0x0004,0x1200> a00041200; (void)a00041200; gdcm::Attribute<0x0004,0x1202> a00041202; (void)a00041202; gdcm::Attribute<0x0004,0x1212> a00041212; (void)a00041212; gdcm::Attribute<0x0004,0x1220> a00041220; (void)a00041220; gdcm::Attribute<0x0004,0x1400> a00041400; (void)a00041400; gdcm::Attribute<0x0004,0x1410> a00041410; (void)a00041410; gdcm::Attribute<0x0004,0x1420> a00041420; (void)a00041420; gdcm::Attribute<0x0004,0x1430> a00041430; (void)a00041430; gdcm::Attribute<0x0004,0x1432> a00041432; (void)a00041432; gdcm::Attribute<0x0004,0x1504> a00041504; (void)a00041504; gdcm::Attribute<0x0004,0x1510> a00041510; (void)a00041510; gdcm::Attribute<0x0004,0x1511> a00041511; (void)a00041511; gdcm::Attribute<0x0004,0x1512> a00041512; (void)a00041512; gdcm::Attribute<0x0004,0x151a> a0004151a; (void)a0004151a; gdcm::Attribute<0x0004,0x1600> a00041600; (void)a00041600; gdcm::Attribute<0x0008,0x0001> a00080001; (void)a00080001; gdcm::Attribute<0x0008,0x0005> a00080005; (void)a00080005; gdcm::Attribute<0x0008,0x0008> a00080008; (void)a00080008; gdcm::Attribute<0x0008,0x0010> a00080010; (void)a00080010; gdcm::Attribute<0x0008,0x0012> a00080012; (void)a00080012; gdcm::Attribute<0x0008,0x0013> a00080013; (void)a00080013; gdcm::Attribute<0x0008,0x0014> a00080014; (void)a00080014; gdcm::Attribute<0x0008,0x0016> a00080016; (void)a00080016; gdcm::Attribute<0x0008,0x0018> a00080018; (void)a00080018; gdcm::Attribute<0x0008,0x001a> a0008001a; (void)a0008001a; gdcm::Attribute<0x0008,0x001b> a0008001b; (void)a0008001b; gdcm::Attribute<0x0008,0x0020> a00080020; (void)a00080020; gdcm::Attribute<0x0008,0x0021> a00080021; (void)a00080021; gdcm::Attribute<0x0008,0x0022> a00080022; (void)a00080022; gdcm::Attribute<0x0008,0x0023> a00080023; (void)a00080023; gdcm::Attribute<0x0008,0x0024> a00080024; (void)a00080024; gdcm::Attribute<0x0008,0x0025> a00080025; (void)a00080025; gdcm::Attribute<0x0008,0x002a> a0008002a; (void)a0008002a; gdcm::Attribute<0x0008,0x0030> a00080030; (void)a00080030; gdcm::Attribute<0x0008,0x0031> a00080031; (void)a00080031; gdcm::Attribute<0x0008,0x0032> a00080032; (void)a00080032; gdcm::Attribute<0x0008,0x0033> a00080033; (void)a00080033; gdcm::Attribute<0x0008,0x0034> a00080034; (void)a00080034; gdcm::Attribute<0x0008,0x0035> a00080035; (void)a00080035; gdcm::Attribute<0x0008,0x0040> a00080040; (void)a00080040; gdcm::Attribute<0x0008,0x0041> a00080041; (void)a00080041; gdcm::Attribute<0x0008,0x0042> a00080042; (void)a00080042; gdcm::Attribute<0x0008,0x0050> a00080050; (void)a00080050; gdcm::Attribute<0x0008,0x0052> a00080052; (void)a00080052; gdcm::Attribute<0x0008,0x0054> a00080054; (void)a00080054; gdcm::Attribute<0x0008,0x0056> a00080056; (void)a00080056; gdcm::Attribute<0x0008,0x0058> a00080058; (void)a00080058; gdcm::Attribute<0x0008,0x0060> a00080060; (void)a00080060; gdcm::Attribute<0x0008,0x0061> a00080061; (void)a00080061; gdcm::Attribute<0x0008,0x0062> a00080062; (void)a00080062; gdcm::Attribute<0x0008,0x0064> a00080064; (void)a00080064; gdcm::Attribute<0x0008,0x0068> a00080068; (void)a00080068; gdcm::Attribute<0x0008,0x0070> a00080070; (void)a00080070; gdcm::Attribute<0x0008,0x0080> a00080080; (void)a00080080; gdcm::Attribute<0x0008,0x0081> a00080081; (void)a00080081; gdcm::Attribute<0x0008,0x0082> a00080082; (void)a00080082; gdcm::Attribute<0x0008,0x0090> a00080090; (void)a00080090; gdcm::Attribute<0x0008,0x0092> a00080092; (void)a00080092; gdcm::Attribute<0x0008,0x0094> a00080094; (void)a00080094; gdcm::Attribute<0x0008,0x0096> a00080096; (void)a00080096; gdcm::Attribute<0x0008,0x0100> a00080100; (void)a00080100; gdcm::Attribute<0x0008,0x0102> a00080102; (void)a00080102; gdcm::Attribute<0x0008,0x0103> a00080103; (void)a00080103; gdcm::Attribute<0x0008,0x0104> a00080104; (void)a00080104; gdcm::Attribute<0x0008,0x0105> a00080105; (void)a00080105; gdcm::Attribute<0x0008,0x0106> a00080106; (void)a00080106; gdcm::Attribute<0x0008,0x0107> a00080107; (void)a00080107; gdcm::Attribute<0x0008,0x010b> a0008010b; (void)a0008010b; gdcm::Attribute<0x0008,0x010c> a0008010c; (void)a0008010c; gdcm::Attribute<0x0008,0x010d> a0008010d; (void)a0008010d; gdcm::Attribute<0x0008,0x010f> a0008010f; (void)a0008010f; gdcm::Attribute<0x0008,0x0110> a00080110; (void)a00080110; gdcm::Attribute<0x0008,0x0112> a00080112; (void)a00080112; gdcm::Attribute<0x0008,0x0114> a00080114; (void)a00080114; gdcm::Attribute<0x0008,0x0115> a00080115; (void)a00080115; gdcm::Attribute<0x0008,0x0116> a00080116; (void)a00080116; gdcm::Attribute<0x0008,0x0201> a00080201; (void)a00080201; gdcm::Attribute<0x0008,0x1000> a00081000; (void)a00081000; gdcm::Attribute<0x0008,0x1010> a00081010; (void)a00081010; gdcm::Attribute<0x0008,0x1030> a00081030; (void)a00081030; gdcm::Attribute<0x0008,0x1032> a00081032; (void)a00081032; gdcm::Attribute<0x0008,0x103e> a0008103e; (void)a0008103e; gdcm::Attribute<0x0008,0x1040> a00081040; (void)a00081040; gdcm::Attribute<0x0008,0x1048> a00081048; (void)a00081048; gdcm::Attribute<0x0008,0x1049> a00081049; (void)a00081049; gdcm::Attribute<0x0008,0x1050> a00081050; (void)a00081050; gdcm::Attribute<0x0008,0x1052> a00081052; (void)a00081052; gdcm::Attribute<0x0008,0x1060> a00081060; (void)a00081060; gdcm::Attribute<0x0008,0x1062> a00081062; (void)a00081062; gdcm::Attribute<0x0008,0x1070> a00081070; (void)a00081070; gdcm::Attribute<0x0008,0x1072> a00081072; (void)a00081072; gdcm::Attribute<0x0008,0x1080> a00081080; (void)a00081080; gdcm::Attribute<0x0008,0x1084> a00081084; (void)a00081084; gdcm::Attribute<0x0008,0x1090> a00081090; (void)a00081090; gdcm::Attribute<0x0008,0x1100> a00081100; (void)a00081100; gdcm::Attribute<0x0008,0x1110> a00081110; (void)a00081110; gdcm::Attribute<0x0008,0x1111> a00081111; (void)a00081111; gdcm::Attribute<0x0008,0x1115> a00081115; (void)a00081115; gdcm::Attribute<0x0008,0x1120> a00081120; (void)a00081120; gdcm::Attribute<0x0008,0x1125> a00081125; (void)a00081125; gdcm::Attribute<0x0008,0x1130> a00081130; (void)a00081130; gdcm::Attribute<0x0008,0x113a> a0008113a; (void)a0008113a; gdcm::Attribute<0x0008,0x1140> a00081140; (void)a00081140; gdcm::Attribute<0x0008,0x1145> a00081145; (void)a00081145; gdcm::Attribute<0x0008,0x114a> a0008114a; (void)a0008114a; gdcm::Attribute<0x0008,0x114b> a0008114b; (void)a0008114b; gdcm::Attribute<0x0008,0x1150> a00081150; (void)a00081150; gdcm::Attribute<0x0008,0x1155> a00081155; (void)a00081155; gdcm::Attribute<0x0008,0x115a> a0008115a; (void)a0008115a; gdcm::Attribute<0x0008,0x1160> a00081160; (void)a00081160; gdcm::Attribute<0x0008,0x1195> a00081195; (void)a00081195; gdcm::Attribute<0x0008,0x1197> a00081197; (void)a00081197; gdcm::Attribute<0x0008,0x1198> a00081198; (void)a00081198; gdcm::Attribute<0x0008,0x1199> a00081199; (void)a00081199; gdcm::Attribute<0x0008,0x1200> a00081200; (void)a00081200; gdcm::Attribute<0x0008,0x1250> a00081250; (void)a00081250; gdcm::Attribute<0x0008,0x2110> a00082110; (void)a00082110; gdcm::Attribute<0x0008,0x2111> a00082111; (void)a00082111; gdcm::Attribute<0x0008,0x2112> a00082112; (void)a00082112; gdcm::Attribute<0x0008,0x2120> a00082120; (void)a00082120; gdcm::Attribute<0x0008,0x2122> a00082122; (void)a00082122; gdcm::Attribute<0x0008,0x2124> a00082124; (void)a00082124; gdcm::Attribute<0x0008,0x2127> a00082127; (void)a00082127; gdcm::Attribute<0x0008,0x2128> a00082128; (void)a00082128; gdcm::Attribute<0x0008,0x2129> a00082129; (void)a00082129; gdcm::Attribute<0x0008,0x212a> a0008212a; (void)a0008212a; gdcm::Attribute<0x0008,0x2130> a00082130; (void)a00082130; gdcm::Attribute<0x0008,0x2132> a00082132; (void)a00082132; gdcm::Attribute<0x0008,0x2142> a00082142; (void)a00082142; gdcm::Attribute<0x0008,0x2143> a00082143; (void)a00082143; gdcm::Attribute<0x0008,0x2144> a00082144; (void)a00082144; gdcm::Attribute<0x0008,0x2200> a00082200; (void)a00082200; gdcm::Attribute<0x0008,0x2204> a00082204; (void)a00082204; gdcm::Attribute<0x0008,0x2208> a00082208; (void)a00082208; gdcm::Attribute<0x0008,0x2218> a00082218; (void)a00082218; gdcm::Attribute<0x0008,0x2220> a00082220; (void)a00082220; gdcm::Attribute<0x0008,0x2228> a00082228; (void)a00082228; gdcm::Attribute<0x0008,0x2229> a00082229; (void)a00082229; gdcm::Attribute<0x0008,0x2230> a00082230; (void)a00082230; gdcm::Attribute<0x0008,0x2240> a00082240; (void)a00082240; gdcm::Attribute<0x0008,0x2242> a00082242; (void)a00082242; gdcm::Attribute<0x0008,0x2244> a00082244; (void)a00082244; gdcm::Attribute<0x0008,0x2246> a00082246; (void)a00082246; gdcm::Attribute<0x0008,0x2251> a00082251; (void)a00082251; gdcm::Attribute<0x0008,0x2253> a00082253; (void)a00082253; gdcm::Attribute<0x0008,0x2255> a00082255; (void)a00082255; gdcm::Attribute<0x0008,0x2256> a00082256; (void)a00082256; gdcm::Attribute<0x0008,0x2257> a00082257; (void)a00082257; gdcm::Attribute<0x0008,0x2258> a00082258; (void)a00082258; gdcm::Attribute<0x0008,0x2259> a00082259; (void)a00082259; gdcm::Attribute<0x0008,0x225a> a0008225a; (void)a0008225a; gdcm::Attribute<0x0008,0x225c> a0008225c; (void)a0008225c; gdcm::Attribute<0x0008,0x3001> a00083001; (void)a00083001; gdcm::Attribute<0x0008,0x3010> a00083010; (void)a00083010; gdcm::Attribute<0x0008,0x4000> a00084000; (void)a00084000; gdcm::Attribute<0x0008,0x9007> a00089007; (void)a00089007; gdcm::Attribute<0x0008,0x9092> a00089092; (void)a00089092; gdcm::Attribute<0x0008,0x9121> a00089121; (void)a00089121; gdcm::Attribute<0x0008,0x9123> a00089123; (void)a00089123; gdcm::Attribute<0x0008,0x9124> a00089124; (void)a00089124; gdcm::Attribute<0x0008,0x9154> a00089154; (void)a00089154; gdcm::Attribute<0x0008,0x9205> a00089205; (void)a00089205; gdcm::Attribute<0x0008,0x9206> a00089206; (void)a00089206; gdcm::Attribute<0x0008,0x9207> a00089207; (void)a00089207; gdcm::Attribute<0x0008,0x9208> a00089208; (void)a00089208; gdcm::Attribute<0x0008,0x9209> a00089209; (void)a00089209; gdcm::Attribute<0x0008,0x9215> a00089215; (void)a00089215; gdcm::Attribute<0x0008,0x9237> a00089237; (void)a00089237; gdcm::Attribute<0x0008,0x9410> a00089410; (void)a00089410; gdcm::Attribute<0x0008,0x9458> a00089458; (void)a00089458; gdcm::Attribute<0x0008,0x9459> a00089459; (void)a00089459; gdcm::Attribute<0x0008,0x9460> a00089460; (void)a00089460; gdcm::Attribute<0x0010,0x0010> a00100010; (void)a00100010; gdcm::Attribute<0x0010,0x0020> a00100020; (void)a00100020; gdcm::Attribute<0x0010,0x0021> a00100021; (void)a00100021; gdcm::Attribute<0x0010,0x0022> a00100022; (void)a00100022; gdcm::Attribute<0x0010,0x0030> a00100030; (void)a00100030; gdcm::Attribute<0x0010,0x0032> a00100032; (void)a00100032; gdcm::Attribute<0x0010,0x0040> a00100040; (void)a00100040; gdcm::Attribute<0x0010,0x0050> a00100050; (void)a00100050; gdcm::Attribute<0x0010,0x0101> a00100101; (void)a00100101; gdcm::Attribute<0x0010,0x0102> a00100102; (void)a00100102; gdcm::Attribute<0x0010,0x1000> a00101000; (void)a00101000; gdcm::Attribute<0x0010,0x1001> a00101001; (void)a00101001; gdcm::Attribute<0x0010,0x1002> a00101002; (void)a00101002; gdcm::Attribute<0x0010,0x1005> a00101005; (void)a00101005; gdcm::Attribute<0x0010,0x1010> a00101010; (void)a00101010; gdcm::Attribute<0x0010,0x1020> a00101020; (void)a00101020; gdcm::Attribute<0x0010,0x1030> a00101030; (void)a00101030; gdcm::Attribute<0x0010,0x1040> a00101040; (void)a00101040; gdcm::Attribute<0x0010,0x1050> a00101050; (void)a00101050; gdcm::Attribute<0x0010,0x1060> a00101060; (void)a00101060; gdcm::Attribute<0x0010,0x1080> a00101080; (void)a00101080; gdcm::Attribute<0x0010,0x1081> a00101081; (void)a00101081; gdcm::Attribute<0x0010,0x1090> a00101090; (void)a00101090; gdcm::Attribute<0x0010,0x2000> a00102000; (void)a00102000; gdcm::Attribute<0x0010,0x2110> a00102110; (void)a00102110; gdcm::Attribute<0x0010,0x2150> a00102150; (void)a00102150; gdcm::Attribute<0x0010,0x2152> a00102152; (void)a00102152; gdcm::Attribute<0x0010,0x2154> a00102154; (void)a00102154; gdcm::Attribute<0x0010,0x2160> a00102160; (void)a00102160; gdcm::Attribute<0x0010,0x2180> a00102180; (void)a00102180; gdcm::Attribute<0x0010,0x21a0> a001021a0; (void)a001021a0; gdcm::Attribute<0x0010,0x21b0> a001021b0; (void)a001021b0; gdcm::Attribute<0x0010,0x21c0> a001021c0; (void)a001021c0; gdcm::Attribute<0x0010,0x21d0> a001021d0; (void)a001021d0; gdcm::Attribute<0x0010,0x21f0> a001021f0; (void)a001021f0; gdcm::Attribute<0x0010,0x2201> a00102201; (void)a00102201; gdcm::Attribute<0x0010,0x2202> a00102202; (void)a00102202; gdcm::Attribute<0x0010,0x2203> a00102203; (void)a00102203; gdcm::Attribute<0x0010,0x2292> a00102292; (void)a00102292; gdcm::Attribute<0x0010,0x2293> a00102293; (void)a00102293; gdcm::Attribute<0x0010,0x2294> a00102294; (void)a00102294; gdcm::Attribute<0x0010,0x2295> a00102295; (void)a00102295; gdcm::Attribute<0x0010,0x2296> a00102296; (void)a00102296; gdcm::Attribute<0x0010,0x2297> a00102297; (void)a00102297; gdcm::Attribute<0x0010,0x2298> a00102298; (void)a00102298; gdcm::Attribute<0x0010,0x2299> a00102299; (void)a00102299; gdcm::Attribute<0x0010,0x4000> a00104000; (void)a00104000; gdcm::Attribute<0x0010,0x9431> a00109431; (void)a00109431; gdcm::Attribute<0x0012,0x0010> a00120010; (void)a00120010; gdcm::Attribute<0x0012,0x0020> a00120020; (void)a00120020; gdcm::Attribute<0x0012,0x0021> a00120021; (void)a00120021; gdcm::Attribute<0x0012,0x0030> a00120030; (void)a00120030; gdcm::Attribute<0x0012,0x0031> a00120031; (void)a00120031; gdcm::Attribute<0x0012,0x0040> a00120040; (void)a00120040; gdcm::Attribute<0x0012,0x0042> a00120042; (void)a00120042; gdcm::Attribute<0x0012,0x0050> a00120050; (void)a00120050; gdcm::Attribute<0x0012,0x0051> a00120051; (void)a00120051; gdcm::Attribute<0x0012,0x0060> a00120060; (void)a00120060; gdcm::Attribute<0x0012,0x0062> a00120062; (void)a00120062; gdcm::Attribute<0x0012,0x0063> a00120063; (void)a00120063; gdcm::Attribute<0x0012,0x0064> a00120064; (void)a00120064; gdcm::Attribute<0x0012,0x0071> a00120071; (void)a00120071; gdcm::Attribute<0x0012,0x0072> a00120072; (void)a00120072; gdcm::Attribute<0x0018,0x0010> a00180010; (void)a00180010; gdcm::Attribute<0x0018,0x0012> a00180012; (void)a00180012; gdcm::Attribute<0x0018,0x0014> a00180014; (void)a00180014; gdcm::Attribute<0x0018,0x0015> a00180015; (void)a00180015; gdcm::Attribute<0x0018,0x0020> a00180020; (void)a00180020; gdcm::Attribute<0x0018,0x0021> a00180021; (void)a00180021; gdcm::Attribute<0x0018,0x0022> a00180022; (void)a00180022; gdcm::Attribute<0x0018,0x0023> a00180023; (void)a00180023; gdcm::Attribute<0x0018,0x0024> a00180024; (void)a00180024; gdcm::Attribute<0x0018,0x0025> a00180025; (void)a00180025; gdcm::Attribute<0x0018,0x0026> a00180026; (void)a00180026; gdcm::Attribute<0x0018,0x0027> a00180027; (void)a00180027; gdcm::Attribute<0x0018,0x0028> a00180028; (void)a00180028; gdcm::Attribute<0x0018,0x0029> a00180029; (void)a00180029; gdcm::Attribute<0x0018,0x002a> a0018002a; (void)a0018002a; gdcm::Attribute<0x0018,0x0030> a00180030; (void)a00180030; gdcm::Attribute<0x0018,0x0031> a00180031; (void)a00180031; gdcm::Attribute<0x0018,0x0032> a00180032; (void)a00180032; gdcm::Attribute<0x0018,0x0033> a00180033; (void)a00180033; gdcm::Attribute<0x0018,0x0034> a00180034; (void)a00180034; gdcm::Attribute<0x0018,0x0035> a00180035; (void)a00180035; gdcm::Attribute<0x0018,0x0036> a00180036; (void)a00180036; gdcm::Attribute<0x0018,0x0037> a00180037; (void)a00180037; gdcm::Attribute<0x0018,0x0038> a00180038; (void)a00180038; gdcm::Attribute<0x0018,0x0039> a00180039; (void)a00180039; gdcm::Attribute<0x0018,0x003a> a0018003a; (void)a0018003a; gdcm::Attribute<0x0018,0x0040> a00180040; (void)a00180040; gdcm::Attribute<0x0018,0x0050> a00180050; (void)a00180050; gdcm::Attribute<0x0018,0x0060> a00180060; (void)a00180060; gdcm::Attribute<0x0018,0x0070> a00180070; (void)a00180070; gdcm::Attribute<0x0018,0x0071> a00180071; (void)a00180071; gdcm::Attribute<0x0018,0x0072> a00180072; (void)a00180072; gdcm::Attribute<0x0018,0x0073> a00180073; (void)a00180073; gdcm::Attribute<0x0018,0x0074> a00180074; (void)a00180074; gdcm::Attribute<0x0018,0x0075> a00180075; (void)a00180075; gdcm::Attribute<0x0018,0x0080> a00180080; (void)a00180080; gdcm::Attribute<0x0018,0x0081> a00180081; (void)a00180081; gdcm::Attribute<0x0018,0x0082> a00180082; (void)a00180082; gdcm::Attribute<0x0018,0x0083> a00180083; (void)a00180083; gdcm::Attribute<0x0018,0x0084> a00180084; (void)a00180084; gdcm::Attribute<0x0018,0x0085> a00180085; (void)a00180085; gdcm::Attribute<0x0018,0x0086> a00180086; (void)a00180086; gdcm::Attribute<0x0018,0x0087> a00180087; (void)a00180087; gdcm::Attribute<0x0018,0x0088> a00180088; (void)a00180088; gdcm::Attribute<0x0018,0x0089> a00180089; (void)a00180089; gdcm::Attribute<0x0018,0x0090> a00180090; (void)a00180090; gdcm::Attribute<0x0018,0x0091> a00180091; (void)a00180091; gdcm::Attribute<0x0018,0x0093> a00180093; (void)a00180093; gdcm::Attribute<0x0018,0x0094> a00180094; (void)a00180094; gdcm::Attribute<0x0018,0x0095> a00180095; (void)a00180095; gdcm::Attribute<0x0018,0x1000> a00181000; (void)a00181000; gdcm::Attribute<0x0018,0x1002> a00181002; (void)a00181002; gdcm::Attribute<0x0018,0x1003> a00181003; (void)a00181003; gdcm::Attribute<0x0018,0x1004> a00181004; (void)a00181004; gdcm::Attribute<0x0018,0x1005> a00181005; (void)a00181005; gdcm::Attribute<0x0018,0x1006> a00181006; (void)a00181006; gdcm::Attribute<0x0018,0x1007> a00181007; (void)a00181007; gdcm::Attribute<0x0018,0x1008> a00181008; (void)a00181008; gdcm::Attribute<0x0018,0x1010> a00181010; (void)a00181010; gdcm::Attribute<0x0018,0x1011> a00181011; (void)a00181011; gdcm::Attribute<0x0018,0x1012> a00181012; (void)a00181012; gdcm::Attribute<0x0018,0x1014> a00181014; (void)a00181014; gdcm::Attribute<0x0018,0x1016> a00181016; (void)a00181016; gdcm::Attribute<0x0018,0x1017> a00181017; (void)a00181017; gdcm::Attribute<0x0018,0x1018> a00181018; (void)a00181018; gdcm::Attribute<0x0018,0x1019> a00181019; (void)a00181019; gdcm::Attribute<0x0018,0x101a> a0018101a; (void)a0018101a; gdcm::Attribute<0x0018,0x101b> a0018101b; (void)a0018101b; gdcm::Attribute<0x0018,0x1020> a00181020; (void)a00181020; gdcm::Attribute<0x0018,0x1022> a00181022; (void)a00181022; gdcm::Attribute<0x0018,0x1023> a00181023; (void)a00181023; gdcm::Attribute<0x0018,0x1030> a00181030; (void)a00181030; gdcm::Attribute<0x0018,0x1040> a00181040; (void)a00181040; gdcm::Attribute<0x0018,0x1041> a00181041; (void)a00181041; gdcm::Attribute<0x0018,0x1042> a00181042; (void)a00181042; gdcm::Attribute<0x0018,0x1043> a00181043; (void)a00181043; gdcm::Attribute<0x0018,0x1044> a00181044; (void)a00181044; gdcm::Attribute<0x0018,0x1045> a00181045; (void)a00181045; gdcm::Attribute<0x0018,0x1046> a00181046; (void)a00181046; gdcm::Attribute<0x0018,0x1047> a00181047; (void)a00181047; gdcm::Attribute<0x0018,0x1048> a00181048; (void)a00181048; gdcm::Attribute<0x0018,0x1049> a00181049; (void)a00181049; gdcm::Attribute<0x0018,0x1050> a00181050; (void)a00181050; gdcm::Attribute<0x0018,0x1060> a00181060; (void)a00181060; gdcm::Attribute<0x0018,0x1061> a00181061; (void)a00181061; gdcm::Attribute<0x0018,0x1062> a00181062; (void)a00181062; gdcm::Attribute<0x0018,0x1063> a00181063; (void)a00181063; gdcm::Attribute<0x0018,0x1064> a00181064; (void)a00181064; gdcm::Attribute<0x0018,0x1065> a00181065; (void)a00181065; gdcm::Attribute<0x0018,0x1066> a00181066; (void)a00181066; gdcm::Attribute<0x0018,0x1067> a00181067; (void)a00181067; gdcm::Attribute<0x0018,0x1068> a00181068; (void)a00181068; gdcm::Attribute<0x0018,0x1069> a00181069; (void)a00181069; gdcm::Attribute<0x0018,0x106a> a0018106a; (void)a0018106a; gdcm::Attribute<0x0018,0x106c> a0018106c; (void)a0018106c; gdcm::Attribute<0x0018,0x106e> a0018106e; (void)a0018106e; gdcm::Attribute<0x0018,0x1070> a00181070; (void)a00181070; gdcm::Attribute<0x0018,0x1071> a00181071; (void)a00181071; gdcm::Attribute<0x0018,0x1072> a00181072; (void)a00181072; gdcm::Attribute<0x0018,0x1073> a00181073; (void)a00181073; gdcm::Attribute<0x0018,0x1074> a00181074; (void)a00181074; gdcm::Attribute<0x0018,0x1075> a00181075; (void)a00181075; gdcm::Attribute<0x0018,0x1076> a00181076; (void)a00181076; gdcm::Attribute<0x0018,0x1077> a00181077; (void)a00181077; gdcm::Attribute<0x0018,0x1078> a00181078; (void)a00181078; gdcm::Attribute<0x0018,0x1079> a00181079; (void)a00181079; gdcm::Attribute<0x0018,0x1080> a00181080; (void)a00181080; gdcm::Attribute<0x0018,0x1081> a00181081; (void)a00181081; gdcm::Attribute<0x0018,0x1082> a00181082; (void)a00181082; gdcm::Attribute<0x0018,0x1083> a00181083; (void)a00181083; gdcm::Attribute<0x0018,0x1084> a00181084; (void)a00181084; gdcm::Attribute<0x0018,0x1085> a00181085; (void)a00181085; gdcm::Attribute<0x0018,0x1086> a00181086; (void)a00181086; gdcm::Attribute<0x0018,0x1088> a00181088; (void)a00181088; gdcm::Attribute<0x0018,0x1090> a00181090; (void)a00181090; gdcm::Attribute<0x0018,0x1094> a00181094; (void)a00181094; gdcm::Attribute<0x0018,0x1100> a00181100; (void)a00181100; gdcm::Attribute<0x0018,0x1110> a00181110; (void)a00181110; gdcm::Attribute<0x0018,0x1111> a00181111; (void)a00181111; gdcm::Attribute<0x0018,0x1114> a00181114; (void)a00181114; gdcm::Attribute<0x0018,0x1120> a00181120; (void)a00181120; gdcm::Attribute<0x0018,0x1121> a00181121; (void)a00181121; gdcm::Attribute<0x0018,0x1130> a00181130; (void)a00181130; gdcm::Attribute<0x0018,0x1131> a00181131; (void)a00181131; gdcm::Attribute<0x0018,0x1134> a00181134; (void)a00181134; gdcm::Attribute<0x0018,0x1135> a00181135; (void)a00181135; gdcm::Attribute<0x0018,0x1136> a00181136; (void)a00181136; gdcm::Attribute<0x0018,0x1137> a00181137; (void)a00181137; gdcm::Attribute<0x0018,0x1138> a00181138; (void)a00181138; gdcm::Attribute<0x0018,0x113a> a0018113a; (void)a0018113a; gdcm::Attribute<0x0018,0x1140> a00181140; (void)a00181140; gdcm::Attribute<0x0018,0x1141> a00181141; (void)a00181141; gdcm::Attribute<0x0018,0x1142> a00181142; (void)a00181142; gdcm::Attribute<0x0018,0x1143> a00181143; (void)a00181143; gdcm::Attribute<0x0018,0x1144> a00181144; (void)a00181144; gdcm::Attribute<0x0018,0x1145> a00181145; (void)a00181145; gdcm::Attribute<0x0018,0x1146> a00181146; (void)a00181146; gdcm::Attribute<0x0018,0x1147> a00181147; (void)a00181147; gdcm::Attribute<0x0018,0x1150> a00181150; (void)a00181150; gdcm::Attribute<0x0018,0x1151> a00181151; (void)a00181151; gdcm::Attribute<0x0018,0x1152> a00181152; (void)a00181152; gdcm::Attribute<0x0018,0x1153> a00181153; (void)a00181153; gdcm::Attribute<0x0018,0x1154> a00181154; (void)a00181154; gdcm::Attribute<0x0018,0x1155> a00181155; (void)a00181155; gdcm::Attribute<0x0018,0x1156> a00181156; (void)a00181156; gdcm::Attribute<0x0018,0x115a> a0018115a; (void)a0018115a; gdcm::Attribute<0x0018,0x115e> a0018115e; (void)a0018115e; gdcm::Attribute<0x0018,0x1160> a00181160; (void)a00181160; gdcm::Attribute<0x0018,0x1161> a00181161; (void)a00181161; gdcm::Attribute<0x0018,0x1162> a00181162; (void)a00181162; gdcm::Attribute<0x0018,0x1164> a00181164; (void)a00181164; gdcm::Attribute<0x0018,0x1166> a00181166; (void)a00181166; gdcm::Attribute<0x0018,0x1170> a00181170; (void)a00181170; gdcm::Attribute<0x0018,0x1180> a00181180; (void)a00181180; gdcm::Attribute<0x0018,0x1181> a00181181; (void)a00181181; gdcm::Attribute<0x0018,0x1190> a00181190; (void)a00181190; gdcm::Attribute<0x0018,0x1191> a00181191; (void)a00181191; gdcm::Attribute<0x0018,0x11a0> a001811a0; (void)a001811a0; gdcm::Attribute<0x0018,0x11a2> a001811a2; (void)a001811a2; gdcm::Attribute<0x0018,0x1200> a00181200; (void)a00181200; gdcm::Attribute<0x0018,0x1201> a00181201; (void)a00181201; gdcm::Attribute<0x0018,0x1210> a00181210; (void)a00181210; gdcm::Attribute<0x0018,0x1240> a00181240; (void)a00181240; gdcm::Attribute<0x0018,0x1242> a00181242; (void)a00181242; gdcm::Attribute<0x0018,0x1243> a00181243; (void)a00181243; gdcm::Attribute<0x0018,0x1244> a00181244; (void)a00181244; gdcm::Attribute<0x0018,0x1250> a00181250; (void)a00181250; gdcm::Attribute<0x0018,0x1251> a00181251; (void)a00181251; gdcm::Attribute<0x0018,0x1260> a00181260; (void)a00181260; gdcm::Attribute<0x0018,0x1261> a00181261; (void)a00181261; gdcm::Attribute<0x0018,0x1300> a00181300; (void)a00181300; gdcm::Attribute<0x0018,0x1301> a00181301; (void)a00181301; gdcm::Attribute<0x0018,0x1302> a00181302; (void)a00181302; gdcm::Attribute<0x0018,0x1310> a00181310; (void)a00181310; gdcm::Attribute<0x0018,0x1312> a00181312; (void)a00181312; gdcm::Attribute<0x0018,0x1314> a00181314; (void)a00181314; gdcm::Attribute<0x0018,0x1315> a00181315; (void)a00181315; gdcm::Attribute<0x0018,0x1316> a00181316; (void)a00181316; gdcm::Attribute<0x0018,0x1318> a00181318; (void)a00181318; gdcm::Attribute<0x0018,0x1400> a00181400; (void)a00181400; gdcm::Attribute<0x0018,0x1401> a00181401; (void)a00181401; gdcm::Attribute<0x0018,0x1402> a00181402; (void)a00181402; gdcm::Attribute<0x0018,0x1403> a00181403; (void)a00181403; gdcm::Attribute<0x0018,0x1404> a00181404; (void)a00181404; gdcm::Attribute<0x0018,0x1405> a00181405; (void)a00181405; gdcm::Attribute<0x0018,0x1450> a00181450; (void)a00181450; gdcm::Attribute<0x0018,0x1460> a00181460; (void)a00181460; gdcm::Attribute<0x0018,0x1470> a00181470; (void)a00181470; gdcm::Attribute<0x0018,0x1480> a00181480; (void)a00181480; gdcm::Attribute<0x0018,0x1490> a00181490; (void)a00181490; gdcm::Attribute<0x0018,0x1491> a00181491; (void)a00181491; gdcm::Attribute<0x0018,0x1495> a00181495; (void)a00181495; gdcm::Attribute<0x0018,0x1500> a00181500; (void)a00181500; gdcm::Attribute<0x0018,0x1508> a00181508; (void)a00181508; gdcm::Attribute<0x0018,0x1510> a00181510; (void)a00181510; gdcm::Attribute<0x0018,0x1511> a00181511; (void)a00181511; gdcm::Attribute<0x0018,0x1520> a00181520; (void)a00181520; gdcm::Attribute<0x0018,0x1521> a00181521; (void)a00181521; gdcm::Attribute<0x0018,0x1530> a00181530; (void)a00181530; gdcm::Attribute<0x0018,0x1531> a00181531; (void)a00181531; gdcm::Attribute<0x0018,0x1602> a00181602; (void)a00181602; gdcm::Attribute<0x0018,0x1604> a00181604; (void)a00181604; gdcm::Attribute<0x0018,0x1606> a00181606; (void)a00181606; gdcm::Attribute<0x0018,0x1608> a00181608; (void)a00181608; gdcm::Attribute<0x0018,0x1610> a00181610; (void)a00181610; gdcm::Attribute<0x0018,0x1612> a00181612; (void)a00181612; gdcm::Attribute<0x0018,0x1620> a00181620; (void)a00181620; gdcm::Attribute<0x0018,0x1622> a00181622; (void)a00181622; gdcm::Attribute<0x0018,0x1623> a00181623; (void)a00181623; gdcm::Attribute<0x0018,0x1624> a00181624; (void)a00181624; gdcm::Attribute<0x0018,0x1702> a00181702; (void)a00181702; gdcm::Attribute<0x0018,0x1704> a00181704; (void)a00181704; gdcm::Attribute<0x0018,0x1706> a00181706; (void)a00181706; gdcm::Attribute<0x0018,0x1708> a00181708; (void)a00181708; gdcm::Attribute<0x0018,0x1710> a00181710; (void)a00181710; gdcm::Attribute<0x0018,0x1712> a00181712; (void)a00181712; gdcm::Attribute<0x0018,0x1720> a00181720; (void)a00181720; gdcm::Attribute<0x0018,0x1800> a00181800; (void)a00181800; gdcm::Attribute<0x0018,0x1801> a00181801; (void)a00181801; gdcm::Attribute<0x0018,0x1802> a00181802; (void)a00181802; gdcm::Attribute<0x0018,0x1803> a00181803; (void)a00181803; gdcm::Attribute<0x0018,0x2001> a00182001; (void)a00182001; gdcm::Attribute<0x0018,0x2002> a00182002; (void)a00182002; gdcm::Attribute<0x0018,0x2003> a00182003; (void)a00182003; gdcm::Attribute<0x0018,0x2004> a00182004; (void)a00182004; gdcm::Attribute<0x0018,0x2005> a00182005; (void)a00182005; gdcm::Attribute<0x0018,0x2006> a00182006; (void)a00182006; gdcm::Attribute<0x0018,0x2010> a00182010; (void)a00182010; gdcm::Attribute<0x0018,0x2020> a00182020; (void)a00182020; gdcm::Attribute<0x0018,0x2030> a00182030; (void)a00182030; gdcm::Attribute<0x0018,0x3100> a00183100; (void)a00183100; gdcm::Attribute<0x0018,0x3101> a00183101; (void)a00183101; gdcm::Attribute<0x0018,0x3102> a00183102; (void)a00183102; gdcm::Attribute<0x0018,0x3103> a00183103; (void)a00183103; gdcm::Attribute<0x0018,0x3104> a00183104; (void)a00183104; gdcm::Attribute<0x0018,0x3105> a00183105; (void)a00183105; gdcm::Attribute<0x0018,0x4000> a00184000; (void)a00184000; gdcm::Attribute<0x0018,0x5000> a00185000; (void)a00185000; gdcm::Attribute<0x0018,0x5010> a00185010; (void)a00185010; gdcm::Attribute<0x0018,0x5012> a00185012; (void)a00185012; gdcm::Attribute<0x0018,0x5020> a00185020; (void)a00185020; gdcm::Attribute<0x0018,0x5021> a00185021; (void)a00185021; gdcm::Attribute<0x0018,0x5022> a00185022; (void)a00185022; gdcm::Attribute<0x0018,0x5024> a00185024; (void)a00185024; gdcm::Attribute<0x0018,0x5026> a00185026; (void)a00185026; gdcm::Attribute<0x0018,0x5027> a00185027; (void)a00185027; gdcm::Attribute<0x0018,0x5028> a00185028; (void)a00185028; gdcm::Attribute<0x0018,0x5029> a00185029; (void)a00185029; gdcm::Attribute<0x0018,0x5030> a00185030; (void)a00185030; gdcm::Attribute<0x0018,0x5040> a00185040; (void)a00185040; gdcm::Attribute<0x0018,0x5050> a00185050; (void)a00185050; gdcm::Attribute<0x0018,0x5100> a00185100; (void)a00185100; gdcm::Attribute<0x0018,0x5101> a00185101; (void)a00185101; gdcm::Attribute<0x0018,0x5104> a00185104; (void)a00185104; gdcm::Attribute<0x0018,0x5210> a00185210; (void)a00185210; gdcm::Attribute<0x0018,0x5212> a00185212; (void)a00185212; gdcm::Attribute<0x0018,0x6000> a00186000; (void)a00186000; gdcm::Attribute<0x0018,0x6011> a00186011; (void)a00186011; gdcm::Attribute<0x0018,0x6012> a00186012; (void)a00186012; gdcm::Attribute<0x0018,0x6014> a00186014; (void)a00186014; gdcm::Attribute<0x0018,0x6016> a00186016; (void)a00186016; gdcm::Attribute<0x0018,0x6018> a00186018; (void)a00186018; gdcm::Attribute<0x0018,0x601a> a0018601a; (void)a0018601a; gdcm::Attribute<0x0018,0x601c> a0018601c; (void)a0018601c; gdcm::Attribute<0x0018,0x601e> a0018601e; (void)a0018601e; gdcm::Attribute<0x0018,0x6020> a00186020; (void)a00186020; gdcm::Attribute<0x0018,0x6022> a00186022; (void)a00186022; gdcm::Attribute<0x0018,0x6024> a00186024; (void)a00186024; gdcm::Attribute<0x0018,0x6026> a00186026; (void)a00186026; gdcm::Attribute<0x0018,0x6028> a00186028; (void)a00186028; gdcm::Attribute<0x0018,0x602a> a0018602a; (void)a0018602a; gdcm::Attribute<0x0018,0x602c> a0018602c; (void)a0018602c; gdcm::Attribute<0x0018,0x602e> a0018602e; (void)a0018602e; gdcm::Attribute<0x0018,0x6030> a00186030; (void)a00186030; gdcm::Attribute<0x0018,0x6031> a00186031; (void)a00186031; gdcm::Attribute<0x0018,0x6032> a00186032; (void)a00186032; gdcm::Attribute<0x0018,0x6034> a00186034; (void)a00186034; gdcm::Attribute<0x0018,0x6036> a00186036; (void)a00186036; gdcm::Attribute<0x0018,0x6038> a00186038; (void)a00186038; gdcm::Attribute<0x0018,0x6039> a00186039; (void)a00186039; gdcm::Attribute<0x0018,0x603a> a0018603a; (void)a0018603a; gdcm::Attribute<0x0018,0x603b> a0018603b; (void)a0018603b; gdcm::Attribute<0x0018,0x603c> a0018603c; (void)a0018603c; gdcm::Attribute<0x0018,0x603d> a0018603d; (void)a0018603d; gdcm::Attribute<0x0018,0x603e> a0018603e; (void)a0018603e; gdcm::Attribute<0x0018,0x603f> a0018603f; (void)a0018603f; gdcm::Attribute<0x0018,0x6040> a00186040; (void)a00186040; gdcm::Attribute<0x0018,0x6041> a00186041; (void)a00186041; gdcm::Attribute<0x0018,0x6042> a00186042; (void)a00186042; gdcm::Attribute<0x0018,0x6043> a00186043; (void)a00186043; gdcm::Attribute<0x0018,0x6044> a00186044; (void)a00186044; gdcm::Attribute<0x0018,0x6046> a00186046; (void)a00186046; gdcm::Attribute<0x0018,0x6048> a00186048; (void)a00186048; gdcm::Attribute<0x0018,0x604a> a0018604a; (void)a0018604a; gdcm::Attribute<0x0018,0x604c> a0018604c; (void)a0018604c; gdcm::Attribute<0x0018,0x604e> a0018604e; (void)a0018604e; gdcm::Attribute<0x0018,0x6050> a00186050; (void)a00186050; gdcm::Attribute<0x0018,0x6052> a00186052; (void)a00186052; gdcm::Attribute<0x0018,0x6054> a00186054; (void)a00186054; gdcm::Attribute<0x0018,0x6056> a00186056; (void)a00186056; gdcm::Attribute<0x0018,0x6058> a00186058; (void)a00186058; gdcm::Attribute<0x0018,0x605a> a0018605a; (void)a0018605a; gdcm::Attribute<0x0018,0x6060> a00186060; (void)a00186060; gdcm::Attribute<0x0018,0x7000> a00187000; (void)a00187000; gdcm::Attribute<0x0018,0x7001> a00187001; (void)a00187001; gdcm::Attribute<0x0018,0x7004> a00187004; (void)a00187004; gdcm::Attribute<0x0018,0x7005> a00187005; (void)a00187005; gdcm::Attribute<0x0018,0x7006> a00187006; (void)a00187006; gdcm::Attribute<0x0018,0x7008> a00187008; (void)a00187008; gdcm::Attribute<0x0018,0x700a> a0018700a; (void)a0018700a; gdcm::Attribute<0x0018,0x700c> a0018700c; (void)a0018700c; gdcm::Attribute<0x0018,0x700e> a0018700e; (void)a0018700e; gdcm::Attribute<0x0018,0x7010> a00187010; (void)a00187010; gdcm::Attribute<0x0018,0x7011> a00187011; (void)a00187011; gdcm::Attribute<0x0018,0x7012> a00187012; (void)a00187012; gdcm::Attribute<0x0018,0x7014> a00187014; (void)a00187014; gdcm::Attribute<0x0018,0x7016> a00187016; (void)a00187016; gdcm::Attribute<0x0018,0x701a> a0018701a; (void)a0018701a; gdcm::Attribute<0x0018,0x7020> a00187020; (void)a00187020; gdcm::Attribute<0x0018,0x7022> a00187022; (void)a00187022; gdcm::Attribute<0x0018,0x7024> a00187024; (void)a00187024; gdcm::Attribute<0x0018,0x7028> a00187028; (void)a00187028; gdcm::Attribute<0x0018,0x702a> a0018702a; (void)a0018702a; gdcm::Attribute<0x0018,0x702b> a0018702b; (void)a0018702b; gdcm::Attribute<0x0018,0x7030> a00187030; (void)a00187030; gdcm::Attribute<0x0018,0x7032> a00187032; (void)a00187032; gdcm::Attribute<0x0018,0x7034> a00187034; (void)a00187034; gdcm::Attribute<0x0018,0x7040> a00187040; (void)a00187040; gdcm::Attribute<0x0018,0x7041> a00187041; (void)a00187041; gdcm::Attribute<0x0018,0x7042> a00187042; (void)a00187042; gdcm::Attribute<0x0018,0x7044> a00187044; (void)a00187044; gdcm::Attribute<0x0018,0x7046> a00187046; (void)a00187046; gdcm::Attribute<0x0018,0x7048> a00187048; (void)a00187048; gdcm::Attribute<0x0018,0x704c> a0018704c; (void)a0018704c; gdcm::Attribute<0x0018,0x7050> a00187050; (void)a00187050; gdcm::Attribute<0x0018,0x7052> a00187052; (void)a00187052; gdcm::Attribute<0x0018,0x7054> a00187054; (void)a00187054; gdcm::Attribute<0x0018,0x7060> a00187060; (void)a00187060; gdcm::Attribute<0x0018,0x7062> a00187062; (void)a00187062; gdcm::Attribute<0x0018,0x7064> a00187064; (void)a00187064; gdcm::Attribute<0x0018,0x7065> a00187065; (void)a00187065; gdcm::Attribute<0x0018,0x8150> a00188150; (void)a00188150; gdcm::Attribute<0x0018,0x8151> a00188151; (void)a00188151; gdcm::Attribute<0x0018,0x9004> a00189004; (void)a00189004; gdcm::Attribute<0x0018,0x9005> a00189005; (void)a00189005; gdcm::Attribute<0x0018,0x9006> a00189006; (void)a00189006; gdcm::Attribute<0x0018,0x9008> a00189008; (void)a00189008; gdcm::Attribute<0x0018,0x9009> a00189009; (void)a00189009; gdcm::Attribute<0x0018,0x9010> a00189010; (void)a00189010; gdcm::Attribute<0x0018,0x9011> a00189011; (void)a00189011; gdcm::Attribute<0x0018,0x9012> a00189012; (void)a00189012; gdcm::Attribute<0x0018,0x9014> a00189014; (void)a00189014; gdcm::Attribute<0x0018,0x9015> a00189015; (void)a00189015; gdcm::Attribute<0x0018,0x9016> a00189016; (void)a00189016; gdcm::Attribute<0x0018,0x9017> a00189017; (void)a00189017; gdcm::Attribute<0x0018,0x9018> a00189018; (void)a00189018; gdcm::Attribute<0x0018,0x9019> a00189019; (void)a00189019; gdcm::Attribute<0x0018,0x9020> a00189020; (void)a00189020; gdcm::Attribute<0x0018,0x9021> a00189021; (void)a00189021; gdcm::Attribute<0x0018,0x9022> a00189022; (void)a00189022; gdcm::Attribute<0x0018,0x9024> a00189024; (void)a00189024; gdcm::Attribute<0x0018,0x9025> a00189025; (void)a00189025; gdcm::Attribute<0x0018,0x9026> a00189026; (void)a00189026; gdcm::Attribute<0x0018,0x9027> a00189027; (void)a00189027; gdcm::Attribute<0x0018,0x9028> a00189028; (void)a00189028; gdcm::Attribute<0x0018,0x9029> a00189029; (void)a00189029; gdcm::Attribute<0x0018,0x9030> a00189030; (void)a00189030; gdcm::Attribute<0x0018,0x9032> a00189032; (void)a00189032; gdcm::Attribute<0x0018,0x9033> a00189033; (void)a00189033; gdcm::Attribute<0x0018,0x9034> a00189034; (void)a00189034; gdcm::Attribute<0x0018,0x9035> a00189035; (void)a00189035; gdcm::Attribute<0x0018,0x9036> a00189036; (void)a00189036; gdcm::Attribute<0x0018,0x9037> a00189037; (void)a00189037; gdcm::Attribute<0x0018,0x9041> a00189041; (void)a00189041; gdcm::Attribute<0x0018,0x9042> a00189042; (void)a00189042; gdcm::Attribute<0x0018,0x9043> a00189043; (void)a00189043; gdcm::Attribute<0x0018,0x9044> a00189044; (void)a00189044; gdcm::Attribute<0x0018,0x9045> a00189045; (void)a00189045; gdcm::Attribute<0x0018,0x9046> a00189046; (void)a00189046; gdcm::Attribute<0x0018,0x9047> a00189047; (void)a00189047; gdcm::Attribute<0x0018,0x9048> a00189048; (void)a00189048; gdcm::Attribute<0x0018,0x9049> a00189049; (void)a00189049; gdcm::Attribute<0x0018,0x9050> a00189050; (void)a00189050; gdcm::Attribute<0x0018,0x9051> a00189051; (void)a00189051; gdcm::Attribute<0x0018,0x9054> a00189054; (void)a00189054; gdcm::Attribute<0x0018,0x9058> a00189058; (void)a00189058; gdcm::Attribute<0x0018,0x9059> a00189059; (void)a00189059; gdcm::Attribute<0x0018,0x9062> a00189062; (void)a00189062; gdcm::Attribute<0x0018,0x9064> a00189064; (void)a00189064; gdcm::Attribute<0x0018,0x9067> a00189067; (void)a00189067; gdcm::Attribute<0x0018,0x9069> a00189069; (void)a00189069; gdcm::Attribute<0x0018,0x9070> a00189070; (void)a00189070; gdcm::Attribute<0x0018,0x9073> a00189073; (void)a00189073; gdcm::Attribute<0x0018,0x9074> a00189074; (void)a00189074; gdcm::Attribute<0x0018,0x9075> a00189075; (void)a00189075; gdcm::Attribute<0x0018,0x9076> a00189076; (void)a00189076; gdcm::Attribute<0x0018,0x9077> a00189077; (void)a00189077; gdcm::Attribute<0x0018,0x9078> a00189078; (void)a00189078; gdcm::Attribute<0x0018,0x9079> a00189079; (void)a00189079; gdcm::Attribute<0x0018,0x9080> a00189080; (void)a00189080; gdcm::Attribute<0x0018,0x9081> a00189081; (void)a00189081; gdcm::Attribute<0x0018,0x9082> a00189082; (void)a00189082; gdcm::Attribute<0x0018,0x9083> a00189083; (void)a00189083; gdcm::Attribute<0x0018,0x9084> a00189084; (void)a00189084; gdcm::Attribute<0x0018,0x9085> a00189085; (void)a00189085; gdcm::Attribute<0x0018,0x9087> a00189087; (void)a00189087; gdcm::Attribute<0x0018,0x9089> a00189089; (void)a00189089; gdcm::Attribute<0x0018,0x9090> a00189090; (void)a00189090; gdcm::Attribute<0x0018,0x9091> a00189091; (void)a00189091; gdcm::Attribute<0x0018,0x9093> a00189093; (void)a00189093; gdcm::Attribute<0x0018,0x9094> a00189094; (void)a00189094; gdcm::Attribute<0x0018,0x9095> a00189095; (void)a00189095; gdcm::Attribute<0x0018,0x9096> a00189096; (void)a00189096; gdcm::Attribute<0x0018,0x9101> a00189101; (void)a00189101; gdcm::Attribute<0x0018,0x9103> a00189103; (void)a00189103; gdcm::Attribute<0x0018,0x9104> a00189104; (void)a00189104; gdcm::Attribute<0x0018,0x9105> a00189105; (void)a00189105; gdcm::Attribute<0x0018,0x9106> a00189106; (void)a00189106; gdcm::Attribute<0x0018,0x9107> a00189107; (void)a00189107; gdcm::Attribute<0x0018,0x9112> a00189112; (void)a00189112; gdcm::Attribute<0x0018,0x9114> a00189114; (void)a00189114; gdcm::Attribute<0x0018,0x9115> a00189115; (void)a00189115; gdcm::Attribute<0x0018,0x9117> a00189117; (void)a00189117; gdcm::Attribute<0x0018,0x9118> a00189118; (void)a00189118; gdcm::Attribute<0x0018,0x9119> a00189119; (void)a00189119; gdcm::Attribute<0x0018,0x9125> a00189125; (void)a00189125; gdcm::Attribute<0x0018,0x9126> a00189126; (void)a00189126; gdcm::Attribute<0x0018,0x9127> a00189127; (void)a00189127; gdcm::Attribute<0x0018,0x9147> a00189147; (void)a00189147; gdcm::Attribute<0x0018,0x9151> a00189151; (void)a00189151; gdcm::Attribute<0x0018,0x9152> a00189152; (void)a00189152; gdcm::Attribute<0x0018,0x9155> a00189155; (void)a00189155; gdcm::Attribute<0x0018,0x9159> a00189159; (void)a00189159; gdcm::Attribute<0x0018,0x9166> a00189166; (void)a00189166; gdcm::Attribute<0x0018,0x9168> a00189168; (void)a00189168; gdcm::Attribute<0x0018,0x9169> a00189169; (void)a00189169; gdcm::Attribute<0x0018,0x9170> a00189170; (void)a00189170; gdcm::Attribute<0x0018,0x9171> a00189171; (void)a00189171; gdcm::Attribute<0x0018,0x9172> a00189172; (void)a00189172; gdcm::Attribute<0x0018,0x9173> a00189173; (void)a00189173; gdcm::Attribute<0x0018,0x9174> a00189174; (void)a00189174; gdcm::Attribute<0x0018,0x9175> a00189175; (void)a00189175; gdcm::Attribute<0x0018,0x9176> a00189176; (void)a00189176; gdcm::Attribute<0x0018,0x9177> a00189177; (void)a00189177; gdcm::Attribute<0x0018,0x9178> a00189178; (void)a00189178; gdcm::Attribute<0x0018,0x9179> a00189179; (void)a00189179; gdcm::Attribute<0x0018,0x9180> a00189180; (void)a00189180; gdcm::Attribute<0x0018,0x9181> a00189181; (void)a00189181; gdcm::Attribute<0x0018,0x9182> a00189182; (void)a00189182; gdcm::Attribute<0x0018,0x9183> a00189183; (void)a00189183; gdcm::Attribute<0x0018,0x9184> a00189184; (void)a00189184; gdcm::Attribute<0x0018,0x9185> a00189185; (void)a00189185; gdcm::Attribute<0x0018,0x9186> a00189186; (void)a00189186; gdcm::Attribute<0x0018,0x9195> a00189195; (void)a00189195; gdcm::Attribute<0x0018,0x9196> a00189196; (void)a00189196; gdcm::Attribute<0x0018,0x9197> a00189197; (void)a00189197; gdcm::Attribute<0x0018,0x9198> a00189198; (void)a00189198; gdcm::Attribute<0x0018,0x9199> a00189199; (void)a00189199; gdcm::Attribute<0x0018,0x9200> a00189200; (void)a00189200; gdcm::Attribute<0x0018,0x9214> a00189214; (void)a00189214; gdcm::Attribute<0x0018,0x9217> a00189217; (void)a00189217; gdcm::Attribute<0x0018,0x9218> a00189218; (void)a00189218; gdcm::Attribute<0x0018,0x9219> a00189219; (void)a00189219; gdcm::Attribute<0x0018,0x9220> a00189220; (void)a00189220; gdcm::Attribute<0x0018,0x9226> a00189226; (void)a00189226; gdcm::Attribute<0x0018,0x9227> a00189227; (void)a00189227; gdcm::Attribute<0x0018,0x9231> a00189231; (void)a00189231; gdcm::Attribute<0x0018,0x9232> a00189232; (void)a00189232; gdcm::Attribute<0x0018,0x9234> a00189234; (void)a00189234; gdcm::Attribute<0x0018,0x9236> a00189236; (void)a00189236; gdcm::Attribute<0x0018,0x9239> a00189239; (void)a00189239; gdcm::Attribute<0x0018,0x9240> a00189240; (void)a00189240; gdcm::Attribute<0x0018,0x9241> a00189241; (void)a00189241; gdcm::Attribute<0x0018,0x9295> a00189295; (void)a00189295; gdcm::Attribute<0x0018,0x9296> a00189296; (void)a00189296; gdcm::Attribute<0x0018,0x9301> a00189301; (void)a00189301; gdcm::Attribute<0x0018,0x9302> a00189302; (void)a00189302; gdcm::Attribute<0x0018,0x9303> a00189303; (void)a00189303; gdcm::Attribute<0x0018,0x9304> a00189304; (void)a00189304; gdcm::Attribute<0x0018,0x9305> a00189305; (void)a00189305; gdcm::Attribute<0x0018,0x9306> a00189306; (void)a00189306; gdcm::Attribute<0x0018,0x9307> a00189307; (void)a00189307; gdcm::Attribute<0x0018,0x9308> a00189308; (void)a00189308; gdcm::Attribute<0x0018,0x9309> a00189309; (void)a00189309; gdcm::Attribute<0x0018,0x9310> a00189310; (void)a00189310; gdcm::Attribute<0x0018,0x9311> a00189311; (void)a00189311; gdcm::Attribute<0x0018,0x9312> a00189312; (void)a00189312; gdcm::Attribute<0x0018,0x9313> a00189313; (void)a00189313; gdcm::Attribute<0x0018,0x9314> a00189314; (void)a00189314; gdcm::Attribute<0x0018,0x9315> a00189315; (void)a00189315; gdcm::Attribute<0x0018,0x9316> a00189316; (void)a00189316; gdcm::Attribute<0x0018,0x9317> a00189317; (void)a00189317; gdcm::Attribute<0x0018,0x9318> a00189318; (void)a00189318; gdcm::Attribute<0x0018,0x9319> a00189319; (void)a00189319; gdcm::Attribute<0x0018,0x9320> a00189320; (void)a00189320; gdcm::Attribute<0x0018,0x9321> a00189321; (void)a00189321; gdcm::Attribute<0x0018,0x9322> a00189322; (void)a00189322; gdcm::Attribute<0x0018,0x9323> a00189323; (void)a00189323; gdcm::Attribute<0x0018,0x9324> a00189324; (void)a00189324; gdcm::Attribute<0x0018,0x9325> a00189325; (void)a00189325; gdcm::Attribute<0x0018,0x9326> a00189326; (void)a00189326; gdcm::Attribute<0x0018,0x9327> a00189327; (void)a00189327; gdcm::Attribute<0x0018,0x9328> a00189328; (void)a00189328; gdcm::Attribute<0x0018,0x9329> a00189329; (void)a00189329; gdcm::Attribute<0x0018,0x9330> a00189330; (void)a00189330; gdcm::Attribute<0x0018,0x9332> a00189332; (void)a00189332; gdcm::Attribute<0x0018,0x9333> a00189333; (void)a00189333; gdcm::Attribute<0x0018,0x9334> a00189334; (void)a00189334; gdcm::Attribute<0x0018,0x9335> a00189335; (void)a00189335; gdcm::Attribute<0x0018,0x9337> a00189337; (void)a00189337; gdcm::Attribute<0x0018,0x9338> a00189338; (void)a00189338; gdcm::Attribute<0x0018,0x9340> a00189340; (void)a00189340; gdcm::Attribute<0x0018,0x9341> a00189341; (void)a00189341; gdcm::Attribute<0x0018,0x9342> a00189342; (void)a00189342; gdcm::Attribute<0x0018,0x9343> a00189343; (void)a00189343; gdcm::Attribute<0x0018,0x9344> a00189344; (void)a00189344; gdcm::Attribute<0x0018,0x9345> a00189345; (void)a00189345; gdcm::Attribute<0x0018,0x9346> a00189346; (void)a00189346; gdcm::Attribute<0x0018,0x9351> a00189351; (void)a00189351; gdcm::Attribute<0x0018,0x9352> a00189352; (void)a00189352; gdcm::Attribute<0x0018,0x9360> a00189360; (void)a00189360; gdcm::Attribute<0x0018,0x9401> a00189401; (void)a00189401; gdcm::Attribute<0x0018,0x9402> a00189402; (void)a00189402; gdcm::Attribute<0x0018,0x9403> a00189403; (void)a00189403; gdcm::Attribute<0x0018,0x9404> a00189404; (void)a00189404; gdcm::Attribute<0x0018,0x9405> a00189405; (void)a00189405; gdcm::Attribute<0x0018,0x9406> a00189406; (void)a00189406; gdcm::Attribute<0x0018,0x9407> a00189407; (void)a00189407; gdcm::Attribute<0x0018,0x9412> a00189412; (void)a00189412; gdcm::Attribute<0x0018,0x9417> a00189417; (void)a00189417; gdcm::Attribute<0x0018,0x9420> a00189420; (void)a00189420; gdcm::Attribute<0x0018,0x9423> a00189423; (void)a00189423; gdcm::Attribute<0x0018,0x9424> a00189424; (void)a00189424; gdcm::Attribute<0x0018,0x9425> a00189425; (void)a00189425; gdcm::Attribute<0x0018,0x9426> a00189426; (void)a00189426; gdcm::Attribute<0x0018,0x9427> a00189427; (void)a00189427; gdcm::Attribute<0x0018,0x9429> a00189429; (void)a00189429; gdcm::Attribute<0x0018,0x9430> a00189430; (void)a00189430; gdcm::Attribute<0x0018,0x9432> a00189432; (void)a00189432; gdcm::Attribute<0x0018,0x9433> a00189433; (void)a00189433; gdcm::Attribute<0x0018,0x9434> a00189434; (void)a00189434; gdcm::Attribute<0x0018,0x9435> a00189435; (void)a00189435; gdcm::Attribute<0x0018,0x9436> a00189436; (void)a00189436; gdcm::Attribute<0x0018,0x9437> a00189437; (void)a00189437; gdcm::Attribute<0x0018,0x9438> a00189438; (void)a00189438; gdcm::Attribute<0x0018,0x9439> a00189439; (void)a00189439; gdcm::Attribute<0x0018,0x9440> a00189440; (void)a00189440; gdcm::Attribute<0x0018,0x9441> a00189441; (void)a00189441; gdcm::Attribute<0x0018,0x9442> a00189442; (void)a00189442; gdcm::Attribute<0x0018,0x9447> a00189447; (void)a00189447; gdcm::Attribute<0x0018,0x9449> a00189449; (void)a00189449; gdcm::Attribute<0x0018,0x9451> a00189451; (void)a00189451; gdcm::Attribute<0x0018,0x9452> a00189452; (void)a00189452; gdcm::Attribute<0x0018,0x9455> a00189455; (void)a00189455; gdcm::Attribute<0x0018,0x9456> a00189456; (void)a00189456; gdcm::Attribute<0x0018,0x9457> a00189457; (void)a00189457; gdcm::Attribute<0x0018,0x9462> a00189462; (void)a00189462; gdcm::Attribute<0x0018,0x9463> a00189463; (void)a00189463; gdcm::Attribute<0x0018,0x9464> a00189464; (void)a00189464; gdcm::Attribute<0x0018,0x9465> a00189465; (void)a00189465; gdcm::Attribute<0x0018,0x9466> a00189466; (void)a00189466; gdcm::Attribute<0x0018,0x9467> a00189467; (void)a00189467; gdcm::Attribute<0x0018,0x9468> a00189468; (void)a00189468; gdcm::Attribute<0x0018,0x9469> a00189469; (void)a00189469; gdcm::Attribute<0x0018,0x9470> a00189470; (void)a00189470; gdcm::Attribute<0x0018,0x9471> a00189471; (void)a00189471; gdcm::Attribute<0x0018,0x9472> a00189472; (void)a00189472; gdcm::Attribute<0x0018,0x9473> a00189473; (void)a00189473; gdcm::Attribute<0x0018,0x9474> a00189474; (void)a00189474; gdcm::Attribute<0x0018,0x9476> a00189476; (void)a00189476; gdcm::Attribute<0x0018,0x9477> a00189477; (void)a00189477; gdcm::Attribute<0x0018,0x9504> a00189504; (void)a00189504; gdcm::Attribute<0x0018,0x9506> a00189506; (void)a00189506; gdcm::Attribute<0x0018,0x9507> a00189507; (void)a00189507; gdcm::Attribute<0x0018,0x9508> a00189508; (void)a00189508; gdcm::Attribute<0x0018,0x9509> a00189509; (void)a00189509; gdcm::Attribute<0x0018,0x9510> a00189510; (void)a00189510; gdcm::Attribute<0x0018,0x9511> a00189511; (void)a00189511; gdcm::Attribute<0x0018,0x9514> a00189514; (void)a00189514; gdcm::Attribute<0x0018,0x9515> a00189515; (void)a00189515; gdcm::Attribute<0x0018,0x9516> a00189516; (void)a00189516; gdcm::Attribute<0x0018,0x9517> a00189517; (void)a00189517; gdcm::Attribute<0x0018,0x9524> a00189524; (void)a00189524; gdcm::Attribute<0x0018,0x9525> a00189525; (void)a00189525; gdcm::Attribute<0x0018,0x9526> a00189526; (void)a00189526; gdcm::Attribute<0x0018,0x9527> a00189527; (void)a00189527; gdcm::Attribute<0x0018,0x9528> a00189528; (void)a00189528; gdcm::Attribute<0x0018,0x9530> a00189530; (void)a00189530; gdcm::Attribute<0x0018,0x9531> a00189531; (void)a00189531; gdcm::Attribute<0x0018,0x9538> a00189538; (void)a00189538; gdcm::Attribute<0x0018,0x9601> a00189601; (void)a00189601; gdcm::Attribute<0x0018,0x9602> a00189602; (void)a00189602; gdcm::Attribute<0x0018,0x9603> a00189603; (void)a00189603; gdcm::Attribute<0x0018,0x9604> a00189604; (void)a00189604; gdcm::Attribute<0x0018,0x9605> a00189605; (void)a00189605; gdcm::Attribute<0x0018,0x9606> a00189606; (void)a00189606; gdcm::Attribute<0x0018,0x9607> a00189607; (void)a00189607; gdcm::Attribute<0x0018,0xa001> a0018a001; (void)a0018a001; gdcm::Attribute<0x0018,0xa002> a0018a002; (void)a0018a002; gdcm::Attribute<0x0018,0xa003> a0018a003; (void)a0018a003; gdcm::Attribute<0x0020,0x000d> a0020000d; (void)a0020000d; gdcm::Attribute<0x0020,0x000e> a0020000e; (void)a0020000e; gdcm::Attribute<0x0020,0x0010> a00200010; (void)a00200010; gdcm::Attribute<0x0020,0x0011> a00200011; (void)a00200011; gdcm::Attribute<0x0020,0x0012> a00200012; (void)a00200012; gdcm::Attribute<0x0020,0x0013> a00200013; (void)a00200013; gdcm::Attribute<0x0020,0x0014> a00200014; (void)a00200014; gdcm::Attribute<0x0020,0x0015> a00200015; (void)a00200015; gdcm::Attribute<0x0020,0x0016> a00200016; (void)a00200016; gdcm::Attribute<0x0020,0x0017> a00200017; (void)a00200017; gdcm::Attribute<0x0020,0x0018> a00200018; (void)a00200018; gdcm::Attribute<0x0020,0x0019> a00200019; (void)a00200019; gdcm::Attribute<0x0020,0x0020> a00200020; (void)a00200020; gdcm::Attribute<0x0020,0x0022> a00200022; (void)a00200022; gdcm::Attribute<0x0020,0x0024> a00200024; (void)a00200024; gdcm::Attribute<0x0020,0x0026> a00200026; (void)a00200026; gdcm::Attribute<0x0020,0x0030> a00200030; (void)a00200030; gdcm::Attribute<0x0020,0x0032> a00200032; (void)a00200032; gdcm::Attribute<0x0020,0x0035> a00200035; (void)a00200035; gdcm::Attribute<0x0020,0x0037> a00200037; (void)a00200037; gdcm::Attribute<0x0020,0x0050> a00200050; (void)a00200050; gdcm::Attribute<0x0020,0x0052> a00200052; (void)a00200052; gdcm::Attribute<0x0020,0x0060> a00200060; (void)a00200060; gdcm::Attribute<0x0020,0x0062> a00200062; (void)a00200062; gdcm::Attribute<0x0020,0x0070> a00200070; (void)a00200070; gdcm::Attribute<0x0020,0x0080> a00200080; (void)a00200080; gdcm::Attribute<0x0020,0x0100> a00200100; (void)a00200100; gdcm::Attribute<0x0020,0x0105> a00200105; (void)a00200105; gdcm::Attribute<0x0020,0x0110> a00200110; (void)a00200110; gdcm::Attribute<0x0020,0x0200> a00200200; (void)a00200200; gdcm::Attribute<0x0020,0x1000> a00201000; (void)a00201000; gdcm::Attribute<0x0020,0x1001> a00201001; (void)a00201001; gdcm::Attribute<0x0020,0x1002> a00201002; (void)a00201002; gdcm::Attribute<0x0020,0x1003> a00201003; (void)a00201003; gdcm::Attribute<0x0020,0x1004> a00201004; (void)a00201004; gdcm::Attribute<0x0020,0x1005> a00201005; (void)a00201005; gdcm::Attribute<0x0020,0x1020> a00201020; (void)a00201020; gdcm::Attribute<0x0020,0x1040> a00201040; (void)a00201040; gdcm::Attribute<0x0020,0x1041> a00201041; (void)a00201041; gdcm::Attribute<0x0020,0x1070> a00201070; (void)a00201070; gdcm::Attribute<0x0020,0x1200> a00201200; (void)a00201200; gdcm::Attribute<0x0020,0x1202> a00201202; (void)a00201202; gdcm::Attribute<0x0020,0x1204> a00201204; (void)a00201204; gdcm::Attribute<0x0020,0x1206> a00201206; (void)a00201206; gdcm::Attribute<0x0020,0x1208> a00201208; (void)a00201208; gdcm::Attribute<0x0020,0x1209> a00201209; (void)a00201209; gdcm::Attribute<0x0020,0x3401> a00203401; (void)a00203401; gdcm::Attribute<0x0020,0x3402> a00203402; (void)a00203402; gdcm::Attribute<0x0020,0x3403> a00203403; (void)a00203403; gdcm::Attribute<0x0020,0x3404> a00203404; (void)a00203404; gdcm::Attribute<0x0020,0x3405> a00203405; (void)a00203405; gdcm::Attribute<0x0020,0x3406> a00203406; (void)a00203406; gdcm::Attribute<0x0020,0x4000> a00204000; (void)a00204000; gdcm::Attribute<0x0020,0x5000> a00205000; (void)a00205000; gdcm::Attribute<0x0020,0x5002> a00205002; (void)a00205002; gdcm::Attribute<0x0020,0x9056> a00209056; (void)a00209056; gdcm::Attribute<0x0020,0x9057> a00209057; (void)a00209057; gdcm::Attribute<0x0020,0x9071> a00209071; (void)a00209071; gdcm::Attribute<0x0020,0x9072> a00209072; (void)a00209072; gdcm::Attribute<0x0020,0x9111> a00209111; (void)a00209111; gdcm::Attribute<0x0020,0x9113> a00209113; (void)a00209113; gdcm::Attribute<0x0020,0x9116> a00209116; (void)a00209116; gdcm::Attribute<0x0020,0x9128> a00209128; (void)a00209128; gdcm::Attribute<0x0020,0x9153> a00209153; (void)a00209153; gdcm::Attribute<0x0020,0x9156> a00209156; (void)a00209156; gdcm::Attribute<0x0020,0x9157> a00209157; (void)a00209157; gdcm::Attribute<0x0020,0x9158> a00209158; (void)a00209158; gdcm::Attribute<0x0020,0x9161> a00209161; (void)a00209161; gdcm::Attribute<0x0020,0x9162> a00209162; (void)a00209162; gdcm::Attribute<0x0020,0x9163> a00209163; (void)a00209163; gdcm::Attribute<0x0020,0x9164> a00209164; (void)a00209164; gdcm::Attribute<0x0020,0x9165> a00209165; (void)a00209165; gdcm::Attribute<0x0020,0x9167> a00209167; (void)a00209167; gdcm::Attribute<0x0020,0x9213> a00209213; (void)a00209213; gdcm::Attribute<0x0020,0x9221> a00209221; (void)a00209221; gdcm::Attribute<0x0020,0x9222> a00209222; (void)a00209222; gdcm::Attribute<0x0020,0x9228> a00209228; (void)a00209228; gdcm::Attribute<0x0020,0x9238> a00209238; (void)a00209238; gdcm::Attribute<0x0020,0x9241> a00209241; (void)a00209241; gdcm::Attribute<0x0020,0x9245> a00209245; (void)a00209245; gdcm::Attribute<0x0020,0x9246> a00209246; (void)a00209246; gdcm::Attribute<0x0020,0x9247> a00209247; (void)a00209247; gdcm::Attribute<0x0020,0x9248> a00209248; (void)a00209248; gdcm::Attribute<0x0020,0x9249> a00209249; (void)a00209249; gdcm::Attribute<0x0020,0x9250> a00209250; (void)a00209250; gdcm::Attribute<0x0020,0x9251> a00209251; (void)a00209251; gdcm::Attribute<0x0020,0x9252> a00209252; (void)a00209252; gdcm::Attribute<0x0020,0x9253> a00209253; (void)a00209253; gdcm::Attribute<0x0020,0x9254> a00209254; (void)a00209254; gdcm::Attribute<0x0020,0x9255> a00209255; (void)a00209255; gdcm::Attribute<0x0020,0x9256> a00209256; (void)a00209256; gdcm::Attribute<0x0020,0x9257> a00209257; (void)a00209257; gdcm::Attribute<0x0020,0x9421> a00209421; (void)a00209421; gdcm::Attribute<0x0020,0x9450> a00209450; (void)a00209450; gdcm::Attribute<0x0020,0x9453> a00209453; (void)a00209453; gdcm::Attribute<0x0020,0x9518> a00209518; (void)a00209518; gdcm::Attribute<0x0020,0x9529> a00209529; (void)a00209529; gdcm::Attribute<0x0020,0x9536> a00209536; (void)a00209536; gdcm::Attribute<0x0022,0x0001> a00220001; (void)a00220001; gdcm::Attribute<0x0022,0x0002> a00220002; (void)a00220002; gdcm::Attribute<0x0022,0x0003> a00220003; (void)a00220003; gdcm::Attribute<0x0022,0x0004> a00220004; (void)a00220004; gdcm::Attribute<0x0022,0x0005> a00220005; (void)a00220005; gdcm::Attribute<0x0022,0x0006> a00220006; (void)a00220006; gdcm::Attribute<0x0022,0x0007> a00220007; (void)a00220007; gdcm::Attribute<0x0022,0x0008> a00220008; (void)a00220008; gdcm::Attribute<0x0022,0x0009> a00220009; (void)a00220009; gdcm::Attribute<0x0022,0x000a> a0022000a; (void)a0022000a; gdcm::Attribute<0x0022,0x000b> a0022000b; (void)a0022000b; gdcm::Attribute<0x0022,0x000c> a0022000c; (void)a0022000c; gdcm::Attribute<0x0022,0x000d> a0022000d; (void)a0022000d; gdcm::Attribute<0x0022,0x000e> a0022000e; (void)a0022000e; gdcm::Attribute<0x0022,0x0010> a00220010; (void)a00220010; gdcm::Attribute<0x0022,0x0011> a00220011; (void)a00220011; gdcm::Attribute<0x0022,0x0012> a00220012; (void)a00220012; gdcm::Attribute<0x0022,0x0013> a00220013; (void)a00220013; gdcm::Attribute<0x0022,0x0014> a00220014; (void)a00220014; gdcm::Attribute<0x0022,0x0015> a00220015; (void)a00220015; gdcm::Attribute<0x0022,0x0016> a00220016; (void)a00220016; gdcm::Attribute<0x0022,0x0017> a00220017; (void)a00220017; gdcm::Attribute<0x0022,0x0018> a00220018; (void)a00220018; gdcm::Attribute<0x0022,0x0019> a00220019; (void)a00220019; gdcm::Attribute<0x0022,0x001a> a0022001a; (void)a0022001a; gdcm::Attribute<0x0022,0x001b> a0022001b; (void)a0022001b; gdcm::Attribute<0x0022,0x001c> a0022001c; (void)a0022001c; gdcm::Attribute<0x0022,0x001d> a0022001d; (void)a0022001d; gdcm::Attribute<0x0022,0x0020> a00220020; (void)a00220020; gdcm::Attribute<0x0022,0x0021> a00220021; (void)a00220021; gdcm::Attribute<0x0022,0x0022> a00220022; (void)a00220022; gdcm::Attribute<0x0022,0x0030> a00220030; (void)a00220030; gdcm::Attribute<0x0022,0x0031> a00220031; (void)a00220031; gdcm::Attribute<0x0022,0x0032> a00220032; (void)a00220032; gdcm::Attribute<0x0022,0x0035> a00220035; (void)a00220035; gdcm::Attribute<0x0022,0x0036> a00220036; (void)a00220036; gdcm::Attribute<0x0022,0x0037> a00220037; (void)a00220037; gdcm::Attribute<0x0022,0x0038> a00220038; (void)a00220038; gdcm::Attribute<0x0022,0x0039> a00220039; (void)a00220039; gdcm::Attribute<0x0022,0x0041> a00220041; (void)a00220041; gdcm::Attribute<0x0022,0x0042> a00220042; (void)a00220042; gdcm::Attribute<0x0022,0x0048> a00220048; (void)a00220048; gdcm::Attribute<0x0022,0x0049> a00220049; (void)a00220049; gdcm::Attribute<0x0022,0x004e> a0022004e; (void)a0022004e; gdcm::Attribute<0x0022,0x0055> a00220055; (void)a00220055; gdcm::Attribute<0x0022,0x0056> a00220056; (void)a00220056; gdcm::Attribute<0x0022,0x0057> a00220057; (void)a00220057; gdcm::Attribute<0x0022,0x0058> a00220058; (void)a00220058; gdcm::Attribute<0x0028,0x0002> a00280002; (void)a00280002; gdcm::Attribute<0x0028,0x0003> a00280003; (void)a00280003; gdcm::Attribute<0x0028,0x0004> a00280004; (void)a00280004; gdcm::Attribute<0x0028,0x0005> a00280005; (void)a00280005; gdcm::Attribute<0x0028,0x0006> a00280006; (void)a00280006; gdcm::Attribute<0x0028,0x0008> a00280008; (void)a00280008; gdcm::Attribute<0x0028,0x0009> a00280009; (void)a00280009; gdcm::Attribute<0x0028,0x000a> a0028000a; (void)a0028000a; gdcm::Attribute<0x0028,0x0010> a00280010; (void)a00280010; gdcm::Attribute<0x0028,0x0011> a00280011; (void)a00280011; gdcm::Attribute<0x0028,0x0012> a00280012; (void)a00280012; gdcm::Attribute<0x0028,0x0014> a00280014; (void)a00280014; gdcm::Attribute<0x0028,0x0030> a00280030; (void)a00280030; gdcm::Attribute<0x0028,0x0031> a00280031; (void)a00280031; gdcm::Attribute<0x0028,0x0032> a00280032; (void)a00280032; gdcm::Attribute<0x0028,0x0034> a00280034; (void)a00280034; gdcm::Attribute<0x0028,0x0040> a00280040; (void)a00280040; gdcm::Attribute<0x0028,0x0050> a00280050; (void)a00280050; gdcm::Attribute<0x0028,0x0051> a00280051; (void)a00280051; gdcm::Attribute<0x0028,0x005f> a0028005f; (void)a0028005f; gdcm::Attribute<0x0028,0x0060> a00280060; (void)a00280060; gdcm::Attribute<0x0028,0x0061> a00280061; (void)a00280061; gdcm::Attribute<0x0028,0x0062> a00280062; (void)a00280062; gdcm::Attribute<0x0028,0x0063> a00280063; (void)a00280063; gdcm::Attribute<0x0028,0x0065> a00280065; (void)a00280065; gdcm::Attribute<0x0028,0x0066> a00280066; (void)a00280066; gdcm::Attribute<0x0028,0x0068> a00280068; (void)a00280068; gdcm::Attribute<0x0028,0x0069> a00280069; (void)a00280069; gdcm::Attribute<0x0028,0x0070> a00280070; (void)a00280070; gdcm::Attribute<0x0028,0x0080> a00280080; (void)a00280080; gdcm::Attribute<0x0028,0x0081> a00280081; (void)a00280081; gdcm::Attribute<0x0028,0x0082> a00280082; (void)a00280082; gdcm::Attribute<0x0028,0x0090> a00280090; (void)a00280090; gdcm::Attribute<0x0028,0x0091> a00280091; (void)a00280091; gdcm::Attribute<0x0028,0x0092> a00280092; (void)a00280092; gdcm::Attribute<0x0028,0x0093> a00280093; (void)a00280093; gdcm::Attribute<0x0028,0x0094> a00280094; (void)a00280094; gdcm::Attribute<0x0028,0x0100> a00280100; (void)a00280100; gdcm::Attribute<0x0028,0x0101> a00280101; (void)a00280101; gdcm::Attribute<0x0028,0x0102> a00280102; (void)a00280102; gdcm::Attribute<0x0028,0x0103> a00280103; (void)a00280103; gdcm::Attribute<0x0028,0x0200> a00280200; (void)a00280200; gdcm::Attribute<0x0028,0x0300> a00280300; (void)a00280300; gdcm::Attribute<0x0028,0x0301> a00280301; (void)a00280301; gdcm::Attribute<0x0028,0x0400> a00280400; (void)a00280400; gdcm::Attribute<0x0028,0x0401> a00280401; (void)a00280401; gdcm::Attribute<0x0028,0x0402> a00280402; (void)a00280402; gdcm::Attribute<0x0028,0x0403> a00280403; (void)a00280403; gdcm::Attribute<0x0028,0x0404> a00280404; (void)a00280404; gdcm::Attribute<0x0028,0x0700> a00280700; (void)a00280700; gdcm::Attribute<0x0028,0x0701> a00280701; (void)a00280701; gdcm::Attribute<0x0028,0x0702> a00280702; (void)a00280702; gdcm::Attribute<0x0028,0x0710> a00280710; (void)a00280710; gdcm::Attribute<0x0028,0x0720> a00280720; (void)a00280720; gdcm::Attribute<0x0028,0x0721> a00280721; (void)a00280721; gdcm::Attribute<0x0028,0x0722> a00280722; (void)a00280722; gdcm::Attribute<0x0028,0x0730> a00280730; (void)a00280730; gdcm::Attribute<0x0028,0x0740> a00280740; (void)a00280740; gdcm::Attribute<0x0028,0x0a02> a00280a02; (void)a00280a02; gdcm::Attribute<0x0028,0x0a04> a00280a04; (void)a00280a04; gdcm::Attribute<0x0028,0x1040> a00281040; (void)a00281040; gdcm::Attribute<0x0028,0x1041> a00281041; (void)a00281041; gdcm::Attribute<0x0028,0x1050> a00281050; (void)a00281050; gdcm::Attribute<0x0028,0x1051> a00281051; (void)a00281051; gdcm::Attribute<0x0028,0x1052> a00281052; (void)a00281052; gdcm::Attribute<0x0028,0x1053> a00281053; (void)a00281053; gdcm::Attribute<0x0028,0x1054> a00281054; (void)a00281054; gdcm::Attribute<0x0028,0x1055> a00281055; (void)a00281055; gdcm::Attribute<0x0028,0x1056> a00281056; (void)a00281056; gdcm::Attribute<0x0028,0x1080> a00281080; (void)a00281080; gdcm::Attribute<0x0028,0x1090> a00281090; (void)a00281090; gdcm::Attribute<0x0028,0x1199> a00281199; (void)a00281199; gdcm::Attribute<0x0028,0x1201> a00281201; (void)a00281201; gdcm::Attribute<0x0028,0x1202> a00281202; (void)a00281202; gdcm::Attribute<0x0028,0x1203> a00281203; (void)a00281203; gdcm::Attribute<0x0028,0x1211> a00281211; (void)a00281211; gdcm::Attribute<0x0028,0x1212> a00281212; (void)a00281212; gdcm::Attribute<0x0028,0x1213> a00281213; (void)a00281213; gdcm::Attribute<0x0028,0x1214> a00281214; (void)a00281214; gdcm::Attribute<0x0028,0x1221> a00281221; (void)a00281221; gdcm::Attribute<0x0028,0x1222> a00281222; (void)a00281222; gdcm::Attribute<0x0028,0x1223> a00281223; (void)a00281223; gdcm::Attribute<0x0028,0x1300> a00281300; (void)a00281300; gdcm::Attribute<0x0028,0x1350> a00281350; (void)a00281350; gdcm::Attribute<0x0028,0x1351> a00281351; (void)a00281351; gdcm::Attribute<0x0028,0x1352> a00281352; (void)a00281352; gdcm::Attribute<0x0028,0x135a> a0028135a; (void)a0028135a; gdcm::Attribute<0x0028,0x2000> a00282000; (void)a00282000; gdcm::Attribute<0x0028,0x2110> a00282110; (void)a00282110; gdcm::Attribute<0x0028,0x2112> a00282112; (void)a00282112; gdcm::Attribute<0x0028,0x2114> a00282114; (void)a00282114; gdcm::Attribute<0x0028,0x3000> a00283000; (void)a00283000; gdcm::Attribute<0x0028,0x3003> a00283003; (void)a00283003; gdcm::Attribute<0x0028,0x3004> a00283004; (void)a00283004; gdcm::Attribute<0x0028,0x3010> a00283010; (void)a00283010; gdcm::Attribute<0x0028,0x3110> a00283110; (void)a00283110; gdcm::Attribute<0x0028,0x4000> a00284000; (void)a00284000; gdcm::Attribute<0x0028,0x5000> a00285000; (void)a00285000; gdcm::Attribute<0x0028,0x6010> a00286010; (void)a00286010; gdcm::Attribute<0x0028,0x6020> a00286020; (void)a00286020; gdcm::Attribute<0x0028,0x6022> a00286022; (void)a00286022; gdcm::Attribute<0x0028,0x6023> a00286023; (void)a00286023; gdcm::Attribute<0x0028,0x6030> a00286030; (void)a00286030; gdcm::Attribute<0x0028,0x6040> a00286040; (void)a00286040; gdcm::Attribute<0x0028,0x6100> a00286100; (void)a00286100; gdcm::Attribute<0x0028,0x6101> a00286101; (void)a00286101; gdcm::Attribute<0x0028,0x6102> a00286102; (void)a00286102; gdcm::Attribute<0x0028,0x6110> a00286110; (void)a00286110; gdcm::Attribute<0x0028,0x6112> a00286112; (void)a00286112; gdcm::Attribute<0x0028,0x6114> a00286114; (void)a00286114; gdcm::Attribute<0x0028,0x6120> a00286120; (void)a00286120; gdcm::Attribute<0x0028,0x6190> a00286190; (void)a00286190; gdcm::Attribute<0x0028,0x7fe0> a00287fe0; (void)a00287fe0; gdcm::Attribute<0x0028,0x9001> a00289001; (void)a00289001; gdcm::Attribute<0x0028,0x9002> a00289002; (void)a00289002; gdcm::Attribute<0x0028,0x9003> a00289003; (void)a00289003; gdcm::Attribute<0x0028,0x9099> a00289099; (void)a00289099; gdcm::Attribute<0x0028,0x9108> a00289108; (void)a00289108; gdcm::Attribute<0x0028,0x9110> a00289110; (void)a00289110; gdcm::Attribute<0x0028,0x9132> a00289132; (void)a00289132; gdcm::Attribute<0x0028,0x9145> a00289145; (void)a00289145; gdcm::Attribute<0x0028,0x9235> a00289235; (void)a00289235; gdcm::Attribute<0x0028,0x9411> a00289411; (void)a00289411; gdcm::Attribute<0x0028,0x9415> a00289415; (void)a00289415; gdcm::Attribute<0x0028,0x9416> a00289416; (void)a00289416; gdcm::Attribute<0x0028,0x9422> a00289422; (void)a00289422; gdcm::Attribute<0x0028,0x9443> a00289443; (void)a00289443; gdcm::Attribute<0x0028,0x9444> a00289444; (void)a00289444; gdcm::Attribute<0x0028,0x9445> a00289445; (void)a00289445; gdcm::Attribute<0x0028,0x9446> a00289446; (void)a00289446; gdcm::Attribute<0x0028,0x9454> a00289454; (void)a00289454; gdcm::Attribute<0x0028,0x9474> a00289474; (void)a00289474; gdcm::Attribute<0x0028,0x9520> a00289520; (void)a00289520; gdcm::Attribute<0x0028,0x9537> a00289537; (void)a00289537; gdcm::Attribute<0x0032,0x000a> a0032000a; (void)a0032000a; gdcm::Attribute<0x0032,0x000c> a0032000c; (void)a0032000c; gdcm::Attribute<0x0032,0x0012> a00320012; (void)a00320012; gdcm::Attribute<0x0032,0x0032> a00320032; (void)a00320032; gdcm::Attribute<0x0032,0x0033> a00320033; (void)a00320033; gdcm::Attribute<0x0032,0x0034> a00320034; (void)a00320034; gdcm::Attribute<0x0032,0x0035> a00320035; (void)a00320035; gdcm::Attribute<0x0032,0x1000> a00321000; (void)a00321000; gdcm::Attribute<0x0032,0x1001> a00321001; (void)a00321001; gdcm::Attribute<0x0032,0x1010> a00321010; (void)a00321010; gdcm::Attribute<0x0032,0x1011> a00321011; (void)a00321011; gdcm::Attribute<0x0032,0x1020> a00321020; (void)a00321020; gdcm::Attribute<0x0032,0x1021> a00321021; (void)a00321021; gdcm::Attribute<0x0032,0x1030> a00321030; (void)a00321030; gdcm::Attribute<0x0032,0x1031> a00321031; (void)a00321031; gdcm::Attribute<0x0032,0x1032> a00321032; (void)a00321032; gdcm::Attribute<0x0032,0x1033> a00321033; (void)a00321033; gdcm::Attribute<0x0032,0x1040> a00321040; (void)a00321040; gdcm::Attribute<0x0032,0x1041> a00321041; (void)a00321041; gdcm::Attribute<0x0032,0x1050> a00321050; (void)a00321050; gdcm::Attribute<0x0032,0x1051> a00321051; (void)a00321051; gdcm::Attribute<0x0032,0x1055> a00321055; (void)a00321055; gdcm::Attribute<0x0032,0x1060> a00321060; (void)a00321060; gdcm::Attribute<0x0032,0x1064> a00321064; (void)a00321064; gdcm::Attribute<0x0032,0x1070> a00321070; (void)a00321070; gdcm::Attribute<0x0032,0x4000> a00324000; (void)a00324000; gdcm::Attribute<0x0038,0x0004> a00380004; (void)a00380004; gdcm::Attribute<0x0038,0x0008> a00380008; (void)a00380008; gdcm::Attribute<0x0038,0x0010> a00380010; (void)a00380010; gdcm::Attribute<0x0038,0x0011> a00380011; (void)a00380011; gdcm::Attribute<0x0038,0x0016> a00380016; (void)a00380016; gdcm::Attribute<0x0038,0x001a> a0038001a; (void)a0038001a; gdcm::Attribute<0x0038,0x001b> a0038001b; (void)a0038001b; gdcm::Attribute<0x0038,0x001c> a0038001c; (void)a0038001c; gdcm::Attribute<0x0038,0x001d> a0038001d; (void)a0038001d; gdcm::Attribute<0x0038,0x001e> a0038001e; (void)a0038001e; gdcm::Attribute<0x0038,0x0020> a00380020; (void)a00380020; gdcm::Attribute<0x0038,0x0021> a00380021; (void)a00380021; gdcm::Attribute<0x0038,0x0030> a00380030; (void)a00380030; gdcm::Attribute<0x0038,0x0032> a00380032; (void)a00380032; gdcm::Attribute<0x0038,0x0040> a00380040; (void)a00380040; gdcm::Attribute<0x0038,0x0044> a00380044; (void)a00380044; gdcm::Attribute<0x0038,0x0050> a00380050; (void)a00380050; gdcm::Attribute<0x0038,0x0060> a00380060; (void)a00380060; gdcm::Attribute<0x0038,0x0061> a00380061; (void)a00380061; gdcm::Attribute<0x0038,0x0062> a00380062; (void)a00380062; gdcm::Attribute<0x0038,0x0100> a00380100; (void)a00380100; gdcm::Attribute<0x0038,0x0300> a00380300; (void)a00380300; gdcm::Attribute<0x0038,0x0400> a00380400; (void)a00380400; gdcm::Attribute<0x0038,0x0500> a00380500; (void)a00380500; gdcm::Attribute<0x0038,0x0502> a00380502; (void)a00380502; gdcm::Attribute<0x0038,0x4000> a00384000; (void)a00384000; gdcm::Attribute<0x003a,0x0004> a003a0004; (void)a003a0004; gdcm::Attribute<0x003a,0x0005> a003a0005; (void)a003a0005; gdcm::Attribute<0x003a,0x0010> a003a0010; (void)a003a0010; gdcm::Attribute<0x003a,0x001a> a003a001a; (void)a003a001a; gdcm::Attribute<0x003a,0x0020> a003a0020; (void)a003a0020; gdcm::Attribute<0x003a,0x0200> a003a0200; (void)a003a0200; gdcm::Attribute<0x003a,0x0202> a003a0202; (void)a003a0202; gdcm::Attribute<0x003a,0x0203> a003a0203; (void)a003a0203; gdcm::Attribute<0x003a,0x0205> a003a0205; (void)a003a0205; gdcm::Attribute<0x003a,0x0208> a003a0208; (void)a003a0208; gdcm::Attribute<0x003a,0x0209> a003a0209; (void)a003a0209; gdcm::Attribute<0x003a,0x020a> a003a020a; (void)a003a020a; gdcm::Attribute<0x003a,0x020c> a003a020c; (void)a003a020c; gdcm::Attribute<0x003a,0x0210> a003a0210; (void)a003a0210; gdcm::Attribute<0x003a,0x0211> a003a0211; (void)a003a0211; gdcm::Attribute<0x003a,0x0212> a003a0212; (void)a003a0212; gdcm::Attribute<0x003a,0x0213> a003a0213; (void)a003a0213; gdcm::Attribute<0x003a,0x0214> a003a0214; (void)a003a0214; gdcm::Attribute<0x003a,0x0215> a003a0215; (void)a003a0215; gdcm::Attribute<0x003a,0x0218> a003a0218; (void)a003a0218; gdcm::Attribute<0x003a,0x021a> a003a021a; (void)a003a021a; gdcm::Attribute<0x003a,0x0220> a003a0220; (void)a003a0220; gdcm::Attribute<0x003a,0x0221> a003a0221; (void)a003a0221; gdcm::Attribute<0x003a,0x0222> a003a0222; (void)a003a0222; gdcm::Attribute<0x003a,0x0223> a003a0223; (void)a003a0223; gdcm::Attribute<0x003a,0x0230> a003a0230; (void)a003a0230; gdcm::Attribute<0x003a,0x0231> a003a0231; (void)a003a0231; gdcm::Attribute<0x003a,0x0240> a003a0240; (void)a003a0240; gdcm::Attribute<0x003a,0x0241> a003a0241; (void)a003a0241; gdcm::Attribute<0x003a,0x0242> a003a0242; (void)a003a0242; gdcm::Attribute<0x003a,0x0244> a003a0244; (void)a003a0244; gdcm::Attribute<0x003a,0x0245> a003a0245; (void)a003a0245; gdcm::Attribute<0x003a,0x0246> a003a0246; (void)a003a0246; gdcm::Attribute<0x003a,0x0247> a003a0247; (void)a003a0247; gdcm::Attribute<0x003a,0x0248> a003a0248; (void)a003a0248; gdcm::Attribute<0x003a,0x0300> a003a0300; (void)a003a0300; gdcm::Attribute<0x003a,0x0301> a003a0301; (void)a003a0301; gdcm::Attribute<0x003a,0x0302> a003a0302; (void)a003a0302; gdcm::Attribute<0x0040,0x0001> a00400001; (void)a00400001; gdcm::Attribute<0x0040,0x0002> a00400002; (void)a00400002; gdcm::Attribute<0x0040,0x0003> a00400003; (void)a00400003; gdcm::Attribute<0x0040,0x0004> a00400004; (void)a00400004; gdcm::Attribute<0x0040,0x0005> a00400005; (void)a00400005; gdcm::Attribute<0x0040,0x0006> a00400006; (void)a00400006; gdcm::Attribute<0x0040,0x0007> a00400007; (void)a00400007; gdcm::Attribute<0x0040,0x0008> a00400008; (void)a00400008; gdcm::Attribute<0x0040,0x0009> a00400009; (void)a00400009; gdcm::Attribute<0x0040,0x000a> a0040000a; (void)a0040000a; gdcm::Attribute<0x0040,0x000b> a0040000b; (void)a0040000b; gdcm::Attribute<0x0040,0x0010> a00400010; (void)a00400010; gdcm::Attribute<0x0040,0x0011> a00400011; (void)a00400011; gdcm::Attribute<0x0040,0x0012> a00400012; (void)a00400012; gdcm::Attribute<0x0040,0x0020> a00400020; (void)a00400020; gdcm::Attribute<0x0040,0x0100> a00400100; (void)a00400100; gdcm::Attribute<0x0040,0x0220> a00400220; (void)a00400220; gdcm::Attribute<0x0040,0x0241> a00400241; (void)a00400241; gdcm::Attribute<0x0040,0x0242> a00400242; (void)a00400242; gdcm::Attribute<0x0040,0x0243> a00400243; (void)a00400243; gdcm::Attribute<0x0040,0x0244> a00400244; (void)a00400244; gdcm::Attribute<0x0040,0x0245> a00400245; (void)a00400245; gdcm::Attribute<0x0040,0x0250> a00400250; (void)a00400250; gdcm::Attribute<0x0040,0x0251> a00400251; (void)a00400251; gdcm::Attribute<0x0040,0x0252> a00400252; (void)a00400252; gdcm::Attribute<0x0040,0x0253> a00400253; (void)a00400253; gdcm::Attribute<0x0040,0x0254> a00400254; (void)a00400254; gdcm::Attribute<0x0040,0x0255> a00400255; (void)a00400255; gdcm::Attribute<0x0040,0x0260> a00400260; (void)a00400260; gdcm::Attribute<0x0040,0x0270> a00400270; (void)a00400270; gdcm::Attribute<0x0040,0x0275> a00400275; (void)a00400275; gdcm::Attribute<0x0040,0x0280> a00400280; (void)a00400280; gdcm::Attribute<0x0040,0x0281> a00400281; (void)a00400281; gdcm::Attribute<0x0040,0x0293> a00400293; (void)a00400293; gdcm::Attribute<0x0040,0x0294> a00400294; (void)a00400294; gdcm::Attribute<0x0040,0x0295> a00400295; (void)a00400295; gdcm::Attribute<0x0040,0x0296> a00400296; (void)a00400296; gdcm::Attribute<0x0040,0x0300> a00400300; (void)a00400300; gdcm::Attribute<0x0040,0x0301> a00400301; (void)a00400301; gdcm::Attribute<0x0040,0x0302> a00400302; (void)a00400302; gdcm::Attribute<0x0040,0x0306> a00400306; (void)a00400306; gdcm::Attribute<0x0040,0x0307> a00400307; (void)a00400307; gdcm::Attribute<0x0040,0x030e> a0040030e; (void)a0040030e; gdcm::Attribute<0x0040,0x0310> a00400310; (void)a00400310; gdcm::Attribute<0x0040,0x0312> a00400312; (void)a00400312; gdcm::Attribute<0x0040,0x0314> a00400314; (void)a00400314; gdcm::Attribute<0x0040,0x0316> a00400316; (void)a00400316; gdcm::Attribute<0x0040,0x0318> a00400318; (void)a00400318; gdcm::Attribute<0x0040,0x0320> a00400320; (void)a00400320; gdcm::Attribute<0x0040,0x0321> a00400321; (void)a00400321; gdcm::Attribute<0x0040,0x0324> a00400324; (void)a00400324; gdcm::Attribute<0x0040,0x0330> a00400330; (void)a00400330; gdcm::Attribute<0x0040,0x0340> a00400340; (void)a00400340; gdcm::Attribute<0x0040,0x0400> a00400400; (void)a00400400; gdcm::Attribute<0x0040,0x0440> a00400440; (void)a00400440; gdcm::Attribute<0x0040,0x0441> a00400441; (void)a00400441; gdcm::Attribute<0x0040,0x050a> a0040050a; (void)a0040050a; gdcm::Attribute<0x0040,0x0550> a00400550; (void)a00400550; gdcm::Attribute<0x0040,0x0551> a00400551; (void)a00400551; gdcm::Attribute<0x0040,0x0552> a00400552; (void)a00400552; gdcm::Attribute<0x0040,0x0553> a00400553; (void)a00400553; gdcm::Attribute<0x0040,0x0555> a00400555; (void)a00400555; gdcm::Attribute<0x0040,0x0556> a00400556; (void)a00400556; gdcm::Attribute<0x0040,0x059a> a0040059a; (void)a0040059a; gdcm::Attribute<0x0040,0x06fa> a004006fa; (void)a004006fa; gdcm::Attribute<0x0040,0x071a> a0040071a; (void)a0040071a; gdcm::Attribute<0x0040,0x072a> a0040072a; (void)a0040072a; gdcm::Attribute<0x0040,0x073a> a0040073a; (void)a0040073a; gdcm::Attribute<0x0040,0x074a> a0040074a; (void)a0040074a; gdcm::Attribute<0x0040,0x08d8> a004008d8; (void)a004008d8; gdcm::Attribute<0x0040,0x08da> a004008da; (void)a004008da; gdcm::Attribute<0x0040,0x08ea> a004008ea; (void)a004008ea; gdcm::Attribute<0x0040,0x09f8> a004009f8; (void)a004009f8; gdcm::Attribute<0x0040,0x1001> a00401001; (void)a00401001; gdcm::Attribute<0x0040,0x1002> a00401002; (void)a00401002; gdcm::Attribute<0x0040,0x1003> a00401003; (void)a00401003; gdcm::Attribute<0x0040,0x1004> a00401004; (void)a00401004; gdcm::Attribute<0x0040,0x1005> a00401005; (void)a00401005; gdcm::Attribute<0x0040,0x1006> a00401006; (void)a00401006; gdcm::Attribute<0x0040,0x1007> a00401007; (void)a00401007; gdcm::Attribute<0x0040,0x1008> a00401008; (void)a00401008; gdcm::Attribute<0x0040,0x1009> a00401009; (void)a00401009; gdcm::Attribute<0x0040,0x100a> a0040100a; (void)a0040100a; gdcm::Attribute<0x0040,0x1010> a00401010; (void)a00401010; gdcm::Attribute<0x0040,0x1011> a00401011; (void)a00401011; gdcm::Attribute<0x0040,0x1101> a00401101; (void)a00401101; gdcm::Attribute<0x0040,0x1102> a00401102; (void)a00401102; gdcm::Attribute<0x0040,0x1103> a00401103; (void)a00401103; gdcm::Attribute<0x0040,0x1400> a00401400; (void)a00401400; gdcm::Attribute<0x0040,0x2001> a00402001; (void)a00402001; gdcm::Attribute<0x0040,0x2004> a00402004; (void)a00402004; gdcm::Attribute<0x0040,0x2005> a00402005; (void)a00402005; gdcm::Attribute<0x0040,0x2006> a00402006; (void)a00402006; gdcm::Attribute<0x0040,0x2007> a00402007; (void)a00402007; gdcm::Attribute<0x0040,0x2008> a00402008; (void)a00402008; gdcm::Attribute<0x0040,0x2009> a00402009; (void)a00402009; gdcm::Attribute<0x0040,0x2010> a00402010; (void)a00402010; gdcm::Attribute<0x0040,0x2016> a00402016; (void)a00402016; gdcm::Attribute<0x0040,0x2017> a00402017; (void)a00402017; gdcm::Attribute<0x0040,0x2400> a00402400; (void)a00402400; gdcm::Attribute<0x0040,0x3001> a00403001; (void)a00403001; gdcm::Attribute<0x0040,0x4001> a00404001; (void)a00404001; gdcm::Attribute<0x0040,0x4002> a00404002; (void)a00404002; gdcm::Attribute<0x0040,0x4003> a00404003; (void)a00404003; gdcm::Attribute<0x0040,0x4004> a00404004; (void)a00404004; gdcm::Attribute<0x0040,0x4005> a00404005; (void)a00404005; gdcm::Attribute<0x0040,0x4006> a00404006; (void)a00404006; gdcm::Attribute<0x0040,0x4007> a00404007; (void)a00404007; gdcm::Attribute<0x0040,0x4009> a00404009; (void)a00404009; gdcm::Attribute<0x0040,0x4010> a00404010; (void)a00404010; gdcm::Attribute<0x0040,0x4011> a00404011; (void)a00404011; gdcm::Attribute<0x0040,0x4015> a00404015; (void)a00404015; gdcm::Attribute<0x0040,0x4016> a00404016; (void)a00404016; gdcm::Attribute<0x0040,0x4018> a00404018; (void)a00404018; gdcm::Attribute<0x0040,0x4019> a00404019; (void)a00404019; gdcm::Attribute<0x0040,0x4020> a00404020; (void)a00404020; gdcm::Attribute<0x0040,0x4021> a00404021; (void)a00404021; gdcm::Attribute<0x0040,0x4022> a00404022; (void)a00404022; gdcm::Attribute<0x0040,0x4023> a00404023; (void)a00404023; gdcm::Attribute<0x0040,0x4025> a00404025; (void)a00404025; gdcm::Attribute<0x0040,0x4026> a00404026; (void)a00404026; gdcm::Attribute<0x0040,0x4027> a00404027; (void)a00404027; gdcm::Attribute<0x0040,0x4028> a00404028; (void)a00404028; gdcm::Attribute<0x0040,0x4029> a00404029; (void)a00404029; gdcm::Attribute<0x0040,0x4030> a00404030; (void)a00404030; gdcm::Attribute<0x0040,0x4031> a00404031; (void)a00404031; gdcm::Attribute<0x0040,0x4032> a00404032; (void)a00404032; gdcm::Attribute<0x0040,0x4033> a00404033; (void)a00404033; gdcm::Attribute<0x0040,0x4034> a00404034; (void)a00404034; gdcm::Attribute<0x0040,0x4035> a00404035; (void)a00404035; gdcm::Attribute<0x0040,0x4036> a00404036; (void)a00404036; gdcm::Attribute<0x0040,0x4037> a00404037; (void)a00404037; gdcm::Attribute<0x0040,0x8302> a00408302; (void)a00408302; gdcm::Attribute<0x0040,0x9094> a00409094; (void)a00409094; gdcm::Attribute<0x0040,0x9096> a00409096; (void)a00409096; gdcm::Attribute<0x0040,0x9098> a00409098; (void)a00409098; gdcm::Attribute<0x0040,0x9210> a00409210; (void)a00409210; gdcm::Attribute<0x0040,0x9212> a00409212; (void)a00409212; gdcm::Attribute<0x0040,0x9224> a00409224; (void)a00409224; gdcm::Attribute<0x0040,0x9225> a00409225; (void)a00409225; gdcm::Attribute<0x0040,0xa010> a0040a010; (void)a0040a010; gdcm::Attribute<0x0040,0xa027> a0040a027; (void)a0040a027; gdcm::Attribute<0x0040,0xa030> a0040a030; (void)a0040a030; gdcm::Attribute<0x0040,0xa032> a0040a032; (void)a0040a032; gdcm::Attribute<0x0040,0xa040> a0040a040; (void)a0040a040; gdcm::Attribute<0x0040,0xa043> a0040a043; (void)a0040a043; gdcm::Attribute<0x0040,0xa050> a0040a050; (void)a0040a050; gdcm::Attribute<0x0040,0xa073> a0040a073; (void)a0040a073; gdcm::Attribute<0x0040,0xa075> a0040a075; (void)a0040a075; gdcm::Attribute<0x0040,0xa078> a0040a078; (void)a0040a078; gdcm::Attribute<0x0040,0xa07a> a0040a07a; (void)a0040a07a; gdcm::Attribute<0x0040,0xa07c> a0040a07c; (void)a0040a07c; gdcm::Attribute<0x0040,0xa080> a0040a080; (void)a0040a080; gdcm::Attribute<0x0040,0xa082> a0040a082; (void)a0040a082; gdcm::Attribute<0x0040,0xa084> a0040a084; (void)a0040a084; gdcm::Attribute<0x0040,0xa088> a0040a088; (void)a0040a088; gdcm::Attribute<0x0040,0xa090> a0040a090; (void)a0040a090; gdcm::Attribute<0x0040,0xa0b0> a0040a0b0; (void)a0040a0b0; gdcm::Attribute<0x0040,0xa120> a0040a120; (void)a0040a120; gdcm::Attribute<0x0040,0xa121> a0040a121; (void)a0040a121; gdcm::Attribute<0x0040,0xa122> a0040a122; (void)a0040a122; gdcm::Attribute<0x0040,0xa123> a0040a123; (void)a0040a123; gdcm::Attribute<0x0040,0xa124> a0040a124; (void)a0040a124; gdcm::Attribute<0x0040,0xa130> a0040a130; (void)a0040a130; gdcm::Attribute<0x0040,0xa132> a0040a132; (void)a0040a132; gdcm::Attribute<0x0040,0xa136> a0040a136; (void)a0040a136; gdcm::Attribute<0x0040,0xa138> a0040a138; (void)a0040a138; gdcm::Attribute<0x0040,0xa13a> a0040a13a; (void)a0040a13a; gdcm::Attribute<0x0040,0xa160> a0040a160; (void)a0040a160; gdcm::Attribute<0x0040,0xa168> a0040a168; (void)a0040a168; gdcm::Attribute<0x0040,0xa170> a0040a170; (void)a0040a170; gdcm::Attribute<0x0040,0xa180> a0040a180; (void)a0040a180; gdcm::Attribute<0x0040,0xa195> a0040a195; (void)a0040a195; gdcm::Attribute<0x0040,0xa300> a0040a300; (void)a0040a300; gdcm::Attribute<0x0040,0xa301> a0040a301; (void)a0040a301; gdcm::Attribute<0x0040,0xa30a> a0040a30a; (void)a0040a30a; gdcm::Attribute<0x0040,0xa353> a0040a353; (void)a0040a353; gdcm::Attribute<0x0040,0xa354> a0040a354; (void)a0040a354; gdcm::Attribute<0x0040,0xa360> a0040a360; (void)a0040a360; gdcm::Attribute<0x0040,0xa370> a0040a370; (void)a0040a370; gdcm::Attribute<0x0040,0xa372> a0040a372; (void)a0040a372; gdcm::Attribute<0x0040,0xa375> a0040a375; (void)a0040a375; gdcm::Attribute<0x0040,0xa385> a0040a385; (void)a0040a385; gdcm::Attribute<0x0040,0xa390> a0040a390; (void)a0040a390; gdcm::Attribute<0x0040,0xa491> a0040a491; (void)a0040a491; gdcm::Attribute<0x0040,0xa492> a0040a492; (void)a0040a492; gdcm::Attribute<0x0040,0xa493> a0040a493; (void)a0040a493; gdcm::Attribute<0x0040,0xa494> a0040a494; (void)a0040a494; gdcm::Attribute<0x0040,0xa504> a0040a504; (void)a0040a504; gdcm::Attribute<0x0040,0xa525> a0040a525; (void)a0040a525; gdcm::Attribute<0x0040,0xa730> a0040a730; (void)a0040a730; gdcm::Attribute<0x0040,0xb020> a0040b020; (void)a0040b020; gdcm::Attribute<0x0040,0xdb00> a0040db00; (void)a0040db00; gdcm::Attribute<0x0040,0xdb06> a0040db06; (void)a0040db06; gdcm::Attribute<0x0040,0xdb07> a0040db07; (void)a0040db07; gdcm::Attribute<0x0040,0xdb0b> a0040db0b; (void)a0040db0b; gdcm::Attribute<0x0040,0xdb0c> a0040db0c; (void)a0040db0c; gdcm::Attribute<0x0040,0xdb0d> a0040db0d; (void)a0040db0d; gdcm::Attribute<0x0040,0xdb73> a0040db73; (void)a0040db73; gdcm::Attribute<0x0040,0xe001> a0040e001; (void)a0040e001; gdcm::Attribute<0x0040,0xe004> a0040e004; (void)a0040e004; gdcm::Attribute<0x0040,0xe006> a0040e006; (void)a0040e006; gdcm::Attribute<0x0040,0xe010> a0040e010; (void)a0040e010; gdcm::Attribute<0x0042,0x0010> a00420010; (void)a00420010; gdcm::Attribute<0x0042,0x0011> a00420011; (void)a00420011; gdcm::Attribute<0x0042,0x0012> a00420012; (void)a00420012; gdcm::Attribute<0x0042,0x0013> a00420013; (void)a00420013; gdcm::Attribute<0x0042,0x0014> a00420014; (void)a00420014; gdcm::Attribute<0x0044,0x0001> a00440001; (void)a00440001; gdcm::Attribute<0x0044,0x0002> a00440002; (void)a00440002; gdcm::Attribute<0x0044,0x0003> a00440003; (void)a00440003; gdcm::Attribute<0x0044,0x0004> a00440004; (void)a00440004; gdcm::Attribute<0x0044,0x0007> a00440007; (void)a00440007; gdcm::Attribute<0x0044,0x0008> a00440008; (void)a00440008; gdcm::Attribute<0x0044,0x0009> a00440009; (void)a00440009; gdcm::Attribute<0x0044,0x000a> a0044000a; (void)a0044000a; gdcm::Attribute<0x0044,0x000b> a0044000b; (void)a0044000b; gdcm::Attribute<0x0044,0x0010> a00440010; (void)a00440010; gdcm::Attribute<0x0044,0x0011> a00440011; (void)a00440011; gdcm::Attribute<0x0044,0x0012> a00440012; (void)a00440012; gdcm::Attribute<0x0044,0x0013> a00440013; (void)a00440013; gdcm::Attribute<0x0044,0x0019> a00440019; (void)a00440019; gdcm::Attribute<0x0050,0x0004> a00500004; (void)a00500004; gdcm::Attribute<0x0050,0x0010> a00500010; (void)a00500010; gdcm::Attribute<0x0050,0x0014> a00500014; (void)a00500014; gdcm::Attribute<0x0050,0x0016> a00500016; (void)a00500016; gdcm::Attribute<0x0050,0x0017> a00500017; (void)a00500017; gdcm::Attribute<0x0050,0x0018> a00500018; (void)a00500018; gdcm::Attribute<0x0050,0x0019> a00500019; (void)a00500019; gdcm::Attribute<0x0050,0x0020> a00500020; (void)a00500020; gdcm::Attribute<0x0054,0x0010> a00540010; (void)a00540010; gdcm::Attribute<0x0054,0x0011> a00540011; (void)a00540011; gdcm::Attribute<0x0054,0x0012> a00540012; (void)a00540012; gdcm::Attribute<0x0054,0x0013> a00540013; (void)a00540013; gdcm::Attribute<0x0054,0x0014> a00540014; (void)a00540014; gdcm::Attribute<0x0054,0x0015> a00540015; (void)a00540015; gdcm::Attribute<0x0054,0x0016> a00540016; (void)a00540016; gdcm::Attribute<0x0054,0x0017> a00540017; (void)a00540017; gdcm::Attribute<0x0054,0x0018> a00540018; (void)a00540018; gdcm::Attribute<0x0054,0x0020> a00540020; (void)a00540020; gdcm::Attribute<0x0054,0x0021> a00540021; (void)a00540021; gdcm::Attribute<0x0054,0x0022> a00540022; (void)a00540022; gdcm::Attribute<0x0054,0x0030> a00540030; (void)a00540030; gdcm::Attribute<0x0054,0x0031> a00540031; (void)a00540031; gdcm::Attribute<0x0054,0x0032> a00540032; (void)a00540032; gdcm::Attribute<0x0054,0x0033> a00540033; (void)a00540033; gdcm::Attribute<0x0054,0x0036> a00540036; (void)a00540036; gdcm::Attribute<0x0054,0x0038> a00540038; (void)a00540038; gdcm::Attribute<0x0054,0x0039> a00540039; (void)a00540039; gdcm::Attribute<0x0054,0x0050> a00540050; (void)a00540050; gdcm::Attribute<0x0054,0x0051> a00540051; (void)a00540051; gdcm::Attribute<0x0054,0x0052> a00540052; (void)a00540052; gdcm::Attribute<0x0054,0x0053> a00540053; (void)a00540053; gdcm::Attribute<0x0054,0x0060> a00540060; (void)a00540060; gdcm::Attribute<0x0054,0x0061> a00540061; (void)a00540061; gdcm::Attribute<0x0054,0x0062> a00540062; (void)a00540062; gdcm::Attribute<0x0054,0x0063> a00540063; (void)a00540063; gdcm::Attribute<0x0054,0x0070> a00540070; (void)a00540070; gdcm::Attribute<0x0054,0x0071> a00540071; (void)a00540071; gdcm::Attribute<0x0054,0x0072> a00540072; (void)a00540072; gdcm::Attribute<0x0054,0x0073> a00540073; (void)a00540073; gdcm::Attribute<0x0054,0x0080> a00540080; (void)a00540080; gdcm::Attribute<0x0054,0x0081> a00540081; (void)a00540081; gdcm::Attribute<0x0054,0x0090> a00540090; (void)a00540090; gdcm::Attribute<0x0054,0x0100> a00540100; (void)a00540100; gdcm::Attribute<0x0054,0x0101> a00540101; (void)a00540101; gdcm::Attribute<0x0054,0x0200> a00540200; (void)a00540200; gdcm::Attribute<0x0054,0x0202> a00540202; (void)a00540202; gdcm::Attribute<0x0054,0x0210> a00540210; (void)a00540210; gdcm::Attribute<0x0054,0x0211> a00540211; (void)a00540211; gdcm::Attribute<0x0054,0x0220> a00540220; (void)a00540220; gdcm::Attribute<0x0054,0x0222> a00540222; (void)a00540222; gdcm::Attribute<0x0054,0x0300> a00540300; (void)a00540300; gdcm::Attribute<0x0054,0x0302> a00540302; (void)a00540302; gdcm::Attribute<0x0054,0x0304> a00540304; (void)a00540304; gdcm::Attribute<0x0054,0x0306> a00540306; (void)a00540306; gdcm::Attribute<0x0054,0x0308> a00540308; (void)a00540308; gdcm::Attribute<0x0054,0x0400> a00540400; (void)a00540400; gdcm::Attribute<0x0054,0x0410> a00540410; (void)a00540410; gdcm::Attribute<0x0054,0x0412> a00540412; (void)a00540412; gdcm::Attribute<0x0054,0x0414> a00540414; (void)a00540414; gdcm::Attribute<0x0054,0x0500> a00540500; (void)a00540500; gdcm::Attribute<0x0054,0x1000> a00541000; (void)a00541000; gdcm::Attribute<0x0054,0x1001> a00541001; (void)a00541001; gdcm::Attribute<0x0054,0x1002> a00541002; (void)a00541002; gdcm::Attribute<0x0054,0x1004> a00541004; (void)a00541004; gdcm::Attribute<0x0054,0x1100> a00541100; (void)a00541100; gdcm::Attribute<0x0054,0x1101> a00541101; (void)a00541101; gdcm::Attribute<0x0054,0x1102> a00541102; (void)a00541102; gdcm::Attribute<0x0054,0x1103> a00541103; (void)a00541103; gdcm::Attribute<0x0054,0x1104> a00541104; (void)a00541104; gdcm::Attribute<0x0054,0x1105> a00541105; (void)a00541105; gdcm::Attribute<0x0054,0x1200> a00541200; (void)a00541200; gdcm::Attribute<0x0054,0x1201> a00541201; (void)a00541201; gdcm::Attribute<0x0054,0x1202> a00541202; (void)a00541202; gdcm::Attribute<0x0054,0x1203> a00541203; (void)a00541203; gdcm::Attribute<0x0054,0x1210> a00541210; (void)a00541210; gdcm::Attribute<0x0054,0x1220> a00541220; (void)a00541220; gdcm::Attribute<0x0054,0x1300> a00541300; (void)a00541300; gdcm::Attribute<0x0054,0x1310> a00541310; (void)a00541310; gdcm::Attribute<0x0054,0x1311> a00541311; (void)a00541311; gdcm::Attribute<0x0054,0x1320> a00541320; (void)a00541320; gdcm::Attribute<0x0054,0x1321> a00541321; (void)a00541321; gdcm::Attribute<0x0054,0x1322> a00541322; (void)a00541322; gdcm::Attribute<0x0054,0x1323> a00541323; (void)a00541323; gdcm::Attribute<0x0054,0x1324> a00541324; (void)a00541324; gdcm::Attribute<0x0054,0x1330> a00541330; (void)a00541330; gdcm::Attribute<0x0054,0x1400> a00541400; (void)a00541400; gdcm::Attribute<0x0054,0x1401> a00541401; (void)a00541401; gdcm::Attribute<0x0060,0x3000> a00603000; (void)a00603000; gdcm::Attribute<0x0060,0x3002> a00603002; (void)a00603002; gdcm::Attribute<0x0060,0x3008> a00603008; (void)a00603008; gdcm::Attribute<0x0060,0x3010> a00603010; (void)a00603010; gdcm::Attribute<0x0060,0x3020> a00603020; (void)a00603020; gdcm::Attribute<0x0062,0x0001> a00620001; (void)a00620001; gdcm::Attribute<0x0062,0x0002> a00620002; (void)a00620002; gdcm::Attribute<0x0062,0x0003> a00620003; (void)a00620003; gdcm::Attribute<0x0062,0x0004> a00620004; (void)a00620004; gdcm::Attribute<0x0062,0x0005> a00620005; (void)a00620005; gdcm::Attribute<0x0062,0x0006> a00620006; (void)a00620006; gdcm::Attribute<0x0062,0x0008> a00620008; (void)a00620008; gdcm::Attribute<0x0062,0x0009> a00620009; (void)a00620009; gdcm::Attribute<0x0062,0x000a> a0062000a; (void)a0062000a; gdcm::Attribute<0x0062,0x000b> a0062000b; (void)a0062000b; gdcm::Attribute<0x0062,0x000c> a0062000c; (void)a0062000c; gdcm::Attribute<0x0062,0x000d> a0062000d; (void)a0062000d; gdcm::Attribute<0x0062,0x000e> a0062000e; (void)a0062000e; gdcm::Attribute<0x0062,0x000f> a0062000f; (void)a0062000f; gdcm::Attribute<0x0062,0x0010> a00620010; (void)a00620010; gdcm::Attribute<0x0064,0x0002> a00640002; (void)a00640002; gdcm::Attribute<0x0064,0x0003> a00640003; (void)a00640003; gdcm::Attribute<0x0064,0x0005> a00640005; (void)a00640005; gdcm::Attribute<0x0064,0x0007> a00640007; (void)a00640007; gdcm::Attribute<0x0064,0x0008> a00640008; (void)a00640008; gdcm::Attribute<0x0064,0x0009> a00640009; (void)a00640009; gdcm::Attribute<0x0064,0x000f> a0064000f; (void)a0064000f; gdcm::Attribute<0x0064,0x0010> a00640010; (void)a00640010; gdcm::Attribute<0x0070,0x0001> a00700001; (void)a00700001; gdcm::Attribute<0x0070,0x0002> a00700002; (void)a00700002; gdcm::Attribute<0x0070,0x0003> a00700003; (void)a00700003; gdcm::Attribute<0x0070,0x0004> a00700004; (void)a00700004; gdcm::Attribute<0x0070,0x0005> a00700005; (void)a00700005; gdcm::Attribute<0x0070,0x0006> a00700006; (void)a00700006; gdcm::Attribute<0x0070,0x0008> a00700008; (void)a00700008; gdcm::Attribute<0x0070,0x0009> a00700009; (void)a00700009; gdcm::Attribute<0x0070,0x0010> a00700010; (void)a00700010; gdcm::Attribute<0x0070,0x0011> a00700011; (void)a00700011; gdcm::Attribute<0x0070,0x0012> a00700012; (void)a00700012; gdcm::Attribute<0x0070,0x0014> a00700014; (void)a00700014; gdcm::Attribute<0x0070,0x0015> a00700015; (void)a00700015; gdcm::Attribute<0x0070,0x0020> a00700020; (void)a00700020; gdcm::Attribute<0x0070,0x0021> a00700021; (void)a00700021; gdcm::Attribute<0x0070,0x0022> a00700022; (void)a00700022; gdcm::Attribute<0x0070,0x0023> a00700023; (void)a00700023; gdcm::Attribute<0x0070,0x0024> a00700024; (void)a00700024; gdcm::Attribute<0x0070,0x0040> a00700040; (void)a00700040; gdcm::Attribute<0x0070,0x0041> a00700041; (void)a00700041; gdcm::Attribute<0x0070,0x0042> a00700042; (void)a00700042; gdcm::Attribute<0x0070,0x0050> a00700050; (void)a00700050; gdcm::Attribute<0x0070,0x0051> a00700051; (void)a00700051; gdcm::Attribute<0x0070,0x0052> a00700052; (void)a00700052; gdcm::Attribute<0x0070,0x0053> a00700053; (void)a00700053; gdcm::Attribute<0x0070,0x005a> a0070005a; (void)a0070005a; gdcm::Attribute<0x0070,0x0060> a00700060; (void)a00700060; gdcm::Attribute<0x0070,0x0062> a00700062; (void)a00700062; gdcm::Attribute<0x0070,0x0066> a00700066; (void)a00700066; gdcm::Attribute<0x0070,0x0067> a00700067; (void)a00700067; gdcm::Attribute<0x0070,0x0068> a00700068; (void)a00700068; gdcm::Attribute<0x0070,0x0080> a00700080; (void)a00700080; gdcm::Attribute<0x0070,0x0081> a00700081; (void)a00700081; gdcm::Attribute<0x0070,0x0082> a00700082; (void)a00700082; gdcm::Attribute<0x0070,0x0083> a00700083; (void)a00700083; gdcm::Attribute<0x0070,0x0084> a00700084; (void)a00700084; gdcm::Attribute<0x0070,0x0086> a00700086; (void)a00700086; gdcm::Attribute<0x0070,0x0100> a00700100; (void)a00700100; gdcm::Attribute<0x0070,0x0101> a00700101; (void)a00700101; gdcm::Attribute<0x0070,0x0102> a00700102; (void)a00700102; gdcm::Attribute<0x0070,0x0103> a00700103; (void)a00700103; gdcm::Attribute<0x0070,0x0306> a00700306; (void)a00700306; gdcm::Attribute<0x0070,0x0308> a00700308; (void)a00700308; gdcm::Attribute<0x0070,0x0309> a00700309; (void)a00700309; gdcm::Attribute<0x0070,0x030a> a0070030a; (void)a0070030a; gdcm::Attribute<0x0070,0x030c> a0070030c; (void)a0070030c; gdcm::Attribute<0x0070,0x030d> a0070030d; (void)a0070030d; gdcm::Attribute<0x0070,0x030f> a0070030f; (void)a0070030f; gdcm::Attribute<0x0070,0x0310> a00700310; (void)a00700310; gdcm::Attribute<0x0070,0x0311> a00700311; (void)a00700311; gdcm::Attribute<0x0070,0x0312> a00700312; (void)a00700312; gdcm::Attribute<0x0070,0x0314> a00700314; (void)a00700314; gdcm::Attribute<0x0070,0x0318> a00700318; (void)a00700318; gdcm::Attribute<0x0070,0x031a> a0070031a; (void)a0070031a; gdcm::Attribute<0x0070,0x031c> a0070031c; (void)a0070031c; gdcm::Attribute<0x0070,0x031e> a0070031e; (void)a0070031e; gdcm::Attribute<0x0070,0x0401> a00700401; (void)a00700401; gdcm::Attribute<0x0070,0x0402> a00700402; (void)a00700402; gdcm::Attribute<0x0070,0x0403> a00700403; (void)a00700403; gdcm::Attribute<0x0070,0x0404> a00700404; (void)a00700404; gdcm::Attribute<0x0070,0x0405> a00700405; (void)a00700405; gdcm::Attribute<0x0072,0x0002> a00720002; (void)a00720002; gdcm::Attribute<0x0072,0x0004> a00720004; (void)a00720004; gdcm::Attribute<0x0072,0x0006> a00720006; (void)a00720006; gdcm::Attribute<0x0072,0x0008> a00720008; (void)a00720008; gdcm::Attribute<0x0072,0x000a> a0072000a; (void)a0072000a; gdcm::Attribute<0x0072,0x000c> a0072000c; (void)a0072000c; gdcm::Attribute<0x0072,0x000e> a0072000e; (void)a0072000e; gdcm::Attribute<0x0072,0x0010> a00720010; (void)a00720010; gdcm::Attribute<0x0072,0x0012> a00720012; (void)a00720012; gdcm::Attribute<0x0072,0x0014> a00720014; (void)a00720014; gdcm::Attribute<0x0072,0x0020> a00720020; (void)a00720020; gdcm::Attribute<0x0072,0x0022> a00720022; (void)a00720022; gdcm::Attribute<0x0072,0x0024> a00720024; (void)a00720024; gdcm::Attribute<0x0072,0x0026> a00720026; (void)a00720026; gdcm::Attribute<0x0072,0x0028> a00720028; (void)a00720028; gdcm::Attribute<0x0072,0x0030> a00720030; (void)a00720030; gdcm::Attribute<0x0072,0x0032> a00720032; (void)a00720032; gdcm::Attribute<0x0072,0x0034> a00720034; (void)a00720034; gdcm::Attribute<0x0072,0x0038> a00720038; (void)a00720038; gdcm::Attribute<0x0072,0x003a> a0072003a; (void)a0072003a; gdcm::Attribute<0x0072,0x003c> a0072003c; (void)a0072003c; gdcm::Attribute<0x0072,0x003e> a0072003e; (void)a0072003e; gdcm::Attribute<0x0072,0x0040> a00720040; (void)a00720040; gdcm::Attribute<0x0072,0x0050> a00720050; (void)a00720050; gdcm::Attribute<0x0072,0x0052> a00720052; (void)a00720052; gdcm::Attribute<0x0072,0x0054> a00720054; (void)a00720054; gdcm::Attribute<0x0072,0x0056> a00720056; (void)a00720056; gdcm::Attribute<0x0072,0x0060> a00720060; (void)a00720060; gdcm::Attribute<0x0072,0x0062> a00720062; (void)a00720062; gdcm::Attribute<0x0072,0x0064> a00720064; (void)a00720064; gdcm::Attribute<0x0072,0x0066> a00720066; (void)a00720066; gdcm::Attribute<0x0072,0x0068> a00720068; (void)a00720068; gdcm::Attribute<0x0072,0x006a> a0072006a; (void)a0072006a; gdcm::Attribute<0x0072,0x006c> a0072006c; (void)a0072006c; gdcm::Attribute<0x0072,0x006e> a0072006e; (void)a0072006e; gdcm::Attribute<0x0072,0x0070> a00720070; (void)a00720070; gdcm::Attribute<0x0072,0x0072> a00720072; (void)a00720072; gdcm::Attribute<0x0072,0x0074> a00720074; (void)a00720074; gdcm::Attribute<0x0072,0x0076> a00720076; (void)a00720076; gdcm::Attribute<0x0072,0x0078> a00720078; (void)a00720078; gdcm::Attribute<0x0072,0x007a> a0072007a; (void)a0072007a; gdcm::Attribute<0x0072,0x007c> a0072007c; (void)a0072007c; gdcm::Attribute<0x0072,0x007e> a0072007e; (void)a0072007e; gdcm::Attribute<0x0072,0x0080> a00720080; (void)a00720080; gdcm::Attribute<0x0072,0x0100> a00720100; (void)a00720100; gdcm::Attribute<0x0072,0x0102> a00720102; (void)a00720102; gdcm::Attribute<0x0072,0x0104> a00720104; (void)a00720104; gdcm::Attribute<0x0072,0x0106> a00720106; (void)a00720106; gdcm::Attribute<0x0072,0x0108> a00720108; (void)a00720108; gdcm::Attribute<0x0072,0x010a> a0072010a; (void)a0072010a; gdcm::Attribute<0x0072,0x010c> a0072010c; (void)a0072010c; gdcm::Attribute<0x0072,0x010e> a0072010e; (void)a0072010e; gdcm::Attribute<0x0072,0x0200> a00720200; (void)a00720200; gdcm::Attribute<0x0072,0x0202> a00720202; (void)a00720202; gdcm::Attribute<0x0072,0x0203> a00720203; (void)a00720203; gdcm::Attribute<0x0072,0x0204> a00720204; (void)a00720204; gdcm::Attribute<0x0072,0x0206> a00720206; (void)a00720206; gdcm::Attribute<0x0072,0x0208> a00720208; (void)a00720208; gdcm::Attribute<0x0072,0x0210> a00720210; (void)a00720210; gdcm::Attribute<0x0072,0x0212> a00720212; (void)a00720212; gdcm::Attribute<0x0072,0x0214> a00720214; (void)a00720214; gdcm::Attribute<0x0072,0x0216> a00720216; (void)a00720216; gdcm::Attribute<0x0072,0x0218> a00720218; (void)a00720218; gdcm::Attribute<0x0072,0x0300> a00720300; (void)a00720300; gdcm::Attribute<0x0072,0x0302> a00720302; (void)a00720302; gdcm::Attribute<0x0072,0x0304> a00720304; (void)a00720304; gdcm::Attribute<0x0072,0x0306> a00720306; (void)a00720306; gdcm::Attribute<0x0072,0x0308> a00720308; (void)a00720308; gdcm::Attribute<0x0072,0x0310> a00720310; (void)a00720310; gdcm::Attribute<0x0072,0x0312> a00720312; (void)a00720312; gdcm::Attribute<0x0072,0x0314> a00720314; (void)a00720314; gdcm::Attribute<0x0072,0x0316> a00720316; (void)a00720316; gdcm::Attribute<0x0072,0x0318> a00720318; (void)a00720318; gdcm::Attribute<0x0072,0x0320> a00720320; (void)a00720320; gdcm::Attribute<0x0072,0x0330> a00720330; (void)a00720330; gdcm::Attribute<0x0072,0x0400> a00720400; (void)a00720400; gdcm::Attribute<0x0072,0x0402> a00720402; (void)a00720402; gdcm::Attribute<0x0072,0x0404> a00720404; (void)a00720404; gdcm::Attribute<0x0072,0x0406> a00720406; (void)a00720406; gdcm::Attribute<0x0072,0x0500> a00720500; (void)a00720500; gdcm::Attribute<0x0072,0x0510> a00720510; (void)a00720510; gdcm::Attribute<0x0072,0x0512> a00720512; (void)a00720512; gdcm::Attribute<0x0072,0x0514> a00720514; (void)a00720514; gdcm::Attribute<0x0072,0x0516> a00720516; (void)a00720516; gdcm::Attribute<0x0072,0x0520> a00720520; (void)a00720520; gdcm::Attribute<0x0072,0x0600> a00720600; (void)a00720600; gdcm::Attribute<0x0072,0x0602> a00720602; (void)a00720602; gdcm::Attribute<0x0072,0x0604> a00720604; (void)a00720604; gdcm::Attribute<0x0072,0x0700> a00720700; (void)a00720700; gdcm::Attribute<0x0072,0x0702> a00720702; (void)a00720702; gdcm::Attribute<0x0072,0x0704> a00720704; (void)a00720704; gdcm::Attribute<0x0072,0x0706> a00720706; (void)a00720706; gdcm::Attribute<0x0072,0x0710> a00720710; (void)a00720710; gdcm::Attribute<0x0072,0x0712> a00720712; (void)a00720712; gdcm::Attribute<0x0072,0x0714> a00720714; (void)a00720714; gdcm::Attribute<0x0072,0x0716> a00720716; (void)a00720716; gdcm::Attribute<0x0072,0x0717> a00720717; (void)a00720717; gdcm::Attribute<0x0072,0x0718> a00720718; (void)a00720718; gdcm::Attribute<0x0074,0x1000> a00741000; (void)a00741000; gdcm::Attribute<0x0074,0x1002> a00741002; (void)a00741002; gdcm::Attribute<0x0074,0x1004> a00741004; (void)a00741004; gdcm::Attribute<0x0074,0x1006> a00741006; (void)a00741006; gdcm::Attribute<0x0074,0x1008> a00741008; (void)a00741008; gdcm::Attribute<0x0074,0x100a> a0074100a; (void)a0074100a; gdcm::Attribute<0x0074,0x100c> a0074100c; (void)a0074100c; gdcm::Attribute<0x0074,0x100e> a0074100e; (void)a0074100e; gdcm::Attribute<0x0074,0x1020> a00741020; (void)a00741020; gdcm::Attribute<0x0074,0x1022> a00741022; (void)a00741022; gdcm::Attribute<0x0074,0x1024> a00741024; (void)a00741024; gdcm::Attribute<0x0074,0x1030> a00741030; (void)a00741030; gdcm::Attribute<0x0074,0x1032> a00741032; (void)a00741032; gdcm::Attribute<0x0074,0x1034> a00741034; (void)a00741034; gdcm::Attribute<0x0074,0x1036> a00741036; (void)a00741036; gdcm::Attribute<0x0074,0x1038> a00741038; (void)a00741038; gdcm::Attribute<0x0074,0x103a> a0074103a; (void)a0074103a; gdcm::Attribute<0x0074,0x1040> a00741040; (void)a00741040; gdcm::Attribute<0x0074,0x1042> a00741042; (void)a00741042; gdcm::Attribute<0x0074,0x1044> a00741044; (void)a00741044; gdcm::Attribute<0x0074,0x1046> a00741046; (void)a00741046; gdcm::Attribute<0x0074,0x1048> a00741048; (void)a00741048; gdcm::Attribute<0x0074,0x104a> a0074104a; (void)a0074104a; gdcm::Attribute<0x0074,0x104c> a0074104c; (void)a0074104c; gdcm::Attribute<0x0074,0x104e> a0074104e; (void)a0074104e; gdcm::Attribute<0x0074,0x1050> a00741050; (void)a00741050; gdcm::Attribute<0x0074,0x1052> a00741052; (void)a00741052; gdcm::Attribute<0x0074,0x1054> a00741054; (void)a00741054; gdcm::Attribute<0x0074,0x1056> a00741056; (void)a00741056; gdcm::Attribute<0x0074,0x1200> a00741200; (void)a00741200; gdcm::Attribute<0x0074,0x1202> a00741202; (void)a00741202; gdcm::Attribute<0x0074,0x1204> a00741204; (void)a00741204; gdcm::Attribute<0x0074,0x1210> a00741210; (void)a00741210; gdcm::Attribute<0x0074,0x1212> a00741212; (void)a00741212; gdcm::Attribute<0x0074,0x1216> a00741216; (void)a00741216; gdcm::Attribute<0x0074,0x1220> a00741220; (void)a00741220; gdcm::Attribute<0x0074,0x1222> a00741222; (void)a00741222; gdcm::Attribute<0x0074,0x1230> a00741230; (void)a00741230; gdcm::Attribute<0x0074,0x1234> a00741234; (void)a00741234; gdcm::Attribute<0x0074,0x1236> a00741236; (void)a00741236; gdcm::Attribute<0x0074,0x1238> a00741238; (void)a00741238; gdcm::Attribute<0x0074,0x1242> a00741242; (void)a00741242; gdcm::Attribute<0x0074,0x1244> a00741244; (void)a00741244; gdcm::Attribute<0x0074,0x1246> a00741246; (void)a00741246; gdcm::Attribute<0x0088,0x0130> a00880130; (void)a00880130; gdcm::Attribute<0x0088,0x0140> a00880140; (void)a00880140; gdcm::Attribute<0x0088,0x0200> a00880200; (void)a00880200; gdcm::Attribute<0x0088,0x0904> a00880904; (void)a00880904; gdcm::Attribute<0x0088,0x0906> a00880906; (void)a00880906; gdcm::Attribute<0x0088,0x0910> a00880910; (void)a00880910; gdcm::Attribute<0x0100,0x0410> a01000410; (void)a01000410; gdcm::Attribute<0x0100,0x0420> a01000420; (void)a01000420; gdcm::Attribute<0x0100,0x0424> a01000424; (void)a01000424; gdcm::Attribute<0x0100,0x0426> a01000426; (void)a01000426; gdcm::Attribute<0x0400,0x0005> a04000005; (void)a04000005; gdcm::Attribute<0x0400,0x0010> a04000010; (void)a04000010; gdcm::Attribute<0x0400,0x0015> a04000015; (void)a04000015; gdcm::Attribute<0x0400,0x0020> a04000020; (void)a04000020; gdcm::Attribute<0x0400,0x0100> a04000100; (void)a04000100; gdcm::Attribute<0x0400,0x0105> a04000105; (void)a04000105; gdcm::Attribute<0x0400,0x0110> a04000110; (void)a04000110; gdcm::Attribute<0x0400,0x0115> a04000115; (void)a04000115; gdcm::Attribute<0x0400,0x0120> a04000120; (void)a04000120; gdcm::Attribute<0x0400,0x0305> a04000305; (void)a04000305; gdcm::Attribute<0x0400,0x0310> a04000310; (void)a04000310; gdcm::Attribute<0x0400,0x0401> a04000401; (void)a04000401; gdcm::Attribute<0x0400,0x0402> a04000402; (void)a04000402; gdcm::Attribute<0x0400,0x0403> a04000403; (void)a04000403; gdcm::Attribute<0x0400,0x0404> a04000404; (void)a04000404; gdcm::Attribute<0x0400,0x0500> a04000500; (void)a04000500; gdcm::Attribute<0x0400,0x0510> a04000510; (void)a04000510; gdcm::Attribute<0x0400,0x0520> a04000520; (void)a04000520; gdcm::Attribute<0x0400,0x0550> a04000550; (void)a04000550; gdcm::Attribute<0x0400,0x0561> a04000561; (void)a04000561; gdcm::Attribute<0x0400,0x0562> a04000562; (void)a04000562; gdcm::Attribute<0x0400,0x0563> a04000563; (void)a04000563; gdcm::Attribute<0x0400,0x0564> a04000564; (void)a04000564; gdcm::Attribute<0x0400,0x0565> a04000565; (void)a04000565; gdcm::Attribute<0x2000,0x0010> a20000010; (void)a20000010; gdcm::Attribute<0x2000,0x001e> a2000001e; (void)a2000001e; gdcm::Attribute<0x2000,0x0020> a20000020; (void)a20000020; gdcm::Attribute<0x2000,0x0030> a20000030; (void)a20000030; gdcm::Attribute<0x2000,0x0040> a20000040; (void)a20000040; gdcm::Attribute<0x2000,0x0050> a20000050; (void)a20000050; gdcm::Attribute<0x2000,0x0060> a20000060; (void)a20000060; gdcm::Attribute<0x2000,0x0061> a20000061; (void)a20000061; gdcm::Attribute<0x2000,0x0062> a20000062; (void)a20000062; gdcm::Attribute<0x2000,0x0063> a20000063; (void)a20000063; gdcm::Attribute<0x2000,0x0065> a20000065; (void)a20000065; gdcm::Attribute<0x2000,0x0067> a20000067; (void)a20000067; gdcm::Attribute<0x2000,0x0069> a20000069; (void)a20000069; gdcm::Attribute<0x2000,0x006a> a2000006a; (void)a2000006a; gdcm::Attribute<0x2000,0x00a0> a200000a0; (void)a200000a0; gdcm::Attribute<0x2000,0x00a1> a200000a1; (void)a200000a1; gdcm::Attribute<0x2000,0x00a2> a200000a2; (void)a200000a2; gdcm::Attribute<0x2000,0x00a4> a200000a4; (void)a200000a4; gdcm::Attribute<0x2000,0x00a8> a200000a8; (void)a200000a8; gdcm::Attribute<0x2000,0x0500> a20000500; (void)a20000500; gdcm::Attribute<0x2000,0x0510> a20000510; (void)a20000510; gdcm::Attribute<0x2010,0x0010> a20100010; (void)a20100010; gdcm::Attribute<0x2010,0x0030> a20100030; (void)a20100030; gdcm::Attribute<0x2010,0x0040> a20100040; (void)a20100040; gdcm::Attribute<0x2010,0x0050> a20100050; (void)a20100050; gdcm::Attribute<0x2010,0x0052> a20100052; (void)a20100052; gdcm::Attribute<0x2010,0x0054> a20100054; (void)a20100054; gdcm::Attribute<0x2010,0x0060> a20100060; (void)a20100060; gdcm::Attribute<0x2010,0x0080> a20100080; (void)a20100080; gdcm::Attribute<0x2010,0x00a6> a201000a6; (void)a201000a6; gdcm::Attribute<0x2010,0x00a7> a201000a7; (void)a201000a7; gdcm::Attribute<0x2010,0x00a8> a201000a8; (void)a201000a8; gdcm::Attribute<0x2010,0x00a9> a201000a9; (void)a201000a9; gdcm::Attribute<0x2010,0x0100> a20100100; (void)a20100100; gdcm::Attribute<0x2010,0x0110> a20100110; (void)a20100110; gdcm::Attribute<0x2010,0x0120> a20100120; (void)a20100120; gdcm::Attribute<0x2010,0x0130> a20100130; (void)a20100130; gdcm::Attribute<0x2010,0x0140> a20100140; (void)a20100140; gdcm::Attribute<0x2010,0x0150> a20100150; (void)a20100150; gdcm::Attribute<0x2010,0x0152> a20100152; (void)a20100152; gdcm::Attribute<0x2010,0x0154> a20100154; (void)a20100154; gdcm::Attribute<0x2010,0x015e> a2010015e; (void)a2010015e; gdcm::Attribute<0x2010,0x0160> a20100160; (void)a20100160; gdcm::Attribute<0x2010,0x0376> a20100376; (void)a20100376; gdcm::Attribute<0x2010,0x0500> a20100500; (void)a20100500; gdcm::Attribute<0x2010,0x0510> a20100510; (void)a20100510; gdcm::Attribute<0x2010,0x0520> a20100520; (void)a20100520; gdcm::Attribute<0x2020,0x0010> a20200010; (void)a20200010; gdcm::Attribute<0x2020,0x0020> a20200020; (void)a20200020; gdcm::Attribute<0x2020,0x0030> a20200030; (void)a20200030; gdcm::Attribute<0x2020,0x0040> a20200040; (void)a20200040; gdcm::Attribute<0x2020,0x0050> a20200050; (void)a20200050; gdcm::Attribute<0x2020,0x00a0> a202000a0; (void)a202000a0; gdcm::Attribute<0x2020,0x00a2> a202000a2; (void)a202000a2; gdcm::Attribute<0x2020,0x0110> a20200110; (void)a20200110; gdcm::Attribute<0x2020,0x0111> a20200111; (void)a20200111; gdcm::Attribute<0x2020,0x0130> a20200130; (void)a20200130; gdcm::Attribute<0x2020,0x0140> a20200140; (void)a20200140; gdcm::Attribute<0x2030,0x0010> a20300010; (void)a20300010; gdcm::Attribute<0x2030,0x0020> a20300020; (void)a20300020; gdcm::Attribute<0x2040,0x0010> a20400010; (void)a20400010; gdcm::Attribute<0x2040,0x0020> a20400020; (void)a20400020; gdcm::Attribute<0x2040,0x0060> a20400060; (void)a20400060; gdcm::Attribute<0x2040,0x0070> a20400070; (void)a20400070; gdcm::Attribute<0x2040,0x0072> a20400072; (void)a20400072; gdcm::Attribute<0x2040,0x0074> a20400074; (void)a20400074; gdcm::Attribute<0x2040,0x0080> a20400080; (void)a20400080; gdcm::Attribute<0x2040,0x0082> a20400082; (void)a20400082; gdcm::Attribute<0x2040,0x0090> a20400090; (void)a20400090; gdcm::Attribute<0x2040,0x0100> a20400100; (void)a20400100; gdcm::Attribute<0x2040,0x0500> a20400500; (void)a20400500; gdcm::Attribute<0x2050,0x0010> a20500010; (void)a20500010; gdcm::Attribute<0x2050,0x0020> a20500020; (void)a20500020; gdcm::Attribute<0x2050,0x0500> a20500500; (void)a20500500; gdcm::Attribute<0x2100,0x0010> a21000010; (void)a21000010; gdcm::Attribute<0x2100,0x0020> a21000020; (void)a21000020; gdcm::Attribute<0x2100,0x0030> a21000030; (void)a21000030; gdcm::Attribute<0x2100,0x0040> a21000040; (void)a21000040; gdcm::Attribute<0x2100,0x0050> a21000050; (void)a21000050; gdcm::Attribute<0x2100,0x0070> a21000070; (void)a21000070; gdcm::Attribute<0x2100,0x0140> a21000140; (void)a21000140; gdcm::Attribute<0x2100,0x0160> a21000160; (void)a21000160; gdcm::Attribute<0x2100,0x0170> a21000170; (void)a21000170; gdcm::Attribute<0x2100,0x0500> a21000500; (void)a21000500; gdcm::Attribute<0x2110,0x0010> a21100010; (void)a21100010; gdcm::Attribute<0x2110,0x0020> a21100020; (void)a21100020; gdcm::Attribute<0x2110,0x0030> a21100030; (void)a21100030; gdcm::Attribute<0x2110,0x0099> a21100099; (void)a21100099; gdcm::Attribute<0x2120,0x0010> a21200010; (void)a21200010; gdcm::Attribute<0x2120,0x0050> a21200050; (void)a21200050; gdcm::Attribute<0x2120,0x0070> a21200070; (void)a21200070; gdcm::Attribute<0x2130,0x0010> a21300010; (void)a21300010; gdcm::Attribute<0x2130,0x0015> a21300015; (void)a21300015; gdcm::Attribute<0x2130,0x0030> a21300030; (void)a21300030; gdcm::Attribute<0x2130,0x0040> a21300040; (void)a21300040; gdcm::Attribute<0x2130,0x0050> a21300050; (void)a21300050; gdcm::Attribute<0x2130,0x0060> a21300060; (void)a21300060; gdcm::Attribute<0x2130,0x0080> a21300080; (void)a21300080; gdcm::Attribute<0x2130,0x00a0> a213000a0; (void)a213000a0; gdcm::Attribute<0x2130,0x00c0> a213000c0; (void)a213000c0; gdcm::Attribute<0x2200,0x0001> a22000001; (void)a22000001; gdcm::Attribute<0x2200,0x0002> a22000002; (void)a22000002; gdcm::Attribute<0x2200,0x0003> a22000003; (void)a22000003; gdcm::Attribute<0x2200,0x0004> a22000004; (void)a22000004; gdcm::Attribute<0x2200,0x0005> a22000005; (void)a22000005; gdcm::Attribute<0x2200,0x0006> a22000006; (void)a22000006; gdcm::Attribute<0x2200,0x0007> a22000007; (void)a22000007; gdcm::Attribute<0x2200,0x0008> a22000008; (void)a22000008; gdcm::Attribute<0x2200,0x0009> a22000009; (void)a22000009; gdcm::Attribute<0x2200,0x000a> a2200000a; (void)a2200000a; gdcm::Attribute<0x2200,0x000b> a2200000b; (void)a2200000b; gdcm::Attribute<0x2200,0x000c> a2200000c; (void)a2200000c; gdcm::Attribute<0x2200,0x000d> a2200000d; (void)a2200000d; gdcm::Attribute<0x2200,0x000e> a2200000e; (void)a2200000e; gdcm::Attribute<0x2200,0x000f> a2200000f; (void)a2200000f; gdcm::Attribute<0x2200,0x0020> a22000020; (void)a22000020; gdcm::Attribute<0x3002,0x0002> a30020002; (void)a30020002; gdcm::Attribute<0x3002,0x0003> a30020003; (void)a30020003; gdcm::Attribute<0x3002,0x0004> a30020004; (void)a30020004; gdcm::Attribute<0x3002,0x000a> a3002000a; (void)a3002000a; gdcm::Attribute<0x3002,0x000c> a3002000c; (void)a3002000c; gdcm::Attribute<0x3002,0x000d> a3002000d; (void)a3002000d; gdcm::Attribute<0x3002,0x000e> a3002000e; (void)a3002000e; gdcm::Attribute<0x3002,0x0010> a30020010; (void)a30020010; gdcm::Attribute<0x3002,0x0011> a30020011; (void)a30020011; gdcm::Attribute<0x3002,0x0012> a30020012; (void)a30020012; gdcm::Attribute<0x3002,0x0020> a30020020; (void)a30020020; gdcm::Attribute<0x3002,0x0022> a30020022; (void)a30020022; gdcm::Attribute<0x3002,0x0024> a30020024; (void)a30020024; gdcm::Attribute<0x3002,0x0026> a30020026; (void)a30020026; gdcm::Attribute<0x3002,0x0028> a30020028; (void)a30020028; gdcm::Attribute<0x3002,0x0029> a30020029; (void)a30020029; gdcm::Attribute<0x3002,0x0030> a30020030; (void)a30020030; gdcm::Attribute<0x3002,0x0032> a30020032; (void)a30020032; gdcm::Attribute<0x3002,0x0034> a30020034; (void)a30020034; gdcm::Attribute<0x3002,0x0040> a30020040; (void)a30020040; gdcm::Attribute<0x3002,0x0041> a30020041; (void)a30020041; gdcm::Attribute<0x3002,0x0042> a30020042; (void)a30020042; gdcm::Attribute<0x3004,0x0001> a30040001; (void)a30040001; gdcm::Attribute<0x3004,0x0002> a30040002; (void)a30040002; gdcm::Attribute<0x3004,0x0004> a30040004; (void)a30040004; gdcm::Attribute<0x3004,0x0006> a30040006; (void)a30040006; gdcm::Attribute<0x3004,0x0008> a30040008; (void)a30040008; gdcm::Attribute<0x3004,0x000a> a3004000a; (void)a3004000a; gdcm::Attribute<0x3004,0x000c> a3004000c; (void)a3004000c; gdcm::Attribute<0x3004,0x000e> a3004000e; (void)a3004000e; gdcm::Attribute<0x3004,0x0010> a30040010; (void)a30040010; gdcm::Attribute<0x3004,0x0012> a30040012; (void)a30040012; gdcm::Attribute<0x3004,0x0040> a30040040; (void)a30040040; gdcm::Attribute<0x3004,0x0042> a30040042; (void)a30040042; gdcm::Attribute<0x3004,0x0050> a30040050; (void)a30040050; gdcm::Attribute<0x3004,0x0052> a30040052; (void)a30040052; gdcm::Attribute<0x3004,0x0054> a30040054; (void)a30040054; gdcm::Attribute<0x3004,0x0056> a30040056; (void)a30040056; gdcm::Attribute<0x3004,0x0058> a30040058; (void)a30040058; gdcm::Attribute<0x3004,0x0060> a30040060; (void)a30040060; gdcm::Attribute<0x3004,0x0062> a30040062; (void)a30040062; gdcm::Attribute<0x3004,0x0070> a30040070; (void)a30040070; gdcm::Attribute<0x3004,0x0072> a30040072; (void)a30040072; gdcm::Attribute<0x3004,0x0074> a30040074; (void)a30040074; gdcm::Attribute<0x3006,0x0002> a30060002; (void)a30060002; gdcm::Attribute<0x3006,0x0004> a30060004; (void)a30060004; gdcm::Attribute<0x3006,0x0006> a30060006; (void)a30060006; gdcm::Attribute<0x3006,0x0008> a30060008; (void)a30060008; gdcm::Attribute<0x3006,0x0009> a30060009; (void)a30060009; gdcm::Attribute<0x3006,0x0010> a30060010; (void)a30060010; gdcm::Attribute<0x3006,0x0012> a30060012; (void)a30060012; gdcm::Attribute<0x3006,0x0014> a30060014; (void)a30060014; gdcm::Attribute<0x3006,0x0016> a30060016; (void)a30060016; gdcm::Attribute<0x3006,0x0020> a30060020; (void)a30060020; gdcm::Attribute<0x3006,0x0022> a30060022; (void)a30060022; gdcm::Attribute<0x3006,0x0024> a30060024; (void)a30060024; gdcm::Attribute<0x3006,0x0026> a30060026; (void)a30060026; gdcm::Attribute<0x3006,0x0028> a30060028; (void)a30060028; gdcm::Attribute<0x3006,0x002a> a3006002a; (void)a3006002a; gdcm::Attribute<0x3006,0x002c> a3006002c; (void)a3006002c; gdcm::Attribute<0x3006,0x0030> a30060030; (void)a30060030; gdcm::Attribute<0x3006,0x0033> a30060033; (void)a30060033; gdcm::Attribute<0x3006,0x0036> a30060036; (void)a30060036; gdcm::Attribute<0x3006,0x0038> a30060038; (void)a30060038; gdcm::Attribute<0x3006,0x0039> a30060039; (void)a30060039; gdcm::Attribute<0x3006,0x0040> a30060040; (void)a30060040; gdcm::Attribute<0x3006,0x0042> a30060042; (void)a30060042; gdcm::Attribute<0x3006,0x0044> a30060044; (void)a30060044; gdcm::Attribute<0x3006,0x0045> a30060045; (void)a30060045; gdcm::Attribute<0x3006,0x0046> a30060046; (void)a30060046; gdcm::Attribute<0x3006,0x0048> a30060048; (void)a30060048; gdcm::Attribute<0x3006,0x0049> a30060049; (void)a30060049; gdcm::Attribute<0x3006,0x0050> a30060050; (void)a30060050; gdcm::Attribute<0x3006,0x0080> a30060080; (void)a30060080; gdcm::Attribute<0x3006,0x0082> a30060082; (void)a30060082; gdcm::Attribute<0x3006,0x0084> a30060084; (void)a30060084; gdcm::Attribute<0x3006,0x0085> a30060085; (void)a30060085; gdcm::Attribute<0x3006,0x0086> a30060086; (void)a30060086; gdcm::Attribute<0x3006,0x0088> a30060088; (void)a30060088; gdcm::Attribute<0x3006,0x00a0> a300600a0; (void)a300600a0; gdcm::Attribute<0x3006,0x00a4> a300600a4; (void)a300600a4; gdcm::Attribute<0x3006,0x00a6> a300600a6; (void)a300600a6; gdcm::Attribute<0x3006,0x00b0> a300600b0; (void)a300600b0; gdcm::Attribute<0x3006,0x00b2> a300600b2; (void)a300600b2; gdcm::Attribute<0x3006,0x00b4> a300600b4; (void)a300600b4; gdcm::Attribute<0x3006,0x00b6> a300600b6; (void)a300600b6; gdcm::Attribute<0x3006,0x00b7> a300600b7; (void)a300600b7; gdcm::Attribute<0x3006,0x00b8> a300600b8; (void)a300600b8; gdcm::Attribute<0x3006,0x00c0> a300600c0; (void)a300600c0; gdcm::Attribute<0x3006,0x00c2> a300600c2; (void)a300600c2; gdcm::Attribute<0x3006,0x00c4> a300600c4; (void)a300600c4; gdcm::Attribute<0x3006,0x00c6> a300600c6; (void)a300600c6; gdcm::Attribute<0x3006,0x00c8> a300600c8; (void)a300600c8; gdcm::Attribute<0x3008,0x0010> a30080010; (void)a30080010; gdcm::Attribute<0x3008,0x0012> a30080012; (void)a30080012; gdcm::Attribute<0x3008,0x0014> a30080014; (void)a30080014; gdcm::Attribute<0x3008,0x0016> a30080016; (void)a30080016; gdcm::Attribute<0x3008,0x0020> a30080020; (void)a30080020; gdcm::Attribute<0x3008,0x0021> a30080021; (void)a30080021; gdcm::Attribute<0x3008,0x0022> a30080022; (void)a30080022; gdcm::Attribute<0x3008,0x0024> a30080024; (void)a30080024; gdcm::Attribute<0x3008,0x0025> a30080025; (void)a30080025; gdcm::Attribute<0x3008,0x002a> a3008002a; (void)a3008002a; gdcm::Attribute<0x3008,0x002b> a3008002b; (void)a3008002b; gdcm::Attribute<0x3008,0x002c> a3008002c; (void)a3008002c; gdcm::Attribute<0x3008,0x0030> a30080030; (void)a30080030; gdcm::Attribute<0x3008,0x0032> a30080032; (void)a30080032; gdcm::Attribute<0x3008,0x0033> a30080033; (void)a30080033; gdcm::Attribute<0x3008,0x0036> a30080036; (void)a30080036; gdcm::Attribute<0x3008,0x0037> a30080037; (void)a30080037; gdcm::Attribute<0x3008,0x003a> a3008003a; (void)a3008003a; gdcm::Attribute<0x3008,0x003b> a3008003b; (void)a3008003b; gdcm::Attribute<0x3008,0x0040> a30080040; (void)a30080040; gdcm::Attribute<0x3008,0x0041> a30080041; (void)a30080041; gdcm::Attribute<0x3008,0x0042> a30080042; (void)a30080042; gdcm::Attribute<0x3008,0x0044> a30080044; (void)a30080044; gdcm::Attribute<0x3008,0x0045> a30080045; (void)a30080045; gdcm::Attribute<0x3008,0x0046> a30080046; (void)a30080046; gdcm::Attribute<0x3008,0x0047> a30080047; (void)a30080047; gdcm::Attribute<0x3008,0x0048> a30080048; (void)a30080048; gdcm::Attribute<0x3008,0x0050> a30080050; (void)a30080050; gdcm::Attribute<0x3008,0x0052> a30080052; (void)a30080052; gdcm::Attribute<0x3008,0x0054> a30080054; (void)a30080054; gdcm::Attribute<0x3008,0x0056> a30080056; (void)a30080056; gdcm::Attribute<0x3008,0x005a> a3008005a; (void)a3008005a; gdcm::Attribute<0x3008,0x0060> a30080060; (void)a30080060; gdcm::Attribute<0x3008,0x0061> a30080061; (void)a30080061; gdcm::Attribute<0x3008,0x0062> a30080062; (void)a30080062; gdcm::Attribute<0x3008,0x0063> a30080063; (void)a30080063; gdcm::Attribute<0x3008,0x0064> a30080064; (void)a30080064; gdcm::Attribute<0x3008,0x0065> a30080065; (void)a30080065; gdcm::Attribute<0x3008,0x0066> a30080066; (void)a30080066; gdcm::Attribute<0x3008,0x0068> a30080068; (void)a30080068; gdcm::Attribute<0x3008,0x006a> a3008006a; (void)a3008006a; gdcm::Attribute<0x3008,0x0070> a30080070; (void)a30080070; gdcm::Attribute<0x3008,0x0072> a30080072; (void)a30080072; gdcm::Attribute<0x3008,0x0074> a30080074; (void)a30080074; gdcm::Attribute<0x3008,0x0076> a30080076; (void)a30080076; gdcm::Attribute<0x3008,0x0078> a30080078; (void)a30080078; gdcm::Attribute<0x3008,0x007a> a3008007a; (void)a3008007a; gdcm::Attribute<0x3008,0x0080> a30080080; (void)a30080080; gdcm::Attribute<0x3008,0x0082> a30080082; (void)a30080082; gdcm::Attribute<0x3008,0x0090> a30080090; (void)a30080090; gdcm::Attribute<0x3008,0x0092> a30080092; (void)a30080092; gdcm::Attribute<0x3008,0x00a0> a300800a0; (void)a300800a0; gdcm::Attribute<0x3008,0x00b0> a300800b0; (void)a300800b0; gdcm::Attribute<0x3008,0x00c0> a300800c0; (void)a300800c0; gdcm::Attribute<0x3008,0x00d0> a300800d0; (void)a300800d0; gdcm::Attribute<0x3008,0x00e0> a300800e0; (void)a300800e0; gdcm::Attribute<0x3008,0x00f0> a300800f0; (void)a300800f0; gdcm::Attribute<0x3008,0x00f2> a300800f2; (void)a300800f2; gdcm::Attribute<0x3008,0x00f4> a300800f4; (void)a300800f4; gdcm::Attribute<0x3008,0x00f6> a300800f6; (void)a300800f6; gdcm::Attribute<0x3008,0x0100> a30080100; (void)a30080100; gdcm::Attribute<0x3008,0x0105> a30080105; (void)a30080105; gdcm::Attribute<0x3008,0x0110> a30080110; (void)a30080110; gdcm::Attribute<0x3008,0x0116> a30080116; (void)a30080116; gdcm::Attribute<0x3008,0x0120> a30080120; (void)a30080120; gdcm::Attribute<0x3008,0x0122> a30080122; (void)a30080122; gdcm::Attribute<0x3008,0x0130> a30080130; (void)a30080130; gdcm::Attribute<0x3008,0x0132> a30080132; (void)a30080132; gdcm::Attribute<0x3008,0x0134> a30080134; (void)a30080134; gdcm::Attribute<0x3008,0x0136> a30080136; (void)a30080136; gdcm::Attribute<0x3008,0x0138> a30080138; (void)a30080138; gdcm::Attribute<0x3008,0x013a> a3008013a; (void)a3008013a; gdcm::Attribute<0x3008,0x013c> a3008013c; (void)a3008013c; gdcm::Attribute<0x3008,0x0140> a30080140; (void)a30080140; gdcm::Attribute<0x3008,0x0142> a30080142; (void)a30080142; gdcm::Attribute<0x3008,0x0150> a30080150; (void)a30080150; gdcm::Attribute<0x3008,0x0152> a30080152; (void)a30080152; gdcm::Attribute<0x3008,0x0160> a30080160; (void)a30080160; gdcm::Attribute<0x3008,0x0162> a30080162; (void)a30080162; gdcm::Attribute<0x3008,0x0164> a30080164; (void)a30080164; gdcm::Attribute<0x3008,0x0166> a30080166; (void)a30080166; gdcm::Attribute<0x3008,0x0168> a30080168; (void)a30080168; gdcm::Attribute<0x3008,0x0200> a30080200; (void)a30080200; gdcm::Attribute<0x3008,0x0202> a30080202; (void)a30080202; gdcm::Attribute<0x3008,0x0220> a30080220; (void)a30080220; gdcm::Attribute<0x3008,0x0223> a30080223; (void)a30080223; gdcm::Attribute<0x3008,0x0224> a30080224; (void)a30080224; gdcm::Attribute<0x3008,0x0230> a30080230; (void)a30080230; gdcm::Attribute<0x3008,0x0240> a30080240; (void)a30080240; gdcm::Attribute<0x3008,0x0250> a30080250; (void)a30080250; gdcm::Attribute<0x3008,0x0251> a30080251; (void)a30080251; gdcm::Attribute<0x300a,0x0002> a300a0002; (void)a300a0002; gdcm::Attribute<0x300a,0x0003> a300a0003; (void)a300a0003; gdcm::Attribute<0x300a,0x0004> a300a0004; (void)a300a0004; gdcm::Attribute<0x300a,0x0006> a300a0006; (void)a300a0006; gdcm::Attribute<0x300a,0x0007> a300a0007; (void)a300a0007; gdcm::Attribute<0x300a,0x0009> a300a0009; (void)a300a0009; gdcm::Attribute<0x300a,0x000a> a300a000a; (void)a300a000a; gdcm::Attribute<0x300a,0x000b> a300a000b; (void)a300a000b; gdcm::Attribute<0x300a,0x000c> a300a000c; (void)a300a000c; gdcm::Attribute<0x300a,0x000e> a300a000e; (void)a300a000e; gdcm::Attribute<0x300a,0x0010> a300a0010; (void)a300a0010; gdcm::Attribute<0x300a,0x0012> a300a0012; (void)a300a0012; gdcm::Attribute<0x300a,0x0013> a300a0013; (void)a300a0013; gdcm::Attribute<0x300a,0x0014> a300a0014; (void)a300a0014; gdcm::Attribute<0x300a,0x0015> a300a0015; (void)a300a0015; gdcm::Attribute<0x300a,0x0016> a300a0016; (void)a300a0016; gdcm::Attribute<0x300a,0x0018> a300a0018; (void)a300a0018; gdcm::Attribute<0x300a,0x001a> a300a001a; (void)a300a001a; gdcm::Attribute<0x300a,0x0020> a300a0020; (void)a300a0020; gdcm::Attribute<0x300a,0x0021> a300a0021; (void)a300a0021; gdcm::Attribute<0x300a,0x0022> a300a0022; (void)a300a0022; gdcm::Attribute<0x300a,0x0023> a300a0023; (void)a300a0023; gdcm::Attribute<0x300a,0x0025> a300a0025; (void)a300a0025; gdcm::Attribute<0x300a,0x0026> a300a0026; (void)a300a0026; gdcm::Attribute<0x300a,0x0027> a300a0027; (void)a300a0027; gdcm::Attribute<0x300a,0x0028> a300a0028; (void)a300a0028; gdcm::Attribute<0x300a,0x002a> a300a002a; (void)a300a002a; gdcm::Attribute<0x300a,0x002b> a300a002b; (void)a300a002b; gdcm::Attribute<0x300a,0x002c> a300a002c; (void)a300a002c; gdcm::Attribute<0x300a,0x002d> a300a002d; (void)a300a002d; gdcm::Attribute<0x300a,0x0040> a300a0040; (void)a300a0040; gdcm::Attribute<0x300a,0x0042> a300a0042; (void)a300a0042; gdcm::Attribute<0x300a,0x0043> a300a0043; (void)a300a0043; gdcm::Attribute<0x300a,0x0044> a300a0044; (void)a300a0044; gdcm::Attribute<0x300a,0x0046> a300a0046; (void)a300a0046; gdcm::Attribute<0x300a,0x0048> a300a0048; (void)a300a0048; gdcm::Attribute<0x300a,0x004a> a300a004a; (void)a300a004a; gdcm::Attribute<0x300a,0x004b> a300a004b; (void)a300a004b; gdcm::Attribute<0x300a,0x004c> a300a004c; (void)a300a004c; gdcm::Attribute<0x300a,0x004e> a300a004e; (void)a300a004e; gdcm::Attribute<0x300a,0x004f> a300a004f; (void)a300a004f; gdcm::Attribute<0x300a,0x0050> a300a0050; (void)a300a0050; gdcm::Attribute<0x300a,0x0051> a300a0051; (void)a300a0051; gdcm::Attribute<0x300a,0x0052> a300a0052; (void)a300a0052; gdcm::Attribute<0x300a,0x0053> a300a0053; (void)a300a0053; gdcm::Attribute<0x300a,0x0055> a300a0055; (void)a300a0055; gdcm::Attribute<0x300a,0x0070> a300a0070; (void)a300a0070; gdcm::Attribute<0x300a,0x0071> a300a0071; (void)a300a0071; gdcm::Attribute<0x300a,0x0072> a300a0072; (void)a300a0072; gdcm::Attribute<0x300a,0x0078> a300a0078; (void)a300a0078; gdcm::Attribute<0x300a,0x0079> a300a0079; (void)a300a0079; gdcm::Attribute<0x300a,0x007a> a300a007a; (void)a300a007a; gdcm::Attribute<0x300a,0x007b> a300a007b; (void)a300a007b; gdcm::Attribute<0x300a,0x0080> a300a0080; (void)a300a0080; gdcm::Attribute<0x300a,0x0082> a300a0082; (void)a300a0082; gdcm::Attribute<0x300a,0x0084> a300a0084; (void)a300a0084; gdcm::Attribute<0x300a,0x0086> a300a0086; (void)a300a0086; gdcm::Attribute<0x300a,0x0088> a300a0088; (void)a300a0088; gdcm::Attribute<0x300a,0x0089> a300a0089; (void)a300a0089; gdcm::Attribute<0x300a,0x008a> a300a008a; (void)a300a008a; gdcm::Attribute<0x300a,0x00a0> a300a00a0; (void)a300a00a0; gdcm::Attribute<0x300a,0x00a2> a300a00a2; (void)a300a00a2; gdcm::Attribute<0x300a,0x00a4> a300a00a4; (void)a300a00a4; gdcm::Attribute<0x300a,0x00b0> a300a00b0; (void)a300a00b0; gdcm::Attribute<0x300a,0x00b2> a300a00b2; (void)a300a00b2; gdcm::Attribute<0x300a,0x00b3> a300a00b3; (void)a300a00b3; gdcm::Attribute<0x300a,0x00b4> a300a00b4; (void)a300a00b4; gdcm::Attribute<0x300a,0x00b6> a300a00b6; (void)a300a00b6; gdcm::Attribute<0x300a,0x00b8> a300a00b8; (void)a300a00b8; gdcm::Attribute<0x300a,0x00ba> a300a00ba; (void)a300a00ba; gdcm::Attribute<0x300a,0x00bb> a300a00bb; (void)a300a00bb; gdcm::Attribute<0x300a,0x00bc> a300a00bc; (void)a300a00bc; gdcm::Attribute<0x300a,0x00be> a300a00be; (void)a300a00be; gdcm::Attribute<0x300a,0x00c0> a300a00c0; (void)a300a00c0; gdcm::Attribute<0x300a,0x00c2> a300a00c2; (void)a300a00c2; gdcm::Attribute<0x300a,0x00c3> a300a00c3; (void)a300a00c3; gdcm::Attribute<0x300a,0x00c4> a300a00c4; (void)a300a00c4; gdcm::Attribute<0x300a,0x00c6> a300a00c6; (void)a300a00c6; gdcm::Attribute<0x300a,0x00c7> a300a00c7; (void)a300a00c7; gdcm::Attribute<0x300a,0x00c8> a300a00c8; (void)a300a00c8; gdcm::Attribute<0x300a,0x00ca> a300a00ca; (void)a300a00ca; gdcm::Attribute<0x300a,0x00cc> a300a00cc; (void)a300a00cc; gdcm::Attribute<0x300a,0x00ce> a300a00ce; (void)a300a00ce; gdcm::Attribute<0x300a,0x00d0> a300a00d0; (void)a300a00d0; gdcm::Attribute<0x300a,0x00d1> a300a00d1; (void)a300a00d1; gdcm::Attribute<0x300a,0x00d2> a300a00d2; (void)a300a00d2; gdcm::Attribute<0x300a,0x00d3> a300a00d3; (void)a300a00d3; gdcm::Attribute<0x300a,0x00d4> a300a00d4; (void)a300a00d4; gdcm::Attribute<0x300a,0x00d5> a300a00d5; (void)a300a00d5; gdcm::Attribute<0x300a,0x00d6> a300a00d6; (void)a300a00d6; gdcm::Attribute<0x300a,0x00d7> a300a00d7; (void)a300a00d7; gdcm::Attribute<0x300a,0x00d8> a300a00d8; (void)a300a00d8; gdcm::Attribute<0x300a,0x00d9> a300a00d9; (void)a300a00d9; gdcm::Attribute<0x300a,0x00da> a300a00da; (void)a300a00da; gdcm::Attribute<0x300a,0x00db> a300a00db; (void)a300a00db; gdcm::Attribute<0x300a,0x00dc> a300a00dc; (void)a300a00dc; gdcm::Attribute<0x300a,0x00dd> a300a00dd; (void)a300a00dd; gdcm::Attribute<0x300a,0x00e0> a300a00e0; (void)a300a00e0; gdcm::Attribute<0x300a,0x00e1> a300a00e1; (void)a300a00e1; gdcm::Attribute<0x300a,0x00e2> a300a00e2; (void)a300a00e2; gdcm::Attribute<0x300a,0x00e3> a300a00e3; (void)a300a00e3; gdcm::Attribute<0x300a,0x00e4> a300a00e4; (void)a300a00e4; gdcm::Attribute<0x300a,0x00e5> a300a00e5; (void)a300a00e5; gdcm::Attribute<0x300a,0x00e6> a300a00e6; (void)a300a00e6; gdcm::Attribute<0x300a,0x00e7> a300a00e7; (void)a300a00e7; gdcm::Attribute<0x300a,0x00e8> a300a00e8; (void)a300a00e8; gdcm::Attribute<0x300a,0x00e9> a300a00e9; (void)a300a00e9; gdcm::Attribute<0x300a,0x00ea> a300a00ea; (void)a300a00ea; gdcm::Attribute<0x300a,0x00eb> a300a00eb; (void)a300a00eb; gdcm::Attribute<0x300a,0x00ec> a300a00ec; (void)a300a00ec; gdcm::Attribute<0x300a,0x00ed> a300a00ed; (void)a300a00ed; gdcm::Attribute<0x300a,0x00ee> a300a00ee; (void)a300a00ee; gdcm::Attribute<0x300a,0x00f0> a300a00f0; (void)a300a00f0; gdcm::Attribute<0x300a,0x00f2> a300a00f2; (void)a300a00f2; gdcm::Attribute<0x300a,0x00f3> a300a00f3; (void)a300a00f3; gdcm::Attribute<0x300a,0x00f4> a300a00f4; (void)a300a00f4; gdcm::Attribute<0x300a,0x00f5> a300a00f5; (void)a300a00f5; gdcm::Attribute<0x300a,0x00f6> a300a00f6; (void)a300a00f6; gdcm::Attribute<0x300a,0x00f7> a300a00f7; (void)a300a00f7; gdcm::Attribute<0x300a,0x00f8> a300a00f8; (void)a300a00f8; gdcm::Attribute<0x300a,0x00f9> a300a00f9; (void)a300a00f9; gdcm::Attribute<0x300a,0x00fa> a300a00fa; (void)a300a00fa; gdcm::Attribute<0x300a,0x00fb> a300a00fb; (void)a300a00fb; gdcm::Attribute<0x300a,0x00fc> a300a00fc; (void)a300a00fc; gdcm::Attribute<0x300a,0x00fe> a300a00fe; (void)a300a00fe; gdcm::Attribute<0x300a,0x0100> a300a0100; (void)a300a0100; gdcm::Attribute<0x300a,0x0102> a300a0102; (void)a300a0102; gdcm::Attribute<0x300a,0x0104> a300a0104; (void)a300a0104; gdcm::Attribute<0x300a,0x0106> a300a0106; (void)a300a0106; gdcm::Attribute<0x300a,0x0107> a300a0107; (void)a300a0107; gdcm::Attribute<0x300a,0x0108> a300a0108; (void)a300a0108; gdcm::Attribute<0x300a,0x0109> a300a0109; (void)a300a0109; gdcm::Attribute<0x300a,0x010a> a300a010a; (void)a300a010a; gdcm::Attribute<0x300a,0x010c> a300a010c; (void)a300a010c; gdcm::Attribute<0x300a,0x010e> a300a010e; (void)a300a010e; gdcm::Attribute<0x300a,0x0110> a300a0110; (void)a300a0110; gdcm::Attribute<0x300a,0x0111> a300a0111; (void)a300a0111; gdcm::Attribute<0x300a,0x0112> a300a0112; (void)a300a0112; gdcm::Attribute<0x300a,0x0114> a300a0114; (void)a300a0114; gdcm::Attribute<0x300a,0x0115> a300a0115; (void)a300a0115; gdcm::Attribute<0x300a,0x0116> a300a0116; (void)a300a0116; gdcm::Attribute<0x300a,0x0118> a300a0118; (void)a300a0118; gdcm::Attribute<0x300a,0x011a> a300a011a; (void)a300a011a; gdcm::Attribute<0x300a,0x011c> a300a011c; (void)a300a011c; gdcm::Attribute<0x300a,0x011e> a300a011e; (void)a300a011e; gdcm::Attribute<0x300a,0x011f> a300a011f; (void)a300a011f; gdcm::Attribute<0x300a,0x0120> a300a0120; (void)a300a0120; gdcm::Attribute<0x300a,0x0121> a300a0121; (void)a300a0121; gdcm::Attribute<0x300a,0x0122> a300a0122; (void)a300a0122; gdcm::Attribute<0x300a,0x0123> a300a0123; (void)a300a0123; gdcm::Attribute<0x300a,0x0124> a300a0124; (void)a300a0124; gdcm::Attribute<0x300a,0x0125> a300a0125; (void)a300a0125; gdcm::Attribute<0x300a,0x0126> a300a0126; (void)a300a0126; gdcm::Attribute<0x300a,0x0128> a300a0128; (void)a300a0128; gdcm::Attribute<0x300a,0x0129> a300a0129; (void)a300a0129; gdcm::Attribute<0x300a,0x012a> a300a012a; (void)a300a012a; gdcm::Attribute<0x300a,0x012c> a300a012c; (void)a300a012c; gdcm::Attribute<0x300a,0x012e> a300a012e; (void)a300a012e; gdcm::Attribute<0x300a,0x0130> a300a0130; (void)a300a0130; gdcm::Attribute<0x300a,0x0134> a300a0134; (void)a300a0134; gdcm::Attribute<0x300a,0x0140> a300a0140; (void)a300a0140; gdcm::Attribute<0x300a,0x0142> a300a0142; (void)a300a0142; gdcm::Attribute<0x300a,0x0144> a300a0144; (void)a300a0144; gdcm::Attribute<0x300a,0x0146> a300a0146; (void)a300a0146; gdcm::Attribute<0x300a,0x0148> a300a0148; (void)a300a0148; gdcm::Attribute<0x300a,0x014a> a300a014a; (void)a300a014a; gdcm::Attribute<0x300a,0x014c> a300a014c; (void)a300a014c; gdcm::Attribute<0x300a,0x014e> a300a014e; (void)a300a014e; gdcm::Attribute<0x300a,0x0180> a300a0180; (void)a300a0180; gdcm::Attribute<0x300a,0x0182> a300a0182; (void)a300a0182; gdcm::Attribute<0x300a,0x0183> a300a0183; (void)a300a0183; gdcm::Attribute<0x300a,0x0184> a300a0184; (void)a300a0184; gdcm::Attribute<0x300a,0x0190> a300a0190; (void)a300a0190; gdcm::Attribute<0x300a,0x0192> a300a0192; (void)a300a0192; gdcm::Attribute<0x300a,0x0194> a300a0194; (void)a300a0194; gdcm::Attribute<0x300a,0x0196> a300a0196; (void)a300a0196; gdcm::Attribute<0x300a,0x0198> a300a0198; (void)a300a0198; gdcm::Attribute<0x300a,0x0199> a300a0199; (void)a300a0199; gdcm::Attribute<0x300a,0x019a> a300a019a; (void)a300a019a; gdcm::Attribute<0x300a,0x01a0> a300a01a0; (void)a300a01a0; gdcm::Attribute<0x300a,0x01a2> a300a01a2; (void)a300a01a2; gdcm::Attribute<0x300a,0x01a4> a300a01a4; (void)a300a01a4; gdcm::Attribute<0x300a,0x01a6> a300a01a6; (void)a300a01a6; gdcm::Attribute<0x300a,0x01a8> a300a01a8; (void)a300a01a8; gdcm::Attribute<0x300a,0x01b0> a300a01b0; (void)a300a01b0; gdcm::Attribute<0x300a,0x01b2> a300a01b2; (void)a300a01b2; gdcm::Attribute<0x300a,0x01b4> a300a01b4; (void)a300a01b4; gdcm::Attribute<0x300a,0x01b6> a300a01b6; (void)a300a01b6; gdcm::Attribute<0x300a,0x01b8> a300a01b8; (void)a300a01b8; gdcm::Attribute<0x300a,0x01ba> a300a01ba; (void)a300a01ba; gdcm::Attribute<0x300a,0x01bc> a300a01bc; (void)a300a01bc; gdcm::Attribute<0x300a,0x01d0> a300a01d0; (void)a300a01d0; gdcm::Attribute<0x300a,0x01d2> a300a01d2; (void)a300a01d2; gdcm::Attribute<0x300a,0x01d4> a300a01d4; (void)a300a01d4; gdcm::Attribute<0x300a,0x01d6> a300a01d6; (void)a300a01d6; gdcm::Attribute<0x300a,0x0200> a300a0200; (void)a300a0200; gdcm::Attribute<0x300a,0x0202> a300a0202; (void)a300a0202; gdcm::Attribute<0x300a,0x0206> a300a0206; (void)a300a0206; gdcm::Attribute<0x300a,0x0210> a300a0210; (void)a300a0210; gdcm::Attribute<0x300a,0x0212> a300a0212; (void)a300a0212; gdcm::Attribute<0x300a,0x0214> a300a0214; (void)a300a0214; gdcm::Attribute<0x300a,0x0216> a300a0216; (void)a300a0216; gdcm::Attribute<0x300a,0x0218> a300a0218; (void)a300a0218; gdcm::Attribute<0x300a,0x021a> a300a021a; (void)a300a021a; gdcm::Attribute<0x300a,0x0222> a300a0222; (void)a300a0222; gdcm::Attribute<0x300a,0x0224> a300a0224; (void)a300a0224; gdcm::Attribute<0x300a,0x0226> a300a0226; (void)a300a0226; gdcm::Attribute<0x300a,0x0228> a300a0228; (void)a300a0228; gdcm::Attribute<0x300a,0x0229> a300a0229; (void)a300a0229; gdcm::Attribute<0x300a,0x022a> a300a022a; (void)a300a022a; gdcm::Attribute<0x300a,0x022b> a300a022b; (void)a300a022b; gdcm::Attribute<0x300a,0x022c> a300a022c; (void)a300a022c; gdcm::Attribute<0x300a,0x022e> a300a022e; (void)a300a022e; gdcm::Attribute<0x300a,0x0230> a300a0230; (void)a300a0230; gdcm::Attribute<0x300a,0x0232> a300a0232; (void)a300a0232; gdcm::Attribute<0x300a,0x0234> a300a0234; (void)a300a0234; gdcm::Attribute<0x300a,0x0236> a300a0236; (void)a300a0236; gdcm::Attribute<0x300a,0x0238> a300a0238; (void)a300a0238; gdcm::Attribute<0x300a,0x0240> a300a0240; (void)a300a0240; gdcm::Attribute<0x300a,0x0242> a300a0242; (void)a300a0242; gdcm::Attribute<0x300a,0x0244> a300a0244; (void)a300a0244; gdcm::Attribute<0x300a,0x0250> a300a0250; (void)a300a0250; gdcm::Attribute<0x300a,0x0260> a300a0260; (void)a300a0260; gdcm::Attribute<0x300a,0x0262> a300a0262; (void)a300a0262; gdcm::Attribute<0x300a,0x0263> a300a0263; (void)a300a0263; gdcm::Attribute<0x300a,0x0264> a300a0264; (void)a300a0264; gdcm::Attribute<0x300a,0x0266> a300a0266; (void)a300a0266; gdcm::Attribute<0x300a,0x026a> a300a026a; (void)a300a026a; gdcm::Attribute<0x300a,0x026c> a300a026c; (void)a300a026c; gdcm::Attribute<0x300a,0x0280> a300a0280; (void)a300a0280; gdcm::Attribute<0x300a,0x0282> a300a0282; (void)a300a0282; gdcm::Attribute<0x300a,0x0284> a300a0284; (void)a300a0284; gdcm::Attribute<0x300a,0x0286> a300a0286; (void)a300a0286; gdcm::Attribute<0x300a,0x0288> a300a0288; (void)a300a0288; gdcm::Attribute<0x300a,0x028a> a300a028a; (void)a300a028a; gdcm::Attribute<0x300a,0x028c> a300a028c; (void)a300a028c; gdcm::Attribute<0x300a,0x0290> a300a0290; (void)a300a0290; gdcm::Attribute<0x300a,0x0291> a300a0291; (void)a300a0291; gdcm::Attribute<0x300a,0x0292> a300a0292; (void)a300a0292; gdcm::Attribute<0x300a,0x0294> a300a0294; (void)a300a0294; gdcm::Attribute<0x300a,0x0296> a300a0296; (void)a300a0296; gdcm::Attribute<0x300a,0x0298> a300a0298; (void)a300a0298; gdcm::Attribute<0x300a,0x029c> a300a029c; (void)a300a029c; gdcm::Attribute<0x300a,0x029e> a300a029e; (void)a300a029e; gdcm::Attribute<0x300a,0x02a0> a300a02a0; (void)a300a02a0; gdcm::Attribute<0x300a,0x02a2> a300a02a2; (void)a300a02a2; gdcm::Attribute<0x300a,0x02a4> a300a02a4; (void)a300a02a4; gdcm::Attribute<0x300a,0x02b0> a300a02b0; (void)a300a02b0; gdcm::Attribute<0x300a,0x02b2> a300a02b2; (void)a300a02b2; gdcm::Attribute<0x300a,0x02b3> a300a02b3; (void)a300a02b3; gdcm::Attribute<0x300a,0x02b4> a300a02b4; (void)a300a02b4; gdcm::Attribute<0x300a,0x02b8> a300a02b8; (void)a300a02b8; gdcm::Attribute<0x300a,0x02ba> a300a02ba; (void)a300a02ba; gdcm::Attribute<0x300a,0x02c8> a300a02c8; (void)a300a02c8; gdcm::Attribute<0x300a,0x02d0> a300a02d0; (void)a300a02d0; gdcm::Attribute<0x300a,0x02d2> a300a02d2; (void)a300a02d2; gdcm::Attribute<0x300a,0x02d4> a300a02d4; (void)a300a02d4; gdcm::Attribute<0x300a,0x02d6> a300a02d6; (void)a300a02d6; gdcm::Attribute<0x300a,0x02e0> a300a02e0; (void)a300a02e0; gdcm::Attribute<0x300a,0x02e1> a300a02e1; (void)a300a02e1; gdcm::Attribute<0x300a,0x02e2> a300a02e2; (void)a300a02e2; gdcm::Attribute<0x300a,0x02e3> a300a02e3; (void)a300a02e3; gdcm::Attribute<0x300a,0x02e4> a300a02e4; (void)a300a02e4; gdcm::Attribute<0x300a,0x02e5> a300a02e5; (void)a300a02e5; gdcm::Attribute<0x300a,0x02e6> a300a02e6; (void)a300a02e6; gdcm::Attribute<0x300a,0x02e7> a300a02e7; (void)a300a02e7; gdcm::Attribute<0x300a,0x02e8> a300a02e8; (void)a300a02e8; gdcm::Attribute<0x300a,0x02ea> a300a02ea; (void)a300a02ea; gdcm::Attribute<0x300a,0x02eb> a300a02eb; (void)a300a02eb; gdcm::Attribute<0x300a,0x0302> a300a0302; (void)a300a0302; gdcm::Attribute<0x300a,0x0304> a300a0304; (void)a300a0304; gdcm::Attribute<0x300a,0x0306> a300a0306; (void)a300a0306; gdcm::Attribute<0x300a,0x0308> a300a0308; (void)a300a0308; gdcm::Attribute<0x300a,0x030a> a300a030a; (void)a300a030a; gdcm::Attribute<0x300a,0x030c> a300a030c; (void)a300a030c; gdcm::Attribute<0x300a,0x030d> a300a030d; (void)a300a030d; gdcm::Attribute<0x300a,0x030f> a300a030f; (void)a300a030f; gdcm::Attribute<0x300a,0x0312> a300a0312; (void)a300a0312; gdcm::Attribute<0x300a,0x0314> a300a0314; (void)a300a0314; gdcm::Attribute<0x300a,0x0316> a300a0316; (void)a300a0316; gdcm::Attribute<0x300a,0x0318> a300a0318; (void)a300a0318; gdcm::Attribute<0x300a,0x0320> a300a0320; (void)a300a0320; gdcm::Attribute<0x300a,0x0322> a300a0322; (void)a300a0322; gdcm::Attribute<0x300a,0x0330> a300a0330; (void)a300a0330; gdcm::Attribute<0x300a,0x0332> a300a0332; (void)a300a0332; gdcm::Attribute<0x300a,0x0334> a300a0334; (void)a300a0334; gdcm::Attribute<0x300a,0x0336> a300a0336; (void)a300a0336; gdcm::Attribute<0x300a,0x0338> a300a0338; (void)a300a0338; gdcm::Attribute<0x300a,0x033a> a300a033a; (void)a300a033a; gdcm::Attribute<0x300a,0x033c> a300a033c; (void)a300a033c; gdcm::Attribute<0x300a,0x0340> a300a0340; (void)a300a0340; gdcm::Attribute<0x300a,0x0342> a300a0342; (void)a300a0342; gdcm::Attribute<0x300a,0x0344> a300a0344; (void)a300a0344; gdcm::Attribute<0x300a,0x0346> a300a0346; (void)a300a0346; gdcm::Attribute<0x300a,0x0348> a300a0348; (void)a300a0348; gdcm::Attribute<0x300a,0x034a> a300a034a; (void)a300a034a; gdcm::Attribute<0x300a,0x034c> a300a034c; (void)a300a034c; gdcm::Attribute<0x300a,0x0350> a300a0350; (void)a300a0350; gdcm::Attribute<0x300a,0x0352> a300a0352; (void)a300a0352; gdcm::Attribute<0x300a,0x0354> a300a0354; (void)a300a0354; gdcm::Attribute<0x300a,0x0356> a300a0356; (void)a300a0356; gdcm::Attribute<0x300a,0x0358> a300a0358; (void)a300a0358; gdcm::Attribute<0x300a,0x035a> a300a035a; (void)a300a035a; gdcm::Attribute<0x300a,0x0360> a300a0360; (void)a300a0360; gdcm::Attribute<0x300a,0x0362> a300a0362; (void)a300a0362; gdcm::Attribute<0x300a,0x0364> a300a0364; (void)a300a0364; gdcm::Attribute<0x300a,0x0366> a300a0366; (void)a300a0366; gdcm::Attribute<0x300a,0x0370> a300a0370; (void)a300a0370; gdcm::Attribute<0x300a,0x0372> a300a0372; (void)a300a0372; gdcm::Attribute<0x300a,0x0374> a300a0374; (void)a300a0374; gdcm::Attribute<0x300a,0x0380> a300a0380; (void)a300a0380; gdcm::Attribute<0x300a,0x0382> a300a0382; (void)a300a0382; gdcm::Attribute<0x300a,0x0384> a300a0384; (void)a300a0384; gdcm::Attribute<0x300a,0x0386> a300a0386; (void)a300a0386; gdcm::Attribute<0x300a,0x0388> a300a0388; (void)a300a0388; gdcm::Attribute<0x300a,0x038a> a300a038a; (void)a300a038a; gdcm::Attribute<0x300a,0x0390> a300a0390; (void)a300a0390; gdcm::Attribute<0x300a,0x0392> a300a0392; (void)a300a0392; gdcm::Attribute<0x300a,0x0394> a300a0394; (void)a300a0394; gdcm::Attribute<0x300a,0x0396> a300a0396; (void)a300a0396; gdcm::Attribute<0x300a,0x0398> a300a0398; (void)a300a0398; gdcm::Attribute<0x300a,0x039a> a300a039a; (void)a300a039a; gdcm::Attribute<0x300a,0x03a0> a300a03a0; (void)a300a03a0; gdcm::Attribute<0x300a,0x03a2> a300a03a2; (void)a300a03a2; gdcm::Attribute<0x300a,0x03a4> a300a03a4; (void)a300a03a4; gdcm::Attribute<0x300a,0x03a6> a300a03a6; (void)a300a03a6; gdcm::Attribute<0x300a,0x03a8> a300a03a8; (void)a300a03a8; gdcm::Attribute<0x300a,0x03aa> a300a03aa; (void)a300a03aa; gdcm::Attribute<0x300a,0x03ac> a300a03ac; (void)a300a03ac; gdcm::Attribute<0x300a,0x0401> a300a0401; (void)a300a0401; gdcm::Attribute<0x300a,0x0402> a300a0402; (void)a300a0402; gdcm::Attribute<0x300a,0x0410> a300a0410; (void)a300a0410; gdcm::Attribute<0x300a,0x0412> a300a0412; (void)a300a0412; gdcm::Attribute<0x300a,0x0420> a300a0420; (void)a300a0420; gdcm::Attribute<0x300a,0x0421> a300a0421; (void)a300a0421; gdcm::Attribute<0x300a,0x0422> a300a0422; (void)a300a0422; gdcm::Attribute<0x300a,0x0423> a300a0423; (void)a300a0423; gdcm::Attribute<0x300a,0x0424> a300a0424; (void)a300a0424; gdcm::Attribute<0x300c,0x0002> a300c0002; (void)a300c0002; gdcm::Attribute<0x300c,0x0004> a300c0004; (void)a300c0004; gdcm::Attribute<0x300c,0x0006> a300c0006; (void)a300c0006; gdcm::Attribute<0x300c,0x0007> a300c0007; (void)a300c0007; gdcm::Attribute<0x300c,0x0008> a300c0008; (void)a300c0008; gdcm::Attribute<0x300c,0x0009> a300c0009; (void)a300c0009; gdcm::Attribute<0x300c,0x000a> a300c000a; (void)a300c000a; gdcm::Attribute<0x300c,0x000c> a300c000c; (void)a300c000c; gdcm::Attribute<0x300c,0x000e> a300c000e; (void)a300c000e; gdcm::Attribute<0x300c,0x0020> a300c0020; (void)a300c0020; gdcm::Attribute<0x300c,0x0022> a300c0022; (void)a300c0022; gdcm::Attribute<0x300c,0x0040> a300c0040; (void)a300c0040; gdcm::Attribute<0x300c,0x0042> a300c0042; (void)a300c0042; gdcm::Attribute<0x300c,0x0050> a300c0050; (void)a300c0050; gdcm::Attribute<0x300c,0x0051> a300c0051; (void)a300c0051; gdcm::Attribute<0x300c,0x0055> a300c0055; (void)a300c0055; gdcm::Attribute<0x300c,0x0060> a300c0060; (void)a300c0060; gdcm::Attribute<0x300c,0x006a> a300c006a; (void)a300c006a; gdcm::Attribute<0x300c,0x0080> a300c0080; (void)a300c0080; gdcm::Attribute<0x300c,0x00a0> a300c00a0; (void)a300c00a0; gdcm::Attribute<0x300c,0x00b0> a300c00b0; (void)a300c00b0; gdcm::Attribute<0x300c,0x00c0> a300c00c0; (void)a300c00c0; gdcm::Attribute<0x300c,0x00d0> a300c00d0; (void)a300c00d0; gdcm::Attribute<0x300c,0x00e0> a300c00e0; (void)a300c00e0; gdcm::Attribute<0x300c,0x00f0> a300c00f0; (void)a300c00f0; gdcm::Attribute<0x300c,0x00f2> a300c00f2; (void)a300c00f2; gdcm::Attribute<0x300c,0x00f4> a300c00f4; (void)a300c00f4; gdcm::Attribute<0x300c,0x00f6> a300c00f6; (void)a300c00f6; gdcm::Attribute<0x300c,0x0100> a300c0100; (void)a300c0100; gdcm::Attribute<0x300c,0x0102> a300c0102; (void)a300c0102; gdcm::Attribute<0x300c,0x0104> a300c0104; (void)a300c0104; gdcm::Attribute<0x300e,0x0002> a300e0002; (void)a300e0002; gdcm::Attribute<0x300e,0x0004> a300e0004; (void)a300e0004; gdcm::Attribute<0x300e,0x0005> a300e0005; (void)a300e0005; gdcm::Attribute<0x300e,0x0008> a300e0008; (void)a300e0008; gdcm::Attribute<0x4000,0x0010> a40000010; (void)a40000010; gdcm::Attribute<0x4000,0x4000> a40004000; (void)a40004000; gdcm::Attribute<0x4008,0x0040> a40080040; (void)a40080040; gdcm::Attribute<0x4008,0x0042> a40080042; (void)a40080042; gdcm::Attribute<0x4008,0x0050> a40080050; (void)a40080050; gdcm::Attribute<0x4008,0x0100> a40080100; (void)a40080100; gdcm::Attribute<0x4008,0x0101> a40080101; (void)a40080101; gdcm::Attribute<0x4008,0x0102> a40080102; (void)a40080102; gdcm::Attribute<0x4008,0x0103> a40080103; (void)a40080103; gdcm::Attribute<0x4008,0x0108> a40080108; (void)a40080108; gdcm::Attribute<0x4008,0x0109> a40080109; (void)a40080109; gdcm::Attribute<0x4008,0x010a> a4008010a; (void)a4008010a; gdcm::Attribute<0x4008,0x010b> a4008010b; (void)a4008010b; gdcm::Attribute<0x4008,0x010c> a4008010c; (void)a4008010c; gdcm::Attribute<0x4008,0x0111> a40080111; (void)a40080111; gdcm::Attribute<0x4008,0x0112> a40080112; (void)a40080112; gdcm::Attribute<0x4008,0x0113> a40080113; (void)a40080113; gdcm::Attribute<0x4008,0x0114> a40080114; (void)a40080114; gdcm::Attribute<0x4008,0x0115> a40080115; (void)a40080115; gdcm::Attribute<0x4008,0x0117> a40080117; (void)a40080117; gdcm::Attribute<0x4008,0x0118> a40080118; (void)a40080118; gdcm::Attribute<0x4008,0x0119> a40080119; (void)a40080119; gdcm::Attribute<0x4008,0x011a> a4008011a; (void)a4008011a; gdcm::Attribute<0x4008,0x0200> a40080200; (void)a40080200; gdcm::Attribute<0x4008,0x0202> a40080202; (void)a40080202; gdcm::Attribute<0x4008,0x0210> a40080210; (void)a40080210; gdcm::Attribute<0x4008,0x0212> a40080212; (void)a40080212; gdcm::Attribute<0x4008,0x0300> a40080300; (void)a40080300; gdcm::Attribute<0x4008,0x4000> a40084000; (void)a40084000; gdcm::Attribute<0x4ffe,0x0001> a4ffe0001; (void)a4ffe0001; gdcm::Attribute<0x5000,0x0005> a50000005; (void)a50000005; gdcm::Attribute<0x5000,0x0010> a50000010; (void)a50000010; gdcm::Attribute<0x5000,0x0020> a50000020; (void)a50000020; gdcm::Attribute<0x5000,0x0022> a50000022; (void)a50000022; gdcm::Attribute<0x5000,0x0030> a50000030; (void)a50000030; gdcm::Attribute<0x5000,0x0040> a50000040; (void)a50000040; gdcm::Attribute<0x5000,0x0103> a50000103; (void)a50000103; gdcm::Attribute<0x5000,0x0104> a50000104; (void)a50000104; gdcm::Attribute<0x5000,0x0105> a50000105; (void)a50000105; gdcm::Attribute<0x5000,0x0106> a50000106; (void)a50000106; gdcm::Attribute<0x5000,0x0110> a50000110; (void)a50000110; gdcm::Attribute<0x5000,0x0112> a50000112; (void)a50000112; gdcm::Attribute<0x5000,0x0114> a50000114; (void)a50000114; gdcm::Attribute<0x5000,0x1001> a50001001; (void)a50001001; gdcm::Attribute<0x5000,0x2000> a50002000; (void)a50002000; gdcm::Attribute<0x5000,0x2002> a50002002; (void)a50002002; gdcm::Attribute<0x5000,0x2004> a50002004; (void)a50002004; gdcm::Attribute<0x5000,0x2006> a50002006; (void)a50002006; gdcm::Attribute<0x5000,0x2008> a50002008; (void)a50002008; gdcm::Attribute<0x5000,0x200a> a5000200a; (void)a5000200a; gdcm::Attribute<0x5000,0x200e> a5000200e; (void)a5000200e; gdcm::Attribute<0x5000,0x2500> a50002500; (void)a50002500; gdcm::Attribute<0x5000,0x2600> a50002600; (void)a50002600; gdcm::Attribute<0x5000,0x2610> a50002610; (void)a50002610; gdcm::Attribute<0x5200,0x9229> a52009229; (void)a52009229; gdcm::Attribute<0x5200,0x9230> a52009230; (void)a52009230; gdcm::Attribute<0x5400,0x0100> a54000100; (void)a54000100; gdcm::Attribute<0x5400,0x1004> a54001004; (void)a54001004; gdcm::Attribute<0x5400,0x1006> a54001006; (void)a54001006; gdcm::Attribute<0x5600,0x0010> a56000010; (void)a56000010; gdcm::Attribute<0x5600,0x0020> a56000020; (void)a56000020; gdcm::Attribute<0x6000,0x0010> a60000010; (void)a60000010; gdcm::Attribute<0x6000,0x0011> a60000011; (void)a60000011; gdcm::Attribute<0x6000,0x0012> a60000012; (void)a60000012; gdcm::Attribute<0x6000,0x0015> a60000015; (void)a60000015; gdcm::Attribute<0x6000,0x0022> a60000022; (void)a60000022; gdcm::Attribute<0x6000,0x0040> a60000040; (void)a60000040; gdcm::Attribute<0x6000,0x0045> a60000045; (void)a60000045; gdcm::Attribute<0x6000,0x0050> a60000050; (void)a60000050; gdcm::Attribute<0x6000,0x0051> a60000051; (void)a60000051; gdcm::Attribute<0x6000,0x0052> a60000052; (void)a60000052; gdcm::Attribute<0x6000,0x0060> a60000060; (void)a60000060; gdcm::Attribute<0x6000,0x0061> a60000061; (void)a60000061; gdcm::Attribute<0x6000,0x0062> a60000062; (void)a60000062; gdcm::Attribute<0x6000,0x0063> a60000063; (void)a60000063; gdcm::Attribute<0x6000,0x0066> a60000066; (void)a60000066; gdcm::Attribute<0x6000,0x0068> a60000068; (void)a60000068; gdcm::Attribute<0x6000,0x0069> a60000069; (void)a60000069; gdcm::Attribute<0x6000,0x0100> a60000100; (void)a60000100; gdcm::Attribute<0x6000,0x0102> a60000102; (void)a60000102; gdcm::Attribute<0x6000,0x0110> a60000110; (void)a60000110; gdcm::Attribute<0x6000,0x0200> a60000200; (void)a60000200; gdcm::Attribute<0x6000,0x0800> a60000800; (void)a60000800; gdcm::Attribute<0x6000,0x0802> a60000802; (void)a60000802; gdcm::Attribute<0x6000,0x0803> a60000803; (void)a60000803; gdcm::Attribute<0x6000,0x0804> a60000804; (void)a60000804; gdcm::Attribute<0x6000,0x1001> a60001001; (void)a60001001; gdcm::Attribute<0x6000,0x1100> a60001100; (void)a60001100; gdcm::Attribute<0x6000,0x1101> a60001101; (void)a60001101; gdcm::Attribute<0x6000,0x1102> a60001102; (void)a60001102; gdcm::Attribute<0x6000,0x1103> a60001103; (void)a60001103; gdcm::Attribute<0x6000,0x1200> a60001200; (void)a60001200; gdcm::Attribute<0x6000,0x1201> a60001201; (void)a60001201; gdcm::Attribute<0x6000,0x1202> a60001202; (void)a60001202; gdcm::Attribute<0x6000,0x1203> a60001203; (void)a60001203; gdcm::Attribute<0x6000,0x1301> a60001301; (void)a60001301; gdcm::Attribute<0x6000,0x1302> a60001302; (void)a60001302; gdcm::Attribute<0x6000,0x1303> a60001303; (void)a60001303; gdcm::Attribute<0x6000,0x1500> a60001500; (void)a60001500; gdcm::Attribute<0x6000,0x4000> a60004000; (void)a60004000; gdcm::Attribute<0x7fe0,0x0020> a7fe00020; (void)a7fe00020; gdcm::Attribute<0x7fe0,0x0030> a7fe00030; (void)a7fe00030; gdcm::Attribute<0x7fe0,0x0040> a7fe00040; (void)a7fe00040; gdcm::Attribute<0x7f00,0x0011> a7f000011; (void)a7f000011; gdcm::Attribute<0x7f00,0x0020> a7f000020; (void)a7f000020; gdcm::Attribute<0x7f00,0x0030> a7f000030; (void)a7f000030; gdcm::Attribute<0x7f00,0x0040> a7f000040; (void)a7f000040; gdcm::Attribute<0xfffa,0xfffa> afffafffa; (void)afffafffa; gdcm::Attribute<0xfffc,0xfffc> afffcfffc; (void)afffcfffc; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestAttribute.xsl000066400000000000000000000046411412732066400301660ustar00rootroot00000000000000 // GENERATED FILE DO NOT EDIT // $ xsltproc TestAttribute.xsl DICOMV3.xml > TestAttribute.cxx /*========================================================================= 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 "gdcmAttribute.h" int TestAttribute(int, char *[]) { gdcm::Attribute<0x ,0x > ; (void) ; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestAttribute1.cxx000066400000000000000000000167421412732066400302500ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAttribute.h" #include #include // fabs int TestAttributeAE() { return 0; } int TestAttributeAS() { return 0; } int TestAttributeAT() { return 0; } /* int TestAttributeCS() { // (0008,9007) CS [ORIGINAL\PRIMARY\T1\NONE] # 24, 4 FrameType static const char* values[] = {"ORIGINAL","PRIMARY","T1","NONE"}; static const char* newvalues[] = {"DERIVED","SECONDARY","T2","ALL"}; const unsigned int numvalues = sizeof(values) / sizeof(values[0]); if( numvalues != 4 ) return 1; gdcm::Attribute<0x0008,0x9007> it = {"ORIGINAL","PRIMARY","T1","NONE"}; // FIXME HARDCODED: if( it.GetVM() != gdcm::VM::VM4 ) return 1; if( it.GetVR() != gdcm::VR::CS ) return 1; // END FIXME if( it.GetNumberOfValues() != numvalues ) return 1; for(unsigned int i = 0; i < numvalues; ++i) if( it.GetValue(i) != values[i] ) return 1; it.Print( std::cout ); std::cout << std::endl; gdcm::DataElement de = it.GetAsDataElement(); std::cout << de << std::endl; // new values: // Using implicit cstor of gdcm::String from const char * for(unsigned int i = 0; i < numvalues; ++i) it.SetValue( newvalues[i], i ); if( it.GetNumberOfValues() != numvalues ) return 1; for(unsigned int i = 0; i < numvalues; ++i) if( it.GetValue(i) != newvalues[i] ) return 1; // const char * is not a gdcm::String, need an array of gdcm::String static const gdcm::String<> newvalues2[] = {"DERIVED","SECONDARY","T2","ALL"}; const unsigned int numnewvalues2 = sizeof(newvalues2) / sizeof(newvalues2[0]); it.SetValues( newvalues2 ); it.Print( std::cout ); std::cout << std::endl; de = it.GetAsDataElement(); std::cout << de << std::endl; // (0008,0008) CS [DERIVED\PRIMARY\AXIAL] # 22, 3 ImageType gdcm::Attribute<0x0008,0x0008> it1; if( it1.GetVM() != gdcm::VM::VM2_n ) { std::cerr << "Wrong VM:" << it1.GetVM() << std::endl; return 1; } it1.SetValues( newvalues2, numnewvalues2 ); it1.Print( std::cout ); std::cout << std::endl; de = it1.GetAsDataElement(); std::cout << de << std::endl; // redo the same but this time copy the values: it1.SetValues( newvalues2, numnewvalues2, true ); it1.Print( std::cout ); std::cout << std::endl; de = it1.GetAsDataElement(); std::cout << de << std::endl; return 0; } */ int TestAttributeDA() { return 0; } int TestAttributeDS() { // (0020,0032) DS [-158.135803\-179.035797\-75.699997] # 34, 3 ImagePositionPatient const double values[] = {-158.135803,-179.035797,-75.699997}; const double newvalues[] = {12.34,56.78,90.0}; const unsigned int numvalues = sizeof(values) / sizeof(values[0]); gdcm::Attribute<0x0020,0x0032> ipp = {{-158.135803,-179.035797,-75.699997}}; // FIXME HARDCODED: if( ipp.GetVM() != gdcm::VM::VM3 ) return 1; if( ipp.GetVR() != gdcm::VR::DS ) return 1; // END FIXME if( ipp.GetNumberOfValues() != numvalues ) return 1; for(unsigned int i = 0; i < numvalues; ++i) if( fabs(ipp.GetValue(i) - values[i]) > std::numeric_limits::epsilon() ) return 1; ipp.Print( std::cout ); std::cout << std::endl; gdcm::DataElement de = ipp.GetAsDataElement(); std::cout << de << std::endl; // new values: ipp.SetValues( newvalues ); if( ipp.GetNumberOfValues() != numvalues ) return 1; for(unsigned int i = 0; i < numvalues; ++i) if( fabs(ipp.GetValue(i) - newvalues[i]) > std::numeric_limits::epsilon() ) return 1; ipp.Print( std::cout ); std::cout << std::endl; de = ipp.GetAsDataElement(); std::cout << de << std::endl; { //const char v[] = "0.960000000000662 "; // not working const char v[] = "1.960000000000662 "; gdcm::DataElement invalid( gdcm::Tag(0x10,0x1030) ); // Patient's Weight invalid.SetVR( gdcm::VR::DS ); invalid.SetByteValue( v, (uint32_t)strlen(v) ); gdcm::Attribute<0x0010,0x1030> pw; pw.SetFromDataElement( invalid ); gdcm::DataElement valid = pw.GetAsDataElement(); std::ostringstream os; os << valid.GetValue(); std::string s = os.str(); size_t l = s.size(); if( l > 16 ) { return 1; } } return 0; } int TestAttributeDT() { return 0; } int TestAttributeFL() { return 0; } int TestAttributeFD() { return 0; } int TestAttributeIS() { // // This case is slightly more complex it is up to the user to say what is the VM: gdcm::Attribute<0x0018,0x1182, gdcm::VR::IS, gdcm::VM::VM1> fd1 = {0}; if( fd1.GetVM() != gdcm::VM::VM1 ) return 1; gdcm::Attribute<0x0018,0x1182, gdcm::VR::IS, gdcm::VM::VM2> fd2 = {{0,1}}; if( fd2.GetVM() != gdcm::VM::VM2 ) return 1; // this one should not be allowed, I need a special CTest macro... //gdcm::Attribute<0x0018,0x1182, gdcm::VR::IS, gdcm::VM::VM3> fd3 = {0,1}; //return 1; return 0; } int TestAttributeLO() { return 0; } int TestAttributeLT() { return 0; } int TestAttributeOB() { return 0; } int TestAttributeOD() { return 0; } int TestAttributeOF() { gdcm::DataSet ds; const float array[] = { 0, 1, 2, 3, 4 }; gdcm::Attribute<0x5600,0x0020, gdcm::VR::OF, gdcm::VM::VM1_n> at; at.SetValues( array, sizeof( array ) / sizeof( *array ) ); ds.Insert( at.GetAsDataElement() ); if( at.GetNumberOfValues() != 5 ) return 1; // Sup 132 // Tag : (0x0066,0x0016), VR : OF, VM : 1, Type : 1 gdcm::Attribute<0x0066,0x0016> at1; float value = 1.f; at1.SetValue( value ); ds.Insert( at1.GetAsDataElement() ); return 0; } int TestAttributeOL() { return 0; } int TestAttributeOW() { return 0; } int TestAttributePN() { return 0; } int TestAttributeSH() { return 0; } int TestAttributeSL() { return 0; } int TestAttributeSQ() { return 0; } int TestAttributeSS() { return 0; } int TestAttributeST() { return 0; } int TestAttributeTM() { return 0; } int TestAttributeUI() { return 0; } int TestAttributeUL() { return 0; } int TestAttributeUN() { return 0; } int TestAttributeUS() { return 0; } int TestAttributeUT() { return 0; } int TestAttribute1(int , char *[]) { int numerrors = 0; numerrors += TestAttributeAE(); numerrors += TestAttributeAS(); numerrors += TestAttributeAT(); //numerrors += TestAttributeCS(); numerrors += TestAttributeDA(); numerrors += TestAttributeDS(); numerrors += TestAttributeDT(); numerrors += TestAttributeFL(); numerrors += TestAttributeFD(); numerrors += TestAttributeIS(); numerrors += TestAttributeLO(); numerrors += TestAttributeLT(); numerrors += TestAttributeOB(); numerrors += TestAttributeOD(); numerrors += TestAttributeOF(); numerrors += TestAttributeOL(); numerrors += TestAttributeOW(); numerrors += TestAttributePN(); numerrors += TestAttributeSH(); numerrors += TestAttributeSL(); numerrors += TestAttributeSQ(); numerrors += TestAttributeSS(); numerrors += TestAttributeST(); numerrors += TestAttributeTM(); numerrors += TestAttributeUI(); numerrors += TestAttributeUL(); numerrors += TestAttributeUN(); numerrors += TestAttributeUS(); numerrors += TestAttributeUT(); return numerrors; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestAttribute2.cxx000066400000000000000000000065161412732066400302470ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAttribute.h" /* (0008,0000) UL 38 (0008,0001) UL 262302 (0008,0010) LO [ACRNEMA_LIBIDO_1.1] (0028,0000) UL 100 (0028,0005) US 2 (0028,0010) US 512 (0028,0011) US 512 (0028,0015) ?? 00\00 (0028,0016) ?? 00\00 (0028,0100) US 8 (0028,0101) US 8 (0028,0102) US 7 (0028,0103) US 0 (0028,0199) ?? 70\00 (7fe0,0000) UL 262152 (7fe0,0010) OW ea00\eaea\e9e9\e9e9\e9e9\e */ int main(int argc, char *argv[]) { const char *filename; if( argc < 2 ) { filename = "/tmp/dummy.dcm"; } else { filename = argv[1]; } //std::cout << "Reading: " << filename << std::endl; std::ifstream is(filename, std::ios::binary ); gdcm::Attribute<0x0008,0x0000, gdcm::VR::UL, gdcm::VM::VM1> a; a.Read(is); a.Print( std::cout << std::endl ); gdcm::Attribute<0x0008,0x0001, gdcm::VR::UL, gdcm::VM::VM1> b; b.Read(is); b.Print( std::cout << std::endl ); gdcm::Attribute<0x0008,0x0010, gdcm::VR::LO, gdcm::VM::VM24> c = {}; c.Read(is); c.Print( std::cout << std::endl ); gdcm::Attribute<0x0028,0x0000, gdcm::VR::UL, gdcm::VM::VM1> d; d.Read(is); d.Print( std::cout << std::endl ); gdcm::Attribute<0x0028,0x0005, gdcm::VR::US, gdcm::VM::VM1> e; e.Read(is); e.Print( std::cout << std::endl ); gdcm::Attribute<0x0028,0x0010, gdcm::VR::US, gdcm::VM::VM1> f; f.Read(is); f.Print( std::cout << std::endl ); gdcm::Attribute<0x0028,0x0011, gdcm::VR::US, gdcm::VM::VM1> g; g.Read(is); g.Print( std::cout << std::endl ); // 0028 0015 US 1 UsedNbX ACR Special (RET) // 0028 0016 US 1 UsedNbY ACR Special (RET) gdcm::Attribute<0x0028,0x0015, gdcm::VR::US, gdcm::VM::VM1> h; h.Read(is); h.Print( std::cout << std::endl ); gdcm::Attribute<0x0028,0x0016, gdcm::VR::US, gdcm::VM::VM1> i; i.Read(is); i.Print( std::cout << std::endl ); gdcm::Attribute<0x0028,0x0100, gdcm::VR::US, gdcm::VM::VM1> j; j.Read(is); j.Print( std::cout << std::endl ); gdcm::Attribute<0x0028,0x0101, gdcm::VR::US, gdcm::VM::VM1> k; k.Read(is); k.Print( std::cout << std::endl ); gdcm::Attribute<0x0028,0x0102, gdcm::VR::US, gdcm::VM::VM1> l; l.Read(is); l.Print( std::cout << std::endl ); gdcm::Attribute<0x0028,0x0103, gdcm::VR::US, gdcm::VM::VM1> m; m.Read(is); m.Print( std::cout << std::endl ); // 0028 0199 US 1 Special Code (RET) gdcm::Attribute<0x0028,0x0199, gdcm::VR::US, gdcm::VM::VM1> n; n.Read(is); n.Print( std::cout << std::endl ); gdcm::Attribute<0x7fe0,0x0000, gdcm::VR::UL, gdcm::VM::VM1> o; o.Read(is); o.Print( std::cout << std::endl ); gdcm::Attribute<0x7fe0,0x0010, gdcm::VR::OW, gdcm::VM::VM1> p; // char bytes[512*512]; p.SetBytes(bytes, 512*512); p.Read(is); p.Print( std::cout << std::endl ); std::streampos pos = is.tellg(); std::cout << "Pos=" << (int)pos << std::endl; is.close(); return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestAttribute3.cxx000066400000000000000000000044601412732066400302440ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAttribute.h" int main(int argc, char *argv[]) { gdcm::Attribute<0x0008,0x0000> a = { 38 }; a.Print( std::cout << std::endl ); gdcm::Attribute<0x0018,0x106c> b = { 123, 456 }; b.Print( std::cout << std::endl ); gdcm::Attribute<0x0018,0x1624> c = { 123, 456, 789 }; c.Print( std::cout << std::endl ); gdcm::Attribute<0x0072,0x0108> d = { 1.2, 3.4, 5.6, 7.8 }; d.Print( std::cout << std::endl ); gdcm::Attribute<0x3002,0x0010> e = { 1.2, 3.4, 5.6, 7.8, 9.0, 10. }; e.Print( std::cout << std::endl ); gdcm::Attribute<0x0018,0x1149, gdcm::VR::IS, gdcm::VM::VM2> f = { 12 , 13 }; f.Print( std::cout << std::endl ); gdcm::Attribute<0x0018,0x1149, gdcm::VR::IS, gdcm::VM::VM1> g = { 12 }; g.Print( std::cout << std::endl ); // grrrr.... too dangerous for users gdcm::Attribute<0x0018,0x1149, gdcm::VR::IS, gdcm::VM::VM1 > h = { 12 }; h.Print( std::cout << std::endl ); typedef gdcm::Attribute<0x3002,0x0010>::ArrayType type; const type &val = e.GetValue(2); std::cout << std::endl << "val=" << val; e.SetValue( 123.456, 2 ); std::cout << std::endl << "val=" << val; // gdcm::Attribute<0x3002,0x0010>::VMType == 6, let's check that: const type my[ gdcm::Attribute<0x3002,0x0010>::VMType ] = { 1.2 }; e.SetValues( my ); e.Print( std::cout << std::endl ); // TODO: // gdcm::Attribute<0x0002,0x0001> i = { '0', '1' }; // i.Print( std::cout << std::endl ); gdcm::Attribute<0x0002, 0x0002> m1 = { "1.2.840.10008.5.1.4.1.1.2" }; m1.Print( std::cout << std::endl ); gdcm::Attribute<0x0008, 0x0016> m2 = { "1.2.840.10008.5.1.4.1.1.3" }; m2.Print( std::cout << std::endl ); m1.SetValues( m2.GetValues() ); // copy all the 64+1 char m1.Print( std::cout << std::endl ); std::cout << std::endl; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestAttribute4.cxx000066400000000000000000000023361412732066400302450ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAttribute.h" int main() { gdcm::Attribute<0x0018,0x1182, gdcm::VR::IS, gdcm::VM::VM1> fd = {0}; fd.Print( std::cout ); /* bool b = gdcm::VR::OB & gdcm::VR::UL; std::cout << b << std::endl; gdcm::VR vr = fd.GetVR(); gdcm::VR dictvr = fd.GetDictVR(); b = vr & dictvr; std::cout << vr << " " << dictvr << std::endl; std::cout << b << std::endl; gdcm::VM vm = fd.GetVM(); gdcm::VM dictvm = fd.GetDictVM(); b = vm & dictvm; std::cout << vm << " " << dictvm << std::endl; std::cout << b << std::endl; // Let's if we can construct a private element: gdcm::Attribute<0x1233,0x5678, gdcm::VR::IS, gdcm::VM::VM1> fd2 = {0}; */ return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestAttribute5.cxx000066400000000000000000000073541412732066400302530ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAttribute.h" /* (0008,0000) UL 38 (0008,0001) UL 262302 (0008,0010) LO [ACRNEMA_LIBIDO_1.1] (0028,0000) UL 100 (0028,0005) US 2 (0028,0010) US 512 (0028,0011) US 512 (0028,0015) ?? 00\00 (0028,0016) ?? 00\00 (0028,0100) US 8 (0028,0101) US 8 (0028,0102) US 7 (0028,0103) US 0 (0028,0199) ?? 70\00 (7fe0,0000) UL 262152 (7fe0,0010) OW ea00\eaea\e9e9\e9e9\e9e9\e */ struct dummy { int u; char v[5]; }; int TestAttribute(int argc, char *argv[]) { dummy du = { 2, "date" }; const char *filename; if( argc < 2 ) { filename = "/tmp/dummy.dcm"; } else { filename = argv[1]; } std::ofstream os(filename, std::ios::binary); //gdcm::Attribute<0x0008,0x0000, gdcm::VR::UL, gdcm::VM::VM1> a = { 38 }; gdcm::Attribute<0x0008,0x0000> a = { 38 }; a.Print( std::cout << std::endl ); a.Write(os); gdcm::Attribute<0x0008,0x0001, gdcm::VR::UL, gdcm::VM::VM1> b = { 262302 }; b.Print( std::cout << std::endl ); b.Write(os); gdcm::Attribute<0x0008,0x0010, gdcm::VR::LO, gdcm::VM::VM1> c = { "ACRNEMA_LIBIDO_1.1" }; c.Print( std::cout << std::endl ); c.Write(os); // 0008 0082 SQ 1 Institution Code Sequence gdcm::Attribute<0x0008,0x0082, gdcm::VR::SQ, gdcm::VM::VM1, gdcm::Attribute<0x0008,0x0080, gdcm::VR::LO> > sq = { "Institution Name" }; sq.Print( std::cout << std::endl ); sq.Write(os); gdcm::Attribute<0x0028,0x0000, gdcm::VR::UL, gdcm::VM::VM1> d = { 100 }; d.Print( std::cout << std::endl ); d.Write(os); gdcm::Attribute<0x0028,0x0005, gdcm::VR::US, gdcm::VM::VM1> e = { 2 }; e.Print( std::cout << std::endl ); e.Write(os); gdcm::Attribute<0x0028,0x0010, gdcm::VR::US, gdcm::VM::VM1> f = { 512 }; f.Print( std::cout << std::endl ); f.Write(os); gdcm::Attribute<0x0028,0x0011, gdcm::VR::US, gdcm::VM::VM1> g = { 512 }; g.Print( std::cout << std::endl ); g.Write(os); // 0028 0015 US 1 UsedNbX ACR Special (RET) // 0028 0016 US 1 UsedNbY ACR Special (RET) gdcm::Attribute<0x0028,0x0015, gdcm::VR::US, gdcm::VM::VM1> h = { 0 }; h.Print( std::cout << std::endl ); h.Write(os); gdcm::Attribute<0x0028,0x0016, gdcm::VR::US, gdcm::VM::VM1> i = { 0 }; i.Print( std::cout << std::endl ); i.Write(os); gdcm::Attribute<0x0028,0x0100, gdcm::VR::US, gdcm::VM::VM1> j = { 8 }; j.Print( std::cout << std::endl ); j.Write(os); gdcm::Attribute<0x0028,0x0101, gdcm::VR::US, gdcm::VM::VM1> k = { 8 }; k.Print( std::cout << std::endl ); k.Write(os); gdcm::Attribute<0x0028,0x0102, gdcm::VR::US, gdcm::VM::VM1> l = { 7 }; l.Print( std::cout << std::endl ); l.Write(os); gdcm::Attribute<0x0028,0x0103, gdcm::VR::US, gdcm::VM::VM1> m = { 0 }; m.Print( std::cout << std::endl ); m.Write(os); // 0028 0199 US 1 Special Code (RET) gdcm::Attribute<0x0028,0x0199, gdcm::VR::US, gdcm::VM::VM1> n = { 112 }; n.Print( std::cout << std::endl ); n.Write(os); gdcm::Attribute<0x7fe0,0x0000, gdcm::VR::UL, gdcm::VM::VM1> o = { 262152 }; o.Print( std::cout << std::endl ); o.Write(os); gdcm::Attribute<0x7fe0,0x0010, gdcm::VR::OW, gdcm::VM::VM1> p; // char bytes[512*512] = {}; p.SetBytes(bytes, 512*512); p.Print( std::cout << std::endl ); p.Write(os); os.close(); return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestAttribute6.cxx000066400000000000000000000023361412732066400302470ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAttribute.h" int main() { gdcm::Attribute<0x0018,0x1182, gdcm::VR::IS, gdcm::VM::VM1> fd = {0}; fd.Print( std::cout ); /* bool b = gdcm::VR::OB & gdcm::VR::UL; std::cout << b << std::endl; gdcm::VR vr = fd.GetVR(); gdcm::VR dictvr = fd.GetDictVR(); b = vr & dictvr; std::cout << vr << " " << dictvr << std::endl; std::cout << b << std::endl; gdcm::VM vm = fd.GetVM(); gdcm::VM dictvm = fd.GetDictVM(); b = vm & dictvm; std::cout << vm << " " << dictvm << std::endl; std::cout << b << std::endl; // Let's if we can construct a private element: gdcm::Attribute<0x1233,0x5678, gdcm::VR::IS, gdcm::VM::VM1> fd2 = {0}; */ return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestAttribute7.cxx000066400000000000000000000033541412732066400302510ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAttribute.h" int TestAttribute7(int, char *[]) { { const char bytes[] = "\030\000e\020"; gdcm::DataElement de( gdcm::Tag(0x28,0x9) ); de.SetVR( gdcm::VR::INVALID ); de.SetByteValue( bytes, 4 ); gdcm::Attribute<0x28,0x9, gdcm::VR::AT, gdcm::VM::VM1 > at; at.SetFromDataElement( de ); std::cout << at.GetValue() << std::endl; gdcm::Attribute<0x3004, 0x0014> tissue; //std::cout << tissue.GetVR() << std::endl; if( tissue.GetVR() != gdcm::VR::CS ) return 1; } { gdcm::Attribute<0x8,0x8> imagetype; imagetype.SetNumberOfValues(0); if( imagetype.GetNumberOfValues() != 0 ) return 1; const char bytes[] = "ORIGINAL\\PRIMARY"; gdcm::DataElement de( gdcm::Tag(0x8,0x8) ); de.SetVR( gdcm::VR::INVALID ); de.SetByteValue( bytes, (uint32_t)strlen(bytes) ); gdcm::DataSet ds; imagetype.SetFromDataSet( ds ); if( imagetype.GetNumberOfValues() != 0 ) return 1; ds.Insert( de ); imagetype.SetFromDataSet( ds ); if( imagetype.GetNumberOfValues() != 2 ) return 1; imagetype.SetNumberOfValues(0); if( imagetype.GetNumberOfValues() != 0 ) return 1; imagetype.SetFromDataSet( ds ); if( imagetype.GetNumberOfValues() != 2 ) return 1; } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestAttribute8.cxx000066400000000000000000000042051412732066400302460ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAttribute.h" #include "gdcmReader.h" #include "gdcmFileMetaInformation.h" #include "gdcmFile.h" #include "gdcmTesting.h" #include "gdcmMediaStorage.h" /* * Contributed by Michele Bosi on gdcm-dev ML */ int TestAttribute8Func(const char *filename, bool verbose = false) { if( verbose ) std::cout << "TestRead: " << filename << std::endl; gdcm::Reader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { std::cerr << "TestReadError: Failed to read: " << filename << std::endl; return 1; } //const gdcm::FileMetaInformation &h = reader.GetFile().GetHeader(); //h is unused //std::cout << h << std::endl; const gdcm::DataSet &ds = reader.GetFile().GetDataSet(); // gdcm::DataSet& ds = file.GetDataSet(); gdcm::Attribute<0x28,0x1050> win_center; const gdcm::DataElement& de = ds.GetDataElement( win_center.GetTag() ); if(!de.IsEmpty()) { win_center.SetFromDataElement( de ); std::cout << win_center.GetNumberOfValues() << ": "; for( unsigned int i = 0; i < win_center.GetNumberOfValues(); ++i) std::cout << win_center[i] << ","; } std::cout << std::endl; return 0; } int TestAttribute8(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestAttribute8Func(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestAttribute8Func( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestBasicOffsetTable.cxx000066400000000000000000000012551412732066400313550ustar00rootroot00000000000000/*========================================================================= 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 "gdcmBasicOffsetTable.h" int TestBasicOffsetTable(int, char *[]) { gdcm::BasicOffsetTable bot; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestByteBuffer.cxx000066400000000000000000000024311412732066400302470ustar00rootroot00000000000000/*========================================================================= 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 "gdcmByteBuffer.h" #include int TestByteBuffer(int, char *[]) { const int size = 128; gdcm::ByteBuffer b; char buffer[size]; int r = 0; for(int i=-size; i<0; ++i) { buffer[i+size] = (char)(i); } memcpy(b.Get(size), buffer, size); const char *start = b.GetStart(); for(int i=size; i>0; --i) { if( (int)start[size-i] != -i ) { std::cout << (int)start[size-i] << " " << -i << std::endl; ++r; } } for(int i=0; i( ss ); std::cout << bv2 << std::endl; if( memcmp(bv2.GetPointer(), array, len ) != 0 ) { return 1; } if( !(bv1 == bv2) ) { return 1; } gdcm::ByteValue bv3(bv2); if( memcmp(bv3.GetPointer(), array, len ) != 0 ) { return 1; } if( !(bv3 == bv1) ) { return 1; } gdcm::ByteValue bv4 = bv3; if( memcmp(bv4.GetPointer(), array, len ) != 0 ) { return 1; } if( !(bv4 == bv1) ) { return 1; } gdcm::ByteValue bv5; if( bv5 == bv1 ) { return 1; } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestCSAElement.cxx000066400000000000000000000012351412732066400301330ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCSAElement.h" int TestCSAElement(int , char * []) { gdcm::CSAElement el; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestCSAHeader.cxx000066400000000000000000000015271412732066400277360ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCSAHeader.h" int TestCSAHeader(int , char * []) { gdcm::CSAHeader h; /* try { const gdcm::CSAElement &foo = csa.GetCSAElementByName( "foo" ); } catch( gdcm::CSAElementNameException &ex ) { std::cout << ex.what() << std::endl; } */ return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestCodeString.cxx000066400000000000000000000072201412732066400302540ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCodeString.h" #include "gdcmAttribute.h" #include int TestCodeString(int , char *[]) { { gdcm::Attribute<0x0008,0x0008> at3; static const gdcm::CSComp values[] = {"DERIVED","SECONDARY"}; at3.SetValues( values, 2, true ); if( at3.GetNumberOfValues() != 2 ) return 1; } const char fn1[] = "IMG01"; gdcm::Attribute< 0x0004, 0x1500 > at; at.SetNumberOfValues( 1 ); at.SetValue( fn1 ); unsigned int n = at.GetNumberOfValues(); if( n != 1 ) return 1; { const char fn2[] = "SUBDIR\\IMG01"; at.SetNumberOfValues( 2 ); at.SetValue( fn2 ); n = at.GetNumberOfValues(); if( n != 2 ) return 1; } const char fn3[] = "SUBDIR1\\SUBDIR2\\IMG01 "; { gdcm::DataElement de( at.GetTag() ); de.SetByteValue( fn3, (uint32_t)strlen(fn3) ); at.SetFromDataElement( de ); n = at.GetNumberOfValues(); //std::cout << n << std::endl; if( n != 3 ) return 1; for( unsigned int i = 0; i < n; ++i) { gdcm::CodeString cs = at.GetValue( i ); if( !cs.IsValid() ) { std::cerr << "Invalid CS: " << cs << std::endl; return 1; } } } const char fn4[] = "SUBDIR1\\SUBDIR2\\IMG01"; { std::string copy = fn4; if( copy.size() % 2 ) { copy.push_back( ' ' ); } gdcm::DataElement de( at.GetTag() ); de.SetByteValue( copy.c_str(), (uint32_t)copy.size() ); at.SetFromDataElement( de ); n = at.GetNumberOfValues(); //std::cout << n << std::endl; if( n != 3 ) return 1; for( unsigned int i = 0; i < n; ++i) { gdcm::CodeString cs = at.GetValue( i ); if( !cs.IsValid() ) { std::cerr << "Invalid CS: " << cs << std::endl; return 1; } } } const char fn5[] = R"(SUBDIR1\SUBDIR2\LONGSUBDIR\IMG01)"; { std::string copy = fn5; if( copy.size() % 2 ) { copy.push_back( ' ' ); } gdcm::DataElement de( at.GetTag() ); de.SetByteValue( copy.c_str(), (uint32_t)copy.size() ); at.SetFromDataElement( de ); n = at.GetNumberOfValues(); //std::cout << n << std::endl; if( n != 4 ) return 1; for( unsigned int i = 0; i < n; ++i) { gdcm::CodeString cs = at.GetValue( i ); if( !cs.IsValid() ) { std::cerr << "Invalid CS: " << cs << std::endl; return 1; } } if( strlen(at.GetValue(2) ) < 8 ) { return 1; } } { gdcm::CodeString cs0 = " SUB\\DIR "; if( cs0.IsValid() ) return 1; gdcm::CodeString cs1 = " SUBDIR "; if( !cs1.IsValid() ) return 1; gdcm::CodeString cs2 = " SUBDIR_0123456789 "; // len == 19 => invalid if( cs2.IsValid() ) return 1; gdcm::CodeString cs3 = " IMG_0123456789 "; if( !cs3.IsValid() ) return 1; // cstor should trim on the fly: gdcm::CodeString cs4 = " IMG_0123456789 "; if( !cs4.IsValid() ) return 1; if( !(cs3 == cs4) ) return 1; if( cs3 != cs4 ) return 1; gdcm::CodeString cs5 = "IMG"; if( cs5 != "IMG ") return 1; // Begin ugly internals. } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestComposite.cxx000066400000000000000000000012571412732066400301610ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSequenceOfItems.h" int TestComposite(int argc, char *argv[]) { (void)argc; (void)argv; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestCopyValue.cxx000066400000000000000000000042631412732066400301260ustar00rootroot00000000000000/*========================================================================= 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 "gdcmValue.h" #include "gdcmByteValue.h" #include //namespace std { namespace tr1 = Boost; } void RawPtr(const char *array, const size_t len) { std::cout << "RawPtr" << std::endl; gdcm::ByteValue *bv1 = new gdcm::ByteValue(array, len); std::cout << *bv1 << std::endl; gdcm::ByteValue *bv2 = new gdcm::ByteValue(array, len); std::cout << *bv2 << std::endl; const gdcm::Value &ref1 = *bv1; std::cout << ref1 << std::endl; const gdcm::Value &ref2 = *bv2; std::cout << ref2 << std::endl; // Need to delete: delete bv1; delete bv2; } typedef std::tr1::shared_ptr ValuePtr; void SharedPtr(const char *array, const size_t len) { std::cout << "SharedPtr" << std::endl; //ValuePtr w; //std::cout << w << std::endl; ValuePtr bv1 ( new gdcm::ByteValue(array, len) ); std::cout << *bv1 << std::endl; ValuePtr bv2 ( new gdcm::ByteValue(array, len) ); std::cout << *bv2 << std::endl; const gdcm::Value &ref1 = *bv1; std::cout << ref1 << std::endl; const gdcm::Value &ref2 = *bv2; std::cout << ref2 << std::endl; // No need to delete :) } int TestCopyValue(int , char *[]) { const char array[] = "GDCM is yet another DICOM library."; const size_t len = strlen( array ); RawPtr(array, len); SharedPtr(array, len); std::vector v; v.push_back( ValuePtr(new gdcm::ByteValue(array, len) )); v.push_back( ValuePtr(new gdcm::ByteValue(array, len) )); v.push_back( ValuePtr(new gdcm::ByteValue(array, len) )); v.push_back( ValuePtr(new gdcm::ByteValue(array, len) )); v.push_back( ValuePtr(new gdcm::ByteValue(array, len) )); // no delete :) return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestDS.cxx000066400000000000000000000530611412732066400265250ustar00rootroot00000000000000/*========================================================================= 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 "gdcmVR.h" #include "gdcmAttribute.h" #include "gdcmByteValue.h" #include #include #include #include // atof #include // std::rand() #include // min_exponent10 and max_exponent10 // WARNING: The number of digits in exponent can be dependent from compiler. // gcc uses 2 digits if the exponent is < 100 and 3 digits if >=, but // some compilers (i.e. MSVC) may always use 3 digits in exponent. // If some other compiler with this behaviour is detected, should be // added here. #if defined(_MSC_VER) #define ALWAYS_3_DIGITS_IN_EXPONENT #endif #ifdef ALWAYS_3_DIGITS_IN_EXPONENT #define MIN_NEGATIVE_EXP 6 //MSVC always use 3 digits in exponent. #else #define MIN_NEGATIVE_EXP 5 #endif template < typename Float > std::string to_string ( Float data ) { std::stringstream in; // in.imbue(std::locale::classic()); // This is not required AFAIK unsigned long digits = 0; // 16 integer digits number or 15 integer digits negative number if ( (data >= 1e+15 && data < 1e16) || (data <= -1e14 && data > -1e+15)) in << std::fixed; else { digits = 15; // 16 - 1 (dot) // negative number if (data < 0) digits -= 1; // (minus) if (data != 0) { Float ldata = log10(fabs(data)); // numbers that need std::scientific representation if ( ldata > 16 || (ldata > 15 && data < 0) || ldata < -MIN_NEGATIVE_EXP+1 ) { in << std::scientific; #ifdef ALWAYS_3_DIGITS_IN_EXPONENT digits -= 6; // (first digit + exponent) #else digits -= 5; // (first digit + exponent) // 3 digits in exponent if ( ldata >= 100 || ldata < -99 ) digits -=1; #endif } else if( ldata < 0){ //since ldata is negative, to have the test pass, //the right casting has to be done to avoid a casting warning here unsigned long uldata = (unsigned long)(fabs(ldata)+1.0); digits -= uldata; // (zeros before first significant digit) } } } /* // I don't know if you really need this check unsigned long const max_digits = static_cast< unsigned long >( - std::log( std::numeric_limits::epsilon() ) / std::log( 10.0 ) ); digits = (digits > max_digits) ? max_digits : digits; */ if ( in << std::dec << std::setprecision((int)digits) << data ) return in.str(); else throw "Impossible Conversion"; // should not happen ... } static bool checkerror(double d, std::string s) { double theConverted = atof(s.c_str()); double error = fabs(d - theConverted); int Log = (int)log10(fabs(d)); int eo = ( Log - 14 ); if ( Log <= -1 && Log >= -4 ) eo = -13; #ifdef ALWAYS_3_DIGITS_IN_EXPONENT else if ( Log >= 15 ) eo = ( Log - 9); #else else if ( Log >= 99 ) eo = ( Log - 9 ); else if ( Log >= 15 ) eo = ( Log - 10); #endif if (d<0) eo += 1; //if (error > pow(10., eo) ) //pow will underflow at 10^-308, so errors lower than -308 will appear to be //larger than pow(10., eo), because the 'pow' result will be 0 in vs2010 if (log10(error) > eo) { std::cout << "ERROR: Absolute Error is too large (error = " << error << ", should be < " << pow(10., eo) << ")" << std::endl; return true; } // else if (error != 0.0) std::cout << "OK (error = " << error << ", is < " << pow(10, eo) << ")" << std::endl; return false; } static bool checkerror(double d, std::string s, bool se) { double error = fabs(d - atof( s.c_str() )); bool has_error = (error != 0); if (has_error) { std::cout << "\tError is: " << error; } std::cout << std::endl; if( has_error != se ) { std::cout << "ERROR: has_error = " << has_error << " (should be " << se << ")" << std::endl; return true; } return checkerror(d,s); } /* d = double to test sz = size expected se = true if there should be an error */ static bool singleTestDS(double d, int sz, bool se = false) { bool fail = false; std::cout << " -|----------------|-" << std::endl; std::string s = to_string( d ); std::cout << " Result: " << s << std::flush; if ( checkerror(d, s, se) ) fail = true; assert(sz >= 0); if( s.size() != (unsigned int)sz ) { std::cout << "ERROR: Size = " << s.size() << " (should be " << sz << ")" << std::endl; fail = true; } std::cout << std::endl; return fail; } #define TEST(x, y, z) { \ std::cout << " Testing: " << #x << std::endl; \ err_count += singleTestDS(x, y, z); \ test_count++; } \ GDCM_NOOP_STATEMENT /* * Test to make sure that double precision ieee 'double' is ok for DICOM VR = 'DS' */ int TestDS(int, char *[]) { int err_count = 0; int test_count = 0; TEST( 118.242525316066 , 16, false); // 3 digits + dot + 12 digits => 16 chars TEST( -118.242525316066 , 16, true); // minus + 3 digits + dot + 12 digits => 16 chars + ERROR TEST( 118.24252531606 , 15, false); // minus + 3 digits + dot + 11 digits => 16 chars TEST( -118.24252531606 , 16, false); // minus + 3 digits + dot + 11 digits => 16 chars TEST( 0.059303515816892 , 16, true); // zero + dot + zero + 14 digits => 16 chars + ERROR TEST( -0.059303515816892 , 16, true); // minus + zero + dot + zero + 14 digits => 16 chars + ERROR TEST( 0.05930351581689 , 16, false); // zero + dot + zero + 13 digits => 16 chars TEST( -0.05930351581689 , 16, true); // minus + zero + dot + zero + 13 digits => 16 chars + ERROR TEST( 0.0593035158168 , 15, false); // zero + dot + zero + 12 digits => 15 chars TEST( -0.0593035158168 , 16, false); // minus + zero + dot + zero + 12 digits => 16 chars TEST( 0.00149700609543456 , 16, true); // zero + dot + 2 zeros + 15 digits => 16 chars + ERROR TEST( -0.00149700609543456 , 16, true); // zero + dot + 2 zeros + 15 digits => 16 chars + ERROR TEST( 0.0014970060954345 , 16, true); // zero + dot + 2 zeros + 14 digits => 16 chars + ERROR TEST( -0.0014970060954345 , 16, true); // zero + dot + 2 zeros + 14 digits => 16 chars + ERROR TEST( 0.001497006095434 , 16, true); // zero + dot + 2 zeros + 13 digits => 16 chars + ERROR TEST( -0.001497006095434 , 16, true); // zero + dot + 2 zeros + 13 digits => 16 chars + ERROR TEST( 0.00149700609543 , 16, false); // zero + dot + 2 zeros + 12 digits => 16 chars TEST( -0.00149700609543 , 16, true); // zero + dot + 2 zeros + 12 digits => 16 chars + ERROR TEST( 0.0014970060954 , 15, false); // zero + dot + 2 zeros + 11 digits => 15 chars TEST( -0.0014970060954 , 16, false); // zero + dot + 2 zeros + 11 digits => 16 chars TEST( 0.000593035158168 , 16, true); // zero + dot + 3 zeros + 12 digits => 16 chars + ERROR TEST( 5.93035158168e-04 , 16, true); // same number: cannot fit in 16 chars even in scientific notation (17 chars) TEST( 0.00059303515816 , 16, false); // zero + dot + 3 zeros + 11 digits => 16 chars TEST( -0.00059303515816 , 16, true); // minus + zero + dot + 3 zeros + 11 digits => 16 chars + ERROR TEST( -5.9303515816e-04 , 16, true); // same number: cannot fit in 16 chars even in scientific notation (17 chars) TEST( -0.0005930351581 , 16, false); // minus + zero + dot + 3 zeros + 10 digits => 16 chars TEST( 0.0000593035158168 , 16, true); // zero + dot + 4 zeros + 12 digits => 16 chars (w/ scientific notation) + ERROR TEST( 0.00005930351581 , 16, false); // zero + dot + 4 zeros + 10 digits => 16 chars TEST( -0.000059303515816 , 16, true); // minus + zero + dot + 4 zeros + 10 digits => 16 chars (w/ scientific notation) + ERROR TEST( -0.0000593035158 , 16, false); // minus + zero + dot + 4 zeros + 10 digits => 16 chars #ifdef ALWAYS_3_DIGITS_IN_EXPONENT TEST( 0.000059303515816 , 16, true); // zero + dot + 4 zeros + 11 digits => 16 chars (w/ scientific notation) + ERROR TEST( -0.00005930351581 , 16, true); // minus + zero + dot + 4 zeros + 10 digits => 16 chars (w/ scientific notation) + ERROR #else TEST( 0.000059303515816 , 16, false); // zero + dot + 4 zeros + 11 digits => 16 chars (w/ scientific notation) TEST( -0.00005930351581 , 16, false); // minus + zero + dot + 4 zeros + 10 digits => 16 chars (w/ scientific notation) #endif TEST( 123456789012.1 , 14, false); // 12 digits + dot + 1 digit => 14 chars TEST( -123456789012.1 , 15, false); // minus + 12 digits + dot + 1 digit => 14 chars TEST( 1234567890123.1 , 15, false); // 13 digits + dot + 1 digit => 15 chars TEST( -1234567890123.1 , 16, false); // minus + 13 digits + dot + 1 digit => 15 chars TEST( 1234567890123.12 , 16, false); // 13 digits + dot + 2 digit => 16 chars TEST( -1234567890123.12 , 16, true); // minus + 13 digits + dot + 2 digit => 16 chars + ERROR TEST( 1234567890123.123 , 16, true); // 13 digits + dot + 3 digit => 16 chars + ERROR TEST( -1234567890123.123 , 16, true); // minus + 13 digits + dot + 3 digit => 16 chars + ERROR // TEST( 12345678901234 , 14, false); // 14 digits => 14 chars TEST( 12345678901234. , 14, false); // same number TEST( 12345678901234.0 , 14, false); // same number TEST( 1.2345678901234e+13 , 14, false); // same number // TEST( -12345678901234 , 15, false); // minus + 14 digits => 15 chars TEST( -12345678901234. , 15, false); // same number TEST( -12345678901234.0 , 15, false); // same number TEST( -1.2345678901234e+13 , 15, false); // same number TEST( 12345678901234.1 , 16, false); // 14 digits + dot + 1 digit => 16 chars TEST( -12345678901234.1 , 15, true); // minus + 14 digits + dot + 1 digit => 15 chars + ERROR TEST( 12345678901234.12 , 16, true); // 14 digits + dot + 2 digit => 16 chars + ERROR TEST( -12345678901234.12 , 15, true); // minus + 15 digits + dot + 1 digit => 15 chars + ERROR // TEST( 123456789012345 , 15, false); // 15 digit => 15 chars TEST( 123456789012345. , 15, false); // same number TEST( 123456789012345.0 , 15, false); // same number TEST( 1.23456789012345e+14 , 15, false); // same number // TEST( -123456789012345 , 16, false); // minus + 15 digit => 16 chars TEST( -123456789012345. , 16, false); // same number TEST( -123456789012345.0 , 16, false); // same number TEST( -1.23456789012345e+14 , 16, false); // same number TEST( 123456789012345.1 , 15, true); // 15 digits + dot + 1 digit => 15 chars + ERROR TEST( -123456789012345.1 , 16, true); // minus + 15 digits + dot + 1 digit => 16 chars + ERROR // TEST( 1234567890123456 , 16, false); // 16 digits => 16 chars TEST( 1234567890123456. , 16, false); // same number TEST( 1234567890123456.0 , 16, false); // same number TEST( 1.234567890123456e+15 , 16, false); // same number // TEST( -1234567890123456 , 16, true); // minus + 6 digits => 16 chars TEST( -1234567890123456. , 16, true); // same number TEST( -1234567890123456.0 , 16, true); // same number TEST( -1.234567890123456e+15 , 16, true); // same number TEST( 1234567890123456.2 , 16, true); // 16 digits + dot + 1 digit => 16 chars + ERROR TEST( -1234567890123456.2 , 16, true); // minus + 16 digits + dot + 1 digit => 16 chars + ERROR // TEST( 12345678901234567 , 16, true); // 17 digits => 16 chars (w/ scientific notation) + ERROR TEST( 12345678901234567. , 16, true); // same number TEST( 1.2345678901234567e+16 , 16, true); // same number // TEST( -12345678901234567 , 16, true); // minus + 17 digits => 16 chars (w/ scientific notation) + ERROR TEST( -12345678901234567. , 16, true); // same number TEST(-1.2345678901234567e+16 , 16, true); // same number // TEST( 123456789012345678 , 16, true); // 18 digits => 16 chars (w/ scientific notation) + ERROR TEST( 123456789012345678. , 16, true); // same number TEST(1.23456789012345678e+17 , 16, true); // same number // TEST(-123456789012345678 , 16, true); // minus + 18 digits => 16 chars (w/ scientific notation) + ERROR TEST(-123456789012345678. , 16, true); // same number TEST(-1.23456789012345678e+17 , 16, true); // same number // TEST( 1234567890123456789 , 16, true); // 19 digits => 16 chars (w/ scientific notation) + ERROR TEST( 1234567890123456789. , 16, true); // same number TEST(1.234567890123456789e+18 , 16, true); // same number // TEST(-1234567890123456789 , 16, true); // minus + 19 digits => 16 chars (w/ scientific notation) + ERROR TEST(-1234567890123456789. , 16, true); // same number TEST(-1.234567890123456789e+18 , 16, true); // same number TEST(1.2345678901234567891e+19 , 16, true); TEST(-1.2345678901234567891e+19 , 16, true); TEST(1.23456789012345678901e+20 , 16, true); TEST(-1.23456789012345678901e+20 , 16, true); TEST(1.23456789012345678901e+99 , 16, true); TEST(-1.23456789012345678901e+99 , 16, true); TEST(1.23456789012345678901e+100 , 16, true); TEST(-1.23456789012345678901e+100 , 16, true); TEST( 100000000000000. , 15, false); // 15 digits => 15 chars TEST( -100000000000000. , 16, false); // minus + 15 digits => 15 chars TEST( 999999999999999. , 15, false); // 15 digits => 15 chars TEST( -999999999999999. , 16, false); // minus + 15 digits => 15 chars TEST( 1000000000000000. , 16, false); // 16 chars TEST( 1e+15 , 16, false); // same number TEST( 9999999999999998. , 16, false); // 16 chars TEST( -9999999999999998. , 16, true); // minus + 16 chars TEST( -9999999990099999. , 16, true); TEST( -10000000000000000. , 16, false); // minus + 17 chars => 16 digits (w/ scientific notation) #ifdef ALWAYS_3_DIGITS_IN_EXPONENT TEST( 10000000000000000. , 6, false); // 17 chars => 6 digits (w/ scientific notation) TEST( 1e16 , 6, false); TEST( -1000000000000000. , 7, false); // minus + 7 chars (w/ scientific notation) TEST( -1e+15 , 7, false); // same number #else TEST( 10000000000000000. , 5, false); // 17 chars => 5 digits (w/ scientific notation) TEST( 1e16 , 5, false); TEST( -1000000000000000. , 6, false); // minus + 7 chars (w/ scientific notation) TEST( -1e+15 , 6, false); // same number #endif TEST( -1e16 , 16, false); TEST( 1e17 , 16, false); TEST( -1e17 , 16, false); TEST( 1e18 , 16, false); TEST( -1e18 , 16, false); TEST( 1e19 , 16, false); TEST( -1e19 , 16, false); TEST( 1e20 , 16, false); TEST( -1e20 , 16, false); //TEST( 0 , 1, false); // zero => 1 char (MM: cannot execute this test with ftrapv) TEST( 1 , 1, false); // 1 digit => 1 char TEST( 9.9999999999e-4 , 16, false); #ifdef ALWAYS_3_DIGITS_IN_EXPONENT TEST( 1e-5 , 6, false); #else TEST( 1e-5 , 16, false); #endif TEST( 5.1e-4 , 7, false); #ifdef ALWAYS_3_DIGITS_IN_EXPONENT TEST( 5.1e-5 , 8, false); #else TEST( 5.1e-5 , 16, false); #endif TEST( 5.1e-6 , 16, false); TEST( 5.1e-7 , 16, false); TEST( 5.1e-8 , 16, false); TEST( 5.1e-9 , 16, false); TEST( 5.1e-10 , 16, false); TEST( 5.1e-11 , 16, false); TEST( 1e+99 , 16, false); TEST( -1e+99 , 16, false); TEST( 1e+100 , 16, false); TEST( -1e+100 , 16, false); TEST( 3.4584e+100 , 16, false); TEST( -3.4584e+100 , 16, false); TEST( 3.4584e+101 , 16, false); TEST( -3.4584e+101 , 16, false); TEST( 1e-99 , 16, false); TEST( -1e-99 , 16, false); TEST( 1e-100 , 16, false); TEST( -1e-100 , 16, false); TEST( 3.4584e-100 , 16, false); TEST( -3.4584e-100 , 16, false); TEST( 3.4584e-101 , 16, false); TEST( -3.4584e-101 , 16, false); // Tests failing due to double precision if (1234567890123456.1 != 1234567890123456.) { TEST( 1234567890123456.1 , 16, true); } // 16 digits + dot + 1 digit => 16 chars + ERROR else { TEST( 1234567890123456.1 , 16, false); } // 16 digits + dot + 1 digit => 16 chars + NO ERROR if ( 9999999999999999. != 1e+16 ) { TEST( 9999999999999999. , 16, false); } // 16 chars => 16 digits else { TEST( 9999999999999999. , 5, false); } // 16 chars => 5 digits (w/ scientific notation) if ( -9999999998999999. != -9.999999999e+15 ) { TEST( -9999999998999999. , 16, true); } else { TEST( -9999999998999999. , 16, false); } std::cout << "---> Failed test(s): " << err_count << " of " << test_count << std::endl << std::endl; // ---- RANDOM TESTS: const unsigned int random_count = 100000; int random_err_count = 0; int min_exp = std::numeric_limits::min_exponent10; int max_exp = std::numeric_limits::max_exponent10; std::cout << "Running " << random_count << " random tests." << std::endl << std::endl; for (unsigned int i = 0; i(std::rand()) * pow(10., rand_exp); if (rand != rand) {i--; continue;} // nan if (rand == std::numeric_limits::infinity()) {i--; continue;} // inf std::string s = to_string( rand ); //std::cout << s; if (s.size() > 16 || !s.compare("inf") || !s.compare("nan") ) { // std::cout << "\t--- FAIL" << std::endl; random_err_count += 1; continue; } if ( checkerror(rand, s) ) random_err_count += 1; // else // std::cout << "\t--- OK" << std::endl; } std::cout << "---> Failed random test(s): " << random_err_count << " of " << random_count << std::endl << std::endl; return err_count + random_err_count; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestDataElement.cxx000066400000000000000000000151741412732066400304050ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDataElement.h" #include "gdcmExplicitDataElement.h" #include "gdcmTag.h" #include "gdcmSwapper.h" #include inline void DebugElement(std::stringstream const &os) { std::ofstream of("/tmp/bla.bin", std::ios::binary); std::string str = os.str(); of.write(str.c_str(), str.size()); of.close(); } inline void WriteRead(gdcm::DataElement const &w, gdcm::DataElement &r) { // w will be written // r will be read back std::stringstream ss; w.Write(ss); r.Read(ss); } int TestDataElement1(const uint16_t group, const uint16_t element, const uint16_t vl) { const char *str; std::stringstream ss; // SimpleData Element, just group,element and length str = reinterpret_cast(&group); ss.write(str, sizeof(group)); str = reinterpret_cast(&element); ss.write(str, sizeof(element)); str = reinterpret_cast(&vl); ss.write(str, sizeof(vl)); // gdcm::DataElement de; // de.Read( ss ); // if( de.GetTag().GetGroup() != group || // de.GetTag().GetElement() != element || // de.GetVL() != vl ) // { // std::cerr << de << std::endl; // return 1; // } // // gdcm::DataElement de2; // WriteRead(de, de2); // if( !(de == de2) ) // { // std::cerr << de << std::endl; // std::cerr << de2 << std::endl; // return 1; // } return 0; } // Explicit int TestDataElement2(const uint16_t group, const uint16_t element, const char* vr, const char* value) { const char *str; const uint32_t vl = (uint32_t)strlen( value ); std::stringstream ss; // SimpleData Element, just group,element and length str = reinterpret_cast(&group); ss.write(str, sizeof(group)); str = reinterpret_cast(&element); ss.write(str, sizeof(element)); if( gdcm::VR::GetVRType(vr) == gdcm::VR::INVALID ) { std::cerr << "Test buggy" << std::endl; return 1; } ss.write(vr, strlen(vr) ); str = reinterpret_cast(&vl); ss.write(str, sizeof(vl)); assert( !(strlen(value) % 2) ); ss.write(value, strlen(value) ); //DebugElement(ss); gdcm::ExplicitDataElement de; de.Read( ss ); if( de.GetTag().GetGroup() != group || de.GetTag().GetElement() != element || de.GetVL() != vl ) { std::cerr << de << std::endl; return 1; } gdcm::ExplicitDataElement de2; WriteRead(de, de2); if( !(de == de2) ) { std::cerr << de << std::endl; std::cerr << de2 << std::endl; return 1; } return 0; } namespace { // Tests operator== and operator!= for various gdcm::DataElement objects. // Also tests comparing to itself, symmetry of the comparison operators // with respect to their operands, and consistency between // operator== and operator!=. // Note: This function recursively calls itself, in order to get a pointer // to an equivalent array of gdcm::DataElement objects. int TestDataElementEqualityComparison( const gdcm::DataElement* const equivalentDataElements = nullptr) { const unsigned int numberOfDataElements = 6; gdcm::DataElement dataElements[numberOfDataElements] = { gdcm::DataElement(gdcm::Tag(0, 0), 0, gdcm::VR::INVALID), gdcm::DataElement(gdcm::Tag(1, 1), 0, gdcm::VR::INVALID), gdcm::DataElement(gdcm::Tag(1, 1), 1, gdcm::VR::INVALID), gdcm::DataElement(gdcm::Tag(1, 1), 1, gdcm::VR::AE) }; dataElements[4].SetByteValue("\0", 2); dataElements[5].SetByteValue("123", 4); // Now all data elements of the array dataElements are different. if ( equivalentDataElements == nullptr ) { return TestDataElementEqualityComparison(dataElements); } // equivalentDataElements != NULL, and because this function // is called recursively, equivalentDataElements[i] is equivalent // to dataElements[i]. for (unsigned int i = 0; i < numberOfDataElements; ++i) { const gdcm::DataElement& dataElement = dataElements[i]; if ( ! (dataElement == dataElement) ) { std::cerr << "Error: A data element should compare equal to itself!\n"; return 1; } if ( dataElement != dataElement ) { std::cerr << "Error: A data element should not compare unequal to itself!\n"; return 1; } const gdcm::DataElement& equivalentDataElement = equivalentDataElements[i]; if ( ! (dataElement == equivalentDataElement) || ! (equivalentDataElement == dataElement ) ) { std::cerr << "Error: A data element should compare equal to an equivalent one!\n"; return 1; } if ( (dataElement != equivalentDataElement) || (equivalentDataElement != dataElement) ) { std::cerr << "Error: A data element should not compare unequal to an equivalent one!\n"; return 1; } for (unsigned int j = i + 1; j < numberOfDataElements; ++j) { // dataElements[j] is different from dataElements[i]. const gdcm::DataElement& differentDataElement = dataElements[j]; if ( (dataElement == differentDataElement) || (differentDataElement == dataElement) ) { std::cerr << "Error: A data element should not compare equal to a different one!\n"; return 1; } if ( !(dataElement != differentDataElement) || !(differentDataElement != dataElement) ) { std::cerr << "Error: A data element should compare unequal to a different one!\n"; return 1; } } } return 0; } } // End of unnamed namespace. // Test Data Element int TestDataElement(int , char *[]) { const uint16_t group = 0x0010; const uint16_t element = 0x0012; const uint16_t vl = 0x0; int r = 0; r += TestDataElement1(group, element, vl); r += TestDataElementEqualityComparison(); // Full DataElement //const char vr[] = "UN"; //const char value[] = "ABCDEFGHIJKLMNOP"; //r += TestDataElement2(group, element, vr, value); return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestDataSet.cxx000066400000000000000000000040331412732066400275370ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDataSet.h" #include "gdcmDataElement.h" #include "gdcmExplicitDataElement.h" #include "gdcmImplicitDataElement.h" int TestDataSet(int , char *[]) { gdcm::DataSet ds; std::cout << sizeof ds << std::endl; gdcm::DataElement d; ds.Insert(d); const gdcm::DataElement& r = ds.GetDataElement( gdcm::Tag(0,0) ); std::cout << r << std::endl; const gdcm::Tag t2 = gdcm::Tag(0x1234, 0x5678); gdcm::DataElement d2(t2); std::cout << d2 << std::endl; ds.Insert(d2); const gdcm::DataElement& r2 = ds.GetDataElement( t2 ); std::cout << r2 << std::endl; const gdcm::Tag t3 = gdcm::Tag(0x1234, 0x5679); gdcm::DataElement d3(t3); d3.SetVR( gdcm::VR::UL ); std::cout << d3 << std::endl; ds.Insert(d3); const gdcm::DataElement& r3 = ds.GetDataElement( t3 ); std::cout << r3 << std::endl; std::cout << "Size:" << ds.Size() << std::endl; if( ds.Size() != 3 ) { //return 1; } std::cout << "Print Dataset:" << std::endl; std::cout << ds << std::endl; const gdcm::DataElement &de1 = ds[ gdcm::Tag(0x0020,0x0037) ]; const gdcm::DataElement &de2 = ds(0x0020,0x0037); if( &de1 != &de2 ) return 1; std::cout << ds << std::endl; gdcm::DataElement de3; std::cout << de3 << std::endl; const gdcm::DataElement &de4 = ds(0x0,0x0); std::cout << de4 << std::endl; const gdcm::DataElement &de5 = ds(0x0,0x1); std::cout << de5 << std::endl; const gdcm::DataElement &de6 = ds(0x1,0x1); std::cout << de6 << std::endl; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestElement1.cxx000066400000000000000000000110161412732066400276630ustar00rootroot00000000000000/*========================================================================= 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 "gdcmElement.h" #include "gdcmDataSet.h" #define TPI 3.1415926535897931 namespace gdcm { int TestFL() { Element a = {{ (float)TPI }}; a.Print( std::cout ); std::cout << std::endl; Element b = {{ 0,1,2,3,4,5,6,7 }}; b.Print( std::cout ); std::cout << std::endl; float f[10] = {}; Element c; c.SetArray( f, sizeof(f), false); c.Print( std::cout ); std::cout << std::endl; { DataElement de = c.GetAsDataElement(); Element el; el.Set( de.GetValue() ); //el.SetFromDataElement( de ); } // Make sure this is possible to output as DataElement // an Element, in case one cannot use gdcm::Attribute // Eg. Sup 145 are not available -yet- { DataSet ds; Element el; el.SetValue(1.2f); DataElement de = el.GetAsDataElement(); de.SetTag( Tag(0x0048,0x0201) ); ds.Insert( de ); } return 0; } int TestFD() { Element a = {{ TPI }}; std::ostringstream os; a.Print( os ); const std::string st = os.str(); // important const char *s = st.c_str(); std::cout << s << std::endl; //double t = *reinterpret_cast(*s); //std::cout << t << std::endl; Element b; double array[] = { 1,2,3,4,5,6,7,9 }; b = reinterpret_cast& >( array ); b.Print( std::cout ); std::cout << std::endl; return 0; } int TestAS() { Element a = { "019Y" }; a.Print( std::cout ); std::cout << std::endl; // TODO this should not compile: Element b = {{ "019Yb" }}; (void)b;//to avoid the warning of b not being useful return 0; } int TestUL() { const signed char array[4] = {-78, 1, 0, 0}; // 434 { Element a; // reinterpret_cast< const Element& > ( array ); memcpy((void*)&a, array, 4); a.Print( std::cout ); } std::cout << std::endl; return 0; } int TestAT() { // = (0020,5000) : (0010,0010)\(0010,0020)\(0020,0013) Element a; Tag list[3]; list[0] = Tag(0x0010,0x0010); list[1] = Tag(0x0010,0x0020); list[2] = Tag(0x0020,0x0013); memcpy(&a, list, sizeof(list)); a.Print( std::cout ); std::cout << std::endl; Element b; b.SetArray( list, sizeof(list), false); b.Print( std::cout ); std::cout << std::endl; return 0; } int TestOB() { const unsigned char array[] = { 0x00,0x00,0x00,0x01,0x42,0x12,0xf9,0x22,0x00,0x31,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x03,0xfe,0x02,0x71 }; // Bad no such thing as 1-n for OB/OW: Element a; a.SetArray( array, sizeof(array), false); // reinterpret_cast< const Element& > ( array ); //memcpy((void*)&a, array, sizeof(array)); a.Print( std::cout ); std::cout << std::endl; Element b; b.SetArray( array, sizeof(array), false); // reinterpret_cast< const Element& > ( array ); //memcpy((void*)&a, array, sizeof(array)); b.Print( std::cout ); std::cout << std::endl; return 0; } int TestUSVM3() { Element a = {{ 0x0001, 0x0002, 0x0003 }}; a.Print( std::cout ); std::cout << std::endl; unsigned short tmp = a.GetValue(0); if( tmp != 0x0001 ) { return 1; } tmp = a.GetValue(1); if( tmp != 0x0002 ) { return 1; } tmp = a.GetValue(2); if( tmp != 0x0003 ) { return 1; } std::stringstream ss; a.Write( ss ); Element b; b.Read( ss ); b.Print( std::cout ); tmp = b.GetValue(0); if( tmp != 0x0001 ) { return 1; } tmp = b.GetValue(1); if( tmp != 0x0002 ) { return 1; } tmp = b.GetValue(2); if( tmp != 0x0003 ) { return 1; } std::cout << std::endl; return 0; } } int TestElement1(int , char *[]) { int r = 0; r += gdcm::TestFL(); r += gdcm::TestFD(); r += gdcm::TestAS(); r += gdcm::TestUSVM3(); r += gdcm::TestUL(); r += gdcm::TestOB(); r += gdcm::TestAT(); return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestElement2.cxx000066400000000000000000000027701412732066400276730ustar00rootroot00000000000000/*========================================================================= 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 "gdcmElement.h" #include "gdcmVR.h" struct dummy { unsigned short I[3]; }; // // template struct TagToElement; template<> struct TagToElement<0x0018,0x1624> { using Type = gdcm::Element; }; int TestElement2(int, char *[]) { gdcm::Element ref = {{0,1,2}}; ref.Print(std::cout); //dummy d = {{0,1,2}};//commenting out TagToElement<0x0018,0x1624>::Type t = {{1,2,3}}; t.Print( std::cout ); std::cout << std::endl; gdcm::Element ref2; // = {{1}}; ref2.SetLength(2); ref2.SetValue(1); ref2.Print(std::cout); std::cout << std::endl; gdcm::Element ref3; // = {{1}}; ref3.SetLength(4); ref3.SetValue(1,0); ref3.SetValue(2,1); ref3.Print(std::cout); std::cout << std::endl; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestElement3.cxx000066400000000000000000000216561412732066400277000ustar00rootroot00000000000000/*========================================================================= 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 struct AE { char Internal[16+1]; void Print(std::ostream &os) { os << Internal; } }; typedef enum { DAY = 'D', WEEK = 'W', MONTH = 'M', YEAR = 'Y' } DateFormat; //template struct ASValid; //template <> struct ASValid<'Y'> { }; struct AS { unsigned short N; unsigned char Format; void Print(std::ostream &os) { if( N < 1000 && (Format == 'D' || Format == 'W' || Format == 'M' || Format == 'Y' )) { os << std::setw(3) << std::setfill('0') << N << Format; } else { os << ""; } } }; struct AT { // Tag Internal; }; struct CS { char Internal[16]; }; struct DA { unsigned short Year : 12; unsigned short Month : 4; unsigned short Day : 5; void Print(std::ostream &os) { os << std::setw(4) << std::setfill('0') << Year; os << std::setw(2) << std::setfill('0') << Month; os << std::setw(2) << std::setfill('0') << Day; } }; struct date { unsigned short day : 5; // 1 to 31 unsigned short month : 4; // 1 to 12 unsigned short year : 12; /* 0 to 9999 (technically :11 should be enough for a couple of years...) */ void Print(std::ostream &os) { os << year << "." << (int)month << "." << (int)day; } }; struct DS { double Internal; // 16 bytes as integer would mean we can have 10^16 as max int // which only double can hold }; struct FL { float Internal; }; struct FD { double Internal; }; struct IS { int Internal; void Print(std::ostream &os) { os << Internal; } }; struct LO { char Internal[64]; void Print(std::ostream &os) { os << Internal; } }; struct LT { std::string Internal; void Print(std::ostream &os) { os << Internal.size(); os << std::endl; os << Internal; } }; struct OB { explicit OB(const char *array = 0, uint32_t length = 0):Internal(array),Length(length) {} void Print( std::ostream &os ) { const char *p = Internal; const char *end = Internal+Length; while(p != end) { os << "\\" << (int)*p++; } } private: const char *Internal; uint32_t Length; }; struct OF; struct OW; struct PN { char Component[5][64]; void Print(std::ostream &os) { //os << "Family Name Complex: " << Component[0] << std::endl; //os << "Given Name Complex: " << Component[1] << std::endl; //os << "Middle Name : " << Component[2] << std::endl; //os << "Name Suffix : " << Component[3] << std::endl; //os << "Name Prefix : " << Component[4] << std::endl; os << Component[0] << "^"; os << Component[1] << "^"; os << Component[2] << "^"; os << Component[3] << "^"; os << Component[4]; } }; struct SH { char Internal[16+1]; }; struct SL { signed long Internal; }; struct SQ; struct SS { signed short Internal; }; struct ST { std::string Internal; }; struct TM { unsigned short hours:5; unsigned short minutes:6; unsigned short seconds:6; unsigned int fracseconds:20; void Print(std::ostream &os) { os << std::setw(2) << std::setfill('0') << hours; os << std::setw(2) << std::setfill('0') << minutes; os << std::setw(2) << std::setfill('0') << seconds; os << "."; os << std::setw(6) << std::setfill('0') << fracseconds; } }; struct Tri { short Internal:2; //operator void *() const { return Internal; } operator short () const { return Internal; } }; struct DT { DA da; TM tm; Tri OffsetSign; unsigned short Hours:5; unsigned short Minutes:6; // YYYYMMDDHHMMSS.FFFFFF&ZZZZ void Print ( std::ostream &os) { da.Print( os ); tm.Print( os ); if( OffsetSign ) { if ( OffsetSign == -1 ) os << "-"; else if ( OffsetSign == +1 ) os << "+"; else return; os << std::setw(2) << std::setfill('0') << Hours; os << std::setw(2) << std::setfill('0') << Minutes; } } }; struct UI { char Internal[64+1]; void Print(std::ostream &os) { os << strlen(Internal) << std::endl; os << Internal; } }; struct UL { unsigned long Internal; }; struct UN { std::vector Internal; }; struct US { unsigned short Internal; }; struct UT { std::string Internal; }; struct S { union { char s[2]; } Internal; //unsigned short Internal; void Print( std::ostream &os ) { os << strlen( Internal.s ) << std::endl; os << Internal.s; } }; int main() { AE ae = { "application enti" }; ae.Print( std::cout ); std::cout << std::endl; AS as = { 1, 'Y' }; as.Print( std::cout ); std::cout << std::endl; DA da = { 10978, 11, 32 }; da.Print( std::cout ); std::cout << std::endl; std::cout << "DA:" << sizeof (DA) << std::endl; double dd = 10*10*10*10*10*10*10*10; std::cout << dd << std::endl; DS ds = { 10*10*10*10*10*10*10*10 + 1 }; std::cout << ds.Internal << std::endl; DT dt = { 1979, 7, 6 }; dt.Print( std::cout << "DT: " ); std::cout << std::endl; DT dt1 = { 1979, 7, 6, 23, 59, 59, 999999 }; dt1.Print( std::cout << "DT: " ); std::cout << std::endl; DT dt2 = { 1979, 7, 6, 23, 59, 59, 999999, -1, 12, 42 }; dt2.Print( std::cout << "DT: " ); std::cout << std::endl; DT dt3 = { 1979, 7, 6, 23, 59, 59, 999999, +1, 12, 42 }; dt3.Print( std::cout << "DT: " ); std::cout << std::endl; IS is = { 2 << 30 }; is.Print( std::cout ); std::cout << std::endl; //std::cout << 8*8 << std::endl; //std::cout << 8*8*8*8 << std::endl; date d = {31, 12, 1978 }; d.Print( std::cout ); std::cout << std::endl; std::cout << "date:" << sizeof (date) << std::endl; LO lo = { "coucou" }; lo.Print( std::cout ); std::cout << std::endl; LT lt = { "very long text\0hello mathieu" }; lt.Print( std::cout ); std::cout << std::endl; OB ob("\0\1", 2); ob.Print( std::cout ); std::cout << std::endl; PN pn1 = { "abc123", "def", "ghi", "klm", "opq" }; pn1.Print( std::cout ); std::cout << std::endl; PN pn2 = { "malaterre", "mathieu olivier patrick"}; pn2.Print( std::cout ); std::cout << std::endl; // Rev. John Robert Quincy Adams, B.A. M.Div. Adams^John Robert Quincy^^Rev.^B.A. M.Div. [One family name; three given names; no middle name; one prefix; two suffixes.] PN pn3 = { "Adams", "John Robert Quincy", "", "Rev.", "B.A. M.Div." }; pn3.Print( std::cout ); std::cout << std::endl; // Susan Morrison-Jones, Ph.D., Chief Executive Officer Morrison-Jones^Susan^^^Ph.D., Chief Executive Officer [Two family names; one given name; no middle name; no prefix; two suffixes.] PN pn4 = { "Morrison-Jones", "Susan", "", "", "Ph.D., Chief Executive Officer" }; pn4.Print( std::cout ); std::cout << std::endl; // John Doe Doe^John [One family name; one given name; no middle name, prefix, or suffix. Delimiters have been omitted for the three trailing null components.] PN pn5 = { "Doe", "John" }; pn5.Print( std::cout ); std::cout << std::endl; // (for examples of the encoding of Person Names using multi-byte character sets see Annex H) // Smith^Fluffy [A cat, rather than a //human, whose responsible party family name is Smith, and whose own name is Fluffy] PN pn6 = { "Smith", "Fluffy" }; pn6.Print( std::cout ); std::cout << std::endl; //ABC Farms^Running on Water [A horse whose responsible organization is named ABC Farms, and whose name is Running On Water] PN pn7 = { "ABC Farms", "Running on Water" }; pn7.Print( std::cout ); std::cout << std::endl; std::cout << "TM:" << sizeof (TM) << std::endl; TM tm1 = { 7, 12, 49, 999999 }; tm1.Print( std::cout ); std::cout << std::endl; TM tm2 = { 23, 59, 59, 999999 }; tm2.Print( std::cout ); std::cout << std::endl; TM tm3 = { 0, 0, 0, 0 }; tm3.Print( std::cout ); std::cout << std::endl; UI ui = { "1234567890.1234567890.1234567890.1234567890.1234567890.123456789" }; ui.Print( std::cout ); std::cout << std::endl; //S s = "10"; S s = { '1' }; s.Print(std::cout); std::cout << std::endl; std::cout << "Tri:" << std::endl; Tri t1 = { 0 }; std::cout << t1.Internal << std::endl; Tri t2 = { 1 }; std::cout << t2.Internal << std::endl; Tri t3 = { 2 }; std::cout << t3.Internal << std::endl; Tri t4 = { 3 }; std::cout << t4.Internal << std::endl; Tri t5 = { '+' }; std::cout << t5.Internal << std::endl; Tri t6 = { '-' }; std::cout << t6.Internal << std::endl; Tri t7 = { -1 }; std::cout << t7.Internal << std::endl; //DateFormat df = 'Y'; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestElement4.cxx000066400000000000000000000014211412732066400276650ustar00rootroot00000000000000/*========================================================================= 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 struct A { float Internal; }; struct B { float Internal[1]; }; int TestElement4(int, char *[]) { std::cout << sizeof( A ) << std::endl; std::cout << sizeof( B ) << std::endl; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestElement5.cxx000066400000000000000000000034411412732066400276720ustar00rootroot00000000000000/*========================================================================= 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 "gdcmElement.h" #include "gdcmVR.h" #include int TestLO() { gdcm::Element el; const char str[] = "WINDOW1\\WINDOW2\\WINDOW3"; const size_t lenstr = strlen(str); std::stringstream ss; ss.str( str ); size_t count = gdcm::VM::GetNumberOfElementsFromArray(str, lenstr); gdcm::VR vr = gdcm::VR::LO; //gdcm::VM vm = gdcm::VM::VM2; //gdcm::VR vr = gdcm::VR::DS; //if( len != vr.GetSizeof() * vm.GetLength() ) // { // return 1; // } el.SetLength( count * vr.GetSizeof() ); el.Read( ss ); std::cout << el.GetLength() << std::endl; std::cout << el.GetValue(0) << std::endl; std::cout << el.GetValue(1) << std::endl; return 1; } int TestElement5(int , char *[]) { gdcm::Element spacing; const char strspacing[] = "1.2345\\6.7890"; std::stringstream ss; ss.str( strspacing ); unsigned int len = 2 * sizeof(double); gdcm::VM vm = gdcm::VM::VM2; gdcm::VR vr = gdcm::VR::DS; if( len != vr.GetSizeof() * vm.GetLength() ) { return 1; } spacing.SetLength( len ); spacing.Read( ss ); std::cout << spacing.GetValue() << std::endl; std::cout << spacing.GetValue(1) << std::endl; //int res = TestLO(); return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestElement6.cxx000066400000000000000000000027001412732066400276700ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAttribute.h" #include "gdcmElement.h" #include "gdcmVR.h" #include int TestElement6(int , char *[]) { gdcm::Attribute<0x18,0x1310> at = {{ 0, 256, 256, 0 }}; gdcm::DataElement de = at.GetAsDataElement(); const gdcm::Tag & t = at.GetTag(); (void)t; const gdcm::VM vm = gdcm::VM::VM4; // mimic string filter behavior: const char input[] = R"(0\256\256\0)"; const char * value = input; const size_t len = strlen( input ); std::istringstream is; std::ostringstream os; std::string s(value,value+len); is.str( s ); gdcm::VL vl = 8; gdcm::Element el; el.SetLength( vl ); for(unsigned int i = 0; i < vm.GetLength(); ++i) { is >> el.GetValue(i); is.get(); std::cout << el.GetValue(i) << std::endl; } el.Write(os); std::string s2 = os.str(); std::cout << s2.size() << std::endl; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestExplicitDataElement.cxx000066400000000000000000000065251412732066400321070ustar00rootroot00000000000000/*========================================================================= 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 "gdcmExplicitDataElement.h" #include "gdcmStringStream.h" #include "gdcmSwapper.h" int TestExplicitDataElement1(const uint16_t group, const uint16_t element, const char* vr, const uint32_t vl) { const char *str; std::stringstream ss; str = reinterpret_cast(&group); ss.write(str, sizeof(group)); str = reinterpret_cast(&element); ss.write(str, sizeof(element)); str = vr; ss.write(str, 2); ss.write("\0\0", 2); str = reinterpret_cast(&vl); ss.write(str, sizeof(vl)); gdcm::ExplicitDataElement de; if( !de.Read(ss) ) { std::cerr << de << std::endl; return 1; } if( de.GetTag().GetGroup() != group || de.GetTag().GetElement() != element || de.GetVL() != vl ) { std::cerr << de << std::endl; return 1; } std::cout << de << std::endl; return 0; } int TestExplicitDataElement2(const uint16_t group, const uint16_t element, const char *vr, const char *value) { const char *str; const uint32_t vl = strlen(value); std::stringstream ss; str = reinterpret_cast(&group); ss.write(str, sizeof(group)); str = reinterpret_cast(&element); ss.write(str, sizeof(element)); str = vr; ss.write(str, 2); ss.write("\0\0", 2); str = reinterpret_cast(&vl); ss.write(str, sizeof(vl)); str = value; ss.write(str, vl); gdcm::ExplicitDataElement de; if( !de.Read(ss) ) { std::cerr << de << std::endl; return 1; } if( de.GetTag().GetGroup() != group || de.GetTag().GetElement() != element || de.GetVL() != vl ) { std::cerr << de << std::endl; return 1; } std::cout << de << std::endl; return 0; } inline void WriteRead(gdcm::DataElement const &w, gdcm::DataElement &r) { // w will be written // r will be read back std::stringstream ss; w.Write(ss); r.Read(ss); } int TestExplicitDataElement(int, char *[]) { const uint16_t group = 0x0010; const uint16_t element = 0x0012; const char vr[] = "UN"; // UN => 4bytes vl const uint32_t vl = 0x0; // 4 bytes const char value[] = "GDCM"; int r = 0; r += TestExplicitDataElement1(group, element, vr, vl); r += TestExplicitDataElement2(group, element, vr, value); gdcm::ExplicitDataElement de1(gdcm::Tag(0x1234, 0x5678), 0x4321); gdcm::ExplicitDataElement de2(gdcm::Tag(0x1234, 0x6789), 0x9876); WriteRead(de1, de2); if( !(de1 == de2) ) { std::cerr << de1 << std::endl; std::cerr << de2 << std::endl; return 1; } return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestFile.cxx000066400000000000000000000014701412732066400270730ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFile.h" #include "gdcmSmartPointer.h" int TestFile(int argc, char *argv[]) { (void)argc; (void)argv; gdcm::File f; gdcm::SmartPointer pf = new gdcm::File; { gdcm::SmartPointer other = pf; } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestFileMetaInformation.cxx000066400000000000000000000023511412732066400321070ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileMetaInformation.h" #include "gdcmReader.h" #include "gdcmTesting.h" int TestFileMetaInformation(int, char *[]) { std::string dataroot = gdcm::Testing::GetDataRoot(); std::string filename = dataroot + "/012345.002.050.dcm"; gdcm::Reader reader; reader.SetFileName(filename.c_str()); if ( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::File& fi = reader.GetFile(); const gdcm::FileMetaInformation& hd = fi.GetHeader(); std::stringstream ss; hd.Write(ss); gdcm::FileMetaInformation hd2; // FAIL //hd2.Read(ss); // WORKS //ss.ignore(132); //hd2.Read(ss); return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestFileSet.cxx000066400000000000000000000014511412732066400275460ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileSet.h" #include "gdcmFile.h" int TestFileSet(int argc, char *argv[]) { (void)argc; (void)argv; gdcm::FileSet fs; std::string f1; std::string f2; fs.AddFile( f1.c_str() ); fs.AddFile( f2.c_str() ); return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestFragment.cxx000066400000000000000000000013361412732066400277600ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFragment.h" int TestFragment(int argc, char *argv[]) { (void)argc; (void)argv; gdcm::Fragment frag; std::cout << frag << std::endl; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestImplicitDataElement.cxx000066400000000000000000000064131412732066400320740ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImplicitDataElement.h" #include "gdcmStringStream.h" #include "gdcmSwapper.h" int TestImplicitDataElement1(const uint16_t group, const uint16_t element, const uint32_t vl) { const char *str; std::stringstream ss; str = reinterpret_cast(&group); ss.write(str, sizeof(group)); str = reinterpret_cast(&element); ss.write(str, sizeof(element)); str = reinterpret_cast(&vl); ss.write(str, sizeof(vl)); gdcm::ImplicitDataElement de; if( !de.Read(ss) ) { std::cerr << de << std::endl; return 1; } if( de.GetTag().GetGroup() != group || de.GetTag().GetElement() != element || de.GetVL() != vl ) { std::cerr << de << std::endl; return 1; } std::cout << de << std::endl; return 0; } int TestImplicitDataElement2(const uint16_t group, const uint16_t element, const char *value) { const char *str; const uint32_t vl = strlen(value); std::stringstream ss; str = reinterpret_cast(&group); ss.write(str, sizeof(group)); str = reinterpret_cast(&element); ss.write(str, sizeof(element)); str = reinterpret_cast(&vl); ss.write(str, sizeof(vl)); str = value; ss.write(str, vl); gdcm::ImplicitDataElement de; if( !de.Read(ss) ) { std::cerr << de << std::endl; return 1; } if( de.GetTag().GetGroup() != group || de.GetTag().GetElement() != element || de.GetVL() != vl ) { std::cerr << de << std::endl; return 1; } const gdcm::ByteValue *bv = dynamic_cast(&de.GetValue()); if( !bv ) { return 1; } if( !(gdcm::ByteValue(value, vl) == *bv ) ) { return 1; } std::cout << de << std::endl; return 0; } inline void WriteRead(gdcm::DataElement const &w, gdcm::DataElement &r) { // w will be written // r will be read back std::stringstream ss; w.Write(ss); r.Read(ss); } int TestImplicitDataElement(int, char *[]) { const uint16_t group = 0x0010; const uint16_t element = 0x0012; const uint32_t vl = 0x0; const char value[] = "GDCM"; int r = 0; r += TestImplicitDataElement1(group, element, vl); r += TestImplicitDataElement2(group, element, value); gdcm::ImplicitDataElement de1(gdcm::Tag(0x1234, 0x5678), 0x4321); gdcm::ImplicitDataElement de2(gdcm::Tag(0x1234, 0x6789), 0x9876); WriteRead(de1, de2); if( !(de1 == de2) ) { std::cerr << de1 << std::endl; std::cerr << de2 << std::endl; return 1; } return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestInvalidDICOMFiles.cxx000066400000000000000000000113271412732066400313430ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmFileMetaInformation.h" #include "gdcmFile.h" #include "gdcmTesting.h" #include "gdcmMediaStorage.h" #include "gdcmSystem.h" struct element { const char *in; const char *inmd5; const char *outmd5; size_t outlen; }; // non of the input file can be read by DCMTK // output file was check against DCMTK on Aug 12 2010 (MM) static const element list[] = { { "Enhanced_MR_Image_Storage_PixelSpacingNotIn_0028_0030.dcm", "854653ae806c224bfae3f196af250311", "e6d42da08e33e526dab4626864a1580e", 26851994 }, { "Siemens_CT_Sensation64_has_VR_RT.dcm", "3388c4f8e35cdb3d9512823f71e2415b", "cc57ee3ff427b859d3022071c8f1be95", 526460 }, { "ITK-GDCM-1.2.2.saysExplicitVR-butIsImplicitVR.dcm", "1158160333e00c0d1f8a7fdcbe352cac", "7fb2ef887fa29b9a793242b28d4e8258", 199218 }, { "MR_Philips_Intera_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm", "a8091f92ae895c2ef70143487e29b7d3", "6bf002815fad665392acab24f09caa5e", 138596 }, { "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm", // still an issue !!! "aa07de9c01765602fe722e9ef2d8b92a", "aa07de9c01765602fe722e9ef2d8b92a", 2106660 }, { "MR_Philips_Intera_PrivateSequenceExplicitVR.dcm", "a8091f92ae895c2ef70143487e29b7d3", "6bf002815fad665392acab24f09caa5e", 138596 }, { "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm", "3bbffc4c87f4f5554fafad5f8a002552", "df0e01aae299317db1719e4de72b8937", 2106428 }, { "illegal_UN_stands_for_SQ.dcm", // JPR ?? "2e1aa4fbebd08bbdf252f57b8343a79a", "4c6832a4378f5d953c1e92fdcbe43666", 33972 }, }; int TestInvalidDICOMFiles(int , char *[]) { int r = 0; gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); const char *extradataroot = gdcm::Testing::GetDataExtraRoot(); if( !extradataroot ) { return 1; } if( !gdcm::System::FileIsDirectory(extradataroot) ) { std::cerr << "No such directory: " << extradataroot << std::endl; return 1; } static const size_t n = sizeof( list ) / sizeof( element ); for( size_t i = 0; i < n; ++i ) { const element &el = list[i]; std::string sfilename = extradataroot; sfilename += "/gdcmSampleData/images_of_interest/"; sfilename += el.in; // dcmdump --disable-cp246 ... const char *filename = sfilename.c_str(); if( !gdcm::System::FileExists(filename) ) { std::cerr << "No such file: " << filename << std::endl; return 1; } gdcm::Reader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { std::cerr << "TestReadError: Failed to read: " << filename << std::endl; return 1; } //const char *ref = gdcm::Testing::GetMediaStorageFromFile(filename); //std::cerr << "ref:" << ref << std::endl; char digest_str[33]; bool b = gdcm::Testing::ComputeFileMD5(filename, digest_str); if( !b ) return 1; std::string md5ref = el.inmd5; if( md5ref != digest_str ) { std::cerr << "pb: " << md5ref << " vs " << digest_str << std::endl; ++r; } const char subdir[] = "TestInvalidDICOMFiles"; // Create directory first: std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); } std::string outfilename = gdcm::Testing::GetTempFilename( filename, subdir ); std::cout << "Corrected to: " << outfilename << std::endl; gdcm::Writer writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); writer.SetCheckFileMetaInformation( false ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; ++r; } char digest_str2[33]; bool b2 = gdcm::Testing::ComputeFileMD5(outfilename.c_str(), digest_str2); if( !b2 ) return 1; std::string md5ref2 = el.outmd5; if( md5ref2 != digest_str2 ) { std::cerr << "pb: " << md5ref2 << " vs " << digest_str2 << std::endl; ++r; } // paranoid: size_t s = gdcm::System::FileSize(outfilename.c_str()); if ( s != el.outlen ) // identical in size ! { std::cerr << "pb size: " << s << std::endl; ++r; } } return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestItem.cxx000066400000000000000000000036051412732066400271140ustar00rootroot00000000000000/*========================================================================= 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 "gdcmItem.h" //#include "gdcmStringStream.h" #include "gdcmVR.h" #include "gdcmExplicitDataElement.h" #include "gdcmSwapper.h" void CreateDataElement(gdcm::ExplicitDataElement &de, int offset) { std::stringstream ss; gdcm::Tag tag(0x1234, (uint16_t)(0x5678+offset)); gdcm::VR vr = gdcm::VR::UN; const char str[] = "GDCM"; uint32_t len = (uint32_t)strlen(str); assert( sizeof(uint32_t) == 4 ); gdcm::ByteValue val(str, len); tag.Write(ss); vr.Write(ss); const char *slen = reinterpret_cast(&len); ss.write( slen, 4); val.Write(ss); #ifdef GDCM_WORDS_BIGENDIAN de.Read( ss ); #else de.Read( ss ); #endif std::cout << de << std::endl; } int TestItem(int , char *[]) { gdcm::Item item; std::cout << item << std::endl; gdcm::Item it1; gdcm::Item it2; gdcm::DataSet ds; gdcm::ExplicitDataElement xde; CreateDataElement(xde,0); ds.Insert( xde ); CreateDataElement(xde,1); ds.Insert( xde ); CreateDataElement(xde,2); ds.Insert( xde ); CreateDataElement(xde,3); ds.Insert( xde ); std::cout << ds << std::endl; // undefined by default: gdcm::Item it3; gdcm::VL vl = it3.GetVL(); if( !vl.IsUndefined() ) { return 1; } if( !it3.IsUndefinedLength() ) { return 1; } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestLCNumeric.cxx000066400000000000000000000037351412732066400300430ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAttribute.h" #include /* setenv */ #include int TestLCNumeric(int , char *[]) { //setenv("LC_NUMERIC", "fr_FR", 1); //const char ss[] = "LC_NUMERIC=fr_FR"; //setlocale(LC_NUMERIC,"C"); // Seems to only affect the local sscanf char *l = setlocale(LC_NUMERIC,"fr_FR.UTF-8"); if( !l ) { std::cerr << "Could not set LC_NUMERIC" << std::endl; return 1; } float a = 1. / 3; printf("Float: %f\n", a ); // The following affect all ostringstream try { //std::locale b = std::locale( "fr_FR" ); std::locale::global( std::locale( "fr_FR.UTF-8" ) ) ; //char *copy = strdup(ss); //putenv(copy); //free(copy); std::ostringstream os; os.imbue(std::locale::classic()); double d = 1.2; os << d; std::string s = os.str(); std::cout << "s:" << s << std::endl; std::string::size_type pos_comma = s.find( "," ); if( pos_comma != std::string::npos ) { std::cerr << "We found the comma symbol" << std::endl; return 1; } std::string::size_type pos_dot = s.find( "." ); if( pos_dot == std::string::npos ) { std::cerr << "We did not found the dot symbol" << std::endl; return 1; } } catch(std::exception &ex) { // ok something went wrong when setting up fr_FR locale. // just ignore for now std::cerr << "What: " << ex.what() << std::endl; } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestLO.cxx000066400000000000000000000022111412732066400265200ustar00rootroot00000000000000/*========================================================================= 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 "gdcmLO.h" #include int TestLO(int , char *[]) { gdcm::LO lo = "hello world !"; if( !lo.IsValid() ) return 1; const char str[] = "this is LO1 \\this is LO2 \\ this is LO 3 "; gdcm::LO lo1, lo2, lo3; std::stringstream ss; ss << str; ss >> lo1; ss.get(); std::cout << lo1 << std::endl; ss >> lo2; ss.get(); std::cout << lo2 << std::endl; ss >> lo3; ss.get(); std::cout << lo3 << std::endl; std::string toolong(65, ' '); gdcm::LO lo4 = gdcm::LO(toolong); std::cout << lo4.size() << std::endl; if ( lo4.IsValid() ) return 1; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestMediaStorage.cxx000066400000000000000000000063121412732066400305600ustar00rootroot00000000000000/*========================================================================= 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 "gdcmMediaStorage.h" #include "gdcmFile.h" #include "gdcmDataElement.h" int TestMediaStorage(int argc, char *argv[]) { (void)argc; (void)argv; gdcm::MediaStorage ms; if( !ms.IsUndefined() ) { std::cerr << "ms.IsUndefined" << std::endl; return 1; } ms = gdcm::MediaStorage::SecondaryCaptureImageStorage; if( ms != gdcm::MediaStorage::SecondaryCaptureImageStorage ) { std::cerr << "SecondaryCaptureImageStorage" << std::endl; return 1; } ms.GuessFromModality( "MR" ); if( ms != gdcm::MediaStorage::MRImageStorage ) { std::cerr << "MRImageStorage" << std::endl; return 1; } ms.GuessFromModality( "MR" , 3 ); if( ms != gdcm::MediaStorage::EnhancedMRImageStorage ) { std::cerr << "EnhancedMRImageStorage" << std::endl; return 1; } //checks *MSStrings[] and MSModalityTypes[] length gdcm::MediaStorage::MSType mst; for ( mst = gdcm::MediaStorage::MediaStorageDirectoryStorage; mst < gdcm::MediaStorage::MS_END; mst = (gdcm::MediaStorage::MSType)(mst + 1) ) { if ( gdcm::MediaStorage::GetMSString(mst) == nullptr ) { std::cerr << "GetMSString" << std::endl; return 1; } } mst = gdcm::MediaStorage::MS_END; if ( gdcm::MediaStorage::GetMSString(mst) != nullptr ) { std::cerr << "2: GetMSString" << std::endl; return 1; } gdcm::MediaStorage ms2; if ( ms2.GetModality() ) { return 1; } // MediaStorage is really poorly implemented. We need to add a test to avoid dev shooting themself in the foot. unsigned int nMSType = gdcm::MediaStorage::GetNumberOfMSType(); unsigned int nMSString = gdcm::MediaStorage::GetNumberOfMSString(); unsigned int nMSMod = gdcm::MediaStorage::GetNumberOfModality(); if( nMSType != nMSString || nMSType != nMSMod ) { std::cerr << "you are shooting yourself in the foot, dear.: " << nMSType << "," << nMSString << "," << nMSMod << std::endl; return 1; } { gdcm::File f; gdcm::DataSet &ds = f.GetDataSet(); gdcm::DataElement de; de.SetTag( gdcm::Tag(0x8,0x16) ); ds.Insert( de ); gdcm::MediaStorage ms3; ms3.SetFromFile( f ); if( ms3 != gdcm::MediaStorage::SecondaryCaptureImageStorage ) { std::cerr << "SecondaryCaptureImageStorage" << std::endl; return 1; } } { gdcm::File f; gdcm::FileMetaInformation &fmi = f.GetHeader(); gdcm::DataElement de; de.SetTag( gdcm::Tag(0x2,0x2) ); // de.SetByteValue( "", 0 ); fmi.Insert( de ); gdcm::MediaStorage ms4; ms4.SetFromFile( f ); if( ms4 != gdcm::MediaStorage::SecondaryCaptureImageStorage ) { std::cerr << "SecondaryCaptureImageStorage" << std::endl; return 1; } } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestPDBHeader.cxx000066400000000000000000000032631412732066400277340ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPDBHeader.h" #include "gdcmTesting.h" #include "gdcmReader.h" int TestPDBHeader(int , char *[]) { const char *dataroot = gdcm::Testing::GetDataRoot(); // gdcmData/GE_MR_0025xx1bProtocolDataBlock.dcm std::string filename = dataroot; filename += "/GE_MR_0025xx1bProtocolDataBlock.dcm"; gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } gdcm::PDBHeader pdb; const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); const gdcm::PrivateTag &t1 = pdb.GetPDBInfoTag(); bool found = false; int ret = 0; if( ds.FindDataElement( t1 ) ) { pdb.LoadFromDataElement( ds.GetDataElement( t1 ) ); pdb.Print( std::cout ); found = true; } if( !found ) { std::cerr << "no pdb tag found" << std::endl; ret = 1; } const gdcm::PDBElement &pe = pdb.GetPDBElementByName( "SEDESC" ); std::cout << pe << std::endl; if( pe.GetValue() != std::string("AX FSE T2") ) { std::cerr << "Value found: " << pe.GetValue() << std::endl; ret = 1; } return ret; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestParseException.cxx000066400000000000000000000012461412732066400311460ustar00rootroot00000000000000/*========================================================================= 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 "gdcmParseException.h" int TestParseException(int, char *[]) { gdcm::ParseException pe; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestParser.cxx000066400000000000000000000037211412732066400274510ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * Pseudo code for ultimately a SAX-like (Simple API for DICOM) */ #include "gdcmParser.h" #include #include #include // for putchar namespace gdcm { // FIXME #define XML_FMT_INT_MOD "l" static void startElement(void *userData, const Tag &name, const char *atts[]) { int i; int *depthPtr = (int *)userData; for (i = 0; i < *depthPtr; i++) putchar('\t'); std::cout << name << std::endl; *depthPtr += 1; } static void endElement(void *userData, const Tag &name) { int *depthPtr = (int *)userData; *depthPtr -= 1; } } // end namespace gdcm int TestParser(int argc, char *argv[]) { if( argc < 2 ) { return 1; } std::string filename = argv[1]; std::ifstream is( filename.c_str(), std::ios::binary ); std::cout << "---------------------------Parsing file :[" << filename << "]" << std::endl; char buf[BUFSIZ]; gdcm::Parser parser; bool done; int depth = 0; parser.SetUserData(&depth); parser.SetElementHandler(gdcm::startElement, gdcm::endElement); do { is.read(buf, sizeof(buf)); size_t len = is.gcount(); done = len < sizeof(buf); if ( parser.Parse(buf, len, done) ) { fprintf(stderr, "%s at line %" XML_FMT_INT_MOD "u\n", gdcm::Parser::GetErrorString(parser.GetErrorCode()), parser.GetCurrentByteIndex()); return 1; } } while (!done); is.close(); return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestPreamble.cxx000066400000000000000000000017451412732066400277500ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPreamble.h" #include "gdcmFileMetaInformation.h" int TestPreamble(int, char *[]) { { gdcm::Preamble p; } gdcm::FileMetaInformation * m_pFileMetaInformation = new gdcm::FileMetaInformation(); gdcm::Preamble *p = new gdcm::Preamble(); m_pFileMetaInformation->SetPreamble( *p ); m_pFileMetaInformation->Clear(); delete m_pFileMetaInformation; m_pFileMetaInformation = nullptr ; delete p; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestPrivateTag.cxx000066400000000000000000000051471412732066400302670ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPrivateTag.h" #include "gdcmDataSet.h" int TestPrivateTag(int , char * []) { gdcm::PrivateTag pt(0x29,0x1018,"SIEMENS CSA HEADER"); if( pt != gdcm::Tag(0x0029,0x18) ) { std::cerr << pt << std::endl; return 1; } if( pt.GetOwner() != std::string("SIEMENS CSA HEADER") ) { std::cerr << "[" << pt.GetOwner() << "]" << std::endl; return 1; } const char str[] = "0029,1019,SIEMENS CSA HEADER"; if( !pt.ReadFromCommaSeparatedString( str ) ) return 1; if( pt != gdcm::Tag(0x0029,0x19) ) { std::cerr << pt << std::endl; return 1; } if( pt.GetOwner() != std::string("SIEMENS CSA HEADER") ) { std::cerr << "[" << pt.GetOwner() << "]" << std::endl; return 1; } const gdcm::PrivateTag pt1(0x1,0x2,"BLA"); const char str0[] = ""; const char str1[] = "1,2,BLA"; const char str2[] = "1,65536,BLU"; const char str3[] = "65536,2,BLU"; const char str4[] = "65536,2"; if( pt.ReadFromCommaSeparatedString( nullptr ) ) { return 1; } if( pt.ReadFromCommaSeparatedString( str0 ) ) { return 1; } if( !pt.ReadFromCommaSeparatedString( str1 ) ) { return 1; } if( pt != pt1 ) { return 1; } if( pt.ReadFromCommaSeparatedString( str2 ) ) { return 1; } if( pt.ReadFromCommaSeparatedString( str3 ) ) { return 1; } if( pt.ReadFromCommaSeparatedString( str4 ) ) { return 1; } gdcm::PrivateTag null(0x0,0x0,nullptr); if( null.GetOwner() == nullptr ) { return 1; } const gdcm::PrivateTag nospaces(0x12,0x34,"Philips MR Imaging DD 001"); gdcm::PrivateTag spaces(0x12,0x34," Philips MR Imaging DD 001 "); if( nospaces != spaces ) return 1; spaces.SetOwner(" Philips MR Imaging DD 001 "); if( nospaces != spaces ) return 1; { // hand-craft Dataset fragment gdcm::DataSet ds; gdcm::DataElement de(gdcm::Tag(0x0029,0x0011), 0,gdcm::VR::LO); ds.Insert(de); // get private tag gdcm::PrivateTag pt0(0x0029, 0x0023, "Titi"); ds.GetDataElement(pt0); } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestReadPatientName.cxx000066400000000000000000000016011412732066400312110ustar00rootroot00000000000000/*========================================================================= 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 "gdcm.h" int TestReadPatientName(int argc, char *argv[]) { (void)argc; gdcm::Parser p; std::string filename = argv[1]; p.SetFileName( filename ); gdcm::Tag t(0x0010, 0x0010); const char *v = p.Request( t ); gdcm::Attributes pn( v ); std::cout << pn << std::endl; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestReader.cxx000066400000000000000000000047221412732066400274210ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmFileMetaInformation.h" #include "gdcmFile.h" #include "gdcmTesting.h" #include "gdcmMediaStorage.h" int TestRead(const char* filename, bool verbose = false) { if( verbose ) std::cout << "TestRead: " << filename << std::endl; gdcm::Reader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { std::cerr << "TestReadError: Failed to read: " << filename << std::endl; return 1; } //commenting out the fmi and ds to avoid warnings //const gdcm::FileMetaInformation &h = reader.GetFile().GetHeader(); //std::cout << h << std::endl; //const gdcm::DataSet &ds = reader.GetFile().GetDataSet(); //std::cout << ds << std::endl; const char *ref = gdcm::Testing::GetMediaStorageFromFile(filename); gdcm::MediaStorage ms; ms.SetFromFile( reader.GetFile() ); if( !ref ) { std::cerr << "TestReadError: Missing MediaStorage: " << filename << std::endl; std::cerr << "It should be: " << ms << std::endl; return 1; } if( ms.IsUndefined() && ref && *ref != 0 ) { std::cerr << "TestReadError: MediaStorage: " << filename << std::endl; std::cerr << "It should be instead: " << ref << std::endl; return 1; } // Make sure it is the right one: if( ref && *ref != 0 && ms != gdcm::MediaStorage::GetMSType(ref) ) { std::cerr << "Error: Found MediaStorage: " << ms << " for " << filename << std::endl; std::cerr << "It should be instead: " << ref << std::endl; return 1; } return 0; } int TestReader(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestRead(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestRead( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestReader2.cxx000066400000000000000000000035721412732066400275050ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmAttribute.h" #include "gdcmElement.h" #include "gdcmTesting.h" // D_CLUNIE_CT1_J2KI.dcm // int TestReader2(int , char *[]) { //const char *filename = argv[1]; std::string dataroot = gdcm::Testing::GetDataRoot(); std::string filename = dataroot + "/012345.002.050.dcm"; gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if ( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } const gdcm::DataSet &ds = reader.GetFile().GetDataSet(); //gdcm::Attribute<0x0008,0x0008> a1; //a1.Set( ds[ gdcm::Tag(0x0008,0x0008) ].GetValue() ); //a1.Print( std::cout ); gdcm::Attribute<0x0020,0x0037> a2; a2.SetFromDataElement( ds[ gdcm::Tag(0x0020,0x0037) ] ); a2.Print( std::cout ); std::cout << std::endl; /* // (0043,1013) SS 107\21\4\2\20 # 10, 5 ReconKernelParameters gdcm::Element el1; el1.Set( ds[ gdcm::Tag(0x0043,0x1013) ].GetValue() ); el1.Print( std::cout ); std::cout << std::endl; // (0043,1031) DS [-11.200000\9.700000] # 20, 2 RACoordOfTargetReconCentre gdcm::Element el2; el2.Set( ds[ gdcm::Tag(0x0043,0x1031) ].GetValue() ); el2.Print( std::cout ); std::cout << std::endl; */ return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestReader3.cxx000066400000000000000000000141311412732066400274770ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * OS Specific: need a POSIX system with mmap functionality */ #include #include #include #include // strstr // fstat #include #include #include /* close */ // open #include #include #include // mmap #include #include "gdcmFile.h" #include "gdcmDataSet.h" #include "gdcmFileMetaInformation.h" #include "gdcmSmartPointer.h" #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmSystem.h" #include "gdcmTesting.h" #include "gdcmAttribute.h" #if 0 class membuf: public std::streambuf { public: membuf(const char* filename) :std::streambuf() { hFile = CreateFileA( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); hFileMappingObject = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL); beg = MapViewOfFile(hFileMappingObject, FILE_MAP_READ, 0, 0, 0); char* e = (char*)beg; e += GetFileSize( hFile, NULL ); setg((char*)beg,(char*)beg,e); setp(&outBuf,&outBuf); } /// Close the memory mapping and the opened /// file. ~membuf() { UnmapViewOfFile(beg); CloseHandle( hFileMappingObject ); CloseHandle( hFile ); } private: /// We can't copy this. membuf(const membuf&); membuf& operator=(const membuf&); /// Outbuf buffer that is not used since we /// don't write to the memory map. char outBuf; HANDLE hFile,hFileMappingObject; /// Pointer to the beginning of the mapped /// memory area. LPVOID beg; }; #endif /* * http://beej.us/guide/bgipc/output/html/multipage/mmap.html * http://www.dba-oracle.com/oracle_tips_mount_options.htm */ class membuf : public std::streambuf { public: membuf(char* mem, size_t length) { setg(mem, mem, mem + length); setp(mem, mem + length); } std::streampos seekpos(std::streampos pos, std::ios_base::openmode) override { char *p = eback() + pos; if(p>=eback() && p <=egptr()) { setg(eback(),p,egptr()); return pos; } else return -1; } std::streampos seekoff(std::streamoff off, std::ios_base::seekdir dir, std::ios_base::openmode) override { char *p; switch(dir) { case std::ios_base::beg: p = eback() + off; break; case std::ios_base::cur: p = gptr() + off; break; case std::ios_base::end: p = egptr() + off; break; default: p = nullptr; break; } if(p>=eback() && p <= egptr()) { setg(eback(),p,egptr()); return {p-egptr()}; } else return -1; } }; std::istream & DoTheMMapRead(std::istream &is) { gdcm::Reader reader; reader.SetStream(is); reader.Read(); //gdcm::Dumper printer; //printer.SetFile ( reader.GetFile() ); //printer.Print( std::cout ); return is; } int TestRead3(const char *subdir, const char * filename) { /// FIXME Because GDCM is seeging back and forth in the DICOM file // we cannot just apply mmap on any file, so let's clean them first: // gdcm::Reader r; r.SetFileName( filename ); if( !r.Read() ) { return 1; } // // Create directory first: const char * tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir ) ) { gdcm::System::MakeDirectory( tmpdir ); //return 1; } const char * outfilename = gdcm::Testing::GetTempFilename( filename, subdir ); // HACK: gdcm::DataSet &ds = r.GetFile().GetDataSet(); gdcm::Attribute<0x0008,0x0018> at; if( !ds.FindDataElement( at.GetTag() ) || ds.GetDataElement( at.GetTag() ).IsEmpty() ) { const gdcm::UIComp dummyuid = "1.2.3.4.5.6.7.8.9.0"; at.SetValue( dummyuid ); ds.Replace( at.GetAsDataElement() ); } gdcm::Writer w; w.SetFile( r.GetFile() ); w.SetFileName( outfilename ); if( !w.Write() ) { return 1; } const char *path = outfilename; bool readonly = true; int flags = (readonly ? O_RDONLY : O_RDWR); int handle = ::open(path, flags, S_IRWXU); struct stat info; const bool success = ::fstat(handle, &info) != -1; if( !success ) return 1; off_t size = info.st_size; off_t offset = 0; char* hint = nullptr; void* data = ::mmap( hint, size, readonly ? PROT_READ : (PROT_READ | PROT_WRITE), readonly ? MAP_PRIVATE : MAP_SHARED, handle, offset ); if (data == MAP_FAILED) { return 1; } char *chardata = reinterpret_cast(data); membuf mb( chardata, size ); std::istream is(&mb) ; DoTheMMapRead(is); // cleanup assert( handle ); bool error = false; error = ::munmap(data, size) != 0 || error; error = ::close(handle) != 0 || error; handle = 0; if ( error ) return 1; return 0; } int TestReader3(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestRead3(argv[0], filename); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { if( strstr(filename, "IllegalGroup2ImplicitTS.dcm" ) == nullptr ) r += TestRead3( argv[0], filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestReader4.cxx000066400000000000000000000027761412732066400275140ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmTesting.h" // Reproduce issue #3538586 int TestReader4(int , char *[]) { const char subdir[] = "TestReader4"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); } std::string outfilename = tmpdir; outfilename += "/"; outfilename += "fake.jpg"; const unsigned char jpeg[] = { 0xFF,0xD8,0xFF,0xE0,0x00,0x10,0x4A,0x46 }; std::ofstream out( outfilename.c_str() ); out.write( (char*)jpeg, sizeof( jpeg ) ); out.close(); const char *filename = outfilename.c_str(); gdcm::Reader reader; reader.SetFileName( filename ); if ( reader.Read() ) { std::cerr << "Success to read zip file !: " << filename << std::endl; return 1; } if ( reader.Read() ) { std::cerr << "Success to read zip file !: " << filename << std::endl; return 1; } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestReaderCanRead.cxx000066400000000000000000000113041412732066400306310ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmTesting.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmWriter.h" #include "gdcmDirectory.h" int TestReadCanRead(const char *subdir, const char* filename, bool verbose = false) { if( verbose ) std::cout << "TestReadCanRead: " << filename << std::endl; bool b1, b2; gdcm::Reader reader; reader.SetFileName( filename ); b1 = reader.CanRead(); b2 = reader.Read(); gdcm::Filename fn( filename ); const char *name = fn.GetName(); int ret = 1; const char dicomdir_bad[] = "gdcmSampleData/ForSeriesTesting/Perfusion/DICOMDIR"; if( fn.EndWith( dicomdir_bad ) ) { ret = 0; } // This is not an error if you are in the black list: if( strcmp(name, "BuggedDicomWorksImage_Hopeless.dcm" ) == 0 || strcmp(name, "Philips_Wrong_Terminator_XX_0277" ) == 0 || strcmp(name, "DICOMDIR_noPATIENT_noSTUDY" ) == 0 || strcmp(name, "JpegLosslessMultiframePapyrus.pap" ) == 0 || strcmp(name, "Fish-1.img" ) == 0 || strcmp(name, "NM_FromJulius_Caesar.dcm" ) == 0 || strcmp(name, "Siemens-leonardo-bugged.dcm" ) == 0 || strcmp(name, "illegal_UN_stands_for_OB.dcm" ) == 0 || strcmp(name, "MR_PHILIPS_LargePreamble.dcm" ) == 0 || strcmp(name, "illegal_UN_stands_for_OB.dcm.secu" ) == 0 ) { ret = 0; } if ( (b1 && !b2) || (!b1 && b2) ) { std::cerr << "TestReadCanRead: incompatible result " << filename << std::endl; if( b1 ) std::cerr << "TestReadCanRead: CanRead was true: " << filename << std::endl; //assert( !ret ); return ret; } // Create directory first: std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = gdcm::Testing::GetTempFilename( filename, subdir ); if( b1 && b2 ) { gdcm::Writer writer; writer.SetFileName( outfilename.c_str() ); writer.GetFile().GetHeader().SetDataSetTransferSyntax( reader.GetFile().GetHeader().GetDataSetTransferSyntax() ); writer.GetFile().SetDataSet( reader.GetFile().GetDataSet() ); writer.SetCheckFileMetaInformation( false ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } gdcm::Reader reader2; reader2.SetFileName( outfilename.c_str() ); b1 = reader2.CanRead( ); //reader2.GetFile().GetHeader().GetPreamble().Remove(); //assert( reader2.GetFile().GetHeader().GetPreamble().IsEmpty() ); b2 = reader2.Read(); if ( (b1 && !b2) || (!b1 && b2) ) { std::cerr << "TestReadCanRead|Write: incompatible result " << outfilename << std::endl; if( b1 ) std::cerr << "TestReadCanRead|Write: CanRead was true: " << outfilename << std::endl; return 1; } } return 0; } int TestReadCanReadExtra() { const char *extradataroot = gdcm::Testing::GetDataExtraRoot(); if( !extradataroot ) { return 0; } if( !gdcm::System::FileIsDirectory(extradataroot) ) { std::cerr << "No such directory: " << extradataroot << std::endl; return 0; } gdcm::Directory d; unsigned int nfiles = d.Load( extradataroot, true ); // no recursion std::cout << "done retrieving file list. " << nfiles << " files found." << std::endl; gdcm::Directory::FilenamesType const & fns = d.GetFilenames(); int r = 0; for( gdcm::Directory::FilenamesType::const_iterator it = fns.begin(); it != fns.end(); ++it ) { const char *filename = it->c_str(); r += TestReadCanRead( "TestReaderCanReadExtra", filename ); } return r; } int TestReaderCanRead(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestReadCanRead(argv[0], filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestReadCanRead( argv[0], filename ); ++i; } //int r2 = TestReadCanReadExtra(); //r += r2; return r; } TestReaderSelectedPrivateGroups.cxx000066400000000000000000000046311412732066400335450ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/*========================================================================= 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 "gdcmReader.h" #include "gdcmFileMetaInformation.h" #include "gdcmFile.h" #include "gdcmTesting.h" #include "gdcmMediaStorage.h" #include "gdcmSystem.h" #include "gdcmDirectory.h" int TestReadSelectedPrivateGroups(const char* filename, bool verbose = false) { if( verbose ) std::cout << "TestRead: " << filename << std::endl; std::ifstream is( filename, std::ios::binary ); gdcm::Reader reader; reader.SetStream( is ); gdcm::PrivateTag group9(0x9,0x10,"GEMS_IDEN_01"); std::set selectedtags; selectedtags.insert ( group9 ); if ( !reader.ReadSelectedPrivateTags( selectedtags ) ) { std::cerr << "TestReadSelectedGroups: Failed to read: " << filename << std::endl; return 1; } std::streamoff outStreamOffset = is.tellg(); gdcm::File & file = reader.GetFile(); gdcm::DataSet & ds = file.GetDataSet(); if( verbose ) std::cout << ds << std::endl; const bool found = ds.FindDataElement(group9); if(verbose) std::cout << "{ \"" << filename << "\"," << outStreamOffset << " }," << std::endl; std::streamoff refoffset = gdcm::Testing::GetSelectedPrivateGroupOffsetFromFile(filename); if( refoffset != outStreamOffset ) { std::cerr << filename << ": " << outStreamOffset << " should be " << refoffset << " found: " << found << std::endl; return 1; } is.close(); return 0; } int TestReaderSelectedPrivateGroups(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestReadSelectedPrivateGroups(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestReadSelectedPrivateGroups( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestReaderSelectedTags.cxx000066400000000000000000000103011412732066400316770ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmFileMetaInformation.h" #include "gdcmFile.h" #include "gdcmTesting.h" #include "gdcmMediaStorage.h" #include "gdcmSystem.h" #include "gdcmDirectory.h" #include "gdcmFilename.h" int TestReadSelectedTags(const char* filename, bool verbose = false) { if( verbose ) std::cout << "TestRead: " << filename << std::endl; std::ifstream is( filename, std::ios::binary ); gdcm::Reader reader; reader.SetStream( is ); // Let's read up to Pixel Data Group Length el... gdcm::Tag pixeldatagl (0x7fe0,0x0000); std::set selectedtags; selectedtags.insert ( pixeldatagl ); if ( !reader.ReadSelectedTags( selectedtags ) ) { if( verbose ) std::cerr << "TestReadSelectedTags : Failed to read: " << filename << std::endl; return 1; } std::streamoff outStreamOffset = is.tellg(); if(verbose) std::cout << "{ \"" << filename << "\"," << outStreamOffset << " }," << std::endl; std::streamoff refoffset = gdcm::Testing::GetSelectedTagsOffsetFromFile(filename); if( refoffset != outStreamOffset ) { if( verbose || refoffset ) // when stored std::cerr << filename << ": " << outStreamOffset << " should be " << refoffset << std::endl; return 1; } size_t filesize = gdcm::System::FileSize(filename); assert( (size_t)refoffset <= filesize ); std::streamoff refoffset2 = gdcm::Testing::GetStreamOffsetFromFile(filename); (void)refoffset2; const gdcm::File & file = reader.GetFile(); //const gdcm::DataSet & ds = file.GetDataSet(); //const bool isfound = ds.FindDataElement( pixeldatagl ); const gdcm::FileMetaInformation & fmi = file.GetHeader(); const gdcm::TransferSyntax & ts = fmi.GetDataSetTransferSyntax(); gdcm::Filename fn( filename ); const char *name = fn.GetName(); // Special handling: bool checkconsist = true; if( strcmp(name, "DMCPACS_ExplicitImplicit_BogusIOP.dcm" ) == 0 ) { checkconsist = false; } if( (size_t)refoffset != filesize ) { if( checkconsist ) { if( ts.GetNegociatedType() == gdcm::TransferSyntax::Explicit ) { assert( refoffset + 12 == refoffset2 ); } else { assert( refoffset + 8 == refoffset2 ); } } } is.close(); return 0; } int TestReadSelectedTagsExtra() { const char *extradataroot = gdcm::Testing::GetDataExtraRoot(); if( !extradataroot ) { return 1; } if( !gdcm::System::FileIsDirectory(extradataroot) ) { std::cerr << "No such directory: " << extradataroot << std::endl; return 1; } gdcm::Directory d; unsigned int nfiles = d.Load( extradataroot, true ); // no recursion std::cout << "done retrieving file list. " << nfiles << " files found." << std::endl; gdcm::Directory::FilenamesType const & fns = d.GetFilenames(); int r = 0; for( gdcm::Directory::FilenamesType::const_iterator it = fns.begin(); it != fns.end(); ++it ) { const char *filename = it->c_str(); r += TestReadSelectedTags( filename ); } return r; } int TestReaderSelectedTags(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestReadSelectedTags(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestReadSelectedTags( filename ); //r += TestReadSelectedTags( filename , true); ++i; } // puposely discard gdcmDataExtra test, this is just an 'extra' test... int b2 = TestReadSelectedTagsExtra(); (void)b2; return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestReaderUpToTag1.cxx000066400000000000000000000064371412732066400307530ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmFileMetaInformation.h" #include "gdcmFile.h" #include "gdcmTesting.h" #include "gdcmMediaStorage.h" #include "gdcmSystem.h" #include "gdcmDirectory.h" static int TestReadUpToTag(const char* filename, bool verbose = false) { if( verbose ) std::cout << "TestRead: " << filename << std::endl; std::ifstream is( filename, std::ios::binary ); gdcm::Reader reader; reader.SetStream( is ); // Let's read up to Pixel Data el... gdcm::Tag pixeldata (0x7fe0,0x0010); std::set skiptags; // ... but do not read it (to skip mem allocation) skiptags.insert( pixeldata ); if ( !reader.ReadUpToTag( pixeldata, skiptags) ) { if( verbose ) std::cerr << "TestReadError: Failed to read: " << filename << std::endl; return 1; } is.clear(); std::streamoff outStreamOffset = is.tellg(); #if 0 const gdcm::FileMetaInformation &h = reader.GetFile().GetHeader(); const gdcm::DataSet &ds = reader.GetFile().GetDataSet(); std::cout << ds << std::endl; #endif if(verbose) std::cout << "{ \"" << filename << "\"," << outStreamOffset << " }," << std::endl; std::streamoff refoffset = gdcm::Testing::GetStreamOffsetFromFile(filename); if( refoffset != outStreamOffset && (refoffset || verbose) ) { std::cerr << filename << ": " << outStreamOffset << " should be " << refoffset << std::endl; return 1; } is.close(); return 0; } static int TestReadUpToTagExtra() { const char *extradataroot = gdcm::Testing::GetDataExtraRoot(); if( !extradataroot ) { return 1; } if( !gdcm::System::FileIsDirectory(extradataroot) ) { std::cerr << "No such directory: " << extradataroot << std::endl; return 1; } gdcm::Directory d; unsigned int nfiles = d.Load( extradataroot, true ); // no recursion std::cout << "done retrieving file list. " << nfiles << " files found." << std::endl; gdcm::Directory::FilenamesType const & fns = d.GetFilenames(); int r = 0; for( gdcm::Directory::FilenamesType::const_iterator it = fns.begin(); it != fns.end(); ++it ) { const char *filename = it->c_str(); r += TestReadUpToTag( filename ); } return r; } int TestReaderUpToTag1(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestReadUpToTag(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestReadUpToTag( filename ); ++i; } // puposely discard gdcmDataExtra test, this is just an 'extra' test... int b2 = TestReadUpToTagExtra(); (void)b2; return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestReaderUpToTag2.cxx000066400000000000000000000071161412732066400307470ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmFileMetaInformation.h" #include "gdcmFile.h" #include "gdcmTesting.h" #include "gdcmMediaStorage.h" #include "gdcmSystem.h" #include "gdcmDirectory.h" static int TestReadUpToTag2(const char* filename, bool verbose = false) { if( verbose ) std::cout << "TestRead: " << filename << std::endl; std::ifstream is( filename, std::ios::binary ); gdcm::Reader reader; reader.SetStream( is ); // Let's read up to end gdcm::Tag maxDataSetTag(0xffff,0xffff); gdcm::Tag pixeldata (0x7fe0,0x0010); std::set skiptags; // ... but do not read Pixel Data attribute (to skip mem allocation) skiptags.insert( pixeldata ); if ( !reader.ReadUpToTag( maxDataSetTag, skiptags) ) { std::cerr << "TestReadError: Failed to read: " << filename << std::endl; return 1; } std::streamoff outStreamOffset = is.tellg(); bool iseof = is.eof(); //commenting out for warning avoidance //const gdcm::FileMetaInformation &h = reader.GetFile().GetHeader(); const gdcm::DataSet &ds = reader.GetFile().GetDataSet(); //std::cout << ds << std::endl; if( ds.FindDataElement( pixeldata ) ) { std::cerr << "Found Pixel Data for: " << filename << std::endl; return 1; } if( !iseof ) { std::cerr << "Lost in out of space: " << outStreamOffset << " -> " << filename << std::endl; return 1; } if(verbose) std::cout << "{ \"" << filename << "\"," << outStreamOffset << " }," << std::endl; const std::streamoff refoffset = -1; if( refoffset != outStreamOffset ) { std::cerr << filename << ": " << outStreamOffset << " " << iseof << " should be " << refoffset << std::endl; return 1; } is.close(); return 0; } static int TestReadUpToTag2Extra() { const char *extradataroot = gdcm::Testing::GetDataExtraRoot(); if( !extradataroot ) { return 1; } if( !gdcm::System::FileIsDirectory(extradataroot) ) { std::cerr << "No such directory: " << extradataroot << std::endl; return 1; } gdcm::Directory d; unsigned int nfiles = d.Load( extradataroot, true ); // no recursion std::cout << "done retrieving file list. " << nfiles << " files found." << std::endl; gdcm::Directory::FilenamesType const & fns = d.GetFilenames(); int r = 0; for( gdcm::Directory::FilenamesType::const_iterator it = fns.begin(); it != fns.end(); ++it ) { const char *filename = it->c_str(); r += TestReadUpToTag2( filename ); } return r; } int TestReaderUpToTag2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestReadUpToTag2(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestReadUpToTag2( filename ); ++i; } // puposely discard gdcmDataExtra test, this is just an 'extra' test... int b2 = TestReadUpToTag2Extra(); (void)b2; return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestSequenceOfFragments.cxx000066400000000000000000000013261412732066400321200ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSequenceOfFragments.h" int TestSequenceOfFragments(int, char *[]) { gdcm::SequenceOfFragments sf; std::cout << sf << std::endl; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestSequenceOfItems.cxx000066400000000000000000000021311412732066400312460ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSequenceOfItems.h" int TestSequenceOfItems(int, char *[]) { gdcm::SequenceOfItems si; std::cout << si << std::endl; gdcm::VL vl = si.GetLength(); if( !vl.IsUndefined() ) { return 1; } if( !si.IsUndefinedLength() ) { return 1; } gdcm::SmartPointer sq = new gdcm::SequenceOfItems(); gdcm::DataElement des( gdcm::Tag(0xdead,0xbeef) ); des.SetVR(gdcm::VR::SQ); des.SetValue(*sq); if( !des.GetValueAsSQ()->IsUndefinedLength() ) { return 1; } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestSequenceOfItems2.cxx000066400000000000000000000050351412732066400313360ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSequenceOfItems.h" #include "gdcmReader.h" #include "gdcmTesting.h" #include "gdcmPrivateTag.h" int TestSequenceOfItems2(int, char *[]) { const char *dataroot = gdcm::Testing::GetDataRoot(); // gdcmData/AMIInvalidPrivateDefinedLengthSQasUN.dcm std::string filename = dataroot; filename += "/AMIInvalidPrivateDefinedLengthSQasUN.dcm"; gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } gdcm::PrivateTag pt(0x0009,0x10,"GEIIS"); const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); if( !ds.FindDataElement( pt ) ) { return 1; } const gdcm::DataElement &de = ds.GetDataElement( pt ); if( de.IsEmpty() ) return 1; std::cout << de << std::endl; gdcm::SmartPointer sqi = de.GetValueAsSQ(); if( !sqi ) return 1; //std::cout << *sqi << std::endl; //sqi->Print( std::cout ); gdcm::SequenceOfItems::SizeType n = sqi->GetNumberOfItems(); if( n != 1 ) return 1; const gdcm::Item & item = sqi->GetItem( 1 ); const gdcm::DataSet &subds = item.GetNestedDataSet(); // std::cout << subds << std::endl; gdcm::Tag ticonpixeldata(0x7fe0,0x0010); //const gdcm::DataElement &iconpixeldata = subds.GetDataElement( ticonpixeldata ); // const gdcm::ByteValue *bv = iconpixeldata.GetByteValue();//unused unless that lower #def is set to true // I could test that gdcm::JPEGCodec::GetHeaderInfo return JPEG file: // JPEG image data, JFIF standard 1.01 gdcm::PrivateTag tgeiiscompressiontype(0x7fd1,0x10,"GEIIS"); const gdcm::DataElement &geiiscompressiontype = subds.GetDataElement( tgeiiscompressiontype ); gdcm::Element el; el.SetFromDataElement( geiiscompressiontype ); unsigned int v = el.GetValue(); if( v != 26 ) return 1; #if 0 std::ofstream of( "/tmp/o.jpg", std::ios::binary ); of.write( bv->GetPointer(), bv->GetLength() ); of.close(); #endif return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestSequenceOfItems3.cxx000066400000000000000000000032171412732066400313370ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSequenceOfItems.h" #include "gdcmReader.h" #include "gdcmTesting.h" int TestSequenceOfItems3Func(const char * filename, bool verbose = false) { (void)verbose; gdcm::Reader r; r.SetFileName( filename ); if( !r.Read() ) { return 1; } gdcm::DataSet const& ds = r.GetFile().GetDataSet(); gdcm::DataSet::ConstIterator it = ds.Begin(); for( ; it != ds.End(); ++it) { const gdcm::DataElement &de = *it; gdcm::SmartPointer sqi = de.GetValueAsSQ(); if( sqi ) { std::stringstream ss; sqi->Print( ss ); // debug invalid read/write } } return 0; } int TestSequenceOfItems3(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestSequenceOfItems3Func(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestSequenceOfItems3Func( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestTag.cxx000066400000000000000000000206771412732066400267410ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTag.h" #include "gdcmSwapper.h" int TestPrivate() { gdcm::Tag t1(0x0009,0x0000); if( t1.IsPublic() ) { return 1; } if( !t1.IsPrivate() ) { return 1; } if( t1.IsPrivateCreator() ) { return 1; } gdcm::Tag t2(0x0009,0x0001); if( t2.IsPublic() ) { return 1; } if( !t2.IsPrivate() ) { return 1; } if( t2.IsPrivateCreator() ) { return 1; } gdcm::Tag t3(0x0009,0x0010); if( t3.IsPublic() ) { return 1; } if( !t3.IsPrivate() ) { return 1; } if( !t3.IsPrivateCreator() ) { return 1; } gdcm::Tag t4(0x0009,0x1010); gdcm::Tag t4_creator(0x0009,0x0010); if( t4.IsPublic() ) { return 1; } if( !t4.IsPrivate() ) { return 1; } if( t4.IsPrivateCreator() ) { return 1; } if( t4.GetPrivateCreator() != t4_creator ) { return 1; } return 0; } int TestPipePrintRead() { gdcm::Tag t(0x1234,0x5678); const char pipesep[] = "1234|5678"; gdcm::Tag tprime(0x0,0x0); if( !tprime.ReadFromPipeSeparatedString(pipesep) ) { return 1; } if( tprime != t ) return 1; std::string str = t.PrintAsPipeSeparatedString(); if( str != pipesep ) return 1; return 0; } int TestOperator() { gdcm::Tag t1(0x1234,0x5678); gdcm::Tag t1bis(0x1234,0x5678); gdcm::Tag t2(0x1234,0x5679); if( t2 < t1 ) { return 1; } if( !(t1 < t2) ) { return 1; } if( !(t1 == t1bis) ) { return 1; } if( !(t1 <= t1bis) ) { return 1; } return 0; } int TestTag(int , char * []) { { const uint32_t dummy = 0x12345678; gdcm::Tag t16(0x1234, 0x5678); std::stringstream ss; t16.Write( ss ); gdcm::Tag t16_2; t16_2.Read( ss ); gdcm::Tag t32( dummy ); if( t32 != t16 ) { return 1; } gdcm::Tag t1; gdcm::Tag t2(0,0); if ( t1[0] != 0 ) { std::cerr << "1" << std::endl; return 1; } if (t1[1] != 0 ) {std::cout << "2" << std::endl ; return 1; } if (t2[0] != 0 ) {std::cout << "3" << std::endl ; return 1; } if (t2[1] != 0 ) {std::cout << "4" << std::endl ; return 1; } if ( !(t1 == t2) ) {std::cout << "5" << std::endl ; return 1; } if ( t1 != t2 ) {std::cout << "6" << std::endl ; return 1; } if ( t1 < t2 ) {std::cout << "7" << std::endl ; return 1; } unsigned int i; const uint32_t tag = dummy; std::cout << "Just to inform : uint32_t value=" << std::hex << tag ; std::cout << " stored in RAM as :"; for (i=0;i> tag2; //std::istringstream is; //is.str( "1234567890" ); //is >> tag2; if( tag != tag2 ) { std::cout << tag << std::endl; std::cout << tag2 << std::endl; return 1; } } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestTorture.cxx000066400000000000000000000027471412732066400276700ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmFileMetaInformation.h" #include "gdcmDataImages.h" int TestTortureRead(const char* filename) { // TODO unsigned long copy = rand()*original_size; std::copy(new_file, filename); gdcm::Reader reader; reader.SetFileName( new_file ); if ( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } std::cerr << "Success to read: " << filename << std::endl; const gdcm::FileMetaInformation &h = reader.GetHeader(); std::cout << h << std::endl; const gdcm::DataSet &ds = reader.GetDataSet(); std::cout << ds << std::endl; return 0; } int TestTorture(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestRead(filename); } // else int r = 0, i = 0; const char *filename; while( (filename = gdcmDataImages[i]) ) { r += TestRead( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestTransferSyntax.cxx000066400000000000000000000065151412732066400312140ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTransferSyntax.h" static const int losslylosslessarray[][3] = { { 0, 1, 1 }, // ImplicitVRLittleEndian = 0, { 0, 1, 1 }, // ImplicitVRBigEndianPrivateGE, { 0, 1, 1 }, // ExplicitVRLittleEndian, { 0, 1, 1 }, // DeflatedExplicitVRLittleEndian, { 0, 1, 1 }, // ExplicitVRBigEndian, { 1, 0, 1 }, // JPEGBaselineProcess1, { 1, 0, 1 }, // JPEGExtendedProcess2_4, { 1, 0, 1 }, // JPEGExtendedProcess3_5, { 1, 0, 1 }, // JPEGSpectralSelectionProcess6_8, { 1, 0, 1 }, // JPEGFullProgressionProcess10_12, { 0, 1, 0 }, // JPEGLosslessProcess14, { 0, 1, 0 }, // JPEGLosslessProcess14_1, { 0, 1, 0 }, // JPEGLSLossless, { 1, 1, 1 }, // JPEGLSNearLossless, { 0, 1, 0 }, // JPEG2000Lossless, { 1, 1, 1 }, // JPEG2000, { 0, 1, 0 }, // JPEG2000Part2Lossless, { 1, 1, 1 }, // JPEG2000Part2, { 0, 1, 0 }, // RLELossless, { 1, 0, 1 }, // MPEG2MainProfile, { 0, 1, 1 }, // ImplicitVRBigEndianACRNEMA, #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION { 0, 1, 1 }, // WeirdPapryus, #endif { 0, 1, 1 }, // CT_private_ELE, { 1, 1, 1 }, // JPIPReferenced { 1, 0, 1 }, // MPEG2MainProfileHighLevel { 1, 0, 1 }, // MPEG4AVCH264HighProfileLevel4_1 { 1, 0, 1 }, // MPEG4AVCH264BDcompatibleHighProfileLevel4_1 }; static int TestTransferSyntaxAll() { for(int i = 0; i < gdcm::TransferSyntax::TS_END; ++i ) { gdcm::TransferSyntax ts = (gdcm::TransferSyntax::TSType)i; const int *ll = losslylosslessarray[i]; if( ll[0] ) { if( !ts.IsLossy() ) { std::cerr << "Lossy Problem with: " << gdcm::TransferSyntax::GetTSString( ts ) << std::endl; return 1; } } if( ll[1] ) { if( !ts.IsLossless() ) { std::cerr << "Lossless Problem with: " << gdcm::TransferSyntax::GetTSString( ts ) << std::endl; return 1; } } if( ll[2] ) { if( !ts.CanStoreLossy() ) { std::cerr << "CanLossy Problem with: " << gdcm::TransferSyntax::GetTSString( ts ) << std::endl; return 1; } } } return 0; } int TestTransferSyntax(int argc, char *argv[]) { (void)argc; (void)argv; if( TestTransferSyntaxAll() ) { return 1; } gdcm::TransferSyntax ts; ts = gdcm::TransferSyntax::JPEG2000; if( !ts.IsLossless() ) { return 1; } if( !ts.IsLossy() ) { return 1; } ts = gdcm::TransferSyntax::JPEGLosslessProcess14_1; if( !ts.IsLossless() ) { return 1; } if( ts.IsLossy() ) { return 1; } ts = gdcm::TransferSyntax::DeflatedExplicitVRLittleEndian; if( !ts.IsLossless() ) { return 1; } if( ts.IsLossy() ) { return 1; } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestVL.cxx000066400000000000000000000012551412732066400265360ustar00rootroot00000000000000/*========================================================================= 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 "gdcmVL.h" int TestVL(int, char *[]) { gdcm::VL vl; if( vl != 0 ) { return 1; } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestVM.cxx000066400000000000000000000135471412732066400265460ustar00rootroot00000000000000/*========================================================================= 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 "gdcmVM.h" #include // strcmp int TestVM(int, char *[]) { //gdcm::VM::VMType vm = gdcm::LengthToVM<1>::TVM; const char str1[] = " 1\\2"; const size_t count1 = gdcm::VM::GetNumberOfElementsFromArray(str1, (unsigned int)strlen(str1) ); if( count1 != 2 ) return 1; const char str2[] = " 1\\2\\3"; const size_t count2 = gdcm::VM::GetNumberOfElementsFromArray(str2, (unsigned int)strlen(str2) ); if( count2 != 3 ) return 1; const char str3[] = " 1"; const size_t count3 = gdcm::VM::GetNumberOfElementsFromArray(str3, (unsigned int)strlen(str3) ); if( count3 != 1 ) return 1; const char str4[] = ""; const size_t count4 = gdcm::VM::GetNumberOfElementsFromArray(str4, (unsigned int)strlen(str4) ); if( count4 != 0 ) return 1; const char *str5 = nullptr; const size_t count5 = gdcm::VM::GetNumberOfElementsFromArray(str5, 0); if( count5 != 0 ) return 1; const char str6[] = " 1"; const size_t count6 = gdcm::VM::GetNumberOfElementsFromArray(str6, (unsigned int)strlen(str6) ); if( count6 != 1 ) return 1; const char str7[] = " 1 \\ 2 "; const size_t count7 = gdcm::VM::GetNumberOfElementsFromArray(str7, (unsigned int)strlen(str7) ); if( count7 != 2 ) return 1; const char str8[] = " "; const size_t count8 = gdcm::VM::GetNumberOfElementsFromArray(str8, (unsigned int)strlen(str8) ); if( count8 != 0 ) { std::cerr << "count8 failed" << std::endl; return 1; } const char str9[] = " \\ "; const size_t count9 = gdcm::VM::GetNumberOfElementsFromArray(str9, (unsigned int)strlen(str9) ); if( count9 != 0 ) return 1; const char str10[] = " 3 \\ "; const size_t count10 = gdcm::VM::GetNumberOfElementsFromArray(str10, (unsigned int)strlen(str10) ); if( count10 != 1 ) return 1; // store invalid combinations inside an int array to trick the compiler // and avoid unreachable return code warning static const int error_combinations[] = { gdcm::VM::VM1 & gdcm::VM::VM2, gdcm::VM::VM1 & gdcm::VM::VM2, gdcm::VM::VM1 & gdcm::VM::VM3, gdcm::VM::VM1 & gdcm::VM::VM32, !(gdcm::VM::VM1 & gdcm::VM::VM1_2), !(gdcm::VM::VM2 & gdcm::VM::VM1_2), !(gdcm::VM::VM1 & gdcm::VM::VM1_3), !(gdcm::VM::VM2 & gdcm::VM::VM1_3), !(gdcm::VM::VM3 & gdcm::VM::VM1_3), !(gdcm::VM::VM1 & gdcm::VM::VM1_n), gdcm::VM::VM1 & gdcm::VM::VM2_n, !(gdcm::VM::VM2 & gdcm::VM::VM2_n), gdcm::VM::VM1 & gdcm::VM::VM3_4, !(gdcm::VM::VM3 & gdcm::VM::VM3_4), !(gdcm::VM::VM4 & gdcm::VM::VM3_4), gdcm::VM::VM1 & gdcm::VM::VM3_3n, !(gdcm::VM::VM3 & gdcm::VM::VM3_3n), !(gdcm::VM::VM9 & gdcm::VM::VM3_3n), !(gdcm::VM::VM99 & gdcm::VM::VM3_3n), gdcm::VM::VM1 & gdcm::VM::VM4_4n, !(gdcm::VM::VM4 & gdcm::VM::VM4_4n), }; static const int nerror_combinations = sizeof( error_combinations ) / sizeof( *error_combinations ); for( int i = 0; i < nerror_combinations; ++i ) { if( error_combinations[i] ) return 1; } const char *vm1 = gdcm::VM::GetVMString( gdcm::VM::VM1 ); if( strcmp(vm1, "1" ) != 0 ) { std::cerr << "Error:" << vm1 << std::endl; return 1; } const char *vm8 = gdcm::VM::GetVMString( gdcm::VM::VM8 ); if( strcmp(vm8, "8" ) != 0 ) { std::cerr << "Error:" << vm8 << std::endl; return 1; } gdcm::VM vm = gdcm::VM::VM0; std::cout << vm << std::endl; vm = gdcm::VM::VM1; std::cout << vm << std::endl; vm = gdcm::VM::VM2; std::cout << vm << std::endl; vm = gdcm::VM::VM3; std::cout << vm << std::endl; vm = gdcm::VM::VM4; std::cout << vm << std::endl; vm = gdcm::VM::VM5; std::cout << vm << std::endl; vm = gdcm::VM::VM6; std::cout << vm << std::endl; vm = gdcm::VM::VM8; std::cout << vm << std::endl; vm = gdcm::VM::VM9; std::cout << vm << std::endl; vm = gdcm::VM::VM10; std::cout << vm << std::endl; vm = gdcm::VM::VM12; std::cout << vm << std::endl; vm = gdcm::VM::VM16; std::cout << vm << std::endl; vm = gdcm::VM::VM18; std::cout << vm << std::endl; vm = gdcm::VM::VM24; std::cout << vm << std::endl; vm = gdcm::VM::VM28; std::cout << vm << std::endl; vm = gdcm::VM::VM32; std::cout << vm << std::endl; vm = gdcm::VM::VM35; std::cout << vm << std::endl; vm = gdcm::VM::VM99; std::cout << vm << std::endl; vm = gdcm::VM::VM256; std::cout << vm << std::endl; vm = gdcm::VM::VM1_2; std::cout << vm << std::endl; vm = gdcm::VM::VM1_3; std::cout << vm << std::endl; vm = gdcm::VM::VM1_4; std::cout << vm << std::endl; vm = gdcm::VM::VM1_5; std::cout << vm << std::endl; vm = gdcm::VM::VM1_8; std::cout << vm << std::endl; vm = gdcm::VM::VM1_32; std::cout << vm << std::endl; vm = gdcm::VM::VM1_99; std::cout << vm << std::endl; vm = gdcm::VM::VM1_n; std::cout << vm << std::endl; vm = gdcm::VM::VM2_2n; std::cout << vm << std::endl; vm = gdcm::VM::VM2_n; std::cout << vm << std::endl; vm = gdcm::VM::VM3_4; std::cout << vm << std::endl; vm = gdcm::VM::VM3_3n; std::cout << vm << std::endl; vm = gdcm::VM::VM3_n; std::cout << vm << std::endl; vm = gdcm::VM::VM4_4n; std::cout << vm << std::endl; vm = gdcm::VM::VM7_7n; std::cout << vm << std::endl; //vm = gdcm::VM::VM_END; //std::cout << vm << std::endl; { gdcm::VM vm1_ = gdcm::VM::VM8; gdcm::VM vm2_ = gdcm::VM::VM1_n; if ( !vm2_.Compatible( vm1_ ) ) { return 1; } } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestVR.cxx000066400000000000000000000172111412732066400265430ustar00rootroot00000000000000/*========================================================================= 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 "gdcmVR.h" #include static int TestEnumString(std::string const & rep, gdcm::VR::VRType vr) { const std::string & odstr = rep; gdcm::VR::VRType od = gdcm::VR::GetVRTypeFromFile(odstr.c_str()); if( od != vr ) return 1; const char *odcstr = gdcm::VR::GetVRStringFromFile(vr); if( odstr != odcstr ) return 1; od = gdcm::VR::GetVRType(odstr.c_str()); if( od != vr ) return 1; odcstr = gdcm::VR::GetVRString(vr); if( !gdcm::VR::IsValid(odstr.c_str())) return 1; return 0; } // Not used... int verify() { // avoid INVALID = 0 for(int i = 1; i < 27; ++i) { gdcm::VR t = (gdcm::VR::VRType)(1 << i); if( gdcm::VR::IsASCII( t ) != gdcm::VR::IsASCII2( t ) ) { std::cerr << t << std::endl; return 1; } //if( gdcm::VR::IsBinary( t ) != gdcm::VR::IsBinary2( t ) ) // { // std::cerr << t << std::endl; //// return 1; // } } return 0; } int TestValue() { int k = 0; gdcm::VR vr; vr = gdcm::VR::INVALID; // = 0, if( (int)vr != 0 ) return 1; vr = gdcm::VR::AE; // = 1, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::AS; // = 2, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::AT; // = 4, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::CS; // = 8, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::DA; // = 16, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::DS; // = 32, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::DT; // = 64, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::FD; // = 256, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::FL; // = 128, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::IS; // = 512, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::LO; // = 1024, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::LT; // = 2048, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::OB; // = 4096, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::OF; // = 8192, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::OW; // = 16384, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::PN; // = 32768, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::SH; // = 65536, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::SL; // = 131072, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::SQ; // = 262144, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::SS; // = 524288, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::ST; // = 1048576, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::TM; // = 2097152, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::UI; // = 4194304, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::UL; // = 8388608, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::UN; // = 16777216, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::US; // = 33554432, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::UT; // = 67108864, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::OD; // = 134217728, if( (int)vr != (1 << k++) ) return 1; vr = gdcm::VR::OL; // = 268435456, if( (int)vr != (1 << k++) ) return 1; return 0; } int TestVR(int, char *[]) { enum { V1 = 0ULL, V2 = 4294967295ULL } E4; std::cout << sizeof E4 << std::endl; enum { V3 = 0ULL, V4 = 4294967296ULL } E8; enum : long long { V5 = 0ULL, V6 = 4294967296ULL } E8ll; std::cout << sizeof E8 << std::endl; if( sizeof E4 != 4 ) { std::cerr << "E4 is: " << sizeof E4 << std::endl; return 1; } if( sizeof E8 != 8 ) { // bad bad compiler std::cerr << "E8 is: " << sizeof E8 << std::endl; } if( sizeof E8ll != 8 ) { std::cerr << "E8ll is: " << sizeof E8 << std::endl; return 1; } if( TestValue() ) return 1; gdcm::VR vr = gdcm::VR::INVALID; const char *inv = gdcm::VR::GetVRString(vr); std::cout << 0 << "," << inv << std::endl; int i; for(i=0; i<27; i++) { int j = 1 << i; //int k = gdcm::VR::GetIndex((gdcm::VR::VRType)j); std::cout << "2^" << i << "=" << (int)j << "," << gdcm::VR::GetVRString((gdcm::VR::VRType)j) << std::endl; } vr = gdcm::VR::OB_OW; //int k = gdcm::VR::GetIndex(vr); std::cout << i++ << "," << gdcm::VR::GetVRString(vr) << std::endl; vr = gdcm::VR::US_SS; //k = gdcm::VR::GetIndex(vr); std::cout << i++ << "," << gdcm::VR::GetVRString(vr) << std::endl; vr = gdcm::VR::US_SS_OW; //k = gdcm::VR::GetIndex(vr); std::cout << i++ << "," << gdcm::VR::GetVRString(vr) << std::endl; std::string s = "OB"; vr = gdcm::VR::GetVRType(s.c_str()); if( s != gdcm::VR::GetVRString(vr)) return 1; s = "UT"; vr = gdcm::VR::GetVRType(s.c_str()); if( s != gdcm::VR::GetVRString(vr)) return 1; std::string s2 = "OB or OW"; gdcm::VR ob_ow = gdcm::VR::OB_OW; vr = gdcm::VR::GetVRType(s2.c_str()); if( vr != ob_ow ) return 1; if( s2 != gdcm::VR::GetVRString(vr)) return 1; // Check that "OB" is in "OB or OW" s = "OB"; if( !gdcm::VR::IsValid(s.c_str(), vr) ) return 1; std::string s3 = "US or SS or OW"; vr = gdcm::VR::GetVRType(s3.c_str()); // Check that "OB" is not in "US or SS or OW" if( gdcm::VR::IsValid(s.c_str(), vr) ) return 1; s = "XX"; //invalid vr = gdcm::VR::GetVRType(s.c_str()); if( vr != gdcm::VR::VR_END ) return 1; const char *t = gdcm::VR::GetVRString(vr); if( t != nullptr ) return 1; s = "??"; //invalid vr = gdcm::VR::GetVRType(s.c_str()); if( vr != gdcm::VR::INVALID) return 1; // Test Partial Match s = "US or SS"; vr = gdcm::VR::GetVRType(s.c_str()); if( vr == gdcm::VR::US ) return 1; { vr = gdcm::VR::AE; if( vr & gdcm::VR::VRASCII ) { std::cout << vr << " is ASCII\n"; } else { return 1; } vr = gdcm::VR::UI; if( vr & gdcm::VR::VRASCII ) { std::cout << vr << " is ASCII\n"; } else { return 1; } vr = gdcm::VR::OB; if( vr & gdcm::VR::VRBINARY ) { std::cout << vr << " is Binary\n"; } else { return 1; } vr = gdcm::VR::UI; if( vr & (gdcm::VR::OB | gdcm::VR::OF | gdcm::VR::OW /*| gdcm::VR::SQ*/ | gdcm::VR::UN) ) { return 1; } } // Let's check the & operator { vr = gdcm::VR::OB; if( !( vr.Compatible( gdcm::VR::OB_OW ) ) ) { return 1; } // if( !( vr.Compatible( gdcm::VR::INVALID) ) ) // { // return 1; // } } // Make sure VR::UT is the last valid VR that can be found in a file: //if( gdcm::VR::OB_OW <= gdcm::VR::UT ) return 1; //else if( gdcm::VR::US_SS <= gdcm::VR::UT ) return 1; //else if( gdcm::VR::US_SS_OW <= gdcm::VR::UT ) return 1; //else if( gdcm::VR::VL32 <= gdcm::VR::UT ) return 1; if( TestEnumString("OD", gdcm::VR::OD ) == 1 ) return 1; if( TestEnumString("OL", gdcm::VR::OL ) == 1 ) return 1; if( TestEnumString("UC", gdcm::VR::UC ) == 1 ) return 1; if( TestEnumString("UR", gdcm::VR::UR ) == 1 ) return 1; if( TestEnumString("OV", gdcm::VR::OV ) == 1 ) return 1; if( TestEnumString("SV", gdcm::VR::SV ) == 1 ) return 1; if( TestEnumString("UV", gdcm::VR::UV ) == 1 ) return 1; return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestVRDS.cxx000066400000000000000000000052751412732066400270010ustar00rootroot00000000000000/*========================================================================= 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 "gdcmVR.h" #include "gdcmAttribute.h" #include "gdcmByteValue.h" #include #include #include template std::string TestVRDSFunc(const char *str) { std::istringstream is( str ); T d; is >> d; std::ostringstream os; os << std::setprecision(MAXBYTES); os << d; std::cout << std::setprecision(MAXBYTES); std::cout << d << std::endl; std::string copy = os.str(); return copy; } /* * Test to make sure that double precision ieee 'double' is ok for DICOM VR = 'DS' */ int TestVRDS(int, char *[]) { const unsigned int dsmaxbytes = 16; const char str0[dsmaxbytes+1] = "0.123456789123"; std::string copy; // Let's demonstrate the float can easily fails; if( (copy = TestVRDSFunc(str0)) == str0 ) { std::cerr << "Float works:" << copy << " vs " << str0 << std::endl; return 1; } // Repeat with double, it works this time if( (copy = TestVRDSFunc(str0)) != str0 ) { std::cerr << "Double does not work:" << copy << " vs " << str0 << std::endl; return 1; } const double d1 = -118.242525316066; const double d2 = 0.00149700609543456; const double d3 = 0.059303515816892; gdcm::Attribute<0x20,0x32> at; at.SetValue( d1, 0); at.SetValue( d2, 1); at.SetValue( d3, 2); gdcm::DataElement de = at.GetAsDataElement(); std::cout << de << std::endl; const gdcm::ByteValue* bv = de.GetByteValue(); { std::string str = bv->GetPointer(); std::string::size_type pos1 = str.find("\\"); std::string::size_type pos2 = str.find("\\", pos1 + 1); if( pos1 > dsmaxbytes ) { std::string s = str.substr(0, pos1); std::cout << "Problem with: " << s << " " << s.size() << std::endl; return 1; } if( (pos2 - pos1) > dsmaxbytes ) { std::string s = str.substr(pos1 + 1, pos2 - pos1 - 1); std::cout << "Problem with: " << s << " " << s.size() << std::endl; return 1; } if( (str.size() - pos2) > dsmaxbytes ) { std::string s = str.substr(pos2 + 1); std::cout << "Problem with: " << s << " " << s.size() << std::endl; return 1; } } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestVRLT.cxx000066400000000000000000000015511412732066400270030ustar00rootroot00000000000000/*========================================================================= 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 "gdcmVR.h" #include #include #include using gdcm::LTComp; int TestVRLT(int, char *[]) { LTComp lt = "hello"; std::cout << lt << std::endl; if( lt.size() % 2 ) { return 1; } if( lt[ lt.size() - 1] != ' ' ) { return 1; } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestVRUI.cxx000066400000000000000000000015751412732066400270070ustar00rootroot00000000000000/*========================================================================= 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 "gdcmVR.h" #include #include #include using gdcm::UIComp; int TestVRUI(int, char *[]) { UIComp ui = "1.2.3.4"; std::cout << ui << "/" << ui.size() << std::endl; if( ui.size() % 2 ) { return 1; } if( ui[ ui.size() - 1] != 0 ) { return 1; } return 0; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestValue.cxx000066400000000000000000000027241412732066400272730ustar00rootroot00000000000000/*========================================================================= 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 "gdcmByteValue.h" #include "gdcmSequenceOfItems.h" #include "gdcmStringStream.h" #include "gdcmSwapper.h" void PrintStream(IStream &is) { char c; while(is.get(c)) { std::cout << (int)c << std::endl; } } int CheckStream(IStream &is, int size) { char c; int t = 0; while(is.get(c) && (int)c == t) { std::cerr << (int)c << std::endl; ++t; } return t != size; } int TestValue(int , char *[]) { int r = 0; gdcm::Value *v; gdcm::SequenceOfItems si; gdcm::ByteValue bv; v = &si; v = &bv; const int size = 128; char buffer[size]; for(int i=0; i(i); } std::stringstream ss; ss.write(buffer, size); //PrintStream(ss); v->SetLength( size ); v->Read(ss); std::stringstream ss2; v->Write(ss2); //PrintStream(ss2); r += CheckStream(ss2, size); return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestWriter.cxx000066400000000000000000000102301412732066400274620ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmTesting.h" //bool IsImpossibleToRewrite(const char *filename) //{ // const char *impossible; // int i = 0; // while( (impossible= gdcmBlackListWriterDataImages[i]) ) // { // if( strcmp( impossible, filename ) == 0 ) // { // return true; // } // ++i; // } // return false; //} namespace gdcm { int TestWrite(const char *subdir, const char* filename, bool recursing, bool verbose = false) { Reader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } // Create directory first: std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); Writer writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); writer.SetCheckFileMetaInformation( false ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // Ok we have now two files let's compare their md5 sum: char digest[33], outdigest[33]; Testing::ComputeFileMD5(filename, digest); Testing::ComputeFileMD5(outfilename.c_str(), outdigest); if( strcmp(digest, outdigest) ) { if (recursing) return 1; // too bad the file is not identical, so let's be paranoid and // try to reread-rewrite this just-written file: // TODO: Copy file System::CopyFile( ); std::string subsubdir = subdir; subsubdir += "/"; subsubdir += subdir; if( TestWrite(subsubdir.c_str(), outfilename.c_str(), true ) ) { std::cerr << filename << " and " << outfilename << " are different\n"; return 1; } const char * ref = Testing::GetMD5FromBrokenFile(filename); if( ref ) { if( strcmp(ref, outdigest) == 0 ) { // ok this situation was already analyzed and the written file is // readable by dcmtk and such //size_t size1 = System::FileSize( filename ); //size_t size2 = System::FileSize( outfilename.c_str() ); //assert( size1 == size2 ); // cannot deal with implicit VR meta data header return 0; } std::cerr << "incompatible ref: " << ref << " vs " << outdigest << " for file: " << filename << " & " << outfilename << std::endl; return 1; // ref exist but does not match, how is that possible ? } //if( !ref ) // { // return 1; // } // In theory I need to compare the two documents to check they // are identical... TODO std::cerr << filename << " and " << outfilename << " are different, output can be read though. Need manual intervention\n"; return 1; } else { size_t size1 = System::FileSize( filename ); size_t size2 = System::FileSize( outfilename.c_str() ); if( size1 != size2 ) return 1; if(verbose) std::cerr << filename << " and " << outfilename << " are identical\n"; return 0; } } } int TestWriter(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestWrite(argv[0], filename, false, true); } // else int r = 0, i = 0; gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestWrite(argv[0], filename, false ); ++i; } return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Cxx/TestWriter2.cxx000066400000000000000000000065721412732066400275620ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmTesting.h" namespace gdcm { /* * we are only testing that we can convert an implicit dataset to explicit all the time... */ int TestWrite2(const char *subdir, const char* filename, bool ) { Reader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } // Create directory first: std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); } std::string outfilename = Testing::GetTempFilename( filename, subdir ); // Invert Transfer Syntax just for fun: const TransferSyntax &ts = reader.GetFile().GetHeader().GetDataSetTransferSyntax(); if( ts.IsExplicit() && ts == TransferSyntax::ExplicitVRLittleEndian ) { reader.GetFile().GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian ); } else if( ts.IsImplicit() ) { gdcm::FileMetaInformation &fmi = reader.GetFile().GetHeader(); gdcm::TransferSyntax ts2 = gdcm::TransferSyntax::ImplicitVRLittleEndian; ts2 = gdcm::TransferSyntax::ExplicitVRLittleEndian; const char *tsuid = gdcm::TransferSyntax::GetTSString( ts2 ); gdcm::DataElement de( gdcm::Tag(0x0002,0x0010) ); de.SetByteValue( tsuid, (uint32_t)strlen(tsuid) ); de.SetVR( VR::UI ); //gdcm::Attribute<0x0002, 0x0010>::GetVR() ); fmi.Replace( de ); reader.GetFile().GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); } else { // nothing to test return 0; } const char str[] = "1.2.3.4.5.6.8.9.0"; DataElement xde; xde.SetByteValue(str, (uint32_t)strlen(str)); xde.SetVR( VR::UI ); xde.SetTag( Tag(0x0008,0x0018) ); reader.GetFile().GetDataSet().Insert( xde ); Writer writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); //writer.SetCheckFileMetaInformation( true ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } Reader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Failed to re-read: " << outfilename << std::endl; return 1; } return 0; } } int TestWriter2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestWrite2(argv[0], filename, false ); } // else int r = 0, i = 0; gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestWrite2(argv[0], filename, false ); ++i; } return r; } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Java/000077500000000000000000000000001412732066400247455ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Java/CMakeLists.txt000066400000000000000000000025441412732066400275120ustar00rootroot00000000000000# Define the tests for gdcm-java set(GDCM_JAVA_TEST_SRCS TestReader TestReaderUnicode TestTag TestReaderUpToTag ) # Do not change anything after here: find_package(Java ${GDCM_DEFAULT_JAVA_VERSION} REQUIRED) # javac, jar find_package(JNI REQUIRED) include_directories( ${JNI_INCLUDE_PATH} ) set(classfilesdep) foreach(example ${GDCM_JAVA_TEST_SRCS}) add_custom_command( OUTPUT ${GDCM_EXECUTABLE_DIR}/${example}.class COMMAND ${Java_JAVAC_EXECUTABLE} ARGS ${CMAKE_CURRENT_SOURCE_DIR}/${example}.java -encoding utf-8 -d ${GDCM_EXECUTABLE_DIR} -source ${GDCM_JAVA_SOURCE_VERSION} -target ${GDCM_JAVA_TARGET_VERSION} -classpath ${GDCM_LIBRARY_DIR}/gdcm.jar WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${example}.java COMMENT "javac ${example}.java" ) list(APPEND classfilesdep ${GDCM_EXECUTABLE_DIR}/${example}.class) set(GDCM_LIBRARY_DIR2 ${LIBRARY_OUTPUT_PATH}/\${BUILD_TYPE}) set_source_files_properties(${GDCM_EXECUTABLE_DIR}/${example}.class PROPERTIES CLASSPATH "${GDCM_LIBRARY_DIR2}/gdcm.jar") ADD_JAVA_TEST(${example}Java ${GDCM_EXECUTABLE_DIR}/${example}) endforeach() # 3. ok now add the target add_custom_target(GDCMJavaDSEDTests ALL DEPENDS ${classfilesdep} COMMENT "building gdcm java dsed tests" ) # make sure gdcm.jar is built add_dependencies(GDCMJavaDSEDTests GDCMJavaJar) GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Java/TestReader.java000066400000000000000000000043231412732066400276540ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* */ import gdcm.*; import java.util.Properties; import java.util.Enumeration; public class TestReader { public static void main(String[] args) throws Exception { /* System.out.println("PATH : " + System.getProperty("java.library.path")); Properties p = System.getProperties(); Enumeration keys = p.keys(); while (keys.hasMoreElements()) { String key = (String)keys.nextElement(); String value = (String)p.get(key); System.out.println(key + ": " + value); } */ long nfiles = Testing.GetNumberOfFileNames(); Trace.DebugOff(); Trace.WarningOff(); for( long i = 0; i < nfiles; ++i ) { String filename = Testing.GetFileName( i ); //System.out.println("Success reading: " + filename ); Reader reader = new Reader(); reader.SetFileName( filename ); if ( !reader.Read() ) { throw new Exception("Could not read: " + filename ); } String ref = Testing.GetMediaStorageFromFile(filename); if( ref == null ) { throw new Exception("Missing ref for: " + filename ); } MediaStorage ms = new MediaStorage(); ms.SetFromFile( reader.GetFile() ); if( ms.IsUndefined() && !"".equals( ref ) ) { // gdcm-CR-DCMTK-16-NonSamplePerPix.dcm is empty throw new Exception("ref is undefined for: " + filename + " should be " + ref ); } MediaStorage.MSType ref_mstype = MediaStorage.GetMSType( ref ); if( !"".equals( ref ) && ms.GetType() != ref_mstype ) { throw new Exception("incompatible type: " + ref + " vs " + ms.GetString() + " for " + filename ); } } } } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Java/TestReaderUnicode.java000066400000000000000000000052401412732066400311620ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* */ import gdcm.*; import java.util.Properties; import java.util.Enumeration; import java.io.IOException; import java.nio.file.Files; public class TestReaderUnicode { public static void copyFile( java.io.File from, java.io.File to ) throws IOException { Files.copy( from.toPath(), to.toPath() ); } public static void process(String template, String tmpdir, String targetname) throws IOException, Exception { if(!PosixEmulation.FileIsDirectory( tmpdir ) ) { PosixEmulation.MakeDirectory( tmpdir ); } String filename = tmpdir + "/" + targetname; PosixEmulation.RemoveFile( filename ); try { copyFile(new java.io.File(template), new java.io.File(filename )); } catch (IOException ex) { System.err.println("Error copying: " + template + " to " + filename ); return; } Reader reader = new Reader(); System.out.println("Reading: " + filename ); reader.SetFileName( filename ); if ( !reader.Read() ) { throw new Exception("Could not read: " + filename ); } String ref = Testing.GetMediaStorageFromFile(template); if( ref == null ) { throw new Exception("Missing ref for: " + template); } MediaStorage ms = new MediaStorage(); ms.SetFromFile( reader.GetFile() ); if( ms.IsUndefined() && !"".equals( ref ) ) { // gdcm-CR-DCMTK-16-NonSamplePerPix.dcm is empty throw new Exception("ref is undefined for: " + filename + " should be " + ref ); } MediaStorage.MSType ref_mstype = MediaStorage.GetMSType( ref ); if( !"".equals( ref ) && ms.GetType() != ref_mstype ) { throw new Exception("incompatible type: " + ref + " vs " + ms.GetString() + " for " + filename ); } } public static void main(String[] args) throws Exception { String dataroot = Testing.GetDataRoot(); String filename = dataroot + "/012345.002.050.dcm"; String subdir = "TestReaderUnicode"; String tmpdir = Testing.GetTempDirectory( subdir ); process(filename, tmpdir, "ascii.dcm" ); process(filename, tmpdir, "ê.dcm" ); process(filename, tmpdir, "А.dcm" ); } } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Java/TestReaderUpToTag.java000066400000000000000000000056521412732066400311260ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* */ import gdcm.*; import java.util.SortedSet; import java.util.TreeSet; import java.util.Set; import java.util.HashSet; import java.util.List; import java.util.ArrayList; public class TestReaderUpToTag { private static void PrintTagSet( Set s ) { for( Tag t : s ) { System.out.println("Print: " + t); } } private static SortedSet getTagSet() { Tag tags[] = { new Tag(0x8,0x8), new Tag(0x8,0x16), new Tag(0x8,0x18), new Tag(0x8,0x60), new Tag(0x10,0x20), new Tag(0x28,0x2), new Tag(0x28,0x10), new Tag(0x28,0x11), new Tag(0x10,0x10) }; SortedSet tagSet = new TreeSet(); for( Tag tag : tags ) { tagSet.add( tag ); } return tagSet; } public static void main(String[] args) throws Exception { long nfiles = Testing.GetNumberOfFileNames(); SortedSet tagSet = getTagSet(); PrintTagSet( tagSet ); Tag last = tagSet.last(); System.out.println("last: " + last); TagSetType skip = new TagSetType(); Tag pixelData = new Tag(0x7fe0,0x0010); skip.insert( pixelData ); Trace.DebugOff(); Trace.WarningOff(); StringFilter sf = new StringFilter(); List> l = new ArrayList>(); for( long i = 0; i < nfiles; ++i ) { Set s = new HashSet(); String filename = Testing.GetFileName( i ); if( true || filename.contains( "ExplicitVRforPublicElementsImplicitVRforShadowElements" ) || filename.contains( "SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs" ) ) { Reader reader = new Reader(); reader.SetFileName( filename ); if ( !reader.ReadUpToTag(pixelData, skip) ) { throw new Exception("Could not read: " + filename ); } System.out.println("reading: " + filename); File file = reader.GetFile(); sf.SetFile( file ); DataSet ds = file.GetDataSet(); for( Tag tag : tagSet ) { if( ds.FindDataElement( tag ) ) { s.add( tag ); DataElement de = ds.GetDataElement( tag ); System.out.println("de: " + tag + " -> " + sf.ToString( de ) ); } } } l.add( s ); // PrintTagSet( s ); System.gc (); } System.gc (); System.runFinalization (); for( Set s : l ) { PrintTagSet( s ); } PrintTagSet( tagSet ); } } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Java/TestTag.java000066400000000000000000000042401412732066400271630ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* */ import gdcm.Tag; import java.util.Set; import java.util.HashSet; public class TestTag { public static void main(String[] args) throws Exception { Tag t1 = new Tag(0x8,0x8); //System.out.println("t1: " + t1.hashCode()); Tag t2 = new Tag(0x8,0x8); //System.out.println("t2: " + t2.hashCode()); Tag t3 = new Tag(0x8,0x9); if( t1 == t2 ) throw new Exception("Instances are identical" ); if( !t1.equals(t2) ) throw new Exception("Instances are different" ); if( !t2.equals(t1) ) throw new Exception("Instances are different" ); if( t1.equals(t3) ) throw new Exception("Instances are equals" ); if( t1.hashCode() != t2.hashCode() ) throw new Exception("hashCodes are different" ); Set s = new HashSet(); s.add(t1); s.add(t2); s.add(t3); if( s.size() != 2 ) throw new Exception("Invalid size: " + s.size() ); //System.out.println("compareTo: " + t1.compareTo(t2)); //System.out.println("compareTo: " + t2.compareTo(t1)); //System.out.println("compareTo: " + t1.compareTo(t3)); //System.out.println("compareTo: " + t3.compareTo(t1)); if( t1.compareTo(t2) != 0 ) throw new Exception("Invalid compareTo: " + t1 + " vs " + t2 ); if( t2.compareTo(t1) != 0 ) throw new Exception("Invalid compareTo: " + t1 + " vs " + t2 ); if( t1.compareTo(t3) >= 0 ) throw new Exception("Invalid compareTo: " + t1 + " vs " + t3 ); if( t3.compareTo(t1) <= 0 ) throw new Exception("Invalid compareTo: " + t1 + " vs " + t3 ); } } GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Python/000077500000000000000000000000001412732066400253455ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Python/CMakeLists.txt000066400000000000000000000005121412732066400301030ustar00rootroot00000000000000# Define the tests for gdcm-python # gdcm-python set(GDCM_PYTHON_TEST_SRCS TestTag ) if(GDCM_DATA_ROOT) set(GDCM_PYTHON_TEST_SRCS ${GDCM_PYTHON_TEST_SRCS} TestReader ) endif() # Loop over files and create executables foreach(name ${GDCM_PYTHON_TEST_SRCS}) ADD_PYTHON_TEST(${name}Python ${name}.py) endforeach() GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Python/TestReader.py000066400000000000000000000023201412732066400277560ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import os,sys import gdcm def TestRead(filename, verbose = False): r = gdcm.Reader() r.SetFileName( filename ) success = r.Read() #if verbose: print r.GetFile() if verbose: print(r.GetFile().GetDataSet()) return success if __name__ == "__main__": success = 0 try: filename = os.sys.argv[1] success += TestRead( filename, True ) except: # loop over all files: gdcm.Trace.DebugOff() gdcm.Trace.WarningOff() t = gdcm.Testing() nfiles = t.GetNumberOfFileNames() for i in range(0,nfiles): filename = t.GetFileName(i) success += TestRead( filename ) # Test succeed ? sys.exit(success == 0) GDCM-3.0.10/Testing/Source/DataStructureAndEncodingDefinition/Python/TestTag.py000066400000000000000000000016721412732066400273000ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import os,sys import gdcm if __name__ == "__main__": o1 = gdcm.Tag(0x0000,0x0000) o2 = gdcm.Tag(0x0010,0x0000) o3 = gdcm.Tag(0x0000,0x0010) o4 = gdcm.Tag(0x0010,0x0010) if o1 == o2: sys.exit(1) if o1 == o3: sys.exit(1) if o1 == o4: sys.exit(1) if o1 != o1: sys.exit(1) if o1 > o2: print("Fail o1 > o2") sys.exit(1) sys.exit(0) GDCM-3.0.10/Testing/Source/InformationObjectDefinition/000077500000000000000000000000001412732066400226145ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/InformationObjectDefinition/CMakeLists.txt000066400000000000000000000001171412732066400253530ustar00rootroot00000000000000add_subdirectory(Cxx) if(GDCM_WRAP_PYTHON) add_subdirectory(Python) endif() GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/000077500000000000000000000000001412732066400233565ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/CMakeLists.txt000066400000000000000000000023311412732066400261150ustar00rootroot00000000000000# Define the tests for Information Object Definition # IOD set(IOD_TEST_SRCS TestTableReader.cxx TestTable.cxx TestTableEntry.cxx TestType.cxx TestModule.cxx TestModules.cxx TestModuleEntry.cxx TestNestedModuleEntries.cxx TestIODEntry.cxx TestIOD.cxx TestIODs.cxx TestDefs.cxx TestPatient.cxx TestSeries.cxx TestStudy.cxx TestDefinedTerms.cxx TestEnumeratedValues.cxx TestUsage.cxx #TestXMLDictReader.cxx #TestXMLPrivateDictReader.cxx ) # Add the include paths include_directories( "${GDCM_BINARY_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition" "${GDCM_SOURCE_DIR}/Source/DataDictionary" "${GDCM_SOURCE_DIR}/Source/InformationObjectDefinition" "${GDCM_BINARY_DIR}/Source/InformationObjectDefinition" # gdcmTables.h ) create_test_sourcelist(IODTests gdcmIODTests.cxx ${IOD_TEST_SRCS} EXTRA_INCLUDE gdcmTestDriver.h ) add_executable(gdcmIODTests ${IODTests}) target_link_libraries(gdcmIODTests gdcmIOD gdcmMSFF) # Loop over files and create executables foreach(name ${IOD_TEST_SRCS}) get_filename_component(testname ${name} NAME_WE) add_test(NAME ${testname} COMMAND gdcmIODTests ${testname}) endforeach() GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestDefinedTerms.cxx000066400000000000000000000012541412732066400273150ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDefinedTerms.h" int TestDefinedTerms(int, char *[]) { gdcm::DefinedTerms dt; (void)dt; return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestDefs.cxx000066400000000000000000000057031412732066400256300ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDefs.h" #include "gdcmUIDs.h" #include "gdcmGlobal.h" #include "gdcmMediaStorage.h" #include "gdcmSOPClassUIDToIOD.h" int TestDefs(int, char *[]) { using gdcm::MediaStorage; gdcm::Global& g = gdcm::Global::GetInstance(); if( !g.LoadResourcesFiles() ) { std::cerr << "Could not LoadResourcesFiles" << std::endl; return 1; } const gdcm::Defs &defs = g.GetDefs(); //std::cout << defs.GetMacros() << std::endl; int ret = 0; gdcm::MediaStorage::MSType mst; for ( mst = gdcm::MediaStorage::MediaStorageDirectoryStorage; mst < gdcm::MediaStorage::MS_END; mst = (gdcm::MediaStorage::MSType)(mst + 1) ) { const char *iod = defs.GetIODNameFromMediaStorage(mst); gdcm::UIDs uid; uid.SetFromUID( gdcm::MediaStorage::GetMSString(mst) /*mst.GetString()*/ ); if( !iod ) { // We do not support Private IODs (for now??) if( mst != MediaStorage::PhilipsPrivateMRSyntheticImageStorage && mst != MediaStorage::ToshibaPrivateDataStorage && mst != MediaStorage::GEPrivate3DModelStorage && mst != MediaStorage::Philips3D && mst != MediaStorage::CSANonImageStorage && mst != MediaStorage::GeneralElectricMagneticResonanceImageStorage ) { std::cerr << "Missing iod for MS: " << (int)mst << " " << gdcm::MediaStorage::GetMSString(mst) << " "; //std::endl; std::cerr << "MediaStorage is " << (int)mst << " [" << uid.GetName() << "]" << std::endl; ++ret; } } else { const char *iod_ref = gdcm::SOPClassUIDToIOD::GetIOD(uid); if( !iod_ref ) { std::cerr << "Could not find IOD for SOPClass: " << uid << std::endl; ++ret; } else { std::string iod_ref_str = iod_ref; //iod_ref_str += " IOD Modules"; if( iod_ref_str != iod ) { std::cerr << "UID: " << uid << " "; std::cerr << "Incompatible IODs: [" << iod << "] versus ref= [" << iod_ref_str << "]" << std::endl; ++ret; } } } } unsigned int nm = MediaStorage::GetNumberOfModality(); unsigned int nsop = gdcm::SOPClassUIDToIOD::GetNumberOfSOPClassToIOD(); if( nm != nsop ) { std::cerr << "Incompatible MediaStorage knows: " << nm << " SOP Classes while SOPClassUIDToIOD knows: " << nsop << " classes" << std::endl; ++ret; } return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestEnumeratedValues.cxx000066400000000000000000000012701412732066400302130ustar00rootroot00000000000000/*========================================================================= 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 "gdcmEnumeratedValues.h" int TestEnumeratedValues(int, char *[]) { gdcm::EnumeratedValues ev; (void)ev; return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestIOD.cxx000066400000000000000000000032271412732066400253610ustar00rootroot00000000000000/*========================================================================= 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 "gdcmIOD.h" #include "gdcmDefs.h" #include "gdcmGlobal.h" #include "gdcmDicts.h" #include "gdcmDict.h" #include "gdcmType.h" #include "gdcmIODs.h" int TestIOD(int, char *[]) { using namespace gdcm; gdcm::Global& g = gdcm::Global::GetInstance(); if( !g.LoadResourcesFiles() ) { std::cerr << "Could not LoadResourcesFiles" << std::endl; return 1; } static const Defs &defs = g.GetDefs(); static const gdcm::Dicts &dicts = g.GetDicts(); static const IODs &iods = defs.GetIODs(); static const gdcm::Dict &pubdict = dicts.GetPublicDict(); //const IOD& iod = defs.GetIODFromFile(*F); IODs::IODMapTypeConstIterator it = iods.Begin(); for( ; it != iods.End(); ++it ) { const IODs::IODName &name = it->first; (void)name; const IOD &iod = it->second; gdcm::Dict::ConstIterator dictit = pubdict.Begin(); for(; dictit != pubdict.End(); ++dictit) { const gdcm::Tag &tag = dictit->first; gdcm::Type t = iod.GetTypeFromTag(defs, tag); (void)t; //std::cout << t << std::endl; } } return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestIODEntry.cxx000066400000000000000000000012261412732066400264000ustar00rootroot00000000000000/*========================================================================= 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 "gdcmIODEntry.h" int TestIODEntry(int, char *[]) { gdcm::IODEntry iode; return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestIODs.cxx000066400000000000000000000012121412732066400255340ustar00rootroot00000000000000/*========================================================================= 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 "gdcmIODs.h" int TestIODs(int, char *[]) { gdcm::IODs iods; return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestModule.cxx000066400000000000000000000012241412732066400261660ustar00rootroot00000000000000/*========================================================================= 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 "gdcmModule.h" int TestModule(int , char *[]) { gdcm::Module module; return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestModuleEntry.cxx000066400000000000000000000013731412732066400272150ustar00rootroot00000000000000/*========================================================================= 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 "gdcmModuleEntry.h" int TestModuleEntry(int, char *[]) { gdcm::ModuleEntry me("Image Type","1","Image identification characteristics. See C.8.3.1.1.1 for specialization."); return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestModules.cxx000066400000000000000000000012301412732066400263460ustar00rootroot00000000000000/*========================================================================= 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 "gdcmModules.h" int TestModules(int , char *[]) { gdcm::Modules modules; return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestNestedModuleEntries.cxx000066400000000000000000000012661412732066400306710ustar00rootroot00000000000000/*========================================================================= 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 "gdcmNestedModuleEntries.h" int TestNestedModuleEntries(int, char *[]) { gdcm::NestedModuleEntries nme; return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestPatient.cxx000066400000000000000000000012221412732066400263430ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPatient.h" int TestPatient(int, char *[]) { gdcm::Patient pat; return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestSeries.cxx000066400000000000000000000012421412732066400261730ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSeries.h" int TestSeries(int, char *[]) { gdcm::Series series; (void)series; return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestStudy.cxx000066400000000000000000000012161412732066400260520ustar00rootroot00000000000000/*========================================================================= 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 "gdcmStudy.h" int TestStudy(int, char *[]) { gdcm::Study study; return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestTable.cxx000066400000000000000000000012121412732066400257650ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTable.h" int TestTable(int, char *[]) { gdcm::Table t; return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestTableEntry.cxx000066400000000000000000000012331412732066400270120ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTableEntry.h" int TestTableEntry(int , char *[]) { gdcm::TableEntry te; return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestTableReader.cxx000066400000000000000000000026151412732066400271200ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTableReader.h" #include "gdcmModules.h" // generated file: #include "gdcmTables.h" void TestReadTable(const char *filename, bool dump = false ) { gdcm::Defs defs; gdcm::TableReader tr(defs); tr.SetFilename(filename); tr.Read(); const gdcm::Modules &modules = defs.GetModules(); if(dump) std::cout << modules << std::endl; const gdcm::Macros ¯os = defs.GetMacros(); if(dump) std::cout << macros << std::endl; const gdcm::IODs &iods = defs.GetIODs(); if(dump) std::cout << iods << std::endl; } int TestTableReader(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; TestReadTable(filename, true); return 0; } // else int i = 0; const char *filename; while( (filename = gdcmTables[i]) ) { TestReadTable( filename ); ++i; } return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestType.cxx000066400000000000000000000012131412732066400256600ustar00rootroot00000000000000/*========================================================================= 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 "gdcmType.h" int TestType(int, char *[]) { gdcm::Type type; return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestUsage.cxx000066400000000000000000000012121412732066400260020ustar00rootroot00000000000000/*========================================================================= 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 "gdcmUsage.h" int TestUsage(int, char *[]) { gdcm::Usage u; return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestXMLDictReader.cxx000066400000000000000000000015161412732066400273340ustar00rootroot00000000000000/*========================================================================= 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 "gdcmXMLDictReader.h" int TestXMLDictReader(int argc, char *argv[]) { if( argc < 2 ) { return 1; } const char *filename = argv[1]; gdcm::XMLDictReader tr; tr.SetFilename(filename); tr.Read(); std::cout << tr.GetDict() << std::endl; return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Cxx/TestXMLPrivateDictReader.cxx000066400000000000000000000016161412732066400306700ustar00rootroot00000000000000/*========================================================================= 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 "gdcmXMLPrivateDictReader.h" int TestXMLPrivateDictReader(int argc, char *argv[]) { if( argc < 2 ) { return 1; } const char *filename = argv[1]; gdcm::XMLPrivateDictReader tr; tr.SetFilename(filename); tr.Read(); std::cout << tr.GetPrivateDict() << std::endl; //tr.GetPrivateDict().PrintXML(); return 0; } GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Python/000077500000000000000000000000001412732066400240755ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Python/CMakeLists.txt000066400000000000000000000003501412732066400266330ustar00rootroot00000000000000# Define the tests for gdcm-python # gdcm-python set(GDCM_PYTHON_TEST_SRCS TestMRModule ) # Loop over files and create executables foreach(name ${GDCM_PYTHON_TEST_SRCS}) ADD_PYTHON_TEST(${name}Python ${name}.py) endforeach() GDCM-3.0.10/Testing/Source/InformationObjectDefinition/Python/TestMRModule.py000066400000000000000000000020641412732066400267750ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import os,sys g = gdcm.Global.GetInstance() g.LoadResourcesFiles() defs = g.GetDefs() modules = defs.GetModules() macros = defs.GetMacros() #module = modules.GetModule( "MR Image Module Attributes" ) module = modules.GetModule( "C.8.3.1" ) #print dir(module) mentry = module.GetModuleEntryInMacros( macros, gdcm.Tag(0x0018,0x0087) ) #print dir(mentry) print(mentry) mentry = module.GetModuleEntryInMacros( macros, gdcm.Tag(0x0018,0x1080) ) print(mentry) # Test succeed ? sys.exit(0) GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/000077500000000000000000000000001412732066400221275ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/CMakeLists.txt000066400000000000000000000003061412732066400246660ustar00rootroot00000000000000# Always add_subdirectory(Cxx) if(GDCM_WRAP_PYTHON) add_subdirectory(Python) endif() if(GDCM_WRAP_CSHARP) add_subdirectory(Csharp) endif() if(GDCM_WRAP_JAVA) add_subdirectory(Java) endif() GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Csharp/000077500000000000000000000000001412732066400233475ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Csharp/CMakeLists.txt000066400000000000000000000021751412732066400261140ustar00rootroot00000000000000# C# MSFF tests set(MSFF_TEST_SRCS FCTS_JPEG FCTS_JPEGLS FCTS_JPEG2000 FCTS_RLE ) set(DEP) set_source_files_properties(${GDCM_LIBRARY_DIR}/gdcm-sharp.dll PROPERTIES GENERATED 1) foreach(test ${MSFF_TEST_SRCS}) file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${test}.cs result) add_custom_command( OUTPUT ${GDCM_EXECUTABLE_DIR}/${test}.exe COMMAND ${CMAKE_CSHARP_COMPILER} "${CSC_PLATFORM_FLAG}" "/r:${GDCM_LIBRARY_DIR}/gdcm-sharp.dll" "/out:${GDCM_EXECUTABLE_DIR}/${test}.exe" ${result} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${test}.cs COMMENT "Create ${test}.exe" ) add_custom_target(gdcm_sharp_${test} DEPENDS ${GDCM_EXECUTABLE_DIR}/${test}.exe) add_dependencies(gdcm_sharp_${test} GDCMCSharp) list(APPEND DEP ${GDCM_EXECUTABLE_DIR}/${test}.exe) # add test if(GDCM_DATA_ROOT) ADD_CSHARP_TEST(Test${test} ${GDCM_EXECUTABLE_DIR}/${test}.exe ${GDCM_DATA_ROOT}/GE_DLX-8-MONO2-Multiframe.dcm ${CMAKE_CURRENT_BINARY_DIR}/${test}.dcm) endif() endforeach() add_custom_target(gdcmMSFFTestsCsharp ALL DEPENDS ${DEP} COMMENT "building MSFF C# tests" ) add_dependencies(gdcmMSFFTestsCsharp GDCMCSharp) GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Csharp/FCTS_JPEG.cs000066400000000000000000000026231412732066400252450ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ using System; using gdcm; public class FCTS_JPEG { public static int Main(string[] args) { string filename = args[0]; string outfilename = args[1]; using( var sfcts = FileChangeTransferSyntax.New() ) { FileChangeTransferSyntax fcts = sfcts.__ref__(); //SimpleSubjectWatcher watcher = new SimpleSubjectWatcher(fcts, "FileChangeTransferSyntax"); gdcm.TransferSyntax ts = new TransferSyntax( TransferSyntax.TSType.JPEGBaselineProcess1 ); fcts.SetTransferSyntax( ts ); ImageCodec ic = fcts.GetCodec(); JPEGCodec jpeg = JPEGCodec.Cast( ic ); jpeg.SetLossless( false ); jpeg.SetQuality( 50 ); // poor quality ! fcts.SetInputFileName( filename ); fcts.SetOutputFileName( outfilename ); if( !fcts.Change() ) { return 1; } } return 0; } } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Csharp/FCTS_JPEG2000.cs000066400000000000000000000026201412732066400255440ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ using System; using gdcm; public class FCTS_JPEG2000 { public static int Main(string[] args) { string filename = args[0]; string outfilename = args[1]; using( var sfcts = FileChangeTransferSyntax.New() ) { FileChangeTransferSyntax fcts = sfcts.__ref__(); //SimpleSubjectWatcher watcher = new SimpleSubjectWatcher(fcts, "FileChangeTransferSyntax"); gdcm.TransferSyntax ts = new TransferSyntax( TransferSyntax.TSType.JPEG2000 ); fcts.SetTransferSyntax( ts ); ImageCodec ic = fcts.GetCodec(); JPEG2000Codec jpeg2000 = JPEG2000Codec.Cast( ic ); jpeg2000.SetReversible( false ); jpeg2000.SetQuality(0, 55); fcts.SetInputFileName( filename ); fcts.SetOutputFileName( outfilename ); if( !fcts.Change() ) { return 1; } } return 0; } } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Csharp/FCTS_JPEGLS.cs000066400000000000000000000026151412732066400255050ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ using System; using gdcm; public class FCTS_JPEGLS { public static int Main(string[] args) { string filename = args[0]; string outfilename = args[1]; using( var sfcts = FileChangeTransferSyntax.New() ) { FileChangeTransferSyntax fcts = sfcts.__ref__(); //SimpleSubjectWatcher watcher = new SimpleSubjectWatcher(fcts, "FileChangeTransferSyntax"); gdcm.TransferSyntax ts = new TransferSyntax( TransferSyntax.TSType.JPEGLSNearLossless ); fcts.SetTransferSyntax( ts ); ImageCodec ic = fcts.GetCodec(); JPEGLSCodec jpegls = JPEGLSCodec.Cast( ic ); jpegls.SetLossless( false ); jpegls.SetLossyError( 2 ); fcts.SetInputFileName( filename ); fcts.SetOutputFileName( outfilename ); if( !fcts.Change() ) { return 1; } } return 0; } } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Csharp/FCTS_RLE.cs000066400000000000000000000027461412732066400251500ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ using System; using gdcm; public class FCTS_RLE { public static int Main(string[] args) { string filename = args[0]; string outfilename = args[1]; using( var sfcts = FileChangeTransferSyntax.New() ) { FileChangeTransferSyntax fcts = sfcts.__ref__(); //SimpleSubjectWatcher watcher = new SimpleSubjectWatcher(fcts, "FileChangeTransferSyntax"); gdcm.TransferSyntax ts = new TransferSyntax( TransferSyntax.TSType.RLELossless ); fcts.SetTransferSyntax( ts ); ImageCodec ic = fcts.GetCodec(); RLECodec rle = RLECodec.Cast( ic ); // need to call at least one member func to check not NULL: long val = rle.GetBufferLength(); System.Console.WriteLine( val ); // use val to remove a warning fcts.SetInputFileName( filename ); fcts.SetOutputFileName( outfilename ); if( !fcts.Change() ) { return 1; } } return 0; } } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/000077500000000000000000000000001412732066400226715ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/CMakeLists.txt000066400000000000000000000236511412732066400254400ustar00rootroot00000000000000# Define the tests for Media Storage and File Format # MSFF set(MSFF_TEST_SRCS TestAnonymizer.cxx TestDataSetHelper.cxx TestEquipmentManufacturer.cxx TestFileChangeTransferSyntax1.cxx TestFileChangeTransferSyntax2.cxx TestFileChangeTransferSyntax3.cxx TestFileChangeTransferSyntax4.cxx TestFileStreamer1.cxx TestFileStreamer2.cxx TestFileStreamer3.cxx TestFileStreamer4.cxx TestFileStreamer5.cxx TestFileStreamer6.cxx TestFileAnonymizer1.cxx TestFileAnonymizer2.cxx TestFileAnonymizer3.cxx TestFileAnonymizer4.cxx TestIconImageFilter.cxx #TestIconImageGenerator.cxx #TestIconImageGenerator2.cxx #TestIconImageGenerator3.cxx #TestIconImageGenerator4.cxx TestParseXPATH.cxx TestValidate.cxx TestAnonymizeEvent.cxx TestFileDerivation.cxx TestSegmentedPaletteColorLookupTable.cxx TestPNMCodec.cxx TestSpacing.cxx TestSerieHelper.cxx TestFileExplicitFilter.cxx TestImageFragmentSplitter.cxx TestTagPath.cxx TestOrientation.cxx TestIconImage.cxx TestImageHelper.cxx TestImageToImageFilter.cxx TestImageChangeTransferSyntax1.cxx #TestImageChangePhotometricInterpretation.cxx #TestImageChangePhotometricInterpretation2.cxx # does not compile on mingw... TestImageChangeTransferSyntax2.cxx TestImageChangeTransferSyntax3.cxx TestImageChangeTransferSyntax4.cxx # see below TestImageChangeTransferSyntax6.cxx TestImageChangeTransferSyntax7.cxx TestImageApplyLookupTable.cxx TestFileDecompressLookupTable.cxx TestImageChangePlanarConfiguration.cxx TestCoder.cxx TestDecoder.cxx TestRescaler1.cxx TestRescaler2.cxx TestDumper.cxx TestDictPrinter.cxx TestApplicationEntity.cxx TestStringFilter1.cxx TestStringFilter2.cxx TestStringFilter3.cxx TestStringFilter4.cxx TestUIDGenerator.cxx TestUUIDGenerator.cxx #TestUIDGenerator3.cxx TestXMLPrinter.cxx TestPrinter1.cxx TestPrint.cxx TestSorter.cxx TestImageReader.cxx TestStreamImageReader.cxx TestImageRegionReader1.cxx TestImageRegionReader2.cxx TestImageRegionReader3.cxx #TestStreamImageWriter.cxx TestImageReaderRandomEmpty.cxx TestDirectionCosines.cxx TestImageWriter.cxx TestCodec.cxx TestPDFCodec.cxx TestRLECodec.cxx TestAudioCodec.cxx TestImage.cxx TestPhotometricInterpretation.cxx TestLookupTable.cxx TestOverlay.cxx TestOverlay3.cxx TestCurve.cxx TestCurve2.cxx TestPixelFormat.cxx TestPersonName.cxx TestImageCodec.cxx TestImageConverter.cxx TestJPEGCodec.cxx TestRAWCodec.cxx TestDICOMDIR.cxx TestWaveform.cxx TestFiducials.cxx TestEncapsulatedDocument.cxx TestSpectroscopy.cxx TestSurfaceWriter.cxx TestSurfaceWriter2.cxx ) if(GDCM_DATA_ROOT) set(MSFF_TEST_SRCS ${MSFF_TEST_SRCS} TestSplitMosaicFilter3.cxx TestStrictScanner1.cxx TestStrictScanner2.cxx TestScanner1.cxx TestScanner2.cxx TestImageHelper2.cxx TestPrinter2.cxx TestIPPSorter.cxx TestIPPSorter2.cxx TestIPPSorter3.cxx TestCopyDataSet.cxx TestDataElementValueAsSQ.cxx TestImageWriter2.cxx TestDICOMDIRGenerator1.cxx # Must be after TestImageChangeTransferSyntax4 TestDICOMDIRGenerator2.cxx # Must be after TestImageChangeTransferSyntax4 ) # Those tests requires that openssl be linked in: if(GDCM_USE_SYSTEM_OPENSSL) set(MSFF_TEST_SRCS ${MSFF_TEST_SRCS} TestAnonymizer2.cxx TestAnonymizer3.cxx ) endif() if(GDCM_USE_SYSTEM_JSON) set(MSFF_TEST_SRCS ${MSFF_TEST_SRCS} TestJSON1.cxx ) endif() endif() # gdcmDataExtra if(GDCM_DATA_EXTRA_ROOT) set(MSFF_TEST_SRCS ${MSFF_TEST_SRCS} TestSplitMosaicFilter.cxx TestSplitMosaicFilter2.cxx TestOverlay2.cxx TestImageRegionReader4.cxx ) endif() if(GDCM_USE_JPEGLS) set(MSFF_TEST_SRCS ${MSFF_TEST_SRCS} TestImageChangeTransferSyntax5.cxx ) endif() if(GDCM_HAVE_PTHREAD_H) set(MSFF_TEST_SRCS ${MSFF_TEST_SRCS} TestUIDGenerator2.cxx ) endif() if(GDCM_PIXEL_SPACING_DATA_ROOT) set(MSFF_TEST_SRCS ${MSFF_TEST_SRCS} TestImageReaderPixelSpacing.cxx ) endif() # Add the include paths include_directories( "${GDCM_BINARY_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Testing/Source/Data" "${GDCM_BINARY_DIR}/Testing/Source/Data" "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition" "${GDCM_SOURCE_DIR}/Source/DataDictionary" "${GDCM_SOURCE_DIR}/Source/MediaStorageAndFileFormat" ) create_test_sourcelist(MSFFTests gdcmMSFFTests.cxx ${MSFF_TEST_SRCS} EXTRA_INCLUDE gdcmTestDriver.h ) add_executable(gdcmMSFFTests ${MSFFTests}) target_link_libraries(gdcmMSFFTests gdcmMSFF) if(GDCM_HAVE_PTHREAD_H) target_link_libraries(gdcmMSFFTests pthread) endif() # Loop over files and create executables foreach(name ${MSFF_TEST_SRCS}) get_filename_component(testname ${name} NAME_WE) add_test(NAME ${testname} COMMAND gdcmMSFFTests ${testname}) endforeach() if(GDCM_DATA_ROOT) set_tests_properties(TestDICOMDIRGenerator2 PROPERTIES WILL_FAIL ON) endif() # We can only run the dcmtk cross-checking test *only* after all the tests have run # in particular once the TestWriter is done. foreach(filename ${gdcm_data_filenames_glob}) get_filename_component(filename_name ${filename} NAME) string(REGEX MATCH ${filename_name} bad_dicom ${black_list_reader}) if(NOT bad_dicom) if(GDCM_TEST_DCMTK) if(DCMTK_DCMDUMP_EXECUTABLE) # -M : load short tags # -dc: disable correction add_test(NAME "DCMDUMP-${filename_name}" COMMAND ${DCMTK_DCMDUMP_EXECUTABLE} -M -dc "${GDCM_TEMP_DIRECTORY}/TestWriter/${filename_name}") endif() endif() endif() endforeach() # Repeat for dcdump foreach(filename ${gdcm_data_filenames_glob}) get_filename_component(filename_name ${filename} NAME) string(REGEX MATCH ${filename_name} bad_dicom ${black_list_reader}) if(NOT bad_dicom) if(GDCM_TEST_DICOM3TOOLS) if(DCDUMP_EXECUTABLE) add_test(NAME "DCDUMP-${filename_name}" COMMAND "${DCDUMP_EXECUTABLE}" "${GDCM_TEMP_DIRECTORY}/TestWriter/${filename_name}") endif() endif() endif() endforeach() # There is a new test that compress all images using the jpeg compression alg: # try to decompress them with dcmtk: file(MAKE_DIRECTORY "${GDCM_TEMP_DIRECTORY}/TestImageChangeTransferSyntax/dcmdjpeg/") foreach(filename ${gdcm_data_filenames_glob}) get_filename_component(filename_name ${filename} NAME) string(REGEX MATCH ${filename_name} bad_dicom ${black_list_reader}) if(NOT bad_dicom) if(GDCM_TEST_DCMTK) if(DCMTK_DCMDJPEG_EXECUTABLE) add_test(NAME "DCMDJPEG-${filename_name}" COMMAND ${DCMTK_DCMDJPEG_EXECUTABLE} "${GDCM_TEMP_DIRECTORY}/TestImageChangeTransferSyntax/${filename_name}" "${GDCM_TEMP_DIRECTORY}/TestImageChangeTransferSyntax/dcmdjpeg/${filename_name}") # Special handling of the DICOMDIR files: string(REGEX MATCH ${filename_name} is_dicomdir ${gdcm_data_dicomdir_filenames_glob}) if(is_dicomdir) #message("IS DICOMDIR ${filename_name}") set_tests_properties("DCMDJPEG-${filename_name}" PROPERTIES WILL_FAIL TRUE) endif() endif() endif() endif() endforeach() file(MAKE_DIRECTORY "${GDCM_TEMP_DIRECTORY}/TestImageChangeTransferSyntax3/dcmdrle/") foreach(filename ${gdcm_data_filenames_glob}) get_filename_component(filename_name ${filename} NAME) string(REGEX MATCH ${filename_name} bad_dicom ${black_list_reader}) if(NOT bad_dicom) if(GDCM_TEST_DCMTK) if(DCMTK_DCMDRLE_EXECUTABLE) add_test(NAME "DCMDRLE-${filename_name}" COMMAND ${DCMTK_DCMDRLE_EXECUTABLE} "${GDCM_TEMP_DIRECTORY}/TestImageChangeTransferSyntax3/${filename_name}" "${GDCM_TEMP_DIRECTORY}/TestImageChangeTransferSyntax3/dcmdrle/${filename_name}") # Special handling of the DICOMDIR files: string(REGEX MATCH ${filename_name} is_dicomdir ${gdcm_data_dicomdir_filenames_glob}) if(is_dicomdir) #message("IS DICOMDIR ${filename_name}") set_tests_properties("DCMDRLE-${filename_name}" PROPERTIES WILL_FAIL TRUE) endif() # endif() endif() endif() endforeach() file(MAKE_DIRECTORY "${GDCM_TEMP_DIRECTORY}/TestImageChangeTransferSyntax5/dcmdjpls/") foreach(filename ${gdcm_data_filenames_glob}) get_filename_component(filename_name ${filename} NAME) string(REGEX MATCH ${filename_name} bad_dicom ${black_list_reader}) if(NOT bad_dicom) if(GDCM_TEST_DCMTK) if(DCMTK_DCMDJPLS_EXECUTABLE) #if(EXISTS "${GDCM_TEMP_DIRECTORY}/TestImageChangeTransferSyntax5/${filename_name}") add_test(NAME "DCMDJPLS-${filename_name}" COMMAND ${DCMTK_DCMDJPLS_EXECUTABLE} "${GDCM_TEMP_DIRECTORY}/TestImageChangeTransferSyntax5/${filename_name}" "${GDCM_TEMP_DIRECTORY}/TestImageChangeTransferSyntax5/dcmdjpls/${filename_name}") # Special handling of the DICOMDIR files: string(REGEX MATCH ${filename_name} is_dicomdir ${gdcm_data_dicomdir_filenames_glob}) if(is_dicomdir) #message("IS DICOMDIR ${filename_name}") set_tests_properties("DCMDJPLS-${filename_name}" PROPERTIES WILL_FAIL TRUE) endif() #endif() # endif() endif() endif() endforeach() # Need to SET_TESTS_PROPERTIES only *after* the loop is done (test need to have been declared first) if(GDCM_TEST_DCMTK) if(GDCM_DATA_ROOT) if(DCMTK_DCMDJPLS_EXECUTABLE) # No pixel data set_tests_properties("DCMDJPLS-ELSCINT1_PMSCT_RLE1.dcm" PROPERTIES WILL_FAIL TRUE) endif() if(DCMTK_DCMDJPEG_EXECUTABLE) # No pixel data set_tests_properties("DCMDJPEG-ELSCINT1_PMSCT_RLE1.dcm" PROPERTIES WILL_FAIL TRUE) endif() if(DCMTK_DCMDRLE_EXECUTABLE) # No pixel data set_tests_properties("DCMDRLE-ELSCINT1_PMSCT_RLE1.dcm" PROPERTIES WILL_FAIL TRUE) # It is missing the very last pixel, so technically is illegal set_tests_properties("DCMDRLE-ALOKA_SSD-8-MONO2-RLE-SQ.dcm" PROPERTIES WILL_FAIL TRUE) endif() endif() endif() GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestAnonymizeEvent.cxx000066400000000000000000000012461412732066400272330ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAnonymizeEvent.h" int TestAnonymizeEvent(int, char *[]) { gdcm::AnonymizeEvent ae; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestAnonymizer.cxx000066400000000000000000000062741412732066400264210ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAnonymizer.h" #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmUIDGenerator.h" namespace gdcm { int TestAnonymize(const char *subdir, const char* filename) { Reader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { return 1; } Anonymizer anonymizer; anonymizer.SetFile( reader.GetFile() ); // Setup some actions: const char patname[] = "test^anonymize"; const Tag pattag = Tag(0x0010,0x0010); anonymizer.Replace( pattag , patname ); anonymizer.Remove( Tag(0x0008,0x2112) ); anonymizer.Empty( Tag(0x0008,0x0070) ); UIDGenerator uid; // Those two are very special, since (0008,0016) needs to be propagated to (0002,0002) and // (0008,0018) needs to be propagated to (0002,0003) std::string newuid = uid.Generate(); anonymizer.Replace( Tag(0x0008,0x0018), newuid.c_str() ); anonymizer.Replace( Tag(0x0008,0x0016), "1.2.840.10008.5.1.4.1.1.1" ); // Make it a CT if( !anonymizer.RemovePrivateTags() ) { return 1; } // Create directory first: std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); Writer writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); writer.SetCheckFileMetaInformation( false ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } std::cout << "Success to write: " << outfilename << std::endl; // now let's try to read it back in: Reader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Could not reread written file: " << outfilename << std::endl; return 1; } const DataSet & ds = reader.GetFile().GetDataSet(); //std::cout << ds << std::endl; const ByteValue *bv = ds.GetDataElement( pattag ).GetByteValue(); if( !bv ) { return 1; } if (strncmp( bv->GetPointer(), patname, strlen(patname) ) != 0 ) { return 1; } if( bv->GetLength() != strlen(patname) ) { return 1; } return 0; } } int TestAnonymizer(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestAnonymize(argv[0], filename); } // else int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestAnonymize( argv[0], filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestAnonymizer2.cxx000066400000000000000000000145351412732066400265020ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAnonymizer.h" #include "gdcmSimpleSubjectWatcher.h" #include "gdcmFilename.h" #include "gdcmTesting.h" #include "gdcmCryptographicMessageSyntax.h" #include "gdcmCryptoFactory.h" #include "gdcmSmartPointer.h" #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmGlobal.h" #include "gdcmSystem.h" #include // std::unique_ptr namespace gdcm { int TestAnonymize2(const char *subdir, const char *filename, bool verbose = false) { gdcm::Global& g = gdcm::Global::GetInstance(); if( !g.LoadResourcesFiles() ) { return 1; } std::string certpath = gdcm::Filename::Join(gdcm::Testing::GetSourceDirectory(), "/Testing/Source/Data/certificate.pem" ); std::string keypath = gdcm::Filename::Join(gdcm::Testing::GetSourceDirectory(), "/Testing/Source/Data/privatekey.pem" ); // Create directory first: std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } if(verbose) std::cout << "Processing: " << filename << std::endl; std::string outfilename = Testing::GetTempFilename( filename, subdir ); // Create directory first: const char subdir2[] = "TestAnonymizer2_2"; std::string tmpdir2 = Testing::GetTempDirectory( subdir2 ); if( !System::FileIsDirectory( tmpdir2.c_str() ) ) { System::MakeDirectory( tmpdir2.c_str() ); //return 1; } std::string outfilename2 = Testing::GetTempFilename( filename, subdir2 ); // Encrypt { gdcm::CryptoFactory* cryptoFactory = gdcm::CryptoFactory::GetFactoryInstance(); if (cryptoFactory == NULL) { std::cerr << "Crypto library not available" << std::endl; return 1; } std::unique_ptr cms_ptr(cryptoFactory->CreateCMSProvider()); gdcm::CryptographicMessageSyntax& cms = *cms_ptr; if( !cms.ParseCertificateFile( certpath.c_str() ) ) { std::cerr << "Could not parse cert: " << certpath << std::endl; return 1; } gdcm::SmartPointer ano = new gdcm::Anonymizer; ano->SetCryptographicMessageSyntax( &cms ); //gdcm::SimpleSubjectWatcher watcher(ano, "Anonymizer"); gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } const DataSet &ds = reader.GetFile().GetDataSet(); bool hasinstanceuid = true; if( !ds.FindDataElement( Tag(0x0008,0x0018) ) || ds.GetDataElement( Tag(0x0008,0x0018) ).IsEmpty() ) { hasinstanceuid = false; } gdcm::MediaStorage ms; ms.SetFromFile( reader.GetFile() ); ano->SetFile( reader.GetFile() ); if( !ano->BasicApplicationLevelConfidentialityProfile() ) { gdcm::Filename fn( filename ); if( strcmp(fn.GetName(), "EmptyIcon_Bug417.dcm") == 0 // not supported for now (already anonymized) || strcmp(fn.GetName(), "PET-GE-dicomwrite-PixelDataSQUNv2.dcm") == 0 // not supported for now (already anonymized) || strcmp(fn.GetName(), "HardcopyColor_YBR_RCT_J2K_PC1.dcm") == 0 // deprecated SOP Class UID ) { return 0; } if( ms != gdcm::MediaStorage::MS_END ) { std::cerr << "BasicApplicationLevelConfidentialityProfile fails for: " << filename << std::endl; return 1; } } gdcm::Writer writer; //writer.SetFileName( "/tmp/ano.dcm" ); writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); if( !writer.Write() ) { if( hasinstanceuid ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } return 0; } } // Decrypt { gdcm::CryptoFactory* cryptoFactory = gdcm::CryptoFactory::GetFactoryInstance(); if (cryptoFactory == NULL) { std::cerr << "Crypto library not available" << std::endl; return 1; } std::unique_ptr cms_ptr(cryptoFactory->CreateCMSProvider()); gdcm::CryptographicMessageSyntax& cms = *cms_ptr; if( !cms.ParseKeyFile( keypath.c_str() ) ) { std::cerr << "Could not parse key: " << keypath << std::endl; return 1; } gdcm::SmartPointer ano = new gdcm::Anonymizer; ano->SetCryptographicMessageSyntax( &cms ); //gdcm::SimpleSubjectWatcher watcher(ano, "Anonymizer"); gdcm::Reader reader; reader.SetFileName( outfilename.c_str() ); if( !reader.Read() ) { std::cerr << "Could not read: " << outfilename << std::endl; return 1; } ano->SetFile( reader.GetFile() ); if( !ano->BasicApplicationLevelConfidentialityProfile(false) ) { std::cerr << "BasicApplicationLevelConfidentialityProfile (false) fails for: " << outfilename << std::endl; return 1; } const DataSet &ds = reader.GetFile().GetDataSet(); bool hasinstanceuid = true; if( !ds.FindDataElement( Tag(0x0008,0x0018) ) || ds.GetDataElement( Tag(0x0008,0x0018) ).IsEmpty() ) { hasinstanceuid = false; } // TODO Need to compare filename to decrypted one. gdcm::Writer writer; writer.SetFileName( outfilename2.c_str() ); writer.SetFile( reader.GetFile() ); if( !writer.Write() ) { if( hasinstanceuid ) { std::cerr << "Failed to write (2): " << outfilename2 << std::endl; std::cerr << "Orig file was : " << outfilename << std::endl; return 1; } return 0; } } return 0; } } int TestAnonymizer2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestAnonymize2(argv[0], filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestAnonymize2( argv[0], filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestAnonymizer3.cxx000066400000000000000000000170321412732066400264760ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAnonymizer.h" #include "gdcmSimpleSubjectWatcher.h" #include "gdcmUIDGenerator.h" #include "gdcmFilename.h" #include "gdcmTesting.h" #include "gdcmCryptographicMessageSyntax.h" #include "gdcmSmartPointer.h" #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmGlobal.h" #include "gdcmFileDerivation.h" #include "gdcmSystem.h" #include "gdcmCryptoFactory.h" #include // std::unique_ptr int TestAnonymizer3(int , char *[]) { using namespace gdcm; gdcm::Global& g = gdcm::Global::GetInstance(); if( !g.LoadResourcesFiles() ) { return 1; } const char *directory = gdcm::Testing::GetDataRoot(); std::string sfilename = std::string(directory) + "/012345.002.050.dcm"; const char *filename = sfilename.c_str(); std::string certpath = gdcm::Filename::Join(gdcm::Testing::GetSourceDirectory(), "/Testing/Source/Data/certificate.pem" ); std::string keypath = gdcm::Filename::Join(gdcm::Testing::GetSourceDirectory(), "/Testing/Source/Data/privatekey.pem" ); // Create directory first: const char subdir[] = "TestAnonymizer3"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); std::string outfilenamelossy = Testing::GetTempFilename( "012345.002.050.lossy.dcm" , subdir ); std::string outfilenamelossy2 = Testing::GetTempFilename( "012345.002.050.lossy.anon.dcm" , subdir ); // Derive { gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } File& file = reader.GetFile(); DataSet &ds = file.GetDataSet(); DataElement instanceuid = ds.GetDataElement( Tag(0x8,0x18) ); UIDGenerator uid; const char *s = uid.Generate(); instanceuid.SetByteValue( s, (uint32_t)strlen(s) ); ds.Replace( instanceuid ); FileDerivation fd; fd.SetFile( file ); // FIXME hardcoded: fd.AddReference( "1.2.840.10008.5.1.4.1.1.4", "1.2.840.113619.2.5.1762386977.1328.985934491.693" ); // CID 7202 Source Image Purposes of Reference // {"DCM",121320,"Uncompressed predecessor"}, fd.SetPurposeOfReferenceCodeSequenceCodeValue( 121320 ); // CID 7203 Image Derivation // { "DCM",113040,"Lossy Compression" }, fd.SetDerivationCodeSequenceCodeValue( 113040 ); fd.SetDerivationDescription( "lossy conversion" ); if( !fd.Derive() ) { std::cerr << "Sorry could not derive using input info" << std::endl; return 1; } gdcm::Writer writer; writer.SetFileName( outfilenamelossy.c_str() ); writer.SetFile( fd.GetFile() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilenamelossy << std::endl; return 1; } } // Encrypt { gdcm::CryptoFactory* cryptoFactory = gdcm::CryptoFactory::GetFactoryInstance(); if (cryptoFactory == NULL) { std::cerr << "Crypto library not available" << std::endl; return 1; } std::unique_ptr cms_ptr(cryptoFactory->CreateCMSProvider()); gdcm::CryptographicMessageSyntax& cms = *cms_ptr; if( !cms.ParseCertificateFile( certpath.c_str() ) ) { return 1; } gdcm::SmartPointer ano = new gdcm::Anonymizer; ano->SetCryptographicMessageSyntax( &cms ); { // original file gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } // order of operation is important ano->SetFile( reader.GetFile() ); if( !ano->BasicApplicationLevelConfidentialityProfile() ) { return 1; } gdcm::Writer writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } } { // derived file gdcm::Reader reader; reader.SetFileName( outfilenamelossy.c_str() ); if( !reader.Read() ) { std::cerr << "Could not read: " << outfilenamelossy << std::endl; return 1; } // order of operation is important ano->SetFile( reader.GetFile() ); if( !ano->BasicApplicationLevelConfidentialityProfile() ) { return 1; } gdcm::Writer writer; writer.SetFileName( outfilenamelossy2.c_str() ); writer.SetFile( reader.GetFile() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilenamelossy2 << std::endl; return 1; } } } // Make sure UID is consistent: { std::string sopinstanceuid_str1; { // original anonymized file gdcm::Reader reader; reader.SetFileName( outfilename.c_str() ); if( !reader.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } File &file = reader.GetFile(); DataSet &ds = file.GetDataSet(); if( !ds.FindDataElement( Tag(0x0008,0x0018) ) || ds.GetDataElement( Tag(0x0008,0x0018) ).IsEmpty() ) { return 1; } const DataElement &sopinstanceuid = ds.GetDataElement( Tag(0x0008,0x0018) ); sopinstanceuid_str1 = std::string( sopinstanceuid.GetByteValue()->GetPointer(), sopinstanceuid.GetByteValue()->GetLength() ); } std::string sopinstanceuid_str2; std::string refsopinstanceuid_str2; { // derived anonymized file gdcm::Reader reader; reader.SetFileName( outfilenamelossy2.c_str() ); if( !reader.Read() ) { std::cerr << "Could not read: " << outfilenamelossy << std::endl; return 1; } File &file = reader.GetFile(); DataSet &ds = file.GetDataSet(); if( !ds.FindDataElement( Tag(0x0008,0x0018) ) || ds.GetDataElement( Tag(0x0008,0x0018) ).IsEmpty() ) { return 1; } const DataElement &sopinstanceuid = ds.GetDataElement( Tag(0x0008,0x0018) ); sopinstanceuid_str2 = std::string( sopinstanceuid.GetByteValue()->GetPointer(), sopinstanceuid.GetByteValue()->GetLength() ); // Source Image Sequence if( !ds.FindDataElement( Tag(0x0008,0x2112) ) || ds.GetDataElement( Tag(0x0008,0x2112) ).IsEmpty() ) { return 1; } const DataElement &sourceimagesq = ds.GetDataElement( Tag(0x0008,0x2112) ); SmartPointer sq = sourceimagesq.GetValueAsSQ(); gdcm::SequenceOfItems::SizeType n = sq->GetNumberOfItems(); if( n != 1 ) return 1; Item &item = sq->GetItem( 1 ); DataSet &nested = item.GetNestedDataSet(); if( !nested.FindDataElement( Tag(0x0008,0x1155) ) || nested.GetDataElement( Tag(0x0008,0x1155) ).IsEmpty() ) { return 1; } const DataElement &refsopinstanceuid = nested.GetDataElement( Tag(0x0008,0x1155) ); refsopinstanceuid_str2 = std::string( refsopinstanceuid.GetByteValue()->GetPointer(), refsopinstanceuid.GetByteValue()->GetLength() ); } std::cout << sopinstanceuid_str1 << std::endl; std::cout << sopinstanceuid_str2 << std::endl; std::cout << refsopinstanceuid_str2 << std::endl; if( sopinstanceuid_str1 == sopinstanceuid_str2 ) { return 1; } if( sopinstanceuid_str1 != refsopinstanceuid_str2 ) { return 1; } } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestApplicationEntity.cxx000066400000000000000000000012571412732066400277220ustar00rootroot00000000000000/*========================================================================= 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 "gdcmApplicationEntity.h" int TestApplicationEntity(int, char *[]) { gdcm::ApplicationEntity ae; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestAudioCodec.cxx000066400000000000000000000012461412732066400262570ustar00rootroot00000000000000/*========================================================================= 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 "gdcmAudioCodec.h" int TestAudioCodec(int , char *[]) { gdcm::AudioCodec c; (void)c; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestCodec.cxx000066400000000000000000000015571412732066400253020ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCodec.h" namespace gdcm { class DummyCodec : public Codec { public: bool CanDecode(TransferSyntax const &) const override { return false; } bool CanCode(TransferSyntax const &) const override { return false; } }; } int TestCodec(int , char *[]) { gdcm::DummyCodec c; (void)c; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestCoder.cxx000066400000000000000000000014301412732066400253070ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCoder.h" namespace gdcm { class DummyCoder : public Coder { public: bool CanCode(TransferSyntax const &) const override { return false; } }; } int TestCoder(int, char *[]) { gdcm::DummyCoder c; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestCopyDataSet.cxx000066400000000000000000000035471412732066400264460ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmDataSet.h" #include "gdcmWriter.h" #include "gdcmTesting.h" int TestCopyDataSet(int, char *[]) { std::string dataroot = gdcm::Testing::GetDataRoot(); std::string filename = dataroot + "/test.acr"; gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if ( !reader.Read() ) { return 1; } const gdcm::DataSet &ds = reader.GetFile().GetDataSet(); gdcm::DataSet ds_copy = ds; gdcm::DataElement n( gdcm::Tag(0x0028,0x0005) ); n.SetByteValue( "3", 1 ); std::cout << n << std::endl; ds_copy.Replace( n ); std::cout << ds_copy << std::endl; // roup="0018" element="1020" vr="LO" vm="1-n" na gdcm::DataElement n2( gdcm::Tag(0x0018,0x1020) ); //const char versions[] = "1234567890\\1234567890\\1234567890\\1234567890\\1234567890\\1234567890"; const char versions[] = "12345678901234567890123456789012345678901234567890123\\45678901234567890"; n2.SetByteValue( versions, (uint32_t)strlen(versions) ); ds_copy.Replace( n2 ); std::string outfilename = gdcm::Testing::GetTempFilename( "TestCopyDataSet.dcm" ); gdcm::Writer writer; writer.SetFile( reader.GetFile() ); writer.GetFile().GetDataSet().Replace( n2 ); writer.SetFileName( outfilename.c_str() ); writer.SetCheckFileMetaInformation( false ); writer.Write(); return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestCurve.cxx000066400000000000000000000016211412732066400253410ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCurve.h" int TestCurve(int, char *[]) { gdcm::Curve c; c.SetTypeOfData( "TAC" ); //c.SetTypeOfData( "PROF" ); //c.SetTypeOfData( "PRESSURE" ); //c.SetTypeOfData( "RESP" ); //c.SetTypeOfData( "dummy" ); std::cout << c.GetTypeOfData() << std::endl; std::cout << c.GetTypeOfDataDescription() << std::endl; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestCurve2.cxx000066400000000000000000000132211412732066400254220ustar00rootroot00000000000000/*========================================================================= 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 "gdcmCurve.h" #include "gdcmFileMetaInformation.h" #include "gdcmSystem.h" #include "gdcmImageReader.h" #include "gdcmFilename.h" #include "gdcmByteSwap.h" #include "gdcmTrace.h" #include "gdcmTesting.h" struct curveinfo { unsigned short dimensions; unsigned short numpts; const char *typeofdata; unsigned short datavaluerepresentation; const char *datamd5; }; static const curveinfo numptsarray1[] = { { 1, 1126, "PHYSIO", 0, "0fee912671ae158390efc7b49fe39f9b" } }; static const curveinfo numptsarray2[] = { { 1, 969, "PHYSIO", 0, "b46d2c6eed2944f1e16c46125022d2d4" } }; static const curveinfo numptsarray3[] = { { 2, 1864, "ECG ", 0, "22aadb1260fcb53a487a2e9e9ee445b3" } }; static const curveinfo numptsarray4[] = { { 2, 1590, "PRESSURE", 0, "6b4125d8a00c65feddb8c7c6f157e6ce" } , { 2, 1588, "ECG ", 0, "7a8e1cf198e74dd37738dbce5262c49d" } }; struct curveel { const char *name; size_t numcurves; const curveinfo *info; }; static const curveel arraycurve[] = { // gdcmData { "GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm", 1, numptsarray1 }, { "GE_DLX-8-MONO2-Multiframe.dcm", 1, numptsarray2 }, // gdcmDataExtra { "xa_integris.dcm", 1, numptsarray3 }, // random stuff: { "XA.1.2.826.0.1.3680043.3.29.1.3230389164.20272.1340974735.2.3.0.000001.dcm", 2, numptsarray4 }, }; static const curveel *getcurveelfromname(const char *filename) { static const size_t nel = sizeof( arraycurve ) / sizeof( *arraycurve ); for( size_t i = 0; i < nel; ++i ) { const curveel &c = arraycurve[i]; if( strcmp( filename, c.name) == 0 ) { return &c; } } return nullptr; } static int TestCurve2Read(const char* filename, bool verbose = false) { if( verbose ) std::cerr << "Reading: " << filename << std::endl; gdcm::ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { } int res = 0; const gdcm::Image &img = reader.GetImage(); size_t numcurves = img.GetNumberOfCurves(); gdcm::Filename fn( filename ); if( numcurves ) { const curveel *c = getcurveelfromname( fn.GetName() ); if( c == nullptr ) { std::cerr << "Can't find: " << filename << std::endl; return 1; } if( c->numcurves != numcurves ) { std::cerr << "Should be: " << numcurves << " while " << c->numcurves << std::endl; return 1; } const curveinfo *info = c->info; for( size_t idx = 0; idx < numcurves; ++idx ) { const gdcm::Curve &curve = img.GetCurve(idx); //curve.Print( std::cout ); unsigned short dim = curve.GetDimensions(); if( info[idx].dimensions != dim ) { std::cerr << "Should be: " << dim << " while " << info[idx].dimensions << " for idx: " << idx << std::endl; return 1; } unsigned short npts = curve.GetNumberOfPoints(); if( info[idx].numpts != npts ) { std::cerr << "Should be: " << npts << " while " << info[idx].numpts << " for idx: " << idx << std::endl; return 1; } const char *tofdata = curve.GetTypeOfData(); if( strcmp(info[idx].typeofdata, tofdata ) != 0 ) { std::cerr << "Should be: [" << tofdata << "] while [" << info[idx].typeofdata << "] for idx: " << idx << std::endl; return 1; } unsigned short dvr = curve.GetDataValueRepresentation(); if( info[idx].datavaluerepresentation != dvr ) { std::cerr << "Should be: " << dvr << " while " << info[idx].datavaluerepresentation << " for idx: " << idx << std::endl; return 1; } std::vector points; points.resize( 3 * npts ); curve.GetAsPoints( (float*)&points[0] ); #if 0 for( size_t i = 0; i < npts; i += 3 ) { std::cout << points[i + 0] << "," << points[i + 1] << "," << points[i + 2] << "\n"; } #endif char digest[33]; const char *buffer = (char*)&points[0]; size_t len = sizeof(float) * 3 * npts; const char *ref = info[idx].datamd5; gdcm::Testing::ComputeMD5(buffer, len, digest); if( verbose ) { std::cout << "ref=" << ref << std::endl; std::cout << "md5=" << digest << std::endl; } if( !ref ) { // new regression image needs a md5 sum std::cout << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } } } return res; } int TestCurve2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestCurve2Read(filename, true); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestCurve2Read(filename); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestDICOMDIR.cxx000066400000000000000000000015151412732066400254510ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDICOMDIR.h" #include "gdcmFileSet.h" int TestDICOMDIR(int argc, char *argv[]) { (void)argc; (void)argv; gdcm::DICOMDIR dd; gdcm::FileSet fs; gdcm::File f1; gdcm::File f2; fs.AddFile( f1 ); fs.AddFile( f2 ); gdcm::DICOMDIR dd2(fs); return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestDICOMDIRGenerator1.cxx000066400000000000000000000054601412732066400274040ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDICOMDIRGenerator.h" #include "gdcmDirectory.h" #include "gdcmWriter.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmFilenameGenerator.h" int TestDICOMDIRGenerator1(int argc, char *argv[]) { (void)argc; (void)argv; gdcm::Directory::FilenamesType filenames; gdcm::Directory::FilenamesType outfilenames; const char outsubdir[] = "TestDICOMDIRGenerator1"; std::string outtmpdir = gdcm::Testing::GetTempDirectory( outsubdir ); if( !gdcm::System::FileIsDirectory( outtmpdir.c_str() ) ) { gdcm::System::MakeDirectory( outtmpdir.c_str() ); } const char subdir[] = "TestImageChangeTransferSyntax4"; std::string directory = gdcm::Testing::GetTempDirectory( subdir ); std::string file0 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm"; std::string file1 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm"; std::string file2 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm"; std::string file3 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm"; filenames.push_back( file1 ); filenames.push_back( file3 ); filenames.push_back( file2 ); filenames.push_back( file0 ); size_t nfiles = filenames.size(); gdcm::FilenameGenerator fg; const char pattern[] = "FILE%03d"; fg.SetPattern( pattern ); fg.SetNumberOfFilenames( nfiles ); if( !fg.Generate() ) { std::cerr << "Could not generate" << std::endl; return 1; } for( unsigned int i = 0; i < nfiles; ++i ) { std::string copy = outtmpdir; copy += "/"; copy += fg.GetFilename( i ); std::cerr << filenames[i] << " -> " << copy << std::endl; std::ifstream f1(filenames[i].c_str(), std::fstream::binary); std::ofstream f2(copy.c_str(), std::fstream::binary); f2 << f1.rdbuf(); outfilenames.push_back( copy ); } gdcm::DICOMDIRGenerator gen; gen.SetFilenames( outfilenames ); gen.SetRootDirectory( outtmpdir ); gen.SetDescriptor( "MYDESCRIPTOR" ); if( !gen.Generate() ) { return 1; } gdcm::Writer writer; writer.SetFile( gen.GetFile() ); std::string outfilename = outtmpdir; outfilename += "/DICOMDIR"; writer.SetFileName( outfilename.c_str() ); if( !writer.Write() ) { return 1; } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestDICOMDIRGenerator2.cxx000066400000000000000000000053061412732066400274040ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDICOMDIRGenerator.h" #include "gdcmDirectory.h" #include "gdcmWriter.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmFilenameGenerator.h" int TestDICOMDIRGenerator2(int argc, char *argv[]) { (void)argc; const char *directory = gdcm::Testing::GetDataRoot(); (void)argv; gdcm::Directory::FilenamesType filenames; gdcm::Directory::FilenamesType outfilenames; gdcm::Directory dir; int recursive = 0; unsigned int nfiles = 1; const char subdir[] = "TestImageChangeTransferSyntax4"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { std::cerr << "Need to run TestImageChangeTransferSyntax4 before" << std::endl; return 1; } directory = tmpdir.c_str(); const char outsubdir[] = "TestDICOMDIRGenerator2"; std::string outtmpdir = gdcm::Testing::GetTempDirectory( outsubdir ); if( !gdcm::System::FileIsDirectory( outtmpdir.c_str() ) ) { gdcm::System::MakeDirectory( outtmpdir.c_str() ); } nfiles = dir.Load(directory, (recursive > 0 ? true : false)); gdcm::FilenameGenerator fg; const char pattern[] = "FILE%03d"; fg.SetPattern( pattern ); fg.SetNumberOfFilenames( nfiles ); if( !fg.Generate() ) { std::cerr << "Could not generate" << std::endl; return 1; } filenames = dir.GetFilenames(); for( unsigned int i = 0; i < nfiles; ++i ) { std::string copy = outtmpdir; copy += "/"; copy += fg.GetFilename( i ); std::cerr << filenames[i] << " -> " << copy << std::endl; std::ifstream f1(filenames[i].c_str(), std::fstream::binary); std::ofstream f2(copy.c_str(), std::fstream::binary); f2 << f1.rdbuf(); outfilenames.push_back( copy ); } gdcm::DICOMDIRGenerator gen; gen.SetFilenames( outfilenames ); gen.SetRootDirectory( outtmpdir ); gen.SetDescriptor( "MYDESCRIPTOR" ); if( !gen.Generate() ) { return 1; } gdcm::Writer writer; writer.SetFile( gen.GetFile() ); std::string outfilename = outtmpdir; outfilename += "/DICOMDIR"; writer.SetFileName( outfilename.c_str() ); if( !writer.Write() ) { return 1; } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestDataElementValueAsSQ.cxx000066400000000000000000000035741412732066400301760ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTesting.h" #include "gdcmReader.h" #include "gdcmDataElement.h" #include "gdcmSequenceOfItems.h" int TestDataElementValueAsSQ(int , char *[]) { int ret = 0; const char *filenames[] = { "D_CLUNIE_CT1_J2KI.dcm", "PET-cardio-Multiframe-Papyrus.dcm" }; const gdcm::Tag tags[] = { gdcm::Tag(0x8,0x2112), gdcm::Tag(0x41,0x1010) }; const unsigned int nfiles = sizeof(filenames)/sizeof(*filenames); const char *root = gdcm::Testing::GetDataRoot(); if( !root || !*root ) { std::cerr << "root is not defined" << std::endl; return 1; } std::string sroot = root; //sroot += "/DISCIMG/IMAGES/"; sroot += "/"; for(unsigned int i = 0; i < nfiles; ++i) { std::string filename = sroot + filenames[i]; //std::cout << filename << std::endl; gdcm::Reader r; r.SetFileName( filename.c_str() ); if( !r.Read() ) { ret++; std::cerr << "could not read: " << filename << std::endl; } const gdcm::Tag &tag = tags[i]; gdcm::DataSet &ds = r.GetFile().GetDataSet(); const gdcm::DataElement &roicsq = ds.GetDataElement( tag ); gdcm::SmartPointer sqi = roicsq.GetValueAsSQ(); if(!sqi) { ++ret; std::cerr << "could not get SQ " << tag << " from: " << filename << std::endl; } } return ret; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestDataSetHelper.cxx000066400000000000000000000173571412732066400267570ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDataSetHelper.h" #include "gdcmPrinter.h" #include "gdcmReader.h" #include "gdcmGlobal.h" #include "gdcmTesting.h" namespace gdcm { class Printer2 : public Printer { public: VR PrintDataElement(std::ostringstream & os, const Dicts &dicts, const DataSet & ds, const DataElement &de, std::ostream &out, std::string const & indent ) { const VR vr = Printer::PrintDataElement(os, dicts, ds, de, out, indent ); const VR vr2 = DataSetHelper::ComputeVR(*F, ds, de.GetTag()); if( vr != vr2 ) { std::string privcrea = ds.GetPrivateCreator(de.GetTag()); // Special case for AMIInvalidPrivateDefinedLengthSQasUN.dcm const PrivateTag pt1(0x0027,0x33,"GEMS_IMAG_01"); // DX_GE_FALCON_SNOWY-VOI.dcm const PrivateTag pt2(0x0045,0x72,"GEMS_FALCON_03"); const PrivateTag pt3(0x0045,0x73,"GEMS_FALCON_03"); if( PrivateTag(de.GetTag(),"GEMS_IMAG_01") == pt1 ) { assert( vr == VR::UL ); assert( vr2 == VR::SL ); return vr; } if( PrivateTag(de.GetTag(),"GEMS_IMAG_01") == pt2 || PrivateTag(de.GetTag(),"GEMS_IMAG_01") == pt3 ) { assert( vr == VR::IS ); assert( vr2 == VR::DS ); return vr; } // ELSCINT1_PMSCT_RLE1.dcm if( de.GetTag() == Tag(0x0020,0x0070) ) { assert( vr == VR::CS ); assert( vr2 == VR::LO ); return vr; } // EmptyIcon_Bug417.dcm if( de.GetTag() == Tag(0x0040,0x1008) ) { assert( vr == VR::ST ); assert( vr2 == VR::LO ); return vr; } // GE_CT_With_Private_compressed-icon.dcm if( de.GetTag() == Tag(0x0040,0x0253) ) { assert( vr == VR::CS ); assert( vr2 == VR::SH ); return vr; } // JPEGInvalidSecondFrag.dcm if( de.GetTag() == Tag(0x0018,0x9305) || de.GetTag() == Tag(0x0018,0x9306) || de.GetTag() == Tag(0x0018,0x9307) || de.GetTag() == Tag(0x0023,0x1070) ) { assert( vr == VR::OB ); assert( vr2 == VR::FD ); return vr; } // NM-PAL-16-PixRep1.dcm...FIXME: dcmconv +te if( de.GetTag() == Tag(0x0028,0x1101) || de.GetTag() == Tag(0x0028,0x1102) || de.GetTag() == Tag(0x0028,0x1103) || de.GetTag() == Tag(0x0028,0x1201) || de.GetTag() == Tag(0x0028,0x1202) || de.GetTag() == Tag(0x0028,0x1203) ) { assert( vr == VR::US ); assert( vr2 == VR::SS || vr2 == VR::OW ); return vr; } // PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm if( de.GetTag() == Tag(0x0008,0x0010) || de.GetTag() == Tag(0x0018,0x4000) || de.GetTag() == Tag(0x0020,0x3402) ) { assert( vr == VR::LO ); assert( vr2 == VR::CS || vr2 == VR::LT || vr2 == VR::SH ); return vr; } // PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm if( de.GetTag() == Tag(0x0020,0x1001) || de.GetTag() == Tag(0x0028,0x0005) || de.GetTag() == Tag(0x0028,0x0040) || de.GetTag() == Tag(0x0028,0x0200) ) { assert( vr == VR::DS || vr == VR::SS || vr == VR::SH ); assert( vr2 == VR::IS || vr2 == VR::US || vr2 == VR::CS ); return vr; } // PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm if( de.GetTag() == Tag(0x0008,0x0040) ) { assert( vr == VR::SS ); assert( vr2 == VR::US ); return vr; } if( vr == VR::SQ || vr2 == VR::SQ ) assert( vr == vr2 ); if( !de.GetTag().IsPrivate() ) assert( vr == vr2 ); //assert( vr.Compatible(vr2) ); } return vr; } void PrintSQ(const SequenceOfItems *sqi, std::ostream & os, std::string const & indent) { if( !sqi ) return; SequenceOfItems::ItemVector::const_iterator it = sqi->Items.begin(); for(; it != sqi->Items.end(); ++it) { const Item &item = *it; const DataSet &ds = item.GetNestedDataSet(); const DataElement &deitem = item; std::string nextindent = indent + " "; os << nextindent << deitem.GetTag(); os << " "; os << "na"; //deitem.GetVR(); os << " "; if( deitem.GetVL().IsUndefined() ) { os << "(Item with undefined length)"; } else { os << "(Item with defined length)"; } os << "\n"; PrintDataSet(ds, os, nextindent + " "); if( deitem.GetVL().IsUndefined() ) { const Tag itemDelItem(0xfffe,0xe00d); os << nextindent << itemDelItem << "\n"; } } if( sqi->GetLength().IsUndefined() ) { const Tag seqDelItem(0xfffe,0xe0dd); os << indent << seqDelItem << "\n"; } } void PrintDataSet(const DataSet &ds, std::ostream &out, std::string const & indent = "" ) { const Global& g = GlobalInstance; const Dicts &dicts = g.GetDicts(); DataSet::ConstIterator it = ds.Begin(); for( ; it != ds.End(); ++it ) { const DataElement &de = *it; const SequenceOfFragments *sqf = de.GetSequenceOfFragments(); std::ostringstream os; VR refvr = PrintDataElement(os, dicts, ds, de, out, indent); if( refvr == VR::SQ /*|| sqi*/ ) { SmartPointer sqi2 = de.GetValueAsSQ(); // may throw PrintSQ(sqi2, os, indent); } else if ( sqf ) { std::string nextindent = indent + " "; const BasicOffsetTable & table = sqf->GetTable(); PrintDataElement(os,dicts,ds,table,out,nextindent); size_t numfrag = sqf->GetNumberOfFragments(); for(size_t i = 0; i < numfrag; ++i) { const Fragment& frag = sqf->GetFragment(i); PrintDataElement(os,dicts,ds,frag,out,nextindent); } const Tag seqDelItem(0xfffe,0xe0dd); VL zero = 0; os << /*nextindent <<*/ seqDelItem; os << " " << zero << "\n"; } else { // This is a byte value, so it should have been already treated } out << os.str(); } } void Print(std::ostream& os) { os << "# Dicom-File-Format\n"; os << "\n"; os << "# Dicom-Meta-Information-Header\n"; os << "# Used TransferSyntax: \n"; const FileMetaInformation &meta = F->GetHeader(); PrintDataSet(meta, os); os << "\n# Dicom-Data-Set\n"; os << "# Used TransferSyntax: "; const TransferSyntax &metats = meta.GetDataSetTransferSyntax(); os << metats; os << std::endl; const DataSet &ds = F->GetDataSet(); PrintDataSet(ds, os); } }; } // namespace gdcm static int TestDataSetHelperFunc(const char *filename, bool verbose= false) { gdcm::Reader r; r.SetFileName( filename ); if( !r.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } const gdcm::File & file = r.GetFile(); gdcm::Printer2 print; print.SetFile( file ); std::ostringstream out; if( verbose ) print.Print( std::cout ); print.Print( out ); return 0; } int TestDataSetHelper(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestDataSetHelperFunc(filename, true); } // else int r = 0, i = 0; gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestDataSetHelperFunc( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestDecoder.cxx000066400000000000000000000014441412732066400256250ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDecoder.h" namespace gdcm { class DummyDecoder : public Decoder { public: bool CanDecode(TransferSyntax const &) const override { return false; } }; } int TestDecoder(int, char *[]) { gdcm::DummyDecoder d; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestDictPrinter.cxx000066400000000000000000000012351412732066400265050ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDictPrinter.h" int TestDictPrinter(int, char *[]) { gdcm::DictPrinter dp; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestDirectionCosines.cxx000066400000000000000000000126631412732066400275310ustar00rootroot00000000000000/*========================================================================= 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 "gdcmDirectionCosines.h" #include #include /* * Let's use the CrossDot API to compare IOP safely */ static const char * ImageOrientationPatientList[] = { R"(0.999081\0.0426953\0.00369275\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369272\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369275\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369272\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369275\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426952\0.00369272\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369272\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369274\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369274\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369272\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369272\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426952\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426952\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369274\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369274\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369274\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369275\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369272\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369275\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369272\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369275\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426952\0.00369272\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369272\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369274\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369274\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369272\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369272\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426952\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426952\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369273\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369274\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369274\-0.0419025\0.955059\0.293439)", R"(0.999081\0.0426953\0.00369274\-0.0419025\0.955059\0.293439)", }; bool TestCrossDot() { std::set< std::string > myset; const unsigned int nipp = sizeof(ImageOrientationPatientList) / sizeof(*ImageOrientationPatientList); for( unsigned int i = 0; i < nipp; ++i ) { myset.insert( ImageOrientationPatientList[i] ); } if( myset.size() <= 1 ) return false; std::set< std::string >::const_iterator it = myset.begin(); gdcm::DirectionCosines ref; gdcm::DirectionCosines dc; for( ; it != myset.end(); ++it ) { ref.SetFromString( it->c_str() ); for( unsigned int i = 0; i < nipp; ++i ) { dc.SetFromString( ImageOrientationPatientList[i] ); const double crossdot = ref.CrossDot( dc); const double eps = 1. - crossdot; if( eps > 1e-6 || eps < 0 ) return false; } } return true; } int TestDirectionCosines(int, char *[]) { gdcm::DirectionCosines dc; //const double *dircos = dc; if( !dc.IsValid() ) { return 1; } const double cross[3] = {0,0,1}; double z[3]; dc.Cross(z); if( z[0] != cross[0] || z[1] != cross[1] || z[2] != cross[2] ) { return 1; } bool b = TestCrossDot(); if( !b ) return 1; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestDumper.cxx000066400000000000000000000037221412732066400255150ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmDumper.h" #include "gdcmTesting.h" #include "gdcmCSAHeader.h" int TestDump(const char *filename) { gdcm::Reader r; r.SetFileName( filename ); if( !r.Read() ) { return 1; } std::ostringstream out; { gdcm::Dumper p; p.SetFile( r.GetFile() ); //p.Print( std::cout ); p.Print( out ); } // Test CSA Header here too gdcm::CSAHeader csa; const gdcm::DataSet& ds = r.GetFile().GetDataSet(); const gdcm::PrivateTag &t1 = csa.GetCSAImageHeaderInfoTag(); const gdcm::PrivateTag &t2 = csa.GetCSASeriesHeaderInfoTag(); if( ds.FindDataElement( t1 ) ) { csa.LoadFromDataElement( ds.GetDataElement( t1 ) ); csa.Print( std::cout ); } if( ds.FindDataElement( t2 ) ) { csa.LoadFromDataElement( ds.GetDataElement( t2 ) ); csa.Print( std::cout ); } if( csa.GetFormat() == gdcm::CSAHeader::DATASET_FORMAT ) { gdcm::Dumper p; gdcm::File f; f.SetDataSet( csa.GetDataSet() ); p.SetFile( f ); //p.Print( std::cout ); p.Print( out ); } return 0; } int TestDumper(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestDump(filename); } // else int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestDump( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestEncapsulatedDocument.cxx000066400000000000000000000013501412732066400303630ustar00rootroot00000000000000/*========================================================================= 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 "gdcmEncapsulatedDocument.h" int TestEncapsulatedDocument(int argc, char *argv[]) { (void)argc; (void)argv; gdcm::EncapsulatedDocument w; (void)w; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestEquipmentManufacturer.cxx000066400000000000000000000114411412732066400306020ustar00rootroot00000000000000/*========================================================================= 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 "gdcmEquipmentManufacturer.h" #include "gdcmReader.h" #include "gdcmFilename.h" #include "gdcmTesting.h" static int TestEquipmentManufacturerFunc(const char* filename, bool verbose = false) { if( verbose ) std::cerr << "Reading: " << filename << std::endl; gdcm::Reader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { std::cerr << "TestReadError: Failed to read: " << filename << std::endl; return 1; } const gdcm::File & file = reader.GetFile(); gdcm::MediaStorage ms; ms.SetFromFile( file ); if(ms == gdcm::MediaStorage::MediaStorageDirectoryStorage) return 0; // skip DICOMDIR gdcm::Filename fn( filename ); const char *name = fn.GetName(); // Special handling: if( strcmp(name, "OsirixFake16BitsStoredFakeSpacing.dcm" ) == 0 || strcmp(name, "simpleImageWithIcon.dcm" ) == 0 || strcmp(name, "rle16sti.dcm" ) == 0 || strcmp(name, "rle16loo.dcm" ) == 0 || strcmp(name, "gdcm-CR-DCMTK-16-NonSamplePerPix.dcm" ) == 0 || strcmp(name, "XA-MONO2-8-12x-catheter.dcm" ) == 0 || strcmp(name, "US-RGB-8-esopecho.dcm" ) == 0 || strcmp(name, "US-PAL-8-10x-echo.dcm" ) == 0 || strcmp(name, "US-MONO2-8-8x-execho.dcm" ) == 0 || strcmp(name, "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm" ) == 0 || strcmp(name, "SignedShortLosslessBug.dcm" ) == 0 || strcmp(name, "SC16BitsAllocated_8BitsStoredJPEG.dcm" ) == 0 || strcmp(name, "SC16BitsAllocated_8BitsStoredJ2K.dcm" ) == 0 || strcmp(name, "RadBWLossLess.dcm" ) == 0 || strcmp(name, "RLEDebianBug816607Orig.dcm" ) == 0 || strcmp(name, "DermaColorLossLess.dcm" ) == 0 || strcmp(name, "00191113.dcm" ) == 0 || strcmp(name, "test.acr" ) == 0 || strcmp(name, "LIBIDO-8-ACR_NEMA-Lena_128_128.acr" ) == 0 || strcmp(name, "gdcm-ACR-LibIDO.acr" ) == 0 || strcmp(name, "libido1.0-vol.acr" ) == 0 || strcmp(name, "DCMTK_JPEGExt_12Bits.dcm" ) == 0 || strcmp(name, "DMCPACS_ExplicitImplicit_BogusIOP.dcm" ) == 0 || strcmp(name, "DX_J2K_0Padding.dcm" ) == 0 || strcmp(name, "GDCMJ2K_TextGBR.dcm" ) == 0 || strcmp(name, "ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm" ) == 0 || strcmp(name, "JPEGLS_CharLS_10742.dcm" ) == 0 || strcmp(name, "JPEGLosslessYBR_FULL_422.dcm" ) == 0 || strcmp(name, "JPEGLosslessSeNonZero.dcm" ) == 0 || strcmp(name, "US-YBR_FULL_422-EVRLE.dcm" ) == 0 || strcmp(name, "LIBIDO-24-ACR_NEMA-Rectangle.dcm" ) == 0 || strcmp(name, "MR-Brucker-CineTagging-NonSquarePixels.dcm" ) == 0 || strcmp(name, "MR16BitsAllocated_8BitsStored.dcm" ) == 0 || strcmp(name, "NM-MONO2-16-13x-heart.dcm" ) == 0 || strcmp(name, "NM-PAL-16-PixRep1.dcm" ) == 0 || strcmp(name, "NM_Kakadu44_SOTmarkerincons.dcm" ) == 0 || strcmp(name, "PICKER-16-MONO2-No_DicomV3_Preamble.dcm" ) == 0 || strcmp(name, "OT-PAL-8-face.dcm" ) == 0 || strcmp(name, "TG18-CH-2k-01.dcm" ) == 0 // wotsit ? || strcmp(name, "HardcopyColor_YBR_RCT_J2K_PC1.dcm" ) == 0 // RamSoft Inc. || strncmp(name, "D_CLUNIE", 8) == 0 // D_CLUNIE* || strncmp(name, "LEADTOOLS_FLOWERS", 17) == 0 // LEADTOOLS_FLOWERS* || strncmp(name, "JDDICOM", 7) == 0 // JDDICOM* || strncmp(name, "JPEGNote", 8) == 0 // JPEGNote* || strncmp(name, "KODAK", 5) == 0 // KODAK* || strncmp(name, "DICOMDIR", 8) == 0 // DICOMDIR* || strncmp(name, "dicomdir", 8) == 0 // dicomdir* ) { if( verbose ) std::cout << "skip: " << filename << std::endl; return 0; } const gdcm::DataSet & ds = file.GetDataSet(); gdcm::EquipmentManufacturer::Type manufacturer = gdcm::EquipmentManufacturer::Compute( ds ); if( verbose ) { std::cout << "Found: " << manufacturer << std::endl; } if( manufacturer == gdcm::EquipmentManufacturer::UNKNOWN ) { std::cerr << "Unknown: " << filename << std::endl; return 1; } return 0; } int TestEquipmentManufacturer(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestEquipmentManufacturerFunc(filename, true); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestEquipmentManufacturerFunc(filename); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFiducials.cxx000066400000000000000000000013071412732066400261610ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFiducials.h" int TestFiducials(int argc, char *argv[]) { (void)argc; (void)argv; gdcm::Fiducials f; (void)f; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileAnonymizer1.cxx000066400000000000000000000072611412732066400272770ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileAnonymizer.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmFilename.h" int TestFileAnonymize1(const char *filename, bool verbose = false) { using namespace gdcm; if( verbose ) std::cout << "Processing: " << filename << std::endl; // Create directory first: const char subdir[] = "TestFileAnonymize1"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); const gdcm::Tag t1(0x0018,0x5100); const gdcm::Tag t2(0x0018,0x1312); const gdcm::Tag t3(0x0018,0x1313); const gdcm::Tag t4(0x0018,0x1317); const gdcm::Tag t5(0x0008,0x2112); const gdcm::Tag t6(0x0008,0x9215); const gdcm::Tag t7(0x0018,0x1020); const gdcm::Tag t8(0x0004,0x1130); // Test DICOMDIR ! const gdcm::Tag t9(0x0008,0x0000); // Earliest possible Data Element const gdcm::Tag t0(0xffff,0xffff); // Latest Possible Element std::vector tags; tags.push_back( t0 ); tags.push_back( t1 ); tags.push_back( t2 ); tags.push_back( t3 ); tags.push_back( t4 ); tags.push_back( t5 ); tags.push_back( t6 ); tags.push_back( t7 ); tags.push_back( t8 ); tags.push_back( t9 ); // precondition, remove the file if present: System::RemoveFile(outfilename.c_str()); gdcm::FileAnonymizer fa; fa.SetInputFileName( filename ); fa.SetOutputFileName( outfilename.c_str() ); for( std::vector::const_iterator it = tags.begin(); it != tags.end(); ++it ) { fa.Remove( *it ); } if( !fa.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // Read back and check: gdcm::Reader r; r.SetFileName( outfilename.c_str() ); if( !r.Read() ) { std::cerr << "Failed to read: " << outfilename << std::endl; return 1; } const File &f = r.GetFile(); const DataSet &ds = f.GetDataSet(); for( std::vector::const_iterator it = tags.begin(); it != tags.end(); ++it ) { const gdcm::Tag & t = *it; if( ds.FindDataElement( t ) ) { gdcm::Filename fn( filename ); std::cerr << "Found element: " << t << " in " << outfilename << std::endl; gdcm::MediaStorage ms; ms.SetFromFile( f ); const bool isdicomdir = (ms == gdcm::MediaStorage::MediaStorageDirectoryStorage); // de-activate for now if( strcmp(fn.GetName(), "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm") == 0 || isdicomdir ) { return 0; } return 1; } } return 0; } int TestFileAnonymizer1(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileAnonymize1(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileAnonymize1( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileAnonymizer2.cxx000066400000000000000000000102231412732066400272700ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileAnonymizer.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmFilename.h" static int TestFileAnonymize2(const char *filename, bool verbose = false) { using namespace gdcm; if( verbose ) std::cout << "Processing: " << filename << std::endl; // Create directory first: const char subdir[] = "TestFileAnonymize2"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); const gdcm::Tag t1(0x0018,0x5100); const gdcm::Tag t2(0x0018,0x1312); const gdcm::Tag t3(0x0018,0x1313); const gdcm::Tag t4(0x0018,0x1317); const gdcm::Tag t5(0x0008,0x2112); const gdcm::Tag t6(0x0008,0x9215); const gdcm::Tag t7(0x0018,0x1020); const gdcm::Tag t8(0x0004,0x1130); // Test DICOMDIR ! const gdcm::Tag t9(0x0008,0x0000); // Earliest possible Data Element const gdcm::Tag t0(0xffff,0xffff); // Latest Possible Element std::vector tags; tags.push_back( t0 ); tags.push_back( t1 ); tags.push_back( t2 ); tags.push_back( t3 ); tags.push_back( t4 ); tags.push_back( t5 ); tags.push_back( t6 ); tags.push_back( t7 ); tags.push_back( t8 ); tags.push_back( t9 ); // precondition, remove the file if present: System::RemoveFile(outfilename.c_str()); gdcm::FileAnonymizer fa; fa.SetInputFileName( filename ); fa.SetOutputFileName( outfilename.c_str() ); for( std::vector::const_iterator it = tags.begin(); it != tags.end(); ++it ) { fa.Empty( *it ); } if( !fa.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // Read back and check: gdcm::Reader r; r.SetFileName( outfilename.c_str() ); if( !r.Read() ) { gdcm::Filename fn( filename ); std::cerr << "Failed to read: " << outfilename << std::endl; if( strcmp(fn.GetName(), "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm") == 0 || strcmp(fn.GetName(), "DMCPACS_ExplicitImplicit_BogusIOP.dcm") == 0 || strcmp(fn.GetName(), "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm") == 0 ) { return 0; } return 1; } const File &f = r.GetFile(); gdcm::MediaStorage ms; ms.SetFromFile( f ); const DataSet &ds = f.GetDataSet(); for( std::vector::const_iterator it = tags.begin(); it != tags.end(); ++it ) { const gdcm::Tag & t = *it; // Special handling of t8 (DICOMDIR only) const bool iserror = (ms == gdcm::MediaStorage::MediaStorageDirectoryStorage && t == t8) && false; // de-activate for now if( !ds.FindDataElement( t ) ) { if( iserror ) { std::cerr << "Not found element: " << t << " in " << outfilename << std::endl; return 1; } } const gdcm::DataElement & de = ds.GetDataElement( t ); if( de.GetVL() != 0 ) { if( iserror ) { std::cerr << "Wrong VL for: " << t << " in " << outfilename << std::endl; return 1; } } } return 0; } int TestFileAnonymizer2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileAnonymize2(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileAnonymize2( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileAnonymizer3.cxx000066400000000000000000000103361412732066400272760ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileAnonymizer.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmFilename.h" #include static int TestFileAnonymize3(const char *filename, bool verbose = false) { using namespace gdcm; if( verbose ) std::cout << "Processing: " << filename << std::endl; // Create directory first: const char subdir[] = "TestFileAnonymize3"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); if( verbose ) std::cout << "Generating: " << outfilename << std::endl; const gdcm::Tag t1(0x0018,0x5100); const gdcm::Tag t2(0x0018,0x1312); const gdcm::Tag t3(0x0018,0x1313); const gdcm::Tag t4(0x0018,0x1317); //const gdcm::Tag t5(0x0008,0x2112); // SQ //const gdcm::Tag t6(0x0008,0x9215); // SQ const gdcm::Tag t7(0x0018,0x1020); const gdcm::Tag t8(0x0004,0x1130); // Test DICOMDIR ! const gdcm::Tag t9(0x0008,0x0000); // Earliest possible Data Element const gdcm::Tag t0(0xffff,0xffff); // Latest Possible Element std::vector tags; tags.push_back( t0 ); tags.push_back( t1 ); tags.push_back( t2 ); tags.push_back( t3 ); tags.push_back( t4 ); tags.push_back( t7 ); tags.push_back( t8 ); tags.push_back( t9 ); // precondition, remove the file if present: System::RemoveFile(outfilename.c_str()); gdcm::FileAnonymizer fa; fa.SetInputFileName( filename ); fa.SetOutputFileName( outfilename.c_str() ); for( std::vector::const_iterator it = tags.begin(); it != tags.end(); ++it ) { fa.Replace( *it, "TOTO" ); } if( !fa.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // Read back and check: gdcm::Reader r; r.SetFileName( outfilename.c_str() ); if( !r.Read() ) { gdcm::Filename fn( filename ); if( strcmp(fn.GetName(), "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm") == 0 || strcmp(fn.GetName(), "DMCPACS_ExplicitImplicit_BogusIOP.dcm") == 0 || strcmp(fn.GetName(), "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm") == 0 ) { return 0; } std::cerr << "Failed to read: " << outfilename << std::endl; return 1; } const File &f = r.GetFile(); gdcm::MediaStorage ms; ms.SetFromFile( f ); const DataSet &ds = f.GetDataSet(); for( std::vector::const_iterator it = tags.begin(); it != tags.end(); ++it ) { const gdcm::Tag & t = *it; // Special handling of t8 (DICOMDIR only) const bool iserror = (ms == gdcm::MediaStorage::MediaStorageDirectoryStorage && t == t8) && false; // de-activate for now if( !ds.FindDataElement( t ) ) { if( iserror ) { std::cerr << "Not found element: " << t << " in " << outfilename << std::endl; return 1; } } const gdcm::DataElement & de = ds.GetDataElement( t ); if( de.GetVL() != 4 ) { if( iserror ) { std::cerr << "Wrong VL for: " << t << " in " << outfilename << std::endl; return 1; } } } return 0; } int TestFileAnonymizer3(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileAnonymize3(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileAnonymize3( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileAnonymizer4.cxx000066400000000000000000000121211412732066400272710ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileAnonymizer.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmFilename.h" #include // in-place replace checking static int TestFileAnonymize4(const char *filename, bool verbose = false) { using namespace gdcm; if( verbose ) std::cout << "Processing: " << filename << std::endl; // Create directory first: const char subdir[] = "TestFileAnonymize4"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); if( verbose ) std::cout << "Generating: " << outfilename << std::endl; const gdcm::Tag t1(0x0018,0x5100); const gdcm::Tag t2(0x0018,0x1312); const gdcm::Tag t3(0x0018,0x1313); const gdcm::Tag t4(0x0018,0x1317); //const gdcm::Tag t5(0x0008,0x2112); // SQ //const gdcm::Tag t6(0x0008,0x9215); // SQ const gdcm::Tag t7(0x0018,0x1020); const gdcm::Tag t8(0x0004,0x1130); // Test DICOMDIR ! const gdcm::Tag t9(0x0008,0x0000); // Earliest possible Data Element const gdcm::Tag t0(0xffff,0xffff); // Latest Possible Element std::vector tags; tags.push_back( t0 ); tags.push_back( t1 ); tags.push_back( t2 ); tags.push_back( t3 ); tags.push_back( t4 ); tags.push_back( t7 ); tags.push_back( t8 ); tags.push_back( t9 ); // precondition, remove the file if present: System::RemoveFile(outfilename.c_str()); { gdcm::FileAnonymizer fa; fa.SetInputFileName( filename ); fa.SetOutputFileName( outfilename.c_str() ); for( std::vector::const_iterator it = tags.begin(); it != tags.end(); ++it ) { fa.Replace( *it, "TOTO" ); } if( !fa.Write() ) { std::cerr << "Failed to write (1): " << outfilename << std::endl; return 1; } } { // Read back and check: gdcm::Reader r; r.SetFileName( outfilename.c_str() ); if( !r.Read() ) { gdcm::Filename fn( filename ); if( strcmp(fn.GetName(), "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm") == 0 || strcmp(fn.GetName(), "DMCPACS_ExplicitImplicit_BogusIOP.dcm") == 0 || strcmp(fn.GetName(), "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm") == 0 ) { return 0; } std::cerr << "Failed to read: " << outfilename << std::endl; return 1; } } { gdcm::FileAnonymizer fa; fa.SetInputFileName( outfilename.c_str() ); fa.SetOutputFileName( outfilename.c_str() ); for( std::vector::const_iterator it = tags.begin(); it != tags.end(); ++it ) { fa.Replace( *it, "TATA" ); } if( !fa.Write() ) { gdcm::Filename fn( filename ); if( strcmp(fn.GetName(), "JPEGInvalidSecondFrag.dcm") == 0 ) { } else { std::cerr << "Failed to write (2): " << outfilename << std::endl; return 1; } } } // Read back and check: gdcm::Reader r; r.SetFileName( outfilename.c_str() ); if( !r.Read() ) { std::cerr << "Failed to read (2): " << outfilename << std::endl; return 1; } const File &f = r.GetFile(); gdcm::MediaStorage ms; ms.SetFromFile( f ); const DataSet &ds = f.GetDataSet(); for( std::vector::const_iterator it = tags.begin(); it != tags.end(); ++it ) { const gdcm::Tag & t = *it; // Special handling of t8 (DICOMDIR only) const bool iserror = (ms == gdcm::MediaStorage::MediaStorageDirectoryStorage && t == t8) && false; // de-activate for now if( !ds.FindDataElement( t ) ) { if( iserror ) { std::cerr << "Not found element: " << t << " in " << outfilename << std::endl; return 1; } } const gdcm::DataElement & de = ds.GetDataElement( t ); if( de.GetVL() != 4 ) { if( iserror ) { std::cerr << "Wrong VL for: " << t << " in " << outfilename << std::endl; return 1; } } } return 0; } int TestFileAnonymizer4(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileAnonymize4(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileAnonymize4( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileChangeTransferSyntax1.cxx000066400000000000000000000161511412732066400312430ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileChangeTransferSyntax.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmImageReader.h" #include "gdcmFilename.h" #include "gdcmImageChangePlanarConfiguration.h" #include "gdcmByteSwap.h" static int TestFileChangeTransferSyntax1Func(const char *filename, bool verbose = false) { using namespace gdcm; if( verbose ) std::cout << "Processing: " << filename << std::endl; // Create directory first: const char subdir[] = "TestFileChangeTransferSyntax1"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); if( verbose ) std::cout << "Generating: " << outfilename << std::endl; const gdcm::TransferSyntax ts( TransferSyntax::JPEGLosslessProcess14_1 ); gdcm::FileChangeTransferSyntax fcts; fcts.SetTransferSyntax( ts ); fcts.SetInputFileName( filename ); fcts.SetOutputFileName( outfilename.c_str() ); ImageCodec *ic = fcts.GetCodec(); if( !ic ) { return 1; } if( !fcts.Change() ) { gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "not dicom" << std::endl; return 1; } const gdcm::File & file = reader.GetFile(); const gdcm::FileMetaInformation & fmi = file.GetHeader(); const TransferSyntax &tsref = fmi.GetDataSetTransferSyntax(); if( tsref.IsEncapsulated() ) { if( verbose ) std::cout << "Will not generate (encaps): " << outfilename << std::endl; return 0; } gdcm::Filename fn( filename ); const char *name = fn.GetName(); // Special handling: if( strcmp(name, "CT-MONO2-12-lomb-an2.acr" ) == 0 || strcmp(name, "LIBIDO-8-ACR_NEMA-Lena_128_128.acr") == 0 || strcmp(name, "gdcm-ACR-LibIDO.acr") == 0 || strcmp(name, "gdcm-MR-SIEMENS-16-2.acr") == 0 || strcmp(name, "libido1.0-vol.acr") == 0 || strcmp(name, "test.acr") == 0 || strcmp(name, "LIBIDO-24-ACR_NEMA-Rectangle.dcm") == 0 || strcmp(name, "MR_Spectroscopy_SIEMENS_OF.dcm") == 0 // not an image || strcmp(name, "ELSCINT1_PMSCT_RLE1.dcm") == 0 || strcmp(name, "ELSCINT1_PMSCT_RLE1_priv.dcm") == 0 || strcmp(name, "gdcm-CR-DCMTK-16-NonSamplePerPix.dcm") == 0 || strcmp(name, "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm") == 0 || strcmp(name, "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm") == 0 // Implicit VR Big Endian DLX (G.E Private) || strcmp(name, "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm") == 0 // Explicit VR Big Endian || strcmp(name, "US-RGB-8-epicard.dcm") == 0 // Explicit VR Big Endian || strcmp(name, "GE_DLX-8-MONO2-PrivateSyntax.dcm") == 0 // Implicit VR Big Endian DLX (G.E Private) || strcmp(name, "GE_CT_With_Private_compressed-icon.dcm") == 0 // Explicit VR Big Endian || strcmp(name, "JDDICOM_Sample2-dcmdjpeg.dcm") == 0 // cannot recreate FMI || strcmp(name, "DMCPACS_ExplicitImplicit_BogusIOP.dcm") == 0 // ImageRegionReader does not handle it || strcmp(name, "unreadable.dcm") == 0 // No Pixel Data (old ACR-NEMA) || strcmp(name, "US-YBR_FULL_422-EVRLE.dcm") == 0 // packed ybr422 || strncmp(name, "DICOMDIR", 8) == 0 // DICOMDIR* || strncmp(name, "dicomdir", 8) == 0 // dicomdir* ) { if( verbose ) std::cout << "Will not generate: " << outfilename << std::endl; return 0; } std::cerr << "Could not change: " << filename << std::endl; return 1; } // Let's read that file back in ! gdcm::ImageReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Could not even reread our generated file : " << outfilename << std::endl; return 1; } // Check that after decompression we still find the same thing: int res = 0; gdcm::Image img = reader2.GetImage(); int pc = 0; // When recompressing: US-RGB-8-epicard.dcm, make sure to compute the md5 using the // same original Planar Configuration... if( (int)img.GetPlanarConfiguration() != pc ) { gdcm::ImageChangePlanarConfiguration icpc; icpc.SetInput( reader2.GetImage() ); icpc.SetPlanarConfiguration( pc ); icpc.Change(); img = icpc.GetOutput(); } //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; bool res2 = img.GetBuffer(buffer); if( !res2 ) { std::cerr << "could not get buffer: " << outfilename << std::endl; return 1; } // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: #ifdef GDCM_WORDS_BIGENDIAN if( img.GetPixelFormat().GetBitsAllocated() == 16 ) { assert( !(len % 2) ); assert( img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 || img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ); gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem( (unsigned short*)buffer, gdcm::SwapCode::LittleEndian, len/2); } #endif const char *ref = gdcm::Testing::GetMD5FromFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( !ref ) { // new regression image needs a md5 sum std::cerr << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } if(res) { std::cerr << "problem with: " << outfilename << std::endl; } if( verbose ) { std::cout << "file was written in: " << outfilename << std::endl; } delete[] buffer; return res; } int TestFileChangeTransferSyntax1(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileChangeTransferSyntax1Func(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileChangeTransferSyntax1Func( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileChangeTransferSyntax2.cxx000066400000000000000000000161401412732066400312420ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileChangeTransferSyntax.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmImageReader.h" #include "gdcmFilename.h" #include "gdcmImageChangePlanarConfiguration.h" #include "gdcmByteSwap.h" static int TestFileChangeTransferSyntax2Func(const char *filename, bool verbose = false) { using namespace gdcm; if( verbose ) std::cout << "Processing: " << filename << std::endl; // Create directory first: const char subdir[] = "TestFileChangeTransferSyntax2"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); if( verbose ) std::cout << "Generating: " << outfilename << std::endl; const gdcm::TransferSyntax ts( TransferSyntax::JPEGLSLossless ); gdcm::FileChangeTransferSyntax fcts; fcts.SetTransferSyntax( ts ); fcts.SetInputFileName( filename ); fcts.SetOutputFileName( outfilename.c_str() ); ImageCodec *ic = fcts.GetCodec(); if( !ic ) { return 1; } if( !fcts.Change() ) { gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "not dicom" << std::endl; return 1; } const gdcm::File & file = reader.GetFile(); const gdcm::FileMetaInformation & fmi = file.GetHeader(); const TransferSyntax &tsref = fmi.GetDataSetTransferSyntax(); if( tsref.IsEncapsulated() ) { if( verbose ) std::cout << "Will not generate (encaps): " << outfilename << std::endl; return 0; } gdcm::Filename fn( filename ); const char *name = fn.GetName(); // Special handling: if( strcmp(name, "CT-MONO2-12-lomb-an2.acr" ) == 0 || strcmp(name, "LIBIDO-8-ACR_NEMA-Lena_128_128.acr") == 0 || strcmp(name, "gdcm-ACR-LibIDO.acr") == 0 || strcmp(name, "gdcm-MR-SIEMENS-16-2.acr") == 0 || strcmp(name, "libido1.0-vol.acr") == 0 || strcmp(name, "test.acr") == 0 || strcmp(name, "LIBIDO-24-ACR_NEMA-Rectangle.dcm") == 0 || strcmp(name, "MR_Spectroscopy_SIEMENS_OF.dcm") == 0 // not an image || strcmp(name, "ELSCINT1_PMSCT_RLE1.dcm") == 0 || strcmp(name, "ELSCINT1_PMSCT_RLE1_priv.dcm") == 0 || strcmp(name, "gdcm-CR-DCMTK-16-NonSamplePerPix.dcm") == 0 || strcmp(name, "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm") == 0 || strcmp(name, "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm") == 0 // Implicit VR Big Endian DLX (G.E Private) || strcmp(name, "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm") == 0 // Explicit VR Big Endian || strcmp(name, "US-RGB-8-epicard.dcm") == 0 // Explicit VR Big Endian || strcmp(name, "GE_DLX-8-MONO2-PrivateSyntax.dcm") == 0 // Implicit VR Big Endian DLX (G.E Private) || strcmp(name, "GE_CT_With_Private_compressed-icon.dcm") == 0 // Explicit VR Big Endian || strcmp(name, "JDDICOM_Sample2-dcmdjpeg.dcm") == 0 // cannot recreate FMI || strcmp(name, "DMCPACS_ExplicitImplicit_BogusIOP.dcm") == 0 // ImageRegionReader does not handle it || strcmp(name, "unreadable.dcm") == 0 // No Pixel Data (old ACR-NEMA) || strcmp(name, "US-YBR_FULL_422-EVRLE.dcm") == 0 // packed ybr422 || strncmp(name, "DICOMDIR", 8) == 0 // DICOMDIR* || strncmp(name, "dicomdir", 8) == 0 // dicomdir* ) { if( verbose ) std::cout << "Will not generate: " << outfilename << std::endl; return 0; } std::cerr << "Could not change: " << filename << std::endl; return 1; } // Let's read that file back in ! gdcm::ImageReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Could not even reread our generated file : " << outfilename << std::endl; return 1; } // Check that after decompression we still find the same thing: int res = 0; gdcm::Image img = reader2.GetImage(); int pc = 0; // When recompressing: US-RGB-8-epicard.dcm, make sure to compute the md5 using the // same original Planar Configuration... if( (int)img.GetPlanarConfiguration() != pc ) { gdcm::ImageChangePlanarConfiguration icpc; icpc.SetInput( reader2.GetImage() ); icpc.SetPlanarConfiguration( pc ); icpc.Change(); img = icpc.GetOutput(); } //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; bool res2 = img.GetBuffer(buffer); if( !res2 ) { std::cerr << "could not get buffer: " << outfilename << std::endl; return 1; } // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: #ifdef GDCM_WORDS_BIGENDIAN if( img.GetPixelFormat().GetBitsAllocated() == 16 ) { assert( !(len % 2) ); assert( img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 || img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ); gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem( (unsigned short*)buffer, gdcm::SwapCode::LittleEndian, len/2); } #endif const char *ref = gdcm::Testing::GetMD5FromFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( !ref ) { // new regression image needs a md5 sum std::cerr << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } if(res) { std::cerr << "problem with: " << outfilename << std::endl; } if( verbose ) { std::cout << "file was written in: " << outfilename << std::endl; } delete[] buffer; return res; } int TestFileChangeTransferSyntax2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileChangeTransferSyntax2Func(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileChangeTransferSyntax2Func( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileChangeTransferSyntax3.cxx000066400000000000000000000161421412732066400312450ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileChangeTransferSyntax.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmImageReader.h" #include "gdcmFilename.h" #include "gdcmImageChangePlanarConfiguration.h" #include "gdcmByteSwap.h" static int TestFileChangeTransferSyntax3Func(const char *filename, bool verbose = false) { using namespace gdcm; if( verbose ) std::cout << "Processing: " << filename << std::endl; // Create directory first: const char subdir[] = "TestFileChangeTransferSyntax3"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); if( verbose ) std::cout << "Generating: " << outfilename << std::endl; const gdcm::TransferSyntax ts( TransferSyntax::JPEG2000Lossless ); gdcm::FileChangeTransferSyntax fcts; fcts.SetTransferSyntax( ts ); fcts.SetInputFileName( filename ); fcts.SetOutputFileName( outfilename.c_str() ); ImageCodec *ic = fcts.GetCodec(); if( !ic ) { return 1; } if( !fcts.Change() ) { gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "not dicom" << std::endl; return 1; } const gdcm::File & file = reader.GetFile(); const gdcm::FileMetaInformation & fmi = file.GetHeader(); const TransferSyntax &tsref = fmi.GetDataSetTransferSyntax(); if( tsref.IsEncapsulated() ) { if( verbose ) std::cout << "Will not generate (encaps): " << outfilename << std::endl; return 0; } gdcm::Filename fn( filename ); const char *name = fn.GetName(); // Special handling: if( strcmp(name, "CT-MONO2-12-lomb-an2.acr" ) == 0 || strcmp(name, "LIBIDO-8-ACR_NEMA-Lena_128_128.acr") == 0 || strcmp(name, "gdcm-ACR-LibIDO.acr") == 0 || strcmp(name, "gdcm-MR-SIEMENS-16-2.acr") == 0 || strcmp(name, "libido1.0-vol.acr") == 0 || strcmp(name, "test.acr") == 0 || strcmp(name, "LIBIDO-24-ACR_NEMA-Rectangle.dcm") == 0 || strcmp(name, "MR_Spectroscopy_SIEMENS_OF.dcm") == 0 // not an image || strcmp(name, "ELSCINT1_PMSCT_RLE1.dcm") == 0 || strcmp(name, "ELSCINT1_PMSCT_RLE1_priv.dcm") == 0 || strcmp(name, "gdcm-CR-DCMTK-16-NonSamplePerPix.dcm") == 0 || strcmp(name, "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm") == 0 || strcmp(name, "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm") == 0 // Implicit VR Big Endian DLX (G.E Private) || strcmp(name, "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm") == 0 // Explicit VR Big Endian || strcmp(name, "US-RGB-8-epicard.dcm") == 0 // Explicit VR Big Endian || strcmp(name, "GE_DLX-8-MONO2-PrivateSyntax.dcm") == 0 // Implicit VR Big Endian DLX (G.E Private) || strcmp(name, "GE_CT_With_Private_compressed-icon.dcm") == 0 // Explicit VR Big Endian || strcmp(name, "JDDICOM_Sample2-dcmdjpeg.dcm") == 0 // cannot recreate FMI || strcmp(name, "DMCPACS_ExplicitImplicit_BogusIOP.dcm") == 0 // ImageRegionReader does not handle it || strcmp(name, "unreadable.dcm") == 0 // No Pixel Data (old ACR-NEMA) || strcmp(name, "US-YBR_FULL_422-EVRLE.dcm") == 0 // packed ybr422 || strncmp(name, "DICOMDIR", 8) == 0 // DICOMDIR* || strncmp(name, "dicomdir", 8) == 0 // dicomdir* ) { if( verbose ) std::cout << "Will not generate: " << outfilename << std::endl; return 0; } std::cerr << "Could not change: " << filename << std::endl; return 1; } // Let's read that file back in ! gdcm::ImageReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Could not even reread our generated file : " << outfilename << std::endl; return 1; } // Check that after decompression we still find the same thing: int res = 0; gdcm::Image img = reader2.GetImage(); int pc = 0; // When recompressing: US-RGB-8-epicard.dcm, make sure to compute the md5 using the // same original Planar Configuration... if( (int)img.GetPlanarConfiguration() != pc ) { gdcm::ImageChangePlanarConfiguration icpc; icpc.SetInput( reader2.GetImage() ); icpc.SetPlanarConfiguration( pc ); icpc.Change(); img = icpc.GetOutput(); } //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; bool res2 = img.GetBuffer(buffer); if( !res2 ) { std::cerr << "could not get buffer: " << outfilename << std::endl; return 1; } // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: #ifdef GDCM_WORDS_BIGENDIAN if( img.GetPixelFormat().GetBitsAllocated() == 16 ) { assert( !(len % 2) ); assert( img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 || img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ); gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem( (unsigned short*)buffer, gdcm::SwapCode::LittleEndian, len/2); } #endif const char *ref = gdcm::Testing::GetMD5FromFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( !ref ) { // new regression image needs a md5 sum std::cerr << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } if(res) { std::cerr << "problem with: " << outfilename << std::endl; } if( verbose ) { std::cout << "file was written in: " << outfilename << std::endl; } delete[] buffer; return res; } int TestFileChangeTransferSyntax3(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileChangeTransferSyntax3Func(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileChangeTransferSyntax3Func( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileChangeTransferSyntax4.cxx000066400000000000000000000161351412732066400312500ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileChangeTransferSyntax.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmImageReader.h" #include "gdcmFilename.h" #include "gdcmImageChangePlanarConfiguration.h" #include "gdcmByteSwap.h" static int TestFileChangeTransferSyntax4Func(const char *filename, bool verbose = false) { using namespace gdcm; if( verbose ) std::cout << "Processing: " << filename << std::endl; // Create directory first: const char subdir[] = "TestFileChangeTransferSyntax4"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); if( verbose ) std::cout << "Generating: " << outfilename << std::endl; const gdcm::TransferSyntax ts( TransferSyntax::RLELossless ); gdcm::FileChangeTransferSyntax fcts; fcts.SetTransferSyntax( ts ); fcts.SetInputFileName( filename ); fcts.SetOutputFileName( outfilename.c_str() ); ImageCodec *ic = fcts.GetCodec(); if( !ic ) { return 1; } if( !fcts.Change() ) { gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { std::cerr << "not dicom" << std::endl; return 1; } const gdcm::File & file = reader.GetFile(); const gdcm::FileMetaInformation & fmi = file.GetHeader(); const TransferSyntax &tsref = fmi.GetDataSetTransferSyntax(); if( tsref.IsEncapsulated() ) { if( verbose ) std::cout << "Will not generate (encaps): " << outfilename << std::endl; return 0; } gdcm::Filename fn( filename ); const char *name = fn.GetName(); // Special handling: if( strcmp(name, "CT-MONO2-12-lomb-an2.acr" ) == 0 || strcmp(name, "LIBIDO-8-ACR_NEMA-Lena_128_128.acr") == 0 || strcmp(name, "gdcm-ACR-LibIDO.acr") == 0 || strcmp(name, "gdcm-MR-SIEMENS-16-2.acr") == 0 || strcmp(name, "libido1.0-vol.acr") == 0 || strcmp(name, "test.acr") == 0 || strcmp(name, "LIBIDO-24-ACR_NEMA-Rectangle.dcm") == 0 || strcmp(name, "MR_Spectroscopy_SIEMENS_OF.dcm") == 0 // not an image || strcmp(name, "ELSCINT1_PMSCT_RLE1.dcm") == 0 || strcmp(name, "ELSCINT1_PMSCT_RLE1_priv.dcm") == 0 || strcmp(name, "gdcm-CR-DCMTK-16-NonSamplePerPix.dcm") == 0 || strcmp(name, "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm") == 0 || strcmp(name, "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm") == 0 // Implicit VR Big Endian DLX (G.E Private) || strcmp(name, "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm") == 0 // Explicit VR Big Endian || strcmp(name, "US-RGB-8-epicard.dcm") == 0 // Explicit VR Big Endian || strcmp(name, "GE_DLX-8-MONO2-PrivateSyntax.dcm") == 0 // Implicit VR Big Endian DLX (G.E Private) || strcmp(name, "GE_CT_With_Private_compressed-icon.dcm") == 0 // Explicit VR Big Endian || strcmp(name, "JDDICOM_Sample2-dcmdjpeg.dcm") == 0 // cannot recreate FMI || strcmp(name, "DMCPACS_ExplicitImplicit_BogusIOP.dcm") == 0 // ImageRegionReader does not handle it || strcmp(name, "unreadable.dcm") == 0 // No Pixel Data (old ACR-NEMA) || strcmp(name, "US-YBR_FULL_422-EVRLE.dcm") == 0 // packed ybr422 || strncmp(name, "DICOMDIR", 8) == 0 // DICOMDIR* || strncmp(name, "dicomdir", 8) == 0 // dicomdir* ) { if( verbose ) std::cout << "Will not generate: " << outfilename << std::endl; return 0; } std::cerr << "Could not change: " << filename << std::endl; return 1; } // Let's read that file back in ! gdcm::ImageReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Could not even reread our generated file : " << outfilename << std::endl; return 1; } // Check that after decompression we still find the same thing: int res = 0; gdcm::Image img = reader2.GetImage(); int pc = 0; // When recompressing: US-RGB-8-epicard.dcm, make sure to compute the md5 using the // same original Planar Configuration... if( (int)img.GetPlanarConfiguration() != pc ) { gdcm::ImageChangePlanarConfiguration icpc; icpc.SetInput( reader2.GetImage() ); icpc.SetPlanarConfiguration( pc ); icpc.Change(); img = icpc.GetOutput(); } //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; bool res2 = img.GetBuffer(buffer); if( !res2 ) { std::cerr << "could not get buffer: " << outfilename << std::endl; return 1; } // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: #ifdef GDCM_WORDS_BIGENDIAN if( img.GetPixelFormat().GetBitsAllocated() == 16 ) { assert( !(len % 2) ); assert( img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 || img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ); gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem( (unsigned short*)buffer, gdcm::SwapCode::LittleEndian, len/2); } #endif const char *ref = gdcm::Testing::GetMD5FromFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( !ref ) { // new regression image needs a md5 sum std::cerr << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } if(res) { std::cerr << "problem with: " << outfilename << std::endl; } if( verbose ) { std::cout << "file was written in: " << outfilename << std::endl; } delete[] buffer; return res; } int TestFileChangeTransferSyntax4(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileChangeTransferSyntax4Func(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileChangeTransferSyntax4Func( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileDecompressLookupTable.cxx000066400000000000000000000122671412732066400313330ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileDecompressLookupTable.h" #include "gdcmImageApplyLookupTable.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmImageReader.h" #include "gdcmPixmapReader.h" #include "gdcmPixmapWriter.h" #include "gdcmImage.h" #include "gdcmFilename.h" // array copy/pasted from: TestImageApplyLookupTable static const char * const lutarray[][2] = { { "d613050ca0f9c924fb5282d140281fcc", "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm" }, { "d613050ca0f9c924fb5282d140281fcc", "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm" }, { "7b8d795eaf99f1fff176c43f9cf76bfb", "NM-PAL-16-PixRep1.dcm" }, { "47715f0a5d5089268bbef6f83251a8ad", "OT-PAL-8-face.dcm" }, { "c70309b66045140b8e08c11aa319c0ab", "US-PAL-8-10x-echo.dcm" }, { "c370ca934dc910eb4b629a2fa8650b67", "gdcm-US-ALOKA-16.dcm" }, { "49ca8ad45fa7f24b0406a5a03ba8aff6", "rle16loo.dcm" }, { "964ea27345a7004325896d34b257f289", "rle16sti.dcm" }, // sentinel { nullptr, nullptr } }; static int TestFileDecompressLookupTableFunc(const char *filename, bool verbose = false) { gdcm::PixmapReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const gdcm::FileMetaInformation &header = reader.GetFile().GetHeader(); gdcm::MediaStorage ms = header.GetMediaStorage(); bool isImage = gdcm::MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( gdcm::Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cout << "Could not read: " << filename << std::endl; return 1; } return 0; } const gdcm::Pixmap &image = reader.GetPixmap(); const gdcm::PhotometricInterpretation &pi = image.GetPhotometricInterpretation(); if( pi != gdcm::PhotometricInterpretation::PALETTE_COLOR ) { // yeah well not much I can do here... if( verbose ) { std::cout << "PhotometricInterpretation is: " << pi << " cannot apply LUT then..." << std::endl; } return 0; } gdcm::FileDecompressLookupTable lutfilt; lutfilt.SetPixmap( image ); lutfilt.SetFile( reader.GetFile() ); bool b = lutfilt.Change(); if( !b ) { std::cerr << "Could not apply lut: " << filename << std::endl; return 1; } // Create directory first: const char subdir[] = "TestFileDecompressLookupTable"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = gdcm::Testing::GetTempFilename( filename, subdir ); gdcm::PixmapWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); // comment out if you dare writer.SetPixmap( lutfilt.GetPixmap() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // Let's read that file back in ! gdcm::ImageReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Failed to read back: " << outfilename << std::endl; return 1; } gdcm::ImageApplyLookupTable lutfilt2; lutfilt2.SetInput( reader2.GetPixmap() ); b = lutfilt2.Apply(); if( !b ) { std::cerr << "Could not apply lut: " << filename << std::endl; return 1; } const gdcm::Image &img = lutfilt2.GetOutput(); unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; img.GetBuffer(buffer); gdcm::Filename fn( filename ); const char *name = fn.GetName(); unsigned int i = 0; const char *p = lutarray[i][1]; while( p != nullptr ) { if( strcmp( name, p ) == 0 ) { break; } ++i; p = lutarray[i][1]; } const char *ref = lutarray[i][0]; char digest[33] = {}; gdcm::Testing::ComputeMD5(buffer, len, digest); int res = 0; if( !ref ) { std::cerr << "Missing LUT-applied MD5 for image from: " << filename << std::endl; res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } delete[] buffer; return res; } int TestFileDecompressLookupTable(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileDecompressLookupTableFunc(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileDecompressLookupTableFunc( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileDerivation.cxx000066400000000000000000000074551412732066400271740ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileDerivation.h" #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmUIDGenerator.h" int TestFileDerive(const char *subdir, const char* filename) { using namespace gdcm; Reader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } FileDerivation fd; fd.SetFile( reader.GetFile() ); // Setup some actions: // TODO we should reference the original image File &file = reader.GetFile(); DataSet &ds = file.GetDataSet(); if( !ds.FindDataElement( Tag(0x0008,0x0016) ) || ds.GetDataElement( Tag(0x0008,0x0016) ).IsEmpty() ) { std::cerr << "Missing sop class giving up: " << filename << std::endl; return 0; } if( !ds.FindDataElement( Tag(0x0008,0x0018) ) || ds.GetDataElement( Tag(0x0008,0x0018) ).IsEmpty() ) { std::cerr << "Missing sop instance giving up: " << filename << std::endl; return 0; } const DataElement &sopclassuid = ds.GetDataElement( Tag(0x0008,0x0016) ); const DataElement &sopinstanceuid = ds.GetDataElement( Tag(0x0008,0x0018) ); // Make sure that const char* pointer will be properly padded with \0 char: std::string sopclassuid_str( sopclassuid.GetByteValue()->GetPointer(), sopclassuid.GetByteValue()->GetLength() ); std::string sopinstanceuid_str( sopinstanceuid.GetByteValue()->GetPointer(), sopinstanceuid.GetByteValue()->GetLength() ); fd.AddReference( sopclassuid_str.c_str(), sopinstanceuid_str.c_str() ); // CID 7202 Source Image Purposes of Reference // {"DCM",121320,"Uncompressed predecessor"}, fd.SetPurposeOfReferenceCodeSequenceCodeValue( 121320 ); // CID 7203 Image Derivation // { "DCM",113040,"Lossy Compression" }, fd.SetDerivationCodeSequenceCodeValue( 113040 ); fd.SetDerivationDescription( "lossy conversion" ); if( !fd.Derive() ) { std::cerr << "Failed to derive: " << filename << std::endl; if( ds.FindDataElement( Tag(0x8,0x2112) ) ) { return 0; } return 1; } // Create directory first: std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); Writer writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // now let's try to read it back in: Reader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Could not reread written file: " << outfilename << std::endl; return 1; } return 0; } int TestFileDerivation( int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileDerive( argv[0], filename); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileDerive( argv[0], filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileExplicitFilter.cxx000066400000000000000000000062531412732066400300120ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileExplicitFilter.h" #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmTesting.h" #include "gdcmSystem.h" int TestFileExplicitFilt(const char *subdir, const char *filename, bool verbose = false) { if( verbose ) std::cerr << "Reading: " << filename << std::endl; gdcm::Reader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { std::cerr << "could not read: " << filename << std::endl; return 1; } //const gdcm::FileMetaInformation &h = reader.GetFile().GetHeader(); //const gdcm::DataSet &ds = reader.GetFile().GetDataSet(); gdcm::FileExplicitFilter im2ex; im2ex.SetFile( reader.GetFile() ); if( !im2ex.Change() ) { std::cerr << "Could not im2ex change: " << filename << std::endl; return 1; } // Create directory first: std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = gdcm::Testing::GetTempFilename( filename, subdir ); gdcm::Writer writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); writer.SetCheckFileMetaInformation( false ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } if(verbose) std::cerr << "write out: " << outfilename << std::endl; char digest1[33] = {}; char digest2[33] = {}; bool b1 = gdcm::Testing::ComputeFileMD5(filename, digest1); if( !b1 ) { std::cerr << "Could not compute md5:" << filename << std::endl; return 1; } bool b2 = gdcm::Testing::ComputeFileMD5(outfilename.c_str(), digest2); if( !b2 ) { std::cerr << "Could not compute md5:" << outfilename << std::endl; return 1; } if( strcmp(digest1, digest2 ) == 0 ) { // Easy case input file was explicit return 0; } else { if(verbose) { std::cerr << "input file contained wrong VR: " << filename << std::endl; std::cerr << "see: " << outfilename << std::endl; } } return 0; } int TestFileExplicitFilter(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileExplicitFilt(argv[0], filename, true); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileExplicitFilt( argv[0], filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileStreamer1.cxx000066400000000000000000000101731412732066400267220ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileStreamer.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmDataSet.h" #include "gdcmPrivateTag.h" #include "gdcmFilename.h" int TestFileStream1(const char *filename, bool verbose = false) { using namespace gdcm; if( verbose ) std::cout << "Processing: " << filename << std::endl; // Create directory first: const char subdir[] = "TestFileStreamer1"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); if( verbose ) std::cout << "Generating: " << outfilename << std::endl; gdcm::Filename fn( filename ); const char *name = fn.GetName(); // Special handling: bool checktemplate = false; if( strcmp(name, "DMCPACS_ExplicitImplicit_BogusIOP.dcm" ) == 0 || strcmp(name, "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm") == 0 || strcmp(name, "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm") == 0 ) { checktemplate = true; } gdcm::FileStreamer fs; fs.SetTemplateFileName( filename ); fs.CheckTemplateFileName( checktemplate ); fs.SetOutputFileName( outfilename.c_str() ); std::vector vbuffer; vbuffer.resize( 8192 ); const char *buffer = &vbuffer[0]; const size_t len = vbuffer.size(); PrivateTag pt( Tag(0x9,0x10), "MYTEST" ); if( !fs.ReserveGroupDataElement( 20 ) ) { return 1; } const uint8_t startoffset = 0x13; // why not ? fs.StartGroupDataElement( pt, 1000, startoffset ); fs.AppendToGroupDataElement( pt, buffer, len ); fs.AppendToGroupDataElement( pt, buffer, len ); fs.StopGroupDataElement( pt ); // Read back and check: gdcm::Reader r; r.SetFileName( outfilename.c_str() ); if( !r.Read() ) { std::cerr << "Failed to read: " << outfilename << std::endl; return 1; } gdcm::File & f = r.GetFile(); gdcm::DataSet & ds = f.GetDataSet(); const DataElement private_creator = pt.GetAsDataElement(); if( !ds.FindDataElement( private_creator.GetTag() ) ) { std::cerr << "Could not find priv creator: " << outfilename << std::endl; return 1; } // Check all the group: const size_t nels = (2 * vbuffer.size() + 999) / 1000; if( nels != 17 ) return 1; PrivateTag check = pt; for( size_t i = startoffset; i < startoffset + nels; ++i ) { #if 1 check.SetElement( (uint16_t)i ); check.SetPrivateCreator( pt ); #else check.SetElement( check.GetElement() + 1 ); #endif if( !ds.FindDataElement( check ) ) { std::cerr << "Could not find priv tag: " << check << " " << outfilename << std::endl; return 1; } const DataElement & de = ds.GetDataElement( check ); const int vl = de.GetVL(); int reflen = 0; if( i == (startoffset + nels - 1) ) { reflen = 384; } else { reflen = 1000; } if( vl != reflen ) { std::cerr << "Wrong length for: " << check << ":" << vl << " should be :" << reflen << std::endl; return 1; } } return 0; } int TestFileStreamer1(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileStream1(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileStream1( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileStreamer2.cxx000066400000000000000000000073641412732066400267330ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileStreamer.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmFilename.h" int TestFileStream2(const char *filename, bool verbose = false) { using namespace gdcm; if( verbose ) std::cout << "Processing: " << filename << std::endl; // Create directory first: const char subdir[] = "TestFileStreamer2"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); if( verbose ) std::cout << "Generating: " << outfilename << std::endl; const gdcm::Tag t1(0x0042,0x0011); gdcm::Filename fn( filename ); const char *name = fn.GetName(); // Special handling: bool checktemplate = false; if( strcmp(name, "DMCPACS_ExplicitImplicit_BogusIOP.dcm" ) == 0 || strcmp(name, "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm") == 0 || strcmp(name, "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm") == 0 ) { checktemplate = true; } gdcm::FileStreamer fs; fs.SetTemplateFileName( filename ); fs.CheckTemplateFileName( checktemplate ); fs.SetOutputFileName( outfilename.c_str() ); const char buffer[10] = { 0, 1, 2 , 3, 4, 5, 6, 7, 8, 9 }; const size_t len = sizeof( buffer ); //fs.ReserveDataElement( 36 ); fs.StartDataElement( t1 ); fs.AppendToDataElement( t1, buffer, len ); fs.AppendToDataElement( t1, buffer, len ); fs.AppendToDataElement( t1, buffer, len ); fs.AppendToDataElement( t1, buffer, len / 2 + 0 ); fs.StopDataElement( t1 ); // Read back and check: gdcm::Reader r; r.SetFileName( outfilename.c_str() ); if( !r.Read() ) { std::cerr << "Failed to read: " << outfilename << std::endl; return 1; } gdcm::File & f = r.GetFile(); gdcm::DataSet & ds = f.GetDataSet(); if( !ds.FindDataElement( t1 ) ) { std::cerr << "Could not find tag: " << t1 << std::endl; return 1; } const DataElement & de = ds.GetDataElement( t1 ); const int vl = de.GetVL(); if( vl != 36 ) // 35 + padding { return 1; } const ByteValue *bv = de.GetByteValue(); const char *ptr = bv->GetPointer(); const int b1 = memcmp( ptr + 0 * len, buffer, len ); const int b2 = memcmp( ptr + 1 * len, buffer, len ); const int b3 = memcmp( ptr + 2 * len, buffer, len ); const int b4 = memcmp( ptr + 3 * len, buffer, len / 2 ); if( b1 || b2 || b3 || b4 ) { std::cerr << "Problem:" << b1 << " " << b2 << " " << b3 << " " << b4 << std::endl; return 1; } // NULL padding if( ptr[35] != 0x0 ) { std::cerr << "Error in padding" << std::endl; return 1; } return 0; } int TestFileStreamer2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileStream2(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileStream2( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileStreamer3.cxx000066400000000000000000000105051412732066400267230ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileStreamer.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmFilename.h" int TestFileStream3(const char *filename, bool verbose = false) { using namespace gdcm; if( verbose ) std::cout << "Processing: " << filename << std::endl; // Create directory first: const char subdir[] = "TestFileStreamer3"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); if( verbose ) std::cout << "Generating: " << outfilename << std::endl; gdcm::Filename fn( filename ); const char *name = fn.GetName(); // Special handling: bool checktemplate = false; if( strcmp(name, "DMCPACS_ExplicitImplicit_BogusIOP.dcm" ) == 0 || strcmp(name, "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm") == 0 || strcmp(name, "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm") == 0 ) { checktemplate = true; } gdcm::FileStreamer fs; fs.SetTemplateFileName( filename ); fs.CheckTemplateFileName( checktemplate ); fs.SetOutputFileName( outfilename.c_str() ); const gdcm::Tag t1(0x0008,0x0010); const gdcm::Tag t2(0x0010,0x0010); // Try a small buffer to find a case where existing element is larger bool b; const char buffer[] = " "; const size_t len = strlen( buffer ); // Recognition Code b = fs.StartDataElement( t1 ); if( !b ) { std::cerr << "Could not StartDataElement" << std::endl; return 1; } b = fs.AppendToDataElement( t1, buffer, len ); if( !b ) { std::cerr << "Could not AppendToDataElement (t1)" << std::endl; return 1; } b = fs.StopDataElement( t1 ); if( !b ) { std::cerr << "Could not StopDataElement" << std::endl; return 1; } // Patient's Name b = fs.StartDataElement( t2 ); if( !b ) { std::cerr << "Could not StartDataElement" << std::endl; return 1; } b = fs.AppendToDataElement( t2, buffer, len ); if( !b ) { std::cerr << "Could not AppendToDataElement" << std::endl; return 1; } b = fs.StopDataElement( t2 ); if( !b ) { std::cerr << "Could not StopDataElement" << std::endl; return 1; } // Read back and check: gdcm::Reader r; r.SetFileName( outfilename.c_str() ); if( !r.Read() ) { std::cerr << "Failed to read: " << outfilename << std::endl; return 1; } gdcm::File & f = r.GetFile(); gdcm::DataSet & ds = f.GetDataSet(); if( !ds.FindDataElement( t1 ) ) { std::cerr << "Could not find tag: " << t1 << std::endl; return 1; } { const DataElement & de = ds.GetDataElement( t1 ); const ByteValue * bv = de.GetByteValue(); if( !bv ) return 1; if( bv->GetLength() != 2 ) { std::cerr << "Wrong length: " << bv->GetLength() << std::endl; return 1; } if( memcmp( bv->GetPointer(), buffer, 2 ) ) { std::cerr << "Wrong content" << std::endl; return 1; } } { const DataElement & de = ds.GetDataElement( t2 ); const ByteValue * bv = de.GetByteValue(); if( !bv ) return 1; if( bv->GetLength() != 2 ) return 1; if( memcmp( bv->GetPointer(), buffer, 2 ) ) { std::cerr << "Wrong content" << std::endl; return 1; } } return 0; } int TestFileStreamer3(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileStream3(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileStream3( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileStreamer4.cxx000066400000000000000000000122761412732066400267330ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileStreamer.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmFilename.h" #include "gdcmImageRegionReader.h" #include "gdcmImageHelper.h" int TestFileStream4(const char *filename, bool verbose = false) { using namespace gdcm; // Create directory first: const char subdir[] = "TestFileStreamer4"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); gdcm::Filename fn( filename ); const char *name = fn.GetName(); // Special handling: bool checktemplate = false; if( strcmp(name, "DMCPACS_ExplicitImplicit_BogusIOP.dcm" ) == 0 || strcmp(name, "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm") == 0 || strcmp(name, "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm") == 0 ) { checktemplate = true; } if( strcmp(name, "JPEGNote_empty.dcm" ) == 0 || strcmp(name, "JPEGNote_missing.dcm" ) == 0 ) { // cannot read dims from DICOM header... return 0; } gdcm::ImageRegionReader irr; irr.SetFileName( filename ); if( !irr.ReadInformation() ) { //std::cerr << "not an image: " << filename << std::endl; return 0; } gdcm::File & file = irr.GetFile(); std::vector dims = gdcm::ImageHelper::GetDimensionsValue(file); PixelFormat pf = gdcm::ImageHelper::GetPixelFormatValue(file); int pixsize = pf.GetPixelSize(); const size_t computedlen = dims[0] * dims[1] * dims[2] * pixsize; const FileMetaInformation &header = file.GetHeader(); const TransferSyntax &ts = header.GetDataSetTransferSyntax(); if( verbose ) { std::cout << "Processing: " << filename << std::endl; std::cout << "Generating: " << outfilename << std::endl; } std::vector vbuffer; assert( dims[0] ); vbuffer.resize( dims[0] * pixsize ); char *buffer = &vbuffer[0]; const size_t len = vbuffer.size(); gdcm::FileStreamer fs; fs.ReserveDataElement( computedlen ); fs.SetTemplateFileName( filename ); fs.CheckTemplateFileName( checktemplate ); fs.SetOutputFileName( outfilename.c_str() ); const gdcm::Tag pixeldata(0x7fe0,0x0010); bool b = true; if( strcmp(name, "libido1.0-vol.acr" ) != 0 ) // use Planes instead of Number of Frames { b = fs.CheckDataElement( pixeldata ); // will be checking file size } if( !b ) { std::cerr << "Failed to CheckDataElement: " << outfilename << std::endl; return 1; } b = fs.StartDataElement( pixeldata ); if( !b ) { std::cerr << "Failed to StartDataElement: " << outfilename << std::endl; return 1; } for( unsigned int z = 0; z < dims[2]; ++z ) for( unsigned int y = 0; y < dims[1]; ++y ) { b = fs.AppendToDataElement( pixeldata, buffer, len ); if( !b ) { std::cerr << "Failed to AppendToDataElement: " << outfilename << std::endl; return 1; } } if( !fs.StopDataElement( pixeldata ) ) { if( ts.IsEncapsulated() ) { // Everything is under control return 0; } std::cerr << "Failed to StopDataElement: " << outfilename << std::endl; return 1; } // Read back and check: gdcm::Reader r; r.SetFileName( outfilename.c_str() ); if( !r.Read() ) { std::cerr << "Failed to read: " << outfilename << std::endl; return 1; } gdcm::File & f = r.GetFile(); gdcm::DataSet & ds = f.GetDataSet(); if( !ds.FindDataElement( pixeldata ) ) { std::cerr << "No pixel data: " << outfilename << std::endl; return 1; } const gdcm::DataElement & de = ds.GetDataElement( pixeldata ); const gdcm::ByteValue *bv = de.GetByteValue(); if( bv->GetLength() != computedlen ) { std::cerr << "Mismatch len: " << outfilename << " : " << bv->GetLength() << " vs " << computedlen << std::endl; return 1; } const char *p = bv->GetPointer(); const char *end = p + dims[0] * dims[1] * dims[2]; int res = 0; for( ; p != end; ++p ) { res += *p; } if( res ) { std::cerr << "Mismatch: " << outfilename << std::endl; } return res; } int TestFileStreamer4(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileStream4(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileStream4( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileStreamer5.cxx000066400000000000000000000053101412732066400267230ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileStreamer.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmDataSet.h" #include "gdcmPrivateTag.h" #include "gdcmFilename.h" int TestFileStream5(const char *filename, bool verbose = false) { using namespace gdcm; if( verbose ) std::cout << "Processing: " << filename << std::endl; // Create directory first: const char subdir[] = "TestFileStreamer5"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); if( verbose ) std::cout << "Generating: " << outfilename << std::endl; gdcm::Filename fn( filename ); const char *name = fn.GetName(); // Special handling: bool checktemplate = false; if( strcmp(name, "DMCPACS_ExplicitImplicit_BogusIOP.dcm" ) == 0 || strcmp(name, "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm") == 0 || strcmp(name, "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm") == 0 ) { checktemplate = true; } gdcm::FileStreamer fs; fs.SetTemplateFileName( filename ); fs.CheckTemplateFileName( checktemplate ); fs.SetOutputFileName( outfilename.c_str() ); std::vector vbuffer; vbuffer.resize( 8192 ); const char *buffer = &vbuffer[0]; const size_t len = vbuffer.size(); PrivateTag pt( Tag(0x9,0x10), "MYTEST" ); fs.StartGroupDataElement( pt, 10 ); if( fs.AppendToGroupDataElement( pt, buffer, len ) ) { std::cerr << "We should not succeed, we should fail this test" << std::endl; return 1; } fs.StopGroupDataElement( pt ); return 0; } int TestFileStreamer5(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileStream5(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileStream5( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFileStreamer6.cxx000066400000000000000000000065011412732066400267270ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFileStreamer.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmDataSet.h" #include "gdcmPrivateTag.h" #include "gdcmFilename.h" /* * Make sure pseudo-private element also works: */ int TestFileStream6(const char *filename, bool verbose = false) { using namespace gdcm; if( verbose ) std::cout << "Processing: " << filename << std::endl; // Create directory first: const char subdir[] = "TestFileStreamer6"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); if( verbose ) std::cout << "Generating: " << outfilename << std::endl; gdcm::Filename fn( filename ); const char *name = fn.GetName(); // Special handling: bool checktemplate = false; if( strcmp(name, "DMCPACS_ExplicitImplicit_BogusIOP.dcm" ) == 0 || strcmp(name, "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm") == 0 || strcmp(name, "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm") == 0 ) { checktemplate = true; } gdcm::FileStreamer fs; fs.SetTemplateFileName( filename ); fs.CheckTemplateFileName( checktemplate ); fs.SetOutputFileName( outfilename.c_str() ); std::vector vbuffer; vbuffer.resize( 8192 ); const char *buffer = &vbuffer[0]; const size_t len = vbuffer.size(); Tag t( Tag(0x9,0x1010) ); fs.StartDataElement( t ); fs.AppendToDataElement( t, buffer, len ); fs.StopDataElement( t ); // Read back and check: gdcm::Reader r; r.SetFileName( outfilename.c_str() ); if( !r.Read() ) { std::cerr << "Failed to read: " << outfilename << std::endl; return 1; } gdcm::File & f = r.GetFile(); gdcm::DataSet & ds = f.GetDataSet(); if( !ds.FindDataElement( t ) ) { return 1; } const gdcm::DataElement & de = ds.GetDataElement( t ); const gdcm::ByteValue * bv = de.GetByteValue(); if( !bv ) return 1; if( bv->GetLength() != 8192 ) return 1; const char *p = bv->GetPointer(); const char *end = p + bv->GetLength(); int res = 0; for( ; p != end; ++p ) { res += *p; } if( res ) { std::cerr << "Mismatch: " << outfilename << std::endl; } return res; } int TestFileStreamer6(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestFileStream6(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestFileStream6( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestFloatingPointDouble.cxx000066400000000000000000000020311412732066400301610ustar00rootroot00000000000000/*========================================================================= 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 int TestFloatingPointDouble(int, char *[]) { // Not applicable const char strnan[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x7F}; const char strinf[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7F}; double inf = std::numeric_limits::infinity(); double nan = std::numeric_limits::quiet_NaN(); std::cout << inf << std::endl; std::cout << nan << std::endl; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestIPPSorter.cxx000066400000000000000000000050341412732066400261060ustar00rootroot00000000000000/*========================================================================= 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 "gdcmIPPSorter.h" #include "gdcmDirectory.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmTrace.h" int TestIPPSorter(int argc, char *argv[]) { const char *directory = gdcm::Testing::GetDataRoot(); std::vector filenames; if( argc == 2 ) { gdcm::Trace::DebugOn(); directory = argv[1]; if( gdcm::System::FileIsDirectory( directory ) ) { gdcm::Directory d; unsigned int nfiles = d.Load( directory ); // no recursion d.Print( std::cout ); std::cout << "done retrieving file list. " << nfiles << " files found." << std::endl; filenames = d.GetFilenames(); } else { std::cerr << "file:" << directory << " is not a directory" << std::endl; return 1; } } else { // default execution (nightly test) // let's take 4 files that can be sorted: std::string file0 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm"; std::string file1 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm"; std::string file2 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm"; std::string file3 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm"; // let's push them in random order (oh my god how are we going to succeed ??) filenames.push_back( file1 ); filenames.push_back( file3 ); filenames.push_back( file2 ); filenames.push_back( file0 ); } gdcm::IPPSorter s; s.SetComputeZSpacing( true ); s.SetZSpacingTolerance( 1e-10 ); bool b = s.Sort( filenames ); if( !b ) { std::cerr << "Failed to sort: " << directory << std::endl; return 1; } std::cout << "Sorting succeeded:" << std::endl; s.Print( std::cout ); double zspacing = s.GetZSpacing(); if(!zspacing) { std::cerr << "computation of ZSpacing failed." << std::endl; return 1; } std::cout << "Found z-spacing:" << std::endl; std::cout << s.GetZSpacing() << std::endl; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestIPPSorter2.cxx000066400000000000000000000056761412732066400262040ustar00rootroot00000000000000/*========================================================================= 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 "gdcmIPPSorter.h" #include "gdcmDirectory.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmAttribute.h" // Sort image using Instance Number: bool mysort(gdcm::DataSet const & ds1, gdcm::DataSet const & ds2 ) { gdcm::Attribute<0x0020,0x0013> at1; // Instance Number at1.Set( ds1 ); gdcm::Attribute<0x0020,0x0013> at2; at2.Set( ds2 ); return at1 < at2; } int TestIPPSorter2(int argc, char *argv[]) { const char *directory = gdcm::Testing::GetDataRoot(); std::vector filenames; if( argc == 2 ) { gdcm::Trace::DebugOn(); directory = argv[1]; if( gdcm::System::FileIsDirectory( directory ) ) { gdcm::Directory d; unsigned int nfiles = d.Load( directory ); // no recursion d.Print( std::cout ); std::cout << "done retrieving file list. " << nfiles << " files found." << std::endl; filenames = d.GetFilenames(); } else { std::cerr << "file:" << directory << " is not a directory" << std::endl; return 1; } } else { // default execution (nightly test) // let's take 4 files that can be sorted: std::string file0 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm"; std::string file1 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm"; std::string file2 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm"; std::string file3 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm"; // let's push them in random order (oh my god how are we going to succeed ??) filenames.push_back( file1 ); filenames.push_back( file3 ); filenames.push_back( file2 ); filenames.push_back( file0 ); } gdcm::IPPSorter s; s.SetComputeZSpacing( true ); s.SetZSpacingTolerance( 1e-10 ); bool b = s.Sort( filenames ); if( !b ) { std::cerr << "Failed to sort:" << directory << std::endl; return 1; } std::cout << "Sorting succeeded:" << std::endl; s.Print( std::cout ); double zspacing = s.GetZSpacing(); if(!zspacing) { std::cerr << "computation of ZSpacing failed." << std::endl; return 1; } std::cout << "Found z-spacing:" << std::endl; std::cout << s.GetZSpacing() << std::endl; // Now apply a StableSort on them: s.SetSortFunction( mysort ); s.StableSort( s.GetFilenames() ); s.Print( std::cout ); return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestIPPSorter3.cxx000066400000000000000000000065061412732066400261760ustar00rootroot00000000000000/*========================================================================= 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 "gdcmIPPSorter.h" #include "gdcmDirectory.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmReader.h" #include "gdcmWriter.h" int TestIPPSorter3(int , char *[]) { const char *directory = gdcm::Testing::GetDataRoot(); std::vector filenames; // let's take 4 files that can be sorted: std::string file0 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm"; std::string file1 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm"; std::string file2 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm"; std::string file3 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm"; // Make a fake copy: const char * reference = file0.c_str(); gdcm::Reader reader; reader.SetFileName( reference ); if( !reader.Read() ) return 1; // Create directory first: const char subdir[] = "TestIPPSorter3"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = gdcm::Testing::GetTempFilename( reference, subdir ); // Tweak the orientation just a little: // [001.000000E+00\-0.000000E+00\-0.000000E+00\00.000000E+00\01.000000E+00\-0.000000E+00] gdcm::Writer writer; writer.SetFileName( outfilename.c_str() ); //const char iop_orig[] = "1\\-0\\-0\\0\\1\\-0"; const char iop[] = R"(1\-0\-0\0\0.99999\0.00001)"; gdcm::DataElement de( gdcm::Tag(0x0020,0x0037) ); de.SetByteValue( iop, (uint32_t)strlen( iop ) ); reader.GetFile().GetDataSet().Replace( de ); writer.SetFile( reader.GetFile() ); if( !writer.Write() ) { return 1; } // let's push them in random order (oh my god how are we going to succeed ??) filenames.push_back( file1 ); filenames.push_back( file3 ); filenames.push_back( outfilename ); filenames.push_back( file2 ); //filenames.push_back( file0 ); gdcm::IPPSorter s; s.SetComputeZSpacing( true ); s.SetZSpacingTolerance( 1e-10 ); s.SetDirectionCosinesTolerance( 1e-6 ); bool b = s.Sort( filenames ); if( b ) { std::cerr << "Success to sort (we should have failed): " << directory << std::endl; return 1; } // Lower the threshold: s.SetDirectionCosinesTolerance( 1e-5 ); b = s.Sort( filenames ); if( !b ) { std::cerr << "Failed to sort: " << directory << std::endl; return 1; } // std::cout << "Sorting succeeded:" << std::endl; // s.Print( std::cout ); double zspacing = s.GetZSpacing(); if(!zspacing) { std::cerr << "computation of ZSpacing failed." << std::endl; return 1; } std::cout << "Found z-spacing:" << std::endl; std::cout << s.GetZSpacing() << std::endl; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestIconImage.cxx000066400000000000000000000045241412732066400261150ustar00rootroot00000000000000/*========================================================================= 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 "gdcmIconImage.h" // FIXME: // gdcmData/US-GE-4AICL142.dcm has a private data element that is an Icon: /* (6003,0010) LO [GEMS_Ultrasound_ImageGroup_001] # 30, 1 PrivateCreator (6003,1010) SQ (Sequence with explicit length #=1) # 12522, 1 Unknown Tag & Data (fffe,e000) na (Item with explicit length #=15) # 12514, 1 Item (0002,0010) UI =LittleEndianExplicit # 20, 1 TransferSyntaxUID (0008,0008) CS [DERIVED\SECONDARY] # 18, 2 ImageType (0008,2111) ST [SmallPreview] # 12, 1 DerivationDescription (0028,0002) US 3 # 2, 1 SamplesPerPixel (0028,0004) CS [RGB] # 4, 1 PhotometricInterpretation (0028,0006) US 0 # 2, 1 PlanarConfiguration (0028,0010) US 64 # 2, 1 Rows (0028,0011) US 64 # 2, 1 Columns (0028,0014) US 1 # 2, 1 UltrasoundColorDataPresent (0028,0100) US 8 # 2, 1 BitsAllocated (0028,0101) US 8 # 2, 1 BitsStored (0028,0102) US 7 # 2, 1 HighBit (0028,0103) US 0 # 2, 1 PixelRepresentation (6003,0010) LO [GEMS_Ultrasound_ImageGroup_001] # 30, 1 PrivateCreator (6003,1011) OB 00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00... # 12288, 1 Unknown Tag & Data (fffe,e00d) na (ItemDelimitationItem for re-encoding) # 0, 0 ItemDelimitationItem */ int TestIconImage(int, char *[]) { gdcm::IconImage icon; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestIconImageFilter.cxx000066400000000000000000000113731412732066400272630ustar00rootroot00000000000000/*========================================================================= 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 "gdcmIconImageFilter.h" #include "gdcmTesting.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmImage.h" static const char * const iconimagearray[][2] = { { "b818c90fc4135423dfc118c3305d23ef" , "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm" }, { "57e43cf467d9bc4c4a43e0a97329075d" , "SIEMENS_CSA2.dcm" }, { "fc5db4e2e7fca8445342b83799ff16d8" , "simpleImageWithIcon.dcm" }, { "93c1b9e4c97cf5ff3501f3d8114c3b89" , "05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm" }, { "07950df5d3662740874e93d2c41dec18" , "MR-SIEMENS-DICOM-WithOverlays.dcm" }, { "e1305d5341e8ced04caff40c706c23b0" , "AMIInvalidPrivateDefinedLengthSQasUN.dcm" }, { "5f76af83e7b99cab45a70248824c2145" , "PICKER-16-MONO2-Nested_icon.dcm" }, { "59d8479e0025d8bbb3244551d6535890" , "MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm" }, { "9ad43e72601a228c4a3d021f08a09b69" , "CT-SIEMENS-Icone-With-PaletteColor.dcm" }, { "a9c3c78082a46e2226a4b1ff499ccd74" , "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm" }, { "50387cdd945b22ccbb5d1824e955deeb" , "05148044-mr-siemens-avanto-syngo.dcm" }, { "e42ea2852be5d20f95083991728d8623" , "GE_LOGIQBook-8-RGB-HugePreview.dcm" }, { "c38df20a8514714f5d5af1699a841c60" , "GE_CT_With_Private_compressed-icon.dcm" }, { "61b2bf04c18a0f67b7e720e07804dcdd" , "KODAK_CompressedIcon.dcm" }, { "620f0b67a91f7f74151bc5be745b7110" , "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm" }, { "938f6ea0bea13ff5c45c7934e603caac" , "US-GE-4AICL142.dcm" }, { "9c145bbfd00e867d5f9f6efe9651a71e" , "SIEMENS_SYNGO-12-MONO2-LUTWrongLength512.dcm" }, { "48bf71ea2e18b0632ec318d55fb455ab" , "Bug_Siemens_PrivateIconNoItem.dcm" }, { "a29e9def9a1478c9f8b957c68b33885b" , "PET-GE-dicomwrite-PixelDataSQUNv2.dcm" }, // VEPRO VIF { "ea4673b2aa72f477188bac340e115f4c" , "PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm" }, { "660417e04b9af62832a43bf82369e4fa" , "GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm" }, // gdcmDataExtra { "a144b851c9262c97dde567d4d3781733" , "2929J888_8b_YBR_RLE_PlanConf0_breaker.dcm" }, // sentinel { nullptr, nullptr } }; int TestIconImageFilterFunc(const char *filename, bool verbose = false) { gdcm::ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { return 0; } gdcm::IconImageFilter iif; iif.SetFile( reader.GetFile() ); bool b = iif.Extract(); gdcm::Filename fn( filename ); const char *name = fn.GetName(); unsigned int i = 0; const char *p = iconimagearray[i][1]; while( p != nullptr ) { if( strcmp( name, p ) == 0 ) { break; } ++i; p = iconimagearray[i][1]; } const char *refmd5 = iconimagearray[i][0]; if( b ) { if( iif.GetNumberOfIconImages() != 1 ) return 1; const gdcm::IconImage &icon = iif.GetIconImage(0); if( verbose ) icon.Print( std::cout ); unsigned long len = icon.GetBufferLength(); std::vector< char > vbuffer; vbuffer.resize( len ); char *buffer = &vbuffer[0]; bool res2 = icon.GetBuffer(buffer); if( !res2 ) { std::cerr << "res2 failure:" << filename << std::endl; return 1; } char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( verbose ) { std::cout << "ref=" << refmd5 << std::endl; std::cout << "md5=" << digest << std::endl; } if( !refmd5 ) { std::cerr << "Problem with : " << name << " missing md5= " << digest << std::endl; return 1; } if( strcmp( refmd5, digest) ) { std::cerr << "Problem with : " << name << " " << refmd5 << " vs " << digest << std::endl; return 1; } } else { assert( refmd5 == nullptr ); } return 0; } int TestIconImageFilter(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestIconImageFilterFunc(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestIconImageFilterFunc( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestIconImageGenerator.cxx000066400000000000000000000443241412732066400277660ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmFileMetaInformation.h" #include "gdcmTesting.h" #include "gdcmByteSwap.h" #include "gdcmIconImageGenerator.h" static const char * const iconimagearray[][2] = { {"f4f187737b9646348844804cd4eda259" , "SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs.acr" }, {"8659bcbae5479e03925ea51af0d42170" , "gdcm-MR-SIEMENS-16-2.acr" }, {"f50225bbd7de605fa5b32d47ab4d0f19" , "test.acr" }, {"890bd3ca8ab288128f520fd2a0c33539" , "MR-MONO2-12-an2.acr" }, {"8893470f6cbe6314c66763b709177c7a" , "CT-MONO2-12-lomb-an2.acr" }, {"2134b4b992ded28502f24ab3f21c6432" , "LIBIDO-8-ACR_NEMA-Lena_128_128.acr" }, {"f9d8a0796ebf5a6aabddb4e133d09770" , "gdcm-ACR-LibIDO.acr" }, {"68525a2313b5416fb6cf1f6b4fdb8d48" , "libido1.0-vol.acr" }, {"a6453c0e0abbaad98edd3fd2d76f9d31" , "SIEMENS_CSA2.dcm" }, {"84b514b71413607571b40dcc73a1e73b" , "gdcm-JPEG-LossLessThoravision.dcm" }, {"c58f9cbfa1fe616278f963b48b33ee9f" , "XA-MONO2-8-12x-catheter.dcm" }, {"d383b49843c5226c8f21cd5ee89b6da4" , "gdcm-MR-PHILIPS-16-Multi-Seq.dcm" }, {"5fd844186b04820e1a55d42e99d81466" , "PHILIPS_GDCM12xBug.dcm" }, {"5ec31742812dc9d3fd2a4eca8e8b8a48" , "MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm" }, {"0132ce06e00b199446ebd14d957e6119" , "D_CLUNIE_CT1_J2KI.dcm" }, {"3f7cae9b920adb3ca4a96ace2c0c91d7" , "rle16sti.dcm" }, {"aa3c60bbe989c9f3ef5e59243e08af56" , "3E768EB7.dcm" }, {"e3dae1f82b71857960bad4103524a72b" , "D_CLUNIE_MR2_JPLY.dcm" }, {"5995fc49c087d64182a7dc2cabedb4b2" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm" }, {"b7051f50189e469f6fc52d5108080b6d" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm" }, {"17cd7bdeb852639b214377f0263a82d3" , "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm" }, {"365049df79c7491d14476c21083283ee" , "LEADTOOLS_FLOWERS-16-MONO2-Uncompressed.dcm" }, {"2cc83519b459f49f22d37c56f0362c3a" , "D_CLUNIE_MR3_JPLY.dcm" }, {"e8b529fbe615b4c540318695913d02e7" , "D_CLUNIE_VL2_RLE.dcm" }, {"e223c80bb1ce7344559632777881fc98" , "OsirixFake16BitsStoredFakeSpacing.dcm" }, {"e1b4e64a3a665d9ad74dc8a14cdc882b" , "GE_RHAPSODE-16-MONO2-JPEG-Fragments.dcm" }, {"cb78acab107d772f3ef2353ffdc32360" , "MR_SIEMENS_forceLoad29-1010_29-1020.dcm" }, {"4755c9b837968ca19b7a9882d4662c33" , "fffc0000UN.dcm" }, {"796594769ee3570292de36fdb4509df1" , "LIBIDO-24-ACR_NEMA-Rectangle.dcm" }, {"ffab5ebdfe60100e71295fe50412a98f" , "IM-0001-0066.CommandTag00.dcm" }, {"4ce869f259e705d596bd459f7863c0ca" , "D_CLUNIE_NM1_JPLY.dcm" }, {"e1b4e64a3a665d9ad74dc8a14cdc882b" , "D_CLUNIE_CT1_J2KR.dcm" }, {"539914be101cd8a0fad88ea3e0827f59" , "TheralysGDCM120Bug.dcm" }, {"20ac559d51fd5685236979d165178dd6" , "SIEMENS_MAGNETOM-12-MONO2-VRUN.dcm" }, {"ed6e642ca59d3e90d7db08856330cf00" , "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm" }, {"209400d084e2c179c8c3d4973e75c66a" , "ALOKA_SSD-8-MONO2-RLE-SQ.dcm" }, {"66bfea16c5837f976654e038b119af7a" , "GE_GENESIS-16-MONO2-WrongLengthItem.dcm" }, {"d4669bd89971c1affd311c7d1d8b20c7" , "US-RGB-8-esopecho.dcm" }, {"4b827f55ca36895f40bc47d27a0d7ea4" , "D_CLUNIE_MR4_RLE.dcm" }, {"7d1c251e29dcd79af32c791a6f8e24e9" , "D_CLUNIE_MR2_JPLL.dcm" }, {"5d642ed928e155551f3431f172e3378d" , "SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm" }, {"365049df79c7491d14476c21083283ee" , "LEADTOOLS_FLOWERS-16-MONO2-JpegLossless.dcm" }, {"4305b70775ce53503ef93614815961e1" , "CT-MONO2-16-ankle.dcm" }, {"1a27a48d4efe2999b83bc89d3003d05c" , "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm" }, {"2134b4b992ded28502f24ab3f21c6432" , "simpleImageWithIcon.dcm" }, {"a13e29a4a0ca1a31338589a45f21a9e2" , "CR-MONO1-10-chest.dcm" }, {"e1b4e64a3a665d9ad74dc8a14cdc882b" , "D_CLUNIE_CT1_RLE.dcm" }, {"32931c4b9131f43496ab4a3518527af1" , "D_CLUNIE_NM1_JPLL.dcm" }, {"efc58ca0ba4b51b511374f8e53f2af4e" , "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm" }, {"620f0b67a91f7f74151bc5be745b7110" , "NM-MONO2-16-13x-heart.dcm" }, {"9abf5e3aadcfe2b9c1cfe41782b36704" , "US-IRAD-NoPreambleStartWith0003.dcm" }, {"f778aac834d5a68acaa97d8faec18e72" , "MR-MONO2-16-head.dcm" }, {"1a27a48d4efe2999b83bc89d3003d05c" , "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm" }, {"09e18d103bc8c9cf08b1455af2717310" , "MAROTECH_CT_JP2Lossy.dcm" }, {"bedb38b85f3bdb85c99b62e5b01a3ada" , "05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm" }, {"fb5402472ee00639ef8dc1b09692c299" , "US-PAL-8-10x-echo.dcm" }, {"cea1ea10e8efc68bfb559bbefd1e4cc1" , "MR-SIEMENS-DICOM-WithOverlays.dcm" }, {"6246c70687f0deab108c889eacda1b8e" , "D_CLUNIE_MR1_JPLL.dcm" }, {"e1b4e64a3a665d9ad74dc8a14cdc882b" , "D_CLUNIE_CT1_JPLL.dcm" }, {"db6293d8adc92a2273b6ae2fee13c2e7" , "AMIInvalidPrivateDefinedLengthSQasUN.dcm" }, {"17cd7bdeb852639b214377f0263a82d3" , "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm" }, {"b041b08aa1786195f3f26a75c1b84b85" , "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm" }, {"9172854202523aa6688367efcbfc3bdc" , "D_CLUNIE_SC1_JPLY.dcm" }, {"d29e7ff251d7d754ce8b5368f61032b0" , "gdcm-MR-PHILIPS-16-NonSquarePixels.dcm" }, {"8a5d13f6c85b2eebc1c02432d729cd45" , "SIEMENS-MR-RGB-16Bits.dcm" }, {"3e8618fee9c8baca508eeef8206a340a" , "US-IRAD-NoPreambleStartWith0005.dcm" }, {"3a7816dc8359a0d8a935313909fcf817" , "PICKER-16-MONO2-Nested_icon.dcm" }, {"be5490cac843a7325027e578067d4eb3" , "gdcm-JPEG-Extended.dcm" }, {"c790d0a462907135c1991f10a4846f98" , "D_CLUNIE_US1_RLE.dcm" }, {"3ac268f0ec6f1005a72db89d182f143c" , "D_CLUNIE_RG2_JPLY.dcm" }, {"5e848e7bc12f27e598c3348a586def24" , "PHILIPS_Brilliance_ExtraBytesInOverlay.dcm" }, {"3bbe5ebe2ff7e260d56e40f670e3e335" , "MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm" }, {"9df1b097f3f7eb4a3725065e361b9213" , "TG18-CH-2k-01.dcm" }, {"365049df79c7491d14476c21083283ee" , "LEADTOOLS_FLOWERS-16-MONO2-RLE.dcm" }, {"27daf49ec13f58db1d800fc58378852e" , "OT-PAL-8-face.dcm" }, {"07fef244d4e14358d453c144770b2a55" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm" }, {"0c38dfd851a74ea2205a0a6b69c2ddf7" , "SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm" }, {"620f0b67a91f7f74151bc5be745b7110" , "GDCMJ2K_TextGBR.dcm" }, {"5158679aaa379a50dec1e4a092d91455" , "MR16BitsAllocated_8BitsStored.dcm" }, {"22103a2ee208d18f8c4e60dc15e5444a" , "GE_GENESIS-16-MONO2-Uncompressed-UnusualVR.dcm" }, {"e1b4e64a3a665d9ad74dc8a14cdc882b" , "D_CLUNIE_CT1_JLSL.dcm" }, {"719505e71eafd643fa2e114acc83496f" , "ELSCINT1_JP2vsJ2K.dcm" }, {"09dd85a0f964f307f66f2b8727d22efb" , "D_CLUNIE_XA1_JPLL.dcm" }, {"a5019730f663a81b50d559c8a98da4a6" , "SIEMENS_Sonata-12-MONO2-SQ.dcm" }, {"ed0f5fc46b2e0bb6550d68686d956ca6" , "JPEGDefinedLengthSequenceOfFragments.dcm" }, {"5aaee8a979cb11627e56ca5757e5d4e3" , "PHILIPS_GDCM12xBug2.dcm" }, {"620f0b67a91f7f74151bc5be745b7110" , "ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm" }, {"e34c7c8d406ceec07ff1c8b82b59d2e5" , "D_CLUNIE_RG2_JPLL.dcm" }, {"7478edd0202fde583138df8dfe2782f9" , "FUJI-10-MONO1-ACR_NEMA_2.dcm" }, {"c5d8e44435241965c400935d30b0d654" , "D_CLUNIE_MR1_JPLY.dcm" }, {"09dd85a0f964f307f66f2b8727d22efb" , "D_CLUNIE_XA1_RLE.dcm" }, {"2783d3ac71623cd136de7eb8af13753b" , "BugGDCM2_UndefItemWrongVL.dcm" }, {"8659bcbae5479e03925ea51af0d42170" , "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm" }, {"477d801b27ef3cb21a8685cedbc9b12e" , "JDDICOM_Sample2.dcm" }, {"028dcdbc8e309eac282f73cff0751273" , "TOSHIBA_MRT150-16-MONO2-ACR_NEMA_2.dcm" }, {"7e183442aefeadbfff9f0d79a7064a5d" , "DCMTK_JPEGExt_12Bits.dcm" }, {"9f04afae98a960de78b31e416bdbe31b" , "US-MONO2-8-8x-execho.dcm" }, {"7cc0d00a56ec460d4025d4f9cea4e445" , "UnexpectedSequenceDelimiterInFixedLengthSequence.dcm" }, {"bee28068ae9edef69fef792583b3e20f" , "ACUSON-24-YBR_FULL-RLE-b.dcm" }, {"b171f7581c9cf15b2d32cfd62e9b6038" , "gdcm-US-ALOKA-16.dcm" }, {"b6ba84d4868436e0b44b19d75cefe239" , "DX_J2K_0Padding.dcm" }, {"76b3e5225e1914e61010eb11c50b0d13" , "D_CLUNIE_CT2_RLE.dcm" }, {"455aa24ef2085a6b57f8b29d4f42b558" , "D_CLUNIE_RG1_JPLL.dcm" }, {"e0a3fd5917c5a13a16981e1d0346af4d" , "D_CLUNIE_VL3_RLE.dcm" }, {"fd69a42d6ed9ac779fbdea5a874f27da" , "NM_Kakadu44_SOTmarkerincons.dcm" }, {"5a622115e307a024aeb6003ad45c87d7" , "CT-SIEMENS-Icone-With-PaletteColor.dcm" }, {"d687a5770da5430258c9354ef7283fb1" , "GE_DLX-8-MONO2-PrivateSyntax.dcm" }, {"48843eac44f481073e2349a9b40034e6" , "CT_16b_signed-UsedBits13.dcm" }, {"7b8f24a39d4d46d6898d0c868e2ead62" , "D_CLUNIE_RG3_JPLY.dcm" }, {"a1b35156bf0be7f0fe5054e13b6dc11f" , "DX_GE_FALCON_SNOWY-VOI.dcm" }, {"8745f035e70b8dad2a4b04b855c1974e" , "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm" }, {"608d7fd9e8cf15f95b75a12072a209d9" , "CT-MONO2-16-brain.dcm" }, {"c2de60330cda14759a117b937a7e5a95" , "D_CLUNIE_VL4_RLE.dcm" }, {"b4213e55f351e2c9e013050652c8fad4" , "D_CLUNIE_MR3_RLE.dcm" }, {"cdae2ce2d07ef1880f9eba78e72c7f03" , "undefined_length_un_vr.dcm" }, {"1e456d9eb136554a3d035d65999ac72f" , "CT-MONO2-16-ort.dcm" }, {"7022cd07ae0e9311ca2bb13372becee1" , "05148044-mr-siemens-avanto-syngo.dcm" }, {"5d6aaab5766479ec6e27de4eaa4a6438" , "GE_LOGIQBook-8-RGB-HugePreview.dcm" }, {"d8b9952cb72ea315ae4b81038ca7498f" , "RadBWLossLess.dcm" }, {"b7b5b0a05dde85a672529e896ffd34cc" , "KODAK-12-MONO1-Odd_Terminated_Sequence.dcm" }, {"c1b31ebeb79ba29263e59254af17eb88" , "CT-MONO2-16-chest.dcm" }, {"4085155ff0a36230f55dfd17c07b016f" , "PhilipsInteraSeqTermInvLen.dcm" }, {"4c80f49834a2f8cec23ff8c7c0e80613" , "D_CLUNIE_MR4_JPLY.dcm" }, {"dc04449fe2bdd8c5ff26f2b6b4f3a1aa" , "D_CLUNIE_RG3_JPLL.dcm" }, {"01d9c3bac1a49f874eb70640d9187657" , "MR_Philips-Intera_BreaksNOSHADOW.dcm" }, {"f86eb566e712fa57bf5bdd13af9233c6" , "GE_CT_With_Private_compressed-icon.dcm" }, {"b2ed24f5bad1fe7fe1ceb62a1a37bf03" , "D_CLUNIE_CT1_JLSN.dcm" }, {"20ac559d51fd5685236979d165178dd6" , "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm" }, {"cee47e57f6b1aaace74bb813e33a74eb" , "00191113.dcm" }, {"645a354b8bfbbda1c3e01a79c583eca0" , "MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm" }, {"f8ef8fa89c0415c54ee8350db9bafc59" , "SignedShortLosslessBug.dcm" }, {"9274ed6683e657a8e6c95278cb93a971" , "GE_DLX-8-MONO2-Multiframe.dcm" }, {"cb7ccda2e8aed6d56df6350207c1d122" , "PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm" }, {"788c5bf06000799bd630c70ce0418430" , "LJPEG_BuginGDCM12.dcm" }, {"610b9ac0f1aac082eb1c0b140a85d2de" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm" }, {"dc04449fe2bdd8c5ff26f2b6b4f3a1aa" , "D_CLUNIE_RG3_RLE.dcm" }, {"587e56aa881d645ee67ac3afe317b11d" , "CT-SIEMENS-MissingPixelDataInIconSQ.dcm" }, {"7d1c251e29dcd79af32c791a6f8e24e9" , "MR-MONO2-12-shoulder.dcm" }, {"0b818ac3983d76cfdc535a46058a1a53" , "LEADTOOLS_FLOWERS-24-RGB-Uncompressed.dcm" }, {"ba8fb87069401e40d9c0dd5bf0f2bb06" , "PICKER-16-MONO2-No_DicomV3_Preamble.dcm" }, {"634fca1b1087cfb2dd4c74a567daf302" , "SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm" }, {"ba0654f3e7aae75bca8fc24705ddb78a" , "CT-MONO2-8-abdo.dcm" }, {"b4213e55f351e2c9e013050652c8fad4" , "D_CLUNIE_MR3_JPLL.dcm" }, {"03f25fb3e6e8ae53b9565553e2026a66" , "D_CLUNIE_VL6_RLE.dcm" }, {"365049df79c7491d14476c21083283ee" , "LEADTOOLS_FLOWERS-8-MONO2-RLE.dcm" }, {"99b13adb3932f9fcf50c0aa936b6e367" , "PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm" }, {"1f0795064ee1d19534780b7a4e92d5db" , "SIEMENS-12-Jpeg_Process_2_4-Lossy-a.dcm" }, {"de42da38e961881e7a68f4d9337007cd" , "gdcm-JPEG-LossLess3a.dcm" }, {"bec532ee78edb47bd0894dcbb2a7d1f5" , "D_CLUNIE_XA1_JPLY.dcm" }, {"455aa24ef2085a6b57f8b29d4f42b558" , "D_CLUNIE_RG1_RLE.dcm" }, {"e77b93eb953f2a21fa75d257da0514fb" , "US-RGB-8-epicard.dcm" }, {"ddc56ce334439f64953f1b11c82aeeb9" , "GE_MR_0025xx1bProtocolDataBlock.dcm" }, {"b9f48f54e75b7f1994cfe1a7152d9ab5" , "rle16loo.dcm" }, {"50bf4b4c98228d2f11fb0d8c4b49e3cc" , "DMCPACS_ExplicitImplicit_BogusIOP.dcm" }, {"76b3e5225e1914e61010eb11c50b0d13" , "D_CLUNIE_CT2_JPLL.dcm" }, {"477d801b27ef3cb21a8685cedbc9b12e" , "JDDICOM_Sample2-dcmdjpeg.dcm" }, {"17cd7bdeb852639b214377f0263a82d3" , "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm" }, {"19cd0ebffc7541a5ec944d25200923ad" , "KODAK_CompressedIcon.dcm" }, {"486199008daf27f167efee9469fffd52" , "ACUSON-24-YBR_FULL-RLE.dcm" }, {"7d1c251e29dcd79af32c791a6f8e24e9" , "D_CLUNIE_MR2_RLE.dcm" }, {"b53c440c32a7bd20d24cc1997bd7c9e6" , "JPEG_LossyYBR.dcm" }, {"4c54ea0d88336020167a5cb9437a1dec" , "012345.002.050.dcm" }, {"e34c7c8d406ceec07ff1c8b82b59d2e5" , "D_CLUNIE_RG2_RLE.dcm" }, {"b209bb00a5bb920ebfb52b50132bd3cb" , "MR_Philips_Intera_PrivateSequenceImplicitVR.dcm" }, {"261065dc52f086beac57ed71977b40ec" , "SIEMENS_ImageLocationUN.dcm" }, {"17cd7bdeb852639b214377f0263a82d3" , "PHILIPS_Intera-16-MONO2-Uncompress.dcm" }, {"60e754c9dfc02bba3aee11e67653d844" , "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm" }, {"0b818ac3983d76cfdc535a46058a1a53" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossless.dcm" }, {"91b4da2ca9fd378ca404580c84c62984" , "US-GE-4AICL142.dcm" }, {"5b24d4a43d7c72090eabb88a06b56f15" , "D_CLUNIE_SC1_RLE.dcm" }, {"4b827f55ca36895f40bc47d27a0d7ea4" , "D_CLUNIE_MR4_JPLL.dcm" }, {"95ccb6a943e1ca82f3be78ceaa72b9d4" , "MR-Brucker-CineTagging-NonSquarePixels.dcm" }, {"552dd953ebd0575d124e44df0218b0ea" , "MR-MONO2-8-16x-heart.dcm" }, {"e73b404ca6d9b4b7ba54f46d2662deca" , "LEADTOOLS_FLOWERS-8-MONO2-JpegLossy.dcm" }, {"8a35a388332dbb40018ee6814ab27994" , "GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm" }, {"32931c4b9131f43496ab4a3518527af1" , "D_CLUNIE_NM1_RLE.dcm" }, {"20e2f6cc2b60ae26adfdd3b3ee0e1915" , "D_CLUNIE_VL1_RLE.dcm" }, {"0b1cb469990edd0cabfa34c8b6cb427d" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm" }, {"620f0b67a91f7f74151bc5be745b7110" , "DermaColorLossLess.dcm" }, {"b9395dcfbb50e1af31147f80e8e0c1e7" , "OT-MONO2-8-a7.dcm" }, {"6246c70687f0deab108c889eacda1b8e" , "D_CLUNIE_MR1_RLE.dcm" }, {"365049df79c7491d14476c21083283ee" , "LEADTOOLS_FLOWERS-8-MONO2-Uncompressed.dcm" }, {"cee47e57f6b1aaace74bb813e33a74eb" , "00191113.dcm" }, {"07b6f4e2fba920d28e2f29dbb037b640" , "TOSHIBA_J2K_SIZ1_PixRep0.dcm" }, {"206713a8ff161546d664d1285f99f90b" , "TOSHIBA_J2K_OpenJPEGv2Regression.dcm" }, {"dc70ae52689ebf8f5003320e1c7f216b" , "TOSHIBA_J2K_SIZ0_PixRep1.dcm" }, {"3475cb96e0308cb84502be1c1531b588" , "NM-PAL-16-PixRep1.dcm" }, {"bcac830aae8652a88f4c4aa6d9e7e116" , "MEDILABInvalidCP246_EVRLESQasUN.dcm" }, {"5b8db1c8d42870f68bfd908529c58710" , "JPEGInvalidSecondFrag.dcm" }, {"37f43037574e53a0c27151443e27613f" , "SC16BitsAllocated_8BitsStoredJ2K.dcm" }, {"620f0b67a91f7f74151bc5be745b7110" , "SC16BitsAllocated_8BitsStoredJPEG.dcm" }, // sentinel { 0, 0 } }; namespace gdcm { int TestIconImageGenerate(const char *subdir, const char* filename, bool verbose = false) { ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const FileMetaInformation &header = reader.GetFile().GetHeader(); MediaStorage ms = header.GetMediaStorage(); bool isImage = MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } else { // not an image give up... std::cerr << "Problem with: " << filename << " but that's ok" << std::endl; return 0; } } // Create directory first: std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); IconImageGenerator iig; iig.SetPixmap( reader.GetImage() ); const unsigned int idims[2] = { 64, 64 }; iig.SetOutputDimensions( idims ); bool b = iig.Generate(); gdcm::Filename fn( filename ); const char *name = fn.GetName(); unsigned int i = 0; const char *p = iconimagearray[i][1]; while( p != 0 ) { if( strcmp( name, p ) == 0 ) { break; } ++i; p = iconimagearray[i][1]; } const char *refmd5 = iconimagearray[i][0]; if( b ) { const gdcm::IconImage &icon = iig.GetIconImage(); if( verbose ) icon.Print( std::cout ); unsigned long len = icon.GetBufferLength(); std::vector< char > vbuffer; vbuffer.resize( len ); char *buffer = &vbuffer[0]; bool res2 = icon.GetBuffer(buffer); if( !res2 ) { std::cerr << "res2 failure:" << filename << std::endl; return 1; } char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); Image & img = reader.GetImage(); img.SetIconImage( iig.GetIconImage() ); ImageWriter writer; writer.SetFileName( outfilename.c_str() ); #if 1 writer.SetImage( img ); #else Image &ii = writer.GetImage(); (Bitmap&)ii = iig.GetIconImage(); #endif if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } if( verbose ) { std::cout << "success: " << outfilename << std::endl; std::cout << "ref=" << refmd5 << std::endl; std::cout << "md5=" << digest << std::endl; } if( !refmd5 ) { std::cerr << " missing md5= {\"" << digest << "\" , \"" << name << "\" }," << std::endl; return 1; } if( strcmp( refmd5, digest) ) { std::cerr << "Problem with : " << name << " " << refmd5 << " vs " << digest << std::endl; return 1; } } else { assert( refmd5 == 0 ); std::cerr << "Could not generate Icon for: " << filename << std::endl; return 1; } return 0; } } int TestIconImageGenerator(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestIconImageGenerate(argv[0],filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestIconImageGenerate(argv[0], filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestIconImageGenerator2.cxx000066400000000000000000000442051412732066400300460ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmFileMetaInformation.h" #include "gdcmTesting.h" #include "gdcmByteSwap.h" #include "gdcmIconImageGenerator.h" static const char * const iconimagearray2[][2] = { {"7e097b4a57af6a823bd692e37b131b1c" , "SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs.acr" }, {"7f2638cea652bf3452ada158d2ea67c4" , "gdcm-MR-SIEMENS-16-2.acr" }, {"da0922a02f8e763ec878089617e0bc4c" , "test.acr" }, {"e75ee90f23db1952a593393cdfaaf99f" , "MR-MONO2-12-an2.acr" }, {"c9c46afd186531850af9576cf54c800b" , "CT-MONO2-12-lomb-an2.acr" }, {"feb10d9a28e5166a3baf9ec6ef4f460a" , "LIBIDO-8-ACR_NEMA-Lena_128_128.acr" }, {"f9d8a0796ebf5a6aabddb4e133d09770" , "gdcm-ACR-LibIDO.acr" }, {"a1bce65e11c5fd2e26f7b38ebfdd1c53" , "libido1.0-vol.acr" }, {"9edea7caea2b85aad952d35c64f1e092" , "SIEMENS_CSA2.dcm" }, {"011d1f2abd9e27a2dc5d013bd4848104" , "gdcm-JPEG-LossLessThoravision.dcm" }, {"ddb7e67d119eb2ce14731cd9007e36cc" , "XA-MONO2-8-12x-catheter.dcm" }, {"1041bae356da40d2113210ff2adef923" , "gdcm-MR-PHILIPS-16-Multi-Seq.dcm" }, {"a3a6b3bf75ccdc91f82effc60d005688" , "PHILIPS_GDCM12xBug.dcm" }, {"a247e2ca32279956079c9a87403bd157" , "MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm" }, {"48b19e53bffc8feab8671fd23c869028" , "D_CLUNIE_CT1_J2KI.dcm" }, {"3f7cae9b920adb3ca4a96ace2c0c91d7" , "rle16sti.dcm" }, {"f706f740496e445ee59141b15f3baeb4" , "3E768EB7.dcm" }, {"b38c113fffa4925f6f06a928b357f6a1" , "D_CLUNIE_MR2_JPLY.dcm" }, {"c3d3a218fcec778476090bce4c8b3201" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm" }, {"882a7327bab05d88571dcf29f902adf3" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm" }, {"7944f0f8eb06466099fe6cd792ae8bfa" , "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm" }, {"af193ff3143f299826d55e00696b3218" , "LEADTOOLS_FLOWERS-16-MONO2-Uncompressed.dcm" }, {"b9b499634bdaff3be7710722f75d9b5d" , "D_CLUNIE_MR3_JPLY.dcm" }, {"e8b529fbe615b4c540318695913d02e7" , "D_CLUNIE_VL2_RLE.dcm" }, {"8393213bd2c340a8cbd639f45a6b497e" , "OsirixFake16BitsStoredFakeSpacing.dcm" }, {"205a3ba253b61bf5ebb374523c366ccb" , "GE_RHAPSODE-16-MONO2-JPEG-Fragments.dcm" }, {"c265bf6c3bf4417987ff81b92ca4ca6c" , "MR_SIEMENS_forceLoad29-1010_29-1020.dcm" }, {"fa7da45d1a8eb16b092880ceff5a50e5" , "fffc0000UN.dcm" }, {"796594769ee3570292de36fdb4509df1" , "LIBIDO-24-ACR_NEMA-Rectangle.dcm" }, {"32b10fd4f13cfb4d74e1145f166e9dae" , "IM-0001-0066.CommandTag00.dcm" }, {"619f8c1650962cddf7695e39f43e8c49" , "D_CLUNIE_NM1_JPLY.dcm" }, {"205a3ba253b61bf5ebb374523c366ccb" , "D_CLUNIE_CT1_J2KR.dcm" }, {"30a530ea4df623cbec31f752637e234b" , "TheralysGDCM120Bug.dcm" }, {"3120b59e3635a912c6a60897f734b2ff" , "SIEMENS_MAGNETOM-12-MONO2-VRUN.dcm" }, {"5bdb2335ceb2dac83c2248d6ff8e0a49" , "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm" }, {"30ff6655c5eb98ad34cd20836418a5a7" , "ALOKA_SSD-8-MONO2-RLE-SQ.dcm" }, {"992e4ef2b01f9d79514d7ab22c354be9" , "GE_GENESIS-16-MONO2-WrongLengthItem.dcm" }, {"d4669bd89971c1affd311c7d1d8b20c7" , "US-RGB-8-esopecho.dcm" }, {"85124dd05ab0567aecaf896373f780da" , "D_CLUNIE_MR4_RLE.dcm" }, {"07964ed19883cb96460d1407795f4306" , "D_CLUNIE_MR2_JPLL.dcm" }, {"096547f2834609ae4dbc115169806fc4" , "SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm" }, {"af193ff3143f299826d55e00696b3218" , "LEADTOOLS_FLOWERS-16-MONO2-JpegLossless.dcm" }, {"da7002947725a950c3226cd23aa8d718" , "CT-MONO2-16-ankle.dcm" }, {"1a27a48d4efe2999b83bc89d3003d05c" , "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm" }, {"feb10d9a28e5166a3baf9ec6ef4f460a" , "simpleImageWithIcon.dcm" }, {"aeb28d2cfb5376e2bb1ac4aac0b4807c" , "CR-MONO1-10-chest.dcm" }, {"205a3ba253b61bf5ebb374523c366ccb" , "D_CLUNIE_CT1_RLE.dcm" }, {"4d469f85f51b3b81bdf38ebba23a68e7" , "D_CLUNIE_NM1_JPLL.dcm" }, {"8ffdae8852e9388369935d65b8afa408" , "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm" }, {"abe1950da247d18196fe5bea54cb26f1" , "NM-MONO2-16-13x-heart.dcm" }, {"6bd67bbd6e3e65808db8598fe0913f86" , "US-IRAD-NoPreambleStartWith0003.dcm" }, {"99672e03104c9176595bc0002cd8edf8" , "MR-MONO2-16-head.dcm" }, {"1a27a48d4efe2999b83bc89d3003d05c" , "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm" }, {"af8491953e762c12feb93a80a1575edf" , "MAROTECH_CT_JP2Lossy.dcm" }, {"932281859be22ffae33a2669b34cc2e6" , "05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm" }, {"fb5402472ee00639ef8dc1b09692c299" , "US-PAL-8-10x-echo.dcm" }, {"038acb53133733a9f2c54528b8029511" , "MR-SIEMENS-DICOM-WithOverlays.dcm" }, {"890d0a5afdbf77398d857b523f86e83a" , "D_CLUNIE_MR1_JPLL.dcm" }, {"205a3ba253b61bf5ebb374523c366ccb" , "D_CLUNIE_CT1_JPLL.dcm" }, {"7e971371b523cc1db53f3fc7f2ac5441" , "AMIInvalidPrivateDefinedLengthSQasUN.dcm" }, {"7944f0f8eb06466099fe6cd792ae8bfa" , "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm" }, {"3443eba48f11dd9aadb4632c8c896b39" , "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm" }, {"b72e483ad977e18b8016c7cc916c4bbd" , "D_CLUNIE_SC1_JPLY.dcm" }, {"582df1a47c5992cc4f37496dab8c5130" , "gdcm-MR-PHILIPS-16-NonSquarePixels.dcm" }, {"8a5d13f6c85b2eebc1c02432d729cd45" , "SIEMENS-MR-RGB-16Bits.dcm" }, {"aacd6f6257e068cf53cdec5c7e172513" , "US-IRAD-NoPreambleStartWith0005.dcm" }, {"6a9ecd676ce47b0fda111a804b58b054" , "PICKER-16-MONO2-Nested_icon.dcm" }, {"9b720fd0aa079bc2f3f9545bd0e207c6" , "gdcm-JPEG-Extended.dcm" }, {"c790d0a462907135c1991f10a4846f98" , "D_CLUNIE_US1_RLE.dcm" }, {"4689c053642dcee7a2a9d0475c1b6528" , "D_CLUNIE_RG2_JPLY.dcm" }, {"b3b8a60e7b7b20c029eec1d5006e2b9c" , "PHILIPS_Brilliance_ExtraBytesInOverlay.dcm" }, {"91533007e5e07353012dea33149d920f" , "MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm" }, {"c8902cc14f285f2687866f60e45c7d86" , "TG18-CH-2k-01.dcm" }, {"af193ff3143f299826d55e00696b3218" , "LEADTOOLS_FLOWERS-16-MONO2-RLE.dcm" }, {"27daf49ec13f58db1d800fc58378852e" , "OT-PAL-8-face.dcm" }, {"07fef244d4e14358d453c144770b2a55" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm" }, {"ad96e04c3c50d463cccdfca68b49b071" , "SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm" }, {"620f0b67a91f7f74151bc5be745b7110" , "GDCMJ2K_TextGBR.dcm" }, {"d1f5dfac9c3213f548df6a1f9e86acd0" , "MR16BitsAllocated_8BitsStored.dcm" }, {"dab7df42898362213062eb0d493eb38e" , "GE_GENESIS-16-MONO2-Uncompressed-UnusualVR.dcm" }, {"205a3ba253b61bf5ebb374523c366ccb" , "D_CLUNIE_CT1_JLSL.dcm" }, {"719505e71eafd643fa2e114acc83496f" , "ELSCINT1_JP2vsJ2K.dcm" }, {"7132fec8839d9c8b26cba4a4f17000da" , "D_CLUNIE_XA1_JPLL.dcm" }, {"cdf5908902fb63e321b224fae86a4128" , "SIEMENS_Sonata-12-MONO2-SQ.dcm" }, {"bc1774acbf5c025aa3b57184213cc98c" , "JPEGDefinedLengthSequenceOfFragments.dcm" }, {"e9faa2ce59db8563d7abe50432f91351" , "PHILIPS_GDCM12xBug2.dcm" }, {"620f0b67a91f7f74151bc5be745b7110" , "ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm" }, {"52d0b90aa78a20cbff6b0beb3bd2c2b3" , "D_CLUNIE_RG2_JPLL.dcm" }, {"50dd1ae0bf918a9144b50229fa04f8e0" , "FUJI-10-MONO1-ACR_NEMA_2.dcm" }, {"d7e55bf3c6eb7a627823b532bcac7e16" , "D_CLUNIE_MR1_JPLY.dcm" }, {"7132fec8839d9c8b26cba4a4f17000da" , "D_CLUNIE_XA1_RLE.dcm" }, {"ddb5ac3f32badb154ce9a8a18c09c2c0" , "BugGDCM2_UndefItemWrongVL.dcm" }, {"7f2638cea652bf3452ada158d2ea67c4" , "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm" }, {"477d801b27ef3cb21a8685cedbc9b12e" , "JDDICOM_Sample2.dcm" }, {"cae77b420f407118f288c14eeb81e11f" , "TOSHIBA_MRT150-16-MONO2-ACR_NEMA_2.dcm" }, {"524014ef866b31e3fd2e33a6148d31bb" , "DCMTK_JPEGExt_12Bits.dcm" }, {"84ea2f46ad98332a06875da922709007" , "US-MONO2-8-8x-execho.dcm" }, {"19d6f17c8a0b2cd04049828dcb304046" , "UnexpectedSequenceDelimiterInFixedLengthSequence.dcm" }, {"bee28068ae9edef69fef792583b3e20f" , "ACUSON-24-YBR_FULL-RLE-b.dcm" }, {"b171f7581c9cf15b2d32cfd62e9b6038" , "gdcm-US-ALOKA-16.dcm" }, {"80be78c9365f6a1604191dd703c84ac5" , "DX_J2K_0Padding.dcm" }, {"a9a72d44b888fb4f1f727af88109cfb3" , "D_CLUNIE_CT2_RLE.dcm" }, {"151376fcac2fbd55c3b5c5a155e16d26" , "D_CLUNIE_RG1_JPLL.dcm" }, {"e0a3fd5917c5a13a16981e1d0346af4d" , "D_CLUNIE_VL3_RLE.dcm" }, {"28ea47a62e1f2ca9d7dcd10ef868701d" , "NM_Kakadu44_SOTmarkerincons.dcm" }, {"e95cec3c8078cea91b287e45d751cf78" , "CT-SIEMENS-Icone-With-PaletteColor.dcm" }, {"eacd1cabeaf78554804ca627344cba91" , "GE_DLX-8-MONO2-PrivateSyntax.dcm" }, {"8f40712ff8e4a7691be144d884546a17" , "CT_16b_signed-UsedBits13.dcm" }, {"da9fb19d564fa01e4633df5c105f5a58" , "D_CLUNIE_RG3_JPLY.dcm" }, {"6510f44ff1dd8daf9b49100fd2c81d85" , "DX_GE_FALCON_SNOWY-VOI.dcm" }, {"5a15bd50c589c9611636dc7813493c03" , "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm" }, {"4948235091edc01603344f79a29835e1" , "CT-MONO2-16-brain.dcm" }, {"c2de60330cda14759a117b937a7e5a95" , "D_CLUNIE_VL4_RLE.dcm" }, {"db07030ff68debba674a6ca5c3e6eeb3" , "D_CLUNIE_MR3_RLE.dcm" }, {"72f55d5cf022e983783185195b77d0e6" , "undefined_length_un_vr.dcm" }, {"a8e2e35044384f31afc1dcf9163154ff" , "CT-MONO2-16-ort.dcm" }, {"0fefcf91a55062f1cb20945b3f726eda" , "05148044-mr-siemens-avanto-syngo.dcm" }, {"5d6aaab5766479ec6e27de4eaa4a6438" , "GE_LOGIQBook-8-RGB-HugePreview.dcm" }, {"acad4e43da617035315bcddc4bbb96bd" , "RadBWLossLess.dcm" }, {"b69e23b6479de4d9c3b4ed51aa748f73" , "KODAK-12-MONO1-Odd_Terminated_Sequence.dcm" }, {"e8458a5483e72cced4d46f93eed1699e" , "CT-MONO2-16-chest.dcm" }, {"728a698e308f7863ba3d103b80dffc45" , "PhilipsInteraSeqTermInvLen.dcm" }, {"35144f65c704edf2d69abc40405c3ea7" , "D_CLUNIE_MR4_JPLY.dcm" }, {"904b38f362b86f626ea7d89eed455709" , "D_CLUNIE_RG3_JPLL.dcm" }, {"707e26b0fa27f670c35ca5cc2bf3eda2" , "MR_Philips-Intera_BreaksNOSHADOW.dcm" }, {"04b97df84da7a126be30993cf9cff942" , "GE_CT_With_Private_compressed-icon.dcm" }, {"04cb0299587f38ba369e1fdcbf07dc25" , "D_CLUNIE_CT1_JLSN.dcm" }, {"3120b59e3635a912c6a60897f734b2ff" , "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm" }, {"cee47e57f6b1aaace74bb813e33a74eb" , "00191113.dcm" }, {"99ba02caa6813cafd254f97fb8377f60" , "MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm" }, {"0a9449186ab107120640910a58a38ec4" , "SignedShortLosslessBug.dcm" }, {"2b306840879792f3509e1c1ccedee81d" , "GE_DLX-8-MONO2-Multiframe.dcm" }, {"fde7dc022ec854a98ffdc2190ceef424" , "PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm" }, {"f4b5fc5cc1440b865f1a99b85b170ecd" , "LJPEG_BuginGDCM12.dcm" }, {"ba2717c0d839213e788a74cccf37f1d4" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm" }, {"904b38f362b86f626ea7d89eed455709" , "D_CLUNIE_RG3_RLE.dcm" }, {"5e51e64ee21c2f643c13257e054c2990" , "CT-SIEMENS-MissingPixelDataInIconSQ.dcm" }, {"07964ed19883cb96460d1407795f4306" , "MR-MONO2-12-shoulder.dcm" }, {"0b818ac3983d76cfdc535a46058a1a53" , "LEADTOOLS_FLOWERS-24-RGB-Uncompressed.dcm" }, {"7f7aaee92f20ffcd64bebf8ce105bf5d" , "PICKER-16-MONO2-No_DicomV3_Preamble.dcm" }, {"fde3b9c4853c597383fab1050b491202" , "SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm" }, {"ba0654f3e7aae75bca8fc24705ddb78a" , "CT-MONO2-8-abdo.dcm" }, {"db07030ff68debba674a6ca5c3e6eeb3" , "D_CLUNIE_MR3_JPLL.dcm" }, {"03f25fb3e6e8ae53b9565553e2026a66" , "D_CLUNIE_VL6_RLE.dcm" }, {"af193ff3143f299826d55e00696b3218" , "LEADTOOLS_FLOWERS-8-MONO2-RLE.dcm" }, {"d46afca30969faa05583e87b0f6e5211" , "PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm" }, {"5885ade0feaaf967f5a1c22724c10d02" , "SIEMENS-12-Jpeg_Process_2_4-Lossy-a.dcm" }, {"13758e32fe34c17b897efcbd26e7e03b" , "gdcm-JPEG-LossLess3a.dcm" }, {"1e61c6d50ae3ef3ac0550277f166bd1c" , "D_CLUNIE_XA1_JPLY.dcm" }, {"151376fcac2fbd55c3b5c5a155e16d26" , "D_CLUNIE_RG1_RLE.dcm" }, {"e77b93eb953f2a21fa75d257da0514fb" , "US-RGB-8-epicard.dcm" }, {"a101ddd933114bcc0145d047d74f41c9" , "GE_MR_0025xx1bProtocolDataBlock.dcm" }, {"b9f48f54e75b7f1994cfe1a7152d9ab5" , "rle16loo.dcm" }, {"cc61470afd2b80014749abbb5bd9109d" , "DMCPACS_ExplicitImplicit_BogusIOP.dcm" }, {"a9a72d44b888fb4f1f727af88109cfb3" , "D_CLUNIE_CT2_JPLL.dcm" }, {"477d801b27ef3cb21a8685cedbc9b12e" , "JDDICOM_Sample2-dcmdjpeg.dcm" }, {"7944f0f8eb06466099fe6cd792ae8bfa" , "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm" }, {"323c2919ea590363dd6eb4105a2566a7" , "KODAK_CompressedIcon.dcm" }, {"486199008daf27f167efee9469fffd52" , "ACUSON-24-YBR_FULL-RLE.dcm" }, {"07964ed19883cb96460d1407795f4306" , "D_CLUNIE_MR2_RLE.dcm" }, {"b53c440c32a7bd20d24cc1997bd7c9e6" , "JPEG_LossyYBR.dcm" }, {"23bf148e163ea7d3f1dbadfc590618fe" , "012345.002.050.dcm" }, {"52d0b90aa78a20cbff6b0beb3bd2c2b3" , "D_CLUNIE_RG2_RLE.dcm" }, {"e44869a1044b611e08a9f1396432a44b" , "MR_Philips_Intera_PrivateSequenceImplicitVR.dcm" }, {"f92d6349e1d80bbdba34a9e1b84eb737" , "SIEMENS_ImageLocationUN.dcm" }, {"7944f0f8eb06466099fe6cd792ae8bfa" , "PHILIPS_Intera-16-MONO2-Uncompress.dcm" }, {"0e82ac528c72a2dd69fa1b52e5370d82" , "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm" }, {"0b818ac3983d76cfdc535a46058a1a53" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossless.dcm" }, {"91b4da2ca9fd378ca404580c84c62984" , "US-GE-4AICL142.dcm" }, {"2ff486489d600e0ab5f8c829960c516f" , "D_CLUNIE_SC1_RLE.dcm" }, {"85124dd05ab0567aecaf896373f780da" , "D_CLUNIE_MR4_JPLL.dcm" }, {"ece67fa0c8a99f8147b26081252cd0a5" , "MR-Brucker-CineTagging-NonSquarePixels.dcm" }, {"bdf48b10871ac0b3c14587eaba9ca998" , "MR-MONO2-8-16x-heart.dcm" }, {"0c65a403a0a24957e523bb29e84c31ef" , "LEADTOOLS_FLOWERS-8-MONO2-JpegLossy.dcm" }, {"f92a60ad3cbc2783db57cac5f800a9c0" , "GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm" }, {"4d469f85f51b3b81bdf38ebba23a68e7" , "D_CLUNIE_NM1_RLE.dcm" }, {"20e2f6cc2b60ae26adfdd3b3ee0e1915" , "D_CLUNIE_VL1_RLE.dcm" }, {"84462b24809f4e9d151c7c27004f7922" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm" }, {"620f0b67a91f7f74151bc5be745b7110" , "DermaColorLossLess.dcm" }, {"72e203ca5756f4491d84d8240c82a59b" , "OT-MONO2-8-a7.dcm" }, {"890d0a5afdbf77398d857b523f86e83a" , "D_CLUNIE_MR1_RLE.dcm" }, {"af193ff3143f299826d55e00696b3218" , "LEADTOOLS_FLOWERS-8-MONO2-Uncompressed.dcm" }, {"cee47e57f6b1aaace74bb813e33a74eb" , "00191113.dcm" }, {"07b6f4e2fba920d28e2f29dbb037b640" , "TOSHIBA_J2K_SIZ1_PixRep0.dcm" }, {"93f60acbb450c62992a1db09a6c19c05" , "TOSHIBA_J2K_OpenJPEGv2Regression.dcm" }, {"fa02ad71bdf3e6970e18fc9a9df03a2d" , "TOSHIBA_J2K_SIZ0_PixRep1.dcm" }, {"3475cb96e0308cb84502be1c1531b588" , "NM-PAL-16-PixRep1.dcm" }, {"2ec6d7c60d6786665cff2b7a31aaeedf" , "MEDILABInvalidCP246_EVRLESQasUN.dcm" }, {"54b1cec013420f771142ca6ec6c274a4" , "JPEGInvalidSecondFrag.dcm" }, // sentinel { 0, 0 } }; namespace gdcm { int TestIconImageGenerate2(const char *subdir, const char* filename, bool verbose = false) { ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const FileMetaInformation &header = reader.GetFile().GetHeader(); MediaStorage ms = header.GetMediaStorage(); bool isImage = MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } else { // not an image give up... std::cerr << "Problem with: " << filename << " but that's ok" << std::endl; return 0; } } // Create directory first: std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); IconImageGenerator iig; iig.SetPixmap( reader.GetImage() ); iig.AutoPixelMinMax(true); const unsigned int idims[2] = { 64, 64 }; //const unsigned int idims[2] = { 600,430 }; iig.SetOutputDimensions( idims ); bool b = iig.Generate(); gdcm::Filename fn( filename ); const char *name = fn.GetName(); unsigned int i = 0; const char *p = iconimagearray2[i][1]; while( p != 0 ) { if( strcmp( name, p ) == 0 ) { break; } ++i; p = iconimagearray2[i][1]; } const char *refmd5 = iconimagearray2[i][0]; if( b ) { const gdcm::IconImage &icon = iig.GetIconImage(); if( verbose ) icon.Print( std::cout ); unsigned long len = icon.GetBufferLength(); std::vector< char > vbuffer; vbuffer.resize( len ); char *buffer = &vbuffer[0]; bool res2 = icon.GetBuffer(buffer); if( !res2 ) { std::cerr << "res2 failure:" << filename << std::endl; return 1; } char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); Image & img = reader.GetImage(); img.SetIconImage( iig.GetIconImage() ); ImageWriter writer; writer.SetFileName( outfilename.c_str() ); #if 1 writer.SetImage( img ); #else Image &ii = writer.GetImage(); (Bitmap&)ii = iig.GetIconImage(); #endif if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } if( verbose ) { std::cout << "success: " << outfilename << std::endl; std::cout << "ref=" << refmd5 << std::endl; std::cout << "md5=" << digest << std::endl; } if( !refmd5 ) { std::cerr << " missing md5= {\"" << digest << "\" , \"" << name << "\" }," << std::endl; return 1; } if( strcmp( refmd5, digest) ) { std::cerr << "Problem with : " << name << " " << refmd5 << " vs " << digest << std::endl; return 1; } } else { assert( refmd5 == 0 ); std::cerr << "Could not generate Icon for: " << filename << std::endl; return 1; } return 0; } } int TestIconImageGenerator2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestIconImageGenerate2(argv[0],filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestIconImageGenerate2(argv[0], filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestIconImageGenerator3.cxx000066400000000000000000000447061412732066400300550ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmFileMetaInformation.h" #include "gdcmTesting.h" #include "gdcmByteSwap.h" #include "gdcmIconImageGenerator.h" static const char * const iconimagearray3[][2] = { {"18de6726bc64732057fb57ffa6f63482" , "SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs.acr" }, {"e751b44ccfa55354e08ba04fade91687" , "gdcm-MR-SIEMENS-16-2.acr" }, {"a7ff57ec105e45b72d91ac750953befc" , "test.acr" }, {"464cc3218d282f534326f2323264f8ca" , "MR-MONO2-12-an2.acr" }, {"e23711964e5606b7cf8a9bf194e46a27" , "CT-MONO2-12-lomb-an2.acr" }, {"fc5db4e2e7fca8445342b83799ff16d8" , "LIBIDO-8-ACR_NEMA-Lena_128_128.acr" }, {"50ab781df5647feb681c6c24a1245d0d" , "gdcm-ACR-LibIDO.acr" }, {"ce338fe6899778aacfc28414f2d9498b" , "libido1.0-vol.acr" }, {"7acad6aa0274edfc797492128c2dd2bf" , "SIEMENS_CSA2.dcm" }, {"231db66c0b1a60cab9e8e879711ebc16" , "gdcm-JPEG-LossLessThoravision.dcm" }, {"353a62510cef13ce252f5e3a7ece54dc" , "XA-MONO2-8-12x-catheter.dcm" }, {"b992b65f8beed6adc2224541be339d68" , "gdcm-MR-PHILIPS-16-Multi-Seq.dcm" }, {"a9b91f5b18b1d7078ce597ec611a2c43" , "PHILIPS_GDCM12xBug.dcm" }, {"a0b26e46dc8920167cd6b9b5ed57d8df" , "MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm" }, {"eff839f187f2dfa07204b6550a96d4b6" , "D_CLUNIE_CT1_J2KI.dcm" }, {"4f94be538667ad8d39abf42ee604bf7d" , "rle16sti.dcm" }, {"7acd654cb0176b7b6f1982245593e8e6" , "3E768EB7.dcm" }, {"6fe22e9a0983a07c5b1dde43373c36f3" , "D_CLUNIE_MR2_JPLY.dcm" }, {"f17269f3d2447ed0b523b41a98b03129" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm" }, {"311524ab5c9cb14812256c561c78e573" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm" }, {"35619ea28ae211558d526e63429d5cbb" , "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm" }, {"a189258582a49855ae002d381016d02f" , "LEADTOOLS_FLOWERS-16-MONO2-Uncompressed.dcm" }, {"b9291915007d8fae5c2a67a691c33236" , "D_CLUNIE_MR3_JPLY.dcm" }, {"e2100ad66e70220df75ee60e9f69acdd" , "D_CLUNIE_VL2_RLE.dcm" }, {"985dd349809ef7d63feeb511a63b05d1" , "OsirixFake16BitsStoredFakeSpacing.dcm" }, {"046896d4baee6361e58217bd0a046162" , "GE_RHAPSODE-16-MONO2-JPEG-Fragments.dcm" }, {"54307dbe02cab5ee23efa8360eb0cbd5" , "MR_SIEMENS_forceLoad29-1010_29-1020.dcm" }, {"7e8bfa2560d883b45a0f868a81daac4d" , "fffc0000UN.dcm" }, {"00f59e7e071f7fdf7d2e700df06a1d6b" , "LIBIDO-24-ACR_NEMA-Rectangle.dcm" }, {"c1d31936337a3c65bba3edf67466a139" , "IM-0001-0066.CommandTag00.dcm" }, {"6d95a1855031ac5401ec2c8ba7ff8b18" , "D_CLUNIE_NM1_JPLY.dcm" }, {"046896d4baee6361e58217bd0a046162" , "D_CLUNIE_CT1_J2KR.dcm" }, {"a439396c24ce353e108bd0308e8a80e2" , "TheralysGDCM120Bug.dcm" }, {"e5155757353de1ad5c2b68c88fd34901" , "SIEMENS_MAGNETOM-12-MONO2-VRUN.dcm" }, {"338d45d1ee3ec0202cdfa637c491669a" , "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm" }, {"5f90ef6a0621c658cfd2ae1f2bba351e" , "ALOKA_SSD-8-MONO2-RLE-SQ.dcm" }, {"c881ef5c9a6a643ac7e890279ffc010f" , "GE_GENESIS-16-MONO2-WrongLengthItem.dcm" }, {"13d97ddbcff7e14a89a6e5c337611881" , "US-RGB-8-esopecho.dcm" }, {"0464a1b7160b097ea33f25865cce8fc9" , "D_CLUNIE_MR4_RLE.dcm" }, {"3703d1695f0c02fa7a5cbe7142c8fc6f" , "D_CLUNIE_MR2_JPLL.dcm" }, {"f0b59feaa0499a68038b627f2df71d93" , "SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm" }, {"a189258582a49855ae002d381016d02f" , "LEADTOOLS_FLOWERS-16-MONO2-JpegLossless.dcm" }, {"dcce1e8c7b5cdc15d315807b4ec2d34b" , "CT-MONO2-16-ankle.dcm" }, {"75c3cb93e002c788acc7eff4a93e2b5b" , "TOSHIBA_J2K_SIZ1_PixRep0.dcm" }, {"4e8c0f3b4154f54ae04756d61fb1c2f5" , "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm" }, {"fc5db4e2e7fca8445342b83799ff16d8" , "simpleImageWithIcon.dcm" }, {"1c582b9b521c398ed55776bcd615af3e" , "CR-MONO1-10-chest.dcm" }, {"046896d4baee6361e58217bd0a046162" , "D_CLUNIE_CT1_RLE.dcm" }, {"f00d34662aeb08d14bcaf230053bfd5f" , "D_CLUNIE_NM1_JPLL.dcm" }, {"39faf30ee66e8c70dd2e772fcdbb1078" , "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm" }, {"ce338fe6899778aacfc28414f2d9498b" , "NM-MONO2-16-13x-heart.dcm" }, {"5a4101fb01068d1b48afcacc9bca9f7e" , "US-IRAD-NoPreambleStartWith0003.dcm" }, {"3c18da99b3d3d53399d622aabdd96b64" , "MR-MONO2-16-head.dcm" }, {"4e8c0f3b4154f54ae04756d61fb1c2f5" , "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm" }, {"443c20bd84b91d30037ad1da84568c6e" , "MAROTECH_CT_JP2Lossy.dcm" }, {"488e407541a6c353f0540049ba36d61c" , "05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm" }, {"50057b97e7c585ba31144867cd40c363" , "US-PAL-8-10x-echo.dcm" }, {"e189b6b3a44a8d929f654105f9842707" , "MR-SIEMENS-DICOM-WithOverlays.dcm" }, {"139f2ba3c6f578f883125d090163e730" , "D_CLUNIE_MR1_JPLL.dcm" }, {"046896d4baee6361e58217bd0a046162" , "D_CLUNIE_CT1_JPLL.dcm" }, {"bbc89a7b6e41d668f22b6e612cfb13e7" , "AMIInvalidPrivateDefinedLengthSQasUN.dcm" }, {"35619ea28ae211558d526e63429d5cbb" , "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm" }, {"8b2eca7c4d23a79a9e6d9437bff66d67" , "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm" }, {"4ef7021ed6522a730693574a37759940" , "D_CLUNIE_SC1_JPLY.dcm" }, {"ce338fe6899778aacfc28414f2d9498b" , "gdcm-MR-PHILIPS-16-NonSquarePixels.dcm" }, {"b92f9dcf1acd6dd998539d22a5296f74" , "SIEMENS-MR-RGB-16Bits.dcm" }, {"07c92897d0cbd052060f8a9d13a6386a" , "US-IRAD-NoPreambleStartWith0005.dcm" }, {"64b228a9c05e2f1b4a6371abf1ac7e21" , "PICKER-16-MONO2-Nested_icon.dcm" }, {"41d6ffef9d2edbad51c94a8d476bb1ab" , "gdcm-JPEG-Extended.dcm" }, {"5d8f3a1415c53f2b8b6ea459b4f3f6c1" , "D_CLUNIE_US1_RLE.dcm" }, {"d0dcc34bad0aa031269d3101fa044e4b" , "D_CLUNIE_RG2_JPLY.dcm" }, {"4a56065c6ab80bc0a32b39a143e58d5c" , "PHILIPS_Brilliance_ExtraBytesInOverlay.dcm" }, {"2888e58bfe4d11b2671f2cd6a35f9b7c" , "MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm" }, {"00d2f91bbf1f1d5c248f98220f85a860" , "TG18-CH-2k-01.dcm" }, {"a189258582a49855ae002d381016d02f" , "LEADTOOLS_FLOWERS-16-MONO2-RLE.dcm" }, {"703d03c5fb65c9493775c7ed6a9aa001" , "OT-PAL-8-face.dcm" }, {"12919f48891b07e74651efd5a2a52676" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm" }, {"94e0346dc7594b042c6e67a0f8ebfa71" , "SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm" }, {"06148d96de1833da4518b6d97fdd4165" , "GDCMJ2K_TextGBR.dcm" }, {"59f3e40cbdd708b43dd818a953bd5ca0" , "MR16BitsAllocated_8BitsStored.dcm" }, {"fe4ee9d2fc8f068c7e5b61e8dc90811d" , "GE_GENESIS-16-MONO2-Uncompressed-UnusualVR.dcm" }, {"046896d4baee6361e58217bd0a046162" , "D_CLUNIE_CT1_JLSL.dcm" }, {"9f04eeafdcd85d84cc6f8edad761e3a1" , "ELSCINT1_JP2vsJ2K.dcm" }, {"531bfd1059c6396e9da4c9a4f5436e86" , "D_CLUNIE_XA1_JPLL.dcm" }, {"12ea2d93daec9fda8f26666dbaf21c30" , "SIEMENS_Sonata-12-MONO2-SQ.dcm" }, {"acf0d5ea13eb09415ffe3ec2d0800590" , "JPEGDefinedLengthSequenceOfFragments.dcm" }, {"6b9e6ee648acb3ca92814bc6642d0b96" , "PHILIPS_GDCM12xBug2.dcm" }, {"ce338fe6899778aacfc28414f2d9498b" , "ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm" }, {"941378c3e000b34264342b1d46ce6dce" , "D_CLUNIE_RG2_JPLL.dcm" }, {"9efc87377ac56dd01476046bbbd5bf7b" , "FUJI-10-MONO1-ACR_NEMA_2.dcm" }, {"99b4254ecb0b4075b8005b775b02bea1" , "D_CLUNIE_MR1_JPLY.dcm" }, {"531bfd1059c6396e9da4c9a4f5436e86" , "D_CLUNIE_XA1_RLE.dcm" }, {"8058ebaf622a0108d12a387c75de5aae" , "BugGDCM2_UndefItemWrongVL.dcm" }, {"e751b44ccfa55354e08ba04fade91687" , "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm" }, {"c860f1795d0be70b310f5b653b34f06f" , "JDDICOM_Sample2.dcm" }, {"5fcd3432874ea0f3cbc59a317534a0b0" , "TOSHIBA_MRT150-16-MONO2-ACR_NEMA_2.dcm" }, {"ce338fe6899778aacfc28414f2d9498b" , "DCMTK_JPEGExt_12Bits.dcm" }, {"7abf9227edf8f7106198b320c5daa538" , "US-MONO2-8-8x-execho.dcm" }, {"16fff764b95a60d83e4b6781da292cea" , "UnexpectedSequenceDelimiterInFixedLengthSequence.dcm" }, {"d600407a5f79393f294518be3bba7fed" , "ACUSON-24-YBR_FULL-RLE-b.dcm" }, {"eb1c07547d036c3f778700cfef1ad24c" , "gdcm-US-ALOKA-16.dcm" }, {"9805da917d916632cf3a22b6b9140bce" , "DX_J2K_0Padding.dcm" }, {"4d6a3590ae425105315a0995f8a7da41" , "D_CLUNIE_CT2_RLE.dcm" }, {"f1b14732b392da7ea5fba9b47225945c" , "D_CLUNIE_RG1_JPLL.dcm" }, {"86362d24addeeaaa8b1b4e485ff49ea7" , "D_CLUNIE_VL3_RLE.dcm" }, {"5d590fa042089bbd62f771e403ad3068" , "NM_Kakadu44_SOTmarkerincons.dcm" }, {"790f684146906a7f0b9d8c3838066579" , "CT-SIEMENS-Icone-With-PaletteColor.dcm" }, {"336e557af65d34ae7cb5dcc18582b12b" , "GE_DLX-8-MONO2-PrivateSyntax.dcm" }, {"848ee1315da8c58064a685e70378dae5" , "CT_16b_signed-UsedBits13.dcm" }, {"29db994be059e339ab881eb760878a54" , "D_CLUNIE_RG3_JPLY.dcm" }, {"d1bd49bdf8ce55652f7802f8f8820f97" , "DX_GE_FALCON_SNOWY-VOI.dcm" }, {"7dcb5cdba4bfc242dbcc0d275ad14970" , "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm" }, {"d66fddd6bc26af655f500cd37de3b135" , "CT-MONO2-16-brain.dcm" }, {"351d2c3befec588fe7798ae0884908e7" , "D_CLUNIE_VL4_RLE.dcm" }, {"97e8c927ca201a2f932b5b3ecc6453e5" , "D_CLUNIE_MR3_RLE.dcm" }, {"bbb1be6461a9c8b1a0fd507b5c19ec20" , "undefined_length_un_vr.dcm" }, {"ae8fe4406652ca3e6b93d2ade029d94e" , "CT-MONO2-16-ort.dcm" }, {"ab976b85e44c2332d826067520f6c2e6" , "05148044-mr-siemens-avanto-syngo.dcm" }, {"8a9c001007c43fff520fada2b75e1e72" , "GE_LOGIQBook-8-RGB-HugePreview.dcm" }, {"3808ac31fbf6ede5d0a1ca47ff604f8d" , "RadBWLossLess.dcm" }, {"0ceae99a40ae6ee2ad5cf1fa06a86820" , "KODAK-12-MONO1-Odd_Terminated_Sequence.dcm" }, {"e8dd9e61c1eb37c4ab54003ef9fd2842" , "CT-MONO2-16-chest.dcm" }, {"63808ab2b6faa36b6914e01907358eb7" , "PhilipsInteraSeqTermInvLen.dcm" }, {"3a1f7960887aa18084a6f7347926c8b5" , "D_CLUNIE_MR4_JPLY.dcm" }, {"91c2703f4a5dec2d780539c29b450d47" , "D_CLUNIE_RG3_JPLL.dcm" }, {"96f9a1224838a0695b3d2cc8b0b26b97" , "MR_Philips-Intera_BreaksNOSHADOW.dcm" }, {"c75d2a8866ccdb2a96f7634bcc81adef" , "GE_CT_With_Private_compressed-icon.dcm" }, {"4c600037ef23dbf2da360db9f8d7e28b" , "TOSHIBA_J2K_OpenJPEGv2Regression.dcm" }, {"6c004779f7e43673883f04742aae9541" , "D_CLUNIE_CT1_JLSN.dcm" }, {"e5155757353de1ad5c2b68c88fd34901" , "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm" }, {"afccf775abd15a6c053c7f134b204762" , "00191113.dcm" }, {"9670e5f8c163087d75cc4044356359c3" , "MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm" }, {"ac1abc22d5d52b21c74c9f34b6178cd1" , "SignedShortLosslessBug.dcm" }, {"0f5efe869ef6b9846707e89fbef18f2c" , "GE_DLX-8-MONO2-Multiframe.dcm" }, {"6763fff05fa5b5dc2b842a40573b18a3" , "PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm" }, {"10151c9ee27d40cfd58f0d79e693f38e" , "LJPEG_BuginGDCM12.dcm" }, {"d1779fd58242dc231aa021cbd9687b04" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm" }, {"91c2703f4a5dec2d780539c29b450d47" , "D_CLUNIE_RG3_RLE.dcm" }, {"ab0815dcb84bd5a42972134ea9c0493d" , "CT-SIEMENS-MissingPixelDataInIconSQ.dcm" }, {"3703d1695f0c02fa7a5cbe7142c8fc6f" , "MR-MONO2-12-shoulder.dcm" }, {"5a898d46c28350c4f55b9915b9001852" , "LEADTOOLS_FLOWERS-24-RGB-Uncompressed.dcm" }, {"654e4af3861f475c16bf498efc5df861" , "PICKER-16-MONO2-No_DicomV3_Preamble.dcm" }, {"885cd1e48a980257534d3c88380ec259" , "SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm" }, {"dbe025b7a22b829898b6eb2b35580171" , "CT-MONO2-8-abdo.dcm" }, {"97e8c927ca201a2f932b5b3ecc6453e5" , "D_CLUNIE_MR3_JPLL.dcm" }, {"5cffc4c262df7534f4008aa49aaef3ae" , "D_CLUNIE_VL6_RLE.dcm" }, {"a189258582a49855ae002d381016d02f" , "LEADTOOLS_FLOWERS-8-MONO2-RLE.dcm" }, {"051d73b41bb387005e1dbcc3af7253b3" , "PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm" }, {"e20e59c88037bbe676e8c67bee2a9540" , "TOSHIBA_J2K_SIZ0_PixRep1.dcm" }, {"ca3a2e9d6d2813df183a9fd9c9d2e9a1" , "SIEMENS-12-Jpeg_Process_2_4-Lossy-a.dcm" }, {"f073eb11257017c6422158aa5cfb372c" , "gdcm-JPEG-LossLess3a.dcm" }, {"9b2dfd69af52cd8625fe1faa73f51493" , "D_CLUNIE_XA1_JPLY.dcm" }, {"f1b14732b392da7ea5fba9b47225945c" , "D_CLUNIE_RG1_RLE.dcm" }, {"8b86324f5b7b88f06dffe975a06f1544" , "US-RGB-8-epicard.dcm" }, {"5a478d37f436a6687a07fd43aaef79ee" , "GE_MR_0025xx1bProtocolDataBlock.dcm" }, {"43d75fbe29085c5760d6ff4c083a9726" , "rle16loo.dcm" }, {"cbebb7b25f11a1c39194566b194e84e5" , "DMCPACS_ExplicitImplicit_BogusIOP.dcm" }, {"4d6a3590ae425105315a0995f8a7da41" , "D_CLUNIE_CT2_JPLL.dcm" }, {"c860f1795d0be70b310f5b653b34f06f" , "JDDICOM_Sample2-dcmdjpeg.dcm" }, {"35619ea28ae211558d526e63429d5cbb" , "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm" }, {"2f2f0a482fc0c1b8d99db02a57122b22" , "KODAK_CompressedIcon.dcm" }, {"1b28808b244d86f4b6ec626b4d538680" , "ACUSON-24-YBR_FULL-RLE.dcm" }, {"3703d1695f0c02fa7a5cbe7142c8fc6f" , "D_CLUNIE_MR2_RLE.dcm" }, {"22a67114d4ae8e036665e1a1a508ca8d" , "JPEG_LossyYBR.dcm" }, {"3646c27f6fb60d66ab916934d331d550" , "012345.002.050.dcm" }, {"941378c3e000b34264342b1d46ce6dce" , "D_CLUNIE_RG2_RLE.dcm" }, {"0ba3c7de165ffe7fb43733f25de2fdf1" , "MR_Philips_Intera_PrivateSequenceImplicitVR.dcm" }, {"e344c9a95328db382caf8a7b86c91992" , "SIEMENS_ImageLocationUN.dcm" }, {"35619ea28ae211558d526e63429d5cbb" , "PHILIPS_Intera-16-MONO2-Uncompress.dcm" }, {"42aa4fa1ac9421f083927baaf7230cf6" , "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm" }, {"5a898d46c28350c4f55b9915b9001852" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossless.dcm" }, {"00e15542d31e48490442eb4c336103e8" , "US-GE-4AICL142.dcm" }, {"2bacf42b57e957883e35451c5ff26f50" , "D_CLUNIE_SC1_RLE.dcm" }, {"0464a1b7160b097ea33f25865cce8fc9" , "D_CLUNIE_MR4_JPLL.dcm" }, {"9b801c57776e5f7c4b45f2c6c47795d8" , "MR-Brucker-CineTagging-NonSquarePixels.dcm" }, {"373a42fc21d411b4c060d2cf2a4e85f4" , "MR-MONO2-8-16x-heart.dcm" }, {"6e9d26218dce3f54b41efbe442a2154b" , "LEADTOOLS_FLOWERS-8-MONO2-JpegLossy.dcm" }, {"ccda9f1170c12f443d83990e9777ca8e" , "GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm" }, {"f00d34662aeb08d14bcaf230053bfd5f" , "D_CLUNIE_NM1_RLE.dcm" }, {"a2b00a80955b1f368dcff51264b9e2e7" , "D_CLUNIE_VL1_RLE.dcm" }, {"f00ef30b32dd57515c2c0d5c921c6ee1" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm" }, {"0638ee027ccf94fd7ecca641b6fd402c" , "DermaColorLossLess.dcm" }, {"5340e9111251343c6a932992241b299e" , "OT-MONO2-8-a7.dcm" }, {"139f2ba3c6f578f883125d090163e730" , "D_CLUNIE_MR1_RLE.dcm" }, {"a189258582a49855ae002d381016d02f" , "LEADTOOLS_FLOWERS-8-MONO2-Uncompressed.dcm" }, {"afccf775abd15a6c053c7f134b204762" , "00191113.dcm" }, {"f4f35d60b3cc18aaa6d8d92f0cd3708a" , "NM-PAL-16-PixRep1.dcm" }, {"843f097f2161014cd1b11be5413eace9" , "MEDILABInvalidCP246_EVRLESQasUN.dcm" }, {"c103d405ae61aa4ed148e17157e5afc1" , "JPEGInvalidSecondFrag.dcm" }, {"c103d405ae61aa4ed148e17157e5afc1" , "Osirix10vs8BitsStored.dcm" }, {"c103d405ae61aa4ed148e17157e5afc1" , "Bug_Siemens_PrivateIconNoItem.dcm" }, {"c103d405ae61aa4ed148e17157e5afc1" , "HardcopyColor_YBR_RCT_J2K_PC1.dcm" }, {"c103d405ae61aa4ed148e17157e5afc1" , "PET-GE-dicomwrite-PixelDataSQUNv2.dcm" }, // sentinel { 0, 0 } }; namespace gdcm { int TestIconImageGenerate3(const char *subdir, const char* filename, bool verbose = false) { ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const FileMetaInformation &header = reader.GetFile().GetHeader(); MediaStorage ms = header.GetMediaStorage(); bool isImage = MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } else { // not an image give up... std::cerr << "Problem with: " << filename << " but that's ok" << std::endl; return 0; } } // Create directory first: std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); IconImageGenerator iig; iig.SetPixmap( reader.GetImage() ); iig.ConvertRGBToPaletteColor( false ); const unsigned int idims[2] = { 128, 128}; //const unsigned int idims[2] = { 552,421 }; iig.SetOutputDimensions( idims ); bool b = iig.Generate(); gdcm::Filename fn( filename ); const char *name = fn.GetName(); unsigned int i = 0; const char *p = iconimagearray3[i][1]; while( p != 0 ) { if( strcmp( name, p ) == 0 ) { break; } ++i; p = iconimagearray3[i][1]; } const char *refmd5 = iconimagearray3[i][0]; if( b ) { const gdcm::IconImage &icon = iig.GetIconImage(); if( verbose ) icon.Print( std::cout ); unsigned long len = icon.GetBufferLength(); std::vector< char > vbuffer; vbuffer.resize( len ); char *buffer = &vbuffer[0]; bool res2 = icon.GetBuffer(buffer); if( !res2 ) { std::cerr << "res2 failure:" << filename << std::endl; return 1; } char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); Image & img = reader.GetImage(); img.SetIconImage( iig.GetIconImage() ); ImageWriter writer; writer.SetFileName( outfilename.c_str() ); #if 1 writer.SetImage( img ); #else Image &ii = writer.GetImage(); (Bitmap&)ii = iig.GetIconImage(); #endif if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } if( verbose ) { std::cout << "success: " << outfilename << std::endl; std::cout << "ref=" << refmd5 << std::endl; std::cout << "md5=" << digest << std::endl; } if( !refmd5 ) { std::cerr << " missing md5= {\"" << digest << "\" , \"" << name << "\" }," << std::endl; return 1; } if( strcmp( refmd5, digest) ) { std::cerr << "Problem with : " << name << " " << refmd5 << " vs " << digest << std::endl; return 1; } } else { assert( refmd5 == 0 ); std::cerr << "Could not generate Icon for: " << filename << std::endl; return 1; } return 0; } } int TestIconImageGenerator3(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestIconImageGenerate3(argv[0],filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestIconImageGenerate3(argv[0], filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestIconImageGenerator4.cxx000066400000000000000000000462621412732066400300550ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmFileMetaInformation.h" #include "gdcmTesting.h" #include "gdcmByteSwap.h" #include "gdcmIconImageGenerator.h" #include "gdcmAttribute.h" #include "gdcmStringFilter.h" static const char * const iconimagearray4[][2] = { {"7e097b4a57af6a823bd692e37b131b1c" , "SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs.acr" }, {"7f2638cea652bf3452ada158d2ea67c4" , "gdcm-MR-SIEMENS-16-2.acr" }, {"da0922a02f8e763ec878089617e0bc4c" , "test.acr" }, {"e75ee90f23db1952a593393cdfaaf99f" , "MR-MONO2-12-an2.acr" }, {"c9c46afd186531850af9576cf54c800b" , "CT-MONO2-12-lomb-an2.acr" }, {"feb10d9a28e5166a3baf9ec6ef4f460a" , "LIBIDO-8-ACR_NEMA-Lena_128_128.acr" }, {"f9d8a0796ebf5a6aabddb4e133d09770" , "gdcm-ACR-LibIDO.acr" }, {"a1bce65e11c5fd2e26f7b38ebfdd1c53" , "libido1.0-vol.acr" }, {"9edea7caea2b85aad952d35c64f1e092" , "SIEMENS_CSA2.dcm" }, {"011d1f2abd9e27a2dc5d013bd4848104" , "gdcm-JPEG-LossLessThoravision.dcm" }, {"ddb7e67d119eb2ce14731cd9007e36cc" , "XA-MONO2-8-12x-catheter.dcm" }, {"1041bae356da40d2113210ff2adef923" , "gdcm-MR-PHILIPS-16-Multi-Seq.dcm" }, {"a3a6b3bf75ccdc91f82effc60d005688" , "PHILIPS_GDCM12xBug.dcm" }, {"a247e2ca32279956079c9a87403bd157" , "MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm" }, {"b29a7fe847f942e3afdda5ddf23c03c3" , "D_CLUNIE_CT1_J2KI.dcm" }, {"3f7cae9b920adb3ca4a96ace2c0c91d7" , "rle16sti.dcm" }, {"f706f740496e445ee59141b15f3baeb4" , "3E768EB7.dcm" }, {"b38c113fffa4925f6f06a928b357f6a1" , "D_CLUNIE_MR2_JPLY.dcm" }, {"c3d3a218fcec778476090bce4c8b3201" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm" }, {"882a7327bab05d88571dcf29f902adf3" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm" }, {"1f4ae64fab8745e6affb72721ffdfaec" , "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm" }, {"af193ff3143f299826d55e00696b3218" , "LEADTOOLS_FLOWERS-16-MONO2-Uncompressed.dcm" }, {"f6a020bb9aab2e59a289064b2add00ec" , "D_CLUNIE_MR3_JPLY.dcm" }, {"e8b529fbe615b4c540318695913d02e7" , "D_CLUNIE_VL2_RLE.dcm" }, {"8393213bd2c340a8cbd639f45a6b497e" , "OsirixFake16BitsStoredFakeSpacing.dcm" }, {"c50f0f97e1e36a4387620634e7a9b152" , "GE_RHAPSODE-16-MONO2-JPEG-Fragments.dcm" }, {"c265bf6c3bf4417987ff81b92ca4ca6c" , "MR_SIEMENS_forceLoad29-1010_29-1020.dcm" }, {"fa7da45d1a8eb16b092880ceff5a50e5" , "fffc0000UN.dcm" }, {"796594769ee3570292de36fdb4509df1" , "LIBIDO-24-ACR_NEMA-Rectangle.dcm" }, {"32b10fd4f13cfb4d74e1145f166e9dae" , "IM-0001-0066.CommandTag00.dcm" }, {"619f8c1650962cddf7695e39f43e8c49" , "D_CLUNIE_NM1_JPLY.dcm" }, {"c50f0f97e1e36a4387620634e7a9b152" , "D_CLUNIE_CT1_J2KR.dcm" }, {"30a530ea4df623cbec31f752637e234b" , "TheralysGDCM120Bug.dcm" }, {"3120b59e3635a912c6a60897f734b2ff" , "SIEMENS_MAGNETOM-12-MONO2-VRUN.dcm" }, {"5bdb2335ceb2dac83c2248d6ff8e0a49" , "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm" }, {"30ff6655c5eb98ad34cd20836418a5a7" , "ALOKA_SSD-8-MONO2-RLE-SQ.dcm" }, {"992e4ef2b01f9d79514d7ab22c354be9" , "GE_GENESIS-16-MONO2-WrongLengthItem.dcm" }, {"d4669bd89971c1affd311c7d1d8b20c7" , "US-RGB-8-esopecho.dcm" }, {"85124dd05ab0567aecaf896373f780da" , "D_CLUNIE_MR4_RLE.dcm" }, {"07964ed19883cb96460d1407795f4306" , "D_CLUNIE_MR2_JPLL.dcm" }, {"096547f2834609ae4dbc115169806fc4" , "SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm" }, {"af193ff3143f299826d55e00696b3218" , "LEADTOOLS_FLOWERS-16-MONO2-JpegLossless.dcm" }, {"da7002947725a950c3226cd23aa8d718" , "CT-MONO2-16-ankle.dcm" }, {"1a27a48d4efe2999b83bc89d3003d05c" , "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm" }, {"feb10d9a28e5166a3baf9ec6ef4f460a" , "simpleImageWithIcon.dcm" }, {"aeb28d2cfb5376e2bb1ac4aac0b4807c" , "CR-MONO1-10-chest.dcm" }, {"c50f0f97e1e36a4387620634e7a9b152" , "D_CLUNIE_CT1_RLE.dcm" }, {"4d469f85f51b3b81bdf38ebba23a68e7" , "D_CLUNIE_NM1_JPLL.dcm" }, {"f7f066f0597791fcc147603ab5af6387" , "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm" }, {"abe1950da247d18196fe5bea54cb26f1" , "NM-MONO2-16-13x-heart.dcm" }, {"6bd67bbd6e3e65808db8598fe0913f86" , "US-IRAD-NoPreambleStartWith0003.dcm" }, {"99672e03104c9176595bc0002cd8edf8" , "MR-MONO2-16-head.dcm" }, {"1a27a48d4efe2999b83bc89d3003d05c" , "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm" }, {"af8491953e762c12feb93a80a1575edf" , "MAROTECH_CT_JP2Lossy.dcm" }, {"932281859be22ffae33a2669b34cc2e6" , "05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm" }, {"fb5402472ee00639ef8dc1b09692c299" , "US-PAL-8-10x-echo.dcm" }, {"038acb53133733a9f2c54528b8029511" , "MR-SIEMENS-DICOM-WithOverlays.dcm" }, {"890d0a5afdbf77398d857b523f86e83a" , "D_CLUNIE_MR1_JPLL.dcm" }, {"c50f0f97e1e36a4387620634e7a9b152" , "D_CLUNIE_CT1_JPLL.dcm" }, {"7897424399822301bdbedbcaf34c7c84" , "AMIInvalidPrivateDefinedLengthSQasUN.dcm" }, {"1f4ae64fab8745e6affb72721ffdfaec" , "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm" }, {"3443eba48f11dd9aadb4632c8c896b39" , "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm" }, {"b72e483ad977e18b8016c7cc916c4bbd" , "D_CLUNIE_SC1_JPLY.dcm" }, {"582df1a47c5992cc4f37496dab8c5130" , "gdcm-MR-PHILIPS-16-NonSquarePixels.dcm" }, {"8a5d13f6c85b2eebc1c02432d729cd45" , "SIEMENS-MR-RGB-16Bits.dcm" }, {"aacd6f6257e068cf53cdec5c7e172513" , "US-IRAD-NoPreambleStartWith0005.dcm" }, {"6a9ecd676ce47b0fda111a804b58b054" , "PICKER-16-MONO2-Nested_icon.dcm" }, {"9b720fd0aa079bc2f3f9545bd0e207c6" , "gdcm-JPEG-Extended.dcm" }, {"c790d0a462907135c1991f10a4846f98" , "D_CLUNIE_US1_RLE.dcm" }, {"4689c053642dcee7a2a9d0475c1b6528" , "D_CLUNIE_RG2_JPLY.dcm" }, {"b3b8a60e7b7b20c029eec1d5006e2b9c" , "PHILIPS_Brilliance_ExtraBytesInOverlay.dcm" }, {"91533007e5e07353012dea33149d920f" , "MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm" }, {"c8902cc14f285f2687866f60e45c7d86" , "TG18-CH-2k-01.dcm" }, {"af193ff3143f299826d55e00696b3218" , "LEADTOOLS_FLOWERS-16-MONO2-RLE.dcm" }, {"27daf49ec13f58db1d800fc58378852e" , "OT-PAL-8-face.dcm" }, {"07fef244d4e14358d453c144770b2a55" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm" }, {"ad96e04c3c50d463cccdfca68b49b071" , "SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm" }, {"620f0b67a91f7f74151bc5be745b7110" , "GDCMJ2K_TextGBR.dcm" }, {"d1f5dfac9c3213f548df6a1f9e86acd0" , "MR16BitsAllocated_8BitsStored.dcm" }, {"cc2aaa869f08908e1f37ccdd314841ab" , "GE_GENESIS-16-MONO2-Uncompressed-UnusualVR.dcm" }, {"c50f0f97e1e36a4387620634e7a9b152" , "D_CLUNIE_CT1_JLSL.dcm" }, {"719505e71eafd643fa2e114acc83496f" , "ELSCINT1_JP2vsJ2K.dcm" }, {"7132fec8839d9c8b26cba4a4f17000da" , "D_CLUNIE_XA1_JPLL.dcm" }, {"cdf5908902fb63e321b224fae86a4128" , "SIEMENS_Sonata-12-MONO2-SQ.dcm" }, {"bc1774acbf5c025aa3b57184213cc98c" , "JPEGDefinedLengthSequenceOfFragments.dcm" }, {"e9faa2ce59db8563d7abe50432f91351" , "PHILIPS_GDCM12xBug2.dcm" }, {"620f0b67a91f7f74151bc5be745b7110" , "ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm" }, {"52d0b90aa78a20cbff6b0beb3bd2c2b3" , "D_CLUNIE_RG2_JPLL.dcm" }, {"50dd1ae0bf918a9144b50229fa04f8e0" , "FUJI-10-MONO1-ACR_NEMA_2.dcm" }, {"d7e55bf3c6eb7a627823b532bcac7e16" , "D_CLUNIE_MR1_JPLY.dcm" }, {"7132fec8839d9c8b26cba4a4f17000da" , "D_CLUNIE_XA1_RLE.dcm" }, {"f48ea76ff11ca6ca4958df9c186422f4" , "BugGDCM2_UndefItemWrongVL.dcm" }, {"7f2638cea652bf3452ada158d2ea67c4" , "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm" }, {"477d801b27ef3cb21a8685cedbc9b12e" , "JDDICOM_Sample2.dcm" }, {"cae77b420f407118f288c14eeb81e11f" , "TOSHIBA_MRT150-16-MONO2-ACR_NEMA_2.dcm" }, {"524014ef866b31e3fd2e33a6148d31bb" , "DCMTK_JPEGExt_12Bits.dcm" }, {"84ea2f46ad98332a06875da922709007" , "US-MONO2-8-8x-execho.dcm" }, {"19d6f17c8a0b2cd04049828dcb304046" , "UnexpectedSequenceDelimiterInFixedLengthSequence.dcm" }, {"bee28068ae9edef69fef792583b3e20f" , "ACUSON-24-YBR_FULL-RLE-b.dcm" }, {"b171f7581c9cf15b2d32cfd62e9b6038" , "gdcm-US-ALOKA-16.dcm" }, {"80be78c9365f6a1604191dd703c84ac5" , "DX_J2K_0Padding.dcm" }, {"a9a72d44b888fb4f1f727af88109cfb3" , "D_CLUNIE_CT2_RLE.dcm" }, {"151376fcac2fbd55c3b5c5a155e16d26" , "D_CLUNIE_RG1_JPLL.dcm" }, {"e0a3fd5917c5a13a16981e1d0346af4d" , "D_CLUNIE_VL3_RLE.dcm" }, {"28ea47a62e1f2ca9d7dcd10ef868701d" , "NM_Kakadu44_SOTmarkerincons.dcm" }, {"e95cec3c8078cea91b287e45d751cf78" , "CT-SIEMENS-Icone-With-PaletteColor.dcm" }, {"eacd1cabeaf78554804ca627344cba91" , "GE_DLX-8-MONO2-PrivateSyntax.dcm" }, {"8f40712ff8e4a7691be144d884546a17" , "CT_16b_signed-UsedBits13.dcm" }, {"da9fb19d564fa01e4633df5c105f5a58" , "D_CLUNIE_RG3_JPLY.dcm" }, {"6510f44ff1dd8daf9b49100fd2c81d85" , "DX_GE_FALCON_SNOWY-VOI.dcm" }, {"5a15bd50c589c9611636dc7813493c03" , "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm" }, {"4948235091edc01603344f79a29835e1" , "CT-MONO2-16-brain.dcm" }, {"c2de60330cda14759a117b937a7e5a95" , "D_CLUNIE_VL4_RLE.dcm" }, {"599ac7bd3a573451f3cd53494ace8cdf" , "D_CLUNIE_MR3_RLE.dcm" }, {"72f55d5cf022e983783185195b77d0e6" , "undefined_length_un_vr.dcm" }, {"a8e2e35044384f31afc1dcf9163154ff" , "CT-MONO2-16-ort.dcm" }, {"0fefcf91a55062f1cb20945b3f726eda" , "05148044-mr-siemens-avanto-syngo.dcm" }, {"5d6aaab5766479ec6e27de4eaa4a6438" , "GE_LOGIQBook-8-RGB-HugePreview.dcm" }, {"acad4e43da617035315bcddc4bbb96bd" , "RadBWLossLess.dcm" }, {"b69e23b6479de4d9c3b4ed51aa748f73" , "KODAK-12-MONO1-Odd_Terminated_Sequence.dcm" }, {"e8458a5483e72cced4d46f93eed1699e" , "CT-MONO2-16-chest.dcm" }, {"728a698e308f7863ba3d103b80dffc45" , "PhilipsInteraSeqTermInvLen.dcm" }, {"35144f65c704edf2d69abc40405c3ea7" , "D_CLUNIE_MR4_JPLY.dcm" }, {"904b38f362b86f626ea7d89eed455709" , "D_CLUNIE_RG3_JPLL.dcm" }, {"707e26b0fa27f670c35ca5cc2bf3eda2" , "MR_Philips-Intera_BreaksNOSHADOW.dcm" }, {"04b97df84da7a126be30993cf9cff942" , "GE_CT_With_Private_compressed-icon.dcm" }, {"04cb0299587f38ba369e1fdcbf07dc25" , "D_CLUNIE_CT1_JLSN.dcm" }, {"3120b59e3635a912c6a60897f734b2ff" , "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm" }, {"cee47e57f6b1aaace74bb813e33a74eb" , "00191113.dcm" }, {"99ba02caa6813cafd254f97fb8377f60" , "MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm" }, {"46c2e032f2858831691a184aa6cdb0da" , "SignedShortLosslessBug.dcm" }, {"2b306840879792f3509e1c1ccedee81d" , "GE_DLX-8-MONO2-Multiframe.dcm" }, {"fde7dc022ec854a98ffdc2190ceef424" , "PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm" }, {"f4b5fc5cc1440b865f1a99b85b170ecd" , "LJPEG_BuginGDCM12.dcm" }, {"ba2717c0d839213e788a74cccf37f1d4" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm" }, {"904b38f362b86f626ea7d89eed455709" , "D_CLUNIE_RG3_RLE.dcm" }, {"5e51e64ee21c2f643c13257e054c2990" , "CT-SIEMENS-MissingPixelDataInIconSQ.dcm" }, {"07964ed19883cb96460d1407795f4306" , "MR-MONO2-12-shoulder.dcm" }, {"0b818ac3983d76cfdc535a46058a1a53" , "LEADTOOLS_FLOWERS-24-RGB-Uncompressed.dcm" }, {"7f7aaee92f20ffcd64bebf8ce105bf5d" , "PICKER-16-MONO2-No_DicomV3_Preamble.dcm" }, {"fde3b9c4853c597383fab1050b491202" , "SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm" }, {"ba0654f3e7aae75bca8fc24705ddb78a" , "CT-MONO2-8-abdo.dcm" }, {"599ac7bd3a573451f3cd53494ace8cdf" , "D_CLUNIE_MR3_JPLL.dcm" }, {"03f25fb3e6e8ae53b9565553e2026a66" , "D_CLUNIE_VL6_RLE.dcm" }, {"af193ff3143f299826d55e00696b3218" , "LEADTOOLS_FLOWERS-8-MONO2-RLE.dcm" }, {"d46afca30969faa05583e87b0f6e5211" , "PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm" }, {"5885ade0feaaf967f5a1c22724c10d02" , "SIEMENS-12-Jpeg_Process_2_4-Lossy-a.dcm" }, {"13758e32fe34c17b897efcbd26e7e03b" , "gdcm-JPEG-LossLess3a.dcm" }, {"1e61c6d50ae3ef3ac0550277f166bd1c" , "D_CLUNIE_XA1_JPLY.dcm" }, {"151376fcac2fbd55c3b5c5a155e16d26" , "D_CLUNIE_RG1_RLE.dcm" }, {"e77b93eb953f2a21fa75d257da0514fb" , "US-RGB-8-epicard.dcm" }, {"a101ddd933114bcc0145d047d74f41c9" , "GE_MR_0025xx1bProtocolDataBlock.dcm" }, {"b9f48f54e75b7f1994cfe1a7152d9ab5" , "rle16loo.dcm" }, {"cc61470afd2b80014749abbb5bd9109d" , "DMCPACS_ExplicitImplicit_BogusIOP.dcm" }, {"a9a72d44b888fb4f1f727af88109cfb3" , "D_CLUNIE_CT2_JPLL.dcm" }, {"477d801b27ef3cb21a8685cedbc9b12e" , "JDDICOM_Sample2-dcmdjpeg.dcm" }, {"1f4ae64fab8745e6affb72721ffdfaec" , "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm" }, {"323c2919ea590363dd6eb4105a2566a7" , "KODAK_CompressedIcon.dcm" }, {"486199008daf27f167efee9469fffd52" , "ACUSON-24-YBR_FULL-RLE.dcm" }, {"07964ed19883cb96460d1407795f4306" , "D_CLUNIE_MR2_RLE.dcm" }, {"b53c440c32a7bd20d24cc1997bd7c9e6" , "JPEG_LossyYBR.dcm" }, {"2b098d933de8c90b317619658f698cc5" , "012345.002.050.dcm" }, {"52d0b90aa78a20cbff6b0beb3bd2c2b3" , "D_CLUNIE_RG2_RLE.dcm" }, {"e44869a1044b611e08a9f1396432a44b" , "MR_Philips_Intera_PrivateSequenceImplicitVR.dcm" }, {"f92d6349e1d80bbdba34a9e1b84eb737" , "SIEMENS_ImageLocationUN.dcm" }, {"1f4ae64fab8745e6affb72721ffdfaec" , "PHILIPS_Intera-16-MONO2-Uncompress.dcm" }, {"0e82ac528c72a2dd69fa1b52e5370d82" , "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm" }, {"0b818ac3983d76cfdc535a46058a1a53" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossless.dcm" }, {"91b4da2ca9fd378ca404580c84c62984" , "US-GE-4AICL142.dcm" }, {"2ff486489d600e0ab5f8c829960c516f" , "D_CLUNIE_SC1_RLE.dcm" }, {"85124dd05ab0567aecaf896373f780da" , "D_CLUNIE_MR4_JPLL.dcm" }, {"ece67fa0c8a99f8147b26081252cd0a5" , "MR-Brucker-CineTagging-NonSquarePixels.dcm" }, {"bdf48b10871ac0b3c14587eaba9ca998" , "MR-MONO2-8-16x-heart.dcm" }, {"0c65a403a0a24957e523bb29e84c31ef" , "LEADTOOLS_FLOWERS-8-MONO2-JpegLossy.dcm" }, {"f92a60ad3cbc2783db57cac5f800a9c0" , "GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm" }, {"4d469f85f51b3b81bdf38ebba23a68e7" , "D_CLUNIE_NM1_RLE.dcm" }, {"20e2f6cc2b60ae26adfdd3b3ee0e1915" , "D_CLUNIE_VL1_RLE.dcm" }, {"84462b24809f4e9d151c7c27004f7922" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm" }, {"620f0b67a91f7f74151bc5be745b7110" , "DermaColorLossLess.dcm" }, {"72e203ca5756f4491d84d8240c82a59b" , "OT-MONO2-8-a7.dcm" }, {"890d0a5afdbf77398d857b523f86e83a" , "D_CLUNIE_MR1_RLE.dcm" }, {"af193ff3143f299826d55e00696b3218" , "LEADTOOLS_FLOWERS-8-MONO2-Uncompressed.dcm" }, {"cee47e57f6b1aaace74bb813e33a74eb" , "00191113.dcm" }, {"07b6f4e2fba920d28e2f29dbb037b640" , "TOSHIBA_J2K_SIZ1_PixRep0.dcm" }, {"93f60acbb450c62992a1db09a6c19c05" , "TOSHIBA_J2K_OpenJPEGv2Regression.dcm" }, {"fa02ad71bdf3e6970e18fc9a9df03a2d" , "TOSHIBA_J2K_SIZ0_PixRep1.dcm" }, {"3475cb96e0308cb84502be1c1531b588" , "NM-PAL-16-PixRep1.dcm" }, {"2ec6d7c60d6786665cff2b7a31aaeedf" , "MEDILABInvalidCP246_EVRLESQasUN.dcm" }, {"560881eca73809ac358aa14733ee64af" , "JPEGInvalidSecondFrag.dcm" }, {"7c70c2aaacf9a4206cbe2191fa4d2041" , "SC16BitsAllocated_8BitsStoredJ2K.dcm" }, {"da0922a02f8e763ec878089617e0bc4c" , "SC16BitsAllocated_8BitsStoredJPEG.dcm" }, {"da0922a02f8e763ec878089617e0bc4c" , "Osirix10vs8BitsStored.dcm" }, {"da0922a02f8e763ec878089617e0bc4c" , "Bug_Siemens_PrivateIconNoItem.dcm" }, {"da0922a02f8e763ec878089617e0bc4c" , "HardcopyColor_YBR_RCT_J2K_PC1.dcm" }, {"da0922a02f8e763ec878089617e0bc4c" , "PET-GE-dicomwrite-PixelDataSQUNv2.dcm" }, // sentinel { 0, 0 } }; namespace gdcm { int TestIconImageGenerate4(const char *subdir, const char* filename, bool verbose = false) { ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const FileMetaInformation &header = reader.GetFile().GetHeader(); MediaStorage ms = header.GetMediaStorage(); bool isImage = MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } else { // not an image give up... std::cerr << "Problem with: " << filename << " but that's ok" << std::endl; return 0; } } // Create directory first: std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); IconImageGenerator iig; iig.SetPixmap( reader.GetImage() ); iig.AutoPixelMinMax(true); gdcm::StringFilter sf; sf.SetFile( reader.GetFile() ); /* const DataSet & ds = reader.GetFile().GetDataSet(); if( ds.FindDataElement( gdcm::Tag(0x0028,0x0120) ) && !ds.GetDataElement(gdcm::Tag(0x0028,0x0120)).IsEmpty() ) { // gdcm::Attribute<0x28,0x120> at; iig.SetOutsideValuePixel( -2000 ); } */ std::string strval = sf.ToString(gdcm::Tag(0x0028,0x0120)); double val; std::istringstream is; is.str( strval ); if( is >> val ) { iig.SetOutsideValuePixel( val ); assert( !strval.empty() ); } const unsigned int idims[2] = { 64, 64 }; //const unsigned int idims[2] = { 600,430 }; iig.SetOutputDimensions( idims ); bool b = iig.Generate(); gdcm::Filename fn( filename ); const char *name = fn.GetName(); unsigned int i = 0; const char *p = iconimagearray4[i][1]; while( p != 0 ) { if( strcmp( name, p ) == 0 ) { break; } ++i; p = iconimagearray4[i][1]; } const char *refmd5 = iconimagearray4[i][0]; if( b ) { const gdcm::IconImage &icon = iig.GetIconImage(); if( verbose ) icon.Print( std::cout ); unsigned long len = icon.GetBufferLength(); std::vector< char > vbuffer; vbuffer.resize( len ); char *buffer = &vbuffer[0]; bool res2 = icon.GetBuffer(buffer); if( !res2 ) { std::cerr << "res2 failure:" << filename << std::endl; return 1; } char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); Image & img = reader.GetImage(); img.SetIconImage( iig.GetIconImage() ); ImageWriter writer; writer.SetFileName( outfilename.c_str() ); #if 1 writer.SetImage( img ); #else Image &ii = writer.GetImage(); (Bitmap&)ii = iig.GetIconImage(); #endif if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } if( verbose ) { std::cout << "success: " << outfilename << std::endl; std::cout << "ref=" << refmd5 << std::endl; std::cout << "md5=" << digest << std::endl; } if( !refmd5 ) { std::cerr << " missing md5= {\"" << digest << "\" , \"" << name << "\" }," << std::endl; return 1; } if( strcmp( refmd5, digest) ) { std::cerr << "Problem with : " << name << " " << refmd5 << " vs " << digest << std::endl; return 1; } } else { assert( refmd5 == 0 ); std::cerr << "Could not generate Icon for: " << filename << std::endl; return 1; } return 0; } } int TestIconImageGenerator4(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestIconImageGenerate4(argv[0],filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestIconImageGenerate4(argv[0], filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImage.cxx000066400000000000000000000034401412732066400253000ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImage.h" #include "gdcmImageReader.h" int TestImage(int, char *[]) { gdcm::Image img; gdcm::ImageReader reader; const gdcm::Image &img2 = reader.GetImage(); img2.Print(std::cout);//just to avoid the warning of img2 being unused #if 0 { gdcm::Image img3 = reader.GetImage(); } gdcm::SmartPointer img4 = const_cast(&img2); gdcm::ImageReader r; //r.SetFileName( "/home/mathieu/Creatis/gdcmData/test.acr" ); r.SetFileName( "/home/mathieu/Creatis/gdcmData/DermaColorLossLess.dcm" ); r.Read(); //std::vector< gdcm::SmartPointer > images; std::vector< gdcm::Image > images; { const gdcm::Image &ref = r.GetImage(); images.push_back( ref ); ref.Print(std::cout); gdcm::Image copy1 = ref; copy1.Print(std::cout); gdcm::SmartPointer copy2; copy2 = r.GetImage(); copy2->Print(std::cout); gdcm::ImageReader r2; r2.SetFileName( "/home/mathieu/Creatis/gdcmData/012345.002.050.dcm" ); r2.Read(); std::cout << " ------------------ " << std::endl; images.push_back( r2.GetImage() ); ref.Print(std::cout); copy1.Print(std::cout); copy2->Print(std::cout); } images[0].Print( std::cout ); images[1].Print( std::cout ); #endif return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageApplyLookupTable.cxx000066400000000000000000000113711412732066400304520ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageApplyLookupTable.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmImage.h" #include "gdcmFilename.h" static const char * const lutarray[][2] = { { "d613050ca0f9c924fb5282d140281fcc", "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm" }, { "d613050ca0f9c924fb5282d140281fcc", "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm" }, { "7b8d795eaf99f1fff176c43f9cf76bfb", "NM-PAL-16-PixRep1.dcm" }, { "47715f0a5d5089268bbef6f83251a8ad", "OT-PAL-8-face.dcm" }, { "c70309b66045140b8e08c11aa319c0ab", "US-PAL-8-10x-echo.dcm" }, { "c370ca934dc910eb4b629a2fa8650b67", "gdcm-US-ALOKA-16.dcm" }, { "49ca8ad45fa7f24b0406a5a03ba8aff6", "rle16loo.dcm" }, { "964ea27345a7004325896d34b257f289", "rle16sti.dcm" }, // sentinel { nullptr, nullptr } }; int TestImageApplyLookupTableFunc(const char *filename, bool verbose = false) { gdcm::ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const gdcm::FileMetaInformation &header = reader.GetFile().GetHeader(); gdcm::MediaStorage ms = header.GetMediaStorage(); bool isImage = gdcm::MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( gdcm::Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cout << "Could not read: " << filename << std::endl; return 1; } return 0; } const gdcm::Image &image = reader.GetImage(); const gdcm::PhotometricInterpretation &pi = image.GetPhotometricInterpretation(); if( pi != gdcm::PhotometricInterpretation::PALETTE_COLOR ) { // yeah well not much I can do here... if( verbose ) { std::cout << "PhotometricInterpretation is: " << pi << " cannot apply LUT then..." << std::endl; } return 0; } gdcm::ImageApplyLookupTable lutfilt; lutfilt.SetInput( image ); bool b = lutfilt.Apply(); if( !b ) { std::cerr << "Could not apply lut: " << filename << std::endl; return 1; } // Create directory first: const char subdir[] = "TestImageApplyLookupTable"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = gdcm::Testing::GetTempFilename( filename, subdir ); gdcm::ImageWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); writer.SetImage( lutfilt.GetOutput() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // Let's read that file back in ! gdcm::ImageReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Failed to read back: " << outfilename << std::endl; return 1; } const gdcm::Image &img = reader2.GetImage(); unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; img.GetBuffer(buffer); gdcm::Filename fn( filename ); const char *name = fn.GetName(); unsigned int i = 0; const char *p = lutarray[i][1]; while( p != nullptr ) { if( strcmp( name, p ) == 0 ) { break; } ++i; p = lutarray[i][1]; } const char *ref = lutarray[i][0]; char digest[33] = {}; gdcm::Testing::ComputeMD5(buffer, len, digest); int res = 0; if( !ref ) { std::cerr << "Missing LUT-applied MD5 for image from: " << filename << std::endl; res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } delete[] buffer; return res; } int TestImageApplyLookupTable(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestImageApplyLookupTableFunc(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestImageApplyLookupTableFunc( filename ); ++i; } return r; } TestImageChangePhotometricInterpretation.cxx000066400000000000000000000070071412732066400335000ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/*========================================================================= 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 "gdcmImageChangePhotometricInterpretation.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmTesting.h" #include "gdcmSystem.h" namespace gdcm { PhotometricInterpretation InvertPI(PhotometricInterpretation pi) { assert( pi == PhotometricInterpretation::MONOCHROME1 || pi == PhotometricInterpretation::MONOCHROME2 ); if( pi == PhotometricInterpretation::MONOCHROME1 ) { return PhotometricInterpretation::MONOCHROME2; } return PhotometricInterpretation::MONOCHROME1; } } int TestImageChangePhotometricInterpretationFunc(const char *filename, bool verbose = false) { gdcm::ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const gdcm::FileMetaInformation &header = reader.GetFile().GetHeader(); gdcm::MediaStorage ms = header.GetMediaStorage(); bool isImage = gdcm::MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( gdcm::Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cout << "Could not read: " << filename << std::endl; return 1; } return 0; } const gdcm::Image &image = reader.GetImage(); //unsigned int pc = image.GetPlanarConfiguration(); gdcm::PhotometricInterpretation pi = image.GetPhotometricInterpretation(); if( pi != gdcm::PhotometricInterpretation::MONOCHROME1 && pi != gdcm::PhotometricInterpretation::MONOCHROME2 ) { // nothing to do: return 0; } gdcm::PhotometricInterpretation invert_pi = gdcm::InvertPI(pi); gdcm::ImageChangePhotometricInterpretation pcfilt; pcfilt.SetInput( image ); pcfilt.SetPhotometricInterpretation( invert_pi ); bool b = pcfilt.Change(); if( !b ) { std::cerr << "Could not apply pcfilt: " << filename << std::endl; return 1; } // Create directory first: const char subdir[] = "TestImageChangePhotometricInterpretation"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = gdcm::Testing::GetTempFilename( filename, subdir ); gdcm::ImageWriter writer; writer.SetFileName( outfilename.c_str() ); //writer.SetFile( reader.GetFile() ); // increase test goal writer.SetImage( pcfilt.GetOutput() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } return 0; } int TestImageChangePhotometricInterpretation(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestImageChangePhotometricInterpretationFunc(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestImageChangePhotometricInterpretationFunc( filename ); ++i; } return r; } TestImageChangePhotometricInterpretation2.cxx000066400000000000000000000060531412732066400335620ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/*========================================================================= 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 "gdcmImageChangePhotometricInterpretation.h" #include #include template double diff(T rgb1[3], T rgb2[2]) { double sum = 0; for(int i = 0; i < 3; ++i) sum += fabs((double)(rgb1[i] - rgb2[i])); return sum < 1e-3 ? 0 : sum; //return sum; } int TestImageChangePhotometricInterpretation2(int argc, char *argv[]) { //typedef float Type; //typedef double Type; //typedef int Type; typedef unsigned char Type; double sdiff = 0; double max = 0; int nerrors = 0; int res = 0; Type error[3] = {}; Type error2[3] = {}; Type yerror[3] = {}; for(int r = 0; r < 256; ++r) for(int g = 0; g < 256; ++g) for(int b = 0; b < 256; ++b) { Type rgb[3]; Type ybr[3] = {}; Type rgb2[3] = {}; rgb[0] = r; rgb[1] = g; rgb[1] = 128; rgb[2] = b; rgb[2] = 128; // convert rgb 2 ybr: //gdcm::ImageChangePhotometricInterpretation::RGB2YBR(ybr,rgb); gdcm::ImageChangePhotometricInterpretation::YBR2RGB(ybr,rgb); // convert back: //gdcm::ImageChangePhotometricInterpretation::YBR2RGB(rgb2,ybr); gdcm::ImageChangePhotometricInterpretation::RGB2YBR(rgb2,ybr); if( memcmp(rgb,rgb2,3*sizeof(Type)) != 0 ) { //std::cerr << "Problem with R,G,B=" << r << "," << g << "," << b << //" instead of " << (int)rgb2[0] << "," << (int)rgb2[1] << "," << (int)rgb2[2] << std::endl; //std::cerr << "diff:" << diff(rgb,rgb2) << std::endl; double d = diff(rgb,rgb2); sdiff += d; if( d > max ) { error2[0] = rgb2[0]; error2[1] = rgb2[1]; error2[2] = rgb2[2]; error[0] = rgb[0]; error[1] = rgb[1]; error[2] = rgb[2]; yerror[0] = ybr[0]; yerror[1] = ybr[1]; yerror[2] = ybr[2]; } max = std::max(d,max); res = 1; ++nerrors; } } std::cerr << "nerrors=" << nerrors << std::endl; std::cerr << "sdiff=" << sdiff<< std::endl; std::cerr << "max=" << max << std::endl; std::cerr << "max error=" << (double)error[0] << "," << (double)error[1] << "," << (double)error[2] << std::endl; std::cerr << "max error2=" << (double)error2[0] << "," << (double)error2[1] << "," << (double)error2[2] << std::endl; std::cerr << "max yerror=" << (double)yerror[0] << "," << (double)yerror[1] << "," << (double)yerror[2] << std::endl; return res; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageChangePlanarConfiguration.cxx000066400000000000000000000133431412732066400322770ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageChangePlanarConfiguration.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmTesting.h" #include "gdcmFilename.h" #include "gdcmByteSwap.h" #include "gdcmSystem.h" int TestImageChangePlanarConfigurationFunc(const char *filename, bool verbose = false) { (void)verbose; gdcm::ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const gdcm::FileMetaInformation &header = reader.GetFile().GetHeader(); gdcm::MediaStorage ms = header.GetMediaStorage(); bool isImage = gdcm::MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( gdcm::Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cout << "Could not read: " << filename << std::endl; return 1; } return 0; } const gdcm::Image &image = reader.GetImage(); unsigned int oldpc = image.GetPlanarConfiguration(); assert( oldpc == 1 || oldpc == 0 ); gdcm::ImageChangePlanarConfiguration pcfilt; pcfilt.SetPlanarConfiguration( !oldpc ); pcfilt.SetInput( image ); bool b = pcfilt.Change(); if( !b ) { unsigned short ba = reader.GetImage().GetPixelFormat().GetBitsAllocated(); if( ba == 12 ) { std::cerr << "fail to change, but that's ok" << std::endl; return 0; } std::cerr << "Could not apply pcfilt: " << filename << std::endl; return 1; } // Create directory first: const char subdir[] = "TestImageChangePlanarConfiguration"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = gdcm::Testing::GetTempFilename( filename, subdir ); gdcm::ImageWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); // important writer.SetImage( pcfilt.GetOutput() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // Let's read that file back in ! gdcm::ImageReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Could not even reread our generated file : " << outfilename << std::endl; return 1; } // Check that after decompression we still find the same thing: int res = 0; const gdcm::Image &img = reader2.GetImage(); //unsigned int newpc = img.GetPlanarConfiguration(); //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; bool res2; { gdcm::ImageChangePlanarConfiguration icpc; icpc.SetPlanarConfiguration( oldpc ); icpc.SetInput( img ); if( !icpc.Change() ) { return 1; } res2 = icpc.GetOutput().GetBuffer(buffer); } if( !res2 ) { std::cerr << "could not get buffer: " << outfilename << std::endl; return 1; } // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: #ifdef GDCM_WORDS_BIGENDIAN if( img.GetPixelFormat().GetBitsAllocated() == 16 ) { assert( !(len % 2) ); assert( img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 || img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ); gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem( (unsigned short*)buffer, gdcm::SwapCode::LittleEndian, len/2); } #endif const char *ref = gdcm::Testing::GetMD5FromFile(filename); // FIXME: PC=1 gdcm::Filename fn( filename ); if( strcmp(fn.GetName(), "ACUSON-24-YBR_FULL-RLE-b.dcm" ) == 0) ref = "2d7a28cae6c3b3183284d1b4ae08307f"; if( strcmp(fn.GetName(), "ACUSON-24-YBR_FULL-RLE.dcm" ) == 0) ref = "429f31f0b70bd515b3feeda5dea5eac0"; char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( !ref ) { // new regression image needs a md5 sum std::cerr << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } if(res) { std::cerr << "problem with: " << outfilename << std::endl; } if( verbose ) { std::cout << "file was written in: " << outfilename << std::endl; } delete[] buffer; return 0; } int TestImageChangePlanarConfiguration(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestImageChangePlanarConfigurationFunc(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestImageChangePlanarConfigurationFunc( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageChangeTransferSyntax1.cxx000066400000000000000000000133461412732066400314110ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageChangeTransferSyntax.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmFileMetaInformation.h" #include "gdcmTesting.h" #include "gdcmByteSwap.h" #include "gdcmImageChangePlanarConfiguration.h" namespace gdcm { int TestImageChangeTransferSyntaxJPEG(const char *filename, bool verbose = false) { ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const FileMetaInformation &header = reader.GetFile().GetHeader(); MediaStorage ms = header.GetMediaStorage(); bool isImage = MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } else { // not an image give up... std::cerr << "Problem with: " << filename << " but that's ok" << std::endl; return 0; } } const gdcm::Image &image = reader.GetImage(); int pc = image.GetPlanarConfiguration(); gdcm::ImageChangeTransferSyntax change; change.SetTransferSyntax( gdcm::TransferSyntax::JPEGLosslessProcess14_1 ); change.SetInput( image ); bool b = change.Change(); if( !b ) { unsigned short ba = reader.GetImage().GetPixelFormat().GetBitsAllocated(); if( ba == 12 ) { std::cerr << "fail to change, but that's ok" << std::endl; return 0; } std::cerr << "Could not change the Transfer Syntax: " << filename << std::endl; return 1; } // Create directory first: const char subdir[] = "TestImageChangeTransferSyntax"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); ImageWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); // increase test goal writer.SetImage( change.GetOutput() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // Let's read that file back in ! ImageReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Could not even reread our generated file : " << outfilename << std::endl; return 1; } // Check that after decompression we still find the same thing: int res = 0; gdcm::Image img = reader2.GetImage(); // When recompressing: US-RGB-8-epicard.dcm, make sure to compute the md5 using the // same original Planar Configuration... if( (int)img.GetPlanarConfiguration() != pc ) { gdcm::ImageChangePlanarConfiguration icpc; icpc.SetInput( reader2.GetImage() ); icpc.SetPlanarConfiguration( pc ); icpc.Change(); img = icpc.GetOutput(); } //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; bool res2 = img.GetBuffer(buffer); if( !res2 ) { std::cerr << "could not get buffer: " << outfilename << std::endl; return 1; } // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: #ifdef GDCM_WORDS_BIGENDIAN if( img.GetPixelFormat().GetBitsAllocated() == 16 ) { assert( !(len % 2) ); assert( img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 || img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ); gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem( (unsigned short*)buffer, gdcm::SwapCode::LittleEndian, len/2); } #endif const char *ref = gdcm::Testing::GetMD5FromFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( !ref ) { // new regression image needs a md5 sum std::cerr << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } if(res) { std::cerr << "problem with: " << outfilename << std::endl; } if( verbose ) { std::cout << "file was written in: " << outfilename << std::endl; } delete[] buffer; return res; } } // end namespace gdcm int TestImageChangeTransferSyntax1(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestImageChangeTransferSyntaxJPEG(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestImageChangeTransferSyntaxJPEG( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageChangeTransferSyntax2.cxx000066400000000000000000000133741412732066400314130ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageChangeTransferSyntax.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmFileMetaInformation.h" #include "gdcmTesting.h" #include "gdcmByteSwap.h" #include "gdcmImageChangePlanarConfiguration.h" namespace gdcm { int TestImageChangeTransferSyntaxJ2K(const char *filename, bool verbose = false) { ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const FileMetaInformation &header = reader.GetFile().GetHeader(); MediaStorage ms = header.GetMediaStorage(); bool isImage = MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } else { // not an image give up... std::cerr << "Problem with: " << filename << " but that's ok" << std::endl; return 0; } } const gdcm::Image &image = reader.GetImage(); int pc = image.GetPlanarConfiguration(); gdcm::ImageChangeTransferSyntax change; change.SetTransferSyntax( gdcm::TransferSyntax::JPEG2000Lossless ); change.SetInput( image ); bool b = change.Change(); if( !b ) { unsigned short ba = reader.GetImage().GetPixelFormat().GetBitsAllocated(); if( ba == 12 ) { std::cerr << "fail to change, but that's ok: " << filename << std::endl; return 0; } std::cerr << "Could not change the Transfer Syntax: " << filename << std::endl; return 1; } // Create directory first: const char subdir[] = "TestImageChangeTransferSyntax2"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); ImageWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); // important for palette + multiframes writer.SetImage( change.GetOutput() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // Let's read that file back in ! ImageReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Could not even reread our generated file : " << outfilename << std::endl; return 1; } // Check that after decompression we still find the same thing: int res = 0; gdcm::Image img = reader2.GetImage(); // When recompressing: US-RGB-8-epicard.dcm, make sure to compute the md5 using the // same original Planar Configuration... if( (int)img.GetPlanarConfiguration() != pc ) { gdcm::ImageChangePlanarConfiguration icpc; icpc.SetInput( reader2.GetImage() ); icpc.SetPlanarConfiguration( pc ); icpc.Change(); img = icpc.GetOutput(); } //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; bool res2 = img.GetBuffer(buffer); if( !res2 ) { std::cerr << "could not get buffer: " << outfilename << std::endl; return 1; } // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: #ifdef GDCM_WORDS_BIGENDIAN if( img.GetPixelFormat().GetBitsAllocated() == 16 ) { assert( !(len % 2) ); assert( img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 || img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ); gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem( (unsigned short*)buffer, gdcm::SwapCode::LittleEndian, len/2); } #endif const char *ref = gdcm::Testing::GetMD5FromFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( !ref ) { // new regression image needs a md5 sum std::cerr << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } if(res) { std::cerr << "problem with: " << outfilename << std::endl; } if( verbose ) { std::cout << "file was written in: " << outfilename << std::endl; } delete[] buffer; return res; } } // end namespace gdcm int TestImageChangeTransferSyntax2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestImageChangeTransferSyntaxJ2K(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestImageChangeTransferSyntaxJ2K( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageChangeTransferSyntax3.cxx000066400000000000000000000133301412732066400314040ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageChangeTransferSyntax.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmFileMetaInformation.h" #include "gdcmTesting.h" #include "gdcmByteSwap.h" #include "gdcmImageChangePlanarConfiguration.h" namespace gdcm { int TestImageChangeTransferSyntaxRLE(const char *filename, bool verbose = false) { ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const FileMetaInformation &header = reader.GetFile().GetHeader(); MediaStorage ms = header.GetMediaStorage(); bool isImage = MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } else { // not an image give up... std::cerr << "Problem with: " << filename << " but that's ok" << std::endl; return 0; } } const gdcm::Image &image = reader.GetImage(); unsigned int oldpc = image.GetPlanarConfiguration(); gdcm::ImageChangeTransferSyntax change; change.SetTransferSyntax( gdcm::TransferSyntax::RLELossless ); change.SetInput( image ); bool b = change.Change(); if( !b ) { unsigned short ba = reader.GetImage().GetPixelFormat().GetBitsAllocated(); if( ba == 12 ) { std::cerr << "fail to change, but that's ok" << std::endl; return 0; } std::cerr << "Could not change the Transfer Syntax: " << filename << std::endl; return 1; } // Create directory first: const char subdir[] = "TestImageChangeTransferSyntax3"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); ImageWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); // important for palette + mf writer.SetImage( change.GetOutput() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // Let's read that file back in ! ImageReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Could not even reread our generated file : " << outfilename << std::endl; return 1; } // Check that after decompression we still find the same thing: int res = 0; const gdcm::Image &img = reader2.GetImage(); unsigned int newpc = img.GetPlanarConfiguration(); //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; bool res2; if( oldpc != newpc ) { gdcm::ImageChangePlanarConfiguration icpc; icpc.SetPlanarConfiguration( oldpc ); icpc.SetInput( img ); if( !icpc.Change() ) { return 1; } res2 = icpc.GetOutput().GetBuffer(buffer); } else { res2 = img.GetBuffer(buffer); } if( !res2 ) { std::cerr << "could not get buffer: " << outfilename << std::endl; return 1; } // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: #ifdef GDCM_WORDS_BIGENDIAN if( img.GetPixelFormat().GetBitsAllocated() == 16 ) { assert( !(len % 2) ); assert( img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 || img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ); gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem( (unsigned short*)buffer, gdcm::SwapCode::LittleEndian, len/2); } #endif const char *ref = gdcm::Testing::GetMD5FromFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( !ref ) { // new regression image needs a md5 sum std::cerr << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } if(res) { std::cerr << "problem with: " << outfilename << std::endl; } if( verbose ) { std::cout << "file was written in: " << outfilename << std::endl; } delete[] buffer; return res; } } // end namespace gdcm int TestImageChangeTransferSyntax3(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestImageChangeTransferSyntaxRLE(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestImageChangeTransferSyntaxRLE( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageChangeTransferSyntax4.cxx000066400000000000000000000127631412732066400314160ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageChangeTransferSyntax.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmFileMetaInformation.h" #include "gdcmTesting.h" #include "gdcmByteSwap.h" namespace gdcm { int TestImageChangeTransferSyntaxRAW(const char *filename, bool verbose = false) { ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const FileMetaInformation &header = reader.GetFile().GetHeader(); MediaStorage ms = header.GetMediaStorage(); bool isImage = MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } else { // not an image give up... std::cerr << "Problem with: " << filename << " but that's ok" << std::endl; return 0; } } const gdcm::Image &image = reader.GetImage(); const TransferSyntax &ts = reader.GetFile().GetHeader().GetDataSetTransferSyntax(); gdcm::ImageChangeTransferSyntax change; if( ts == gdcm::TransferSyntax::ExplicitVRLittleEndian ) { // TODO: I think that duplicate goals of TestImageWriter2 ... //change.SetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian ); change.SetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); } else { change.SetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); } change.SetInput( image ); bool b = change.Change(); if( !b ) { std::cerr << "Could not change the Transfer Syntax: " << filename << std::endl; return 1; } // Create directory first: const char subdir[] = "TestImageChangeTransferSyntax4"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); ImageWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); // increase test goal writer.SetImage( change.GetOutput() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // Let's read that file back in ! ImageReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Could not even reread our generated file : " << outfilename << std::endl; return 1; } // Check that after decompression we still find the same thing: int res = 0; const gdcm::Image &img = reader2.GetImage(); //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; bool res2 = img.GetBuffer(buffer); if( !res2 ) { std::cerr << "could not get buffer: " << outfilename << std::endl; return 1; } // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: #ifdef GDCM_WORDS_BIGENDIAN if( img.GetPixelFormat().GetBitsAllocated() == 16 ) { assert( !(len % 2) ); assert( img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 || img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ); gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem( (unsigned short*)buffer, gdcm::SwapCode::LittleEndian, len/2); } #endif const char *ref = gdcm::Testing::GetMD5FromFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( !ref ) { // new regression image needs a md5 sum std::cerr << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } if(res) { std::cerr << "problem with: " << outfilename << std::endl; } if( verbose ) { std::cout << "file was written in: " << outfilename << std::endl; } delete[] buffer; return res; } } // end namespace gdcm int TestImageChangeTransferSyntax4(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestImageChangeTransferSyntaxRAW(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestImageChangeTransferSyntaxRAW( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageChangeTransferSyntax5.cxx000066400000000000000000000121411412732066400314050ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageChangeTransferSyntax.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmFileMetaInformation.h" #include "gdcmTesting.h" #include "gdcmByteSwap.h" namespace gdcm { int TestImageChangeTransferSyntaxJPEGLS(const char *filename, bool verbose = false) { ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const FileMetaInformation &header = reader.GetFile().GetHeader(); MediaStorage ms = header.GetMediaStorage(); bool isImage = MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } else { // not an image give up... std::cerr << "Problem with: " << filename << " but that's ok" << std::endl; return 0; } } const gdcm::Image &image = reader.GetImage(); gdcm::ImageChangeTransferSyntax change; change.SetTransferSyntax( gdcm::TransferSyntax::JPEGLSLossless ); change.SetInput( image ); bool b = change.Change(); if( !b ) { std::cerr << "Could not change the Transfer Syntax: " << filename << std::endl; return 1; } // Create directory first: const char subdir[] = "TestImageChangeTransferSyntax5"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); ImageWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); // increase test goal writer.SetImage( change.GetOutput() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // Let's read that file back in ! ImageReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Could not even reread our generated file : " << outfilename << std::endl; return 1; } // Check that after decompression we still find the same thing: int res = 0; const gdcm::Image &img = reader2.GetImage(); //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; bool res2 = img.GetBuffer(buffer); if( !res2 ) { std::cerr << "could not get buffer: " << outfilename << std::endl; return 1; } // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: #ifdef GDCM_WORDS_BIGENDIAN if( img.GetPixelFormat().GetBitsAllocated() == 16 ) { assert( !(len % 2) ); assert( img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 || img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ); gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem( (unsigned short*)buffer, gdcm::SwapCode::LittleEndian, len/2); } #endif const char *ref = gdcm::Testing::GetMD5FromFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( !ref ) { // new regression image needs a md5 sum std::cerr << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } if(res) { std::cerr << "problem with: " << outfilename << std::endl; } if( verbose ) { std::cout << "file was written in: " << outfilename << std::endl; } delete[] buffer; return res; } } // end namespace gdcm int TestImageChangeTransferSyntax5(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestImageChangeTransferSyntaxJPEGLS(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestImageChangeTransferSyntaxJPEGLS( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageChangeTransferSyntax6.cxx000066400000000000000000000122731412732066400314140ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageChangeTransferSyntax.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmFileMetaInformation.h" #include "gdcmTesting.h" #include "gdcmByteSwap.h" namespace gdcm { int TestImageChangeTransferSyntaxRAWBE(const char *filename, bool verbose = false) { ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const FileMetaInformation &header = reader.GetFile().GetHeader(); MediaStorage ms = header.GetMediaStorage(); bool isImage = MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } else { // not an image give up... std::cerr << "Problem with: " << filename << " but that's ok" << std::endl; return 0; } } const gdcm::Image &image = reader.GetImage(); //const TransferSyntax &ts = reader.GetFile().GetHeader().GetDataSetTransferSyntax(); gdcm::ImageChangeTransferSyntax change; change.SetTransferSyntax( gdcm::TransferSyntax::ExplicitVRBigEndian ); change.SetInput( image ); bool b = change.Change(); if( !b ) { std::cerr << "Could not change the Transfer Syntax: " << filename << std::endl; return 1; } // Create directory first: const char subdir[] = "TestImageChangeTransferSyntax6"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); ImageWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); // increase test goal writer.SetImage( change.GetOutput() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // Let's read that file back in ! ImageReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Could not even reread our generated file : " << outfilename << std::endl; return 1; } // Check that after decompression we still find the same thing: int res = 0; const gdcm::Image &img = reader2.GetImage(); //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; bool res2 = img.GetBuffer(buffer); if( !res2 ) { std::cerr << "could not get buffer: " << outfilename << std::endl; return 1; } // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: #ifdef GDCM_WORDS_BIGENDIAN if( img.GetPixelFormat().GetBitsAllocated() == 16 ) { assert( !(len % 2) ); assert( img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 || img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ); gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem( (unsigned short*)buffer, gdcm::SwapCode::LittleEndian, len/2); } #endif const char *ref = gdcm::Testing::GetMD5FromFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( !ref ) { // new regression image needs a md5 sum std::cerr << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } if(res) { std::cerr << "problem with: " << outfilename << std::endl; } if( verbose ) { std::cout << "file was written in: " << outfilename << std::endl; } delete[] buffer; return res; } } // end namespace gdcm int TestImageChangeTransferSyntax6(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestImageChangeTransferSyntaxRAWBE(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestImageChangeTransferSyntaxRAWBE( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageChangeTransferSyntax7.cxx000066400000000000000000000145221412732066400314140ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageChangeTransferSyntax.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmFileMetaInformation.h" #include "gdcmTesting.h" #include "gdcmByteSwap.h" namespace gdcm { int TestImageChangeTransferSyntaxIM2RAWBE(const char *filename, bool verbose = false) { ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const FileMetaInformation &header = reader.GetFile().GetHeader(); MediaStorage ms = header.GetMediaStorage(); bool isImage = MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } else { // not an image give up... std::cerr << "Problem with: " << filename << " but that's ok" << std::endl; return 0; } } const gdcm::Image &image = reader.GetImage(); gdcm::ImageChangeTransferSyntax change; change.SetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian ); change.SetInput( image ); bool b = change.Change(); if( !b ) { std::cerr << "Could not change the Transfer Syntax: " << filename << std::endl; return 1; } // Create directory first: const char subdir[] = "TestImageChangeTransferSyntax7"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); ImageWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); // increase test goal writer.SetImage( change.GetOutput() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // Let's read that file back in ! ImageReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Could not even reread our generated file : " << outfilename << std::endl; return 1; } gdcm::ImageChangeTransferSyntax change2; change2.SetTransferSyntax( gdcm::TransferSyntax::ExplicitVRBigEndian ); const gdcm::Image &image2 = reader2.GetImage(); change2.SetInput( image2 ); b = change2.Change(); if( !b ) { std::cerr << "Could not change the Transfer Syntax: " << outfilename << std::endl; return 1; } // Create directory first: const char subdir2[] = "TestImageChangeTransferSyntax7_2"; std::string tmpdir2 = Testing::GetTempDirectory( subdir2 ); if( !System::FileIsDirectory( tmpdir2.c_str() ) ) { System::MakeDirectory( tmpdir2.c_str() ); //return 1; } std::string outfilename2 = Testing::GetTempFilename( filename, subdir2 ); ImageWriter writer2; writer2.SetFileName( outfilename2.c_str() ); writer2.SetFile( reader2.GetFile() ); // increase test goal writer2.SetImage( change2.GetOutput() ); if( !writer2.Write() ) { std::cerr << "Failed to write: " << outfilename2 << std::endl; return 1; } // Let's read that file back in ! ImageReader reader3; reader3.SetFileName( outfilename2.c_str() ); if ( !reader3.Read() ) { std::cerr << "Could not even reread our generated file : " << outfilename2 << std::endl; return 1; } // Check that after decompression we still find the same thing: int res = 0; const gdcm::Image &img = reader3.GetImage(); //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; bool res2 = img.GetBuffer(buffer); if( !res2 ) { std::cerr << "could not get buffer: " << outfilename << std::endl; return 1; } // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: #ifdef GDCM_WORDS_BIGENDIAN if( img.GetPixelFormat().GetBitsAllocated() == 16 ) { assert( !(len % 2) ); assert( img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 || img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ); gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem( (unsigned short*)buffer, gdcm::SwapCode::LittleEndian, len/2); } #endif const char *ref = gdcm::Testing::GetMD5FromFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( !ref ) { // new regression image needs a md5 sum std::cerr << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } if(res) { std::cerr << "problem with: " << outfilename2 << std::endl; } if( verbose ) { std::cout << "file was written in: " << outfilename2 << std::endl; } delete[] buffer; return res; } } // end namespace gdcm int TestImageChangeTransferSyntax7(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestImageChangeTransferSyntaxIM2RAWBE(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestImageChangeTransferSyntaxIM2RAWBE( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageCodec.cxx000066400000000000000000000012511412732066400262340ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageCodec.h" int TestImageCodec(int argc, char *argv[]) { (void)argc; (void)argv; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageConverter.cxx000066400000000000000000000012611412732066400271670ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageConverter.h" int TestImageConverter(int argc, char *argv[]) { (void)argc; (void)argv; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageFragmentSplitter.cxx000066400000000000000000000100771412732066400305170ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageFragmentSplitter.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmTransferSyntax.h" #include "gdcmImage.h" #include "gdcmFilename.h" int TestImageFragmentSplitterFunc(const char *filename, bool verbose = false) { gdcm::ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const gdcm::FileMetaInformation &header = reader.GetFile().GetHeader(); gdcm::MediaStorage ms = header.GetMediaStorage(); bool isImage = gdcm::MediaStorage::IsImage( ms ); if( isImage ) { if( reader.GetFile().GetDataSet().FindDataElement( gdcm::Tag(0x7fe0,0x0010) ) ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } } return 0; } const gdcm::Image &image = reader.GetImage(); const unsigned int *dims = image.GetDimensions(); if( dims[2] != 1 ) { return 0; // nothing to do } const gdcm::File &file = reader.GetFile(); const gdcm::FileMetaInformation &header = file.GetHeader(); //gdcm::MediaStorage ms = header.GetMediaStorage(); if( header.GetDataSetTransferSyntax() == gdcm::TransferSyntax::ImplicitVRLittleEndian || header.GetDataSetTransferSyntax() == gdcm::TransferSyntax::ImplicitVRBigEndianPrivateGE || header.GetDataSetTransferSyntax() == gdcm::TransferSyntax::ExplicitVRLittleEndian || header.GetDataSetTransferSyntax() == gdcm::TransferSyntax::DeflatedExplicitVRLittleEndian || header.GetDataSetTransferSyntax() == gdcm::TransferSyntax::ExplicitVRBigEndian ) { return 0; // nothing to do } gdcm::ImageFragmentSplitter splitter; splitter.SetInput( image ); splitter.SetFragmentSizeMax( 65536 ); bool b = splitter.Split(); if( !b ) { const gdcm::DataElement &pixeldata = file.GetDataSet().GetDataElement( gdcm::Tag(0x7fe0,0x0010) ); const gdcm::SequenceOfFragments* sqf = pixeldata.GetSequenceOfFragments(); if( sqf && dims[2] == 1 ) { return 0; } gdcm::Filename fn( filename ); if( fn.GetName() == std::string("JPEGDefinedLengthSequenceOfFragments.dcm" ) ) { // JPEG Fragments are packed in a VR:OB Attribute return 0; } std::cerr << "Could not apply splitter: " << filename << std::endl; return 1; } // Create directory first: const char subdir[] = "TestImageFragmentSplitter"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = gdcm::Testing::GetTempFilename( filename, subdir ); gdcm::ImageWriter writer; writer.SetFileName( outfilename.c_str() ); //writer.SetFile( reader.GetFile() ); // increase test goal writer.SetImage( splitter.GetOutput() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } if( verbose ) std::cout << "Success to write: " << outfilename << std::endl; return 0; } int TestImageFragmentSplitter(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestImageFragmentSplitterFunc(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestImageFragmentSplitterFunc( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageHelper.cxx000066400000000000000000000132441412732066400264430ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageHelper.h" #include "gdcmMediaStorage.h" #include "gdcmDataSet.h" #include "gdcmAttribute.h" #include "gdcmDirectionCosines.h" int TestImageHelper(int, char *[]) { // gdcm::ImageHelper sh; const double pos[] = { 0,0,0, 1,1,1}; //const double answer[3] = {1,1,1}; std::vector impos(pos,pos+6); std::vector spacing; spacing.resize(3); if( !gdcm::ImageHelper::ComputeSpacingFromImagePositionPatient(impos, spacing) ) { return 1; } std::cout << spacing[0] << std::endl; std::cout << spacing[1] << std::endl; std::cout << spacing[2] << std::endl; std::vector dircos; // make it an invalid call dircos.resize(6); dircos[0] = 1; dircos[1] = 0; dircos[2] = 0; dircos[3] = 1; dircos[4] = 0; dircos[5] = 0; // Try SC { gdcm::MediaStorage ms( gdcm::MediaStorage::SecondaryCaptureImageStorage ); gdcm::DataSet ds; gdcm::DataElement de( gdcm::Tag(0x0008, 0x0016) ); const char* msstr = gdcm::MediaStorage::GetMSString(ms); de.SetByteValue( msstr, (uint32_t)strlen(msstr) ); de.SetVR( gdcm::Attribute<0x0008, 0x0016>::GetVR() ); ds.Insert( de ); // Since SC this is a no-op gdcm::ImageHelper::SetDirectionCosinesValue( ds, dircos ); // previous call removed the attribute gdcm::Tag iop(0x0020,0x0037); if( ds.FindDataElement( iop ) ) return 1; } // MR now { gdcm::MediaStorage ms( gdcm::MediaStorage::MRImageStorage ); gdcm::DataSet ds; gdcm::DataElement de( gdcm::Tag(0x0008, 0x0016) ); const char* msstr = gdcm::MediaStorage::GetMSString(ms); de.SetByteValue( msstr, (uint32_t)strlen(msstr) ); de.SetVR( gdcm::Attribute<0x0008, 0x0016>::GetVR() ); ds.Insert( de ); // Since SC this is a no-op gdcm::ImageHelper::SetDirectionCosinesValue( ds, dircos ); // previous call should not have replaced tag with default value gdcm::Tag iop(0x0020,0x0037); if( !ds.FindDataElement( iop ) ) return 1; const gdcm::DataElement &iopde = ds.GetDataElement( iop ); gdcm::Attribute<0x0020,0x0037> at; at.SetFromDataElement( iopde ); dircos.clear(); dircos.push_back( at.GetValue(0) ); dircos.push_back( at.GetValue(1) ); dircos.push_back( at.GetValue(2) ); dircos.push_back( at.GetValue(3) ); dircos.push_back( at.GetValue(4) ); dircos.push_back( at.GetValue(5) ); gdcm::DirectionCosines dc( &dircos[0] ); if (!dc.IsValid()) return 1; if ( (at.GetValue(0) != 1) || (at.GetValue(1) != 0) || (at.GetValue(2) != 0) || (at.GetValue(3) != 0) || (at.GetValue(4) != 1) || (at.GetValue(5) != 0) ) return 1; } // SC family //ms = gdcm::MediaStorage::SecondaryCaptureImageStorage; gdcm::PixelFormat pf; gdcm::PhotometricInterpretation pi = gdcm::PhotometricInterpretation::MONOCHROME2; gdcm::MediaStorage ms; ms = gdcm::ImageHelper::ComputeMediaStorageFromModality( "OT", 2 ); if( ms != gdcm::MediaStorage::SecondaryCaptureImageStorage ) { std::cerr << "SecondaryCaptureImageStorage 1" << std::endl; return 1; } ms = gdcm::ImageHelper::ComputeMediaStorageFromModality( "OT", 2, pf ); if( ms != gdcm::MediaStorage::SecondaryCaptureImageStorage ) { std::cerr << "SecondaryCaptureImageStorage 2" << std::endl; return 1; } ms = gdcm::ImageHelper::ComputeMediaStorageFromModality( "OT", 2, pf, pi ); if( ms != gdcm::MediaStorage::SecondaryCaptureImageStorage ) { std::cerr << "SecondaryCaptureImageStorage 3" << std::endl; return 1; } ms = gdcm::ImageHelper::ComputeMediaStorageFromModality( "OT", 3, pf, pi ); if( ms != gdcm::MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage ) { std::cerr << "MultiframeGrayscaleByteSecondaryCaptureImageStorage" << std::endl; return 1; } pf.SetBitsAllocated( 1 ); ms = gdcm::ImageHelper::ComputeMediaStorageFromModality( "OT", 3, pf, pi ); if( ms != gdcm::MediaStorage::MultiframeSingleBitSecondaryCaptureImageStorage ) { std::cerr << "MultiframeSingleBitSecondaryCaptureImageStorage" << std::endl; return 1; } pf.SetBitsAllocated( 16 ); ms = gdcm::ImageHelper::ComputeMediaStorageFromModality( "OT", 3, pf, pi ); if( ms != gdcm::MediaStorage::MultiframeGrayscaleWordSecondaryCaptureImageStorage ) { std::cerr << "MultiframeGrayscaleWordSecondaryCaptureImageStorage" << std::endl; return 1; } pf.SetBitsAllocated( 8 ); pf.SetSamplesPerPixel( 3 ); pi = gdcm::PhotometricInterpretation::RGB; ms = gdcm::ImageHelper::ComputeMediaStorageFromModality( "OT", 3, pf, pi ); if( ms != gdcm::MediaStorage::MultiframeTrueColorSecondaryCaptureImageStorage ) { std::cerr << "MultiframeTrueColorSecondaryCaptureImageStorage" << std::endl; return 1; } ms = gdcm::ImageHelper::ComputeMediaStorageFromModality( "OT", 3, pf, pi, -1024, 1 ); if( ms != gdcm::MediaStorage::MS_END ) { std::cerr << "MultiframeTrueColorSecondaryCaptureImageStorage 2" << std::endl; return 1; } ms = gdcm::ImageHelper::ComputeMediaStorageFromModality( "OT", 3, pf, pi, 0, 2 ); if( ms != gdcm::MediaStorage::MS_END ) { std::cerr << "MultiframeTrueColorSecondaryCaptureImageStorage 3" << std::endl; return 1; } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageHelper2.cxx000066400000000000000000000075031412732066400265260ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTesting.h" #include "gdcmImageHelper.h" #include "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmMediaStorage.h" #include "gdcmDataSet.h" #include "gdcmAttribute.h" #include "gdcmDirectionCosines.h" /* * Let's check this is easy with GDCM to handle the new * Real World Value Mapping Sequence mechanism */ int TestImageHelper2(int, char *[]) { static const char *filenames[] = { "D_CLUNIE_MR2_JPLL.dcm", "D_CLUNIE_MR2_JPLY.dcm", "D_CLUNIE_MR2_RLE.dcm", "D_CLUNIE_MR4_JPLL.dcm", "D_CLUNIE_MR4_JPLY.dcm", "D_CLUNIE_MR4_RLE.dcm", "MR-MONO2-12-shoulder.dcm", "MR_Philips-Intera_BreaksNOSHADOW.dcm", "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm", "MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm", "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm", "PHILIPS_GDCM12xBug.dcm", "PHILIPS_GDCM12xBug2.dcm", "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm", "PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm", "PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm", "PHILIPS_Intera-16-MONO2-Uncompress.dcm", "PhilipsInteraSeqTermInvLen.dcm", "SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm", "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm", "gdcm-MR-PHILIPS-16-Multi-Seq.dcm", "gdcm-MR-PHILIPS-16-NonSquarePixels.dcm", "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm", // need PVRG option }; const unsigned int nfiles = sizeof(filenames)/sizeof(*filenames); const char *root = gdcm::Testing::GetDataRoot(); if( !root || !*root ) { std::cerr << "root is not defined" << std::endl; return 1; } std::string sroot = root; sroot += "/"; gdcm::Trace::WarningOff(); for(unsigned int i = 0; i < nfiles; ++i) { const char * filename = filenames[i]; std::string fullpath = sroot + filename; gdcm::ImageHelper::SetForceRescaleInterceptSlope(true); gdcm::ImageReader r; r.SetFileName( fullpath.c_str() ); if( !r.Read() ) { return 1; } gdcm::ImageHelper::SetForceRescaleInterceptSlope(false); gdcm::Image & img = r.GetImage(); //std::cout << img.GetIntercept() << std::endl; //std::cout << img.GetSlope() << std::endl; // Create directory first: const char subdir[] = "TestImageHelper2"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = gdcm::Testing::GetTempFilename( filename, subdir ); gdcm::ImageWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( r.GetFile() ); writer.SetImage( r.GetImage() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } gdcm::ImageReader r2; r2.SetFileName( outfilename.c_str() ); if( !r2.Read() ) { return 1; } gdcm::Image & img2 = r2.GetImage(); if( img.GetIntercept() != img2.GetIntercept() ) { std::cerr << img2.GetIntercept() << std::endl; return 1; } if( img.GetSlope() != img2.GetSlope() ) { std::cout << img2.GetSlope() << std::endl; return 1; } } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageReader.cxx000066400000000000000000000115411412732066400264240ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageReader.h" #include "gdcmFileMetaInformation.h" #include "gdcmSystem.h" #include "gdcmFilename.h" #include "gdcmByteSwap.h" #include "gdcmTrace.h" #include "gdcmTesting.h" int TestImageRead(const char* filename, bool verbose = false, bool lossydump = false) { if( verbose ) std::cerr << "Reading: " << filename << std::endl; gdcm::ImageReader reader; reader.SetFileName( filename ); if ( reader.Read() ) { int res = 0; const gdcm::Image &img = reader.GetImage(); //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len = img.GetBufferLength(); if ( lossydump ) { int lossy = img.IsLossy(); std::cout << lossy << "," << filename << std::endl; } int reflossy = gdcm::Testing::GetLossyFlagFromFile( filename ); if( reflossy == -1 ) { std::cerr << "Missing lossy flag for: " << filename << std::endl; return 1; } if( img.IsLossy() != (reflossy > 0 ? true : false) )//vs10 has a stupid bool/int cast warning { std::cerr << "Inconsistency for lossy flag for: " << filename << std::endl; return 1; } char* buffer = new char[len]; bool res2 = img.GetBuffer(buffer); if( !res2 ) { std::cerr << "res2 failure: " << filename << std::endl; return 1; } // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: #ifdef GDCM_WORDS_BIGENDIAN if( img.GetPixelFormat().GetBitsAllocated() == 16 ) { assert( !(len % 2) ); // gdcm-US-ALOKA is a 16 bits image with PALETTE //assert( img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 // || img.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ); gdcm::ByteSwap::SwapRangeFromSwapCodeIntoSystem( (unsigned short*)buffer, gdcm::SwapCode::LittleEndian, len/2); } #endif const char *ref = gdcm::Testing::GetMD5FromFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( verbose ) { std::cout << "ref=" << ref << std::endl; std::cout << "md5=" << digest << std::endl; } if( !ref ) { // new regression image needs a md5 sum std::cout << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; #if 0 std::ofstream debug("/tmp/dump.gray",std::ios::binary); debug.write(buffer, len); debug.close(); //assert(0); #endif } delete[] buffer; return res; } const gdcm::FileMetaInformation &header = reader.GetFile().GetHeader(); gdcm::MediaStorage ms = header.GetMediaStorage(); bool isImage = gdcm::MediaStorage::IsImage( ms ); if( isImage ) { if( reader.GetFile().GetDataSet().FindDataElement( gdcm::Tag(0x7fe0,0x0010) ) ) { std::cerr << "Failed to read image from file: " << filename << std::endl; return 1; } else { std::cerr << "no Pixel Data Element found in the file:" << filename << std::endl; return 0; } } // else // well this is not an image, so thankfully we fail to read it std::cerr << "Could not read image(" << filename << "), since file is a: " << ms << std::endl; //assert( ms != gdcm::MediaStorage::MS_END ); return 0; } int TestImageReader(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestImageRead(filename, true); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestImageRead( filename); //r += TestImageRead( filename, false, true ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageReaderPixelSpacing.cxx000066400000000000000000000034321412732066400307330ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTesting.h" #include "gdcmImageReader.h" #include "gdcmImage.h" int TestImageReaderPixelSpacing(int argc, char *argv[]) { int ret = 0; const char *filenames[] = { "CRIMAGE", "DXIMAGE", "MGIMAGE" }; const unsigned int nfiles = sizeof(filenames)/sizeof(*filenames); const char *root = gdcm::Testing::GetPixelSpacingDataRoot(); if( !root || !*root ) { std::cerr << "root is not defined" << std::endl; return 1; } std::string sroot = root; sroot += "/DISCIMG/IMAGES/"; const double spacing_ref[] = {0.5, 0.5}; for(unsigned int i = 0; i < nfiles; ++i) { std::string filename = sroot + filenames[i]; //std::cout << filename << std::endl; gdcm::ImageReader r; r.SetFileName( filename.c_str() ); if( !r.Read() ) { ret++; std::cerr << "could not read: " << filename << std::endl; } const gdcm::Image &image = r.GetImage(); const double *spacing = image.GetSpacing(); std::cout << spacing[0] << "," << spacing[1] << "," << spacing[2] << std::endl; if( spacing[0] != spacing_ref[0] || spacing[1] != spacing_ref[1] ) { std::cerr << "Wrong spacing for: " << filename << std::endl; ++ret; } } return ret; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageReaderRandomEmpty.cxx000066400000000000000000000065671412732066400306200ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageReader.h" #include "gdcmFileMetaInformation.h" #include "gdcmSystem.h" #include "gdcmWriter.h" #include "gdcmFilename.h" #include "gdcmAnonymizer.h" #include "gdcmByteSwap.h" #include "gdcmTrace.h" #include "gdcmTesting.h" #include int TestImageReaderRandomEmptyFunc(const char *subdir, const char* filename, bool verbose = false, bool lossydump = false) { (void)lossydump; if( verbose ) std::cerr << "Reading: " << filename << std::endl; gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { return 0;//this is NOT a test of the ImageReader read function //this is a test of the anonymizer. As such, if the reader can't read this file, //that should be handled in the TestImageReader test, NOT here. //There is a lot of logic involved in testing non-standard images that should not be //duplicated here. } const gdcm::File &file = reader.GetFile(); const gdcm::DataSet &ds = file.GetDataSet(); const gdcm::FileMetaInformation &fmi = file.GetHeader(); gdcm::DataSet::ConstIterator it = ds.Begin(); // Create directory first: std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = gdcm::Testing::GetTempFilename( filename, subdir ); int ret = 0; int i = 0; for( ; it != ds.End(); ++it, ++i ) { //std::cout << "Processing Tag: " << *it << std::endl; gdcm::Writer writer; gdcm::File &filecopy = writer.GetFile(); filecopy.SetDataSet( ds ); filecopy.SetHeader( fmi ); gdcm::Anonymizer ano; ano.SetFile( filecopy ); ano.Empty( it->GetTag() ); //std::ostringstream os; //os << "/tmp/ddd"; //os << i; //os << ".dcm"; //std::string outfn = os.str(); std::string outfn = outfilename; writer.SetFile( ano.GetFile() ); writer.CheckFileMetaInformationOff(); // FIXME ? writer.SetFileName( outfn.c_str() ); if( !writer.Write() ) { std::cerr << "Could not write: " << outfn << std::endl; ret++; } gdcm::ImageReader readercopy; readercopy.SetFileName( outfn.c_str() ); readercopy.Read(); } return ret; } int TestImageReaderRandomEmpty(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestImageReaderRandomEmptyFunc(argv[0], filename, true); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestImageReaderRandomEmptyFunc( argv[0], filename); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageRegionReader1.cxx000066400000000000000000000105051412732066400276500ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageRegionReader.h" #include "gdcmImageHelper.h" #include "gdcmFilename.h" #include "gdcmBoxRegion.h" #include "gdcmTesting.h" static int TestImageRegionRead(const char* filename, bool verbose = false) { if( verbose ) std::cerr << "Reading: " << filename << std::endl; gdcm::ImageRegionReader reader; gdcm::Filename fn( filename ); // DMCPACS_ExplicitImplicit_BogusIOP.dcm is very difficult to handle since // we need to read 3 attribute to detect the "well known" bug. However the third // attribute is (b500,b700) which make ReadUpToTag(7fe0,0010) fails... if( strcmp(fn.GetName(), "DMCPACS_ExplicitImplicit_BogusIOP.dcm" ) == 0 || strcmp(fn.GetName(), "SC16BitsAllocated_8BitsStoredJ2K.dcm" ) == 0 // mismatch pixel format in JPEG 2000 vs DICOM || strcmp(fn.GetName(), "SC16BitsAllocated_8BitsStoredJPEG.dcm" ) == 0 // mismatch pixel format in JPEG vs DICOM || strcmp(fn.GetName(), "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm" ) == 0 // bogus JPEG cannot be streamed || strcmp(fn.GetName(), "US-YBR_FULL_422-EVRLE.dcm" ) == 0 // FIXME TODO // FIXME: we should be able to handle those at some point: || strcmp(fn.GetName(), "JPEGNote_empty.dcm" ) == 0 || strcmp(fn.GetName(), "JPEGNote_missing.dcm" ) == 0 || strcmp(fn.GetName(), "JPEGNote_bogus.dcm" ) == 0 ) { std::cerr << "Skipping impossible file: " << filename << std::endl; return 0; } reader.SetFileName( filename ); bool canReadInformation = reader.ReadInformation(); if (!canReadInformation) { //std::cerr << "Cannot ReadInformation: " << filename << std::endl; return 0; //unable to read tags as expected. } int res = 0; //std::cout << reader.GetFile().GetDataSet() << std::endl; std::vector dims = gdcm::ImageHelper::GetDimensionsValue(reader.GetFile()); gdcm::BoxRegion box; box.SetDomain(0, dims[0] - 1, 0, dims[1] - 1, 0, dims[2] - 1); reader.SetRegion( box ); size_t len = reader.ComputeBufferLength(); if( !len ) { std::cerr << "No length for: " << filename << std::endl; return 1; } std::vector vbuffer; vbuffer.resize( len ); char* buffer = &vbuffer[0]; bool b = reader.ReadIntoBuffer(buffer, len); if( !b ) { std::cerr << "Could not ReadIntoBuffer: " << filename << std::endl; return 1; } #if 0 std::ofstream of( "/tmp/dd.raw", std::ios::binary ); of.write( buffer, len ); of.close(); #endif const char *ref = gdcm::Testing::GetMD5FromFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); // FIXME: PC=1 if( strcmp(fn.GetName(), "ACUSON-24-YBR_FULL-RLE-b.dcm" ) == 0) ref = "2d7a28cae6c3b3183284d1b4ae08307f"; if( strcmp(fn.GetName(), "ACUSON-24-YBR_FULL-RLE.dcm" ) == 0) ref = "429f31f0b70bd515b3feeda5dea5eac0"; if( verbose ) { if(ref) std::cout << "ref=" << ref << std::endl; std::cout << "md5=" << digest << std::endl; } if( !ref ) { // new regression image needs a md5 sum std::cout << "Missing md5 " << digest << " for: " << filename << std::endl; res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } return res; } int TestImageRegionReader1(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestImageRegionRead(filename, true); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestImageRegionRead(filename); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageRegionReader2.cxx000066400000000000000000000107001412732066400276460ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageRegionReader.h" #include "gdcmImageHelper.h" #include "gdcmFilename.h" #include "gdcmBoxRegion.h" #include "gdcmTesting.h" static int TestImageRegionRead(const char* filename, bool verbose = false) { if( verbose ) std::cerr << "Reading: " << filename << std::endl; gdcm::ImageRegionReader reader; gdcm::Filename fn( filename ); // DMCPACS_ExplicitImplicit_BogusIOP.dcm is very difficult to handle since // we need to read 3 attribute to detect the "well known" bug. However the third // attribute is (b500,b700) which make ReadUpToTag(7fe0,0010) fails... if( strcmp(fn.GetName(), "DMCPACS_ExplicitImplicit_BogusIOP.dcm" ) == 0 || strcmp(fn.GetName(), "SC16BitsAllocated_8BitsStoredJ2K.dcm" ) == 0 // mismatch pixel format in JPEG 2000 vs DICOM || strcmp(fn.GetName(), "SC16BitsAllocated_8BitsStoredJPEG.dcm" ) == 0 // mismatch pixel format in JPEG vs DICOM || strcmp(fn.GetName(), "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm" ) == 0 // bogus JPEG cannot be streamed || strcmp(fn.GetName(), "US-YBR_FULL_422-EVRLE.dcm" ) == 0 // FIXME TODO // FIXME: we should be able to handle those at some point: || strcmp(fn.GetName(), "JPEGNote_empty.dcm" ) == 0 || strcmp(fn.GetName(), "JPEGNote_missing.dcm" ) == 0 || strcmp(fn.GetName(), "JPEGNote_bogus.dcm" ) == 0 ) { std::cerr << "Skipping impossible file: " << filename << std::endl; return 0; } reader.SetFileName( filename ); bool canReadInformation = reader.ReadInformation(); if (!canReadInformation) { std::cerr << "Cannot ReadInformation: " << filename << std::endl; return 0; //unable to read tags as expected. } int res = 0; size_t len = 0; std::vector vbuffer; std::vector dims = gdcm::ImageHelper::GetDimensionsValue(reader.GetFile()); gdcm::BoxRegion box; for( unsigned int z = 0; z < dims[2]; ++z ) { box.SetDomain(0, dims[0] - 1, 0, dims[1] - 1, z, z); reader.SetRegion( box ); size_t zlen = reader.ComputeBufferLength(); if( !zlen ) { std::cerr << "No length for: " << filename << std::endl; return 1; } size_t oldlen = vbuffer.size(); len += zlen; vbuffer.resize( oldlen + zlen ); char* buffer = &vbuffer[0] + oldlen; bool b = reader.ReadIntoBuffer(buffer, zlen); if( !b ) { std::cerr << "Could not ReadIntoBuffer" << std::endl; return 1; } } const char *ref = gdcm::Testing::GetMD5FromFile(filename); // FIXME: PC=1 if( strcmp(fn.GetName(), "ACUSON-24-YBR_FULL-RLE-b.dcm" ) == 0) ref = "2d7a28cae6c3b3183284d1b4ae08307f"; if( strcmp(fn.GetName(), "ACUSON-24-YBR_FULL-RLE.dcm" ) == 0) ref = "429f31f0b70bd515b3feeda5dea5eac0"; char digest[33]; char* buffer = &vbuffer[0]; #if 0 std::ofstream of( "/tmp/dd.raw", std::ios::binary ); of.write( buffer, len ); of.close(); #endif gdcm::Testing::ComputeMD5(buffer, len, digest); if( verbose ) { std::cout << "ref=" << ref << std::endl; std::cout << "md5=" << digest << std::endl; } if( !ref ) { // new regression image needs a md5 sum std::cout << "Missing md5 " << digest << " for: " << filename << std::endl; res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } return res; } int TestImageRegionReader2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestImageRegionRead(filename, true); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestImageRegionRead(filename); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageRegionReader3.cxx000066400000000000000000000117511412732066400276560ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageRegionReader.h" #include "gdcmImageHelper.h" #include "gdcmFilename.h" #include "gdcmBoxRegion.h" #include "gdcmTesting.h" static int TestImageRegionRead(const char* filename, bool verbose = false) { using gdcm::System; using gdcm::Testing; if( verbose ) std::cerr << "Reading: " << filename << std::endl; gdcm::Filename fn( filename ); // DMCPACS_ExplicitImplicit_BogusIOP.dcm is very difficult to handle since // we need to read 3 attribute to detect the "well known" bug. However the third // attribute is (b500,b700) which make ReadUpToTag(7fe0,0010) fails... if( strcmp(fn.GetName(), "DMCPACS_ExplicitImplicit_BogusIOP.dcm" ) == 0 || strcmp(fn.GetName(), "SC16BitsAllocated_8BitsStoredJ2K.dcm" ) == 0 // mismatch pixel format in JPEG 2000 vs DICOM || strcmp(fn.GetName(), "SC16BitsAllocated_8BitsStoredJPEG.dcm" ) == 0 // mismatch pixel format in JPEG vs DICOM || strcmp(fn.GetName(), "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm" ) == 0 // bogus JPEG cannot be streamed || strcmp(fn.GetName(), "US-YBR_FULL_422-EVRLE.dcm" ) == 0 // FIXME TODO // FIXME: we should be able to handle those at some point: || strcmp(fn.GetName(), "JPEGNote_empty.dcm" ) == 0 || strcmp(fn.GetName(), "JPEGNote_missing.dcm" ) == 0 || strcmp(fn.GetName(), "JPEGNote_bogus.dcm" ) == 0 ) { std::cerr << "Skipping impossible file: " << filename << std::endl; return 0; } gdcm::ImageRegionReader reader; reader.SetFileName( filename ); bool canReadInformation = reader.ReadInformation(); if (!canReadInformation) { std::cerr << "Cannot ReadInformation: " << filename << std::endl; return 0; //unable to read tags as expected. } // Create directory first: const char subdir[] = "TestImageRegionReader3"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); outfilename += ".raw"; std::ofstream of( outfilename.c_str(), std::ios::binary ); int res = 0; std::vector dims = gdcm::ImageHelper::GetDimensionsValue(reader.GetFile()); std::vector vbuffer; gdcm::BoxRegion box; for( unsigned int z = 0; z < dims[2]; ++z ) { const unsigned int xdelta = dims[0] / 1; const unsigned int ydelta = dims[1] / 4; size_t zlen; bool b; for( unsigned int y = 0; y < 4; ++y ) { unsigned int maxy = ydelta + y * ydelta; if( y == 3 ) maxy = dims[1]; box.SetDomain(0, xdelta - 1, 0 + y * ydelta, (unsigned int)(maxy - 1), z, z); reader.SetRegion(box); zlen = reader.ComputeBufferLength(); assert( zlen ); vbuffer.resize( zlen ); char* buffer = &vbuffer[0]; b = reader.ReadIntoBuffer(buffer, zlen); if( !b ) return 1; assert( zlen ); of.write( buffer, zlen ); } } of.close(); char digest[33]; bool b = gdcm::Testing::ComputeFileMD5(outfilename.c_str(), digest); if( !b ) { std::cerr << "Could not ComputeFileMD5: " << outfilename << std::endl; return 1; } const char *ref = gdcm::Testing::GetMD5FromFile(filename); // FIXME: PC=1 if( strcmp(fn.GetName(), "ACUSON-24-YBR_FULL-RLE-b.dcm" ) == 0) ref = "2d7a28cae6c3b3183284d1b4ae08307f"; if( strcmp(fn.GetName(), "ACUSON-24-YBR_FULL-RLE.dcm" ) == 0) ref = "429f31f0b70bd515b3feeda5dea5eac0"; if( verbose ) { std::cout << "ref=" << ref << std::endl; std::cout << "md5=" << digest << std::endl; } if( !ref ) { // new regression image needs a md5 sum std::cout << "Missing md5 " << digest << " for: " << filename << std::endl; res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } return res; } int TestImageRegionReader3(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestImageRegionRead(filename, true); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestImageRegionRead(filename); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageRegionReader4.cxx000066400000000000000000000100301412732066400276440ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageRegionReader.h" #include "gdcmImageHelper.h" #include "gdcmFilename.h" #include "gdcmBoxRegion.h" #include "gdcmTesting.h" #include "gdcmSystem.h" static int TestImageRegionRead(const char* filename, bool verbose = false) { using gdcm::System; using gdcm::Testing; if( verbose ) std::cerr << "Reading: " << filename << std::endl; gdcm::ImageRegionReader reader; reader.SetFileName( filename ); bool canReadInformation = reader.ReadInformation(); if (!canReadInformation) { std::cerr << "Cannot ReadInformation: " << filename << std::endl; return 1; } // Create directory first: const char subdir[] = "TestImageRegionReader4"; std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); outfilename += ".raw"; std::ofstream of( outfilename.c_str(), std::ios::binary ); int res = 0; std::vector dims = gdcm::ImageHelper::GetDimensionsValue(reader.GetFile()); std::vector vbuffer; gdcm::BoxRegion box; for( unsigned int z = 0; z < dims[2]; ++z ) { box.SetDomain(0, dims[0] - 1, 0, dims[1] - 1, z, z); reader.SetRegion( box ); size_t len = reader.ComputeBufferLength(); if( !len ) { std::cerr << "No length for: " << filename << std::endl; return 1; } vbuffer.resize( len ); char* buffer = &vbuffer[0]; bool b = reader.ReadIntoBuffer(buffer, len); if( !b ) { std::cerr << "Could not ReadIntoBuffer" << std::endl; return 1; } of.write( buffer, len ); } of.close(); char digest[33]; bool b = gdcm::Testing::ComputeFileMD5(outfilename.c_str(), digest); if( !b ) { std::cerr << "Could not ComputeFileMD5: " << outfilename << std::endl; return 1; } const char *ref = gdcm::Testing::GetMD5FromFile(filename); if( verbose ) { std::cout << "ref=" << ref << std::endl; std::cout << "md5=" << digest << std::endl; } if( !ref ) { // new regression image needs a md5 sum std::cout << "Missing md5 " << digest << " for: " << filename << std::endl; res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Into: " << outfilename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } return res; } int TestImageRegionReader4(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestImageRegionRead(filename, true); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *extradataroot = gdcm::Testing::GetDataExtraRoot(); static const char *names[] = { "/gdcmSampleData/images_of_interest/US_512x512x2496_JPEG_BaseLine_Process_1.dcm", "/gdcmSampleData/images_of_interest/PHILIPS_Integris_V-10-MONO2-Multiframe.dcm", "/gdcmSampleData/ForSeriesTesting/MultiFramesSingleSerieXR/1.3.46.670589.7.5.10.80002138018.20001204.181556.9.1.1.dcm", "/gdcmSampleData/images_of_interest/i32.XADC.7.215MegaBytes.dcm", nullptr }; const char *filename; while( (filename = names[i]) ) { std::string fn = extradataroot; fn += filename; r += TestImageRegionRead(fn.c_str()); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageToImageFilter.cxx000066400000000000000000000012611412732066400277130ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageToImageFilter.h" int TestImageToImageFilter(int, char *[]) { gdcm::ImageToImageFilter f; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageWriter.cxx000066400000000000000000000125071412732066400265010ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageReader.h" #include "gdcmImageWriter.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmFileMetaInformation.h" #include "gdcmTesting.h" #include "gdcmByteSwap.h" namespace gdcm { int TestImageWrite(const char *subdir, const char* filename) { ImageReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { const FileMetaInformation &header = reader.GetFile().GetHeader(); MediaStorage ms = header.GetMediaStorage(); bool isImage = MediaStorage::IsImage( ms ); bool pixeldata = reader.GetFile().GetDataSet().FindDataElement( Tag(0x7fe0,0x0010) ); if( isImage && pixeldata ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } else { // not an image give up... std::cerr << "Problem with: " << filename << " but that's ok" << std::endl; return 0; } } // Create directory first: std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); ImageWriter writer; writer.SetFileName( outfilename.c_str() ); writer.SetFile( reader.GetFile() ); // important writer.SetImage( reader.GetImage() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } std::cout << "success: " << outfilename << std::endl; // Let's read that file back in ! ImageReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( reader2.Read() ) { int res = 0; const Image &img = reader2.GetImage(); //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; img.GetBuffer(buffer); // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: #ifdef GDCM_WORDS_BIGENDIAN if( img.GetPixelFormat().GetBitsAllocated() == 16 ) { assert( !(len % 2) ); assert( img.GetPhotometricInterpretation() == PhotometricInterpretation::MONOCHROME1 || img.GetPhotometricInterpretation() == PhotometricInterpretation::MONOCHROME2 ); ByteSwap::SwapRangeFromSwapCodeIntoSystem( (unsigned short*)buffer, SwapCode::LittleEndian, len/2); } #endif // reuse the filename, since outfilename is simply the new representation of the old filename const char *ref = Testing::GetMD5FromFile(filename); char digest[33] = {}; Testing::ComputeMD5(buffer, len, digest); if( !ref ) { // new regression image needs a md5 sum std::cout << "Missing md5 " << digest << " for: " << outfilename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { std::cerr << "Problem reading image from: " << outfilename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; #if 0 std::ofstream debug("/tmp/dump.gray", std::ios::binary); debug.write(buffer, len); debug.close(); //assert(0); #endif } delete[] buffer; return res; } #if 0 // Ok we have now two files let's compare their md5 sum: char digest[33], outdigest[33]; System::ComputeFileMD5(filename, digest); System::ComputeFileMD5(outfilename.c_str(), outdigest); if( strcmp(digest, outdigest) ) { // too bad the file is not identical, so let's be paranoid and // try to reread-rewrite this just-writen file: // TODO: Copy file System::CopyFile( ); if( TestImageWrite( outfilename.c_str() ) ) { std::cerr << filename << " and " << outfilename << " are different\n"; return 1; } // In theory I need to compare the two documents to check they // are identical... TODO std::cerr << filename << " and " << outfilename << " should be compatible\n"; return 0; } else { std::cerr << filename << " and " << outfilename << " are identical\n"; return 0; } #endif return 0; } } int TestImageWriter(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestImageWrite(argv[0],filename); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestImageWrite(argv[0], filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestImageWriter2.cxx000066400000000000000000000144301412732066400265600ustar00rootroot00000000000000/*========================================================================= 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 "gdcmImageWriter.h" #include "gdcmImageReader.h" #include "gdcmImage.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmAttribute.h" /* Let's test the relation in between lossless transfer syntax and lossless compressed stream. D_CLUNIE_CT1_J2KR.dcm D_CLUNIE_CT1_J2KI.dcm D_CLUNIE_MR1_JPLL.dcm D_CLUNIE_MR1_JPLY.dcm D_CLUNIE_CT1_JLSL.dcm D_CLUNIE_CT1_JLSN.dcm */ struct LossLessTest { const char *lossyfile; const char *losslessfile; gdcm::TransferSyntax::TSType lossyts; gdcm::TransferSyntax::TSType losslessts; }; static const LossLessTest LossLessTestArray[] = { { "/D_CLUNIE_CT1_J2KI.dcm", "/D_CLUNIE_CT1_J2KR.dcm", gdcm::TransferSyntax::JPEG2000, gdcm::TransferSyntax::JPEG2000Lossless }, { "/D_CLUNIE_MR1_JPLY.dcm", "/D_CLUNIE_MR1_JPLL.dcm", gdcm::TransferSyntax::JPEGExtendedProcess2_4, gdcm::TransferSyntax::JPEGLosslessProcess14_1 }, { "/D_CLUNIE_CT1_JLSN.dcm", "/D_CLUNIE_CT1_JLSL.dcm", gdcm::TransferSyntax::JPEGLSNearLossless, gdcm::TransferSyntax::JPEGLSLossless } }; int TestImageWriter2(int , char *[]) { const char *directory = gdcm::Testing::GetDataRoot(); gdcm::Trace::WarningOff(); static const unsigned int ntests = sizeof( LossLessTestArray ) / sizeof( *LossLessTestArray ); for( unsigned int test = 0; test < ntests; ++test ) { const LossLessTest <est = LossLessTestArray[test]; const char *j2k_filename1 = ltest.lossyfile; const char *j2k_filename2 = ltest.losslessfile; //const char j2k_filename1[] = "/D_CLUNIE_CT1_J2KI.dcm"; //const char j2k_filename2[] = "/D_CLUNIE_CT1_J2KR.dcm"; std::string filename_lossy = directory; filename_lossy += j2k_filename1; std::string filename_lossless = directory; filename_lossless += j2k_filename2; // Create directory first: const char subdir[] = "TestImageWriter2"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename_lossy = gdcm::Testing::GetTempFilename( filename_lossy.c_str(), subdir ); std::string outfilename_lossless = gdcm::Testing::GetTempFilename( filename_lossless.c_str(), subdir ); { gdcm::ImageReader reader; reader.SetFileName( filename_lossy.c_str() ); if( !reader.Read() ) { return 1; } gdcm::Image &ir = reader.GetImage(); if( !ir.IsLossy() ) { std::cerr << "Image is not lossy" << std::endl; std::cerr << filename_lossy << std::endl; return 1; } //if( ir.GetTransferSyntax() != gdcm::TransferSyntax::JPEG2000 ) if( ir.GetTransferSyntax() != ltest.lossyts ) { std::cerr << filename_lossy << " " << filename_lossless << std::endl; std::cerr << ir.GetTransferSyntax() << " vs " << gdcm::TransferSyntax::GetTSString( ltest.lossyts ) << std::endl; return 1; } //ir.SetTransferSyntax( gdcm::TransferSyntax::JPEG2000Lossless ); ir.SetTransferSyntax( ltest.losslessts ); gdcm::ImageWriter writer; writer.SetImage( ir ); writer.SetFileName( outfilename_lossy.c_str() ); // We should never authorized writing of image that was lossy compress and declare as lossless if( writer.Write() ) { gdcm::Attribute<0x0028,0x2110> at; at.Set( writer.GetFile().GetDataSet() ); if( at.GetValue() != "01" ) { std::cerr << "We should never authorize writing of image that was lossy " "compress and declare as lossless" << std::endl; std::cerr << filename_lossy << " " << filename_lossless << std::endl; return 1; } } } // But the contrary is ok: { gdcm::ImageReader reader; reader.SetFileName( filename_lossless.c_str() ); if( !reader.Read() ) { return 1; } gdcm::Image &ir = reader.GetImage(); //if( ir.GetTransferSyntax() != gdcm::TransferSyntax::JPEG2000Lossless ) if( ir.GetTransferSyntax() != ltest.losslessts ) { return 1; } //ir.SetTransferSyntax( gdcm::TransferSyntax::JPEG2000 ); ir.SetTransferSyntax( ltest.lossyts ); gdcm::ImageWriter writer; writer.SetImage( ir ); writer.SetFileName( outfilename_lossless.c_str() ); // It is ok to save a lossless file and declare transfer syntax to JPEG2000 if( !writer.Write() ) { return 1; } } } #if 0 const gdcm::Image &ir = reader.GetImage(); gdcm::Image image; image.SetNumberOfDimensions( ir.GetNumberOfDimensions() ); const unsigned int *dims = ir.GetDimensions(); image.SetDimension(0, dims[0] ); image.SetDimension(1, dims[1] ); const gdcm::PixelFormat &pixeltype = ir.GetPixelFormat(); image.SetPixelFormat( pixeltype ); const gdcm::PhotometricInterpretation &pi = ir.GetPhotometricInterpretation(); image.SetPhotometricInterpretation( pi ); unsigned long len = image.GetBufferLength(); assert( len = ir.GetBufferLength() ); std::vector buffer; buffer.resize(len); // black image gdcm::ByteValue *bv = new gdcm::ByteValue(buffer); gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0,0x0010) ); pixeldata.SetValue( *bv ); image.SetDataElement( pixeldata ); const char filename[] = "toto.dcm"; gdcm::ImageWriter writer; writer.SetImage( image ); writer.SetFileName( filename ); gdcm::File& file = writer.GetFile(); gdcm::DataSet& ds = file.GetDataSet(); gdcm::DataElement de( gdcm::Tag(0x0010,0x0010) ); const char s[] = "GDCM^Rocks"; de.SetByteValue( s, strlen( s ) ); ds.Insert( de ); if( !writer.Write() ) { return 1; } return 0; #endif return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestJPEGCodec.cxx000066400000000000000000000012011412732066400257320ustar00rootroot00000000000000/*========================================================================= 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 "gdcmJPEGCodec.h" int TestJPEGCodec(int, char *[]) { return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestJSON1.cxx000066400000000000000000000032361412732066400251130ustar00rootroot00000000000000/*========================================================================= 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 "gdcmJSON.h" #include "gdcmFilename.h" #include "gdcmTesting.h" #include "gdcmDataSet.h" #include "gdcmWriter.h" #include "gdcmFile.h" int TestJSON1(int, char *[]) { //std::string sup166 = gdcm::Filename::Join(gdcm::Testing::GetSourceDirectory(), "/Testing/Source/Data/QIDO-RS_examplesup166.json" ); std::string sup166 = gdcm::Filename::Join(gdcm::Testing::GetSourceDirectory(), "/Testing/Source/Data/QIDO-RS_examplesup166_2.json" ); if( !gdcm::System::FileExists( sup166.c_str() ) ) { std::cerr << sup166 << std::endl; return 1; } std::ifstream is( sup166.c_str() ); gdcm::JSON json; json.PrettyPrintOn(); #if 1 gdcm::DataSet ds; json.Decode(is, ds ); //std::cout << ds << std::endl; #else gdcm::Writer w; gdcm::File & ff = w.GetFile(); gdcm::DataSet &ds = ff.GetDataSet(); ff.GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); json.Decode(is, ff.GetDataSet() ); w.SetFileName( "/tmp/debug2.dcm" ); if( !w.Write() ) return 1; #endif std::stringstream ss; json.Code(ds, ss ); std::cout << ss.str() << std::endl; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestLookupTable.cxx000066400000000000000000000012361412732066400265000ustar00rootroot00000000000000/*========================================================================= 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 "gdcmLookupTable.h" int TestLookupTable(int, char *[]) { gdcm::LookupTable lut; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestOrientation.cxx000066400000000000000000000030661412732066400265550ustar00rootroot00000000000000/*========================================================================= 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 "gdcmOrientation.h" #include int TestOrientation(int, char *[]) { gdcm::Orientation o; { double dircos[] = { 1, 0, 0, 0, 1, 0 }; gdcm::Orientation::OrientationType type = gdcm::Orientation::GetType(dircos); if( type != gdcm::Orientation::AXIAL ) { std::cerr << "Should be AXIAL: " << gdcm::Orientation::GetLabel( type ) << std::endl; return 1; } } { double dircos[] = { 1, 0, 0, 0, 0, 1 }; gdcm::Orientation::OrientationType type = gdcm::Orientation::GetType(dircos); if( type != gdcm::Orientation::CORONAL ) { return 1; } } { double dircos[] = { 0, 1, 0, 0, 0, -1 }; gdcm::Orientation::OrientationType type = gdcm::Orientation::GetType(dircos); if( type != gdcm::Orientation::SAGITTAL ) { return 1; } } if( o.GetObliquityThresholdCosineValue() != 0.8 ) { return 1; } gdcm::Orientation::SetObliquityThresholdCosineValue( 0.75 ); if( o.GetObliquityThresholdCosineValue() != 0.75 ) { return 1; } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestOverlay.cxx000066400000000000000000000012501412732066400256740ustar00rootroot00000000000000/*========================================================================= 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 "gdcmOverlay.h" int TestOverlay(int, char *[]) { gdcm::Overlay o; o.Print( std::cout ); return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestOverlay2.cxx000066400000000000000000000034311412732066400257610ustar00rootroot00000000000000/*========================================================================= 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 "gdcmOverlay.h" #include "gdcmPixmapReader.h" #include "gdcmTesting.h" #include "gdcmSystem.h" int TestOverlay2(int, char *[]) { const char *extradataroot = gdcm::Testing::GetDataExtraRoot(); if( !extradataroot ) { return 1; } if( !gdcm::System::FileIsDirectory(extradataroot) ) { std::cerr << "No such directory: " << extradataroot << std::endl; return 1; } std::string filename = extradataroot; filename += "/gdcmSampleData/images_of_interest/XA_GE_JPEG_02_with_Overlays.dcm"; if( !gdcm::System::FileExists(filename.c_str()) ) { return 1; } gdcm::PixmapReader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "could not read: " << filename << std::endl; return 1; } gdcm::Pixmap &pixmap = reader.GetPixmap(); if( pixmap.GetNumberOfOverlays() != 8 ) { return 1; } size_t numoverlays = pixmap.GetNumberOfOverlays(); for( size_t ovidx = 0; ovidx < numoverlays; ++ovidx ) { const gdcm::Overlay& ov = pixmap.GetOverlay(ovidx); if( ov.GetTypeAsEnum() != gdcm::Overlay::Graphics ) { std::cerr << "Wrong Type for overlay #" << ovidx << std::endl; return 1; } } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestOverlay3.cxx000066400000000000000000000132651412732066400257700ustar00rootroot00000000000000/*========================================================================= 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 "gdcmOverlay.h" #include "gdcmImageReader.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmFilename.h" using namespace gdcm; struct ovel { const char *md5; const char *fn; unsigned int idx; Overlay::OverlayType type; }; static const ovel overlay3array[] = { // gdcmData {"d42bff3545ed8c5fccb39d9a61828992", "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm", 0, Overlay::Graphics }, {"2cf60257b75a034fbdc98e560881184e", "PHILIPS_Brilliance_ExtraBytesInOverlay.dcm", 0, Overlay::Graphics }, {"b2dd1007e018b3b9691761cf93f77552", "05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm", 0, Overlay::Graphics }, {"d42bff3545ed8c5fccb39d9a61828992", "MR-SIEMENS-DICOM-WithOverlays.dcm", 0, Overlay::Graphics }, // gdcmDataExtra {"4b0240033afba211eeac42a44417d4c9", "05119848_IS_Black_hasOverlayData.dcm", 0, Overlay::Graphics }, {"349d1f9510f64467ecf73eeea46c9c6e", "45909476", 0, Overlay::Graphics }, {"6a5f8038cc8cf753bf74422164adc24c", "45909517", 0, Overlay::Graphics }, {"1a3bf73e42b0f6dc282a9be59c054027", "OverlayDICOMDataSet.dcm", 0, Overlay::Graphics }, // gdcmConformanceTests {"040560796c1a53ffce0d2f7e90c9dc26", "CT_OSIRIX_OddOverlay.dcm", 0, Overlay::Graphics }, // random // {"f7e43de189a1bc08044c13aefac73fed", "1.dcm", 0 }, // {"e7859c818f26202fb63a2b205ff16297", "1.dcm", 1 }, // {"aa4c726bc52e13b750ac8c94c7b06e07", "0.dcm", 0 }, // {"31d58476326722793379fbcda55a4856", "0.dcm", 1 }, // sentinel { nullptr, nullptr, 0, Overlay::Invalid } }; static int TestReadOverlay(const char* filename, bool verbose = false) { if( verbose ) std::cerr << "Reading: " << filename << std::endl; gdcm::ImageReader reader; reader.SetFileName( filename ); int ret = 0; if ( reader.Read() ) { gdcm::Filename fn( filename ); const char *name = fn.GetName(); std::vector overlay; const gdcm::Image &img = reader.GetImage(); size_t numoverlays = img.GetNumberOfOverlays(); for( size_t ovidx = 0; ovidx < numoverlays; ++ovidx ) { const gdcm::Overlay& ov = img.GetOverlay(ovidx); size_t len = ov.GetUnpackBufferLength(); overlay.resize( len ); if( !ov.GetUnpackBuffer(&overlay[0], len) ) { std::cerr << "GetUnpackBuffer: Problem with Overlay: #" << ovidx << std::endl; ++ret; } char digest1[33]; if( !gdcm::Testing::ComputeMD5(&overlay[0], len, digest1) ) { std::cerr << "ComputeMD5: Problem with Overlay: #" << ovidx << std::endl; ++ret; } std::stringstream overlay2; ov.Decompress(overlay2); Overlay::OverlayType type = ov.GetTypeAsEnum(); const std::string soverlay2 = overlay2.str(); if( soverlay2.size() != len ) { std::cerr << "Decompress: Problem with Overlay: #" << ovidx << std::endl; std::cerr << "Size is: " << soverlay2.size() << " vs " << len << std::endl; ++ret; } char digest2[33]; if( !gdcm::Testing::ComputeMD5(soverlay2.c_str(), soverlay2.size(), digest2) ) { std::cerr << "ComputeMD5: Problem with Overlay: #" << ovidx << std::endl; ++ret; } Overlay::OverlayType reftype = Overlay::Invalid; const char *refmd5 = nullptr; { unsigned int i = 0; const char *p = overlay3array[i].fn; unsigned int idx = overlay3array[i].idx; while( p != nullptr ) { if( strcmp( name, p ) == 0 && ovidx == idx ) { break; } ++i; p = overlay3array[i].fn; idx = overlay3array[i].idx; } refmd5 = overlay3array[i].md5; reftype = overlay3array[i].type; } if( !refmd5 ) { std::cerr << "refmd5: Problem with Overlay: #" << ovidx << std::endl; std::cerr << name << std::endl; ++ret; } if( refmd5 && strcmp(digest1, refmd5) ) { std::cerr << "strcmp/ref: Problem with Overlay: #" << ovidx << std::endl; std::cerr << "ref: " << refmd5 << " vs " << digest1 << std::endl; ++ret; } if( strcmp(digest1, digest2) ) { std::cerr << "strcmp/1/2: Problem with Overlay: #" << ovidx << std::endl; std::cerr << "digest1: " << digest1 << " vs " << digest2 << std::endl; ++ret; } if( reftype != type ) { std::cerr << "OverlayType: Problem with Overlay: #" << ovidx << std::endl; std::cerr << "reftype: " << (int)reftype << " vs " << (int)type << std::endl; std::cerr << name << std::endl; ++ret; } } } return ret; } int TestOverlay3(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestReadOverlay(filename, true); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestReadOverlay( filename); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestPDFCodec.cxx000066400000000000000000000013321412732066400256230ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPDFCodec.h" #include "gdcmTransferSyntax.h" int TestPDFCodec(int , char *[]) { gdcm::PDFCodec c; c.CanCode(gdcm::TransferSyntax()); return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestPNMCodec.cxx000066400000000000000000000013661412732066400256530ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPNMCodec.h" #include "gdcmTransferSyntax.h" int TestPNMCodec(int, char *[]) { gdcm::PNMCodec pnm; pnm.CanDecode( gdcm::TransferSyntax::ImplicitVRLittleEndian ); return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestParseXPATH.cxx000066400000000000000000000062031412732066400261350ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmDataSet.h" #include "gdcmDict.h" #include "gdcmDicts.h" #include "gdcmGlobal.h" #include "gdcmStringFilter.h" #include "gdcmTesting.h" #include "gdcmFilename.h" static bool CheckResult( std::string const & filename, std::string const & value ) { if( filename == "D_CLUNIE_MR3_JPLY.dcm" || filename == "D_CLUNIE_RG3_JPLY.dcm" || filename == "D_CLUNIE_NM1_JPLY.dcm" || filename == "D_CLUNIE_MR4_JPLY.dcm" || filename == "D_CLUNIE_CT1_J2KI.dcm" || filename == "D_CLUNIE_CT1_JLSN.dcm" || filename == "D_CLUNIE_MR1_JPLY.dcm" || filename == "D_CLUNIE_SC1_JPLY.dcm" || filename == "D_CLUNIE_MR2_JPLY.dcm" || filename == "D_CLUNIE_RG2_JPLY.dcm" || filename == "D_CLUNIE_XA1_JPLY.dcm" ) { return value == "Lossy Compression "; } else if ( filename == "JPEG_LossyYBR.dcm" || filename == "MEDILABInvalidCP246_EVRLESQasUN.dcm" ) return value == "Full fidelity image, uncompressed or lossless compressed"; else if ( filename == "NM-PAL-16-PixRep1.dcm" ) return value == "Full fidelity image "; else return value.empty(); } int TestParseXPATHFile(const char* filename, bool verbose = false ) { (void)verbose; //static gdcm::Global &g = gdcm::Global::GetInstance(); //static const gdcm::Dicts &dicts = g.GetDicts(); //static const gdcm::Dict &pubdict = dicts.GetPublicDict(); gdcm::Reader reader; // reader.SetFileName( "/home/mathieu/Creatis/gdcmData/D_CLUNIE_CT1_J2KI.dcm" ); reader.SetFileName( filename ); if( !reader.Read() ) { return 1; } gdcm::StringFilter sf; sf.SetFile( reader.GetFile() ); const char query_const[] = "/DicomNativeModel/DicomAttribute[@keyword='DerivationCodeSequence']/Item[@number=1]//DicomAttribute[@keyword='CodeMeaning']/Value[@number=1]"; std::string value; bool ret = sf.ExecuteQuery( query_const, value ); if( !ret ) { return 1; } gdcm::Filename fn( filename ); bool b = CheckResult( fn.GetName(), value ); if( !b ) { std::cerr << "Problem with: " << filename << " -> " << value << std::endl; } return !b; } int TestParseXPATH(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestParseXPATHFile(filename, true); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestParseXPATHFile(filename); ++i; } return EXIT_SUCCESS; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestPersonName.cxx000066400000000000000000000061471412732066400263340ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPersonName.h" #include "gdcmByteValue.h" #include int TestPersonName(int, char *[]) { using PN = gdcm::PersonName; PN pn0; pn0.SetComponents(); std::cout << "NumComp:" << pn0.GetNumberOfComponents() << std::endl; pn0.Print( std::cout ); std::cout << std::endl; PN pn00 = {{ "" }}; std::cout << "NumComp:" << pn00.GetNumberOfComponents() << std::endl; PN pn1 = {{ "abc123", "def", "ghi", "klm", "opq" }}; pn1.Print( std::cout ); std::cout << std::endl; std::cout << "NumComp:" << pn1.GetNumberOfComponents() << std::endl; PN pn2 = {{ "malaterre", "mathieu olivier patrick"}}; pn2.Print( std::cout ); std::cout << std::endl; std::cout << "NumComp:" << pn2.GetNumberOfComponents() << std::endl; // Rev. John Robert Quincy Adams, B.A. M.Div. Adams^John Robert Quincy^^Rev.^B.A. M.Div. [One family name; three given names; no middle name; one prefix; two suffixes.] PN pn3 = {{ "Adams", "John Robert Quincy", "", "Rev.", "B.A. M.Div." }}; pn3.Print( std::cout ); std::cout << std::endl; std::cout << "NumComp:" << pn3.GetNumberOfComponents() << std::endl; // Susan Morrison-Jones, Ph.D., Chief Executive Officer Morrison-Jones^Susan^^^Ph.D., Chief Executive Officer [Two family names; one given name; no middle name; no prefix; two suffixes.] PN pn4 = {{ "Morrison-Jones", "Susan", "", "", "Ph.D., Chief Executive Officer" }}; pn4.Print( std::cout ); std::cout << std::endl; std::cout << "NumComp:" << pn4.GetNumberOfComponents() << std::endl; // John Doe Doe^John [One family name; one given name; no middle name, prefix, or suffix. Delimiters have been omitted for the three trailing null components.] PN pn5 = {{ "Doe", "John" }}; pn5.Print( std::cout ); std::cout << std::endl; std::cout << "NumComp:" << pn5.GetNumberOfComponents() << std::endl; // (for examples of the encoding of Person Names using multi-byte character sets see Annex H) // Smith^Fluffy [A cat, rather than a //human, whose responsible party family name is Smith, and whose own name is Fluffy] PN pn6 = {{ "Smith", "Fluffy" }}; pn6.Print( std::cout ); std::cout << std::endl; std::cout << "NumComp:" << pn6.GetNumberOfComponents() << std::endl; //ABC Farms^Running on Water [A horse whose responsible organization is named ABC Farms, and whose name is Running On Water] PN pn7 = {{ "ABC Farms", "Running on Water" }}; pn7.Print( std::cout ); std::cout << std::endl; std::cout << "NumComp:" << pn7.GetNumberOfComponents() << std::endl; gdcm::ByteValue bv; PN pn8; pn8.SetBlob( bv ); return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestPhotometricInterpretation.cxx000066400000000000000000000063731412732066400315130ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPhotometricInterpretation.h" #include // strlen int TestPhotometricInterpretation(int, char *[]) { gdcm::PhotometricInterpretation pi; int end = gdcm::PhotometricInterpretation::PI_END; for( int i = 1; i < end; ++i) { const char *pistr = gdcm::PhotometricInterpretation::GetPIString( (gdcm::PhotometricInterpretation::PIType)i ); if( strlen( pistr ) % 2 ) { std::cerr << pistr << std::endl; return 1; } } pi = gdcm::PhotometricInterpretation::RGB; pi = gdcm::PhotometricInterpretation::GetPIType( "MONOCHROME2" ); if( pi != gdcm::PhotometricInterpretation::MONOCHROME2 ) { std::cerr << "PhotometricInterpretation: " << pi << std::endl; return 1; } pi = gdcm::PhotometricInterpretation::GetPIType( "MONOCHROME2 " ); if( pi != gdcm::PhotometricInterpretation::MONOCHROME2 ) { std::cerr << "PhotometricInterpretation: " << pi << std::endl; return 1; } pi = gdcm::PhotometricInterpretation::GetPIType( " MONOCHROME2 " ); if( pi != gdcm::PhotometricInterpretation::MONOCHROME2 ) { std::cerr << "PhotometricInterpretation: " << pi << std::endl; return 1; } pi = gdcm::PhotometricInterpretation::GetPIType( " MONOCHROME2 " ); if( pi != gdcm::PhotometricInterpretation::MONOCHROME2 ) { std::cerr << "PhotometricInterpretation: " << pi << std::endl; return 1; } pi = gdcm::PhotometricInterpretation::GetPIType( " MONOCHROME2 " ); if( pi != gdcm::PhotometricInterpretation::MONOCHROME2 ) { std::cerr << "PhotometricInterpretation: " << pi << std::endl; return 1; } pi = gdcm::PhotometricInterpretation::GetPIType( "MONOCHROME" ); if( pi != gdcm::PhotometricInterpretation::MONOCHROME1 ) { std::cerr << "PhotometricInterpretation: " << pi << std::endl; return 1; } pi = gdcm::PhotometricInterpretation::GetPIType( "YBR_PARTIAL_42 " ); if( pi != gdcm::PhotometricInterpretation::YBR_PARTIAL_422) { std::cerr << "PhotometricInterpretation: " << pi << std::endl; return 1; } pi = gdcm::PhotometricInterpretation::GetPIType( "PALETTE" ); if( pi != gdcm::PhotometricInterpretation::PALETTE_COLOR ) { std::cerr << "PhotometricInterpretation: " << pi << std::endl; return 1; } pi = gdcm::PhotometricInterpretation::GetPIType( "YBR_FULL_4" ); if( pi != gdcm::PhotometricInterpretation::YBR_FULL_422) { std::cerr << "PhotometricInterpretation: " << pi << std::endl; return 1; } // FIXME ? pi = gdcm::PhotometricInterpretation::GetPIType( "YBR_FUL" ); if( pi != gdcm::PhotometricInterpretation::YBR_FULL ) { std::cerr << "PhotometricInterpretation: " << pi << std::endl; return 1; } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestPixelFormat.cxx000066400000000000000000000103011412732066400265020ustar00rootroot00000000000000/*========================================================================= 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 "gdcmPixelFormat.h" struct frame_info { gdcm::PixelFormat pixeltype; }; int TestPixelFormat(int , char *[]) { using gdcm::PixelFormat; gdcm::PixelFormat pf; pf.SetScalarType( gdcm::PixelFormat::UNKNOWN ); if( pf.GetScalarType() != gdcm::PixelFormat::UNKNOWN ) { return 1; } pf.SetScalarType( gdcm::PixelFormat::UINT32 ); //pf.SetScalarType( gdcm::PixelFormat::UINT64 ); static const int64_t values[][2] = { { 0LL,255LL }, { 0LL,4095LL }, { 0LL,65535LL }, { 0LL,4294967295LL }, { -128LL,127LL }, { -2048LL,2047LL }, { -32768LL,32767LL }, { -2147483648LL,2147483647LL }, // { -2147483648LL,2147483647LL } }; static const size_t n = sizeof( values ) / sizeof( *values ); size_t c = 0; pf.SetBitsStored( 8 ); if( pf.GetMin() != values[c][0] || pf.GetMax() != values[c][1] ) { std::cerr << pf.GetMin() << "," << pf.GetMax() << std::endl; return 1; } ++c; pf.SetBitsStored( 12 ); if( pf.GetMin() != values[c][0] || pf.GetMax() != values[c][1] ) { std::cerr << pf.GetMin() << "," << pf.GetMax() << std::endl; return 1; } ++c; pf.SetBitsStored( 16 ); if( pf.GetMin() != values[c][0] || pf.GetMax() != values[c][1] ) { std::cerr << pf.GetMin() << "," << pf.GetMax() << std::endl; return 1; } ++c; pf.SetBitsStored( 32 ); if( pf.GetMin() != values[c][0] || pf.GetMax() != values[c][1] ) { std::cerr << pf.GetMin() << "," << pf.GetMax() << std::endl; return 1; } // ++c; // pf.SetBitsStored( 64 ); // if( pf.GetMin() != values[c][0] || pf.GetMax() != values[c][1] ) // { // std::cerr << pf.GetMin() << "," << pf.GetMax() << std::endl; // return 1; // } pf.SetPixelRepresentation( 1 ); ++c; pf.SetBitsStored( 8 ); if( pf.GetMin() != values[c][0] || pf.GetMax() != values[c][1] ) { std::cerr << pf.GetMin() << "," << pf.GetMax() << std::endl; return 1; } ++c; pf.SetBitsStored( 12 ); if( pf.GetMin() != values[c][0] || pf.GetMax() != values[c][1] ) { std::cerr << pf.GetMin() << "," << pf.GetMax() << std::endl; return 1; } ++c; pf.SetBitsStored( 16 ); if( pf.GetMin() != values[c][0] || pf.GetMax() != values[c][1] ) { std::cerr << pf.GetMin() << "," << pf.GetMax() << std::endl; return 1; } ++c; pf.SetBitsStored( 32 ); if( pf.GetMin() != values[c][0] || pf.GetMax() != values[c][1] ) { std::cerr << pf.GetMin() << "," << pf.GetMax() << std::endl; return 1; } // ++c; // pf.SetBitsStored( 64 ); // if( pf.GetMin() != values[c][0] || pf.GetMax() != values[c][1] ) // { // std::cerr << pf.GetMin() << "," << pf.GetMax() << std::endl; // return 1; // } ++c; if ( c != n ) return 1; for(unsigned int i = 0; i < PixelFormat::UNKNOWN; ++i) { PixelFormat::ScalarType st = (PixelFormat::ScalarType)i; pf.SetScalarType( st ); gdcm::PixelFormat pf2 = st; std::cout << pf << std::endl; std::cout << pf.GetPixelRepresentation() << std::endl; std::cout << pf.GetScalarTypeAsString() << std::endl; if( pf2 != pf ) return 1; } // make to avoid user mistakes: gdcm::PixelFormat pf3 = PixelFormat::UINT8; if( pf3.GetBitsStored() != 8 ) return 1; pf3.SetBitsStored( 32 ); // previous call should not execute if( pf3.GetBitsStored() != 8 ) return 1; pf3.SetHighBit( 8 ); if( pf3.GetHighBit() != 7 ) return 1; gdcm::PixelFormat pf4 = PixelFormat::UINT16; pf4.SetBitsStored(8); if( pf4.GetScalarType() != gdcm::PixelFormat::UINT16 ) return 1; pf4.SetPixelRepresentation(1); if( pf4.GetScalarType() != gdcm::PixelFormat::INT16 ) return 1; frame_info fi = {}; (void)fi; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestPrint.cxx000066400000000000000000000031641412732066400253550ustar00rootroot00000000000000/*========================================================================= 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 "gdcmStringFilter.h" #include "gdcmReader.h" #include "gdcmSequenceOfItems.h" #include "gdcmTrace.h" #include "gdcmTesting.h" int TestSimplePrint(const char *filename, bool verbose = false) { gdcm::Reader r; r.SetFileName( filename ); if( !r.Read() ) { return 1; } gdcm::DataSet const& ds = r.GetFile().GetDataSet(); int ret = 0; gdcm::DataSet::ConstIterator it = ds.Begin(); std::ostringstream os; for( ; it != ds.End(); ++it) { const gdcm::DataElement &ref = *it; os << ref << std::endl; } if( verbose ) std::cout << os.str(); return ret; } int TestPrint(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestSimplePrint(filename, true); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestSimplePrint( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestPrinter1.cxx000066400000000000000000000501611412732066400257640ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmPrinter.h" #include "gdcmFilename.h" #include "gdcmTesting.h" // How to update this file: // $ while IFS=\; read -r col1 col2 col3; do echo "-e 's/$col2/$col3/g'"; done < /tmp/full > /tmp/s // the following list has been generated using gdcm, git: df760b9d8b3c9b280ad423153c649190f6e21204 // This correspond to the commit just before: // BUG: an explicit length VR=SQ dataelement would not have been loaded as // expected and a call to GetSequenceOfItems would fails. Thus downstream filter // would fail load the SQ as expected. Introducing the more robust interface: // GetValueAsSQ to solve that issue. static const char * const printmd5[][2] = { { "a19bffac370df32acbf6b4991d1cbafe" , "00191113.dcm" } , { "94816f96c7db33e8449cc4f2e0843ff8" , "012345.002.050.dcm" } , { "94f8c6ab090bdc11e61625bfc2dd39b7" , "05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm" } , { "20c11831c616eb121a405cd73de5cba2" , "05148044-mr-siemens-avanto-syngo.dcm" } , { "ec10dcbf1b13ace8a6c0cc5b24c6c870" , "3E768EB7.dcm" } , { "fde1da68a1707dcc687ddffd57e6b3c3" , "ACUSON-24-YBR_FULL-RLE-b.dcm" } , { "a27c6628d6379783a3be223481d5cba4" , "ACUSON-24-YBR_FULL-RLE.dcm" } , { "9f3aa114b955a812942f815b6b456eaf" , "ALOKA_SSD-8-MONO2-RLE-SQ.dcm" } , { "0f44d8305020f5fb854563eb4335e207" , "AMIInvalidPrivateDefinedLengthSQasUN.dcm" } , { "56aea0ecd59a5b9427dbd60523eeb2c1" , "BugGDCM2_UndefItemWrongVL.dcm" } , { "6d2af85d2af299c223b684538d42d9e5" , "CR-MONO1-10-chest.dcm" } , { "820d45cefd528e011921ea129bec9084" , "CT_16b_signed-UsedBits13.dcm" } , { "fcf2ca019aa3138188edb18552983733" , "CT-MONO2-12-lomb-an2.acr" } , { "0e4137f63819c706dfa370405d662c79" , "CT-MONO2-16-ankle.dcm" } , { "f00a663066627e7ecdd1a7379137d396" , "CT-MONO2-16-brain.dcm" } , { "87eadd3a3460c13593c9468bc533aa58" , "CT-MONO2-16-chest.dcm" } , { "8b0efbe7cfd72a7d14cef44683fbacab" , "CT-MONO2-16-ort.dcm" } , { "32c8e40e0726bbcc374f20771d37a312" , "CT-MONO2-8-abdo.dcm" } , { "c5ffd15172c43b200e3654d5e3e45f3e" , "CT-SIEMENS-Icone-With-PaletteColor.dcm" } , { "ca0e93a8995fccad9d031e0125ea1a29" , "CT-SIEMENS-MissingPixelDataInIconSQ.dcm" } , { "a46ca467a0df5e1c71c8017b6b6768e7" , "D_CLUNIE_CT1_J2KI.dcm" } , { "d2698545b07ad721faa71fdc1cf4a35d" , "D_CLUNIE_CT1_J2KR.dcm" } , { "78f619a764a94a2c2bdc084d53ad2577" , "D_CLUNIE_CT1_JPLL.dcm" } , { "4aaa4a602d7a1fd80c023acba36d6a84" , "D_CLUNIE_CT1_RLE.dcm" } , { "9ee24f3a3291cd86f0bc78fddc3417e7" , "D_CLUNIE_CT2_JPLL.dcm" } , { "b01b2b28aa3caa945b05865a9c440349" , "D_CLUNIE_CT2_RLE.dcm" } , { "7d6531dc92c53ad25835b75fa5505b66" , "D_CLUNIE_MR1_JPLL.dcm" } , { "e8a970a1c861192331a98162146ee0f9" , "D_CLUNIE_MR1_JPLY.dcm" } , { "6f8b7b128c86c5a670a284e7eac38391" , "D_CLUNIE_MR1_RLE.dcm" } , { "b770b1ca257d7c1c885f69a5a1b58808" , "D_CLUNIE_MR2_JPLL.dcm" } , { "da74aefef4e8ac49dbe1a4dd3b1dcb26" , "D_CLUNIE_MR2_JPLY.dcm" } , { "023eb2a9ecbfd3c04bb148ec339865f0" , "D_CLUNIE_MR2_RLE.dcm" } , { "fbeaa26ab8c0ce7abcae5c24532cab0c" , "D_CLUNIE_MR3_JPLL.dcm" } , { "d2b228b64ef53df5b8fb07c227e4250a" , "D_CLUNIE_MR3_JPLY.dcm" } , { "ef7b70b4f87f540f7c2fe954c5988d82" , "D_CLUNIE_MR3_RLE.dcm" } , { "1646ec013060ef3f261849db705f80f3" , "D_CLUNIE_MR4_JPLL.dcm" } , { "fbbfe4caab2179641bd0de5d8ccf79ae" , "D_CLUNIE_MR4_JPLY.dcm" } , { "fafdb8499580e59c2f6d9047894272ea" , "D_CLUNIE_MR4_RLE.dcm" } , { "bc35454da5d8c0825236ccae83adcb82" , "D_CLUNIE_NM1_JPLL.dcm" } , { "03527dbfa9b0b82fee7d6eb601abf470" , "D_CLUNIE_NM1_JPLY.dcm" } , { "9488a473e2cd1fc981f36643e7dc1b82" , "D_CLUNIE_NM1_RLE.dcm" } , { "d9da8798488b1c825dbd4ef940e386b9" , "D_CLUNIE_RG1_JPLL.dcm" } , { "68a498853d26cce827eefb0f8be3581d" , "D_CLUNIE_RG1_RLE.dcm" } , { "9f652b621320650c6be743b6bafcf539" , "D_CLUNIE_RG2_JPLL.dcm" } , { "1f0e2edba097f4491b7d45fed604729d" , "D_CLUNIE_RG2_JPLY.dcm" } , { "403e0e40507608cdcd61ee461de91226" , "D_CLUNIE_RG2_RLE.dcm" } , { "73ecf348f874e7fb69f5dbfb4637979e" , "D_CLUNIE_RG3_JPLL.dcm" } , { "f454ce36a97e4d4164a628e686a9977b" , "D_CLUNIE_RG3_JPLY.dcm" } , { "ec7dcf6857238547f0fb43f51317b05f" , "D_CLUNIE_RG3_RLE.dcm" } , { "af35b9ad269b8a37df3d25389655272e" , "D_CLUNIE_SC1_JPLY.dcm" } , { "50f92b02a370e2858632dfde330a2881" , "D_CLUNIE_SC1_RLE.dcm" } , { "ad377bc5cc50cb1b6312e9035417b2f1" , "D_CLUNIE_US1_RLE.dcm" } , { "e6ea16c1ba4a8e8f97383811fd91288a" , "D_CLUNIE_VL1_RLE.dcm" } , { "291ac2ee3c48a76ae0ab9a095199997c" , "D_CLUNIE_VL2_RLE.dcm" } , { "91c92c4d1330c283012d2bdd3a91dc2f" , "D_CLUNIE_VL3_RLE.dcm" } , { "fcc44b14754a56879e0f3afc8161c1c0" , "D_CLUNIE_VL4_RLE.dcm" } , { "d7ded36c6827f41d61790bed41b963e3" , "D_CLUNIE_VL6_RLE.dcm" } , { "75801e9732698ea89740f935052f28d6" , "D_CLUNIE_XA1_JPLL.dcm" } , { "79d8daf6837a4b5aefaa963b1fb88df1" , "D_CLUNIE_XA1_JPLY.dcm" } , { "e2bda8297745ab7a77ca84242ad4c980" , "D_CLUNIE_XA1_RLE.dcm" } , { "bb52d9f7a9116c87103066dd18a60e68" , "D_CLUNIE_CT1_JLSN.dcm" } , { "8984d6319cd913d0f88fdb61989412f2" , "D_CLUNIE_CT1_JLSL.dcm" } , { "4ef94d44a83066b80b39d254fb2a1c28" , "DCMTK_JPEGExt_12Bits.dcm" } , { "d982dca9cc6c9db94a6233ca76e52f26" , "DermaColorLossLess.dcm" } , { "ee354d9b221360982f15b630e1fdb046" , "DICOMDIR" } , { "aa0556f64fb938935447f3e3b6b67b68" , "dicomdir_Acusson_WithPrivate_WithSR" } , { "9934ab3c8adca82cad0fe8997b6c5cd3" , "DICOMDIR_MR_B_VA12A" } , { "6a4cfd1ddd6eea5538dd7f8cf1ba1e1f" , "DICOMDIR-Philips-EasyVision-4200-Entries" } , { "4254e4123245565e43a86e191acff01b" , "dicomdir_Pms_With_heavy_embedded_sequence" } , { "6b4a338aff7a2e0b75e39bc7b2393ec2" , "dicomdir_Pms_WithVisit_WithPrivate_WithStudyComponents" } , { "356f30be965bbe4e335a56c6c5fe1928" , "dicomdir_With_embedded_icons" } , { "cfa838dc4a9f62199b10909744dee484" , "DMCPACS_ExplicitImplicit_BogusIOP.dcm" } , { "c28bfc62319b6059b4e7a30dd31599de" , "DX_GE_FALCON_SNOWY-VOI.dcm" } , { "1cbeb77ea2d6e0171dd38e0d6d5cb0b9" , "DX_J2K_0Padding.dcm" } , { "3493bf0e698798529fde6ef488289879" , "ELSCINT1_JP2vsJ2K.dcm" } , { "8f5581be656bd6f1ab6c9ec94f302284" , "ELSCINT1_LOSSLESS_RICE.dcm" } , { "54f138a1aa6819ec1560a7ed344cde1a" , "ELSCINT1_PMSCT_RLE1.dcm" } , { "1f3720cdf4c65748d512fe7e6f5dcab8" , "EnhancedWithIPPPerFrameIOPShared.dcm"} , { "d576bf8e8b2ca71fd543d29698807e85" , "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm" } , { "3199cd21166043d619209d7a2073fb56" , "fffc0000UN.dcm" } , { "9b426b02521cbc2f3ee25ab383ca835e" , "FUJI-10-MONO1-ACR_NEMA_2.dcm" } , { "f705cfe771a299023c8dcc94b2184960" , "FUJI-ffff-MONO1-J2K.dcm"} , { "2aba3dacd00a0bc14a06e2d7142b916a" , "gdcm-ACR-LibIDO.acr" } , { "b808c747b59f9d1a91a01491103abea5" , "gdcm-CR-DCMTK-16-NonSamplePerPix.dcm" } , { "e7b5089a2a007221993ee5a7e6d44959" , "gdcm-JPEG-Extended.dcm" } , { "20894653d750b4edf6034258a8dc3cf7" , "gdcm-JPEG-LossLess3a.dcm" } , { "5011206e2a744c8a6f2cedb1ff7e5e11" , "gdcm-JPEG-LossLessThoravision.dcm" } , { "49f3c524267607c09b6a78448f804eb8" , "gdcm-MR-PHILIPS-16-Multi-Seq.dcm" } , { "3ada4145885084c465fc0d2969299428" , "gdcm-MR-PHILIPS-16-NonSquarePixels.dcm" } , { "ac5f5bea451fd81aa2416fbab1a4e8c4" , "gdcm-MR-SIEMENS-16-2.acr" } , { "48c49a7a41a7efea9ea0eadcd89ac9fa" , "gdcm-US-ALOKA-16.dcm" } , { "7d42ad3c14c4fc9953ed8da6df4ae6c6" , "GE_CT_With_Private_compressed-icon.dcm" } , { "9e126a24f81534e1cd653f16739a6192" , "GE_DLX-8-MONO2-Multiframe.dcm" } , { "aa39aa421b9d1e9c51e261ed632250a3" , "GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm" } , { "61ca6c5115e6f74565f6f2ca06647444" , "GE_DLX-8-MONO2-PrivateSyntax.dcm" } , { "84b29e188d5067565469c7c31676ff58" , "GE_GENESIS-16-MONO2-Uncompressed-UnusualVR.dcm" } , { "8d398fce426d3a248d8c3f7582e3751d" , "GE_GENESIS-16-MONO2-WrongLengthItem.dcm" } , { "d9111c251fd785c328897e8eadc19dbc" , "GE_LOGIQBook-8-RGB-HugePreview.dcm" } , { "511da6acdb4f3189c93928e99b73ba39" , "GE_MR_0025xx1bProtocolDataBlock.dcm" } , { "d5efa34d8091e1ad04683eefb41f33c7" , "GE_RHAPSODE-16-MONO2-JPEG-Fragments.dcm" } , { "d41d8cd98f00b204e9800998ecf8427e" , "IM-0001-0066.dcm" } , { "cd085d783924d8a7fa2270ff40c6dc3e" , "ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm" } , { "40b0edf4b7c8a6f3756cbc1cd2d00359" , "JDDICOM_Sample2.dcm" } , { "e08545c49082b527a6446c9077227471" , "JDDICOM_Sample2-dcmdjpeg.dcm" } , { "9fc7096fd5d3ffdcbfe535f517689e62" , "JPEGDefinedLengthSequenceOfFragments.dcm" } , { "9c0548b6cc474c309686cfc3bdff7723" , "JPEG_LossyYBR.dcm" } , { "7c666b7c8fe0d52d906150d80d805cb7" , "KODAK-12-MONO1-Odd_Terminated_Sequence.dcm" } , { "492ba4d8a4b904a15a4f14fe35b31a16" , "KODAK_CompressedIcon.dcm" } , { "3b2388a839775bb10d45ff19465a63ce" , "LEADTOOLS_FLOWERS-16-MONO2-JpegLossless.dcm" } , { "3789010ccb4520b923e2bdc260377a2f" , "LEADTOOLS_FLOWERS-16-MONO2-RLE.dcm" } , { "27626466079fd8b8f8965947a0bba342" , "LEADTOOLS_FLOWERS-16-MONO2-Uncompressed.dcm" } , { "ee4b520d66c63601d228168c84a95150" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossless.dcm" } , { "dbd4d69de9e9579fa9938bbfba0bf770" , "LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm" } , { "43a20a3308793dabbc8ea4b7e0a0e04f" , "LEADTOOLS_FLOWERS-24-RGB-Uncompressed.dcm" } , { "8af486710c7ff58fdedc6543aec353fe" , "LEADTOOLS_FLOWERS-8-MONO2-JpegLossy.dcm" } , { "b708f5dd17424f0d2fe9355a345b5954" , "LEADTOOLS_FLOWERS-8-MONO2-RLE.dcm" } , { "e3ca577b17fbc3bb8c0b0da85cc9cd6c" , "LEADTOOLS_FLOWERS-8-MONO2-Uncompressed.dcm" } , { "0082bdcd44ae5d2681d645b49ec49a80" , "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm" } , { "6ac99a8ae372d278c96627f9cf76b6bb" , "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm" } , { "8fb0042d71596bb45e7387b0f0ed0d6b" , "libido1.0-vol.acr" } , { "05fe8714421e16371d62ae2c280b7107" , "LIBIDO-16-ACR_NEMA-Volume.dcm" } , { "251033db6d79bcfde7a8e17a814713a9" , "LIBIDO-24-ACR_NEMA-Rectangle.dcm" } , { "d71a08e78c1d33c858836f6c1a0f2231" , "LIBIDO-8-ACR_NEMA-Lena_128_128.acr" } , { "e39e4923be2d8bb2fb19c6c8deae216f" , "LJPEG_BuginGDCM12.dcm" } , { "e6bc657d132abebb01a675ade04129f1" , "MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm" } , { "4d808eca0d736b876cad3c566722d077" , "MAROTECH_CT_JP2Lossy.dcm" } , { "497d6ea45b8f3f7f6a3bf8125dcc43b1" , "MR16BitsAllocated_8BitsStored.dcm" } , { "cff201fb9749bd85a43d9bfb3675a25e" , "MR-Brucker-CineTagging-NonSquarePixels.dcm" } , { "31246836410a24124acf6bea5a36a942" , "MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm" } , { "84d300c76b8e8bee108d7a1e2da81319" , "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm" } , { "8419613dfb8d4b190ef8a988f8927bce" , "MR-MONO2-12-an2.acr" } , { "b4058b67ec1eb3d3d3acde27d51eb24a" , "MR-MONO2-12-angio-an1.acr" } , { "f782f6ea25928310bd69c3ca5c6a97d2" , "MR-MONO2-12-shoulder.dcm" } , { "7f6bccb00b34a7d277eacaffd2bb0362" , "MR-MONO2-16-head.dcm" } , { "294324abb8e0e5df7907fba58d60ab99" , "MR-MONO2-8-16x-heart.dcm" } , { "cd623ac04602182dc66adb505c516341" , "MR_Philips-Intera_BreaksNOSHADOW.dcm" } , { "ced145431248f1e00e9bdc23b0c61674" , "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm" } , { "8eab7fcf9c53d06968dde33f6b3a8918" , "MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm" } , { "3d24233b19788d349f64b7b267723186" , "MR_Philips_Intera_PrivateSequenceImplicitVR.dcm" } , { "1693399bc1edb7cdc494095a27201eab" , "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm" } , { "5797c9dfe94e4a4bccfbf81ab0aaa957" , "MR-SIEMENS-DICOM-WithOverlays.dcm" } , { "cc2f9bcd27cf7880482fcf72b9afd303" , "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm" } , { "bf324a1c91d3a09d9136f54f5910e570" , "MR_SIEMENS_forceLoad29-1010_29-1020.dcm" } , { "67d2eb3dba82f5d3ac5620b3fb7932d6" , "MR_Spectroscopy_SIEMENS_OF.dcm" } , { "1a5646a7b05840813c067d8c8dfa507e" , "NM-MONO2-16-13x-heart.dcm" } , { "1bc606b879ab7bd244782685f5f6149d" , "OsirixFake16BitsStoredFakeSpacing.dcm" } , { "bf793beb0e96f2399e467409e3cf5311" , "OT-MONO2-8-a7.dcm" } , { "7f4cddc9a88f8c5147b89f769eb1cae7" , "OT-PAL-8-face.dcm" } , { "5fce2728bd9457d4fc1224a374829e2f" , "PET-cardio-Multiframe-Papyrus.dcm" } , { "aa865ae5cf7c0c0320b58e7714155f13" , "PHILIPS_Brilliance_ExtraBytesInOverlay.dcm" } , { "020332d94a89fd2be159f9b82637db5d" , "PHILIPS_GDCM12xBug2.dcm" } , { "9f97969789e9ae279c87189a62ab12d4" , "PHILIPS_GDCM12xBug.dcm" } , { "c38ad661c6a14f8bd88b304755e7ba7b" , "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm" } , { "73d6489008482473f2839c3984d987c6" , "PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm" } , { "03d88060c3bd820b96840599c0099470" , "PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm" } , { "1f198bdb09f5e52dc3f9ad1dfced8a4d" , "PHILIPS_Intera-16-MONO2-Uncompress.dcm" } , { "4f34474ed72e6a5960fc4691e588f8e0" , "PICKER-16-MONO2-Nested_icon.dcm" } , { "629da04611e097e2cc532d6fe5e6454d" , "PICKER-16-MONO2-No_DicomV3_Preamble.dcm" } , { "3aaca1826b4a4deb9e41ebf2af4fa6b2" , "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm" } , { "62837f966bfd15ca8f9853cc905e20a4" , "RadBWLossLess.dcm" } , { "c2f13224f3f0bc3aa8bbfa6f4a0a23ec" , "rle16loo.dcm" } , { "bd5d9b2f994cfc0c6a95cca8c586533a" , "rle16sti.dcm" } , { "631c5bb2e2f046215999072d13316363" , "SIEMENS-12-Jpeg_Process_2_4-Lossy-a.dcm" } , { "d8e82f56fd66b15dc3bd055daa212143" , "SIEMENS_CSA2.dcm" } , { "fa919f3ee7cef3af1f362dd166d53103" , "SIEMENS_GBS_III-16-ACR_NEMA_1.acr" } , { "825580733e8cfaf5d8679348889db40d" , "SIEMENS_GBS_III-16-ACR_NEMA_1-ULis2Bytes.dcm" } , { "ff6bf3c70ef86ca08244317afd7fb98a" , "SIEMENS_ImageLocationUN.dcm" } , { "ac5f5bea451fd81aa2416fbab1a4e8c4" , "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm" } , { "5202b5e2521b1a5b480317864081beae" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm" } , { "8969371a42ecebc02f316a344a887c81" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm" } , { "c32e8171b87f3825bf6a37c4ed4b627a" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm" } , { "ea85da9fae20a585af6a71467916fa4a" , "SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm" } , { "1e22b1b3ef16b82cac4299279018282a" , "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm" } , { "16f02a1ee88f8753978a3dad9a5968ac" , "SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm" } , { "bec3be5aaf61c96757095120bc5db29e" , "SIEMENS_MAGNETOM-12-MONO2-VRUN.dcm" } , { "37e064a26737be39cfec1fa9078ba920" , "SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm" } , { "be0b7098b442990aebf3364d747af482" , "SIEMENS-MR-RGB-16Bits.dcm" } , { "a6469a8635a1b08b9642394e8dc6b350" , "SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs.acr" } , { "5fc4be2074b6186d3993818cd1baeb89" , "SIEMENS_Sonata-12-MONO2-SQ.dcm" } , { "c56ae357244ed3d4203c2b28fe3ab447" , "SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm" } , { "7176eb4ec64dab63578eb6826318c87d" , "SignedShortLosslessBug.dcm" } , { "3b7f193595e3954796ed5c15ba65f9e4" , "simpleImageWithIcon.dcm" } , { "cbd59e416dd82dc14df251ea6fccb55b" , "test.acr" } , { "0c2c475f6d21ae0aeadbf16565dcdbc4" , "TG18-CH-2k-01.dcm" } , { "e8cc7ed19eedf9bed9ab60683f3dbfa1" , "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm" } , { "aa708d3b15e451c8367e7909257d9346" , "TheralysGDCM120Bug.dcm" } , { "e8819809884c214fe78ee2b227417e5c" , "TOSHIBA_MRT150-16-MONO2-ACR_NEMA_2.dcm" } , { "203e3207fb53e4141341cd112fc2e867" , "undefined_length_un_vr.dcm" } , { "787ca80c8dd1aa619d5f85610862380b" , "US-GE-4AICL142.dcm" } , { "f1e9c893391e1d458cffa2a1e0904160" , "US-IRAD-NoPreambleStartWith0003.dcm" } , { "d1d9be67c9d066fabc8e1c4ae124f9a0" , "US-IRAD-NoPreambleStartWith0005.dcm" } , { "a917b69aed7c81f4e2fb5983ca340ebf" , "US-MONO2-8-8x-execho.dcm" } , { "d58a4930f5b436939d297730b883d5b9" , "US-PAL-8-10x-echo.dcm" } , { "b42152fc38f88b3a52f93003ab83a148" , "US-RGB-8-epicard.dcm" } , { "87fa2e4c03b664afa7f5b70cdaa5ac59" , "US-RGB-8-esopecho.dcm" } , { "7a3535f869f4a450b8de3d73a268e713" , "XA-MONO2-8-12x-catheter.dcm" } , { "167af475c7e2f4605544fa1602c34d50" , "IM-0001-0066.CommandTag00.dcm" }, { "d2cb6962750eb8f92c480e6cc2f4d104" , "GDCMJ2K_TextGBR.dcm" }, { "2e039bbc7520f809963e051ff5144ccf" , "UnexpectedSequenceDelimiterInFixedLengthSequence.dcm" }, { "5046074a1377d76f109df7ce331c8144" , "NM_Kakadu44_SOTmarkerincons.dcm" }, { "fdd8a53915712a924ac74c26ec4d1051" , "PhilipsInteraSeqTermInvLen.dcm" }, { "2940bd46f097f79012d24f47504c3c8c" , "TOSHIBA_J2K_OpenJPEGv2Regression.dcm" }, { "696917fea41e83b9980bad82b609162c" , "TOSHIBA_J2K_SIZ0_PixRep1.dcm" }, { "7ef3da46c43e51cfe2eb82e4d23dd623" , "TOSHIBA_J2K_SIZ1_PixRep0.dcm" }, { "5b77abdbd612e78f87efce4a211c3ccb" , "NM-PAL-16-PixRep1.dcm" }, { "27ccfa08495b406c9c5e1b686a8b35f9" , "MEDILABInvalidCP246_EVRLESQasUN.dcm" }, { "fb202f4c8b4f807031e57dd52b004d06" , "JPEGInvalidSecondFrag.dcm" }, { "2a8649f99c4ada4109b6aa7c52cf1a6a" , "SC16BitsAllocated_8BitsStoredJPEG.dcm" }, { "25cca40808c9ecdaac6316667c77daac" , "SC16BitsAllocated_8BitsStoredJ2K.dcm" }, { "98cd51ca2afc715fbfc659b4ba34991b" , "SIEMENS_SYNGO-12-MONO2-LUTWrongLength512.dcm" }, { "41d1baead629d878d09d6c1037faf47a" , "JPEGNote_empty.dcm" }, { "3cb9917c468226c265ef637aac5f4b61" , "JPEGLS_CharLS_10742.dcm" }, { "8381875d83ce321955a064e40d047dde" , "JPEGLosslessYBR_FULL_422.dcm" }, { "67f7b36ad6e54889b4a2581baa41afdf" , "JPEGNote_missing.dcm" }, { "807bf2aef3bc1885217c8a12d2d2bc19" , "JPEGNote_bogus.dcm" }, { "669cc0e807673ebe57124739a1874f35" , "RLEDebianBug816607Orig.dcm" }, { "1daa9bb53a8ce090041472f528248686" , "IllegalGroup2ImplicitTS.dcm" }, { "d8ca0903beb2ed12cf3083a13bd879e6" , "GE_MR_0025xx1bProtocolDataBlockXML.dcm" }, { "df3327313dadcc29e88779c7bc884abb" , "EmptyIcon_Bug417.dcm" }, { "7d0db54d48964c813d513b472f29155c" , "JPEGLosslessSeNonZero.dcm" }, { "44e6c3eef66b555ec3ae3e6dec6e8157" , "US-YBR_FULL_422-EVRLE.dcm" }, { "80deb837f8cfc1edc95f636ef099d431" , "Osirix10vs8BitsStored.dcm" }, { "a638f2bc00e67f35257f36e5d5caa6b0" , "Bug_Siemens_PrivateIconNoItem.dcm" }, { "f64bcbdf9396df3eb3cedd28457042da" , "HardcopyColor_YBR_RCT_J2K_PC1.dcm" }, { "4f9b4e5530f1d60472d85a641105c009" , "PET-GE-dicomwrite-PixelDataSQUNv2.dcm" }, { nullptr ,nullptr } }; int TestPrint(const char *filename, bool verbose= false) { gdcm::Reader r; r.SetFileName( filename ); if( !r.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } gdcm::Printer print; print.SetFile( r.GetFile() ); std::ostringstream out; if( verbose ) print.Print( std::cout ); #if defined(_MSC_VER) && (_MSC_VER <= 1800) // Visual Studio 2013 auto old_exponent_format = _set_output_format(_TWO_DIGIT_EXPONENT); #endif print.Print( out ); #if defined(_MSC_VER) && (_MSC_VER <= 1800) // Visual Studio 2013 _set_output_format(old_exponent_format); #endif gdcm::Filename fn( filename ); const char *name = fn.GetName(); std::string buf = out.str(); if( buf.find( "GDCM:UNKNOWN" ) != std::string::npos ) { if( strcmp(name, "test.acr" ) != 0 && strcmp(name, "LIBIDO-8-ACR_NEMA-Lena_128_128.acr" ) != 0 && strcmp(name, "gdcm-ACR-LibIDO.acr" ) != 0 && strcmp(name, "SIEMENS_GBS_III-16-ACR_NEMA_1.acr" ) != 0 && strcmp(name, "LIBIDO-24-ACR_NEMA-Rectangle.dcm" ) != 0 && strcmp(name, "NM_Kakadu44_SOTmarkerincons.dcm" ) != 0 && strcmp(name, "GE_MR_0025xx1bProtocolDataBlockXML.dcm" ) != 0 ) { std::cerr << "UNKNOWN Attribute with : " << name << std::endl; return 1; } } char digest[33]; gdcm::Testing::ComputeMD5(&buf[0], buf.size(), digest); unsigned int i = 0; const char *p = printmd5[i][1]; while( p != nullptr ) { if( strcmp( name, p ) == 0 ) { break; } ++i; p = printmd5[i][1]; } const char *refmd5 = printmd5[i][0]; if( !refmd5 ) { std::cerr << "Problem with : " << name << " missing md5= " << digest << std::endl; return 1; } if( strcmp( refmd5, digest) ) { std::cerr << "Problem with : " << name << " " << refmd5 << " vs " << digest << std::endl; return 1; } return 0; } int TestPrinter1(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestPrint(filename, true); } // else int r = 0, i = 0; gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestPrint( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestPrinter2.cxx000066400000000000000000000035451412732066400257710ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmPrinter.h" #include "gdcmFilename.h" #include "gdcmTesting.h" #include "gdcmGlobal.h" #include "gdcmDicts.h" /* This test exercise a very obscure section of gdcm::Printer when it handles a SQ when it is hidden as VR::UN + undefined length which means this is a Implicit VR Little Endian encoded SQ in an Explicit VR Little Endian DataSet */ int TestPrinter2(int , char *[]) { const char *directory = gdcm::Testing::GetDataRoot(); std::string filename = std::string(directory) + "/undefined_length_un_vr.dcm"; gdcm::Reader r; r.SetFileName( filename.c_str() ); if( !r.Read() ) { return 1; } gdcm::Printer print; print.SetFile( r.GetFile() ); std::ostringstream out; print.Print( out ); gdcm::Global &g = gdcm::Global::GetInstance(); gdcm::Dicts &dicts = g.GetDicts(); gdcm::PrivateDict &priv_dict = dicts.GetPrivateDict(); gdcm::PrivateTag pt(0x2001,0x005f,"Philips Imaging DD 001"); if( !priv_dict.RemoveDictEntry( pt ) ) { return 1; } gdcm::Reader r2; r2.SetFileName( filename.c_str() ); if( !r2.Read() ) { return 1; } gdcm::Printer print2; print2.SetFile( r.GetFile() ); std::ostringstream out2; print2.Print( out2 ); // if( out2.str() != out.str() ) // { // return 1; // } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestRAWCodec.cxx000066400000000000000000000012451412732066400256460ustar00rootroot00000000000000/*========================================================================= 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 "gdcmRAWCodec.h" int TestRAWCodec(int argc, char *argv[]) { (void)argc; (void)argv; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestRLECodec.cxx000066400000000000000000000014061412732066400256360ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTypes.h" int TestRLECodec(int, char *[]) { // Compress a black images: should give a good result // Compress a checkboard (black/white alternate). Should give a mediocre result return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestRescaler1.cxx000066400000000000000000000106761412732066400261100ustar00rootroot00000000000000/*========================================================================= 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 "gdcmRescaler.h" #include #include // atof static bool check_roundtrip(const gdcm::PixelFormat & pf ) { gdcm::Rescaler r; r.SetIntercept( 0. ); r.SetSlope( 1. ); r.SetPixelFormat( pf ); r.SetMinMaxForPixelType((double)pf.GetMin(),(double)pf.GetMax()); const gdcm::PixelFormat outputpt = r.ComputePixelTypeFromMinMax(); if( outputpt != pf ) return false; return true; } int TestRescaler1(int, char *[]) { gdcm::Rescaler ir; /* gdcmData/MR-MONO2-12-shoulder.dcm (gdb) p intercept $1 = 6.0999999999999999e-05 (gdb) p slope $2 = 3.774114 (gdb) p in[i] $3 = 3.77417493 ... p (in[i] - intercept)/slope $7 = 0.99999998109891775 $10 = {Intercept = 6.0999999999999999e-05, Slope = 3.774114, PF = {SamplesPerPixel = 1, BitsAllocated = 32, BitsStored = 32, HighBit = 31, PixelRepresentation = 3}, ScalarRangeMin = 6.0999998822808266e-05, ScalarRangeMax = 247336.561051} */ // (0028,1052) DS [0.000061] # 8, 1 RescaleIntercept // (0028,1053) DS [3.774114] # 8, 1 RescaleSlope const double intercept = atof( "0.000061" ); const double slope = atof( "3.774114" ); ir.SetIntercept( intercept ); ir.SetSlope( slope ); ir.SetPixelFormat( gdcm::PixelFormat::FLOAT64 ); const double smin = 6.0999998822808266e-05; const double smax = 247336.561051; ir.SetMinMaxForPixelType( smin, smax ); double outref[] = { 0 }; { char *copy = (char*)outref; const uint16_t in[] = { 1 }; const char *tempimage = (const char*)in; size_t vtklen = sizeof(in); ir.SetPixelFormat( gdcm::PixelFormat::UINT16 ); bool b = ir.Rescale(copy,tempimage,vtklen); if( !b ) return 1; std::cout << outref[0] << std::endl; } ir.SetPixelFormat( gdcm::PixelFormat::FLOAT64 ); uint16_t out[] = { 0 }; char *copy = (char*)out; //const double in[] = { 3.77417493 }; const double in[] = { 3.774175 }; if( outref[0] != in[0] ) { std::cerr << "Wrong input/output:" << std::endl; std::cerr << outref[0] << " vs " << in[0] << std::endl; std::cerr << (outref[0] - in[0]) << std::endl; return 1; } const char *tempimage = (const char*)in; size_t vtklen = sizeof(in); ir.InverseRescale(copy,tempimage,vtklen); std::cout << out[0] << std::endl; if( out[0] != 1 ) { return 1; } // Let's make sure that rescaler works in the simplest case // it should be idempotent: { gdcm::PixelFormat pixeltype = gdcm::PixelFormat::INT16; gdcm::Rescaler r; r.SetIntercept( 0.0 ); r.SetSlope( 1.0 ); r.SetPixelFormat( pixeltype ); gdcm::PixelFormat::ScalarType outputpt; outputpt = r.ComputeInterceptSlopePixelType(); if( outputpt != pixeltype ) { return 1; } if( ! (outputpt == pixeltype) ) { return 1; } } { gdcm::PixelFormat::ScalarType outputpt ; double shift = -1024; double scale = 1; // gdcmData/CT-MONO2-16-ort.dcm gdcm::PixelFormat pixeltype( 1, 16, 16, 15, 1 ); gdcm::Rescaler r; r.SetIntercept( shift ); r.SetSlope( scale ); r.SetPixelFormat( pixeltype ); outputpt = r.ComputeInterceptSlopePixelType(); // min,max = [-33792, 31743] // we need at least int32 to store that if( outputpt != gdcm::PixelFormat::INT32 ) { return 1; } // let's pretend image is really the full range: // FIXME: I think it is ok to compute this way since shift is double anyway: r.SetMinMaxForPixelType(std::numeric_limits::min() + shift,std::numeric_limits::max() + shift ); gdcm::PixelFormat pf2 = r.ComputePixelTypeFromMinMax(); if( pf2 != pixeltype ) { return 1; } } // ComputePixelTypeFromMinMax() { if( !check_roundtrip(gdcm::PixelFormat(1,16,12,11,0) ) ) return 1; if( !check_roundtrip(gdcm::PixelFormat(1,16,12,11,1) ) ) return 1; if( !check_roundtrip(gdcm::PixelFormat(1,8,8,7,0) ) ) return 1; if( !check_roundtrip(gdcm::PixelFormat(1,8,8,7,1) ) ) return 1; } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestRescaler2.cxx000066400000000000000000000145201412732066400261010ustar00rootroot00000000000000/*========================================================================= 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 "gdcmRescaler.h" #include #include template < typename T > struct TypeToPixelFormat; template<> struct TypeToPixelFormat { enum { Type = gdcm::PixelFormat::FLOAT64 }; }; template<> struct TypeToPixelFormat { enum { Type = gdcm::PixelFormat::FLOAT32 }; }; template<> struct TypeToPixelFormat { enum { Type = gdcm::PixelFormat::INT16 }; }; template<> struct TypeToPixelFormat { enum { Type = gdcm::PixelFormat::UINT16 }; }; template<> struct TypeToPixelFormat { enum { Type = gdcm::PixelFormat::UINT8 }; }; template<> struct TypeToPixelFormat { enum { Type = gdcm::PixelFormat::INT8 }; }; template<> struct TypeToPixelFormat { enum { Type = gdcm::PixelFormat::INT32 }; }; template bool TestRescaler2Func( const double intercept, const double slope, const unsigned short bitsallocated, const unsigned short bitsstored, const unsigned short pixelrepresentation, const bool best_fit ) { const gdcm::PixelFormat pixeltype(1,bitsallocated,bitsstored, (unsigned short)(bitsstored-1),pixelrepresentation); uint8_t ps = pixeltype.GetPixelSize(); // programmer error: if( ps != sizeof( input_pixel ) ) return false; if( pixelrepresentation ) // signed { if( std::numeric_limits::min() == 0 ) return false; } else { if( std::numeric_limits::min() != 0 ) return false; } gdcm::Rescaler r; r.SetIntercept( intercept ); r.SetSlope( slope ); r.SetPixelFormat( pixeltype ); const int64_t min = pixeltype.GetMin(); const int64_t max = pixeltype.GetMax(); gdcm::PixelFormat::ScalarType outputpt; outputpt = r.ComputeInterceptSlopePixelType(); gdcm::PixelFormat::ScalarType targetpixeltype = (gdcm::PixelFormat::ScalarType)TypeToPixelFormat::Type; if( best_fit ) { if( targetpixeltype != outputpt ) { return false; } } else { if( targetpixeltype == outputpt ) { return false; } } r.SetTargetPixelType( targetpixeltype ); r.SetUseTargetPixelType(true); std::vector values; const int nvalues = 1 << bitsstored; values.reserve( nvalues ); for( int i = 0; i < nvalues; ++i ) { //values.push_back( (input_pixel)(std::numeric_limits::min() + i) ); values.push_back( (input_pixel)(min + i) ); } std::vector output; output.resize( nvalues ); if( !r.Rescale((char*)&output[0],(char*)&values[0],nvalues * sizeof( values[0] ) ) ) return false; // get the min/max: double min2 = (double)output[0]; double max2 = (double)output[nvalues-1]; if( min2 > max2 ) return false; if( intercept == 0 && slope == 1 ) { if( min != min2 ) return false; if( max != max2 ) return false; } gdcm::Rescaler ir; ir.SetIntercept( intercept ); ir.SetSlope( slope ); ir.SetPixelFormat( targetpixeltype ); ir.SetMinMaxForPixelType( min2, max2 ); const gdcm::PixelFormat pf2 = ir.ComputePixelTypeFromMinMax(); if( pf2 != pixeltype ) return false; std::vector check; check.resize( nvalues ); if( check == values ) // dummy check return false; if( !ir.InverseRescale((char*)&check[0],(char*)&output[0], nvalues * sizeof( output[0] ) ) ) return false; if( check != values ) return false; return true; } int TestRescaler2(int, char *[]) { { double intercept = 0.000061; double slope = 3.774114; // Case 1. // gdcmData/MR-MONO2-12-shoulder.dcm // (0028,0100) US 16 # 2,1 Bits Allocated // (0028,0101) US 12 # 2,1 Bits Stored // (0028,0102) US 11 # 2,1 High Bit // (0028,0103) US 0 # 2,1 Pixel Representation // [...] // (0028,1052) DS [0.000061] # 8,1 Rescale Intercept // (0028,1053) DS [3.774114] # 8,1 Rescale Slope if( !TestRescaler2Func(intercept, slope,16,12,0,true) ) return 1; // Case 2. // use float instead of default double if( !TestRescaler2Func(intercept, slope,16,12,0,false) ) return 1; } { double intercept = 0; double slope = 1; // Case 3. if( !TestRescaler2Func(intercept, slope,16,12,0,false) ) return 1; // Case 4. if( !TestRescaler2Func(intercept, slope,16,12,0,false) ) return 1; // Case 5. best fit if( !TestRescaler2Func(intercept, slope,16,12,0,true) ) return 1; // Case 6. unsigned char: if( !TestRescaler2Func(intercept,slope,8,8,0,true) ) return 1; // Case 7. char if( !TestRescaler2Func(intercept,slope,8,7,0,false) ) return 1; } { double intercept = 0; double slope = 1; // Case 8. if( !TestRescaler2Func(intercept,slope,16,12,1,false) ) return 1; // Case 9. if( !TestRescaler2Func(intercept, slope,16,12,1,false) ) return 1; // Case 10. best fit if( !TestRescaler2Func(intercept, slope,16,12,1,true) ) return 1; // Case 11. unsigned char: if( !TestRescaler2Func(intercept,slope,8,8,1,true) ) return 1; // Case 12. char if( !TestRescaler2Func(intercept,slope,8,7,1,true) ) return 1; } { double intercept = -1024; double slope = 1; // Case 13. if( !TestRescaler2Func(intercept, slope,16,12,0,true) ) return 1; // Case 14. if( !TestRescaler2Func(intercept, slope,16,12,0,false) ) return 1; // Case 15. if( !TestRescaler2Func(intercept, slope,8,8,0,true) ) return 1; // Case 16. if( !TestRescaler2Func(intercept, slope,8,8,0,false) ) return 1; } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestScanner1.cxx000066400000000000000000000151441412732066400257340ustar00rootroot00000000000000/*========================================================================= 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 "gdcmScanner.h" #include "gdcmDirectory.h" #include "gdcmSystem.h" #include "gdcmTesting.h" #include "gdcmTrace.h" // dcmdump /path/to/image/*.dcm 2>&/dev/null| grep 0020 | grep "000e\|000d" | sort | uniq // // $ find /images/ -type f -exec dcmdump -s +P 0010,0010 {} \; static int TestScannerExtra() { const char *extradataroot = gdcm::Testing::GetDataExtraRoot(); if( !extradataroot ) { return 1; } if( !gdcm::System::FileIsDirectory(extradataroot) ) { std::cerr << "No such directory: " << extradataroot << std::endl; return 1; } gdcm::Directory d; unsigned int nfiles = d.Load( extradataroot, true ); // no recursion std::cout << "done retrieving file list. " << nfiles << " files found." << std::endl; gdcm::Scanner s; const gdcm::Tag t1(0x0020,0x000d); // Study Instance UID const gdcm::Tag t2(0x0020,0x000e); // Series Instance UID const gdcm::Tag t3(0x0010,0x0010); // Patient's Name const gdcm::Tag t4(0x0004,0x5678); // DUMMY element const gdcm::Tag t5(0x0028,0x0010); // Rows const gdcm::Tag t6(0x0028,0x0011); // Columns s.AddTag( t1 ); s.AddTag( t2 ); s.AddTag( t3 ); s.AddTag( t4 ); s.AddTag( t5 ); s.AddTag( t6 ); bool b = s.Scan( d.GetFilenames() ); if( !b ) { std::cerr << "Scanner failed" << std::endl; return 1; } //s.Print( std::cout ); return 0; } int TestScanner1(int argc, char *argv[]) { gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); const char *directory = gdcm::Testing::GetDataRoot(); if( argc == 2 ) { directory = argv[1]; } if( !gdcm::System::FileIsDirectory(directory) ) { std::cerr << "No such directory: " << directory << std::endl; return 1; } gdcm::Directory d; unsigned int nfiles = d.Load( directory ); // no recursion // d.Print( std::cout ); std::cout << "done retrieving file list. " << nfiles << " files found." << std::endl; gdcm::Scanner s; const gdcm::Tag t1(0x0020,0x000d); // Study Instance UID const gdcm::Tag t2(0x0020,0x000e); // Series Instance UID const gdcm::Tag t3(0x0010,0x0010); // Patient's Name const gdcm::Tag t4(0x0004,0x5678); // DUMMY element const gdcm::Tag t5(0x0028,0x0010); // Rows const gdcm::Tag t6(0x0028,0x0011); // Columns const gdcm::Tag t7(0x0008,0x0016); // s.AddTag( t1 ); s.AddTag( t2 ); s.AddTag( t3 ); s.AddTag( t4 ); s.AddTag( t5 ); s.AddTag( t6 ); s.AddTag( t7 ); bool b = s.Scan( d.GetFilenames() ); if( !b ) { std::cerr << "Scanner failed" << std::endl; return 1; } // s.Print( std::cout ); gdcm::Directory::FilenamesType const & files = s.GetFilenames(); if( files != d.GetFilenames() ) { return 1; } int numerrors = 0; for( gdcm::Directory::FilenamesType::const_iterator it = files.begin(); it != files.end(); ++it ) { const char *filename = it->c_str(); const char* value = s.GetValue(filename, t7); const char *msstr = gdcm::Testing::GetMediaStorageFromFile(filename); if( msstr && strcmp(msstr, "1.2.840.10008.1.3.10" ) == 0 ) { // would need to check (0002,0002)... } if( value && msstr ) { if( strcmp( value, msstr ) != 0 ) { std::cerr << "Problem with file " << filename << std::endl; std::cerr << value << "/" << msstr << std::endl; ++numerrors; } } else { if ( !msstr ) { std::cerr << "Problem with file " << filename << std::endl; if( value ) std::cerr << "Value found: " << value << std::endl; ++numerrors; } } } if( numerrors ) return numerrors; // Check dummy filename: bool iskey = s.IsKey( "gdcm.rocks.invalid.name" ); if( iskey ) { std::cout << "IsKey returned: " << iskey << std::endl; return 1; } // Let's get the value for tag t1 in first file: gdcm::Scanner::MappingType const &mt = s.GetMappings(); std::string sfilename; sfilename = gdcm::Testing::GetDataRoot(); sfilename+= "/test.acr"; { //const char *filename = d.GetFilenames()[0].c_str(); const char *filename = sfilename.c_str(); // The following breaks with Papyrus file: PET-cardio-Multiframe-Papyrus.dcm unsigned int i = 0; gdcm::Scanner::MappingType::const_iterator it = mt.find(filename); assert( it != mt.end() ); while( it == mt.end() ) { ++i; if( i == d.GetFilenames().size() ) { return 1; } filename = d.GetFilenames()[i].c_str(); it = mt.find(filename); } std::cout << "Mapping for " << filename << " is :" << std::endl; const gdcm::Scanner::TagToValue &tv = it->second; //const std::string &filename = d.GetFilenames()[0]; gdcm::Scanner::TagToValue::const_iterator it2 = tv.find( t5 ); if( it2 == tv.end() || t5 != it2->first ) { std::cerr << "Could not find tag:" << t5 << std::endl; return 1; } const char * t1value = it2->second; std::cout << filename << " -> " << t1 << " = " << (*t1value ? t1value : "none" ) << std::endl; } const gdcm::Directory::FilenamesType &filenames = d.GetFilenames(); { gdcm::Directory::FilenamesType::const_iterator it = filenames.begin(); for(; it != filenames.end(); ++it) { const char *filename = it->c_str(); const gdcm::Tag &reftag = t6; const char *value = s.GetValue( filename, reftag ); if( value ) { assert( value ); std::cout << filename << " has " << reftag << " = " << value << std::endl; } else { std::cout << filename << " has " << reftag << " = no value or not DICOM" << std::endl; } } } /* { std::vector keys = s.GetKeys(); for( std::vector::const_iterator it = keys.begin(); it != keys.end(); ++it) { const char *filename = *it; const gdcm::Directory::FilenamesType::const_iterator it2 = std::find(filenames.begin(), filenames.end(), filename); if( it2 == filenames.end() ) { return 1; } if( !s.IsKey( filename ) ) { return 1; } } } */ // puposely discard gdcmDataExtra test, this is just an 'extra' test... int b2 = TestScannerExtra(); (void)b2; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestScanner2.cxx000066400000000000000000000036651412732066400257420ustar00rootroot00000000000000/*========================================================================= 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 "gdcmScanner.h" #include "gdcmDirectory.h" #include "gdcmSystem.h" #include "gdcmTesting.h" #include "gdcmTrace.h" int TestScanner2(int argc, char *argv[]) { gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); const char *directory = gdcm::Testing::GetDataRoot(); if( argc == 2 ) { directory = argv[1]; } if( !gdcm::System::FileIsDirectory(directory) ) { std::cerr << "No such directory: " << directory << std::endl; return 1; } gdcm::Directory d; unsigned int nfiles = d.Load( directory ); // no recursion std::cout << "done retrieving file list. " << nfiles << " files found." << std::endl; gdcm::Scanner s; const gdcm::Tag t2(0x0020,0x000e); // Series Instance UID s.AddTag( t2 ); bool b = s.Scan( d.GetFilenames() ); if( !b ) { std::cerr << "Scanner failed" << std::endl; return 1; } gdcm::Directory::FilenamesType const & files = s.GetFilenames(); if( files != d.GetFilenames() ) { return 1; } const char str1[] = "1.3.12.2.1107.5.2.4.7630.20010301125744000008"; gdcm::Directory::FilenamesType fns = s.GetAllFilenamesFromTagToValue(t2, str1); // all SIEMENS_MAGNETOM-12-MONO2-FileSeq*.dcm: if( fns.size() != 4 ) return 1; const char str2[] = "1.3.12.2.1107.5.2.4.7630.2001030112574400000"; fns = s.GetAllFilenamesFromTagToValue(t2, str2); if( !fns.empty() ) return 1; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSegmentedPaletteColorLookupTable.cxx000066400000000000000000000013331412732066400326500ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSegmentedPaletteColorLookupTable.h" int TestSegmentedPaletteColorLookupTable(int, char *[]) { gdcm::SegmentedPaletteColorLookupTable o; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSerieHelper.cxx000066400000000000000000000012351412732066400264650ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSerieHelper.h" int TestSerieHelper(int, char *[]) { gdcm::SerieHelper sh; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSorter.cxx000066400000000000000000000025331412732066400255360ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSorter.h" #include "gdcmTesting.h" int TestSorter(int argc, char *argv[]) { // Black box: gdcm::Directory::FilenamesType fns; gdcm::Sorter s; // No sort function and fns is empty if( !s.Sort( fns ) ) { return 1; } // White box: const char *directory = gdcm::Testing::GetDataRoot(); if( argc == 2 ) { directory = argv[1]; } gdcm::Directory d; unsigned int nfiles = d.Load( directory ); // no recursion d.Print( std::cout ); std::cout << "done retrieving file list. " << nfiles << " files found." << std::endl; /* bool b = s.Sort( d.GetFilenames() ); if( !b ) { std::cerr << "Failed to sort:" << directory << std::endl; return 1; } std::cout << "Sorting succeeded:" << std::endl; s.Print( std::cout ); */ return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSpacing.cxx000066400000000000000000000027361412732066400256510ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSpacing.h" int TestSpacing(int argc, char *argv[]) { (void)argc; (void)argv; gdcm::Spacing s; // gdcmData/gdcm-MR-PHILIPS-16-NonSquarePixels.dcm // (0028,0030) DS [ 0.487416\0.194966] # 18,2 Pixel Spacing // 0.487416 / 0.194966 = 2.5000051290994327 // Simple case ratio 1:1 gdcm::Attribute<0x28,0x30> pixelspacing = {{0.5, 0.5}}; gdcm::Attribute<0x28,0x34> par = gdcm::Spacing::ComputePixelAspectRatioFromPixelSpacing(pixelspacing); if( par[0] != 1 || par[1] != 1 ) { std::cerr << "par[0] = " << par[0] << " par[1]=" << par[1] << std::endl; return 1; } // More complex pixelspacing[0] = 0.487416; pixelspacing[1] = 0.194966; par = gdcm::Spacing::ComputePixelAspectRatioFromPixelSpacing(pixelspacing); if( par[0] != 5 || par[1] != 2 ) { std::cerr << "par[0] = " << par[0] << " par[1]=" << par[1] << std::endl; return 1; } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSpectroscopy.cxx000066400000000000000000000013201412732066400267460ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSpectroscopy.h" int TestSpectroscopy(int argc, char *argv[]) { (void)argc; (void)argv; gdcm::Spectroscopy w; (void)w; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSplitMosaicFilter.cxx000066400000000000000000000100341412732066400276500ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSplitMosaicFilter.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmImageReader.h" static bool reorganize_mosaic_invert(unsigned short *input, const unsigned int *inputdims, unsigned int square, const unsigned int *outputdims, const unsigned short *output ) { for(unsigned x = 0; x < outputdims[0]; ++x) { for(unsigned y = 0; y < outputdims[1]; ++y) { for(unsigned z = 0; z < outputdims[2]; ++z) { size_t outputidx = x + y*outputdims[0] + z*outputdims[0]*outputdims[1]; size_t inputidx = (x + (z%square)*outputdims[0]) + (y + (z/square)*outputdims[1])*inputdims[0]; input[ inputidx ] = output[ outputidx ]; } } } return true; } int TestSplitMosaicFilter(int argc, char *argv[]) { std::string filename; if( argc == 2 ) { filename = argv[1]; } else { const char *extradataroot = gdcm::Testing::GetDataExtraRoot(); if( !extradataroot ) { return 1; } if( !gdcm::System::FileIsDirectory(extradataroot) ) { std::cerr << "No such directory: " << extradataroot << std::endl; return 1; } filename = extradataroot; filename += "/gdcmSampleData/images_of_interest/MR-sonata-3D-as-Tile.dcm"; } gdcm::SplitMosaicFilter s; // std::cout << filename << std::endl; if( !gdcm::System::FileExists(filename.c_str()) ) { return 1; } gdcm::ImageReader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "could not read: " << filename << std::endl; return 1; } const gdcm::Image &image = reader.GetImage(); unsigned int inputdims[3] = { 0, 0, 1 }; const unsigned int *dims = image.GetDimensions(); inputdims[0] = dims[0]; inputdims[1] = dims[1]; gdcm::SplitMosaicFilter filter; filter.SetImage( reader.GetImage() ); filter.SetFile( reader.GetFile() ); bool b = filter.Split(); if( !b ) { std::cerr << "Could not split << " << filename << std::endl; return 1; } unsigned int modims[3]; b = filter.ComputeMOSAICDimensions( modims ); if( !b ) { std::cerr << "Could not ComputeMOSAICDimensions << " << filename << std::endl; return 1; } const unsigned int ref[3] = { 64u, 64u, 31u }; if( modims[0] != ref[0] || modims[1] != ref[1] || modims[2] != ref[2] ) { std::cerr << "Invalid ComputeMOSAICDimensions << " << filename << std::endl; return 1; } // const gdcm::Image &image = filter.GetImage(); unsigned long l = image.GetBufferLength(); std::vector buf; buf.resize(l); if( !image.GetBuffer( &buf[0] ) ) { std::cerr << "Could not GetBuffer << " << filename << std::endl; return 1; } std::vector outbuf; unsigned long ll = inputdims[0] * inputdims[1] * sizeof( unsigned short ); outbuf.resize(ll); const unsigned int *mos_dims = image.GetDimensions(); unsigned int div = (unsigned int )ceil(sqrt( (double)mos_dims[2]) ); reorganize_mosaic_invert((unsigned short *)&outbuf[0], inputdims, div, mos_dims, (const unsigned short*)&buf[0] ); #if 0 std::ofstream o( "/tmp/debug", std::ios::binary ); o.write( &outbuf[0], ll ); o.close(); #endif char digest[33]; gdcm::Testing::ComputeMD5(&outbuf[0], ll, digest); // $ gdcminfo --md5sum gdcmSampleData/images_of_interest/MR-sonata-3D-as-Tile.dcm if( strcmp(digest, "be96c01db8a0ec0753bd43f6a985345c" ) != 0 ) { std::cerr << "Problem found: " << digest << std::endl; return 1; } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSplitMosaicFilter2.cxx000066400000000000000000000134641412732066400277440ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSplitMosaicFilter.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmAnonymizer.h" #include "gdcmPrivateTag.h" #include "gdcmCSAHeader.h" #include "gdcmElement.h" #include "gdcmDirectionCosines.h" int TestSplitMosaicFilter2(int argc, char *argv[]) { std::string filename; if( argc == 2 ) { filename = argv[1]; } else { const char *extradataroot = gdcm::Testing::GetDataExtraRoot(); if( !extradataroot ) { return 1; } if( !gdcm::System::FileIsDirectory(extradataroot) ) { std::cerr << "No such directory: " << extradataroot << std::endl; return 1; } filename = extradataroot; filename += "/gdcmSampleData/images_of_interest/MR-sonata-3D-as-Tile.dcm"; } gdcm::SplitMosaicFilter s; if( !gdcm::System::FileExists(filename.c_str()) ) { return 1; } gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "could not read: " << filename << std::endl; return 1; } gdcm::SplitMosaicFilter filter; filter.SetFile( reader.GetFile() ); bool inverted; double slicenormal[3]; bool b = filter.ComputeMOSAICSliceNormal( slicenormal, inverted ); if( !b ) { std::cerr << "Could not ComputeMOSAICSliceNormal: " << filename << std::endl; return 1; } // SliceNormalVector is slightly less precise that sNormal: //const double refnormal[3] = {-0.08193696,0.08808136,0.99273763}; // Value as read from sNormal (sSlice) const double refnor[3] = { -0.08193693363, 0.08808135446, 0.992737636 }; const double eps = 1e-6; gdcm::DirectionCosines dc; const double dot = dc.Dot( slicenormal, refnor ); if( std::fabs( 1.0 - dot ) > eps ) { std::cerr << "Invalid ComputeMOSAICSliceNormal: " << filename << std::endl; return 1; } double slicepos[3]; b = filter.ComputeMOSAICSlicePosition( slicepos, inverted ); if( !b ) { std::cerr << "Could not ComputeMOSAICSlicePosition: " << filename << std::endl; return 1; } const double refpos[3] = { 2.24891108,-52.65585315,-26.94105767 }; for( int i = 0; i < 3; ++i ) { if( std::fabs( refpos[i] - slicepos[i] ) > eps ) { std::cerr << "Invalid ComputeMOSAICSlicePosition: " << filename << std::endl; return 1; } } gdcm::CSAHeader csa; gdcm::DataSet & ds = reader.GetFile().GetDataSet(); gdcm::MrProtocol mrprot; if( !csa.GetMrProtocol(ds, mrprot)) { std::cerr << "No MrProtocol" << filename << std::endl; return 1; } gdcm::MrProtocol::SliceArray sa; b = mrprot.GetSliceArray(sa); if( !b || sa.Slices.size() != 31 ) { return 1; } gdcm::MrProtocol::Slice & slice0 = sa.Slices[0]; gdcm::MrProtocol::Vector3 & p0 = slice0.Position; double pos0[3]; pos0[0] = p0.dSag; pos0[1] = p0.dCor; pos0[2] = p0.dTra; for( int i = 0; i < 3; ++i ) { if( std::fabs( refpos[i] - pos0[i] ) > eps ) { std::cerr << "Invalid slice0: " << filename << std::endl; return 1; } } gdcm::MrProtocol::Slice & slice1 = sa.Slices[1]; gdcm::MrProtocol::Vector3 & p1 = slice1.Position; double pos1[3]; pos1[0] = p1.dSag; pos1[1] = p1.dCor; pos1[2] = p1.dTra; double altnor[3]; for( int i = 0; i < 3; ++i ) { altnor[i] = pos1[i] - pos0[i]; } dc.Normalize( altnor ); const double dot2 = dc.Dot( altnor, refnor ); if( std::fabs( 1.0 - dot2 ) > eps ) { std::cerr << "Incompatible alt " << filename << std::endl; return 1; } for( int k = 0; k < 31; ++k ) { gdcm::MrProtocol::Slice & slice = sa.Slices[k]; gdcm::MrProtocol::Vector3 & nor = slice.Normal; double normal[3]; normal[0] = nor.dSag; normal[1] = nor.dCor; normal[2] = nor.dTra; for( int i = 0; i < 3; ++i ) { if( std::fabs( refnor[i] - normal[i] ) > eps ) { std::cerr << "Invalid normal: " << filename << std::endl; return 1; } } } gdcm::Anonymizer ano; ano.SetFile( reader.GetFile() ); const gdcm::PrivateTag &t1 = csa.GetCSAImageHeaderInfoTag(); ano.Remove( t1 ); unsigned int modims[3]; b = filter.ComputeMOSAICDimensions( modims ); if( b ) return 1; // alternate code path: gdcm::PrivateTag t2 (0x0019,0x0a, "SIEMENS MR HEADER"); if( ds.FindDataElement( t2 ) ) { return 1; } else { // Create a fake one: std::string creator = ds.GetPrivateCreator( t2 ); if( !creator.empty() ) return 1; gdcm::Tag t3 (0x0019,0x10); ano.Replace( t3, t2.GetOwner() ); gdcm::Element elem; elem.SetValue( 31 ); gdcm::DataElement de = elem.GetAsDataElement(); de.SetTag( t2 ); const uint16_t el = de.GetTag().GetElement(); de.GetTag().SetElement( 0x1000 + el ); if( de.GetVR() != gdcm::VR::US ) return 1; ds.Insert( de ); creator = ds.GetPrivateCreator( de.GetTag() ); if( creator.empty() ) return 1; } b = filter.ComputeMOSAICDimensions( modims ); if( !b ) { std::cerr << "Could not ComputeMOSAICDimensions " << filename << std::endl; return 1; } const unsigned int ref[3] = { 64u, 64u, 31u }; if( modims[0] != ref[0] || modims[1] != ref[1] || modims[2] != ref[2] ) { std::cerr << "Invalid ComputeMOSAICDimensions " << filename << std::endl; return 1; } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSplitMosaicFilter3.cxx000066400000000000000000000110501412732066400277320ustar00rootroot00000000000000/*========================================================================= 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 "gdcmSplitMosaicFilter.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmReader.h" #include "gdcmAnonymizer.h" #include "gdcmPrivateTag.h" #include "gdcmCSAHeader.h" #include "gdcmElement.h" #include "gdcmDirectionCosines.h" int TestSplitMosaicFilter3(int , char *[]) { const char *directory = gdcm::Testing::GetDataRoot(); std::string filename = std::string(directory) + "/SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm"; gdcm::SplitMosaicFilter s; if( !gdcm::System::FileExists(filename.c_str()) ) { return 1; } gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { std::cerr << "could not read: " << filename << std::endl; return 1; } gdcm::SplitMosaicFilter filter; filter.SetFile( reader.GetFile() ); bool inverted; double slicenormal[3]; bool b = filter.ComputeMOSAICSliceNormal( slicenormal, inverted ); if( !b ) { std::cerr << "Could not ComputeMOSAICSliceNormal: " << filename << std::endl; return 1; } const double refnor[3] = { -0.03737130908,-0.314588168,0.9484923141 }; const double eps = 1e-6; gdcm::DirectionCosines dc; const double dot = dc.Dot( slicenormal, refnor ); if( std::fabs( 1.0 - dot ) > eps ) { std::cerr << "Invalid ComputeMOSAICSliceNormal: " << filename << std::endl; return 1; } double slicepos[3]; b = filter.ComputeMOSAICSlicePosition( slicepos, inverted ); if( !b ) { std::cerr << "Could not ComputeMOSAICSlicePosition: " << filename << std::endl; return 1; } const double refpos[3] = { -10.48860023,-7.82515782,-28.87523447 }; for( int i = 0; i < 3; ++i ) { if( std::fabs( refpos[i] - slicepos[i] ) > eps ) { std::cerr << "Invalid ComputeMOSAICSlicePosition: " << filename << std::endl; return 1; } } gdcm::CSAHeader csa; gdcm::DataSet & ds = reader.GetFile().GetDataSet(); gdcm::MrProtocol mrprot; if( !csa.GetMrProtocol(ds, mrprot)) { std::cerr << "No MrProtocol" << filename << std::endl; return 1; } gdcm::MrProtocol::SliceArray sa; b = mrprot.GetSliceArray(sa); if( !b || sa.Slices.size() != 18 ) { std::cerr << "Size" << filename << std::endl; return 1; } gdcm::MrProtocol::Slice & slice0 = sa.Slices[0]; gdcm::MrProtocol::Vector3 & p0 = slice0.Position; double pos0[3]; pos0[0] = p0.dSag; pos0[1] = p0.dCor; pos0[2] = p0.dTra; for( int i = 0; i < 3; ++i ) { if( std::fabs( refpos[i] - pos0[i] ) > eps ) { std::cerr << "Invalid slice0: " << filename << std::endl; return 1; } } gdcm::MrProtocol::Slice & slice1 = sa.Slices[1]; gdcm::MrProtocol::Vector3 & p1 = slice1.Position; double pos1[3]; pos1[0] = p1.dSag; pos1[1] = p1.dCor; pos1[2] = p1.dTra; double altnor[3]; for( int i = 0; i < 3; ++i ) { altnor[i] = pos1[i] - pos0[i]; } dc.Normalize( altnor ); const double dot2 = dc.Dot( altnor, refnor ); if( std::fabs( 1.0 - dot2 ) > eps ) { std::cerr << "Incompatible alt " << filename << std::endl; return 1; } for( int k = 0; k < 18; ++k ) { gdcm::MrProtocol::Slice & slice = sa.Slices[k]; gdcm::MrProtocol::Vector3 & nor = slice.Normal; double normal[3]; normal[0] = nor.dSag; normal[1] = nor.dCor; normal[2] = nor.dTra; for( int i = 0; i < 3; ++i ) { if( std::fabs( refnor[i] - normal[i] ) > eps ) { std::cerr << "Invalid normal: " << filename << std::endl; return 1; } } } gdcm::Anonymizer ano; ano.SetFile( reader.GetFile() ); const gdcm::PrivateTag &t1 = csa.GetCSAImageHeaderInfoTag(); ano.Remove( t1 ); unsigned int modims[3]; b = filter.ComputeMOSAICDimensions( modims ); if(! b ) { std::cerr << "ComputeMOSAICDimensions: " << filename << std::endl; return 1; } const unsigned int ref[3] = { 64u, 64u, 18u }; if( modims[0] != ref[0] || modims[1] != ref[1] || modims[2] != ref[2] ) { std::cerr << "Invalid ComputeMOSAICDimensions " << filename << std::endl; return 1; } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestStreamImageReader.cxx000066400000000000000000000163431412732066400276050ustar00rootroot00000000000000/*========================================================================= 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 "gdcmStreamImageReader.h" #include "gdcmFileMetaInformation.h" #include "gdcmSystem.h" #include "gdcmFilename.h" #include "gdcmByteSwap.h" #include "gdcmTrace.h" #include "gdcmTesting.h" #include "gdcmImageHelper.h" #include "gdcmImageReader.h" #include "gdcmImage.h" #include "gdcmMediaStorage.h" #include "gdcmRAWCodec.h" #include "gdcmJPEGLSCodec.h" int TestStreamImageRead(const char* filename, bool verbose = false, bool lossydump = false) { (void)lossydump; if( verbose ) std::cerr << "Reading: " << filename << std::endl; gdcm::StreamImageReader reader; reader.SetFileName( filename ); bool canReadImageInformation = reader.ReadImageInformation(); if (!canReadImageInformation) { return 0; //unable to read tags as expected. } else { int res = 0; //let's be tricky; each image will be read in portions, first the top half, then the bottom //that way, we can test how the stream handles fragmentation of the data //we could also loop this to get various different size combinations, but I'm not sure //that's useful, yet. std::vector extent = gdcm::ImageHelper::GetDimensionsValue(reader.GetFile()); //at this point, these values aren't used, but may be in the future //unsigned short xmin = 0; //unsigned short xmax = extent[0]; //unsigned short ymin = 0; //unsigned short ymax = extent[1]; //unsigned short zmin = 0; //unsigned short zmax = extent[2]; reader.DefinePixelExtent(0, (uint16_t)extent[0], 0, (uint16_t)extent[1], 0, (uint16_t)extent[2]); unsigned long len = reader.DefineProperBufferLength(); char* finalBuffer = new char[len]; memset(finalBuffer, 0, sizeof(char)*len); if (reader.CanReadImage()){ bool result = reader.Read(finalBuffer, len); if( !result ){ std::cerr << "res2 failure:" << filename << std::endl; delete [] finalBuffer; return 1; } } else { delete [] finalBuffer; return 0; //essentially, we're going to skip this file since it can't be read by the streamer } /* //now, read in smaller buffer extents reader.DefinePixelExtent(xmin, xmax, ymin, ymax); len = reader.DefineProperBufferLength(); char* buffer = new char[len]; bool res2 = reader.Read(buffer, len); if( !res2 ){ std::cerr << "res2 failure:" << filename << std::endl; return 1; } //copy the result into finalBuffer memcpy(finalBuffer, buffer, len); //now read the next half of the image ymin = ymax; ymax = extent[1]; reader.DefinePixelExtent(xmin, xmax, ymin, ymax); //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len2 = reader.DefineProperBufferLength(); char* buffer2 = new char[len2]; bool res3 = reader.Read(buffer2, len2); if( !res3 ){ std::cerr << "res3 failure:" << filename << std::endl; return 1; } //copy the result into finalBuffer memcpy(&(finalBuffer[len]), buffer2, len2); delete [] buffer; delete [] buffer2; */ // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: const char *ref = gdcm::Testing::GetMD5FromFile(filename); const char *correct_ref = gdcm::Testing::GetMD5FromBrokenFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(finalBuffer, len, digest); if( verbose ) { std::cout << "ref=" << ref << std::endl; std::cout << "md5=" << digest << std::endl; } if( !ref ) { // new regression image needs a md5 sum std::cout << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { // let's be nice for now and only truly fails when file is proper DICOM if( correct_ref && !strcmp(correct_ref, ref) ) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; /* //uncomment this code to explicitly read and check the md5 hash gdcm::ImageReader reader; reader.SetFileName( filename ); if (reader.Read()) { const gdcm::Image &img = reader.GetImage(); //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len2 = img.GetBufferLength(); char* buffer2 = new char[len]; bool res3 = img.GetBuffer(buffer2); if (res3) { char digest2[33]; gdcm::Testing::ComputeMD5(buffer2, len2, digest2); if (strcmp(digest2, digest)) { std::cerr << "Second check read " << digest2 << " not " << digest << std::endl; } } delete [] buffer2; } */ res = 1; } #if 0 std::ofstream debug("/tmp/dump.gray",std::ios::binary); debug.write(finalBuffer, len); debug.close(); #endif } delete[] finalBuffer; if (res == 0) { //uncomment this line to determine if a file was correctly read //std::cerr << "Correctly read " << filename << std::endl; } return res; } #if 0 const gdcm::FileMetaInformation &header = reader.GetFile().GetHeader(); gdcm::MediaStorage ms = header.GetMediaStorage(); bool isImage = gdcm::MediaStorage::IsImage( ms ); if( isImage ) { if( reader.GetFile().GetDataSet().FindDataElement( gdcm::Tag(0x7fe0,0x0010) ) ) { std::cerr << "Failed to read image from file: " << filename << std::endl; return 1; } else { std::cerr << "no Pixel Data Element found in the file:" << filename << std::endl; return 0; } } // else // well this is not an image, so thankfully we fail to read it std::cerr << "Could not read image(" << filename << "), since file is a: " << ms << std::endl; //assert( ms != gdcm::MediaStorage::MS_END ); return 0; #endif } int TestStreamImageReader(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestStreamImageRead(filename, true); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestStreamImageRead( filename); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestStreamImageWriter.cxx000066400000000000000000000201721412732066400276520ustar00rootroot00000000000000/*========================================================================= 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 "gdcmStreamImageReader.h" #include "gdcmStreamImageWriter.h" #include "gdcmFileMetaInformation.h" #include "gdcmSystem.h" #include "gdcmFilename.h" #include "gdcmByteSwap.h" #include "gdcmTrace.h" #include "gdcmTesting.h" #include "gdcmImageHelper.h" #include "gdcmImageReader.h" #include "gdcmImage.h" int TestStreamImageWrite(const char *subdir, const char* filename, bool verbose = false, bool lossydump = false) { (void)lossydump; if( verbose ) std::cerr << "Reading and writing: " << filename << std::endl; gdcm::ImageReader theImageReaderOriginal; gdcm::ImageReader theImageReader; gdcm::StreamImageWriter theStreamWriter; theImageReaderOriginal.SetFileName( filename ); // Create directory first: std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = gdcm::Testing::GetTempFilename( filename, subdir ); if ( theImageReaderOriginal.Read() ) { //int res = 0; //to test the writer out, we have to read an image and then //write it out one line at a time. //a _real_ test would include both the streamimagereader and writer. //so, this test is: //1) read in the image via the stream reader //2) write it out line by line //3) read it in by a reader //4) compare the image from step 1 with step 3 //5) go to step2, replace step 3 with a regular image reader. //for now, we'll do 1-4 //pull image information prior to messing with the file gdcm::Image theOriginalImage = theImageReaderOriginal.GetImage(); char* theOriginalBuffer = new char[theOriginalImage.GetBufferLength()]; if (!theOriginalImage.GetBuffer(theOriginalBuffer)){ std::cerr << "Unable to get original image buffer, stopping." << std::endl; delete [] theOriginalBuffer; return 1; } //first, check that the image information can be written //theStreamReader.GetFile().GetDataSet().Print( std::cout ); theStreamWriter.SetFile(theImageReaderOriginal.GetFile()); #if 0 theStreamWriter.SetFileName(outfilename.c_str()); #else std::ofstream of; of.open( outfilename.c_str(), std::ios::out | std::ios::binary ); theStreamWriter.SetStream(of); #endif if (!theStreamWriter.CanWriteFile()){ delete [] theOriginalBuffer; return 0;//this means that the file was unwritable, period. //very similar to a ReadImageInformation failure } if (!theStreamWriter.WriteImageInformation()){ std::cerr << "unable to write image information" << std::endl; delete [] theOriginalBuffer; return 1; //the CanWrite function should prevent getting here, else, //that's a test failure } std::vector extent = gdcm::ImageHelper::GetDimensionsValue(theImageReaderOriginal.GetFile()); unsigned short xmax = (unsigned short)extent[0]; unsigned short ymax = (unsigned short)extent[1]; unsigned short theChunkSize = 4; unsigned short ychunk = (unsigned short)(extent[1]/theChunkSize); //go in chunk sizes of theChunkSize unsigned short zmax = (unsigned short)extent[2]; if (xmax == 0 || ymax == 0) { std::cerr << "Image has no size, unable to write zero-sized image." << std::endl; return 0; } int z, y, nexty; unsigned long prevLen = 0; //when going through the char buffer, make sure to grab //the bytes sequentially. So, store how far you got in the buffer with each iteration. for (z = 0; z < zmax; ++z){ for (y = 0; y < ymax; y += ychunk){ nexty = y + ychunk; if (nexty > ymax) nexty = ymax; theStreamWriter.DefinePixelExtent(0, (uint16_t)xmax, (uint16_t)y, (uint16_t)nexty, (uint16_t)z, (uint16_t)(z+1)); unsigned long len = theStreamWriter.DefineProperBufferLength(); char* finalBuffer = new char[len]; memcpy(finalBuffer, &(theOriginalBuffer[prevLen]), len); if (!theStreamWriter.Write(finalBuffer, len)){ std::cerr << "writing failure:" << outfilename << " at y = " << y << " and z= " << z << std::endl; delete [] theOriginalBuffer; delete [] finalBuffer; return 1; } delete [] finalBuffer; prevLen += len; } } delete [] theOriginalBuffer; theImageReader.SetFileName(outfilename.c_str()); if (!theImageReader.Read()){ std::cerr << "unable to read in the written test file: " << outfilename << std::endl; return 1; } else { int res = 0; const gdcm::Image &img = theImageReader.GetImage(); //std::cerr << "Success to read image from file: " << filename << std::endl; unsigned long len = img.GetBufferLength(); char* buffer = new char[len]; img.GetBuffer(buffer); // On big Endian system we have byteswapped the buffer (duh!) // Since the md5sum is byte based there is now way it would detect // that the file is written in big endian word, so comparing against // a md5sum computed on LittleEndian would fail. Thus we need to // byteswap (again!) here: const char *ref = gdcm::Testing::GetMD5FromFile(filename); const char *correct_ref = gdcm::Testing::GetMD5FromBrokenFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( verbose ) { std::cout << "ref=" << ref << std::endl; std::cout << "md5=" << digest << std::endl; } if( !ref ) { // new regression image needs a md5 sum std::cout << "Missing md5 " << digest << " for: " << filename << std::endl; //assert(0); res = 1; } else if( strcmp(digest, ref) ) { // let's be nice for now and only truly fails when file is proper DICOM if( correct_ref && !strcmp(correct_ref, ref)) { std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; res = 1; } } delete[] buffer; return res; } } else { //std::cerr << "Unable to read test file: " << filename << std::endl; //return 1; return 0; //this is NOT a test of the reader, but a test of streaming writing } #if 0 const gdcm::FileMetaInformation &header = reader.GetFile().GetHeader(); gdcm::MediaStorage ms = header.GetMediaStorage(); bool isImage = gdcm::MediaStorage::IsImage( ms ); if( isImage ) { if( reader.GetFile().GetDataSet().FindDataElement( gdcm::Tag(0x7fe0,0x0010) ) ) { std::cerr << "Failed to read image from file: " << filename << std::endl; return 1; } else { std::cerr << "no Pixel Data Element found in the file:" << filename << std::endl; return 0; } } // else // well this is not an image, so thankfully we fail to read it std::cerr << "Could not read image(" << filename << "), since file is a: " << ms << std::endl; //assert( ms != gdcm::MediaStorage::MS_END ); #endif return 0; } int TestStreamImageWriter(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestStreamImageWrite(argv[0], filename, true); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestStreamImageWrite( argv[0], filename); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestStrictScanner1.cxx000066400000000000000000000154231412732066400271250ustar00rootroot00000000000000/*========================================================================= 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 "gdcmStrictScanner.h" #include "gdcmDirectory.h" #include "gdcmSystem.h" #include "gdcmTesting.h" #include "gdcmTrace.h" // dcmdump /path/to/image/*.dcm 2>&/dev/null| grep 0020 | grep "000e\|000d" | sort | uniq // // $ find /images/ -type f -exec dcmdump -s +P 0010,0010 {} \; static int TestScannerExtra() { const char *extradataroot = gdcm::Testing::GetDataExtraRoot(); if( !extradataroot ) { return 1; } if( !gdcm::System::FileIsDirectory(extradataroot) ) { std::cerr << "No such directory: " << extradataroot << std::endl; return 1; } gdcm::Directory d; unsigned int nfiles = d.Load( extradataroot, true ); // no recursion std::cout << "done retrieving file list. " << nfiles << " files found." << std::endl; gdcm::StrictScanner s; const gdcm::Tag t1(0x0020,0x000d); // Study Instance UID const gdcm::Tag t2(0x0020,0x000e); // Series Instance UID const gdcm::Tag t3(0x0010,0x0010); // Patient's Name const gdcm::Tag t4(0x0004,0x5678); // DUMMY element const gdcm::Tag t5(0x0028,0x0010); // Rows const gdcm::Tag t6(0x0028,0x0011); // Columns s.AddTag( t1 ); s.AddTag( t2 ); s.AddTag( t3 ); s.AddTag( t4 ); s.AddTag( t5 ); s.AddTag( t6 ); bool b = s.Scan( d.GetFilenames() ); if( !b ) { std::cerr << "Scanner failed" << std::endl; return 1; } //s.Print( std::cout ); return 0; } int TestStrictScanner1(int argc, char *argv[]) { gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); const char *directory = gdcm::Testing::GetDataRoot(); std::string tmpdir = gdcm::Testing::GetTempDirectory( "TestWriter" ); directory = tmpdir.c_str(); if( argc == 2 ) { directory = argv[1]; } if( !gdcm::System::FileIsDirectory(directory) ) { std::cerr << "No such directory: " << directory << std::endl; return 1; } gdcm::Directory d; unsigned int nfiles = d.Load( directory ); // no recursion // d.Print( std::cout ); std::cout << "done retrieving file list. " << nfiles << " files found." << std::endl; gdcm::StrictScanner s; const gdcm::Tag t1(0x0020,0x000d); // Study Instance UID const gdcm::Tag t2(0x0020,0x000e); // Series Instance UID const gdcm::Tag t3(0x0010,0x0010); // Patient's Name const gdcm::Tag t4(0x0004,0x5678); // DUMMY element const gdcm::Tag t5(0x0028,0x0010); // Rows const gdcm::Tag t6(0x0028,0x0011); // Columns const gdcm::Tag t7(0x0008,0x0016); // s.AddTag( t1 ); s.AddTag( t2 ); s.AddTag( t3 ); s.AddTag( t4 ); s.AddTag( t5 ); s.AddTag( t6 ); s.AddTag( t7 ); bool b = s.Scan( d.GetFilenames() ); if( !b ) { std::cerr << "Scanner failed" << std::endl; return 1; } // s.Print( std::cout ); gdcm::Directory::FilenamesType const & files = s.GetFilenames(); if( files != d.GetFilenames() ) { return 1; } int numerrors = 0; for( gdcm::Directory::FilenamesType::const_iterator it = files.begin(); it != files.end(); ++it ) { const char *filename = it->c_str(); const char* value = s.GetValue(filename, t7); const char *msstr = gdcm::Testing::GetMediaStorageFromFile(filename); if( msstr && strcmp(msstr, "1.2.840.10008.1.3.10" ) == 0 ) { // would need to check (0002,0002)... } if( value && msstr ) { if( strcmp( value, msstr ) != 0 ) { std::cerr << "Problem with file " << filename << std::endl; std::cerr << value << "/" << msstr << std::endl; ++numerrors; } } else { if ( !msstr ) { std::cerr << "Problem with file " << filename << std::endl; if( value ) std::cerr << "Value found: " << value << std::endl; ++numerrors; } } } if( numerrors ) return numerrors; // Check dummy filename: bool iskey = s.IsKey( "gdcm.rocks.invalid.name" ); if( iskey ) { std::cout << "IsKey returned: " << iskey << std::endl; return 1; } // Let's get the value for tag t1 in first file: gdcm::StrictScanner::MappingType const &mt = s.GetMappings(); std::string sfilename; sfilename = gdcm::Testing::GetDataRoot(); sfilename = directory; sfilename+= "/test.acr"; { //const char *filename = d.GetFilenames()[0].c_str(); const char *filename = sfilename.c_str(); // The following breaks with Papyrus file: PET-cardio-Multiframe-Papyrus.dcm unsigned int i = 0; gdcm::StrictScanner::MappingType::const_iterator it = mt.find(filename); assert( it != mt.end() ); while( it == mt.end() ) { ++i; if( i == d.GetFilenames().size() ) { return 1; } filename = d.GetFilenames()[i].c_str(); it = mt.find(filename); } std::cout << "Mapping for " << filename << " is :" << std::endl; const gdcm::StrictScanner::TagToValue &tv = it->second; //const std::string &filename = d.GetFilenames()[0]; gdcm::StrictScanner::TagToValue::const_iterator it2 = tv.find( t5 ); if( it2 == tv.end() || t5 != it2->first ) { std::cerr << "Could not find tag:" << t5 << std::endl; return 1; } const char * t1value = it2->second; std::cout << filename << " -> " << t1 << " = " << (*t1value ? t1value : "none" ) << std::endl; } const gdcm::Directory::FilenamesType &filenames = d.GetFilenames(); { gdcm::Directory::FilenamesType::const_iterator it = filenames.begin(); for(; it != filenames.end(); ++it) { const char *filename = it->c_str(); const gdcm::Tag &reftag = t6; const char *value = s.GetValue( filename, reftag ); if( value ) { assert( value ); std::cout << filename << " has " << reftag << " = " << value << std::endl; } else { std::cout << filename << " has " << reftag << " = no value or not DICOM" << std::endl; } } } /* { std::vector keys = s.GetKeys(); for( std::vector::const_iterator it = keys.begin(); it != keys.end(); ++it) { const char *filename = *it; const gdcm::Directory::FilenamesType::const_iterator it2 = std::find(filenames.begin(), filenames.end(), filename); if( it2 == filenames.end() ) { return 1; } if( !s.IsKey( filename ) ) { return 1; } } } */ // puposely discard gdcmDataExtra test, this is just an 'extra' test... int b2 = TestScannerExtra(); (void)b2; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestStrictScanner2.cxx000066400000000000000000000040541412732066400271240ustar00rootroot00000000000000/*========================================================================= 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 "gdcmStrictScanner.h" #include "gdcmDirectory.h" #include "gdcmSystem.h" #include "gdcmTesting.h" #include "gdcmTrace.h" int TestStrictScanner2(int argc, char *argv[]) { gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); const char *directory = gdcm::Testing::GetDataRoot(); std::string tmpdir = gdcm::Testing::GetTempDirectory( "TestWriter" ); directory = tmpdir.c_str(); if( argc == 2 ) { directory = argv[1]; } if( !gdcm::System::FileIsDirectory(directory) ) { std::cerr << "No such directory: " << directory << std::endl; return 1; } gdcm::Directory d; unsigned int nfiles = d.Load( directory ); // no recursion std::cout << "done retrieving file list. " << nfiles << " files found." << std::endl; gdcm::StrictScanner s; const gdcm::Tag t2(0x0020,0x000e); // Series Instance UID s.AddTag( t2 ); bool b = s.Scan( d.GetFilenames() ); if( !b ) { std::cerr << "Scanner failed" << std::endl; return 1; } gdcm::Directory::FilenamesType const & files = s.GetFilenames(); if( files != d.GetFilenames() ) { return 1; } const char str1[] = "1.3.12.2.1107.5.2.4.7630.20010301125744000008"; gdcm::Directory::FilenamesType fns = s.GetAllFilenamesFromTagToValue(t2, str1); // all SIEMENS_MAGNETOM-12-MONO2-FileSeq*.dcm: if( fns.size() != 4 ) return 1; const char str2[] = "1.3.12.2.1107.5.2.4.7630.2001030112574400000"; fns = s.GetAllFilenamesFromTagToValue(t2, str2); if( !fns.empty() ) return 1; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestStringFilter1.cxx000066400000000000000000000045221412732066400267550ustar00rootroot00000000000000/*========================================================================= 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 "gdcmStringFilter.h" #include "gdcmReader.h" #include "gdcmSequenceOfItems.h" #include "gdcmTesting.h" #include "gdcmTrace.h" static int TestStringFilt(const char *filename) { gdcm::StringFilter sf; gdcm::Reader r; r.SetFileName( filename ); if( !r.Read() ) { return 1; } gdcm::DataSet const& ds = r.GetFile().GetDataSet(); sf.SetFile( r.GetFile() ); int ret = 0; gdcm::DataSet::ConstIterator it = ds.Begin(); for( ; it != ds.End(); ++it) { const gdcm::DataElement &ref = *it; std::pair s = sf.ToStringPair( ref.GetTag() ); if( !s.second.empty() || ref.GetVL() == 0 ) { std::cout << s.first << " -> " << s.second << std::endl; std::string s2 = sf.FromString( ref.GetTag(), s.second.c_str(), s.second.size() ); //std::cout << s.first << " -> " << s2 << std::endl; } else if( !ref.GetByteValue() ) // It means it's a SQ { std::cout << "SQ:" << ref.GetTag() << std::endl; } else if( ref.GetTag().IsPrivate() ) { //std::cout << "Private:" << ref.GetTag() << std::endl; std::string s2 = sf.FromString( ref.GetTag(), s.second.c_str(), s.second.size() ); } else { std::cerr << "Not supported: " << ref << std::endl; //ret += 1; } } return ret; } int TestStringFilter1(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestStringFilt(filename); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestStringFilt( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestStringFilter2.cxx000066400000000000000000000045111412732066400267540ustar00rootroot00000000000000/*========================================================================= 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 "gdcmStringFilter.h" #include "gdcmReader.h" #include "gdcmSequenceOfItems.h" #include "gdcmTesting.h" #include "gdcmTrace.h" static int TestStringFilt(const char *filename) { gdcm::StringFilter sf; gdcm::Reader r; r.SetFileName( filename ); if( !r.Read() ) { return 1; } gdcm::DataSet const& ds = r.GetFile().GetDataSet(); sf.SetFile( r.GetFile() ); int ret = 0; gdcm::DataSet::ConstIterator it = ds.Begin(); for( ; it != ds.End(); ++it) { const gdcm::DataElement &ref = *it; std::pair s = sf.ToStringPair( ref ); if( !s.second.empty() || ref.GetVL() == 0 ) { std::cout << s.first << " -> " << s.second << std::endl; std::string s2 = sf.FromString( ref.GetTag(), s.second.c_str(), s.second.size() ); //std::cout << s.first << " -> " << s2 << std::endl; } else if( !ref.GetByteValue() ) // It means it's a SQ { std::cout << "SQ:" << ref.GetTag() << std::endl; } else if( ref.GetTag().IsPrivate() ) { //std::cout << "Private:" << ref.GetTag() << std::endl; std::string s2 = sf.FromString( ref.GetTag(), s.second.c_str(), s.second.size() ); } else { std::cerr << "Not supported: " << ref << std::endl; //ret += 1; } } return ret; } int TestStringFilter2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestStringFilt(filename); } // else // First of get rid of warning/debug message gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestStringFilt( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestStringFilter3.cxx000066400000000000000000000041471412732066400267620ustar00rootroot00000000000000/*========================================================================= 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 "gdcmStringFilter.h" #include "gdcmAttribute.h" #include "gdcmSmartPointer.h" // reproduce a bug with multi value binary attribute int TestStringFilter3(int , char *[]) { gdcm::SmartPointer f = new gdcm::File; gdcm::DataSet & ds = f->GetDataSet(); // (0020,0032) DS [-85.000000\ 21.600000\108.699997] # 32,3 Image Position (Patient) { gdcm::Attribute<0x20,0x32> at = {{ -85, 21.6, 108.699997 }}; gdcm::DataElement de = at.GetAsDataElement(); const gdcm::ByteValue * bv = de.GetByteValue(); const std::string ref( bv->GetPointer(), bv->GetLength() ); ds.Insert( de ); gdcm::StringFilter sf; sf.SetFile( *f ); const gdcm::Tag & t = at.GetTag(); std::string s1 = sf.ToString( t ); std::string s2 = sf.FromString(t, &s1[0], s1.size() ); std::cout << s1 << std::endl; //std::cout << s2 << std::endl; if( s2 != ref ) return 1; } // (0018,1310) US 0\256\256\0 # 8,4 Acquisition Matrix { gdcm::Attribute<0x18,0x1310> at = {{ 0, 256, 256, 0 }}; gdcm::DataElement de = at.GetAsDataElement(); const gdcm::ByteValue * bv = de.GetByteValue(); const std::string ref( bv->GetPointer(), bv->GetLength() ); ds.Insert( de ); gdcm::StringFilter sf; sf.SetFile( *f ); const gdcm::Tag & t = at.GetTag(); std::string s1 = sf.ToString( t ); std::string s2 = sf.FromString(t, &s1[0], s1.size() ); std::cout << "[" << s1 << "]" << std::endl; //std::cout << s2 << std::endl; if( s2 != ref ) return 1; } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestStringFilter4.cxx000066400000000000000000000034351412732066400267620ustar00rootroot00000000000000/*========================================================================= 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 "gdcmStringFilter.h" #include "gdcmAttribute.h" #include "gdcmSmartPointer.h" // https://sourceforge.net/p/gdcm/bugs/485/ int TestStringFilter4(int , char *[]) { gdcm::SmartPointer f = new gdcm::File; gdcm::DataSet & ds = f->GetDataSet(); { gdcm::Element priv_creator; priv_creator.SetValue( "SIEMENS MED SP DXMG WH AWS 1" ); gdcm::DataElement de1 = priv_creator.GetAsDataElement(); de1.SetTag( gdcm::Tag(0x19,0x10) ); ds.Insert( de1 ); gdcm::Element el; el.SetValue( "TestStringFilter4" ); gdcm::DataElement de2 = el.GetAsDataElement(); de2.SetTag( gdcm::Tag(0x19,0x1010) ); ds.Insert( de2 ); // std::cout << ds << std::endl; gdcm::StringFilter filter; filter.SetFile(*f); gdcm::PrivateTag privTag(0x0019, 0x10, "SIEMENS MED SP DXMG WH AWS 1"); // Works as intended std::string privTagValue1 = filter.ToString(ds.GetDataElement(privTag)); std::cout << privTagValue1 << std::endl; // Does not work, returns string value of the private creator instead of the actual tag std::string privTagValue2 = filter.ToString(privTag); std::cout << privTagValue2 << std::endl; } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSurfaceWriter.cxx000066400000000000000000000065251412732066400270520ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTesting.h" #include "gdcmSurfaceWriter.h" #include "gdcmSurfaceReader.h" #include "gdcmFileMetaInformation.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmAttribute.h" namespace gdcm { int TestSurfaceWriter(const char *subdir, const char* filename) { SurfaceReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { int ret = 1; gdcm::MediaStorage ms; if( ms.SetFromFile( reader.GetFile() ) ) { if( ms == gdcm::MediaStorage::SurfaceSegmentationStorage ) { ret = 0; } } if( !ret ) { std::cerr << "Failed to read: " << filename << std::endl; std::cerr << "MediaStorage is: " << ms.GetString() << std::endl; } return !ret; } // Get content of filename const File & FReader = reader.GetFile(); const FileMetaInformation & fmiReader = FReader.GetHeader(); const DataSet & dsReader = FReader.GetDataSet(); // Create directory first: std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); // Write file from content reader SurfaceWriter writer; writer.SetFileName( outfilename.c_str() ); SegmentReader::SegmentVector segments = reader.GetSegments(); writer.SetSegments( segments ); writer.SetNumberOfSurfaces( reader.GetNumberOfSurfaces() ); // Set content from filename File & FWriter = writer.GetFile(); FWriter.SetHeader(fmiReader); FWriter.SetDataSet(dsReader); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // reuse the filename, since outfilename is simply the new representation // of the old filename const char * ref = Testing::GetMD5FromFile(filename); char digest[33] = {}; Testing::ComputeFileMD5(outfilename.c_str(), digest); if( ref == nullptr ) { // new regression file needs a md5 sum std::cout << "Missing md5 " << digest << " for: " << outfilename << std::endl; return 1; } else if( strcmp(digest, ref) != 0 ) { std::cerr << "Found " << digest << " instead of " << ref << std::endl; return 1; } return 0; } } int TestSurfaceWriter(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestSurfaceWriter(argv[0],filename); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestSurfaceWriter(argv[0], filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestSurfaceWriter2.cxx000066400000000000000000000160001412732066400271210ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTesting.h" #include "gdcmSurfaceWriter.h" #include "gdcmSurfaceReader.h" #include "gdcmFileMetaInformation.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmAttribute.h" #include namespace gdcm { /** * Test surface reading and writing method. */ int TestSurfaceWriter2(const char *subdir, const char* filename) { SurfaceReader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { int ret = 1; gdcm::MediaStorage ms; if( ms.SetFromFile( reader.GetFile() ) ) { if( ms == gdcm::MediaStorage::SurfaceSegmentationStorage ) { ret = 0; } } if( !ret ) { std::cerr << "Failed to read: " << filename << std::endl; std::cerr << "MediaStorage is: " << ms.GetString() << std::endl; } return !ret; } // std::cout << "success to read" << std::endl; if (reader.GetNumberOfSurfaces() < 2) { std::cerr << "File with not enough surfaces (min : 2): " << filename << std::endl; return 1; } // Modify data to test other writing/reading way SmartPointer< Segment > segment = new Segment; srand( (unsigned int)time(nullptr)); SegmentHelper::BasicCodedEntry processingAlgo("123", "TEST", "Test123"); { SegmentReader::SegmentVector segments = reader.GetSegments(); Segment::SurfaceVector tmp; SegmentReader::SegmentVector::iterator itSegments = segments.begin(); SegmentReader::SegmentVector::iterator itEndSegments = segments.end(); for (; itSegments != itEndSegments; itSegments++) { tmp = (*itSegments)->GetSurfaces(); Segment::SurfaceVector::iterator itSurfaces = tmp.begin(); Segment::SurfaceVector::iterator itEndSurfaces = tmp.end(); for (; itSurfaces != itEndSurfaces; itSurfaces++) { SmartPointer< Surface > surf = *itSurfaces; surf->SetSurfaceProcessing( true ); surf->SetSurfaceProcessingRatio( 0.42f ); surf->SetSurfaceProcessingDescription( "Test processing" ); surf->SetProcessingAlgorithm( processingAlgo ); if (surf->GetNumberOfVectors() > 0) surf->SetNumberOfVectors( 42 ); surf->SetSurfaceNumber( rand()%1000 ); segment->AddSurface(surf); } } segment->SetSegmentDescription("Surface test"); // segment.SetSurfaceCount( segment.GetSurfaces().size() ); } // Create directory first: std::string tmpdir = Testing::GetTempDirectory( subdir ); if( !System::FileIsDirectory( tmpdir.c_str() ) ) { System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string outfilename = Testing::GetTempFilename( filename, subdir ); // Write file from content reader { SurfaceWriter writer; writer.SetFileName( outfilename.c_str() ); writer.AddSegment( segment ); // writer.SetNumberOfSurfaces( segment.GetSurfaces().size() ); // Set same header to write file const FileMetaInformation & header = reader.GetFile().GetHeader(); writer.GetFile().SetHeader( header ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } // std::cout << "success to write" << std::endl; } SurfaceReader reader2; reader2.SetFileName( outfilename.c_str() ); if ( !reader2.Read() ) { std::cerr << "Failed to read again: " << outfilename << std::endl; return 1; } // std::cout << "success to read again" << std::endl; SegmentReader::SegmentVector segments2 = reader2.GetSegments(); if ( strcmp(segment->GetSegmentDescription(), segments2[0]->GetSegmentDescription()) != 0) { std::cerr << "Find different segment description"<< std::endl; return 1; } Segment::SurfaceVector surfaces2 = segments2[0]->GetSurfaces(); if ( segment->GetSurfaces().size() != surfaces2.size() ) { std::cerr << "Find different surface count"<< std::endl; return 1; } Segment::SurfaceVector::iterator itSurfaces2 = surfaces2.begin(); Segment::SurfaceVector::iterator itEndSurfaces2 = surfaces2.end(); SegmentHelper::BasicCodedEntry processingAlgo2; Segment::SurfaceVector surfaces = segment->GetSurfaces(); Segment::SurfaceVector::iterator itSurfaces = surfaces.begin(); Segment::SurfaceVector::iterator itEndSurfaces = surfaces.end(); for (; itSurfaces2 != itEndSurfaces2; itSurfaces2++) { SmartPointer< Surface > surf = *itSurfaces2; if (!surf->GetSurfaceProcessing()) { std::cerr << "Find different surface processing"<< std::endl; return 1; } if ( 0.41f > surf->GetSurfaceProcessingRatio() || surf->GetSurfaceProcessingRatio() > 0.43f) { std::cerr << "Find different surface processing ratio"<< std::endl; return 1; } String<> str; str = surf->GetSurfaceProcessingDescription(); if (str.Trim() != "Test processing") { std::cerr << "Find different surface processing description"<< std::endl; return 1; } processingAlgo2 = surf->GetProcessingAlgorithm(); str = processingAlgo2.CV; processingAlgo2.CV = str.Trim(); str = processingAlgo2.CSD; processingAlgo2.CSD = str.Trim(); str = processingAlgo2.CM; processingAlgo2.CM = str.Trim(); if (processingAlgo2.CV != processingAlgo.CV || processingAlgo2.CSD != processingAlgo.CSD || processingAlgo2.CM != processingAlgo.CM ) { std::cerr << "Find different surface processing algorithm"<< std::endl; return 1; } if (itSurfaces != itEndSurfaces) { if (surf->GetSurfaceNumber() != (*itSurfaces)->GetSurfaceNumber()) { std::cerr << "Find different surface number"<< std::endl; return 1; } if (surf->GetNumberOfVectors() > 0) { std::cerr << "Find different number of vectors"<< std::endl; return 1; } itSurfaces++; } else { std::cerr << "Find different surface organization"<< std::endl; return 1; } } return 0; } } int TestSurfaceWriter2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return gdcm::TestSurfaceWriter2(argv[0],filename); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += gdcm::TestSurfaceWriter2(argv[0], filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestTagPath.cxx000066400000000000000000000026751412732066400256170ustar00rootroot00000000000000/*========================================================================= 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 "gdcmTagPath.h" #include "gdcmTag.h" int TestTagPath(int argc, char *argv[]) { (void)argc; (void)argv; gdcm::TagPath tp; const char path[] = "/0010,0010"; if( !gdcm::TagPath::IsValid( path ) ) { return 1; } if( !tp.ConstructFromString( path ) ) { return 1; } tp.Print( std::cout ); const char path2[] = "/0010,0011/*/1234,5678"; if( !gdcm::TagPath::IsValid( path2 ) ) { return 1; } if( !tp.ConstructFromString( path2 ) ) { return 1; } std::cout << "FromString:" << std::endl; tp.Print( std::cout ); const unsigned int n = 10; gdcm::Tag list[n]; for(unsigned i = 0; i < n; ++i) { list[i].SetGroup( 0x1234 ); list[i].SetElement( (uint16_t)i ); } if( !tp.ConstructFromTagList( list, n ) ) { return 1; } std::cout << "TagList:" << std::endl; tp.Print( std::cout ); return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestUIDGenerator.cxx000066400000000000000000000115231412732066400265470ustar00rootroot00000000000000/*========================================================================= 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 "gdcmUIDGenerator.h" #include #include #include #include int TestUIDGeneratorValid() { gdcm::UIDGenerator uid; uid.SetRoot( "1.2.3.4.0.0.1" ); const char *s = uid.Generate(); if( !gdcm::UIDGenerator::IsValid( s ) ) { return 1; } const char invalid0[] = ".0.123"; if( gdcm::UIDGenerator::IsValid( invalid0 ) ) { return 1; } const char invalid1[] = "abcd"; if( gdcm::UIDGenerator::IsValid( invalid1 ) ) { return 1; } const char invalid2[] = "1.2.3.4.0.0.123.a"; if( gdcm::UIDGenerator::IsValid( invalid2 ) ) { return 1; } const char invalid3[] = "1.2.3.4.0.0.123.."; if( gdcm::UIDGenerator::IsValid( invalid3 ) ) { return 1; } const char invalid4[] = "1.2.3.4.0.0..123"; if( gdcm::UIDGenerator::IsValid( invalid4 ) ) { return 1; } const char invalid5[] = "1.2.3.4.00.123"; if( gdcm::UIDGenerator::IsValid( invalid5 ) ) { return 1; } const char invalid6[] = "1.2.3.4.00.123."; if( gdcm::UIDGenerator::IsValid( invalid6 ) ) { return 1; } const char invalid7[] = "1234567890.1234567890.1234567890.1234567890.1234567890.1234567890"; if( gdcm::UIDGenerator::IsValid( invalid7 ) ) { return 1; } const char invalid8[] = "1234567890.1234567890.1234567890.1234567890.1234567890/123456789"; if( gdcm::UIDGenerator::IsValid( invalid8 ) ) { return 1; } const char invalid9[] = ""; if( gdcm::UIDGenerator::IsValid( invalid9 ) ) { return 1; } const char invalid10[] = "."; if( gdcm::UIDGenerator::IsValid( invalid10 ) ) { return 1; } const char invalid11[] = "00.1"; if( gdcm::UIDGenerator::IsValid( invalid11 ) ) { return 1; } return 0; // no error } int TestUIDGenerator(int , char *[]) { gdcm::UIDGenerator uid; std::cout << gdcm::UIDGenerator::GetGDCMUID() << std::endl; std::cout << uid.GetRoot() << std::endl; if( strcmp( gdcm::UIDGenerator::GetGDCMUID(), uid.GetRoot() ) != 0 ) { return 1; } /* * Purposely take a very long root, to test the robustness of the generator * since we are left with fewer bytes to still generate uniq UID */ // let's test 27 bytes root: const char myroot[] = "9876543210.9876543210.98765"; // 26 bytes is the length of GDCM root //if( strlen(myroot) != 26 ) // { // return 1; // } uid.SetRoot( myroot ); std::cerr << "before generate" << std::endl; const char *s = uid.Generate(); std::cerr << "after generate" << std::endl; std::cout << "s:" << s << std::endl; if( strcmp( myroot, uid.GetRoot() ) != 0 ) { std::cerr << "1 failed" << std::endl; return 1; } if( strcmp( gdcm::UIDGenerator::GetGDCMUID(), myroot ) == 0 ) { std::cerr << "2 failed" << std::endl; return 1; } if( strncmp( s, uid.GetRoot(), strlen( uid.GetRoot() ) ) != 0 ) { std::cerr << "3 failed" << std::endl; return 1; } /* std::string s0 = "123456"; std::cout << (s0.c_str() + s0.find_first_not_of('0')) << std::endl; std::string s1 = "0123456"; std::cout << (s1.c_str() + s1.find_first_not_of('0')) << std::endl; std::string s2 = "00123456"; std::cout << (s2.c_str() + s2.find_first_not_of('0')) << std::endl; std::string s3 = "000"; if( s3.find_first_not_of('0') != std::string::npos ) std::cout << (s3.c_str() + s3.find_first_not_of('0')) << std::endl; */ // Threading issue, make sure that two different UIDs cannot generate same UID gdcm::UIDGenerator uid1; gdcm::UIDGenerator uid2; const unsigned int n = 100; std::set uids; for(unsigned int i = 0; i < n; ++i) { const char *unique1 = uid1.Generate(); const char *unique2 = uid2.Generate(); if( !unique1 || !unique2 ) return 1; std::cout << unique1 << std::endl; std::cout << unique2 << std::endl; if ( uids.count(unique1) == 1 ) { std::cerr << "Already found: " << unique1 << std::endl; return 1; } uids.insert( unique1 ); if ( uids.count(unique2) == 1 ) { std::cerr << "Already found: " << unique2 << std::endl; return 1; } uids.insert( unique2 ); if( strcmp(unique1 , unique2 ) == 0 ) { // That would be very bad ! return 1; } } int ret = 0; ret += TestUIDGeneratorValid(); return ret; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestUIDGenerator2.cxx000066400000000000000000000044361412732066400266360ustar00rootroot00000000000000/*========================================================================= 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 "gdcmUIDGenerator.h" #include #include #include #include #include #include const unsigned int nuids = 100; void* func (void* argc) { gdcm::UIDGenerator g; std::set *uids= reinterpret_cast< std::set* >(argc); for(unsigned int i = 0; i < nuids; i++) { const char *s = g.Generate(); //std::cout << s << std::endl; if ( uids->count(s) == 1 ) { std::cerr << "Already found: " << s << std::endl; //pthread_exit(); // How do I say this is an error... } uids->insert( s ); } return nullptr; } int TestUIDGenerator2(int , char *[]) { const unsigned int nthreads = 10; // multiple of 2 please pthread_t th[nthreads]; std::set uids[nthreads]; unsigned int i; for (i = 0; i < nthreads; i++) { const int ret = pthread_create (&th[i], nullptr, func, (void*)(uids+i)); if( ret ) return 1; } for (i = 0; i < nthreads; i++) pthread_join (th[i], nullptr); std::vector v_one(nuids*nthreads); std::vector::iterator it = v_one.begin(); for(i = 0; i < nthreads; i+=2) { std::set_union(uids[i].begin(), uids[i].end(), uids[i+1].begin(), uids[i+1].end(), it); it += nuids*2; } std::cout << v_one.size() << std::endl; assert( v_one.size() == nuids * nthreads ); // programmer error std::copy(v_one.begin(), v_one.end(), std::ostream_iterator(std::cout, "\n")); std::set global; for(it = v_one.begin(); it != v_one.end(); ++it) { global.insert( *it ); } std::cout << "set:" << global.size() << std::endl; if( global.size() != nuids * nthreads ) { return 1; } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestUIDGenerator3.cxx000066400000000000000000000037221412732066400266340ustar00rootroot00000000000000/*========================================================================= 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 "gdcmUIDGenerator.h" #include "gdcmSystem.h" #include #include int TestUIDGenerator3(int argc, char *argv[]) { char randbytesbuf[200]; gdcm::UIDGenerator uid; unsigned char data[16]; for(unsigned int i = 0; i < 100; ++i) { uid.GenerateUUID( data ); size_t len = gdcm::System::EncodeBytes(randbytesbuf, data, sizeof(data)); //std::cout << randbytesbuf << std::endl; std::bitset<8> x; //x.reset(); //std::cout << x << std::endl; //x.flip(); //std::cout << x << std::endl; //std::cout << sizeof(x) << std::endl; //std::cout << sizeof(data) << std::endl; x = data[0]; //std::cout << x << std::endl; //std::cout << (int)data[0] << std::endl; //x = data[5]; //std::cout << x << std::endl; x[2+0] = 0; x[2+1] = 0; x[2+2] = 0; x[2+3] = 0; x[2+4] = 0; x[2+5] = 0; data[0] = x.to_ulong(); //std::cout << x << std::endl; //std::cout << (int)data[0] << std::endl; len = gdcm::System::EncodeBytes(randbytesbuf, data, sizeof(data)); std::cout << randbytesbuf << std::endl; if( len > 37 ) { return 1; } // Can't use the following, this would declare x2 as a function //std::bitset<128> x2( std::string(randbytesbuf) ); // instead split it out : //std::string s(randbytesbuf); //std::bitset<128> x2( s ); //std::cout << x2 << std::endl; } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestUUIDGenerator.cxx000066400000000000000000000024231412732066400266730ustar00rootroot00000000000000/*========================================================================= 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 "gdcmUUIDGenerator.h" #include int TestUUIDGenerator(int , char *[]) { gdcm::UUIDGenerator uid; const char *suid = uid.Generate(); if( !gdcm::UUIDGenerator::IsValid( suid ) ) { std::cerr << "Invalid: " << suid << std::endl; return 1; } const char *valids[] = { "00000000-0000-0000-0000-000000000000", "ba209999-0c6c-11d2-97cf-00c04f8eea45", "67C8770B-44F1-410A-AB9A-F9B5446F13EE" }; const size_t nv = sizeof( valids ) / sizeof( *valids ); for( size_t i = 0; i < nv; ++i ) { const char *valid = valids[i]; if( !gdcm::UUIDGenerator::IsValid( valid ) ) { std::cerr << "Invalid: " << valid << std::endl; return 1; } } return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestValidate.cxx000066400000000000000000000012451412732066400260100ustar00rootroot00000000000000/*========================================================================= 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 "gdcmValidate.h" int TestValidate(int, char *[]) { gdcm::Validate v; v.Validation(); return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestWaveform.cxx000066400000000000000000000013041412732066400260410ustar00rootroot00000000000000/*========================================================================= 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 "gdcmWaveform.h" int TestWaveform(int argc, char *argv[]) { (void)argc; (void)argv; gdcm::Waveform w; (void)w; return 0; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestWriter2.cxx000066400000000000000000000020351412732066400256130ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ int TestWriter2(int argc, char *argv[]) { const char *filename = argv[1]; const char *outfilename = argv[2]; Reader reader; reader.SetFileName( filename ); if ( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; return 1; } Writer writer; writer.SetFileName( outfilename ); writer.SetFile( reader.GetFile() ); if( !writer.Write() ) { std::cerr << "Failed to write: " << outfilename << std::endl; return 1; } } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Cxx/TestXMLPrinter.cxx000066400000000000000000000034331412732066400262640ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmXMLPrinter.h" #include "gdcmFilename.h" #include "gdcmTesting.h" int TestXMLPrint(const char *filename, bool verbose= false) { gdcm::Reader r; r.SetFileName( filename ); if( !r.Read() ) { std::cerr << "Could not read: " << filename << std::endl; return 1; } gdcm::XMLPrinter print; //print.SetStyle( gdcm::XMLPrinter::LOADBULKDATA ); print.SetFile( r.GetFile() ); std::ostringstream out; if( verbose ) print.Print( std::cout ); print.Print( out ); gdcm::Filename fn( filename ); const char *name = fn.GetName(); std::string buf = out.str(); if( buf.find( "GDCM:UNKNOWN" ) != std::string::npos ) { std::cerr << "UNKNOWN Attribute with : " << name << std::endl; return 1; } return 0; } int TestXMLPrinter(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestXMLPrint(filename, true); } // else int r = 0, i = 0; gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestXMLPrint( filename ); ++i; } return r; } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Java/000077500000000000000000000000001412732066400230105ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Java/CMakeLists.txt000066400000000000000000000024501412732066400255510ustar00rootroot00000000000000# Define the tests for gdcm-java set(GDCM_JAVA_TEST_SRCS TestStringFilter ) # Do not change anything after here: find_package(Java ${GDCM_DEFAULT_JAVA_VERSION} REQUIRED) # javac, jar find_package(JNI REQUIRED) include_directories( ${JNI_INCLUDE_PATH} ) set(classfilesdep) foreach(example ${GDCM_JAVA_TEST_SRCS}) add_custom_command( OUTPUT ${GDCM_EXECUTABLE_DIR}/${example}.class COMMAND ${Java_JAVAC_EXECUTABLE} ARGS ${CMAKE_CURRENT_SOURCE_DIR}/${example}.java -d ${GDCM_EXECUTABLE_DIR} -source ${GDCM_JAVA_SOURCE_VERSION} -target ${GDCM_JAVA_TARGET_VERSION} -classpath ${GDCM_LIBRARY_DIR}/gdcm.jar WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${example}.java COMMENT "javac ${example}.java" ) list(APPEND classfilesdep ${GDCM_EXECUTABLE_DIR}/${example}.class) set(GDCM_LIBRARY_DIR2 ${LIBRARY_OUTPUT_PATH}/\${BUILD_TYPE}) set_source_files_properties(${GDCM_EXECUTABLE_DIR}/${example}.class PROPERTIES CLASSPATH "${GDCM_LIBRARY_DIR2}/gdcm.jar") ADD_JAVA_TEST(${example}Java ${GDCM_EXECUTABLE_DIR}/${example}) endforeach() # 3. ok now add the target add_custom_target(GDCMJavaMSFFTests ALL DEPENDS ${classfilesdep} COMMENT "building gdcm java msff tests" ) # make sure gdcm.jar is built add_dependencies(GDCMJavaMSFFTests GDCMJavaJar) GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Java/TestStringFilter.java000066400000000000000000000060001412732066400271230ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* */ import gdcm.*; public class TestStringFilter { public static void main(String[] args) throws Exception { /* System.out.println("PATH : " + System.getProperty("java.library.path")); Properties p = System.getProperties(); Enumeration keys = p.keys(); while (keys.hasMoreElements()) { String key = (String)keys.nextElement(); String value = (String)p.get(key); System.out.println(key + ": " + value); } */ long nfiles = Testing.GetNumberOfFileNames(); Trace.DebugOff(); Trace.WarningOff(); for( long i = 0; i < nfiles; ++i ) { String filename = Testing.GetFileName( i ); if( filename.contains( "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm" )) { //System.out.println("Success reading: " + filename ); Reader reader = new Reader(); reader.SetFileName( filename ); if ( !reader.Read() ) { throw new Exception("Could not read: " + filename ); } File file = reader.GetFile(); DataSet ds = file.GetDataSet(); Tag t1 = new Tag(0x2005,0xe229); StringFilter sf = new StringFilter(); sf.SetFile( file ); if( ds.FindDataElement( t1 ) ) { DataElement de1 = ds.GetDataElement(t1); System.out.println("de1: " + de1 ); String s1 = sf.ToString( de1 ); System.out.println("s1: " + s1 ); float array[] = { 5.1f, -4.9f }; de1.SetArray( array, array.length ); System.out.println("de1: " + de1 ); s1 = sf.ToString( de1 ); System.out.println("s1: " + s1 ); } Tag t2 = new Tag(0x18,0x2043); float array[] = { 2.5f, -1.6f }; DataElement de = new DataElement(t2); //de.SetVR( new VR(VR.VRType.FL) ); de.SetArray( array, array.length ); String s = sf.ToString( de ); System.out.println("s: " + s ); ds.Replace( de ); if( ds.FindDataElement( t2 ) ) { DataElement de2 = ds.GetDataElement(t2); System.out.println("de2: " + de2 ); String s2 = sf.ToString( de2 ); System.out.println("s2: " + s2 ); //float array[] = { 51, 49 }; //de1.SetArray( array, array.length ); //System.out.println("de1: " + de1 ); //s1 = sf.ToString( de1 ); //System.out.println("s1: " + s1 ); //ds.Replace( de1 ); } Writer writer = new Writer(); writer.SetFile( reader.GetFile() ); writer.SetFileName( "testsf.dcm" ); if ( !writer.Write() ) { throw new Exception("Could not write: " + filename ); } } } } } GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Python/000077500000000000000000000000001412732066400234105ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Python/CMakeLists.txt000066400000000000000000000020051412732066400261450ustar00rootroot00000000000000# Define the tests for gdcm-python # gdcm-python set(GDCM_PYTHON_TEST_SRCS #TestPythonFilter #TestStringFilter TestIPPSorter TestOrientation TestUIDGenerator ) if(GDCM_DATA_ROOT) set(GDCM_PYTHON_TEST_SRCS ${GDCM_PYTHON_TEST_SRCS} TestAnonymizer TestModifyFields TestImageReader TestScanner ) endif() if(BUILD_APPLICATIONS) if(DCMTK_DCMDUMP_EXECUTABLE) if(UNIX) if(GDCM_DATA_ROOT) set(GDCM_PYTHON_TEST_SRCS ${GDCM_PYTHON_TEST_SRCS} TestDCMTKMD5 # need dcmdrle and dcmdjpeg ) endif() endif() endif() endif() # Loop over files and create executables foreach(name ${GDCM_PYTHON_TEST_SRCS}) ADD_PYTHON_TEST(${name}Python ${name}.py) endforeach() # Special test that need extra arg: # TestKakaduDecompressionMD5 find_package(KAKADU) if(BUILD_APPLICATIONS) if(KDU_EXPAND_EXECUTABLE) if(UNIX) if(GDCM_DATA_ROOT) ADD_PYTHON_TEST(TestKakaduDecompressionMD5Python TestKakaduDecompressionMD5.py ${KDU_EXPAND_EXECUTABLE}) endif() endif() endif() endif() GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Python/TestAnonymizer.py000066400000000000000000000046771412732066400267730ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import os,sys def TestAnonymizer(filename, verbose = False): r = gdcm.Reader() r.SetFileName( filename ) success = r.Read() if( not success ): return 1 #print r.GetFile().GetDataSet() ano = gdcm.Anonymizer() ano.SetFile( r.GetFile() ) # 1. Replace with another value ano.Replace( gdcm.Tag(0x0010,0x0010), "Test^Anonymize" ) # 2. Remove a tag (even a SQ) ano.Remove( gdcm.Tag(0x0008,0x2112) ) # 3. Make a tag empty ano.Empty( gdcm.Tag(0x0008,0x0070) ) # Call the main function: success = ano.RemovePrivateTags() # do it ! if( not success ): return 1 # Check we can also change value from binary field #ano.Replace( gdcm.Tag(0x0010,0x0010), "16", gdcm. ) # Let's check if our anonymization worked: if verbose: print(ano.GetFile().GetDataSet()) # So at that point r.GetFile() was modified, let's simply passed it to the Writer: # First find a place where to write it out: subdir = "TestAnonymizerPython" tmpdir = gdcm.Testing.GetTempDirectory( subdir ) if not gdcm.System.FileIsDirectory( tmpdir ): gdcm.System.MakeDirectory( tmpdir ) # Ok directory does exist now, extract the name of the input file, and merge it in # our newly created tmpdir: outfilename = gdcm.Testing.GetTempFilename( filename, subdir ) w = gdcm.Writer() w.SetFileName( outfilename ) w.SetFile( r.GetFile() ) w.SetCheckFileMetaInformation( False ) success = w.Write() if( not success ): return 1 if verbose: print("Success to write: %s"%outfilename) return success if __name__ == "__main__": success = 0 try: filename = os.sys.argv[1] success += TestAnonymizer( filename, True ) except: # loop over all files: t = gdcm.Testing() nfiles = t.GetNumberOfFileNames() for i in range(0,nfiles): filename = t.GetFileName(i) success += TestAnonymizer( filename ) # Test succeed ? sys.exit(success == 0) GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Python/TestDCMTKMD5.py000066400000000000000000000145221412732066400257760ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import os,sys,re """ You need to have dcmdump/dcmdrle/dcmdjpeg in your PATH """ def TestDCMTKMD5( filename, verbose = False ): blacklist = [ # Get rid of DICOMDIR if any: 'DICOMDIR', 'DICOMDIR_MR_B_VA12A', 'DICOMDIR-Philips-EasyVision-4200-Entries', 'dicomdir_Acusson_WithPrivate_WithSR', 'dicomdir_Pms_With_heavy_embedded_sequence', 'dicomdir_Pms_WithVisit_WithPrivate_WithStudyComponents', 'dicomdir_With_embedded_icons', # Unsupported file: 'MR_Spectroscopy_SIEMENS_OF.dcm', 'gdcm-CR-DCMTK-16-NonSamplePerPix.dcm', # this is not an image 'ELSCINT1_PMSCT_RLE1.dcm', 'SignedShortLosslessBug.dcm', 'JPEGDefinedLengthSequenceOfFragments.dcm', # dcmtk 3.6.0 gives garbage 'GE_DLX-8-MONO2-PrivateSyntax.dcm', 'PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm', #'DermaColorLossLess.dcm', # technically I could support this one... #'LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm', # idem 'ALOKA_SSD-8-MONO2-RLE-SQ.dcm'] # this one is not supported by dcmtk 3.5.4 for f in blacklist: if f in filename: print("%s is on the black list, giving up"%filename) return 0 #print filename # #dcmdump_exec = "dcmdump -dc -E +P 2,10 -s " + filename + " 2> /dev/null" # I had to remove the -dc for the following file: # GE_GENESIS-16-MONO2-Uncompressed-UnusualVR.dcm there is trailing space instead of \0 dcmdump_exec = "dcmdump -E +P 2,10 -s " + filename + " 2> /dev/null" #print dcmdump_exec f = os.popen(dcmdump_exec) ret = f.read() #assert ret == 0 #print ret jpegre = re.compile('^.*JPEGLossless.*$') jpegre2 = re.compile('^.*JPEGExtended.*$') jpegre3 = re.compile('^.*JPEGBaseline.*$') j2kre = re.compile('^.*JPEG2000.*$') jplsre = re.compile('^.*JPEGLS.*$') rlere = re.compile('^.*RLELossless.*$') lexre = re.compile('^.*LittleEndianExplicit.*$') leire = re.compile('^.*LittleEndianImplicit.*$') beire = re.compile('^.*BigEndianExplicit.*$') testing = gdcm.Testing() outputdir = testing.GetTempDirectory( "TestDCMTKMD5" ) gdcm.System.MakeDirectory( outputdir ) outputfilename = testing.GetTempFilename( filename, "TestDCMTKMD5" ) executable_output_path = gdcm.GDCM_EXECUTABLE_OUTPUT_PATH gdcmraw = executable_output_path + '/gdcmraw -P' if not ret: #print "empty, problem with:", filename return 0 elif type(ret) != type(''): print("problem of type with:", filename) return 0 #print ret #print ret.__class__ elif( jpegre.match( ret ) or jpegre2.match(ret) or jpegre3.match(ret) ): #print "jpeg: ",filename # +cn : conv-never # +px : color by pixel dcmdjpeg_exec = "dcmdjpeg +cn +px " + filename + " " + outputfilename ret = os.system( dcmdjpeg_exec ) if ret: print("dcmdjpeg failed to decompress file. giving up") return 0 gdcmraw_args = ' -i ' + outputfilename + ' -o ' + outputfilename + ".raw" gdcmraw += gdcmraw_args #print gdcmraw ret = os.system( gdcmraw ) md5 = gdcm.Testing.ComputeFileMD5( outputfilename + ".raw" ) ref = gdcm.Testing.GetMD5FromFile(filename) #print md5 retval = 0 if ref != md5: print("md5 are different: %s should be: %s for file %s"%(md5,ref,filename)) retval = 1 #print outputfilename return retval elif( jplsre.match( ret ) ): #print "jpegls: ",filename dcmdjpls_exec = "dcmdjpls " + filename + " " + outputfilename ret = os.system( dcmdjpls_exec ) if ret: print("failed with: ", dcmdjpls_exec) return 1 gdcmraw_args = ' -i ' + outputfilename + ' -o ' + outputfilename + ".raw" gdcmraw += gdcmraw_args #print gdcmraw ret = os.system( gdcmraw ) md5 = gdcm.Testing.ComputeFileMD5( outputfilename + ".raw" ) ref = gdcm.Testing.GetMD5FromFile(filename) #print md5 retval = 0 if ref != md5: print("md5 are different: %s should be: %s for file %s"%(md5,ref,filename)) retval = 1 #print outputfilename return retval elif( rlere.match( ret ) ): #print "rle: ",filename dcmdrle_exec = "dcmdrle " + filename + " " + outputfilename ret = os.system( dcmdrle_exec ) if ret: print("failed with: ", dcmdrle_exec) return 1 gdcmraw_args = ' -i ' + outputfilename + ' -o ' + outputfilename + ".raw" gdcmraw += gdcmraw_args #print gdcmraw ret = os.system( gdcmraw ) md5 = gdcm.Testing.ComputeFileMD5( outputfilename + ".raw" ) ref = gdcm.Testing.GetMD5FromFile(filename) #print md5 retval = 0 if ref != md5: print("md5 are different: %s should be: %s for file %s"%(md5,ref,filename)) retval = 1 #print outputfilename return retval elif( j2kre.match( ret ) ): return 0 elif( lexre.match( ret ) or leire.match(ret) or beire.match(ret) ): #print "rle: ",filename #dcmdrle_exec = "dcmdrle " + filename + " " + outputfilename #ret = os.system( dcmdrle_exec ) gdcmraw_args = ' -i ' + filename + ' -o ' + outputfilename + ".raw" gdcmraw += gdcmraw_args #print gdcmraw ret = os.system( gdcmraw ) if ret: print("failed with: ", gdcmraw) return 1 md5 = gdcm.Testing.ComputeFileMD5( outputfilename + ".raw" ) ref = gdcm.Testing.GetMD5FromFile(filename) #print md5 retval = 0 if ref != md5: print("md5 are different: %s should be: %s for file %s"%(md5,ref,filename)) retval = 1 #print outputfilename return retval #else print("Unhandled:",filename,"with ret=",ret) return 1 if __name__ == "__main__": success = 0 try: filename = os.sys.argv[1] success += TestDCMTKMD5( filename, True ) except: # loop over all files: t = gdcm.Testing() gdcm.Trace.WarningOff() gdcm.Trace.DebugOff() nfiles = t.GetNumberOfFileNames() for i in range(0,nfiles): filename = t.GetFileName(i) success += TestDCMTKMD5( filename ) # Test succeed ? sys.exit(success) GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Python/TestIPPSorter.py000066400000000000000000000013451412732066400264540ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import os,sys if __name__ == "__main__": success = 0 s = gdcm.IPPSorter() # black box test: if not s.Sort([]): sys.exit(1) sys.exit(0) GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Python/TestImageReader.py000066400000000000000000000023241412732066400267700ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import os,sys def TestImageRead(filename, verbose = False): r = gdcm.ImageReader() r.SetFileName( filename ) success = r.Read() if verbose: print(r.GetImage()) return success if __name__ == "__main__": success = 0 try: filename = os.sys.argv[1] success += TestImageRead( filename, True ) except: # loop over all files: gdcm.Trace.DebugOff() gdcm.Trace.WarningOff() t = gdcm.Testing() nfiles = t.GetNumberOfFileNames() for i in range(0,nfiles): #print t.GetFileName(i) filename = t.GetFileName(i) success += TestImageRead( filename ) # Test succeed ? sys.exit(success == 0) GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Python/TestKakaduDecompressionMD5.py000066400000000000000000000065621412732066400310740ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import os,sys def TestKakadu(filename, kdu_expand): fn = gdcm.Filename(filename) testdir = fn.GetPath() testbasename = fn.GetName() ext = fn.GetExtension() #print ext #kakadu_path = '/home/mmalaterre/Software/Kakadu60' kakadu_path = os.path.dirname( kdu_expand ) #kdu_expand = kakadu_path + '/kdu_expand' kdu_args = ' -quiet -i ' output_dcm = testdir + '/kakadu/' + testbasename output_j2k = output_dcm + '.j2k' output_ppm = output_dcm + '.ppm' # output_raw = output_dcm + '.rawl' # FIXME: little endian only... kdu_expand += kdu_args + output_j2k + ' -o ' + output_raw # $ ./bin/gdcmraw -i .../TestImageChangeTransferSyntax2/012345.002.050.dcm -o toto.j2k executable_output_path = gdcm.GDCM_EXECUTABLE_OUTPUT_PATH gdcmraw = executable_output_path + '/gdcmraw' outputfilename = output_j2k gdcmraw_args = ' -i ' + filename + ' -o ' + outputfilename gdcmraw += gdcmraw_args #print gdcmraw ret = os.system( gdcmraw ) #print "ret:",ret #print kdu_expand os.environ["LD_LIBRARY_PATH"]=kakadu_path ret = os.system( kdu_expand ) # now need to skip the ppm header: dd_cmd = 'dd bs=15 skip=1 if=%s of = %s'%(output_ppm,output_raw) #print "ret:",ret md5 = gdcm.Testing.ComputeFileMD5( output_raw ) # ok this is the md5 as computed after decompression using kdu_expand # let see if it match out previously (stored) md5: ref = gdcm.Testing.GetMD5FromFile(filename) #print ref retval = 0 if ref != md5: img = gdcm.ImageReader() img.SetFileName( filename ) img.Read() if img.GetImage().GetDimension(2) != 1: print("Test do not handle multiframes for now") elif img.GetImage().GetPixelFormat().GetSamplesPerPixel() != 1: print("Test do not handle RGB for now. kdu_expand expand as RRR GGG BBB by default") else: print("md5 are different: %s should be: %s for file %s"%(md5,ref,filename)) print("raw file was: %s"%(output_raw)) retval = 1 return retval if __name__ == "__main__": success = 0 #try: # filename = os.sys.argv[1] # success += TestKakadu( filename ) #except: # loop over all files: #t = gdcm.Testing() #nfiles = t.GetNumberOfFileNames() #for i in range(0,nfiles): # filename = t.GetFileName(i) # success += TestKakadu( filename ) d = gdcm.Directory() tempdir = gdcm.Testing.GetTempDirectory() j2ksubdir = 'TestImageChangeTransferSyntax2' # FIXME hardcoded ! nfiles = d.Load( tempdir + '/' + j2ksubdir ) # make sure the output dir for temporary j2k files exists: md = gdcm.System.MakeDirectory( tempdir + '/' + j2ksubdir + '/kakadu' ); if not md: sys.exit(1) files = d.GetFilenames() for i in range(0,nfiles): filename = files[i] success += TestKakadu( filename, os.sys.argv[1] ) # Test succeed ? sys.exit(success) GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Python/TestModifyFields.py000066400000000000000000000050351412732066400272030ustar00rootroot00000000000000########################################################################### # # 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. # ############################################################################ import gdcm import os,sys def TestModifyFields(filename): outfilename = filename + ".rewrite" r = gdcm.Reader() r.SetFileName( filename ) success = r.Read() #print r.GetFile().GetDataSet() ds = r.GetFile().GetDataSet() #print dir(ds) # eg, let's remove a tag removetag = gdcm.Tag(0x0043,0x106f) if ds.FindDataElement( removetag ): ds.Remove( removetag ) # let's replace a value: replacetag = gdcm.Tag(0x0010,0x0010) if ds.FindDataElement( replacetag ): de = ds.GetDataElement( replacetag ) #print dir(de) patname = b"This^is^an^example" de.SetByteStringValue( patname ) # let's insert a new dataelement # pir = gdcm.DataElement( gdcm.Tag(0x0012,0x0062) ) pir.SetVR( gdcm.VR( gdcm.VR.CS ) ) # specify the VR explicitly yes = b"YES" pir.SetByteStringValue( yes ) ds.Insert( pir ) # try again but pretend we don't know the VR # deidmethod = gdcm.Tag(0x0012,0x0063) # retrieve the supreme global instance, sum of all knowledge in da whole universe: dicomdicts = gdcm.GlobalInstance.GetDicts() dictel = dicomdicts.GetDictEntry( deidmethod ) #print dictel.GetVR() deid = gdcm.DataElement( deidmethod ) deid.SetVR( dictel.GetVR() ) methodstr = b"Well known Company" #deid.SetByteStringValue( methodstr ) deid.SetByteStringValue( methodstr ) ds.Insert( deid ) #w = gdcm.Writer() #w.SetFileName( outfilename ) #w.SetFile( r.GetFile() ) #success = w.Write() return success if __name__ == "__main__": success = 0 try: filename = os.sys.argv[1] success += TestModifyFields( filename ) except: # loop over all files: t = gdcm.Testing() nfiles = t.GetNumberOfFileNames() for i in range(0,nfiles): filename = t.GetFileName(i) success += TestModifyFields( filename ) # Test succeed ? sys.exit(success == 0) GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Python/TestOrientation.py000066400000000000000000000031411412732066400271140ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import os,sys if __name__ == "__main__": success = True ori1 = (1,0,0,0,1,0) ori2 = (1,0,0,0,0,1) ori3 = (0,1,0,0,0,1) label1 = gdcm.Orientation.GetLabel( gdcm.Orientation.GetType( ori1 ) ) if label1 != 'AXIAL': print("Found:",label1) success = False label2 = gdcm.Orientation.GetLabel( gdcm.Orientation.GetType( ori2 ) ) if label2 != 'CORONAL': print("Found:",label2) success = False label3 = gdcm.Orientation.GetLabel( gdcm.Orientation.GetType( ori3 ) ) if label3 != 'SAGITTAL': print("Found:",label3) success = False image = gdcm.Image() image.SetNumberOfDimensions(2) print(image) print(image.GetDimensions()) print(image.GetOrigin()) print(image.GetSpacing()) print(image.GetDirectionCosines()) image.SetNumberOfDimensions(3) image.SetDimensions( (512,256,128) ) print(image.GetDimensions()) #dircos = gdcm.DirectionCosines( (1,0,0,0,0,-1) ) dircos = gdcm.DirectionCosines() print(dircos) #print dircos.Cross() # Test succeed ? sys.exit(success == False) GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Python/TestPythonFilter.py000066400000000000000000000033731412732066400272570ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import os,sys def TestPythonFilter(filename, verbose = False): r = gdcm.Reader() r.SetFileName( filename ) success = r.Read() if( not success ): return 1 file = r.GetFile() ds = file.GetDataSet() # Change gdcm struct into something swig can digest: pds = gdcm.PythonDataSet(ds) sf = gdcm.PythonFilter() pds.Start() # Make iterator go at beginning dic1={} dic2={} sf.SetFile(file) # extremely important while(not pds.IsAtEnd() ): t = str(pds.GetCurrent().GetTag()) print(t) res = sf.ToPyObject( pds.GetCurrent().GetTag() ) dic2[t] = res[1] dic1[res[0]] = res[1] pds.Next() #print dic1 #print dic2 try: print("Pixel Representation=",dic2[ '(0028,0103)' ]) except KeyError: print("Tag not found in dataset") return 0 if __name__ == "__main__": success = 0 try: filename = os.sys.argv[1] success += TestPythonFilter( filename, True ) except: # loop over all files: gdcm.Trace.WarningOff() t = gdcm.Testing() nfiles = t.GetNumberOfFileNames() for i in range(0,nfiles): filename = t.GetFileName(i) success += TestPythonFilter( filename ) # Test succeed ? sys.exit(success == 0) GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Python/TestScanner.py000066400000000000000000000050041412732066400262120ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import os,sys def TestScan(dirname, recursive = False): # Check the dirname is indeed a directory system = gdcm.System() if not system.FileIsDirectory(dirname): print("Need a directory") sys.exit(1) # Retrieve all the files within that dir (recursively?) d = gdcm.Directory() nfiles = d.Load( dirname, recursive ) print("done retrieving all the",nfiles,"files") s = gdcm.Scanner() t1 = gdcm.Tag(0x0020,0x000d) # VR::UI t2 = gdcm.Tag(0x0020,0x000e) # VR::UI t3 = gdcm.Tag(0x0028,0x0011) # VR::US # Some fun tags, with dual VR: t4 = gdcm.Tag(0x0028,0x0106) # VR::US_SS t5 = gdcm.Tag(0x0028,0x0107) # VR::US_SS s.AddTag( t1 ) s.AddTag( t2 ) s.AddTag( t3 ) s.AddTag( t4 ) s.AddTag( t5 ) b = s.Scan( d.GetFilenames() ) if not b: print("Scanner failed") sys.exit(1) # Raw Values found: values = s.GetValues() print("Values found for all tags are:") print(values) # get the main super-map : mappings = s.GetMappings() #file1 = d.GetFilenames()[0]; #print file1 #m1 = s.GetMapping( file1 ) #print m1 #print dir(m1) #for k,v in m1.iteritems(): # print "item", k,v # For each file get the value for tag t1: for f in d.GetFilenames(): print("Working on:",f) mapping = s.GetMapping(f) pttv = gdcm.PythonTagToValue(mapping) # reset iterator to start position pttv.Start() # iterate until the end: while( not pttv.IsAtEnd() ): # get current value for tag and associated value: # if tag was not found, then it was simply not added to the internal std::map # Warning value can be None tag = pttv.GetCurrentTag() value = pttv.GetCurrentValue() print(tag,"->",value) # increment iterator pttv.Next() if __name__ == "__main__": try: dirname = os.sys.argv[1] recursive = True except: t = gdcm.Testing() dirname = t.GetDataRoot() recursive = False TestScan( dirname, recursive) sys.exit(0) GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Python/TestStringFilter.py000066400000000000000000000033561412732066400272450ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import os,sys def TestStringFilter(filename, verbose = False): r = gdcm.Reader() r.SetFileName( filename ) success = r.Read() if( not success ): return 1 file = r.GetFile() ds = file.GetDataSet() # Change gdcm struct into something swig can digest: pds = gdcm.PythonDataSet(ds) sf = gdcm.StringFilter() pds.Start() # Make iterator go at beginning dic1={} dic2={} sf.SetFile(file) # extremely important while(not pds.IsAtEnd() ): t = str(pds.GetCurrent().GetTag()) res = sf.ToStringPair( pds.GetCurrent().GetTag() ) dic2[t] = res[1] dic1[res[0]] = res[1] pds.Next() #print dic1 #print dic2 try: print "Pixel Representation=",dic2[ '(0028,0103)' ] except KeyError: print "Tag not found in dataset" return 0 if __name__ == "__main__": success = 0 try: filename = os.sys.argv[1] success += TestStringFilter( filename, True ) except: # loop over all files: gdcm.Trace.WarningOff() t = gdcm.Testing() nfiles = t.GetNumberOfFileNames() for i in range(0,nfiles): filename = t.GetFileName(i) success += TestStringFilter( filename ) # Test succeed ? sys.exit(success == 0) GDCM-3.0.10/Testing/Source/MediaStorageAndFileFormat/Python/TestUIDGenerator.py000066400000000000000000000015611412732066400271150ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import gdcm import os,sys if __name__ == "__main__": uid = gdcm.UIDGenerator() for i in range(0,100): print(uid.Generate()) MY_ROOT = "1.2.3.4" # static function: gdcm.UIDGenerator_SetRoot( MY_ROOT ) for i in range(0,100): print(uid.Generate()) # Test succeed ? sys.exit(0) GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/000077500000000000000000000000001412732066400222275ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/CMakeLists.txt000066400000000000000000000000261412732066400247650ustar00rootroot00000000000000add_subdirectory(Cxx) GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/Cxx/000077500000000000000000000000001412732066400227715ustar00rootroot00000000000000GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/Cxx/CMakeLists.txt000066400000000000000000000042251412732066400255340ustar00rootroot00000000000000# MEXD Testing set(MEXD_TEST_SRCS TestPresentationContextRQ.cxx TestQueryFactory.cxx TestULConnectionManager.cxx TestServiceClassUser1.cxx TestServiceClassUser2.cxx TestServiceClassUser3.cxx TestSCUValidation.cxx TestEcho.cxx TestFind.cxx #TestULTransitionTable.cxx # symbols are not exported, mainly used for debugging TestFindStudyRootQuery.cxx TestFindPatientRootQuery.cxx ) if(GDCM_DATA_ROOT) set(MEXD_TEST_SRCS ${MEXD_TEST_SRCS} TestSCUFunctions.cxx ) endif() # Add the include paths include_directories( "${GDCM_BINARY_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Source/Common" "${GDCM_SOURCE_DIR}/Testing/Source/Data" "${GDCM_BINARY_DIR}/Testing/Source/Data" "${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition" "${GDCM_SOURCE_DIR}/Source/DataDictionary" "${GDCM_SOURCE_DIR}/Source/MediaStorageAndFileFormat" "${GDCM_SOURCE_DIR}/Source/MessageExchangeDefinition" ) create_test_sourcelist(MEXDTests gdcmMEXDTests.cxx ${MEXD_TEST_SRCS} EXTRA_INCLUDE gdcmTestDriver.h ) add_executable(gdcmMEXDTests ${MEXDTests}) target_link_libraries(gdcmMEXDTests gdcmMEXD gdcmMSFF gdcmDSED gdcmDICT gdcmCommon) # Loop over files and create executables foreach(name ${MEXD_TEST_SRCS}) if(${name} STREQUAL "TestSCUFunctions.cxx" OR ${name} STREQUAL "TestServiceClassUser1.cxx" OR ${name} STREQUAL "TestServiceClassUser2.cxx" OR ${name} STREQUAL "TestServiceClassUser3.cxx" ) if(GDCM_DICOM_SERVER_AETITLE) add_test(NAME ${name} COMMAND gdcmMEXDTests ${name} ${GDCM_DICOM_CLIENT_AETITLE} ${GDCM_DICOM_SERVER_AETITLE} ${GDCM_DICOM_SERVER_PORT} ${GDCM_DICOM_CLIENT_PORT} ${GDCM_DICOM_SERVER_PEER}) endif() else() get_filename_component(testname ${name} NAME_WE) add_test(NAME ${testname} COMMAND gdcmMEXDTests ${testname}) endif() endforeach() set(DCMQRSCP_HOSTNAME gotlib) set(DCMQRSCP_PORT 5677) set(DCMQRSCP_DIRECTORY ${GDCM_TEMP_DIRECTORY}) configure_file( ${GDCM_SOURCE_DIR}/CMake/dcmqrscp.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/dcmqrscp.cfg ) # execute_process(COMMAND ${DCMTK_DCMQRSCP_EXECUTABLE} # --verbose --debug -c ${CMAKE_CURRENT_BINARY_DIR}/dcmqrscp.cfg) GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/Cxx/TestEcho.cxx000066400000000000000000000023121412732066400252310ustar00rootroot00000000000000/*========================================================================= * * Copyright Insight Software Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmCompositeNetworkFunctions.h" #include "gdcmTag.h" #include "gdcmQueryFactory.h" int TestEcho(int , char *[]) { std::string hostname = "www.dicomserver.co.uk"; uint16_t port = 11112; std::string callaetitle = "GDCM_ROCKS"; std::string callingaetitle = "ACME1"; bool didItWork = gdcm::CompositeNetworkFunctions::CEcho( hostname.c_str(), port, callingaetitle.c_str(), callaetitle.c_str() ); return (didItWork ? 0:1); } GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/Cxx/TestFind.cxx000066400000000000000000000040731412732066400252410ustar00rootroot00000000000000/*========================================================================= * * Copyright Insight Software Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmCompositeNetworkFunctions.h" #include "gdcmTag.h" #include "gdcmQueryFactory.h" #include "gdcmMovePatientRootQuery.h" int TestFind(int , char *[]) { std::string hostname = "www.dicomserver.co.uk"; uint16_t port = 11112; std::string callaetitle = "GDCM_ROCKS"; std::string callingaetitle = "ACME1"; gdcm::Tag theTag(0x0010, 0x0010); std::string theName = "F*"; std::pair theTagPair = std::make_pair(theTag, theName); std::vector > theTags; theTags.push_back(theTagPair); gdcm::BaseRootQuery* theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery( gdcm::ePatientRootType, gdcm::ePatient, theTags); if (!theQuery) { std::cerr << "Query construction failed!" << std::endl; return 1; } if (!theQuery->ValidateQuery(false)) { std::cerr << "Find query is not valid. Please try again." << std::endl; delete theQuery; return 1; } std::vector theDataSet ; bool b = gdcm::CompositeNetworkFunctions::CFind(hostname.c_str(), port, theQuery, theDataSet , callingaetitle.c_str(), callaetitle.c_str()); if( !b ) return 1; //need to put some kind of validation of theDataSet here return (theDataSet.empty() ? 1:0);//shouldn't be a zero-sized dataset } GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/Cxx/TestFindPatientRootQuery.cxx000066400000000000000000000207661412732066400304670ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFindPatientRootQuery.h" #include "gdcmCompositeNetworkFunctions.h" #include "gdcmTrace.h" /* * STUDY: * $ findscu --call GDCM_STORE --aetitle GDCMDASH -P server 11112 -k 8,52="PATIENT" -k 10,20="1*" * $ findscu --call GDCM_STORE --aetitle GDCMDASH -S server 11112 -k 8,52="STUDY" -k 10,20="FOO" * * SERIES: * $ findscu --call GDCM_STORE --aetitle GDCMDASH -S lirispat 11112 -k 8,52="SERIES" -k 20,d="1.2.3" -k 8,60 */ int TestFindPatientRootQuery(int , char *[]) { //gdcm::Trace::DebugOn(); gdcm::Trace::WarningOff(); // PATIENT: gdcm::ERootType theRoot = gdcm::ePatientRootType; gdcm::EQueryLevel theLevel = gdcm::ePatient; { std::vector< std::pair > keys; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // No key found is an error return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x10,0x10), "patient" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // required key return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x10,0x20), "patientid" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( !theQuery->ValidateQuery( true ) ) { // unique key return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x10,0x20), "patientid" ) ; keys.emplace_back( gdcm::Tag(0x10,0x10), "patient" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( !theQuery->ValidateQuery( true ) ) { // unique key + required return 1; } } // STUDY: theLevel = gdcm::eStudy; { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x10,0x10), "PATIENT" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // Patient Id is a Required Key in Study return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0x10), "studyid" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // Study Id is a required tag return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x8,0x90), "physician" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // ref physician's name is optional return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x10,0x20), "patientid" ) ; keys.emplace_back( gdcm::Tag(0x20,0xd), "studyuid" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( !theQuery->ValidateQuery( true ) ) { // Study UID is the unique tag return 1; } } // SERIES: theLevel = gdcm::eSeries; { std::vector< std::pair > keys; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // No key found is an error return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // No key at level Series return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; keys.emplace_back( gdcm::Tag(0x8,0x60), "" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // missing unique at series level return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; keys.emplace_back( gdcm::Tag(0x20,0xe), "4.5.6" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( !theQuery->ValidateQuery( true ) ) { // all unique keys present return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; keys.emplace_back( gdcm::Tag(0x20,0xe), "4.5.6" ) ; keys.emplace_back( gdcm::Tag(0x8,0x60), "" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( !theQuery->ValidateQuery( true ) ) { // all unique keys present and required is correct level return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; keys.emplace_back( gdcm::Tag(0x20,0xe), "4.5.6" ) ; keys.emplace_back( gdcm::Tag(0x8,0x20), "" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // all unique keys present and required is incorrect level return 1; } } // IMAGES: theLevel = gdcm::eImage; { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; keys.emplace_back( gdcm::Tag(0x20,0xe), "4.5.6" ) ; keys.emplace_back( gdcm::Tag(0x8,0x18), "7.8.9" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( !theQuery->ValidateQuery( true ) ) { // all unique keys present return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; keys.emplace_back( gdcm::Tag(0x20,0xe), "4.5.6" ) ; keys.emplace_back( gdcm::Tag(0x8,0x18), "7.8.9" ) ; keys.emplace_back( gdcm::Tag(0x20,0x13), "" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( !theQuery->ValidateQuery( true ) ) { // all unique keys present + required correct level return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; keys.emplace_back( gdcm::Tag(0x20,0xe), "4.5.6" ) ; keys.emplace_back( gdcm::Tag(0x8,0x18), "7.8.9" ) ; keys.emplace_back( gdcm::Tag(0x20,0x13), "" ) ; keys.emplace_back( gdcm::Tag(0x20,0x11), "" ) ; // series level gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // all unique keys present + required correct level + one incorrect return 1; } } //std::cout << "success" << std::endl; return 0; } GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/Cxx/TestFindStudyRootQuery.cxx000066400000000000000000000164051412732066400301660ustar00rootroot00000000000000/*========================================================================= 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 "gdcmFindStudyRootQuery.h" #include "gdcmCompositeNetworkFunctions.h" #include "gdcmTrace.h" /* * STUDY: * $ findscu --call GDCM_STORE --aetitle GDCMDASH -P server 11112 -k 8,52="PATIENT" -k 10,20="1*" * $ findscu --call GDCM_STORE --aetitle GDCMDASH -S server 11112 -k 8,52="STUDY" -k 10,20="FOO" * * SERIES: * $ findscu --call GDCM_STORE --aetitle GDCMDASH -S lirispat 11112 -k 8,52="SERIES" -k 20,d="1.2.3" -k 8,60 */ int TestFindStudyRootQuery(int , char *[]) { //gdcm::Trace::DebugOn(); gdcm::Trace::WarningOff(); // STUDY: gdcm::ERootType theRoot = gdcm::eStudyRootType; gdcm::EQueryLevel theLevel = gdcm::eStudy; { std::vector< std::pair > keys; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // No key found is an error return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x10,0x10), "PATIENT" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // Patient Id is a Required Key in Study return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0x10), "studyid" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // Study Id is a required tag return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x8,0x90), "physician" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // ref physician's name is optional return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "studyuid" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( !theQuery->ValidateQuery( true ) ) { // Study UID is the unique tag return 1; } } // SERIES: theLevel = gdcm::eSeries; { std::vector< std::pair > keys; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // No key found is an error return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // No key at level Series return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; keys.emplace_back( gdcm::Tag(0x8,0x60), "" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // missing unique at series level return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; keys.emplace_back( gdcm::Tag(0x20,0xe), "4.5.6" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( !theQuery->ValidateQuery( true ) ) { // all unique keys present return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; keys.emplace_back( gdcm::Tag(0x20,0xe), "4.5.6" ) ; keys.emplace_back( gdcm::Tag(0x8,0x60), "" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( !theQuery->ValidateQuery( true ) ) { // all unique keys present and required is correct level return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; keys.emplace_back( gdcm::Tag(0x20,0xe), "4.5.6" ) ; keys.emplace_back( gdcm::Tag(0x8,0x20), "" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // all unique keys present and required is incorrect level return 1; } } // IMAGES: theLevel = gdcm::eImage; { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; keys.emplace_back( gdcm::Tag(0x20,0xe), "4.5.6" ) ; keys.emplace_back( gdcm::Tag(0x8,0x18), "7.8.9" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( !theQuery->ValidateQuery( true ) ) { // all unique keys present return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; keys.emplace_back( gdcm::Tag(0x20,0xe), "4.5.6" ) ; keys.emplace_back( gdcm::Tag(0x8,0x18), "7.8.9" ) ; keys.emplace_back( gdcm::Tag(0x20,0x13), "" ) ; gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( !theQuery->ValidateQuery( true ) ) { // all unique keys present + required correct level return 1; } } { std::vector< std::pair > keys; keys.emplace_back( gdcm::Tag(0x20,0xd), "1.2.3" ) ; keys.emplace_back( gdcm::Tag(0x20,0xe), "4.5.6" ) ; keys.emplace_back( gdcm::Tag(0x8,0x18), "7.8.9" ) ; keys.emplace_back( gdcm::Tag(0x20,0x13), "" ) ; keys.emplace_back( gdcm::Tag(0x20,0x11), "" ) ; // series level gdcm::SmartPointer theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(theRoot, theLevel ,keys); if( theQuery->ValidateQuery( true ) ) { // all unique keys present + required correct level + one incorrect return 1; } } //std::cout << "success" << std::endl; return 0; } GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/Cxx/TestPresentationContextRQ.cxx000066400000000000000000000016301412732066400306400ustar00rootroot00000000000000/*========================================================================= * * Copyright Insight Software Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmPresentationContextRQ.h" int TestPresentationContextRQ(int , char *[]) { gdcm::network::PresentationContextRQ o; return 0; } GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/Cxx/TestQueryFactory.cxx000066400000000000000000000015771412732066400270240ustar00rootroot00000000000000/*========================================================================= * * Copyright Insight Software Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmQueryFactory.h" int TestQueryFactory(int , char *[]) { gdcm::QueryFactory o; (void)o; return 0; } GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/Cxx/TestSCUFunctions.cxx000066400000000000000000000237741412732066400267150ustar00rootroot00000000000000/*========================================================================= * * Copyright Insight Software Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmCompositeNetworkFunctions.h" #include "gdcmBaseRootQuery.h" //#include "gdcmDirectory.h" #include "gdcmScanner.h" #include "gdcmTesting.h" #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmAttribute.h" #include "gdcmGlobal.h" #include #include //this should maybe override == ? bool AreDataSetsEqual(const gdcm::DataSet& ds1, const gdcm::DataSet& ds2){ gdcm::DataSet::ConstIterator it1 = ds1.Begin(); gdcm::DataSet::ConstIterator it2 = ds2.Begin(); const gdcm::DataElement &de1 = *it1; const gdcm::DataElement &de2 = *it2; if( de1 == de2 ) { } while( it1 != ds1.End() && it2 != ds2.End() && *it1 == *it2 ) { ++it1; ++it2; } if( it1 != ds1.End() || it2 != ds2.End() ) { std::cerr << "Problem with:" << std::endl; if( it1 != ds1.End() ) { std::cerr << "ds1: " << *it1 << std::endl; } if( it2 != ds2.End() ) { std::cerr << "ds2: " << *it2 << std::endl; } return false; } return true; } bool checkbl( const char *filename ) { static const char *blacklist[] = { "PHILIPS_GDCM12xBug2.dcm", // #3196213 // W: DIMSE Warning: (GDCMSCU,ANY-SCP): DIMSE receiveDataSetInMemory: // dset->read() Failed (Corrupted data) "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm", "MR_Philips_Intera_PrivateSequenceImplicitVR.dcm", "GE_DLX-8-MONO2-PrivateSyntax.dcm", // Implicit VR Big Endian DLX (G.E Private) "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm", // Implicit VR Big Endian DLX (G.E Private) // W: DIMSE Warning: (STORESCU,ANY-SCP): sendMessage: unable to convert // dataset from 'JPEG Lossless, Non-hierarchical, Process 14' transfer // syntax to 'Big Endian Explicit' "SignedShortLosslessBug.dcm", "MR-MONO2-12-shoulder.dcm", // difficult for now: "SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs.acr", "MR-MONO2-12-an2.acr", "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm", nullptr }; for( const char **bl = blacklist; *bl; ++bl ) { const char *res = strstr( filename, *bl ); if( res ) { return true; } } return false; } int TestSCUFunctions(int argc, char *argv[]) { if( argc < 6 ) { std::cerr << argv[0] << " aetitle call portno moveReturnPort remote" << std::endl; return 1; } gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); std::string aetitle = argv[1]; // the ae title of this computer std::string call = argv[2]; // the ae title of the server uint16_t portno = (uint16_t)atoi(argv[3]); // the port of the server uint16_t moveReturnPort = (uint16_t)atoi(argv[4]); // the port over which return cstore scps are done for cmove std::string remote = argv[5]; //the ip address of the remote server std::string tmpdir = gdcm::Testing::GetTempDirectory( "TestSCUFunctions" ); std::string outputDir = tmpdir; //place to where data is returned by cmove //std::string inputDir = gdcm::Testing::GetDataRoot(); //input collection of data to transfer bool didItWork = gdcm::CompositeNetworkFunctions::CEcho( remote.c_str(), portno, aetitle.c_str(), call.c_str() ); if (!didItWork) { std::cerr << "Echo failed." << std::endl; return 1; } std::vector theFilenames; const char *filename; int i = 0; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { theFilenames.emplace_back(filename ); ++i; } // Fow now lets eliminate invalid candidates: // - no SOP Class UID // - no SOP Instance UID gdcm::Scanner sc; gdcm::Tag tts(0x0002,0x0010); gdcm::Tag sopclass(0x8,0x16); gdcm::Tag sopinstance(0x8,0x18); sc.AddTag( tts ); sc.AddTag( sopclass ); sc.AddTag( sopinstance ); if( !sc.Scan( theFilenames ) ) { return 1; } std::vector< gdcm::UIComp > validuids; validuids.emplace_back("1.2.840.10008.1.2" ); validuids.emplace_back("1.2.840.10008.1.2.1" ); //validuids.push_back( "1.2.840.10008.1.2.2" ); // remove any file without SOP Instance UID for( gdcm::Directory::FilenamesType::iterator it = theFilenames.begin(); it != theFilenames.end(); ) { const char *file = it->c_str(); const char* v1 = sc.GetValue(file, sopclass ); const char* v2 = sc.GetValue(file, sopinstance ); const char* v3 = sc.GetValue(file, tts ); gdcm::UIComp v3uid; if ( v3 ) v3uid = v3; std::vector< gdcm::UIComp >::const_iterator it2 = std::find( validuids.begin(), validuids.end(), v3uid ); if( !v1 || !v2 || !*v1 || !*v2 ) it = theFilenames.erase( it ); else if( checkbl( file ) ) it = theFilenames.erase( it ); else if( v3 && it2 == validuids.end() ) { //std::cerr << "erase: " << *it << " [" << v3uid << "]" << std::endl; it = theFilenames.erase( it ); } else ++it; } //store the datasets remotely didItWork = gdcm::CompositeNetworkFunctions::CStore(remote.c_str(), portno, theFilenames, aetitle.c_str(), call.c_str()); if (!didItWork) { std::cerr << "Store failed." << std::endl; return 1; } std::vector::iterator fitor; for (fitor = theFilenames.begin(); fitor < theFilenames.end(); ++fitor) { //read in the file gdcm::Reader theReader; theReader.SetFileName(fitor->c_str()); if (!theReader.Read()) { std::cerr << "Test failed, dicom file " << *fitor << " failed to load." < > keys; gdcm::Tag theTag(0x0010, 0x0010); gdcm::Tag theIDTag(0x0010, 0x0020); if (ds.FindDataElement(theTag)) { gdcm::DataElement de = ds.GetDataElement(theTag); const gdcm::ByteValue* bv = de.GetByteValue(); int theBufferLen = bv->GetLength(); if (theBufferLen < 2) continue; char* theBuf = new char[theBufferLen]; bv->GetBuffer(theBuf, theBufferLen); gdcm::UIComp theSearchStringRaw(theBuf, theBufferLen/2); delete [] theBuf; // HACK: std::string theSearchString = theSearchStringRaw.Trim(); std::replace( theSearchString.begin(), theSearchString.end(), ' ', '?'); theSearchString += "*"; std::cerr << "search for: [" << theSearchString << "]" << std::endl; if (theSearchString.size() %2 == 1) { theSearchString += " "; //to make sure everything is double spaced } keys.emplace_back(theTag, theSearchString); } else { continue; } std::string theEmptyString; keys.emplace_back(theIDTag, theEmptyString); gdcm::BaseRootQuery *theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(gdcm::ePatientRootType, gdcm::ePatient, keys); std::vector theDataSets; bool b = gdcm::CompositeNetworkFunctions::CFind(remote.c_str(), portno, theQuery, theDataSets, aetitle.c_str(), call.c_str()); //std::cout << theQuery->GetQueryDataSet() << std::endl; delete theQuery; if( !b ) { std::cerr << "Problem in CFind" << std::endl; return 1; } if (theDataSets.empty()) { std::cerr << "Unable to find the dataset that was just sent to the server, " << *fitor << std::endl; return 1; } keys.clear(); //if it's not empty, then pull it. std::vector::iterator itor; for (itor = theDataSets.begin(); itor != theDataSets.end(); itor++) { if (itor->FindDataElement(theIDTag)) { gdcm::DataElement de = itor->GetDataElement(theIDTag); const gdcm::ByteValue *bv = de.GetByteValue(); int theBufferLen = bv->GetLength(); char* theBuf = new char[theBufferLen]; bv->GetBuffer(theBuf, theBufferLen); std::string theSearchString(theBuf, theBuf + theBufferLen); delete [] theBuf; keys.emplace_back(theIDTag, theSearchString); gdcm::DataElement de2 = ds.GetDataElement(theIDTag); de2.SetVR( gdcm::VR::INVALID ); de.SetVR( gdcm::VR::INVALID ); if (!(de == de2)) { std::cerr << "Sent dataset does not match returned dataset ID. " << std::endl; std::cerr << de << std::endl; std::cerr << " vs " << std::endl; std::cerr << de2 << std::endl; std::cerr << "File: " << *fitor << std::endl; return 1; } break; } else { continue; } } if (keys.empty()) { std::cerr << "Sent dataset " << *fitor << " was not found by resulting CFind query. " << std::endl; return 1; } theQuery = gdcm::CompositeNetworkFunctions::ConstructQuery(gdcm::ePatientRootType, gdcm::ePatient, keys, gdcm::eMove ); didItWork = gdcm::CompositeNetworkFunctions::CMove(remote.c_str(), portno, theQuery, moveReturnPort, aetitle.c_str(), call.c_str(), outputDir.c_str() ); if ( !didItWork ) { std::cerr << "CMove failed for file " << *fitor << std::endl; return 1; } delete theQuery; std::cout << "File " << *fitor << " moved back to server." << std::endl; } return 0; } GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/Cxx/TestSCUValidation.cxx000066400000000000000000000214021412732066400270210ustar00rootroot00000000000000/*========================================================================= 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 "gdcmULConnectionManager.h" #include "gdcmPresentationContextGenerator.h" #include "gdcmReader.h" #include "gdcmAttribute.h" #include "gdcmDataSet.h" #include "gdcmUIDGenerator.h" #include "gdcmStringFilter.h" #include "gdcmWriter.h" #include "gdcmDirectory.h" #include "gdcmImageReader.h" #include "gdcmQueryFactory.h" #include "gdcmGlobal.h" static const char AETitle[] = "ANY"; static const char PeerAETitle[] = "ANY"; static const char ComputerName[] = "51.75.171.41"; // www.dicomserver.co.uk static int port = 11112; static gdcm::network::ULConnectionManager *GetConnectionManager(gdcm::BaseRootQuery* theQuery) { gdcm::PresentationContextGenerator generator; if( !generator.GenerateFromUID( theQuery->GetAbstractSyntaxUID() ) ) { gdcmErrorMacro( "Failed to generate pres. context." ); return nullptr; } gdcm::network::ULConnectionManager *theManager = new gdcm::network::ULConnectionManager(); if (!theManager->EstablishConnection(AETitle, PeerAETitle, ComputerName, 0, (uint16_t)port, 1000, generator.GetPresentationContexts() )) { throw gdcm::Exception("Failed to establish connection."); } return theManager; } #if 0 static std::vector GetPatientInfo(bool validateQuery, bool inStrictQuery) { std::vector theDataSets; gdcm::BaseRootQuery* theQuery = gdcm::QueryFactory::ProduceQuery(gdcm::ePatientRootType, gdcm::eFind, gdcm::ePatient); theQuery->SetSearchParameter(gdcm::Tag(0x8, 0x52), "PATIENT"); //Query/Retrieval Level theQuery->SetSearchParameter(gdcm::Tag(0x10,0x20), ""); //Patient ID theQuery->SetSearchParameter(gdcm::Tag(0x10,0x10), "*"); //Patient Name if(validateQuery && !theQuery->ValidateQuery(inStrictQuery)) { return theDataSets; } gdcm::network::ULConnectionManager *theManager = GetConnectionManager( theQuery ); theDataSets = theManager->SendFind( theQuery ); return theDataSets; } #endif static std::vector GetStudyInfo(const char *patientID, bool validateQuery, bool inStrictQuery) { std::vector theDataSets; gdcm::BaseRootQuery* theQuery = gdcm::QueryFactory::ProduceQuery(gdcm::eStudyRootType, gdcm::eFind, gdcm::eStudy); theQuery->SetSearchParameter(gdcm::Tag(0x8, 0x52), "STUDY"); //Query/Retrieval Level theQuery->SetSearchParameter(gdcm::Tag(0x10,0x20), patientID); //Patient ID theQuery->SetSearchParameter(gdcm::Tag(0x20, 0x10), ""); //Study ID theQuery->SetSearchParameter(gdcm::Tag(0x20, 0xD), ""); //Study Instance UID theQuery->SetSearchParameter(gdcm::Tag(0x20, 0xE), ""); //Series Instance UID if(validateQuery && !theQuery->ValidateQuery(inStrictQuery)) { return theDataSets; } gdcm::network::ULConnectionManager *theManager = GetConnectionManager( theQuery ); theDataSets = theManager->SendFind( theQuery ); return theDataSets; } static std::vector GetSeriesInfo(const char *patientID, const char *studyInstanceUID, bool validateQuery, bool inStrictQuery) { std::vector theDataSets; gdcm::BaseRootQuery* theQuery = gdcm::QueryFactory::ProduceQuery(gdcm::eStudyRootType, gdcm::eFind, gdcm::eSeries); theQuery->SetSearchParameter(gdcm::Tag(0x8, 0x52), "SERIES"); //Query/Retrieval Level theQuery->SetSearchParameter(gdcm::Tag(0x10,0x20), patientID); //Patient ID theQuery->SetSearchParameter(gdcm::Tag(0x20, 0xD), studyInstanceUID); //Study Instance UID theQuery->SetSearchParameter(gdcm::Tag(0x20, 0xE), ""); //Series Instance UID if(validateQuery && !theQuery->ValidateQuery(inStrictQuery)) { return theDataSets; } gdcm::network::ULConnectionManager *theManager = GetConnectionManager( theQuery ); theDataSets = theManager->SendFind( theQuery ); return theDataSets; } static std::vector GetImageInfo(const char *patientID, const char *studyInstanceUID, const char *seriesInstanceUID, bool validateQuery, bool inStrictQuery) { std::vector theDataSets; gdcm::BaseRootQuery* theQuery = gdcm::QueryFactory::ProduceQuery(gdcm::eStudyRootType, gdcm::eFind, gdcm::eImage); theQuery->SetSearchParameter(gdcm::Tag(0x8, 0x52), "SERIES"); //Query/Retrieval Level theQuery->SetSearchParameter(gdcm::Tag(0x10,0x20), patientID); //Patient ID theQuery->SetSearchParameter(gdcm::Tag(0x20, 0xD), studyInstanceUID); //Study Instance UID theQuery->SetSearchParameter(gdcm::Tag(0x20, 0xE), seriesInstanceUID); //Series Instance UID theQuery->SetSearchParameter(gdcm::Tag(0x8, 0x18), ""); //SOP Instance UID if(validateQuery && !theQuery->ValidateQuery(inStrictQuery)) { return theDataSets; } gdcm::network::ULConnectionManager *theManager = GetConnectionManager( theQuery ); theDataSets = theManager->SendFind( theQuery ); return theDataSets; } static void PrintDataSets(std::vector theDataSets) { std::vector::iterator itor; for (itor = theDataSets.begin(); itor < theDataSets.end(); itor++) itor->Print(std::cout); } int TestSCUValidation(int , char *[]) { try { //set this to true to use a strict interpretation of the DICOM standard for query validation bool theUseStrictQueries = false; //Case 1: //Here I want to retrieve Study Information for the known Patient. //Here I pass the PatientID as a input and I need to reterive the StudyId, //StudyDate and Series Instance UID. std::vector theDataSets = GetStudyInfo("Z354998", true, theUseStrictQueries); PrintDataSets(theDataSets); //In the above I validated the constructed Query. This will not allow to add the //Series Instance UID as a search parameter for the query. On the result of //this I can't get the SeriesInstanceUID from the study level. //Case 2: //Here I execute the above same CFind Query with out validating. //This will send the Query which is having the SeriesInstanceUID tag //in search parameter to the CFind. This will executed successfully and //returns the SeriesInsanceUID related to the given StudyUID. theDataSets = GetStudyInfo("Z354998", false, theUseStrictQueries); PrintDataSets(theDataSets); //case 3: //If I validated the Query Like case 1, I can't get the Series Instance UID from //Study level. With out SeriesInstanceUID I can't retrieve the other series Information. //In Series Level also I can't add the StudyInstanceUID or other study information //as a search parameter. It allows only SeriesInstanceUID, Modality and SeriesNumber //as a search parameter. theDataSets = GetSeriesInfo("Z354998", "1.2.826.0.1.3680043.4.1.19990124221049.2", true, theUseStrictQueries); PrintDataSets(theDataSets); //case 4: //If I execute the above same CFind Query for Get Series with out validating //the query, it will return the requested SeriesInstanceUID for Known Study level. theDataSets = GetSeriesInfo("Z354998", "1.2.826.0.1.3680043.4.1.19990124221049.2", false, theUseStrictQueries); PrintDataSets(theDataSets); //In StudyLevel I can't get the Series information(Ref:Case 2). In Series Level //also I can't get the Series information for the known Study Level(Ref:Case 3). //How should I get the Series level information for the known patient and study //level information??? //case 5: //For retrieve the Image Level Information (SOP Instance UID) for the known //Patient,Study and Series level information, the Image level query is not //allowing. It allows only SOP Instance UID and SOP Instance Number as a //search Query. theDataSets = GetImageInfo("Z354998", "1.2.826.0.1.3680043.4.1.19990124221049.2", "1.2.826.0.1.3680043.4.1.19990124221049.3", true, theUseStrictQueries); PrintDataSets(theDataSets); //case 6: //Image Level retrieval also give the required information with out //validate the generated Query. theDataSets = GetImageInfo("Z354998", "1.2.826.0.1.3680043.4.1.19990124221049.2", "1.2.826.0.1.3680043.4.1.19990124221049.3", false, theUseStrictQueries); PrintDataSets(theDataSets); } catch( std::exception & ) { return 1; } //I want the Following things to do in CFind Query. // 1. Reterive the Study Level Information for the known Patient. // 2. Reterive the Series Level Information for the known Patient and Study. // 3. Reterive the Image Level Information for the known Patient, Study and Series. return 0; } GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/Cxx/TestServiceClassUser1.cxx000066400000000000000000000203161412732066400276650ustar00rootroot00000000000000/*========================================================================= 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 "gdcmServiceClassUser.h" #include "gdcmDataEvent.h" #include "gdcmSimpleSubjectWatcher.h" #include "gdcmPresentationContextGenerator.h" #include "gdcmAttribute.h" #include "gdcmCompositeNetworkFunctions.h" #include "gdcmTransferSyntax.h" #include "gdcmWriter.h" #include "gdcmTesting.h" /* * This small example show how the association pipeline works. * the start association is an important step as it will define all the object * to be send in subsequence C-operation (c-echo, c-store, c-find, c-move). * In this example we will demonstrate how we can send a JPEG-Lossless object * and then further on, a non-jpeg encapsulated file * * The test also uses the Subject/Observer API for progress report. */ int TestServiceClassUser1(int argc, char *argv[]) { if( argc < 5 ) { std::cerr << argv[0] << " aetitle call portno moveReturnPort remote" << std::endl; return 1; } std::string aetitle = argv[1]; // the ae title of this computer std::string call = argv[2]; // the ae title of the server uint16_t portno = (uint16_t)atoi(argv[3]); // the port of the server uint16_t moveReturnPort = (uint16_t)atoi(argv[4]); // the port over which return cstore scps are done for cmove std::string remote = argv[5]; //the ip address of the remote server gdcm::SmartPointer scup = new gdcm::ServiceClassUser; gdcm::ServiceClassUser &scu = *scup; gdcm::SimpleSubjectWatcher w( &scu, "TestServiceClassUser1" ); scu.SetHostname( remote.c_str() ); scu.SetPort( portno ); scu.SetTimeout( 1000 ); scu.SetCalledAETitle( call.c_str() ); scu.SetAETitle( aetitle.c_str() ); std::ostringstream error_log; gdcm::Trace::SetErrorStream( error_log ); if( !scu.InitializeConnection() ) { return 1; } gdcm::PresentationContextGenerator generator; if( !generator.GenerateFromUID( gdcm::UIDs::VerificationSOPClass ) ) { return 1; } // make sure to fail if no pres. contexts: if( scu.StartAssociation() ) { return 1; } scu.SetPresentationContexts( generator.GetPresentationContexts() ); if( !scu.StartAssociation() ) { std::cerr << "Could not StartAssociation" << std::endl; std::cerr << "Error log is:" << std::endl; std::cerr << error_log.str() << std::endl; return 1; } // C-ECHO if( !scu.SendEcho() ) { std::cerr << "Could not Echo" << std::endl; std::cerr << "Error log is:" << std::endl; std::cerr << error_log.str() << std::endl; return 1; } if( !scu.StopAssociation() ) { return 1; } gdcm::Directory::FilenamesType filenames; const char *directory = gdcm::Testing::GetDataRoot(); // DEBUG: // storescu -R -xs --call GDCM_STORE macminig4 11112 gdcmData/012345.002.050.dcm std::string filename = std::string(directory) + "/012345.002.050.dcm"; filenames.push_back( filename ); if( !generator.GenerateFromFilenames(filenames) ) { return 1; } scu.SetPresentationContexts( generator.GetPresentationContexts() ); if( !scu.StartAssociation() ) { return 1; } // C-STORE MRImageStorage/JPEGLossless if( !scu.SendStore( filename.c_str() ) ) { std::cerr << "Could not C-Store" << std::endl; std::cerr << "Error log is:" << std::endl; std::cerr << error_log.str() << std::endl; return 1; } if( !scu.StopAssociation() ) { return 1; } //filename = std::string(directory) + "/MR-MONO2-12-an2.acr"; filename = std::string(directory) + "/MR_Spectroscopy_SIEMENS_OF.dcm"; filenames.clear(); filenames.push_back( filename ); if( !generator.GenerateFromFilenames(filenames) ) { return 1; } scu.SetPresentationContexts( generator.GetPresentationContexts() ); if( !scu.StartAssociation() ) { return 1; } // C-STORE MRImageStorage/LittleEndianImplicit if( !scu.SendStore( filename.c_str() ) ) { std::cerr << "Could not SendStore" << std::endl; std::cerr << "Error log is:" << std::endl; std::cerr << error_log.str() << std::endl; return 1; } if( !scu.StopAssociation() ) { return 1; } // customize the find query gdcm::DataSet findds; gdcm::Attribute<0x10,0x10> pn1 ={"ABCDEFGH^IJKLM"}; findds.Insert( pn1.GetAsDataElement() ); gdcm::Attribute<0x10,0x20> pid; findds.Insert( pid.GetAsDataElement() ); gdcm::SmartPointer findquery = gdcm::CompositeNetworkFunctions::ConstructQuery( gdcm::ePatientRootType, gdcm::ePatient, findds); // make sure the query is valid if (!findquery->ValidateQuery()) { return 1; } // Generate the PresentationContext array from the query UID: if( !generator.GenerateFromUID( findquery->GetAbstractSyntaxUID() ) ) { return 1; } scu.SetPresentationContexts( generator.GetPresentationContexts() ); if( !scu.StartAssociation() ) { return 1; } // C-FIND std::vector datasets; if( !scu.SendFind(findquery, datasets) ) { return 1; } // Need to make sure we have one dataset if( datasets.size() != 1 ) { std::cerr << "size: " << datasets.size() << std::endl; return 1; } datasets[0].Print( std::cout ); // C-find the second patient gdcm::Attribute<0x10,0x10> pn2 ={"XXXXXXXXXXX"}; findquery->GetQueryDataSet().Replace( pn2.GetAsDataElement() ); if( !scu.SendFind(findquery, datasets) ) { return 1; } if( datasets.size() != 2 ) { std::cerr << "size: " << datasets.size() << std::endl; return 1; } std::cout << std::endl; datasets[1].Print( std::cout ); if( !scu.StopAssociation() ) { return 1; } // C-MOVE // customize the move query gdcm::DataSet moveds; // use results from the c-find to construct the c-move query: moveds.Insert( datasets[0].GetDataElement( pid.GetTag() ) ); gdcm::SmartPointer movequery = gdcm::CompositeNetworkFunctions::ConstructQuery( gdcm::ePatientRootType, gdcm::ePatient, moveds, gdcm::eMove); // make sure the query is valid if (!movequery->ValidateQuery()) { return 1; } //generator.SetDefaultTransferSyntax( gdcm::TransferSyntax::JPEGLosslessProcess14_1 ); // Generate the PresentationContext array from the query UID: if( !generator.GenerateFromUID( movequery->GetAbstractSyntaxUID() ) ) { return 1; } scu.SetPresentationContexts( generator.GetPresentationContexts() ); scu.SetPortSCP( moveReturnPort ); if( !scu.StartAssociation() ) { return 1; } // C-MOVE std::vector data; if( !scu.SendMove(movequery, data) ) { return 1; } if( data.size() != 1 ) { std::cerr << "data size: " << data.size() << std::endl; return 1; } // SendMove + dataset is implicit by default: gdcm::Writer writer; writer.GetFile().GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian ); writer.GetFile().SetDataSet( data[0] ); const char *outfilename = "dummy.dcm"; writer.SetFileName( outfilename ); if( !writer.Write() ) { return 1; } if( !gdcm::System::FileExists(outfilename) ) { std::cerr << "FileExists: " << outfilename << std::endl; return 1; } char digest_str[33]; if( !gdcm::Testing::ComputeFileMD5(outfilename, digest_str) ) { return 1; } if( strcmp( digest_str, "ae1f9a1bfc617f73ae8f72f81777dc03") != 0 ) { std::cerr << "md5: " << digest_str << std::endl; return 1; } // TODO: testing of CMove + JPEG Lossless is a *lot* more difficult // since we have to assume some behavior on the remote side (SCP) which // we cannot query. if( !scu.StopAssociation() ) { return 1; } // scu dstor will close the connection (!= association) return 0; } GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/Cxx/TestServiceClassUser2.cxx000066400000000000000000000174111412732066400276700ustar00rootroot00000000000000/*========================================================================= 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 "gdcmServiceClassUser.h" #include "gdcmDataEvent.h" #include "gdcmSimpleSubjectWatcher.h" #include "gdcmPresentationContextGenerator.h" #include "gdcmAttribute.h" #include "gdcmCompositeNetworkFunctions.h" #include "gdcmTransferSyntax.h" #include "gdcmWriter.h" #include "gdcmReader.h" #include "gdcmUIDGenerator.h" #include "gdcmTesting.h" /* * This test make sure we can send/receive as many dataset as we want */ int TestServiceClassUser2(int argc, char *argv[]) { if( argc < 5 ) { std::cerr << argv[0] << " aetitle call portno moveReturnPort remote" << std::endl; return 1; } std::string aetitle = argv[1]; // the ae title of this computer std::string call = argv[2]; // the ae title of the server uint16_t portno = (uint16_t)atoi(argv[3]); // the port of the server uint16_t moveReturnPort = (uint16_t)atoi(argv[4]); // the port over which return cstore scps are done for cmove std::string remote = argv[5]; //the ip address of the remote server gdcm::SmartPointer scup = new gdcm::ServiceClassUser; gdcm::ServiceClassUser &scu = *scup; gdcm::SimpleSubjectWatcher w( &scu, "TestServiceClassUser2" ); scu.SetHostname( remote.c_str() ); scu.SetPort( portno ); scu.SetTimeout( 1000 ); scu.SetCalledAETitle( call.c_str() ); scu.SetAETitle( aetitle.c_str() ); std::ostringstream error_log; gdcm::Trace::SetErrorStream( error_log ); if( !scu.InitializeConnection() ) { return 1; } gdcm::PresentationContextGenerator generator; if( !generator.GenerateFromUID( gdcm::UIDs::VerificationSOPClass ) ) { return 1; } // make sure to fail if no pres. contexts: if( scu.StartAssociation() ) { return 1; } scu.SetPresentationContexts( generator.GetPresentationContexts() ); if( !scu.StartAssociation() ) { return 1; } // C-ECHO if( !scu.SendEcho() ) { return 1; } if( !scu.StopAssociation() ) { return 1; } gdcm::Directory::FilenamesType filenames; const char *directory = gdcm::Testing::GetDataRoot(); // storescu -R -xs --call GDCM_STORE macminig4 11112 gdcmData/gdcm-MR-PHILIPS-16-NonSquarePixels.dcm std::string filename = std::string(directory) + "/gdcm-MR-PHILIPS-16-NonSquarePixels.dcm"; filenames.push_back( filename ); if( !generator.GenerateFromUID( gdcm::UIDs::MRImageStorage ) ) { return 1; } scu.SetPresentationContexts( generator.GetPresentationContexts() ); if( !scu.StartAssociation() ) { return 1; } gdcm::Reader reader; reader.SetFileName( filename.c_str() ); if( !reader.Read() ) { return 1; } gdcm::File & file = reader.GetFile(); gdcm::UIDGenerator uid; const int nmax = 500; for( int i = 0; i < nmax; ++i ) { gdcm::DataSet & ds = file.GetDataSet(); std::string instance_uid = uid.Generate(); { gdcm::Attribute<0x8,0x18> at; at.SetValue( instance_uid.c_str() ); ds.Replace( at.GetAsDataElement() ); } { gdcm::Attribute<0x10,0x20> at; at.SetValue( "TestServiceClassUser2" ); ds.Replace( at.GetAsDataElement() ); } if( !scu.SendStore( file.GetDataSet() ) ) { return 1; } } if( !scu.StopAssociation() ) { return 1; } // customize the find query gdcm::DataSet findds; gdcm::Attribute<0x10,0x20> pid ={"TestServiceClassUser2"}; findds.Insert( pid.GetAsDataElement() ); gdcm::Attribute<0x8,0x18> iuid; findds.Insert( iuid.GetAsDataElement() ); gdcm::SmartPointer findquery = gdcm::CompositeNetworkFunctions::ConstructQuery( gdcm::ePatientRootType, gdcm::eImage, findds); // make sure the query is valid if (!findquery->ValidateQuery(false)) { return 1; } // Generate the PresentationContext array from the query UID: if( !generator.GenerateFromUID( findquery->GetAbstractSyntaxUID() ) ) { return 1; } scu.SetPresentationContexts( generator.GetPresentationContexts() ); if( !scu.StartAssociation() ) { return 1; } // C-FIND // $ findscu --call GDCM_STORE -P macminig4 11112 -k 8,52=IMAGE -k // 10,20=TestServiceClassUser2 -k 20,d -k 20,e -k 8,18 // gdcmscu --find --call GDCM_STORE --image --patientroot macminig4 11112 // -k 10,20=TestServiceClassUser2 -k 8,18 std::vector datasets; if( !scu.SendFind(findquery, datasets) ) { return 1; } if( !scu.StopAssociation() ) { return 1; } // C-MOVE // customize the move query gdcm::DataSet moveds1; // use results from the C-FIND to construct the c-move query: moveds1.Insert( datasets[0].GetDataElement( gdcm::Tag(0x10,0x20) ) ); moveds1.Insert( datasets[0].GetDataElement( gdcm::Tag(0x20,0xd) ) ); moveds1.Insert( datasets[0].GetDataElement( gdcm::Tag(0x20,0xe) ) ); gdcm::SmartPointer movequery1 = gdcm::CompositeNetworkFunctions::ConstructQuery( gdcm::ePatientRootType, gdcm::eImage, moveds1, gdcm::eMove); // Generate the PresentationContext array from the query UID: if( !generator.GenerateFromUID( movequery1->GetAbstractSyntaxUID() ) ) { return 1; } scu.SetPresentationContexts( generator.GetPresentationContexts() ); scu.SetPortSCP( moveReturnPort ); if( !scu.StartAssociation() ) { return 1; } size_t ndatasets = 0; for( std::vector::const_iterator cfind_it = datasets.begin(); cfind_it != datasets.end(); ++cfind_it ) { gdcm::DataSet &queryds = movequery1->GetQueryDataSet(); const gdcm::DataElement &instanceuid = cfind_it->GetDataElement( gdcm::Tag(0x8,0x18) ); queryds.Replace( instanceuid ); // C-MOVE std::vector data; if( !scu.SendMove(movequery1, data) ) { std::cerr << "CMove Failure for: " << instanceuid << std::endl; std::cerr << "Error log is:" << std::endl; std::cerr << error_log.str() << std::endl; return 1; } if( data.size() != 1 ) { std::cerr << "data size: " << data.size() << std::endl; return 1; } ++ndatasets; } //std::cerr << "Total number of dataset: " << ndatasets << std::endl; // Now let's do this again with a simpler request: gdcm::DataSet moveds2; moveds2.Insert( pid.GetAsDataElement() ); gdcm::SmartPointer movequery2 = gdcm::CompositeNetworkFunctions::ConstructQuery( gdcm::ePatientRootType, gdcm::ePatient, moveds2, gdcm::eMove ); const char outputdir[] = "TestServiceClassUser2"; // Make sure output dir exist, it will not be created if( gdcm::System::FileIsDirectory( outputdir ) ) { // cleanups old files: gdcm::System::DeleteDirectory( outputdir ); } gdcm::System::MakeDirectory( outputdir ); if( !scu.SendMove(movequery2, outputdir) ) { std::cerr << "CMove Failure for Patient ID: " << pid.GetValue() << std::endl; return 1; } // Compare results: gdcm::Directory dir; unsigned int ndatasets2 = dir.Load( outputdir, true ); if( ndatasets != ndatasets2 ) { std::cerr << "Incompatible number of results: " << ndatasets << " vs " << ndatasets2 << std::endl; return 1; } if( !scu.StopAssociation() ) { return 1; } // scu dstor will close the connection (!= association) return 0; } GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/Cxx/TestServiceClassUser3.cxx000066400000000000000000000077621412732066400277010ustar00rootroot00000000000000/*========================================================================= 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 "gdcmServiceClassUser.h" #include "gdcmDataEvent.h" #include "gdcmSimpleSubjectWatcher.h" #include "gdcmPresentationContextGenerator.h" #include "gdcmAttribute.h" #include "gdcmCompositeNetworkFunctions.h" #include "gdcmTransferSyntax.h" #include "gdcmWriter.h" #include "gdcmReader.h" #include "gdcmUIDGenerator.h" #include "gdcmTesting.h" /* * This test actually fails on D. Clunie PACS, but succeed on DicomObject (www.dicomserver.co.uk)... * * $ findscu 184.73.255.26 11112 --call AWSPIXELMEDPUB -P -k 8,52=IMAGE -k 8,16="1.*" -k 20,d * $ gdcmscu --find 184.73.255.26 11112 --call AWSPIXELMEDPUB --patientroot --image -k 8,16="1.*" -k 20,d */ int TestServiceClassUser3(int argc, char *argv[]) { if( argc < 5 ) { std::cerr << argv[0] << " aetitle call portno moveReturnPort remote" << std::endl; return 1; } std::string aetitle = argv[1]; // the ae title of this computer std::string call = argv[2]; // the ae title of the server uint16_t portno = (uint16_t)atoi(argv[3]); // the port of the server uint16_t moveReturnPort = (uint16_t)atoi(argv[4]); // the port over which return cstore scps are done for cmove std::string remote = argv[5]; //the ip address of the remote server (void)moveReturnPort; gdcm::SmartPointer scup = new gdcm::ServiceClassUser; gdcm::ServiceClassUser &scu = *scup; gdcm::SimpleSubjectWatcher w( &scu, "TestServiceClassUser3" ); std::ostringstream error_log; gdcm::Trace::SetErrorStream( error_log ); scu.SetHostname( remote.c_str() ); scu.SetPort( portno ); scu.SetTimeout( 1000 ); scu.SetCalledAETitle( call.c_str() ); scu.SetAETitle( aetitle.c_str() ); if( !scu.InitializeConnection() ) { return 1; } gdcm::PresentationContextGenerator generator; if( !generator.GenerateFromUID( gdcm::UIDs::VerificationSOPClass ) ) { return 1; } // make sure to fail if no pres. contexts: if( scu.StartAssociation() ) { return 1; } scu.SetPresentationContexts( generator.GetPresentationContexts() ); if( !scu.StartAssociation() ) { return 1; } // C-ECHO if( !scu.SendEcho() ) { return 1; } if( !scu.StopAssociation() ) { return 1; } // customize the find query gdcm::DataSet findds; gdcm::Attribute<0x8,0x16> sop ={"1.*"}; findds.Insert( sop.GetAsDataElement() ); gdcm::Attribute<0x20,0xd> uid; findds.Insert( uid.GetAsDataElement() ); gdcm::SmartPointer findquery = gdcm::CompositeNetworkFunctions::ConstructQuery( gdcm::ePatientRootType, gdcm::eImage, findds); // make sure the query is valid findquery->Print( std::cout ); if (!findquery->ValidateQuery(false)) { return 1; } // Generate the PresentationContext array from the query UID: if( !generator.GenerateFromUID( findquery->GetAbstractSyntaxUID() ) ) { return 1; } scu.SetPresentationContexts( generator.GetPresentationContexts() ); if( !scu.StartAssociation() ) { return 1; } // C-FIND std::vector datasets; // This is an error if the previous query succeed: if( scu.SendFind(findquery, datasets) ) { std::cerr << "Could SendFind, this is not possible !" << std::endl; std::cerr << "Error log is:" << std::endl; std::cerr << error_log.str() << std::endl; return 1; } if( !scu.StopAssociation() ) { return 1; } // scu dstor will close the connection (!= association) return 0; } GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/Cxx/TestULConnectionManager.cxx000066400000000000000000000016221412732066400302110ustar00rootroot00000000000000/*========================================================================= * * Copyright Insight Software Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #include "gdcmULConnectionManager.h" int TestULConnectionManager(int , char *[]) { gdcm::network::ULConnectionManager o; return 0; } GDCM-3.0.10/Testing/Source/MessageExchangeDefinition/Cxx/TestULTransitionTable.cxx000066400000000000000000000017671412732066400277330ustar00rootroot00000000000000/*========================================================================= 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 "gdcmULTransitionTable.h" #include "gdcmULActionAA.h" int TestULTransitionTable(int , char *[]) { gdcm::network::Transition t1; gdcm::network::Transition *t2 = gdcm::network::Transition::MakeNew( gdcm::network::eSta1Idle, new gdcm::network::ULActionAA2() ); gdcm::network::TableRow tr1; //tr1.transitions[0] = &t1; // no stack please tr1.transitions[1] = t2; gdcm::network::ULTransitionTable o; return 0; } GDCM-3.0.10/Utilities/000077500000000000000000000000001412732066400142655ustar00rootroot00000000000000GDCM-3.0.10/Utilities/CMakeLists.txt000066400000000000000000000110311412732066400170210ustar00rootroot00000000000000# Wrapping and stuff # Do jpeg (8,12, 16 lossly lossless). From ijg APPEND_COPYRIGHT(${CMAKE_CURRENT_SOURCE_DIR}/gdcmjpeg/COPYRIGHT.dcmtk) if(NOT GDCM_USE_SYSTEM_LJPEG) set(JPEG_NAMESPACE "GDCMJPEG") set(JPEG_INSTALL_NO_LIBRARIES ${GDCM_INSTALL_NO_LIBRARIES}) set(JPEG_INSTALL_BIN_DIR ${GDCM_INSTALL_BIN_DIR}) set(JPEG_INSTALL_LIB_DIR ${GDCM_INSTALL_LIB_DIR}) set(JPEG_INSTALL_INCLUDE_DIR ${GDCM_INSTALL_INCLUDE_DIR}/gdcmjpeg) add_subdirectory(gdcmjpeg) endif() # Do expat APPEND_COPYRIGHT(${CMAKE_CURRENT_SOURCE_DIR}/gdcmexpat/COPYING) if(NOT GDCM_USE_SYSTEM_EXPAT) set(EXPAT_NAMESPACE "GDCMEXPAT") set(EXPAT_INSTALL_NO_LIBRARIES ${GDCM_INSTALL_NO_LIBRARIES}) set(EXPAT_INSTALL_BIN_DIR ${GDCM_INSTALL_BIN_DIR}) set(EXPAT_INSTALL_LIB_DIR ${GDCM_INSTALL_LIB_DIR}) add_subdirectory(gdcmexpat) endif() # Do openjpeg (jpeg2000 implementation) APPEND_COPYRIGHT(${CMAKE_CURRENT_SOURCE_DIR}/gdcmopenjpeg/LICENSE) if(NOT GDCM_USE_SYSTEM_OPENJPEG) set(OPENJPEG_NAMESPACE "GDCMOPENJPEG") set(OPENJPEG_INSTALL_NO_LIBRARIES ${GDCM_INSTALL_NO_LIBRARIES}) set(OPENJPEG_INSTALL_BIN_DIR ${GDCM_INSTALL_BIN_DIR}) set(OPENJPEG_INSTALL_LIB_DIR ${GDCM_INSTALL_LIB_DIR}) set(OPENJPEG_INSTALL_INCLUDE_DIR ${GDCM_INSTALL_INCLUDE_DIR}/gdcmopenjpeg) add_subdirectory(gdcmopenjpeg) mark_as_advanced(BUILD_JPIP BUILD_JPWL BUILD_CODEC BUILD_DOC BUILD_MJ2 BUILD_PKGCONFIG_FILES BUILD_SHARED_LIBS BUILD_THIRDPARTY OPJ_DATA_ROOT OPJ_DISABLE_TPSOT_FIX OPJ_USE_THREAD) endif() # Do jpegls (JPEG-LS aka near lossless implementation) APPEND_COPYRIGHT(${CMAKE_CURRENT_SOURCE_DIR}/gdcmcharls/License.txt) if(GDCM_USE_JPEGLS) if(NOT GDCM_USE_SYSTEM_CHARLS) set(CHARLS_NAMESPACE "GDCMCHARLS") set(CHARLS_INSTALL_NO_LIBRARIES ${GDCM_INSTALL_NO_LIBRARIES}) set(CHARLS_INSTALL_BIN_DIR ${GDCM_INSTALL_BIN_DIR}) set(CHARLS_INSTALL_LIB_DIR ${GDCM_INSTALL_LIB_DIR}) set(CHARLS_INSTALL_INCLUDE_DIR ${GDCM_INSTALL_INCLUDE_DIR}/gdcmcharls) add_subdirectory(gdcmcharls) endif() endif() # Do md5 APPEND_COPYRIGHT(${CMAKE_CURRENT_SOURCE_DIR}/gdcmmd5/COPYING) if(GDCM_BUILD_TESTING) if(NOT GDCM_USE_SYSTEM_MD5) set(MD5_NAMESPACE "GDCMMD5") set(MD5_INSTALL_NO_LIBRARIES ${GDCM_INSTALL_NO_LIBRARIES}) set(MD5_INSTALL_BIN_DIR ${GDCM_INSTALL_BIN_DIR}) set(MD5_INSTALL_LIB_DIR ${GDCM_INSTALL_LIB_DIR}) add_subdirectory(gdcmmd5) endif() endif() # Do zlib APPEND_COPYRIGHT(${CMAKE_CURRENT_SOURCE_DIR}/gdcmzlib/COPYING) if(NOT GDCM_USE_SYSTEM_ZLIB) set(ZLIB_NAMESPACE "GDCMZLIB") set(ZLIB_INSTALL_NO_LIBRARIES ${GDCM_INSTALL_NO_LIBRARIES}) set(ZLIB_INSTALL_BIN_DIR ${GDCM_INSTALL_BIN_DIR}) set(ZLIB_INSTALL_LIB_DIR ${GDCM_INSTALL_LIB_DIR}) add_subdirectory(gdcmzlib) endif() # Do getopt if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/getopt) APPEND_COPYRIGHT(${CMAKE_CURRENT_SOURCE_DIR}/getopt/COPYING) if(WIN32 AND NOT CYGWIN AND NOT MINGW) set(GETOPT_NAMESPACE "GDCMGETOPT") set(GETOPT_INSTALL_NO_LIBRARIES ${GDCM_INSTALL_NO_LIBRARIES}) set(GETOPT_INSTALL_BIN_DIR ${GDCM_INSTALL_BIN_DIR}) set(GETOPT_INSTALL_LIB_DIR ${GDCM_INSTALL_LIB_DIR}) add_subdirectory(getopt) endif() endif() # you could be running mingw32 on linux in which case you do NOT want the gdcmuuid lib APPEND_COPYRIGHT(${CMAKE_CURRENT_SOURCE_DIR}/gdcmuuid/COPYING) if(NOT WIN32 AND NOT MINGW) if(NOT GDCM_USE_SYSTEM_UUID) set(UUID_NAMESPACE "GDCMUUID") set(UUID_INSTALL_NO_LIBRARIES ${GDCM_INSTALL_NO_LIBRARIES}) set(UUID_INSTALL_BIN_DIR ${GDCM_INSTALL_BIN_DIR}) set(UUID_INSTALL_LIB_DIR ${GDCM_INSTALL_LIB_DIR}) add_subdirectory(gdcmuuid) endif() endif() APPEND_COPYRIGHT(${CMAKE_CURRENT_SOURCE_DIR}/pvrg/COPYING) if(GDCM_USE_PVRG) if(NOT GDCM_USE_SYSTEM_PVRG) add_subdirectory(pvrg) endif() endif() #if(NOT GDCM_INSTALL_NO_DEVELOPMENT) ## file(GLOB header_files "*.h" "*.txx") # install(FILES ##${header_files} #gdcm_expat.h ##gdcm_md5.h # In an install tree there should not be the need for the md5 lib... #gdcm_openjpeg.h #gdcm_uuid.h #gdcm_zlib.h # DESTINATION ${GDCM_INSTALL_INCLUDE_DIR} COMPONENT Headers # ) #endif() if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/KWStyle) add_subdirectory(KWStyle) endif() if(NOT GDCM_USE_SYSTEM_SOCKETXX) #set(SOCKETXX_NAMESPACE "GDCMSOCKETXX") set(SOCKETXX_INSTALL_NO_LIBRARIES ${GDCM_INSTALL_NO_LIBRARIES}) set(SOCKETXX_INSTALL_BIN_DIR ${GDCM_INSTALL_BIN_DIR}) set(SOCKETXX_INSTALL_LIB_DIR ${GDCM_INSTALL_LIB_DIR}) set(SOCKETXX_INSTALL_INCLUDE_DIR ${GDCM_INSTALL_INCLUDE_DIR}/socketxx) add_subdirectory(socketxx) endif() add_subdirectory(gdcmrle) GDCM-3.0.10/Utilities/KWStyle/000077500000000000000000000000001412732066400156275ustar00rootroot00000000000000GDCM-3.0.10/Utilities/KWStyle/CMakeLists.txt000066400000000000000000000027411412732066400203730ustar00rootroot00000000000000#----------------------------------------------------------------------------- # GDCM uses KWStyle for checking the coding style option(GDCM_USE_KWSTYLE "Run KWStyle in order to check for violations of the coding standard." OFF) mark_as_advanced(GDCM_USE_KWSTYLE) if(GDCM_USE_KWSTYLE) find_package(KWStyle) configure_file(${GDCM_SOURCE_DIR}/Utilities/KWStyle/GDCM.kws.xml.in ${GDCM_BINARY_DIR}/Utilities/KWStyle/GDCM.kws.xml) #configure_file(${GDCM_SOURCE_DIR}/Utilities/KWStyle/GDCMMoreChecks.kws.xml.in # ${GDCM_BINARY_DIR}/GDCMMoreChecks.kws.xml) configure_file(${GDCM_SOURCE_DIR}/Utilities/KWStyle/GDCMFiles.txt.in ${GDCM_BINARY_DIR}/Utilities/KWStyle/GDCMFiles.txt) add_custom_command( OUTPUT ${GDCM_BINARY_DIR}/KWStyleReport.txt COMMAND ${KWSTYLE_EXECUTABLE} ARGS -xml ${GDCM_BINARY_DIR}/Utilities/KWStyle/GDCM.kws.xml -o ${GDCM_SOURCE_DIR}/Utilities/KWStyle/GDCMOverwrite.txt -v ${KWSTYLE_ARGUMENTS} -D ${GDCM_BINARY_DIR}/Utilities/KWStyle/GDCMFiles.txt COMMENT "Coding Style Checker" ) #add_custom_target(MoreStyleChecks # COMMAND ${KWSTYLE_EXECUTABLE} # -xml ${GDCM_BINARY_DIR}/GDCMMoreChecks.kws.xml -html ${GDCM_BINARY_DIR}/html -o ${GDCM_SOURCE_DIR}/Utilities/KWStyle/GDCMOverwrite.txt -v ${KWSTYLE_ARGUMENTS} -D ${GDCM_BINARY_DIR}/GDCMKWSFiles.txt # COMMENT "Coding Style Checker, more checks enabled" # ) add_custom_target(StyleCheck DEPENDS ${GDCM_BINARY_DIR}/KWStyleReport.txt) endif() GDCM-3.0.10/Utilities/KWStyle/GDCM.kws.xml.in000066400000000000000000000003761412732066400203010ustar00rootroot00000000000000 81 GDCM-3.0.10/Utilities/KWStyle/GDCMFiles.txt.in000066400000000000000000000011061412732066400204700ustar00rootroot00000000000000"@GDCM_SOURCE_DIR@/Source/Common/*.h" "@GDCM_SOURCE_DIR@/Source/Common/*.cxx" "@GDCM_SOURCE_DIR@/Source/Common/*.txx" "@GDCM_SOURCE_DIR@/Source/DataDictionary/*.h" "@GDCM_SOURCE_DIR@/Source/DataDictionary/*.cxx" "@GDCM_SOURCE_DIR@/Source/DataStructureAndEncodingDefinition/*.h" "@GDCM_SOURCE_DIR@/Source/DataStructureAndEncodingDefinition/*.cxx" "@GDCM_SOURCE_DIR@/Source/InformationObjectDefinition/*.h" "@GDCM_SOURCE_DIR@/Source/InformationObjectDefinition/*.cxx" "@GDCM_SOURCE_DIR@/Source/MediaStorageAndFileFormat/*.h" "@GDCM_SOURCE_DIR@/Source/MediaStorageAndFileFormat/*.cxx" GDCM-3.0.10/Utilities/KWStyle/GDCMHeader.h000066400000000000000000000010641412732066400176240ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ GDCM-3.0.10/Utilities/KWStyle/GDCMOverwrite.txt000066400000000000000000000000411412732066400210040ustar00rootroot00000000000000zipstreamimpl.hpp Header Disable GDCM-3.0.10/Utilities/Release/000077500000000000000000000000001412732066400156455ustar00rootroot00000000000000GDCM-3.0.10/Utilities/Release/README.md000066400000000000000000000005251412732066400171260ustar00rootroot00000000000000GDCM binaries have moved ! -------------------------- They are now automatically uploaded to github: [github release](https://github.com/malaterre/GDCM/releases/tag/vVERSION) They are build using travis and appveyor automatically As a side note the old zip (source) file is not available anymore on sf.net, please see instead on github. GDCM-3.0.10/Utilities/Release/README.txt000066400000000000000000000001471412732066400173450ustar00rootroot000000000000001. For now need to make sure docstrings.i is up to date 2. Run release.sh 3. Run release.bat 4. Done ! GDCM-3.0.10/Utilities/Release/bootstrap.sh000077500000000000000000000053301412732066400202220ustar00rootroot00000000000000#!/bin/sh rm -rf $HOME/.wine SETUPVS=no if [ "$SETUPVS" = "yes"]; then # install gecko stuff: winetricks apps list # install VS 2005 # see http://bugs.winehq.org/show_bug.cgi?id=31052 for reason option no-isolate: winetricks --no-isolate vc2005express #export WINEPREFIX=$HOME/.local/share/wineprefixes/vc2005express # required see: http://bugs.winehq.org/show_bug.cgi?id=20110#c8 #winetricks vcrun2005 mkdir -p $HOME/.cache/winetricks/junk cd $HOME/.cache/winetricks/junk # install VS 2005/SP1 # see why: https://code.google.com/p/winetricks/issues/detail?id=18 wget -c http://download.microsoft.com/download/7/7/3/7737290f-98e8-45bf-9075-85cc6ae34bf1/VS80sp1-KB926748-X86-INTL.exe # now instal SP1 #wine VS80sp1-KB926748-X86-INTL.exe fi SETUP3RD=no if [ "$SETUP3RD" = "yes"]; then wget -c http://msysgit.googlecode.com/files/Git-1.7.11-preview20120620.exe wget -c http://www.cmake.org/files/v2.8/cmake-2.8.8-win32-x86.exe wget -c http://prdownloads.sourceforge.net/swig/swigwin-2.0.7.zip wget -c http://slproweb.com/download/Win32OpenSSL-1_0_1c.exe #wget "http://download.oracle.com/otn-pub/java/jdk/6u25-b06/jdk-6u25-windows-i586.exe?AuthParam=1340870089_b98e26f4e28100ecbb9c7ca9d3c3353f" # have to manually download it at: # http://www.oracle.com/technetwork/java/javase/downloads/jdk6-downloads-1637591.html wget -c http://www.python.org/ftp/python/2.7.3/python-2.7.3.msi # install ! wine cmake-2.8.8-win32-x86.exe wine Git-1.7.11-preview20120620.exe msiexec /i python-2.7.3.msi # dont ask: #winetricks vcrun2005 # call twice in case of failure: #wine VS80sp1-KB926748-X86-INTL.exe wine Win32OpenSSL-1_0_1c.exe wine jdk-6u33-windows-i586.exe mkdir "$HOME/.wine/drive_c/Program Files/Swig" unzip -d "$HOME/.wine/drive_c/Program Files/Swig" swigwin-2.0.7.zip fi # You will need wine 1.5.7 otherwise you get: # Unhandled exception: unimplemented function msvcp90.dll.??0?$basic_ifstream@DU?$char_traits@D@std@@@std@@QAE@PBDHH@Z called in 32-bit code (0x7b83bbb2). # -> http://bugs.winehq.org/show_bug.cgi?id=28228#c15 # you should then be stuck on: # Unhandled exception: unimplemented function msvcp90.dll.??0?$basic_ostringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@H@Z called in 32-bit code (0x7b83bcb2). # See: http://bugs.winehq.org/show_bug.cgi?id=26832 #winetricks vcrun2008 #winetricks --no-isolate psdk2003 # impossible to install SDK Win7: #winetricks --no-isolate psdkwin7 # local vs2008express installation: cd $HOME/.cache/winetricks/vc2008express wget -c http://download.microsoft.com/download/e/8/e/e8eeb394-7f42-4963-a2d8-29559b738298/VS2008ExpressWithSP1ENUX1504728.iso 7z x VS2008ExpressWithSP1ENUX1504728.iso # http://appdb.winehq.org/objectManager.php?sClass=version&iId=11210 winetricks dotnet35 wine VCExpress/autorun.exe GDCM-3.0.10/Utilities/Release/config.linux000066400000000000000000000010701412732066400201710ustar00rootroot00000000000000CMAKE_BUILD_TYPE:STRING=Release GDCM_BUILD_APPLICATIONS:BOOL=ON GDCM_BUILD_EXAMPLES:BOOL=OFF GDCM_BUILD_SHARED_LIBS:BOOL=ON GDCM_BUILD_TESTING:BOOL=OFF GDCM_DOCUMENTATION:BOOL=ON GDCM_PDF_DOCUMENTATION:BOOL=ON GDCM_USE_VTK:BOOL=OFF GDCM_USE_JPEGLS:BOOL=ON GDCM_USE_PVRG:BOOL=ON GDCM_USE_SYSTEM_OPENJPEG:BOOL=OFF GDCM_USE_SYSTEM_OPENSSL:BOOL=OFF GDCM_USE_SYSTEM_EXPAT:BOOL=OFF GDCM_USE_SYSTEM_POPPLER:BOOL=OFF GDCM_USE_SYSTEM_UUID:BOOL=OFF GDCM_USE_SYSTEM_ZLIB:BOOL=OFF GDCM_WRAP_CSHARP:BOOL=ON GDCM_WRAP_JAVA:BOOL=ON GDCM_WRAP_PYTHON:BOOL=ON CPACK_SOURCE_ZIP:BOOL=OFF GDCM-3.0.10/Utilities/Release/config.win32000066400000000000000000000010721412732066400177760ustar00rootroot00000000000000CMAKE_BUILD_TYPE:STRING=Release GDCM_BUILD_APPLICATIONS:BOOL=ON GDCM_BUILD_EXAMPLES:BOOL=OFF GDCM_BUILD_SHARED_LIBS:BOOL=ON GDCM_BUILD_TESTING:BOOL=OFF GDCM_DOCUMENTATION:BOOL=OFF GDCM_PDF_DOCUMENTATION:BOOL=OFF GDCM_USE_VTK:BOOL=OFF GDCM_USE_JPEGLS:BOOL=ON GDCM_USE_PVRG:BOOL=OFF GDCM_USE_SYSTEM_OPENJPEG:BOOL=OFF GDCM_USE_SYSTEM_OPENSSL:BOOL=OFF GDCM_USE_SYSTEM_EXPAT:BOOL=OFF GDCM_USE_SYSTEM_POPPLER:BOOL=OFF #GDCM_USE_SYSTEM_UUID:BOOL=ON GDCM_USE_SYSTEM_ZLIB:BOOL=OFF GDCM_WRAP_CSHARP:BOOL=ON GDCM_WRAP_JAVA:BOOL=ON GDCM_WRAP_PYTHON:BOOL=ON CPACK_SOURCE_ZIP:BOOL=ON GDCM-3.0.10/Utilities/Release/makerelease.sh000077500000000000000000000002011412732066400204530ustar00rootroot00000000000000#!/bin/sh # http://www.winehq.org/docs/winedev-guide/dbg-control WINEDEBUG=-all wineconsole --backend=curses cmd /c release.bat GDCM-3.0.10/Utilities/Release/release.bat000077500000000000000000000037011412732066400177610ustar00rootroot00000000000000@rem @rem Program: GDCM (Grassroots DICOM). A DICOM library @rem @rem Copyright (c) 2006-2011 Mathieu Malaterre @rem All rights reserved. @rem See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. @rem @rem This software is distributed WITHOUT ANY WARRANTY; without even @rem the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR @rem PURPOSE. See the above copyright notice for more information. @rem @rem generate GDCM release on Windows @rem get tmpdir: set TMPDIR=%TMP%\gdcm_release set major=2 set minor=2 set patch=5 set version="%major%.%minor%.%patch%" @rem use VCExpress 2008 for compatibilities with OpenSSL binaries call "%VS90COMNTOOLS%vsvars32.bat" @rem User32.lib and al. SET LIB=C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib;%LIB% SET INCLUDE=C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include;%INCLUDE% @rem GDCM deps: @rem IF "%ProgramFiles(x86)%"=="" ( SET PATH=%PATH%;%ProgramFiles%\Git\bin SET PATH=%PATH%;%ProgramFiles%\Swig\swigwin-2.0.7 SET PATH=%PATH%;%ProgramFiles%\Java\jdk1.6.0_25\bin @rem ) ELSE ( @rem SET PATH=%PATH%;%ProgramFiles(x86)%\Git\bin @rem SET PATH=%PATH%;%ProgramFiles(x86)%\Swig\swigwin-2.0.8 @rem SET PATH=%PATH%;%ProgramFiles(x86)%\Java\jdk1.6.0_34\bin @rem ) ECHO %PATH% PAUSE @rem needed to get RC.EXE: SET PATH=C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin;%PATH% @rem prepare target dir mkdir %TMPDIR% mkdir %TMPDIR%\gdcm-build copy config.win32 %TMPDIR%\gdcm-build\CMakeCache.txt c: cd %TMPDIR% @rem git is itselft a batch: call git clone --branch release git://git.code.sf.net/p/gdcm/gdcm > git.log 2>&1 cd gdcm call git checkout "v%version%" cd .. cd %TMPDIR%\gdcm-build cmake -G "NMake Makefiles" ..\gdcm > config.log 2>&1 @rem build gdcm nmake > nmake.log 2>&1 @rem create NSIS installer cpack -G NSIS > nsis.log 2>&1 @rem create binary zip cpack -G ZIP > zip.log 2>&1 @rem create source zip cpack -G ZIP --config CPackSourceConfig.cmake szip.log 2>&1 GDCM-3.0.10/Utilities/Release/release.sh000077500000000000000000000150441412732066400176300ustar00rootroot00000000000000#!/bin/sh ############################################################################ # # 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. # ############################################################################ echo "Start release" date echo "" major=3 minor=0 patch=0 dirversion="$major.$minor" version="$major.$minor.$patch" version2="$major-$minor-$patch" basedir="/tmp/gdcm_release" check_exit_value() { VALUE="$1" if [ "$VALUE" != "0" ]; then echo "error in $2" exit 1 fi } if [ ! -d $basedir ]; then mkdir $basedir else echo "$basedir already exist" echo "$basedir/gdcm already exist, cleaning it up:" rm -rf $basedir/gdcm fi echo "Checking out gdcm" git clone --branch release git://git.code.sf.net/p/gdcm/gdcm $basedir/gdcm check_exit_value $? "git did not return properly" || exit 1 # Get the specific tag # There is no way apparently to directly clone and checkout a tag; you can do # that only for branch name cd $basedir/gdcm git checkout "v$version" check_exit_value $? "git checkout did not return properly" || exit 1 if [ ! -d $basedir/gdcm-build ]; then mkdir $basedir/gdcm-build else echo "$basedir/gdcm-build already exist, cleaning it up:" rm -rf $basedir/gdcm-build mkdir $basedir/gdcm-build fi cd $basedir/gdcm-build # debian default: export JAVA_HOME=/usr/lib/jvm/default-java cat > $basedir/gdcm-build/CMakeCache.txt << EOT CMAKE_BUILD_TYPE:STRING=Release GDCM_BUILD_APPLICATIONS:BOOL=ON GDCM_BUILD_EXAMPLES:BOOL=OFF GDCM_BUILD_SHARED_LIBS:BOOL=ON GDCM_BUILD_TESTING:BOOL=OFF GDCM_DOCUMENTATION:BOOL=ON GDCM_PDF_DOCUMENTATION:BOOL=ON GDCM_USE_VTK:BOOL=OFF GDCM_USE_JPEGLS:BOOL=ON GDCM_USE_PVRG:BOOL=ON GDCM_USE_SYSTEM_OPENJPEG:BOOL=OFF GDCM_USE_SYSTEM_OPENSSL:BOOL=OFF GDCM_USE_SYSTEM_EXPAT:BOOL=OFF GDCM_USE_SYSTEM_POPPLER:BOOL=OFF GDCM_USE_SYSTEM_UUID:BOOL=OFF GDCM_USE_SYSTEM_ZLIB:BOOL=OFF GDCM_WRAP_CSHARP:BOOL=ON GDCM_WRAP_JAVA:BOOL=ON GDCM_WRAP_PYTHON:BOOL=ON Python_ADDITIONAL_VERSIONS:STRING=2.7 CPACK_SOURCE_ZIP:BOOL=ON EOT cmake $basedir/gdcm #cmake $basedir/gdcm -DCMAKE_TOOLCHAIN_FILE=$basedir/gdcm/CMake/Toolchain-gcc-m32.cmake check_exit_value $? "cmake did not return properly" || exit 1 make -j2 check_exit_value $? "make did not return properly" || exit 1 cpack -G TGZ check_exit_value $? "cpack did not return properly" || exit 1 cpack -G TBZ2 check_exit_value $? "cpack did not return properly" || exit 1 # source release cpack -G ZIP --config CPackSourceConfig.cmake check_exit_value $? "cpack did not return properly" || exit 1 cpack -G TGZ --config CPackSourceConfig.cmake check_exit_value $? "cpack did not return properly" || exit 1 cpack -G TBZ2 --config CPackSourceConfig.cmake check_exit_value $? "cpack did not return properly" || exit 1 # Let's start doing the VTK documentation then: #cmake -DGDCM_VTK_DOCUMENTATION:BOOL=ON -DGDCM_USE_VTK:BOOL=ON -DVTK_DIR:PATH=/home/mathieu/tmp/vtk-5.10.1+dfsg/Build . cmake -DGDCM_VTK_DOCUMENTATION:BOOL=ON -DGDCM_USE_VTK:BOOL=ON -DVTK_DIR:PATH=/home/mathieu/tmp/vtk6-6.2.0+dfsg1/debian/build . check_exit_value $? "cmake did not return properly" || exit 1 #make -j4 make rebuild_cache make vtkgdcmDoxygenDoc check_exit_value $? "vtkgdcmDoxygenDoc did not return properly" || exit 1 # https://sourceforge.net/p/forge/documentation/File%20Management/#rsync-over-ssh # Warning need to create /manually/ the subfolder: # https://sourceforge.net/projects/gdcm/files/gdcm%203.x/#folder-create # Update default version: #https://sourceforge.net/p/forge/documentation/Using%20the%20Release%20API/ #rsync -e ssh GDCM-$version-Linux-x86_64.tar.gz "malat,gdcm@frs.sourceforge.net:/home/frs/project/gdcm/gdcm\ 3.x/GDCM\ $version" #check_exit_value $? "rsync did not return properly" || exit 1 #rsync -e ssh GDCM-$version-Linux-x86_64.tar.bz2 "malat,gdcm@frs.sourceforge.net:/home/frs/project/gdcm/gdcm\ 3.x/GDCM\ $version" #check_exit_value $? "rsync did not return properly" || exit 1 #rsync -e ssh gdcm-$version.zip "malat,gdcm@frs.sourceforge.net:/home/frs/project/gdcm/gdcm\ 3.x/GDCM\ $version" #check_exit_value $? "rsync did not return properly" || exit 1 rsync --protect-args -e ssh gdcm-$version.tar.gz "malat,gdcm@frs.sourceforge.net:/home/frs/project/gdcm/gdcm\ 3.x/GDCM\ $version" check_exit_value $? "rsync did not return properly" || exit 1 def_prop="default=windows&default=mac&default=linux&default=bsd&default=solaris&default=android&default=others" def_path="https://sourceforge.net/projects/gdcm/files/gdcm%203.x/GDCM%20$version/gdcm-$version.tar.gz" curl -k -H "Accept: application/json" -X PUT -d $def_prop -d "api_key=$SFAPIKEY" $def_path rsync --protect-args -e ssh gdcm-$version.tar.bz2 "malat,gdcm@frs.sourceforge.net:/home/frs/project/gdcm/gdcm\ 3.x/GDCM\ $version" check_exit_value $? "rsync did not return properly" || exit 1 rsync --protect-args -e ssh Utilities/doxygen/gdcm-$version-doc.tar.gz "malat,gdcm@frs.sourceforge.net:/home/frs/project/gdcm/gdcm\ 3.x/GDCM\ $version" check_exit_value $? "rsync did not return properly" || exit 1 sed "s/vVERSION/v$version/" $basedir/gdcm/Utilities/Release/README.md > $basedir/README.md rsync --protect-args -e ssh $basedir/README.md "malat,gdcm@frs.sourceforge.net:/home/frs/project/gdcm/gdcm\ 3.x/GDCM\ $version" check_exit_value $? "rsync did not return properly" || exit 1 # create htaccess for sf.net echo "DirectoryIndex index.xhtml" > Utilities/doxygen/html/.htaccess rsync --protect-args -a -r Utilities/doxygen/html malat,gdcm@web.sourceforge.net:htdocs/$dirversion check_exit_value $? "rsync recursive html did not return properly" || exit 1 rsync --protect-args -av Utilities/doxygen/gdcm-$version-doc.tar.gz malat,gdcm@web.sourceforge.net:htdocs/$dirversion check_exit_value $? "rsync tarball did not return properly" || exit 1 # This need to be done last, sometime we cannot generated PDF, see #318 rsync --protect-args -av Utilities/doxygen/latex/gdcm-$version.pdf malat,gdcm@web.sourceforge.net:htdocs/$dirversion check_exit_value $? "rsync pdf did not return properly" || exit 1 # same comment: rsync --protect-args -e ssh Utilities/doxygen/latex/gdcm-$version.pdf "malat,gdcm@frs.sourceforge.net:/home/frs/project/gdcm/gdcm\ 3.x/GDCM\ $version" check_exit_value $? "rsync did not return properly" || exit 1 GDCM-3.0.10/Utilities/Release/upload.sh000077500000000000000000000150051412732066400174710ustar00rootroot00000000000000#!/bin/sh -x ############################################################################ # # 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. # ############################################################################ echo "Start release" date echo "" major=3 minor=0 patch=0 dirversion="$major.$minor" version="$major.$minor.$patch" version2="$major-$minor-$patch" basedir="/tmp/gdcm_release" check_exit_value() { VALUE="$1" if [ "$VALUE" != "0" ]; then echo "error in $2" exit 1 fi } #if [ ! -d $basedir ]; then # mkdir $basedir #else # echo "$basedir already exist" # echo "$basedir/gdcm already exist, cleaning it up:" # rm -rf $basedir/gdcm #fi echo "Checking out gdcm" #git clone --branch release git://git.code.sf.net/p/gdcm/gdcm $basedir/gdcm check_exit_value $? "git did not return properly" || exit 1 # Get the specific tag # There is no way apparently to directly clone and checkout a tag; you can do # that only for branch name cd $basedir/gdcm #git checkout "v$version" check_exit_value $? "git checkout did not return properly" || exit 1 #if [ ! -d $basedir/gdcm-build ]; then # mkdir $basedir/gdcm-build #else # echo "$basedir/gdcm-build already exist, cleaning it up:" # rm -rf $basedir/gdcm-build # mkdir $basedir/gdcm-build #fi cd $basedir/gdcm-build # debian default: export JAVA_HOME=/usr/lib/jvm/default-java #cat > $basedir/gdcm-build/CMakeCache.txt << EOT #CMAKE_BUILD_TYPE:STRING=Release #GDCM_BUILD_APPLICATIONS:BOOL=ON #GDCM_BUILD_EXAMPLES:BOOL=OFF #GDCM_BUILD_SHARED_LIBS:BOOL=ON #GDCM_BUILD_TESTING:BOOL=OFF #GDCM_DOCUMENTATION:BOOL=ON #GDCM_PDF_DOCUMENTATION:BOOL=ON #GDCM_USE_VTK:BOOL=OFF #GDCM_USE_JPEGLS:BOOL=ON #GDCM_USE_PVRG:BOOL=ON #GDCM_USE_SYSTEM_OPENJPEG:BOOL=OFF #GDCM_USE_SYSTEM_OPENSSL:BOOL=OFF #GDCM_USE_SYSTEM_EXPAT:BOOL=OFF #GDCM_USE_SYSTEM_POPPLER:BOOL=OFF #GDCM_USE_SYSTEM_UUID:BOOL=OFF #GDCM_USE_SYSTEM_ZLIB:BOOL=OFF #GDCM_WRAP_CSHARP:BOOL=ON #GDCM_WRAP_JAVA:BOOL=ON #GDCM_WRAP_PYTHON:BOOL=ON #Python_ADDITIONAL_VERSIONS:STRING=2.7 #CPACK_SOURCE_ZIP:BOOL=ON #EOT #cmake $basedir/gdcm #cmake $basedir/gdcm -DCMAKE_TOOLCHAIN_FILE=$basedir/gdcm/CMake/Toolchain-gcc-m32.cmake check_exit_value $? "cmake did not return properly" || exit 1 #make -j2 check_exit_value $? "make did not return properly" || exit 1 #cpack -G TGZ check_exit_value $? "cpack did not return properly" || exit 1 #cpack -G TBZ2 check_exit_value $? "cpack did not return properly" || exit 1 # source release #cpack -G ZIP --config CPackSourceConfig.cmake check_exit_value $? "cpack did not return properly" || exit 1 #cpack -G TGZ --config CPackSourceConfig.cmake check_exit_value $? "cpack did not return properly" || exit 1 #cpack -G TBZ2 --config CPackSourceConfig.cmake check_exit_value $? "cpack did not return properly" || exit 1 # Let's start doing the VTK documentation then: #cmake -DGDCM_VTK_DOCUMENTATION:BOOL=ON -DGDCM_USE_VTK:BOOL=ON -DVTK_DIR:PATH=/home/mathieu/tmp/vtk-5.10.1+dfsg/Build . #cmake -DGDCM_VTK_DOCUMENTATION:BOOL=ON -DGDCM_USE_VTK:BOOL=ON -DVTK_DIR:PATH=/home/mathieu/tmp/vtk6-6.2.0+dfsg1/debian/build . check_exit_value $? "cmake did not return properly" || exit 1 #make -j4 #make rebuild_cache #make vtkgdcmDoxygenDoc check_exit_value $? "vtkgdcmDoxygenDoc did not return properly" || exit 1 # https://sourceforge.net/p/forge/documentation/File%20Management/#rsync-over-ssh # Warning need to create /manually/ the subfolder: # https://sourceforge.net/projects/gdcm/files/gdcm%203.x/#folder-create # Update default version: #https://sourceforge.net/p/forge/documentation/Using%20the%20Release%20API/ #rsync -e ssh GDCM-$version-Linux-x86_64.tar.gz "malat,gdcm@frs.sourceforge.net:/home/frs/project/gdcm/gdcm\ 3.x/GDCM\ $version" #check_exit_value $? "rsync did not return properly" || exit 1 #rsync -e ssh GDCM-$version-Linux-x86_64.tar.bz2 "malat,gdcm@frs.sourceforge.net:/home/frs/project/gdcm/gdcm\ 3.x/GDCM\ $version" #check_exit_value $? "rsync did not return properly" || exit 1 #rsync -e ssh gdcm-$version.zip "malat,gdcm@frs.sourceforge.net:/home/frs/project/gdcm/gdcm\ 3.x/GDCM\ $version" #check_exit_value $? "rsync did not return properly" || exit 1 rsync --protect-args -e ssh gdcm-$version.tar.gz "malat,gdcm@frs.sourceforge.net:/home/frs/project/g/gd/gdcm/gdcm 3.x/GDCM $version" check_exit_value $? "rsync did not return properly" || exit 1 def_prop="default=windows&default=mac&default=linux&default=bsd&default=solaris&default=android&default=others" def_path="https://sourceforge.net/projects/gdcm/files/gdcm%203.x/GDCM%20$version/gdcm-$version.tar.gz" curl -k -H "Accept: application/json" -X PUT -d $def_prop -d "api_key=$SFAPIKEY" $def_path rsync --protect-args -e ssh gdcm-$version.tar.bz2 "malat,gdcm@frs.sourceforge.net:/home/frs/project/g/gd/gdcm/gdcm 3.x/GDCM $version" check_exit_value $? "rsync did not return properly" || exit 1 rsync --protect-args -e ssh Utilities/doxygen/gdcm-$version-doc.tar.gz "malat,gdcm@frs.sourceforge.net:/home/frs/project/g/gd/gdcm/gdcm 3.x/GDCM $version" check_exit_value $? "rsync did not return properly" || exit 1 sed "s/vVERSION/v$version/" $basedir/gdcm/Utilities/Release/README.md > $basedir/README.md rsync --protect-args -e ssh $basedir/README.md "malat,gdcm@frs.sourceforge.net:/home/frs/project/g/gd/gdcm/gdcm 3.x/GDCM $version" check_exit_value $? "rsync did not return properly" || exit 1 rsync --protect-args -a -r Utilities/doxygen/html malat,gdcm@web.sourceforge.net:htdocs/$dirversion check_exit_value $? "rsync recursive html did not return properly" || exit 1 rsync --protect-args -av Utilities/doxygen/gdcm-$version-doc.tar.gz malat,gdcm@web.sourceforge.net:htdocs/$dirversion check_exit_value $? "rsync tarball did not return properly" || exit 1 # This need to be done last, sometime we cannot generated PDF, see #318 rsync --protect-args -av Utilities/doxygen/latex/gdcm-$version.pdf malat,gdcm@web.sourceforge.net:htdocs/$dirversion check_exit_value $? "rsync pdf did not return properly" || exit 1 # same comment: rsync --protect-args -e ssh Utilities/doxygen/latex/gdcm-$version.pdf "malat,gdcm@frs.sourceforge.net:/home/frs/project/g/gd/gdcm/gdcm 3.x/GDCM $version" check_exit_value $? "rsync did not return properly" || exit 1 GDCM-3.0.10/Utilities/VTK/000077500000000000000000000000001412732066400147315ustar00rootroot00000000000000GDCM-3.0.10/Utilities/VTK/.NoDartCoverage000066400000000000000000000000471412732066400175760ustar00rootroot00000000000000# do not do coverage in this directory GDCM-3.0.10/Utilities/VTK/Applications/000077500000000000000000000000001412732066400173575ustar00rootroot00000000000000GDCM-3.0.10/Utilities/VTK/Applications/CMakeLists.txt000066400000000000000000000031101412732066400221120ustar00rootroot00000000000000# Build the vtk-gdcm simple viewer include_directories( ${GDCM_SOURCE_DIR}/Utilities/VTK ) if(WIN32 AND NOT CYGWIN) include_directories( "${GDCM_SOURCE_DIR}/Utilities/getopt" ) endif() if(WIN32) if (BUILD_SHARED_LIBS) add_definitions(-DGETOPT_DLL) endif () endif() set(GDCM_VTK_APPS gdcm2vtk ) if(VTK_USE_RENDERING OR vtkRenderingCore_LOADED) set(GDCM_VTK_APPS ${GDCM_VTK_APPS} gdcmviewer # vtkImageViewer2 gdcm2pnm ) endif() foreach(app ${GDCM_VTK_APPS}) add_executable(${app} ${app}.cxx) if(GDCM_EXECUTABLE_PROPERTIES) set_target_properties(${app} PROPERTIES ${GDCM_EXECUTABLE_PROPERTIES}) endif() target_link_libraries(${app} ${VTKGDCM_NAME}) target_link_libraries(${app} gdcmDSED gdcmMSFF gdcmCommon) if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" LESS 6.0 ) target_link_libraries(${app} vtkCommon vtkFiltering vtkIO vtkImaging) if(VTK_USE_RENDERING) target_link_libraries(${app} vtkRendering) endif() if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" GREATER 5.0 ) target_link_libraries(${app} vtkWidgets vtkHybrid) endif() else() # >= 6.0 target_link_libraries(${app} ${VTK_LIBRARIES} vtkIOXML) endif() if(WIN32 AND NOT CYGWIN) target_link_libraries(${app} gdcmgetopt) endif() if(NOT GDCM_INSTALL_NO_RUNTIME) install(TARGETS ${app} RUNTIME DESTINATION ${GDCM_INSTALL_BIN_DIR} COMPONENT VTKApplications LIBRARY DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT VTKLibraries ARCHIVE DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT VTKDebugDevel ) endif() endforeach() GDCM-3.0.10/Utilities/VTK/Applications/gdcm2pnm.cxx000066400000000000000000000054761412732066400216260ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkImageMapToWindowLevelColors.h" #include "vtkImageActor.h" #include "vtkPNGWriter.h" #include "vtkWindowToImageFilter.h" #include "vtkMedicalImageProperties.h" /* * Inspired by dcm2pnm from DCMTK toolkit * for now it always output PNG file and does not handle very well window/level * since it needs to be stored in the DICOM file... * It also only takes the first window/level from the list */ int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.pnm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); reader->SetFileName( filename ); reader->Update(); // important to read the window/level info vtkMedicalImageProperties *prop = reader->GetMedicalImageProperties(); vtkRenderWindow *renWin = vtkRenderWindow::New(); renWin->OffScreenRenderingOn(); vtkRenderer *renderer = vtkRenderer::New(); renWin->AddRenderer(renderer); vtkImageMapToWindowLevelColors *windowlevel = vtkImageMapToWindowLevelColors::New(); #if (VTK_MAJOR_VERSION >= 6) windowlevel->SetInputConnection( reader->GetOutputPort() ); #else windowlevel->SetInput( reader->GetOutput() ); #endif unsigned int n = prop->GetNumberOfWindowLevelPresets(); if( n ) { // Take the first one by default: const double *wl = prop->GetNthWindowLevelPreset(0); windowlevel->SetWindow( wl[0] ); windowlevel->SetLevel( wl[1] ); } vtkImageActor *actor = vtkImageActor::New(); #if (VTK_MAJOR_VERSION >= 6) actor->SetInputData( windowlevel->GetOutput() ); #else actor->SetInput( windowlevel->GetOutput() ); #endif renderer->AddActor( actor ); renWin->Render(); vtkWindowToImageFilter *w2if = vtkWindowToImageFilter::New(); w2if->SetInput ( renWin ); vtkPNGWriter *wr = vtkPNGWriter::New(); #if (VTK_MAJOR_VERSION >= 6) wr->SetInputConnection( w2if->GetOutputPort() ); #else wr->SetInput( w2if->GetOutput() ); #endif wr->SetFileName ( outfilename ); wr->Write(); reader->Delete(); renWin->Delete(); renderer->Delete(); windowlevel->Delete(); actor->Delete(); w2if->Delete(); wr->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/Applications/gdcm2vtk.cxx000066400000000000000000000776531412732066400216460ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * TODO: This app should be a suclass of gdcmimg application to avoid code duplication */ #include "vtkGDCMImageReader.h" #include "vtkGDCMImageWriter.h" #include "vtkVersion.h" #include "vtkErrorCode.h" #include "vtkStringArray.h" //#include "vtkImageCast.h" // DEBUG #include "vtkImageReader2Factory.h" #include "vtkImageReader2.h" #include "vtkImageData.h" #include "vtkTIFFWriter.h" #include "vtkPNGWriter.h" #include "vtkPNMWriter.h" #include "vtkBMPWriter.h" #include "vtkImageChangeInformation.h" #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) #include "vtkMetaImageReader.h" #include "vtkXMLImageDataReader.h" #include "vtkMetaImageWriter.h" #include "vtkDICOMImageReader.h" #include "vtkMINCImageReader.h" #include "vtkMINCImageAttributes.h" #include "vtk_tiff.h" // ORIENTATION_BOTLEFT #include "vtkImageRGBToYBR.h" #endif #include "vtkMedicalImageProperties.h" #include "vtkTIFFReader.h" #include "vtkGESignaReader.h" #include "vtkImageExtractComponents.h" #include "vtkJPEGReader.h" #include "vtkBMPReader.h" #include "vtkLookupTable.h" #include "vtkPointData.h" #include "vtkStructuredPointsReader.h" #include "vtkStructuredPointsWriter.h" #include "vtkStructuredPoints.h" #include "vtkXMLImageDataWriter.h" #include "gdcmFilename.h" #include "gdcmTrace.h" #include "gdcmVersion.h" #include "gdcmImageHelper.h" #include "gdcmFileMetaInformation.h" #include "gdcmSystem.h" #include "gdcmUIDGenerator.h" #include "gdcmDirectory.h" #include "gdcmIPPSorter.h" #include #ifndef vtkFloatingPointType #define vtkFloatingPointType double #endif void PrintVersion() { std::cout << "gdcm2vtk: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; //std::cout << " VTK " << vtkVersion::GetVTKVersion() << std::endl; std::cout << " " << vtkVersion::GetVTKSourceVersion() << std::endl; } void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcm2vtk [OPTION] input output" << std::endl; std::cout << "Convert a vtk-supported file into DICOM.\n"; std::cout << "Options:" << std::endl; std::cout << " --force-rescale force rescale." << std::endl; std::cout << " --force-spacing force spacing." << std::endl; std::cout << " --palette-color when supported generate a PALETTE COLOR file." << std::endl; std::cout << " --argb when supported generate a ARGB file." << std::endl; std::cout << " --compress when supported generate a compressed file." << std::endl; std::cout << " --use-vtkdicom Use vtkDICOMImageReader (instead of GDCM)." << std::endl; std::cout << " --modality set Modality." << std::endl; std::cout << " --lower-left set lower left." << std::endl; std::cout << " --shift set shift." << std::endl; std::cout << " --scale set scale." << std::endl; std::cout << " --compress set compression (MetaIO)." << std::endl; std::cout << " -T --study-uid Study UID." << std::endl; std::cout << " -S --series-uid Series UID." << std::endl; std::cout << " --root-uid Root UID." << std::endl; std::cout << " --imageformat Image Format [1-8] (aka PhotometricInterpretation)." << std::endl; std::cout << " --ipp-sort When input is directory, sort instances using IOP/IPP."<< std::endl; std::cout << "Compression Types (lossless):" << std::endl; std::cout << " -J --jpeg Compress image in jpeg." << std::endl; std::cout << " -K --j2k Compress image in j2k." << std::endl; std::cout << " -L --jpegls Compress image in jpeg-ls." << std::endl; std::cout << " -R --rle Compress image in rle (lossless only)." << std::endl; std::cout << "General Options:" << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " -v --version print version." << std::endl; std::cout << "Env var:" << std::endl; std::cout << " GDCM_ROOT_UID Root UID" << std::endl; } static inline void copy_files( const std::vector & files, vtkStringArray * names ) { for( gdcm::Directory::FilenamesType::const_iterator it = files.begin(); it != files.end(); ++it ) { names->InsertNextValue( it->c_str() ); } } int main(int argc, char *argv[]) { int retcode = 0; int c; //int digit_optind = 0; std::string root_uid; int rootuid = 0; std::vector filenames; int forcerescale = 0; int forcespacing = 0; int palettecolor = 0; int argb = 0; int modality = 0; std::string modality_str; int studyuid = 0; int seriesuid = 0; // compression int jpeg = 0; int jpegls = 0; int j2k = 0; int rle = 0; int usevtkdicom = 0; int compress = 0; int ippsort = 0; int lowerleft = 0; int oshift = 0; int oscale = 0; int oimageformat = 0; double shift = 0.; double scale = 1.; int imageformat = 0; int verbose = 0; int warning = 0; int debug = 0; int error = 0; int help = 0; int version = 0; gdcm::UIDGenerator uid; std::string series_uid = uid.Generate(); std::string study_uid = uid.Generate(); while (1) { //int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"force-rescale", 0, &forcerescale, 1}, {"force-spacing", 0, &forcespacing, 1}, {"palette-color", 0, &palettecolor, 1}, {"argb", 0, &argb, 1}, {"modality", 1, &modality, 1}, {"study-uid", 1, &studyuid, 1}, {"series-uid", 1, &seriesuid, 1}, {"root-uid", 1, &rootuid, 1}, // specific Root (not GDCM) {"jpeg", 0, &jpeg, 1}, // JPEG lossy / lossless {"jpegls", 0, &jpegls, 1}, // JPEG-LS: lossy / lossless {"j2k", 0, &j2k, 1}, // J2K: lossy / lossless {"rle", 0, &rle, 1}, // lossless ! {"compress", 0, &compress, 1}, // compress with using MetaIO {"use-vtkdicom", 0, &usevtkdicom, 1}, // use vtkDICOMImageReader {"lower-left", 0, &lowerleft, 1}, // use FileLowerLeftOn {"shift", 1, &oshift, 1}, // {"scale", 1, &oscale, 1}, // {"imageformat", 1, &oimageformat, 1}, // {"ipp-sort", 0, &ippsort, 1}, // use IPP sorting // General options ! {"verbose", 0, &verbose, 1}, {"warning", 0, &warning, 1}, {"debug", 0, &debug, 1}, {"error", 0, &error, 1}, {"help", 0, &help, 1}, {"version", 0, &version, 1}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "JKLRT:S:VWDEhv", long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: { const char *s = long_options[option_index].name; (void)s; //printf ("option %s", s); if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); //assert( filename.empty() ); //filename = optarg; } else if( option_index == 4 ) /* modality */ { assert( strcmp(s, "modality") == 0 ); //assert( filename.empty() ); modality_str = optarg; } else if( option_index == 5 ) /* study-uid */ { assert( strcmp(s, "study-uid") == 0 ); series_uid = optarg; } else if( option_index == 6 ) /* series-uid */ { assert( strcmp(s, "series-uid") == 0 ); study_uid = optarg; } else if( option_index == 7 ) /* root-uid */ { assert( strcmp(s, "root-uid") == 0 ); root_uid = optarg; } else if( option_index == 15 ) /* shift */ { assert( strcmp(s, "shift") == 0 ); shift = atof(optarg); } else if( option_index == 16 ) /* scale */ { assert( strcmp(s, "scale") == 0 ); scale = atof(optarg); } else if( option_index == 17 ) /* imageformat */ { assert( strcmp(s, "imageformat") == 0 ); imageformat = atoi(optarg); } //printf (" with arg %s", optarg); } //printf ("\n"); } break; case 'J': jpeg = 1; break; case 'K': j2k = 1; break; case 'L': jpegls = 1; break; case 'R': rle = 1; break; case 'T': studyuid = 1; study_uid = optarg; break; case 'S': seriesuid = 1; series_uid = optarg; break; case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { //printf ("non-option ARGV-elements: "); while (optind < argc) { //printf ("%s ", argv[optind]); filenames.push_back( argv[optind++] ); } //printf ("\n"); } if( version ) { //std::cout << "version" << std::endl; PrintVersion(); return 0; } if( help ) { //std::cout << "help" << std::endl; PrintHelp(); return 0; } // Debug is a little too verbose gdcm::Trace::SetDebug( debug ); gdcm::Trace::SetWarning( warning ); gdcm::Trace::SetError( error ); // when verbose is true, make sure warning+error are turned on: if( verbose ) { gdcm::Trace::SetWarning( verbose ); gdcm::Trace::SetError( verbose); } if( filenames.empty() ) { PrintHelp(); return 1; } int recursive = 0; const char *outfilename = NULL; double ippzspacing; vtkStringArray *names = vtkStringArray::New(); { // Is it a single directory ? If so loop over all files contained in it: //const char *filename = argv[1]; if( filenames.size() == 2 && gdcm::System::FileIsDirectory( filenames[0].c_str() ) ) { if( verbose ) std::cout << "Loading directory: " << filenames[0] << std::endl; gdcm::Directory d; d.Load(filenames[0].c_str(), recursive); gdcm::Directory::FilenamesType const &files = d.GetFilenames(); if( ippsort ) { gdcm::IPPSorter s; s.SetComputeZSpacing( true ); s.SetZSpacingTolerance( 1e-3 ); bool b = s.Sort( files ); if( !b ) { std::cerr << "Failed to sort files" << std::endl; return 1; } std::cout << "Sorting succeeded:" << std::endl; s.Print( std::cout ); std::cout << "Found z-spacing:" << std::endl; std::cout << s.GetZSpacing() << std::endl; ippzspacing = s.GetZSpacing(); const std::vector & sorted = s.GetFilenames(); copy_files( sorted, names ); } else copy_files( files, names ); outfilename = filenames[1].c_str(); } else // list of files passed directly on the cmd line: // discard non-existing or directory { for(std::vector::const_iterator it = filenames.begin(); it != filenames.end() - 1; ++it) { const std::string & filename = *it; if( gdcm::System::FileExists( filename.c_str() ) ) { if( gdcm::System::FileIsDirectory( filename.c_str() ) ) { if(verbose) std::cerr << "Discarding directory: " << filename << std::endl; } else { names->InsertNextValue( filename.c_str() ); } } else { if(verbose) std::cerr << "Discarding non existing file: " << filename << std::endl; } } outfilename = filenames[ filenames.size() - 1 ].c_str(); } } if( !names->GetNumberOfValues() ) { std::cerr << "Missing parameters on the command line" << std::endl; return 1; } const char *filename = names->GetValue( 0 ).c_str(); gdcm::ImageHelper::SetForceRescaleInterceptSlope(forcerescale); gdcm::ImageHelper::SetForcePixelSpacing(forcespacing); vtkGDCMImageReader *gdcmreader = vtkGDCMImageReader::New(); #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) vtkDICOMImageReader *dicomreader = vtkDICOMImageReader::New(); #endif if( debug ) { gdcmreader->DebugOn(); #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) dicomreader->DebugOn(); #endif } vtkImageReader2Factory* imgfactory = vtkImageReader2Factory::New(); #if VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION <= 4 // warning vtk 5.4 is broken metaimage are not added to factory // by default vtkMetaImageReader *d = vtkMetaImageReader::New(); imgfactory->RegisterReader( d ); d->Delete(); #endif if( usevtkdicom ) #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) imgfactory->RegisterReader( dicomreader ); #else (void)0; #endif else imgfactory->RegisterReader( gdcmreader ); vtkImageReader2* imgreader = imgfactory->CreateImageReader2(filename); vtkStructuredPointsReader *datareader = vtkStructuredPointsReader::New(); datareader->SetFileName( filename ); vtkXMLReader *xmlreader = vtkXMLImageDataReader::New(); int res = 0; if( !imgreader ) { int xmlres = xmlreader->CanReadFile( filename ); if( !xmlres ) { res = datareader->IsFileStructuredPoints(); if( !res ) { std::cerr << "could not find no reader to handle file: " << filename << std::endl; return 1; } } } imgfactory->Delete(); vtkImageData *imgdata = NULL; vtkImageChangeInformation *v16 = vtkImageChangeInformation::New(); std::string image_comments; if( imgreader ) { imgreader->SetFileLowerLeft( lowerleft ); if( names->GetNumberOfValues() == 1 ) imgreader->SetFileName( names->GetValue(0) ); else imgreader->SetFileNames(names); imgreader->Update(); if( imgreader->GetErrorCode() ) { std::cerr << "There was an error: " << vtkErrorCode::GetStringFromErrorCode(imgreader->GetErrorCode()) << std::endl; return 1; } imgdata = imgreader->GetOutput(); if( ippsort ) { const vtkFloatingPointType *spacing = imgreader->GetOutput()->GetSpacing(); #if VTK_MAJOR_VERSION >= 6 v16->SetInputConnection( imgreader->GetOutputPort() ); #else v16->SetInput( imgreader->GetOutput() ); #endif v16->SetOutputSpacing( spacing[0], spacing[1], ippzspacing ); v16->Update(); imgdata = v16->GetOutput(); } if( verbose ) std::cout << "imgreader classname: " << imgreader->GetClassName() << std::endl; } else if( res ) { datareader->Update(); if( datareader->GetErrorCode() ) { std::cerr << "There was an error: " << vtkErrorCode::GetStringFromErrorCode(datareader->GetErrorCode()) << std::endl; return 1; } imgdata = datareader->GetOutput(); if( datareader->GetHeader() ) { image_comments = datareader->GetHeader(); } } else if( xmlreader->CanReadFile( filename ) ) { xmlreader->SetFileName(filename); xmlreader->Update(); imgdata = vtkXMLImageDataReader::SafeDownCast(xmlreader)->GetOutput(); } gdcm::Filename fn = outfilename; const char *outputextension = fn.GetExtension(); if ( outputextension ) { if( gdcm::System::StrCaseCmp(outputextension,".vtk") == 0 ) { vtkStructuredPointsWriter * writer = vtkStructuredPointsWriter::New(); writer->SetFileName( outfilename ); writer->SetFileTypeToBinary(); #if VTK_MAJOR_VERSION >= 6 writer->SetInputData( imgdata ); #else writer->SetInput( imgdata ); #endif writer->Write(); #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) if( writer->GetErrorCode() ) { std::cerr << "There was an error: " << vtkErrorCode::GetStringFromErrorCode(writer->GetErrorCode()) << std::endl; retcode = 1; } #endif writer->Delete(); goto cleanup; } else if( gdcm::System::StrCaseCmp(outputextension,".bmp") == 0 ) { vtkBMPWriter * writer = vtkBMPWriter::New(); writer->SetFileName( outfilename ); #if VTK_MAJOR_VERSION >= 6 writer->SetInputData( imgdata ); #else writer->SetInput( imgdata ); #endif writer->Write(); #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) if( writer->GetErrorCode() ) { std::cerr << "There was an error: " << vtkErrorCode::GetStringFromErrorCode(writer->GetErrorCode()) << std::endl; retcode = 1; } #endif writer->Delete(); goto cleanup; } else if( gdcm::System::StrCaseCmp(outputextension,".pgm") == 0 || gdcm::System::StrCaseCmp(outputextension,".pnm") == 0 || gdcm::System::StrCaseCmp(outputextension,".ppm") == 0 ) { vtkPNMWriter * writer = vtkPNMWriter::New(); writer->SetFileName( outfilename ); #if VTK_MAJOR_VERSION >= 6 writer->SetInputData( imgdata ); #else writer->SetInput( imgdata ); #endif writer->Write(); #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) if( writer->GetErrorCode() ) { std::cerr << "There was an error: " << vtkErrorCode::GetStringFromErrorCode(writer->GetErrorCode()) << std::endl; retcode = 1; } #endif writer->Delete(); goto cleanup; } else if( gdcm::System::StrCaseCmp(outputextension,".png") == 0 ) { vtkPNGWriter * writer = vtkPNGWriter::New(); writer->SetFileName( outfilename ); #if VTK_MAJOR_VERSION >= 6 writer->SetInputData( imgdata ); #else writer->SetInput( imgdata ); #endif writer->Write(); #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) if( writer->GetErrorCode() ) { std::cerr << "There was an error: " << vtkErrorCode::GetStringFromErrorCode(writer->GetErrorCode()) << std::endl; retcode = 1; } #endif writer->Delete(); goto cleanup; } else if( gdcm::System::StrCaseCmp(outputextension,".tif") == 0 || gdcm::System::StrCaseCmp(outputextension,".tiff") == 0 ) // { vtkTIFFWriter * writer = vtkTIFFWriter::New(); writer->SetFileName( outfilename ); #if VTK_MAJOR_VERSION >= 6 writer->SetInputData( imgdata ); #else writer->SetInput( imgdata ); #endif writer->Write(); #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) if( writer->GetErrorCode() ) { std::cerr << "There was an error: " << vtkErrorCode::GetStringFromErrorCode(writer->GetErrorCode()) << std::endl; retcode = 1; } #endif writer->Delete(); goto cleanup; } else if( gdcm::System::StrCaseCmp(outputextension,".vti") == 0 ) // vtkXMLImageDataWriter::GetDefaultFileExtension() { vtkXMLImageDataWriter * writer = vtkXMLImageDataWriter::New(); writer->SetFileName( outfilename ); writer->SetDataModeToBinary(); #if VTK_MAJOR_VERSION >= 6 writer->SetInputData( imgdata ); #else writer->SetInput( imgdata ); #endif writer->Write(); #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) if( writer->GetErrorCode() ) { std::cerr << "There was an error: " << vtkErrorCode::GetStringFromErrorCode(writer->GetErrorCode()) << std::endl; retcode = 1; } #endif writer->Delete(); goto cleanup; } #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) else if( gdcm::System::StrCaseCmp(outputextension,".mha") == 0 || gdcm::System::StrCaseCmp(outputextension,".mhd") == 0 ) // vtkMetaImageReader::GetFileExtensions() { // Weird, the writer does not offer the same API as the Reader, for instance // One cannot set the patient name to store (see vtkMetaImageReader::GetPatientName ...) // worse I cannot even set the transform ! Which means Reader -> Writer just breaks everything -sigh- vtkMetaImageWriter * writer = vtkMetaImageWriter::New(); writer->SetFileName( outfilename ); #if VTK_MAJOR_VERSION >= 6 writer->SetInputData( imgdata ); #else writer->SetInput( imgdata ); #endif writer->SetCompression( compress ); //writer->FileLowerLeftOff(); // not used in the implementation writer->Write(); if( writer->GetErrorCode() ) { std::cerr << "There was an error: " << vtkErrorCode::GetStringFromErrorCode(writer->GetErrorCode()) << std::endl; retcode = 1; } writer->Delete(); goto cleanup; } #endif } // else { vtkGDCMImageWriter * writer = vtkGDCMImageWriter::New(); //writer->SetFileLowerLeft( 1 ); if( studyuid ) { writer->SetStudyUID( study_uid.c_str() ); } if( seriesuid ) { writer->SetSeriesUID( series_uid.c_str() ); } // Default: writer->SetCompressionType( vtkGDCMImageWriter::NO_COMPRESSION ); // Implicit VR Little Endian if( jpeg ) { writer->SetCompressionType( vtkGDCMImageWriter::JPEG_COMPRESSION ); } else if( j2k ) { writer->SetCompressionType( vtkGDCMImageWriter::JPEG2000_COMPRESSION ); } else if( jpegls ) { writer->SetCompressionType( vtkGDCMImageWriter::JPEGLS_COMPRESSION ); } else if( rle ) { writer->SetCompressionType( vtkGDCMImageWriter::RLE_COMPRESSION ); } // HACK: call it *after* instanciating vtkGDCMImageWriter if( !gdcm::UIDGenerator::IsValid( study_uid.c_str() ) ) { std::cerr << "Invalid UID for Study UID: " << study_uid << std::endl; return 1; } if( !gdcm::UIDGenerator::IsValid( series_uid.c_str() ) ) { std::cerr << "Invalid UID for Series UID: " << series_uid << std::endl; return 1; } gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( "gdcm2vtk" ); if( !rootuid ) { // only read the env var is no explicit cmd line option // maybe there is an env var defined... let's check const char *rootuid_env = getenv("GDCM_ROOT_UID"); if( rootuid_env ) { rootuid = 1; root_uid = rootuid_env; } } if( rootuid ) { if( !gdcm::UIDGenerator::IsValid( root_uid.c_str() ) ) { std::cerr << "specified Root UID is not valid: " << root_uid << std::endl; return 1; } gdcm::UIDGenerator::SetRoot( root_uid.c_str() ); } writer->SetFileName( outfilename ); if( imgreader && imgreader->GetOutput()->GetNumberOfScalarComponents() == 4 && !argb ) { if( verbose ) { std::cout << "alpha channel will be lost " << imgreader->GetOutput()->GetNumberOfScalarComponents() << std::endl; } vtkImageExtractComponents *extract = vtkImageExtractComponents::New(); #if VTK_MAJOR_VERSION >= 6 extract->SetInputConnection( imgreader->GetOutputPort() ); #else extract->SetInput( imgreader->GetOutput() ); #endif extract->SetComponents( 0,1,2 ); #if VTK_MAJOR_VERSION >= 6 writer->SetInputConnection( extract->GetOutputPort() ); #else writer->SetInput( extract->GetOutput() ); #endif extract->Delete(); } else { //writer->SetInput( imgreader->GetOutput() ); #if VTK_MAJOR_VERSION >= 6 writer->SetInputData( imgdata ); #else writer->SetInput( imgdata ); #endif #if 0 vtkImageRGBToYBR * rgb2ybr = vtkImageRGBToYBR::New(); rgb2ybr->SetInput( imgreader->GetOutput() ); writer->SetInput( rgb2ybr->GetOutput() ); writer->SetImageFormat( VTK_YBR ); #endif } // If input is 3D, let's write output as 3D if possible: if( imgdata->GetDimensions()[2] != 1 ) { writer->SetFileDimensionality( 3 ); } if( imgreader ) { if( vtkGDCMImageReader * reader0 = vtkGDCMImageReader::SafeDownCast(imgreader) ) { writer->SetMedicalImageProperties( reader0->GetMedicalImageProperties() ); writer->SetDirectionCosines( reader0->GetDirectionCosines() ); writer->SetShift( reader0->GetShift() ); writer->SetScale( reader0->GetScale() ); writer->SetImageFormat( reader0->GetImageFormat() ); writer->SetLossyFlag( reader0->GetLossyFlag() ); if( verbose ) { reader0->GetOutput()->Print( std::cout ); reader0->GetMedicalImageProperties()->Print( std::cout ); } } #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) else if( vtkDICOMImageReader * reader1 = vtkDICOMImageReader::SafeDownCast(imgreader) ) { const float* iop = reader1->GetImageOrientationPatient(); double dircos[6]; for(int i = 0; i < 6; ++i) dircos[i] = iop[i]; writer->SetDirectionCosinesFromImageOrientationPatient( dircos ); writer->GetMedicalImageProperties()->SetModality( "MR" ); // FIXME writer->GetMedicalImageProperties()->SetPatientName( reader1->GetPatientName() ); //writer->GetMedicalImageProperties()->SetStudyUID( reader1->GetStudyUID() ); // TODO writer->GetMedicalImageProperties()->SetStudyID( reader1->GetStudyID() ); //writer->GetMedicalImageProperties()->SetGantryTilt( reader1->GetGantryAngle() ); // TODO #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 2) writer->GetMedicalImageProperties()->SetDirectionCosine( dircos[0], dircos[1], dircos[2], dircos[3], dircos[4], dircos[5] ); #endif writer->SetShift( reader1->GetRescaleOffset() ); writer->SetScale( reader1->GetRescaleSlope() ); //writer->SetImageFormat( reader1->GetImageFormat() ); //writer->SetLossyFlag( reader1->GetLossyFlag() ); } #endif else if( vtkJPEGReader * reader2 = vtkJPEGReader::SafeDownCast(imgreader) ) { (void)reader2; // vtk JPEG reader only read 8bits lossy file writer->SetLossyFlag( 1 ); // TODO: It would be nice to specify the original encoder was JPEG -> ISO_10918_1 } else if( vtkBMPReader * reader3 = vtkBMPReader::SafeDownCast(imgreader) ) { if( palettecolor ) reader3->Allow8BitBMPOn( ); reader3->Update( ); //reader3->GetLookupTable()->Print( std::cout ); if( palettecolor ) { if( reader3->GetNumberOfScalarComponents() == 1 ) { reader3->GetOutput()->GetPointData()->GetScalars()->SetLookupTable( reader3->GetLookupTable() ); writer->SetImageFormat( VTK_LOOKUP_TABLE ); } } } else if( vtkGESignaReader * reader4 = vtkGESignaReader::SafeDownCast(imgreader) ) { #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) writer->SetMedicalImageProperties( reader4->GetMedicalImageProperties() ); #endif //reader4->GetMedicalImageProperties()->Print( std::cout ); } #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) else if( vtkMINCImageReader *reader5 = vtkMINCImageReader::SafeDownCast( imgreader ) ) { writer->SetDirectionCosines( reader5->GetDirectionCosines() ); //writer->GetMedicalImageProperties()->SetModality( "MR" ); // the following does not work with VTKData/Data/t3_grid_0.mnc //writer->SetScale( reader5->GetRescaleSlope() ); //writer->SetShift( reader5->GetRescaleIntercept() ); if( verbose ) reader5->GetImageAttributes()->PrintFileHeader(); } #endif else if( vtkTIFFReader *reader6 = vtkTIFFReader::SafeDownCast( imgreader ) ) { // TIFF has resolution (spacing), and VTK make sure to set set in mm // For some reason vtkTIFFReader is all skrew up and will load the image in whatever orientation // as stored on file, thus this is up to the user to set it properly... // If anyone has any clue why... #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) reader6->SetOrientationType( ORIENTATION_BOTLEFT ); #endif } #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) else if( vtkMetaImageReader *reader7 = vtkMetaImageReader::SafeDownCast( imgreader ) ) { // vtkGetMacro(RescaleSlope, double); // vtkGetMacro(RescaleOffset, double); writer->SetScale( reader7->GetRescaleSlope() ); writer->SetShift( reader7->GetRescaleOffset() ); // vtkGetStringMacro(Modality); writer->GetMedicalImageProperties()->SetModality( reader7->GetModality() ); writer->SetFileLowerLeft( lowerleft ); // vtkGetStringMacro(DistanceUnits); // -> this one is insane, the default behavior is 'um' . What in the world is 'um' unit ? // I think I should discard any non 'mm' distance unit, simple as that // The following looks nice from the API, but the VTK implementation only sets them to '?' ... weird // vtkGetMacro(BitsAllocated, int); // vtkGetStringMacro(AnatomicalOrientation); // vtkGetMacro(GantryAngle, double); // vtkGetStringMacro(PatientName); // vtkGetStringMacro(PatientID); // vtkGetStringMacro(Date); // vtkGetStringMacro(Series); // vtkGetStringMacro(ImageNumber); // vtkGetStringMacro(StudyID); // vtkGetStringMacro(StudyUID); // vtkGetStringMacro(TransferSyntaxUID); } #endif } // nothing special need to be done for vtkStructuredPointsReader // Handle here the specific modality: if ( modality ) { if( !modality_str.empty() ) writer->GetMedicalImageProperties()->SetModality( modality_str.c_str() );; } // I would like to use vtkStructuredPointsReader::GetHeader as Image Comments, // however this is not possible with the current vtkMedicalImageProperties... if( !image_comments.empty() ) { writer->GetMedicalImageProperties()->SetSeriesDescription( image_comments.c_str() );; } // Let's do that at the end to be sure it always overwrite any other default if( oshift ) { writer->SetShift( shift ); } if( oscale ) { writer->SetScale( scale ); } if( oimageformat ) { writer->SetImageFormat( imageformat ); } // Pass on the filetime of input file time_t studydatetime = gdcm::System::FileTime( filename ); char date[22]; gdcm::System::FormatDateTime(date, studydatetime); // ContentDate const size_t datelen = 8; { // Do not copy the whole cstring: std::string s( date, date+datelen ); writer->GetMedicalImageProperties()->SetImageDate( s.c_str() );; } // ContentTime const size_t timelen = 6; // get rid of milliseconds { // Do not copy the whole cstring: std::string s( date+datelen, timelen ); writer->GetMedicalImageProperties()->SetImageTime( s.c_str() );; } writer->Write(); #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) if( writer->GetErrorCode() ) { std::cerr << "There was an error: " << vtkErrorCode::GetStringFromErrorCode(writer->GetErrorCode()) << std::endl; return 1; } #endif if( verbose ) writer->GetInput()->Print( std::cout ); writer->Delete(); } cleanup: if( imgreader ) imgreader->Delete(); names->Delete(); xmlreader->Delete(); datareader->Delete(); gdcmreader->Delete(); #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) dicomreader->Delete(); #endif return retcode; } GDCM-3.0.10/Utilities/VTK/Applications/gdcmviewer.cxx000066400000000000000000000737011412732066400222470ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /* * TODO: vtkPlaybackWidget would be cool for 4D images... * should I do it here, or a specified 4Dviewer application that will reexecute the reader (TIME* * stuff in vtk) */ #include "vtkGDCMImageReader.h" #include "vtkVersion.h" #include "vtkErrorCode.h" #include "vtkMedicalImageProperties.h" #include "vtkXMLImageDataWriter.h" #include "vtkInteractorStyleImage.h" #include "vtkCornerAnnotation.h" #include "vtkPNGWriter.h" #include "vtkImageShiftScale.h" #include "vtkOutlineFilter.h" #include "vtkMath.h" #include "vtkPolyDataMapper2D.h" #include "vtkImageReslice.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderWindow.h" #include "vtkPointData.h" #include "vtkImageMapToColors.h" #include "vtkLookupTable.h" #include "vtkActor2D.h" #include "vtkImageMapToWindowLevelColors.h" #include "vtkImageActor.h" #include "vtkWindowToImageFilter.h" #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) #include "vtkImageMapToColors16.h" #include "vtkBalloonWidget.h" #include "vtkBalloonRepresentation.h" #include "vtkLogoWidget.h" #include "vtkLogoRepresentation.h" #include "vtkAngleWidget.h" #include "vtkAngleRepresentation2D.h" #include "vtkBiDimensionalWidget.h" #include "vtkBiDimensionalRepresentation2D.h" #include "vtkDistanceWidget.h" #include "vtkContourWidget.h" #include "vtkOrientedGlyphContourRepresentation.h" #include "vtkPointHandleRepresentation2D.h" #include "vtkDistanceRepresentation2D.h" #include "vtkLegendScaleActor.h" #include "vtkProperty2D.h" #else class vtkLogoWidget; class vtkBiDimensionalWidget; class vtkDistanceWidget; class vtkLogoRepresentation; class vtkContourWidget; class vtkAngleWidget; #endif #if VTK_MAJOR_VERSION >= 5 #include "vtkImageYBRToRGB.h" #include "vtkImageColorViewer.h" #else #include "vtkImageViewer2.h" #endif #include "vtkImageData.h" #include "vtkCommand.h" #include "vtkRenderer.h" #include "vtkStringArray.h" #include "vtkDebugLeaks.h" #include "vtkWorldPointPicker.h" #include "vtkMultiThreader.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmDirectory.h" #include "gdcmImageHelper.h" #include "gdcmReader.h" #include "gdcmTrace.h" #include "gdcmVersion.h" #include #include #ifndef vtkFloatingPointType #define vtkFloatingPointType double #endif #if VTK_MAJOR_VERSION >= 5 #else class vtkImageColorViewer : public vtkImageViewer2 { public: vtkTypeMacro(vtkImageColorViewer,vtkImageViewer2); static vtkImageColorViewer *New() { #ifdef VTK_DEBUG_LEAKS vtkDebugLeaks::ConstructClass("vtkImageColorViewer"); #endif return new vtkImageColorViewer; } vtkImageColorViewer() { OverlayImageActor = vtkImageActor::New(); } ~vtkImageColorViewer() { OverlayImageActor->Delete(); } double GetOverlayVisibility() { return 0; } void SetOverlayVisibility(double vis) {} void AddInput(vtkImageData * input) { vtkRenderWindow *renwin = this->GetRenderWindow (); renwin->SetNumberOfLayers(2); vtkRenderer *Renderer = vtkRenderer::New(); Renderer->SetLayer(0); //OverlayImageActor->SetOpacity(0.5); //OverlayImageActor->GetProperty()->SetOpacity(1.0); vtkImageMapToWindowLevelColors *WindowLevel = vtkImageMapToWindowLevelColors::New(); WindowLevel->SetInput(input); OverlayImageActor->SetInput(WindowLevel->GetOutput()); Renderer->AddProp(OverlayImageActor); OverlayImageActor->SetVisibility(1); renwin->AddRenderer(Renderer); Renderer->Delete(); WindowLevel->Delete(); } private: vtkImageActor *OverlayImageActor; }; //vtkCxxRevisionMacro(vtkImageColorViewer, "$Revision: 1.30 $") vtkInstantiatorNewMacro(vtkImageColorViewer) #endif //---------------------------------------------------------------------------- // Callback for the interaction template class vtkGDCMObserver : public vtkCommand { public: static vtkGDCMObserver *New() { return new vtkGDCMObserver; } vtkGDCMObserver() { ImageViewer = NULL; IconWidget = NULL; DistanceWidget = NULL; BiDimWidget = NULL; AngleWidget = NULL; ContourWidget = NULL; picker = vtkWorldPointPicker::New(); } ~vtkGDCMObserver() { picker->Delete(); } virtual void Execute(vtkObject *caller, unsigned long event, void* /*calldata*/) { if ( this->ImageViewer ) { vtkRenderWindowInteractor * rwi = vtkRenderWindowInteractor::SafeDownCast( caller ); if ( event == vtkCommand::CharEvent ) { char keycode = 0; if( rwi ) keycode = rwi->GetKeyCode(); // 'o' is a special key for overlay visibility if ( keycode == 'o' ) { ImageViewer->SetOverlayVisibility( 1 - ImageViewer->GetOverlayVisibility() ); ImageViewer->Render(); //std::cerr << ImageViewer->GetOverlayVisibility() << std::endl; } else if ( keycode == 's' ) { vtkPNGWriter * writer = vtkPNGWriter::New(); vtkWindowToImageFilter * w2i = vtkWindowToImageFilter::New(); w2i->SetInput( rwi->GetRenderWindow() ); #if VTK_MAJOR_VERSION >= 6 writer->SetInputConnection( w2i->GetOutputPort() ); #else writer->SetInput( w2i->GetOutput() ); #endif writer->SetFileName( "snapshot.png" ); writer->Write(); writer->Delete(); w2i->Delete(); //std::cerr << "Screenshort saved to snapshot.png" << std::endl; } #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) else if ( keycode == 'l' ) { IconWidget->Off(); } else if ( keycode == 'a' ) { AngleWidget->On(); } else if ( keycode == 'b' ) { BiDimWidget->On(); } else if ( keycode == 'c' ) { ContourWidget->On(); } else if ( keycode == 'd' ) { DistanceWidget->On(); } else if ( keycode == 'p' ) { } #endif else { #if VTK_MAJOR_VERSION >= 5 || (VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5) int max = ImageViewer->GetSliceMax(); int slice = (ImageViewer->GetSlice() + 1) % ++max; ImageViewer->SetSlice( slice ); ImageViewer->GetRenderer()->ResetCamera(); #else int max = ImageViewer->GetWholeZMax(); int slice = (ImageViewer->GetZSlice() + 1 ) % ++max; ImageViewer->SetZSlice( slice ); ImageViewer->GetRenderer()->ResetCameraClippingRange(); #endif ImageViewer->Render(); } } else if ( event == vtkCommand::EndPickEvent ) { //std::cerr << "EndPickEvent" << std::endl; int *pick = rwi->GetEventPosition(); vtkRenderer *ren1 = ImageViewer->GetRenderer(); picker->Pick((double)pick[0], (double)pick[1], 0.0, ren1); vtkFloatingPointType *pos = picker->GetPickPosition (); std::cout << pos[0] << "," << pos[1] << "," << pos[2] << std::endl; } else { std::cerr << "Unhandled even:" << event << std::endl; } } } TViewer *ImageViewer; vtkWorldPointPicker *picker; vtkLogoWidget *IconWidget; vtkDistanceWidget *DistanceWidget; vtkAngleWidget *AngleWidget; vtkBiDimensionalWidget *BiDimWidget; vtkContourWidget *ContourWidget; }; int verbose; #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) class vtkBalloonCallback : public vtkCommand { public: static vtkBalloonCallback *New() { return new vtkBalloonCallback; } virtual void Execute(vtkObject *caller, unsigned long, void*) { vtkBalloonWidget *balloonWidget = reinterpret_cast(caller); if ( balloonWidget->GetCurrentProp() != NULL ) { cout << "Prop selected\n"; } } }; #endif void FillCornerFromMedProp( vtkCornerAnnotation *ca, vtkMedicalImageProperties *medprop ) { std::string bottomleft = "S: "; if( medprop->GetSeriesNumber() ) bottomleft += medprop->GetSeriesNumber(); bottomleft += "\nI: "; if( medprop->GetImageNumber() ) bottomleft += medprop->GetImageNumber(); bottomleft += "\n"; ca->SetText(0, bottomleft.c_str()); if( medprop->GetStationName() ) { const std::string bottomright = medprop->GetStationName(); ca->SetText(1, bottomright.c_str()); } std::string topleft; if( medprop->GetInstitutionName() ) topleft += medprop->GetInstitutionName(); topleft += "\n"; if( medprop->GetPatientName() ) topleft += medprop->GetPatientName(); ca->SetText(2, topleft.c_str()); std::string topright; if( medprop->GetStudyDate() ) topright += medprop->GetStudyDate(); topright += "\n"; if( medprop->GetAcquisitionTime() ) topright += medprop->GetAcquisitionTime(); ca->SetText(3, topright.c_str()); } // A feature in VS6 make it painfull to write template code // that do not contain the template parameter in the function // signature. Thus always pass parameter in the function: template void ExecuteViewer(TViewer *viewer, vtkStringArray *filenames) { vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); if( filenames->GetSize() == 1 ) // Backward compatible... { reader->SetFileName( filenames->GetValue(0) ); } else { reader->SetFileNames( filenames ); } vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); // For a single medical image, it would be more efficient to use // 0028|1050 [DS] [Window Center] // 0028|1051 [DS] [Window Width] // but gdcmviewer doesn't know about them :-( //reader->FileLowerLeftOn(); reader->Update(); if( reader->GetErrorCode() ) { std::cerr << "There was an error: " << vtkErrorCode:: GetStringFromErrorCode(reader->GetErrorCode()) << std::endl; return; } //reader->Print( cout ); if( verbose ) reader->GetOutput()->Print( cout ); //reader->GetOutput(1)->Print( cout ); vtkFloatingPointType range[2]; reader->GetOutput()->GetScalarRange(range); #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) viewer->SetInputConnection ( reader->GetOutputPort(0) ); // Technically we could just simple always call AddInputConnection on the overlay // but there is something wrong going on, when overlay visibility is set to 0 at startup // thus we need to make it visible by default which is annoying, so activate only // if overlays are found: if( reader->GetNumberOfOverlays() ) { // Add first overlay: // WARNING: gdcmviewer2 only ! viewer->AddInputConnection ( reader->GetOverlayPort(0) ); } // TODO: Icon can be added using the vtkLogoWidget #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) vtkPointHandleRepresentation2D *handle = vtkPointHandleRepresentation2D::New(); handle->GetProperty()->SetColor(1,0,0); vtkDistanceRepresentation2D *drep = vtkDistanceRepresentation2D::New(); drep->SetHandleRepresentation(handle); handle->Delete(); vtkDistanceWidget *dwidget = vtkDistanceWidget::New(); dwidget->SetInteractor(iren); dwidget->CreateDefaultRepresentation(); dwidget->SetRepresentation(drep); drep->Delete(); vtkAngleRepresentation2D *anglerep = vtkAngleRepresentation2D::New(); vtkAngleWidget *anglewidget = vtkAngleWidget::New(); anglewidget->SetInteractor(iren); anglewidget->SetRepresentation(anglerep); anglerep->Delete(); vtkBiDimensionalRepresentation2D *brep = vtkBiDimensionalRepresentation2D::New(); vtkBiDimensionalWidget *bwidget = vtkBiDimensionalWidget::New(); bwidget->SetInteractor(iren); bwidget->SetRepresentation(brep); brep->Delete(); vtkOrientedGlyphContourRepresentation *contourRep = vtkOrientedGlyphContourRepresentation::New(); vtkContourWidget *contourWidget = vtkContourWidget::New(); contourWidget->SetInteractor(iren); contourWidget->SetRepresentation(contourRep); contourRep->Delete(); vtkBalloonRepresentation *balloonrep = vtkBalloonRepresentation::New(); balloonrep->SetBalloonLayoutToImageRight(); vtkBalloonWidget *balloonwidget = vtkBalloonWidget::New(); balloonwidget->SetInteractor(iren); balloonwidget->SetRepresentation(balloonrep); balloonrep->Delete(); //balloonwidget->AddBalloon(viewer->GetImageActor(),"This is a DICOM image",NULL); vtkBalloonCallback *cbk = vtkBalloonCallback::New(); balloonwidget->AddObserver(vtkCommand::WidgetActivateEvent,cbk); vtkLogoWidget * iconwidget = 0; if( reader->GetNumberOfIconImages() ) { vtkLogoRepresentation *rep = vtkLogoRepresentation::New(); rep->SetImage(reader->GetIconImage()); //reader->GetIconImage()->Print( std::cout ); if( reader->GetIconImage()->GetPointData()->GetScalars() && reader->GetIconImage()->GetPointData()->GetScalars()->GetLookupTable() ) { vtkLookupTable *lut = reader->GetIconImage()->GetPointData()->GetScalars()->GetLookupTable(); vtkImageMapToColors *map = vtkImageMapToColors::New (); #if (VTK_MAJOR_VERSION >= 6) map->SetInputData(reader->GetIconImage()); #else map->SetInput (reader->GetIconImage()); #endif map->SetLookupTable ( lut ); //FIXME there is no way to know the type of LUT the icon is using: //if( reader->GetImageFormat() == VTK_LOOKUP_TABLE ) { map->SetOutputFormatToRGB(); } //else if( reader->GetImageFormat() == VTK_INVERSE_LUMINANCE ) // { // map->SetOutputFormatToLuminance(); // } map->Update(); //map->GetOutput()->GetScalarRange(range); //viewer->SetInput( map->GetOutput() ); //map->GetOutput()->Print( std::cout ); rep->SetImage( map->GetOutput() ); map->Delete(); //vtkPNGWriter *iconw = vtkPNGWriter::New(); //iconw->SetInput( map->GetOutput() ); //iconw->SetFileName( "/tmp/icon.png" ); //iconw->Write(); //iconw->Delete(); } //reader->GetIconImage()->Print( std::cout ); //vtkPropCollection *pc = vtkPropCollection::New(); //rep->GetActors2D(pc); //balloonwidget->AddBalloon(pc->GetLastProp(),"This is a DICOM thumbnail image",NULL); vtkLogoWidget *widget = vtkLogoWidget::New(); widget->SetInteractor(iren); widget->SetRepresentation(rep); iconwidget = widget; //widget->Delete(); rep->Delete(); //viewer->AddInputConnection ( reader->GetIconImagePort() ); } #endif #else viewer->SetInput( reader->GetOutput(0) ); if( reader->GetNumberOfOverlays() ) { viewer->AddInput( reader->GetOverlay(0) ); } #endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/ // IconImage: //if( reader->GetNumberOfIconImages() ) // { // std::cerr << "NumberOfIconImages:" << reader->GetNumberOfIconImages() << std::endl; // reader->GetIconImage()->Print( std::cerr ); // vtkPNGWriter *writer = vtkPNGWriter::New(); // writer->SetInput( reader->GetIconImage() ); // writer->SetFileName( "icon.png" ); // //writer->Write(); // writer->Delete(); // } // In case of palette color, let's tell VTK to map color: // MONOCHROME1 is also implemented with a lookup table if( reader->GetImageFormat() == VTK_LOOKUP_TABLE || reader->GetImageFormat() == VTK_INVERSE_LUMINANCE ) { #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) assert( reader->GetOutput()->GetPointData()->GetScalars() && reader->GetOutput()->GetPointData()->GetScalars()->GetLookupTable() ); #endif //convert to color: vtkLookupTable *lut = reader->GetOutput()->GetPointData()->GetScalars()->GetLookupTable(); if( !lut ) { // This must be a Segmented Palette and on VTK 4.4 this is not supported std::cerr << "Not implemented. You will not see the Color LUT" << std::endl; } #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) if( lut->IsA( "vtkLookupTable16" ) ) { vtkImageMapToColors16 *map = vtkImageMapToColors16::New (); #if VTK_MAJOR_VERSION >= 6 map->SetInputConnection (reader->GetOutputPort()); #else map->SetInput (reader->GetOutput()); #endif map->SetLookupTable (reader->GetOutput()->GetPointData()->GetScalars()->GetLookupTable()); if( reader->GetImageFormat() == VTK_LOOKUP_TABLE ) { map->SetOutputFormatToRGB(); } else if( reader->GetImageFormat() == VTK_INVERSE_LUMINANCE ) { map->SetOutputFormatToLuminance(); } map->Update(); map->GetOutput()->GetScalarRange(range); #if VTK_MAJOR_VERSION >= 6 viewer->SetInputConnection( map->GetOutputPort() ); #else viewer->SetInput( map->GetOutput() ); #endif map->Delete(); } else #endif { vtkImageMapToColors *map = vtkImageMapToColors::New (); #if VTK_MAJOR_VERSION >= 6 map->SetInputConnection (reader->GetOutputPort()); #else map->SetInput (reader->GetOutput()); #endif map->SetLookupTable (reader->GetOutput()->GetPointData()->GetScalars()->GetLookupTable()); if( reader->GetImageFormat() == VTK_LOOKUP_TABLE ) { map->SetOutputFormatToRGB(); } else if( reader->GetImageFormat() == VTK_INVERSE_LUMINANCE ) { map->SetOutputFormatToLuminance(); } map->Update(); map->GetOutput()->GetScalarRange(range); #if VTK_MAJOR_VERSION >= 6 viewer->SetInputConnection( map->GetOutputPort() ); #else viewer->SetInput( map->GetOutput() ); #endif map->Delete(); } } else if( reader->GetImageFormat() == VTK_YBR ) { #if VTK_MAJOR_VERSION >= 5 vtkImageYBRToRGB *filter = vtkImageYBRToRGB::New(); #if VTK_MAJOR_VERSION >= 6 filter->SetInputConnection( reader->GetOutputPort() ); #else filter->SetInput( reader->GetOutput() ); #endif filter->Update(); filter->GetOutput()->GetScalarRange(range); #if VTK_MAJOR_VERSION >= 6 viewer->SetInputConnection( filter->GetOutputPort() ); #else viewer->SetInput( filter->GetOutput() ); #endif filter->Delete(); #else std::cerr << "Not implemented" << std::endl; #endif } else if( reader->GetImageFormat() == VTK_RGB || reader->GetImageFormat() == VTK_RGBA ) { // easy case ! } // vtkImageShiftScale *ss = vtkImageShiftScale::New(); // ss->SetInput( reader->GetOutput() ); // ss->SetShift( -1024 ); // ss->SetOutputScalarTypeToShort(); // ss->Update(); // ss->GetOutput()->GetScalarRange(range); // viewer->SetInput( ss->GetOutput() ); // ss->Delete(); if( reader->GetCurve() ) { vtkPolyDataMapper2D * rectMapper = vtkPolyDataMapper2D::New(); #if VTK_MAJOR_VERSION >= 6 rectMapper->SetInputData( reader->GetCurve() ); #else rectMapper->SetInput( reader->GetCurve() ); #endif vtkActor2D * rectActor = vtkActor2D::New(); rectActor->SetMapper( rectMapper ); viewer->GetRenderer()->AddActor2D( rectActor ); rectActor->Delete(); rectMapper->Delete(); } #if 0 vtkImageReslice * slicer = vtkImageReslice::New(); slicer->SetInput( reader->GetOutput() ); slicer->InterpolateOn(); //slicer->SetResliceAxesOrigin(0, 0, 0); //slicer->SetResliceAxesOrigin( reader->GetImagePositionPatient() ); //slicer->SetResliceAxes( reader->GetDirectionCosines() ); const double *dircos = reader->GetImageOrientationPatient(); double dcos[9]; for(int i=0;i<6;++i) dcos[i] = dircos[i]; dcos[6] = dircos[1] * dircos[5] - dircos[2] * dircos[4]; dcos[7] = dircos[2] * dircos[3] - dircos[0] * dircos[5]; dcos[8] = dircos[0] * dircos[4] - dircos[3] * dircos[1]; double dummy[3]; double dot = vtkMath::Dot(dircos, dircos+3); std::cout << dot << std::endl; vtkMath::Cross(dircos, dircos+3, dummy); std::cout << dcos[6] << "," << dcos[7] << "," << dcos[8] << std::endl; std::cout << dummy[0] << "," << dummy[1] << "," << dummy[2] << std::endl; dot = vtkMath::Dot(dircos, dummy); std::cout << dot << std::endl; dot = vtkMath::Dot(dircos+3, dummy); std::cout << dot << std::endl; slicer->SetResliceAxesDirectionCosines(dcos); slicer->Update(); slicer->GetOutput()->Print( std::cout ); //viewer->SetInput( slicer->GetOutput() ); vtkOutlineFilter * outline = vtkOutlineFilter::New(); outline->SetInput( slicer->GetOutput() ); outline->GetOutput()->Print( std::cout ); //slicer->AddInput( (vtkPolyData*)outline->GetOutput() ); #endif // Always overwriting default is not always nice looking... viewer->SetColorLevel (0.5 * (range[1] + range[0])); viewer->SetColorWindow (range[1] - range[0]); if( verbose ) std::cout << "Range: " << range[0] << " " << range[1] << std::endl; viewer->SetupInteractor (iren); // vtkInteractorStyleImage *is = viewer->GetInteractorStyle(); // viewer->GetInteractorStyle()->AutoAdjustCameraClippingRangeOn(); vtkCornerAnnotation * ca = vtkCornerAnnotation::New(); ca->SetImageActor( viewer->GetImageActor() ); ca->SetWindowLevel( (vtkImageMapToWindowLevelColors*)viewer->GetWindowLevel() ); vtkMedicalImageProperties * medprop = reader->GetMedicalImageProperties(); FillCornerFromMedProp( ca, medprop ); #if VTK_MAJOR_VERSION >= 5 viewer->GetRenderer()->AddViewProp( ca ); #else viewer->GetRenderer()->AddProp( ca ); #endif int dims[3]; reader->GetOutput()->GetDimensions(dims); // Make sure to display on most screen dims[0] = (dims[0] < 600 ) ? dims[0] : 600; dims[1] = (dims[1] < 600 ) ? dims[1] : 600; viewer->Render(); // EXTREMELY IMPORTANT for vtkImageViewer2 viewer->GetRenderer()->ResetCamera(); viewer->SetSize( dims ); // Here is where we setup the observer, vtkGDCMObserver *obs = vtkGDCMObserver::New(); obs->ImageViewer = viewer; #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) if(iconwidget) iconwidget->On(); obs->IconWidget = iconwidget; obs->DistanceWidget = dwidget; obs->AngleWidget = anglewidget; obs->BiDimWidget = bwidget; obs->ContourWidget = contourWidget; balloonwidget->On(); #endif iren->AddObserver(vtkCommand::CharEvent,obs); iren->AddObserver(vtkCommand::EndPickEvent,obs); obs->Delete(); //vtkLegendScaleActor *legend = vtkLegendScaleActor::New(); //viewer->GetRenderer()->AddActor( legend ); iren->Initialize(); iren->Start(); //if you wish you can export dicom to a vtk file #if 0 vtkXMLImageDataWriter *writer = vtkXMLImageDataWriter::New(); writer->SetInputConnection( reader->GetOutputPort()); writer->SetFileName( "debug.vtk" ); writer->SetDataModeToBinary(); writer->Write(); writer->Delete(); #endif #if 0 vtkPNGWriter *writer = vtkPNGWriter::New(); //writer->SetInputConnection( reader->GetOutputPort() ); writer->SetInputConnection( reader->GetOutputPort(1) ); //range = overlay->GetScalarRange(); //std::cerr << "Range: " << range[0] << " " << range[1] << std::endl; //overlay->Print( std::cout ); //writer->SetInput( overlay ); writer->SetFileName( "debug.png" ); writer->Write(); writer->Delete(); #endif reader->Delete(); #if VTK_MAJOR_VERSION >= 6 || (VTK_MAJOR_VERSION >= 5 && VTK_MINOR_VERSION > 0) cbk->Delete(); dwidget->Off(); balloonwidget->Off(); balloonwidget->Delete(); dwidget->Delete(); anglewidget->Off(); anglewidget->Delete(); bwidget->Off(); bwidget->Delete(); contourWidget->Off(); contourWidget->Delete(); if( iconwidget ) { iconwidget->Off(); iconwidget->Delete(); } #endif iren->Delete(); viewer->Delete(); } void PrintVersion() { std::cout << "gdcmviewer: gdcm " << gdcm::Version::GetVersion() << " "; const char date[] = "$Date$"; std::cout << date << std::endl; //std::cout << " VTK " << vtkVersion::GetVTKVersion() << std::endl; std::cout << " " << vtkVersion::GetVTKSourceVersion() << std::endl; } void PrintHelp() { PrintVersion(); std::cout << "Usage: gdcmviewer [OPTION] filename1.dcm [filename2.dcm...]" << std::endl; std::cout << "or : gdcmviewer [OPTION] directory" << std::endl; std::cout << "Display a DICOM image file.\n"; std::cout << "Options:" << std::endl; std::cout << " --force-rescale force rescale." << std::endl; std::cout << " --force-spacing force spacing." << std::endl; std::cout << " -r --recursive Recursively descend directory." << std::endl; std::cout << "General Options:" << std::endl; std::cout << " -V --verbose more verbose (warning+error)." << std::endl; std::cout << " -W --warning print warning info." << std::endl; std::cout << " -D --debug print debug info." << std::endl; std::cout << " -E --error print error info." << std::endl; std::cout << " -h --help print help." << std::endl; std::cout << " -v --version print version." << std::endl; } int main(int argc, char *argv[]) { int c; //int digit_optind = 0; std::vector filenames; int forcerescale = 0; int forcespacing = 0; int recursive = 0; verbose = 0; int warning = 0; int debug = 0; int error = 0; int help = 0; int version = 0; while (1) { //int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"force-rescale", 0, &forcerescale, 1}, {"force-spacing", 0, &forcespacing, 1}, {"recursive", 0, &recursive, 1}, // General options ! {"verbose", 0, &verbose, 1}, {"warning", 0, &warning, 1}, {"debug", 0, &debug, 1}, {"error", 0, &error, 1}, {"help", 0, &help, 1}, {"version", 0, &version, 1}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "rVWDEhv", long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: { const char *s = long_options[option_index].name; (void)s; //printf ("option %s", s); if (optarg) { if( option_index == 0 ) /* input */ { assert( strcmp(s, "input") == 0 ); //assert( filename.empty() ); //filename = optarg; } printf (" with arg %s", optarg); } //printf ("\n"); } break; case 'r': recursive = 1; break; case 'V': verbose = 1; break; case 'W': warning = 1; break; case 'D': debug = 1; break; case 'E': error = 1; break; case 'h': help = 1; break; case 'v': version = 1; break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { //printf ("non-option ARGV-elements: "); while (optind < argc) { //printf ("%s ", argv[optind]); filenames.push_back( argv[optind++] ); } //printf ("\n"); } if( version ) { //std::cout << "version" << std::endl; PrintVersion(); return 0; } if( help ) { //std::cout << "help" << std::endl; PrintHelp(); return 0; } // Debug is a little too verbose gdcm::Trace::SetDebug( debug ); gdcm::Trace::SetWarning( warning ); gdcm::Trace::SetError( error ); // when verbose is true, make sure warning+error are turned on: if( verbose ) { gdcm::Trace::SetWarning( verbose ); gdcm::Trace::SetError( verbose); } //vtkMultiThreader::SetGlobalMaximumNumberOfThreads(1); gdcm::ImageHelper::SetForceRescaleInterceptSlope(forcerescale); gdcm::ImageHelper::SetForcePixelSpacing(forcespacing); if( filenames.empty() ) { PrintHelp(); return 1; } gdcm::Reader testreader; vtkStringArray *names = vtkStringArray::New(); { // Is it a single directory ? If so loop over all files contained in it: //const char *filename = argv[1]; if( filenames.size() == 1 && gdcm::System::FileIsDirectory( filenames[0].c_str() ) ) { if( verbose ) std::cout << "Loading directory: " << filenames[0] << std::endl; gdcm::Directory d; d.Load(filenames[0].c_str(), recursive); gdcm::Directory::FilenamesType const &files = d.GetFilenames(); for( gdcm::Directory::FilenamesType::const_iterator it = files.begin(); it != files.end(); ++it ) { testreader.SetFileName( it->c_str() ); if( testreader.CanRead() ) { names->InsertNextValue( it->c_str() ); } else { if(verbose) std::cerr << "Discarding non DICOM file: " << it->c_str() << std::endl; } } } else // list of files passed directly on the cmd line: // discard non-existing or directory { //for(int i=1; i < argc; ++i) for(std::vector::const_iterator it = filenames.begin(); it != filenames.end(); ++it) { //filename = argv[i]; const std::string & filename = *it; if( gdcm::System::FileExists( filename.c_str() ) ) { if( gdcm::System::FileIsDirectory( filename.c_str() ) ) { if(verbose) std::cerr << "Discarding directory: " << filename << std::endl; } else { testreader.SetFileName( filename.c_str() ); if( testreader.CanRead() ) { names->InsertNextValue( filename.c_str() ); } else { if(verbose) std::cerr << "Discarding non DICOM file: " << filename.c_str() << std::endl; } } } else { if(verbose) std::cerr << "Discarding non existing file: " << filename << std::endl; } } } //names->Print( std::cout ); } vtkImageColorViewer *viewer = vtkImageColorViewer::New(); ExecuteViewer(viewer, names); names->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/AssemblyInfo.cs.in000066400000000000000000000065111412732066400202630ustar00rootroot00000000000000#region License /*========================================================================= BSD License [http://www.opensource.org/licenses/bsd-license.php] Copyright (c) 2006-2011 Mathieu Malaterre All rights reserved. See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither name of Mathieu Malaterre, or CREATIS, nor the names of any contributors (CNRS, INSERM, UCB, Universite Lyon I), may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =========================================================================*/ #endregion License using System.Reflection; using System.Runtime.CompilerServices; // Information about this assembly is defined by the following // attributes. // // change them to the information which is associated with the assembly // you compile. [assembly: AssemblyTitle("VTK-GDCM Framework Binding For .NET")] [assembly: AssemblyDescription("VTK-GDCM Framework Binding For .NET")] [assembly: AssemblyConfiguration("Retail")] [assembly: AssemblyCompany("GDCM -- http://gdcm.sourceforge.net")] [assembly: AssemblyProduct("vtkgdcm-sharp.dll")] [assembly: AssemblyDefaultAlias("vtkgdcm-sharp")] [assembly: AssemblyCopyright("Copyright ©2006-2011 Mathieu Malaterre. All rights reserved.")] [assembly: AssemblyTrademark("GDCM -- http://gdcm.sourceforge.net")] [assembly: AssemblyCulture("")] // The assembly version has following format : // // Major.Minor.Build.Revision // // You can specify all values by your own or you can build default build and revision // numbers with the '*' character (the default): [assembly: AssemblyVersion("@GDCM_API_VERSION@")] [assembly: AssemblyFileVersion("@GDCM_API_VERSION@")] [assembly: AssemblyInformationalVersion("@GDCM_API_VERSION@")] // The following attributes specify the key for the sign of your assembly. See the // .NET Framework documentation for more information about signing. // This is not required, if you don't want signing let these attributes like they're. [assembly: AssemblyDelaySign(false)] [assembly: AssemblyKeyFile("key.snk")] //[assembly: AssemblyKeyName("")] GDCM-3.0.10/Utilities/VTK/CMakeLists.txt000066400000000000000000001016041412732066400174730ustar00rootroot00000000000000project(vtkgdcm) # We need VTK # Technically we require VTK 5.0 and above # Define the src for the vtk-gdcm bridge set(vtkgdcm_SRCS vtkGDCMTesting.cxx vtkGDCMImageReader.cxx vtkGDCMImageWriter.cxx vtkGDCMMedicalImageProperties.cxx ) if(GDCM_HAVE_PTHREAD_H AND CMAKE_USE_PTHREADS) set(vtkgdcm_SRCS ${vtkgdcm_SRCS} vtkGDCMThreadedImageReader.cxx ) endif() #if( ${VTK_VERSION_MAJOR} LESS 7 ) include(${VTK_USE_FILE}) #endif() if( ${VTK_MAJOR_VERSION} GREATER 5 ) list(APPEND vtkgdcm_SRCS vtkGDCMImageReader2.cxx ) endif() include(CheckCXXSourceCompiles) set(CMAKE_REQUIRED_INCLUDES ${VTK_INCLUDE_DIRS}) CHECK_CXX_SOURCE_COMPILES( "\#include \nint main() { vtkSmartVolumeMapper* p; return 0;}" VTK_HAS_SMARTVOLUMEMAPPER) CHECK_CXX_SOURCE_COMPILES( "\#include \nint main() { vtkImageResliceMapper* p; return 0;}" VTK_HAS_IMAGERESLICEMAPPER) include_directories( ${GDCM_BINARY_DIR}/Source/Common ${GDCM_SOURCE_DIR}/Source/Common ${GDCM_SOURCE_DIR}/Source/DataStructureAndEncodingDefinition ${GDCM_SOURCE_DIR}/Source/MediaStorageAndFileFormat ${GDCM_SOURCE_DIR}/Source/DataDictionary ${GDCM_SOURCE_DIR}/Utilities/VTK ) # FIXME: temp fix #if(UNIX) # link_directories(/usr/X11R6/lib) #endif() # List the kits from VTK that are needed by this project. if("${VTK_MAJOR_VERSION}" LESS 6) set(vtkgdcm_LIBS vtkCommon vtkFiltering vtkIO vtkImaging ) if(VTK_USE_RENDERING) set(vtkgdcm_LIBS ${vtkgdcm_LIBS} vtkRendering ) endif() else() set(vtkgdcm_LIBS vtkCommonCore vtkImagingCore vtkImagingSources vtkIOImage vtkIOLegacy #vtksys ) set(vtkgdcm_COND_LIBS vtkIOMPIImage vtkInteractionStyle vtkRenderingCore vtkRenderingFreeType vtkRenderingFreeTypeOpenGL vtkFiltersParallelDIY2 ) if(("${VTK_MAJOR_VERSION}" EQUAL 6) OR ("${VTK_RENDERING_BACKEND}" STREQUAL "OpenGL")) list(APPEND vtkgdcm_COND_LIBS vtkRenderingOpenGL) else() list(APPEND vtkgdcm_COND_LIBS vtkRenderingOpenGL2) endif() foreach(TMP_LIB ${VTK_LIBRARIES}) foreach(TRY_LIB ${vtkgdcm_COND_LIBS}) if("${TMP_LIB}" STREQUAL "${TRY_LIB}") set(vtkgdcm_LIBS ${vtkgdcm_LIBS} "${TRY_LIB}") endif() endforeach() endforeach() endif() # Use wrapping hints for this project. #set(VTK_WRAP_HINTS "${PROJECT_SOURCE_DIR}/hints") set(VTKGDCM_NAME vtkgdcm CACHE STRING "vtk-gdcm lib name") mark_as_advanced(VTKGDCM_NAME) # Create the instantiator for these classes. # FIXME: Are instantiator really needed when only doing python wrapping ? if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" LESS 4.5 ) set(vtkgdcm_SRCS ${vtkgdcm_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/VTK4/vtkMedicalImageProperties.cxx ${CMAKE_CURRENT_SOURCE_DIR}/VTK4/vtkStringArray.cxx ) # Setup vtkInstantiator registration for this library's classes. include_directories( ${GDCM_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/VTK4 ) VTK_MAKE_INSTANTIATOR2( "${VTKGDCM_NAME}Instantiator" vtkgdcmInstantiator_SRCS "${vtkgdcm_SRCS}" EXPORT_MACRO "" #GDCM_EXPORT HEADER_LOCATION ${GDCM_BINARY_DIR} ) else() set(vtkgdcm_SRCS ${vtkgdcm_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/vtkImageMapToWindowLevelColors2.cxx ${CMAKE_CURRENT_SOURCE_DIR}/vtkImageYBRToRGB.cxx ${CMAKE_CURRENT_SOURCE_DIR}/vtkImageRGBToYBR.cxx ${CMAKE_CURRENT_SOURCE_DIR}/vtkGDCMPolyDataReader.cxx ${CMAKE_CURRENT_SOURCE_DIR}/vtkGDCMPolyDataWriter.cxx ${CMAKE_CURRENT_SOURCE_DIR}/vtkRTStructSetProperties.cxx ${CMAKE_CURRENT_SOURCE_DIR}/vtkLookupTable16.cxx ${CMAKE_CURRENT_SOURCE_DIR}/vtkImageMapToColors16.cxx #${CMAKE_CURRENT_SOURCE_DIR}/vtkImagePlanarComponentsToComponents.cxx ) if(VTK_USE_RENDERING OR vtkRenderingCore_LOADED) set(vtkgdcm_SRCS ${vtkgdcm_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/vtkImageColorViewer.cxx ) endif() #if(GDCM_HAVE_PTHREAD_H) set(vtkgdcm_SRCS ${vtkgdcm_SRCS} vtkGDCMThreadedImageReader2.cxx ) #endif() if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" LESS 6.0 ) set(VTK_USE_INSTANTIATOR_NEW 1) VTK_MAKE_INSTANTIATOR3( "${VTKGDCM_NAME}Instantiator" vtkgdcmInstantiator_SRCS "${vtkgdcm_SRCS}" "" #"VTK_${VTKGDCM_NAME}_EXPORT" ${PROJECT_BINARY_DIR} "" #"${VTKGDCM_NAME}Configure.h" ) endif() endif() #Hum... not sure why this is needed. #if(NOT VTK_BUILD_SHARED_LIBS AND GDCM_BUILD_SHARED_LIBS) # add_library(vtkgdcm STATIC ${vtkgdcm_SRCS} ${vtkgdcmInstantiator_SRCS}) #else() add_library(${VTKGDCM_NAME} ${vtkgdcm_SRCS} ${vtkgdcmInstantiator_SRCS}) #endif() set_target_properties(${VTKGDCM_NAME} PROPERTIES ${GDCM_LIBRARY_PROPERTIES}) target_link_libraries(${VTKGDCM_NAME} LINK_PRIVATE gdcmMSFF ${vtkgdcm_LIBS}) if(GDCM_HAVE_PTHREAD_H) target_link_libraries(${VTKGDCM_NAME} LINK_PRIVATE pthread) endif() if(NOT GDCM_INSTALL_NO_LIBRARIES) install(TARGETS ${VTKGDCM_NAME} EXPORT ${GDCM_TARGETS_NAME} RUNTIME DESTINATION ${GDCM_INSTALL_BIN_DIR} COMPONENT VTKLibraries LIBRARY DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT VTKLibraries #${NAMELINK_SKIP} ARCHIVE DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT VTKDebugDevel ) #if(NAMELINK_ONLY) # install(TARGETS vtkgdcm # LIBRARY DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT DebugDevel ${NAMELINK_ONLY} # ) # endif() endif() if(NOT GDCM_INSTALL_NO_DEVELOPMENT) set(header_files_glob "*.h" "*.txx") if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" LESS 4.5 ) set(header_files_glob ${header_files_glob} "VTK4/*.h" ) endif() file(GLOB header_files ${header_files_glob}) install(FILES ${header_files} DESTINATION ${GDCM_INSTALL_INCLUDE_DIR} COMPONENT VTKHeaders ) endif() if(GDCM_WRAP_PHP) if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" LESS 4.5 ) message(FATAL_ERROR "you need a newer VTK version >= 5.0") endif() find_package(PHP5 REQUIRED) include_directories( ${PHP5_INCLUDE_PATH} ) find_package(SWIG REQUIRED) mark_as_advanced(SWIG_DIR SWIG_EXECUTABLE SWIG_VERSION) include(${SWIG_USE_FILE}) set_source_files_properties(vtkgdcm.i PROPERTIES CPLUSPLUS ON) #set_source_files_properties(vtkgdcm.i PROPERTIES COMPILE_FLAGS -DUSEACTIVIZ) #if(GDCM_USE_ACTIVIZ) #set(CMAKE_SWIG_FLAGS "-namespace vtkgdcm -dllimport vtkgdcmsharpglue -DUSEACTIVIZ") #else() #set(CMAKE_SWIG_FLAGS "-namespace vtkgdcm -dllimport vtkgdcmsharpglue") #endif() #separate_arguments(CMAKE_SWIG_FLAGS) SWIG_ADD_LIBRARY( php_vtkgdcm LANGUAGE php SOURCES vtkgdcm.i ) SWIG_LINK_LIBRARIES(php_vtkgdcm vtkgdcm) target_link_libraries(${SWIG_MODULE_php_vtkgdcm_REAL_NAME} LINK_PRIVATE ${vtkgdcm_LIBS}) if(UNIX) set_target_properties(${SWIG_MODULE_php_vtkgdcm_REAL_NAME} PROPERTIES OUTPUT_NAME "vtkgdcm") endif() set_target_properties(${SWIG_MODULE_php_vtkgdcm_REAL_NAME} PROPERTIES PREFIX "") set_property(TARGET ${SWIG_MODULE_php_vtkgdcm_REAL_NAME} PROPERTY NO_SONAME 1) if(NOT GDCM_INSTALL_NO_LIBRARIES) install(TARGETS ${SWIG_MODULE_php_vtkgdcm_REAL_NAME} EXPORT ${GDCM_TARGETS_NAME} RUNTIME DESTINATION ${GDCM_INSTALL_BIN_DIR} COMPONENT Applications LIBRARY DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT Libraries ) #if(NAMELINK_ONLY) # install(TARGETS ${SWIG_MODULE_vtkgdcmsharpglue_REAL_NAME} # LIBRARY DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT DebugDevel ${NAMELINK_ONLY} # ) # endif() # See gdcm bug #3175803 if(${SWIG_VERSION} LESS 2.0.2) add_custom_command(TARGET ${SWIG_MODULE_php_vtkgdcm_REAL_NAME} PRE_BUILD COMMAND sed -i -e 's/zend_error_noreturn/zend_error/g' "${swig_generated_file_fullname}" COMMENT "Patching zend_error_noreturn into zend_error" ) endif() # Let's copy vtkgdcm.php into the bin dir: add_custom_command( OUTPUT ${LIBRARY_OUTPUT_PATH}/vtkgdcm.php COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/vtkgdcm.php ${LIBRARY_OUTPUT_PATH}/vtkgdcm.php DEPENDS "${swig_generated_file_fullname}" COMMENT "copying vtkgdcm.php" ) add_custom_target(VTKGDCMPHP ALL DEPENDS ${LIBRARY_OUTPUT_PATH}/vtkgdcm.php COMMENT "building vtkgdcm.php" ) install(FILES ${LIBRARY_OUTPUT_PATH}/vtkgdcm.php DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT VTKPythonModule ) endif() endif() if(GDCM_WRAP_CSHARP) if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" LESS 4.5 ) message(FATAL_ERROR "you need a newer VTK version >= 5.0") endif() if(GDCM_USE_ACTIVIZ) find_package(ACTIVIZ REQUIRED) else() message(STATUS "You are using the SWIG version of VTKGDCM. This is not compatible with Activiz") find_package(SWIG REQUIRED) mark_as_advanced(SWIG_DIR SWIG_EXECUTABLE SWIG_VERSION) include(${SWIG_USE_FILE}) set_source_files_properties(vtkgdcm.i PROPERTIES CPLUSPLUS ON) #set_source_files_properties(vtkgdcm.i PROPERTIES COMPILE_FLAGS -DUSEACTIVIZ) endif() if(GDCM_USE_ACTIVIZ) #set(CMAKE_SWIG_FLAGS "-namespace vtkgdcm -dllimport vtkgdcmsharpglue -DUSEACTIVIZ") else() set(CMAKE_SWIG_FLAGS "-namespace vtkgdcm -dllimport vtkgdcmsharpglue") separate_arguments(CMAKE_SWIG_FLAGS) SWIG_ADD_LIBRARY( vtkgdcmsharpglue LANGUAGE csharp SOURCES vtkgdcm.i ) target_link_libraries(${SWIG_MODULE_vtkgdcmsharpglue_REAL_NAME} LINK_PRIVATE vtkgdcm) # Stupid cmake-swig module is doing that for us, when not needed if(UNIX) set_target_properties(${SWIG_MODULE_vtkgdcmsharpglue_REAL_NAME} PROPERTIES PREFIX "lib") endif() target_link_libraries(${SWIG_MODULE_vtkgdcmsharpglue_REAL_NAME} LINK_PRIVATE ${vtkgdcm_LIBS}) if(NOT GDCM_INSTALL_NO_LIBRARIES) install(TARGETS ${SWIG_MODULE_vtkgdcmsharpglue_REAL_NAME} EXPORT ${GDCM_TARGETS_NAME} RUNTIME DESTINATION ${GDCM_VTK_INSTALL_CSHARPMODULE_DIR} COMPONENT Applications LIBRARY DESTINATION ${GDCM_VTK_INSTALL_CSHARPMODULE_DIR} COMPONENT Libraries ) endif() endif() configure_file( ${GDCM_SOURCE_DIR}/Wrapping/Csharp/key.snk ${CMAKE_CURRENT_BINARY_DIR}/key.snk COPYONLY) if(GDCM_USE_ACTIVIZ) find_package(Mummy REQUIRED) mark_as_advanced(Mummy_DIR) if(NOT Mummy_BASE_DIR) message(FATAL_ERROR "error: Mummy_BASE_DIR not defined. Please set Mummy_DIR to the directory containing MummyConfig.cmake") endif() include("${Mummy_DIR}/MummyCMakeMacros.cmake") if(NOT mummy_EXECUTABLE) find_program(mummy_EXECUTABLE mummy) endif() mark_as_advanced(mummy_EXECUTABLE) if(NOT mummy_EXECUTABLE) message(FATAL_ERROR "error: mummy not found. mummy_EXECUTABLE='${mummy_EXECUTABLE}'") endif() if(NOT castxml_EXECUTABLE) find_program(castxml_EXECUTABLE castxml) endif() mark_as_advanced(castxml_EXECUTABLE) if(NOT castxml_EXECUTABLE) message(FATAL_ERROR "error: castxml not found. castxml_EXECUTABLE='${castxml_EXECUTABLE}'") endif() set(castxml_include_args "") foreach(dir ${Mummy_INCLUDE_DIRS} ${VTK_INCLUDE_DIRS}) set(castxml_include_args ${castxml_include_args} "-I${dir}") endforeach() configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/MummySettings.xml.in" "${CMAKE_CURRENT_BINARY_DIR}/xml/MummySettings.xml" @ONLY ) file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/csharp") file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/export-layer") set(theclasslist vtkGDCMImageReader vtkGDCMImageWriter vtkGDCMMedicalImageProperties vtkGDCMPolyDataReader vtkGDCMPolyDataWriter vtkGDCMTesting vtkGDCMThreadedImageReader vtkGDCMThreadedImageReader2 vtkImageColorViewer vtkImageMapToColors16 vtkImageMapToWindowLevelColors2 #vtkImagePlanarComponentsToComponents vtkImageRGBToYBR vtkImageYBRToRGB vtkLookupTable16 vtkRTStructSetProperties ) set(kits gdcm) # foreach kit set(kit gdcm) foreach(class ${theclasslist}) if(NOT VTK_CLASS_WRAP_EXCLUDE_${class}) #set(header "${VTK_${ukit}_HEADER_DIR}/${class}.h") set(header "${CMAKE_CURRENT_SOURCE_DIR}/${class}.h") set(cxxclass "${class}") # handle full paths if("${class}" MATCHES "^(\\/|.\\/|.\\\\|.:\\/|.:\\\\)") set(header "${class}.h") string(REGEX MATCH "[^/]*$" cxxclass "${class}") get_filename_component(dir "${header}" PATH) include_directories("${dir}") endif() set(abstract 0) if(VTK_CLASS_ABSTRACT_${class}) set(abstract 1) set_source_files_properties(${header} PROPERTIES ABSTRACT 1) endif() # Build one master in-memory table so that we don't have to re-do all the # logic in this nested FOREACH loop later on... Instead we'll simply iterate # the in-memory table built here: # set(WRAPPED_CLASS_TABLE ${WRAPPED_CLASS_TABLE} "${cxxclass} ${kit} ${abstract} ${header}") set(include_source_text "") string(REGEX REPLACE "(.*).h" "\\1.cxx" source "${header}") if(EXISTS "${source}") set(include_source_text "#include \"${source}\"") else() #message(FATAL_ERROR "error: Source file '${source}' does not exist...") endif() configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/gccxml.cxx.in" "${CMAKE_CURRENT_BINARY_DIR}/xml/${cxxclass}_gccxml.cxx" @ONLY ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xml/${cxxclass}.xml COMMAND ${castxml_EXECUTABLE} ARGS --castxml-gccxml -o ${CMAKE_CURRENT_BINARY_DIR}/xml/${cxxclass}.xml --castxml-start _cable_ ${castxml_include_args} -DCABLE_CONFIGURATION ${CMAKE_CURRENT_BINARY_DIR}/xml/${cxxclass}_gccxml.cxx # Remove the "Converter" and "Destructor" XML tags that are # generated by "castxml" with a format that is different # from that of "gccxml", and thus that are not properly # understood by "mummy". Removing these tags does not seem # to modify the output of "mummy". COMMAND sed ARGS -i "/^ <\\(Converter\\|Destructor\\) /d" ${CMAKE_CURRENT_BINARY_DIR}/xml/${cxxclass}.xml DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/xml/${cxxclass}_gccxml.cxx ${header} ${gccxml_EXECUTABLE} VERBATIM ) # # *before* custom command re-arranging: # # OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/csharp/${cxxclass}.cs # ${CMAKE_CURRENT_BINARY_DIR}/export-layer/${cxxclass}EL.cxx # # Do not list the *.cs or *EL.cxx files as outputs of this custom command. # If you do, the custom command chains out into other targets rather than # being defined solely in the "generate wrappers" custom target. # # The output of this command is the generated sentinel file that the # "generate wrappers" target depends on. The other files are generated as an # intentional "side effect" and after the target is done building, the other # targets that build the generated source code may build... That is controlled # by target level dependencies to reduce complexity. # add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/csharp/${cxxclass}-sentinel.txt COMMAND ${mummy_EXECUTABLE} --suppress-warnings 6005 6006 6009 6010 6012 6013 6015 6016 6017 6018 6019 --settings-file ${CMAKE_CURRENT_BINARY_DIR}/xml/MummySettings.xml --gccxml-file ${CMAKE_CURRENT_BINARY_DIR}/xml/${cxxclass}.xml --csharp-file ${CMAKE_CURRENT_BINARY_DIR}/csharp/${cxxclass}.cs --export-layer-file ${CMAKE_CURRENT_BINARY_DIR}/export-layer/${cxxclass}EL.cxx COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/csharp/${cxxclass}-sentinel.txt DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/xml/${cxxclass}.xml ${CMAKE_CURRENT_BINARY_DIR}/xml/MummySettings.xml ${mummy_EXECUTABLE} ${${cxxclass}_EXTRA_DEPENDENCIES} ) set(${kit}_EL_SOURCES ${${kit}_EL_SOURCES} "${CMAKE_CURRENT_BINARY_DIR}/export-layer/${cxxclass}EL.cxx") set(ALLKITS_EL_SOURCES ${ALLKITS_EL_SOURCES} "${CMAKE_CURRENT_BINARY_DIR}/export-layer/${cxxclass}EL.cxx") set(${kit}_CS_SOURCES ${${kit}_CS_SOURCES} "${CMAKE_CURRENT_BINARY_DIR}/csharp/${cxxclass}.cs") set(ALLKITS_CS_SOURCES ${ALLKITS_CS_SOURCES} "${CMAKE_CURRENT_BINARY_DIR}/csharp/${cxxclass}.cs") set(${kit}_SENTINELS ${${kit}_SENTINELS} "${CMAKE_CURRENT_BINARY_DIR}/csharp/${cxxclass}-sentinel.txt") set(ALLKITS_SENTINELS ${ALLKITS_SENTINELS} "${CMAKE_CURRENT_BINARY_DIR}/csharp/${cxxclass}-sentinel.txt") endif() endforeach() add_custom_target( "vtk${kit}GenerateWrappers" ALL DEPENDS ${${kit}_SENTINELS} ) set_source_files_properties( ${ALLKITS_EL_SOURCES} ${ALLKITS_CS_SOURCES} PROPERTIES GENERATED 1) if(VTK_BUILD_SHARED_LIBS) set(MV_ONE_EXPORT_LAYER_DLL 0) else() set(MV_ONE_EXPORT_LAYER_DLL 1) endif() if(MV_ONE_EXPORT_LAYER_DLL) message(FATAL_ERROR "Unimplemented") #set(AVDN_INSTALL_TARGETS ${AVDN_INSTALL_TARGETS} "Kitware.VTK.Unmanaged") #add_library(Kitware.VTK.Unmanaged SHARED ${ALLKITS_EL_SOURCES}) #set(unmanaged_targets ${unmanaged_targets} "Kitware.VTK.Unmanaged") #set(unmanaged_dlls ${unmanaged_dlls} "${CMAKE_SHARED_LIBRARY_PREFIX}Kitware.VTK.Unmanaged${CMAKE_SHARED_LIBRARY_SUFFIX}") #if(WIN32) # target_link_libraries(Kitware.VTK.Unmanaged "${exe_dir}/Kitware.mummy.Runtime.Unmanaged.lib") #else() # target_link_libraries(Kitware.VTK.Unmanaged "${exe_dir}/${CMAKE_SHARED_LIBRARY_PREFIX}Kitware.mummy.Runtime.Unmanaged${CMAKE_SHARED_LIBRARY_SUFFIX}") #endif() ## TODO -- rename this CopyLibraries here too... #add_dependencies(Kitware.VTK.Unmanaged Kitware.mummy.CopyLibraries2) #foreach(kit ${kits}) # target_link_libraries(Kitware.VTK.Unmanaged vtk${kit}) # add_dependencies(Kitware.VTK.Unmanaged "vtk${kit}GenerateWrappers") #endforeach() else() include_directories(${Mummy_INCLUDE_DIRS}) foreach(kit ${kits}) set(AVDN_INSTALL_TARGETS ${AVDN_INSTALL_TARGETS} "Kitware.VTK.vtk${kit}.Unmanaged") add_library(Kitware.VTK.vtk${kit}.Unmanaged SHARED ${${kit}_EL_SOURCES}) set(unmanaged_targets ${unmanaged_targets} "Kitware.VTK.vtk${kit}.Unmanaged") set(unmanaged_dlls ${unmanaged_dlls} "${CMAKE_SHARED_LIBRARY_PREFIX}Kitware.VTK.vtk${kit}.Unmanaged${CMAKE_SHARED_LIBRARY_SUFFIX}") if(WIN32) target_link_libraries(Kitware.VTK.vtk${kit}.Unmanaged "${exe_dir}/Kitware.mummy.Runtime.Unmanaged.lib") else() target_link_libraries(Kitware.VTK.vtk${kit}.Unmanaged ${Mummy_RUNTIME_LINK_LIBRARIES}) endif() target_link_libraries(Kitware.VTK.vtk${kit}.Unmanaged vtk${kit}) target_link_libraries(Kitware.VTK.vtk${kit}.Unmanaged vtkCommon) set_property(TARGET Kitware.VTK.vtk${kit}.Unmanaged PROPERTY NO_SONAME 1) # TODO -- rename this CopyLibraries here too... add_dependencies(Kitware.VTK.vtk${kit}.Unmanaged Kitware.mummy.CopyLibraries2) add_dependencies(Kitware.VTK.vtk${kit}.Unmanaged "vtk${kit}GenerateWrappers") endforeach() endif() set(csc_EXECUTABLE ${CMAKE_CSHARP_COMPILER}) # Set list of export-layer dlls in C# syntax as CMake variable # MV_EXPORTLAYER_DLL_VARIABLES. This gets configured into # WrappedObject.cs below. # set(MV_EXPORTLAYER_DLL_VARIABLES "") foreach(kit ${kits}) set(MV_EXPORTLAYER_DLL_VARIABLES "${MV_EXPORTLAYER_DLL_VARIABLES} /// \n") set(MV_EXPORTLAYER_DLL_VARIABLES "${MV_EXPORTLAYER_DLL_VARIABLES} /// Export layer functions for 'vtk${kit}' are exported from\n") set(MV_EXPORTLAYER_DLL_VARIABLES "${MV_EXPORTLAYER_DLL_VARIABLES} /// the DLL named by the value of this variable.\n") set(MV_EXPORTLAYER_DLL_VARIABLES "${MV_EXPORTLAYER_DLL_VARIABLES} /// \n") if(MV_ONE_EXPORT_LAYER_DLL) set(MV_EXPORTLAYER_DLL_VARIABLES "${MV_EXPORTLAYER_DLL_VARIABLES} public const string vtk${kit}EL_dll = \"${CMAKE_SHARED_LIBRARY_PREFIX}Kitware.VTK.Unmanaged${CMAKE_SHARED_LIBRARY_SUFFIX}\";\n") else() set(MV_EXPORTLAYER_DLL_VARIABLES "${MV_EXPORTLAYER_DLL_VARIABLES} public const string vtk${kit}EL_dll = \"${CMAKE_SHARED_LIBRARY_PREFIX}Kitware.VTK.vtk${kit}.Unmanaged${CMAKE_SHARED_LIBRARY_SUFFIX}\";\n") endif() endforeach() set(csharp_namespace "Kitware.VTK.GDCM") configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/AssemblyInfo.cs.in" "${CMAKE_CURRENT_BINARY_DIR}/csharp/AssemblyInfo.cs" @ONLY ) set(ALLKITS_CS_SOURCES ${ALLKITS_CS_SOURCES} "${CMAKE_CURRENT_BINARY_DIR}/csharp/AssemblyInfo.cs" ${CMAKE_CURRENT_SOURCE_DIR}/vtkGDCMImageReader_Extra.cs ) set(AVDN_VTK_CSC_REFS ${ACTIVIZ_KITWARE_VTK_LIBRARY} ${ACTIVIZ_KITWARE_MUMMY_RUNTIME_LIBRARY}) ADD_CSHARP_LIBRARY( "Kitware.VTK.GDCM" # name of library "${unmanaged_targets}" # list of CMake targets that need to build first "${AVDN_VTK_CSC_REFS}" # list of csc "/reference:" args "${unmanaged_dlls}" # list of csc "/linkresource:" args "${AVDN_SNKEYFILE}" # strong name signing keyfile # Source files: ${ALLKITS_CS_SOURCES} ) foreach(kit ${kits}) add_dependencies(Kitware.VTK.GDCM "vtk${kit}GenerateWrappers") endforeach() # add_custom_command( # OUTPUT ${GDCM_LIBRARY_DIR}/vtkgdcm-sharp.dll # COMMAND ${CMAKE_CSHARP_COMPILER} ARGS "/r:${ACTIVIZ_KITWARE_VTK_LIBRARY}" "/r:${ACTIVIZ_KITWARE_MUMMY_RUNTIME_LIBRARY}" "/t:library" "/out:${GDCM_LIBRARY_DIR}/vtkgdcm-sharp.dll" "*.cs" # #COMMAND ${CMAKE_CSHARP_COMPILER} ARGS "/t:library" "/out:${GDCM_LIBRARY_DIR}/vtkgdcm-sharp.dll" "*.cs" # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} # DEPENDS "${swig_generated_file_fullname}" # ${CMAKE_CURRENT_BINARY_DIR}/AssemblyInfo.cs # COMMENT "csc *.cs" # ) install(FILES ${GDCM_LIBRARY_DIR}/Kitware.VTK.GDCM.dll ${GDCM_LIBRARY_DIR}/Kitware.VTK.GDCM.xml DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT VTKCSharpModule ) install(TARGETS Kitware.VTK.vtk${kit}.Unmanaged EXPORT ${GDCM_TARGETS_NAME} RUNTIME DESTINATION ${GDCM_INSTALL_BIN_DIR} COMPONENT VTKLibraries LIBRARY DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT VTKLibraries #${NAMELINK_SKIP} ARCHIVE DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT VTKDebugDevel ) else() configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/AssemblyInfo.cs.in ${CMAKE_CURRENT_BINARY_DIR}/AssemblyInfo.cs @ONLY) add_custom_command( OUTPUT ${GDCM_LIBRARY_DIR}/vtkgdcm-sharp.dll COMMAND ${CMAKE_CSHARP_COMPILER} ARGS "/t:library" "/out:${GDCM_LIBRARY_DIR}/vtkgdcm-sharp.dll" "*.cs" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${SWIG_MODULE_vtkgdcmsharpglue_REAL_NAME} ${CMAKE_CURRENT_BINARY_DIR}/AssemblyInfo.cs COMMENT "csc *.cs" ) add_custom_target(VTKGDCMCSharp ALL DEPENDS ${GDCM_LIBRARY_DIR}/vtkgdcm-sharp.dll #${GDCM_LIBRARY_DIR}/vtkgdcm-sharp.dll.config #${GDCM_EXECUTABLE_DIR}/HelloWorld.exe COMMENT "building vtkgdcm-sharp.dll" ) # because vtkgdcm-sharp.dll is constructed with custom commands, it need the install(FILES signature: set(GDCM_LIBRARY_DIR2 ${LIBRARY_OUTPUT_PATH}/\${BUILD_TYPE}) install(FILES ${GDCM_LIBRARY_DIR2}/vtkgdcm-sharp.dll #${GDCM_LIBRARY_DIR2}/vtkgdcm-sharp.dll.config DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT VTKCSharpModule ) endif() #add_custom_command( # OUTPUT ${GDCM_LIBRARY_DIR}/vtkgdcm-sharp.dll.config # COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/vtkgdcm-sharp.dll.config ${GDCM_LIBRARY_DIR} # DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/vtkgdcm-sharp.dll.config # COMMENT "Copying vtkgdcm-sharp.dll.config" #) endif() if( (GDCM_WRAP_JAVA AND VTK_WRAP_JAVA) OR (GDCM_WRAP_PYTHON AND VTK_WRAP_PYTHON) ) if( ${VTK_MAJOR_VERSION} GREATER 7 ) set(MODULE_HIERARCHY_NAME ${VTKGDCM_NAME}Hierarchy) set(${VTKGDCM_NAME}_WRAP_DEPENDS ${vtkgdcm_LIBS}) include(vtkWrapHierarchy) vtk_wrap_hierarchy(${VTKGDCM_NAME} ${CMAKE_CURRENT_BINARY_DIR} "${vtkgdcm_SRCS}") set(KIT_HIERARCHY_FILE ${CMAKE_CURRENT_BINARY_DIR}/${MODULE_HIERARCHY_NAME}.txt) set(LIB_HIERARCHY_STAMP ${CMAKE_CURRENT_BINARY_DIR}/${MODULE_HIERARCHY_NAME}.stamp.txt) endif() endif() if(GDCM_WRAP_JAVA) if(VTK_WRAP_JAVA) find_package(Java ${GDCM_DEFAULT_JAVA_VERSION} REQUIRED) # javac, jar find_package(JNI REQUIRED) include_directories(${JNI_INCLUDE_DIRS}) set(VTK_WRAP_JAVA3_INIT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") # Lars Matthaus patch (package vtk => imply vtk subdir ) set(VTK_JAVA_HOME ${CMAKE_CURRENT_BINARY_DIR}/java/vtk) # This is *required* don't ask file(MAKE_DIRECTORY ${VTK_JAVA_HOME}) include(${VTK_CMAKE_DIR}/vtkWrapJava.cmake) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) # libvtk-java is a pain to handle... if(EXISTS ${VTK_JAVA_JAR}) # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=533193 set(GDCM_VTK_JAVA_JAR ${VTK_JAVA_JAR}) else() # http://bugs.debian.org/834493 find_file(VTK_JAVA_JAR NAMES vtk.jar vtk6.jar vtk5.jar PATHS ${vtkWrappingJava_RUNTIME_LIBRARY_DIRS} /usr/share/java) set(GDCM_VTK_JAVA_JAR ${VTK_JAVA_JAR}) endif() if(EXISTS /usr/lib/jni/libvtkCommonJava.so) # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=533198 message(STATUS "Implicitely adding debian package layout...") link_directories("/usr/lib/jni") endif() mark_as_advanced(GDCM_VTK_JAVA_JAR) if(EXISTS ${GDCM_VTK_JAVA_JAR}) VTK_WRAP_JAVA3(${VTKGDCM_NAME}Java vtkgdcmJAVA_SRCS "${vtkgdcm_SRCS}") add_library(${VTKGDCM_NAME}Java SHARED ${vtkgdcmJAVA_SRCS}) # special jnilib extension: if(APPLE) set_target_properties(${VTKGDCM_NAME}Java PROPERTIES SUFFIX ".jnilib") endif() target_link_libraries(${VTKGDCM_NAME}Java LINK_PRIVATE ${VTKGDCM_NAME}) set_property(TARGET ${VTKGDCM_NAME}Java PROPERTY NO_SONAME 1) # By default link those module since APPLE and WIN32 needs fully resolved # shared lib allow advanced users to skip the link step: if(NOT GDCM_NO_VTKJAVA_LIBS_LINKING) foreach(c ${vtkgdcm_LIBS}) target_link_libraries(${VTKGDCM_NAME}Java LINK_PRIVATE ${c}Java) endforeach() endif() # Create the jar file: # I am pretty sure this *.java thingy will bite me one day, when someone will try # to recompile from an existing build tree with invalid generated *.java file... set(jflags $ENV{JFLAGS}) add_custom_command( OUTPUT ${LIBRARY_OUTPUT_PATH}/vtkgdcm.jar #COMMAND ${Java_JAVAC_EXECUTABLE} ARGS -cp ${GDCM_VTK_JAVA_JAR} "vtk/*.java" # No such thing as -cp for javac only java is listed: # http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/classpath.html COMMAND ${Java_JAVAC_EXECUTABLE} ARGS ${jflags} -source ${GDCM_JAVA_SOURCE_VERSION} -target ${GDCM_JAVA_TARGET_VERSION} -classpath ${GDCM_VTK_JAVA_JAR} -d . "vtk/*.java" COMMAND ${Java_JAR_EXECUTABLE} ARGS -cvfm ${LIBRARY_OUTPUT_PATH}/${PROJECT_NAME}.jar ${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt vtk/*.class WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/java DEPENDS ${VTKGDCM_NAME}Java #${VTK_JAVA_DEPENDENCIES} #vtkgdcmJavaJavaClasses COMMENT "javac *.java -> jar; jar cvf -> vtkgdcm.jar" ) # Target to execute custom command: add_custom_target(VTKGDCMJavaJar ALL DEPENDS ${LIBRARY_OUTPUT_PATH}/vtkgdcm.jar COMMENT "building vtkgdcm.jar" ) add_dependencies(VTKGDCMJavaJar vtkgdcmJavaJavaClasses) # Install rules: if(NOT GDCM_INSTALL_NO_LIBRARIES) install(TARGETS ${VTKGDCM_NAME}Java EXPORT ${GDCM_TARGETS_NAME} RUNTIME DESTINATION ${GDCM_VTK_INSTALL_JAVAMODULE_DIR} COMPONENT VTKJavaModule LIBRARY DESTINATION ${GDCM_VTK_INSTALL_JAVAMODULE_DIR} COMPONENT VTKJavaModule ) #DebugDevel #if(NAMELINK_ONLY) # install(TARGETS ${VTKGDCM_NAME}Java # LIBRARY DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT VTKJavaModule ${NAMELINK_ONLY} # ) #endif() # because vtkgdcm.jar is constructed with custom commands, it need the # install(FILES signature: install(FILES ${LIBRARY_OUTPUT_PATH}/vtkgdcm.jar DESTINATION ${GDCM_VTK_INSTALL_JARMODULE_DIR} COMPONENT VTKJavaModule ) endif() else() message(WARNING "Could not find vtk.jar file, VTK_JAVA_JAR is wrong: ${VTK_JAVA_JAR}, please set proper GDCM_VTK_JAVA_JAR: ${GDCM_VTK_JAVA_JAR} replacement var") endif() else() message(STATUS "GDCM_WRAP_JAVA canot be build without VTK_WRAP_JAVA") endif() endif() if(GDCM_WRAP_PYTHON) if(VTK_WRAP_PYTHON) set(DEXTENSION "") if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" LESS 4.5 ) VTK_WRAP_PYTHON2(${VTKGDCM_NAME}Python vtkgdcmPYTHON_SRCS ${vtkgdcm_SRCS}) else() include(${VTK_CMAKE_DIR}/vtkWrapPython.cmake) include_directories( ${PYTHON_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ) VTK_WRAP_PYTHON3(${VTKGDCM_NAME}Python vtkgdcmPYTHON_SRCS "${vtkgdcm_SRCS}") set(DEXTENSION "D") endif() add_library(${VTKGDCM_NAME}PythonD ${vtkgdcmPYTHON_SRCS}) # this is a library set the version: # do not set the version on the Python module: set_target_properties(${VTKGDCM_NAME}PythonD PROPERTIES ${GDCM_LIBRARY_PROPERTIES}) add_library(${VTKGDCM_NAME}Python MODULE ${VTKGDCM_NAME}PythonInit.cxx) # do not set the version on the Python module: #set_target_properties(${VTKGDCM_NAME}Python PROPERTIES ${GDCM_LIBRARY_PROPERTIES}) target_link_libraries(${VTKGDCM_NAME}PythonD LINK_PRIVATE ${VTKGDCM_NAME} ${PYTHON_LIBRARY}) foreach(c ${vtkgdcm_LIBS}) target_link_libraries(${VTKGDCM_NAME}PythonD LINK_PRIVATE ${c}Python${DEXTENSION}) endforeach() if(TARGET vtkPythonCore) target_link_libraries(${VTKGDCM_NAME}PythonD LINK_PRIVATE vtkPythonCore) endif() target_link_libraries(${VTKGDCM_NAME}Python LINK_PRIVATE ${VTKGDCM_NAME}PythonD) if(NOT GDCM_NO_PYTHON_LIBS_LINKING) target_link_libraries(${VTKGDCM_NAME}Python LINK_PRIVATE ${PYTHON_LIBRARY}) endif() set_property(TARGET ${VTKGDCM_NAME}Python PROPERTY NO_SONAME 1) #set_property(TARGET ${VTKGDCM_NAME}PythonD PROPERTY NO_SONAME 1) # Removing lib prefix if we are at VTK7. Based on a reply by David Gobbi to # this Thread # http://vtk.1045678.n5.nabble.com/python-wrapping-with-VTK-7-td5737442.html if( "${VTK_MAJOR_VERSION}" GREATER 6 ) set_target_properties(${VTKGDCM_NAME}Python PROPERTIES PREFIX "") endif() # Python extension modules on Windows must have the extension ".pyd" # instead of ".dll" as of Python 2.5. Older python versions do support # this suffix. if(WIN32 AND NOT CYGWIN) set_target_properties(${VTKGDCM_NAME}Python PROPERTIES SUFFIX ".pyd") endif() add_custom_command( TARGET ${VTKGDCM_NAME}Python POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/vtkgdcm.py ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/ DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/vtkgdcm.py" COMMENT "Copy vtkgdcm.py into ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/" ) if(NOT GDCM_INSTALL_NO_LIBRARIES) install(TARGETS ${VTKGDCM_NAME}Python EXPORT ${GDCM_TARGETS_NAME} RUNTIME DESTINATION ${GDCM_VTK_INSTALL_PYTHONMODULE_DIR} COMPONENT VTKPythonModule LIBRARY DESTINATION ${GDCM_VTK_INSTALL_PYTHONMODULE_DIR} COMPONENT VTKPythonModule #${NAMELINK_SKIP} ) install(TARGETS ${VTKGDCM_NAME}PythonD EXPORT ${GDCM_TARGETS_NAME} RUNTIME DESTINATION ${GDCM_INSTALL_BIN_DIR} COMPONENT VTKPythonModule LIBRARY DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT VTKPythonModule #${NAMELINK_ONLY} ) # the python file is not a dev file, but part of the gdcm module... install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/vtkgdcm.py DESTINATION ${GDCM_VTK_INSTALL_PYTHONMODULE_DIR} COMPONENT VTKPythonModule ) endif() else() message(STATUS "GDCM_WRAP_PYTHON canot be build without VTK_WRAP_PYTHON") endif() endif() if(BUILD_TESTING) add_subdirectory(Testing) endif() if(BUILD_APPLICATIONS) add_subdirectory(Applications) endif() if(BUILD_EXAMPLES) add_subdirectory(Examples) endif() if(GDCM_USE_PARAVIEW) # http://www.cmake.org/Wiki/Plugin_HowTo#Adding_a_Reader find_package(ParaView REQUIRED) include(${PARAVIEW_USE_FILE}) ADD_PARAVIEW_PLUGIN(GDCMImageReader "1.0" SERVER_MANAGER_SOURCES vtkGDCMImageReader.cxx SERVER_MANAGER_XML GDCMImageReader.xml GUI_RESOURCE_FILES GDCMImageGUI.xml) target_link_libraries(GDCMImageReader ${VTKGDCM_NAME}) install(TARGETS GDCMImageReader EXPORT ${GDCM_TARGETS_NAME} RUNTIME DESTINATION ${GDCM_INSTALL_BIN_DIR} COMPONENT ParaViewModule LIBRARY DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT ParaViewModule ARCHIVE DESTINATION ${GDCM_INSTALL_LIB_DIR} COMPONENT ParaViewModule ) endif() GDCM-3.0.10/Utilities/VTK/CscArgs.txt.in000066400000000000000000000000121412732066400174150ustar00rootroot00000000000000@CscArgs@ GDCM-3.0.10/Utilities/VTK/Examples/000077500000000000000000000000001412732066400165075ustar00rootroot00000000000000GDCM-3.0.10/Utilities/VTK/Examples/CMakeLists.txt000066400000000000000000000003641412732066400212520ustar00rootroot00000000000000#add_subdirectory(Cxx Python) add_subdirectory(Cxx) if(GDCM_WRAP_CSHARP) add_subdirectory(Csharp) endif() if(GDCM_WRAP_JAVA) if(VTK_WRAP_JAVA) if(EXISTS ${GDCM_VTK_JAVA_JAR}) add_subdirectory(Java) endif() endif() endif() GDCM-3.0.10/Utilities/VTK/Examples/Csharp/000077500000000000000000000000001412732066400177275ustar00rootroot00000000000000GDCM-3.0.10/Utilities/VTK/Examples/Csharp/CMakeLists.txt000066400000000000000000000044361412732066400224760ustar00rootroot00000000000000set(DEP) if(GDCM_USE_ACTIVIZ) set(examples #HelloActiviz HelloActiviz2 HelloActiviz3 HelloActiviz4 HelloActiviz5 RefCounting MetaImageMD5Activiz ) foreach(example ${examples}) file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${example}.cs result) add_custom_command( OUTPUT ${GDCM_EXECUTABLE_DIR}/${example}.exe COMMAND ${CMAKE_CSHARP_COMPILER} ARGS "/r:${ACTIVIZ_KITWARE_VTK_LIBRARY}" "/r:${ACTIVIZ_KITWARE_MUMMY_RUNTIME_LIBRARY}" "/r:${GDCM_LIBRARY_DIR}/Kitware.VTK.GDCM.dll" "/r:${GDCM_LIBRARY_DIR}/gdcm-sharp.dll" "/out:${GDCM_EXECUTABLE_DIR}/${example}.exe" ${result} DEPENDS ${GDCM_LIBRARY_DIR}/Kitware.VTK.GDCM.dll ${CMAKE_CURRENT_SOURCE_DIR}/${example}.cs COMMENT "Create ${example}.exe" ) set(DEP ${DEP} ${GDCM_EXECUTABLE_DIR}/${example}.exe) endforeach() if(BUILD_TESTING) get_filename_component(runtimepath ${ACTIVIZ_KITWARE_VTK_LIBRARY} PATH) if(GDCM_DATA_ROOT) set_source_files_properties(${GDCM_EXECUTABLE_DIR}/HelloActiviz5.exe PROPERTIES RUNTIMEPATH ${runtimepath}) ADD_CSHARP_TEST(TestHelloActiviz5CSharp ${GDCM_EXECUTABLE_DIR}/HelloActiviz5.exe) endif() set_source_files_properties(${GDCM_EXECUTABLE_DIR}/RefCounting.exe PROPERTIES RUNTIMEPATH ${runtimepath}) ADD_CSHARP_TEST(TestRefCountingCSharp ${GDCM_EXECUTABLE_DIR}/RefCounting.exe) endif() else() set(CSHARP_EXAMPLES HelloVTKWorld HelloVTKWorld2 ) foreach(example ${CSHARP_EXAMPLES}) file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${example}.cs result) # WORKING_DIRECTORY is set to the src dir because of a strange issue with CSC compiler on Win32 system: # http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/browse_thread/thread/9d3ac7eb9f7f56be add_custom_command( OUTPUT ${GDCM_EXECUTABLE_DIR}/${example}.exe COMMAND ${CMAKE_CSHARP_COMPILER} ARGS "/r:${GDCM_LIBRARY_DIR}/vtkgdcm-sharp.dll" "/out:${GDCM_EXECUTABLE_DIR}/${example}.exe" ${result} DEPENDS ${GDCM_LIBRARY_DIR}/vtkgdcm-sharp.dll ${CMAKE_CURRENT_SOURCE_DIR}/${example}.cs COMMENT "Create ${example}.exe" ) set(DEP ${DEP} ${GDCM_EXECUTABLE_DIR}/${example}.exe) endforeach() endif() add_custom_target(VTKGDCMExampleCSharp ALL DEPENDS ${DEP} COMMENT "building examples" ) GDCM-3.0.10/Utilities/VTK/Examples/Csharp/HelloActiviz.cs000066400000000000000000000104541412732066400226570ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ using vtkgdcm; using Kitware.VTK; using System; using System.Runtime.InteropServices; /* * This example shows how vtkgdcm can be connected to Kitware.VTK Activiz product. * Three (3) arguments are required: * 1. Input DICOM file (SWIG) * 2. Temporary PNG (intermediate) file (Activiz) * 3. Final DICOM file (SWIG) * * $ export MONO_PATH=/usr/lib/cli/ActiViz.NET/:/usr/lib/cli/Kitware.mummy.Runtime-1.0 * $ mono ./bin/HelloActiviz.exe ~/Creatis/gdcmData/test.acr out.png toto.dcm * * Footnote: * this test originally used vtkBMPWriter / vtkBMPReader combination to store intermediate * image file, but BMP file are 24bits by default. Instead use PNG format which supports seems * to be closer to what was expected in this simple test. */ public class HelloActiviz { // Does not work with ActiViz.NET-5.4.0.455-Linux-x86_64-Personal /* static void ConnectSWIGToActiviz(Kitware.VTK.vtkImageExport imgin, Kitware.VTK.vtkImageImport imgout) { imgout.SetUpdateInformationCallback(imgin.GetUpdateInformationCallback()); imgout.SetPipelineModifiedCallback(imgin.GetPipelineModifiedCallback()); imgout.SetWholeExtentCallback(imgin.GetWholeExtentCallback()); imgout.SetSpacingCallback(imgin.GetSpacingCallback()); imgout.SetOriginCallback(imgin.GetOriginCallback()); imgout.SetScalarTypeCallback(imgin.GetScalarTypeCallback()); imgout.SetNumberOfComponentsCallback(imgin.GetNumberOfComponentsCallback()); imgout.SetPropagateUpdateExtentCallback(imgin.GetPropagateUpdateExtentCallback()); imgout.SetUpdateDataCallback(imgin.GetUpdateDataCallback()); imgout.SetDataExtentCallback(imgin.GetDataExtentCallback()); imgout.SetBufferPointerCallback(imgin.GetBufferPointerCallback()); imgout.SetCallbackUserData(imgin.GetCallbackUserData()); } */ static Kitware.VTK.vtkImageData ConnectSWIGToActiviz(vtkgdcm.vtkImageData imgin) { HandleRef rawCppThis = imgin.GetCppThis(); Kitware.VTK.vtkImageData imgout = new Kitware.VTK.vtkImageData( rawCppThis.Handle, false, false); return imgout; } static vtkgdcm.vtkImageData ConnectActivizToSWIG(Kitware.VTK.vtkImageData imgin) { HandleRef rawCppThis = imgin.GetCppThis(); vtkgdcm.vtkImageData imgout = new vtkgdcm.vtkImageData( rawCppThis ); return imgout; } public static int Main(string[] args) { string filename = args[0]; string outfilename = args[1]; // Step 1. Test SWIG -> Activiz vtkGDCMImageReader reader = vtkGDCMImageReader.New(); reader.SetFileName( filename ); //reader.Update(); // DO NOT call Update to check pipeline execution Kitware.VTK.vtkImageData imgout = ConnectSWIGToActiviz(reader.GetOutput()); System.Console.WriteLine( imgout.ToString() ); // not initialized as expected vtkPNGWriter writer = new vtkPNGWriter(); writer.SetInput( imgout ); writer.SetFileName( outfilename ); writer.Write(); // Step 2. Test Activiz -> SWIG vtkPNGReader bmpreader = new vtkPNGReader(); bmpreader.SetFileName( outfilename ); //bmpreader.Update(); // DO NOT update to check pipeline execution System.Console.WriteLine( bmpreader.GetOutput().ToString() ); // not initialized as expected vtkgdcm.vtkImageData imgout2 = ConnectActivizToSWIG(bmpreader.GetOutput()); System.Console.WriteLine( imgout2.ToString() ); // not initialized as expected Kitware.VTK.vtkMedicalImageProperties prop = new Kitware.VTK.vtkMedicalImageProperties(); prop.SetModality( "MR" ); string outfilename2 = args[2]; vtkGDCMImageWriter writer2 = vtkGDCMImageWriter.New(); writer2.SetMedicalImageProperties( prop.CastToActiviz() ); writer2.SetFileName( outfilename2 ); writer2.SetInput( imgout2 ); writer2.Write(); return 0; } } GDCM-3.0.10/Utilities/VTK/Examples/Csharp/HelloActiviz2.cs000066400000000000000000000060471412732066400227440ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ using Kitware.VTK; using Kitware.VTK.GDCM; /* * Usage: * $ export MONO_PATH=/usr/lib/cli/ActiViz.NET/:/usr/lib/cli/Kitware.mummy.Runtime-1.0 * $ mono ./bin/HelloActiviz2.exe gdcmData/test.acr bla.png bla2.dcm */ /* * From the outside view, no-one can detect that object pass to/from * vtkGDCMImageWriter/vtkGDCMImageReader are not Activiz object. * * TODO: Test Command/Observer */ public class HelloActiviz2 { public static int Main(string[] args) { string filename = args[0]; string outfilename = args[1]; string outfilename2 = args[2]; vtkGDCMImageReader reader = new Kitware.VTK.GDCM.vtkGDCMImageReader(); reader.SetFileName( filename ); // When calling multiple times creation of C# object from the same C++ object it triggers a: //error: potential refcounting error: Duplicate rawCppThis - weak reference that is still alive. Attempting to add '0x00b2dc10' again. // Allowing new wrapped object to take over table key... // Original object should *not* have been destroyed while we still had it in our table without notifying us... //reader.GetOutput(); //reader.GetOutput(); System.Console.WriteLine( reader.ToString() ); // Test the ToString compat with Activiz vtkGDCMImageWriter writer = new vtkGDCMImageWriter(); writer.SetInput( reader.GetOutput() ); writer.SetFileName( outfilename2 ); writer.Write(); System.Console.WriteLine( reader.GetOutput().ToString() ); // Test the ToString compat with Activiz System.Console.WriteLine( writer.ToString() ); // Test the ToString compat with Activiz vtkPNGWriter pngwriter = new vtkPNGWriter(); pngwriter.SetInput( reader.GetOutput() ); pngwriter.SetFileName( outfilename ); pngwriter.Write(); // at that point the .Write() should have triggered an Update() on the reader: if( reader.GetImageFormat() == vtkgdcm.VTK_LUMINANCE ) // MONOCHROME2 { System.Console.WriteLine( "Image is MONOCHROME2" ); // } vtkPNGReader bmpreader = new vtkPNGReader(); bmpreader.SetFileName( outfilename ); vtkMedicalImageProperties prop = new vtkMedicalImageProperties(); prop.SetModality( "MR" ); vtkMatrix4x4 dircos = reader.GetDirectionCosines(); dircos.Invert(); vtkGDCMImageWriter writer2 = new vtkGDCMImageWriter(); writer2.SetFileName( outfilename2 ); writer2.SetDirectionCosines( dircos ); writer2.SetMedicalImageProperties( prop ); writer2.SetInput( bmpreader.GetOutput() ); writer2.Write(); return 0; } } GDCM-3.0.10/Utilities/VTK/Examples/Csharp/HelloActiviz3.cs000066400000000000000000000026311412732066400227400ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ using Kitware.VTK; using Kitware.VTK.GDCM; /* * $ export MONO_PATH=/usr/lib/cli/ActiViz.NET/:/usr/lib/cli/Kitware.mummy.Runtime-1.0 * $ mono ./bin/HelloActiviz3.exe ~/Creatis/gdcmData/test.acr */ public class HelloActiviz3 { public static int Main(string[] args) { string filename = args[0]; vtkGDCMImageReader reader = vtkGDCMImageReader.New(); vtkStringArray array = vtkStringArray.New(); array.InsertNextValue(filename); reader.SetFileNames(array); reader.Update(); //System.Console.Write(reader.GetOutput()); vtkRenderWindowInteractor iren = vtkRenderWindowInteractor.New(); vtkImageViewer2 viewer = vtkImageViewer2.New(); viewer.SetInput(reader.GetOutput()); viewer.SetupInteractor(iren); viewer.SetSize(600, 600); viewer.Render(); iren.Initialize(); iren.Start(); return 0; } } GDCM-3.0.10/Utilities/VTK/Examples/Csharp/HelloActiviz4.cs000066400000000000000000000026271412732066400227460ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ using Kitware.VTK; using Kitware.VTK.GDCM; /* * $ export MONO_PATH=/usr/lib/cli/ActiViz.NET/:/usr/lib/cli/Kitware.mummy.Runtime-1.0 * $ mono ./bin/HelloActiviz4.exe ~/Creatis/gdcmData/test.acr */ public class HelloActiviz4 { public static int Main(string[] args) { string filename = args[0]; vtkGDCMImageReader reader = new vtkGDCMImageReader(); vtkStringArray array = vtkStringArray.New(); array.InsertNextValue(filename); reader.SetFileNames(array); reader.Update(); //System.Console.Write(reader.GetOutput()); vtkRenderWindowInteractor iren = vtkRenderWindowInteractor.New(); vtkImageViewer viewer = vtkImageViewer.New(); viewer.SetInput(reader.GetOutput()); viewer.SetupInteractor(iren); viewer.SetSize(600, 600); viewer.Render(); iren.Initialize(); iren.Start(); return 0; } } GDCM-3.0.10/Utilities/VTK/Examples/Csharp/HelloActiviz5.cs000066400000000000000000000057651412732066400227550ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ using Kitware.VTK; using Kitware.VTK.GDCM; // The command line arguments are: // -I => run in interactive mode; unless this is used, the program will // not allow interaction and exit // -D => path to the data; the data should be in /Data/ /* * $ export MONO_PATH=/usr/lib/cli/ActiViz.NET/:/usr/lib/cli/Kitware.mummy.Runtime-1.0 * $ mono ./bin/HelloActiviz5.exe -I */ public class HelloActiviz5 { public static int Main(string[] args) { vtkTesting testHelper = vtkTesting.New(); for ( int cc = 0; cc < args.Length; cc++ ) { //testHelper.AddArguments(argc,const_cast(argv)); //System.Console.Write( "args: " + args[cc] + "\n" ); testHelper.AddArgument( args[cc] ); } if ( testHelper.IsFlagSpecified("-D") != 0 ) { string VTK_DATA_ROOT = vtkGDCMTesting.GetVTKDataRoot(); if( VTK_DATA_ROOT != null ) { //System.Console.Write( "VTK_DATA_ROOT: " + VTK_DATA_ROOT + "\n" ); testHelper.SetDataRoot(VTK_DATA_ROOT); testHelper.AddArgument("-D"); testHelper.AddArgument(VTK_DATA_ROOT); } } string dataRoot = testHelper.GetDataRoot(); string filename = dataRoot; filename += "/Data/mr.001"; vtkDirectory dir = vtkDirectory.New(); if( dir.FileIsDirectory( dataRoot ) == 0 ) { filename = vtkGDCMTesting.GetGDCMDataRoot() + "/test.acr"; } //System.Console.Write( "dataRoot: " + dataRoot + "\n" ); System.Console.Write( "filename being used is: " + filename + "\n" ); vtkGDCMImageReader reader = vtkGDCMImageReader.New(); vtkStringArray array = vtkStringArray.New(); array.InsertNextValue(filename); reader.SetFileNames(array); reader.Update(); System.Console.Write(reader.GetOutput()); vtkRenderWindowInteractor iren = vtkRenderWindowInteractor.New(); vtkRenderer ren1 = vtkRenderer.New(); vtkRenderWindow renWin = vtkRenderWindow.New(); renWin.AddRenderer(ren1); vtkImageActor actor = vtkImageActor.New(); vtkImageMapToWindowLevelColors coronalColors = vtkImageMapToWindowLevelColors.New(); coronalColors.SetInput(reader.GetOutput()); actor.SetInput(coronalColors.GetOutput()); ren1.AddActor(actor); iren.SetRenderWindow(renWin); iren.Initialize(); renWin.Render(); int retVal = testHelper.IsInteractiveModeSpecified(); if( retVal != 0 ) { iren.Start(); } return 0; } } GDCM-3.0.10/Utilities/VTK/Examples/Csharp/HelloVTKWorld.cs000066400000000000000000000034231412732066400227200ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ using vtkgdcm; /* * This test only test the SWIG/VTK part, you do not need Activiz */ public class HelloVTKWorld { public static int Main(string[] args) { string filename = args[0]; vtkGDCMImageReader reader = vtkGDCMImageReader.New(); reader.SetFileName( filename ); reader.Update(); vtkMedicalImageProperties prop = reader.GetMedicalImageProperties(); System.Console.WriteLine( prop.GetPatientName() ); // if( reader.GetImageFormat() == vtkgdcm.vtkgdcm.VTK_LUMINANCE ) // MONOCHROME2 { System.Console.WriteLine( "Image is MONOCHROME2" ); // } // Just for fun, invert the direction cosines, output should reflect that: vtkMatrix4x4 dircos = reader.GetDirectionCosines(); dircos.Invert(); string outfilename = args[1]; vtkGDCMImageWriter writer = vtkGDCMImageWriter.New(); writer.SetMedicalImageProperties( reader.GetMedicalImageProperties() ); writer.SetDirectionCosines( dircos ); writer.SetShift( reader.GetShift() ); writer.SetScale( reader.GetScale() ); writer.SetImageFormat( reader.GetImageFormat() ); writer.SetFileName( outfilename ); writer.SetInputConnection( reader.GetOutputPort() ); writer.Write(); return 0; } } GDCM-3.0.10/Utilities/VTK/Examples/Csharp/HelloVTKWorld2.cs000066400000000000000000000032201412732066400227750ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ using vtkgdcm; /* * This test only test the SWIG/VTK part, you do not need Activiz */ public class HelloVTKWorld2 { public static int Main(string[] args) { string VTK_DATA_ROOT = vtkGDCMTesting.GetVTKDataRoot(); vtkVolume16Reader reader = vtkVolume16Reader.New(); reader.SetDataDimensions(64, 64); reader.SetDataByteOrderToLittleEndian(); reader.SetFilePrefix(VTK_DATA_ROOT + "/Data/headsq/quarter"); reader.SetImageRange(1, 93); reader.SetDataSpacing(3.2, 3.2, 1.5); vtkImageCast cast = vtkImageCast.New(); cast.SetInputConnection( reader.GetOutputPort() ); cast.SetOutputScalarTypeToUnsignedChar(); // By default this is creating a Multiframe Grayscale Word Secondary Capture Image Storage vtkGDCMImageWriter writer = vtkGDCMImageWriter.New(); writer.SetFileName( "headsq.dcm" ); writer.SetInputConnection( reader.GetOutputPort() ); // cast -> Multiframe Grayscale Byte Secondary Capture Image Storage // writer.SetInputConnection( cast.GetOutputPort() ); writer.SetFileDimensionality( 3 ); writer.Write(); return 0; } } GDCM-3.0.10/Utilities/VTK/Examples/Csharp/MetaImageMD5Activiz.cs000066400000000000000000000065361412732066400237610ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ using Kitware.VTK; using Kitware.VTK.GDCM; using gdcm; /* * $ export MONO_PATH=/usr/lib/cli/ActiViz.NET/:/usr/lib/cli/Kitware.mummy.Runtime-1.0 * $ mono ./bin/MetaImageMD5Activiz.exe gdcmData/012345.002.050.dcm */ public class MetaImageMD5Activiz { public static int ProcessOneMHDMD5(string filename) { vtkGDCMImageReader reader = vtkGDCMImageReader.New(); reader.FileLowerLeftOn(); reader.DebugOff(); int canread = reader.CanReadFile( filename ); if( canread == 0 ) { string refms = gdcm.Testing.GetMediaStorageFromFile(filename); if( gdcm.MediaStorage.IsImage( gdcm.MediaStorage.GetMSType(refms) ) ) { System.Console.Write( "Problem with file: " + filename + "\n" ); return 1; } // not an image return 0; } reader.SetFileName( filename ); reader.Update(); // System.Console.Write(reader.GetOutput()); vtkMetaImageWriter writer = vtkMetaImageWriter.New(); writer.SetCompression( false ); writer.SetInput( reader.GetOutput() ); string subdir = "MetaImageMD5Activiz"; string tmpdir = gdcm.Testing.GetTempDirectory( subdir ); if( !gdcm.PosixEmulation.FileIsDirectory( tmpdir ) ) { gdcm.PosixEmulation.MakeDirectory( tmpdir ); } string mhdfile = gdcm.Testing.GetTempFilename( filename, subdir ); string rawfile = mhdfile; mhdfile += ".mhd"; rawfile += ".raw"; writer.SetFileName( mhdfile ); writer.Write(); string digestmhd = gdcm.Testing.ComputeFileMD5( mhdfile ); string digestraw = gdcm.Testing.ComputeFileMD5( rawfile ); string mhdref = vtkGDCMTesting.GetMHDMD5FromFile(filename); string rawref = vtkGDCMTesting.GetRAWMD5FromFile(filename); if( mhdref != digestmhd ) { System.Console.Write( "Problem with mhd file: " + filename + "\n" ); System.Console.Write( digestmhd ); System.Console.Write( "\n" ); System.Console.Write( mhdref ); System.Console.Write( "\n" ); return 1; } if( rawref != digestraw ) { System.Console.Write( "Problem with raw file: " + filename + "\n" ); System.Console.Write( digestraw ); System.Console.Write( "\n" ); System.Console.Write( rawref ); System.Console.Write( "\n" ); return 1; } return 0; } public static int Main(string[] args) { if ( args.Length == 1 ) { string filename = args[0]; return ProcessOneMHDMD5( filename ); } // Loop over all gdcmData gdcm.Trace.DebugOff(); gdcm.Trace.WarningOff(); gdcm.Trace.ErrorOff(); uint n = gdcm.Testing.GetNumberOfFileNames(); int ret = 0; for( uint i = 0; i < n; ++i ) { string filename = gdcm.Testing.GetFileName( i ); ret += ProcessOneMHDMD5( filename ); } return ret; } } GDCM-3.0.10/Utilities/VTK/Examples/Csharp/RefCounting.cs000066400000000000000000000037401412732066400225050ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ using Kitware.VTK; using Kitware.VTK.GDCM; /* * this is not so much an example but simply a test to make sure cstor / dstor work as expected * and call the ::New and ->Delete() of VTK style. */ public class RefCounting { public static int Main(string[] args) { vtkGDCMTesting testing1 = vtkGDCMTesting.New(); vtkGDCMTesting testing2 = new vtkGDCMTesting(); // just in case people do not read STYLE documentation vtkGDCMImageReader reader1 = vtkGDCMImageReader.New(); vtkGDCMImageReader reader2 = new vtkGDCMImageReader(); vtkGDCMImageWriter writer1 = vtkGDCMImageWriter.New(); vtkGDCMImageWriter writer2 = new vtkGDCMImageWriter(); using (vtkGDCMTesting testing3 = new vtkGDCMTesting()) { System.Console.Write( "GetReferenceCount: " + testing1.GetReferenceCount() + "\n"); System.Console.Write( "GetReferenceCount: " + testing2.GetReferenceCount() + "\n"); System.Console.Write( "GetReferenceCount: " + testing3.GetReferenceCount() + "\n"); } using (vtkGDCMImageReader reader3 = new vtkGDCMImageReader()) { System.Console.Write( "GetReferenceCount: " + reader3.GetReferenceCount() + "\n"); } using (vtkGDCMImageWriter writer3 = vtkGDCMImageWriter.New()) { System.Console.Write( "GetReferenceCount: " + writer3.GetReferenceCount() + "\n"); } // C# destructor will call ->Delete on all C++ object as expected. return 0; } } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/000077500000000000000000000000001412732066400172515ustar00rootroot00000000000000GDCM-3.0.10/Utilities/VTK/Examples/Cxx/CMakeLists.txt000066400000000000000000000042361412732066400220160ustar00rootroot00000000000000include_directories( ${GDCM_SOURCE_DIR}/Utilities/VTK ) if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" GREATER 5.0 ) set(GDCM_VTK_APPS CreateFakeRTDOSE CreateFakePET ConvertSingleBitTo8Bits GenerateRTSTRUCT offscreenimage ) if( ${VTK_MAJOR_VERSION} GREATER 5 ) set(GDCM_VTK_APPS ${GDCM_VTK_APPS} Compute3DSpacing ) endif() if(VTK_USE_RENDERING OR vtkRenderingCore_LOADED) set(GDCM_VTK_APPS ${GDCM_VTK_APPS} gdcmorthoplanes gdcmreslice gdcmrtionplan gdcmrtplan gdcmscene gdcmtexture gdcmvolume rtstructapp ) endif() if(GDCM_BUILD_TESTING) set(GDCM_VTK_APPS ${GDCM_VTK_APPS} ConvertRGBToLuminance Convert16BitsTo8Bits ConvertMultiFrameToSingleFrame MagnifyFile ) if(GDCM_DATA_EXTRA_ROOT) if(VTK_USE_RENDERING OR vtkRenderingCore_LOADED) set(GDCM_VTK_APPS ${GDCM_VTK_APPS} reslicesphere ) endif() endif() endif() endif() foreach(app ${GDCM_VTK_APPS}) add_executable(${app} ${app}.cxx) #set_target_properties(${app} PROPERTIES ${GDCM_EXECUTABLE_PROPERTIES}) target_link_libraries(${app} ${VTKGDCM_NAME} ${vtkgdcm_LIBS}) target_link_libraries(${app} gdcmDSED gdcmMSFF gdcmCommon) if(GDCM_BUILD_TESTING) # gdcmTesting is in Common: target_link_libraries(${app} gdcmCommon) endif() if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" GREATER 6.0 ) target_link_libraries(${app} ${VTK_LIBRARIES}) else() if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" GREATER 5.0 ) if(VTK_USE_RENDERING) target_link_libraries(${app} vtkWidgets vtkVolumeRendering) endif() endif() endif() endforeach() if(GDCM_HAVE_PTHREAD_H) # Dev only: I dont need to install that one: add_executable(threadgdcm threadgdcm.cxx) target_link_libraries(threadgdcm gdcmMSFF pthread ) if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" GREATER 6.0 ) target_link_libraries(threadgdcm ${VTK_LIBRARIES}) else() target_link_libraries(threadgdcm vtkIO) endif() endif() #add_executable(gdcm2vtk gdcm2vtk.cxx) #target_link_libraries(gdcm2vtk gdcmMSFF pthread) GDCM-3.0.10/Utilities/VTK/Examples/Cxx/Compute3DSpacing.cxx000066400000000000000000000054131412732066400231100ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader2.h" #include "vtkImageChangeInformation.h" #include "vtkStringArray.h" #include "gdcmIPPSorter.h" #ifndef vtkFloatingPointType #define vtkFloatingPointType double #endif /* * Simple example to check computation of spacing within vtkGDCMImageReader2 * This is a direct implementation of: * * http://gdcm.sourceforge.net/wiki/index.php/Using_GDCM_API#Automatic_ordering_of_slices_for_vtkGDCMImageReader.SetFileNames * * For more advanced information on how 3D spacing is being computed see: * * - http://gdcm.sourceforge.net/html/classgdcm_1_1IPPSorter.html * * Usage: * * $ Compute3DSpacing SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm \ * SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm \ * SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm \ * SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm */ int main(int argc, char *argv[]) { if( argc < 2 ) return 1; std::vector filenames; for( int i = 1; i < argc; ++i ) { filenames.push_back( argv[i] ); } gdcm::IPPSorter s; s.SetComputeZSpacing( true ); s.SetZSpacingTolerance( 1e-3 ); bool b = s.Sort( filenames ); if( !b ) { std::cerr << "Failed to sort files" << std::endl; return 1; } std::cout << "Sorting succeeded:" << std::endl; //s.Print( std::cout ); std::cout << "Found z-spacing:" << std::endl; std::cout << s.GetZSpacing() << std::endl; const double ippzspacing = s.GetZSpacing(); const std::vector & sorted = s.GetFilenames(); vtkGDCMImageReader2 * reader = vtkGDCMImageReader2::New(); vtkStringArray *files = vtkStringArray::New(); std::vector< std::string >::const_iterator it = sorted.begin(); for( ; it != sorted.end(); ++it) { const std::string &f = *it; files->InsertNextValue( f.c_str() ); } reader->SetFileNames( files ); reader->Update(); const vtkFloatingPointType *spacing = reader->GetOutput()->GetSpacing(); vtkImageChangeInformation *v16 = vtkImageChangeInformation::New(); #if (VTK_MAJOR_VERSION >= 6) v16->SetInputConnection( reader->GetOutputPort() ); #else v16->SetInput( reader->GetOutput() ); #endif v16->SetOutputSpacing( spacing[0], spacing[1], ippzspacing ); v16->Update(); v16->GetOutput()->Print( std::cout ); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/Convert16BitsTo8Bits.cxx000066400000000000000000000040361412732066400236260ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkGDCMImageWriter.h" #include "vtkImageData.h" #include "vtkImageCast.h" #include "gdcmTesting.h" // The following file is 16/16/15 but the scalar range of the image is [0,192] // it could be safely stored as 8bits instead: // gdcmData/012345.002.050.dcm int main(int, char *[]) { const char *directory = gdcm::Testing::GetDataRoot(); if(!directory) return 1; std::string file = std::string(directory) + "/012345.002.050.dcm"; std::cout << file << std::endl; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); reader->SetFileName( file.c_str() ); reader->Update(); //reader->GetOutput()->Print( std::cout ); vtkImageCast *cast = vtkImageCast::New(); #if (VTK_MAJOR_VERSION >= 6) cast->SetInputConnection( reader->GetOutputPort() ); #else cast->SetInput( reader->GetOutput() ); #endif cast->SetOutputScalarTypeToUnsignedChar(); vtkGDCMImageWriter *writer = vtkGDCMImageWriter::New(); writer->SetFileName( "/tmp/cast.dcm" ); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputConnection( cast->GetOutputPort() ); #else writer->SetInput( cast->GetOutput() ); #endif writer->SetImageFormat( reader->GetImageFormat() ); writer->SetMedicalImageProperties( reader->GetMedicalImageProperties() ); writer->SetDirectionCosines( reader->GetDirectionCosines() ); writer->SetShift( reader->GetShift() ); writer->SetScale( reader->GetScale() ); writer->Write(); reader->Delete(); cast->Delete(); writer->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/ConvertMultiFrameToSingleFrame.cxx000066400000000000000000000050121412732066400260210ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkGDCMImageWriter.h" #include "vtkImageData.h" #include "vtkStringArray.h" #include "gdcmTesting.h" #include "gdcmFilenameGenerator.h" int main(int argc, char *argv[]) { std::string filename; if( argc <= 1 ) { const char *directory = gdcm::Testing::GetDataRoot(); if(!directory) return 1; std::string file = std::string(directory) + "/US-PAL-8-10x-echo.dcm"; filename = file; } else { filename = argv[1]; } std::cout << "file: " << filename << std::endl; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); reader->SetFileName( filename.c_str() ); reader->Update(); //reader->GetOutput()->Print( std::cout ); int dims[3]; reader->GetOutput()->GetDimensions( dims ); std::ostringstream os; os << "singleframe"; os << "%04d.dcm"; gdcm::FilenameGenerator fg; fg.SetPattern( os.str().c_str() ); unsigned int nfiles = dims[2]; fg.SetNumberOfFilenames( nfiles ); bool b = fg.Generate(); if( !b ) { std::cerr << "FilenameGenerator::Generate() failed" << std::endl; return 1; } if( !fg.GetNumberOfFilenames() ) { std::cerr << "FilenameGenerator::Generate() failed somehow..." << std::endl; return 1; } // By default write them as Secondary Capture (for portability) vtkGDCMImageWriter *writer = vtkGDCMImageWriter::New(); vtkStringArray *filenames = vtkStringArray::New(); for(unsigned int i = 0; i < fg.GetNumberOfFilenames(); ++i) { filenames->InsertNextValue( fg.GetFilename(i) ); } assert( filenames->GetNumberOfValues() == (int)fg.GetNumberOfFilenames() ); writer->SetFileNames( filenames ); filenames->Delete(); writer->SetFileDimensionality( 2 ); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputConnection( reader->GetOutputPort() ); #else writer->SetInput( reader->GetOutput() ); #endif writer->SetImageFormat( reader->GetImageFormat() ); writer->Write(); reader->Delete(); writer->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/ConvertRGBToLuminance.cxx000066400000000000000000000041351412732066400241120ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkGDCMImageWriter.h" #include "vtkImageData.h" #include "vtkImageLuminance.h" #include "gdcmTesting.h" // There is no such thing as MR Image Storage + Photometric Interpretation = RGB // let's rewrite that into a proper single component image: int main(int, char *[]) { const char *directory = gdcm::Testing::GetDataRoot(); if(!directory) return 1; std::string file = std::string(directory) + "/SIEMENS-MR-RGB-16Bits.dcm"; std::cout << file << std::endl; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); reader->SetFileName( file.c_str() ); reader->Update(); //reader->GetOutput()->Print( std::cout ); vtkImageLuminance *luminance = vtkImageLuminance::New(); #if (VTK_MAJOR_VERSION >= 6) luminance->SetInputConnection( reader->GetOutputPort() ); #else luminance->SetInput( reader->GetOutput() ); #endif vtkGDCMImageWriter *writer = vtkGDCMImageWriter::New(); writer->SetFileName( "/tmp/bla.dcm" ); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputConnection( luminance->GetOutputPort() ); #else writer->SetInput( luminance->GetOutput() ); #endif //writer->SetImageFormat( reader->GetImageFormat() ); // Do NOT pass image format writer->SetMedicalImageProperties( reader->GetMedicalImageProperties() ); writer->SetDirectionCosines( reader->GetDirectionCosines() ); writer->SetShift( reader->GetShift() ); writer->SetScale( reader->GetScale() ); writer->Write(); // TODO: //vtkImageAppendComponents.h reader->Delete(); luminance->Delete(); writer->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/ConvertSingleBitTo8Bits.cxx000066400000000000000000000052421412732066400244360ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkGDCMImageWriter.h" #include "vtkImageData.h" #include "vtkImageCast.h" #include "vtkPointData.h" #include "vtkBitArray.h" #include "vtkUnsignedCharArray.h" int main(int argc, char *argv[]) { if( argc < 3 ) { return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); reader->SetFileName( filename ); reader->Update(); //reader->GetOutput()->Print( std::cout ); vtkDataArray* array = reader->GetOutput()->GetPointData()->GetScalars(); vtkBitArray *barray = vtkBitArray::SafeDownCast( array ); if( !barray ) return false; vtkIdType nvalues = array->GetNumberOfTuples(); vtkUnsignedCharArray *uarray = vtkUnsignedCharArray::New(); uarray->SetNumberOfTuples( nvalues ); for(vtkIdType i = 0; i < nvalues; ++i) { uarray->SetValue( i, (unsigned char)barray->GetValue(i) ); } vtkImageData *copy = vtkImageData::New(); // http://www.vtk.org/Wiki/VTK/VTK_6_Migration/Changes_to_Scalars_Manipulation_Functions#AllocateScalars.28.29 copy->SetExtent( reader->GetOutput()->GetExtent() ); #if (VTK_MAJOR_VERSION >= 6) copy->AllocateScalars(VTK_UNSIGNED_CHAR, 3); #else copy->SetScalarType( VTK_UNSIGNED_CHAR ); copy->AllocateScalars(); #endif //uarray->Print( std::cout ); //copy->GetPointData()->GetScalars()->Print( std::cout ); copy->GetPointData()->SetScalars( uarray ); uarray->Delete(); vtkGDCMImageWriter *writer = vtkGDCMImageWriter::New(); writer->SetFileName( outfilename ); //writer->SetInput( cast->GetOutput() ); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputData( copy ); #else writer->SetInput( copy ); #endif writer->SetImageFormat( reader->GetImageFormat() ); writer->SetMedicalImageProperties( reader->GetMedicalImageProperties() ); writer->SetDirectionCosines( reader->GetDirectionCosines() ); writer->SetShift( reader->GetShift() ); writer->SetScale( reader->GetScale() ); writer->SetFileDimensionality( reader->GetFileDimensionality( ) ); writer->Write(); reader->Delete(); copy->Delete(); writer->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/CreateFakePET.cxx000066400000000000000000000066471412732066400223550ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageWriter.h" #include "vtkImageReader.h" #include "vtkImageCast.h" #include "vtkImageData.h" #include "vtkPointData.h" #include "vtkDataArray.h" #include "vtkMedicalImageProperties.h" #include "vtkStringArray.h" #include "gdcmTrace.h" #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmAttribute.h" #include "gdcmFilenameGenerator.h" /* * Minimal example to create a fake RTDOSE file. The data contains a sphere * just for testing. * The vtkMedicalImageProperties is not properly filled, but only contains a * single field which is required to set the proper SOP Class */ int main(int, char *[]) { gdcm::Trace::DebugOn(); const vtkIdType xSize = 512; const vtkIdType ySize = 512; const vtkIdType zSize = 512; // Create the filenames in advance to supply to the vtkGDCMImageWriter std::ostringstream os; os << "PT"; os << "%03d.dcm"; gdcm::FilenameGenerator fg; fg.SetPattern( os.str().c_str() ); unsigned int nfiles = zSize; fg.SetNumberOfFilenames( nfiles ); bool b = fg.Generate(); if( !b ) { std::cerr << "FilenameGenerator::Generate() failed" << std::endl; return 1; } if( !fg.GetNumberOfFilenames() ) { std::cerr << "FilenameGenerator::Generate() failed somehow..." << std::endl; return 1; } vtkStringArray *filenames = vtkStringArray::New(); for(unsigned int i = 0; i < fg.GetNumberOfFilenames(); ++i) { filenames->InsertNextValue( fg.GetFilename(i) ); } vtkImageData *image = vtkImageData::New(); image->SetDimensions(xSize,ySize,zSize); image->SetOrigin(-350.684,350.0,890.76); image->SetSpacing(5.4688,-5.4688,-3.27); #if VTK_MAJOR_VERSION <= 5 image->SetNumberOfScalarComponents(1); image->SetScalarTypeToDouble(); #else image->AllocateScalars(VTK_DOUBLE ,1); #endif double pt[3]; for( int z = 0; z < zSize; ++z ) for( int y = 0; y < ySize; ++y ) for( int x = 0; x < xSize; ++x ) { pt[0] = x; pt[1] = y; pt[2] = z; pt[0] -= xSize / 2; pt[1] -= ySize / 2; pt[2] -= zSize / 2; pt[0] /= xSize / 2; pt[1] /= ySize / 2; pt[2] /= zSize / 2; const double unit = pt[0] * pt[0] + pt[1] * pt[1] + pt[2] * pt[2]; const double inval = unit <= 1. ? (3 * unit + 7) : 0.; // just for fun => max == 10. double* pixel= static_cast(image->GetScalarPointer(x,y,z)); pixel[0] = inval; } vtkGDCMImageWriter *writer = vtkGDCMImageWriter::New(); writer->SetFileDimensionality( 2 ); writer->SetFileNames(filenames); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputData( image ); #else writer->SetInput( image ); #endif writer->GetMedicalImageProperties()->SetSliceThickness("1.5"); writer->GetMedicalImageProperties()->SetModality( "PT" ); writer->SetScale( 0.0042 ); // why not writer->Write(); image->Delete(); writer->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/CreateFakeRTDOSE.cxx000066400000000000000000000100211412732066400227020ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageWriter.h" #include "vtkImageReader.h" #include "vtkImageCast.h" #include "vtkImageData.h" #include "vtkPointData.h" #include "vtkDataArray.h" #include "vtkMedicalImageProperties.h" #include "gdcmTrace.h" #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmAttribute.h" /* * Minimal example to create a fake RTDOSE file. The data contains a sphere * just for testing. * The vtkMedicalImageProperties is not properly filled, but only contains a * single field which is required to set the proper SOP Class */ int main(int, char *[]) { //gdcm::Trace::DebugOn(); const vtkIdType xSize = 512; const vtkIdType ySize = 512; const vtkIdType zSize = 512; vtkImageData *image = vtkImageData::New(); image->SetDimensions(xSize,ySize,zSize); image->SetOrigin(-350.684,350.0,890.76); image->SetSpacing(5.4688,-5.4688,-3.27); #if VTK_MAJOR_VERSION <= 5 image->SetNumberOfScalarComponents(1); image->SetScalarTypeToDouble(); #else image->AllocateScalars(VTK_DOUBLE ,1); #endif double pt[3]; for( int z = 0; z < zSize; ++z ) for( int y = 0; y < ySize; ++y ) for( int x = 0; x < xSize; ++x ) { pt[0] = x; pt[1] = y; pt[2] = z; pt[0] -= xSize / 2; pt[1] -= ySize / 2; pt[2] -= zSize / 2; pt[0] /= xSize / 2; pt[1] /= ySize / 2; pt[2] /= zSize / 2; const double unit = pt[0] * pt[0] + pt[1] * pt[1] + pt[2] * pt[2]; const double inval = unit <= 1. ? (3 * unit + 7) : 0.; // just for fun => max == 10. double* pixel= static_cast(image->GetScalarPointer(x,y,z)); pixel[0] = inval; } vtkGDCMImageWriter *writer = vtkGDCMImageWriter::New(); writer->SetFileDimensionality( 3 ); writer->SetFileName( "rtdose.dcm" ); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputData( image ); #else writer->SetInput( image ); #endif writer->GetMedicalImageProperties()->SetSliceThickness("1.5"); writer->GetMedicalImageProperties()->AddUserDefinedValue( "Dose Units", "GY"); writer->GetMedicalImageProperties()->AddUserDefinedValue( "Dose Summation Type", "PLAN"); writer->GetMedicalImageProperties()->AddUserDefinedValue( "Dose Type", "PHYSICAL"); writer->GetMedicalImageProperties()->AddUserDefinedValue( "Frame of Reference UID", "1.3.12.2.1107.5.6.1.68100.30270111041215391275000000001"); writer->GetMedicalImageProperties()->SetModality( "RTDOSE" ); //writer->GetMedicalImageProperties()->SetModality( "PT" ); // debug writer->SetScale( 0.0042 ); // why not writer->Write(); image->Delete(); writer->Delete(); // BEGIN HACK // In GDCM version 2.4.3 and before, the following tag was missing which caused issue with some RTDose software: // Open the DICOM file that was temporarily created. This will allows me to used // GDCM to append specific tags that allows the RTDOSE to be associated with the // relevant CT images. gdcm::Reader reader2; reader2.SetFileName("rtdose.dcm" ); reader2.Read(); gdcm::File &file = reader2.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); // Required by some software and not automagically added by GDCM in old version gdcm::Attribute<0x0028,0x0009> framePointer; framePointer.SetNumberOfValues(1); framePointer.SetValue( gdcm::Tag(0x3004,0x000C) ); ds.Replace( framePointer.GetAsDataElement() ); gdcm::Writer writer2; writer2.CheckFileMetaInformationOff(); writer2.SetFileName("rtdose2.dcm"); writer2.SetFile( file ); writer2.Write(); // END HACK return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/GenerateRTSTRUCT.cxx000066400000000000000000000166011412732066400227460ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMPolyDataWriter.h" #include "vtkGDCMPolyDataReader.h" #include "vtkPolyData.h" #include "vtkPolyDataReader.h" #include "vtkMedicalImageProperties.h" #include "vtkRTStructSetProperties.h" #include "vtkStringArray.h" #include "vtkAppendPolyData.h" #include "vtkPolyDataWriter.h" #include "vtkPolyDataMapper.h" #include "vtkPolyDataMapper2D.h" #include "vtkActor2D.h" #include "vtkRenderWindowInteractor.h" #include "vtkMedicalImageProperties.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkCamera.h" #include "vtkProperty.h" #include "vtkProperty2D.h" #include "vtkImageData.h" #include //for std::find #include "gdcmDirectoryHelper.h" using namespace gdcm; //view each organ independently of the others, to make sure that //organ names correspond to actual segmentations. void ShowOrgan(vtkPolyData* inData) { // Now we'll look at it. vtkPolyDataMapper *cubeMapper = vtkPolyDataMapper::New(); #if (VTK_MAJOR_VERSION >= 6) cubeMapper->SetInputData( inData ); #else cubeMapper->SetInput( inData ); #endif cubeMapper->SetScalarRange(0,7); vtkActor *cubeActor = vtkActor::New(); cubeActor->SetMapper(cubeMapper); vtkProperty * property = cubeActor->GetProperty(); property->SetRepresentationToWireframe(); vtkRenderer *renderer = vtkRenderer::New(); vtkRenderWindow *renWin = vtkRenderWindow::New(); renWin->AddRenderer(renderer); vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); iren->SetRenderWindow(renWin); renderer->AddActor(cubeActor); renderer->ResetCamera(); renderer->SetBackground(1,1,1); renWin->SetSize(300,300); renWin->Render(); iren->Start(); cubeMapper->Delete(); cubeActor->Delete(); renderer->Delete(); renWin->Delete(); iren->Delete(); } /* * Full application which ... RTSTUCT */ int main(int argc, char *argv[]) { if( argc < 2 ) { std::cerr << argv[0] << " directory-with-rtstruct-and-ct-images\n"; return 1; } std::string theDirName(argv[1]); Directory::FilenamesType theRTSeries = DirectoryHelper::GetRTStructSeriesUIDs(theDirName); gdcm::Directory theDir; theDir.Load(argv[1]); if (theRTSeries.empty()) { std::cerr << "No RTStructs found for the test, ending." << std::endl; return 1; } for (size_t q = 0; q < theRTSeries.size(); q++) { Directory::FilenamesType theRTNames = DirectoryHelper::GetFilenamesFromSeriesUIDs(theDirName, theRTSeries[q]); if (theRTNames.empty()){ std::cerr << "Unable to load RT Series " << theRTSeries[q] << ", continuing. " << std::endl; continue; } vtkGDCMPolyDataReader * reader = vtkGDCMPolyDataReader::New(); reader->SetFileName( theRTNames[0].c_str() ); reader->Update(); //std::cout << reader->GetMedicalImageProperties()->GetStudyDate() << std::endl; vtkGDCMPolyDataWriter * writer = vtkGDCMPolyDataWriter::New(); int numMasks = reader->GetNumberOfOutputPorts() + 1;//add a blank one in writer->SetNumberOfInputPorts( numMasks ); std::string thePotentialName = theDirName + "/" + "GDCMTestRTStruct." + theRTSeries[q] + ".dcm"; gdcm::Directory::FilenamesType theFileNames = theDir.GetFilenames(); //keep renaming the output until we get something that doesn't overwrite what was there already int count = 0; while (std::find(theFileNames.begin(), theFileNames.end(), thePotentialName) != theFileNames.end()) { char buff[255]; sprintf(buff,"%d",count); thePotentialName = theDirName + "/" + "GDCMTestRTStruct." + buff + "." + theRTSeries[q] + ".dcm"; } writer->SetFileName( thePotentialName.c_str()); writer->SetMedicalImageProperties( reader->GetMedicalImageProperties() ); //this line is cheating, we won't have the same stuff, and may not have a struct //to start with. //have to go back to the original data to reconstruct the RTStructureSetProperties //writer->SetRTStructSetProperties( reader->GetRTStructSetProperties() ); //writer->Write(); //loop through the outputs in order to write them out as if they had been created and appended vtkStringArray* roiNames = vtkStringArray::New(); vtkStringArray* roiAlgorithms = vtkStringArray::New(); vtkStringArray* roiTypes = vtkStringArray::New(); roiNames->SetNumberOfValues(numMasks); roiAlgorithms->SetNumberOfValues(numMasks); roiTypes->SetNumberOfValues(numMasks); vtkAppendPolyData* append = vtkAppendPolyData::New(); //ok, now we'll add a blank organ //the blank organ is to test to ensure that blank organs work; there have been crash reports //this code is added at the beginning to ensure that the blank organs are read //and preserved as individual organs. vtkPolyData* blank = vtkPolyData::New(); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputData(0, blank); #else writer->SetInput(0, blank); #endif roiNames->InsertValue(0, "blank"); roiAlgorithms->InsertValue(0, "blank"); roiTypes->InsertValue(0, "ORGAN"); //note the offsets used to place the blank rtstruct at the beginning of the newly generated RT. //the idea is to run the program twice; first to generate an rtstruct with a blank mask (making //sure that that functionality works), and then a second time to make sure that everything is //being read properly. Multiple organs with the same name could cause some strangenesses. for (int i = 1; i < numMasks; ++i) { #if (VTK_MAJOR_VERSION >= 6) writer->SetInputConnection(i, reader->GetOutputPort(i-1)); append->AddInputConnection(reader->GetOutputPort(i-1)); #else writer->SetInput(i, reader->GetOutput(i-1)); append->AddInput(reader->GetOutput(i-1)); #endif std::string theString = reader->GetRTStructSetProperties()->GetStructureSetROIName(i-1); roiNames->InsertValue(i, theString); theString = reader->GetRTStructSetProperties()->GetStructureSetROIGenerationAlgorithm(i-1); roiAlgorithms->InsertValue(i, theString); theString = reader->GetRTStructSetProperties()->GetStructureSetRTROIInterpretedType(i-1); roiTypes->InsertValue(i, theString); ShowOrgan(reader->GetOutput(i-1)); } vtkRTStructSetProperties* theProperties = vtkRTStructSetProperties::New(); writer->SetRTStructSetProperties(theProperties); writer->InitializeRTStructSet(theDirName, reader->GetRTStructSetProperties()->GetStructureSetLabel(), reader->GetRTStructSetProperties()->GetStructureSetName(), roiNames, roiAlgorithms, roiTypes); writer->SetRTStructSetProperties(theProperties); writer->Write(); // print reader output: reader->Print( std::cout ); // print first output: reader->GetOutput()->Print( std::cout ); reader->Delete(); append->Delete(); roiNames->Delete(); roiTypes->Delete(); theProperties->Delete(); roiAlgorithms->Delete(); blank->Delete(); writer->Delete(); } return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/MagnifyFile.cxx000066400000000000000000000047701412732066400221770ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkGDCMImageWriter.h" #include "vtkImageData.h" #include "vtkImageMagnify.h" #include "vtkImageCast.h" #include "gdcmTesting.h" #include "gdcmSystem.h" // This is a simple test to magnify an image that is known to give excellent // compression ratio. This will be our test for those large image int main(int, char *[]) { const char *directory = gdcm::Testing::GetDataRoot(); if(!directory) return 1; std::string file = std::string(directory) + "/test.acr"; std::cout << file << std::endl; if( !gdcm::System::FileExists( file.c_str() ) ) return 1; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); reader->SetFileName( file.c_str() ); reader->Update(); //reader->GetOutput()->Print( std::cout ); vtkImageCast *cast = vtkImageCast::New(); #if (VTK_MAJOR_VERSION >= 6) cast->SetInputConnection( reader->GetOutputPort() ); #else cast->SetInput( reader->GetOutput() ); #endif cast->SetOutputScalarTypeToUnsignedShort(); vtkImageMagnify *magnify = vtkImageMagnify::New(); #if (VTK_MAJOR_VERSION >= 6) magnify->SetInputConnection( cast->GetOutputPort() ); #else magnify->SetInput( cast->GetOutput() ); #endif magnify->SetInterpolate( 1 ); magnify->SetInterpolate( 0 ); int factor = 100; magnify->SetMagnificationFactors (factor, factor, 1); vtkGDCMImageWriter *writer = vtkGDCMImageWriter::New(); writer->SetFileName( "/tmp/bla.dcm" ); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputConnection( magnify->GetOutputPort() ); #else writer->SetInput( magnify->GetOutput() ); #endif writer->SetImageFormat( reader->GetImageFormat() ); writer->SetMedicalImageProperties( reader->GetMedicalImageProperties() ); writer->SetDirectionCosines( reader->GetDirectionCosines() ); writer->SetShift( reader->GetShift() ); writer->SetScale( reader->GetScale() ); writer->Write(); // TODO: //vtkImageAppendComponents.h reader->Delete(); magnify->Delete(); writer->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/gdcmorthoplanes.cxx000066400000000000000000000360211412732066400231700ustar00rootroot00000000000000/*========================================================================= 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 "vtkActor.h" #include "vtkCamera.h" #include "vtkMatrix4x4.h" #include "vtkTransform.h" #include "vtkAssembly.h" #include "vtkCellPicker.h" #include "vtkCommand.h" #include "vtkImageActor.h" #include "vtkImageMapToColors.h" #include "vtkImageOrthoPlanes.h" #include "vtkImagePlaneWidget.h" #include "vtkImageReader.h" #include "vtkInteractorEventRecorder.h" #include "vtkLookupTable.h" #include "vtkOutlineFilter.h" #include "vtkPolyDataMapper.h" #include "vtkProperty.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" #include "vtkVolume16Reader.h" #include "vtkImageData.h" #include "vtkImageChangeInformation.h" #include "vtkOrientationMarkerWidget.h" #include "vtkAnnotatedCubeActor.h" #include "vtkAxesActor.h" #include "vtkCaptionActor2D.h" #include "vtkTextProperty.h" #include "vtkPropAssembly.h" #include "vtkGDCMImageReader.h" #include "vtkGDCMImageWriter.h" #include "vtkStringArray.h" #include "gdcmSystem.h" #include "gdcmDirectory.h" #include "gdcmIPPSorter.h" #ifndef vtkFloatingPointType #define vtkFloatingPointType double #endif //---------------------------------------------------------------------------- class vtkOrthoPlanesCallback : public vtkCommand { public: static vtkOrthoPlanesCallback *New() { return new vtkOrthoPlanesCallback; } void Execute( vtkObject *caller, unsigned long vtkNotUsed( event ), void *callData ) { vtkImagePlaneWidget* self = reinterpret_cast< vtkImagePlaneWidget* >( caller ); if(!self) return; double* wl = static_cast( callData ); if ( self == this->WidgetX ) { this->WidgetY->SetWindowLevel(wl[0],wl[1],1); this->WidgetZ->SetWindowLevel(wl[0],wl[1],1); } else if( self == this->WidgetY ) { this->WidgetX->SetWindowLevel(wl[0],wl[1],1); this->WidgetZ->SetWindowLevel(wl[0],wl[1],1); } else if (self == this->WidgetZ) { this->WidgetX->SetWindowLevel(wl[0],wl[1],1); this->WidgetY->SetWindowLevel(wl[0],wl[1],1); } } vtkOrthoPlanesCallback():WidgetX( 0 ), WidgetY( 0 ), WidgetZ ( 0 ) {} vtkImagePlaneWidget* WidgetX; vtkImagePlaneWidget* WidgetY; vtkImagePlaneWidget* WidgetZ; }; int main( int argc, char *argv[] ) { //char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/headsq/quarter"); //vtkVolume16Reader* v16 = vtkVolume16Reader::New(); // v16->SetDataDimensions( 64, 64); // v16->SetDataByteOrderToLittleEndian(); // v16->SetImageRange( 1, 93); // v16->SetDataSpacing( 3.2, 3.2, 1.5); // v16->SetFilePrefix( fname ); // v16->SetDataMask( 0x7fff); // v16->Update(); std::vector filenames; if( argc < 2 ) { std::cerr << argv[0] << " filename1.dcm [filename2.dcm ...]\n"; return 1; } else { // Is it a single directory ? If so loop over all files contained in it: const char *filename = argv[1]; if( argc == 2 && gdcm::System::FileIsDirectory( filename ) ) { std::cout << "Loading directory: " << filename << std::endl; bool recursive = false; gdcm::Directory d; d.Load(filename, recursive); gdcm::Directory::FilenamesType const &files = d.GetFilenames(); for( gdcm::Directory::FilenamesType::const_iterator it = files.begin(); it != files.end(); ++it ) { filenames.push_back( it->c_str() ); } } else // list of files passed directly on the cmd line: // discard non-existing or directory { for(int i=1; i < argc; ++i) { filename = argv[i]; if( gdcm::System::FileExists( filename ) ) { if( gdcm::System::FileIsDirectory( filename ) ) { std::cerr << "Discarding directory: " << filename << std::endl; } else { filenames.push_back( filename ); } } else { std::cerr << "Discarding non existing file: " << filename << std::endl; } } } //names->Print( std::cout ); } vtkGDCMImageReader * reader = vtkGDCMImageReader::New(); double ippzspacing; if( filenames.size() > 1 ) { //gdcm::Trace::DebugOn(); //gdcm::Trace::WarningOn(); gdcm::IPPSorter s; s.SetComputeZSpacing( true ); s.SetZSpacingTolerance( 1e-3 ); bool b = s.Sort( filenames ); if( !b ) { std::cerr << "Failed to sort files" << std::endl; return 1; } std::cout << "Sorting succeeded:" << std::endl; s.Print( std::cout ); std::cout << "Found z-spacing:" << std::endl; std::cout << s.GetZSpacing() << std::endl; ippzspacing = s.GetZSpacing(); const std::vector & sorted = s.GetFilenames(); vtkStringArray *files = vtkStringArray::New(); std::vector< std::string >::const_iterator it = sorted.begin(); for( ; it != sorted.end(); ++it) { const std::string &f = *it; files->InsertNextValue( f.c_str() ); } reader->SetFileNames( files ); //reader->SetFileLowerLeft( 1 ); reader->Update(); // important files->Delete(); } else { reader->SetFileName( argv[1] ); reader->Update(); // important ippzspacing = reader->GetOutput()->GetSpacing()[2]; ippzspacing = 4; } //reader->GetOutput()->Print( std::cout ); //vtkFloatingPointType range[2]; //reader->GetOutput()->GetScalarRange(range); //std::cout << "Range: " << range[0] << " " << range[1] << std::endl; const vtkFloatingPointType *spacing = reader->GetOutput()->GetSpacing(); vtkImageChangeInformation *v16 = vtkImageChangeInformation::New(); #if (VTK_MAJOR_VERSION >= 6) v16->SetInputConnection( reader->GetOutputPort() ); #else v16->SetInput( reader->GetOutput() ); #endif v16->SetOutputSpacing( spacing[0], spacing[1], ippzspacing ); v16->Update(); #if 0 vtkGDCMImageWriter *writer = vtkGDCMImageWriter::New(); writer->SetInput( v16->GetOutput() ); writer->SetFileLowerLeft( reader->GetFileLowerLeft() ); writer->SetDirectionCosines( reader->GetDirectionCosines() ); writer->SetImageFormat( reader->GetImageFormat() ); writer->SetFileDimensionality( 3); //reader->GetFileDimensionality() ); writer->SetMedicalImageProperties( reader->GetMedicalImageProperties() ); writer->SetShift( reader->GetShift() ); writer->SetScale( reader->GetScale() ); writer->SetFileName( "out.dcm" ); writer->Write(); #endif vtkOutlineFilter* outline = vtkOutlineFilter::New(); outline->SetInputConnection(v16->GetOutputPort()); vtkPolyDataMapper* outlineMapper = vtkPolyDataMapper::New(); outlineMapper->SetInputConnection(outline->GetOutputPort()); vtkActor* outlineActor = vtkActor::New(); outlineActor->SetMapper( outlineMapper); vtkRenderer* ren1 = vtkRenderer::New(); vtkRenderer* ren2 = vtkRenderer::New(); vtkRenderWindow* renWin = vtkRenderWindow::New(); renWin->AddRenderer(ren2); renWin->AddRenderer(ren1); vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New(); iren->SetRenderWindow(renWin); vtkCellPicker* picker = vtkCellPicker::New(); picker->SetTolerance(0.005); vtkProperty* ipwProp = vtkProperty::New(); //assign default props to the ipw's texture plane actor vtkImagePlaneWidget* planeWidgetX = vtkImagePlaneWidget::New(); planeWidgetX->SetInteractor( iren); planeWidgetX->SetKeyPressActivationValue('x'); planeWidgetX->SetPicker(picker); planeWidgetX->RestrictPlaneToVolumeOn(); planeWidgetX->GetPlaneProperty()->SetColor(1,0,0); planeWidgetX->SetTexturePlaneProperty(ipwProp); planeWidgetX->TextureInterpolateOff(); planeWidgetX->SetResliceInterpolateToNearestNeighbour(); #if (VTK_MAJOR_VERSION >= 6) planeWidgetX->SetInputConnection(v16->GetOutputPort()); #else planeWidgetX->SetInput(v16->GetOutput()); #endif planeWidgetX->SetPlaneOrientationToXAxes(); //planeWidgetX->SetSliceIndex(32); planeWidgetX->DisplayTextOn(); planeWidgetX->On(); planeWidgetX->InteractionOff(); planeWidgetX->InteractionOn(); vtkImagePlaneWidget* planeWidgetY = vtkImagePlaneWidget::New(); planeWidgetY->SetInteractor( iren); planeWidgetY->SetKeyPressActivationValue('y'); planeWidgetY->SetPicker(picker); planeWidgetY->GetPlaneProperty()->SetColor(1,1,0); planeWidgetY->SetTexturePlaneProperty(ipwProp); planeWidgetY->TextureInterpolateOn(); planeWidgetY->SetResliceInterpolateToLinear(); #if (VTK_MAJOR_VERSION >= 6) planeWidgetY->SetInputConnection(v16->GetOutputPort()); #else planeWidgetY->SetInput(v16->GetOutput()); #endif planeWidgetY->SetPlaneOrientationToYAxes(); //planeWidgetY->SetSlicePosition(102.4); planeWidgetY->SetLookupTable( planeWidgetX->GetLookupTable()); planeWidgetY->DisplayTextOn(); planeWidgetY->UpdatePlacement(); planeWidgetY->On(); vtkImagePlaneWidget* planeWidgetZ = vtkImagePlaneWidget::New(); planeWidgetZ->SetInteractor( iren); planeWidgetZ->SetKeyPressActivationValue('z'); planeWidgetZ->SetPicker(picker); planeWidgetZ->GetPlaneProperty()->SetColor(0,0,1); planeWidgetZ->SetTexturePlaneProperty(ipwProp); planeWidgetZ->TextureInterpolateOn(); planeWidgetZ->SetResliceInterpolateToCubic(); #if (VTK_MAJOR_VERSION >= 6) planeWidgetZ->SetInputConnection(v16->GetOutputPort()); #else planeWidgetZ->SetInput(v16->GetOutput()); #endif planeWidgetZ->SetPlaneOrientationToZAxes(); //planeWidgetZ->SetSliceIndex(25); planeWidgetZ->SetLookupTable( planeWidgetX->GetLookupTable()); planeWidgetZ->DisplayTextOn(); planeWidgetZ->On(); vtkImageOrthoPlanes *orthoPlanes = vtkImageOrthoPlanes::New(); orthoPlanes->SetPlane(0, planeWidgetX); orthoPlanes->SetPlane(1, planeWidgetY); orthoPlanes->SetPlane(2, planeWidgetZ); orthoPlanes->ResetPlanes(); vtkOrthoPlanesCallback* cbk = vtkOrthoPlanesCallback::New(); cbk->WidgetX = planeWidgetX; cbk->WidgetY = planeWidgetY; cbk->WidgetZ = planeWidgetZ; planeWidgetX->AddObserver( vtkCommand::EndWindowLevelEvent, cbk ); planeWidgetY->AddObserver( vtkCommand::EndWindowLevelEvent, cbk ); planeWidgetZ->AddObserver( vtkCommand::EndWindowLevelEvent, cbk ); cbk->Delete(); double wl[2]; planeWidgetZ->GetWindowLevel(wl); // Add a 2D image to test the GetReslice method // vtkImageMapToColors* colorMap = vtkImageMapToColors::New(); colorMap->PassAlphaToOutputOff(); colorMap->SetActiveComponent(0); colorMap->SetOutputFormatToLuminance(); #if (VTK_MAJOR_VERSION >= 6) colorMap->SetInputData(planeWidgetZ->GetResliceOutput()); #else colorMap->SetInput(planeWidgetZ->GetResliceOutput()); #endif colorMap->SetLookupTable(planeWidgetX->GetLookupTable()); vtkImageActor* imageActor = vtkImageActor::New(); imageActor->PickableOff(); #if (VTK_MAJOR_VERSION >= 6) imageActor->SetInputData(colorMap->GetOutput()); #else imageActor->SetInput(colorMap->GetOutput()); #endif // Add the actors // ren1->AddActor( outlineActor); ren2->AddActor( imageActor); ren1->SetBackground( 0.1, 0.1, 0.2); ren2->SetBackground( 0.2, 0.1, 0.2); renWin->SetSize( 600, 350); ren1->SetViewport(0,0,0.58333,1); ren2->SetViewport(0.58333,0,1,1); // Set the actors' postions // renWin->Render(); //iren->SetEventPosition( 175,175); //iren->SetKeyCode('r'); //iren->InvokeEvent(vtkCommand::CharEvent,NULL); //iren->SetEventPosition( 475,175); //iren->SetKeyCode('r'); //iren->InvokeEvent(vtkCommand::CharEvent,NULL); //renWin->Render(); //ren1->GetActiveCamera()->Elevation(110); //ren1->GetActiveCamera()->SetViewUp(0, 0, -1); //ren1->GetActiveCamera()->Azimuth(45); //ren1->GetActiveCamera()->Dolly(1.15); ren1->ResetCameraClippingRange(); vtkAnnotatedCubeActor* cube = vtkAnnotatedCubeActor::New(); cube->SetXPlusFaceText ( "R" ); cube->SetXMinusFaceText( "L" ); cube->SetYPlusFaceText ( "A" ); cube->SetYMinusFaceText( "P" ); cube->SetZPlusFaceText ( "H" ); cube->SetZMinusFaceText( "F" ); cube->SetFaceTextScale( 0.666667 ); vtkAxesActor* axes2 = vtkAxesActor::New(); vtkMatrix4x4 *invert = vtkMatrix4x4::New(); invert->DeepCopy( reader->GetDirectionCosines() ); invert->Invert(); // simulate a left-handed coordinate system // vtkTransform *transform = vtkTransform::New(); transform->Identity(); //transform->RotateY(90); transform->Concatenate(invert); axes2->SetShaftTypeToCylinder(); axes2->SetUserTransform( transform ); cube->GetAssembly()->SetUserTransform( transform ); axes2->SetTotalLength( 1.5, 1.5, 1.5 ); axes2->SetCylinderRadius( 0.500 * axes2->GetCylinderRadius() ); axes2->SetConeRadius ( 1.025 * axes2->GetConeRadius() ); axes2->SetSphereRadius ( 1.500 * axes2->GetSphereRadius() ); vtkTextProperty* tprop = axes2->GetXAxisCaptionActor2D()-> GetCaptionTextProperty(); tprop->ItalicOn(); tprop->ShadowOn(); tprop->SetFontFamilyToTimes(); axes2->GetYAxisCaptionActor2D()->GetCaptionTextProperty()->ShallowCopy( tprop ); axes2->GetZAxisCaptionActor2D()->GetCaptionTextProperty()->ShallowCopy( tprop ); vtkPropAssembly* assembly = vtkPropAssembly::New(); assembly->AddPart( axes2 ); assembly->AddPart( cube ); vtkOrientationMarkerWidget* widget = vtkOrientationMarkerWidget::New(); widget->SetOutlineColor( 0.9300, 0.5700, 0.1300 ); widget->SetOrientationMarker( assembly ); widget->SetInteractor( iren ); widget->SetViewport( 0.0, 0.0, 0.4, 0.4 ); widget->SetEnabled( 1 ); widget->InteractiveOff(); widget->InteractiveOn(); // Playback recorded events // //vtkInteractorEventRecorder *recorder = vtkInteractorEventRecorder::New(); //recorder->SetInteractor(iren); //recorder->ReadFromInputStringOn(); //recorder->SetInputString(IOPeventLog); // Interact with data // Render the image // iren->Initialize(); renWin->Render(); // Test SetKeyPressActivationValue for one of the widgets // //iren->SetKeyCode('z'); //iren->InvokeEvent(vtkCommand::CharEvent,NULL); //iren->SetKeyCode('z'); //iren->InvokeEvent(vtkCommand::CharEvent,NULL); //int retVal = vtkRegressionTestImage( renWin ); // //if ( retVal == vtkRegressionTester::DO_INTERACTOR) { iren->Start(); } // Clean up // //recorder->Off(); //recorder->Delete(); ipwProp->Delete(); orthoPlanes->Delete(); planeWidgetX->Delete(); planeWidgetY->Delete(); planeWidgetZ->Delete(); colorMap->Delete(); imageActor->Delete(); picker->Delete(); outlineActor->Delete(); outlineMapper->Delete(); outline->Delete(); iren->Delete(); renWin->Delete(); ren1->Delete(); ren2->Delete(); v16->Delete(); reader->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/gdcmreslice.cxx000066400000000000000000000111321412732066400222540ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkRenderer.h" #include "vtkAssembly.h" #include "vtkImageFlip.h" #include "vtkImageReslice.h" #include "vtkRenderWindow.h" #include "vtkAnnotatedCubeActor.h" #include "vtkTransform.h" #include "vtkAxesActor.h" #include "vtkTextProperty.h" #include "vtkCaptionActor2D.h" #include "vtkPropAssembly.h" #include "vtkOrientationMarkerWidget.h" #include "vtkRenderWindowInteractor.h" #include "vtkPolyDataMapper.h" #include "vtkActor.h" #include "vtkImageData.h" #include "vtkLookupTable.h" #include "vtkTexture.h" #include "vtkPlaneSource.h" int main( int argc, char *argv[] ) { if( argc < 2 ) return 1; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); reader->SetFileName( argv[1] ); //reader->FileLowerLeftOn(); reader->Update(); vtkImageFlip *flip = vtkImageFlip::New(); #if (VTK_MAJOR_VERSION >= 6) flip->SetInputConnection(reader->GetOutputPort()); #else flip->SetInput(reader->GetOutput()); #endif flip->SetFilteredAxis(0); flip->Update(); vtkImageReslice *reslice = vtkImageReslice::New(); //reslice->SetInput(reader->GetOutput()); #if (VTK_MAJOR_VERSION >= 6) reslice->SetInputConnection(flip->GetOutputPort()); #else reslice->SetInput(flip->GetOutput()); #endif //reslice->SetResliceAxesDirectionCosines() reader->GetDirectionCosines()->Print(std::cout); vtkMatrix4x4 *invert = vtkMatrix4x4::New(); invert->DeepCopy( reader->GetDirectionCosines() ); invert->Invert(); //reslice->SetResliceAxes( reader->GetDirectionCosines() ); reslice->SetResliceAxes( invert ); reslice->Update(); vtkImageData* ima = reslice->GetOutput(); vtkLookupTable* table = vtkLookupTable::New(); table->SetNumberOfColors(1000); table->SetTableRange(0,1000); table->SetSaturationRange(0,0); table->SetHueRange(0,1); table->SetValueRange(0,1); table->SetAlphaRange(1,1); table->Build(); // Texture vtkTexture* texture = vtkTexture::New(); #if (VTK_MAJOR_VERSION >= 6) texture->SetInputData(ima); #else texture->SetInput(ima); #endif texture->InterpolateOn(); texture->SetLookupTable(table); // PlaneSource vtkPlaneSource* plane = vtkPlaneSource::New(); // PolyDataMapper vtkPolyDataMapper *planeMapper = vtkPolyDataMapper::New(); #if (VTK_MAJOR_VERSION >= 6) planeMapper->SetInputConnection(plane->GetOutputPort()); #else planeMapper->SetInput(plane->GetOutput()); #endif // Actor vtkActor* planeActor = vtkActor::New(); planeActor->SetTexture(texture); planeActor->SetMapper(planeMapper); planeActor->PickableOn(); // Final rendering with simple interactor: vtkRenderer *ren = vtkRenderer::New(); vtkRenderWindow *renwin = vtkRenderWindow::New(); renwin->AddRenderer(ren); vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); iren->SetRenderWindow(renwin); ren->AddActor(planeActor); ren->SetBackground(0,0,0.5); // DICOM is RAH: vtkAnnotatedCubeActor* cube = vtkAnnotatedCubeActor::New(); cube->SetXPlusFaceText ( "R" ); cube->SetXMinusFaceText( "L" ); cube->SetYPlusFaceText ( "A" ); cube->SetYMinusFaceText( "P" ); cube->SetZPlusFaceText ( "H" ); cube->SetZMinusFaceText( "F" ); vtkAxesActor* axes2 = vtkAxesActor::New(); vtkTransform *transform = vtkTransform::New(); transform->Identity(); //reader->GetDirectionCosines()->Print(std::cout); transform->Concatenate(invert); //axes2->SetShaftTypeToCylinder(); axes2->SetUserTransform( transform ); cube->GetAssembly()->SetUserTransform( transform ); // cant get it to work vtkPropAssembly* assembly = vtkPropAssembly::New(); assembly->AddPart( axes2 ); assembly->AddPart( cube ); vtkOrientationMarkerWidget* widget = vtkOrientationMarkerWidget::New(); widget->SetOrientationMarker( assembly ); widget->SetInteractor( iren ); widget->SetEnabled( 1 ); widget->InteractiveOff(); widget->InteractiveOn(); renwin->Render(); iren->Start(); // Clean up: reader->Delete(); table->Delete(); texture->Delete(); plane->Delete(); planeMapper->Delete(); planeActor->Delete(); ren->Delete(); renwin->Delete(); iren->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/gdcmrtionplan.cxx000066400000000000000000000321011412732066400226330ustar00rootroot00000000000000/*========================================================================= 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 "vtkImageData.h" #include "vtkPointData.h" #include "vtkPolyData.h" #include "vtkProperty.h" #include "vtkPolyDataMapper.h" #include "vtkActor.h" #include "vtkRenderer.h" #include "vtkCellArray.h" #include "vtkPoints.h" #include "vtkDoubleArray.h" #include #include #include #include #include "gdcmReader.h" #include "gdcmAttribute.h" /* This example is just for fun. We found a RT Ion Plan Storage and simply extracted the viz stuff for VTK RTIonPlanStorage, // 1.2.840.10008.5.1.4.1.1.481.8 */ int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " filename.dcm outfile.vti\n"; return 1; } const char * filename = argv[1]; const char * outfilename = argv[2]; const char * outfilename2 = argv[3]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { return 1; } gdcm::MediaStorage ms; ms.SetFromFile( reader.GetFile() ); if( ms != gdcm::MediaStorage::RTIonPlanStorage ) { return 1; } /* (300a,03a2) SQ # u/l,1 Ion Beam Sequence (fffe,e000) na (Item with undefined length) (0008,1040) LO [Test] # 4,1 Institutional Department Name (300a,00b2) SH (no value) # 0,1 Treatment Machine Name (300a,00b3) CS [MU] # 2,1 Primary Dosimeter Unit (300a,00c0) IS [1 ] # 2,1 Beam Number (300a,00c2) LO [1 ] # 2,1 Beam Name (300a,00c4) CS [STATIC] # 6,1 Beam Type (300a,00c6) CS [PROTON] # 6,1 Radiation Type (300a,00ce) CS [TREATMENT ] # 10,1 Treatment Delivery Type (300a,00d0) IS [0 ] # 2,1 Number of Wedges (300a,00e0) IS [1 ] # 2,1 Number of Compensators (300a,00ed) IS [0 ] # 2,1 Number of Boli (300a,00f0) IS [1 ] # 2,1 Number of Blocks (300a,0110) IS [2 ] # 2,1 Number of Control Points (300a,02ea) SQ # u/l,1 Ion Range Compensator Sequence (fffe,e000) na (Item with undefined length) (300a,00e1) SH [lucite] # 6,1 Material ID (300a,00e4) IS [1 ] # 2,1 Compensator Number (300a,00e5) SH [75hdhe5 ] # 8,1 Compensator ID (300a,00e7) IS [35] # 2,1 Compensator Rows (300a,00e8) IS [37] # 2,1 Compensator Columns (300a,00e9) DS [3.679991\4.249288 ] # 18,2 Compensator Pixel Spacing (300a,00ea) DS [-76.00\62.50] # 12,2 Compensator Position (300a,00ec) DS [52.13\52.13\52.13\53.18\54.04\54.04\47.11\40.06\40.06\38.79\34.87\33.28\33.28\33.28\33.28\35.43\35.43\34.54\34.54\34.71\36.10\38.62\44.88\44.88\44.88\45.00\45.00\45.00\45.66\45.66\46.42\39.77\39.77\39.77\39.77\39.77\43.52\52.13\52.13\52.13\53.18\53.52\54.0] # 7618,1-n Compensator Thickness Data (300a,02e0) CS [ABSENT] # 6,1 Compensator Divergence (300a,02e1) CS [SOURCE_SIDE ] # 12,1 Compensator Mounting Position (300a,02e4) FL 39.2 # 4,1 Isocenter to Compensator Tray Distance (300a,02e5) FL 2.12 # 4,1 Compensator Column Offset (300a,02e8) FL 4.76 # 4,1 Compensator Milling Tool Diameter (fffe,e00d) */ const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); gdcm::Tag tbeamsq(0x300a,0x03a2); if( !ds.FindDataElement( tbeamsq ) ) { return 1; } const gdcm::DataElement &beamsq = ds.GetDataElement( tbeamsq ); //std::cout << beamsq << std::endl; gdcm::SmartPointer sqi = beamsq.GetValueAsSQ(); if( !sqi || !sqi->GetNumberOfItems() ) { return 1; } //for(unsigned int pd = 0; pd < sqi->GetNumberOfItems(); ++pd) // { //const gdcm::Item & item = sqi->GetItem(1); // Item start at #1 const gdcm::Item & item = sqi->GetItem(1); // Item start at #1 const gdcm::DataSet& nestedds = item.GetNestedDataSet(); //std::cout << nestedds << std::endl; gdcm::Tag tcompensatorsq(0x300a,0x02ea); if( !nestedds.FindDataElement( tcompensatorsq ) ) { return 1; } const gdcm::DataElement &compensatorsq = nestedds.GetDataElement( tcompensatorsq ); //std::cout << compensatorsq << std::endl; gdcm::SmartPointer ssqi = compensatorsq.GetValueAsSQ(); const gdcm::Item & item2 = ssqi->GetItem(1); // Item start at #1 const gdcm::DataSet& nestedds2 = item2.GetNestedDataSet(); //std::cout << nestedds2 << std::endl; gdcm::Tag tcompensatorthicknessdata(0x300a,0x00ec); if( !nestedds2.FindDataElement( tcompensatorthicknessdata ) ) { return 1; } const gdcm::DataElement &compensatorthicknessdata = nestedds2.GetDataElement( tcompensatorthicknessdata ); // std::cout << compensatorthicknessdata << std::endl; gdcm::Attribute<0x300a,0x00ec> at; at.SetFromDataElement( compensatorthicknessdata ); const double* pts = at.GetValues(); // (300a,00e7) IS [35] # 2,1 Compensator Rows gdcm::Attribute<0x300a,0x00e7> at1; const gdcm::DataElement &compensatorrows = nestedds2.GetDataElement( at1.GetTag() ); at1.SetFromDataElement( compensatorrows ); std::cout << at1.GetValue() << std::endl; // (300a,00e8) IS [37] # 2,1 Compensator Columns gdcm::Attribute<0x300a,0x00e8> at2; const gdcm::DataElement &compensatorcols = nestedds2.GetDataElement( at2.GetTag() ); at2.SetFromDataElement( compensatorcols ); std::cout << at2.GetValue() << std::endl; // (300a,00e9) DS [3.679991\4.249288 ] # 18,2 Compensator Pixel Spacing gdcm::Attribute<0x300a,0x00e9> at3; const gdcm::DataElement &compensatorpixelspacing = nestedds2.GetDataElement( at3.GetTag() ); at3.SetFromDataElement( compensatorpixelspacing ); std::cout << at3.GetValue(0) << std::endl; // (300a,00ea) DS [-76.00\62.50] # 12,2 Compensator Position gdcm::Attribute<0x300a,0x00ea> at4; const gdcm::DataElement &compensatorposition = nestedds2.GetDataElement( at4.GetTag() ); at4.SetFromDataElement( compensatorposition ); std::cout << at4.GetValue(0) << std::endl; vtkDoubleArray *d = vtkDoubleArray::New(); d->SetArray( const_cast(pts) , at1.GetValue() * at2.GetValue() , 0 ); vtkImageData *img = vtkImageData::New(); img->Initialize(); img->SetDimensions( at2.GetValue(), at1.GetValue(), 1 ); //imgb->SetExtent(1, xdim, 1, ydim, 1, zdim); #if (VTK_MAJOR_VERSION >= 6) assert(0); #else img->SetScalarTypeToDouble(); #endif img->SetSpacing( at3.GetValue(1), at3.GetValue(0), 1); // FIXME image is upside down img->SetOrigin( at4.GetValue(0), at4.GetValue(1), 1); #if (VTK_MAJOR_VERSION >= 6) assert(0); #else img->SetNumberOfScalarComponents(1); #endif img->GetPointData()->SetScalars(d); #if (VTK_MAJOR_VERSION >= 6) #else img->Update(); #endif img->Print(std::cout); vtkXMLImageDataWriter *writeb= vtkXMLImageDataWriter::New(); #if (VTK_MAJOR_VERSION >= 6) writeb->SetInputData( img ); #else writeb->SetInput( img ); #endif writeb->SetFileName( outfilename ); writeb->Write( ); /* (300a,03a6) SQ # u/l,1 Ion Block Sequence (fffe,e000) na (Item with undefined length) (300a,00e1) SH [brass ] # 6,1 Material ID (300a,00f7) FL 95.03 # 4,1 Isocenter to Block Tray Distance (300a,00f8) CS [APERTURE] # 8,1 Block Type (300a,00fa) CS [ABSENT] # 6,1 Block Divergence (300a,00fb) CS [SOURCE_SIDE ] # 12,1 Block Mounting Position (300a,00fc) IS [1 ] # 2,1 Block Number (300a,0100) DS [50.00 ] # 6,1 Block Thickness (300a,0104) IS [179 ] # 4,1 Block Number of Points (300a,0106) DS [1.7\50.0\14.3\50.0\16.7\49.4\18.7\48.2\19.4\47.7\20.1\47.1\21.0\47.0\22.3\47.0\23.7\46.8\25.7\46.2\27.0\45.6\27.2\45.4\28.2\44.6\28.9\44.2\29.7\43.9\31.5\43.5\33.0\42.8\33.7\42.4\35.2\41.3\38.2\40.4\39.6\39.7\40.0\39.5\41.5\37.9\42 2\37.4\43.0\37.1\44.7\36] # 1934,2-2n Block Data (fffe,e00d) (fffe,e0dd) */ gdcm::Tag tblocksq(0x300a,0x03a6); if( !nestedds.FindDataElement( tblocksq ) ) { return 1; } const gdcm::DataElement &blocksq = nestedds.GetDataElement( tblocksq ); //std::cout << blocksq << std::endl; gdcm::SmartPointer sssqi = blocksq.GetValueAsSQ(); const gdcm::Item & item3 = sssqi->GetItem(1); // Item start at #1 const gdcm::DataSet& nestedds3 = item3.GetNestedDataSet(); gdcm::Tag tblockdata(0x300a,0x0106); if( !nestedds3.FindDataElement( tblockdata ) ) { return 1; } const gdcm::DataElement &blockdata = nestedds3.GetDataElement( tblockdata ); // std::cout << blockdata << std::endl; gdcm::Attribute<0x300a,0x0106> at_; at_.SetFromDataElement( blockdata ); vtkDoubleArray *scalars = vtkDoubleArray::New(); scalars->SetNumberOfComponents(3); gdcm::Attribute<0x300a,0x0104> bnpts; // IS [179 ] # 4,1 Block Number of Points if( !nestedds3.FindDataElement( bnpts.GetTag() ) ) { return 1; } const gdcm::DataElement &blocknpts = nestedds3.GetDataElement( bnpts.GetTag() ); bnpts.SetFromDataElement( blocknpts ); //std::cout << bnpts.GetValue() << std::endl; vtkPolyData *output = vtkPolyData::New(); vtkPoints *newPts = vtkPoints::New(); vtkCellArray *polys = vtkCellArray::New(); const double *ptr = at_.GetValues(); //unsigned int npts = bnpts.GetNumberOfValues() / 2; unsigned int npts = bnpts.GetValue(); vtkIdType *ptIds = new vtkIdType[npts]; for(unsigned int i = 0; i < npts; ++i) { float x[3] = {}; x[0] = (float)ptr[2*i+0]; x[1] = (float)ptr[2*i+1]; //x[2] = pts[i+2]; vtkIdType ptId = newPts->InsertNextPoint( x ); //std::cout << x[0] << "," << x[1] << "," << x[2] << std::endl; ptIds[i ] = ptId; } vtkIdType cellId = polys->InsertNextCell(npts , ptIds); (void)cellId; delete[] ptIds; output->SetPoints(newPts); newPts->Delete(); output->SetPolys(polys); polys->Delete(); //output->GetCellData()->SetScalars(scalars); //scalars->Delete(); #if (VTK_MAJOR_VERSION >= 6) #else output->Update(); #endif output->Print( std::cout ); // } vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); vtkImageColorViewer *viewer = vtkImageColorViewer::New(); #if (VTK_MAJOR_VERSION >= 6) viewer->SetInputData(img); #else viewer->SetInput(img); #endif viewer->SetupInteractor(iren); viewer->SetSize(600, 600); viewer->GetRenderer()->ResetCameraClippingRange(); viewer->Render(); viewer->GetRenderer()->ResetCameraClippingRange(); vtkPolyDataMapper *cubeMapper = vtkPolyDataMapper::New(); //vtkPolyDataMapper2D* cubeMapper = vtkPolyDataMapper2D::New(); #if (VTK_MAJOR_VERSION >= 6) cubeMapper->SetInputData( output ); #else cubeMapper->SetInput( output ); #endif cubeMapper->SetScalarRange(0,7); vtkActor *cubeActor = vtkActor::New(); //vtkActor2D* cubeActor = vtkActor2D::New(); cubeActor->SetMapper(cubeMapper); vtkProperty * property = cubeActor->GetProperty(); property->SetRepresentationToWireframe(); viewer->GetRenderer()->AddActor( cubeActor ); vtkXMLPolyDataWriter *writec= vtkXMLPolyDataWriter::New(); #if (VTK_MAJOR_VERSION >= 6) writec->SetInputData( output ); #else writec->SetInput( output ); #endif writec->SetFileName( outfilename2 ); writec->Write( ); iren->Initialize(); iren->Start(); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/gdcmrtplan.cxx000066400000000000000000000274241412732066400221410ustar00rootroot00000000000000/*========================================================================= 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 "vtkImageData.h" #include "vtkPointData.h" #include "vtkPolyData.h" #include "vtkProperty.h" #include "vtkPolyDataMapper.h" #include "vtkActor.h" #include "vtkRenderer.h" #include "vtkCellArray.h" #include "vtkPoints.h" #include "vtkDoubleArray.h" #include #include #include #include "gdcmReader.h" #include "gdcmAttribute.h" /* This example is just for fun. We found a fake RT Ion Plan Storage and simply extracted the viz stuff for VTK but this is rather a RT Plan storage */ int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " filename.dcm outfile.vti\n"; return 1; } const char * filename = argv[1]; const char * outfilename = argv[2]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { return 1; } gdcm::MediaStorage ms; ms.SetFromFile( reader.GetFile() ); if( ms != gdcm::MediaStorage::RTIonPlanStorage ) { return 1; } /* (300a,00b0) SQ # u/l,1 Beam Sequence (fffe,e000) na (Item with undefined length) (300a,00b2) SH (no value) # 0,1 Treatment Machine Name (300a,00c0) IS [1 ] # 2,1 Beam Number (300a,00c2) LO [1 ] # 2,1 Beam Name (300a,00c4) CS [STATIC] # 6,1 Beam Type (300a,00c6) CS [PROTON] # 6,1 Radiation Type (300a,00ce) CS [TREATMENT ] # 10,1 Treatment Delivery Type (300a,00e0) IS [1 ] # 2,1 Number of Compensators (300a,00e3) SQ # u/l,1 Compensator Sequence (fffe,e000) na (Item with undefined length) (300a,00e1) SH [lucite] # 6,1 Material ID (300a,00e4) IS [1 ] # 2,1 Compensator Number (300a,00e5) SH [75hdhe5 ] # 8,1 Compensator ID (300a,00e7) IS [35] # 2,1 Compensator Rows (300a,00e8) IS [37] # 2,1 Compensator Columns (300a,00e9) DS [3.679991\4.249288 ] # 18,2 Compensator Pixel Spacing (300a,00ea) DS [-76.00\62.50] # 12,2 Compensator Position (300a,00ec) DS [52.13\52.13\52.13\53.18\54.04\54.04\47.11\40.06\40.06\38.79\34.87\33.28\33.28\33.28\33.28\35.43\35.43\34.54\34.54\34.71\36.10\38.62\44.88\44.88\44.88\45.00\45.00\45.00\45.66\45.66\46.42\39.77\39.77\39.77\39.77\39.77\43.52\52.13\52.13\52.13\53.18\53.52\54.0] # 7618,1-n Compensator Thickness Data (300a,02e0) CS [ABSENT] # 6,1 Compensator Divergence (300a,02e1) CS [SOURCE_SIDE ] # 12,1 Compensator Mounting Position (fffe,e00d) (fffe,e000) na (Item with undefined length) (fffe,e00d) (fffe,e0dd) */ const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); gdcm::Tag tbeamsq(0x300a,0x00b0); if( !ds.FindDataElement( tbeamsq ) ) { return 1; } const gdcm::DataElement &beamsq = ds.GetDataElement( tbeamsq ); //std::cout << beamsq << std::endl; gdcm::SmartPointer sqi = beamsq.GetValueAsSQ(); if( !sqi || !sqi->GetNumberOfItems() ) { return 1; } //for(unsigned int pd = 0; pd < sqi->GetNumberOfItems(); ++pd) // { //const gdcm::Item & item = sqi->GetItem(1); // Item start at #1 const gdcm::Item & item = sqi->GetItem(2); // Item start at #1 const gdcm::DataSet& nestedds = item.GetNestedDataSet(); //std::cout << nestedds << std::endl; gdcm::Tag tcompensatorsq(0x300a,0x00e3); if( !nestedds.FindDataElement( tcompensatorsq ) ) { return 1; } const gdcm::DataElement &compensatorsq = nestedds.GetDataElement( tcompensatorsq ); //std::cout << compensatorsq << std::endl; gdcm::SmartPointer ssqi = compensatorsq.GetValueAsSQ(); const gdcm::Item & item2 = ssqi->GetItem(1); // Item start at #1 const gdcm::DataSet& nestedds2 = item2.GetNestedDataSet(); //std::cout << nestedds2 << std::endl; gdcm::Tag tcompensatorthicknessdata(0x300a,0x00ec); if( !nestedds2.FindDataElement( tcompensatorthicknessdata ) ) { return 1; } const gdcm::DataElement &compensatorthicknessdata = nestedds2.GetDataElement( tcompensatorthicknessdata ); // std::cout << compensatorthicknessdata << std::endl; gdcm::Attribute<0x300a,0x00ec> at; at.SetFromDataElement( compensatorthicknessdata ); const double* pts = at.GetValues(); // (300a,00e7) IS [35] # 2,1 Compensator Rows gdcm::Attribute<0x300a,0x00e7> at1; const gdcm::DataElement &compensatorrows = nestedds2.GetDataElement( at1.GetTag() ); at1.SetFromDataElement( compensatorrows ); std::cout << at1.GetValue() << std::endl; // (300a,00e8) IS [37] # 2,1 Compensator Columns gdcm::Attribute<0x300a,0x00e8> at2; const gdcm::DataElement &compensatorcols = nestedds2.GetDataElement( at2.GetTag() ); at2.SetFromDataElement( compensatorcols ); std::cout << at2.GetValue() << std::endl; // (300a,00e9) DS [3.679991\4.249288 ] # 18,2 Compensator Pixel Spacing gdcm::Attribute<0x300a,0x00e9> at3; const gdcm::DataElement &compensatorpixelspacing = nestedds2.GetDataElement( at3.GetTag() ); at3.SetFromDataElement( compensatorpixelspacing ); std::cout << at3.GetValue(0) << std::endl; // (300a,00ea) DS [-76.00\62.50] # 12,2 Compensator Position gdcm::Attribute<0x300a,0x00ea> at4; const gdcm::DataElement &compensatorposition = nestedds2.GetDataElement( at4.GetTag() ); at4.SetFromDataElement( compensatorposition ); std::cout << at4.GetValue(0) << std::endl; vtkDoubleArray *d = vtkDoubleArray::New(); d->SetArray( const_cast(pts) , at1.GetValue() * at2.GetValue() , 0 ); vtkImageData *img = vtkImageData::New(); img->Initialize(); img->SetDimensions( at2.GetValue(), at1.GetValue(), 1 ); //imgb->SetExtent(1, xdim, 1, ydim, 1, zdim); #if (VTK_MAJOR_VERSION >= 6) assert(0); #else img->SetScalarTypeToDouble(); #endif img->SetSpacing( at3.GetValue(1), at3.GetValue(0), 1); // FIXME image is upside down img->SetOrigin( at4.GetValue(0), at4.GetValue(1), 1); #if (VTK_MAJOR_VERSION >= 6) assert(0); #else img->SetNumberOfScalarComponents(1); #endif img->GetPointData()->SetScalars(d); vtkXMLImageDataWriter *writeb= vtkXMLImageDataWriter::New(); #if (VTK_MAJOR_VERSION >= 6) writeb->SetInputData( img ); #else writeb->SetInput( img ); #endif writeb->SetFileName( outfilename ); writeb->Write( ); /* (300a,00f4) SQ # u/l,1 Block Sequence (fffe,e000) na (Item with undefined length) (300a,00e1) SH [brass ] # 6,1 Material ID (300a,00f8) CS [APERTURE] # 8,1 Block Type (300a,00fa) CS [ABSENT] # 6,1 Block Divergence (300a,00fb) CS [SOURCE_SIDE ] # 12,1 Block Mounting Position (300a,00fc) IS [1 ] # 2,1 Block Number (300a,0100) DS [50.00 ] # 6,1 Block Thickness (300a,0104) IS [179 ] # 4,1 Block Number of Points (300a,0106) DS [1.7\50.0\14.3\50.0\16.7\49.4\18.7\48.2\19.4\47.7\20.1\47.1\21.0\47.0\22.3\47.0\23.7\46.8\25.7\46.2\27.0\45.6\27.2\45.4\28.2\44.6\28.9\44.2\29.7\43.9\31.5\43.5\33.0\42.8\33.7\42.4\35.2\41.3\38.2\40.4\39.6\39.7\40.0\39.5\41.5\37.9\42.2\37.4\43.0\37.1\44.7\36] # 1934,2-2n Block Data (fffe,e00d) (fffe,e000) na (Item with undefined length) (fffe,e00d) (fffe,e0dd) */ gdcm::Tag tblocksq(0x300a,0x00f4); if( !nestedds.FindDataElement( tblocksq ) ) { return 1; } const gdcm::DataElement &blocksq = nestedds.GetDataElement( tblocksq ); //std::cout << blocksq << std::endl; gdcm::SmartPointer sssqi = blocksq.GetValueAsSQ(); const gdcm::Item & item3 = sssqi->GetItem(1); // Item start at #1 const gdcm::DataSet& nestedds3 = item3.GetNestedDataSet(); gdcm::Tag tblockdata(0x300a,0x0106); if( !nestedds3.FindDataElement( tblockdata ) ) { return 1; } const gdcm::DataElement &blockdata = nestedds3.GetDataElement( tblockdata ); // std::cout << blockdata << std::endl; gdcm::Attribute<0x300a,0x0106> at_; at_.SetFromDataElement( blockdata ); vtkDoubleArray *scalars = vtkDoubleArray::New(); scalars->SetNumberOfComponents(3); gdcm::Attribute<0x300a,0x0104> bnpts; // IS [179 ] # 4,1 Block Number of Points if( !nestedds3.FindDataElement( bnpts.GetTag() ) ) { return 1; } const gdcm::DataElement &blocknpts = nestedds3.GetDataElement( bnpts.GetTag() ); bnpts.SetFromDataElement( blocknpts ); std::cout << bnpts.GetValue() << std::endl; vtkPolyData *output = vtkPolyData::New(); vtkPoints *newPts = vtkPoints::New(); vtkCellArray *polys = vtkCellArray::New(); const double *ptr = at_.GetValues(); //unsigned int npts = bnpts.GetNumberOfValues() / 2; unsigned int npts = bnpts.GetValue(); vtkIdType *ptIds = new vtkIdType[npts]; for(unsigned int i = 0; i < npts; ++i) { float x[3] = {}; x[0] = (float)ptr[2*i+0]; x[1] = (float)ptr[2*i+1]; //x[2] = pts[i+2]; vtkIdType ptId = newPts->InsertNextPoint( x ); //std::cout << x[0] << "," << x[1] << "," << x[2] << std::endl; ptIds[i ] = ptId; } vtkIdType cellId = polys->InsertNextCell(npts , ptIds); (void)cellId; delete[] ptIds; output->SetPoints(newPts); newPts->Delete(); output->SetPolys(polys); polys->Delete(); //output->GetCellData()->SetScalars(scalars); //scalars->Delete(); #if (VTK_MAJOR_VERSION >= 6) #else output->Update(); #endif output->Print( std::cout ); // } vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); vtkImageColorViewer *viewer = vtkImageColorViewer::New(); #if (VTK_MAJOR_VERSION >= 6) viewer->SetInputData(img); #else viewer->SetInput(img); #endif viewer->SetupInteractor(iren); viewer->SetSize(600, 600); viewer->Render(); vtkPolyDataMapper *cubeMapper = vtkPolyDataMapper::New(); //vtkPolyDataMapper2D* cubeMapper = vtkPolyDataMapper2D::New(); #if (VTK_MAJOR_VERSION >= 6) cubeMapper->SetInputData( output ); #else cubeMapper->SetInput( output ); #endif cubeMapper->SetScalarRange(0,7); vtkActor *cubeActor = vtkActor::New(); //vtkActor2D* cubeActor = vtkActor2D::New(); cubeActor->SetMapper(cubeMapper); vtkProperty * property = cubeActor->GetProperty(); property->SetRepresentationToWireframe(); viewer->GetRenderer()->AddActor( cubeActor ); iren->Initialize(); iren->Start(); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/gdcmscene.cxx000066400000000000000000000075141412732066400217340ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMPolyDataReader.h" //#include "vtkGDCMPolyDataWriter.h" #include "vtkAppendPolyData.h" #include "vtkPolyDataWriter.h" #include "vtkPolyDataMapper.h" #include "vtkPolyDataMapper2D.h" #include "vtkActor2D.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkCamera.h" #include "vtkProperty.h" #include "vtkProperty2D.h" // gdcmDataExtra/gdcmNonImageData/exRT_Structure_Set_Storage.dcm // gdcmDataExtra/gdcmNonImageData/RTSTRUCT_1.3.6.1.4.1.22213.1.1396.2.dcm // gdcmDataExtra/gdcmNonImageData/RT/RTStruct.dcm int main(int argc, char *argv[]) { if( argc < 2 ) { std::cerr << argv[0] << " filename1.dcm\n"; return 1; } const char * filename = argv[1]; vtkGDCMPolyDataReader * reader = vtkGDCMPolyDataReader::New(); reader->SetFileName( filename ); reader->Update(); // vtkGDCMPolyDataWriter * writer2 = vtkGDCMPolyDataWriter::New(); // for(int num = 0; num < reader->GetNumberOfOutputPorts(); ++num ) // writer2->SetInput( num, reader->GetOutput(num) ); // writer2->SetFileName( "rtstruct.dcm" ); // writer2->Write(); // print reader output: reader->Print( std::cout ); // print first output: reader->GetOutput()->Print( std::cout ); vtkAppendPolyData *append = vtkAppendPolyData::New(); int n = reader->GetNumberOfOutputPorts(); for(int i = 0; i < n; ++i) { #if (VTK_MAJOR_VERSION >= 6) append->AddInputConnection( reader->GetOutputPort(i) ); #else append->AddInput( reader->GetOutput(i) ); #endif } vtkPolyDataWriter * writer = vtkPolyDataWriter::New(); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputConnection( reader->GetOutputPort() ); #else writer->SetInput( reader->GetOutput() ); #endif writer->SetFileName( "rtstruct.vtk" ); //writer->Write(); // Now we'll look at it. vtkPolyDataMapper *cubeMapper = vtkPolyDataMapper::New(); //vtkPolyDataMapper2D* cubeMapper = vtkPolyDataMapper2D::New(); //cubeMapper->SetInput( reader->GetOutput() ); #if (VTK_MAJOR_VERSION >= 6) cubeMapper->SetInputConnection( append->GetOutputPort() ); #else cubeMapper->SetInput( append->GetOutput() ); #endif cubeMapper->SetScalarRange(0,7); vtkActor *cubeActor = vtkActor::New(); //vtkActor2D* cubeActor = vtkActor2D::New(); cubeActor->SetMapper(cubeMapper); vtkProperty * property = cubeActor->GetProperty(); property->SetRepresentationToWireframe(); //cubeActor->GetProperty()->SetColor(1, 0, 0); // The usual rendering stuff. // vtkCamera *camera = vtkCamera::New(); // camera->SetPosition(1,1,1); // camera->SetFocalPoint(0,0,0); vtkRenderer *renderer = vtkRenderer::New(); vtkRenderWindow *renWin = vtkRenderWindow::New(); renWin->AddRenderer(renderer); vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); iren->SetRenderWindow(renWin); renderer->AddActor(cubeActor); //renderer->AddActor2D(cubeActor); //renderer->SetActiveCamera(camera); renderer->ResetCamera(); renderer->SetBackground(1,1,1); renWin->SetSize(300,300); // interact with data renWin->Render(); iren->Start(); reader->Delete(); append->Delete(); cubeMapper->Delete(); cubeActor->Delete(); // camera->Delete(); renderer->Delete(); renWin->Delete(); iren->Delete(); writer->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/gdcmtexture.cxx000066400000000000000000000101211412732066400223230ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkRenderer.h" #include "vtkAssembly.h" #include "vtkRenderWindow.h" #include "vtkAnnotatedCubeActor.h" #include "vtkTransform.h" #include "vtkAxesActor.h" #include "vtkTextProperty.h" #include "vtkCaptionActor2D.h" #include "vtkPropAssembly.h" #include "vtkOrientationMarkerWidget.h" #include "vtkRenderWindowInteractor.h" #include "vtkPolyDataMapper.h" #include "vtkActor.h" #include "vtkImageData.h" #include "vtkLookupTable.h" #include "vtkTexture.h" #include "vtkPlaneSource.h" int main( int argc, char *argv[] ) { if( argc < 2 ) return 1; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); reader->SetFileName( argv[1] ); reader->Update(); vtkImageData* ima = reader->GetOutput(); vtkLookupTable* table = vtkLookupTable::New(); table->SetNumberOfColors(1000); table->SetTableRange(0,1000); table->SetSaturationRange(0,0); table->SetHueRange(0,1); table->SetValueRange(0,1); table->SetAlphaRange(1,1); table->Build(); // Texture vtkTexture* texture = vtkTexture::New(); #if (VTK_MAJOR_VERSION >= 6) texture->SetInputData(ima); #else texture->SetInput(ima); #endif texture->InterpolateOn(); texture->SetLookupTable(table); // PlaneSource vtkPlaneSource* plane = vtkPlaneSource::New(); plane->SetOrigin( -0.5, -0.5, 0.0); plane->SetPoint1( 0.5, -0.5, 0.0); plane->SetPoint2( -0.5, 0.5, 0.0); // PolyDataMapper vtkPolyDataMapper *planeMapper = vtkPolyDataMapper::New(); #if (VTK_MAJOR_VERSION >= 6) planeMapper->SetInputConnection(plane->GetOutputPort()); #else planeMapper->SetInput(plane->GetOutput()); #endif // Actor vtkActor* planeActor = vtkActor::New(); planeActor->SetTexture(texture); planeActor->SetMapper(planeMapper); planeActor->PickableOn(); // Final rendering with simple interactor: vtkRenderer *ren = vtkRenderer::New(); vtkRenderWindow *renwin = vtkRenderWindow::New(); renwin->AddRenderer(ren); vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); iren->SetRenderWindow(renwin); ren->AddActor(planeActor); ren->SetBackground(0,0,0.5); vtkAnnotatedCubeActor* cube = vtkAnnotatedCubeActor::New(); cube->SetXPlusFaceText ( "L" ); cube->SetXMinusFaceText( "R" ); cube->SetYPlusFaceText ( "A" ); cube->SetYMinusFaceText( "P" ); cube->SetZPlusFaceText ( "H" ); cube->SetZMinusFaceText( "F" ); vtkAxesActor* axes2 = vtkAxesActor::New(); // simulate a left-handed coordinate system // vtkTransform *transform = vtkTransform::New(); transform->Identity(); //transform->RotateY(180); reader->GetDirectionCosines()->Print(std::cout); transform->Concatenate(reader->GetDirectionCosines()); //axes2->SetShaftTypeToCylinder(); axes2->SetUserTransform( transform ); //cube->SetUserTransform( transform ); // cant get it to work cube->GetAssembly()->SetUserTransform( transform ); // cant get it to work vtkPropAssembly* assembly = vtkPropAssembly::New(); assembly->AddPart( axes2 ); assembly->AddPart( cube ); vtkOrientationMarkerWidget* widget = vtkOrientationMarkerWidget::New(); //widget->SetOutlineColor( 0.9300, 0.5700, 0.1300 ); widget->SetOrientationMarker( assembly ); widget->SetInteractor( iren ); //widget->SetViewport( 0.0, 0.0, 0.4, 0.4 ); widget->SetEnabled( 1 ); widget->InteractiveOff(); widget->InteractiveOn(); renwin->Render(); iren->Start(); // Clean up: reader->Delete(); table->Delete(); texture->Delete(); plane->Delete(); planeMapper->Delete(); planeActor->Delete(); ren->Delete(); renwin->Delete(); iren->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/gdcmvolume.cxx000066400000000000000000000055701412732066400221460ustar00rootroot00000000000000/*========================================================================= 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 "vtkVersion.h" #include "vtkGDCMImageReader.h" #include "vtkPiecewiseFunction.h" #include "vtkColorTransferFunction.h" #include "vtkVolume.h" #include "vtkVolumeProperty.h" #if VTK_MAJOR_VERSION < 7 #include "vtkVolumeTextureMapper3D.h" #endif #include "vtkFixedPointVolumeRayCastMapper.h" #include "vtkInteractorStyleTrackballCamera.h" #include "vtkRenderer.h" #include "vtkRenderWindow.h" #include "vtkImageClip.h" #include "vtkRenderWindowInteractor.h" // gdcmvolume gdcmData/GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm int main(int argc, char *argv[]) { if( argc < 2 ) return 1; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); reader->SetFileName( argv[1] ); reader->Update(); // Create the renderers, render window, and interactor vtkRenderWindow *renWin = vtkRenderWindow::New(); vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); iren->SetRenderWindow(renWin); vtkRenderer *ren = vtkRenderer::New(); renWin->AddRenderer(ren); // Create a transfer function mapping scalar value to opacity vtkPiecewiseFunction *oTFun = vtkPiecewiseFunction::New(); //oTFun->AddSegment(0, 1.0, 256, 0.1); oTFun->AddSegment(0, 1.0, 240, 0.1); vtkColorTransferFunction *cTFun = vtkColorTransferFunction::New(); cTFun->AddRGBPoint( 0, 1.0, 1.0, 1.0 ); //cTFun->AddRGBPoint( 255, 1.0, 1.0, 1.0 ); cTFun->AddRGBPoint( 240, 1.0, 1.0, 1.0 ); // Need to crop to actually see minimum intensity vtkImageClip *clip = vtkImageClip::New(); clip->SetInputConnection( reader->GetOutputPort() ); clip->SetOutputWholeExtent(0,66,0,66,30,37); clip->ClipDataOn(); vtkVolumeProperty *property = vtkVolumeProperty::New(); property->SetScalarOpacity(oTFun); property->SetColor(cTFun); property->SetInterpolationTypeToLinear(); vtkFixedPointVolumeRayCastMapper *mapper = vtkFixedPointVolumeRayCastMapper::New(); mapper->SetBlendModeToMinimumIntensity(); mapper->SetInputConnection( reader->GetOutputPort() ); vtkVolume *volume = vtkVolume::New(); volume->SetMapper(mapper); volume->SetProperty(property); ren->AddViewProp(volume); renWin->Render(); { iren->Start(); } volume->Delete(); mapper->Delete(); property->Delete(); clip->Delete(); cTFun->Delete(); oTFun->Delete(); reader->Delete(); renWin->Delete(); iren->Delete(); ren->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/offscreenimage.cxx000066400000000000000000000047601412732066400227610ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkImageMapToWindowLevelColors.h" #include "vtkImageActor.h" #include "vtkPNGWriter.h" #include "vtkWindowToImageFilter.h" #include "vtkMedicalImageProperties.h" int main(int argc, char *argv[]) { if( argc < 2 ) { return 1; } const char *filename = argv[1]; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); reader->SetFileName( filename ); reader->Update(); // important to read the window/level info vtkMedicalImageProperties *prop = reader->GetMedicalImageProperties(); vtkRenderWindow *renWin = vtkRenderWindow::New(); renWin->OffScreenRenderingOn(); vtkRenderer *renderer = vtkRenderer::New(); renWin->AddRenderer(renderer); vtkImageMapToWindowLevelColors *windowlevel = vtkImageMapToWindowLevelColors::New(); #if (VTK_MAJOR_VERSION >= 6) windowlevel->SetInputConnection( reader->GetOutputPort() ); #else windowlevel->SetInput( reader->GetOutput() ); #endif unsigned int n = prop->GetNumberOfWindowLevelPresets(); if( n ) { // Take the first one by default: const double *wl = prop->GetNthWindowLevelPreset(0); windowlevel->SetWindow( wl[0] ); windowlevel->SetLevel( wl[1] ); } vtkImageActor *actor = vtkImageActor::New(); #if (VTK_MAJOR_VERSION >= 6) actor->SetInputData( windowlevel->GetOutput() ); #else actor->SetInput( windowlevel->GetOutput() ); #endif renderer->AddActor( actor ); renWin->Render(); vtkWindowToImageFilter *w2if = vtkWindowToImageFilter::New(); w2if->SetInput ( renWin ); vtkPNGWriter *wr = vtkPNGWriter::New(); #if (VTK_MAJOR_VERSION >= 6) wr->SetInputConnection( w2if->GetOutputPort() ); #else wr->SetInput( w2if->GetOutput() ); #endif wr->SetFileName ( "offscreenimage.png" ); wr->Write(); reader->Delete(); renWin->Delete(); renderer->Delete(); windowlevel->Delete(); actor->Delete(); w2if->Delete(); wr->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/reslicesphere.cxx000066400000000000000000000471561412732066400226470ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // // Load a DICOM series. // Position a sphere within the volume. // Allow the user to change between Axial, Sagittal, Coronal, and // Oblique view of the images and move through the slices. // The display should show the resliced image and the cross section // of the sphere intersecting that plane. // /* from Scott Johnson /Scott Johnson neuwave com/ to VTK /vtkusers vtk.org/ date Tue, May 11, 2010 at 7:01 PM */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vtkTransformPolyDataFilter.h" #include #include #include #include #include #include #include #include #include #include "gdcmDirectory.h" #include "gdcmTesting.h" #include "gdcmIPPSorter.h" // Change to match the path to find Raw_0.vti or provide // the parameter when starting ResliceSphere. const double sphereCenter[3]={74, 219, 70}; // Angles (0, 0, 0) const double AxialMatrix[] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 }; // Angles (0, 90, 0) const double SagittalMatrix[] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 }; // Angles (-90, 0, 0) const double CoronalMatrix[] = { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 }; // Angles (0, 90, 31) const double ObliqueMatrix[] = { 0.0, -0.515038, 0.857167, 0.0, 0.0, 0.857167, 0.515038, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 }; class ResliceRender; // Class to handle key press events. class KeyCallback : public vtkCommand { public: static KeyCallback* New() { return new KeyCallback(); } void Execute(vtkObject* caller, unsigned long eventId, void *calldata); void SetCallbackData(ResliceRender* reslice); protected: ResliceRender* _reslice; }; class ResliceRender { public: typedef enum _ORIENTATION { AXIAL = 0, SAGITTAL = 1, CORONAL = 2, OBLIQUE = 3 } ORIENTATION; ResliceRender() { _orientation=AXIAL; } ~ResliceRender() { _transform->Delete(); _reader->Delete(); _reslice->Delete(); _interactor->Delete(); _imageViewer->Delete(); _sphere->Delete(); _sphereMapper->Delete(); _sphereActor->Delete(); _plane->Delete(); _cutter->Delete(); _polyTransform->Delete(); _ROIMapper->Delete(); _ROIActor->Delete(); _annotation->Delete(); } void CreatePipeline(const char* fileName) { vtkProperty2D* props; //_reader=vtkXMLImageDataReader::New(); //_reader->SetFileName(fileName); //_reader->Update(); //_reader=qzDICOMImageReader::New(); _reader=vtkGDCMImageReader::New(); //vtkDirectory *d = vtkDirectory::New(); //d->Open(fileName); //d->Print( std::cout ); gdcm::Directory d; d.Load(fileName); gdcm::Directory::FilenamesType const &files = d.GetFilenames(); gdcm::IPPSorter s; s.SetComputeZSpacing( true ); s.SetZSpacingTolerance( 1e-3 ); bool b = s.Sort( files ); if( !b ) { std::cerr << "Failed to sort:" << fileName << std::endl; //return ; } //std::cout << "Sorting succeeded:" << std::endl; //s.Print( std::cout ); //std::cout << "Found z-spacing:" << std::endl; //std::cout << s.GetZSpacing() << std::endl; double ippzspacing = s.GetZSpacing(); const std::vector & sorted = s.GetFilenames(); vtkStringArray *vtkfiles = vtkStringArray::New(); std::vector< std::string >::const_iterator it = sorted.begin(); for( ; it != sorted.end(); ++it) { const std::string &f = *it; vtkfiles->InsertNextValue( f.c_str() ); } //_reader->SetDirectoryName(fileName); //_reader->SetFileNames( d->GetFiles() ); _reader->SetFileNames( vtkfiles ); _reader->Update(); const vtkFloatingPointType *spacing = _reader->GetOutput()->GetSpacing(); vtkImageChangeInformation *v16 = vtkImageChangeInformation::New(); #if (VTK_MAJOR_VERSION >= 6) v16->SetInputConnection( _reader->GetOutputPort() ); #else v16->SetInput( _reader->GetOutput() ); #endif v16->SetOutputSpacing( spacing[0], spacing[1], ippzspacing ); v16->Update(); _threshold=vtkImageThreshold::New(); _threshold->ThresholdByUpper(-3024.0); _threshold->ReplaceOutOn(); _threshold->SetOutValue(0.0); _threshold->SetInputConnection(v16->GetOutputPort()); _shift=vtkImageShiftScale::New(); _shift->SetShift(0); _shift->SetScale(1); _shift->SetInputConnection(_threshold->GetOutputPort()); // Initialize the reslice with an axial orientation. vtkSmartPointer matrix = vtkSmartPointer::New(); matrix->Identity(); _transform = vtkTransform::New(); _transform->SetMatrix(matrix); _reslice = vtkImageReslice::New(); _reslice->SetOutputDimensionality(3); // PROBLEM: // The original intent was to connect the same transform // to the vtkImageReslice and vtkTransformPolyDataFilter, // but the resulting reslices appear different using the // vtkTransform as opposed to explicitly setting the // reslice axes via SetResliceAxes. Also, if the vtkTransform // is connected and orientated other than axial, the extents // don't seem to update resulting in VTK believing the slice // is out of range. //_reslice->SetResliceTransform(_transform); _reslice->SetResliceAxes(matrix); //_reslice->SetInputConnection(_reader->GetOutputPort()); _reslice->SetInputConnection(_shift->GetOutputPort()); // Create the sphere target shape. _sphere=vtkSphereSource::New(); _sphere->SetRadius(7.0); _sphere->SetThetaResolution(16); _sphere->SetPhiResolution(16); _sphere->SetCenter(sphereCenter[0], sphereCenter[1], sphereCenter[2]); _sphereMapper=vtkPolyDataMapper::New(); _sphereMapper->SetInputConnection(_sphere->GetOutputPort()); _sphereActor=vtkActor::New(); _sphereActor->SetMapper(_sphereMapper); _sphereActor->PickableOff(); _sphereActor->GetProperty()->SetColor(1.0, 0.0, 0.0); _sphereActor->GetProperty()->SetEdgeColor(1.0, 0.0, 0.0); _sphereActor->GetProperty()->SetDiffuseColor(1.0, 0.0, 0.0); _sphereActor->SetVisibility(true); // Create the cutting pipeline. // This plane will be positioned in the original image coordinate system. _plane = vtkPlane::New(); _plane->SetNormal(0.0, 0.0, 1.0); _cutter = vtkCutter::New(); _cutter->SetInputConnection(_sphere->GetOutputPort()); _cutter->SetCutFunction(_plane); _cutter->GenerateCutScalarsOn(); _cutter->SetValue(0, 0.5); // The transform attached to _polyTransform should move the cut // ROI into the resliced coordinate system, which should be the // same as the coordinate system of the resliced images. // PROBLEM: It doesn't. _polyTransform = vtkTransformPolyDataFilter::New(); _polyTransform->SetTransform(_transform); _polyTransform->SetInputConnection(_cutter->GetOutputPort()); _ROIMapper = vtkPolyDataMapper2D::New(); _ROIMapper->SetInputConnection(_polyTransform->GetOutputPort()); vtkCoordinate* coordinate = vtkCoordinate::New(); coordinate->SetCoordinateSystemToWorld(); _ROIMapper->SetTransformCoordinate(coordinate); _ROIActor = vtkActor2D::New(); _ROIActor->SetMapper(_ROIMapper); // Make sure the cut can be seen, especially the edges. props=_ROIActor->GetProperty(); props->SetLineWidth(2); props->SetOpacity(1.0); // props->EdgeVisibilityOn(); // props->SetDiffuse(0.8); // props->SetSpecular(0.3); // props->SetSpecularPower(20); // props->SetRepresentationToSurface(); // props->SetDiffuseColor(1.0, 0.0, 0.0); // props->SetEdgeColor(1.0, 0.0, 0.0); props->SetColor(1.0, 0.0, 0.0); _interactor = vtkRenderWindowInteractor::New(); // Create the image viewer and add the actor with the cut ROI. _imageViewer = vtkImageViewer2::New(); _imageViewer->SetupInteractor(_interactor); _imageViewer->SetSize(400, 400); _imageViewer->SetColorWindow(1024); _imageViewer->SetColorLevel(800); _imageViewer->SetInputConnection(_reslice->GetOutputPort()); _imageViewer->GetImageActor()->SetOpacity(0.5); _annotation = vtkTextActor::New(); _annotation->SetTextScaleModeToViewport(); _imageViewer->GetRenderer()->AddActor(_annotation); // Add the cut shape actor to the renderer. _imageViewer->GetRenderer()->AddActor(_ROIActor); // Set up the key handler. vtkSmartPointer callback = vtkSmartPointer::New(); callback->SetCallbackData(this); _interactor->AddObserver(vtkCommand::KeyPressEvent, callback); _interactor->Initialize(); } void Start() { _interactor->Start(); } void ResetOrientation() { vtkSmartPointer matrix = vtkSmartPointer::New(); matrix->Identity(); SetOrientation(matrix); } // Make sure the orientation of the vtkImageReslice and // vtkTransform are in sync. void SetOrientation(vtkMatrix4x4* matrix) { _reslice->SetResliceAxes(matrix); _reslice->Update(); vtkMatrix4x4* inverse = vtkMatrix4x4::New(); vtkMatrix4x4::Invert(matrix, inverse); _transform->SetMatrix(inverse); _transform->Update(); } // Set the current slice of the current view. void SetSlice(int slice) { std::strstream posString; double center[3]; double spacing[3]; double origin[3]; double point[4]; double newPoint[4]; vtkImageData* imageData; int newSlice; // Try to make sure the extents of the reslice are updated. // PROBLEM: It doesn't seem to work when changing the orientation. imageData=vtkImageData::SafeDownCast(_reslice->GetOutput()); #if (VTK_MAJOR_VERSION >= 6) assert(0); #else imageData->UpdateInformation(); #endif // Let vtkImageViewer2 handle the slice limits. _imageViewer->SetSlice(slice); newSlice=GetSlice(); imageData->GetCenter(center); imageData->GetSpacing(spacing); imageData->GetOrigin(origin); // Compute the position of the center of the slice based on the // spacing of the slices. The resliced axis will always // be the "Z" axis. point[0]=center[0]; point[1]=center[1]; point[2]=(newSlice * spacing[2]) + origin[2]; point[3]=1.0; // Convert the coordinate from the reslice coordinate system to the // original image coordinate system. // PROBLEM: Logically this seems like it should have been multiplied // by the inverse to translate from the resliced coordinate system to // the original coordinate system. However, multiplying by the inverse // sticks the plane in the wrong place completely. Using the original // matrix at least gets the Z coordinate right. vtkMatrix4x4* matrix=_reslice->GetResliceAxes(); vtkSmartPointer inverse = vtkSmartPointer::New(); vtkMatrix4x4::Invert(matrix, inverse); matrix->MultiplyPoint(point, newPoint); _plane->SetOrigin(newPoint[0], newPoint[1], newPoint[2]); // Annotate the image. posString << "Position: (" << newPoint[0] << ", " << newPoint[1] << ", " << newPoint[2] << ") Slice: " << newSlice; _annotation->SetInput(posString.str()); _imageViewer->Render(); } int GetSlice() { return _imageViewer->GetSlice(); } // Set the orientation of the view. void SetOrientation(ResliceRender::ORIENTATION orientation) { vtkCamera* camera=_imageViewer->GetRenderer()->GetActiveCamera(); double spacing[3]; double origin[3]; double point[4]; double newPoint[4]; double initialPosition; double xDirCosine[3]; double yDirCosine[3]; double zDirCosine[3]; double normal[3]; vtkImageData* imageData; vtkSmartPointer matrix = vtkSmartPointer::New(); _orientation=orientation; // Reset ViewUp camera->SetViewUp(0.0, 1.0, 0.0); // Compute the cut plane position to the input coordinate system. imageData=vtkImageData::SafeDownCast(_reslice->GetInput()); #if (VTK_MAJOR_VERSION >= 6) assert(0); #else imageData->UpdateInformation(); #endif imageData->GetSpacing(spacing); imageData->GetOrigin(origin); point[0]=origin[0]; point[1]=origin[1]; point[2]=origin[2]; point[3]=1.0; switch (_orientation) { case AXIAL: matrix->DeepCopy(AxialMatrix); initialPosition=sphereCenter[2]; break; case CORONAL: matrix->DeepCopy(CoronalMatrix); initialPosition=sphereCenter[1]; break; case SAGITTAL: matrix->DeepCopy(SagittalMatrix); initialPosition=sphereCenter[0]; break; case OBLIQUE: matrix->DeepCopy(ObliqueMatrix); initialPosition=sphereCenter[2]; break; } // Move the origin from the original image coordinate system to the // resliced image coordinate system. matrix->MultiplyPoint(point, newPoint); matrix->SetElement(0, 3, newPoint[0]); matrix->SetElement(1, 3, newPoint[1]); matrix->SetElement(2, 3, newPoint[2]); ResetOrientation(); SetOrientation(matrix); // Compute the cutting plane normal and set it. // PROBLEM: If the transformation is connected rather than // using SetResliceAxes, the Direction Cosines do not reflect // the orientation of the vtkImageReslice. _reslice->GetResliceAxesDirectionCosines(xDirCosine, yDirCosine, zDirCosine); vtkMath::Cross(xDirCosine, yDirCosine, normal); _plane->SetNormal(normal); // Set the extents and spacing of the reslice to account for // all of the data. _reslice->SetOutputExtentToDefault(); _reslice->SetOutputSpacing(spacing[0], spacing[0], spacing[0]); // Force the vtkImageViewer2 to update. // PROBLEM: The whole extent does not seem to be set in time // for the first render. This results in an error because the // slice is positioned outside the old bounds. #if (VTK_MAJOR_VERSION >= 6) _imageViewer->SetInputData(NULL); #else _imageViewer->SetInput(NULL); #endif _imageViewer->SetInputConnection(_reslice->GetOutputPort()); _imageViewer->GetRenderer()->ResetCameraClippingRange(); _imageViewer->GetRenderer()->ResetCamera(); // Set the initial slice to be at the center of the sphere. // Divide by the spacing because this will be undone in SetSlice. SetSlice( (int)(initialPosition / spacing[0])); } vtkRenderWindowInteractor* GetInteractor() { return _interactor; } protected: ORIENTATION _orientation; //qzDICOMImageReader* _reader; vtkGDCMImageReader* _reader; vtkImageThreshold* _threshold; vtkImageShiftScale* _shift; vtkImageReslice* _reslice; vtkRenderWindowInteractor* _interactor; vtkImageViewer2* _imageViewer; vtkSphereSource* _sphere; vtkPolyDataMapper* _sphereMapper; vtkActor* _sphereActor; vtkPlane* _plane; vtkCutter* _cutter; vtkTransform* _transform; vtkTransformPolyDataFilter* _polyTransform; vtkPolyDataMapper2D* _ROIMapper; vtkActor2D* _ROIActor; vtkTextActor* _annotation; }; // Catch KeyPress events. // Up Arrow - increases the slice // Down Arrow - decreases the slice // 'A' - sets the view to Axial // 'S' - sets the view to Sagittal // 'C' - sets the view to Coronal // 'O' - set the view to Oblique void KeyCallback::Execute(vtkObject* caller, unsigned long eventId, void *calldata) { (void)caller; (void)eventId; (void)calldata; std::string sym=_reslice->GetInteractor()->GetKeySym(); if (!sym.compare("Up")) { _reslice->SetSlice(_reslice->GetSlice() + 1); } else if (!sym.compare("Down")) { _reslice->SetSlice(_reslice->GetSlice() - 1); } else if ((!sym.compare("A")) || (!sym.compare("a"))) { _reslice->SetOrientation(ResliceRender::AXIAL); } else if ((!sym.compare("C")) || (!sym.compare("c"))) { _reslice->SetOrientation(ResliceRender::CORONAL); } else if ((!sym.compare("S")) || (!sym.compare("s"))) { _reslice->SetOrientation(ResliceRender::SAGITTAL); } else if ((!sym.compare("O")) || (!sym.compare("o"))) { _reslice->SetOrientation(ResliceRender::OBLIQUE); } } void KeyCallback::SetCallbackData(ResliceRender* reslice) { _reslice=reslice; } // Usage: ResliceSphere [fileName] int main(int argc, char *argv[]) { ResliceRender render; if (argc == 1) { const char *root = gdcm::Testing::GetDataExtraRoot(); std::string dir3 = root; dir3 += "/gdcmSampleData/ForSeriesTesting/Dentist/images/"; render.CreatePipeline(dir3.c_str()); } else { render.CreatePipeline(argv[1]); } render.SetOrientation(ResliceRender::AXIAL); render.Start(); return EXIT_SUCCESS; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/rtstructapp.cxx000066400000000000000000000073011412732066400223710ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMPolyDataReader.h" #include "vtkGDCMPolyDataWriter.h" #include "vtkPolyDataWriter.h" #include "vtkPolyDataMapper.h" #include "vtkPolyDataMapper2D.h" #include "vtkActor2D.h" #include "vtkRenderWindowInteractor.h" #include "vtkMedicalImageProperties.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkCamera.h" #include "vtkProperty.h" #include "vtkProperty2D.h" #include "vtkAppendPolyData.h" #include "vtkImageData.h" /* * Small example to read in a RTSTUCT and write it out (displays it too). */ // gdcmDataExtra/gdcmNonImageData/exRT_Structure_Set_Storage.dcm // gdcmDataExtra/gdcmNonImageData/RTSTRUCT_1.3.6.1.4.1.22213.1.1396.2.dcm // gdcmDataExtra/gdcmNonImageData/RT/RTStruct.dcm int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.dcm\n"; return 1; } const char * filename = argv[1]; const char * outfilename = argv[2]; vtkGDCMPolyDataReader * reader = vtkGDCMPolyDataReader::New(); reader->SetFileName( filename ); reader->Update(); //std::cout << reader->GetMedicalImageProperties()->GetStudyDate() << std::endl; vtkGDCMPolyDataWriter * writer = vtkGDCMPolyDataWriter::New(); writer->SetNumberOfInputPorts( reader->GetNumberOfOutputPorts() ); writer->SetFileName( outfilename ); for(int num = 0; num < reader->GetNumberOfOutputPorts(); ++num ) #if (VTK_MAJOR_VERSION >= 6) writer->SetInputConnection( num, reader->GetOutputPort(num) ); #else writer->SetInput( num, reader->GetOutput(num) ); #endif //doesn't look like the medical properties are actually written out writer->SetMedicalImageProperties( reader->GetMedicalImageProperties() ); writer->SetRTStructSetProperties( reader->GetRTStructSetProperties() ); writer->Write(); // print reader output: reader->Print( std::cout ); // print first output: reader->GetOutput()->Print( std::cout ); vtkAppendPolyData *append = vtkAppendPolyData::New(); int n = reader->GetNumberOfOutputPorts(); for(int i = 0; i < n; ++i) { #if (VTK_MAJOR_VERSION >= 6) append->AddInputConnection( reader->GetOutputPort(i) ); #else append->AddInput( reader->GetOutput(i) ); #endif } // Now we'll look at it. vtkPolyDataMapper *cubeMapper = vtkPolyDataMapper::New(); #if (VTK_MAJOR_VERSION >= 6) cubeMapper->SetInputConnection( append->GetOutputPort()); #else cubeMapper->SetInput( append->GetOutput()); #endif cubeMapper->SetScalarRange(0,7); vtkActor *cubeActor = vtkActor::New(); cubeActor->SetMapper(cubeMapper); vtkProperty * property = cubeActor->GetProperty(); property->SetRepresentationToWireframe(); vtkRenderer *renderer = vtkRenderer::New(); vtkRenderWindow *renWin = vtkRenderWindow::New(); renWin->AddRenderer(renderer); vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); iren->SetRenderWindow(renWin); renderer->AddActor(cubeActor); renderer->ResetCamera(); renderer->SetBackground(1,1,1); renWin->SetSize(300,300); renWin->Render(); iren->Start(); reader->Delete(); append->Delete(); cubeMapper->Delete(); cubeActor->Delete(); renderer->Delete(); renWin->Delete(); iren->Delete(); writer->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Cxx/threadgdcm.cxx000066400000000000000000000166531412732066400221120ustar00rootroot00000000000000/*========================================================================= 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 "gdcmReader.h" #include "gdcmImageReader.h" #include "gdcmDirectory.h" #include "gdcmSystem.h" #include "vtkImageData.h" #include "vtkStructuredPointsWriter.h" #include struct threadparams { const char **filenames; size_t nfiles; char *scalarpointer; // TODO I should also pass in the dim of the reference image just in case }; void *ReadFilesThread(void *voidparams) { const threadparams *params = static_cast (voidparams); const size_t nfiles = params->nfiles; for(unsigned int file = 0; file < nfiles; ++file) { /* // TODO: update progress pthread_mutex_lock(¶ms->lock); //section critique ReadingProgress+=params->stepProgress; pthread_mutex_unlock(¶ms->lock); */ const char *filename = params->filenames[file]; //std::cerr << filename << std::endl; gdcm::ImageReader reader; reader.SetFileName( filename ); try { if( !reader.Read() ) { std::cerr << "Failed to read: " << filename << std::endl; break; } } catch( ... ) { std::cerr << "Failed to read: " << filename << std::endl; break; } const gdcm::Image &image = reader.GetImage(); unsigned long len = image.GetBufferLength(); char * pointer = params->scalarpointer; #if 0 char *tempimage = new char[len]; image.GetBuffer(tempimage); memcpy(pointer + file*len, tempimage, len); delete[] tempimage; #else char *tempimage = pointer + file * len; image.GetBuffer(tempimage); #endif } return voidparams; } void ShowFilenames(const threadparams ¶ms) { std::cout << "start" << std::endl; for(unsigned int i = 0; i < params.nfiles; ++i) { const char *filename = params.filenames[i]; std::cout << filename << std::endl; } std::cout << "end" << std::endl; } void ReadFiles(size_t nfiles, const char *filenames[]) { // \precondition: nfiles > 0 assert( nfiles > 0 ); const char *reference= filenames[0]; // take the first image as reference gdcm::ImageReader reader; reader.SetFileName( reference ); if( !reader.Read() ) { // That would be very bad... assert(0); } const gdcm::Image &image = reader.GetImage(); gdcm::PixelFormat pixeltype = image.GetPixelFormat(); unsigned long len = image.GetBufferLength(); const unsigned int *dims = image.GetDimensions(); unsigned short pixelsize = pixeltype.GetPixelSize(); (void)pixelsize; assert( image.GetNumberOfDimensions() == 2 ); vtkImageData *output = vtkImageData::New(); output->SetDimensions(dims[0], dims[1], (int)nfiles); #if (VTK_MAJOR_VERSION >= 6) int numscal = pixeltype.GetSamplesPerPixel(); switch( pixeltype ) { case gdcm::PixelFormat::INT8: output->AllocateScalars( VTK_SIGNED_CHAR, numscal ); break; case gdcm::PixelFormat::UINT8: output->AllocateScalars( VTK_UNSIGNED_CHAR, numscal ); break; case gdcm::PixelFormat::INT16: output->AllocateScalars( VTK_SHORT, numscal ); break; case gdcm::PixelFormat::UINT16: output->AllocateScalars( VTK_UNSIGNED_SHORT, numscal ); break; case gdcm::PixelFormat::INT32: output->AllocateScalars( VTK_INT, numscal ); break; case gdcm::PixelFormat::UINT32: output->AllocateScalars( VTK_UNSIGNED_INT, numscal ); break; default: assert(0); } #else switch( pixeltype ) { case gdcm::PixelFormat::INT8: #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) output->SetScalarType ( VTK_SIGNED_CHAR ); #else output->SetScalarType ( VTK_CHAR ); #endif break; case gdcm::PixelFormat::UINT8: output->SetScalarType ( VTK_UNSIGNED_CHAR ); break; case gdcm::PixelFormat::INT16: output->SetScalarType ( VTK_SHORT ); break; case gdcm::PixelFormat::UINT16: output->SetScalarType ( VTK_UNSIGNED_SHORT ); break; case gdcm::PixelFormat::INT32: output->SetScalarType ( VTK_INT ); break; case gdcm::PixelFormat::UINT32: output->SetScalarType ( VTK_UNSIGNED_INT ); break; default: assert(0); } output->SetNumberOfScalarComponents ( pixeltype.GetSamplesPerPixel() ); output->AllocateScalars(); #endif char * scalarpointer = static_cast(output->GetScalarPointer()); const unsigned int nthreads = 4; threadparams params[nthreads]; //pthread_mutex_t lock; //pthread_mutex_init(&lock, NULL); pthread_t *pthread = new pthread_t[nthreads]; // There is nfiles, and nThreads assert( nfiles > nthreads ); const size_t partition = nfiles / nthreads; for (unsigned int thread=0; thread < nthreads; ++thread) { params[thread].filenames = filenames + thread * partition; params[thread].nfiles = partition; if( thread == nthreads - 1 ) { // There is slightly more files to process in this thread: params[thread].nfiles += nfiles % nthreads; } assert( thread * partition < nfiles ); params[thread].scalarpointer = scalarpointer + thread * partition * len; //assert( params[thread].scalarpointer < scalarpointer + 2 * dims[0] * dims[1] * dims[2] ); // start thread: int res = pthread_create( &pthread[thread], NULL, ReadFilesThread, ¶ms[thread]); if( res ) { std::cerr << "Unable to start a new thread, pthread returned: " << res << std::endl; assert(0); } //ShowFilenames(params[thread]); } // DEBUG size_t total = 0; for (unsigned int thread=0; thread < nthreads; ++thread) { total += params[thread].nfiles; } assert( total == nfiles ); // END DEBUG for (unsigned int thread=0;thread= 6) writer->SetInputData( output ); #else writer->SetInput( output ); #endif writer->SetFileName( "/tmp/threadgdcm.vtk" ); writer->SetFileTypeToBinary(); //writer->Write(); writer->Delete(); //output->Print( std::cout ); output->Delete(); } int main(int argc, char *argv[]) { if( argc < 2 ) { std::cerr << argv[0] << " [directory|list of filenames]\n"; return 1; } // Check if user pass in a single directory if( argc == 2 && gdcm::System::FileIsDirectory( argv[1] ) ) { gdcm::Directory d; d.Load( argv[1] ); gdcm::Directory::FilenamesType l = d.GetFilenames(); const size_t nfiles = l.size(); const char **filenames = new const char* [ nfiles ]; for(unsigned int i = 0; i < nfiles; ++i) { filenames[i] = l[i].c_str(); } ReadFiles(nfiles, filenames); delete[] filenames; } else { // Simply copy all filenames into the vector: const char **filenames = const_cast(argv+1); const size_t nfiles = argc - 1; ReadFiles(nfiles, filenames); } return 0; } GDCM-3.0.10/Utilities/VTK/Examples/Java/000077500000000000000000000000001412732066400173705ustar00rootroot00000000000000GDCM-3.0.10/Utilities/VTK/Examples/Java/AWTMedical3.java000066400000000000000000000313701412732066400222340ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ package examples; import vtk.*; //import gdcm.*; import vtk.util.VtkPanelContainer; import vtk.util.VtkPanelUtil; import vtk.util.VtkUtil; import java.util.ArrayList; import javax.swing.*; import java.awt.*; import java.io.File; /** * * This class should show how to read an image and display it * using gdcm and vtk, similar to gdcmorthoplanes * * used to test the transition from vtk 5.6 to vtk 5.9 * @author mmroden */ public class AWTMedical3 extends JComponent implements VtkPanelContainer { private vtkPanel renWin; vtkImageData ReadDataFile(File inSelectedFile){ vtkImageData outImageData = null; Directory theDir = new Directory(); String theInputDirectory = inSelectedFile.getPath(); theDir.Load(theInputDirectory); Scanner theScanner = new Scanner(); Tag theStudyTag = new Tag(0x0020,0x000d); Tag theSeriesTag = new Tag(0x0020,0x000e); theScanner.AddTag(theStudyTag);//get studies, theScanner.AddTag(theSeriesTag);//get studies, theScanner.Scan(theDir.GetFilenames()); FilenamesType theStudyValues = theScanner.GetOrderedValues(theStudyTag); long theNumStudies = theStudyValues.size(); //for now, take the first study, and nothing else. //and the return is actually not FilenamesType, just a //vector of strings if (theNumStudies != 1) return outImageData; String theStudyVal = theStudyValues.get(0); //now, get all the values from the scanner that are in that //study, then from that get their different series FilenamesType theFilenames = theScanner.GetAllFilenamesFromTagToValue(theStudyTag, theStudyVal); //from that set of filenames, isolate individual series //conclude that singleton series = RT struct (can do further //checking for things like MIPs and the like) //and multiple series entries = volumetric data theScanner.Scan(theFilenames); FilenamesType theSeriesValues = theScanner.GetOrderedValues(theSeriesTag); String studyUID = theScanner.GetValue(theScanner.GetFilenames().get(0), theStudyTag); long theNumSeries = theSeriesValues.size(); for (int i = 0; i < theNumSeries; i++) { FilenamesType theSeriesFiles = theScanner.GetAllFilenamesFromTagToValue(theSeriesTag, theSeriesValues.get(i)); long theNumFilesInSeries = theSeriesFiles.size(); if (theNumFilesInSeries > 1) {//assume it's CT or volumetric data //for now, assume a single volume //could have multiples, like PET and CT IPPSorter sorter = new IPPSorter(); sorter.SetComputeZSpacing(true); sorter.SetZSpacingTolerance(0.001); Boolean sorted = sorter.Sort(theSeriesFiles); if (!sorted){ //need some better way to handle failures here return outImageData; } FilenamesType sortedFT = sorter.GetFilenames(); long theSize = sortedFT.size(); vtkStringArray sa = new vtkStringArray(); ArrayList theStrings = new ArrayList(); vtkGDCMImageReader gdcmReader = new vtkGDCMImageReader(); for (int j = 0; j < theSize; j++) { String theFileName = sortedFT.get(j); if (gdcmReader.CanReadFile(theFileName) > 0){ theStrings.add(theFileName); sa.InsertNextValue(theFileName); } else { //this is a busted series //need some more appropriate error here return outImageData; } } gdcmReader.SetFileNames(sa); gdcmReader.Update(); outImageData = gdcmReader.GetOutput();//the zeroth output should be the image } } String theImageInfo = ""; if (outImageData != null){ theImageInfo = outImageData.Print(); } return outImageData; } //this function is a rewrite of Medical3 to see if data can //be loaded via gdcm easily public AWTMedical3(File inFile) { // Create the buttons. renWin = new vtkPanel(); vtkImageData theImageData = ReadDataFile(inFile); // An isosurface, or contour value of 500 is known to correspond to the // skin of the patient. Once generated, a vtkPolyDataNormals filter is // is used to create normals for smooth surface shading during rendering. // The triangle stripper is used to create triangle strips from the // isosurface these render much faster on some systems. vtkContourFilter skinExtractor = new vtkContourFilter(); skinExtractor.SetInput(theImageData); skinExtractor.SetValue(0, 500); vtkPolyDataNormals skinNormals = new vtkPolyDataNormals(); skinNormals.SetInput(skinExtractor.GetOutput()); skinNormals.SetFeatureAngle(60.0); // vtkStripper skinStripper = new vtkStripper(); // skinStripper.SetInput(skinNormals.GetOutput()); vtkPolyDataMapper skinMapper = new vtkPolyDataMapper(); skinMapper.SetInput(skinNormals.GetOutput()); skinMapper.ScalarVisibilityOff(); vtkActor skin = new vtkActor(); skin.SetMapper(skinMapper); skin.GetProperty().SetDiffuseColor(1, .49, .25); skin.GetProperty().SetSpecular(.3); skin.GetProperty().SetSpecularPower(20); // An isosurface, or contour value of 1150 is known to correspond to the // skin of the patient. Once generated, a vtkPolyDataNormals filter is // is used to create normals for smooth surface shading during rendering. // The triangle stripper is used to create triangle strips from the // isosurface these render much faster on some systems. vtkContourFilter boneExtractor = new vtkContourFilter(); boneExtractor.SetInput(theImageData); boneExtractor.SetValue(0, 1150); vtkPolyDataNormals boneNormals = new vtkPolyDataNormals(); boneNormals.SetInput(boneExtractor.GetOutput()); boneNormals.SetFeatureAngle(60.0); vtkStripper boneStripper = new vtkStripper(); boneStripper.SetInput(boneNormals.GetOutput()); vtkPolyDataMapper boneMapper = new vtkPolyDataMapper(); boneMapper.SetInput(boneStripper.GetOutput()); boneMapper.ScalarVisibilityOff(); vtkActor bone = new vtkActor(); bone.SetMapper(boneMapper); bone.GetProperty().SetDiffuseColor(1, 1, .9412); // An outline provides context around the data. vtkOutlineFilter outlineData = new vtkOutlineFilter(); outlineData.SetInput(theImageData); vtkPolyDataMapper mapOutline = new vtkPolyDataMapper(); mapOutline.SetInput(outlineData.GetOutput()); vtkActor outline = new vtkActor(); outline.SetMapper(mapOutline); outline.GetProperty().SetColor(0, 0, 0); // Now we are creating three orthogonal planes passing through the // volume. Each plane uses a different texture map and therefore has // diferent coloration. // Start by creatin a black/white lookup table. vtkLookupTable bwLut = new vtkLookupTable(); bwLut.SetTableRange(0, 2000); bwLut.SetSaturationRange(0, 0); bwLut.SetHueRange(0, 0); bwLut.SetValueRange(0, 1); bwLut.Build(); // Now create a lookup table that consists of the full hue circle (from // HSV);. vtkLookupTable hueLut = new vtkLookupTable(); hueLut.SetTableRange(0, 2000); hueLut.SetHueRange(0, 1); hueLut.SetSaturationRange(1, 1); hueLut.SetValueRange(1, 1); hueLut.Build(); // Finally, create a lookup table with a single hue but having a range // in the saturation of the hue. vtkLookupTable satLut = new vtkLookupTable(); satLut.SetTableRange(0, 2000); satLut.SetHueRange(.6, .6); satLut.SetSaturationRange(0, 1); satLut.SetValueRange(1, 1); satLut.Build(); // Create the first of the three planes. The filter vtkImageMapToColors // maps the data through the corresponding lookup table created above. // The vtkImageActor is a type of vtkProp and conveniently displays an // image on a single quadrilateral plane. It does this using texture // mapping and as a result is quite fast. (Note: the input image has to // be unsigned char values, which the vtkImageMapToColors produces.); // Note also that by specifying the DisplayExtent, the pipeline // requests data of this extent and the vtkImageMapToColors only // processes a slice of data. vtkImageMapToColors saggitalColors = new vtkImageMapToColors(); saggitalColors.SetInput(theImageData); saggitalColors.SetLookupTable(bwLut); vtkImageActor saggital = new vtkImageActor(); saggital.SetInput(saggitalColors.GetOutput()); saggital.SetDisplayExtent(32, 32, 0, 63, 0, 92); // Create the second (axial); plane of the three planes. We use the same // approach as before except that the extent differs. vtkImageMapToColors axialColors = new vtkImageMapToColors(); axialColors.SetInput(theImageData); axialColors.SetLookupTable(hueLut); vtkImageActor axial = new vtkImageActor(); axial.SetInput(axialColors.GetOutput()); axial.SetDisplayExtent(0, 63, 0, 63, 46, 46); // Create the third (coronal); plane of the three planes. We use the same // approach as before except that the extent differs. vtkImageMapToColors coronalColors = new vtkImageMapToColors(); coronalColors.SetInput(theImageData); coronalColors.SetLookupTable(satLut); vtkImageActor coronal = new vtkImageActor(); coronal.SetInput(coronalColors.GetOutput()); coronal.SetDisplayExtent(0, 63, 32, 32, 0, 92); // It is convenient to create an initial view of the data. The FocalPoint // and Position form a vector direction. Later on (ResetCamera() method) // this vector is used to position the camera to look at the data in // this direction. vtkCamera aCamera = new vtkCamera(); aCamera.SetViewUp(0, 0, -1); aCamera.SetPosition(0, 1, 0); aCamera.SetFocalPoint(0, 0, 0); aCamera.ComputeViewPlaneNormal(); // Actors are added to the renderer. An initial camera view is created. // The Dolly() method moves the camera towards the FocalPoint, // thereby enlarging the image. renWin.GetRenderer().AddActor(saggital); renWin.GetRenderer().AddActor(axial); renWin.GetRenderer().AddActor(coronal); renWin.GetRenderer().AddActor(outline); renWin.GetRenderer().AddActor(skin); renWin.GetRenderer().AddActor(bone); // Turn off bone for this example. bone.VisibilityOff(); // Set skin to semi-transparent. skin.GetProperty().SetOpacity(0.5); // An initial camera view is created. The Dolly() method moves // the camera towards the FocalPoint, thereby enlarging the image. renWin.GetRenderer().SetActiveCamera(aCamera); renWin.GetRenderer().ResetCamera(); aCamera.Dolly(1.5); // Set a background color for the renderer and set the size of the // render window (expressed in pixels). renWin.GetRenderer().SetBackground(1, 1, 1); VtkPanelUtil.setSize(renWin, 640, 480); // Note that when camera movement occurs (as it does in the Dolly() // method), the clipping planes often need adjusting. Clipping planes // consist of two planes: near and far along the view direction. The // near plane clips out objects in front of the plane the far plane // clips out objects behind the plane. This way only what is drawn // between the planes is actually rendered. renWin.GetRenderer().ResetCameraClippingRange(); // Setup panel setLayout(new BorderLayout()); add(renWin, BorderLayout.CENTER); } public vtkPanel getRenWin() { return renWin; } public static void main(String s[]) { if (s.length == 0){ return; //need a filename here } File theFile = new File(s[0]); //File theFile = new File("/Users/mmroden/Documents/MVSDownloadDirectory/Documents/1.2.840.113704.1.111.3384.1271766367.5/"); AWTMedical3 panel = new AWTMedical3(theFile); JFrame frame = new JFrame("AWTMedical3"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add("Center", panel); frame.pack(); frame.setVisible(true); } } GDCM-3.0.10/Utilities/VTK/Examples/Java/CMakeLists.txt000066400000000000000000000042451412732066400221350ustar00rootroot00000000000000set(classpath ${LIBRARY_OUTPUT_PATH}/vtkgdcm.jar${JavaProp_PATH_SEPARATOR}${LIBRARY_OUTPUT_PATH}/gdcm.jar${JavaProp_PATH_SEPARATOR}${VTK_JAVA_JAR}${JavaProp_PATH_SEPARATOR}${GDCM_VTK_JAVA_JAR}) set(classfilesdep) set(examples HelloVTKWorld ReadSeriesIntoVTK #AWTMedical3 MPRViewer2 ) if(VTK_HAS_IMAGERESLICEMAPPER) set(examples ${examples} MPRViewer ) endif() if(VTK_HAS_SMARTVOLUMEMAPPER) set(examples ${examples} MIPViewer ) endif() foreach(example ${examples}) add_custom_command( OUTPUT ${EXECUTABLE_OUTPUT_PATH}/${example}.class COMMAND ${Java_JAVAC_EXECUTABLE} ARGS -source ${GDCM_JAVA_SOURCE_VERSION} -target ${GDCM_JAVA_TARGET_VERSION} -classpath "${classpath}" ${CMAKE_CURRENT_SOURCE_DIR}/${example}.java -d ${EXECUTABLE_OUTPUT_PATH} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${example}.java COMMENT "javac ${example}.java" ) list(APPEND classfilesdep ${EXECUTABLE_OUTPUT_PATH}/${example}.class) endforeach() # 3. ok now add the target add_custom_target(GDCMJavaVTKExample ALL DEPENDS ${classfilesdep} COMMENT "building gdcm java example" ) add_dependencies(GDCMJavaVTKExample VTKGDCMJavaJar) if(BUILD_TESTING) if(GDCM_DATA_ROOT) #set_source_files_properties(${EXECUTABLE_OUTPUT_PATH}/${test}.class PROPERTIES RUNTIMEPATH "${EXECUTABLE_OUTPUT_PATH}") set_source_files_properties(${EXECUTABLE_OUTPUT_PATH}/HelloVTKWorld.class PROPERTIES CLASSPATH "${EXECUTABLE_OUTPUT_PATH}/vtkgdcm.jar:${GDCM_VTK_JAVA_JAR}") ADD_JAVA_TEST(TestHelloVTKWorldJava ${EXECUTABLE_OUTPUT_PATH}/HelloVTKWorld ${GDCM_DATA_ROOT}/012345.002.050.dcm ${GDCM_TEMP_DIRECTORY}/HelloVTKWorld.dcm) set_source_files_properties(${EXECUTABLE_OUTPUT_PATH}/ReadSeriesIntoVTK.class PROPERTIES CLASSPATH "${EXECUTABLE_OUTPUT_PATH}/vtkgdcm.jar:${GDCM_VTK_JAVA_JAR}") ADD_JAVA_TEST(TestReadSeriesIntoVTKJava ${EXECUTABLE_OUTPUT_PATH}/ReadSeriesIntoVTK) #set_source_files_properties(${EXECUTABLE_OUTPUT_PATH}/AWTMedical3.class PROPERTIES CLASSPATH "${EXECUTABLE_OUTPUT_PATH}/vtkgdcm.jar:${GDCM_VTK_JAVA_JAR}") #ADD_JAVA_TEST(TestAWTMedical3Java ${EXECUTABLE_OUTPUT_PATH}/AWTMedical3) endif() endif() GDCM-3.0.10/Utilities/VTK/Examples/Java/HelloVTKWorld.java000066400000000000000000000066071412732066400227040ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // We are required to call the package 'vtk' eventhough I (MM) would have prefered // an import statement along the line of: // import vtkgdcm.*; import vtk.*; /* * Compilation: * CLASSPATH=vtkgdcm.jar:/usr/share/java/vtk.jar javac HelloVTKWorld.java * * Usage: * LD_LIBRARY_PATH=/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/xawt:/usr/lib/jni:. CLASSPATH=/usr/share/java/vtk.jar:vtkgdcm.jar:gdcm.jar:. java HelloVTKWorld gdcmData/012345.002.050.dcm bla.dcm * */ public class HelloVTKWorld { static { System.loadLibrary("vtkCommonJava"); System.loadLibrary("vtkFilteringJava"); System.loadLibrary("vtkIOJava"); System.loadLibrary("vtkImagingJava"); System.loadLibrary("vtkGraphicsJava"); System.loadLibrary("vtkgdcmJava"); try { System.loadLibrary("vtkRenderingJava"); } catch (Throwable e) { System.out.println("cannot load vtkHybrid, skipping..."); } try { System.loadLibrary("vtkHybridJava"); } catch (Throwable e) { System.out.println("cannot load vtkHybrid, skipping..."); } try { System.loadLibrary("vtkVolumeRenderingJava"); } catch (Throwable e) { System.out.println("cannot load vtkVolumeRendering, skipping..."); } } public static void main(String[] args) { String filename = args[0]; vtkGDCMImageReader reader = new vtkGDCMImageReader(); reader.SetFileName( filename ); reader.Update(); vtkMedicalImageProperties prop = reader.GetMedicalImageProperties(); System.out.println( prop.GetPatientName() ); // // if( reader.GetImageFormat() == vtkgdcm.vtkgdcm.VTK_LUMINANCE ) // MONOCHROME2 // { // System.out.println( "Image is MONOCHROME2" ); // // } // Just for fun, invert the direction cosines, output should reflect that: vtkMatrix4x4 dircos = reader.GetDirectionCosines(); dircos.Invert(); // We need to maintain in sync information stored in vtkMedicalImageProperties: double[] cosines = new double[6]; cosines[0] = dircos.GetElement(0,0); cosines[1] = dircos.GetElement(1,0); cosines[2] = dircos.GetElement(2,0); cosines[3] = dircos.GetElement(0,1); cosines[4] = dircos.GetElement(1,1); cosines[5] = dircos.GetElement(2,1); reader.GetMedicalImageProperties().SetDirectionCosine( cosines ); String outfilename = args[1]; vtkGDCMImageWriter writer = new vtkGDCMImageWriter(); writer.SetMedicalImageProperties( reader.GetMedicalImageProperties() ); writer.SetDirectionCosines( dircos ); writer.SetShift( reader.GetShift() ); writer.SetScale( reader.GetScale() ); writer.SetImageFormat( reader.GetImageFormat() ); writer.SetFileName( outfilename ); writer.SetInputConnection( reader.GetOutputPort() ); // new //writer.SetInput( reader.GetOutput() ); // old writer.Write(); System.out.println("Success reading: " + filename ); } } GDCM-3.0.10/Utilities/VTK/Examples/Java/MIPViewer.java000066400000000000000000000130751412732066400220500ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ import vtk.*; import gdcm.*; import java.io.File; import java.awt.Canvas; /* * Compilation: * CLASSPATH=vtkgdcm.jar:/usr/share/java/vtk.jar javac MIPViewer.java * * Usage: * LD_LIBRARY_PATH=/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/xawt:/usr/lib/jni:. CLASSPATH=/usr/share/java/vtk.jar:vtkgdcm.jar:gdcm.jar:. java MIPViewer BRAINX * */ public class MIPViewer extends Canvas { static { // VTK System.loadLibrary("vtkCommonJava"); System.loadLibrary("vtkFilteringJava"); System.loadLibrary("vtkIOJava"); System.loadLibrary("vtkImagingJava"); System.loadLibrary("vtkGraphicsJava"); System.loadLibrary("vtkRenderingJava"); System.loadLibrary("vtkVolumeRenderingJava"); // vtkSmartVolumeMapper System.loadLibrary("vtkWidgetsJava"); // vtkBoxWidget // VTK-GDCM System.loadLibrary("vtkgdcmJava"); } static FilenamesType fns = new FilenamesType(); protected native int Lock(); protected native int UnLock(); public static void process(String path) { fns.add( path ); } // Process only files under dir public static void visitAllFiles(File dir) { if (dir.isDirectory()) { String[] children = dir.list(); for (int i=0; iSetFilename( "test.dcm" ); $reader->Update(); $prop = $reader->GetMedicalImageProperties(); $n = $prop->GetNumberOfWindowLevelPresets(); print( "coudou" ); //print( "coucou %d", $n ); if( $n != 0 ) { // Take the first one by default: $w = 0; $l = 0; $a = $prop->GetNthWindowLevelPreset(0); print( $a[0] ); //$windowlevel->SetWindow( wl[0] ); //$windowlevel->SetLevel( wl[1] ); } /* $renderer = vtkRenderer::c_New(); $windowlevel = vtkImageMapToWindowLevelColors::c_New(); $windowlevel->SetInput( $reader->GetOutput() ); $actor = vtkImageActor::c_New(); $actor->SetInput( $windowlevel->GetOutput() ); $renderer->AddActor( actor ); $renWin = vtkRenderWindow::c_New(); $renWin->OffScreenRenderingOn(); $renWin->AddRenderer($renderer); $renWin->Render(); $w2if = vtkWindowToImageFilter::c_New(); $w2if->SetInput ( $renWin ); $wr = vtkPNGWriter::c_New(); $wr->SetInput( $w2if->GetOutput() ); $wr->SetFileName ( "offscreenimage.png" ); $wr->Write(); */ ?> GDCM-3.0.10/Utilities/VTK/Examples/Python/000077500000000000000000000000001412732066400177705ustar00rootroot00000000000000GDCM-3.0.10/Utilities/VTK/Examples/Python/CastConvertPhilips.py000066400000000000000000000125221412732066400241300ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Usage: python --public /path/to/directory/ or python --private /path/to/directory/ python --public --extension bak /path/to/directory/ rename -f 's/\.bak$//' *.bak TODO: http://docs.python.org/library/optparse.html#module-optparse """ import vtkgdcm import vtk import sys import gdcm def ProcessOneFilePublic(filename, outfilename, tmpfile): gdcm.ImageHelper.SetForceRescaleInterceptSlope(True) vtkreader = vtkgdcm.vtkGDCMImageReader() vtkreader.SetFileName( filename ) vtkreader.Update() cast = vtk.vtkImageCast() cast.SetInput( vtkreader.GetOutput() ) cast.SetOutputScalarTypeToUnsignedShort() # vtkGDCMImageWriter does not support Sequence, so let's write a tmp file first: # Some operation will actually be discarded (we simply need a temp storage) vtkwriter = vtkgdcm.vtkGDCMImageWriter() vtkwriter.SetFileName( tmpfile ) vtkwriter.SetMedicalImageProperties( vtkreader.GetMedicalImageProperties() ) vtkwriter.SetDirectionCosines( vtkreader.GetDirectionCosines() ) print "Format:",vtkreader.GetImageFormat() vtkwriter.SetImageFormat( vtkreader.GetImageFormat() ) vtkwriter.SetInput( cast.GetOutput() ) #vtkwriter.Update() vtkwriter.Write() # ok now rewrite the exact same file as the original (keep all info) # but use the Pixel Data Element from the written file tmpreader = gdcm.ImageReader() tmpreader.SetFileName( tmpfile ) if not tmpreader.Read(): sys.exit(1) reader = gdcm.Reader() reader.SetFileName( filename ) if not reader.Read(): sys.exit(1) # Make sure to remove Slope/Rescale to avoid re-execution ds = reader.GetFile().GetDataSet() tags = [ gdcm.Tag(0x0028,0x1052), gdcm.Tag(0x0028,0x1053), gdcm.Tag(0x0028,0x1053), ] for tag in tags: ds.Remove( tag ) writer = gdcm.ImageWriter() writer.SetFileName( outfilename ) # Pass image from vtk written file writer.SetImage( tmpreader.GetImage() ) # pass dataset from initial 'reader' writer.SetFile( reader.GetFile() ) if not writer.Write(): sys.exit(1) def ProcessOneFilePrivate(filename, outfilename, tmpfile): vtkreader = vtkgdcm.vtkGDCMImageReader() vtkreader.SetFileName( filename ) vtkreader.Update() # (2005,1409) DS 4 0.0 # (2005,140a) DS 16 1.52283272283272 # (2005,0014) LO 26 Philips MR Imaging DD 005 tag1 = gdcm.PrivateTag(0x2005,0x09,"Philips MR Imaging DD 005") tag2 = gdcm.PrivateTag(0x2005,0x0a,"Philips MR Imaging DD 005") # Need to access some private tags, reread the file (for now): reader = gdcm.Reader() reader.SetFileName( filename ) if not reader.Read(): sys.exit(1) ds = reader.GetFile().GetDataSet() el1 = ds.GetDataElement( tag1 ) el2 = ds.GetDataElement( tag2 ) #pf = gdcm.PythonFilter() #pf.SetFile( reader.GetFile() ) #print el1.GetTag() print el1.GetByteValue() v1 = eval(el1.GetByteValue().GetBuffer()) print el2.GetByteValue() v2 = eval(el2.GetByteValue().GetBuffer()) print v1 shift = v1 print v2 scale = v2 ss = vtk.vtkImageShiftScale() ss.SetInput( vtkreader.GetOutput() ) # because VTK image shift / scale convention is inverted from DICOM make sure shift is 0 assert shift == 0 ss.SetShift( shift ) ss.SetScale( scale ) ss.SetOutputScalarTypeToUnsignedShort () ss.Update() # vtkGDCMImageWriter does not support Sequence, so let's write a tmp file first: # Some operation will actually be discarded (we simply need a temp storage) vtkwriter = vtkgdcm.vtkGDCMImageWriter() vtkwriter.SetFileName( tmpfile ) vtkwriter.SetMedicalImageProperties( vtkreader.GetMedicalImageProperties() ) vtkwriter.SetDirectionCosines( vtkreader.GetDirectionCosines() ) vtkwriter.SetImageFormat( reader.GetImageFormat() ) # do not pass shift/scale again vtkwriter.SetInput( ss.GetOutput() ) #vtkwriter.Update() vtkwriter.Write() # ok now rewrite the exact same file as the original (keep all info) # but use the Pixel Data Element from the written file tmpreader = gdcm.ImageReader() tmpreader.SetFileName( tmpfile ) if not tmpreader.Read(): sys.exit(1) writer = gdcm.ImageWriter() writer.SetFileName( outfilename ) # Pass image from vtk written file writer.SetImage( tmpreader.GetImage() ) # pass dataset from initial 'reader' writer.SetFile( reader.GetFile() ) if not writer.Write(): sys.exit(1) if __name__ == "__main__": gdcm.Trace.DebugOff() gdcm.Trace.WarningOff() #filename = sys.argv[1] #outfilename = sys.argv[2] tmpfile = "/tmp/philips_rescaled.dcm" #ProcessOneFile( filename, outfilename, tmpfile ) rescaletype = sys.argv[1] assert rescaletype == "--public" or rescaletype == "--private" dirname = sys.argv[2] d = gdcm.Directory() d.Load( dirname ) for f in d.GetFilenames(): #print f ProcessOneFilePublic( f, f + ".bak", tmpfile ) print "success" GDCM-3.0.10/Utilities/VTK/Examples/Python/headsq2dcm.py000066400000000000000000000026251412732066400223620ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ Usage: python headsq2dcm.py -D /path/to/VTKData """ import vtk import vtkgdcm from vtk.util.misc import vtkGetDataRoot VTK_DATA_ROOT = vtkGetDataRoot() reader = vtk.vtkVolume16Reader() reader.SetDataDimensions(64, 64) reader.SetDataByteOrderToLittleEndian() reader.SetFilePrefix(VTK_DATA_ROOT + "/Data/headsq/quarter") reader.SetImageRange(1, 93) reader.SetDataSpacing(3.2, 3.2, 1.5) cast = vtk.vtkImageCast() cast.SetInput( reader.GetOutput() ) cast.SetOutputScalarTypeToUnsignedChar() # By default this is creating a Multiframe Grayscale Word Secondary Capture Image Storage writer = vtkgdcm.vtkGDCMImageWriter() writer.SetFileName( "headsq.dcm" ) writer.SetInput( reader.GetOutput() ) # cast -> Multiframe Grayscale Byte Secondary Capture Image Storage #writer.SetInput( cast.GetOutput() ) writer.SetFileDimensionality( 3 ) writer.Write() GDCM-3.0.10/Utilities/VTK/GDCMImageGUI.xml000066400000000000000000000010721412732066400174750ustar00rootroot00000000000000 GDCM-3.0.10/Utilities/VTK/GDCMImageReader.xml000066400000000000000000000026261412732066400202610ustar00rootroot00000000000000 The GDCM Image reader reads DICOM files containing image data. The expected file extensions are .dcm. This property specifies the file name for the GDCM Image reader. GDCM-3.0.10/Utilities/VTK/JavaDependencies.cmake.in000066400000000000000000000002201412732066400215220ustar00rootroot00000000000000# This file is automatically generated by CMake VTK_WRAP_JAVA set(VTK_JAVA_DEPENDENCIES ${VTK_JAVA_DEPENDENCIES} @VTK_JAVA_DEPENDENCIES_FILE@ ) GDCM-3.0.10/Utilities/VTK/MummySettings.xml.in000066400000000000000000000203021412732066400207020ustar00rootroot00000000000000 @AVDN_EXTRA_EXCLUDE_CLASSES_XML@ GDCM-3.0.10/Utilities/VTK/Testing/000077500000000000000000000000001412732066400163465ustar00rootroot00000000000000GDCM-3.0.10/Utilities/VTK/Testing/CMakeLists.txt000066400000000000000000000003251412732066400211060ustar00rootroot00000000000000add_subdirectory(Cxx) if(VTK_WRAP_PYTHON) add_subdirectory(Python) endif() if(GDCM_WRAP_JAVA) if(VTK_WRAP_JAVA) if(EXISTS ${GDCM_VTK_JAVA_JAR}) add_subdirectory(Java) endif() endif() endif() GDCM-3.0.10/Utilities/VTK/Testing/Cxx/000077500000000000000000000000001412732066400171105ustar00rootroot00000000000000GDCM-3.0.10/Utilities/VTK/Testing/Cxx/CMakeLists.txt000066400000000000000000000050531412732066400216530ustar00rootroot00000000000000# Define the tests for vtk-gdcm # vtkGDCM set(VTK_GDCM_TEST_SRCS TestvtkGDCMImageReader.cxx TestvtkGDCMImageReader4.cxx TestvtkGDCMImageReaderIsLossy.cxx TestvtkGDCMImageWriterIsLossy.cxx #TestvtkImageChangeInformation.cxx #TestvtkGDCMImageActor.cxx #TestvtkGDCMImageViewer.cxx ) if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" GREATER 4.5 ) set(VTK_GDCM_TEST_SRCS ${VTK_GDCM_TEST_SRCS} TestvtkGDCMImageWriter1.cxx TestvtkGDCMImageWriter2.cxx TestvtkGDCMThreadedImageReader2.cxx TestvtkGDCMMetaImageWriter.cxx ) endif() if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" GREATER 6.0 ) set(VTK_GDCM_TEST_SRCS ${VTK_GDCM_TEST_SRCS} TestvtkGDCMImageReader2_1.cxx TestvtkGDCMImageReader2_2.cxx TestvtkGDCMImageReader2_3.cxx TestvtkGDCMMetaImageWriter2.cxx ) endif() # Need gdcmData if(GDCM_DATA_ROOT) set(VTK_GDCM_TEST_SRCS ${VTK_GDCM_TEST_SRCS} TestvtkGDCMImageReader1.cxx ) endif() # Need gdcmDataExtra if(GDCM_DATA_EXTRA_ROOT) set(VTK_GDCM_TEST_SRCS ${VTK_GDCM_TEST_SRCS} TestvtkGDCMImageReader3.cxx TestvtkGDCMPolyDataReader.cxx ) endif() if(VTK_USE_RENDERING) if(GDCM_HAVE_PTHREAD_H AND CMAKE_USE_PTHREADS) set(VTK_GDCM_TEST_SRCS ${VTK_GDCM_TEST_SRCS} TestvtkGDCMThreadedImageReader.cxx ) endif() endif() # Add the include paths include_directories( "${GDCM_SOURCE_DIR}/Utilities/VTK" "${GDCM_BINARY_DIR}/Testing/Source/Data" # for gdcmDataImages.h ) create_test_sourcelist(vtkGDCMTests gdcmvtkGDCMTests.cxx ${VTK_GDCM_TEST_SRCS} EXTRA_INCLUDE gdcmTestDriver.h ) add_executable(gdcmvtkGDCMTests ${vtkGDCMTests}) target_link_libraries(gdcmvtkGDCMTests ${VTKGDCM_NAME} gdcmMSFF) target_link_libraries(gdcmvtkGDCMTests vtksys) if(VTK_USE_RENDERING) if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" LESS 4.5 ) target_link_libraries(gdcmvtkGDCMTests vtkRendering) elseif( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" LESS 6.0 ) target_link_libraries(gdcmvtkGDCMTests vtkVolumeRendering) endif() endif() # VTK 6.0 does not set VTK_USE_RENDERING anymore ? if( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" GREATER 6.0 ) target_link_libraries(gdcmvtkGDCMTests ${vtkgdcm_LIBS}) target_link_libraries(gdcmvtkGDCMTests vtkIOLegacy vtkCommonCore) endif() # Need full path to executable: set(GDCM_VTK_GDCM_TESTS "${EXECUTABLE_OUTPUT_PATH}/gdcmvtkGDCMTests") # Loop over files and create executables foreach(name ${VTK_GDCM_TEST_SRCS}) get_filename_component(testname ${name} NAME_WE) add_test(NAME ${testname} COMMAND ${GDCM_VTK_GDCM_TESTS} ${testname}) endforeach() GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMImageActor.cxx000066400000000000000000000042661412732066400236770ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkPNGWriter.h" #include "vtkImageData.h" #include "vtkImageActor.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkInteractorStyleImage.h" #include #include "gdcmTesting.h" int TestvtkGDCMReadImageActor(const char *filename) { vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); //reader->CanReadFile( filename ); std::cerr << "Reading : " << filename << std::endl; reader->SetFileName( filename ); reader->Update(); //reader->GetOutput()->Print( cout ); vtkImageActor *ia = vtkImageActor::New(); ia->SetInput( reader->GetOutput() ); // Create the RenderWindow, Renderer and both Actors vtkRenderer *ren1 = vtkRenderer::New(); vtkRenderWindow *renWin = vtkRenderWindow::New(); renWin->AddRenderer (ren1); vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); iren->SetRenderWindow (renWin); // Add the actors to the renderer, set the background and size ren1->AddActor (ia); vtkInteractorStyleImage *style = vtkInteractorStyleImage::New(); iren->SetInteractorStyle( style ); style->Delete(); iren->Initialize(); iren->Start(); reader->Delete(); return 0; } int TestvtkGDCMImageActor(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestvtkGDCMReadImageActor(filename); } // else int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestvtkGDCMReadImageActor( filename ); ++i; } return r; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMImageReader.cxx000066400000000000000000000061531412732066400240260ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkMedicalImageProperties.h" #include "vtkPNGWriter.h" #include "vtkImageData.h" #include "vtkStringArray.h" #include "vtkVersion.h" #include "gdcmFilename.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmDirectory.h" static int TestvtkGDCMImageRead(const char *filename, bool verbose) { if( verbose ) std::cerr << "Reading : " << filename << std::endl; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); if( gdcm::System::FileIsDirectory( filename ) ) { verbose = false; gdcm::Directory d; d.Load( filename ); gdcm::Directory::FilenamesType l = d.GetFilenames(); const size_t nfiles = l.size(); vtkStringArray *sarray = vtkStringArray::New(); for(unsigned int i = 0; i < nfiles; ++i) { sarray->InsertNextValue( l[i] ); } assert( sarray->GetNumberOfValues() == (int)nfiles ); reader->SetFileNames( sarray ); sarray->Delete(); } else { reader->SetFileName( filename ); } //int canread = reader->CanReadFile( filename ); reader->Update(); if( verbose ) { reader->GetOutput()->Print( cout ); reader->GetMedicalImageProperties()->Print( cout ); } if( verbose && false ) { // Create directory first: const char subdir[] = "TestvtkGDCMImageReader"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string pngfile = gdcm::Testing::GetTempFilename( filename, subdir ); vtkPNGWriter *writer = vtkPNGWriter::New(); #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) writer->SetInputConnection( reader->GetOutputPort() ); #else writer->SetInput( reader->GetOutput() ); #endif pngfile += ".png"; writer->SetFileName( pngfile.c_str() ); //writer->Write(); writer->Delete(); cout << "Wrote PNG output into:" << pngfile << std::endl; } reader->Delete(); return 0; } int TestvtkGDCMImageReader(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestvtkGDCMImageRead(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestvtkGDCMImageRead( filename, false ); ++i; } return r; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMImageReader1.cxx000066400000000000000000000133221412732066400241030ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkGDCMImageWriter.h" #include "vtkStringArray.h" #include "vtkImageData.h" #include "vtkImageChangeInformation.h" #include "vtkVersion.h" #include "gdcmFilename.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmDirectory.h" #include "gdcmIPPSorter.h" #include "gdcmFilenameGenerator.h" #ifndef vtkFloatingPointType #define vtkFloatingPointType double #endif /* * Test to show the pipeline for * IPPSorter -> vtkGDCMImageReader -> vtkImageChangeInformation */ int TestvtkGDCMImageReader1(int , char *[]) { const char *directory = gdcm::Testing::GetDataRoot(); std::vector filenames; std::string file0 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm"; std::string file1 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm"; std::string file2 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm"; std::string file3 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm"; filenames.push_back( file1 ); filenames.push_back( file3 ); filenames.push_back( file2 ); filenames.push_back( file0 ); gdcm::IPPSorter s; s.SetComputeZSpacing( true ); s.SetZSpacingTolerance( 1e-10 ); bool b = s.Sort( filenames ); if( !b ) { std::cerr << "Failed to sort:" << directory << std::endl; return 1; } std::cout << "Sorting succeeded:" << std::endl; s.Print( std::cout ); std::cout << "Found z-spacing:" << std::endl; std::cout << s.GetZSpacing() << std::endl; double ippzspacing = s.GetZSpacing(); if( ippzspacing != 5.5 ) { // This should be test in another specific test ... return 1; } const std::vector & sorted = s.GetFilenames(); vtkGDCMImageReader * reader = vtkGDCMImageReader::New(); vtkStringArray *files = vtkStringArray::New(); std::vector< std::string >::const_iterator it = sorted.begin(); for( ; it != sorted.end(); ++it) { const std::string &f = *it; files->InsertNextValue( f.c_str() ); } reader->SetFileNames( files ); reader->Update(); const vtkFloatingPointType *spacing = reader->GetOutput()->GetSpacing(); std::cout << spacing[0] << "," << spacing[1] << "," << spacing[2] << std::endl; int ret = 0; if( spacing[2] != 0.5 ) { // Spacing Between Slice is set to 0.5 in those files ret++; } // try again but this time we want 5.5 to be the spacing vtkGDCMImageReader * reader2 = vtkGDCMImageReader::New(); reader2->SetDataSpacing( spacing[0], spacing[1], ippzspacing ); reader2->SetFileNames( files ); //reader2->FileLowerLeftOn(); // TODO reader2->Update(); const vtkFloatingPointType *spacing2 = reader2->GetOutput()->GetSpacing(); std::cout << spacing2[0] << "," << spacing2[1] << "," << spacing2[2] << std::endl; // You need to use this class to preserve spacing // across pipeline re-execution vtkImageChangeInformation *change = vtkImageChangeInformation::New(); #if (VTK_MAJOR_VERSION >= 6) change->SetInputConnection( reader2->GetOutputPort() ); #else change->SetInput( reader2->GetOutput() ); #endif change->SetOutputSpacing( spacing2[0], spacing2[1], ippzspacing ); change->Update(); const vtkFloatingPointType *spacing3 = change->GetOutput()->GetSpacing(); std::cout << spacing3[0] << "," << spacing3[1] << "," << spacing3[2] << std::endl; if( spacing3[2] != 5.5 ) { ret++; } // Ok Let's try to write this volume back to disk: vtkGDCMImageWriter *writer = vtkGDCMImageWriter::New(); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputData( change->GetOutput() ); #else writer->SetInput( change->GetOutput() ); #endif writer->SetFileDimensionality( 2 ); //writer->SetFileLowerLeft( reader2->GetFileLowerLeft() ); // TODO writer->SetMedicalImageProperties( reader2->GetMedicalImageProperties() ); // nasty writer->SetDirectionCosines( reader2->GetDirectionCosines() ); writer->SetImageFormat( reader2->GetImageFormat() ); const char subdir[] = "TestvtkGDCMImageReader1"; std::string tmpdir = gdcm::Testing::GetTempDirectory(subdir); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } tmpdir += "/"; const char tfilename[] = "SIEMENS_MAGNETOM-12-MONO2-FileSeq%01d.dcm"; tmpdir += tfilename; gdcm::FilenameGenerator fg; fg.SetPattern( tmpdir.c_str() ); fg.SetNumberOfFilenames( files->GetNumberOfValues() ); bool bb = fg.Generate(); if( !bb ) { std::cerr << "FilenameGenerator::Generate failed" << std::endl; return 1; } if( !fg.GetNumberOfFilenames() ) { std::cerr << "No filenames generated" << std::endl; return 1; } vtkStringArray *wfilenames = vtkStringArray::New(); for(unsigned int i = 0; i < fg.GetNumberOfFilenames(); ++i) { wfilenames->InsertNextValue( fg.GetFilename(i) ); std::cerr << fg.GetFilename(i) << std::endl; } assert( (gdcm::FilenameGenerator::SizeType)wfilenames->GetNumberOfValues() == fg.GetNumberOfFilenames() ); writer->SetFileNames( wfilenames ); wfilenames->Delete(); writer->Write(); change->Delete(); reader->Delete(); reader2->Delete(); writer->Delete(); files->Delete(); return ret; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMImageReader2_1.cxx000066400000000000000000000057161412732066400243340ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader2.h" #include "vtkMedicalImageProperties.h" #include "vtkPNGWriter.h" #include "vtkImageData.h" #include "vtkStringArray.h" #include "gdcmFilename.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmDirectory.h" static int TestvtkGDCMImageRead(const char *filename, bool verbose) { if( verbose ) std::cerr << "Reading : " << filename << std::endl; vtkGDCMImageReader2 *reader = vtkGDCMImageReader2::New(); if( gdcm::System::FileIsDirectory( filename ) ) { verbose = false; gdcm::Directory d; d.Load( filename ); gdcm::Directory::FilenamesType l = d.GetFilenames(); const size_t nfiles = l.size(); vtkStringArray *sarray = vtkStringArray::New(); for(unsigned int i = 0; i < nfiles; ++i) { sarray->InsertNextValue( l[i] ); } assert( sarray->GetNumberOfValues() == (int)nfiles ); reader->SetFileNames( sarray ); sarray->Delete(); } else { reader->SetFileName( filename ); } //int canread = reader->CanReadFile( filename ); reader->Update(); if( verbose ) { reader->GetOutput()->Print( cout ); reader->GetMedicalImageProperties()->Print( cout ); } if( verbose && false ) { // Create directory first: const char subdir[] = "TestvtkGDCMImageReader2_1"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string pngfile = gdcm::Testing::GetTempFilename( filename, subdir ); vtkPNGWriter *writer = vtkPNGWriter::New(); writer->SetInputConnection( reader->GetOutputPort() ); pngfile += ".png"; writer->SetFileName( pngfile.c_str() ); //writer->Write(); writer->Delete(); cout << "Wrote PNG output into:" << pngfile << std::endl; } reader->Delete(); return 0; } int TestvtkGDCMImageReader2_1(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestvtkGDCMImageRead(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestvtkGDCMImageRead( filename, false ); ++i; } return r; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMImageReader2_2.cxx000066400000000000000000000062751412732066400243360ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader2.h" #include "vtkMedicalImageProperties.h" #include "vtkInformation.h" #include "vtkStreamingDemandDrivenPipeline.h" #include "vtkStringArray.h" #include "vtkVersion.h" // DEBUG #include "vtkImageColorViewer.h" #include "vtkRenderWindowInteractor.h" #include "gdcmSystem.h" #include "gdcmTesting.h" #include "gdcmDirectory.h" static int TestvtkGDCMImageRead(const char *filename, bool verbose) { // if( verbose ) std::cerr << "Reading : " << filename << std::endl; vtkGDCMImageReader2 *reader = vtkGDCMImageReader2::New(); if( gdcm::System::FileIsDirectory( filename ) ) { gdcm::Directory d; d.Load( filename ); gdcm::Directory::FilenamesType l = d.GetFilenames(); const size_t nfiles = l.size(); vtkStringArray *sarray = vtkStringArray::New(); for(unsigned int i = 0; i < nfiles; ++i) { sarray->InsertNextValue( l[i] ); } assert( sarray->GetNumberOfValues() == (int)nfiles ); reader->SetFileNames( sarray ); sarray->Delete(); } else { reader->SetFileName( filename ); } reader->UpdateInformation(); if( reader->GetErrorCode() ) { return 1; } int wext[6]; reader->GetOutputInformation(0)->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wext); //reader->GetOutput()->Print( std::cout ); const int mid = (wext[5] - wext[0]) / 2; wext[4] = wext[5] = mid; #if VTK_MAJOR_VERSION > 7 || (VTK_MAJOR_VERSION == 7 && VTK_MINOR_VERSION > 0) int ret = reader->UpdateExtent( wext ); #else reader->SetUpdateExtent( wext ); //reader->Update(); int ret = reader->GetExecutive()->Update(); #endif if( !ret ) { std::cerr << "Problem with: " << filename << std::endl; } if( verbose ) { reader->GetOutput()->Print( cout ); reader->GetMedicalImageProperties()->Print( cout ); } if( 0 ) { vtkImageColorViewer *viewer = vtkImageColorViewer::New(); viewer->SetInputConnection( reader->GetOutputPort() ); vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); viewer->SetupInteractor( iren ); viewer->Render(); iren->Initialize(); iren->Start(); } reader->Delete(); return ret; } int TestvtkGDCMImageReader2_2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestvtkGDCMImageRead(filename, true); } gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestvtkGDCMImageRead( filename, false ); ++i; } return r; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMImageReader2_3.cxx000066400000000000000000000135771412732066400243420ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader2.h" #include "vtkGDCMImageWriter.h" #include "vtkStringArray.h" #include "vtkImageData.h" #include "vtkImageChangeInformation.h" #include "vtkVersion.h" #include "gdcmFilename.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmDirectory.h" #include "gdcmIPPSorter.h" #include "gdcmFilenameGenerator.h" #ifndef vtkFloatingPointType #define vtkFloatingPointType double #endif /* * Test to show the pipeline for * IPPSorter -> vtkGDCMImageReader2 -> vtkImageChangeInformation */ int TestvtkGDCMImageReader2_3(int , char *[]) { const char *directory = gdcm::Testing::GetDataRoot(); std::vector filenames; #if 1 std::string file0 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm"; std::string file1 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm"; std::string file2 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm"; std::string file3 = std::string(directory) + "/SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm"; #else std::string file0 = "/tmp/0.dcm"; std::string file1 = "/tmp/1.dcm"; std::string file2 = "/tmp/2.dcm"; std::string file3 = "/tmp/3.dcm"; #endif filenames.push_back( file1 ); filenames.push_back( file3 ); filenames.push_back( file2 ); filenames.push_back( file0 ); gdcm::IPPSorter s; s.SetComputeZSpacing( true ); s.SetZSpacingTolerance( 1e-10 ); bool b = s.Sort( filenames ); if( !b ) { std::cerr << "Failed to sort:" << directory << std::endl; return 1; } std::cout << "Sorting succeeded:" << std::endl; s.Print( std::cout ); std::cout << "Found z-spacing:" << std::endl; std::cout << s.GetZSpacing() << std::endl; double ippzspacing = s.GetZSpacing(); if( ippzspacing != 5.5 ) { // This should be test in another specific test ... return 1; } const std::vector & sorted = s.GetFilenames(); vtkGDCMImageReader2 * reader = vtkGDCMImageReader2::New(); vtkStringArray *files = vtkStringArray::New(); std::vector< std::string >::const_iterator it = sorted.begin(); for( ; it != sorted.end(); ++it) { const std::string &f = *it; files->InsertNextValue( f.c_str() ); } reader->SetFileNames( files ); reader->Update(); const vtkFloatingPointType *spacing = reader->GetOutput()->GetSpacing(); std::cout << spacing[0] << "," << spacing[1] << "," << spacing[2] << std::endl; int ret = 0; if( spacing[2] != 0.5 ) { // Spacing Between Slice is set to 0.5 in those files ret++; } // try again but this time we want 5.5 to be the spacing vtkGDCMImageReader2 * reader2 = vtkGDCMImageReader2::New(); reader2->SetDataSpacing( spacing[0], spacing[1], ippzspacing ); reader2->SetFileNames( files ); //reader2->FileLowerLeftOn(); // TODO reader2->Update(); const vtkFloatingPointType *spacing2 = reader2->GetOutput()->GetSpacing(); std::cout << spacing2[0] << "," << spacing2[1] << "," << spacing2[2] << std::endl; // You need to use this class to preserve spacing // across pipeline re-execution vtkImageChangeInformation *change = vtkImageChangeInformation::New(); #if (VTK_MAJOR_VERSION >= 6) change->SetInputConnection( reader2->GetOutputPort() ); #else change->SetInput( reader2->GetOutput() ); #endif change->SetOutputSpacing( spacing2[0], spacing2[1], ippzspacing ); change->Update(); const vtkFloatingPointType *spacing3 = change->GetOutput()->GetSpacing(); std::cout << spacing3[0] << "," << spacing3[1] << "," << spacing3[2] << std::endl; if( spacing3[2] != 5.5 ) { ret++; } // Ok Let's try to write this volume back to disk: vtkGDCMImageWriter *writer = vtkGDCMImageWriter::New(); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputData( change->GetOutput() ); #else writer->SetInput( change->GetOutput() ); #endif writer->SetFileDimensionality( 2 ); //writer->SetFileLowerLeft( reader2->GetFileLowerLeft() ); // TODO writer->SetMedicalImageProperties( reader2->GetMedicalImageProperties() ); // nasty writer->SetDirectionCosines( reader2->GetDirectionCosines() ); writer->SetImageFormat( reader2->GetImageFormat() ); const char subdir[] = "TestvtkGDCMImageReader2_3"; std::string tmpdir = gdcm::Testing::GetTempDirectory(subdir); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } tmpdir += "/"; const char tfilename[] = "SIEMENS_MAGNETOM-12-MONO2-FileSeq%01d.dcm"; tmpdir += tfilename; gdcm::FilenameGenerator fg; fg.SetPattern( tmpdir.c_str() ); fg.SetNumberOfFilenames( files->GetNumberOfValues() ); bool bb = fg.Generate(); if( !bb ) { std::cerr << "FilenameGenerator::Generate failed" << std::endl; return 1; } if( !fg.GetNumberOfFilenames() ) { std::cerr << "No filenames generated" << std::endl; return 1; } vtkStringArray *wfilenames = vtkStringArray::New(); for(unsigned int i = 0; i < fg.GetNumberOfFilenames(); ++i) { wfilenames->InsertNextValue( fg.GetFilename(i) ); std::cerr << fg.GetFilename(i) << std::endl; } assert( (gdcm::FilenameGenerator::SizeType)wfilenames->GetNumberOfValues() == fg.GetNumberOfFilenames() ); writer->SetFileNames( wfilenames ); wfilenames->Delete(); writer->Write(); change->Delete(); reader->Delete(); reader2->Delete(); writer->Delete(); files->Delete(); return ret; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMImageReader3.cxx000066400000000000000000000122761412732066400241140ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkImageData.h" #include "vtkStringArray.h" #include "gdcmIPPSorter.h" #include "gdcmFilename.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmDirectory.h" #include "gdcmScanner.h" #include /* * There is special case we need to handle here: * What if the Series we are trying to read contained a changing shift/scale ? */ int TestvtkGDCMImageRead3(const char *dir, const char *studyuid) { std::cout << "Working on : " << dir << std::endl; int ret = 0; gdcm::Directory d; d.Load( dir ); const gdcm::Directory::FilenamesType &l1 = d.GetFilenames(); const size_t nfiles = l1.size(); (void)nfiles; // Sub-select only the DICOM files in this directory: gdcm::Scanner s; const gdcm::Tag t1(0x0020,0x000d); // Study Instance UID const gdcm::Tag t2(0x0020,0x000e); // Series Instance UID const gdcm::Tag t3(0x0028,0x1052); // Rescale Intercept const gdcm::Tag t4(0x0028,0x1053); // Rescale Slope s.AddTag( t1 ); s.AddTag( t2 ); s.AddTag( t3 ); s.AddTag( t4 ); bool b = s.Scan( d.GetFilenames() ); if( !b ) { std::cerr << "Scanner failed" << std::endl; return 1; } //s.Print( std::cout ); //std::cout << dir1 << std::endl; //gdcm::Scanner::ValuesType const &v = s.GetValues(); //std::cout << v.size() << std::endl; //std::copy(v.begin(), v.end(), // std::ostream_iterator(std::cout, "\n")); // Let take all the following files and pretend there are part of the // same Series: // (0020,000d) UI [1.3.46.670589.11.30.6.106253130282775287] # 40, 1 StudyInstanceUID // ... footnote : they are part of the same Study, but separate Series gdcm::Directory::FilenamesType keys = s.GetKeys(); gdcm::Directory::FilenamesType::const_iterator it = keys.begin(); std::vector wholebuffer; vtkStringArray *sarray = vtkStringArray::New(); for(; it != keys.end() /*&& i < 2*/; ++it) { const char *filename = it->c_str(); assert( s.IsKey( filename ) ); const gdcm::Tag &reftag = t1; const char *value = s.GetValue( filename, reftag ); if( value && strcmp( value, studyuid ) == 0 ) { //std::cout << "file: " << filename << std::endl; sarray->InsertNextValue( filename ); // Read each file vtkGDCMImageReader *singlereader = vtkGDCMImageReader::New(); singlereader->SetFileName( filename ); singlereader->Update(); vtkImageData* img = singlereader->GetOutput(); int ssize = img->GetScalarSize(); vtkIdType npts = img->GetNumberOfPoints(); char * ptr = (char*)img->GetScalarPointer(); //std::vector buffer(ptr, ptr+npts*ssize); wholebuffer.insert(wholebuffer.end(), ptr, ptr+npts*ssize); singlereader->Delete(); } } std::cout << "Found " << sarray->GetSize() << " files belonging to StudyUID: " << studyuid << std::endl; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); reader->SetFileNames( sarray ); sarray->Delete(); reader->Update(); vtkImageData* img = reader->GetOutput(); size_t ssize = img->GetScalarSize(); vtkIdType npts = img->GetNumberOfPoints(); char * ptr = (char*)img->GetScalarPointer(); if( wholebuffer.size() != npts * ssize || wholebuffer.empty() ) { std::cerr << "Something went terribly wrong" << std::endl; ret = 1; } if( memcmp(&wholebuffer[0], ptr, wholebuffer.size() ) != 0 ) { std::cerr << "BUG: (n) Readers are not equivalent to a single reader !" << std::endl; ret = 1; } #if 0 std::ofstream o1("/tmp/debug1.raw", std::ios::binary); o1.write(&wholebuffer[0], wholebuffer.size()); o1.close(); std::ofstream o2("/tmp/debug2.raw", std::ios::binary); o2.write(ptr, wholebuffer.size()); o2.close(); #endif reader->Delete(); return ret; } int TestvtkGDCMImageReader3(int , char *[]) { int ret = 0; gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); const char *root = gdcm::Testing::GetDataExtraRoot(); std::string dir1 = root; std::string dir2 = root; std::string dir3 = root; // dir1 & dir2 have changing 'Rescale Slope': dir1 += "/gdcmSampleData/Philips_Medical_Images/mr711-mr712/"; dir2 += "/gdcmSampleData/ForSeriesTesting/Perfusion/images/"; // dir3 has RescaleSlope == 0 ! dir3 += "/gdcmSampleData/ForSeriesTesting/Dentist/images/"; const char *studyuids[] = { "1.3.46.670589.11.30.6.106253130282775287", "1.2.250.1.38.2.1.12.7118916513228.20041110114508.431746279", "1.76.380.18.1.10713.1.1335" }; ret += TestvtkGDCMImageRead3(dir1.c_str(), studyuids[0]); ret += TestvtkGDCMImageRead3(dir2.c_str(), studyuids[1]); ret += TestvtkGDCMImageRead3(dir3.c_str(), studyuids[2]); return ret; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMImageReader4.cxx000066400000000000000000000114741412732066400241140ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkGDCMImageWriter.h" #include "vtkMedicalImageProperties.h" #include "vtkPNGWriter.h" #include "vtkImageData.h" #include "vtkStringArray.h" #include "vtkVersion.h" //#include #include "gdcmFilename.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmDirectory.h" #include "gdcmScanner.h" #include "gdcmGlobal.h" #include "gdcmDicts.h" /* * This test shows how can one extent value stored in the vtkMedicalImageProperties * For instance we will add the following two value in the struct: * (0008,0005) CS [ISO_IR 100] # 10, 1 SpecificCharacterSet * (0008,0008) CS [ORIGINAL\PRIMARY\AXIAL] # 22, 3 ImageType */ int TestvtkGDCMImageRead4(const char *filename, bool verbose) { if( verbose ) std::cerr << "Reading : " << filename << std::endl; gdcm::Directory::FilenamesType l; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); if( gdcm::System::FileIsDirectory( filename ) ) { verbose = false; gdcm::Directory d; d.Load( filename ); l = d.GetFilenames(); const size_t nfiles = l.size(); vtkStringArray *sarray = vtkStringArray::New(); for(unsigned int i = 0; i < nfiles; ++i) { sarray->InsertNextValue( l[i] ); } assert( sarray->GetNumberOfValues() == (int)nfiles ); reader->SetFileNames( sarray ); sarray->Delete(); } else { reader->SetFileName( filename ); l.push_back( filename ); } //int canread = reader->CanReadFile( filename ); reader->Update(); gdcm::Scanner scanner; // (0008,0005) CS [ISO_IR 100] # 10, 1 SpecificCharacterSet // (0008,0008) CS [ORIGINAL\PRIMARY\AXIAL] # 22, 3 ImageType const gdcm::Tag t1(0x0008,0x0005); const gdcm::Tag t2(0x0008,0x0008); scanner.AddTag( t1 ); scanner.AddTag( t2 ); const gdcm::Global& g = gdcm::Global::GetInstance(); const gdcm::Dicts &ds = g.GetDicts(); (void)ds; bool b = scanner.Scan( l ); if( !b ) { return 1; } vtkMedicalImageProperties * medprop = reader->GetMedicalImageProperties(); #if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) || VTK_MAJOR_VERSION > 5 const char *value1 = scanner.GetValue( filename, t1 ); const gdcm::DictEntry& de1 = ds.GetDictEntry( t1 ); medprop->AddUserDefinedValue(de1.GetName(), value1); const char *value2 = scanner.GetValue( filename, t2 ); const gdcm::DictEntry& de2 = ds.GetDictEntry( t2 ); medprop->AddUserDefinedValue(de2.GetName(), value2); #endif if( verbose ) { reader->GetOutput()->Print( cout ); reader->GetMedicalImageProperties()->Print( cout ); } // Create directory first: const char subdir[] = "TestvtkGDCMImageReader4"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string gdcmfile = gdcm::Testing::GetTempFilename( filename, subdir ); vtkGDCMImageWriter *writer = vtkGDCMImageWriter::New(); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputConnection( reader->GetOutputPort() ); #else writer->SetInput( reader->GetOutput() ); #endif writer->SetFileLowerLeft( reader->GetFileLowerLeft() ); writer->SetDirectionCosines( reader->GetDirectionCosines() ); writer->SetImageFormat( reader->GetImageFormat() ); writer->SetFileDimensionality( reader->GetFileDimensionality() ); writer->SetMedicalImageProperties( reader->GetMedicalImageProperties() ); writer->SetShift( reader->GetShift() ); writer->SetScale( reader->GetScale() ); writer->SetFileName( gdcmfile.c_str() ); writer->Write(); if( verbose ) std::cerr << "Write out: " << gdcmfile << std::endl; reader->Delete(); writer->Delete(); return 0; } int TestvtkGDCMImageReader4(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestvtkGDCMImageRead4(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestvtkGDCMImageRead4( filename, false ); ++i; } return r; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMImageReaderIsLossy.cxx000066400000000000000000000042401412732066400253470ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkImageData.h" #include "vtkMultiThreader.h" #include "vtkMedicalImageProperties.h" #include "gdcmTesting.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmImageReader.h" #ifndef vtkFloatingPointType #define vtkFloatingPointType double #endif int TestvtkGDCMImageReaderIsLossyFunc(const char *filename, bool verbose = false) { gdcm::Filename fn = filename; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); int canread = reader->CanReadFile( filename ); int res = 0; if( canread ) { reader->SetFileName( filename ); reader->Update(); if( verbose ) { reader->GetOutput()->Print( cout ); reader->GetMedicalImageProperties()->Print( cout ); } int reflossy = gdcm::Testing::GetLossyFlagFromFile( filename ); if( reader->GetLossyFlag() != reflossy ) { std::cerr << "Mismatch for " << filename << std::endl; ++res; } } else { std::cerr << "Could not read: " << filename << std::endl; //++res; } reader->Delete(); return res; } int TestvtkGDCMImageReaderIsLossy(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestvtkGDCMImageReaderIsLossyFunc(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestvtkGDCMImageReaderIsLossyFunc( filename ); ++i; } return r; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMImageViewer.cxx000066400000000000000000000036201412732066400240610ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkPNGWriter.h" #include "vtkImageColorViewer.h" #include "vtkImageData.h" #include "vtkImageActor.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkInteractorStyleImage.h" #include #include "gdcmTesting.h" int TestvtkGDCMReadImageViewer(const char *filename) { vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); //reader->CanReadFile( filename ); std::cerr << "Reading : " << filename << std::endl; reader->SetFileName( filename ); reader->Update(); reader->GetOutput()->Print( cout ); vtkImageColorViewer *viewer = vtkImageColorViewer::New(); viewer->SetInput( reader->GetOutput() ); vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); viewer->SetupInteractor( iren ); viewer->Render(); iren->Initialize(); iren->Start(); reader->Delete(); iren->Delete(); return 0; } int TestvtkGDCMImageViewer(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestvtkGDCMReadImageViewer(filename); } // else int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestvtkGDCMReadImageViewer( filename ); ++i; } return r; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMImageWriter1.cxx000066400000000000000000000217211412732066400241570ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkGDCMImageWriter.h" #include "vtkImageData.h" #include "vtkMultiThreader.h" #include "vtkMedicalImageProperties.h" #include "vtkVersion.h" #include "gdcmTesting.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmImageReader.h" #ifndef vtkFloatingPointType #define vtkFloatingPointType double #endif int TestvtkGDCMImageWrite(const char *filename, bool verbose = false) { int res = 0; // no error if( verbose ) std::cerr << "Reading : " << filename << std::endl; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); reader->FileLowerLeftOn(); int canread = reader->CanReadFile( filename ); if( canread ) { reader->SetFileName( filename ); reader->Update(); if( verbose ) { reader->GetOutput()->Print( cout ); reader->GetMedicalImageProperties()->Print( cout ); } // Create directory first: const char subdir[] = "TestvtkGDCMImageWriter"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string gdcmfile = gdcm::Testing::GetTempFilename( filename, subdir ); vtkGDCMImageWriter *writer = vtkGDCMImageWriter::New(); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputConnection( reader->GetOutputPort() ); #else writer->SetInput( reader->GetOutput() ); #endif writer->SetFileLowerLeft( reader->GetFileLowerLeft() ); writer->SetDirectionCosines( reader->GetDirectionCosines() ); writer->SetImageFormat( reader->GetImageFormat() ); writer->SetFileDimensionality( reader->GetFileDimensionality() ); writer->SetMedicalImageProperties( reader->GetMedicalImageProperties() ); writer->SetPlanarConfiguration( reader->GetPlanarConfiguration() ); writer->SetShift( reader->GetShift() ); writer->SetScale( reader->GetScale() ); writer->SetFileName( gdcmfile.c_str() ); writer->Write(); if( verbose ) std::cerr << "Write out: " << gdcmfile << std::endl; writer->Delete(); // Need to check we can still read this image back: gdcm::ImageReader r; if( gdcm::System::FileExists( gdcmfile.c_str() ) ) { r.SetFileName( gdcmfile.c_str() ); } if( !r.Read() ) { std::cerr << "failed to read back:" << gdcmfile << std::endl; res = 1; } else { // ok could read the file, now check origin is ok: const gdcm::Image &image = r.GetImage(); const double *origin = image.GetOrigin(); if( origin ) { vtkImageData * vtkimg = reader->GetOutput(); const vtkFloatingPointType *vtkorigin = vtkimg->GetOrigin(); if( fabs(vtkorigin[0] - origin[0]) > 1.e-3 || fabs(vtkorigin[1] - origin[1]) > 1.e-3 || fabs(vtkorigin[2] - origin[2]) > 1.e-3 ) { std::cerr << "Problem:" << vtkorigin[0] << "," << vtkorigin[1] << "," << vtkorigin[2] ; std::cerr << " should be:" << origin[0] << "," << origin[1] << "," << origin[2] << std::endl ; std::cerr << filename << std::endl; res = 1; } } gdcm::ImageReader r2; r2.SetFileName( filename ); if( !r2.Read() ) { std::cerr << "failed to re-read initial image...how is that possible ?:" << filename << std::endl; res = 1; } const gdcm::Image &compimage = r2.GetImage(); // Check that Media Storage is still correct: // Well this is difficult to implement as Retired class are replaced with newer one automatically gdcm::MediaStorage ms1; ms1.SetFromFile( r.GetFile() ); // our rewritten file gdcm::MediaStorage ms2; ms2.SetFromFile( r2.GetFile() ); // original file if( ms1 != ms2 ) { if( ms1 == gdcm::MediaStorage::MultiframeGrayscaleByteSecondaryCaptureImageStorage ) { // Hum I have this weird case when reading libido1.0-vol.acr... } else if( ms1 == gdcm::MediaStorage::XRayAngiographicImageStorage && ms2 == gdcm::MediaStorage::SecondaryCaptureImageStorage ) { // FIXME: D_CLUNIE_XA1_JPLL.dcm } else if( ms2 == gdcm::MediaStorage::XRayRadiofluoroscopingImageStorage ) { // gdcmData/JDDICOM_Sample5.dcm } else if( ms1 == gdcm::MediaStorage::EnhancedMRImageStorage && ms2 == gdcm::MediaStorage::MRImageStorage ) { // gdcmData/MR-MONO2-8-16x-heart.dcm } else if( ms1 == gdcm::MediaStorage::UltrasoundImageStorage && ms2 == gdcm::MediaStorage::UltrasoundImageStorageRetired ) { // gdcmData/US-RGB-8-esopecho.dcm } else if( ms1 == gdcm::MediaStorage::UltrasoundMultiFrameImageStorage && ms2 == gdcm::MediaStorage::UltrasoundMultiFrameImageStorageRetired ) { // gdcmData/US-MONO2-8-8x-execho.dcm } else if ( ms1 == gdcm::MediaStorage::NuclearMedicineImageStorage && ms2 == gdcm::MediaStorage::SecondaryCaptureImageStorage ) { // gdcmData/Renal_Flow.dcm } else if ( ms1 == gdcm::MediaStorage::CTImageStorage && ms2 == gdcm::MediaStorage::SecondaryCaptureImageStorage ) { // gdcmData/D_CLUNIE_SC1_JPLY.dcm } else if ( ms1 == gdcm::MediaStorage::EnhancedCTImageStorage && ms2 == gdcm::MediaStorage::CTImageStorage && compimage.GetNumberOfDimensions() == 3 ) { // gdcmData/CroppedArm.dcm } else if( ms1 == gdcm::MediaStorage::MRImageStorage && ms2 == gdcm::MediaStorage::GeneralElectricMagneticResonanceImageStorage ) { // gdcmData/MR00010001.dcm } else if( ms1 == gdcm::MediaStorage::UltrasoundImageStorage && ms2 == gdcm::MediaStorage::SecondaryCaptureImageStorage ) { // gdcmData/GE_LOGIQBook-8-RGB-HugePreview.dcm } else if( ms1 == gdcm::MediaStorage::DigitalXRayImageStorageForProcessing && ms2 == gdcm::MediaStorage::DigitalXRayImageStorageForPresentation ) { // gdcmData/DX_GE_FALCON_SNOWY-VOI.dcm } else { std::cerr << "MediaStorage incompatible: " << ms1 << " vs " << ms2 << " for file: " << filename << std::endl; res = 1; } } // Make sure that md5 is still ok: unsigned long len = image.GetBufferLength(); char* buffer = new char[len]; bool res2 = image.GetBuffer(buffer); if( !res2 ) { std::cerr << "Could not get buffer" << std::endl; res = 1; } const char *ref = gdcm::Testing::GetMD5FromFile(filename); char digest[33]; gdcm::Testing::ComputeMD5(buffer, len, digest); if( !ref ) { std::cerr << "Could not compute md5" << std::endl; res = 1; } const gdcm::PixelFormat &comppf = compimage.GetPixelFormat(); if( !ref ) { std::cerr << "Missing md5: " << digest << std::endl; } else if( strcmp(digest, ref) != 0 // I do not support rewritting 12Bits pack image (illegal anyway) && comppf != gdcm::PixelFormat::UINT12 ) { #if 0 { unsigned long len = compimage.GetBufferLength(); char* buffer = new char[len]; bool res2 = compimage.GetBuffer(buffer); std::ofstream out("/tmp/debug.raw", std::ios::binary); out.write( buffer, len ); out.close(); } #endif std::cerr << "Problem reading image from: " << filename << std::endl; std::cerr << "Found " << digest << " instead of " << ref << std::endl; std::cerr << "Original TransferSyntax was: " << compimage.GetTransferSyntax() << std::endl; std::cerr << "Output image: " << gdcmfile << std::endl; res = 1; } delete[] buffer; } } else { if( verbose ) std::cerr << "vtkGDCMImageReader cannot read: " << filename << std::endl; } reader->Delete(); return res; } int TestvtkGDCMImageWriter1(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestvtkGDCMImageWrite(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestvtkGDCMImageWrite( filename ); ++i; } return r; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMImageWriter2.cxx000066400000000000000000000132551412732066400241630ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkGDCMImageWriter.h" #include "vtkImageData.h" #include "vtkMultiThreader.h" #include "vtkMedicalImageProperties.h" #include "vtkStringArray.h" #include "vtkVersion.h" #include "gdcmTesting.h" #include "gdcmFilename.h" #include "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmFilenameGenerator.h" #include "gdcmImageReader.h" #include #ifndef vtkFloatingPointType #define vtkFloatingPointType double #endif int TestvtkGDCMImageWrite2(const char *filename, bool verbose = false) { int res = 0; // no error if( verbose ) std::cerr << "Reading : " << filename << std::endl; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); reader->FileLowerLeftOn(); int canread = reader->CanReadFile( filename ); if( canread ) { reader->SetFileName( filename ); reader->Update(); if( verbose ) { reader->GetOutput()->Print( cout ); reader->GetMedicalImageProperties()->Print( cout ); } // Create directory first: const char subdir[] = "TestvtkGDCMImageWriter2"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string gdcmfile = gdcm::Testing::GetTempFilename( filename, subdir ); //std::cerr << filename << std::endl; //std::cerr << gdcmfile << std::endl; std::ostringstream os; os << gdcmfile; os << "%01d"; gdcm::FilenameGenerator fg; //fg.SetPattern( gdcmfile.c_str() ); fg.SetPattern( os.str().c_str() ); unsigned int nfiles = reader->GetOutput()->GetDimensions()[2]; fg.SetNumberOfFilenames( nfiles ); bool b = fg.Generate(); if( !b ) { std::cerr << "FilenameGenerator::Generate() failed" << std::endl; return 1; } if( !fg.GetNumberOfFilenames() ) { std::cerr << "FilenameGenerator::Generate() failed somehow..." << std::endl; return 1; } vtkGDCMImageWriter *writer = vtkGDCMImageWriter::New(); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputConnection( reader->GetOutputPort() ); #else writer->SetInput( reader->GetOutput() ); #endif writer->SetFileLowerLeft( reader->GetFileLowerLeft() ); writer->SetDirectionCosines( reader->GetDirectionCosines() ); writer->SetImageFormat( reader->GetImageFormat() ); writer->SetFileDimensionality( 2 ); // test the 3D to 2D writing mode writer->SetMedicalImageProperties( reader->GetMedicalImageProperties() ); writer->SetShift( reader->GetShift() ); writer->SetScale( reader->GetScale() ); //writer->SetFileName( gdcmfile.c_str() ); vtkStringArray *filenames = vtkStringArray::New(); for(unsigned int i = 0; i < fg.GetNumberOfFilenames(); ++i) { filenames->InsertNextValue( fg.GetFilename(i) ); std::cerr << fg.GetFilename(i) << std::endl; } assert( filenames->GetNumberOfValues() == (int)fg.GetNumberOfFilenames() ); writer->SetFileNames( filenames ); writer->Write(); //if( verbose ) std::cerr << "Write out: " << gdcmfile << std::endl; writer->Delete(); // Need to check we can still read those files back: for(int file=0; fileGetNumberOfValues(); ++file) { const char *fname = filenames->GetValue(file); gdcm::ImageReader r; //r.SetFileName( gdcmfile.c_str() ); r.SetFileName( fname ); if( !r.Read() ) { std::cerr << "failed to read back:" << fname << std::endl; res = 1; } else { if( file == 0 ) { // ok could read the file, now check origin is ok: const gdcm::Image &image = r.GetImage(); const double *origin = image.GetOrigin(); if( origin ) { /* FIXME: it would be nice if this test would also handle FileLowerLeftOff to do d'une pierre deux coups. */ vtkImageData * vtkimg = reader->GetOutput(); const vtkFloatingPointType *vtkorigin = vtkimg->GetOrigin(); if( fabs(vtkorigin[0] - origin[0]) > 1.e-3 || fabs(vtkorigin[1] - origin[1]) > 1.e-3 || fabs(vtkorigin[2] - origin[2]) > 1.e-3 ) { std::cerr << "Problem:" << vtkorigin[0] << "," << vtkorigin[1] << "," << vtkorigin[2] ; std::cerr << " should be:" << origin[0] << "," << origin[1] << "," << origin[2] << std::endl ; res = 1; } } } } } filenames->Delete(); } else { if( verbose ) std::cerr << "vtkGDCMImageReader cannot read: " << filename << std::endl; //res++; } reader->Delete(); return res; } int TestvtkGDCMImageWriter2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestvtkGDCMImageWrite2(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestvtkGDCMImageWrite2( filename ); ++i; } return r; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMImageWriterIsLossy.cxx000066400000000000000000000036561412732066400254330ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkImageNoiseSource.h" #include "vtkVersion.h" #include "vtkGDCMImageWriter.h" #include "gdcmTesting.h" #include "gdcmSystem.h" int TestvtkGDCMImageWriterIsLossy(int , char *[]) { vtkImageNoiseSource * noise = vtkImageNoiseSource::New(); noise->SetWholeExtent(1,256,1,256,0,0); noise->SetMinimum(0.0); noise->SetMaximum(255.0); // Create directory first: const char subdir[] = "TestvtkGDCMImageWriterIsLossy"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } const char *filename = "noise.dcm"; std::string gdcmfile = gdcm::Testing::GetTempFilename( filename, subdir ); vtkGDCMImageWriter *writer = vtkGDCMImageWriter::New(); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputConnection( noise->GetOutputPort() ); #else writer->SetInput( noise->GetOutput() ); #endif writer->SetShift( 0 ); writer->SetScale( 1.5 ); writer->SetLossyFlag( 1 ); writer->SetFileName( gdcmfile.c_str() ); writer->Write(); noise->Delete(); writer->Delete(); vtkGDCMImageReader * reader = vtkGDCMImageReader::New(); reader->SetFileName( gdcmfile.c_str() ); reader->Update(); int lossyflag = reader->GetLossyFlag(); reader->Delete(); if( lossyflag != 1 ) return 1; return 0; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMMetaImageWriter.cxx000066400000000000000000000115071412732066400247060ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkGDCMTesting.h" #include "vtkMedicalImageProperties.h" #include "vtkMetaImageWriter.h" #include "vtkImageData.h" #include "vtkStringArray.h" //#include #include "gdcmFilename.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmDirectory.h" #include "gdcmMediaStorage.h" static int TestvtkGDCMMetaImageWrite(const char *filename, bool verbose) { if( verbose ) std::cerr << "Reading : " << filename << std::endl; vtkGDCMImageReader *reader = vtkGDCMImageReader::New(); reader->FileLowerLeftOn(); reader->DebugOff(); int canread = reader->CanReadFile( filename ); if( !canread ) { reader->Delete(); gdcm::Filename fn( filename ); if( fn.GetName() == std::string("ELSCINT1_PMSCT_RLE1.dcm" ) ) { // No Pixel Data... return 0; } const char *refms = gdcm::Testing::GetMediaStorageFromFile(filename); if( gdcm::MediaStorage::IsImage( gdcm::MediaStorage::GetMSType(refms) ) ) { std::cerr << "Problem with: " << filename << std::endl; return 1; } // not an image return 0; } const char *refms = gdcm::Testing::GetMediaStorageFromFile(filename); if( !gdcm::MediaStorage::IsImage( gdcm::MediaStorage::GetMSType(refms) ) ) { if( !refms ) { std::cerr << "Missing SOP Class: " << filename << std::endl; return 1; } } reader->SetFileName( filename ); reader->Update(); if( verbose ) { reader->GetOutput()->Print( cout ); reader->GetMedicalImageProperties()->Print( cout ); } // if( verbose ) { // Create directory first: const char subdir[] = "TestvtkGDCMMetaImageWriter"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string mhdfile = gdcm::Testing::GetTempFilename( filename, subdir ); std::string rawfile = mhdfile; vtkMetaImageWriter *writer = vtkMetaImageWriter::New(); writer->SetCompression( false ); writer->SetInputConnection( reader->GetOutputPort() ); mhdfile += ".mhd"; rawfile += ".raw"; writer->SetFileName( mhdfile.c_str() ); writer->Write(); writer->Delete(); if( verbose ) cout << "Wrote MHD output into: " << mhdfile << std::endl; char digestmhd[33] = {}; char digestraw[33] = {}; bool bmhd = gdcm::Testing::ComputeFileMD5( mhdfile.c_str() , digestmhd ); bool braw = gdcm::Testing::ComputeFileMD5( rawfile.c_str() , digestraw ); assert( bmhd && braw ); (void)bmhd; (void)braw; const char * mhdref = vtkGDCMTesting::GetMHDMD5FromFile(filename); const char * rawref = vtkGDCMTesting::GetRAWMD5FromFile(filename); if( !mhdref || !rawref ) { std::cout << "Found: \"" << filename << "\",\"" << digestmhd << "\", \"" << digestraw << "\"" << std::endl; return 1; } else if( strcmp(digestraw, rawref) ) { std::cerr << "Problem reading RAW from: " << rawfile << std::endl; std::cerr << "Found " << digestraw << " instead of " << rawref << std::endl; return 1; } else if( strcmp(digestmhd, mhdref) ) { std::cerr << "Problem reading MHD from: " << mhdfile << std::endl; std::cerr << "Found " << digestmhd << " instead of " << mhdref << std::endl; return 1; } } reader->Delete(); return 0; } int TestvtkGDCMMetaImageWriter(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestvtkGDCMMetaImageWrite(filename, true); } #if 0 unsigned int n = vtkGDCMTesting::GetNumberOfMD5MetaImages(); for( unsigned int i = 0; i < n; ++i ) { const char * const * p = vtkGDCMTesting::GetMD5MetaImage(i); std::cout << p[1] << " " << p[0] << ".mhd" << std::endl; std::cout << p[2] << " " << p[0] << ".raw" << std::endl; } return 0; #endif // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestvtkGDCMMetaImageWrite( filename, false ); ++i; } return r; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMMetaImageWriter2.cxx000066400000000000000000000115151412732066400247670ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader2.h" #include "vtkGDCMTesting.h" #include "vtkMedicalImageProperties.h" #include "vtkMetaImageWriter.h" #include "vtkImageData.h" #include "vtkStringArray.h" //#include #include "gdcmFilename.h" #include "gdcmTesting.h" #include "gdcmSystem.h" #include "gdcmTrace.h" #include "gdcmDirectory.h" #include "gdcmMediaStorage.h" static int TestvtkGDCMMetaImageWrite(const char *filename, bool verbose) { if( verbose ) std::cerr << "Reading : " << filename << std::endl; vtkGDCMImageReader2 * reader = vtkGDCMImageReader2::New(); reader->FileLowerLeftOn(); reader->DebugOff(); int canread = reader->CanReadFile( filename ); if( !canread ) { reader->Delete(); gdcm::Filename fn( filename ); if( fn.GetName() == std::string("ELSCINT1_PMSCT_RLE1.dcm" ) ) { // No Pixel Data... return 0; } const char *refms = gdcm::Testing::GetMediaStorageFromFile(filename); if( gdcm::MediaStorage::IsImage( gdcm::MediaStorage::GetMSType(refms) ) ) { std::cerr << "Problem with: " << filename << std::endl; return 1; } // not an image return 0; } const char *refms = gdcm::Testing::GetMediaStorageFromFile(filename); if( !gdcm::MediaStorage::IsImage( gdcm::MediaStorage::GetMSType(refms) ) ) { if( !refms ) { std::cerr << "Missing SOP Class: " << filename << std::endl; return 1; } } reader->SetFileName( filename ); reader->Update(); if( verbose ) { reader->GetOutput()->Print( cout ); reader->GetMedicalImageProperties()->Print( cout ); } // if( verbose ) { // Create directory first: const char subdir[] = "TestvtkGDCMMetaImageWriter2"; std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string mhdfile = gdcm::Testing::GetTempFilename( filename, subdir ); std::string rawfile = mhdfile; vtkMetaImageWriter *writer = vtkMetaImageWriter::New(); writer->SetCompression( false ); writer->SetInputConnection( reader->GetOutputPort() ); mhdfile += ".mhd"; rawfile += ".raw"; writer->SetFileName( mhdfile.c_str() ); writer->Write(); writer->Delete(); if( verbose ) cout << "Wrote MHD output into: " << mhdfile << std::endl; char digestmhd[33] = {}; char digestraw[33] = {}; bool bmhd = gdcm::Testing::ComputeFileMD5( mhdfile.c_str() , digestmhd ); bool braw = gdcm::Testing::ComputeFileMD5( rawfile.c_str() , digestraw ); assert( bmhd && braw ); (void)bmhd; (void)braw; const char * mhdref = vtkGDCMTesting::GetMHDMD5FromFile(filename); const char * rawref = vtkGDCMTesting::GetRAWMD5FromFile(filename); if( !mhdref || !rawref ) { std::cout << "Found: \"" << filename << "\",\"" << digestmhd << "\", \"" << digestraw << "\"" << std::endl; return 1; } else if( strcmp(digestraw, rawref) ) { std::cerr << "Problem reading RAW from: " << rawfile << std::endl; std::cerr << "Found " << digestraw << " instead of " << rawref << std::endl; return 1; } else if( strcmp(digestmhd, mhdref) ) { std::cerr << "Problem reading MHD from: " << mhdfile << std::endl; std::cerr << "Found " << digestmhd << " instead of " << mhdref << std::endl; return 1; } } reader->Delete(); return 0; } int TestvtkGDCMMetaImageWriter2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestvtkGDCMMetaImageWrite(filename, true); } #if 0 unsigned int n = vtkGDCMTesting::GetNumberOfMD5MetaImages(); for( unsigned int i = 0; i < n; ++i ) { const char * const * p = vtkGDCMTesting::GetMD5MetaImage(i); std::cout << p[1] << " " << p[0] << ".mhd" << std::endl; std::cout << p[2] << " " << p[0] << ".raw" << std::endl; } return 0; #endif // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); gdcm::Trace::ErrorOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestvtkGDCMMetaImageWrite( filename, false ); ++i; } return r; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMPolyDataReader.cxx000066400000000000000000000044051412732066400245170ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMPolyDataReader.h" #include "vtkMedicalImageProperties.h" #include "gdcmDirectory.h" #include "gdcmTesting.h" #include "gdcmTrace.h" static const char * rtstruct_files[] = { "gdcmNonImageData/RTSTRUCT_1.3.6.1.4.1.22213.1.1396.2.dcm", "gdcmNonImageData/RT/RTStruct.dcm", "gdcmNonImageData/exRT_Structure_Set_Storage.dcm", 0 }; static const int rtstruct_files_nb[] = { 9, 4, 10 }; int TestvtkGDCMPolyDataRead(const char *filename, int nb, bool verbose) { int ret = 0; if( verbose ) std::cerr << "Reading : " << filename << std::endl; vtkGDCMPolyDataReader *reader = vtkGDCMPolyDataReader::New(); reader->SetFileName( filename ); //int canread = reader->CanReadFile( filename ); reader->Update(); if( verbose ) { reader->GetOutput()->Print( cout ); reader->GetMedicalImageProperties()->Print( cout ); } //std::cout << reader->GetNumberOfOutputPorts() << std::endl; if( nb != -1 && reader->GetNumberOfOutputPorts() != nb ) { ret = 1; } reader->Delete(); return ret; } int TestvtkGDCMPolyDataReader(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestvtkGDCMPolyDataRead(filename, -1, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; //const char * const *filenames = gdcm::Testing::GetFileNames(); //gdcmDataExtra const char *extradataroot = gdcm::Testing::GetDataExtraRoot(); while( (filename = rtstruct_files[i]) ) { std::string fullpath = extradataroot; fullpath += "/"; fullpath += filename; r += TestvtkGDCMPolyDataRead( fullpath.c_str(), rtstruct_files_nb[i], true); ++i; } return r; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMThreadedImageReader.cxx000066400000000000000000000162221412732066400254650ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMThreadedImageReader.h" #include "vtkGDCMImageReader.h" #include "vtkCommand.h" #include "vtkVersion.h" #include "gdcmDirectory.h" #include "gdcmSystem.h" #include "gdcmImageReader.h" #include "gdcmTesting.h" #include "vtkPNGWriter.h" #include "vtkStringArray.h" #include "vtkStructuredPointsWriter.h" #include "vtkImageData.h" #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) #include #include "vtkVolumeTextureMapper3D.h" #endif #include "vtkPiecewiseFunction.h" #include "vtkColorTransferFunction.h" #include "vtkVolumeProperty.h" #include "vtkVolume.h" #include "vtkRenderer.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" class ProgressObserver : public vtkCommand { public: static ProgressObserver* New() { return new ProgressObserver; } virtual void Execute(vtkObject* caller, unsigned long event, void *callData) { (void)callData; if( event == vtkCommand::ProgressEvent ) { std::cout << ((vtkGDCMThreadedImageReader*)caller)->GetProgress() << std::endl; } } }; template int ExecuteInformation(const char *filename, TReader *vtkreader) { gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { return 0; } const gdcm::Image &image = reader.GetImage(); const unsigned int *dims = image.GetDimensions(); // Set the Extents. assert( image.GetNumberOfDimensions() >= 2 ); int dataextent[6] = {}; dataextent[0] = 0; dataextent[1] = dims[0] - 1; dataextent[2] = 0; dataextent[3] = dims[1] - 1; if( image.GetNumberOfDimensions() == 2 ) { vtkStringArray *filenames = vtkreader->GetFileNames(); if ( filenames && filenames->GetNumberOfValues() > 1 ) { dataextent[4] = 0; dataextent[5] = (int)filenames->GetNumberOfValues() - 1; } else { dataextent[4] = 0; dataextent[5] = 0; } } else { assert( image.GetNumberOfDimensions() == 3 ); //this->FileDimensionality = 3; dataextent[4] = 0; dataextent[5] = dims[2] - 1; } //this->DataSpacing[0] = 1.; //this->DataSpacing[1] = -1.; //this->DataSpacing[2] = 1.; gdcm::PixelFormat pixeltype = image.GetPixelFormat(); int datascalartype = VTK_VOID; switch( pixeltype ) { case gdcm::PixelFormat::INT8: datascalartype = VTK_CHAR; break; case gdcm::PixelFormat::UINT8: datascalartype = VTK_UNSIGNED_CHAR; break; case gdcm::PixelFormat::INT16: datascalartype = VTK_SHORT; break; case gdcm::PixelFormat::UINT16: datascalartype = VTK_UNSIGNED_SHORT; break; case gdcm::PixelFormat::INT32: datascalartype = VTK_INT; break; case gdcm::PixelFormat::UINT32: datascalartype = VTK_UNSIGNED_INT; break; default: ; } if( datascalartype == VTK_VOID ) { return 0; } unsigned int numberOfScalarComponents = pixeltype.GetSamplesPerPixel(); vtkreader->SetDataExtent( dataextent ); vtkreader->SetDataScalarType ( datascalartype ); //vtkreader->SetShift( image.GetIntercept() ); //vtkreader->SetScale( image.GetSlope() ); vtkreader->SetNumberOfScalarComponents( numberOfScalarComponents ); vtkreader->LoadOverlaysOff(); if( image.GetNumberOfOverlays() ) { vtkreader->LoadOverlaysOn(); } return 1; } template int TestvtkGDCMThreadedImageRead(const char *filename, bool verbose = false) { TReader *reader = TReader::New(); reader->FileLowerLeftOn(); //reader->CanReadFile( filename ); if( verbose) std::cerr << "Reading : " << filename << std::endl; const char *refimage = NULL; if( gdcm::System::FileIsDirectory( filename ) ) { gdcm::Directory d; d.Load( filename ); gdcm::Directory::FilenamesType l = d.GetFilenames(); const size_t nfiles = l.size(); vtkStringArray *sarray = vtkStringArray::New(); for(unsigned int i = 0; i < nfiles; ++i) { sarray->InsertNextValue( l[i] ); } assert( sarray->GetNumberOfValues() == (int)nfiles ); reader->SetFileNames( sarray ); sarray->Delete(); refimage = sarray->GetValue( 0 ); // Ok since sarray is ref count } else { reader->SetFileName( filename ); refimage = filename; } // In all cases we need to explicitly say what the image type is: if( !ExecuteInformation(refimage, reader) ) { std::cerr << "file: " << refimage << " is not an image. giving up" << std::endl; reader->Delete(); return 0; } ProgressObserver *obs = ProgressObserver::New(); if( verbose ) { reader->AddObserver( vtkCommand::ProgressEvent, obs); } reader->Update(); obs->Delete(); //reader->GetOutput()->Print( cout ); //reader->GetOutput(1)->Print( cout ); if( reader->GetNumberOfOverlays() ) { vtkPNGWriter *writer = vtkPNGWriter::New(); writer->SetInput( reader->GetOutput(1) ); const char subdir[] = "TestvtkGDCMThreadedImageReader"; // Create directory first: std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string pngfile = gdcm::Testing::GetTempFilename( filename, subdir ); //pngfile += vtksys::SystemTools::GetFilenameWithoutExtension( filename ); pngfile += ".png"; writer->SetFileName( pngfile.c_str() ); if( verbose ) std::cerr << pngfile << std::endl; //writer->Write(); writer->Delete(); } /* vtkStructuredPointsWriter *writer = vtkStructuredPointsWriter::New(); writer->SetInput( reader->GetOutput() ); writer->SetFileName( "TestvtkGDCMThreadedImageReader.vtk" ); writer->SetFileTypeToBinary(); //writer->Write(); writer->Delete(); */ bool compute = false; if( verbose && compute ) { #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 2 ) double *s = reader->GetOutput()->GetScalarRange(); #else float *s = reader->GetOutput()->GetScalarRange(); #endif std::cout << s[0] << " " << s[1] << std::endl; } reader->Delete(); return 0; } int TestvtkGDCMThreadedImageReader(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestvtkGDCMThreadedImageRead(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestvtkGDCMThreadedImageRead( filename ); ++i; } return r; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkGDCMThreadedImageReader2.cxx000066400000000000000000000157771412732066400255650ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMThreadedImageReader2.h" #include "vtkGDCMImageReader.h" #include "vtkCommand.h" #include "vtkVersion.h" #include "gdcmDirectory.h" #include "gdcmSystem.h" #include "gdcmImageReader.h" #include "gdcmTesting.h" #include "vtkPNGWriter.h" #include "vtkStringArray.h" #include "vtkStructuredPointsWriter.h" #include "vtkImageData.h" #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) #include #endif class ProgressObserver : public vtkCommand { public: static ProgressObserver* New() { return new ProgressObserver; } virtual void Execute(vtkObject* caller, unsigned long event, void *callData) { (void)callData; if( event == vtkCommand::ProgressEvent ) { std::cout << ((vtkGDCMThreadedImageReader2*)caller)->GetProgress() << std::endl; } } }; template int ExecuteInformation(const char *filename, TReader *vtkreader) { gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { return 0; } const gdcm::Image &image = reader.GetImage(); const unsigned int *dims = image.GetDimensions(); // Set the Extents. assert( image.GetNumberOfDimensions() >= 2 ); int dataextent[6] = {}; dataextent[0] = 0; dataextent[1] = dims[0] - 1; dataextent[2] = 0; dataextent[3] = dims[1] - 1; if( image.GetNumberOfDimensions() == 2 ) { vtkStringArray *filenames = vtkreader->GetFileNames(); if ( filenames && filenames->GetNumberOfValues() > 1 ) { dataextent[4] = 0; dataextent[5] = (int)filenames->GetNumberOfValues() - 1; } else { dataextent[4] = 0; dataextent[5] = 0; } } else { assert( image.GetNumberOfDimensions() == 3 ); //this->FileDimensionality = 3; dataextent[4] = 0; dataextent[5] = dims[2] - 1; } //this->DataSpacing[0] = 1.; //this->DataSpacing[1] = -1.; //this->DataSpacing[2] = 1.; gdcm::PixelFormat pixeltype = image.GetPixelFormat(); int datascalartype = VTK_VOID; switch( pixeltype ) { case gdcm::PixelFormat::INT8: datascalartype = VTK_CHAR; break; case gdcm::PixelFormat::UINT8: datascalartype = VTK_UNSIGNED_CHAR; break; case gdcm::PixelFormat::INT16: datascalartype = VTK_SHORT; break; case gdcm::PixelFormat::UINT16: datascalartype = VTK_UNSIGNED_SHORT; break; case gdcm::PixelFormat::INT32: datascalartype = VTK_INT; break; case gdcm::PixelFormat::UINT32: datascalartype = VTK_UNSIGNED_INT; break; default: ; } if( datascalartype == VTK_VOID ) { return 0; } unsigned int numberOfScalarComponents = pixeltype.GetSamplesPerPixel(); vtkreader->SetDataExtent( dataextent ); vtkreader->SetDataScalarType ( datascalartype ); //vtkreader->SetShift( image.GetIntercept() ); //vtkreader->SetScale( image.GetSlope() ); vtkreader->SetNumberOfScalarComponents( numberOfScalarComponents ); vtkreader->LoadOverlaysOff(); if( image.GetNumberOfOverlays() ) { vtkreader->LoadOverlaysOn(); } return 1; } template int TestvtkGDCMThreadedImageRead2(const char *filename, bool verbose = false) { TReader *reader = TReader::New(); reader->FileLowerLeftOn(); //reader->CanReadFile( filename ); if( verbose) std::cerr << "Reading : " << filename << std::endl; const char *refimage = NULL; if( gdcm::System::FileIsDirectory( filename ) ) { gdcm::Directory d; d.Load( filename ); gdcm::Directory::FilenamesType l = d.GetFilenames(); const size_t nfiles = l.size(); vtkStringArray *sarray = vtkStringArray::New(); for(unsigned int i = 0; i < nfiles; ++i) { sarray->InsertNextValue( l[i] ); } assert( sarray->GetNumberOfValues() == (int)nfiles ); reader->SetFileNames( sarray ); sarray->Delete(); refimage = sarray->GetValue( 0 ); // Ok since sarray is ref count } else { reader->SetFileName( filename ); refimage = filename; } // In all cases we need to explicitly say what the image type is: if( !ExecuteInformation(refimage, reader) ) { std::cerr << "file: " << refimage << " is not an image. giving up" << std::endl; reader->Delete(); return 0; } ProgressObserver *obs = ProgressObserver::New(); if( verbose ) { reader->AddObserver( vtkCommand::ProgressEvent, obs); } reader->Update(); obs->Delete(); //reader->GetOutput()->Print( cout ); //reader->GetOutput(1)->Print( cout ); if( reader->GetNumberOfOverlays() ) { vtkPNGWriter *writer = vtkPNGWriter::New(); #if (VTK_MAJOR_VERSION >= 6) writer->SetInputConnection( reader->GetOutputPort(1) ); #else writer->SetInput( reader->GetOutput(1) ); #endif const char subdir[] = "TestvtkGDCMThreadedImageReader2"; // Create directory first: std::string tmpdir = gdcm::Testing::GetTempDirectory( subdir ); if( !gdcm::System::FileIsDirectory( tmpdir.c_str() ) ) { gdcm::System::MakeDirectory( tmpdir.c_str() ); //return 1; } std::string pngfile = gdcm::Testing::GetTempFilename( filename, subdir ); //pngfile += vtksys::SystemTools::GetFilenameWithoutExtension( filename ); pngfile += ".png"; writer->SetFileName( pngfile.c_str() ); if( verbose ) std::cerr << pngfile << std::endl; //writer->Write(); writer->Delete(); } /* vtkStructuredPointsWriter *writer = vtkStructuredPointsWriter::New(); writer->SetInput( reader->GetOutput() ); writer->SetFileName( "TestvtkGDCMThreadedImageReader2.vtk" ); writer->SetFileTypeToBinary(); //writer->Write(); writer->Delete(); */ bool compute = false; if( verbose && compute ) { #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 2 ) double *s = reader->GetOutput()->GetScalarRange(); #else float *s = reader->GetOutput()->GetScalarRange(); #endif std::cout << s[0] << " " << s[1] << std::endl; } reader->Delete(); return 0; } int TestvtkGDCMThreadedImageReader2(int argc, char *argv[]) { if( argc == 2 ) { const char *filename = argv[1]; return TestvtkGDCMThreadedImageRead2(filename, true); } // else gdcm::Trace::DebugOff(); gdcm::Trace::WarningOff(); int r = 0, i = 0; const char *filename; const char * const *filenames = gdcm::Testing::GetFileNames(); while( (filename = filenames[i]) ) { r += TestvtkGDCMThreadedImageRead2( filename ); ++i; } return r; } GDCM-3.0.10/Utilities/VTK/Testing/Cxx/TestvtkImageChangeInformation.cxx000066400000000000000000000052521412732066400255630ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkDirectory.h" #include "vtkImageActor.h" #include "vtkImageChangeInformation.h" #include "vtkImageMapToWindowLevelColors.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" int TestvtkImageChangeInformation(int argc, char *argv[]) { if( argc < 2 ) { std::cerr << "Need arg" << std::endl; return 1; } const char *dirname = argv[1]; vtkDirectory * dir = vtkDirectory::New(); int r = dir->Open( dirname ); if( !r ) { std::cerr << "Cannot open dir:" << dirname << std::endl; return 1; } vtkIdType nfiles = dir->GetNumberOfFiles(); vtkImageChangeInformation *ici = vtkImageChangeInformation::New(); ici->SetOutputOrigin(0, 0, 0); vtkImageMapToWindowLevelColors * windowlevel = vtkImageMapToWindowLevelColors::New(); windowlevel->SetInput( ici->GetOutput() ); vtkImageActor *imageactor = vtkImageActor::New(); imageactor->SetInput( windowlevel->GetOutput() ); // Create the RenderWindow, Renderer and both Actors vtkRenderer *ren = vtkRenderer::New(); vtkRenderWindow *renWin = vtkRenderWindow::New(); renWin->AddRenderer (ren); // Add the actors to the renderer, set the background and size ren->AddActor (imageactor); double range[2]; for ( vtkIdType file = 0; file < nfiles; ++file ) { vtkGDCMImageReader * reader = vtkGDCMImageReader::New(); ici->SetInput( reader->GetOutput() ); std::string filename = dir->GetFile(file); if( filename.find( "dcm" ) != std::string::npos ) { std::string fullpath = dirname; fullpath += "/"; fullpath += filename; std::cerr << "Processing: " << fullpath << std::endl; reader->SetFileName( fullpath.c_str() ); //reader->Update(); //ici->GetOutput()->Update(); // bad ! ici->GetOutput()->GetScalarRange(range); //reader->GetOutput()->GetScalarRange(range); renWin->Render(); std::cerr << "Range: " << range[0] << " " << range[1] << std::endl; } reader->Delete(); } dir->Delete(); ici->Delete(); windowlevel->Delete(); imageactor->Delete(); return 0; } GDCM-3.0.10/Utilities/VTK/Testing/Java/000077500000000000000000000000001412732066400172275ustar00rootroot00000000000000GDCM-3.0.10/Utilities/VTK/Testing/Java/CMakeLists.txt000066400000000000000000000032701412732066400217710ustar00rootroot00000000000000# Define the tests for vtkgdcm-java set(VTKGDCM_JAVA_TEST_SRCS TestvtkGDCMImageReader ) set(classpath ${LIBRARY_OUTPUT_PATH}/vtkgdcm.jar${JavaProp_PATH_SEPARATOR}${LIBRARY_OUTPUT_PATH}/gdcm.jar${JavaProp_PATH_SEPARATOR}${VTK_JAVA_JAR}${JavaProp_PATH_SEPARATOR}${GDCM_VTK_JAVA_JAR}) if(IS_DIRECTORY ${VTK_DIR}) if(IS_DIRECTORY ${VTK_DIR}/bin) # this is a build-tree VTK set(runtimepath "${VTK_DIR}/bin") if(UNIX) get_filename_component(dummyjava ${JAVA_MAWT_LIBRARY} PATH) set(runtimepath "${runtimepath}:${JAVA_LIBRARY_PATH}:${dummyjava}") endif() endif() endif() set(classfilesdep) foreach(example ${VTKGDCM_JAVA_TEST_SRCS}) add_custom_command( OUTPUT ${EXECUTABLE_OUTPUT_PATH}/${example}.class COMMAND ${Java_JAVAC_EXECUTABLE} ARGS -source ${GDCM_JAVA_SOURCE_VERSION} -target ${GDCM_JAVA_TARGET_VERSION} -classpath "${classpath}" ${CMAKE_CURRENT_SOURCE_DIR}/${example}.java -d ${EXECUTABLE_OUTPUT_PATH} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${example}.java COMMENT "javac ${example}.java" ) list(APPEND classfilesdep ${EXECUTABLE_OUTPUT_PATH}/${example}.class) set_source_files_properties(${EXECUTABLE_OUTPUT_PATH}/${example}.class PROPERTIES RUNTIMEPATH "${runtimepath}") set_source_files_properties(${EXECUTABLE_OUTPUT_PATH}/${example}.class PROPERTIES CLASSPATH "${classpath}") if(GDCM_WRAP_JAVA) ADD_JAVA_TEST(${example}Java ${EXECUTABLE_OUTPUT_PATH}/${example}) endif() endforeach() # 3. ok now add the target add_custom_target(VTKGDCMJavaTests ALL DEPENDS ${classfilesdep} COMMENT "building gdcm java vtk tests" ) add_dependencies(VTKGDCMJavaTests VTKGDCMJavaJar GDCMJavaJar) GDCM-3.0.10/Utilities/VTK/Testing/Java/TestvtkGDCMImageReader.java000066400000000000000000000023471412732066400242650ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ import gdcm.*; import vtk.*; /* */ public class TestvtkGDCMImageReader { static { System.loadLibrary("vtkCommonJava"); System.loadLibrary("vtkFilteringJava"); System.loadLibrary("vtkIOJava"); System.loadLibrary("vtkgdcmJava"); } public static void main(String[] args) { long nfiles = Testing.GetNumberOfFileNames(); Trace.DebugOff(); Trace.WarningOff(); for( long i = 0; i < nfiles; ++i ) { String filename = Testing.GetFileName( i ); //System.out.println("Success reading: " + filename ); vtkGDCMImageReader reader = new vtkGDCMImageReader(); reader.SetFileName( filename ); reader.Update(); } } } GDCM-3.0.10/Utilities/VTK/Testing/Python/000077500000000000000000000000001412732066400176275ustar00rootroot00000000000000GDCM-3.0.10/Utilities/VTK/Testing/Python/CMakeLists.txt000066400000000000000000000031541412732066400223720ustar00rootroot00000000000000# VTK-Python testing if(GDCM_WRAP_PYTHON) if(VTK_PYTHONPATH_DIRS) if(WIN32) #message(${VTK_PYTHONPATH_DIRS}) #string(REGEX REPLACE ";" ";" UNIX_VTK_PYTHONPATH_DIRS "${VTK_PYTHONPATH_DIRS}") set(UNIX_VTK_PYTHONPATH_DIRS "${VTK_PYTHONPATH_DIRS}") else() string(REGEX REPLACE ";" ":" UNIX_VTK_PYTHONPATH_DIRS "${VTK_PYTHONPATH_DIRS}") endif() else() # if VTK_PYTHONPATH_DIRS is not given (very old VTK) then simply hope the user set his pythonpath properly: # set(UNIX_VTK_PYTHONPATH_DIRS "$ENV{PYTHONPATH}") # previous solution was not safe, let's hope the following are set properly: if(WIN32) set(PATH_SEPARATOR ";") else() set(PATH_SEPARATOR ":") endif() if(VTK_SOURCE_DIR) set(UNIX_VTK_PYTHONPATH_DIRS "${VTK_SOURCE_DIR}/Wrapping/Python${PATH_SEPARATOR}${VTK_LIBRARY_DIRS}") else() # FIXME: hardcoded set(UNIX_VTK_PYTHONPATH_DIRS "/usr/local/src/vtk/build/Wrapping/Python${PATH_SEPARATOR}${VTK_LIBRARY_DIRS}") endif() endif() set(VTK_PYTHON_TESTS TestvtkGDCMImageReader TestvtkGDCMImageReader2 TestvtkGDCMImageWriter TestMultiframeGrayscaleWordSecondaryCaptureImageStorage ) if(GDCM_HAVE_PTHREAD_H) set(VTK_PYTHON_TESTS ${VTK_PYTHON_TESTS} #TestvtkGDCMThreadedImageReader TestvtkGDCMThreadedImageReader2 ) endif() foreach(test ${VTK_PYTHON_TESTS}) #message(${UNIX_VTK_PYTHONPATH_DIRS}) set_source_files_properties(${test}.py PROPERTIES PYTHONPATH "${UNIX_VTK_PYTHONPATH_DIRS}") ADD_PYTHON_TEST(${test}Python ${test}.py ${GDCM_DATA_ROOT}/test.acr) endforeach() endif() GDCM-3.0.10/Utilities/VTK/Testing/Python/TestMultiframeGrayscaleWordSecondaryCaptureImageStorage.py000066400000000000000000000024721412732066400333260ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import vtkgdcm import vtk from vtk.util.misc import vtkGetDataRoot #print vtkGetDataRoot() VTK_DATA_ROOT = vtkGetDataRoot() print(VTK_DATA_ROOT) v16 = vtk.vtkVolume16Reader() v16.SetDataDimensions(64, 64) v16.SetDataByteOrderToLittleEndian() v16.SetFilePrefix(VTK_DATA_ROOT + "/Data/headsq/quarter") v16.SetImageRange(1, 93) v16.SetDataSpacing(3.2, 3.2, 1.5) #v16.Update() # #print v16.GetOutput() w = vtkgdcm.vtkGDCMImageWriter() w.SetInputConnection( v16.GetOutputPort() ) w.SetFileDimensionality( 3 ) w.SetFileName( "sc.dcm" ) w.Write() # Now pretend this is an MR Image Storage: # Since image is 3D it should default to the new Enhance MR Image Storage: med = w.GetMedicalImageProperties() med.SetModality( "MR" ) w.SetFileName( "mr.dcm" ) w.Write() GDCM-3.0.10/Utilities/VTK/Testing/Python/TestvtkGDCMImageReader.py000066400000000000000000000034351412732066400243730ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ # Simply check that we can read mr.001 from VTKData import vtkgdcm import vtk from vtk.util.misc import vtkGetDataRoot VTK_DATA_ROOT = vtkGetDataRoot() r = vtkgdcm.vtkGDCMImageReader() r.SetFileName( VTK_DATA_ROOT + "/Data/mr.001" ) r.Update() #print r.GetOutput() # Pixel Spacing # 0.78125, 0.78125, 0 # Image Position (Patient) # -13.3034, -80.8219, 119.178 # try to rewrite it: w = vtkgdcm.vtkGDCMImageWriter() w.SetInput( r.GetOutput() ) w.SetMedicalImageProperties( r.GetMedicalImageProperties() ) w.SetDirectionCosines( r.GetDirectionCosines() ) w.SetFileName( "mr.001.dcm" ) w.Write() # beach.tif #tiffreader = vtk.vtkTIFFReader() #tiffreader.SetFileName( VTK_DATA_ROOT + "/Data/beach.tif" ) #tiffreader.Update() # print tiffreader.GetOutput() # -> TIFF reader was apparently broken in VTK until some very recent # version and thus image appear upside down, unless you also update VTKData :( jpegreader = vtk.vtkJPEGReader() jpegreader.SetFileName( VTK_DATA_ROOT + "/Data/beach.jpg" ) #jpegreader.Update() # Need a new writer otherwise MedicalImageProperties are re-used... w2 = vtkgdcm.vtkGDCMImageWriter() #w2.SetInput( tiffreader.GetOutput() ) w2.SetInput( jpegreader.GetOutput() ) w2.SetFileName( "beach.dcm" ) w2.Write() GDCM-3.0.10/Utilities/VTK/Testing/Python/TestvtkGDCMImageReader2.py000066400000000000000000000023711412732066400244530ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ # Simply check that we can read mr.001 from VTKData import vtkgdcm import vtk from vtk.util.misc import vtkGetDataRoot VTK_DATA_ROOT = vtkGetDataRoot() fns = vtk.vtkStringArray() fns.InsertNextValue( VTK_DATA_ROOT + "/Data/mr.001" ) fns.InsertNextValue( VTK_DATA_ROOT + "/Data/mr.001" ) fns.InsertNextValue( VTK_DATA_ROOT + "/Data/mr.001" ) r = vtkgdcm.vtkGDCMImageReader() r.SetFileNames( fns ) r.Update() print r.GetOutput() # try to rewrite it: w = vtkgdcm.vtkGDCMImageWriter() w.SetFileDimensionality( 3 ) w.SetInput( r.GetOutput() ) w.SetMedicalImageProperties( r.GetMedicalImageProperties() ) w.SetDirectionCosines( r.GetDirectionCosines() ) w.SetFileName( "mr3.001.dcm" ) w.Write() GDCM-3.0.10/Utilities/VTK/Testing/Python/TestvtkGDCMImageWriter.py000066400000000000000000000024251412732066400244430ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ import vtkgdcm import os,sys def PrintProgress(object, event): assert event == "ProgressEvent" print("Progress:", object.GetProgress()) if __name__ == "__main__": try: filename = os.sys.argv[1] except: # failure print("Need a filename") sys.exit(1) # setup reader r = vtkgdcm.vtkGDCMImageReader() r.SetFileName( filename ) r.AddObserver("ProgressEvent", PrintProgress) r.Update() print(r.GetOutput()) # Write output writer = vtkgdcm.vtkGDCMImageWriter() writer.SetInput( r.GetOutput() ) writer.SetMedicalImageProperties( r.GetMedicalImageProperties() ) writer.SetFileName( "TestvtkGDCMImageWriterPython.dcm" ) writer.Write() # Test succeed ? #sys.exit(success != 1) GDCM-3.0.10/Utilities/VTK/Testing/Python/TestvtkGDCMThreadedImageReader.py000066400000000000000000000101751412732066400260330ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ # This is important for now to load the vtkgdcm module first import vtkgdcm from vtk import vtkImageGradient from vtk import vtkMultiThreader from vtk import vtkDirectory from vtk import vtkStructuredPointsWriter from vtk.util import vtkConstants as vtkType from vtkgdcm import vtkStringArray import gdcm # for gdcm.Directory import os,sys def PrintProgress(object, event): assert event == "ProgressEvent" print "Progress:", object.GetProgress() # Helper function to extract image dimension and type # this info could also be coming from a database for example instead of read from a particular file def ExecuteInformation(reader, filename, dimz = 1): import gdcm reffile = filename # filenames.GetValue(0) # Take first image as reference #print reader r = gdcm.ImageReader() r.SetFileName( reffile ) success = r.Read() assert success #print r.GetImage().Print() image = r.GetImage() assert image.GetNumberOfDimensions() == 2 or image.GetNumberOfDimensions() == 3 dims = [0,0,0] dims[0] = image.GetDimension(0) dims[1] = image.GetDimension(1) dims[2] = dimz # filenames.GetNumberOfValues() #print dims #print image.GetPixelFormat().GetTPixelFormat() pixelformat = image.GetPixelFormat().GetScalarType() datascalartype = vtkType.VTK_VOID # dummy should not happen if pixelformat == gdcm.PixelFormat.INT8: datascalartype = vtkType.VTK_SIGNED_CHAR elif pixelformat == gdcm.PixelFormat.UINT8: datascalartype = vtkType.VTK_UNSIGNED_CHAR elif pixelformat == gdcm.PixelFormat.INT16: datascalartype = vtkType.VTK_SHORT elif pixelformat == gdcm.PixelFormat.UINT16: datascalartype = vtkType.VTK_UNSIGNED_SHORT else: print "Unhandled PixelFormat: ", pixelformat sys.exit(1) #print datascalartype numberOfScalarComponents = image.GetPixelFormat().GetSamplesPerPixel() #print numberOfScalarComponents #print gdcm.PhotometricInterpretation.GetPIString( image.GetPhotometricInterpretation().PIType() ) #reader.SetDataExtent( dataextent ); reader.SetDataExtent( 0, dims[0] - 1, 0, dims[1] - 1, 0, dims[2] - 1 ) reader.SetDataScalarType ( datascalartype ) reader.SetNumberOfScalarComponents( numberOfScalarComponents ) if __name__ == "__main__": try: filename = os.sys.argv[1] except: # failure print "Need a filename" sys.exit(1) # setup reader r = vtkgdcm.vtkGDCMThreadedImageReader() r.FileLowerLeftOn() #dir = vtkDirectory() dir = gdcm.Directory() # Did user pass in a directory: system = gdcm.System() if system.FileIsDirectory( filename ): nfiles = dir.Load( filename ) files = dir.GetFilenames() # Need to construct full path out of the simple filename fullpath = vtkStringArray() for file in files: fullpath.InsertNextValue( file ) r.SetFileNames( fullpath ) assert fullpath.GetNumberOfValues() # Need at least one file ExecuteInformation(r, fullpath.GetValue(0), fullpath.GetNumberOfValues() ) r.AddObserver("ProgressEvent", PrintProgress) r.Update() #print r.GetOutput() #print vtkMultiThreader.GetGlobalDefaultNumberOfThreads() #g = vtkImageGradient() #g.SetInput( r.GetOutput() ) #g.AddObserver("ProgressEvent", PrintProgress) #g.Update() # Write output writer = vtkStructuredPointsWriter() writer.SetInput( r.GetOutput() ) writer.SetFileName( "TestvtkGDCMThreadedImageReaderPython.vtk" ) writer.SetFileTypeToBinary() #writer.Write() else: # TODO r.SetFileName( filename ) ExecuteInformation(r, filename ) r.Update() print r.GetOutput() #sys.exit(1) # Test succeed ? #sys.exit(success != 1) GDCM-3.0.10/Utilities/VTK/Testing/Python/TestvtkGDCMThreadedImageReader2.py000066400000000000000000000065431412732066400261210ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ # This used to be important to load the vtkgdcm module first # (VTK 5.2 contains the proper patch now) import vtkgdcm from vtkgdcm import vtkStringArray from vtk.util import vtkConstants as vtkType import gdcm # for gdcm.Directory import os,sys def PrintProgress(object, event): assert event == "ProgressEvent" print("Progress:", object.GetProgress()) if __name__ == "__main__": root = gdcm.Testing.GetDataExtraRoot() dirname = os.path.join(root, "gdcmSampleData/ForSeriesTesting/Perfusion/images" ) print(dirname) # setup reader r = vtkgdcm.vtkGDCMThreadedImageReader2() dir = gdcm.Directory() # Did user pass in a directory: system = gdcm.System() if system.FileIsDirectory( dirname ): nfiles = dir.Load( dirname ) files = dir.GetFilenames() # Need to construct full path out of the simple filename fullpath = vtkStringArray() for file in files: fullpath.InsertNextValue( file ) r.SetFileNames( fullpath ) assert fullpath.GetNumberOfValues() # Need at least one file # Now specify the property of the image: """ Note (MM), I verified that even if there are multiple Series in this Study they are all compatible and thus can be loaded as a fake 3D (VTK) volume, only origin is changing & shift/scale . See: $ for i in `ls ForSeriesTesting/Perfusion/images/1.*`; do gdcminfo $i; done | sort | uniq """ """ gdcminfo ForSeriesTesting/Perfusion/images/1.3.46.670589.5.2.14.2198403904.1100092395.157798.dcm MediaStorage is 1.2.840.10008.5.1.4.1.1.4 [MR Image Storage] NumberOfDimensions: 2 Dimensions: (256,256) Origin: (-115,-125.969,-17.068) Spacing: (0.898438,0.898438,5.5) DirectionCosines: (1,0,0,0,0.949631,-0.31337) Rescale Intercept/Slope: (-1985.36,1) SamplesPerPixel :1 BitsAllocated :16 BitsStored :12 HighBit :11 PixelRepresentation:0 Orientation Label: AXIAL """ dims = [0,0,0] dims[0] = 256 dims[1] = 256 dims[2] = nfiles # Even if Stored Pixel is UINT16, the World Value Pixel is Float datascalartype = vtkType.VTK_FLOAT spacing = [0.898438,0.898438,5.5] origin = [-115,-125.969,-17.068] intercept_slope = [-1985.36,1] numberOfScalarComponents = 1 r.SetDataExtent( 0, dims[0] - 1, 0, dims[1] - 1, 0, dims[2] - 1 ) r.SetDataScalarType ( datascalartype ) r.SetNumberOfScalarComponents( numberOfScalarComponents ) r.SetDataOrigin( origin ) r.SetDataSpacing( spacing ) # Useless only for backward compatibily, the real shift/scale will be read from files: #r.SetShift( intercept_slope[0] ) #r.SetScale( intercept_slope[1] ) # Setup the ProgressEvent r.AddObserver("ProgressEvent", PrintProgress) r.Update() print(r.GetOutput()) # Test succeed ? #sys.exit(success != 1) GDCM-3.0.10/Utilities/VTK/VTK4/000077500000000000000000000000001412732066400154615ustar00rootroot00000000000000GDCM-3.0.10/Utilities/VTK/VTK4/vtkMedicalImageProperties.cxx000066400000000000000000000702451412732066400233200ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /*========================================================================= Portions of this file are subject to the VTK Toolkit Version 3 copyright. Program: Visualization Toolkit Module: vtkMedicalImageProperties.cxx,v Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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 "vtkMedicalImageProperties.h" #include "vtkObjectFactory.h" #include #include #include #include #include // for strftime #include // for isdigit #include //---------------------------------------------------------------------------- //vtkCxxRevisionMacro(vtkMedicalImageProperties, "1.21") vtkStandardNewMacro(vtkMedicalImageProperties) static const char *vtkMedicalImagePropertiesOrientationString[] = { "AXIAL", "CORONAL", "SAGITTAL", NULL }; //---------------------------------------------------------------------------- class vtkMedicalImagePropertiesInternals { public: class WindowLevelPreset { public: double Window; double Level; std::string Comment; }; class UserDefinedValue { public: UserDefinedValue(const char *name = 0, const char *value = 0):Name(name ? name : ""),Value(value ? value : "") {} std::string Name; std::string Value; // order for the std::set bool operator<(const UserDefinedValue &udv) const { return Name < udv.Name; } }; typedef std::set< UserDefinedValue > UserDefinedValues; UserDefinedValues Mapping; void AddUserDefinedValue(const char *name, const char *value) { if( name && *name && value && *value ) { Mapping.insert( UserDefinedValues::value_type(name, value) ); } // else raise a warning ? } const char *GetUserDefinedValue(const char *name) const { if( name && *name ) { UserDefinedValue key(name); UserDefinedValues::const_iterator it = Mapping.find( key ); assert( strcmp(it->Name.c_str(), name) == 0 ); return it->Value.c_str(); } return NULL; } unsigned int GetNumberOfUserDefinedValues() const { return Mapping.size(); } const char *GetUserDefinedNameByIndex(unsigned int idx) { if( idx < Mapping.size() ) { UserDefinedValues::const_iterator it = Mapping.begin(); while( idx ) { it++; idx--; } return it->Name.c_str(); } return NULL; } const char *GetUserDefinedValueByIndex(unsigned int idx) { if( idx < Mapping.size() ) { UserDefinedValues::const_iterator it = Mapping.begin(); while( idx ) { it++; idx--; } return it->Value.c_str(); } return NULL; } typedef std::vector WindowLevelPresetPoolType; typedef std::vector::iterator WindowLevelPresetPoolIterator; WindowLevelPresetPoolType WindowLevelPresetPool; // It is also useful to have a mapping from DICOM UID to slice id, for application like VolView typedef std::map< unsigned int, std::string> SliceUIDType; typedef std::vector< SliceUIDType > VolumeSliceUIDType; VolumeSliceUIDType UID; void SetNumberOfVolumes(unsigned int n) { UID.resize(n); Orientation.resize(n); } void SetUID(unsigned int vol, unsigned int slice, const char *uid) { SetNumberOfVolumes( vol + 1 ); UID[vol][slice] = uid; } const char *GetUID(unsigned int vol, unsigned int slice) { assert( vol < UID.size() ); assert( UID[vol].find(slice) != UID[vol].end() ); //if( UID[vol].find(slice) == UID[vol].end() ) // { // this->Print( cerr, vtkIndent() ); // } return UID[vol].find(slice)->second.c_str(); } // Extensive lookup int FindSlice(int &vol, const char *uid) { vol = -1; for(unsigned int v = 0; v < UID.size(); ++v ) { SliceUIDType::const_iterator cit = UID[v].begin(); while (cit != UID[v].end()) { if (cit->second == uid) { vol = v; return (int)(cit->first); } ++cit; } } return -1; // volume not found. } int GetSlice(unsigned int vol, const char *uid) { assert( vol < UID.size() ); SliceUIDType::const_iterator cit = UID[vol].begin(); while (cit != UID[vol].end()) { if (cit->second == uid) return (int)(cit->first); ++cit; } return -1; // uid not found. } void Print(ostream &os, vtkIndent indent) { os << indent << "WindowLevel: \n"; for( WindowLevelPresetPoolIterator it = WindowLevelPresetPool.begin(); it != WindowLevelPresetPool.end(); ++it ) { const WindowLevelPreset &wlp = *it; os << indent << "Window:" << wlp.Window << endl; os << indent << "Level:" << wlp.Level << endl; os << indent << "Comment:" << wlp.Comment << endl; } os << indent << "UID(s): "; for( VolumeSliceUIDType::const_iterator it = UID.begin(); it != UID.end(); ++it) { for( SliceUIDType::const_iterator it2 = it->begin(); it2 != it->end(); ++it2) { os << indent << it2->first << " " << it2->second << "\n"; } } os << indent << "Orientation(s): "; for( std::vector::const_iterator it = Orientation.begin(); it != Orientation.end(); ++it) { os << indent << vtkMedicalImageProperties::GetStringFromOrientationType(*it) << endl; } } std::vector Orientation; void SetOrientation(unsigned int vol, unsigned int ori) { // see SetNumberOfVolumes for allocation assert( ori <= vtkMedicalImageProperties::SAGITTAL ); Orientation[vol] = ori; } unsigned int GetOrientation(unsigned int vol) { assert( vol < Orientation.size() ); const unsigned int &val = Orientation[vol]; assert( val <= vtkMedicalImageProperties::SAGITTAL ); return val; } void DeepCopy(vtkMedicalImagePropertiesInternals *p) { WindowLevelPresetPool = p->WindowLevelPresetPool; UID = p->UID; Orientation = p->Orientation; } }; //---------------------------------------------------------------------------- vtkMedicalImageProperties::vtkMedicalImageProperties() { this->Internals = new vtkMedicalImagePropertiesInternals; this->StudyDate = NULL; this->AcquisitionDate = NULL; this->StudyTime = NULL; this->AcquisitionTime = NULL; this->ConvolutionKernel = NULL; this->EchoTime = NULL; this->EchoTrainLength = NULL; this->Exposure = NULL; this->ExposureTime = NULL; this->GantryTilt = NULL; this->ImageDate = NULL; this->ImageNumber = NULL; this->ImageTime = NULL; this->InstitutionName = NULL; this->KVP = NULL; this->ManufacturerModelName = NULL; this->Manufacturer = NULL; this->Modality = NULL; this->PatientAge = NULL; this->PatientBirthDate = NULL; this->PatientID = NULL; this->PatientName = NULL; this->PatientSex = NULL; this->RepetitionTime = NULL; this->SeriesDescription = NULL; this->SeriesNumber = NULL; this->SliceThickness = NULL; this->StationName = NULL; this->StudyDescription = NULL; this->StudyID = NULL; this->XRayTubeCurrent = NULL; } //---------------------------------------------------------------------------- vtkMedicalImageProperties::~vtkMedicalImageProperties() { if (this->Internals) { delete this->Internals; this->Internals = NULL; } this->Clear(); } //---------------------------------------------------------------------------- void vtkMedicalImageProperties::AddUserDefinedValue(const char *name, const char *value) { this->Internals->AddUserDefinedValue(name, value); } //---------------------------------------------------------------------------- const char *vtkMedicalImageProperties::GetUserDefinedValue(const char *name) { return this->Internals->GetUserDefinedValue(name); } //---------------------------------------------------------------------------- unsigned int vtkMedicalImageProperties::GetNumberOfUserDefinedValues() { return this->Internals->GetNumberOfUserDefinedValues(); } //---------------------------------------------------------------------------- const char *vtkMedicalImageProperties::GetUserDefinedValueByIndex(unsigned int idx) { return this->Internals->GetUserDefinedValueByIndex(idx); } //---------------------------------------------------------------------------- const char *vtkMedicalImageProperties::GetUserDefinedNameByIndex(unsigned int idx) { return this->Internals->GetUserDefinedNameByIndex(idx); } //---------------------------------------------------------------------------- void vtkMedicalImageProperties::Clear() { this->SetStudyDate(NULL); this->SetAcquisitionDate(NULL); this->SetStudyTime(NULL); this->SetAcquisitionTime(NULL); this->SetConvolutionKernel(NULL); this->SetEchoTime(NULL); this->SetEchoTrainLength(NULL); this->SetExposure(NULL); this->SetExposureTime(NULL); this->SetGantryTilt(NULL); this->SetImageDate(NULL); this->SetImageNumber(NULL); this->SetImageTime(NULL); this->SetInstitutionName(NULL); this->SetKVP(NULL); this->SetManufacturerModelName(NULL); this->SetManufacturer(NULL); this->SetModality(NULL); this->SetPatientAge(NULL); this->SetPatientBirthDate(NULL); this->SetPatientID(NULL); this->SetPatientName(NULL); this->SetPatientSex(NULL); this->SetRepetitionTime(NULL); this->SetSeriesDescription(NULL); this->SetSeriesNumber(NULL); this->SetSliceThickness(NULL); this->SetStationName(NULL); this->SetStudyDescription(NULL); this->SetStudyID(NULL); this->SetXRayTubeCurrent(NULL); this->RemoveAllWindowLevelPresets(); } //---------------------------------------------------------------------------- void vtkMedicalImageProperties::DeepCopy(vtkMedicalImageProperties *p) { if (p == NULL) { return; } this->Clear(); this->SetStudyDate(p->GetStudyDate()); this->SetAcquisitionDate(p->GetAcquisitionDate()); this->SetStudyTime(p->GetStudyTime()); this->SetAcquisitionTime(p->GetAcquisitionTime()); this->SetConvolutionKernel(p->GetConvolutionKernel()); this->SetEchoTime(p->GetEchoTime()); this->SetEchoTrainLength(p->GetEchoTrainLength()); this->SetExposure(p->GetExposure()); this->SetExposureTime(p->GetExposureTime()); this->SetGantryTilt(p->GetGantryTilt()); this->SetImageDate(p->GetImageDate()); this->SetImageNumber(p->GetImageNumber()); this->SetImageTime(p->GetImageTime()); this->SetInstitutionName(p->GetInstitutionName()); this->SetKVP(p->GetKVP()); this->SetManufacturerModelName(p->GetManufacturerModelName()); this->SetManufacturer(p->GetManufacturer()); this->SetModality(p->GetModality()); this->SetPatientAge(p->GetPatientAge()); this->SetPatientBirthDate(p->GetPatientBirthDate()); this->SetPatientID(p->GetPatientID()); this->SetPatientName(p->GetPatientName()); this->SetPatientSex(p->GetPatientSex()); this->SetRepetitionTime(p->GetRepetitionTime()); this->SetSeriesDescription(p->GetSeriesDescription()); this->SetSeriesNumber(p->GetSeriesNumber()); this->SetSliceThickness(p->GetSliceThickness()); this->SetStationName(p->GetStationName()); this->SetStudyDescription(p->GetStudyDescription()); this->SetStudyID(p->GetStudyID()); this->SetXRayTubeCurrent(p->GetXRayTubeCurrent()); this->Internals->DeepCopy( p->Internals ); } //---------------------------------------------------------------------------- void vtkMedicalImageProperties::AddWindowLevelPreset( double w, double l) { if (!this->Internals || this->HasWindowLevelPreset(w, l)) { return; } vtkMedicalImagePropertiesInternals::WindowLevelPreset preset; preset.Window = w; preset.Level = l; this->Internals->WindowLevelPresetPool.push_back(preset); } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::HasWindowLevelPreset(double w, double l) { if (this->Internals) { vtkMedicalImagePropertiesInternals::WindowLevelPresetPoolIterator it = this->Internals->WindowLevelPresetPool.begin(); vtkMedicalImagePropertiesInternals::WindowLevelPresetPoolIterator end = this->Internals->WindowLevelPresetPool.end(); for (; it != end; ++it) { if ((*it).Window == w && (*it).Level == l) { return 1; } } } return 0; } //---------------------------------------------------------------------------- void vtkMedicalImageProperties::RemoveWindowLevelPreset(double w, double l) { if (this->Internals) { vtkMedicalImagePropertiesInternals::WindowLevelPresetPoolIterator it = this->Internals->WindowLevelPresetPool.begin(); vtkMedicalImagePropertiesInternals::WindowLevelPresetPoolIterator end = this->Internals->WindowLevelPresetPool.end(); for (; it != end; ++it) { if ((*it).Window == w && (*it).Level == l) { this->Internals->WindowLevelPresetPool.erase(it); break; } } } } //---------------------------------------------------------------------------- void vtkMedicalImageProperties::RemoveAllWindowLevelPresets() { if (this->Internals) { this->Internals->WindowLevelPresetPool.clear(); } } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetNumberOfWindowLevelPresets() { return this->Internals ? this->Internals->WindowLevelPresetPool.size() : 0; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetNthWindowLevelPreset( int idx, double *w, double *l) { if (this->Internals && idx >= 0 && idx < this->GetNumberOfWindowLevelPresets()) { *w = this->Internals->WindowLevelPresetPool[idx].Window; *l = this->Internals->WindowLevelPresetPool[idx].Level; return 1; } return 0; } //---------------------------------------------------------------------------- double* vtkMedicalImageProperties::GetNthWindowLevelPreset(int idx) { static double wl[2]; if (this->GetNthWindowLevelPreset(idx, wl, wl + 1)) { return wl; } return NULL; } //---------------------------------------------------------------------------- const char* vtkMedicalImageProperties::GetNthWindowLevelPresetComment( int idx) { if (this->Internals && idx >= 0 && idx < this->GetNumberOfWindowLevelPresets()) { return this->Internals->WindowLevelPresetPool[idx].Comment.c_str(); } return NULL; } //---------------------------------------------------------------------------- void vtkMedicalImageProperties::SetNthWindowLevelPresetComment( int idx, const char *comment) { if (this->Internals && idx >= 0 && idx < this->GetNumberOfWindowLevelPresets()) { this->Internals->WindowLevelPresetPool[idx].Comment = (comment ? comment : ""); } } //---------------------------------------------------------------------------- const char *vtkMedicalImageProperties::GetInstanceUIDFromSliceID( int volumeidx, int sliceid) { return this->Internals->GetUID(volumeidx, sliceid); } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetSliceIDFromInstanceUID( int &volumeidx, const char *uid) { if( volumeidx == -1 ) { return this->Internals->FindSlice(volumeidx, uid); } else { return this->Internals->GetSlice(volumeidx, uid); } } //---------------------------------------------------------------------------- void vtkMedicalImageProperties::SetInstanceUIDFromSliceID( int volumeidx, int sliceid, const char *uid) { this->Internals->SetUID(volumeidx,sliceid, uid); } //---------------------------------------------------------------------------- void vtkMedicalImageProperties::SetOrientationType(int volumeidx, int orientation) { this->Internals->SetOrientation(volumeidx, orientation); } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetOrientationType(int volumeidx) { return this->Internals->GetOrientation(volumeidx); } //---------------------------------------------------------------------------- const char *vtkMedicalImageProperties::GetStringFromOrientationType(unsigned int type) { static unsigned int numtypes = 0; // find length of table if (!numtypes) { while (vtkMedicalImagePropertiesOrientationString[numtypes] != NULL) { numtypes++; } } if (type < numtypes) { return vtkMedicalImagePropertiesOrientationString[type]; } return NULL; } //---------------------------------------------------------------------------- double vtkMedicalImageProperties::GetSliceThicknessAsDouble() { if (this->SliceThickness) { return atof(this->SliceThickness); } return 0; } //---------------------------------------------------------------------------- double vtkMedicalImageProperties::GetGantryTiltAsDouble() { if (this->GantryTilt) { return atof(this->GantryTilt); } return 0; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetAgeAsFields(const char *age, int &year, int &month, int &week, int &day) { year = month = week = day = -1; if( !age ) { return 0; } size_t len = strlen(age); if( len == 4 ) { // DICOM V3 unsigned int val; char type; if( !isdigit(age[0]) || !isdigit(age[1]) || !isdigit(age[2])) { return 0; } if( sscanf(age, "%3u%c", &val, &type) != 2 ) { return 0; } switch(type) { case 'Y': year = (int)val; break; case 'M': month = (int)val; break; case 'W': week = (int)val; break; case 'D': day = (int)val; break; default: return 0; } } else { return 0; } return 1; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetPatientAgeYear() { const char *age = this->GetPatientAge(); int year, month, week, day; vtkMedicalImageProperties::GetAgeAsFields(age, year, month, week, day); return year; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetPatientAgeMonth() { const char *age = this->GetPatientAge(); int year, month, week, day; vtkMedicalImageProperties::GetAgeAsFields(age, year, month, week, day); return month; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetPatientAgeWeek() { const char *age = this->GetPatientAge(); int year, month, week, day; vtkMedicalImageProperties::GetAgeAsFields(age, year, month, week, day); return week; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetPatientAgeDay() { const char *age = this->GetPatientAge(); int year, month, week, day; vtkMedicalImageProperties::GetAgeAsFields(age, year, month, week, day); return day; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetDateAsFields(const char *date, int &year, int &month, int &day) { if( !date ) { return 0; } size_t len = strlen(date); if( len == 8 ) { // DICOM V3 if( sscanf(date, "%04d%02d%02d", &year, &month, &day) != 3 ) { return 0; } } else if( len == 10 ) { // Some *very* old ACR-NEMA if( sscanf(date, "%04d.%02d.%02d", &year, &month, &day) != 3 ) { return 0; } } else { return 0; } return 1; } //---------------------------------------------------------------------------- // Some buggy versions of gcc complain about the use of %c: warning: `%c' // yields only last 2 digits of year in some locales. Of course program- // mers are encouraged to use %c, it gives the preferred date and time // representation. One meets all kinds of strange obfuscations to circum- // vent this gcc problem. A relatively clean one is to add an intermediate // function. This is described as bug #3190 in gcc bugzilla: // [-Wformat-y2k doesn't belong to -Wall - it's hard to avoid] inline size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm) { return strftime(s, max, fmt, tm); } // Helper function to convert a DICOM iso date format into a locale one // locale buffer should be typically char locale[200] int vtkMedicalImageProperties::GetDateAsLocale(const char *iso, char *locale) { int year, month, day; if( vtkMedicalImageProperties::GetDateAsFields(iso, year, month, day) ) { struct tm date; memset(&date,0, sizeof(date)); date.tm_mday = day; // month are expressed in the [0-11] range: date.tm_mon = month - 1; // structure is date starting at 1900 date.tm_year = year - 1900; my_strftime(locale, 200, "%x", &date); return 1; } return 0; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetPatientBirthDateYear() { const char *date = this->GetPatientBirthDate(); int year, month, day; vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); return year; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetPatientBirthDateMonth() { const char *date = this->GetPatientBirthDate(); int year, month, day; vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); return month; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetPatientBirthDateDay() { const char *date = this->GetPatientBirthDate(); int year, month, day; vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); return day; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetAcquisitionDateYear() { const char *date = this->GetAcquisitionDate(); int year, month, day; vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); return year; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetAcquisitionDateMonth() { const char *date = this->GetAcquisitionDate(); int year, month, day; vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); return month; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetAcquisitionDateDay() { const char *date = this->GetAcquisitionDate(); int year, month, day; vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); return day; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetImageDateYear() { const char *date = this->GetImageDate(); int year, month, day; vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); return year; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetImageDateMonth() { const char *date = this->GetImageDate(); int year, month, day; vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); return month; } //---------------------------------------------------------------------------- int vtkMedicalImageProperties::GetImageDateDay() { const char *date = this->GetImageDate(); int year, month, day; vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); return day; } //---------------------------------------------------------------------------- void vtkMedicalImageProperties::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << "\n" << indent << "PatientName: "; if (this->PatientName) { os << this->PatientName; } os << "\n" << indent << "PatientID: "; if (this->PatientID) { os << this->PatientID; } os << "\n" << indent << "PatientAge: "; if (this->PatientAge) { os << this->PatientAge; } os << "\n" << indent << "PatientSex: "; if (this->PatientSex) { os << this->PatientSex; } os << "\n" << indent << "PatientBirthDate: "; if (this->PatientBirthDate) { os << this->PatientBirthDate; } os << "\n" << indent << "ImageDate: "; if (this->ImageDate) { os << this->ImageDate; } os << "\n" << indent << "ImageTime: "; if (this->ImageTime) { os << this->ImageTime; } os << "\n" << indent << "ImageNumber: "; if (this->ImageNumber) { os << this->ImageNumber; } os << "\n" << indent << "StudyDate: "; if (this->StudyDate) { os << this->StudyDate; } os << "\n" << indent << "AcquisitionDate: "; if (this->AcquisitionDate) { os << this->AcquisitionDate; } os << "\n" << indent << "StudyTime: "; if (this->StudyTime) { os << this->StudyTime; } os << "\n" << indent << "AcquisitionTime: "; if (this->AcquisitionTime) { os << this->AcquisitionTime; } os << "\n" << indent << "SeriesNumber: "; if (this->SeriesNumber) { os << this->SeriesNumber; } os << "\n" << indent << "SeriesDescription: "; if (this->SeriesDescription) { os << this->SeriesDescription; } os << "\n" << indent << "StudyDescription: "; if (this->StudyDescription) { os << this->StudyDescription; } os << "\n" << indent << "StudyID: "; if (this->StudyID) { os << this->StudyID; } os << "\n" << indent << "Modality: "; if (this->Modality) { os << this->Modality; } os << "\n" << indent << "ManufacturerModelName: "; if (this->ManufacturerModelName) { os << this->ManufacturerModelName; } os << "\n" << indent << "Manufacturer: "; if (this->Manufacturer) { os << this->Manufacturer; } os << "\n" << indent << "StationName: "; if (this->StationName) { os << this->StationName; } os << "\n" << indent << "InstitutionName: "; if (this->InstitutionName) { os << this->InstitutionName; } os << "\n" << indent << "ConvolutionKernel: "; if (this->ConvolutionKernel) { os << this->ConvolutionKernel; } os << "\n" << indent << "SliceThickness: "; if (this->SliceThickness) { os << this->SliceThickness; } os << "\n" << indent << "KVP: "; if (this->KVP) { os << this->KVP; } os << "\n" << indent << "GantryTilt: "; if (this->GantryTilt) { os << this->GantryTilt; } os << "\n" << indent << "EchoTime: "; if (this->EchoTime) { os << this->EchoTime; } os << "\n" << indent << "EchoTrainLength: "; if (this->EchoTrainLength) { os << this->EchoTrainLength; } os << "\n" << indent << "RepetitionTime: "; if (this->RepetitionTime) { os << this->RepetitionTime; } os << "\n" << indent << "ExposureTime: "; if (this->ExposureTime) { os << this->ExposureTime; } os << "\n" << indent << "XRayTubeCurrent: "; if (this->XRayTubeCurrent) { os << this->XRayTubeCurrent; } os << "\n" << indent << "Exposure: "; if (this->Exposure) { os << this->Exposure; } this->Internals->Print(os << "\n", indent.GetNextIndent() ); } GDCM-3.0.10/Utilities/VTK/VTK4/vtkMedicalImageProperties.h000066400000000000000000000324131412732066400227400ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /*========================================================================= Portions of this file are subject to the VTK Toolkit Version 3 copyright. Program: Visualization Toolkit Module: $RCSfile: vtkMedicalImageProperties.h,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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. =========================================================================*/ // .NAME vtkMedicalImageProperties - some medical image properties. // .SECTION Description // vtkMedicalImageProperties is a helper class that can be used by medical // image readers and applications to encapsulate medical image/acquisition // properties. Later on, this should probably be extended to add // any user-defined property. // .SECTION See Also // vtkMedicalImageReader2 #ifndef VTKMEDICALIMAGEPROPERTIES_H #define VTKMEDICALIMAGEPROPERTIES_H #ifdef __vtkMedicalImageProperties_h #error Something went terribly wrong #endif #include "vtkObject.h" class vtkMedicalImagePropertiesInternals; class VTK_IO_EXPORT vtkMedicalImageProperties : public vtkObject { public: static vtkMedicalImageProperties *New(); vtkTypeMacro(vtkMedicalImageProperties,vtkObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Convenience method to reset all fields to an empty string/value virtual void Clear(); // Description: // Patient name // For ex: DICOM (0010,0010) = DOE,JOHN vtkSetStringMacro(PatientName); vtkGetStringMacro(PatientName); // Description: // Patient ID // For ex: DICOM (0010,0020) = 1933197 vtkSetStringMacro(PatientID); vtkGetStringMacro(PatientID); // Description: // Patient age // Format: nnnD, nnW, nnnM or nnnY (eventually nnD, nnW, nnY) // with D (day), M (month), W (week), Y (year) // For ex: DICOM (0010,1010) = 031Y vtkSetStringMacro(PatientAge); vtkGetStringMacro(PatientAge); // Description: // Take as input a string in VR=AS (DICOM PS3.5) and extract either // different fields namely: year month week day // Return 0 on error, 1 on success // One can test fields if they are different from -1 upon success static int GetAgeAsFields(const char *age, int &year, int &month, int &week, int &day); // For Tcl: // From C++ use GetPatientAge + GetAgeAsField // Those function parse a DICOM string, and return the value of the number expressed // this is either expressed in year, month or days. Thus if a string is expressed in years // GetPatientAgeDay/GetPatientAgeWeek/GetPatientAgeMonth will return 0 int GetPatientAgeYear(); int GetPatientAgeMonth(); int GetPatientAgeWeek(); int GetPatientAgeDay(); // Description: // Patient sex // For ex: DICOM (0010,0040) = M vtkSetStringMacro(PatientSex); vtkGetStringMacro(PatientSex); // Description: // Patient birth date // Format: yyyymmdd // For ex: DICOM (0010,0030) = 19680427 vtkSetStringMacro(PatientBirthDate); vtkGetStringMacro(PatientBirthDate); // For Tcl: // From C++ use GetPatientBirthDate + GetDateAsFields int GetPatientBirthDateYear(); int GetPatientBirthDateMonth(); int GetPatientBirthDateDay(); // Description: // Study Date // Format: yyyymmdd // For ex: DICOM (0008,0020) = 20030617 vtkSetStringMacro(StudyDate); vtkGetStringMacro(StudyDate); // Description: // Acquisition Date // Format: yyyymmdd // For ex: DICOM (0008,0022) = 20030617 vtkSetStringMacro(AcquisitionDate); vtkGetStringMacro(AcquisitionDate); // For Tcl: // From C++ use GetAcquisitionDate + GetDateAsFields int GetAcquisitionDateYear(); int GetAcquisitionDateMonth(); int GetAcquisitionDateDay(); // Description: // Study Time // Format: hhmmss.frac (any trailing component(s) can be ommited) // For ex: DICOM (0008,0030) = 162552.0705 or 230012, or 0012 vtkSetStringMacro(StudyTime); vtkGetStringMacro(StudyTime); // Description: // Acquisition time // Format: hhmmss.frac (any trailing component(s) can be ommited) // For ex: DICOM (0008,0032) = 162552.0705 or 230012, or 0012 vtkSetStringMacro(AcquisitionTime); vtkGetStringMacro(AcquisitionTime); // Description: // Image Date aka Content Date // Format: yyyymmdd // For ex: DICOM (0008,0023) = 20030617 vtkSetStringMacro(ImageDate); vtkGetStringMacro(ImageDate); // For Tcl: // From C++ use GetImageDate + GetDateAsFields int GetImageDateYear(); int GetImageDateMonth(); int GetImageDateDay(); // Description: // Take as input a string in ISO 8601 date (YYYY/MM/DD) and extract the // different fields namely: year month day // Return 0 on error, 1 on success static int GetDateAsFields(const char *date, int &year, int &month, int &day); // Description: // Take as input a string in ISO 8601 date (YYYY/MM/DD) and construct a // locale date based on the different fields (see GetDateAsFields to extract // different fields) // Return 0 on error, 1 on success static int GetDateAsLocale(const char *date, char *locale); // Description: // Image Time // Format: hhmmss.frac (any trailing component(s) can be ommited) // For ex: DICOM (0008,0033) = 162552.0705 or 230012, or 0012 vtkSetStringMacro(ImageTime); vtkGetStringMacro(ImageTime); // Description: // Image number // For ex: DICOM (0020,0013) = 1 vtkSetStringMacro(ImageNumber); vtkGetStringMacro(ImageNumber); // Description: // Series number // For ex: DICOM (0020,0011) = 902 vtkSetStringMacro(SeriesNumber); vtkGetStringMacro(SeriesNumber); // Description: // Series Description // User provided description of the Series // For ex: DICOM (0008,103e) = SCOUT vtkSetStringMacro(SeriesDescription); vtkGetStringMacro(SeriesDescription); // Description: // Study ID // For ex: DICOM (0020,0010) = 37481 vtkSetStringMacro(StudyID); vtkGetStringMacro(StudyID); // Description: // Study description // For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL vtkSetStringMacro(StudyDescription); vtkGetStringMacro(StudyDescription); // Description: // Modality // For ex: DICOM (0008,0060)= CT vtkSetStringMacro(Modality); vtkGetStringMacro(Modality); // Description: // Manufacturer // For ex: DICOM (0008,0070) = Siemens vtkSetStringMacro(Manufacturer); vtkGetStringMacro(Manufacturer); // Description: // Manufacturer's Model Name // For ex: DICOM (0008,1090) = LightSpeed QX/i vtkSetStringMacro(ManufacturerModelName); vtkGetStringMacro(ManufacturerModelName); // Description: // Station Name // For ex: DICOM (0008,1010) = LSPD_OC8 vtkSetStringMacro(StationName); vtkGetStringMacro(StationName); // Description: // Institution Name // For ex: DICOM (0008,0080) = FooCity Medical Center vtkSetStringMacro(InstitutionName); vtkGetStringMacro(InstitutionName); // Description: // Convolution Kernel (or algorithm used to reconstruct the data) // For ex: DICOM (0018,1210) = Bone vtkSetStringMacro(ConvolutionKernel); vtkGetStringMacro(ConvolutionKernel); // Description: // Slice Thickness (Nominal reconstructed slice thickness, in mm) // For ex: DICOM (0018,0050) = 0.273438 vtkSetStringMacro(SliceThickness); vtkGetStringMacro(SliceThickness); virtual double GetSliceThicknessAsDouble(); // Description: // Peak kilo voltage output of the (x-ray) generator used // For ex: DICOM (0018,0060) = 120 vtkSetStringMacro(KVP); vtkGetStringMacro(KVP); // Description: // Gantry/Detector tilt (Nominal angle of tilt in degrees of the scanning // gantry.) // For ex: DICOM (0018,1120) = 15 vtkSetStringMacro(GantryTilt); vtkGetStringMacro(GantryTilt); virtual double GetGantryTiltAsDouble(); // Description: // Echo Time // (Time in ms between the middle of the excitation pulse and the peak of // the echo produced) // For ex: DICOM (0018,0081) = 105 vtkSetStringMacro(EchoTime); vtkGetStringMacro(EchoTime); // Description: // Echo Train Length // (Number of lines in k-space acquired per excitation per image) // For ex: DICOM (0018,0091) = 35 vtkSetStringMacro(EchoTrainLength); vtkGetStringMacro(EchoTrainLength); // Description: // Repetition Time // The period of time in msec between the beginning of a pulse sequence and // the beginning of the succeeding (essentially identical) pulse sequence. // For ex: DICOM (0018,0080) = 2040 vtkSetStringMacro(RepetitionTime); vtkGetStringMacro(RepetitionTime); // Description: // Exposure time (time of x-ray exposure in msec) // For ex: DICOM (0018,1150) = 5 vtkSetStringMacro(ExposureTime); vtkGetStringMacro(ExposureTime); // Description: // X-ray tube current (in mA) // For ex: DICOM (0018,1151) = 400 vtkSetStringMacro(XRayTubeCurrent); vtkGetStringMacro(XRayTubeCurrent); // Description: // Exposure (The exposure expressed in mAs, for example calculated // from Exposure Time and X-ray Tube Current) // For ex: DICOM (0018,1152) = 114 vtkSetStringMacro(Exposure); vtkGetStringMacro(Exposure); // Interface to allow insertion of user define values, for instance in DICOM one would want to // store the Protocol Name (0018,1030), in this case one would do: // AddUserDefinedValue( "Protocol Name", "T1W/SE/1024" ); void AddUserDefinedValue(const char *name, const char *value); // Get a particular user value const char *GetUserDefinedValue(const char *name); // Get the number of user defined values unsigned int GetNumberOfUserDefinedValues(); // Get a name/value by index const char *GetUserDefinedNameByIndex(unsigned int idx); const char *GetUserDefinedValueByIndex(unsigned int idx); // Description: // Copy the contents of p to this instance. virtual void DeepCopy(vtkMedicalImageProperties *p); // Description: // Add/Remove/Query the window/level presets that may have been associated // to a medical image. Window is also known as 'width', level is also known // as 'center'. The same window/level pair can not be added twice. // As a convenience, a comment (aka Explanation) can be associated to a preset. // For ex: DICOM Window Center (0028,1050) = 00045\000470 // DICOM Window Width (0028,1051) = 0106\03412 // DICOM Window Center Width Explanation (0028,1055) = WINDOW1\WINDOW2 virtual void AddWindowLevelPreset(double w, double l); virtual void RemoveWindowLevelPreset(double w, double l); virtual void RemoveAllWindowLevelPresets(); virtual int GetNumberOfWindowLevelPresets(); virtual int HasWindowLevelPreset(double w, double l); virtual int GetNthWindowLevelPreset(int idx, double *w, double *l); virtual double* GetNthWindowLevelPreset(int idx); virtual void SetNthWindowLevelPresetComment(int idx, const char *comment); virtual const char* GetNthWindowLevelPresetComment(int idx); // Description: // Mapping from a sliceidx within a volumeidx into a DICOM Instance UID // Some DICOM reader can populate this structure so that later on from a slice index // in a vtkImageData volume we can backtrack and find out which 2d slice it was coming from const char *GetInstanceUIDFromSliceID(int volumeidx, int sliceid); void SetInstanceUIDFromSliceID(int volumeidx, int sliceid, const char *uid); // Description: // Provides the inverse mapping. Returns -1 if a slice for this uid is // not found. int GetSliceIDFromInstanceUID(int &volumeidx, const char *uid); //BTX typedef enum { AXIAL = 0, CORONAL, SAGITTAL } OrientationType; //ETX int GetOrientationType(int volumeidx); void SetOrientationType(int volumeidx, int orientation); static const char *GetStringFromOrientationType(unsigned int type); protected: vtkMedicalImageProperties(); ~vtkMedicalImageProperties(); char *StudyDate; char *AcquisitionDate; char *StudyTime; char *AcquisitionTime; char *ConvolutionKernel; char *EchoTime; char *EchoTrainLength; char *Exposure; char *ExposureTime; char *GantryTilt; char *ImageDate; char *ImageNumber; char *ImageTime; char *InstitutionName; char *KVP; char *ManufacturerModelName; char *Manufacturer; char *Modality; char *PatientAge; char *PatientBirthDate; char *PatientID; char *PatientName; char *PatientSex; char *RepetitionTime; char *SeriesDescription; char *SeriesNumber; char *SliceThickness; char *StationName; char *StudyDescription; char *StudyID; char *XRayTubeCurrent; // Description: // PIMPL Encapsulation for STL containers //BTX vtkMedicalImagePropertiesInternals *Internals; //ETX private: vtkMedicalImageProperties(const vtkMedicalImageProperties&); // Not implemented. void operator=(const vtkMedicalImageProperties&); // Not implemented. }; #endif GDCM-3.0.10/Utilities/VTK/VTK4/vtkStringArray.cxx000066400000000000000000000033231412732066400212000ustar00rootroot00000000000000/*========================================================================= 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 "vtkStringArray.h" #include "vtkObjectFactory.h" #include #include //vtkCxxRevisionMacro(vtkStringArray, "$Revision: 1.1 $") vtkStandardNewMacro(vtkStringArray) struct vtkStringArrayInternals { std::vector< std::string > Internal; }; vtkStringArray::vtkStringArray() { Internal = new vtkStringArrayInternals; } vtkStringArray::~vtkStringArray() { delete Internal; } //std::string &vtkStringArray::GetValue(unsigned int i) const char *vtkStringArray::GetValue(unsigned int i) { return Internal->Internal[i].c_str(); } int vtkStringArray::GetNumberOfValues() { return Internal->Internal.size(); } vtkIdType vtkStringArray::InsertNextValue(const char *f) { Internal->Internal.push_back( f ); return Internal->Internal.size(); } vtkIdType vtkStringArray::InsertNextValue(std::string const & f) { Internal->Internal.push_back( f ); return Internal->Internal.size(); } vtkIdType vtkStringArray::GetSize() { return Internal->Internal.size(); } //---------------------------------------------------------------------------- void vtkStringArray::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } GDCM-3.0.10/Utilities/VTK/VTK4/vtkStringArray.h000066400000000000000000000027611412732066400206320ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // .NAME vtkStringArray - // .SECTION Description // // .SECTION // // .SECTION See Also #ifndef VTKSTRINGARRAY_H #define VTKSTRINGARRAY_H #ifdef __vtkStringArray_h #error Something went terribly wrong #endif #include "vtkObject.h" #include class vtkStringArrayInternals; class VTK_EXPORT vtkStringArray : public vtkObject { public: static vtkStringArray *New(); vtkTypeMacro(vtkStringArray,vtkObject); virtual void PrintSelf(ostream& os, vtkIndent indent); //BTX //std::string &GetValue(unsigned int i); vtkIdType InsertNextValue(std::string const & f); //ETX const char *GetValue(unsigned int i); int GetNumberOfValues(); vtkIdType InsertNextValue(const char *f); vtkIdType GetSize(); protected: vtkStringArray(); ~vtkStringArray(); private: vtkStringArray(const vtkStringArray&); // Not implemented. void operator=(const vtkStringArray&); // Not implemented. vtkStringArrayInternals *Internal; }; #endif GDCM-3.0.10/Utilities/VTK/dllexportconf.cs000066400000000000000000000001131412732066400201360ustar00rootroot00000000000000public const string vtkgdcmEL_dll = "libKitware.VTK.vtkgdcm.Unmanaged.so"; GDCM-3.0.10/Utilities/VTK/gccxml.cxx.in000066400000000000000000000005201412732066400173340ustar00rootroot00000000000000#include "@header@" #ifdef CABLE_CONFIGURATION namespace _cable_ { const char* const package = "Kitware.VTK.GDCM"; const char* const package_version = "@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@.@VTK_BUILD_VERSION@"; const char* const group = "vtk@kit@"; namespace wrappers { typedef @cxxclass@ @cxxclass@_W; } } #endif GDCM-3.0.10/Utilities/VTK/manifest.txt000066400000000000000000000000241412732066400172740ustar00rootroot00000000000000Class-Path: vtk.jar GDCM-3.0.10/Utilities/VTK/vtkGDCMImageReader.cxx000066400000000000000000001565071412732066400210200ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader.h" #include "vtkObjectFactory.h" #include "vtkImageData.h" #include "vtkErrorCode.h" #include "vtkMath.h" #include "vtkPolyData.h" #include "vtkCellArray.h" #include "vtkPoints.h" #include "vtkMedicalImageProperties.h" #include "vtkGDCMMedicalImageProperties.h" #include "vtkStringArray.h" #include "vtkPointData.h" #include "vtkLookupTable.h" #include "vtkWindowLevelLookupTable.h" #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) #include "vtkLookupTable16.h" #include "vtkInformationVector.h" #include "vtkInformation.h" #include "vtkDemandDrivenPipeline.h" #include "vtkStreamingDemandDrivenPipeline.h" #endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/ #include "vtkMatrix4x4.h" #include "vtkUnsignedCharArray.h" //#include "vtkUnsignedShortArray.h" #include "vtkBitArray.h" #include "gdcmImageReader.h" #include "gdcmDataElement.h" #include "gdcmByteValue.h" #include "gdcmSwapper.h" #include "gdcmUnpacker12Bits.h" #include "gdcmRescaler.h" #include "gdcmOrientation.h" #include "gdcmTrace.h" #include "gdcmImageChangePlanarConfiguration.h" #include "gdcmDirectoryHelper.h" #include //vtkCxxRevisionMacro(vtkGDCMImageReader, "$Revision: 1.1 $") vtkStandardNewMacro(vtkGDCMImageReader) static inline bool vtkGDCMImageReader_IsCharTypeSigned() { #ifndef VTK_TYPE_CHAR_IS_SIGNED unsigned char uc = 255; return (*reinterpret_cast(&uc) < 0) ? true : false; #else return VTK_TYPE_CHAR_IS_SIGNED; #endif } // Output Ports are as follow: // #0: The image/volume (root PixelData element) // #1: (if present): the Icon Image (0088,0200) // #2-xx: (if present): the Overlay (60xx,3000) #define ICONIMAGEPORTNUMBER 1 #define OVERLAYPORTNUMBER 2 vtkCxxSetObjectMacro(vtkGDCMImageReader,Curve,vtkPolyData) vtkCxxSetObjectMacro(vtkGDCMImageReader,MedicalImageProperties,vtkMedicalImageProperties) //---------------------------------------------------------------------------- vtkGDCMImageReader::vtkGDCMImageReader() { // vtkDataArray has an internal vtkLookupTable why not used it ? // vtkMedicalImageProperties is in the parent class //this->FileLowerLeft = 1; this->DirectionCosines = vtkMatrix4x4::New(); this->DirectionCosines->Identity(); //this->DirectionCosines->SetElement(0,0,1); // x0 //this->DirectionCosines->SetElement(1,0,0); // x1 //this->DirectionCosines->SetElement(2,0,0); // x2 //this->DirectionCosines->SetElement(3,0,0); // //this->DirectionCosines->SetElement(0,1,0); // y0 //this->DirectionCosines->SetElement(1,1,1); // y1 //this->DirectionCosines->SetElement(2,1,0); // y2 //this->DirectionCosines->SetElement(3,1,0); // //this->DirectionCosines->SetElement(0,2,0); // y0 //this->DirectionCosines->SetElement(1,2,0); // y1 //this->DirectionCosines->SetElement(2,2,1); // y2 //this->DirectionCosines->SetElement(3,2,0); // #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) #else this->MedicalImageProperties = vtkMedicalImageProperties::New(); #endif #if (VTK_MAJOR_VERSION > 5) || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) //this->SetNumberOfInputPorts(0); #else this->FileNames = NULL; //vtkStringArray::New(); #endif this->LoadOverlays = 1; this->LoadIconImage = 1; this->NumberOfOverlays = 0; this->NumberOfIconImages = 0; memset(this->IconImageDataExtent,0,6*sizeof(int)); this->ImageFormat = 0; // INVALID this->ApplyInverseVideo = 0; this->ApplyLookupTable = 0; this->ApplyYBRToRGB = 0; this->ApplyPlanarConfiguration = 1; this->ApplyShiftScale = 1; memset(this->ImagePositionPatient,0,3*sizeof(double)); memset(this->ImageOrientationPatient,0,6*sizeof(double)); this->Curve = 0; this->Shift = 0.; this->Scale = 1.; this->IconDataScalarType = VTK_CHAR; this->IconNumberOfScalarComponents = 1; this->PlanarConfiguration = 0; this->LossyFlag = 0; // DirectionCosine was added after 5.2 #if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 2 ) this->MedicalImageProperties->SetDirectionCosine(1,0,0,0,1,0); #endif this->SetImageOrientationPatient(1,0,0,0,1,0); // this->SetMedicalImageProperties( vtkGDCMMedicalImageProperties::New() ); this->ForceRescale = 0; } //---------------------------------------------------------------------------- vtkGDCMImageReader::~vtkGDCMImageReader() { //delete this->Internals; this->DirectionCosines->Delete(); #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) #else this->MedicalImageProperties->Delete(); #endif #if (VTK_MAJOR_VERSION > 5) || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) #else if( this->FileNames ) { this->FileNames->Delete(); } #endif if( this->Curve ) { this->Curve->Delete(); } } //---------------------------------------------------------------------------- #if (VTK_MAJOR_VERSION > 5) || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) #else void vtkGDCMImageReader::SetFileNames(vtkStringArray *filenames) { if (filenames == this->FileNames) { return; } if (this->FileNames) { this->FileNames->Delete(); this->FileNames = 0; } if (filenames) { this->FileNames = filenames; this->FileNames->Register(this); if (this->FileNames->GetNumberOfValues() > 0) { this->DataExtent[4] = 0; this->DataExtent[5] = this->FileNames->GetNumberOfValues() - 1; } if (this->FilePrefix) { delete [] this->FilePrefix; this->FilePrefix = NULL; } if (this->FileName) { delete [] this->FileName; this->FileName = NULL; } } this->Modified(); } #endif //---------------------------------------------------------------------------- #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) #else void vtkGDCMImageReader::ExecuteInformation() { //std::cerr << "ExecuteInformation" << std::endl; // FIXME: I think it only apply to VTK 4.2... vtkImageData *output = this->GetOutput(); output->SetUpdateExtentToWholeExtent(); // pipeline is not reexecuting properly without that... int res = RequestInformationCompat(); if( !res ) { vtkErrorMacro( "ExecuteInformation failed" ); this->SetErrorCode(vtkErrorCode::FileFormatError); return; } int numvol = 1; if( this->LoadIconImage ) { numvol = 2; } if( this->LoadOverlays ) { // If not icon found, we still need to be associated to port #2: numvol = 3; } this->SetNumberOfOutputs(numvol); // vtkImageReader2::ExecuteInformation only allocate first output this->vtkImageReader2::ExecuteInformation(); // Let's do the other ones ourselves: for (int i=1; iOutputs[i]) { vtkImageData * img = vtkImageData::New(); this->SetNthOutput(i, img); img->Delete(); } vtkImageData *output = this->GetOutput(i); switch(i) { case 0: output->SetWholeExtent(this->DataExtent); output->SetSpacing(this->DataSpacing); #ifdef GDCMV2_0_COMPATIBILITY output->SetOrigin(this->DataOrigin); #endif output->SetScalarType(this->DataScalarType); output->SetNumberOfScalarComponents(this->NumberOfScalarComponents); break; case ICONIMAGEPORTNUMBER: output->SetWholeExtent(this->IconImageDataExtent); output->SetScalarType( this->IconDataScalarType ); output->SetNumberOfScalarComponents( this->IconNumberOfScalarComponents ); break; //case OVERLAYPORTNUMBER: default: output->SetWholeExtent(this->DataExtent[0],this->DataExtent[1], this->DataExtent[2],this->DataExtent[3], 0,0 ); //output->SetSpacing(this->DataSpacing); //output->SetOrigin(this->DataOrigin); output->SetScalarType(VTK_UNSIGNED_CHAR); output->SetNumberOfScalarComponents(1); break; } } } //---------------------------------------------------------------------------- void vtkGDCMImageReader::ExecuteData(vtkDataObject *output) { //std::cerr << "ExecuteData" << std::endl; // In VTK 4.2 AllocateOutputData is reexecuting ExecuteInformation which is bad ! //vtkImageData *data = this->AllocateOutputData(output); vtkImageData *res = vtkImageData::SafeDownCast(output); res->SetExtent(res->GetUpdateExtent()); res->AllocateScalars(); if( this->LoadIconImage ) { vtkImageData *res = vtkImageData::SafeDownCast(this->Outputs[ICONIMAGEPORTNUMBER]); res->SetUpdateExtentToWholeExtent(); res->SetExtent(res->GetUpdateExtent()); res->AllocateScalars(); } if( this->LoadOverlays ) { vtkImageData *res = vtkImageData::SafeDownCast(this->Outputs[OVERLAYPORTNUMBER]); res->SetUpdateExtentToWholeExtent(); res->SetExtent(res->GetUpdateExtent()); res->AllocateScalars(); } //int * updateExtent = data->GetUpdateExtent(); //std::cout << "UpdateExtent:" << updateExtent[4] << " " << updateExtent[5] << std::endl; RequestDataCompat(); } #endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/ //---------------------------------------------------------------------------- int vtkGDCMImageReader::CanReadFile(const char* fname) { gdcm::ImageReader reader; reader.SetFileName( fname ); if( !reader.Read() ) { return 0; } // 3 means: I might be able to read... return 3; } //---------------------------------------------------------------------------- #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) int vtkGDCMImageReader::ProcessRequest(vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector) { // generate the data if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) { return this->RequestData(request, inputVector, outputVector); } // execute information if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) { return this->RequestInformation(request, inputVector, outputVector); } return this->Superclass::ProcessRequest(request, inputVector, outputVector); } #endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/ //---------------------------------------------------------------------------- void vtkGDCMImageReader::FillMedicalImageInformation(const gdcm::ImageReader &reader) { const gdcm::File &file = reader.GetFile(); const gdcm::DataSet &ds = file.GetDataSet(); // $ grep "vtkSetString\|DICOM" vtkMedicalImageProperties.h // For ex: DICOM (0010,0010) = DOE,JOHN this->MedicalImageProperties->SetPatientName( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0010,0x0010), ds).c_str() ); // For ex: DICOM (0010,0020) = 1933197 this->MedicalImageProperties->SetPatientID( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0010,0x0020), ds).c_str() ); // For ex: DICOM (0010,1010) = 031Y this->MedicalImageProperties->SetPatientAge( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0010,0x1010), ds).c_str() ); // For ex: DICOM (0010,0040) = M this->MedicalImageProperties->SetPatientSex( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0010,0x0040), ds).c_str() ); // For ex: DICOM (0010,0030) = 19680427 this->MedicalImageProperties->SetPatientBirthDate( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0010,0x0030), ds).c_str() ); #if (VTK_MAJOR_VERSION > 5) || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) // For ex: DICOM (0008,0020) = 20030617 this->MedicalImageProperties->SetStudyDate( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0020), ds).c_str() ); #endif // For ex: DICOM (0008,0022) = 20030617 this->MedicalImageProperties->SetAcquisitionDate( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0022), ds).c_str() ); #if (VTK_MAJOR_VERSION > 5) || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) // For ex: DICOM (0008,0030) = 162552.0705 or 230012, or 0012 this->MedicalImageProperties->SetStudyTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0030), ds).c_str() ); #endif // For ex: DICOM (0008,0032) = 162552.0705 or 230012, or 0012 this->MedicalImageProperties->SetAcquisitionTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0032), ds).c_str() ); // For ex: DICOM (0008,0023) = 20030617 this->MedicalImageProperties->SetImageDate( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0023), ds).c_str() ); // For ex: DICOM (0008,0033) = 162552.0705 or 230012, or 0012 this->MedicalImageProperties->SetImageTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0033), ds).c_str() ); // For ex: DICOM (0020,0013) = 1 this->MedicalImageProperties->SetImageNumber( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0020,0x0013), ds).c_str() ); // For ex: DICOM (0020,0011) = 902 this->MedicalImageProperties->SetSeriesNumber( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0020,0x0011), ds).c_str() ); // For ex: DICOM (0008,103e) = SCOUT this->MedicalImageProperties->SetSeriesDescription( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x103e), ds).c_str() ); // For ex: DICOM (0020,0010) = 37481 this->MedicalImageProperties->SetStudyID( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0020,0x0010), ds).c_str() ); // For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL this->MedicalImageProperties->SetStudyDescription( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x1030), ds).c_str() ); // For ex: DICOM (0008,0060)= CT this->MedicalImageProperties->SetModality( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0060), ds).c_str() ); // For ex: DICOM (0008,0070) = Siemens this->MedicalImageProperties->SetManufacturer( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0070), ds).c_str() ); // For ex: DICOM (0008,1090) = LightSpeed QX/i this->MedicalImageProperties->SetManufacturerModelName( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x1090), ds).c_str() ); // For ex: DICOM (0008,1010) = LSPD_OC8 this->MedicalImageProperties->SetStationName( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x1010), ds).c_str() ); // For ex: DICOM (0008,0080) = FooCity Medical Center this->MedicalImageProperties->SetInstitutionName( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0080), ds).c_str() ); // For ex: DICOM (0018,1210) = Bone this->MedicalImageProperties->SetConvolutionKernel( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x1210), ds).c_str() ); // For ex: DICOM (0018,0050) = 0.273438 this->MedicalImageProperties->SetSliceThickness( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x0050), ds).c_str() ); // For ex: DICOM (0018,0060) = 120 this->MedicalImageProperties->SetKVP( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x0060), ds).c_str() ); // For ex: DICOM (0018,1120) = 15 this->MedicalImageProperties->SetGantryTilt( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x1120), ds).c_str() ); // For ex: DICOM (0018,0081) = 105 this->MedicalImageProperties->SetEchoTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x0081), ds).c_str() ); // For ex: DICOM (0018,0091) = 35 this->MedicalImageProperties->SetEchoTrainLength( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x0091), ds).c_str() ); // For ex: DICOM (0018,0080) = 2040 this->MedicalImageProperties->SetRepetitionTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x0080), ds).c_str() ); // For ex: DICOM (0018,1150) = 5 this->MedicalImageProperties->SetExposureTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x1150), ds).c_str() ); // For ex: DICOM (0018,1151) = 400 this->MedicalImageProperties->SetXRayTubeCurrent( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x1151), ds).c_str() ); // For ex: DICOM (0018,1152) = 114 this->MedicalImageProperties->SetExposure( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x1152), ds).c_str() ); // virtual void AddWindowLevelPreset(double w, double l); // (0028,1050) DS [ 498\ 498] # 12, 2 WindowCenter // (0028,1051) DS [ 1063\ 1063] # 12, 2 WindowWidth gdcm::Tag twindowcenter(0x0028,0x1050); gdcm::Tag twindowwidth(0x0028,0x1051); if( ds.FindDataElement( twindowcenter ) && ds.FindDataElement( twindowwidth) ) { const gdcm::DataElement& windowcenter = ds.GetDataElement( twindowcenter ); const gdcm::DataElement& windowwidth = ds.GetDataElement( twindowwidth ); const gdcm::ByteValue *bvwc = windowcenter.GetByteValue(); const gdcm::ByteValue *bvww = windowwidth.GetByteValue(); if( bvwc && bvww ) // Can be Type 2 { //gdcm::Attributes<0x0028,0x1050> at; gdcm::Element elwc; std::stringstream ss1; std::string swc = std::string( bvwc->GetPointer(), bvwc->GetLength() ); ss1.str( swc ); gdcm::VR vr = gdcm::VR::DS; unsigned int vrsize = vr.GetSizeof(); unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swc.c_str(), (unsigned int)swc.size()); elwc.SetLength( count * vrsize ); elwc.Read( ss1 ); std::stringstream ss2; std::string sww = std::string( bvww->GetPointer(), bvww->GetLength() ); ss2.str( sww ); gdcm::Element elww; elww.SetLength( count * vrsize ); elww.Read( ss2 ); //assert( elww.GetLength() == elwc.GetLength() ); for(unsigned int i = 0; i < elwc.GetLength(); ++i) { this->MedicalImageProperties->AddWindowLevelPreset( elww.GetValue(i), elwc.GetValue(i) ); } } } gdcm::Tag twindowexplanation(0x0028,0x1055); if( ds.FindDataElement( twindowexplanation ) ) { const gdcm::DataElement& windowexplanation = ds.GetDataElement( twindowexplanation ); const gdcm::ByteValue *bvwe = windowexplanation.GetByteValue(); if( bvwe ) // Can be Type 2 { unsigned int n = this->MedicalImageProperties->GetNumberOfWindowLevelPresets(); gdcm::Element elwe; // window explanation gdcm::VR vr = gdcm::VR::LO; std::stringstream ss; ss.str( "" ); std::string swe = std::string( bvwe->GetPointer(), bvwe->GetLength() ); unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swe.c_str(), (unsigned int)swe.size()); (void)count; // I found a case with only one W/L but two comments: WINDOW1\WINDOW2 // SIEMENS-IncompletePixelData.dcm // oh wait but what if we have the countrary... //assert( count >= (unsigned int)n ); elwe.SetLength( count * vr.GetSizeof() ); ss.str( swe ); elwe.Read( ss ); unsigned int c = std::min(n, count); for(unsigned int i = 0; i < c; ++i) { this->MedicalImageProperties->SetNthWindowLevelPresetComment(i, elwe.GetValue(i).c_str() ); } } } #if 0 // gdcmData/JDDICOM_Sample4.dcm // -> (0008,0060) CS [DM Digital microscopy] # 24, 1 Modality gdcm::MediaStorage ms1 = gdcm::MediaStorage::SecondaryCaptureImageStorage; ms1.GuessFromModality( this->MedicalImageProperties->GetModality(), this->FileDimensionality ); gdcm::MediaStorage ms2; ms2.SetFromFile( reader.GetFile() ); if( ms2 != ms1 && ms2 != gdcm::MediaStorage::SecondaryCaptureImageStorage ) { vtkWarningMacro( "SHOULD NOT HAPPEN. Unrecognized Modality: " << this->MedicalImageProperties->GetModality() << " Will be set instead to the known one: " << ms2.GetModality() ) this->MedicalImageProperties->SetModality( ms2.GetModality() ); } #endif // Add more info: vtkGDCMMedicalImageProperties *gdcmmip = dynamic_cast( this->MedicalImageProperties ); if( gdcmmip ) { gdcmmip->PushBackFile( file ); } } //---------------------------------------------------------------------------- #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) int vtkGDCMImageReader::RequestInformation(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) { (void)request;(void)inputVector; int res = RequestInformationCompat(); if( !res ) { vtkErrorMacro( "RequestInformationCompat failed: " << res ); this->SetErrorCode(vtkErrorCode::FileFormatError); return 0; } int numvol = 1; if( this->LoadIconImage ) { numvol = 2; } if( this->LoadOverlays ) { // If no icon found, we still need to be associated to port #2: numvol = 2 + this->NumberOfOverlays; } this->SetNumberOfOutputPorts(numvol); // For each output: for(int i = 0; i < numvol; ++i) { // Allocate ! if( !this->GetOutput(i) ) { vtkImageData *img = vtkImageData::New(); this->GetExecutive()->SetOutputData(i, img ); img->Delete(); } vtkInformation *outInfo = outputVector->GetInformationObject(i); switch(i) { // root Pixel Data case 0: outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->DataExtent, 6); //outInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), this->DataExtent, 6); outInfo->Set(vtkDataObject::SPACING(), this->DataSpacing, 3); #ifdef GDCMV2_0_COMPATIBILITY outInfo->Set(vtkDataObject::ORIGIN(), this->DataOrigin, 3); #endif vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->DataScalarType, this->NumberOfScalarComponents); break; // Icon Image case ICONIMAGEPORTNUMBER: outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->IconImageDataExtent, 6); vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->IconDataScalarType, this->IconNumberOfScalarComponents ); break; // Overlays: //case OVERLAYPORTNUMBER: default: outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->DataExtent[0], this->DataExtent[1], this->DataExtent[2], this->DataExtent[3], 0,0 ); vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 1); break; } } //return res; return 1; } #endif static gdcm::PixelFormat::ScalarType ComputePixelTypeFromFiles(const char *inputfilename, vtkStringArray *filenames, gdcm::Image const & imageref) { gdcm::PixelFormat::ScalarType outputpt; outputpt = gdcm::PixelFormat::UNKNOWN; // there is a very subtle bug here. Let's imagine we have a collection of files // they can all have different Rescale Slope / Intercept. In this case we should: // 1. Make sure to read each Rescale Slope / Intercept individually // 2. Make sure to decide which Pixel Type to use using *all* slices: if( inputfilename ) { const gdcm::Image &image = imageref; const gdcm::PixelFormat &pixeltype = image.GetPixelFormat(); double shift = image.GetIntercept(); double scale = image.GetSlope(); gdcm::Rescaler r; r.SetIntercept( shift ); r.SetSlope( scale ); r.SetPixelFormat( pixeltype ); outputpt = r.ComputeInterceptSlopePixelType(); } else if ( filenames && filenames->GetNumberOfValues() > 0 ) { std::set< gdcm::PixelFormat::ScalarType > pixeltypes; std::set< unsigned short > samplesperpixel; // FIXME a gdcm::Scanner would be much faster here: for(int i = 0; i < filenames->GetNumberOfValues(); ++i ) { const char *filename = filenames->GetValue( i ); gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { vtkGenericWarningMacro( "ImageReader failed: " << filename ); return gdcm::PixelFormat::UNKNOWN; } const gdcm::Image &image = reader.GetImage(); const gdcm::PixelFormat &pixeltype = image.GetPixelFormat(); samplesperpixel.insert( pixeltype.GetSamplesPerPixel() ); double shift = image.GetIntercept(); double scale = image.GetSlope(); gdcm::PixelFormat::ScalarType outputpt2 = pixeltype; gdcm::Rescaler r; r.SetIntercept( shift ); r.SetSlope( scale ); r.SetPixelFormat( pixeltype ); outputpt2 = r.ComputeInterceptSlopePixelType(); //std::cout << "Found: " << outputpt << std::endl; pixeltypes.insert( outputpt2 ); } if( pixeltypes.size() == 1 ) { assert( samplesperpixel.size() == 1 ); // Ok easy case outputpt = *pixeltypes.begin(); } else if( samplesperpixel.size() == 1 ) { // Hardcoded. If Pixel Type found is the maximum (as of PS 3.5 - 2008) // There is nothing bigger that FLOAT64 if( pixeltypes.count( gdcm::PixelFormat::FLOAT64 ) != 0 ) { outputpt = gdcm::PixelFormat::FLOAT64; } else { // should I just take the biggest value ? // MM: I am not sure UINT16 and INT16 are really compatible // so taking the biggest value might not be the solution // In this case we could use INT32, but FLOAT64 also works... // oh well, let's just use FLOAT64 always. vtkGenericWarningMacro( "This may not always be optimized. Sorry" ); outputpt = gdcm::PixelFormat::FLOAT64; } } else { vtkGenericWarningMacro( "Could not compute Pixel Type. Sorry" ); } } else { assert( 0 ); // I do not think this is possible } //gdcmAssertMacro( outputpt >= pixeltype_ref ); //(void)pixeltype_ref; return outputpt; } //---------------------------------------------------------------------------- int vtkGDCMImageReader::RequestInformationCompat() { // FIXME, need to implement the other modes too: if( this->ApplyLookupTable || this->ApplyYBRToRGB || this->ApplyInverseVideo ) { vtkErrorMacro( "ApplyLookupTable/ApplyYBRToRGB/ApplyInverseVideo not compatible" ); return 0; } // I do not think this is a good idea anyway to let the user decide // whether or not she wants *not* to apply shift/scale... if( !this->ApplyShiftScale ) { vtkErrorMacro("ApplyShiftScale not compatible" ); return 0; } // I do not think this one will ever be implemented: if( !this->ApplyPlanarConfiguration ) { vtkErrorMacro("ApplyPlanarConfiguration not compatible" ); return 0; } // Let's read the first file : const char *filename; if( this->FileName ) { filename = this->FileName; } else if ( this->FileNames && this->FileNames->GetNumberOfValues() > 0 ) { filename = this->FileNames->GetValue( 0 ); } else { // hey! I need at least one file to schew on ! vtkErrorMacro( "You did not specify any filenames" ); return 0; } gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { vtkErrorMacro( "ImageReader failed on " << filename ); return 0; } const gdcm::Image &image = reader.GetImage(); this->LossyFlag = image.IsLossy(); const unsigned int *dims = image.GetDimensions(); // Set the Extents. assert( image.GetNumberOfDimensions() >= 2 ); this->DataExtent[0] = 0; this->DataExtent[1] = dims[0] - 1; this->DataExtent[2] = 0; this->DataExtent[3] = dims[1] - 1; if( image.GetNumberOfDimensions() == 2 ) { // This is just so much painful to deal with DICOM / VTK // they simply assume that number of file is equal to the dimension // of the last axe (see vtkImageReader2::SetFileNames ) if ( this->FileNames && this->FileNames->GetNumberOfValues() > 1 ) { this->DataExtent[4] = 0; //this->DataExtent[5] = this->FileNames->GetNumberOfValues() - 1; } else { this->DataExtent[4] = 0; this->DataExtent[5] = 0; } } else { assert( image.GetNumberOfDimensions() == 3 ); this->FileDimensionality = 3; this->DataExtent[4] = 0; this->DataExtent[5] = dims[2] - 1; } gdcm::MediaStorage ms; ms.SetFromFile( reader.GetFile() ); assert( gdcm::MediaStorage::IsImage( ms ) || ms == gdcm::MediaStorage::MRSpectroscopyStorage ); // There is no point in adding world info to a SC object since noone but GDCM can use this info... //if( ms != gdcm::MediaStorage::SecondaryCaptureImageStorage ) const double *spacing = image.GetSpacing(); if( spacing ) { this->DataSpacing[0] = spacing[0]; this->DataSpacing[1] = spacing[1]; this->DataSpacing[2] = image.GetSpacing(2); } const double *origin = image.GetOrigin(); if( origin ) { this->ImagePositionPatient[0] = image.GetOrigin(0); this->ImagePositionPatient[1] = image.GetOrigin(1); this->ImagePositionPatient[2] = image.GetOrigin(2); } const double *dircos = image.GetDirectionCosines(); if( dircos ) { this->DirectionCosines->SetElement(0,0, dircos[0]); this->DirectionCosines->SetElement(1,0, dircos[1]); this->DirectionCosines->SetElement(2,0, dircos[2]); this->DirectionCosines->SetElement(3,0, 0); this->DirectionCosines->SetElement(0,1, dircos[3]); this->DirectionCosines->SetElement(1,1, dircos[4]); this->DirectionCosines->SetElement(2,1, dircos[5]); this->DirectionCosines->SetElement(3,1, 0); double dircosz[3]; vtkMath::Cross(dircos, dircos+3, dircosz); this->DirectionCosines->SetElement(0,2, dircosz[0]); this->DirectionCosines->SetElement(1,2, dircosz[1]); this->DirectionCosines->SetElement(2,2, dircosz[2]); this->DirectionCosines->SetElement(3,2, 0); //std::cout << "Det: " << this->DirectionCosines->Determinant() << std::endl; for(int i=0;i<6;++i) this->ImageOrientationPatient[i] = dircos[i]; #if VTK_MAJOR_VERSION >= 6 || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 2 ) this->MedicalImageProperties->SetDirectionCosine( this->ImageOrientationPatient ); #endif } // Apply transform: #ifdef GDCMV2_0_COMPATIBILITY if( dircos && origin ) { if( this->FileLowerLeft ) { // Since we are not doing the VTK Y-flipping operation, Origin and Image Position (Patient) // are the same: this->DataOrigin[0] = origin[0]; this->DataOrigin[1] = origin[1]; this->DataOrigin[2] = origin[2]; } else { // We are doing the Y-flip: // translate Image Position (Patient) along the Y-vector of the Image Orientation (Patient): // Step 1: Compute norm of translation vector: // Because position is in the center of the pixel, we need to substract 1 to the dimY: assert( dims[1] >=1 ); double norm = (dims[1] - 1) * this->DataSpacing[1]; // Step 2: translate: this->DataOrigin[0] = origin[0] + norm * dircos[3+0]; this->DataOrigin[1] = origin[1] + norm * dircos[3+1]; this->DataOrigin[2] = origin[2] + norm * dircos[3+2]; } } // Need to set the rest to 0 ??? #endif const gdcm::PixelFormat &pixeltype = image.GetPixelFormat(); this->Shift = image.GetIntercept(); this->Scale = image.GetSlope(); //gdcm::PixelFormat::ScalarType outputpt = pixeltype; gdcm::PixelFormat::ScalarType outputpt = ComputePixelTypeFromFiles(this->FileName, this->FileNames, image); if( this->FileName ) { // We should test that outputpt is 8 when BitsAllocated = 16 / Bits Stored = 8 // BUT we should test that output is 16 when BitsAllocated = 16 / BitsStored = 12 // assert( outputpt == pixeltype ); } // Compute output pixel format when Rescaling: // if( this->Shift != 0 || this->Scale != 1. ) // { // gdcm::Rescaler r; // r.SetIntercept( this->Shift ); // r.SetSlope( this->Scale ); // r.SetPixelFormat( pixeltype ); // outputpt = r.ComputeInterceptSlopePixelType(); // assert( pixeltype <= outputpt ); // assert( pixeltype.GetSamplesPerPixel() == 1 && image.GetPhotometricInterpretation().GetSamplesPerPixel() == 1 ); // assert( image.GetPhotometricInterpretation() != gdcm::PhotometricInterpretation::PALETTE_COLOR ); // } //if( pixeltype != outputpt ) assert( Shift != 0. || Scale != 1 ); this->ForceRescale = 0; // always reset this thing // gdcmData/DCMTK_JPEGExt_12Bits.dcm if( pixeltype != outputpt && pixeltype.GetBitsAllocated() != 12 && pixeltype.GetSamplesPerPixel() == 1 ) { this->ForceRescale = 1; } switch( outputpt ) { case gdcm::PixelFormat::INT8: #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) this->DataScalarType = VTK_SIGNED_CHAR; #else if( !vtkGDCMImageReader_IsCharTypeSigned() ) { vtkErrorMacro( "Output Pixel Type will be incorrect, go get a newer VTK version" ); } this->DataScalarType = VTK_CHAR; #endif break; case gdcm::PixelFormat::UINT8: this->DataScalarType = VTK_UNSIGNED_CHAR; break; case gdcm::PixelFormat::INT16: this->DataScalarType = VTK_SHORT; break; case gdcm::PixelFormat::UINT16: this->DataScalarType = VTK_UNSIGNED_SHORT; break; // RT / SC have 32bits case gdcm::PixelFormat::INT32: this->DataScalarType = VTK_INT; break; case gdcm::PixelFormat::UINT32: this->DataScalarType = VTK_UNSIGNED_INT; break; case gdcm::PixelFormat::INT12: this->DataScalarType = VTK_SHORT; break; case gdcm::PixelFormat::UINT12: this->DataScalarType = VTK_UNSIGNED_SHORT; break; //case gdcm::PixelFormat::FLOAT16: // TODO case gdcm::PixelFormat::FLOAT32: this->DataScalarType = VTK_FLOAT; break; case gdcm::PixelFormat::FLOAT64: this->DataScalarType = VTK_DOUBLE; break; case gdcm::PixelFormat::SINGLEBIT: this->DataScalarType = VTK_BIT; break; default: this->SetErrorCode(vtkErrorCode::FileFormatError); vtkErrorMacro( "Do not support this Pixel Type: " << pixeltype.GetScalarTypeAsString() << " with " << gdcm::PixelFormat(outputpt).GetScalarTypeAsString() ); return 0; } this->NumberOfScalarComponents = pixeltype.GetSamplesPerPixel(); // Ok let's fill in the 'extra' info: this->FillMedicalImageInformation(reader); // Do the IconImage if requested: const gdcm::IconImage& icon = image.GetIconImage(); if( this->LoadIconImage && !icon.IsEmpty() ) { this->IconImageDataExtent[0] = 0; this->IconImageDataExtent[1] = icon.GetColumns() - 1; this->IconImageDataExtent[2] = 0; this->IconImageDataExtent[3] = icon.GetRows() - 1; // const gdcm::PixelFormat &iconpixelformat = icon.GetPixelFormat(); switch(iconpixelformat) { case gdcm::PixelFormat::INT8: #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) this->IconDataScalarType = VTK_SIGNED_CHAR; #else this->IconDataScalarType = VTK_CHAR; #endif break; case gdcm::PixelFormat::UINT8: this->IconDataScalarType = VTK_UNSIGNED_CHAR; break; case gdcm::PixelFormat::INT16: this->IconDataScalarType = VTK_SHORT; break; case gdcm::PixelFormat::UINT16: this->IconDataScalarType = VTK_UNSIGNED_SHORT; break; default: vtkErrorMacro( "Do not support this Icon Pixel Type: " << (int)iconpixelformat.GetScalarType() ); return 0; } this->IconNumberOfScalarComponents = iconpixelformat.GetSamplesPerPixel(); } // Overlay! size_t numoverlays = image.GetNumberOfOverlays(); if( this->LoadOverlays && numoverlays ) { // Do overlay specific stuff... // what if overlay do not have the same data extent as image ? for( unsigned int ovidx = 0; ovidx < numoverlays; ++ovidx ) { const gdcm::Overlay& ov = image.GetOverlay(ovidx); assert( (unsigned int)ov.GetRows() == image.GetRows() ); (void)ov; assert( (unsigned int)ov.GetColumns() == image.GetColumns() ); } this->NumberOfOverlays = (int)numoverlays; } // return this->Superclass::RequestInformation( // request, inputVector, outputVector); return 1; } //---------------------------------------------------------------------------- template static inline unsigned long vtkImageDataGetTypeSize(T*, int a = 0,int b = 0) { (void)a;(void)b; return sizeof(T); } //---------------------------------------------------------------------------- static void InPlaceYFlipImage(vtkImageData* data, const int dext[6]) { unsigned long outsize = data->GetNumberOfScalarComponents(); if( dext[1] == dext[0] && dext[0] == 0 ) return; // Multiply by the number of bytes per scalar switch (data->GetScalarType()) { #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) case VTK_BIT: { outsize /= 8; }; break; vtkTemplateMacro( outsize *= vtkImageDataGetTypeSize(static_cast(0)) ); #else case VTK_BIT: { outsize /= 8; }; break; vtkTemplateMacro3( outsize *= vtkImageDataGetTypeSize, static_cast(0), 0, 0 ); #endif default: //vtkErrorMacro("do not support scalar type: " << data->GetScalarType() ); assert(0); } outsize *= (dext[1] - dext[0] + 1); char * ref = static_cast(data->GetScalarPointer()); char * pointer = static_cast(data->GetScalarPointer()); assert( pointer ); char *line = new char[outsize]; for(int j = dext[4]; j <= dext[5]; ++j) { char *start = pointer; assert( start == ref + j * outsize * (dext[3] - dext[2] + 1) ); (void)ref; // Swap two-lines at a time // when Rows is odd number (359) then dext[3] == 178 // so we should avoid copying the line right in the center of the image // since memcpy does not like copying on itself... for(int i = dext[2]; i < (dext[3]+1) / 2; ++i) { // image: char * end = start+(dext[3] - i)*outsize; assert( (end - pointer) >= (int)outsize ); memcpy(line,end,outsize); // duplicate line memcpy(end,pointer,outsize); memcpy(pointer,line,outsize); pointer += outsize; } // because the for loop iterated only over 1/2 all lines, skip to the next slice: assert( dext[2] == 0 ); pointer += (dext[3] + 1 - (dext[3]+1)/2 )*outsize; } // Did we reach the end ? assert( pointer == ref + (dext[5]-dext[4]+1)*(dext[3]-dext[2]+1)*outsize ); delete[] line; } //---------------------------------------------------------------------------- int vtkGDCMImageReader::LoadSingleFile(const char *filename, char *pointer, unsigned long &outlen) { int *dext = this->GetDataExtent(); vtkImageData *data = this->GetOutput(0); //bool filelowerleft = this->FileLowerLeft ? true : false; //char * pointer = static_cast(data->GetScalarPointer()); gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { vtkErrorMacro( "ImageReader failed: " << filename ); return 0; } gdcm::Image &image = reader.GetImage(); this->LossyFlag = image.IsLossy(); //VTK does not cope with Planar Configuration, so let's schew the work to please it assert( this->PlanarConfiguration == 0 || this->PlanarConfiguration == 1 ); // Store the PlanarConfiguration before inverting it ! this->PlanarConfiguration = image.GetPlanarConfiguration(); //assert( this->PlanarConfiguration == 0 || this->PlanarConfiguration == 1 ); if( image.GetPlanarConfiguration() == 1 ) { gdcm::ImageChangePlanarConfiguration icpc; icpc.SetInput( image ); icpc.SetPlanarConfiguration( 0 ); icpc.Change(); image = icpc.GetOutput(); } const gdcm::PixelFormat &pixeltype = image.GetPixelFormat(); assert( image.GetNumberOfDimensions() == 2 || image.GetNumberOfDimensions() == 3 ); /*const*/ unsigned long len = image.GetBufferLength(); outlen = len; unsigned long overlaylen = 0; //image.GetBuffer(pointer); // HACK: Make sure that Shift/Scale are the one from the file: this->Shift = image.GetIntercept(); this->Scale = image.GetSlope(); if( (this->Scale != 1.0 || this->Shift != 0.0) || this->ForceRescale ) { if( pixeltype.GetSamplesPerPixel() != 1 ) { vtkWarningMacro( "Cannot do Rescale with Sample Per Pixel != 1. Discarding rescale" ); this->Shift = 0.0; this->Scale = 1.0; } } if( (this->Scale != 1.0 || this->Shift != 0.0) || this->ForceRescale ) { assert( pixeltype.GetSamplesPerPixel() == 1 ); gdcm::Rescaler r; r.SetIntercept( Shift ); // FIXME r.SetSlope( Scale ); // FIXME gdcm::PixelFormat::ScalarType targetpixeltype = gdcm::PixelFormat::UNKNOWN; // r.SetTargetPixelType( gdcm::PixelFormat::FLOAT64 ); int scalarType = data->GetScalarType(); switch( scalarType ) { case VTK_CHAR: if( vtkGDCMImageReader_IsCharTypeSigned() ) targetpixeltype = gdcm::PixelFormat::INT8; else targetpixeltype = gdcm::PixelFormat::UINT8; break; #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) case VTK_SIGNED_CHAR: targetpixeltype = gdcm::PixelFormat::INT8; break; #endif case VTK_UNSIGNED_CHAR: targetpixeltype = gdcm::PixelFormat::UINT8; break; case VTK_SHORT: targetpixeltype = gdcm::PixelFormat::INT16; break; case VTK_UNSIGNED_SHORT: targetpixeltype = gdcm::PixelFormat::UINT16; break; case VTK_INT: targetpixeltype = gdcm::PixelFormat::INT32; break; case VTK_UNSIGNED_INT: targetpixeltype = gdcm::PixelFormat::UINT32; break; case VTK_FLOAT: targetpixeltype = gdcm::PixelFormat::FLOAT32; break; case VTK_DOUBLE: targetpixeltype = gdcm::PixelFormat::FLOAT64; break; case VTK_BIT: targetpixeltype = gdcm::PixelFormat::SINGLEBIT; break; default: vtkErrorMacro( "Do not support this Pixel Type: " << scalarType ); assert( 0 ); return 0; } r.SetTargetPixelType( targetpixeltype ); r.SetUseTargetPixelType(true); r.SetPixelFormat( pixeltype ); char * copy = new char[len]; //memcpy(copy, pointer, len); image.GetBuffer(copy); if( !r.Rescale(pointer,copy,len) ) { vtkErrorMacro( "Could not Rescale" ); // problem with gdcmData/3E768EB7.dcm return 0; } delete[] copy; // WARNING: sizeof(Real World Value) != sizeof(Stored Pixel) outlen = data->GetScalarSize() * data->GetNumberOfPoints() / data->GetDimensions()[2]; assert( data->GetNumberOfScalarComponents() == 1 ); } else { image.GetBuffer(pointer); } // Do the Icon Image: if( this->LoadIconImage ) { this->NumberOfIconImages = image.GetIconImage().IsEmpty() ? 0 : 1; if( this->NumberOfIconImages ) { char * iconpointer = static_cast(this->GetOutput(ICONIMAGEPORTNUMBER)->GetScalarPointer()); assert( iconpointer ); image.GetIconImage().GetBuffer( iconpointer ); if ( image.GetIconImage().GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::PALETTE_COLOR ) { const gdcm::LookupTable &lut = image.GetIconImage().GetLUT(); assert( lut.GetBitSample() == 8 ); { vtkLookupTable *vtklut = vtkLookupTable::New(); vtklut->SetNumberOfTableValues(256); // SOLVED: GetPointer(0) is skrew up, need to replace it with WritePointer(0,4) ... if( !lut.GetBufferAsRGBA( vtklut->WritePointer(0,4) ) ) { vtkWarningMacro( "Could not get values from LUT" ); return 0; } vtklut->SetRange(0,255); this->GetOutput(ICONIMAGEPORTNUMBER)->GetPointData()->GetScalars()->SetLookupTable( vtklut ); vtklut->Delete(); } } } } // Do the Curve: size_t numcurves = image.GetNumberOfCurves(); if( numcurves ) { const gdcm::Curve& curve = image.GetCurve(); //curve.Print( std::cout ); vtkPoints * pts = vtkPoints::New(); pts->SetNumberOfPoints( curve.GetNumberOfPoints() ); curve.GetAsPoints( (float*)pts->GetVoidPointer(0) ); vtkCellArray *polys = vtkCellArray::New(); for(unsigned int i = 0; i < curve.GetNumberOfPoints(); i+=2 ) { polys->InsertNextCell(2); polys->InsertCellPoint(i); polys->InsertCellPoint(i+1); } vtkPolyData *cube = vtkPolyData::New(); cube->SetPoints(pts); pts->Delete(); cube->SetLines(polys); polys->Delete(); SetCurve(cube); cube->Delete(); } // Do the Overlay: if( this->LoadOverlays ) { size_t numoverlays = image.GetNumberOfOverlays(); long overlayoutsize = (dext[1] - dext[0] + 1); //this->NumberOfOverlays = numoverlays; //if( numoverlays ) if( !this->LoadOverlays ) assert( this->NumberOfOverlays == 0 ); for( int ovidx = 0; ovidx < this->NumberOfOverlays; ++ovidx ) { vtkImageData *vtkimage = this->GetOutput(OVERLAYPORTNUMBER + ovidx); // vtkOpenGLImageMapper::RenderData does not support bit array (since OpenGL does not either) // we have to decompress the bit overlay into an unsigned char array to please everybody: const gdcm::Overlay& ov1 = image.GetOverlay(ovidx); vtkUnsignedCharArray *chararray = vtkUnsignedCharArray::New(); chararray->SetNumberOfTuples( overlayoutsize * ( dext[3] - dext[2] + 1 ) ); overlaylen = overlayoutsize * ( dext[3] - dext[2] + 1 ); assert( (unsigned long)ov1.GetRows()*ov1.GetColumns() <= overlaylen ); const signed short *origin = ov1.GetOrigin(); if( (unsigned long)ov1.GetRows()*ov1.GetColumns() != overlaylen ) { vtkWarningMacro( "vtkImageData Overlay have an extent that do not match the one of the image" ); } if( origin[0] != 1 || origin[1] != 1 ) { // Table C.9-2 OVERLAY PLANE MODULE ATTRIBUTES vtkWarningMacro( "Overlay with origin are not supported right now" ); } vtkimage->GetPointData()->SetScalars( chararray ); vtkimage->GetPointData()->GetScalars()->SetName( ov1.GetDescription() ); chararray->Delete(); assert( vtkimage->GetScalarType() == VTK_UNSIGNED_CHAR ); char * overlaypointer = static_cast(vtkimage->GetScalarPointer()); assert( overlaypointer ); //assert( image->GetPointData()->GetScalars() != 0 ); //memset(overlaypointer,0,overlaylen); // FIXME: can be optimized if( !ov1.GetUnpackBuffer( overlaypointer, overlaylen ) ) { vtkErrorMacro( "Problem in GetUnpackBuffer" ); } } if( numoverlays ) assert( (unsigned long)overlayoutsize * ( dext[3] - dext[2] + 1 ) == overlaylen ); } //const gdcm::PixelFormat &pixeltype = image.GetPixelFormat(); // Do the LUT if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::PALETTE_COLOR ) { this->ImageFormat = VTK_LOOKUP_TABLE; const gdcm::LookupTable &lut = image.GetLUT(); if( lut.GetBitSample() == 8 ) { vtkLookupTable *vtklut = vtkLookupTable::New(); vtklut->SetNumberOfTableValues(256); // SOLVED: GetPointer(0) is skrew up, need to replace it with WritePointer(0,4) ... if( !lut.GetBufferAsRGBA( vtklut->WritePointer(0,4) ) ) { vtkWarningMacro( "Could not get values from LUT" ); return 0; } vtklut->SetRange(0,255); data->GetPointData()->GetScalars()->SetLookupTable( vtklut ); vtklut->Delete(); } else { #if (VTK_MAJOR_VERSION >= 5) assert( lut.GetBitSample() == 16 ); vtkLookupTable16 *vtklut = vtkLookupTable16::New(); vtklut->SetNumberOfTableValues(256*256); // SOLVED: GetPointer(0) is skrew up, need to replace it with WritePointer(0,4) ... if( !lut.GetBufferAsRGBA( (unsigned char*)vtklut->WritePointer(0,4) ) ) { vtkWarningMacro( "Could not get values from LUT" ); return 0; } vtklut->SetRange(0,256*256-1); data->GetPointData()->GetScalars()->SetLookupTable( vtklut ); vtklut->Delete(); #else vtkWarningMacro( "Unhandled" ); #endif } } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 ) { this->ImageFormat = VTK_INVERSE_LUMINANCE; vtkWindowLevelLookupTable *vtklut = vtkWindowLevelLookupTable::New(); // Technically we could also use the first of the Window Width / Window Center // oh well, if they are missing let's just compute something: const double min = (double)pixeltype.GetMin(); const double max = (double)pixeltype.GetMax(); vtklut->SetWindow( max - min ); vtklut->SetLevel( 0.5 * (max + min) ); //vtklut->SetWindow(1024); // WindowWidth //vtklut->SetLevel(550); // WindowCenter vtklut->InverseVideoOn(); data->GetPointData()->GetScalars()->SetLookupTable( vtklut ); vtklut->Delete(); } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::YBR_FULL_422 ) { this->ImageFormat = VTK_YBR; } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::YBR_FULL ) { this->ImageFormat = VTK_YBR; } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::RGB ) { this->ImageFormat = VTK_RGB; } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ) { this->ImageFormat = VTK_LUMINANCE; } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::YBR_RCT ) { this->ImageFormat = VTK_RGB; } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::YBR_ICT ) { this->ImageFormat = VTK_RGB; } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::CMYK ) { this->ImageFormat = VTK_CMYK; } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::ARGB ) { this->ImageFormat = VTK_RGBA; } else { // HSV / CMYK ??? // let's just give up for now vtkErrorMacro( "Does not handle: " << image.GetPhotometricInterpretation().GetString() ); //return 0; } //assert( this->ImageFormat ); long outsize; if( data->GetScalarType() == VTK_BIT ) { outsize = (dext[1] - dext[0] + 1) / 8; } else { outsize = pixeltype.GetPixelSize()*(dext[1] - dext[0] + 1); } if( this->FileName) assert( (unsigned long)outsize * (dext[3] - dext[2]+1) * (dext[5]-dext[4]+1) == len ); return 1; // success } //---------------------------------------------------------------------------- #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) int vtkGDCMImageReader::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) { //this->UpdateProgress(0.2); // Make sure the output dimension is OK, and allocate its scalars for(int i = 0; i < this->GetNumberOfOutputPorts(); ++i) { #if (VTK_MAJOR_VERSION >= 6) vtkInformation* outInfo = outputVector->GetInformationObject(i); vtkImageData *data = static_cast(outInfo->Get(vtkDataObject::DATA_OBJECT())); // Make sure that this output is an image if (data) { int extent[6]; outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent); this->AllocateOutputData(data, outInfo, extent); } #else (void)outputVector; // Copy/paste from vtkImageAlgorithm::AllocateScalars. Cf. "this needs to be fixed -Ken" vtkStreamingDemandDrivenPipeline *sddp = vtkStreamingDemandDrivenPipeline::SafeDownCast(this->GetExecutive()); if (sddp) { int extent[6]; sddp->GetOutputInformation(i)->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),extent); this->GetOutput(i)->SetExtent(extent); } this->GetOutput(i)->AllocateScalars(); #endif } int res = RequestDataCompat(); return res; } #endif //---------------------------------------------------------------------------- int vtkGDCMImageReader::RequestDataCompat() { vtkImageData *output = this->GetOutput(0); output->GetPointData()->GetScalars()->SetName("GDCMImage"); // The outExt is the allocated data extent int outExt[6]; output->GetExtent(outExt); // The dext is the whole extent (includes not-loaded data) int *dext = this->GetDataExtent(); //vtkIdType outInc[3]; //data->GetIncrements(outInc); //int outSize[3]; //data->GetDimensions(outSize); //void *outPtr = data->GetScalarPointerForExtent(outExt); char * pointer = static_cast(output->GetScalarPointerForExtent(outExt)); if( this->FileName ) { const char *filename = this->FileName; unsigned long len; int load = this->LoadSingleFile( filename, pointer, len ); (void)len; if( !load ) { // FIXME: I need to fill the buffer with 0, shouldn't I ? return 0; } } else if( this->FileNames && this->FileNames->GetNumberOfValues() >= 1 ) { // Load each 2D files // HACK: len is moved out of the loop so that when file > 1 start failing we can still know // the len of the buffer...technically all files should have the same len (not checked for now) unsigned long len = 0; for(int j = dext[4]; !this->AbortExecute && j <= dext[5]; ++j) { assert( j >= 0 && j <= this->FileNames->GetNumberOfValues() ); const char *filename = this->FileNames->GetValue( j ); int load = this->LoadSingleFile( filename, pointer, len ); if( !load ) { // hum... we could not read this file within the series, let's just fill // the slice with 0 value, hopefully this should be the right thing to do memset( pointer, 0, len); } assert( len ); pointer += len; this->UpdateProgress( (double)(j - dext[4] ) / ( dext[5] - dext[4] )); } } else { return 0; } // Y-flip image if (!this->FileLowerLeft) { InPlaceYFlipImage(this->GetOutput(0), dext); if( this->LoadIconImage ) { int *iiext = this->IconImageDataExtent; InPlaceYFlipImage(this->GetOutput(ICONIMAGEPORTNUMBER), iiext); } for( int ovidx = 0; ovidx < this->NumberOfOverlays; ++ovidx ) { assert( this->LoadOverlays ); int oext[6]; this->GetDataExtent(oext); oext[4] = 0; oext[5] = 0; InPlaceYFlipImage(this->GetOutput(OVERLAYPORTNUMBER+ovidx), oext); } } return 1; } //---------------------------------------------------------------------------- #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) vtkAlgorithmOutput* vtkGDCMImageReader::GetOverlayPort(int index) { if( index >= 0 && index < this->NumberOfOverlays) return this->GetOutputPort(index+OVERLAYPORTNUMBER); return NULL; } vtkAlgorithmOutput* vtkGDCMImageReader::GetIconImagePort() { const int index = 0; if( index >= 0 && index < this->NumberOfIconImages) return this->GetOutputPort(index+ICONIMAGEPORTNUMBER); return NULL; } #endif //---------------------------------------------------------------------------- vtkImageData* vtkGDCMImageReader::GetOverlay(int i) { if( i >= 0 && i < this->NumberOfOverlays) return this->GetOutput(i+OVERLAYPORTNUMBER); return NULL; } //---------------------------------------------------------------------------- vtkImageData* vtkGDCMImageReader::GetIconImage() { const int i = 0; if( i >= 0 && i < this->NumberOfIconImages) return this->GetOutput(i+ICONIMAGEPORTNUMBER); return NULL; } //---------------------------------------------------------------------------- void vtkGDCMImageReader::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } GDCM-3.0.10/Utilities/VTK/vtkGDCMImageReader.h000066400000000000000000000272311412732066400204340ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // .NAME vtkGDCMImageReader - read DICOM Image files (Pixel Data) // .SECTION Description // vtkGDCMImageReader is a source object that reads some DICOM files // this reader is single threaded. // .SECTION Implementation note: when FileLowerLeft is set to on the image is not flipped // upside down as VTK would expect, use this option only if you know what you are doing. // .SECTION Implementation note: when reading a series of 2D slices, user is // expected to provide an ordered list of filenames. No sorting will be applied afterward. // .SECTION Implementation note: Although 99% of the time the Zspacing as read // from a tag in a 2D DICOM file should be correct, there has been reports that this // value can be missing, or incorrect, in which case users are advised to override this // value using the return value from gdcm::IPPSorter::GetZSpacing() and set it via // vtkImageChangeInformation on the reader itself. // .SECTION TODO // This reader does not handle a series of 3D images, only a single 3D (multi frame) or a // list of 2D files are supported for now. // .SECTION TODO // Did not implement SetFilePattern / SetFilePrefix API, move it to protected section for now. // .SECTION BUG // Overlay are assumed to have the same extent as image. Right now if overlay origin is not // 0,0 the overlay will have an offset... // Only the very first overlay is loaded at the VTK level, for now (even if there are more than one in the file) // .SECTION DataOrigin // When the reader is instanciated with FileLowerLeftOn the DataOrigin and Image Position (Patient) are // identical. But when FileLowerLeft is Off, we have to reorder the Y-line of the image, and thus the DataOrigin // is then translated to the other side of the image. // .SECTION Spacing // When reading a 3D volume, the spacing along the Z dimension might be negative (so as to respect up-side-down) // as specified in the Image Orientation (Patient) tag. When Z-spacing is 0, this means the multi-frame object // contains image which do not represent uniform volume. // .SECTION Warning // When using vtkGDCMPolyDataReader in conjonction with vtkGDCMImageReader // it is *required* that FileLowerLeft is set to ON as coordinate system // would be inconsistent in between the two data structures. // .SECTION Color Space mapping: // * VTK_LUMINANCE <-> MONOCHROME2 // * VTK_LUMINANCE_ALPHA <-> Not supported // * VTK_RGB <-> RGB // * VTK_RGBA <-> ARGB (deprecated, DICOM 2008) // * VTK_INVERSE_LUMINANCE <-> MONOCHROME1 // * VTK_LOOKUP_TABLE <-> PALETTE COLOR // * VTK_YBR <-> YBR_FULL // // For detailed information on color space transformation and true lossless transformation see: // http://gdcm.sourceforge.net/wiki/index.php/Color_Space_Transformations // .SECTION See Also // vtkMedicalImageReader2 vtkMedicalImageProperties vtkGDCMPolyDataReader vtkGDCMImageWriter // vtkDICOMImageReader #ifndef VTKGDCMIMAGEREADER_H #define VTKGDCMIMAGEREADER_H #include "vtkMedicalImageReader2.h" #include "vtkImageData.h" #include "vtkVersion.h" #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) #else class vtkMedicalImageProperties; #endif #if (VTK_MAJOR_VERSION > 5) || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) #else class vtkStringArray; #endif class vtkPolyData; // vtkSystemIncludes.h defines: // #define VTK_LUMINANCE 1 // #define VTK_LUMINANCE_ALPHA 2 // #define VTK_RGB 3 // #define VTK_RGBA 4 #ifndef VTK_INVERSE_LUMINANCE #define VTK_INVERSE_LUMINANCE 5 #endif #ifndef VTK_LOOKUP_TABLE #define VTK_LOOKUP_TABLE 6 #endif #ifndef VTK_YBR #define VTK_YBR 7 #endif #ifndef VTK_CMYK #define VTK_CMYK 8 #endif //BTX namespace gdcm { class ImageReader; } //ETX class vtkMatrix4x4; class VTK_EXPORT vtkGDCMImageReader : public vtkMedicalImageReader2 { public: static vtkGDCMImageReader *New(); vtkTypeMacro(vtkGDCMImageReader,vtkMedicalImageReader2); virtual void PrintSelf(ostream& os, vtkIndent indent); // Description: is the given file name a DICOM file containing an image ? virtual int CanReadFile(const char* fname); // Description: // Valid extensions virtual const char* GetFileExtensions() { // I would like to get rid of ACR/NEMA/IMA so only allow dcm extension for now return ".dcm .DCM"; } // Description: // A descriptive name for this format virtual const char* GetDescriptiveName() { return "DICOM"; } // Description: // Get the Image Position (Patient) as stored in the DICOM file // This is a read-only data member vtkGetObjectMacro(DirectionCosines, vtkMatrix4x4); #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) #else // Description: // Get the medical image properties object vtkGetObjectMacro(MedicalImageProperties, vtkMedicalImageProperties); #endif virtual void SetMedicalImageProperties(vtkMedicalImageProperties *pd); #if (VTK_MAJOR_VERSION > 5) || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) #else virtual void SetFileNames(vtkStringArray*); vtkGetObjectMacro(FileNames, vtkStringArray); #endif // Description: // Specifically request to load the overlay into the gdcm-VTK layer (gdcm always loads them when found). // If no overlay is found in the image, then the vtkImageData for the overlay will be empty. vtkGetMacro(LoadOverlays,int); vtkSetMacro(LoadOverlays,int); vtkBooleanMacro(LoadOverlays,int); // Description: // Set/Get whether or not to load the Icon as vtkImageData (if found in the DICOM file) vtkGetMacro(LoadIconImage,int); vtkSetMacro(LoadIconImage,int); vtkBooleanMacro(LoadIconImage,int); // Description: // Set/Get whether or not the image was compressed using a lossy compression algorithm vtkGetMacro(LossyFlag,int); vtkSetMacro(LossyFlag,int); vtkBooleanMacro(LossyFlag,int); // Description: // Read only: number of overlays as found in this image (multiple overlays per slice is allowed) // Only valid when LoadOverlays is true vtkGetMacro(NumberOfOverlays,int); // Description: // Read only: number of icon image (there can only be zero or one icon per file) // Only valid when LoadIconImage is true vtkGetMacro(NumberOfIconImages,int); // Description: // Get Overlay/IconImage // Remember to ALWAYS use those methods in your code, as the internal number for the output port // is not garantee to remain the same, as features are added to the reader #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) //FIXME: Need to get rid of BTX/ETX if only the Python Wrapper of VTK 4.2 would let me //BTX vtkAlgorithmOutput* GetOverlayPort(int index); vtkAlgorithmOutput* GetIconImagePort(); //ETX #endif vtkImageData* GetOverlay(int i); vtkImageData* GetIconImage(); // Description: // Load image with its associated Lookup Table vtkGetMacro(ApplyLookupTable,int); vtkSetMacro(ApplyLookupTable,int); vtkBooleanMacro(ApplyLookupTable,int); // Description: // Load image as YBR vtkGetMacro(ApplyYBRToRGB,int) vtkSetMacro(ApplyYBRToRGB,int) vtkBooleanMacro(ApplyYBRToRGB,int); // Description: // Return VTK_LUMINANCE, VTK_INVERSE_LUMINANCE, VTK_RGB, VTK_RGBA, VTK_LOOKUP_TABLE, VTK_YBR or VTK_CMYK // or 0 when ImageFormat is not handled. // Warning: For color image, PlanarConfiguration need to be taken into account. vtkGetMacro(ImageFormat,int); // Description: // Return the Planar Configuration. This simply means that the internal DICOM image was stored // using a particular planar configuration (most of the time: 0) // For monochrome image, PlanarConfiguration is always 0 vtkGetMacro(PlanarConfiguration,int); // Description: // Return the 'raw' information stored in the DICOM file: // In case of a series of multiple files, only the first file is considered. The Image Orientation (Patient) // is garantee to remain the same, and image Image Position (Patient) in other slice can be computed // using the ZSpacing (3rd dimension) // (0020,0032) DS [87.774866\-182.908510\168.629671] # 32, 3 ImagePositionPatient // (0020,0037) DS [0.001479\0.999989\-0.004376\-0.002039\-0.004372\-0.999988] # 58, 6 ImageOrientationPatient vtkGetVector3Macro(ImagePositionPatient,double); vtkGetVector6Macro(ImageOrientationPatient,double); // Description: // Set/Get the first Curve Data: vtkGetObjectMacro(Curve,vtkPolyData); virtual void SetCurve(vtkPolyData *pd); // Description: // \DEPRECATED: // Modality LUT // Value returned by GetShift/GetScale might be innacurate since Shift/Scale could be // varying along the Series read. Therefore user are advices not to use those functions // anymore vtkGetMacro(Shift,double); vtkGetMacro(Scale,double); protected: vtkGDCMImageReader(); ~vtkGDCMImageReader(); vtkSetVector6Macro(ImageOrientationPatient,double); //BTX void FillMedicalImageInformation(const gdcm::ImageReader &reader); //ETX int RequestInformationCompat(); int RequestDataCompat(); #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) int ProcessRequest(vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector); int RequestInformation(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector); int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector); #else /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/ void ExecuteInformation(); void ExecuteData(vtkDataObject *out); #endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/ protected: #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) #else // Description: // Medical Image properties vtkMedicalImageProperties *MedicalImageProperties; #endif #if (VTK_MAJOR_VERSION > 5) || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) #else vtkStringArray *FileNames; #endif vtkMatrix4x4 *DirectionCosines; int LoadOverlays; int NumberOfOverlays; int LoadIconImage; int NumberOfIconImages; int IconImageDataExtent[6]; double ImagePositionPatient[3]; double ImageOrientationPatient[6]; vtkPolyData *Curve; int ImageFormat; // the following 3, should remain optional int ApplyInverseVideo; int ApplyLookupTable; int ApplyYBRToRGB; // I think that planar configuration need to always be applied as far as VTK is concerned int ApplyPlanarConfiguration; int ApplyShiftScale; int LoadSingleFile(const char *filename, char *pointer, unsigned long &outlen); double Shift; double Scale; int IconDataScalarType; int IconNumberOfScalarComponents; int PlanarConfiguration; int LossyFlag; int ForceRescale; protected: // TODO / FIXME void SetFilePrefix(const char *) {} vtkGetStringMacro(FilePrefix); void SetFilePattern(const char *) {} vtkGetStringMacro(FilePattern); private: vtkGDCMImageReader(const vtkGDCMImageReader&); // Not implemented. void operator=(const vtkGDCMImageReader&); // Not implemented. }; #endif GDCM-3.0.10/Utilities/VTK/vtkGDCMImageReader2.cxx000066400000000000000000001325321412732066400210720ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageReader2.h" #include "vtkObjectFactory.h" #include "vtkImageData.h" #include "vtkErrorCode.h" #include "vtkMath.h" #include "vtkPolyData.h" #include "vtkCellArray.h" #include "vtkPoints.h" #include "vtkMedicalImageProperties.h" #include "vtkGDCMMedicalImageProperties.h" #include "vtkStringArray.h" #include "vtkPointData.h" #include "vtkLookupTable.h" #include "vtkWindowLevelLookupTable.h" #include "vtkLookupTable16.h" #include "vtkInformationVector.h" #include "vtkInformation.h" #include "vtkDemandDrivenPipeline.h" #include "vtkStreamingDemandDrivenPipeline.h" #include "vtkMatrix4x4.h" #include "vtkUnsignedCharArray.h" #include "vtkBitArray.h" #include "gdcmImageRegionReader.h" #include "gdcmDataElement.h" #include "gdcmByteValue.h" #include "gdcmSwapper.h" #include "gdcmUnpacker12Bits.h" #include "gdcmRescaler.h" #include "gdcmOrientation.h" #include "gdcmTrace.h" #include "gdcmImageChangePlanarConfiguration.h" #include "gdcmDirectoryHelper.h" #include "gdcmBoxRegion.h" #include //vtkCxxRevisionMacro(vtkGDCMImageReader2, "$Revision: 1.1 $") vtkStandardNewMacro(vtkGDCMImageReader2) static inline bool vtkGDCMImageReader2_IsCharTypeSigned() { #ifndef VTK_TYPE_CHAR_IS_SIGNED unsigned char uc = 255; return (*reinterpret_cast(&uc) < 0) ? true : false; #else return VTK_TYPE_CHAR_IS_SIGNED; #endif } // Output Ports are as follow: // #0: The image/volume (root PixelData element) // #1: (if present): the Icon Image (0088,0200) // #2-xx: (if present): the Overlay (60xx,3000) #define ICONIMAGEPORTNUMBER 1 #define OVERLAYPORTNUMBER 2 vtkCxxSetObjectMacro(vtkGDCMImageReader2,Curve,vtkPolyData) vtkCxxSetObjectMacro(vtkGDCMImageReader2,MedicalImageProperties,vtkMedicalImageProperties) //---------------------------------------------------------------------------- vtkGDCMImageReader2::vtkGDCMImageReader2() { this->DirectionCosines = vtkMatrix4x4::New(); this->DirectionCosines->Identity(); this->LoadOverlays = 1; this->LoadIconImage = 1; this->NumberOfOverlays = 0; this->NumberOfIconImages = 0; memset(this->IconImageDataExtent,0,6*sizeof(int)); this->ImageFormat = 0; // INVALID this->ApplyInverseVideo = 0; this->ApplyLookupTable = 0; this->ApplyYBRToRGB = 0; this->ApplyPlanarConfiguration = 1; this->ApplyShiftScale = 1; memset(this->ImagePositionPatient,0,3*sizeof(double)); memset(this->ImageOrientationPatient,0,6*sizeof(double)); this->Curve = 0; this->Shift = 0.; this->Scale = 1.; this->IconDataScalarType = VTK_CHAR; this->IconNumberOfScalarComponents = 1; this->PlanarConfiguration = 0; this->LossyFlag = 0; this->MedicalImageProperties->SetDirectionCosine(1,0,0,0,1,0); this->SetImageOrientationPatient(1,0,0,0,1,0); this->ForceRescale = 0; } //---------------------------------------------------------------------------- vtkGDCMImageReader2::~vtkGDCMImageReader2() { this->DirectionCosines->Delete(); if( this->Curve ) { this->Curve->Delete(); } } //---------------------------------------------------------------------------- int vtkGDCMImageReader2::CanReadFile(const char* fname) { gdcm::ImageReader reader; reader.SetFileName( fname ); if( !reader.Read() ) { return 0; } // 3 means: I might be able to read... return 3; } //---------------------------------------------------------------------------- int vtkGDCMImageReader2::ProcessRequest(vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector) { // generate the data if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) { return this->RequestData(request, inputVector, outputVector); } // execute information if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) { return this->RequestInformation(request, inputVector, outputVector); } return this->Superclass::ProcessRequest(request, inputVector, outputVector); } //---------------------------------------------------------------------------- void vtkGDCMImageReader2::FillMedicalImageInformation(const gdcm::ImageReader &reader) { const gdcm::File &file = reader.GetFile(); const gdcm::DataSet &ds = file.GetDataSet(); // $ grep "vtkSetString\|DICOM" vtkMedicalImageProperties.h // For ex: DICOM (0010,0010) = DOE,JOHN this->MedicalImageProperties->SetPatientName( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0010,0x0010), ds).c_str() ); // For ex: DICOM (0010,0020) = 1933197 this->MedicalImageProperties->SetPatientID( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0010,0x0020), ds).c_str() ); // For ex: DICOM (0010,1010) = 031Y this->MedicalImageProperties->SetPatientAge( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0010,0x1010), ds).c_str() ); // For ex: DICOM (0010,0040) = M this->MedicalImageProperties->SetPatientSex( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0010,0x0040), ds).c_str() ); // For ex: DICOM (0010,0030) = 19680427 this->MedicalImageProperties->SetPatientBirthDate( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0010,0x0030), ds).c_str() ); // For ex: DICOM (0008,0020) = 20030617 this->MedicalImageProperties->SetStudyDate( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0020), ds).c_str() ); // For ex: DICOM (0008,0022) = 20030617 this->MedicalImageProperties->SetAcquisitionDate( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0022), ds).c_str() ); // For ex: DICOM (0008,0030) = 162552.0705 or 230012, or 0012 this->MedicalImageProperties->SetStudyTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0030), ds).c_str() ); // For ex: DICOM (0008,0032) = 162552.0705 or 230012, or 0012 this->MedicalImageProperties->SetAcquisitionTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0032), ds).c_str() ); // For ex: DICOM (0008,0023) = 20030617 this->MedicalImageProperties->SetImageDate( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0023), ds).c_str() ); // For ex: DICOM (0008,0033) = 162552.0705 or 230012, or 0012 this->MedicalImageProperties->SetImageTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0033), ds).c_str() ); // For ex: DICOM (0020,0013) = 1 this->MedicalImageProperties->SetImageNumber( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0020,0x0013), ds).c_str() ); // For ex: DICOM (0020,0011) = 902 this->MedicalImageProperties->SetSeriesNumber( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0020,0x0011), ds).c_str() ); // For ex: DICOM (0008,103e) = SCOUT this->MedicalImageProperties->SetSeriesDescription( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x103e), ds).c_str() ); // For ex: DICOM (0020,0010) = 37481 this->MedicalImageProperties->SetStudyID( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0020,0x0010), ds).c_str() ); // For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL this->MedicalImageProperties->SetStudyDescription( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x1030), ds).c_str() ); // For ex: DICOM (0008,0060)= CT this->MedicalImageProperties->SetModality( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0060), ds).c_str() ); // For ex: DICOM (0008,0070) = Siemens this->MedicalImageProperties->SetManufacturer( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0070), ds).c_str() ); // For ex: DICOM (0008,1090) = LightSpeed QX/i this->MedicalImageProperties->SetManufacturerModelName( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x1090), ds).c_str() ); // For ex: DICOM (0008,1010) = LSPD_OC8 this->MedicalImageProperties->SetStationName( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x1010), ds).c_str() ); // For ex: DICOM (0008,0080) = FooCity Medical Center this->MedicalImageProperties->SetInstitutionName( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0080), ds).c_str() ); // For ex: DICOM (0018,1210) = Bone this->MedicalImageProperties->SetConvolutionKernel( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x1210), ds).c_str() ); // For ex: DICOM (0018,0050) = 0.273438 this->MedicalImageProperties->SetSliceThickness( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x0050), ds).c_str() ); // For ex: DICOM (0018,0060) = 120 this->MedicalImageProperties->SetKVP( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x0060), ds).c_str() ); // For ex: DICOM (0018,1120) = 15 this->MedicalImageProperties->SetGantryTilt( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x1120), ds).c_str() ); // For ex: DICOM (0018,0081) = 105 this->MedicalImageProperties->SetEchoTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x0081), ds).c_str() ); // For ex: DICOM (0018,0091) = 35 this->MedicalImageProperties->SetEchoTrainLength( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x0091), ds).c_str() ); // For ex: DICOM (0018,0080) = 2040 this->MedicalImageProperties->SetRepetitionTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x0080), ds).c_str() ); // For ex: DICOM (0018,1150) = 5 this->MedicalImageProperties->SetExposureTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x1150), ds).c_str() ); // For ex: DICOM (0018,1151) = 400 this->MedicalImageProperties->SetXRayTubeCurrent( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x1151), ds).c_str() ); // For ex: DICOM (0018,1152) = 114 this->MedicalImageProperties->SetExposure( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x1152), ds).c_str() ); // virtual void AddWindowLevelPreset(double w, double l); // (0028,1050) DS [ 498\ 498] # 12, 2 WindowCenter // (0028,1051) DS [ 1063\ 1063] # 12, 2 WindowWidth gdcm::Tag twindowcenter(0x0028,0x1050); gdcm::Tag twindowwidth(0x0028,0x1051); if( ds.FindDataElement( twindowcenter ) && ds.FindDataElement( twindowwidth) ) { const gdcm::DataElement& windowcenter = ds.GetDataElement( twindowcenter ); const gdcm::DataElement& windowwidth = ds.GetDataElement( twindowwidth ); const gdcm::ByteValue *bvwc = windowcenter.GetByteValue(); const gdcm::ByteValue *bvww = windowwidth.GetByteValue(); if( bvwc && bvww ) // Can be Type 2 { gdcm::Element elwc; std::stringstream ss1; std::string swc = std::string( bvwc->GetPointer(), bvwc->GetLength() ); ss1.str( swc ); gdcm::VR vr = gdcm::VR::DS; unsigned int vrsize = vr.GetSizeof(); unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swc.c_str(), (unsigned int)swc.size()); elwc.SetLength( count * vrsize ); elwc.Read( ss1 ); std::stringstream ss2; std::string sww = std::string( bvww->GetPointer(), bvww->GetLength() ); ss2.str( sww ); gdcm::Element elww; elww.SetLength( count * vrsize ); elww.Read( ss2 ); for(unsigned int i = 0; i < elwc.GetLength(); ++i) { this->MedicalImageProperties->AddWindowLevelPreset( elww.GetValue(i), elwc.GetValue(i) ); } } } gdcm::Tag twindowexplanation(0x0028,0x1055); if( ds.FindDataElement( twindowexplanation ) ) { const gdcm::DataElement& windowexplanation = ds.GetDataElement( twindowexplanation ); const gdcm::ByteValue *bvwe = windowexplanation.GetByteValue(); if( bvwe ) // Can be Type 2 { unsigned int n = this->MedicalImageProperties->GetNumberOfWindowLevelPresets(); gdcm::Element elwe; // window explanation gdcm::VR vr = gdcm::VR::LO; std::stringstream ss; ss.str( "" ); std::string swe = std::string( bvwe->GetPointer(), bvwe->GetLength() ); unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swe.c_str(), (unsigned int)swe.size()); (void)count; // I found a case with only one W/L but two comments: WINDOW1\WINDOW2 // SIEMENS-IncompletePixelData.dcm // oh wait but what if we have the countrary... //assert( count >= (unsigned int)n ); elwe.SetLength( count * vr.GetSizeof() ); ss.str( swe ); elwe.Read( ss ); unsigned int c = std::min(n, count); for(unsigned int i = 0; i < c; ++i) { this->MedicalImageProperties->SetNthWindowLevelPresetComment(i, elwe.GetValue(i).c_str() ); } } } // Add more info: vtkGDCMMedicalImageProperties *gdcmmip = dynamic_cast( this->MedicalImageProperties ); if( gdcmmip ) { gdcmmip->PushBackFile( file ); } } //---------------------------------------------------------------------------- int vtkGDCMImageReader2::RequestInformation(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) { (void)request; (void)inputVector; int res = RequestInformationCompat(); if( !res ) { vtkErrorMacro( "RequestInformationCompat failed: " << res ); this->SetErrorCode(vtkErrorCode::FileFormatError); return 0; } int numvol = 1; if( this->LoadIconImage ) { numvol = 2; } if( this->LoadOverlays ) { // If no icon found, we still need to be associated to port #2: numvol = 2 + this->NumberOfOverlays; } this->SetNumberOfOutputPorts(numvol); // For each output: for(int i = 0; i < numvol; ++i) { // Allocate ! if( !this->GetOutput(i) ) { vtkImageData *img = vtkImageData::New(); this->GetExecutive()->SetOutputData(i, img ); img->Delete(); } vtkInformation *outInfo = outputVector->GetInformationObject(i); switch(i) { // root Pixel Data case 0: outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->DataExtent, 6); //outInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), this->DataExtent, 6); outInfo->Set(vtkDataObject::SPACING(), this->DataSpacing, 3); #ifdef GDCMV2_0_COMPATIBILITY outInfo->Set(vtkDataObject::ORIGIN(), this->DataOrigin, 3); #endif vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->DataScalarType, this->NumberOfScalarComponents); break; // Icon Image case ICONIMAGEPORTNUMBER: outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->IconImageDataExtent, 6); vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->IconDataScalarType, this->IconNumberOfScalarComponents ); break; // Overlays: //case OVERLAYPORTNUMBER: default: outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->DataExtent[0], this->DataExtent[1], this->DataExtent[2], this->DataExtent[3], 0,0 ); vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 1); break; } } return 1; } static gdcm::PixelFormat::ScalarType ComputePixelTypeFromFiles(const char *inputfilename, vtkStringArray *filenames, gdcm::Image const & imageref) { gdcm::PixelFormat::ScalarType outputpt ; outputpt = gdcm::PixelFormat::UNKNOWN; // there is a very subtle bug here. Let's imagine we have a collection of files // they can all have different Rescale Slope / Intercept. In this case we should: // 1. Make sure to read each Rescale Slope / Intercept individually // 2. Make sure to decide which Pixel Type to use using *all* slices: if( inputfilename ) { const gdcm::Image &image = imageref; const gdcm::PixelFormat &pixeltype = image.GetPixelFormat(); double shift = image.GetIntercept(); double scale = image.GetSlope(); gdcm::Rescaler r; r.SetIntercept( shift ); r.SetSlope( scale ); r.SetPixelFormat( pixeltype ); outputpt = r.ComputeInterceptSlopePixelType(); } else if ( filenames && filenames->GetNumberOfValues() > 0 ) { std::set< gdcm::PixelFormat::ScalarType > pixeltypes; std::set< unsigned short > samplesperpixel; // FIXME a gdcm::Scanner would be much faster here: for(int i = 0; i < filenames->GetNumberOfValues(); ++i ) { const char *filename = filenames->GetValue( i ); gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { vtkGenericWarningMacro( "ImageReader failed: " << filename ); return gdcm::PixelFormat::UNKNOWN; } const gdcm::Image &image = reader.GetImage(); const gdcm::PixelFormat &pixeltype = image.GetPixelFormat(); samplesperpixel.insert( pixeltype.GetSamplesPerPixel() ); double shift = image.GetIntercept(); double scale = image.GetSlope(); gdcm::PixelFormat::ScalarType outputpt2 = pixeltype; gdcm::Rescaler r; r.SetIntercept( shift ); r.SetSlope( scale ); r.SetPixelFormat( pixeltype ); outputpt2 = r.ComputeInterceptSlopePixelType(); pixeltypes.insert( outputpt2 ); } if( pixeltypes.size() == 1 ) { assert( samplesperpixel.size() == 1 ); // Ok easy case outputpt = *pixeltypes.begin(); } else if( samplesperpixel.size() == 1 ) { // Hardcoded. If Pixel Type found is the maximum (as of PS 3.5 - 2008) // There is nothing bigger that FLOAT64 if( pixeltypes.count( gdcm::PixelFormat::FLOAT64 ) != 0 ) { outputpt = gdcm::PixelFormat::FLOAT64; } else { // should I just take the biggest value ? // MM: I am not sure UINT16 and INT16 are really compatible // so taking the biggest value might not be the solution // In this case we could use INT32, but FLOAT64 also works... // oh well, let's just use FLOAT64 always. vtkGenericWarningMacro( "This may not always be optimized. Sorry" ); outputpt = gdcm::PixelFormat::FLOAT64; } } else { vtkGenericWarningMacro( "Could not compute Pixel Type. Sorry" ); } } else { assert( 0 ); // I do not think this is possible } return outputpt; } //---------------------------------------------------------------------------- int vtkGDCMImageReader2::RequestInformationCompat() { // FIXME, need to implement the other modes too: if( this->ApplyLookupTable || this->ApplyYBRToRGB || this->ApplyInverseVideo ) { vtkErrorMacro( "ApplyLookupTable/ApplyYBRToRGB/ApplyInverseVideo not compatible" ); return 0; } // I do not think this is a good idea anyway to let the user decide // whether or not she wants *not* to apply shift/scale... if( !this->ApplyShiftScale ) { vtkErrorMacro("ApplyShiftScale not compatible" ); return 0; } // I do not think this one will ever be implemented: if( !this->ApplyPlanarConfiguration ) { vtkErrorMacro("ApplyPlanarConfiguration not compatible" ); return 0; } // Let's read the first file : const char *filename; if( this->FileName ) { filename = this->FileName; } else if ( this->FileNames && this->FileNames->GetNumberOfValues() > 0 ) { filename = this->FileNames->GetValue( 0 ); } else { // hey! I need at least one file to schew on ! vtkErrorMacro( "You did not specify any filenames" ); return 0; } #if 0 gdcm::ImageRegionReader reader; reader.SetFileName( filename ); if( !reader.ReadInformation() ) #else gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) #endif { vtkErrorMacro( "ImageReader failed on " << filename ); return 0; } const gdcm::Image &image = reader.GetImage(); this->LossyFlag = image.IsLossy(); const unsigned int *dims = image.GetDimensions(); // Set the Extents. assert( image.GetNumberOfDimensions() >= 2 ); this->DataExtent[0] = 0; this->DataExtent[1] = dims[0] - 1; this->DataExtent[2] = 0; this->DataExtent[3] = dims[1] - 1; if( image.GetNumberOfDimensions() == 2 ) { // This is just so much painful to deal with DICOM / VTK // they simply assume that number of file is equal to the dimension // of the last axe (see vtkImageReader2::SetFileNames ) if ( this->FileNames && this->FileNames->GetNumberOfValues() > 1 ) { this->DataExtent[4] = 0; } else { this->DataExtent[4] = 0; this->DataExtent[5] = 0; } } else { assert( image.GetNumberOfDimensions() == 3 ); this->FileDimensionality = 3; this->DataExtent[4] = 0; this->DataExtent[5] = dims[2] - 1; } gdcm::MediaStorage ms; ms.SetFromFile( reader.GetFile() ); assert( gdcm::MediaStorage::IsImage( ms ) ); const double *spacing = image.GetSpacing(); if( spacing ) { this->DataSpacing[0] = spacing[0]; this->DataSpacing[1] = spacing[1]; this->DataSpacing[2] = image.GetSpacing(2); } const double *origin = image.GetOrigin(); if( origin ) { this->ImagePositionPatient[0] = image.GetOrigin(0); this->ImagePositionPatient[1] = image.GetOrigin(1); this->ImagePositionPatient[2] = image.GetOrigin(2); } const double *dircos = image.GetDirectionCosines(); if( dircos ) { this->DirectionCosines->SetElement(0,0, dircos[0]); this->DirectionCosines->SetElement(1,0, dircos[1]); this->DirectionCosines->SetElement(2,0, dircos[2]); this->DirectionCosines->SetElement(3,0, 0); this->DirectionCosines->SetElement(0,1, dircos[3]); this->DirectionCosines->SetElement(1,1, dircos[4]); this->DirectionCosines->SetElement(2,1, dircos[5]); this->DirectionCosines->SetElement(3,1, 0); double dircosz[3]; vtkMath::Cross(dircos, dircos+3, dircosz); this->DirectionCosines->SetElement(0,2, dircosz[0]); this->DirectionCosines->SetElement(1,2, dircosz[1]); this->DirectionCosines->SetElement(2,2, dircosz[2]); this->DirectionCosines->SetElement(3,2, 0); for(int i=0;i<6;++i) this->ImageOrientationPatient[i] = dircos[i]; this->MedicalImageProperties->SetDirectionCosine( this->ImageOrientationPatient ); } // Apply transform: #ifdef GDCMV2_0_COMPATIBILITY if( dircos && origin ) { if( this->FileLowerLeft ) { // Since we are not doing the VTK Y-flipping operation, Origin and Image Position (Patient) // are the same: this->DataOrigin[0] = origin[0]; this->DataOrigin[1] = origin[1]; this->DataOrigin[2] = origin[2]; } else { // We are doing the Y-flip: // translate Image Position (Patient) along the Y-vector of the Image Orientation (Patient): // Step 1: Compute norm of translation vector: // Because position is in the center of the pixel, we need to substract 1 to the dimY: assert( dims[1] >=1 ); double norm = (dims[1] - 1) * this->DataSpacing[1]; // Step 2: translate: this->DataOrigin[0] = origin[0] + norm * dircos[3+0]; this->DataOrigin[1] = origin[1] + norm * dircos[3+1]; this->DataOrigin[2] = origin[2] + norm * dircos[3+2]; } } // Need to set the rest to 0 ??? #endif const gdcm::PixelFormat &pixeltype = image.GetPixelFormat(); this->Shift = image.GetIntercept(); this->Scale = image.GetSlope(); gdcm::PixelFormat::ScalarType outputpt = ComputePixelTypeFromFiles(this->FileName, this->FileNames, image); if( this->FileName ) { // We should test that outputpt is 8 when BitsAllocated = 16 / Bits Stored = 8 // BUT we should test that output is 16 when BitsAllocated = 16 / BitsStored = 12 // assert( outputpt == pixeltype ); } this->ForceRescale = 0; // always reset this thing // gdcmData/DCMTK_JPEGExt_12Bits.dcm if( pixeltype != outputpt && pixeltype.GetBitsAllocated() != 12 ) { this->ForceRescale = 1; } switch( outputpt ) { case gdcm::PixelFormat::INT8: this->DataScalarType = VTK_SIGNED_CHAR; break; case gdcm::PixelFormat::UINT8: this->DataScalarType = VTK_UNSIGNED_CHAR; break; case gdcm::PixelFormat::INT16: this->DataScalarType = VTK_SHORT; break; case gdcm::PixelFormat::UINT16: this->DataScalarType = VTK_UNSIGNED_SHORT; break; // RT / SC have 32bits case gdcm::PixelFormat::INT32: this->DataScalarType = VTK_INT; break; case gdcm::PixelFormat::UINT32: this->DataScalarType = VTK_UNSIGNED_INT; break; case gdcm::PixelFormat::INT12: this->DataScalarType = VTK_SHORT; break; case gdcm::PixelFormat::UINT12: this->DataScalarType = VTK_UNSIGNED_SHORT; break; //case gdcm::PixelFormat::FLOAT16: // TODO case gdcm::PixelFormat::FLOAT32: this->DataScalarType = VTK_FLOAT; break; case gdcm::PixelFormat::FLOAT64: this->DataScalarType = VTK_DOUBLE; break; case gdcm::PixelFormat::SINGLEBIT: this->DataScalarType = VTK_BIT; break; default: this->SetErrorCode(vtkErrorCode::FileFormatError); vtkErrorMacro( "Do not support this Pixel Type: " << (int)pixeltype.GetScalarType() << " with " << (int)outputpt ); return 0; } this->NumberOfScalarComponents = pixeltype.GetSamplesPerPixel(); // Ok let's fill in the 'extra' info: this->FillMedicalImageInformation(reader); // Do the IconImage if requested: const gdcm::IconImage& icon = image.GetIconImage(); if( this->LoadIconImage && !icon.IsEmpty() ) { this->IconImageDataExtent[0] = 0; this->IconImageDataExtent[1] = icon.GetColumns() - 1; this->IconImageDataExtent[2] = 0; this->IconImageDataExtent[3] = icon.GetRows() - 1; // const gdcm::PixelFormat &iconpixelformat = icon.GetPixelFormat(); switch(iconpixelformat) { case gdcm::PixelFormat::INT8: this->IconDataScalarType = VTK_SIGNED_CHAR; break; case gdcm::PixelFormat::UINT8: this->IconDataScalarType = VTK_UNSIGNED_CHAR; break; case gdcm::PixelFormat::INT16: this->IconDataScalarType = VTK_SHORT; break; case gdcm::PixelFormat::UINT16: this->IconDataScalarType = VTK_UNSIGNED_SHORT; break; default: vtkErrorMacro( "Do not support this Icon Pixel Type: " << (int)iconpixelformat.GetScalarType() ); return 0; } this->IconNumberOfScalarComponents = iconpixelformat.GetSamplesPerPixel(); } // Overlay! size_t numoverlays = image.GetNumberOfOverlays(); if( this->LoadOverlays && numoverlays ) { // Do overlay specific stuff... // what if overlay do not have the same data extent as image ? for( unsigned int ovidx = 0; ovidx < numoverlays; ++ovidx ) { const gdcm::Overlay& ov = image.GetOverlay(ovidx); assert( (unsigned int)ov.GetRows() == image.GetRows() ); (void)ov; assert( (unsigned int)ov.GetColumns() == image.GetColumns() ); } this->NumberOfOverlays = (int)numoverlays; } return 1; } //---------------------------------------------------------------------------- template static inline unsigned long vtkImageDataGetTypeSize(T*, int a = 0, int b = 0) { (void)a;(void)b; return sizeof(T); } //---------------------------------------------------------------------------- static void InPlaceYFlipImage2(vtkImageData* data, const int dext[6]) { unsigned long outsize = data->GetNumberOfScalarComponents(); if( dext[1] == dext[0] && dext[0] == 0 ) return; // Multiply by the number of bytes per scalar switch (data->GetScalarType()) { case VTK_BIT: { outsize /= 8; }; break; vtkTemplateMacro( outsize *= vtkImageDataGetTypeSize(static_cast(0)) ); default: //vtkErrorMacro("do not support scalar type: " << data->GetScalarType() ); assert(0); } outsize *= (dext[1] - dext[0] + 1); char * ref = static_cast(data->GetScalarPointer()); char * pointer = static_cast(data->GetScalarPointer()); assert( pointer ); char *line = new char[outsize]; for(int j = dext[4]; j <= dext[5]; ++j) { char *start = pointer; /* assert( start == ref + j * outsize * (dext[3] - dext[2] + 1) ); (void)ref; */ // Swap two-lines at a time // when Rows is odd number (359) then dext[3] == 178 // so we should avoid copying the line right in the center of the image // since memcpy does not like copying on itself... for(int i = dext[2]; i < (dext[3]+1) / 2; ++i) { // image: char * end = start+(dext[3] - i)*outsize; assert( (end - pointer) >= (int)outsize ); memcpy(line,end,outsize); // duplicate line memcpy(end,pointer,outsize); memcpy(pointer,line,outsize); pointer += outsize; } // because the for loop iterated only over 1/2 all lines, skip to the next slice: assert( dext[2] == 0 ); pointer += (dext[3] + 1 - (dext[3]+1)/2 )*outsize; } // Did we reach the end ? assert( pointer == ref + (dext[5]-dext[4]+1)*(dext[3]-dext[2]+1)*outsize ); delete[] line; } //---------------------------------------------------------------------------- int vtkGDCMImageReader2::LoadSingleFile(const char *filename, char *pointer, unsigned long &outlen) { int *dext = this->GetDataExtent(); vtkImageData *data = this->GetOutput(0); int outExt[6]; data->GetExtent(outExt); gdcm::ImageRegionReader reader; reader.SetFileName( filename ); if( !reader.ReadInformation() ) { vtkErrorMacro( "ImageRegionReader failed: " << filename ); return 0; } #if 0 // TODO could check compat: std::vector dims = gdcm::ImageHelper::GetDimensionsValue(reader.GetFile()); #endif const bool assume2d = this->FileNames && this->FileNames->GetNumberOfValues() >= 1; gdcm::BoxRegion box; if( assume2d ) box.SetDomain(outExt[0], outExt[1], outExt[2], outExt[3], 0, 0); else box.SetDomain(outExt[0], outExt[1], outExt[2], outExt[3], outExt[4], outExt[5]); reader.SetRegion( box ); gdcm::Image &image = reader.GetImage(); this->LossyFlag = image.IsLossy(); //VTK does not cope with Planar Configuration, so let's schew the work to please it assert( this->PlanarConfiguration == 0 || this->PlanarConfiguration == 1 ); // Store the PlanarConfiguration before inverting it ! this->PlanarConfiguration = image.GetPlanarConfiguration(); //assert( this->PlanarConfiguration == 0 || this->PlanarConfiguration == 1 ); if( image.GetPlanarConfiguration() == 1 ) { vtkErrorMacro( "vtkGDCMImageReader2 does not handle Planar Configuration: " << filename ); return 0; } const gdcm::PixelFormat &pixeltype = image.GetPixelFormat(); assert( image.GetNumberOfDimensions() == 2 || image.GetNumberOfDimensions() == 3 ); /* unsigned long len = image.GetBufferLength(); */ unsigned long len = reader.ComputeBufferLength(); outlen = len; unsigned long overlaylen = 0; // HACK: Make sure that Shift/Scale are the one from the file: this->Shift = image.GetIntercept(); this->Scale = image.GetSlope(); if( (this->Scale != 1.0 || this->Shift != 0.0) || this->ForceRescale ) { assert( pixeltype.GetSamplesPerPixel() == 1 ); gdcm::Rescaler r; r.SetIntercept( Shift ); // FIXME r.SetSlope( Scale ); // FIXME gdcm::PixelFormat::ScalarType targetpixeltype = gdcm::PixelFormat::UNKNOWN; // r.SetTargetPixelType( gdcm::PixelFormat::FLOAT64 ); int scalarType = data->GetScalarType(); switch( scalarType ) { case VTK_CHAR: if( vtkGDCMImageReader2_IsCharTypeSigned() ) targetpixeltype = gdcm::PixelFormat::INT8; else targetpixeltype = gdcm::PixelFormat::UINT8; break; case VTK_SIGNED_CHAR: targetpixeltype = gdcm::PixelFormat::INT8; break; case VTK_UNSIGNED_CHAR: targetpixeltype = gdcm::PixelFormat::UINT8; break; case VTK_SHORT: targetpixeltype = gdcm::PixelFormat::INT16; break; case VTK_UNSIGNED_SHORT: targetpixeltype = gdcm::PixelFormat::UINT16; break; case VTK_INT: targetpixeltype = gdcm::PixelFormat::INT32; break; case VTK_UNSIGNED_INT: targetpixeltype = gdcm::PixelFormat::UINT32; break; case VTK_FLOAT: targetpixeltype = gdcm::PixelFormat::FLOAT32; break; case VTK_DOUBLE: targetpixeltype = gdcm::PixelFormat::FLOAT64; break; case VTK_BIT: targetpixeltype = gdcm::PixelFormat::SINGLEBIT; break; default: vtkErrorMacro( "Do not support this Pixel Type: " << scalarType ); assert( 0 ); return 0; } r.SetTargetPixelType( targetpixeltype ); r.SetUseTargetPixelType(true); r.SetPixelFormat( pixeltype ); char * copy = new char[len]; /*image.GetBuffer(copy);*/ bool b = reader.ReadIntoBuffer(copy, len); assert( b ); if( !r.Rescale(pointer,copy,len) ) { delete[] copy; vtkErrorMacro( "Could not Rescale" ); // problem with gdcmData/3E768EB7.dcm return 0; } delete[] copy; // WARNING: sizeof(Real World Value) != sizeof(Stored Pixel) outlen = data->GetScalarSize() * data->GetNumberOfPoints() / data->GetDimensions()[2]; assert( data->GetNumberOfScalarComponents() == 1 ); } else { /* image.GetBuffer(pointer); */ bool b = reader.ReadIntoBuffer(pointer, len); if( !b ) { vtkErrorMacro( "Could not ReadIntoBuffer" ); return 0; } } // Do the Icon Image: if( this->LoadIconImage ) { this->NumberOfIconImages = image.GetIconImage().IsEmpty() ? 0 : 1; if( this->NumberOfIconImages ) { char * iconpointer = static_cast(this->GetOutput(ICONIMAGEPORTNUMBER)->GetScalarPointer()); assert( iconpointer ); image.GetIconImage().GetBuffer( iconpointer ); if ( image.GetIconImage().GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::PALETTE_COLOR ) { const gdcm::LookupTable &lut = image.GetIconImage().GetLUT(); assert( lut.GetBitSample() == 8 ); { vtkLookupTable *vtklut = vtkLookupTable::New(); vtklut->SetNumberOfTableValues(256); // SOLVED: GetPointer(0) is skrew up, need to replace it with WritePointer(0,4) ... if( !lut.GetBufferAsRGBA( vtklut->WritePointer(0,4) ) ) { vtkWarningMacro( "Could not get values from LUT" ); return 0; } vtklut->SetRange(0,255); this->GetOutput(ICONIMAGEPORTNUMBER)->GetPointData()->GetScalars()->SetLookupTable( vtklut ); vtklut->Delete(); } } } } // Do the Curve: size_t numcurves = image.GetNumberOfCurves(); if( numcurves ) { const gdcm::Curve& curve = image.GetCurve(); vtkPoints * pts = vtkPoints::New(); pts->SetNumberOfPoints( curve.GetNumberOfPoints() ); curve.GetAsPoints( (float*)pts->GetVoidPointer(0) ); vtkCellArray *polys = vtkCellArray::New(); for(unsigned int i = 0; i < curve.GetNumberOfPoints(); i+=2 ) { polys->InsertNextCell(2); polys->InsertCellPoint(i); polys->InsertCellPoint(i+1); } vtkPolyData *cube = vtkPolyData::New(); cube->SetPoints(pts); pts->Delete(); cube->SetLines(polys); polys->Delete(); SetCurve(cube); cube->Delete(); } // Do the Overlay: if( this->LoadOverlays ) { size_t numoverlays = image.GetNumberOfOverlays(); long overlayoutsize = (dext[1] - dext[0] + 1); if( !this->LoadOverlays ) assert( this->NumberOfOverlays == 0 ); for( int ovidx = 0; ovidx < this->NumberOfOverlays; ++ovidx ) { vtkImageData *vtkimage = this->GetOutput(OVERLAYPORTNUMBER + ovidx); // vtkOpenGLImageMapper::RenderData does not support bit array (since OpenGL does not either) // we have to decompress the bit overlay into an unsigned char array to please everybody: const gdcm::Overlay& ov1 = image.GetOverlay(ovidx); vtkUnsignedCharArray *chararray = vtkUnsignedCharArray::New(); chararray->SetNumberOfTuples( overlayoutsize * ( dext[3] - dext[2] + 1 ) ); overlaylen = overlayoutsize * ( dext[3] - dext[2] + 1 ); assert( (unsigned long)ov1.GetRows()*ov1.GetColumns() <= overlaylen ); const signed short *origin = ov1.GetOrigin(); if( (unsigned long)ov1.GetRows()*ov1.GetColumns() != overlaylen ) { vtkWarningMacro( "vtkImageData Overlay have an extent that do not match the one of the image" ); } if( origin[0] != 1 || origin[1] != 1 ) { // Table C.9-2 OVERLAY PLANE MODULE ATTRIBUTES vtkWarningMacro( "Overlay with origin are not supported right now" ); } vtkimage->GetPointData()->SetScalars( chararray ); vtkimage->GetPointData()->GetScalars()->SetName( ov1.GetDescription() ); chararray->Delete(); assert( vtkimage->GetScalarType() == VTK_UNSIGNED_CHAR ); char * overlaypointer = static_cast(vtkimage->GetScalarPointer()); assert( overlaypointer ); if( !ov1.GetUnpackBuffer( overlaypointer, overlaylen ) ) { vtkErrorMacro( "Problem in GetUnpackBuffer" ); } } if( numoverlays ) assert( (unsigned long)overlayoutsize * ( dext[3] - dext[2] + 1 ) == overlaylen ); } // Do the LUT if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::PALETTE_COLOR ) { this->ImageFormat = VTK_LOOKUP_TABLE; const gdcm::LookupTable &lut = image.GetLUT(); if( lut.GetBitSample() == 8 ) { vtkLookupTable *vtklut = vtkLookupTable::New(); vtklut->SetNumberOfTableValues(256); // SOLVED: GetPointer(0) is skrew up, need to replace it with WritePointer(0,4) ... if( !lut.GetBufferAsRGBA( vtklut->WritePointer(0,4) ) ) { vtkWarningMacro( "Could not get values from LUT" ); return 0; } vtklut->SetRange(0,255); data->GetPointData()->GetScalars()->SetLookupTable( vtklut ); vtklut->Delete(); } else { assert( lut.GetBitSample() == 16 ); vtkLookupTable16 *vtklut = vtkLookupTable16::New(); vtklut->SetNumberOfTableValues(256*256); // SOLVED: GetPointer(0) is skrew up, need to replace it with WritePointer(0,4) ... if( !lut.GetBufferAsRGBA( (unsigned char*)vtklut->WritePointer(0,4) ) ) { vtkWarningMacro( "Could not get values from LUT" ); return 0; } vtklut->SetRange(0,256*256-1); data->GetPointData()->GetScalars()->SetLookupTable( vtklut ); vtklut->Delete(); } } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 ) { this->ImageFormat = VTK_INVERSE_LUMINANCE; vtkWindowLevelLookupTable *vtklut = vtkWindowLevelLookupTable::New(); // Technically we could also use the first of the Window Width / Window Center // oh well, if they are missing let's just compute something: const double min = (double)pixeltype.GetMin(); const double max = (double)pixeltype.GetMax(); vtklut->SetWindow( max - min ); vtklut->SetLevel( 0.5 * (max + min) ); //vtklut->SetWindow(1024); // WindowWidth //vtklut->SetLevel(550); // WindowCenter vtklut->InverseVideoOn(); data->GetPointData()->GetScalars()->SetLookupTable( vtklut ); vtklut->Delete(); } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::YBR_FULL_422 ) { this->ImageFormat = VTK_YBR; } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::YBR_FULL ) { this->ImageFormat = VTK_YBR; } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::RGB ) { this->ImageFormat = VTK_RGB; } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ) { this->ImageFormat = VTK_LUMINANCE; } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::YBR_RCT ) { this->ImageFormat = VTK_RGB; } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::YBR_ICT ) { this->ImageFormat = VTK_RGB; } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::CMYK ) { this->ImageFormat = VTK_CMYK; } else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::ARGB ) { this->ImageFormat = VTK_RGBA; } else { // HSV / CMYK ??? // let's just give up for now vtkErrorMacro( "Does not handle: " << image.GetPhotometricInterpretation().GetString() ); //return 0; } //assert( this->ImageFormat ); long outsize; if( data->GetScalarType() == VTK_BIT ) { outsize = (dext[1] - dext[0] + 1) / 8; } else { outsize = pixeltype.GetPixelSize()*(dext[1] - dext[0] + 1); } if( this->FileName ) { assert( (unsigned long)outsize * (outExt[3] - outExt[2]+1) * (outExt[5] - outExt[4]+1) == len ); } return 1; // success } //---------------------------------------------------------------------------- int vtkGDCMImageReader2::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) { // Make sure the output dimension is OK, and allocate its scalars for(int i = 0; i < this->GetNumberOfOutputPorts(); ++i) { vtkInformation* outInfo = outputVector->GetInformationObject(i); vtkImageData *data = static_cast(outInfo->Get(vtkDataObject::DATA_OBJECT())); // Make sure that this output is an image if (data) { int extent[6]; outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent); this->AllocateOutputData(data, outInfo, extent); } } int res = RequestDataCompat(); return res; } //---------------------------------------------------------------------------- int vtkGDCMImageReader2::RequestDataCompat() { vtkImageData *output = this->GetOutput(0); output->GetPointData()->GetScalars()->SetName("GDCMImage"); // The outExt is the allocated data extent int outExt[6]; output->GetExtent(outExt); // The dext is the whole extent (includes not-loaded data) int *dext = this->GetDataExtent(); (void)dext; char * pointer = static_cast(output->GetScalarPointerForExtent(outExt)); if( this->FileName ) { const char *filename = this->FileName; unsigned long len; int load = this->LoadSingleFile( filename, pointer, len ); (void)len; if( !load ) { // FIXME: I need to fill the buffer with 0, shouldn't I ? return 0; } } else if( this->FileNames && this->FileNames->GetNumberOfValues() >= 1 ) { // Load each 2D files // HACK: len is moved out of the loop so that when file > 1 start failing we can still know // the len of the buffer...technically all files should have the same len (not checked for now) unsigned long len = 0; for(int j = outExt[4]; !this->AbortExecute && j <= outExt[5]; ++j) { assert( j >= 0 && j <= this->FileNames->GetNumberOfValues() ); const char *filename = this->FileNames->GetValue( j ); int load = this->LoadSingleFile( filename, pointer, len ); vtkDebugMacro( "LoadSingleFile: " << filename ); if( !load ) { // hum... we could not read this file within the series, let's just fill // the slice with 0 value, hopefully this should be the right thing to do memset( pointer, 0, len); } assert( len ); pointer += len; this->UpdateProgress( (double)(j - outExt[4] ) / ( outExt[5] - outExt[4] )); } } else { return 0; } // Y-flip image if (!this->FileLowerLeft) { InPlaceYFlipImage2(this->GetOutput(0), outExt); if( this->LoadIconImage ) { int *iiext = this->IconImageDataExtent; InPlaceYFlipImage2(this->GetOutput(ICONIMAGEPORTNUMBER), iiext); } for( int ovidx = 0; ovidx < this->NumberOfOverlays; ++ovidx ) { assert( this->LoadOverlays ); int oext[6]; this->GetDataExtent(oext); oext[4] = 0; oext[5] = 0; InPlaceYFlipImage2(this->GetOutput(OVERLAYPORTNUMBER+ovidx), oext); } } return 1; } //---------------------------------------------------------------------------- vtkAlgorithmOutput* vtkGDCMImageReader2::GetOverlayPort(int index) { if( index >= 0 && index < this->NumberOfOverlays) return this->GetOutputPort(index+OVERLAYPORTNUMBER); return NULL; } //---------------------------------------------------------------------------- vtkAlgorithmOutput* vtkGDCMImageReader2::GetIconImagePort() { const int index = 0; if( index >= 0 && index < this->NumberOfIconImages) return this->GetOutputPort(index+ICONIMAGEPORTNUMBER); return NULL; } //---------------------------------------------------------------------------- vtkImageData* vtkGDCMImageReader2::GetOverlay(int i) { if( i >= 0 && i < this->NumberOfOverlays) return this->GetOutput(i+OVERLAYPORTNUMBER); return NULL; } //---------------------------------------------------------------------------- vtkImageData* vtkGDCMImageReader2::GetIconImage() { const int i = 0; if( i >= 0 && i < this->NumberOfIconImages) return this->GetOutput(i+ICONIMAGEPORTNUMBER); return NULL; } //---------------------------------------------------------------------------- void vtkGDCMImageReader2::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } GDCM-3.0.10/Utilities/VTK/vtkGDCMImageReader2.h000066400000000000000000000242371412732066400205210ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // .NAME vtkGDCMImageReader2 - read DICOM Image files (Pixel Data) // .SECTION Description // vtkGDCMImageReader2 is a source object that reads some DICOM files // this reader is single threaded. // .SECTION Implementation note: when FileLowerLeft is set to on the image is not flipped // upside down as VTK would expect, use this option only if you know what you are doing. // .SECTION Implementation note: when reading a series of 2D slices, user is // expected to provide an ordered list of filenames. No sorting will be applied afterward. // .SECTION Implementation note: Although 99% of the time the Zspacing as read // from a tag in a 2D DICOM file should be correct, there has been reports that this // value can be missing, or incorrect, in which case users are advised to override this // value using the return value from gdcm::IPPSorter::GetZSpacing() and set it via // vtkImageChangeInformation on the reader itself. // .SECTION TODO // This reader does not handle a series of 3D images, only a single 3D (multi frame) or a // list of 2D files are supported for now. // .SECTION TODO // Did not implement SetFilePattern / SetFilePrefix API, move it to protected section for now. // .SECTION BUG // Overlay are assumed to have the same extent as image. Right now if overlay origin is not // 0,0 the overlay will have an offset... // Only the very first overlay is loaded at the VTK level, for now (even if there are more than one in the file) // .SECTION DataOrigin // When the reader is instanciated with FileLowerLeftOn the DataOrigin and Image Position (Patient) are // identical. But when FileLowerLeft is Off, we have to reorder the Y-line of the image, and thus the DataOrigin // is then translated to the other side of the image. // .SECTION Spacing // When reading a 3D volume, the spacing along the Z dimension might be negative (so as to respect up-side-down) // as specified in the Image Orientation (Patient) tag. When Z-spacing is 0, this means the multi-frame object // contains image which do not represent uniform volume. // .SECTION Warning // When using vtkGDCMPolyDataReader in conjonction with vtkGDCMImageReader2 // it is *required* that FileLowerLeft is set to ON as coordinate system // would be inconsistent in between the two data structures. // .SECTION Color Space mapping: // * VTK_LUMINANCE <-> MONOCHROME2 // * VTK_LUMINANCE_ALPHA <-> Not supported // * VTK_RGB <-> RGB // * VTK_RGBA <-> ARGB (deprecated, DICOM 2008) // * VTK_INVERSE_LUMINANCE <-> MONOCHROME1 // * VTK_LOOKUP_TABLE <-> PALETTE COLOR // * VTK_YBR <-> YBR_FULL // // For detailed information on color space transformation and true lossless transformation see: // http://gdcm.sourceforge.net/wiki/index.php/Color_Space_Transformations // .SECTION See Also // vtkMedicalImageReader2 vtkMedicalImageProperties vtkGDCMPolyDataReader vtkGDCMImageWriter // vtkDICOMImageReader #ifndef VTKGDCMIMAGEREADER2_H #define VTKGDCMIMAGEREADER2_H #include "vtkMedicalImageReader2.h" #include "vtkImageData.h" class vtkPolyData; // vtkSystemIncludes.h defines: // #define VTK_LUMINANCE 1 // #define VTK_LUMINANCE_ALPHA 2 // #define VTK_RGB 3 // #define VTK_RGBA 4 #ifndef VTK_INVERSE_LUMINANCE #define VTK_INVERSE_LUMINANCE 5 #endif #ifndef VTK_LOOKUP_TABLE #define VTK_LOOKUP_TABLE 6 #endif #ifndef VTK_YBR #define VTK_YBR 7 #endif #ifndef VTK_CMYK #define VTK_CMYK 8 #endif //BTX namespace gdcm { class ImageReader; } //ETX class vtkMatrix4x4; class VTK_EXPORT vtkGDCMImageReader2 : public vtkMedicalImageReader2 { public: static vtkGDCMImageReader2 *New(); vtkTypeMacro(vtkGDCMImageReader2,vtkMedicalImageReader2); virtual void PrintSelf(ostream& os, vtkIndent indent); // Description: is the given file name a DICOM file containing an image ? virtual int CanReadFile(const char* fname); // Description: // Valid extensions virtual const char* GetFileExtensions() { // I would like to get rid of ACR/NEMA/IMA so only allow dcm extension for now return ".dcm .DCM"; } // Description: // A descriptive name for this format virtual const char* GetDescriptiveName() { return "DICOM"; } // Description: // Get the Image Position (Patient) as stored in the DICOM file // This is a read-only data member vtkGetObjectMacro(DirectionCosines, vtkMatrix4x4); virtual void SetMedicalImageProperties(vtkMedicalImageProperties *pd); // Description: // Specifically request to load the overlay into the gdcm-VTK layer (gdcm always loads them when found). // If no overlay is found in the image, then the vtkImageData for the overlay will be empty. vtkGetMacro(LoadOverlays,int); vtkSetMacro(LoadOverlays,int); vtkBooleanMacro(LoadOverlays,int); // Description: // Set/Get whether or not to load the Icon as vtkImageData (if found in the DICOM file) vtkGetMacro(LoadIconImage,int); vtkSetMacro(LoadIconImage,int); vtkBooleanMacro(LoadIconImage,int); // Description: // Set/Get whether or not the image was compressed using a lossy compression algorithm vtkGetMacro(LossyFlag,int); vtkSetMacro(LossyFlag,int); vtkBooleanMacro(LossyFlag,int); // Description: // Read only: number of overlays as found in this image (multiple overlays per slice is allowed) // Only valid when LoadOverlays is true vtkGetMacro(NumberOfOverlays,int); // Description: // Read only: number of icon image (there can only be zero or one icon per file) // Only valid when LoadIconImage is true vtkGetMacro(NumberOfIconImages,int); // Description: // Get Overlay/IconImage // Remember to ALWAYS use those methods in your code, as the internal number for the output port // is not garantee to remain the same, as features are added to the reader vtkAlgorithmOutput* GetOverlayPort(int index); vtkAlgorithmOutput* GetIconImagePort(); vtkImageData* GetOverlay(int i); vtkImageData* GetIconImage(); // Description: // Load image with its associated Lookup Table vtkGetMacro(ApplyLookupTable,int); vtkSetMacro(ApplyLookupTable,int); vtkBooleanMacro(ApplyLookupTable,int); // Description: // Load image as YBR vtkGetMacro(ApplyYBRToRGB,int) vtkSetMacro(ApplyYBRToRGB,int) vtkBooleanMacro(ApplyYBRToRGB,int); // Description: // Return VTK_LUMINANCE, VTK_INVERSE_LUMINANCE, VTK_RGB, VTK_RGBA, VTK_LOOKUP_TABLE, VTK_YBR or VTK_CMYK // or 0 when ImageFormat is not handled. // Warning: For color image, PlanarConfiguration need to be taken into account. vtkGetMacro(ImageFormat,int); // Description: // Return the Planar Configuration. This simply means that the internal DICOM image was stored // using a particular planar configuration (most of the time: 0) // For monochrome image, PlanarConfiguration is always 0 vtkGetMacro(PlanarConfiguration,int); // Description: // Return the 'raw' information stored in the DICOM file: // In case of a series of multiple files, only the first file is considered. The Image Orientation (Patient) // is garantee to remain the same, and image Image Position (Patient) in other slice can be computed // using the ZSpacing (3rd dimension) // (0020,0032) DS [87.774866\-182.908510\168.629671] # 32, 3 ImagePositionPatient // (0020,0037) DS [0.001479\0.999989\-0.004376\-0.002039\-0.004372\-0.999988] # 58, 6 ImageOrientationPatient vtkGetVector3Macro(ImagePositionPatient,double); vtkGetVector6Macro(ImageOrientationPatient,double); // Description: // Set/Get the first Curve Data: vtkGetObjectMacro(Curve,vtkPolyData); virtual void SetCurve(vtkPolyData *pd); // Description: // \DEPRECATED: // Modality LUT // Value returned by GetShift/GetScale might be innacurate since Shift/Scale could be // varying along the Series read. Therefore user are advices not to use those functions // anymore vtkGetMacro(Shift,double); vtkGetMacro(Scale,double); protected: vtkGDCMImageReader2(); ~vtkGDCMImageReader2(); vtkSetVector6Macro(ImageOrientationPatient,double); //BTX void FillMedicalImageInformation(const gdcm::ImageReader &reader); //ETX int RequestInformationCompat(); int RequestDataCompat(); int ProcessRequest(vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector); int RequestInformation(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector); int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector); protected: vtkMatrix4x4 *DirectionCosines; int LoadOverlays; int NumberOfOverlays; int LoadIconImage; int NumberOfIconImages; int IconImageDataExtent[6]; double ImagePositionPatient[3]; double ImageOrientationPatient[6]; vtkPolyData *Curve; int ImageFormat; // the following 3, should remain optional int ApplyInverseVideo; int ApplyLookupTable; int ApplyYBRToRGB; // I think that planar configuration need to always be applied as far as VTK is concerned int ApplyPlanarConfiguration; int ApplyShiftScale; int LoadSingleFile(const char *filename, char *pointer, unsigned long &outlen); double Shift; double Scale; int IconDataScalarType; int IconNumberOfScalarComponents; int PlanarConfiguration; int LossyFlag; int ForceRescale; protected: // TODO / FIXME void SetFilePrefix(const char *) {} vtkGetStringMacro(FilePrefix); void SetFilePattern(const char *) {} vtkGetStringMacro(FilePattern); private: vtkGDCMImageReader2(const vtkGDCMImageReader2&); // Not implemented. void operator=(const vtkGDCMImageReader2&); // Not implemented. }; #endif GDCM-3.0.10/Utilities/VTK/vtkGDCMImageReader_Extra.cs000066400000000000000000000020141412732066400217450ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ namespace Kitware.VTK.GDCM { public class vtkgdcm { // FIXME why isn't mummy doing it ? public static readonly int VTK_LUMINANCE = 1; public static readonly int VTK_LUMINANCE_ALPHA = 2; public static readonly int VTK_RGB = 3; public static readonly int VTK_RGBA = 4; public static readonly int VTK_INVERSE_LUMINANCE = 5; public static readonly int VTK_LOOKUP_TABLE = 6; public static readonly int VTK_YBR = 7; public static readonly int VTK_CMYK = 8; } } GDCM-3.0.10/Utilities/VTK/vtkGDCMImageWriter.cxx000066400000000000000000001261651412732066400210670ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMImageWriter.h" #include "vtkVersion.h" #include "vtkObjectFactory.h" #include "vtkImageData.h" #include "vtkLookupTable.h" #include "vtkLookupTable16.h" #include "vtkMath.h" #include "vtkMatrix4x4.h" #include "vtkMedicalImageProperties.h" #include "vtkGDCMMedicalImageProperties.h" #include "vtkStringArray.h" #include "vtkPointData.h" #include "vtkGDCMImageReader.h" #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) #include "vtkInformationVector.h" #include "vtkStreamingDemandDrivenPipeline.h" #include "vtkInformation.h" #endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/ #include "gdcmImageWriter.h" #include "gdcmByteValue.h" #include "gdcmUIDGenerator.h" #include "gdcmAnonymizer.h" #include "gdcmAttribute.h" #include "gdcmRescaler.h" #include "gdcmGlobal.h" #include "gdcmDicts.h" #include "gdcmDict.h" #include "gdcmTag.h" #include "gdcmImageHelper.h" #include "gdcmImageChangePlanarConfiguration.h" #include "gdcmImageChangeTransferSyntax.h" #include //vtkCxxRevisionMacro(vtkGDCMImageWriter, "$Revision: 1.1 $") vtkStandardNewMacro(vtkGDCMImageWriter) //vtkCxxSetObjectMacro(vtkGDCMImageWriter,LookupTable,vtkLookupTable) vtkCxxSetObjectMacro(vtkGDCMImageWriter,MedicalImageProperties,vtkMedicalImageProperties) vtkCxxSetObjectMacro(vtkGDCMImageWriter,FileNames,vtkStringArray) vtkCxxSetObjectMacro(vtkGDCMImageWriter,DirectionCosines,vtkMatrix4x4) inline bool vtkGDCMImageWriter_IsCharTypeSigned() { #ifndef VTK_TYPE_CHAR_IS_SIGNED unsigned char uc = 255; return (*reinterpret_cast(&uc) < 0) ? true : false; #else return VTK_TYPE_CHAR_IS_SIGNED; #endif } #ifndef vtkFloatingPointType #define vtkFloatingPointType double #endif //---------------------------------------------------------------------------- vtkGDCMImageWriter::vtkGDCMImageWriter() { this->DataUpdateExtent[0] = 0; this->DataUpdateExtent[1] = 0; this->DataUpdateExtent[2] = 0; this->DataUpdateExtent[3] = 0; this->DataUpdateExtent[4] = 0; this->DataUpdateExtent[5] = 0; //this->LookupTable = vtkLookupTable::New(); this->MedicalImageProperties = vtkMedicalImageProperties::New(); this->FileNames = vtkStringArray::New(); this->StudyUID = 0; this->SeriesUID = 0; this->DirectionCosines = vtkMatrix4x4::New(); this->DirectionCosines->SetElement(0,0,1); this->DirectionCosines->SetElement(1,0,0); this->DirectionCosines->SetElement(2,0,0); this->DirectionCosines->SetElement(0,1,0); this->DirectionCosines->SetElement(1,1,1); this->DirectionCosines->SetElement(2,1,0); // This is the same root as ITK, but implementation version will be different... gdcm::UIDGenerator::SetRoot( "1.2.826.0.1.3680043.2.1125" ); // echo "VTK" | od -b gdcm::FileMetaInformation::AppendImplementationClassUID( "126.124.113" ); const std::string project_name = std::string("GDCM/VTK ") + vtkVersion::GetVTKVersion(); gdcm::FileMetaInformation::SetSourceApplicationEntityTitle( project_name.c_str() ); this->ImageFormat = 0; // invalid this->Shift = 0.; this->Scale = 1.; this->FileLowerLeft = 0; // same default as vtkImageReader2 this->PlanarConfiguration = 0; this->LossyFlag = 0; this->CompressionType = NO_COMPRESSION; // For both case (2d file or 3d file) we need a common uid for the Series/Study: gdcm::UIDGenerator uidgen; const char *uid = uidgen.Generate(); this->SetStudyUID(uid); uid = uidgen.Generate(); this->SetSeriesUID(uid); } //---------------------------------------------------------------------------- vtkGDCMImageWriter::~vtkGDCMImageWriter() { //this->LookupTable->Delete(); this->MedicalImageProperties->Delete(); this->FileNames->Delete(); this->SetStudyUID(NULL); this->SetSeriesUID(NULL); this->DirectionCosines->Delete(); } //---------------------------------------------------------------------------- #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) int vtkGDCMImageWriter::FillInputPortInformation( int port, vtkInformation *info) { if (!this->Superclass::FillInputPortInformation(port, info)) { return 0; } info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); return 1; } //--------------------------------------------------------------------------- int vtkGDCMImageWriter::RequestInformation( vtkInformation *vtkNotUsed(request), vtkInformationVector **inputVector, vtkInformationVector *vtkNotUsed(outputVector)) { // Check to make sure that all input information agrees //int mismatchedInputs = 0; double spacing[3]; double origin[3]; int extent[6]; int components = 0; int dataType = 0; // For each connection on port 0, check against the first connection for (int i = 0; i < this->GetNumberOfInputConnections(0); i++) { vtkInformation *inInfo = inputVector[0]->GetInformationObject(i); if (i == 0) { inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent); inInfo->Get(vtkDataObject::SPACING(), spacing); inInfo->Get(vtkDataObject::ORIGIN(), origin); components = inInfo->Get(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS()); dataType = inInfo->Get(vtkDataObject::FIELD_ARRAY_TYPE()); continue; } if (memcmp(inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()), extent, sizeof(extent)) || memcmp(inInfo->Get(vtkDataObject::SPACING()), spacing, sizeof(spacing)) || memcmp(inInfo->Get(vtkDataObject::ORIGIN()), origin, sizeof(origin)) || inInfo->Get(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS()) != components || inInfo->Get(vtkDataObject::FIELD_ARRAY_TYPE()) != dataType) { //mismatchedInputs = 1; return 0; } } // Technically we should be much more paranoid with the shift scale (like value bigger // then stored pixel type: does this even make sense ?) // Let's do the easy one here: // do I really need to comment on this one: if( this->Scale == 0 ) { return 0; } return 1; } //-------------------------------------------------------------------------- int vtkGDCMImageWriter::RequestUpdateExtent( vtkInformation *vtkNotUsed(request), vtkInformationVector **inputVector, vtkInformationVector *vtkNotUsed(outputVector)) { // Set the UpdateExtent from the DataUpdateExtent for the current slice int n = inputVector[0]->GetNumberOfInformationObjects(); for (int i = 0; i < n; i++) { vtkInformation *inInfo = inputVector[0]->GetInformationObject(i); inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), this->DataUpdateExtent, 6); } return 1; } //-------------------------------------------------------------------------- int vtkGDCMImageWriter::RequestData( vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* vtkNotUsed(outputVector)) { // Go through the inputs and write the data for each int numTimeSteps = inputVector[0]->GetNumberOfInformationObjects(); for (int timeStep = 0; timeStep < numTimeSteps; timeStep++) { vtkInformation *inInfo = inputVector[0]->GetInformationObject(timeStep); vtkImageData *input = vtkImageData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); // Error checking if (input == NULL) { // Close file, set GDCMFileID to zero //this->CloseFile(this->GDCMFileId); //this->GDCMFileId = 0; vtkErrorMacro(<<"Write: Please specify an input!"); return 0; } // Call WriteGDCMData for each input if (this->WriteGDCMData(input, timeStep) == 0) { return 0; } } return 1; } #endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/ //---------------------------------------------------------------------------- /*const*/ char *vtkGDCMImageWriter::GetFileName() { if( this->FileNames->GetNumberOfValues() ) { const char *filename = this->FileNames->GetValue(0); return const_cast(filename); } return this->Superclass::GetFileName(); } //---------------------------------------------------------------------------- #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) void vtkGDCMImageWriter::Write() { if (this->GetFileName() == 0) { vtkErrorMacro("Write: You must supply a file name."); return; } // Get the first input and update its information. vtkImageData *input = this->GetImageDataInput(0); if (input == 0) { vtkErrorMacro("Write: No input supplied."); return; } #if (VTK_MAJOR_VERSION >= 6) #else input->UpdateInformation(); #endif // Update the rest. this->UpdateInformation(); // Get the whole extent of the input #if (VTK_MAJOR_VERSION >= 6) vtkInformation *inInfo = this->GetInputInformation(0, 0); inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->DataUpdateExtent); #else input->GetWholeExtent(this->DataUpdateExtent); #endif if (this->DataUpdateExtent[0] == (this->DataUpdateExtent[1] + 1) || this->DataUpdateExtent[2] == (this->DataUpdateExtent[3] + 1) || this->DataUpdateExtent[4] == (this->DataUpdateExtent[5] + 1)) { vtkErrorMacro("Write: Empty input supplied."); return; } // For both case (2d file or 3d file) we need a common uid for the Series/Study: //gdcm::UIDGenerator uidgen; //const char *uid = uidgen.Generate(); //this->SetStudyUID(uid); //uid = uidgen.Generate(); //this->SetSeriesUID(uid); // Did the user specified dim of output file to be 2 ? if( this->FileDimensionality == 2 ) { int dimIndex = 2; int firstSlice = this->DataUpdateExtent[2*dimIndex]; int lastSlice = this->DataUpdateExtent[2*dimIndex+1]; assert( lastSlice >= firstSlice ); if( lastSlice - firstSlice ) // will be == 0 when only a single slice { if( lastSlice - firstSlice + 1 != this->FileNames->GetNumberOfValues() ) { vtkErrorMacro("Wrong number of filenames: " << this->FileNames->GetNumberOfValues() << " should be " << lastSlice - firstSlice + 1); return; } } // Go through data slice-by-slice using file-order slices for (int slice = firstSlice; slice <= lastSlice; slice++) { //std::cerr << "Slice:" << slice << std::endl; // Set the DataUpdateExtent to the slice extent we want to write this->DataUpdateExtent[2*dimIndex] = slice; this->DataUpdateExtent[2*dimIndex+1] = slice; this->Modified(); // Call Update to execute pipeline and write slice to disk. this->Update(); } } else if( this->FileDimensionality == 3 ) { // Call Update to execute pipeline and write slice to disk. this->Update(); } else { vtkErrorMacro( "Unhandled: " << this->FileDimensionality ); } } #else //---------------------------------------------------------------------------- // Writes all the data from the input. void vtkGDCMImageWriter::Write() { // Error checking if ( this->GetInput() == NULL ) { vtkErrorMacro(<<"Write:Please specify an input!"); return; } // if (!this->WriteToMemory && !this->FileName && !this->FilePattern) // { // vtkErrorMacro(<<"Write:Please specify either a FileName or a file prefix and pattern"); // return; // } // Make sure the file name is allocated this->InternalFileName = 0; // new char[(this->FileName ? strlen(this->FileName) : 1) + // (this->FilePrefix ? strlen(this->FilePrefix) : 1) + // (this->FilePattern ? strlen(this->FilePattern) : 1) + 10]; // Fill in image information. this->GetInput()->UpdateInformation(); int *wExtent; wExtent = this->GetInput()->GetWholeExtent(); this->FileNumber = this->GetInput()->GetWholeExtent()[4]; this->UpdateProgress(0.0); // loop over the z axis and write the slices for (this->FileNumber = wExtent[4]; this->FileNumber <= wExtent[5]; ++this->FileNumber) { this->GetInput()->SetUpdateExtent(wExtent[0], wExtent[1], wExtent[2], wExtent[3], this->FileNumber, this->FileNumber); // determine the name /* if (this->FileName) { sprintf(this->InternalFileName,"%s",this->FileName); } else { if (this->FilePrefix) { sprintf(this->InternalFileName, this->FilePattern, this->FilePrefix, this->FileNumber); } else { sprintf(this->InternalFileName, this->FilePattern,this->FileNumber); } } */ this->GetInput()->UpdateData(); this->WriteSlice(this->GetInput()); this->UpdateProgress((this->FileNumber - wExtent[4])/ (wExtent[5] - wExtent[4] + 1.0)); } //delete [] this->InternalFileName; //this->InternalFileName = NULL; } //---------------------------------------------------------------------------- void vtkGDCMImageWriter::WriteSlice(vtkImageData *data) { this->WriteGDCMData(data, 0); } #endif //---------------------------------------------------------------------------- //void SetStringValueFromTag(const char *s, const gdcm::Tag& t, gdcm::DataSet& ds) static void SetStringValueFromTag(const char *s, const gdcm::Tag& t, gdcm::Anonymizer & ano) { if( s && *s ) { #if 0 gdcm::DataElement de( t ); de.SetByteValue( s, strlen( s ) ); const gdcm::Global& g = gdcm::Global::GetInstance(); const gdcm::Dicts &dicts = g.GetDicts(); // FIXME: we know the tag at compile time we could save some time // Using the static dict instead of the run-time one: const gdcm::DictEntry &dictentry = dicts.GetDictEntry( t ); de.SetVR( dictentry.GetVR() ); ds.Insert( de ); #else ano.Replace(t, s); #endif } } //---------------------------------------------------------------------------- int vtkGDCMImageWriter::WriteGDCMData(vtkImageData *data, int timeStep) { //std::cerr << "Calling WriteGDCMData" << std::endl; assert( timeStep >= 0 ); #if (VTK_MAJOR_VERSION >= 6) vtkInformation *inInfo = this->GetInputInformation(0, timeStep); int inWholeExt[6]; inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inWholeExt); int inExt[6]; inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt); #else int inWholeExt[6]; data->GetWholeExtent(inWholeExt); int inExt[6]; data->GetUpdateExtent(inExt); #endif #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 2 ) vtkIdType inInc[3]; #else int inInc[3]; #endif data->GetIncrements(inInc); //data->Update(); //data->Print( std::cout ); //const char * filename = this->GetFileName(); //std::cerr << data->GetDataDimension() << std::endl; gdcm::ImageWriter writer; //writer.SetImage( image ); gdcm::ImageChangeTransferSyntax change; //gdcm::Image &image = writer.GetImage(); gdcm::Image &image = change.GetInput(); image.SetLossyFlag( this->LossyFlag ); // Nowadays this is the default one: #ifdef GDCM_WORDS_BIGENDIAN // FIXME: this is not the default syntax, but should be a little faster on big endian machine // let see if people complain dataset cannot be sent image.SetTransferSyntax( gdcm::TransferSyntax::ExplicitVRBigEndian ); #else // that's the default syntax AND it is the fastest syntax to write to disk. image.SetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); #endif image.SetNumberOfDimensions( 2 ); // good default const int *dims = data->GetDimensions(); assert( dims[0] >= 0 && dims[1] >= 0 && dims[2] >= 0 ); image.SetDimension(0, dims[0] ); image.SetDimension(1, dims[1] ); #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 2 ) const double *spacing = data->GetSpacing(); #else const float *spacing = data->GetSpacing(); #endif image.SetSpacing(0, spacing[0] ); image.SetSpacing(1, spacing[1] ); if( dims[2] > 1 && this->FileDimensionality == 3 ) { // resize num of dim to 3: image.SetNumberOfDimensions( 3 ); image.SetDimension(2, dims[2] ); } // Even in case of 2D image, pass the 3rd dimension spacing, this might // Be needed for example in MR : Spacing Between Slice tag image.SetSpacing(2, spacing[2] ); // should always be valid... // TODO: need to do Origin / Image Position (Patient) // For now FileDimensionality should match File Dimension //this->FileDimensionality int scalarType = data->GetScalarType(); gdcm::PixelFormat pixeltype = gdcm::PixelFormat::UNKNOWN; bool forcerescale = false; switch( scalarType ) { case VTK_BIT: pixeltype = gdcm::PixelFormat::SINGLEBIT; break; case VTK_CHAR: if( vtkGDCMImageWriter_IsCharTypeSigned() ) pixeltype = gdcm::PixelFormat::INT8; else pixeltype = gdcm::PixelFormat::UINT8; break; #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) case VTK_SIGNED_CHAR: pixeltype = gdcm::PixelFormat::INT8; break; #endif case VTK_UNSIGNED_CHAR: pixeltype = gdcm::PixelFormat::UINT8; break; case VTK_SHORT: pixeltype = gdcm::PixelFormat::INT16; break; case VTK_UNSIGNED_SHORT: pixeltype = gdcm::PixelFormat::UINT16; break; case VTK_INT: pixeltype = gdcm::PixelFormat::INT32; break; case VTK_UNSIGNED_INT: pixeltype = gdcm::PixelFormat::UINT32; break; case VTK_FLOAT: if( this->Shift == (int)this->Shift && this->Scale == (int)this->Scale ) { // I cannot consider that this is a problem, afterall a floating point type image // could in fact really be only integer type, only print a warning to inform dummy user vtkWarningMacro( "Image is floating point type, but rescale type is integer type. Rescaling anyway" ); } /* Note to myself: should I allow people to squeeze into unsigned char ? Or can I assume most people will be doing unsigned short anyway... */ pixeltype = gdcm::PixelFormat::FLOAT32; forcerescale = true; break; case VTK_DOUBLE: if( this->Shift == (int)this->Shift && this->Scale == (int)this->Scale ) { // I cannot consider that this is a problem, afterall a floating point type image // could in fact really be only integer type, only print a warning to inform dummy user vtkWarningMacro( "Image is floating point type, but rescale type is integer type. Rescaling anyway" ); } /* Note to myself: should I allow people to squeeze into unsigned char ? Or can I assume most people will be doing unsigned short anyway... */ pixeltype = gdcm::PixelFormat::FLOAT64; forcerescale = true; break; default: vtkErrorMacro( "Do not support this Pixel Type: " << scalarType ); return 0; } gdcm::PhotometricInterpretation pi; if( this->ImageFormat ) { // We have been passed the proper image format, let's use it ! switch( this->ImageFormat ) { case VTK_LUMINANCE: pi = gdcm::PhotometricInterpretation::MONOCHROME2; break; case VTK_RGB: pi = gdcm::PhotometricInterpretation::RGB; break; case VTK_RGBA: pi = gdcm::PhotometricInterpretation::ARGB; break; case VTK_INVERSE_LUMINANCE: pi = gdcm::PhotometricInterpretation::MONOCHROME1; break; case VTK_LOOKUP_TABLE: pi = gdcm::PhotometricInterpretation::PALETTE_COLOR; break; case VTK_YBR: pi = gdcm::PhotometricInterpretation::YBR_FULL; break; default: vtkErrorMacro( "Unknown ImageFormat:" << this->ImageFormat ); return 0; } } else { // Attempt a guess if( data->GetNumberOfScalarComponents() == 1 ) { pi = gdcm::PhotometricInterpretation::MONOCHROME2; } else if( data->GetNumberOfScalarComponents() == 3 ) { // It could well be YBR ... oh well pi = gdcm::PhotometricInterpretation::RGB; // (0028,0006) US 0 # 2, 1 PlanarConfiguration } else if( data->GetNumberOfScalarComponents() == 4 ) { // It could well be CMYK ... oh well pi = gdcm::PhotometricInterpretation::ARGB; } else { return 0; } } // Let's try to fake out the SOP Class UID here: gdcm::MediaStorage ms = gdcm::MediaStorage::SecondaryCaptureImageStorage; ms.GuessFromModality( this->MedicalImageProperties->GetModality(), this->FileDimensionality ); // Will override SC only if something is found... // store in a safe place the 'raw' pixeltype from vtk gdcm::PixelFormat savepixeltype = pixeltype; // fast path, when (shift,scale) is (0,1) we do not need no rescale function // at all. Pay attention in some case users really wants to store floating // point values anyway, be nice with them if( !forcerescale && (this->Shift == 0 && this->Scale == 1) ) { //assert( pixeltype == outputpt ); } else { gdcm::Rescaler ir2; ir2.SetIntercept( this->Shift ); ir2.SetSlope( this->Scale ); ir2.SetPixelFormat( pixeltype ); // TODO: Hum...ScalarRange is -I believe- computed on the WholeExtent... vtkFloatingPointType srange[2]; data->GetScalarRange(srange); // HACK !!! // MR Image Storage cannot have Shift / Rescale , however it looks like people are doing it // anyway, so let's make GDCM just as bad as any other library, by providing a fix: if( ms == gdcm::MediaStorage::MRImageStorage /*&& pixeltype.GetBitsAllocated() == 8*/ ) { srange[1] = std::numeric_limits::max() * this->Scale + this->Shift; } ir2.SetMinMaxForPixelType( srange[0], srange[1] ); //gdcm::PixelFormat::ScalarType outputpt = ir2.ComputeInterceptSlopePixelType(); gdcm::PixelFormat outputpt = ir2.ComputePixelTypeFromMinMax(); // override pixeltype with what is found by Rescaler pixeltype = outputpt; } pixeltype.SetSamplesPerPixel( (unsigned short)data->GetNumberOfScalarComponents() ); image.SetPhotometricInterpretation( pi ); image.SetPixelFormat( pixeltype ); image.SetPlanarConfiguration( 0 ); // VTK default // Setup LUT if any: if( pi == gdcm::PhotometricInterpretation::PALETTE_COLOR ) { assert( pixeltype.GetSamplesPerPixel() == 1 ); vtkLookupTable * vtklut = data->GetPointData()->GetScalars()->GetLookupTable(); //vtkLookupTable * vtklut = this->LookupTable; assert( vtklut ); //const char *name = vtklut->GetClassName (); vtkLookupTable16 * vtklut16 = vtkLookupTable16::SafeDownCast( vtklut ); //assert( vtklut->GetNumberOfTableValues() == 256 ); //vtkIdType vtknumcolors = vtklut->GetNumberOfTableValues(); unsigned int lutlen = 256; assert( pixeltype.GetBitsAllocated() == 8 || pixeltype.GetBitsAllocated() == 16 ); if( pixeltype.GetBitsAllocated() == 8 ) { lutlen = 256; } else { //assert( pixeltype.GetBitsAllocated() == 16 ); lutlen = 65536; } gdcm::SmartPointer lut = new gdcm::LookupTable; lut->Allocate( pixeltype.GetBitsAllocated() ); lut->InitializeLUT( gdcm::LookupTable::RED, (unsigned short)lutlen, 0, 16 ); lut->InitializeLUT( gdcm::LookupTable::GREEN, (unsigned short)lutlen, 0, 16 ); lut->InitializeLUT( gdcm::LookupTable::BLUE, (unsigned short)lutlen, 0, 16 ); bool b; if( vtklut16 ) b = lut->WriteBufferAsRGBA( vtklut16->WritePointer(0,4) ); else b = lut->WriteBufferAsRGBA( vtklut->WritePointer(0,4) ); if( !b ) { vtkWarningMacro( "Could not get values from LUT" ); return 0; } image.SetLUT( *lut ); } unsigned long len = image.GetBufferLength(); vtkIdType npts = (vtkIdType)(inExt[5] - inExt[4] + 1) * (inExt[3] - inExt[2] + 1) * (inExt[1] - inExt[0] + 1); if( npts < 0 ) { vtkErrorMacro( "Could not Get number of points" ); return 0; } //assert( npts >= 0 ); //assert( npts == data->GetNumberOfPoints() ); int ssize = data->GetScalarSize(); unsigned long vtklen = npts * ssize; if( ssize == 0 ) { assert( data->GetScalarType() == VTK_BIT ); vtklen = npts / 8; } else { vtklen = npts * ssize; assert( vtklen >= (unsigned long)npts ); } //unsigned long vtklen = npts * ssize; //assert( vtklen == len * ssize ); gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0,0x0010) ); gdcm::ByteValue *bv = new gdcm::ByteValue(); // (char*)data->GetScalarPointer(), len ); bv->SetLength( (uint32_t)len ); // allocate ! // std::ofstream of( "/tmp/bla.raw", std::ios::binary ); // of.write( (char*)data->GetScalarPointer(), len); // of.close(); // re shuffle the line within ByteValue: // char *pointer = const_cast(bv->GetPointer()); //const char *tempimage = (char*)data->GetScalarPointer(); const char *tempimage = (char*)data->GetScalarPointerForExtent(inExt); //std::cerr << "Pointer:" << (unsigned int)tempimage << std::endl; int *dext = data->GetExtent(); long outsize; if( data->GetScalarType() == VTK_BIT ) { outsize = (dext[1] - dext[0] + 1) / 8; } else { outsize = pixeltype.GetPixelSize()*(dext[1] - dext[0] + 1); } int jj = dext[4]; bool rescaled = false; char * copy = NULL; // Whenever shift / scale is needed... do it ! if( this->Shift != 0 || this->Scale != 1 || forcerescale ) { assert( this->PlanarConfiguration == 0 ); // rescale from float to unsigned short gdcm::Rescaler ir; ir.SetIntercept( this->Shift ); ir.SetSlope( this->Scale ); ir.SetPixelFormat( savepixeltype ); vtkFloatingPointType srange[2]; data->GetScalarRange(srange); // HACK !!! // MR Image Storage cannot have Shift / Rescale , however it looks like people are doing it // anyway, so let's make GDCM just as bad as any other library, by providing a fix: if( ms == gdcm::MediaStorage::MRImageStorage /*&& pixeltype.GetBitsAllocated() == 8*/ ) { srange[1] = std::numeric_limits::max() * this->Scale + this->Shift; } ir.SetMinMaxForPixelType( srange[0], srange[1] ); image.SetIntercept( this->Shift ); image.SetSlope( this->Scale ); copy = new char[len]; ir.InverseRescale(copy,tempimage,vtklen); rescaled = true; tempimage = copy; } //std::cerr << "dext[4]:" << j << std::endl; //std::cerr << "inExt[4]:" << inExt[4] << std::endl; if( this->FileLowerLeft ) { memcpy(pointer,tempimage,len); } else { if( dims[2] > 1 && this->FileDimensionality == 3 ) { for(int j = dext[4]; j <= dext[5]; ++j) { for(int i = dext[2]; i <= dext[3]; ++i) { memcpy(pointer, tempimage+((dext[3] - i)+j*(dext[3]+1))*outsize, outsize); pointer += outsize; } } } else { for(int i = dext[2]; i <= dext[3]; ++i) { memcpy(pointer, tempimage+((dext[3] - i)+jj*(dext[3]+1))*outsize, outsize); pointer += outsize; } } } if( rescaled ) { delete[] copy; } pixeldata.SetValue( *bv ); image.SetDataElement( pixeldata ); // DEBUG #ifndef NDEBUG const gdcm::DataElement &pixeldata2 = image.GetDataElement(); //const gdcm::Value &v = image.GetValue(); //const gdcm::ByteValue *bv1 = dynamic_cast(&v); const gdcm::ByteValue *bv1 = pixeldata2.GetByteValue(); assert( bv1 && bv1 == bv ); //image.Print( std::cerr ); #endif // END DEBUG // Do PlanarConfiguration if( this->PlanarConfiguration ) { gdcm::ImageChangePlanarConfiguration icpc; icpc.SetInput( image ); icpc.SetPlanarConfiguration( 1 ); icpc.Change(); image = icpc.GetOutput(); assert( image.GetPlanarConfiguration() == 1 ); } int year, month, day; gdcm::File& file = writer.GetFile(); gdcm::DataSet& ds = file.GetDataSet(); vtkGDCMMedicalImageProperties *gdcmmip = dynamic_cast( this->MedicalImageProperties ); gdcm::Anonymizer ano; if( gdcmmip ) { gdcm::File const &f = gdcmmip->GetFile(timeStep); writer.SetFile( f ); ano.SetFile( writer.GetFile() ); } else { ano.SetFile( file ); // For ex: DICOM (0010,0010) = DOE,JOHN SetStringValueFromTag(this->MedicalImageProperties->GetPatientName(), gdcm::Tag(0x0010,0x0010), ano); // For ex: DICOM (0010,0020) = 1933197 SetStringValueFromTag( this->MedicalImageProperties->GetPatientID(), gdcm::Tag(0x0010,0x0020), ano); // For ex: DICOM (0010,1010) = 031Y SetStringValueFromTag( this->MedicalImageProperties->GetPatientAge(), gdcm::Tag(0x0010,0x1010), ano); // For ex: DICOM (0010,0040) = M SetStringValueFromTag( this->MedicalImageProperties->GetPatientSex(), gdcm::Tag(0x0010,0x0040), ano); // For ex: DICOM (0010,0030) = 19680427 SetStringValueFromTag( this->MedicalImageProperties->GetPatientBirthDate(), gdcm::Tag(0x0010,0x0030), ano); #if VTK_MAJOR_VERSION >= 6 || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) // For ex: DICOM (0008,0020) = 20030617 if( vtkMedicalImageProperties::GetDateAsFields( this->MedicalImageProperties->GetStudyDate(), year, month, day ) ) SetStringValueFromTag( this->MedicalImageProperties->GetStudyDate(), gdcm::Tag(0x0008,0x0020), ano); #endif // For ex: DICOM (0008,0022) = 20030617 SetStringValueFromTag( this->MedicalImageProperties->GetAcquisitionDate(), gdcm::Tag(0x0008,0x0022), ano); #if VTK_MAJOR_VERSION >= 6 || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) // For ex: DICOM (0008,0030) = 162552.0705 or 230012, or 0012 #if 0 int hour, minute, second; if( vtkMedicalImageProperties::GetTimeAsFields( this->MedicalImageProperties->GetStudyTime(), hour, minute, second ) ) #else time_t studytime; char date[22] = { ' ' }; strcpy( date, "19000101" ); if( this->MedicalImageProperties->GetStudyTime() ) strncpy( date + 8 , this->MedicalImageProperties->GetStudyTime(), 22 - 8 ); date[21] = 0; if( gdcm::System::ParseDateTime(studytime, date ) ) #endif SetStringValueFromTag( this->MedicalImageProperties->GetStudyTime(), gdcm::Tag(0x0008,0x0030), ano); #endif // For ex: DICOM (0008,0032) = 162552.0705 or 230012, or 0012 SetStringValueFromTag( this->MedicalImageProperties->GetAcquisitionTime(), gdcm::Tag(0x0008,0x0032), ano); // For ex: DICOM (0008,0023) = 20030617 SetStringValueFromTag( this->MedicalImageProperties->GetImageDate(), gdcm::Tag(0x0008,0x0023), ano); // For ex: DICOM (0008,0033) = 162552.0705 or 230012, or 0012 SetStringValueFromTag( this->MedicalImageProperties->GetImageTime(), gdcm::Tag(0x0008,0x0033), ano); // For ex: DICOM (0020,0013) = 1 SetStringValueFromTag( this->MedicalImageProperties->GetImageNumber(), gdcm::Tag(0x0020,0x0013), ano); // For ex: DICOM (0020,0011) = 902 SetStringValueFromTag( this->MedicalImageProperties->GetSeriesNumber(), gdcm::Tag(0x0020,0x0011), ano); // For ex: DICOM (0008,103e) = SCOUT SetStringValueFromTag( this->MedicalImageProperties->GetSeriesDescription(), gdcm::Tag(0x0008,0x103e), ano); // For ex: DICOM (0020,0010) = 37481 SetStringValueFromTag( this->MedicalImageProperties->GetStudyID(), gdcm::Tag(0x0020,0x0010), ano); // For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL SetStringValueFromTag( this->MedicalImageProperties->GetStudyDescription(), gdcm::Tag(0x0008,0x1030), ano); // For ex: DICOM (0008,0060)= CT SetStringValueFromTag( this->MedicalImageProperties->GetModality(), gdcm::Tag(0x0008,0x0060), ano); // For ex: DICOM (0008,0070) = Siemens SetStringValueFromTag( this->MedicalImageProperties->GetManufacturer(), gdcm::Tag(0x0008,0x0070), ano); // For ex: DICOM (0008,1090) = LightSpeed QX/i SetStringValueFromTag( this->MedicalImageProperties->GetManufacturerModelName(), gdcm::Tag(0x0008,0x1090), ano); // For ex: DICOM (0008,1010) = LSPD_OC8 SetStringValueFromTag( this->MedicalImageProperties->GetStationName(), gdcm::Tag(0x0008,0x1010), ano); // For ex: DICOM (0008,0080) = FooCity Medical Center SetStringValueFromTag( this->MedicalImageProperties->GetInstitutionName(), gdcm::Tag(0x0008,0x0080), ano); // For ex: DICOM (0018,1210) = Bone SetStringValueFromTag( this->MedicalImageProperties->GetConvolutionKernel(), gdcm::Tag(0x0018,0x1210), ano); // For ex: DICOM (0018,0050) = 0.273438 SetStringValueFromTag( this->MedicalImageProperties->GetSliceThickness(), gdcm::Tag(0x0018,0x0050), ano); // For ex: DICOM (0018,0060) = 120 SetStringValueFromTag( this->MedicalImageProperties->GetKVP(), gdcm::Tag(0x0018,0x0060), ano); // For ex: DICOM (0018,1120) = 15 SetStringValueFromTag( this->MedicalImageProperties->GetGantryTilt(), gdcm::Tag(0x0018,0x1120), ano); // For ex: DICOM (0018,0081) = 105 SetStringValueFromTag( this->MedicalImageProperties->GetEchoTime(), gdcm::Tag(0x0018,0x0081), ano); // For ex: DICOM (0018,0091) = 35 SetStringValueFromTag( this->MedicalImageProperties->GetEchoTrainLength(), gdcm::Tag(0x0018,0x0091), ano); // For ex: DICOM (0018,0080) = 2040 SetStringValueFromTag( this->MedicalImageProperties->GetRepetitionTime(), gdcm::Tag(0x0018,0x0080), ano); // For ex: DICOM (0018,1150) = 5 SetStringValueFromTag( this->MedicalImageProperties->GetExposureTime(), gdcm::Tag(0x0018,0x1150), ano); // For ex: DICOM (0018,1151) = 400 SetStringValueFromTag( this->MedicalImageProperties->GetXRayTubeCurrent(), gdcm::Tag(0x0018,0x1151), ano); // For ex: DICOM (0018,1152) = 114 SetStringValueFromTag( this->MedicalImageProperties->GetExposure(), gdcm::Tag(0x0018,0x1152), ano); // Window Level / Window Center int numwl = this->MedicalImageProperties->GetNumberOfWindowLevelPresets(); if( numwl ) { gdcm::VR vr = gdcm::VR::DS; gdcm::Element elwc; elwc.SetLength( numwl * vr.GetSizeof() ); gdcm::Element elww; elww.SetLength( numwl * vr.GetSizeof() ); vr = gdcm::VR::LO; gdcm::Element elwe; elwe.SetLength( numwl * vr.GetSizeof() ); for(int i = 0; i < numwl; ++i) { const double *wl = this->MedicalImageProperties->GetNthWindowLevelPreset(i); elww.SetValue( wl[0], i ); elwc.SetValue( wl[1], i ); const char* we = this->MedicalImageProperties->GetNthWindowLevelPresetComment(i); elwe.SetValue( we, i ); } { gdcm::DataElement de = elwc.GetAsDataElement(); de.SetTag( gdcm::Tag(0x0028,0x1050) ); ds.Insert( de ); } { gdcm::DataElement de = elww.GetAsDataElement(); de.SetTag( gdcm::Tag(0x0028,0x1051) ); ds.Insert( de ); } { gdcm::DataElement de = elwe.GetAsDataElement(); de.SetTag( gdcm::Tag(0x0028,0x1055) ); ds.Insert( de ); } } #if VTK_MAJOR_VERSION >= 6 || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) // User defined value // Remap any user defined value from the DICOM name to the DICOM tag unsigned int nvalues = this->MedicalImageProperties->GetNumberOfUserDefinedValues(); for(unsigned int i = 0; i < nvalues; ++i) { const char *name = this->MedicalImageProperties->GetUserDefinedNameByIndex(i); const char *value = this->MedicalImageProperties->GetUserDefinedValueByIndex(i); assert( name && value && *name && *value ); // Only deal with public elements: const gdcm::Global& g = gdcm::Global::GetInstance(); const gdcm::Dicts &dicts = g.GetDicts(); const gdcm::Dict &pubdict = dicts.GetPublicDict(); gdcm::Tag t; // Lookup up tag by name is truly inefficient : 0(n) const gdcm::DictEntry &de = pubdict.GetDictEntryByName(name, t); (void)de; SetStringValueFromTag( value, t, ano); } #endif } ms = gdcm::ImageHelper::ComputeMediaStorageFromModality( this->MedicalImageProperties->GetModality(), this->FileDimensionality, pixeltype, pi, this->Shift, this->Scale ); if( ms == gdcm::MediaStorage::MS_END ) { vtkErrorMacro( "Incompatible MediaStorage" ); return 0; } // FIXME: new Secondary object handle multi frames... assert( gdcm::MediaStorage::IsImage( ms ) ); { gdcm::DataElement de( gdcm::Tag(0x0008, 0x0016) ); const char* msstr = gdcm::MediaStorage::GetMSString(ms); assert( msstr ); de.SetByteValue( msstr, (uint32_t)strlen(msstr) ); de.SetVR( gdcm::Attribute<0x0008, 0x0016>::GetVR() ); ds.Insert( de ); } // Image Type is pretty much always required: gdcm::Attribute<0x0008,0x0008> imagetype; const gdcm::CSComp values[] = { "ORIGINAL", "PRIMARY" }; imagetype.SetValues( values, 2 ); ds.Insert( imagetype.GetAsDataElement() ); // Image Orientation (Patient) //gdcm::Attribute<0x0020,0x0037> iop = {{1,0,0,0,1,0}}; // default value std::vector iop; iop.resize(6); const vtkMatrix4x4 *dircos = this->DirectionCosines; for(int i = 0; i < 3; ++i) { iop[i] = dircos->GetElement(i,0); } for(int i = 0; i < 3; ++i) { iop[i+3] = dircos->GetElement(i,1); } #if VTK_MAJOR_VERSION >= 6 || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 2 ) const double *iop_mip = this->MedicalImageProperties->GetDirectionCosine(); if( iop[0] != iop_mip[0] || iop[1] != iop_mip[1] || iop[2] != iop_mip[2] || iop[3] != iop_mip[3] || iop[4] != iop_mip[4] || iop[5] != iop_mip[5] ) { vtkErrorMacro( "DirectionCosines is not compatible with vtkMedicalImageProperties::DirectionCosine" ); return 0; } #endif image.SetDirectionCosines( &iop[0] ); std::vector ipp; ipp.resize(3); // Image Position (Patient) // cross product of direction cosines gives the direction along // which the slices are stacked const double *iop1 = &iop[0]; const double *iop2 = iop1+3; double zaxis[3]; vtkMath::Cross(iop1, iop2, zaxis); // determine the relative index of the current slice // in the case of a single volume, this will be 0 // since inExt (UpdateExtent) and WholeExt are the same int n = inExt[4] - inWholeExt[4]; const vtkFloatingPointType *vtkorigin = data->GetOrigin(); vtkFloatingPointType origin[3]; if( this->FileLowerLeft ) { origin[0] = vtkorigin[0]; origin[1] = vtkorigin[1]; origin[2] = vtkorigin[2]; } else { double norm = (dims[1] - 1) * spacing[1]; origin[0] = vtkorigin[0] - norm * iop[3+0]; origin[1] = vtkorigin[1] - norm * iop[3+1]; origin[2] = vtkorigin[2] - norm * iop[3+2]; } double new_origin[3]; // In order to compute the newer Image Position (Patient) we need to have a valid spacing along // 3rd dimension. Simply give up in case 0: // FIXME: Actually if user decides to write a series of SC object it is ok... if( spacing[2] == 0. && dims[2] > 1 ) { vtkErrorMacro( "Z-spacing cannot be 0 for multiframe image" ); return 0; } for (int i = 0; i < 3; i++) { // the n'th slice is n * z-spacing aloung the IOP-derived // z-axis new_origin[i] = origin[i] + zaxis[i] * n * spacing[2]; } for(int i = 0; i < 3; ++i) ipp[i] = new_origin[i]; image.SetOrigin(0, ipp[0] ); image.SetOrigin(1, ipp[1] ); image.SetOrigin(2, ipp[2] ); assert( ipp.size() < 3 || image.GetOrigin(2) == ipp[2] ); //gdcm::ImageHelper::SetOriginValue(ds, ipp, dims[2], spacing[2]); // Here come the important part: generate proper UID for Series/Study so that people knows this is the same Study/Series const char *studyuid = this->StudyUID; assert( studyuid ); // programmer error { gdcm::DataElement de( gdcm::Tag(0x0020,0x000d) ); // Study de.SetByteValue( studyuid, (uint32_t)strlen(studyuid) ); de.SetVR( gdcm::Attribute<0x0020, 0x000d>::GetVR() ); ds.Insert( de ); } const char *seriesuid = this->SeriesUID; assert( seriesuid ); // programmer error { gdcm::DataElement de( gdcm::Tag(0x0020,0x000e) ); // Series de.SetByteValue( seriesuid, (uint32_t)strlen(seriesuid) ); de.SetVR( gdcm::Attribute<0x0020, 0x000e>::GetVR() ); ds.Insert( de ); } const char *filename = NULL; int k = inExt[4]; if( this->FileNames->GetNumberOfValues() ) { //int n = this->FileNames->GetNumberOfValues(); filename = this->FileNames->GetValue(k); } else { filename = this->GetFileName(); } assert( filename ); // Let's add an Instance Number just for fun, unless we have a vtkGDCMMedicalImageProperties if( !gdcmmip ) { std::ostringstream os; os << k; // Will only be added if none found SetStringValueFromTag(os.str().c_str(), gdcm::Tag(0x0020,0x0013), ano); } switch( this->CompressionType ) { /* * 10.1 DICOM DEFAULT TRANSFER SYNTAX * DICOM defines a default Transfer Syntax, the DICOM Implicit VR Little Endian Transfer Syntax (UID = * "1.2.840.10008.1.2"), which shall be supported by every conformant DICOM Implementation. */ case NO_COMPRESSION: change.SetTransferSyntax( gdcm::TransferSyntax::ImplicitVRLittleEndian ); break; case JPEG_COMPRESSION: change.SetTransferSyntax( gdcm::TransferSyntax::JPEGLosslessProcess14_1 ); break; case JPEG2000_COMPRESSION: change.SetTransferSyntax( gdcm::TransferSyntax::JPEG2000Lossless ); break; case JPEGLS_COMPRESSION: change.SetTransferSyntax( gdcm::TransferSyntax::JPEGLSLossless ); break; case RLE_COMPRESSION: change.SetTransferSyntax( gdcm::TransferSyntax::RLELossless ); break; } if( !change.Change() ) { vtkErrorMacro( "Could not change the Transfer Syntax for Compression Type: " ); return 0; } writer.SetImage( change.GetOutput() ); writer.SetFileName( filename ); if( !writer.Write() ) { vtkErrorMacro( "Could not write" ); return 0; } return 1; } //void vtkGDCMImageWriter::SetCompressionTypeFromString(const char *) //{ //} // //const char *vtkGDCMImageWriter::GetCompressionTypeAsString() //{ // NO_COMPRESSION = 0, // raw (default) // JPEG_COMPRESSION, // JPEG // JPEG2000_COMPRESSION, // J2K // JPEGLS_COMPRESSION, // JPEG-LS // RLE_COMPRESSION // RLE //} void vtkGDCMImageWriter::SetDirectionCosinesFromImageOrientationPatient(const double dircos[6]) { this->DirectionCosines->SetElement(0,0, dircos[0]); this->DirectionCosines->SetElement(1,0, dircos[1]); this->DirectionCosines->SetElement(2,0, dircos[2]); this->DirectionCosines->SetElement(3,0, 0); this->DirectionCosines->SetElement(0,1, dircos[3]); this->DirectionCosines->SetElement(1,1, dircos[4]); this->DirectionCosines->SetElement(2,1, dircos[5]); this->DirectionCosines->SetElement(3,1, 0); double dircosz[3]; vtkMath::Cross(dircos, dircos+3, dircosz); this->DirectionCosines->SetElement(0,2, dircosz[0]); this->DirectionCosines->SetElement(1,2, dircosz[1]); this->DirectionCosines->SetElement(2,2, dircosz[2]); this->DirectionCosines->SetElement(3,2, 0); } //---------------------------------------------------------------------------- void vtkGDCMImageWriter::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } GDCM-3.0.10/Utilities/VTK/vtkGDCMImageWriter.h000066400000000000000000000142141412732066400205030ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // .NAME vtkGDCMImageWriter - write DICOM files // .SECTION Description // vtkGDCMImageWriter is a sink object that write DICOM files // this writer is single threaded (see vtkGDCMThreadedImageReader2 for multi-thread) // // .SECTION Warning: vtkLookupTable from the vtkImageData object taken into account // only if ImageFormat is set to VTK_LOOKUP_TABLE // // .SECTION NOTE We are not using the usual API SetFilePrefix / SetFilePattern, // but instead a list of filenames: see SetFileNames and class gdcm::FilenameGenerator // // .SECTION Warning // You need to specify the correct ImageFormat (taken from the reader) // You need to explicitly specify the DirectionCosines (taken from the reader) // Since VTK 5.4 vtkMedicalImageProperties has its own DirectionCosine (no 's') // user need to make sure the vtkMatrix4x4 is compatible with the 6-vector DirectionCosine. // // .SECTION NOTE Shift/Scale are global to all DICOM frames (=files) written // as 2D slice, therefore the shift/scale operation might not be optimized for // all slices. This is not recommended for image with a large dynamic range. // // .SECTION See Also // vtkImageWriter vtkMedicalImageProperties vtkGDCMImageReader #ifndef VTKGDCMIMAGEWRITER_H #define VTKGDCMIMAGEWRITER_H #include "vtkImageWriter.h" #include "vtkVersion.h" class vtkLookupTable; class vtkMedicalImageProperties; class vtkMatrix4x4; class vtkStringArray; class VTK_EXPORT vtkGDCMImageWriter : public vtkImageWriter { public: static vtkGDCMImageWriter *New(); vtkTypeMacro(vtkGDCMImageWriter,vtkImageWriter); virtual void PrintSelf(ostream& os, vtkIndent indent); // Description: // Pass in the vtkmedicalimageproperties object for medical information // to be mapped to DICOM attributes. vtkGetObjectMacro(MedicalImageProperties, vtkMedicalImageProperties); virtual void SetMedicalImageProperties(vtkMedicalImageProperties*); // Description: // Pass in the list of filename to be used to write out the DICOM file(s) virtual void SetFileNames(vtkStringArray*); vtkGetObjectMacro(FileNames, vtkStringArray); // Description: // Set/Get whether or not the image was compressed using a lossy compression algorithm vtkGetMacro(LossyFlag,int); vtkSetMacro(LossyFlag,int); vtkBooleanMacro(LossyFlag,int); // I need that... virtual void Write(); // Description: // Get the entension for this file format. virtual const char* GetFileExtensions() { return ".dcm .DCM"; } // Description: // Get the name of this file format. virtual const char* GetDescriptiveName() { return "DICOM"; } // Description: // You need to manually specify the direction the image is in to write a valid DICOM file // since vtkImageData do not contains one (eg. MR Image Storage, CT Image Storage...) virtual void SetDirectionCosines(vtkMatrix4x4 *matrix); vtkGetObjectMacro(DirectionCosines, vtkMatrix4x4); virtual void SetDirectionCosinesFromImageOrientationPatient(const double dircos[6]); // Description: // Modality LUT vtkSetMacro(Shift, double); vtkGetMacro(Shift, double); vtkSetMacro(Scale, double); vtkGetMacro(Scale, double); // Description: // See vtkGDCMImageReader for list of ImageFormat vtkGetMacro(ImageFormat,int); vtkSetMacro(ImageFormat,int); // Description: // Set/Get whether the data comes from the file starting in the lower left // corner or upper left corner. vtkBooleanMacro(FileLowerLeft, int); vtkGetMacro(FileLowerLeft, int); vtkSetMacro(FileLowerLeft, int); // Description: // For color image (more than a single comp) you can specify the planar configuration you prefer vtkSetMacro(PlanarConfiguration,int); vtkGetMacro(PlanarConfiguration,int); // Description: // Set/Get specific StudyUID / SeriesUID vtkSetStringMacro(StudyUID); vtkGetStringMacro(StudyUID); vtkSetStringMacro(SeriesUID); vtkGetStringMacro(SeriesUID); //BTX enum CompressionTypes { NO_COMPRESSION = 0, // raw (default) JPEG_COMPRESSION, // JPEG JPEG2000_COMPRESSION, // J2K JPEGLS_COMPRESSION, // JPEG-LS RLE_COMPRESSION // RLE }; //ETX // Set/Get the compression type vtkSetMacro(CompressionType, int); vtkGetMacro(CompressionType, int); //void SetCompressionTypeFromString(const char *); //const char *GetCompressionTypeAsString(); protected: vtkGDCMImageWriter(); ~vtkGDCMImageWriter(); #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) int FillInputPortInformation(int port, vtkInformation *info); int RequestInformation( vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector); int RequestUpdateExtent( vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector); int RequestData( vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector); #else void WriteSlice(vtkImageData *data); #endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/ int WriteGDCMData(vtkImageData *data, int timeStep); protected: virtual /*const*/ char *GetFileName(); private: vtkGDCMImageWriter(const vtkGDCMImageWriter&); // Not implemented. void operator=(const vtkGDCMImageWriter&); // Not implemented. // VTK structs: //vtkLookupTable *LookupTable; vtkMedicalImageProperties *MedicalImageProperties; char *StudyUID; char *SeriesUID; int DataUpdateExtent[6]; int ImageFormat; vtkStringArray *FileNames; vtkMatrix4x4 *DirectionCosines; double Shift; double Scale; int FileLowerLeft; int PlanarConfiguration; int LossyFlag; int CompressionType; }; #endif GDCM-3.0.10/Utilities/VTK/vtkGDCMMedicalImageProperties.cxx000066400000000000000000000044471412732066400232240ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMMedicalImageProperties.h" #include "vtkObjectFactory.h" #include "gdcmFile.h" //---------------------------------------------------------------------------- //vtkCxxRevisionMacro(vtkGDCMMedicalImageProperties, "1.21") vtkStandardNewMacro(vtkGDCMMedicalImageProperties) class vtkGDCMMedicalImagePropertiesInternals { public: std::vector< gdcm::SmartPointer > Files; }; //---------------------------------------------------------------------------- vtkGDCMMedicalImageProperties::vtkGDCMMedicalImageProperties() { this->Internals = new vtkGDCMMedicalImagePropertiesInternals; } //---------------------------------------------------------------------------- vtkGDCMMedicalImageProperties::~vtkGDCMMedicalImageProperties() { if (this->Internals) { delete this->Internals; this->Internals = NULL; } this->Clear(); } //---------------------------------------------------------------------------- void vtkGDCMMedicalImageProperties::Clear() { this->Superclass::Clear(); } //---------------------------------------------------------------------------- void vtkGDCMMedicalImageProperties::PushBackFile(gdcm::File const &f) { this->Internals->Files.push_back( f ); size_t i = this->Internals->Files.size(); gdcm::DataSet &ds = this->Internals->Files[ i - 1 ]->GetDataSet(); ds.Remove( gdcm::Tag( 0x7fe0, 0x0010 ) ); } //---------------------------------------------------------------------------- gdcm::File const & vtkGDCMMedicalImageProperties::GetFile(unsigned int t) { return *this->Internals->Files[ t ]; } //---------------------------------------------------------------------------- void vtkGDCMMedicalImageProperties::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); } GDCM-3.0.10/Utilities/VTK/vtkGDCMMedicalImageProperties.h000066400000000000000000000301751412732066400226460ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // .NAME vtkGDCMMedicalImageProperties - some medical image properties. // .SECTION Description // vtkGDCMMedicalImageProperties is a helper class that can be used by medical // image readers and applications to encapsulate medical image/acquisition // properties. Later on, this should probably be extended to add // any user-defined property. // .SECTION See Also // vtkMedicalImageReader2 #ifndef VTKGDCMMEDICALIMAGEPROPERTIES_H #define VTKGDCMMEDICALIMAGEPROPERTIES_H #include "vtkMedicalImageProperties.h" class vtkGDCMMedicalImagePropertiesInternals; //BTX namespace gdcm { class File; } //ETX class VTK_EXPORT vtkGDCMMedicalImageProperties : public vtkMedicalImageProperties { public: static vtkGDCMMedicalImageProperties *New(); vtkTypeMacro(vtkGDCMMedicalImageProperties,vtkMedicalImageProperties); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Convenience method to reset all fields to an empty string/value virtual void Clear(); /* // Description: // Patient name // For ex: DICOM (0010,0010) = DOE,JOHN vtkSetStringMacro(PatientName); vtkGetStringMacro(PatientName); // Description: // Patient ID // For ex: DICOM (0010,0020) = 1933197 vtkSetStringMacro(PatientID); vtkGetStringMacro(PatientID); // Description: // Patient age // Format: nnnD, nnW, nnnM or nnnY (eventually nnD, nnW, nnY) // with D (day), M (month), W (week), Y (year) // For ex: DICOM (0010,1010) = 031Y vtkSetStringMacro(PatientAge); vtkGetStringMacro(PatientAge); // Description: // Take as input a string in VR=AS (DICOM PS3.5) and extract either // different fields namely: year month week day // Return 0 on error, 1 on success // One can test fields if they are different from -1 upon success static int GetAgeAsFields(const char *age, int &year, int &month, int &week, int &day); // For Tcl: // From C++ use GetPatientAge + GetAgeAsField // Those function parse a DICOM string, and return the value of the number expressed // this is either expressed in year, month or days. Thus if a string is expressed in years // GetPatientAgeDay/GetPatientAgeWeek/GetPatientAgeMonth will return 0 int GetPatientAgeYear(); int GetPatientAgeMonth(); int GetPatientAgeWeek(); int GetPatientAgeDay(); // Description: // Patient sex // For ex: DICOM (0010,0040) = M vtkSetStringMacro(PatientSex); vtkGetStringMacro(PatientSex); // Description: // Patient birth date // Format: yyyymmdd // For ex: DICOM (0010,0030) = 19680427 vtkSetStringMacro(PatientBirthDate); vtkGetStringMacro(PatientBirthDate); // For Tcl: // From C++ use GetPatientBirthDate + GetDateAsFields int GetPatientBirthDateYear(); int GetPatientBirthDateMonth(); int GetPatientBirthDateDay(); // Description: // Study Date // Format: yyyymmdd // For ex: DICOM (0008,0020) = 20030617 vtkSetStringMacro(StudyDate); vtkGetStringMacro(StudyDate); // Description: // Acquisition Date // Format: yyyymmdd // For ex: DICOM (0008,0022) = 20030617 vtkSetStringMacro(AcquisitionDate); vtkGetStringMacro(AcquisitionDate); // For Tcl: // From C++ use GetAcquisitionDate + GetDateAsFields int GetAcquisitionDateYear(); int GetAcquisitionDateMonth(); int GetAcquisitionDateDay(); // Description: // Study Time // Format: hhmmss.frac (any trailing component(s) can be ommited) // For ex: DICOM (0008,0030) = 162552.0705 or 230012, or 0012 vtkSetStringMacro(StudyTime); vtkGetStringMacro(StudyTime); // Description: // Acquisition time // Format: hhmmss.frac (any trailing component(s) can be ommited) // For ex: DICOM (0008,0032) = 162552.0705 or 230012, or 0012 vtkSetStringMacro(AcquisitionTime); vtkGetStringMacro(AcquisitionTime); // Description: // Image Date aka Content Date // Format: yyyymmdd // For ex: DICOM (0008,0023) = 20030617 vtkSetStringMacro(ImageDate); vtkGetStringMacro(ImageDate); // For Tcl: // From C++ use GetImageDate + GetDateAsFields int GetImageDateYear(); int GetImageDateMonth(); int GetImageDateDay(); // Description: // Take as input a string in ISO 8601 date (YYYY/MM/DD) and extract the // different fields namely: year month day // Return 0 on error, 1 on success static int GetDateAsFields(const char *date, int &year, int &month, int &day); // Description: // Take as input a string in ISO 8601 date (YYYY/MM/DD) and construct a // locale date based on the different fields (see GetDateAsFields to extract // different fields) // Return 0 on error, 1 on success static int GetDateAsLocale(const char *date, char *locale); // Description: // Image Time // Format: hhmmss.frac (any trailing component(s) can be ommited) // For ex: DICOM (0008,0033) = 162552.0705 or 230012, or 0012 vtkSetStringMacro(ImageTime); vtkGetStringMacro(ImageTime); // Description: // Image number // For ex: DICOM (0020,0013) = 1 vtkSetStringMacro(ImageNumber); vtkGetStringMacro(ImageNumber); // Description: // Series number // For ex: DICOM (0020,0011) = 902 vtkSetStringMacro(SeriesNumber); vtkGetStringMacro(SeriesNumber); // Description: // Series Description // User provided description of the Series // For ex: DICOM (0008,103e) = SCOUT vtkSetStringMacro(SeriesDescription); vtkGetStringMacro(SeriesDescription); // Description: // Study ID // For ex: DICOM (0020,0010) = 37481 vtkSetStringMacro(StudyID); vtkGetStringMacro(StudyID); // Description: // Study description // For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL vtkSetStringMacro(StudyDescription); vtkGetStringMacro(StudyDescription); // Description: // Modality // For ex: DICOM (0008,0060)= CT vtkSetStringMacro(Modality); vtkGetStringMacro(Modality); // Description: // Manufacturer // For ex: DICOM (0008,0070) = Siemens vtkSetStringMacro(Manufacturer); vtkGetStringMacro(Manufacturer); // Description: // Manufacturer's Model Name // For ex: DICOM (0008,1090) = LightSpeed QX/i vtkSetStringMacro(ManufacturerModelName); vtkGetStringMacro(ManufacturerModelName); // Description: // Station Name // For ex: DICOM (0008,1010) = LSPD_OC8 vtkSetStringMacro(StationName); vtkGetStringMacro(StationName); // Description: // Institution Name // For ex: DICOM (0008,0080) = FooCity Medical Center vtkSetStringMacro(InstitutionName); vtkGetStringMacro(InstitutionName); // Description: // Convolution Kernel (or algorithm used to reconstruct the data) // For ex: DICOM (0018,1210) = Bone vtkSetStringMacro(ConvolutionKernel); vtkGetStringMacro(ConvolutionKernel); // Description: // Slice Thickness (Nominal reconstructed slice thickness, in mm) // For ex: DICOM (0018,0050) = 0.273438 vtkSetStringMacro(SliceThickness); vtkGetStringMacro(SliceThickness); virtual double GetSliceThicknessAsDouble(); // Description: // Peak kilo voltage output of the (x-ray) generator used // For ex: DICOM (0018,0060) = 120 vtkSetStringMacro(KVP); vtkGetStringMacro(KVP); // Description: // Gantry/Detector tilt (Nominal angle of tilt in degrees of the scanning // gantry.) // For ex: DICOM (0018,1120) = 15 vtkSetStringMacro(GantryTilt); vtkGetStringMacro(GantryTilt); virtual double GetGantryTiltAsDouble(); // Description: // Echo Time // (Time in ms between the middle of the excitation pulse and the peak of // the echo produced) // For ex: DICOM (0018,0081) = 105 vtkSetStringMacro(EchoTime); vtkGetStringMacro(EchoTime); // Description: // Echo Train Length // (Number of lines in k-space acquired per excitation per image) // For ex: DICOM (0018,0091) = 35 vtkSetStringMacro(EchoTrainLength); vtkGetStringMacro(EchoTrainLength); // Description: // Repetition Time // The period of time in msec between the beginning of a pulse sequence and // the beginning of the succeeding (essentially identical) pulse sequence. // For ex: DICOM (0018,0080) = 2040 vtkSetStringMacro(RepetitionTime); vtkGetStringMacro(RepetitionTime); // Description: // Exposure time (time of x-ray exposure in msec) // For ex: DICOM (0018,1150) = 5 vtkSetStringMacro(ExposureTime); vtkGetStringMacro(ExposureTime); // Description: // X-ray tube current (in mA) // For ex: DICOM (0018,1151) = 400 vtkSetStringMacro(XRayTubeCurrent); vtkGetStringMacro(XRayTubeCurrent); // Description: // Exposure (The exposure expressed in mAs, for example calculated // from Exposure Time and X-ray Tube Current) // For ex: DICOM (0018,1152) = 114 vtkSetStringMacro(Exposure); vtkGetStringMacro(Exposure); // Interface to allow insertion of user define values, for instance in DICOM one would want to // store the Protocol Name (0018,1030), in this case one would do: // AddUserDefinedValue( "Protocol Name", "T1W/SE/1024" ); void AddUserDefinedValue(const char *name, const char *value); // Get a particular user value const char *GetUserDefinedValue(const char *name); // Get the number of user defined values unsigned int GetNumberOfUserDefinedValues(); // Get a name/value by index const char *GetUserDefinedNameByIndex(unsigned int idx); const char *GetUserDefinedValueByIndex(unsigned int idx); // Description: // Copy the contents of p to this instance. virtual void DeepCopy(vtkGDCMMedicalImageProperties *p); // Description: // Add/Remove/Query the window/level presets that may have been associated // to a medical image. Window is also known as 'width', level is also known // as 'center'. The same window/level pair can not be added twice. // As a convenience, a comment (aka Explanation) can be associated to a preset. // For ex: DICOM Window Center (0028,1050) = 00045\000470 // DICOM Window Width (0028,1051) = 0106\03412 // DICOM Window Center Width Explanation (0028,1055) = WINDOW1\WINDOW2 virtual void AddWindowLevelPreset(double w, double l); virtual void RemoveWindowLevelPreset(double w, double l); virtual void RemoveAllWindowLevelPresets(); virtual int GetNumberOfWindowLevelPresets(); virtual int HasWindowLevelPreset(double w, double l); virtual int GetNthWindowLevelPreset(int idx, double *w, double *l); virtual double* GetNthWindowLevelPreset(int idx); virtual void SetNthWindowLevelPresetComment(int idx, const char *comment); virtual const char* GetNthWindowLevelPresetComment(int idx); // Description: // Mapping from a sliceidx within a volumeidx into a DICOM Instance UID // Some DICOM reader can populate this structure so that later on from a slice index // in a vtkImageData volume we can backtrack and find out which 2d slice it was coming from const char *GetInstanceUIDFromSliceID(int volumeidx, int sliceid); void SetInstanceUIDFromSliceID(int volumeidx, int sliceid, const char *uid); // Description: // Provides the inverse mapping. Returns -1 if a slice for this uid is // not found. int GetSliceIDFromInstanceUID(int &volumeidx, const char *uid); //BTX typedef enum { AXIAL = 0, CORONAL, SAGITTAL } OrientationType; //ETX int GetOrientationType(int volumeidx); void SetOrientationType(int volumeidx, int orientation); static const char *GetStringFromOrientationType(unsigned int type); */ protected: vtkGDCMMedicalImageProperties(); ~vtkGDCMMedicalImageProperties(); //BTX friend class vtkGDCMImageReader; friend class vtkGDCMImageReader2; friend class vtkGDCMImageWriter; void PushBackFile(gdcm::File const &f); gdcm::File const & GetFile(unsigned int t); //ETX private: vtkGDCMMedicalImagePropertiesInternals *Internals; vtkGDCMMedicalImageProperties(const vtkGDCMMedicalImageProperties&); // Not implemented. void operator=(const vtkGDCMMedicalImageProperties&); // Not implemented. }; #endif GDCM-3.0.10/Utilities/VTK/vtkGDCMPolyDataReader.cxx000066400000000000000000001036121412732066400215000ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMPolyDataReader.h" #include "vtkObjectFactory.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkPolyData.h" #include "vtkStreamingDemandDrivenPipeline.h" #include "vtkDoubleArray.h" #include "vtkCellArray.h" #include "vtkCellData.h" #include "vtkMedicalImageProperties.h" #include "vtkRTStructSetProperties.h" #include "vtkEmptyCell.h" #include "vtkVersion.h" #include "gdcmReader.h" #include "gdcmSmartPointer.h" #include "gdcmAttribute.h" #include "gdcmSequenceOfItems.h" #include "gdcmDirectoryHelper.h" //vtkCxxRevisionMacro(vtkGDCMPolyDataReader, "$Revision: 1.74 $") vtkStandardNewMacro(vtkGDCMPolyDataReader) //---------------------------------------------------------------------------- vtkGDCMPolyDataReader::vtkGDCMPolyDataReader() { this->FileName = NULL; this->SetNumberOfInputPorts(0); this->MedicalImageProperties = vtkMedicalImageProperties::New(); this->RTStructSetProperties = vtkRTStructSetProperties::New(); } //---------------------------------------------------------------------------- vtkGDCMPolyDataReader::~vtkGDCMPolyDataReader() { this->SetFileName(0); this->MedicalImageProperties->Delete(); this->RTStructSetProperties->Delete(); } //---------------------------------------------------------------------------- void vtkGDCMPolyDataReader::FillMedicalImageInformation(const gdcm::Reader &reader) { const gdcm::File &file = reader.GetFile(); const gdcm::DataSet &ds = file.GetDataSet(); this->RTStructSetProperties->SetStructureSetLabel( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x3006,0x0002), ds).c_str() ); this->RTStructSetProperties->SetStructureSetName( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x3006,0x0004), ds).c_str() ); this->RTStructSetProperties->SetStructureSetDate( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x3006,0x0008), ds).c_str() ); this->RTStructSetProperties->SetStructureSetTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x3006,0x0009), ds).c_str() ); this->RTStructSetProperties->SetSOPInstanceUID( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0018), ds).c_str() ); this->RTStructSetProperties->SetStudyInstanceUID( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0020,0x000d), ds).c_str() ); this->RTStructSetProperties->SetSeriesInstanceUID( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0020,0x000e), ds).c_str() ); // $ grep "vtkSetString\|DICOM" vtkMedicalImageProperties.h // For ex: DICOM (0010,0010) = DOE,JOHN this->MedicalImageProperties->SetPatientName( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0010,0x0010), ds).c_str() ); // For ex: DICOM (0010,0020) = 1933197 this->MedicalImageProperties->SetPatientID( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0010,0x0020), ds).c_str() ); // For ex: DICOM (0010,1010) = 031Y this->MedicalImageProperties->SetPatientAge( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0010,0x1010), ds).c_str() ); // For ex: DICOM (0010,0040) = M this->MedicalImageProperties->SetPatientSex( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0010,0x0040), ds).c_str() ); // For ex: DICOM (0010,0030) = 19680427 this->MedicalImageProperties->SetPatientBirthDate( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0010,0x0030), ds).c_str() ); #if VTK_MAJOR_VERSION >= 6 || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) // For ex: DICOM (0008,0020) = 20030617 this->MedicalImageProperties->SetStudyDate( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0020), ds).c_str() ); #endif // For ex: DICOM (0008,0022) = 20030617 this->MedicalImageProperties->SetAcquisitionDate( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0022), ds).c_str() ); #if VTK_MAJOR_VERSION >= 6 || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) // For ex: DICOM (0008,0030) = 162552.0705 or 230012, or 0012 this->MedicalImageProperties->SetStudyTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0030), ds).c_str() ); #endif // For ex: DICOM (0008,0032) = 162552.0705 or 230012, or 0012 this->MedicalImageProperties->SetAcquisitionTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0032), ds).c_str() ); // For ex: DICOM (0008,0023) = 20030617 this->MedicalImageProperties->SetImageDate( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0023), ds).c_str() ); // For ex: DICOM (0008,0033) = 162552.0705 or 230012, or 0012 this->MedicalImageProperties->SetImageTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0033), ds).c_str() ); // For ex: DICOM (0020,0013) = 1 this->MedicalImageProperties->SetImageNumber( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0020,0x0013), ds).c_str() ); // For ex: DICOM (0020,0011) = 902 this->MedicalImageProperties->SetSeriesNumber( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0020,0x0011), ds).c_str() ); // For ex: DICOM (0008,103e) = SCOUT this->MedicalImageProperties->SetSeriesDescription( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x103e), ds).c_str() ); // For ex: DICOM (0020,0010) = 37481 this->MedicalImageProperties->SetStudyID( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0020,0x0010), ds).c_str() ); // For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL this->MedicalImageProperties->SetStudyDescription( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x1030), ds).c_str() ); // For ex: DICOM (0008,0060)= CT this->MedicalImageProperties->SetModality( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0060), ds).c_str() ); // For ex: DICOM (0008,0070) = Siemens this->MedicalImageProperties->SetManufacturer( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0070), ds).c_str() ); // For ex: DICOM (0008,1090) = LightSpeed QX/i this->MedicalImageProperties->SetManufacturerModelName( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x1090), ds).c_str() ); // For ex: DICOM (0008,1010) = LSPD_OC8 this->MedicalImageProperties->SetStationName( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x1010), ds).c_str() ); // For ex: DICOM (0008,0080) = FooCity Medical Center this->MedicalImageProperties->SetInstitutionName( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0008,0x0080), ds).c_str() ); // For ex: DICOM (0018,1210) = Bone this->MedicalImageProperties->SetConvolutionKernel( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x1210), ds).c_str() ); // For ex: DICOM (0018,0050) = 0.273438 this->MedicalImageProperties->SetSliceThickness( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x0050), ds).c_str() ); // For ex: DICOM (0018,0060) = 120 this->MedicalImageProperties->SetKVP( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x0060), ds).c_str() ); // For ex: DICOM (0018,1120) = 15 this->MedicalImageProperties->SetGantryTilt( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x1120), ds).c_str() ); // For ex: DICOM (0018,0081) = 105 this->MedicalImageProperties->SetEchoTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x0081), ds).c_str() ); // For ex: DICOM (0018,0091) = 35 this->MedicalImageProperties->SetEchoTrainLength( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x0091), ds).c_str() ); // For ex: DICOM (0018,0080) = 2040 this->MedicalImageProperties->SetRepetitionTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x0080), ds).c_str() ); // For ex: DICOM (0018,1150) = 5 this->MedicalImageProperties->SetExposureTime( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x1150), ds).c_str() ); // For ex: DICOM (0018,1151) = 400 this->MedicalImageProperties->SetXRayTubeCurrent( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x1151), ds).c_str() ); // For ex: DICOM (0018,1152) = 114 this->MedicalImageProperties->SetExposure( gdcm::DirectoryHelper::GetStringValueFromTag( gdcm::Tag(0x0018,0x1152), ds).c_str() ); // virtual void AddWindowLevelPreset(double w, double l); // (0028,1050) DS [ 498\ 498] # 12, 2 WindowCenter // (0028,1051) DS [ 1063\ 1063] # 12, 2 WindowWidth gdcm::Tag twindowcenter(0x0028,0x1050); gdcm::Tag twindowwidth(0x0028,0x1051); if( ds.FindDataElement( twindowcenter ) && ds.FindDataElement( twindowwidth) ) { const gdcm::DataElement& windowcenter = ds.GetDataElement( twindowcenter ); const gdcm::DataElement& windowwidth = ds.GetDataElement( twindowwidth ); const gdcm::ByteValue *bvwc = windowcenter.GetByteValue(); const gdcm::ByteValue *bvww = windowwidth.GetByteValue(); if( bvwc && bvww ) // Can be Type 2 { //gdcm::Attributes<0x0028,0x1050> at; gdcm::Element elwc; std::stringstream ss1; std::string swc = std::string( bvwc->GetPointer(), bvwc->GetLength() ); ss1.str( swc ); gdcm::VR vr = gdcm::VR::DS; unsigned int vrsize = vr.GetSizeof(); unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swc.c_str(), (unsigned int)swc.size()); elwc.SetLength( count * vrsize ); elwc.Read( ss1 ); std::stringstream ss2; std::string sww = std::string( bvww->GetPointer(), bvww->GetLength() ); ss2.str( sww ); gdcm::Element elww; elww.SetLength( count * vrsize ); elww.Read( ss2 ); //assert( elww.GetLength() == elwc.GetLength() ); for(unsigned int i = 0; i < elwc.GetLength(); ++i) { this->MedicalImageProperties->AddWindowLevelPreset( elww.GetValue(i), elwc.GetValue(i) ); } } } gdcm::Tag twindowexplanation(0x0028,0x1055); if( ds.FindDataElement( twindowexplanation ) ) { const gdcm::DataElement& windowexplanation = ds.GetDataElement( twindowexplanation ); const gdcm::ByteValue *bvwe = windowexplanation.GetByteValue(); if( bvwe ) // Can be Type 2 { int n = this->MedicalImageProperties->GetNumberOfWindowLevelPresets(); gdcm::Element elwe; // window explanation gdcm::VR vr = gdcm::VR::LO; std::stringstream ss; ss.str( "" ); std::string swe = std::string( bvwe->GetPointer(), bvwe->GetLength() ); unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swe.c_str(), (unsigned int)swe.size()); (void)count; // I found a case with only one W/L but two comments: WINDOW1\WINDOW2 // SIEMENS-IncompletePixelData.dcm //assert( count >= (unsigned int)n ); elwe.SetLength( /*count*/ n * vr.GetSizeof() ); ss.str( swe ); elwe.Read( ss ); for(int i = 0; i < n; ++i) { this->MedicalImageProperties->SetNthWindowLevelPresetComment(i, elwe.GetValue(i).c_str() ); } } } #if 0 // gdcmData/JDDICOM_Sample4.dcm // -> (0008,0060) CS [DM Digital microscopy] # 24, 1 Modality gdcm::MediaStorage ms1 = gdcm::MediaStorage::SecondaryCaptureImageStorage; ms1.GuessFromModality( this->MedicalImageProperties->GetModality(), this->FileDimensionality ); gdcm::MediaStorage ms2; ms2.SetFromFile( reader.GetFile() ); if( ms2 != ms1 && ms2 != gdcm::MediaStorage::SecondaryCaptureImageStorage ) { vtkWarningMacro( "SHOULD NOT HAPPEN. Unrecognized Modality: " << this->MedicalImageProperties->GetModality() << " Will be set instead to the known one: " << ms2.GetModality() ) this->MedicalImageProperties->SetModality( ms2.GetModality() ); } #endif // Add more info: } //(3006,0022) ?? (IS) [2 ] # 2,1 ROI Number //(3006,0024) ?? (UI) [2.16.840.1.114362.1.759508.1251415878280.193] # 44,1 Referenced Frame of Reference UID //(3006,0026) ?? (LO) [Bladder ] # 8,1 ROI Name //(3006,0028) ST [STATIC] # 6, 1 ROIDescription //(3006,0036) ?? (CS) [MANUAL] # 6,1 ROI Generation Algorithm int vtkGDCMPolyDataReader::RequestData_RTStructureSetStorage(gdcm::Reader const &reader, vtkInformationVector *outputVector) { // This is done in RequestInformation // gdcm::MediaStorage ms; // ms.SetFromFile( reader.GetFile() ); // //std::cout << ms << std::endl; // if( ms != gdcm::MediaStorage::RTStructureSetStorage ) // { // return 0; // } const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); // (3006,0010) SQ (Sequence with undefined length #=1) # u/l, 1 ReferencedFrameOfReferenceSequence // (3006,0020) SQ (Sequence with explicit length #=4) # 370, 1 StructureSetROISequence // (3006,0039) SQ (Sequence with explicit length #=4) # 24216, 1 ROIContourSequence gdcm::Tag troicsq(0x3006,0x0039); if( !ds.FindDataElement( troicsq ) ) { return 0; } gdcm::Tag tssroisq(0x3006,0x0020); if( !ds.FindDataElement( tssroisq ) ) { return 0; } gdcm::Tag trefframerefsq(0x3006,0x0010); if( !ds.FindDataElement( trefframerefsq ) ) { return 0; } const gdcm::DataElement &refframerefsq = ds.GetDataElement( trefframerefsq ); gdcm::SmartPointer sqi0 = refframerefsq.GetValueAsSQ(); if( !sqi0 || !sqi0->GetNumberOfItems() ) { return 0; } //assert( sqi0->GetNumberOfItems() == 1 ); for(unsigned int pd = 0; pd < sqi0->GetNumberOfItems(); ++pd) { const gdcm::Item & item0 = sqi0->GetItem(pd+1); // Item start at #1 const gdcm::DataSet& nestedds0 = item0.GetNestedDataSet(); // (3006,0012) SQ (Sequence with undefined length #=1) # u/l, 1 RTReferencedStudySequence gdcm::Attribute<0x0020,0x052> frameofreferenceuid; frameofreferenceuid.SetFromDataSet( nestedds0 ); this->RTStructSetProperties->SetReferenceFrameOfReferenceUID( frameofreferenceuid.GetValue() ); gdcm::Tag trtrefstudysq(0x3006,0x0012); if( !nestedds0.FindDataElement( trtrefstudysq) ) { return 0; } const gdcm::DataElement &rtrefstudysq = nestedds0.GetDataElement( trtrefstudysq ); gdcm::SmartPointer sqi00 = rtrefstudysq.GetValueAsSQ(); if( !sqi00 || !sqi00->GetNumberOfItems() ) { return 0; } assert( sqi00->GetNumberOfItems() == 1 ); for(unsigned int pd0 = 0; pd0 < sqi00->GetNumberOfItems(); ++pd0) { const gdcm::Item & item00 = sqi00->GetItem(pd0+1); // Item start at #1 const gdcm::DataSet& nestedds00 = item00.GetNestedDataSet(); // (3006,0014) SQ (Sequence with undefined length #=1) # u/l, 1 RTReferencedSeriesSequence gdcm::Tag trtrefseriessq(0x3006,0x0014); if( !nestedds00.FindDataElement( trtrefseriessq) ) { return 0; } const gdcm::DataElement &rtrefseriessq = nestedds00.GetDataElement( trtrefseriessq); gdcm::SmartPointer sqi000 = rtrefseriessq.GetValueAsSQ(); if( !sqi000 || !sqi000->GetNumberOfItems() ) { return 0; } assert( sqi000->GetNumberOfItems() == 1 ); for(unsigned int pd00 = 0; pd00 < sqi000->GetNumberOfItems(); ++pd00) { const gdcm::Item & item000 = sqi000->GetItem(pd00+1); // Item start at #1 const gdcm::DataSet& nestedds000 = item000.GetNestedDataSet(); gdcm::Attribute<0x0020,0x000e> seriesinstanceuid; seriesinstanceuid.SetFromDataSet( nestedds000 ); this->RTStructSetProperties->SetReferenceSeriesInstanceUID( seriesinstanceuid.GetValue() ); // (3006,0016) SQ (Sequence with undefined length #=162) # u/l, 1 ContourImageSequence gdcm::Tag tcontourimageseq(0x3006,0x0016); if( !nestedds000.FindDataElement( tcontourimageseq) ) { return 0; } const gdcm::DataElement &contourimageseq = nestedds000.GetDataElement( tcontourimageseq ); gdcm::SmartPointer sqi0000 = contourimageseq.GetValueAsSQ(); if( !sqi0000 || !sqi0000->GetNumberOfItems() ) { return 0; } for(unsigned int pd000 = 0; pd000 < sqi0000->GetNumberOfItems(); ++pd000) { const gdcm::Item & item = sqi0000->GetItem(pd000+1); // Item start at #1 const gdcm::DataSet& nestedds = item.GetNestedDataSet(); gdcm::Attribute<0x0008,0x1150> refsopclassuid; refsopclassuid.SetFromDataSet( nestedds ); gdcm::Attribute<0x0008,0x1155> refinstanceuid; refinstanceuid.SetFromDataSet( nestedds ); this->RTStructSetProperties->AddReferencedFrameOfReference( refsopclassuid.GetValue().c_str(), refinstanceuid.GetValue().c_str() ); } } } } const gdcm::DataElement &roicsq = ds.GetDataElement( troicsq ); //std::cout << roicsq << std::endl; //const gdcm::SequenceOfItems *sqi_debug = roicsq.GetSequenceOfItems(); gdcm::SmartPointer sqi = roicsq.GetValueAsSQ(); if( !sqi || !sqi->GetNumberOfItems() ) { return 0; } const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq ); //const gdcm::SequenceOfItems *ssqi = ssroisq.GetSequenceOfItems(); gdcm::SmartPointer ssqi = ssroisq.GetValueAsSQ(); if( !ssqi || !ssqi->GetNumberOfItems() ) { return 0; } // For each Item in the DataSet create a vtkPolyData for(unsigned int pd = 0; pd < sqi->GetNumberOfItems(); ++pd) { //StructureSetROI structuresetroi; // get the info object vtkInformation *outInfo1 = outputVector->GetInformationObject(pd); // get the ouptut vtkPolyData *output = vtkPolyData::SafeDownCast( outInfo1->Get(vtkDataObject::DATA_OBJECT())); const gdcm::Item & item = sqi->GetItem(pd+1); // Item start at #1 //std::cout << item << std::endl; const gdcm::Item & sitem = ssqi->GetItem(pd+1); // Item start at #1 const gdcm::DataSet& snestedds = sitem.GetNestedDataSet(); // (3006,0026) ?? (LO) [date] # 4,1 ROI Name gdcm::Tag stcsq(0x3006,0x0026); if( !snestedds.FindDataElement( stcsq ) ) { continue; } const gdcm::DataElement &sde = snestedds.GetDataElement( stcsq ); std::string s(sde.GetByteValue()->GetPointer(), sde.GetByteValue()->GetLength()); //structuresetroi.ROIName = s; gdcm::Attribute<0x3006,0x0022> roinumber; roinumber.SetFromDataSet( snestedds ); //structuresetroi.ROINumber = roinumber.GetValue(); gdcm::Attribute<0x3006,0x0024> refframeuid; refframeuid.SetFromDataSet( snestedds ); //structuresetroi.RefFrameRefUID = refframeuid.GetValue(); gdcm::Attribute<0x3006,0x0026> roiname; roiname.SetFromDataSet( snestedds ); gdcm::Attribute<0x3006,0x0028> roidesc; roidesc.SetFromDataSet( snestedds ); assert( s == roiname.GetValue() ); gdcm::Attribute<0x3006,0x0036> roigenalg; roigenalg.SetFromDataSet( snestedds ); //structuresetroi.ROIGenerationAlgorithm = roigenalg.GetValue(); //structuresetrois.push_back( structuresetroi ); this->RTStructSetProperties->AddStructureSetROI( roinumber.GetValue(), refframeuid.GetValue(), roiname.GetValue(), roigenalg.GetValue(), roidesc.GetValue() ); const gdcm::DataSet& nestedds = item.GetNestedDataSet(); //std::cout << nestedds << std::endl; //(3006,002a) IS [255\192\96] # 10,3 ROI Display Color gdcm::Tag troidc(0x3006,0x002a); gdcm::Attribute<0x3006,0x002a> color; bool hasColor = false;//so that color[0] isn't referenced if the color isn't present. if( nestedds.FindDataElement( troidc) ) { const gdcm::DataElement &decolor = nestedds.GetDataElement( troidc ); color.SetFromDataElement( decolor ); hasColor = true; //std::cout << "color: " << roinumber.GetValue() << " -> " << color[0] << "," << color[1] << "," << color[2] << std::endl; } //(3006,0040) SQ (Sequence with explicit length #=8) # 4326, 1 ContourSequence gdcm::Tag tcsq(0x3006,0x0040); if( !nestedds.FindDataElement( tcsq ) ) { // FIXME: What if a contour sequence is empty but the color is set to // -say- 0/255/0 Since we are skipping entirely the contour sequence (no // vtkCellArray) we will not save the color. which means it will be // reported as 0/0/0 in the output DICOM file. continue; } const gdcm::DataElement& csq = nestedds.GetDataElement( tcsq ); //std::cout << csq << std::endl; //const gdcm::SequenceOfItems *sqi2 = csq.GetSequenceOfItems(); gdcm::SmartPointer sqi2 = csq.GetValueAsSQ(); if( !sqi2 )//|| !sqi2->GetNumberOfItems() ) { continue; } size_t nitems = sqi2->GetNumberOfItems(); //std::cout << nitems << std::endl; //this->SetNumberOfOutputPorts(nitems); vtkDoubleArray *scalars = vtkDoubleArray::New(); scalars->SetNumberOfComponents(3); scalars->SetName( roiname.GetValue().c_str() ); vtkCellArray *polys = vtkCellArray::New(); if (nitems == 0) { //still have to insert colors in blank masks, else they can get written incorrectly. //also because the number of points of a contour should not define whether or not the color is used. //looks kind of wonky to have a zero-sized polydata, but the polydata does need to still define organ color. vtkEmptyCell* theEmptyCell = vtkEmptyCell::New(); vtkIdType cellId = polys->InsertNextCell(theEmptyCell); if (hasColor) { scalars->InsertTuple3(cellId, (double)color[0]/255.0, (double)color[1]/255.0, (double)color[2]/255.0); } else { scalars->InsertTuple3(cellId, 0,0,0); } theEmptyCell->Delete(); output->GetCellData()->SetScalars(scalars); scalars->Delete(); polys->Delete(); continue; } vtkPoints *newPts = vtkPoints::New(); newPts->SetDataTypeToDouble();//ensure that full precision is retained //std::string s(sde.GetByteValue()->GetPointer(), sde.GetByteValue()->GetLength()); //std::cout << s << std::endl; //newPts->GetData()->SetName( s.c_str() ); // In VTK there is no API to specify the name of a vtkPolyData, you can only specify Name // for the scalars (pointdata or celldata), so let's do that... //scalars->SetName( structuresetroi.ROIName.c_str() ); for(unsigned int ii = 0; ii < nitems; ++ii) { const gdcm::Item & item2 = sqi2->GetItem(ii+1); // Item start at #1 const gdcm::DataSet& nestedds2 = item2.GetNestedDataSet(); //std::cout << nestedds2 << std::endl; // (3006,0050) DS [43.57636\65.52504\-10.0\46.043102\62.564945\-10.0\49.126537\60.714... # 398,48 ContourData gdcm::Tag tcontourdata(0x3006,0x0050); const gdcm::DataElement & contourdata = nestedds2.GetDataElement( tcontourdata ); //std::cout << contourdata << std::endl; //const gdcm::ByteValue *bv = contourdata.GetByteValue(); gdcm::Attribute<0x3006,0x0042> contgeotype; contgeotype.SetFromDataSet( nestedds2 ); assert( contgeotype.GetValue() == "CLOSED_PLANAR " || contgeotype.GetValue() == "POINT " || contgeotype.GetValue() == "OPEN_NONPLANAR" ); gdcm::Attribute<0x3006,0x0046> numcontpoints; numcontpoints.SetFromDataSet( nestedds2 ); if( contgeotype.GetValue() == "POINT " ) { assert( numcontpoints.GetValue() == 1 ); } gdcm::Attribute<0x3006,0x0050> at; at.SetFromDataElement( contourdata ); if( contgeotype.GetValue() == "CLOSED_PLANAR " || contgeotype.GetValue() == "OPEN_NONPLANAR" ) { // http://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.8.8.6.html if( nestedds2.FindDataElement( gdcm::Tag(0x3006,0x0016) ) ) { const gdcm::DataElement &contourimagesequence = nestedds2.GetDataElement( gdcm::Tag(0x3006,0x0016) ); gdcm::SmartPointer contourimagesequence_sqi = contourimagesequence.GetValueAsSQ(); assert( contourimagesequence_sqi && contourimagesequence_sqi->GetNumberOfItems() == 1 ); const gdcm::Item & theitem = contourimagesequence_sqi->GetItem(1); const gdcm::DataSet& thenestedds = theitem.GetNestedDataSet(); gdcm::Attribute<0x0008,0x1150> classat; classat.SetFromDataSet( thenestedds ); gdcm::Attribute<0x0008,0x1155> instat; instat.SetFromDataSet( thenestedds ); this->RTStructSetProperties->AddContourReferencedFrameOfReference( pd, classat.GetValue(), instat.GetValue() ); } } //newPts->SetNumberOfPoints( at.GetNumberOfValues() / 3 ); //assert( at.GetNumberOfValues() % 3 == 0); // FIXME const double* pts = at.GetValues(); vtkIdType *ptIds; unsigned int npts = at.GetNumberOfValues() / 3; assert( npts == (unsigned int)numcontpoints.GetValue() ); assert( npts * 3 == at.GetNumberOfValues() ); ptIds = new vtkIdType[npts]; for(unsigned int i = 0; i < npts * 3; i+=3) { double x[3];//must be double precision, as that's the precision in vtk x[0] = pts[i+0]; x[1] = pts[i+1]; x[2] = pts[i+2]; vtkIdType ptId = newPts->InsertNextPoint( x ); assert( i / 3 < npts ); ptIds[i / 3] = ptId; } // Each Contour Data is in fact a Cell: vtkIdType cellId = polys->InsertNextCell( npts , ptIds); if (hasColor) { scalars->InsertTuple3(cellId, (double)color[0]/255.0, (double)color[1]/255.0, (double)color[2]/255.0); } else { scalars->InsertTuple3(cellId, 0,0,0); } delete[] ptIds; ptIds = NULL; } output->SetPoints(newPts); newPts->Delete(); output->SetPolys(polys); polys->Delete(); output->GetCellData()->SetScalars(scalars); scalars->Delete(); } // Add the Observations: // we can only be doing it here once all RT are loaded, since we will // attach observation to *existing* rtstruct gdcm::Tag trtroiobssq(0x3006,0x0080); if( !ds.FindDataElement( trtroiobssq ) ) { return 0; } const gdcm::DataElement &rtroiobssq = ds.GetDataElement( trtroiobssq ); gdcm::SmartPointer rtroiobssqsqi = rtroiobssq.GetValueAsSQ(); size_t theNumberOfItems = rtroiobssqsqi->GetNumberOfItems(); if( !rtroiobssqsqi )// || !rtroiobssqsqi->GetNumberOfItems() ) { return 0; } for(unsigned int obs = 0; obs < theNumberOfItems ; ++obs) { const gdcm::Item & item = rtroiobssqsqi->GetItem(obs+1); // Item start at #1 const gdcm::DataSet& nestedds = item.GetNestedDataSet(); gdcm::Attribute<0x3006,0x0082> observationnumber; observationnumber.SetFromDataSet( nestedds ); gdcm::Attribute<0x3006,0x0084> referencedroinumber; referencedroinumber.SetFromDataSet( nestedds ); gdcm::Attribute<0x3006,0x0085> roiobservationlabel; roiobservationlabel.SetFromDataSet( nestedds ); gdcm::Attribute<0x3006,0x00a4> rtroiinterpretedtype; rtroiinterpretedtype.SetFromDataSet( nestedds ); gdcm::Attribute<0x3006,0x00a6> roiinterpreter; roiinterpreter.SetFromDataSet( nestedds ); this->RTStructSetProperties-> AddStructureSetROIObservation( referencedroinumber.GetValue(), observationnumber.GetValue(), rtroiinterpretedtype.GetValue(), roiinterpreter.GetValue(), roiobservationlabel.GetValue() ); } return 1; } int vtkGDCMPolyDataReader::RequestData_HemodynamicWaveformStorage(gdcm::Reader const &reader, vtkInformationVector *outputVector) { const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); // (5400,0100) SQ (Sequence with undefined length #=1) # u/l, 1 WaveformSequence gdcm::Tag twsq(0x5400,0x0100); if( !ds.FindDataElement( twsq) ) { return 0; } const gdcm::DataElement &wsq = ds.GetDataElement( twsq ); //std::cout << wsq << std::endl; //const gdcm::SequenceOfItems *sqi = wsq.GetSequenceOfItems(); gdcm::SmartPointer sqi = wsq.GetValueAsSQ(); if( !sqi || !sqi->GetNumberOfItems() ) { return 0; } const gdcm::Item & item = sqi->GetItem(1); // Item start at #1 const gdcm::DataSet& nestedds = item.GetNestedDataSet(); // (5400,1004) US 16 # 2, 1 WaveformBitsAllocated gdcm::Tag twba(0x5400,0x1004); if( !nestedds.FindDataElement( twba ) ) { return 0; } const gdcm::DataElement &wba= nestedds.GetDataElement( twba ); (void)wba; //std::cout << wba << std::endl; // (5400,1006) CS [SS] # 2, 1 WaveformSampleInterpretation // (5400,1010) OW 00ba\0030\ff76\ff8b\00a2\ffd3\ffae\ff50\0062\00c4\011e\00c2\00ba... # 57600, 1 WaveformData gdcm::Tag twd(0x5400,0x1010); if( !nestedds.FindDataElement( twd ) ) { return 0; } const gdcm::DataElement &wd = nestedds.GetDataElement( twd ); const gdcm::ByteValue *bv = wd.GetByteValue(); size_t len = bv->GetLength(); const int16_t *p = (const int16_t*)bv; // get the info object int pd = 0; vtkInformation *outInfo1 = outputVector->GetInformationObject(pd); // get the ouptut vtkPolyData *output = vtkPolyData::SafeDownCast( outInfo1->Get(vtkDataObject::DATA_OBJECT())); vtkPoints *newPts = vtkPoints::New(); size_t npts = len / 2; //npts = 10; // DEBUG ! for(size_t i = 0; i < npts; ++i ) { float x[3]; x[0] = (float)p[i] / 8800; //std::cout << p[i] << std::endl; x[1] = (float)i; x[2] = 0; vtkIdType ptId = newPts->InsertNextPoint( x ); (void)ptId; } output->SetPoints(newPts); newPts->Delete(); vtkCellArray* lines = vtkCellArray::New(); for ( int i = 0; i < newPts->GetNumberOfPoints() - 1; ++i ) { vtkIdType topol[2]; topol[0] = i; topol[1] = i+1; lines->InsertNextCell( 2, topol ); } output->SetLines(lines); lines->Delete(); output->BuildCells(); //output->GetCellData()->SetScalars(scalars); //scalars->Delete(); return 1; } //---------------------------------------------------------------------------- int vtkGDCMPolyDataReader::RequestData( vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) { vtkInformation *outInfo = outputVector->GetInformationObject(0); //vtkPoints *newPts, *mergedPts; //vtkCellArray *newPolys, *mergedPolys; //vtkFloatArray *newScalars=0, *mergedScalars=0; // All of the data in the first piece. if (outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0) { return 0; } if ( !this->FileName || !*this->FileName ) { vtkErrorMacro(<<"A FileName must be specified."); return 0; } gdcm::Reader reader; reader.SetFileName( this->FileName ); if( !reader.Read() ) { return 0; } gdcm::MediaStorage ms; ms.SetFromFile( reader.GetFile() ); int ret; if( ms == gdcm::MediaStorage::RTStructureSetStorage ) { ret = this->RequestData_RTStructureSetStorage(reader, outputVector); } else if( ms == gdcm::MediaStorage::HemodynamicWaveformStorage) { ret = this->RequestData_HemodynamicWaveformStorage(reader, outputVector); } else { // not handled assume error ret = 0; } return ret; } int vtkGDCMPolyDataReader::RequestInformation_RTStructureSetStorage(gdcm::Reader const & reader) { const gdcm::DataSet& ds = reader.GetFile().GetDataSet(); // (3006,0020) SQ (Sequence with explicit length #=4) # 370, 1 StructureSetROISequence gdcm::Tag tssroisq(0x3006,0x0020); if( !ds.FindDataElement( tssroisq ) ) { return 0; } const gdcm::DataElement &ssroisq = ds.GetDataElement( tssroisq ); //const gdcm::SequenceOfItems *sqi = ssroisq.GetSequenceOfItems(); gdcm::SmartPointer sqi = ssroisq.GetValueAsSQ(); if( !sqi || !sqi->GetNumberOfItems() ) { return 0; } size_t npds = sqi->GetNumberOfItems(); //std::cout << "Nb pd:" << npds << std::endl; this->SetNumberOfOutputPorts( (int)npds ); // Allocate for(unsigned int i = 1; i < npds; ++i) // first output is allocated for us { vtkPolyData *output2 = vtkPolyData::New(); this->GetExecutive()->SetOutputData(i, output2); output2->Delete(); } return 1; } int vtkGDCMPolyDataReader::RequestInformation_HemodynamicWaveformStorage(gdcm::Reader const & ) { return 1; } //---------------------------------------------------------------------------- int vtkGDCMPolyDataReader::RequestInformation( vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *vtkNotUsed(outputVector)) { // get the info object // vtkInformation *outInfo = outputVector->GetInformationObject(0); // // outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), // -1); gdcm::Reader reader; reader.SetFileName( this->FileName ); if( !reader.Read() ) { return 0; } gdcm::MediaStorage ms; ms.SetFromFile( reader.GetFile() ); int ret; if( ms == gdcm::MediaStorage::RTStructureSetStorage ) { ret = this->RequestInformation_RTStructureSetStorage(reader); } else if( ms == gdcm::MediaStorage::HemodynamicWaveformStorage) { ret = this->RequestInformation_HemodynamicWaveformStorage(reader); } else { // not handled assume error ret = 0; } if( ret ) { // Ok let's fill in the 'extra' info: this->FillMedicalImageInformation(reader); } return ret; } //---------------------------------------------------------------------------- void vtkGDCMPolyDataReader::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "File Name: " << (this->FileName ? this->FileName : "(none)") << "\n"; } GDCM-3.0.10/Utilities/VTK/vtkGDCMPolyDataReader.h000066400000000000000000000056311412732066400211270ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // .NAME vtkGDCMPolyDataReader - read DICOM PolyData files (Contour Data...) // .SECTION Description // For now only support RTSTRUCT (RT Structure Set Storage) // .SECTION TODO // Need to do the same job for DVH Sequence/DVH Data... // .SECTION Warning // When using vtkGDCMPolyDataReader in conjonction with vtkGDCMImageReader // it is *required* that FileLowerLeft is set to ON as coordinate system // would be inconsistent in between the two data structures. // // .SECTION See Also // vtkGDCMImageReader vtkGDCMPolyDataWriter vtkRTStructSetProperties #ifndef VTKGDCMPOLYDATAREADER_H #define VTKGDCMPOLYDATAREADER_H #include "vtkPolyDataAlgorithm.h" class vtkMedicalImageProperties; class vtkRTStructSetProperties; //BTX namespace gdcm { class Reader; } //ETX class VTK_EXPORT vtkGDCMPolyDataReader : public vtkPolyDataAlgorithm { public: static vtkGDCMPolyDataReader *New(); vtkTypeMacro(vtkGDCMPolyDataReader,vtkPolyDataAlgorithm); virtual void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the filename of the file to be read vtkSetStringMacro(FileName); vtkGetStringMacro(FileName); // Description: // Get the medical image properties object vtkGetObjectMacro(MedicalImageProperties, vtkMedicalImageProperties); vtkGetObjectMacro(RTStructSetProperties, vtkRTStructSetProperties); protected: vtkGDCMPolyDataReader(); ~vtkGDCMPolyDataReader(); char *FileName; vtkMedicalImageProperties *MedicalImageProperties; vtkRTStructSetProperties *RTStructSetProperties; //BTX void FillMedicalImageInformation(const gdcm::Reader &reader); //ETX int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); int RequestInformation( vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector); //BTX int RequestInformation_RTStructureSetStorage(gdcm::Reader const & reader); int RequestData_RTStructureSetStorage(gdcm::Reader const &reader, vtkInformationVector *outputVector); int RequestInformation_HemodynamicWaveformStorage(gdcm::Reader const & reader); int RequestData_HemodynamicWaveformStorage(gdcm::Reader const &reader, vtkInformationVector *outputVector); //ETX private: vtkGDCMPolyDataReader(const vtkGDCMPolyDataReader&); // Not implemented. void operator=(const vtkGDCMPolyDataReader&); // Not implemented. }; #endif GDCM-3.0.10/Utilities/VTK/vtkGDCMPolyDataWriter.cxx000066400000000000000000000756351412732066400215670ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMPolyDataWriter.h" #include "vtkObjectFactory.h" #include "vtkInformation.h" #include "vtkDoubleArray.h" #include "vtkPointData.h" #include "vtkInformationVector.h" #include "vtkPolyData.h" #include "vtkStreamingDemandDrivenPipeline.h" #include "vtkFloatArray.h" #include "vtkCellArray.h" #include "vtkCellData.h" #include "vtkErrorCode.h" #include "vtkMedicalImageProperties.h" #include "vtkRTStructSetProperties.h" #include "vtkVersion.h" #include "gdcmSystem.h" #include "gdcmWriter.h" #include "gdcmUIDs.h" #include "gdcmUIDGenerator.h" #include "gdcmSmartPointer.h" #include "gdcmAttribute.h" #include "gdcmSmartPointer.h" #include "gdcmSequenceOfItems.h" #include "gdcmAnonymizer.h" #include "gdcmIPPSorter.h" #include "gdcmAttribute.h" #include "gdcmDirectoryHelper.h" //vtkCxxRevisionMacro(vtkGDCMPolyDataWriter, "$Revision: 1.74 $") vtkStandardNewMacro(vtkGDCMPolyDataWriter) vtkCxxSetObjectMacro(vtkGDCMPolyDataWriter,MedicalImageProperties,vtkMedicalImageProperties) vtkCxxSetObjectMacro(vtkGDCMPolyDataWriter,RTStructSetProperties,vtkRTStructSetProperties) //---------------------------------------------------------------------------- vtkGDCMPolyDataWriter::vtkGDCMPolyDataWriter() { this->SetNumberOfInputPorts(1); this->MedicalImageProperties = vtkMedicalImageProperties::New(); this->RTStructSetProperties = vtkRTStructSetProperties::New(); } //---------------------------------------------------------------------------- vtkGDCMPolyDataWriter::~vtkGDCMPolyDataWriter() { this->MedicalImageProperties->Delete(); this->RTStructSetProperties->Delete(); } static void SetStringValueFromTag(const char *s, const gdcm::Tag& t, gdcm::Anonymizer & ano) { if( s && *s ) { #if 0 gdcm::DataElement de( t ); de.SetByteValue( s, strlen( s ) ); const gdcm::Global& g = gdcm::Global::GetInstance(); const gdcm::Dicts &dicts = g.GetDicts(); // FIXME: we know the tag at compile time we could save some time // Using the static dict instead of the run-time one: const gdcm::DictEntry &dictentry = dicts.GetDictEntry( t ); de.SetVR( dictentry.GetVR() ); ds.Insert( de ); #else ano.Replace(t, s); #endif } } using namespace gdcm; //---------------------------------------------------------------------------- void vtkGDCMPolyDataWriter::WriteData() { if ( this->FileName == NULL) { vtkErrorMacro(<< "Please specify FileName to write"); this->SetErrorCode(vtkErrorCode::NoFileNameError); return; } Writer writer; writer.SetFileName( this->FileName ); File &file = writer.GetFile(); this->WriteRTSTRUCTInfo(file); int numInputs = this->GetNumberOfInputPorts(); for(int input = 0; input < numInputs; ++input ) { this->WriteRTSTRUCTData(file, input); } if( !writer.Write() ) { vtkErrorMacro(<< "Could not write"); this->SetErrorCode(vtkErrorCode::FileFormatError); return; } } //---------------------------------------------------------------------------- void vtkGDCMPolyDataWriter::WriteRTSTRUCTInfo(gdcm::File &file) { DataSet& ds = file.GetDataSet(); { const Tag sisq(0x3006,0x0039); DataElement de( sisq ); de.SetVR( VR::SQ ); SmartPointer sqi1 = 0; sqi1 = new SequenceOfItems; de.SetValue( *sqi1 ); de.SetVLToUndefined(); ds.Insert( de ); } UIDGenerator uid; { const char *sop = uid.Generate(); DataElement de( Tag(0x0008,0x0018) ); VL::Type strlenSOP = (VL::Type) strlen(sop); de.SetByteValue( sop, strlenSOP ); de.SetVR( Attribute<0x0008, 0x0018>::GetVR() ); ds.ReplaceEmpty( de ); } { //this is incorrect. //the study MUST be the same as the image from which this object is derived. // const char *study = uid.Generate(); // DataElement de( Tag(0x0020,0x000d) ); // VL::Type strlenStudy= (VL::Type)strlen(study); // de.SetByteValue( study, strlenStudy ); // de.SetVR( Attribute<0x0020, 0x000d>::GetVR() ); // ds.ReplaceEmpty( de ); } { const char *series = uid.Generate(); DataElement de( Tag(0x0020,0x000e) ); VL::Type strlenSeries= (VL::Type)strlen(series); de.SetByteValue( series, strlenSeries ); de.SetVR( Attribute<0x0020, 0x000e>::GetVR() ); ds.ReplaceEmpty( de ); } FileMetaInformation &fmi = file.GetHeader(); TransferSyntax ts = TransferSyntax::ImplicitVRLittleEndian; { const char *tsuid = TransferSyntax::GetTSString( ts ); DataElement de( Tag(0x0002,0x0010) ); VL::Type strlenTSUID = (VL::Type)strlen(tsuid); de.SetByteValue( tsuid, strlenTSUID ); de.SetVR( Attribute<0x0002, 0x0010>::GetVR() ); fmi.Replace( de ); fmi.SetDataSetTransferSyntax(ts); } MediaStorage ms = MediaStorage::RTStructureSetStorage ; const char* msstr = MediaStorage::GetMSString(ms); { DataElement de( Tag(0x0008, 0x0016 ) ); VL::Type strlenMsstr = (VL::Type)strlen(msstr); de.SetByteValue( msstr, strlenMsstr); de.SetVR( Attribute<0x0008, 0x0016>::GetVR() ); ds.Insert( de ); } int year, month, day; gdcm::Anonymizer ano; ano.SetFile( file ); SetStringValueFromTag(this->RTStructSetProperties->GetStructureSetLabel(), gdcm::Tag(0x3006,0x0002), ano); SetStringValueFromTag(this->RTStructSetProperties->GetStructureSetName(), gdcm::Tag(0x3006,0x0004), ano); SetStringValueFromTag(this->RTStructSetProperties->GetStructureSetDate(), gdcm::Tag(0x3006,0x0008), ano); SetStringValueFromTag(this->RTStructSetProperties->GetStructureSetTime(), gdcm::Tag(0x3006,0x0009), ano); SetStringValueFromTag(this->RTStructSetProperties->GetSOPInstanceUID(), gdcm::Tag(0x0008,0x0018), ano); SetStringValueFromTag(this->RTStructSetProperties->GetStudyInstanceUID(), gdcm::Tag(0x0020,0x000d), ano); SetStringValueFromTag(this->RTStructSetProperties->GetSeriesInstanceUID(), gdcm::Tag(0x0020,0x000e), ano); { SmartPointer sqi; sqi = new SequenceOfItems; vtkIdType n = this->RTStructSetProperties->GetNumberOfReferencedFrameOfReferences(); for( vtkIdType id = 0; id < n; ++id ) { const char *sopclass = this->RTStructSetProperties->GetReferencedFrameOfReferenceClassUID(id); const char *instanceuid = this->RTStructSetProperties->GetReferencedFrameOfReferenceInstanceUID(id); Item item; item.SetVLToUndefined(); DataSet &subds = item.GetNestedDataSet(); { Attribute<0x0008,0x1150> at; at.SetValue( sopclass ); subds.Insert( at.GetAsDataElement() ); } { Attribute<0x0008,0x1155> at; at.SetValue( instanceuid ); subds.Insert( at.GetAsDataElement() ); } sqi->AddItem( item ); } DataElement de1( Tag(0x3006,0x0010) ); de1.SetVR( VR::SQ ); SmartPointer sqi1 = new SequenceOfItems; de1.SetValue( *sqi1 ); de1.SetVLToUndefined(); ds.Insert( de1 ); Item item1; item1.SetVLToUndefined(); DataSet &ds2 = item1.GetNestedDataSet(); gdcm::Attribute<0x0020,0x052> frameofreferenceuid; if( this->RTStructSetProperties->GetReferenceFrameOfReferenceUID() ) frameofreferenceuid.SetValue( this->RTStructSetProperties->GetReferenceFrameOfReferenceUID() ); ds2.Insert( frameofreferenceuid.GetAsDataElement() ); DataElement de2( Tag(0x3006,0x0012) ); de2.SetVR( VR::SQ ); SmartPointer sqi2 = new SequenceOfItems; de2.SetValue( *sqi2 ); de2.SetVLToUndefined(); ds2.Insert( de2 ); Item item2; item2.SetVLToUndefined(); DataSet &ds3 = item2.GetNestedDataSet(); Attribute<0x0008,0x1150> refsopclassuid; const char *rtuid = gdcm::UIDs::GetUIDString( gdcm::UIDs::RTStructureSetStorage); refsopclassuid.SetValue ( rtuid ); ds3.Insert( refsopclassuid.GetAsDataElement() ); Attribute<0x0008,0x1155> refsopinstuid; if( this->RTStructSetProperties->GetStudyInstanceUID() ) refsopinstuid.SetValue ( this->RTStructSetProperties->GetStudyInstanceUID() ); ds3.Insert( refsopinstuid.GetAsDataElement() ); DataElement de3( Tag(0x3006,0x0014) ); de3.SetVR( VR::SQ ); SmartPointer sqi3 = new SequenceOfItems; de3.SetValue( *sqi3 ); de3.SetVLToUndefined(); ds3.Insert( de3 ); Item item3; item3.SetVLToUndefined(); DataSet &ds4 = item3.GetNestedDataSet(); gdcm::Attribute<0x0020,0x000e> seriesinstanceuid; if ( this->RTStructSetProperties->GetReferenceSeriesInstanceUID() ) seriesinstanceuid.SetValue( this->RTStructSetProperties->GetReferenceSeriesInstanceUID() ); ds4.Insert( seriesinstanceuid.GetAsDataElement() ); DataElement de4( Tag(0x3006,0x0016) ); de4.SetVR( VR::SQ ); //SmartPointer sqi4 = new SequenceOfItems; de4.SetValue( *sqi ); de4.SetVLToUndefined(); ds4.Insert( de4 ); //Item item4; //item4.SetVLToUndefined(); //DataSet &ds5 = item4.GetNestedDataSet(); //sqi4->AddItem( item4 ); sqi3->AddItem( item3 ); sqi2->AddItem( item2 ); sqi1->AddItem( item1 ); } { SmartPointer sqi; sqi = new SequenceOfItems; SmartPointer sqiobs; sqiobs = new SequenceOfItems; vtkIdType n = this->RTStructSetProperties->GetNumberOfStructureSetROIs(); for( vtkIdType id = 0; id < n; ++id ) { int roinumber = this->RTStructSetProperties->GetStructureSetROINumber(id); const char *refframerefuid = this->RTStructSetProperties->GetStructureSetROIRefFrameRefUID(id); const char *roiname = this->RTStructSetProperties->GetStructureSetROIName(id); const char *roigenalgo = this->RTStructSetProperties->GetStructureSetROIGenerationAlgorithm(id); const char *roidesc = this->RTStructSetProperties->GetStructureSetROIDescription(id); Item item; item.SetVLToUndefined(); DataSet &subds = item.GetNestedDataSet(); gdcm::Attribute<0x3006,0x0022> atroinumber; atroinumber.SetValue( roinumber ); subds.Insert( atroinumber.GetAsDataElement() ); gdcm::Attribute<0x3006,0x0024> atrefframeuid; atrefframeuid.SetValue( refframerefuid ); subds.Insert( atrefframeuid.GetAsDataElement() ); gdcm::Attribute<0x3006,0x0026> atroiname; atroiname.SetValue( roiname ); subds.Insert( atroiname.GetAsDataElement() ); if( roidesc && *roidesc ) { gdcm::Attribute<0x3006,0x0028> atroidesc; atroidesc.SetValue( roidesc ); subds.Insert( atroidesc.GetAsDataElement() ); } gdcm::Attribute<0x3006,0x0036> atroigenalg; atroigenalg.SetValue( roigenalgo ); subds.Insert( atroigenalg.GetAsDataElement() ); // do the obs stuff Item itemobs; itemobs.SetVLToUndefined(); DataSet &subdsobs = itemobs.GetNestedDataSet(); int observationnumber = this->RTStructSetProperties->GetStructureSetObservationNumber(id); gdcm::Attribute<0x3006,0x0082> atobservationnumber; atobservationnumber.SetValue( observationnumber ); subdsobs.Insert( atobservationnumber.GetAsDataElement() ); gdcm::Attribute<0x3006,0x0084> atreferencedroinumber; atreferencedroinumber.SetValue( roinumber ); subdsobs.Insert( atreferencedroinumber.GetAsDataElement() ); const char *roiobservationlabel = this->RTStructSetProperties->GetStructureSetROIObservationLabel(id); if( roiobservationlabel && *roiobservationlabel ) { gdcm::Attribute<0x3006,0x0085> atroiobservationlabel; atroiobservationlabel.SetValue( roiobservationlabel ); subdsobs.Insert( atroiobservationlabel.GetAsDataElement() ); } const char *rtroiinterpretedtype = this->RTStructSetProperties->GetStructureSetRTROIInterpretedType(id); gdcm::Attribute<0x3006,0x00a4> atrtroiinterpretedtype; atrtroiinterpretedtype.SetValue( rtroiinterpretedtype ); subdsobs.Insert( atrtroiinterpretedtype.GetAsDataElement() ); gdcm::Attribute<0x3006,0x00a6> atroiinterpreter; //atroiinterpreter.SetValue( rtroiinterpretedtype ); subdsobs.Insert( atroiinterpreter.GetAsDataElement() ); sqiobs->AddItem( itemobs ); sqi->AddItem( item ); } DataElement de1( Tag(0x3006,0x0020) ); de1.SetVR( VR::SQ ); de1.SetValue( *sqi ); de1.SetVLToUndefined(); ds.Insert( de1 ); DataElement de2( Tag(0x3006,0x0080) ); de2.SetVR( VR::SQ ); de2.SetValue( *sqiobs ); de2.SetVLToUndefined(); ds.Insert( de2 ); } // For ex: DICOM (0010,0010) = DOE,JOHN SetStringValueFromTag(this->MedicalImageProperties->GetPatientName(), gdcm::Tag(0x0010,0x0010), ano); // For ex: DICOM (0010,0020) = 1933197 SetStringValueFromTag( this->MedicalImageProperties->GetPatientID(), gdcm::Tag(0x0010,0x0020), ano); // For ex: DICOM (0010,1010) = 031Y SetStringValueFromTag( this->MedicalImageProperties->GetPatientAge(), gdcm::Tag(0x0010,0x1010), ano); // For ex: DICOM (0010,0040) = M SetStringValueFromTag( this->MedicalImageProperties->GetPatientSex(), gdcm::Tag(0x0010,0x0040), ano); // For ex: DICOM (0010,0030) = 19680427 SetStringValueFromTag( this->MedicalImageProperties->GetPatientBirthDate(), gdcm::Tag(0x0010,0x0030), ano); #if VTK_MAJOR_VERSION >= 6 || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) // For ex: DICOM (0008,0020) = 20030617 if( vtkMedicalImageProperties::GetDateAsFields( this->MedicalImageProperties->GetStudyDate(), year, month, day ) ) SetStringValueFromTag( this->MedicalImageProperties->GetStudyDate(), gdcm::Tag(0x0008,0x0020), ano); #endif // For ex: DICOM (0008,0022) = 20030617 SetStringValueFromTag( this->MedicalImageProperties->GetAcquisitionDate(), gdcm::Tag(0x0008,0x0022), ano); #if VTK_MAJOR_VERSION >= 6 || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 ) // For ex: DICOM (0008,0030) = 162552.0705 or 230012, or 0012 #if VTK_MAJOR_VERSION >= 6 || ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 4 ) int hour, minute, second; if( vtkMedicalImageProperties::GetTimeAsFields( this->MedicalImageProperties->GetStudyTime(), hour, minute, second ) ) #endif SetStringValueFromTag( this->MedicalImageProperties->GetStudyTime(), gdcm::Tag(0x0008,0x0030), ano); #endif // For ex: DICOM (0008,0032) = 162552.0705 or 230012, or 0012 SetStringValueFromTag( this->MedicalImageProperties->GetAcquisitionTime(), gdcm::Tag(0x0008,0x0032), ano); // For ex: DICOM (0008,0023) = 20030617 SetStringValueFromTag( this->MedicalImageProperties->GetImageDate(), gdcm::Tag(0x0008,0x0023), ano); // For ex: DICOM (0008,0033) = 162552.0705 or 230012, or 0012 SetStringValueFromTag( this->MedicalImageProperties->GetImageTime(), gdcm::Tag(0x0008,0x0033), ano); // For ex: DICOM (0020,0013) = 1 SetStringValueFromTag( this->MedicalImageProperties->GetImageNumber(), gdcm::Tag(0x0020,0x0013), ano); // For ex: DICOM (0020,0011) = 902 SetStringValueFromTag( this->MedicalImageProperties->GetSeriesNumber(), gdcm::Tag(0x0020,0x0011), ano); // For ex: DICOM (0008,103e) = SCOUT SetStringValueFromTag( this->MedicalImageProperties->GetSeriesDescription(), gdcm::Tag(0x0008,0x103e), ano); // For ex: DICOM (0020,0010) = 37481 SetStringValueFromTag( this->MedicalImageProperties->GetStudyID(), gdcm::Tag(0x0020,0x0010), ano); // For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL SetStringValueFromTag( this->MedicalImageProperties->GetStudyDescription(), gdcm::Tag(0x0008,0x1030), ano); // For ex: DICOM (0008,0060)= CT SetStringValueFromTag( this->MedicalImageProperties->GetModality(), gdcm::Tag(0x0008,0x0060), ano); // For ex: DICOM (0008,0070) = Siemens SetStringValueFromTag( this->MedicalImageProperties->GetManufacturer(), gdcm::Tag(0x0008,0x0070), ano); // For ex: DICOM (0008,1090) = LightSpeed QX/i SetStringValueFromTag( this->MedicalImageProperties->GetManufacturerModelName(), gdcm::Tag(0x0008,0x1090), ano); // For ex: DICOM (0008,1010) = LSPD_OC8 SetStringValueFromTag( this->MedicalImageProperties->GetStationName(), gdcm::Tag(0x0008,0x1010), ano); // For ex: DICOM (0008,0080) = FooCity Medical Center SetStringValueFromTag( this->MedicalImageProperties->GetInstitutionName(), gdcm::Tag(0x0008,0x0080), ano); // For ex: DICOM (0018,1210) = Bone SetStringValueFromTag( this->MedicalImageProperties->GetConvolutionKernel(), gdcm::Tag(0x0018,0x1210), ano); // For ex: DICOM (0018,0050) = 0.273438 SetStringValueFromTag( this->MedicalImageProperties->GetSliceThickness(), gdcm::Tag(0x0018,0x0050), ano); // For ex: DICOM (0018,0060) = 120 SetStringValueFromTag( this->MedicalImageProperties->GetKVP(), gdcm::Tag(0x0018,0x0060), ano); // For ex: DICOM (0018,1120) = 15 SetStringValueFromTag( this->MedicalImageProperties->GetGantryTilt(), gdcm::Tag(0x0018,0x1120), ano); // For ex: DICOM (0018,0081) = 105 SetStringValueFromTag( this->MedicalImageProperties->GetEchoTime(), gdcm::Tag(0x0018,0x0081), ano); // For ex: DICOM (0018,0091) = 35 SetStringValueFromTag( this->MedicalImageProperties->GetEchoTrainLength(), gdcm::Tag(0x0018,0x0091), ano); // For ex: DICOM (0018,0080) = 2040 SetStringValueFromTag( this->MedicalImageProperties->GetRepetitionTime(), gdcm::Tag(0x0018,0x0080), ano); // For ex: DICOM (0018,1150) = 5 SetStringValueFromTag( this->MedicalImageProperties->GetExposureTime(), gdcm::Tag(0x0018,0x1150), ano); // For ex: DICOM (0018,1151) = 400 SetStringValueFromTag( this->MedicalImageProperties->GetXRayTubeCurrent(), gdcm::Tag(0x0018,0x1151), ano); // For ex: DICOM (0018,1152) = 114 SetStringValueFromTag( this->MedicalImageProperties->GetExposure(), gdcm::Tag(0x0018,0x1152), ano); } //---------------------------------------------------------------------------- void vtkGDCMPolyDataWriter::WriteRTSTRUCTData(gdcm::File &file, int pdidx ) { vtkPolyData *input = this->GetInput(pdidx); assert( input ); vtkPoints *pts; vtkCellArray *polys; polys = input->GetPolys(); vtkCellArray* lines = input->GetLines(); pts = input->GetPoints(); vtkDataArray *scalars = input->GetCellData()->GetScalars(); vtkDoubleArray *darray = vtkDoubleArray::SafeDownCast( scalars ); vtkFloatArray *farray = vtkFloatArray::SafeDownCast( scalars ); if (pts == NULL || polys == NULL || lines == NULL) { vtkWarningMacro(<<"No data to write!");//should be a warning, not an error, because //it's entirely possible to have a blank ROI //return;//ok, you have to put the observation here, even if it's blank //if it's blank, the color and so forth are still defined. Otherwise, //the observation will be incomplete. } /* (3006,0039) ?? (SQ) # u/l,1 ROI Contour Sequence (fffe,e000) na (Item with undefined length) (3006,002a) ?? (IS) [220\160\120 ] # 12,3 ROI Display Color (3006,0040) ?? (SQ) # u/l,1 Contour Sequence (fffe,e000) na (Item with undefined length) (3006,0016) ?? (SQ) # u/l,1 Contour Image Sequence (fffe,e000) na (Item with undefined length) (0008,1150) ?? (UI) [1.2.840.10008.5.1.4.1.1.2] # 26,1 Referenced SOP Class UID (0008,1155) ?? (UI) [1.3.6.1.4.1.22213.1.1396.148] # 28,1 Referenced SOP Instance UID (fffe,e00d) (fffe,e0dd) (3006,0042) ?? (CS) [CLOSED_PLANAR ] # 14,1 Contour Geometric Type (3006,0046) ?? (IS) [139 ] # 4,1 Number of Contour Points (3006,0050) ?? (DS) [-209.81171875\-392.41171875\...] # 5004,3-3n Contour Data (fffe,e00d) */ SmartPointer sqi; sqi = new SequenceOfItems; vtkIdType npts = 0; vtkIdType *indx = 0; double v[3]; unsigned int cellnum = 0; //choose to use either polys or lines //the result of vtk marching cubes->stripper->appendpolydata is a set of lines, //not polys, so favor that one for now. //choose by the number of polys/lines available. vtkCellArray* theCells = lines; if (!lines || lines->GetNumberOfCells() == 0){ theCells = polys; } std::vector cellpoints; for (theCells->InitTraversal(); theCells->GetNextCell(npts,indx); cellnum++ ){ cellpoints.resize(0); for(vtkIdType index = 0; index < npts; ++index){ pts->GetPoint(indx[index],v); //precision problems are _definitely_ here by this point //this a crude hack to the get the 9999's under control, //or pollution by switching from doubles to floats and back again //cellpoints.push_back( (double)((int)(v[0]*10000.0))/10000.0 ); //cellpoints.push_back( (double)((int)(v[1]*10000.0))/10000.0 ); //cellpoints.push_back( (double)((int)(v[2]*10000.0))/10000.0 ); cellpoints.push_back( v[0] ); cellpoints.push_back( v[1] ); cellpoints.push_back( v[2 ]); } Item item0; item0.SetVLToUndefined(); DataSet &subds0 = item0.GetNestedDataSet(); Attribute<0x3006,0x0050> at; at.SetValues( &cellpoints[0], (unsigned int)cellpoints.size(), false ); subds0.Insert( at.GetAsDataElement() ); Attribute<0x3006,0x0046> numcontpoints; numcontpoints.SetValue( (int)npts ); subds0.Insert( numcontpoints.GetAsDataElement() ); Attribute<0x3006,0x0042> contgeotype; contgeotype.SetValue( "CLOSED_PLANAR " ); subds0.Insert( contgeotype.GetAsDataElement() ); SmartPointer thesqi = new SequenceOfItems; { Item item; item.SetVLToUndefined(); DataSet &subds = item.GetNestedDataSet(); gdcm::Attribute<0x0008,0x1150> classat; classat.SetValue ( this->RTStructSetProperties-> GetContourReferencedFrameOfReferenceClassUID( pdidx, cellnum )); subds.Insert( classat.GetAsDataElement() ); gdcm::Attribute<0x0008,0x1155> instat; instat.SetValue ( this->RTStructSetProperties-> GetContourReferencedFrameOfReferenceInstanceUID( pdidx, cellnum )); subds.Insert( instat.GetAsDataElement() ); thesqi->AddItem( item ); } DataElement contimsq = DataElement( Tag(0x3006,0x0016) ); contimsq.SetVR( VR::SQ ); contimsq.SetValue( *thesqi ); contimsq.SetVLToUndefined(); subds0.Insert( contimsq ); sqi->AddItem( item0 ); } DataSet& ds = file.GetDataSet(); { const Tag sisq(0x3006,0x0039); SmartPointer sqi1 = 0; sqi1 = ds.GetDataElement( sisq ).GetValueAsSQ(); assert( sqi1 ); Item item; item.SetVLToUndefined(); DataSet &subds = item.GetNestedDataSet(); gdcm::Attribute<0x3006,0x0084> referencedroinumber; //referencedroinumber.SetValue ( pdidx ); referencedroinumber.SetValue( this->RTStructSetProperties->GetStructureSetROINumber(pdidx) ); subds.Insert( referencedroinumber.GetAsDataElement() ); //(3006,002a) IS [220\160\120] # 12, 3 ROIDisplayColor gdcm::Attribute<0x3006,0x002a> roidispcolor; int32_t intcolor[3] = {0,0,0}; //assert( darray || farray ); if( darray ) { double tuple[3]; #if VTK_MAJOR_VERSION > 7 || (VTK_MAJOR_VERSION == 7 && VTK_MINOR_VERSION >= 1) darray->GetTypedTuple( 0, tuple ); #else darray->GetTupleValue( 0, tuple ); #endif intcolor[0] = (int32_t)(tuple[0] * 255.); intcolor[1] = (int32_t)(tuple[1] * 255.); intcolor[2] = (int32_t)(tuple[2] * 255.); } else if( farray ) { float ftuple[3]; #if VTK_MAJOR_VERSION > 7 || (VTK_MAJOR_VERSION == 7 && VTK_MINOR_VERSION >= 1) farray->GetTypedTuple( 0, ftuple ); #else farray->GetTupleValue( 0, ftuple ); #endif intcolor[0] = (int32_t)(ftuple[0] * 255.); intcolor[1] = (int32_t)(ftuple[1] * 255.); intcolor[2] = (int32_t)(ftuple[2] * 255.); } else { vtkDebugMacro( "No color" ); } roidispcolor.SetValues( intcolor, 3 ); subds.Insert( roidispcolor.GetAsDataElement() ); if( sqi->GetNumberOfItems() ) { const Tag sisq2(0x3006,0x0040); DataElement de2( sisq2 ); de2.SetVR( VR::SQ ); de2.SetValue( *sqi ); de2.SetVLToUndefined(); subds.Insert( de2 ); } sqi1->AddItem( item ); } } //---------------------------------------------------------------------------- void vtkGDCMPolyDataWriter::SetNumberOfInputPorts(int n) { Superclass::SetNumberOfInputPorts(n); } //---------------------------------------------------------------------------- void vtkGDCMPolyDataWriter::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } //this function will initialize the contained rtstructset with //the inputs of the writer and the various extra information //necessary for writing a complete rtstructset. //NOTE: inputs must be set BEFORE calling this function! //NOTE: the number of outputs for the appendpolydata MUST MATCH the organ vectors! void vtkGDCMPolyDataWriter::InitializeRTStructSet(vtkStdString inDirectory, vtkStdString inStructLabel, vtkStdString inStructName, vtkStringArray* inROINames, vtkStringArray* inROIAlgorithmName, vtkStringArray* inROIType) { gdcm::Directory::FilenamesType theCTSeries = gdcm::DirectoryHelper::GetCTImageSeriesUIDs(inDirectory); if (theCTSeries.size() > 1) { gdcmWarningMacro("More than one CT series detected, only reading series UID: " << theCTSeries[0]); } if (theCTSeries.empty()) { gdcmWarningMacro("No CT Series found, trying MR."); theCTSeries = gdcm::DirectoryHelper::GetMRImageSeriesUIDs(inDirectory); if (theCTSeries.size() > 1) { gdcmWarningMacro("More than one MR series detected, only reading series UID: " << theCTSeries[0]); } if (theCTSeries.empty()) { gdcmWarningMacro("No CT or MR series found, throwing."); return;// false; } } //load the images in the CT series std::vector theCTDataSets = gdcm::DirectoryHelper::LoadImageFromFiles(inDirectory, theCTSeries[0]); if (theCTDataSets.empty()) { gdcmWarningMacro("No CT or MR Images loaded, throwing."); return;// false; } //now, armed with this set of images, we can begin to properly construct the RTStructureSet vtkRTStructSetProperties* theRTStruct = RTStructSetProperties;//initially, this function was a static construction //but that doesn't jive with swig wrapping easily theRTStruct->SetStructureSetLabel(inStructLabel.c_str()); theRTStruct->SetStructureSetName(inStructName.c_str()); //theRTStruct->SetSOPInstanceUID(<#const char *_arg#>);//should be autogenerated by the object itself { const ByteValue* theValue = theCTDataSets[0].FindNextDataElement(Tag(0x0020,0x000d)).GetByteValue(); std::string theStringValue(theValue->GetPointer(), theValue->GetLength()); theRTStruct->SetStudyInstanceUID(theStringValue.c_str()); } { const ByteValue* theValue = theCTDataSets[0].FindNextDataElement(Tag(0x0020,0x000e)).GetByteValue(); std::string theStringValue(theValue->GetPointer(), theValue->GetLength()); theRTStruct->SetReferenceSeriesInstanceUID(theStringValue.c_str()); } { const ByteValue* theValue = theCTDataSets[0].FindNextDataElement(Tag(0x0020,0x0052)).GetByteValue(); std::string theStringValue(theValue->GetPointer(), theValue->GetLength()); theRTStruct->SetReferenceFrameOfReferenceUID(theStringValue.c_str()); } //the series UID should be set automatically, and happen during creation //set the date and time to be now char date[22]; const size_t datelen = 8; int res = System::GetCurrentDateTime(date); assert( res ); (void)res;//warning removal//causes java wrapping to fail //the date is the first 8 chars std::string dateString; dateString.insert(dateString.begin(), &(date[0]), &(date[datelen])); theRTStruct->SetStructureSetDate(dateString.c_str()); std::string timeString; const size_t timelen = 6; //for now, only need hhmmss timeString.insert(timeString.begin(), &(date[datelen]), &(date[datelen+timelen])); theRTStruct->SetStructureSetTime(timeString.c_str()); //for each image, we need to fill in the sop class and instance UIDs for the frame of reference std::string theSOPClassID = DirectoryHelper::GetSOPClassUID(theCTDataSets).c_str(); for (unsigned long i = 0; i < theCTDataSets.size(); i++) { theRTStruct->AddReferencedFrameOfReference(theSOPClassID.c_str(), DirectoryHelper::RetrieveSOPInstanceUIDFromIndex((int)i,theCTDataSets).c_str()); } //now, we have go to through each vtkPolyData, assign the ROI names per polydata, and then also assign the //reference SOP instance UIDs on a per-plane basis. int theNumPorts = GetNumberOfInputPorts(); for (int j = 0; j < theNumPorts; j++) { int contour = j; theRTStruct->AddStructureSetROI(contour, theRTStruct->GetReferenceFrameOfReferenceUID(), inROINames->GetValue(j).c_str(), inROIAlgorithmName->GetValue(j).c_str()); theRTStruct->AddStructureSetROIObservation(contour, contour, inROIType->GetValue(j).c_str(), ""); //for each organ, gotta go through and add in the right planes in the //order that the tuples appear, as well as the colors //right now, each cell in the vtkpolydata is a contour in an xy plane //that's what MUST be passed in vtkPolyData* theData = dynamic_cast(GetInput(j)); if (theData == NULL) { gdcmWarningMacro("theData for input " << j << " is NULL, continuing"); continue; } unsigned int cellnum = 0; vtkPoints *pts; vtkCellArray *polys; vtkIdType npts = 0; vtkIdType *indx = 0; pts = theData->GetPoints(); polys = theData->GetPolys(); vtkCellArray* lines = theData->GetLines(); //choose to use either polys or lines //the result of vtk marching cubes->stripper->appendpolydata is a set of lines, //not polys, so favor that one for now. //choose by the number of polys/lines available. vtkCellArray* theCells = lines; if (!lines || lines->GetNumberOfCells() == 0) { theCells = polys; } double v[3]; vtkIdType theNumCells = theCells->GetNumberOfCells(); gdcmDebugMacro("The number of cells:" << theNumCells); if (theNumCells == 0) continue;// no observation of blank organs for (theCells->InitTraversal(); theCells->GetNextCell(npts,indx); cellnum++ ) { if (npts < 1) { gdcmWarningMacro("theCells for input " << j << " is less than 1, continuing"); continue; } pts->GetPoint(indx[0],v); double theZ = v[2]; std::string theSOPInstance = DirectoryHelper::RetrieveSOPInstanceUIDFromZPosition(theZ, theCTDataSets); //j is correct here, because it's adding, as in there's an internal vector //that's growing. gdcmDebugMacro("SOP Instance for plane " << theZ << " is " << theSOPInstance); theRTStruct->AddContourReferencedFrameOfReference(contour, theSOPClassID.c_str(), theSOPInstance.c_str()); } } } GDCM-3.0.10/Utilities/VTK/vtkGDCMPolyDataWriter.h000066400000000000000000000055301412732066400211770ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // .NAME vtkGDCMPolyDataWriter - writer DICOM PolyData files (Contour Data...) // .SECTION Description // For now only support RTSTRUCT (RT Structure Set Storage) // .SECTION TODO // Need to do the same job for DVH Sequence/DVH Data... // .SECTION Warning // // .SECTION See Also // vtkGDCMImageReader vtkGDCMPolyDataReader vtkRTStructSetProperties #ifndef VTKGDCMPOLYDATAWRITER_H #define VTKGDCMPOLYDATAWRITER_H #include "vtkPolyDataWriter.h" #include "vtkStringArray.h" #include "vtkStdString.h" class vtkMedicalImageProperties; class vtkRTStructSetProperties; //BTX namespace gdcm { class File; } //ETX class VTK_EXPORT vtkGDCMPolyDataWriter : public vtkPolyDataWriter { public: static vtkGDCMPolyDataWriter *New(); vtkTypeMacro(vtkGDCMPolyDataWriter,vtkPolyDataWriter); virtual void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set/Get the filename of the file to be read // vtkSetStringMacro(FileName); // vtkGetStringMacro(FileName); // Description: // Get the medical image properties object // vtkGetObjectMacro(MedicalImageProperties, vtkMedicalImageProperties); virtual void SetMedicalImageProperties(vtkMedicalImageProperties *pd); virtual void SetRTStructSetProperties(vtkRTStructSetProperties *pd); //this function will initialize the contained rtstructset with //the inputs of the writer and the various extra information //necessary for writing a complete rtstructset. //NOTE: inputs must be set BEFORE calling this function! //NOTE: the number of outputs for the appendpolydata MUST MATCH the ROI vectors! void InitializeRTStructSet(vtkStdString inDirectory, vtkStdString inStructLabel, vtkStdString inStructName, vtkStringArray* inROINames, vtkStringArray* inROIAlgorithmName, vtkStringArray* inROIType); // make parent class public... void SetNumberOfInputPorts(int n); protected: vtkGDCMPolyDataWriter(); ~vtkGDCMPolyDataWriter(); vtkMedicalImageProperties *MedicalImageProperties; vtkRTStructSetProperties *RTStructSetProperties; void WriteData(); //BTX void WriteRTSTRUCTInfo(gdcm::File &file); void WriteRTSTRUCTData(gdcm::File &file, int num); //ETX private: vtkGDCMPolyDataWriter(const vtkGDCMPolyDataWriter&); // Not implemented. void operator=(const vtkGDCMPolyDataWriter&); // Not implemented. }; #endif GDCM-3.0.10/Utilities/VTK/vtkGDCMTesting.cxx000066400000000000000000000607671412732066400202720ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMTesting.h" #include "vtkObjectFactory.h" #include "vtkToolkits.h" #include "gdcmTesting.h" #include "gdcmFilename.h" //vtkCxxRevisionMacro(vtkGDCMTesting, "$Revision: 1.31 $") vtkStandardNewMacro(vtkGDCMTesting) // DICOM Filename, MHD MD5, RAW MD5 static const char * const vtkgdcmMD5MetaImages[][3] = { { "MR-SIEMENS-DICOM-WithOverlays-extracted-overlays.dcm","3d77fa60702897dd0ad601ee728f93d3", "8b636107a6d8e6a6b3d1d7eed966d7a0" }, { "PHILIPS_Gyroscan-8-MONO2-Odd_Sequence.dcm","3b22e8e2aea4354ed947786152504d4d", "cd301effb5e2020f539a2f5d24a429d7" }, { "SIEMENS_GBS_III-16-ACR_NEMA_1.acr","3864799d39588714e16c3a4482137c74", "ea24c09f475a4e9643e27f6d470edc67" }, { "SIEMENS_GBS_III-16-ACR_NEMA_1-ULis2Bytes.dcm","f285ebea4a7675457b916c16ff770934", "ea24c09f475a4e9643e27f6d470edc67" }, { "test.acr","06165c1b4e64898394fdc0598eb5971a", "f845c8f283d39a0204c325654493ba53" }, { "MR-MONO2-12-angio-an1.acr","849ce36c711f742e64c5bd5a161bb849", "ae5c00b60a58849b19aaabfc6521eeed" }, { "CT-MONO2-12-lomb-an2.acr","554cc0adb0dea2023d255d0eccbb21a6", "672d4cd82896c2b0dc09b6fe3eb748b0" }, { "SIEMENS_SOMATOM-12-ACR_NEMA-ZeroLengthUs.acr","ac6311f0db183e427e69650ba2e632b4", "a909e448b66303df6f5a512d169921d5" }, { "gdcm-MR-SIEMENS-16-2.acr","670ba858ad6f6eefb4b59cb24e5a3b31", "864e2c5d6acf5a371fe9eaa7ee0dcf5f" }, { "LIBIDO-8-ACR_NEMA-Lena_128_128.acr","e186747fca1e99d9f5b0c1607f19a9cb", "fc5db4e2e7fca8445342b83799ff16d8" }, { "libido1.0-vol.acr","b10050e7aa8fa72228d8d33bf0504238", "f17cf873a3c07f3d91dc88f34664bf0d" }, { "gdcm-ACR-LibIDO.acr","eb59c5fd7a6cc0bc1223e15e08a3637d", "59d9851ca0f214d57fdfd6a8c13bc91c" }, { "MR-MONO2-12-an2.acr","356cb716cc543209113c0e2b535faba9", "f54c7ea520ab3ec32b6303581ecd262f" }, { "012345.002.050.dcm","ea9ca1be179f269583c5c27e89c0a46d", "d594a5e2fde12f32b6633ca859b4d4a6" }, { "GE_MR_0025xx1bProtocolDataBlock.dcm","c9d8d1f0e94a06a98469926ec83a08da", "b620a57170941e26dfd07ff334c73cb4" }, { "MR_GE_with_Private_Compressed_Icon_0009_1110.dcm","91fb4352059cf7f7ba023599ec2c39a9", "8fe67e8e1f849c1b61f59e70d2d53cf7" }, { "gdcm-JPEG-LossLessThoravision.dcm","e5cb57f774e3be543169af242d27c93d", "c15c1e18a0c41970fbded48b20e834a1" }, { "SIEMENS_MAGNETOM-12-MONO2-Uncompressed.dcm","0a6af461c022adb1cdbef8836a3426f7", "4b426d4cd570bd4c998f3d19cfddfbb8" }, { "MR-MONO2-12-shoulder.dcm","ab968254870fdc9e41055d2adfe9ffef", "a70676f0e60a58f55a5ac517ff662e7e" }, { "PICKER-16-MONO2-No_DicomV3_Preamble.dcm","ff5f52a1ffd97d0cc6dad2c59e371b95", "5ea911b29f472f371d21f2da2fd6b016" }, { "LEADTOOLS_FLOWERS-8-PAL-Uncompressed.dcm","92629f1a782a3d10998d01a8af5df991", "16e999d6afc5574bcb075f296c3bcbbc" }, { "D_CLUNIE_CT1_JPLL.dcm","74360148191955d7e5664952d85ad01c", "a109da372df2b85ff0a705fba62e9589" }, { "DMCPACS_ExplicitImplicit_BogusIOP.dcm","3f434e2196fbe53d0024704c707254e9", "ef9f915086db838334ddc656a10486f2" }, { "PHILIPS_GDCM12xBug2.dcm","7b17feb9fc02abf1ccfbef7be168c012", "22a1e3f971865b95ca7f367de094e680" }, { "PICKER-16-MONO2-Nested_icon.dcm","2642d6b9be2d28d57f85abffc661bdb7", "954c99e48a083cc54de16ad07d553005" }, { "RadBWLossLess.dcm","1cbcd5c44f8ffe7c448520971233afb4", "dbbf39ac11a39372b1e961f40ac6f62a" }, { "gdcm-JPEG-Extended.dcm","4873a6ad617c2a8f86d130c853c5e127", "f05174b105604a462af0fa733fceebde" }, { "DX_J2K_0Padding.dcm","6986a0e25c3c39e30ad30f5cdb17cbfe", "52607a16af1eaddbbc71c14d32e489d8" }, { "CT-MONO2-16-ort.dcm","f758d2ad7de59ccf49473db31bb07825", "ca3c1630965318e6321daac7b39d8883" }, { "D_CLUNIE_XA1_RLE.dcm","6992adfe56cdd43fdb5c4ae832be0bb3", "6111657e6b01ec7b243d63f5dec6ec48" }, { "OT-MONO2-8-a7.dcm","7611df3cbfd9ac2e137a78d732d98603", "a155c3004bb902ed3f2d78f482923b32" }, { "fffc0000UN.dcm","1ca6fabea6962185ade0592a7e0db06a", "a136e501bcd1b8ee0835981d2bc8dd87" }, { "LEADTOOLS_FLOWERS-16-MONO2-RLE.dcm","9e1e8d58a04142531c21f3a39664edb0", "70166425c4dca767e22d3f25f737922b" }, { "gdcm-US-ALOKA-16.dcm","6dfc2e8a30cd515b12a3c0891b1496b5", "f85ff02a143c426edc4b2f6b9a175305" }, { "TG18-CH-2k-01.dcm","ff2121ad1e7471cd9f5c75d74664c8a1", "46bf12c412590767bb8cd7f0d53eaa87" }, { "05115014-mr-siemens-avanto-syngo-with-palette-icone.dcm","5d007c4979f5c401c623b8b1d095a339", "c68cf1c4ae59903930e334498389ea88" }, { "D_CLUNIE_RG1_RLE.dcm","e39a383f71c5f996cd2116e0312fc808", "ae141f6fb91f63769a6adc572a942fb9" }, { "PHILIPS_Brilliance_ExtraBytesInOverlay.dcm","675cb24b99d9c6cca3259e5e87bb6aea", "7f4158c2946981465bf409f2433ebaa7" }, { "MR_Philips_Intera_PrivateSequenceExplicitVR_in_SQ_2001_e05f_item_wrong_lgt_use_NOSHADOWSEQ.dcm","778a5b6f00dd312b2ecad0deac6b9577", "7775ffdd374994b7dd029f45f198844f" }, { "LEADTOOLS_FLOWERS-16-MONO2-JpegLossless.dcm","bd7bdc10de0df526ee6858da2c13018c", "70166425c4dca767e22d3f25f737922b" }, { "gdcm-JPEG-LossLess3a.dcm","62822559a854373b843ce8de2cc3ed7d", "a341e8cb1ec2aa07cb0e5b71bbe87087" }, { "D_CLUNIE_MR1_JPLY.dcm","0a4ce0b9f33ccf29ced7537327052978", "2824e914ecae250a755a8a0bb1a7d4b1" }, { "SIEMENS_MAGNETOM-12-MONO2-GDCM12-VRUN.dcm","a53035663a2de05df96871cf6a2773f1", "d2fab61e0fff8869e448d69951f1084d" }, { "PHILIPS_Gyroscan-12-MONO2-Jpeg_Lossless.dcm","adecccb2b55c791fb9a5f9adb9b5c7be", "b78366162d9d43b2852d2637c5365c89" }, { "SignedShortLosslessBug.dcm","dbf67ea5171e87a11ffbadc1ac8af3e8", "bdec90fcb90f68b34f0a306c40443610" }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq2.dcm","cc1e8af8bb7bf4d1e9ec20bad537cdfd", "f932a194df62ec99aef676c563893496" }, { "BugGDCM2_UndefItemWrongVL.dcm","84fc423a48309bdb0256ace6c7cf1458", "dae9d2e2b412646fd0a0f31dc2d17aa4" }, { "US-PAL-8-10x-echo.dcm","e83577771dbdb47f3046277bcdfe2758", "1785f4d8af4717c17bfb78ba74c18ea5" }, { "MR_Philips-Intera_BreaksNOSHADOW.dcm","aa9341fd51dd1dd640fa6420b274f507", "b606add66c681bbe674f972799c6d336" }, { "D_CLUNIE_RG3_RLE.dcm","df3d8699a986204038e3f9debde3a1d2", "e7c857ef7e6a2c81498297a072a0332e" }, { "JPEGDefinedLengthSequenceOfFragments.dcm","cc21f41e99625aac7308d9fdd01481d6", "484754f6dd1cc59325e9a5bbf76c5f2c" }, { "SIEMENS-MR-RGB-16Bits.dcm","56f175c3a227ca322245e90a625470a4", "faff9970b905458c0844400b5b869e25" }, { "JDDICOM_Sample2.dcm","76ef935051cf0e816a0e8864f88d4814", "33aa469ec024188d692262d03e7108a0" }, { "D_CLUNIE_MR2_JPLL.dcm","c3281801885ac42ec0e82af71636798d", "a70676f0e60a58f55a5ac517ff662e7e" }, { "PHILIPS_Intera-16-MONO2-Uncompress.dcm","89fc7c6e5ccc5ed3320197d9bdfc4dc6", "0b4dff77726ccf037fa83c42cc186a98" }, { "THERALYS-12-MONO2-Uncompressed-Even_Length_Tag.dcm","2a8441911c2135e94cd16f231c7ad8e6", "0121cd64c3b9957f76dd338d27454bc6" }, { "D_CLUNIE_CT2_RLE.dcm","74e31e7ac318cdcaffb172277f166e2e", "2e389ddbfc1b29d55c52c97e7f2c6f9c" }, { "ExplicitVRforPublicElementsImplicitVRforShadowElements.dcm","6f97e45b637beb9282e85c7b81b1473b", "0b4dff77726ccf037fa83c42cc186a98" }, { "D_CLUNIE_MR2_RLE.dcm","8bc2159b48a5a069ac7371f69694d761", "a70676f0e60a58f55a5ac517ff662e7e" }, { "SIEMENS_ImageLocationUN.dcm","4fd3c5e0b413ccfbec2b4706ad23200b", "0621954acd5815e0b4f7b65fcc6506b1" }, { "TOSHIBA_MRT150-16-MONO2-ACR_NEMA_2.dcm","a68236a0584e518d5ca9fce9136da38f", "09661bd8516aeb5a6f09239f9ca1b092" }, { "ACUSON-24-YBR_FULL-RLE-b.dcm","479d056e0a591bc2850eef632fc2345c", "22b32f23beb118f7b64c13bf04bc2809" }, { "D_CLUNIE_RG3_JPLL.dcm","351293952be98d7ce8e73ab574648daa", "e7c857ef7e6a2c81498297a072a0332e" }, { "AMIInvalidPrivateDefinedLengthSQasUN.dcm","0f5c34ef47b32554270a52201ce26daf", "ae1290d59c63b0c334a4834c5995fe45" }, { "CT-SIEMENS-Icone-With-PaletteColor.dcm","f0dc9d6c14c010948fdb64a4c6466565", "c6bdfac1d97c4dc60423b5b63a39a64a" }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm","d351dce81724bbd2b0bea467ad6942ff", "a13466d96b2f068c4844240797069f13" }, { "LJPEG_BuginGDCM12.dcm","fb9e4419f90eaa9c2a6c4ae98b750348", "9214cc4f62fbea873ffad88e1be877c5" }, { "XA-MONO2-8-12x-catheter.dcm","639e46ee89a1204df2ed708e33c3357b", "136eaf8f7d654bbb08741c201a945561" }, { "LEADTOOLS_FLOWERS-16-MONO2-Uncompressed.dcm","e086859c0b556c3d22d51bf2a05db26a", "70166425c4dca767e22d3f25f737922b" }, { "TheralysGDCM120Bug.dcm","e656263a9a475027fd356a30c26979d1", "d92b88a18dc63add8265ad338f8a58e9" }, { "D_CLUNIE_VL1_RLE.dcm","668904d73866455812fee0aabdbcff1e", "b07e34ec35ba1be62ee7d4a404cf0b90" }, { "D_CLUNIE_MR1_JPLL.dcm","087e123efb3e18f5e7693390926f08c6", "7b7424e6115931c371f3c94c2f5d32d9" }, { "GE_DLX-8-MONO2-Multiframe-Jpeg_Lossless.dcm","61c2a3757ad053c52eeeaa94f5d6cadd", "b8bcbccd17b76a0f8e3d4c342f855f9f" }, { "SIEMENS_Sonata-12-MONO2-SQ.dcm","91ee14eaab0a6f98b366ff3406b8d295", "a3009bc70444148c5ea2441a099f9dc6" }, { "3E768EB7.dcm","a8f6eb80f1aebdcc2716435b7049be6c", "a0fcdd5b68358d7078421e260fa749b7" }, { "DX_GE_FALCON_SNOWY-VOI.dcm","d3efd7ae0f764f26c22dfbfec46b13e9", "ba8dae4b43075c7e8562f5addf5f95c3" }, { "US-RGB-8-epicard.dcm","d139728ec75594e11fd2d489049756f5", "fe2d477d699e327be2d3d65eb76203e9" }, { "D_CLUNIE_NM1_JPLL.dcm","0210138626fc112253519cd202dac179", "6b5c1eff0ef65e36b0565f96507e96fd" }, { "SIEMENS_MAGNETOM-12-ACR_NEMA_2-Modern.dcm","3ec03618a9dcb12c636dae46cfa12bc5", "864e2c5d6acf5a371fe9eaa7ee0dcf5f" }, { "MR_SIEMENS_forceLoad29-1010_29-1020.dcm","d887c10d6058b568dd3a07c573faf5e1", "6a925f871c58553f84ad24195e155c52" }, { "D_CLUNIE_CT1_RLE.dcm","87ca724fcddef83277f918f7e7d4b235", "a109da372df2b85ff0a705fba62e9589" }, { "D_CLUNIE_XA1_JPLY.dcm","df8bca314462d849da13af4c971eb616", "51af0d83fe795f9c9544c20d0bbac11c" }, { "D_CLUNIE_MR3_JPLY.dcm","c2872e85ff9f155d80b6c703add04d8f", "d7009808a147f59a9bdf58d5c5924ef2" }, { "D_CLUNIE_CT1_J2KI.dcm","2923abe11b2f7898af31cfada0005cea", "bc127eee2ebf5f2ee2a6a1daeac364ce" }, { "CT_16b_signed-UsedBits13.dcm","2122e1b307aa75d602c665852a2daaff", "8c8b9d99ad12fb4d231182d4fc14c042" }, { "D_CLUNIE_VL6_RLE.dcm","04550649448200f4f3b5e478044c021a", "b825c0ed35c7c896fb707c14b534c233" }, { "DCMTK_JPEGExt_12Bits.dcm","1a9268135f0c200ffee17babd894352d", "c57035e2dac52e339b27e8c965251b3d" }, { "D_CLUNIE_MR4_RLE.dcm","d682f844f5cc19df26dc9acf434da818", "14fa2ae9f63742af6944edd4a61145e8" }, { "simpleImageWithIcon.dcm","eaf8ce3d45bf4f6e4991db6acbb4d673", "fc5db4e2e7fca8445342b83799ff16d8" }, { "gdcm-MR-PHILIPS-16-Multi-Seq.dcm","0af3267489f800c8e272f607f1d9a938", "ad85be428c08ab4166347ef04bda9637" }, { "D_CLUNIE_VL3_RLE.dcm","8ba4764396aa1d1c7fd84bf4132b273e", "65cd359ea4c6c13ca89b906215a4b762" }, { "CT-MONO2-16-brain.dcm","cdcf9ee879a4159cc686004f76745148", "a6cf43e05087b6c31644c1d360701ff2" }, { "CT-MONO2-16-ankle.dcm","803a459d3a6df6473c3f3e46129df147", "13e853d75ffe289b8210d1336e2394dd" }, { "MR_ELSCINT1_00e1_1042_SQ_feff_00e0_Item.dcm","4bb845dfa4b1f9b46fa53006e82bf4c8", "4d790e17ee35572d64e37c55dbc36725" }, { "LEADTOOLS_FLOWERS-24-RGB-JpegLossy.dcm","e91814bf121ae0dad75be63fbf1b1e93", "38c2784aa485733fef45b6517479a4f5" }, { "undefined_length_un_vr.dcm","88cbd399556f1ac8172153400f0eaf2f", "99cae85becc9b35b9385297c9a4b3708" }, { "JPEG_LossyYBR.dcm","351424d0392db74bc69cf6f6537ddb88", "d6fb1fb06318dd305a461db9c84cf825" }, { "rle16loo.dcm","fd66e0089e5c343d3f24642710eb0129", "04b42f011bdcf56e8a22607cb715447c" }, { "D_CLUNIE_MR2_JPLY.dcm","013b4754a4224b10cb503dead5a6a79e", "981510df3a57e98141c7d192b45bd93f" }, { "DermaColorLossLess.dcm","2d02d5385526970fffbb5cebafd6b4df", "b4f442047a209a98af015c89b4a3c4ed" }, { "KODAK-12-MONO1-Odd_Terminated_Sequence.dcm","601f6ff54e324ccc4e9e5627c0593027", "c1ed06d39821a5fd65abc397982e2ac1" }, { "D_CLUNIE_RG1_JPLL.dcm","08a9f8187cfad52150fffc80e76efa9e", "ae141f6fb91f63769a6adc572a942fb9" }, { "D_CLUNIE_RG3_JPLY.dcm","3c39fb636e231a66e425d6c8645e086c", "cc2968949ffbb6548288ffde7e5202e4" }, { "D_CLUNIE_MR3_RLE.dcm","847c8b74671107b463b90cbfa6535f7f", "fb03254fad02d2330d404225c3ea9b4e" }, { "NM-MONO2-16-13x-heart.dcm","7bfdb71668190142a547899329c1d9c3", "c83ef2159abef677229d3afd26f9e6a0" }, { "LEADTOOLS_FLOWERS-8-MONO2-JpegLossy.dcm","bcfdeefa6f9808ae020586b164a29d99", "fa08fec923f34e009ec89f77232e52ad" }, { "CT-MONO2-16-chest.dcm","f9110218ff6bd9310e6eb089fdb4ab0a", "78bb9ea4b746ff2aa5559be567f95030" }, { "SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm","aafebb62a52ad79ca0aea428fdfc7d1e", "017237320ccded3a367f07b44851788e" }, { "PrivateGEImplicitVRBigEndianTransferSyntax16Bits.dcm","3e1c33b362a0fb5a3c3009e681a6e546", "e5a0f7083de19fcc63dfdec9d754470f" }, { "US-GE-4AICL142.dcm","a9142c48ce2499d1f67e67db1b6f87d6", "23ec8ed09e1ecc353c2e6436a1de6cb2" }, { "gdcm-MR-PHILIPS-16-NonSquarePixels.dcm","68b7e492026a8a4da1e579802c2ef1ac", "2f7f9ef80b49111c5a7cfdb60a97f523" }, { "SIEMENS_MOSAIC_12BitsStored-16BitsJPEG.dcm","7433cf1900fbc331517e196daca6a4ef", "6396332b75b15bf30b1dd1cd0f212691" }, { "KODAK_CompressedIcon.dcm","2ad7b4697b63a2fe0082374ff6ea58d8", "79b8705f2e6c7464bd3e2fc7e1d3483b" }, { "D_CLUNIE_US1_RLE.dcm","14baf3e73f87d5b0893a9f305b11c87e", "eb52dce9eed5ad677364baadf6144ac4" }, { "D_CLUNIE_CT1_J2KR.dcm","0eb834e9d393fd41cf0ceb5b9c0c8959", "a109da372df2b85ff0a705fba62e9589" }, { "MAROTECH_CT_JP2Lossy.dcm","13a06166e548dc268ece0e22c860c387", "0e78a01c664550949071796339ac280e" }, { "CR-MONO1-10-chest.dcm","0cccf203c6c2a097383e8a017322b77b", "1f772b4849727a9750931b60d920436f" }, { "rle16sti.dcm","a225d3ea83666526eca91750e478b3ee", "f799773abbe36a1a8a3a881e27f8084d" }, { "D_CLUNIE_MR4_JPLL.dcm","355a76b3d43982ad2256e010d0230835", "14fa2ae9f63742af6944edd4a61145e8" }, { "US-IRAD-NoPreambleStartWith0003.dcm","27d939385c633d1db6943628a4e778cf", "ba092234639594ee9091b46997532cce" }, { "00191113.dcm","7c17afc7815f18ebaecd99b9b07950f1", "bfff320d1b058e91b4819aa4560c16f7" }, { "MR16BitsAllocated_8BitsStored.dcm","9d0266b04310ea377cf4d4c704ae44ba", "49b62d0b9004c2e1579317a36825cc5f" }, { "D_CLUNIE_XA1_JPLL.dcm","462a9583d0241ead2f5a1bab318e177a", "6111657e6b01ec7b243d63f5dec6ec48" }, { "MR-MONO2-8-16x-heart.dcm","379f882b2df9bdf115c38c4c68aea867", "01db0d71100c47013e588082d5f39bab" }, { "ACUSON-24-YBR_FULL-RLE.dcm","1715cfceb7141080e09954ac55f1640b", "435c66f7e113d11d226d500294aae865" }, { "D_CLUNIE_RG2_JPLL.dcm","ec91a9e10b3b9ba44305e62400db1ce9", "06900ee4323a91b7f5ffab8655e3c845" }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq3.dcm","366582d77fed1513d96acce3ba37da11", "b6e4780d8aa8c1d3642377a60a5302dd" }, { "GE_CT_With_Private_compressed-icon.dcm","48dd87fff8790e7fc2b1d31b03acd65a", "67206c434201b17a3a52ef42588b02e2" }, { "D_CLUNIE_NM1_JPLY.dcm","b0227cfc9911bb0d18402685fd437a84", "812050a7fc53b5735f7740b60969cb6b" }, { "US-RGB-8-esopecho.dcm","0916c89d6e3f3f28a52933829e5d0b3c", "4b350b9353a93c747917c7c3bf9b8f44" }, { "FUJI-10-MONO1-ACR_NEMA_2.dcm","98190f9abe6cdf82e565aee55288aaba", "da2415a1e58b4ca2e588d0de18274f60" }, { "JDDICOM_Sample2-dcmdjpeg.dcm","d883a2a8e69820f465865200cc726a4f", "33aa469ec024188d692262d03e7108a0" }, { "MR_Philips_Intera_PrivateSequenceImplicitVR.dcm","a98b2a5739a8956a6a811fcfcf988f60", "c6f98b5a0aac88e16b211981a6074a43" }, { "D_CLUNIE_RG2_JPLY.dcm","e4e64e50877ce1134a58824e4b3b0cda", "27fa50d4cf6b31baa669e9746ce10f63" }, { "ITK_GDCM124_MultiframeSecondaryCaptureInvalid.dcm","31a2d7476b505c01d77bf06333a3b797", "83601a7a4fa987c61b865b4b92f3caa0" }, { "GE_RHAPSODE-16-MONO2-JPEG-Fragments.dcm","12d33998ab1c371f3c2401fa362b2663", "a109da372df2b85ff0a705fba62e9589" }, { "PHILIPS_GDCM12xBug.dcm","c119395093c64d50d1c2aad34d99d08e", "396d74c4589f18bb26b14a7006eb9d8a" }, { "OT-PAL-8-face.dcm","42c16b6897e32fbac5fd68a2d2523642", "d7c30d57af821b02c67103250a744235" }, { "D_CLUNIE_SC1_JPLY.dcm","46dc0d3ad79883f0f5866ceeeb43c979", "994a5abb70d3f5968672ce4970a9d4da" }, { "CT-MONO2-8-abdo.dcm","e94fa94ff3b7a34db63d40790995ce9c", "86d3e09a5858aa3844cb3be1b822a069" }, { "GE_LOGIQBook-8-RGB-HugePreview.dcm","08a05020b521684a67d2ec40c2dc1600", "13fd8c7e533a3d7199bb78de45710f5c" }, { "MR-Brucker-CineTagging-NonSquarePixels.dcm","e9c9b806ebf112c342426fc6b35f4471", "d9f47017de79e8755e4bc5d3c9146ebd" }, { "SIEMENS-12-Jpeg_Process_2_4-Lossy-a.dcm","21f5f8c1d2b221833b665fae40327ce9", "698d6a3e88b270d4ad5ecfb00c11b634" }, { "D_CLUNIE_CT2_JPLL.dcm","92f22a280db62906e4b894d0e7882550", "2e389ddbfc1b29d55c52c97e7f2c6f9c" }, { "SIEMENS_CSA2.dcm","eb1db86d50a09dcf607af389e823d985", "62687f0a17e9c4153f18b55c8abfcef3" }, { "MR-MONO2-16-head.dcm","49c0aea0ba79ac781a53dac56db530e1", "83be31fb5e5cee60dedaf485bf592ac3" }, { "ELSCINT1_JP2vsJ2K.dcm","7d24121c34065f054fd398b5cf663a43", "87f5809b641b7235bfe5900a6281862b" }, { "D_CLUNIE_MR4_JPLY.dcm","eb5b39beed663bec16b26bcfcaedddfe", "a33ad864b49ae7daa59cfaabdf751976" }, { "MR-SIEMENS-DICOM-WithOverlays.dcm","9ad170d29a5e16ec04229b356f34ad45", "3027eda10630e5c845f456264dc65210" }, { "GE_GENESIS-16-MONO2-Uncompressed-UnusualVR.dcm","24a56cb80de943a06d82042933d22ea2", "8ac7f7891fb4506e2cd3ae2f0f7e9f46" }, { "OsirixFake16BitsStoredFakeSpacing.dcm","a7f05bcbea7af6ab00c58950144fa86c", "68269299e8f4341120aaa13a933c6c11" }, { "D_CLUNIE_VL2_RLE.dcm","017c67d4a3fedafb9d37264b4a4a68a1", "d215c88125359d34474a741d793c2215" }, { "ALOKA_SSD-8-MONO2-RLE-SQ.dcm","6a8d9e3420077ef24de8cd0e490895ce", "7d8858e3419392b7f39a99fdc8028064" }, { "D_CLUNIE_NM1_RLE.dcm","926811c358070765622fb131b9d4a39f", "6b5c1eff0ef65e36b0565f96507e96fd" }, { "D_CLUNIE_SC1_RLE.dcm","2085edf780950a21167765481ad92811", "bd0cccbfd8db465c0af306ba0f482d72" }, { "MR_Philips_Intera_SwitchIndianess_noLgtSQItem_in_trueLgtSeq.dcm","ba1e9ecee0fee60f3037cd7fb2e7023e", "0b4dff77726ccf037fa83c42cc186a98" }, { "GE_DLX-8-MONO2-PrivateSyntax.dcm","24e671036bdc9facc372b1ec4737e751", "51c998d3474c069b5703e98313258a1e" }, { "D_CLUNIE_MR3_JPLL.dcm","baac36788bfa8d192455ca79f9b7af36", "fb03254fad02d2330d404225c3ea9b4e" }, { "05148044-mr-siemens-avanto-syngo.dcm","60d33c5aecfe33a238e8ab8957194f4a", "9acdd9969f5d0584ddd67e994f00b7c7" }, { "US-IRAD-NoPreambleStartWith0005.dcm","3c0377fbaca00a9dcd17fa0258caa2c0", "1bde104ba256fb73528c5d9a02e363d7" }, { "LEADTOOLS_FLOWERS-8-MONO2-RLE.dcm","95d5f4e573800918664796910c238ed0", "3cd8bd92db17bff54e376885dfefdd8d" }, { "US-MONO2-8-8x-execho.dcm","14a483a14e070ead0a31a96d86146311", "bf63affde325b3fa81cd5a700f30bd5b" }, { "D_CLUNIE_RG2_RLE.dcm","bda1db6bbe98fcf680c4073df99e7b18", "06900ee4323a91b7f5ffab8655e3c845" }, { "LEADTOOLS_FLOWERS-24-RGB-Uncompressed.dcm","d7292927bd1aef2298c25524055cc2ab", "279e2b0363394a553ff8571cf3540c6c" }, { "CT-SIEMENS-MissingPixelDataInIconSQ.dcm","eed1e36b9333d9a50458e19bd0203455", "a86e48680d8ca941aa694d81872e8490" }, { "LEADTOOLS_FLOWERS-8-PAL-RLE.dcm","ec48c6dda2fdff2dd59366764d1fb0bd", "16e999d6afc5574bcb075f296c3bcbbc" }, { "D_CLUNIE_VL4_RLE.dcm","c1bdaec5bf045ae322068790c2f304a8", "e2fdf24d2c03dd0991b4f4e9d6e84ed6" }, { "GE_GENESIS-16-MONO2-WrongLengthItem.dcm","97e495e5e6b9fd9e080c7b9e40589b84", "1497fb9d7467b1eb36d5618e254aac76" }, { "MARCONI_MxTWin-12-MONO2-JpegLossless-ZeroLengthSQ.dcm","a7da0400b907b86ef97af8e61658b569", "6bbe3a067ff90eae950bc901f0f92f9e" }, { "LEADTOOLS_FLOWERS-24-RGB-JpegLossless.dcm","09dc2ab46d45d47a3ad41e9d53bf3c8d", "279e2b0363394a553ff8571cf3540c6c" }, { "SIEMENS_MAGNETOM-12-MONO2-FileSeq1.dcm","c1bcf58ffa46cfe50a989847cdd3e3c9", "73f5986082729c2661cdc8de81fd26d0" }, { "SIEMENS_MAGNETOM-12-MONO2-VRUN.dcm","3c10ecf511e1316d367399eeb4ee70dd", "d2fab61e0fff8869e448d69951f1084d" }, { "D_CLUNIE_MR1_RLE.dcm","a9c04692b4126a69e2cffc81f567a516", "7b7424e6115931c371f3c94c2f5d32d9" }, { "MR_Philips_Intera_No_PrivateSequenceImplicitVR.dcm","eab7f8484a6c3d6e76a8e281213e56e4", "0b4dff77726ccf037fa83c42cc186a98" }, { "GE_DLX-8-MONO2-Multiframe.dcm","67c44b08178efe2857221f3015b0510f", "71e4ea61df4f7ada2955799c91f93e74" }, { "LEADTOOLS_FLOWERS-8-MONO2-Uncompressed.dcm","4a967f8f35bfb93262dc90e0b8acf6b8", "3cd8bd92db17bff54e376885dfefdd8d" }, { "00191113.dcm","7c17afc7815f18ebaecd99b9b07950f1", "bfff320d1b058e91b4819aa4560c16f7" }, { "D_CLUNIE_CT1_JLSL.dcm","4efffce4cded3f8785d5ac4d3b11da41", "a109da372df2b85ff0a705fba62e9589" }, { "D_CLUNIE_CT1_JLSN.dcm","bcf17a67d96046ce7a2b4de4495dbd4c", "7ca273fff6311586bd02ac983ccfbb6b" }, { "IM-0001-0066.CommandTag00.dcm","51450a7a49ce7bc0e6a4ce18eaef2fff", "fb8119f30ec32ff575789caa969180ca" }, { "PHILIPS_Gyroscan-12-Jpeg_Extended_Process_2_4.dcm","2b1296ded36f37beb83e28fae108c280", "d93d2f78d845c7a132489aab92eadd32" }, { "UnexpectedSequenceDelimiterInFixedLengthSequence.dcm","f507ab11e56de33d6f0195dd185b5c62", "9eb513314b2fcf25d895e18ffb2ead0b" }, { "GDCMJ2K_TextGBR.dcm","9935ec525ea42203f3a535d4c1187ed4", "56238d3665ebdb0251d1161fb7f4edc6" }, { "NM_Kakadu44_SOTmarkerincons.dcm","99b60ec88d410b437adc06a809590127", "6f26e552a1b71d386483118779d192ad" }, { "PhilipsInteraSeqTermInvLen.dcm","6ccabe05841e29633d9e4fe1aec81039", "f8a1f4ce85b51527267e670a8aa0c308" }, { "LIBIDO-24-ACR_NEMA-Rectangle.dcm","28376a8bb2a64a9c8f6a50abfdbb336f", "81a40454eec2b18f4331cfd1ba4e501e" }, { "TOSHIBA_J2K_SIZ1_PixRep0.dcm","b7551911535d7ee21a336b700e4f0e4f", "d6347ed051d7b887bdaad1a91433c6ba" }, { "TOSHIBA_J2K_OpenJPEGv2Regression.dcm","f417f1a4552aeb03137ed91a04345fa2", "94414d8b4300aa3d8cbe4475d34e8e54" }, { "TOSHIBA_J2K_SIZ0_PixRep1.dcm","fcaab3ded5c41993b82d831c4251526e", "d6347ed051d7b887bdaad1a91433c6ba" }, { "NM-PAL-16-PixRep1.dcm","a04de15a87306cf77cd85ae5b720a0b2", "304f147752d46adfdcff71a30cd03d0a" }, { "MEDILABInvalidCP246_EVRLESQasUN.dcm","da13f42e41d36ef065af2cb5d770f70b", "d99ace99196e148522c8599803bacc28" }, { "JPEGInvalidSecondFrag.dcm","32ea68aea0c81d4cc75c5a234e1719ed", "8fb3a76c1f18b71b52d139ebd8406b50" }, { "SC16BitsAllocated_8BitsStoredJPEG.dcm","c9f9d07783496fa9a9e5b28a90603a70", "f845c8f283d39a0204c325654493ba53" }, { "SC16BitsAllocated_8BitsStoredJ2K.dcm","96639bac776d875b02f6aa9b35ee2db7", "dbf83984984741c98205d77a947b442c" }, { "SIEMENS_SYNGO-12-MONO2-LUTWrongLength512.dcm","81f79e2fcb3caec752e55be8077441dc", "4a5d8549791432b29948dd8ff63e2534" }, { "IllegalGroup2ImplicitTS.dcm","7c922536b5cf4143ce931ff5f552f588", "f666a95dde9ddfdec0cf9574a7985ae3" }, { "JPEGLosslessYBR_FULL_422.dcm","90a95c01f320809e3f6b6c720e78d457", "cdfb5dd0c999d88badeb00a16f96554f" }, { "JPEGNote_bogus.dcm","eeb1028e53ef4dcfc6b4100f8525be41", "161e9fd986ea87adf2596e8e16641f11" }, { "JPEGNote_empty.dcm","e6add795da6e0ccd4ed02f5689a61260", "464960d948dff0ded72b0380080f18a3" }, { "JPEGNote_missing.dcm","dce9f8853a528d423efc95a9bafee938", "464960d948dff0ded72b0380080f18a3" }, { "RLEDebianBug816607Orig.dcm","bb7bb73068f494c3cf947d2375af3501", "b85686dd3169b99725149abb00181254" }, /* Stopping condition */ { 0 , 0 , 0 } }; //static MD5MetaImagesType vtkGDCMTesting::GetMD5MetaImages() //{ //} unsigned int vtkGDCMTesting::GetNumberOfMD5MetaImages() { // Do not count NULL value: static const unsigned int size = sizeof(vtkgdcmMD5MetaImages)/sizeof(*vtkgdcmMD5MetaImages) - 1; return size; } const char * const * vtkGDCMTesting::GetMD5MetaImage(unsigned int file) { if( file < vtkGDCMTesting::GetNumberOfMD5MetaImages() ) return vtkgdcmMD5MetaImages[file]; return NULL; } const char * vtkGDCMTesting::GetMHDMD5FromFile(const char *filepath) { if(!filepath) return NULL; unsigned int i = 0; // MD5DataImagesType md5s = GetMD5DataImages(); MD5MetaImagesType md5s = vtkgdcmMD5MetaImages; const char *p = md5s[i][0]; gdcm::Filename comp(filepath); const char *filename = comp.GetName(); while( p != 0 ) { if( strcmp( filename, p ) == 0 ) { break; } ++i; p = md5s[i][0]; } // \postcondition always valid (before sentinel) // assert( i <= GetNumberOfMD5DataImages() ); return md5s[i][1]; } const char * vtkGDCMTesting::GetRAWMD5FromFile(const char *filepath) { if(!filepath) return NULL; unsigned int i = 0; // MD5DataImagesType md5s = GetMD5DataImages(); MD5MetaImagesType md5s = vtkgdcmMD5MetaImages; const char *p = md5s[i][0]; gdcm::Filename comp(filepath); const char *filename = comp.GetName(); while( p != 0 ) { if( strcmp( filename, p ) == 0 ) { break; } ++i; p = md5s[i][0]; } // \postcondition always valid (before sentinel) // assert( i <= GetNumberOfMD5DataImages() ); return md5s[i][2]; } //---------------------------------------------------------------------------- vtkGDCMTesting::vtkGDCMTesting() { } vtkGDCMTesting::~vtkGDCMTesting() { } //---------------------------------------------------------------------------- const char *vtkGDCMTesting::GetVTKDataRoot() { #ifdef VTK_DATA_ROOT return VTK_DATA_ROOT; #else return NULL; #endif } //---------------------------------------------------------------------------- const char *vtkGDCMTesting::GetGDCMDataRoot() { #ifdef GDCM_BUILD_TESTING return gdcm::Testing::GetDataRoot(); #else return NULL; #endif } //---------------------------------------------------------------------------- void vtkGDCMTesting::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } GDCM-3.0.10/Utilities/VTK/vtkGDCMTesting.h000066400000000000000000000027661412732066400177120ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // .NAME vtkGDCMTesting - GDCM Testing // .SECTION Description // GDCM Testing // .SECTION See Also // vtkTesting #ifndef VTKGDCMTESTING_H #define VTKGDCMTESTING_H #include "vtkObject.h" class VTK_EXPORT vtkGDCMTesting : public vtkObject { public: static vtkGDCMTesting *New(); vtkTypeMacro(vtkGDCMTesting,vtkObject); void PrintSelf(ostream& os, vtkIndent indent); static const char *GetVTKDataRoot(); static const char *GetGDCMDataRoot(); //BTX typedef const char* const (*MD5MetaImagesType)[3]; static const char * const * GetMD5MetaImage(unsigned int file); //ETX static unsigned int GetNumberOfMD5MetaImages(); static const char * GetMHDMD5FromFile(const char *filepath); static const char * GetRAWMD5FromFile(const char *filepath); protected: vtkGDCMTesting(); ~vtkGDCMTesting(); private: vtkGDCMTesting(const vtkGDCMTesting&); // Not implemented. void operator=(const vtkGDCMTesting&); // Not implemented. }; #endif GDCM-3.0.10/Utilities/VTK/vtkGDCMThreadedImageReader.cxx000066400000000000000000000507461412732066400224570ustar00rootroot00000000000000/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2016 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 "vtkGDCMThreadedImageReader.h" #include "vtkObjectFactory.h" #include "vtkImageData.h" #include "vtkMedicalImageProperties.h" #include "vtkStringArray.h" #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) #include "vtkInformationVector.h" #include "vtkInformation.h" #include "vtkDemandDrivenPipeline.h" #include "vtkStreamingDemandDrivenPipeline.h" #endif /* (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) */ #include "gdcmImageReader.h" #include "gdcmDataElement.h" #include "gdcmByteValue.h" #include "gdcmSwapper.h" #include #include #include // sysconf #ifdef _WIN32 #include // SYSTEM_INFO (mingw) #endif #ifdef __APPLE__ #include #include #endif //vtkCxxRevisionMacro(vtkGDCMThreadedImageReader, "$Revision: 1.1 $") vtkStandardNewMacro(vtkGDCMThreadedImageReader) // Output Ports are as follow: // #0: The image/volume (root PixelData element) // #1: (if present): the Icon Image (0088,0200) // #2-xx: (if present): the Overlay (60xx,3000) #define IconImagePortNumber 1 #define OverlayPortNumber 2 vtkGDCMThreadedImageReader::vtkGDCMThreadedImageReader() { this->LoadIconImage = 0; this->UseShiftScale = 1; } vtkGDCMThreadedImageReader::~vtkGDCMThreadedImageReader() { } #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) #else /* (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) */ void vtkGDCMThreadedImageReader::ExecuteInformation() { //std::cerr << "ExecuteInformation" << std::endl; // This reader only implement case where image is flipped upside down if( !this->FileLowerLeft ) { vtkErrorMacro( "You need to set the FileLowerLeft flag to On" ); } if( this->LoadIconImage ) { vtkErrorMacro( "Icon are not supported" ); } //int * updateExtent = this->Outputs[0]->GetUpdateExtent(); //std::cout << "UpdateExtent:" << updateExtent[4] << " " << updateExtent[5] << std::endl; vtkImageData *output = this->GetOutput(); output->SetUpdateExtentToWholeExtent(); // pipeline is not reexecuting properly without that... int numvol = 1; if( this->LoadIconImage) { numvol = 2; } if( this->LoadOverlays ) { this->NumberOfOverlays = 1; numvol = 3; } this->SetNumberOfOutputs(numvol); assert( numvol == 1 || numvol == 3 ); // vtkImageReader2::ExecuteInformation only allocate first output this->vtkImageReader2::ExecuteInformation(); // Let's do the other ones ourselves: for (int i=1; iOutputs[i]) { vtkImageData * img = vtkImageData::New(); this->SetNthOutput(i, img); img->Delete(); } vtkImageData *output = this->GetOutput(i); switch(i) { case 0: output->SetWholeExtent(this->DataExtent); output->SetSpacing(this->DataSpacing); output->SetOrigin(this->DataOrigin); output->SetScalarType(this->DataScalarType); output->SetNumberOfScalarComponents(this->NumberOfScalarComponents); break; case IconImagePortNumber: output->SetWholeExtent(this->IconImageDataExtent); output->SetScalarType( VTK_UNSIGNED_CHAR ); output->SetNumberOfScalarComponents( 1 ); break; //case OverlayPortNumber: default: output->SetWholeExtent(this->DataExtent[0],this->DataExtent[1], this->DataExtent[2],this->DataExtent[3], 0,0 ); //output->SetSpacing(this->DataSpacing); //output->SetOrigin(this->DataOrigin); output->SetScalarType(VTK_UNSIGNED_CHAR); output->SetNumberOfScalarComponents(1); break; } } } void vtkGDCMThreadedImageReader::ExecuteData(vtkDataObject *output) { //std::cerr << "ExecuteData" << std::endl; // In VTK 4.2 AllocateOutputData is reexecuting ExecuteInformation which is bad ! //vtkImageData *data = this->AllocateOutputData(output); vtkImageData *res = vtkImageData::SafeDownCast(output); res->SetExtent(res->GetUpdateExtent()); res->AllocateScalars(); if( this->LoadIconImage ) { /* vtkImageData *res = vtkImageData::SafeDownCast(this->Outputs[IconImagePortNumber]); res->SetUpdateExtentToWholeExtent(); res->SetExtent(res->GetUpdateExtent()); res->AllocateScalars(); */ vtkErrorMacro( "IconImage are not supported" ); } if( this->LoadOverlays ) { vtkImageData *res = vtkImageData::SafeDownCast(this->Outputs[OverlayPortNumber]); res->SetUpdateExtentToWholeExtent(); res->SetExtent(res->GetUpdateExtent()); res->AllocateScalars(); } // if( data->UpdateExtentIsEmpty() ) // { // return; // } //int * updateExtent = data->GetUpdateExtent(); //std::cout << "UpdateExtent:" << updateExtent[4] << " " << updateExtent[5] << std::endl; RequestDataCompat(); } #endif /* (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) */ //---------------------------------------------------------------------------- #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) int vtkGDCMThreadedImageReader::RequestInformation(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) { (void)request;(void)inputVector;(void)outputVector; // Some information need to have been set outside (user specified) //assert( this->GetOutput(0)->GetNumberOfPoints() != 0 ); // For now only handles series: if( !this->FileNames && !this->FileName ) { return 0; } // This reader only implement case where image is flipped upside down if( !this->FileLowerLeft ) { vtkErrorMacro( "You need to set the FileLowerLeft flag to On" ); return 0; } if( this->FileNames ) { int zmin = 0; int zmax = 0; zmax = (int)this->FileNames->GetNumberOfValues() - 1; if( this->DataExtent[4] != zmin || this->DataExtent[5] != zmax ) { vtkErrorMacro( "Problem with extent" ); return 0; } } // Cannot deduce anything else otherwise... int numvol = 1; if( this->LoadIconImage ) { numvol = 2; return 0; } if( this->LoadOverlays ) { this->NumberOfOverlays = 1; numvol = 3; } assert( numvol == 1 || numvol == 3 ); this->SetNumberOfOutputPorts(numvol); assert( this->DataScalarType != VTK_VOID ); // For each output: for(int i = 0; i < numvol; ++i) { // Allocate ! if( !this->GetOutput(i) ) { vtkImageData *img = vtkImageData::New(); this->GetExecutive()->SetOutputData(i, img ); img->Delete(); } vtkInformation *outInfo = outputVector->GetInformationObject(i); switch(i) { // root Pixel Data case 0: outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->DataExtent, 6); //outInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), this->DataExtent, 6); outInfo->Set(vtkDataObject::SPACING(), this->DataSpacing, 3); outInfo->Set(vtkDataObject::ORIGIN(), this->DataOrigin, 3); vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->DataScalarType, this->NumberOfScalarComponents); break; // Icon Image case IconImagePortNumber: outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->IconImageDataExtent, 6); vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 1); break; // Overlays: //case OverlayPortNumber: default: outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->DataExtent[0], this->DataExtent[1], this->DataExtent[2], this->DataExtent[3], 0,0 ); vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 1); break; } } // Ok let's fill in the 'extra' info: //FillMedicalImageInformation(reader); return 1; } #endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/ struct threadparams { unsigned int threadid; unsigned int nthreads; const char **filenames; // array of filenames thread will process (order is important!) unsigned int nfiles; // number of files the thread will process char *scalarpointer; // start of the image buffer affected to the thread char *overlayscalarpointer; unsigned long len; // This is not required but useful to check if files are consistant unsigned long overlaylen; unsigned long totalfiles; // total number of files being processed (needed to compute progress) pthread_mutex_t lock; // critial section for updating progress vtkGDCMThreadedImageReader *reader; // needed for calling updateprogress }; void *ReadFilesThread(void *voidparams) { threadparams *params = static_cast (voidparams); assert( params ); const unsigned int nfiles = params->nfiles; assert( nfiles ); // // pre compute progress delta for one file: assert( params->totalfiles ); const double progressdelta = 1. / (double)params->totalfiles; for(unsigned int file = 0; file < nfiles; ++file) { const char *filename = params->filenames[file]; //std::cerr << filename << std::endl; gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { return 0; } // Update progress // We are done reading one file, let's shout it loud: assert( params->reader->GetDebug() == 0 ); const double progress = params->reader->GetProgress(); // other thread might have updated it also... if( params->threadid == 0 ) { // IMPLEMENTATION NOTE (WARNING) // I think this is ok to assume that thread are equally distributed and the progress of thread 0 // actually represent nthreads times the local progress... params->reader->UpdateProgress( progress + params->nthreads*progressdelta ); } // BUG: //const double shift = params->reader->GetShift(); //const double scale = params->reader->GetScale(); // This is NOT safe to assume that shift/scale is constant thoughout the Series, this is better to // read the shift/scale from the image const gdcm::Image &image = reader.GetImage(); const double shift = image.GetIntercept(); const double scale = image.GetSlope(); unsigned long len = image.GetBufferLength(); // When not applying a transform: // len -> sizeof stored image // params->len sizeof world value image (after transform) if( shift == 1 && scale == 0 ) assert( len == params->len ); // that would be very bad char * pointer = params->scalarpointer; //memcpy(pointer + file*len, tempimage, len); // image char *tempimage = pointer + file*params->len; image.GetBuffer(tempimage); // overlay size_t numoverlays = image.GetNumberOfOverlays(); //if( numoverlays && !params->reader->GetLoadOverlays() ) //params->reader->SetNumberOfOverlays( numoverlays ); if( numoverlays ) { const gdcm::Overlay& ov = image.GetOverlay(); char * overlaypointer = params->overlayscalarpointer; char *tempimage2 = overlaypointer + file*params->overlaylen; memset(tempimage2,0,params->overlaylen); assert( (unsigned long)ov.GetRows()*ov.GetColumns() <= params->overlaylen ); if( !ov.GetUnpackBuffer(tempimage2, params->overlaylen) ) { vtkGenericWarningMacro( "Problem in GetUnpackBuffer" ); } } //if( params->reader->GetShift() != 1 || params->reader->GetScale() != 0 ) if( params->reader->GetUseShiftScale() && (shift != 1 || scale != 0) ) { const int shift_int = (int)shift; const int scale_int = (int)scale; if( scale == 1 && shift == (double)shift_int ) { unsigned short *out = (unsigned short*)(pointer + file * params->len); unsigned short *pout = out; for( ; pout != out + params->len / sizeof(unsigned short); ++pout ) { *pout = (unsigned short)(*pout + (short)shift); } } else if ( shift == 0 && scale != (double)scale_int ) { // FIXME TODO tempimage stored the DICOM image at the beginning of the buffer, // we could avoid duplicating the memory by iterating over the buffer starting // from the end and filling out the target buffer by the end... // scale is a float !! char * duplicate = new char[len]; memcpy(duplicate,tempimage,len); const unsigned short *in = (unsigned short*)duplicate; const unsigned short *pin = in; float *out = (float*)(pointer + file * params->len); float *pout = out; for( ; pout != out + params->len / sizeof(float); ++pout ) { // scale is a double, but DICOM specify 32bits for floating point value *pout = (float)((double)*pin * (float)scale); ++pin; } //assert( pin == in + len / sizeof(unsigned short) ); delete[] duplicate; } else { //assert( 0 && "Not Implemented" ); vtkGenericWarningMacro( "Not Implemented" ); } } } return voidparams; } void ShowFilenames(const threadparams ¶ms) { std::cout << "start" << std::endl; for(unsigned int i = 0; i < params.nfiles; ++i) { const char *filename = params.filenames[i]; std::cout << filename << std::endl; } std::cout << "end" << std::endl; } //---------------------------------------------------------------------------- void vtkGDCMThreadedImageReader::ReadFiles(unsigned int nfiles, const char *filenames[]) { // image data: vtkImageData *output = this->GetOutput(0); assert( output->GetNumberOfPoints() % nfiles == 0 ); const unsigned long len = output->GetNumberOfPoints() * output->GetScalarSize() / nfiles; const unsigned long overlaylen = output->GetNumberOfPoints() / nfiles; char * scalarpointer = static_cast(output->GetScalarPointer()); // overlay data: char * overlayscalarpointer = 0; if( this->LoadOverlays ) { vtkImageData *overlayoutput = this->GetOutput(OverlayPortNumber); #if (VTK_MAJOR_VERSION >= 6) // allocation is done in RequestData #else overlayoutput->SetScalarTypeToUnsignedChar(); overlayoutput->AllocateScalars(); #endif overlayscalarpointer = static_cast(overlayoutput->GetScalarPointer()); } #ifdef _WIN32 // mingw SYSTEM_INFO info; GetSystemInfo (&info); const unsigned int nprocs = info.dwNumberOfProcessors; #else #ifdef _SC_NPROCESSORS_ONLN const unsigned int nprocs = (unsigned int)sysconf( _SC_NPROCESSORS_ONLN ); #else #ifdef __APPLE__ int32_t count = 1; size_t size = sizeof(count); // hw.ncpu is deprecated and should be replaced with hw.logicalcpu one day. // hw.logicalcpu exists since at least 10.8, but maybe not earlier... int res = sysctlbyname("hw.ncpu",&count,&size,NULL,0); if( res == -1 ) { count = 1; } const unsigned int nprocs = (unsigned int)count; #endif // __APPLE__ #endif // _SC_NPROCESSORS_ONLN #endif // _WIN32 const unsigned int nthreads = std::min( nprocs, nfiles ); threadparams *params = new threadparams[nthreads]; pthread_mutex_t lock; pthread_mutex_init(&lock, NULL); pthread_t *pthread = new pthread_t[nthreads]; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS); this->Debug = 0; // There is nfiles, and nThreads assert( nfiles >= nthreads ); const unsigned int partition = nfiles / nthreads; assert( partition ); for (unsigned int thread=0; thread < nthreads; ++thread) { params[thread].filenames = filenames + thread * partition; params[thread].nfiles = partition; if( thread == nthreads - 1 ) { // There is slightly more files to process in this thread: params[thread].nfiles += nfiles % nthreads; } assert( thread * partition < nfiles ); //ShowFilenames(params[thread]); params[thread].scalarpointer = scalarpointer + thread * partition * len; params[thread].overlayscalarpointer = overlayscalarpointer + thread * partition * len; params[thread].len = len; params[thread].overlaylen = overlaylen; params[thread].totalfiles = nfiles; params[thread].threadid = thread; params[thread].nthreads = nthreads; params[thread].lock = lock; assert( this->Debug == 0 ); params[thread].reader = this; assert( params[thread].reader->Debug == 0 ); // start thread: //int res = pthread_create( &pthread[thread], NULL, ReadFilesThread, ¶ms[thread]); int res = pthread_create( &pthread[thread], &attr, ReadFilesThread, ¶ms[thread]); if( res ) { std::cerr << "Unable to start a new thread, pthread returned: " << res << std::endl; assert(0); } } // DEBUG unsigned int total = 0; for (unsigned int thread=0; thread < nthreads; ++thread) { total += params[thread].nfiles; } assert( total == nfiles ); // END DEBUG for (unsigned int thread=0;threadSetInput( output ); writer->SetFileName( "/tmp/threadgdcm.vtk" ); writer->SetFileTypeToBinary(); //writer->Write(); writer->Delete(); #endif //output->Print( std::cout ); } //---------------------------------------------------------------------------- #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) int vtkGDCMThreadedImageReader::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) { //this->UpdateProgress(0.2); // Make sure the output dimension is OK, and allocate its scalars for(int i = 0; i < this->GetNumberOfOutputPorts(); ++i) { #if (VTK_MAJOR_VERSION >= 6) vtkInformation* outInfo = outputVector->GetInformationObject(i); vtkImageData *data = static_cast(outInfo->Get(vtkDataObject::DATA_OBJECT())); // Make sure that this output is an image if (data) { int extent[6]; outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent); this->AllocateOutputData(data, outInfo, extent); } #else (void)outputVector; // Copy/paste from vtkImageAlgorithm::AllocateScalars. Cf. "this needs to be fixed -Ken" vtkStreamingDemandDrivenPipeline *sddp = vtkStreamingDemandDrivenPipeline::SafeDownCast(this->GetExecutive()); if (sddp) { int extent[6]; sddp->GetOutputInformation(i)->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),extent); this->GetOutput(i)->SetExtent(extent); } this->GetOutput(i)->AllocateScalars(); #endif } RequestDataCompat(); return 1; } #endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/ void vtkGDCMThreadedImageReader::RequestDataCompat() { int *dext = this->GetDataExtent(); if( this->FileNames ) { // Make sure that each file is single slice assert( dext[5] - dext[4] == this->FileNames->GetNumberOfValues() - 1 ); (void)dext; const vtkIdType nfiles = this->FileNames->GetNumberOfValues(); const char **filenames = new const char* [ nfiles ]; for(unsigned int i = 0; i < nfiles; ++i) { filenames[i] = this->FileNames->GetValue( i ); //std::cerr << filenames[i] << std::endl; } ReadFiles((unsigned int)nfiles, filenames); delete[] filenames; } else if( this->FileName ) { // File can be a volume const char *filename = this->FileName; ReadFiles(1, &filename); } else { // Impossible case since ExecuteInformation would have failed earlier... assert( 0 && "Impossible happen" ); } } //---------------------------------------------------------------------------- void vtkGDCMThreadedImageReader::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } GDCM-3.0.10/Utilities/VTK/vtkGDCMThreadedImageReader.h000066400000000000000000000072001412732066400220670ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // .NAME vtkGDCMThreadedImageReader - read DICOM files with multiple threads // .SECTION Description // vtkGDCMThreadedImageReader is a source object that reads some DICOM files // This reader is threaded. Meaning that on a multiple core CPU with N cpu, it will // read approx N times faster than when reading in a single thread. // // .SECTION Warning: Advanced users only. Do not use this class in the general case, // you have to understand how physicaly medium works first (sequential reading for // instance) before playing with this class // // .SECTION Implementation note: when FileLowerLeft is set to on the image is not flipped // upside down as VTK would expect, use this option only if you know what you are doing // // .SECTION FIXME: need to implement the other mode where FileLowerLeft is set to OFF // // .SECTION FIXME: you need to call SetFileName when reading a volume file (multiple slices DICOM) // since SetFileNames expect each single file to be single slice (see parent class) // // .SECTION BUG: you should really consider using vtkGDCMThreadedImageReader2 instead ! // // .SECTION See Also // vtkMedicalImageReader2 vtkMedicalImageProperties vtkGDCMThreadedImageReader2 #ifndef VTKGDCMTHREADEDIMAGEREADER_H #define VTKGDCMTHREADEDIMAGEREADER_H #include "vtkGDCMImageReader.h" #include "vtkVersion.h" class VTK_EXPORT vtkGDCMThreadedImageReader : public vtkGDCMImageReader { public: static vtkGDCMThreadedImageReader *New(); vtkTypeMacro(vtkGDCMThreadedImageReader,vtkGDCMImageReader); virtual void PrintSelf(ostream& os, vtkIndent indent); // Description: // Explicitly set the Rescale Intercept (0028,1052) vtkSetMacro(Shift,double); // Description: // Explicitly get/set the Rescale Slope (0028,1053) vtkSetMacro(Scale,double); // Description: // Determine whether or not reader should use value from Shift/Scale // Default is 1 vtkSetMacro(UseShiftScale,int); vtkGetMacro(UseShiftScale,int); vtkBooleanMacro(UseShiftScale,int); // Within this class this is allowed to set the Number of Overlays from outside //vtkSetMacro(NumberOfOverlays,int); protected: vtkGDCMThreadedImageReader(); ~vtkGDCMThreadedImageReader(); #if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 ) int RequestInformation(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector); int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector); #else /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/ void ExecuteInformation(); void ExecuteData(vtkDataObject *out); #endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/ void ReadFiles(unsigned int nfiles, const char *filenames[]); void RequestDataCompat(); private: vtkGDCMThreadedImageReader(const vtkGDCMThreadedImageReader&); // Not implemented. void operator=(const vtkGDCMThreadedImageReader&); // Not implemented. int UseShiftScale; }; #endif GDCM-3.0.10/Utilities/VTK/vtkGDCMThreadedImageReader2.cxx000066400000000000000000000311601412732066400225260ustar00rootroot00000000000000/*========================================================================= 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 "vtkGDCMThreadedImageReader2.h" #include "vtkObjectFactory.h" #include "vtkImageData.h" #include "vtkStringArray.h" #include "vtkInformationVector.h" #include "vtkInformation.h" #include "vtkDemandDrivenPipeline.h" #include "vtkStreamingDemandDrivenPipeline.h" #include "gdcmImageReader.h" #include //vtkCxxRevisionMacro(vtkGDCMThreadedImageReader2, "$Revision: 1.1 $") vtkStandardNewMacro(vtkGDCMThreadedImageReader2) vtkCxxSetObjectMacro(vtkGDCMThreadedImageReader2,FileNames,vtkStringArray) // Output Ports are as follow: // #0: The image/volume (root PixelData element) // #1: (if present): the Icon Image (0088,0200) // #2-xx: (if present): the Overlay (60xx,3000) #define IconImagePortNumber 1 #define OverlayPortNumber 2 vtkGDCMThreadedImageReader2::vtkGDCMThreadedImageReader2() { this->SetNumberOfInputPorts(0); this->FileLowerLeft = 1; this->FileName = NULL; this->FileNames = vtkStringArray::New(); this->LoadIconImage = 0; memset(this->DataExtent,0,6*sizeof(*DataExtent)); this->LoadOverlays = 0; this->NumberOfOverlays = 0; this->DataScalarType = VTK_VOID; this->NumberOfScalarComponents = 1; this->DataSpacing[0] = DataSpacing[1] = DataSpacing[2] = 1; this->DataOrigin[0] = DataOrigin[1] = DataOrigin[2] = 0; memset(this->IconImageDataExtent,0,6*sizeof(*IconImageDataExtent)); this->Shift = 0.; this->Scale = 1.; this->UseShiftScale = 1; } //---------------------------------------------------------------------------- vtkGDCMThreadedImageReader2::~vtkGDCMThreadedImageReader2() { if( this->FileNames ) { this->FileNames->Delete(); } this->SetFileName(NULL); } //---------------------------------------------------------------------------- const char *vtkGDCMThreadedImageReader2::GetFileName(int i) { return this->FileNames->GetValue( i ); } //---------------------------------------------------------------------------- void vtkGDCMThreadedImageReader2::SetFileName(const char *filename) { if( !filename ) { return; } //this->FileNames->Clear(); this->FileNames->InsertNextValue( filename ); assert( this->FileNames->GetNumberOfValues() == 1 ); } //---------------------------------------------------------------------------- // Description: // This templated function executes the filter for any type of data. template void vtkGDCMThreadedImageReader2Execute(vtkGDCMThreadedImageReader2 *self, vtkImageData **inDatas, int numFiles, vtkImageData *outData, int outExt[6], int id, T*) { (void)numFiles; (void)inDatas; //printf("outExt:%d,%d,%d,%d,%d,%d\n", // outExt[0], outExt[1], outExt[2], outExt[3], outExt[4], outExt[5]); // FIXME: // The code could be a little tidier, all I am trying to do here is differenciate the // case where we have a series of 2D files and the case where we have a single multi-frames // files... vtkIdType maxfiles = self->GetFileNames()->GetNumberOfValues(); const unsigned long params_len = self->GetOutput()->GetNumberOfPoints() * self->GetOutput()->GetScalarSize() / maxfiles; for( int i = outExt[4]; i <= outExt[5] && i < maxfiles; ++i ) { assert( i < maxfiles ); const char *filename = self->GetFileNames()->GetValue( i ); //ReadOneFile( filename ); //outData->GetPointData()->GetScalars()->SetName("GDCMImage"); if( id == 0 ) { // we only consider outExt here for computing the progress, while in fact we should really // consider numFiles to compute exact update progress...oh well let's assume this is almost // correct. self->UpdateProgress(float(i)/float(outExt[5]-outExt[4]+1)); } //char * pointer = static_cast(outData->GetScalarPointerForExtent(outExt)); char * pointer = static_cast(outData->GetScalarPointer(0,0,i)); //printf("pointer:%i\n",*pointer); gdcm::ImageReader reader; reader.SetFileName( filename ); if( !reader.Read() ) { vtkGenericWarningMacro( "Could not read: " << filename ); //memset(pointer,); return; } const gdcm::Image &image = reader.GetImage(); unsigned long len = image.GetBufferLength(); image.GetBuffer(pointer); size_t numoverlays = image.GetNumberOfOverlays(); if( numoverlays ) { vtkImageData *vtkimage = self->GetOutput(OverlayPortNumber); const gdcm::Overlay& ov = image.GetOverlay(); const size_t overlaylen = (outExt[1]-outExt[0])*(outExt[3]-outExt[2]); char * overlaypointer = static_cast(vtkimage->GetScalarPointer()); if( !ov.GetUnpackBuffer(overlaypointer, overlaylen) ) { vtkGenericWarningMacro( "Problem in GetUnpackBuffer" ); } } const double shift = image.GetIntercept(); const double scale = image.GetSlope(); if( self->GetShift() != shift || self->GetScale() != scale ) { vtkGenericWarningMacro( "Specified Shift/Scale do not match file. This is not supported" ); } //if( shift != 1 || scale != 0 ) if( self->GetUseShiftScale() && (shift != 1 || scale != 0) ) { const int shift_int = (int)shift; const int scale_int = (int)scale; if( scale == 1 && shift == (double)shift_int ) { unsigned short *out = (unsigned short*)pointer; unsigned short *pout = out; for( ; pout != out + params_len / sizeof(unsigned short); ++pout ) { *pout = (unsigned short)(*pout + (short)shift); } } else if ( shift == 0 && scale != (double)scale_int ) { // FIXME TODO tempimage stored the DICOM image at the beginning of the buffer, // we could avoid duplicating the memory by iterating over the buffer starting // from the end and filling out the target buffer by the end... // scale is a float !! char * duplicate = new char[len]; memcpy(duplicate,pointer,len); const unsigned short *in = (unsigned short*)duplicate; const unsigned short *pin = in; float *out = (float*)pointer; float *pout = out; for( ; pout != out + params_len / sizeof(float); ++pout ) { // scale is a double, but to be backward compatible we need the explicit cast *pout = (float)((double)*pin * (float)scale); ++pin; } //assert( pin == in + len / sizeof(unsigned short) ); delete[] duplicate; } else { //assert( 0 && "Not Implemented" ); vtkGenericWarningMacro( "Not Implemented" ); } } } } //---------------------------------------------------------------------------- int vtkGDCMThreadedImageReader2::RequestInformation ( vtkInformation * request, vtkInformationVector** inputVector, vtkInformationVector *outputVector) { (void)request;(void)inputVector;(void)outputVector; // Some information need to have been set outside (user specified) //assert( this->GetOutput(0)->GetNumberOfPoints() != 0 ); // For now only handles series: if( !this->FileNames && !this->FileName ) { return 0; } // This reader only implement case where image is flipped upside down if( !this->FileLowerLeft ) { vtkErrorMacro( "You need to set the FileLowerLeft flag to On" ); return 0; } /* if( this->FileNames ) { int zmin = 0; int zmax = 0; zmax = this->FileNames->GetNumberOfValues() - 1; if( this->DataExtent[4] != zmin || this->DataExtent[5] != zmax ) { vtkErrorMacro( "Problem with extent" ); return 0; } } */ // Cannot deduce anything else otherwise... int numvol = 1; if( this->LoadIconImage ) { numvol = 2; return 0; } if( this->LoadOverlays ) { this->NumberOfOverlays = 1; numvol = 3; } assert( numvol == 1 || numvol == 3 ); this->SetNumberOfOutputPorts(numvol); assert( this->DataScalarType != VTK_VOID ); // For each output: for(int i = 0; i < numvol; ++i) { // Allocate ! if( !this->GetOutput(i) ) { vtkImageData *img = vtkImageData::New(); this->GetExecutive()->SetOutputData(i, img ); img->Delete(); } vtkInformation *outInfo = outputVector->GetInformationObject(i); switch(i) { // root Pixel Data case 0: outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->DataExtent, 6); //outInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), this->DataExtent, 6); outInfo->Set(vtkDataObject::SPACING(), this->DataSpacing, 3); outInfo->Set(vtkDataObject::ORIGIN(), this->DataOrigin, 3); vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->DataScalarType, this->NumberOfScalarComponents); break; // Icon Image case IconImagePortNumber: outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->IconImageDataExtent, 6); vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 1); break; // Overlays: //case OverlayPortNumber: default: outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->DataExtent[0], this->DataExtent[1], this->DataExtent[2], this->DataExtent[3], 0,0 ); vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 1); break; } } // Ok let's fill in the 'extra' info: //FillMedicalImageInformation(reader); return 1; } // For streaming and threads. Splits output update extent into num pieces. // This method needs to be called num times. Results must not overlap for // consistent starting extent. Subclass can override this method. // This method returns the number of peices resulting from a successful split. // This can be from 1 to "total". // If 1 is returned, the extent cannot be split. int vtkGDCMThreadedImageReader2::SplitExtent(int splitExt[6], int startExt[6], int num, int total) { memcpy(splitExt, startExt, 6 * sizeof(*splitExt)); vtkDebugMacro("SplitExtent: ( " << startExt[0] << ", " << startExt[1] << ", " << startExt[2] << ", " << startExt[3] << ", " << startExt[4] << ", " << startExt[5] << "), " << num << " of " << total); // We should only split along the Z direction (only in the case of multiple files...) int splitAxis = 2; int min = startExt[4]; int max = startExt[5]; if( min >= max ) { assert ( min == 0 ); assert ( max == 0 ); return 1; } // If single file always says 1: // FIXME need to handle series of 3D files too... if( this->GetFileNames()->GetNumberOfValues() == 1 ) { return 1; } // else normal SplitExtent as copied from vtkThreadedImageAlgorithm // determine the actual number of pieces that will be generated int range = max - min + 1; int valuesPerThread = static_cast(ceil(range/static_cast(total))); int maxThreadIdUsed = static_cast(ceil(range/static_cast(valuesPerThread))) - 1; if (num < maxThreadIdUsed) { splitExt[splitAxis*2] = splitExt[splitAxis*2] + num*valuesPerThread; splitExt[splitAxis*2+1] = splitExt[splitAxis*2] + valuesPerThread - 1; } if (num == maxThreadIdUsed) { splitExt[splitAxis*2] = splitExt[splitAxis*2] + num*valuesPerThread; } return maxThreadIdUsed + 1; } void vtkGDCMThreadedImageReader2::ThreadedRequestData ( vtkInformation * vtkNotUsed( request ), vtkInformationVector** vtkNotUsed( inputVector ), vtkInformationVector * vtkNotUsed( outputVector ), vtkImageData ***inData, vtkImageData **outData, int outExt[6], int id) { (void)inData; // printf("ThreadedRequestData::outExt:%d,%d,%d,%d,%d,%d\n", // outExt[0], outExt[1], outExt[2], outExt[3], outExt[4], outExt[5]); assert( this->DataScalarType != VTK_VOID ); switch (this->GetDataScalarType()) { vtkTemplateMacro( vtkGDCMThreadedImageReader2Execute(this , 0 , 3, outData[0], outExt, id, static_cast(0)) ); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } //---------------------------------------------------------------------------- void vtkGDCMThreadedImageReader2::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } GDCM-3.0.10/Utilities/VTK/vtkGDCMThreadedImageReader2.h000066400000000000000000000117661412732066400221650ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // .NAME vtkGDCMThreadedImageReader2 - read DICOM files with multiple threads // .SECTION Description // vtkGDCMThreadedImageReader2 is a source object that reads some DICOM files // This reader is threaded. Meaning that on a multiple core CPU with N cpu, it will // read approx N times faster than when reading in a single thread assuming the IO is // not a bottleneck operation. // If looking for a single threaded class see: vtkGDCMImageReader // // .SECTION Warning: Advanced users only. Do not use this class in the general case, // you have to understand how physicaly medium works first (sequential reading for // instance) before playing with this class // // .SECTION Implementation note: when FileLowerLeft is set to on the image is not flipped // upside down as VTK would expect, use this option only if you know what you are doing // // .SECTION FIXME: need to implement the other mode where FileLowerLeft is set to OFF // // .SECTION FIXME: need to implement reading of series of 3D files // // .SECTION Implementation note: this class is meant to superseed vtkGDCMThreadedImageReader // because it had support for ProgressEvent support even from python layer. There is a // subtle trick down in the threading mechanism in VTK were the main thread (talking to the // python interpreter) is also part of the execution process (and the N-1 other thread // are just there to execute the remaining of ThreadedRequestData), this separation into // two types of thread is necessary to acheive a working implementation of UpdateProgress // .SECTION See Also // vtkMedicalImageReader2 vtkMedicalImageProperties vtkGDCMImageReader #ifndef VTKGDCMTHREADEDIMAGEREADER2_H #define VTKGDCMTHREADEDIMAGEREADER2_H #include "vtkThreadedImageAlgorithm.h" class vtkStringArray; class VTK_EXPORT vtkGDCMThreadedImageReader2 : public vtkThreadedImageAlgorithm { public: static vtkGDCMThreadedImageReader2 *New(); vtkTypeMacro(vtkGDCMThreadedImageReader2,vtkThreadedImageAlgorithm); virtual void PrintSelf(ostream& os, vtkIndent indent); vtkGetMacro(FileLowerLeft,int); vtkSetMacro(FileLowerLeft,int); vtkBooleanMacro(FileLowerLeft,int); vtkGetMacro(NumberOfOverlays,int); vtkSetMacro(DataScalarType,int); vtkGetMacro(DataScalarType,int); vtkSetMacro(NumberOfScalarComponents,int); vtkGetMacro(NumberOfScalarComponents,int); vtkGetMacro(LoadOverlays,int); vtkSetMacro(LoadOverlays,int); vtkBooleanMacro(LoadOverlays,int); vtkSetVector6Macro(DataExtent,int); vtkGetVector6Macro(DataExtent,int); vtkSetVector3Macro(DataOrigin,double); vtkGetVector3Macro(DataOrigin,double); vtkSetVector3Macro(DataSpacing,double); vtkGetVector3Macro(DataSpacing,double); //vtkGetStringMacro(FileName); //vtkSetStringMacro(FileName); virtual const char *GetFileName(int i = 0); virtual void SetFileName(const char *filename); virtual void SetFileNames(vtkStringArray*); vtkGetObjectMacro(FileNames, vtkStringArray); int SplitExtent(int splitExt[6], int startExt[6], int num, int total); // Description: // Explicitly set the Rescale Intercept (0028,1052) vtkSetMacro(Shift,double); vtkGetMacro(Shift,double); // Description: // Explicitly get/set the Rescale Slope (0028,1053) vtkSetMacro(Scale,double); vtkGetMacro(Scale,double); // Description: // Determine whether or not reader should use value from Shift/Scale // Default is 1 vtkSetMacro(UseShiftScale,int); vtkGetMacro(UseShiftScale,int); vtkBooleanMacro(UseShiftScale,int); protected: vtkGDCMThreadedImageReader2(); ~vtkGDCMThreadedImageReader2(); int RequestInformation(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector); protected: void ThreadedRequestData ( vtkInformation * request, vtkInformationVector** inputVector, vtkInformationVector * outputVector, vtkImageData ***inData, vtkImageData **outData, int outExt[6], int id); private: int FileLowerLeft; char *FileName; vtkStringArray *FileNames; int LoadIconImage; int DataExtent[6]; int LoadOverlays; int NumberOfOverlays; int DataScalarType; int NumberOfScalarComponents; double DataSpacing[3]; double DataOrigin[3]; int IconImageDataExtent[6]; double Shift; double Scale; int UseShiftScale; private: vtkGDCMThreadedImageReader2(const vtkGDCMThreadedImageReader2&); // Not implemented. void operator=(const vtkGDCMThreadedImageReader2&); // Not implemented. }; #endif GDCM-3.0.10/Utilities/VTK/vtkImageColorViewer.cxx000066400000000000000000000633451412732066400214200ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /*========================================================================= Portions of this file are subject to the VTK Toolkit Version 3 copyright. Program: Visualization Toolkit Module: $RCSfile: vtkImageColorViewer.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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 "vtkImageColorViewer.h" #include "vtkCamera.h" #include "vtkCommand.h" #include "vtkImageActor.h" #include "vtkImageData.h" #if (VTK_MAJOR_VERSION >= 6) #include "vtkImageMapper3D.h" #endif #include "vtkImageData.h" #include "vtkImageMapToWindowLevelColors2.h" #include "vtkInteractorStyleImage.h" #include "vtkObjectFactory.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" #include "vtkPolyDataMapper.h" #if (VTK_MAJOR_VERSION >= 5) #include "vtkStreamingDemandDrivenPipeline.h" #include "vtkInformation.h" #endif //vtkCxxRevisionMacro(vtkImageColorViewer, "$Revision: 1.3 $") vtkStandardNewMacro(vtkImageColorViewer) //---------------------------------------------------------------------------- vtkImageColorViewer::vtkImageColorViewer() { this->RenderWindow = NULL; this->Renderer = NULL; this->ImageActor = vtkImageActor::New(); this->OverlayImageActor = vtkImageActor::New(); this->WindowLevel = vtkImageMapToWindowLevelColors2::New(); this->Interactor = NULL; this->InteractorStyle = NULL; this->Slice = 0; this->FirstRender = 1; this->SliceOrientation = vtkImageColorViewer::SLICE_ORIENTATION_XY; // Setup the pipeline vtkRenderWindow *renwin = vtkRenderWindow::New(); this->SetRenderWindow(renwin); renwin->Delete(); vtkRenderer *ren = vtkRenderer::New(); this->SetRenderer(ren); ren->Delete(); this->InstallPipeline(); } //---------------------------------------------------------------------------- vtkImageColorViewer::~vtkImageColorViewer() { if (this->WindowLevel) { this->WindowLevel->Delete(); this->WindowLevel = NULL; } if (this->ImageActor) { this->ImageActor->Delete(); this->ImageActor = NULL; } if (this->OverlayImageActor) { this->OverlayImageActor->Delete(); this->OverlayImageActor = NULL; } if (this->Renderer) { this->Renderer->Delete(); this->Renderer = NULL; } if (this->RenderWindow) { this->RenderWindow->Delete(); this->RenderWindow = NULL; } if (this->Interactor) { this->Interactor->Delete(); this->Interactor = NULL; } if (this->InteractorStyle) { this->InteractorStyle->Delete(); this->InteractorStyle = NULL; } } //---------------------------------------------------------------------------- void vtkImageColorViewer::SetupInteractor(vtkRenderWindowInteractor *arg) { if (this->Interactor == arg) { return; } this->UnInstallPipeline(); if (this->Interactor) { this->Interactor->UnRegister(this); } this->Interactor = arg; if (this->Interactor) { this->Interactor->Register(this); } this->InstallPipeline(); if (this->Renderer) { this->Renderer->GetActiveCamera()->ParallelProjectionOn(); } } //---------------------------------------------------------------------------- void vtkImageColorViewer::SetRenderWindow(vtkRenderWindow *arg) { if (this->RenderWindow == arg) { return; } this->UnInstallPipeline(); if (this->RenderWindow) { this->RenderWindow->UnRegister(this); } this->RenderWindow = arg; if (this->RenderWindow) { this->RenderWindow->Register(this); } this->InstallPipeline(); } //---------------------------------------------------------------------------- void vtkImageColorViewer::SetRenderer(vtkRenderer *arg) { if (this->Renderer == arg) { return; } this->UnInstallPipeline(); if (this->Renderer) { this->Renderer->UnRegister(this); } this->Renderer = arg; if (this->Renderer) { this->Renderer->Register(this); } this->InstallPipeline(); this->UpdateOrientation(); } //---------------------------------------------------------------------------- void vtkImageColorViewer::SetSize(int a,int b) { this->RenderWindow->SetSize(a, b); } //---------------------------------------------------------------------------- int* vtkImageColorViewer::GetSize() { return this->RenderWindow->GetSize(); } //---------------------------------------------------------------------------- void vtkImageColorViewer::GetSliceRange(int &min, int &max) { #if (VTK_MAJOR_VERSION >= 6) vtkAlgorithm *input = this->GetInputAlgorithm(); #else vtkImageData *input = this->GetInput(); #endif if (input) { input->UpdateInformation(); #if (VTK_MAJOR_VERSION >= 6) int *w_ext = input->GetOutputInformation(0)->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); #else int *w_ext = input->GetWholeExtent(); #endif min = w_ext[this->SliceOrientation * 2]; max = w_ext[this->SliceOrientation * 2 + 1]; } } //---------------------------------------------------------------------------- int* vtkImageColorViewer::GetSliceRange() { #if (VTK_MAJOR_VERSION >= 6) vtkAlgorithm *input = this->GetInputAlgorithm(); #else vtkImageData *input = this->GetInput(); #endif if (input) { input->UpdateInformation(); #if (VTK_MAJOR_VERSION >= 6) return input->GetOutputInformation(0)->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()) + this->SliceOrientation * 2; #else return input->GetWholeExtent() + this->SliceOrientation * 2; #endif } return NULL; } //---------------------------------------------------------------------------- int vtkImageColorViewer::GetSliceMin() { int *range = this->GetSliceRange(); if (range) { return range[0]; } return 0; } //---------------------------------------------------------------------------- int vtkImageColorViewer::GetSliceMax() { int *range = this->GetSliceRange(); if (range) { return range[1]; } return 0; } //---------------------------------------------------------------------------- void vtkImageColorViewer::SetSlice(int slice) { int *range = this->GetSliceRange(); if (range) { if (slice < range[0]) { slice = range[0]; } else if (slice > range[1]) { slice = range[1]; } } if (this->Slice == slice) { return; } this->Slice = slice; this->Modified(); this->UpdateDisplayExtent(); this->Render(); } //---------------------------------------------------------------------------- void vtkImageColorViewer::SetSliceOrientation(int orientation) { if (orientation < vtkImageColorViewer::SLICE_ORIENTATION_YZ || orientation > vtkImageColorViewer::SLICE_ORIENTATION_XY) { vtkErrorMacro("Error - invalid slice orientation " << orientation); return; } if (this->SliceOrientation == orientation) { return; } this->SliceOrientation = orientation; // Update the viewer int *range = this->GetSliceRange(); if (range) { this->Slice = static_cast((range[0] + range[1]) * 0.5); } this->UpdateOrientation(); this->UpdateDisplayExtent(); if (this->Renderer && this->GetInput()) { double scale = this->Renderer->GetActiveCamera()->GetParallelScale(); this->Renderer->ResetCamera(); this->Renderer->GetActiveCamera()->SetParallelScale(scale); } this->Render(); } //---------------------------------------------------------------------------- void vtkImageColorViewer::UpdateOrientation() { // Set the camera position vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL; if (cam) { switch (this->SliceOrientation) { case vtkImageColorViewer::SLICE_ORIENTATION_XY: cam->SetFocalPoint(0,0,0); cam->SetPosition(0,0,1); // -1 if medical ? cam->SetViewUp(0,1,0); break; case vtkImageColorViewer::SLICE_ORIENTATION_XZ: cam->SetFocalPoint(0,0,0); cam->SetPosition(0,-1,0); // 1 if medical ? cam->SetViewUp(0,0,1); break; case vtkImageColorViewer::SLICE_ORIENTATION_YZ: cam->SetFocalPoint(0,0,0); cam->SetPosition(1,0,0); // -1 if medical ? cam->SetViewUp(0,0,1); break; } } } //---------------------------------------------------------------------------- void vtkImageColorViewer::UpdateDisplayExtent() { #if (VTK_MAJOR_VERSION >= 6) vtkAlgorithm *input = this->GetInputAlgorithm(); #else vtkImageData *input = this->GetInput(); #endif if (!input || !this->ImageActor) { return; } input->UpdateInformation(); #if (VTK_MAJOR_VERSION >= 6) vtkInformation* outInfo = input->GetOutputInformation(0); int *w_ext = outInfo->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); #else int *w_ext = input->GetWholeExtent(); #endif // Is the slice in range ? If not, fix it int slice_min = w_ext[this->SliceOrientation * 2]; int slice_max = w_ext[this->SliceOrientation * 2 + 1]; if (this->Slice < slice_min || this->Slice > slice_max) { this->Slice = static_cast((slice_min + slice_max) * 0.5); } // Set the image actor switch (this->SliceOrientation) { case vtkImageColorViewer::SLICE_ORIENTATION_XY: this->ImageActor->SetDisplayExtent( w_ext[0], w_ext[1], w_ext[2], w_ext[3], this->Slice, this->Slice); break; case vtkImageColorViewer::SLICE_ORIENTATION_XZ: this->ImageActor->SetDisplayExtent( w_ext[0], w_ext[1], this->Slice, this->Slice, w_ext[4], w_ext[5]); break; case vtkImageColorViewer::SLICE_ORIENTATION_YZ: this->ImageActor->SetDisplayExtent( this->Slice, this->Slice, w_ext[2], w_ext[3], w_ext[4], w_ext[5]); break; } // Figure out the correct clipping range if (this->Renderer) { if (this->InteractorStyle && this->InteractorStyle->GetAutoAdjustCameraClippingRange()) { this->Renderer->ResetCameraClippingRange(); } else { vtkCamera *cam = this->Renderer->GetActiveCamera(); if (cam) { double bounds[6]; this->ImageActor->GetBounds(bounds); double spos = (double)bounds[this->SliceOrientation * 2]; double cpos = (double)cam->GetPosition()[this->SliceOrientation]; double range = fabs(spos - cpos); #if (VTK_MAJOR_VERSION >= 6) double *spacing = outInfo->Get(vtkDataObject::SPACING()); #else double *spacing = input->GetSpacing(); #endif double avg_spacing = ((double)spacing[0] + (double)spacing[1] + (double)spacing[2]) / 3.0; cam->SetClippingRange( range - avg_spacing * 3.0, range + avg_spacing * 3.0); } } } } //---------------------------------------------------------------------------- void vtkImageColorViewer::SetPosition(int a,int b) { this->RenderWindow->SetPosition(a, b); } //---------------------------------------------------------------------------- int* vtkImageColorViewer::GetPosition() { return this->RenderWindow->GetPosition(); } //---------------------------------------------------------------------------- void vtkImageColorViewer::SetDisplayId(void *a) { this->RenderWindow->SetDisplayId(a); } //---------------------------------------------------------------------------- void vtkImageColorViewer::SetWindowId(void *a) { this->RenderWindow->SetWindowId(a); } //---------------------------------------------------------------------------- void vtkImageColorViewer::SetParentId(void *a) { this->RenderWindow->SetParentId(a); } //---------------------------------------------------------------------------- double vtkImageColorViewer::GetColorWindow() { return this->WindowLevel->GetWindow(); } //---------------------------------------------------------------------------- double vtkImageColorViewer::GetColorLevel() { return this->WindowLevel->GetLevel(); } //---------------------------------------------------------------------------- void vtkImageColorViewer::SetColorWindow(double s) { this->WindowLevel->SetWindow(s); } //---------------------------------------------------------------------------- void vtkImageColorViewer::SetColorLevel(double s) { this->WindowLevel->SetLevel(s); } //---------------------------------------------------------------------------- class vtkImageColorViewerCallback : public vtkCommand { public: static vtkImageColorViewerCallback *New() { return new vtkImageColorViewerCallback; } void Execute(vtkObject *caller, unsigned long event, void *vtkNotUsed(callData)) { if (this->IV->GetInput() == NULL) { return; } // Reset if (event == vtkCommand::ResetWindowLevelEvent) { #if VTK_MAJOR_VERSION > 7 || (VTK_MAJOR_VERSION == 7 && VTK_MINOR_VERSION >= 1) this->IV->GetInputAlgorithm()->UpdateInformation(); this->IV->GetInputInformation()->Set( vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), vtkStreamingDemandDrivenPipeline::GetWholeExtent( this->IV->GetInputInformation()), 6); this->IV->GetInputAlgorithm()->Update(); #elif (VTK_MAJOR_VERSION >= 6) this->IV->GetInputAlgorithm()->UpdateInformation(); vtkStreamingDemandDrivenPipeline::SetUpdateExtent( this->IV->GetInputInformation(), vtkStreamingDemandDrivenPipeline::GetWholeExtent( this->IV->GetInputInformation())); this->IV->GetInputAlgorithm()->Update(); #else this->IV->GetInput()->UpdateInformation(); this->IV->GetInput()->SetUpdateExtent (this->IV->GetInput()->GetWholeExtent()); this->IV->GetInput()->Update(); #endif double *range = this->IV->GetInput()->GetScalarRange(); this->IV->SetColorWindow(range[1] - range[0]); this->IV->SetColorLevel(0.5 * (range[1] + range[0])); this->IV->Render(); return; } // Start if (event == vtkCommand::StartWindowLevelEvent) { this->InitialWindow = this->IV->GetColorWindow(); this->InitialLevel = this->IV->GetColorLevel(); return; } // Adjust the window level here vtkInteractorStyleImage *isi = static_cast(caller); int *size = this->IV->GetRenderWindow()->GetSize(); double window = this->InitialWindow; double level = this->InitialLevel; // Compute normalized delta double dx = 4.0 * (isi->GetWindowLevelCurrentPosition()[0] - isi->GetWindowLevelStartPosition()[0]) / size[0]; double dy = 4.0 * (isi->GetWindowLevelStartPosition()[1] - isi->GetWindowLevelCurrentPosition()[1]) / size[1]; // Scale by current values if (fabs(window) > 0.01) { dx = dx * window; } else { dx = dx * (window < 0 ? -0.01 : 0.01); } if (fabs(level) > 0.01) { dy = dy * level; } else { dy = dy * (level < 0 ? -0.01 : 0.01); } // Abs so that direction does not flip if (window < 0.0) { dx = -1*dx; } if (level < 0.0) { dy = -1*dy; } // Compute new window level double newWindow = dx + window; double newLevel; newLevel = level - dy; // Stay away from zero and really if (fabs(newWindow) < 0.01) { newWindow = 0.01*(newWindow < 0 ? -1 : 1); } if (fabs(newLevel) < 0.01) { newLevel = 0.01*(newLevel < 0 ? -1 : 1); } this->IV->SetColorWindow(newWindow); this->IV->SetColorLevel(newLevel); this->IV->Render(); } vtkImageColorViewer *IV; double InitialWindow; double InitialLevel; }; //---------------------------------------------------------------------------- void vtkImageColorViewer::InstallPipeline() { if (this->RenderWindow && this->Renderer) { this->RenderWindow->AddRenderer(this->Renderer); } if (this->Interactor) { if (!this->InteractorStyle) { this->InteractorStyle = vtkInteractorStyleImage::New(); vtkImageColorViewerCallback *cbk = vtkImageColorViewerCallback::New(); cbk->IV = this; this->InteractorStyle->AddObserver( vtkCommand::WindowLevelEvent, cbk); this->InteractorStyle->AddObserver( vtkCommand::StartWindowLevelEvent, cbk); this->InteractorStyle->AddObserver( vtkCommand::ResetWindowLevelEvent, cbk); cbk->Delete(); } this->Interactor->SetInteractorStyle(this->InteractorStyle); this->Interactor->SetRenderWindow(this->RenderWindow); } if (this->Renderer && this->ImageActor) { this->Renderer->AddViewProp(this->ImageActor); } if (this->ImageActor && this->WindowLevel) { #if (VTK_MAJOR_VERSION >= 6) this->ImageActor->GetMapper()->SetInputConnection( this->WindowLevel->GetOutputPort()); #else this->ImageActor->SetInput(this->WindowLevel->GetOutput()); #endif } } //---------------------------------------------------------------------------- void vtkImageColorViewer::UnInstallPipeline() { if (this->ImageActor) { #if (VTK_MAJOR_VERSION >= 6) this->ImageActor->GetMapper()->SetInputConnection(NULL); #else this->ImageActor->SetInput(NULL); #endif } if (this->Renderer && this->ImageActor) { this->Renderer->RemoveViewProp(this->ImageActor); } if (this->RenderWindow && this->Renderer) { this->RenderWindow->RemoveRenderer(this->Renderer); } if (this->Interactor) { this->Interactor->SetInteractorStyle(NULL); this->Interactor->SetRenderWindow(NULL); } } //---------------------------------------------------------------------------- void vtkImageColorViewer::Render() { if (this->FirstRender) { // Initialize the size if not set yet #if (VTK_MAJOR_VERSION >= 6) vtkAlgorithm *input = this->GetInputAlgorithm(); #else vtkImageData *input = this->GetInput(); #endif if (input) { input->UpdateInformation(); #if (VTK_MAJOR_VERSION >= 6) int *w_ext = this->GetInputInformation()->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); #else int *w_ext = input->GetWholeExtent(); #endif int xs = 0, ys = 0; switch (this->SliceOrientation) { case vtkImageColorViewer::SLICE_ORIENTATION_XY: default: xs = w_ext[1] - w_ext[0] + 1; ys = w_ext[3] - w_ext[2] + 1; break; case vtkImageColorViewer::SLICE_ORIENTATION_XZ: xs = w_ext[1] - w_ext[0] + 1; ys = w_ext[5] - w_ext[4] + 1; break; case vtkImageColorViewer::SLICE_ORIENTATION_YZ: xs = w_ext[3] - w_ext[2] + 1; ys = w_ext[5] - w_ext[4] + 1; break; } // if it would be smaller than 150 by 100 then limit to 150 by 100 if (this->RenderWindow->GetSize()[0] == 0) { this->RenderWindow->SetSize( xs < 150 ? 150 : xs, ys < 100 ? 100 : ys); } if (this->Renderer) { this->Renderer->ResetCamera(); this->Renderer->GetActiveCamera()->SetParallelScale( xs < 150 ? 75 : (xs - 1 ) / 2.0); } this->FirstRender = 0; } } if (this->GetInput()) { this->RenderWindow->Render(); } } //---------------------------------------------------------------------------- const char* vtkImageColorViewer::GetWindowName() { return this->RenderWindow->GetWindowName(); } //---------------------------------------------------------------------------- void vtkImageColorViewer::SetOffScreenRendering(int i) { this->RenderWindow->SetOffScreenRendering(i); } //---------------------------------------------------------------------------- int vtkImageColorViewer::GetOffScreenRendering() { return this->RenderWindow->GetOffScreenRendering(); } //---------------------------------------------------------------------------- #if (VTK_MAJOR_VERSION >= 6) void vtkImageColorViewer::SetInputData(vtkImageData *in) { this->WindowLevel->SetInputData(in); this->UpdateDisplayExtent(); } #else void vtkImageColorViewer::SetInput(vtkImageData *in) { this->WindowLevel->SetInput(in); this->UpdateDisplayExtent(); } #endif //---------------------------------------------------------------------------- vtkImageData* vtkImageColorViewer::GetInput() { return vtkImageData::SafeDownCast(this->WindowLevel->GetInput()); } //---------------------------------------------------------------------------- #if (VTK_MAJOR_VERSION >= 6) vtkInformation* vtkImageColorViewer::GetInputInformation() { return this->WindowLevel->GetInputInformation(); } //---------------------------------------------------------------------------- vtkAlgorithm* vtkImageColorViewer::GetInputAlgorithm() { return this->WindowLevel->GetInputAlgorithm(); } #endif //---------------------------------------------------------------------------- void vtkImageColorViewer::SetInputConnection(vtkAlgorithmOutput* input) { this->WindowLevel->SetInputConnection(input); this->UpdateDisplayExtent(); } //---------------------------------------------------------------------------- /* void vtkImageColorViewer::AddInput(vtkPolyData * input) { vtkRenderWindow *renwin = this->GetRenderWindow (); vtkRenderer *Renderer = vtkRenderer::New(); vtkPolyDataMapper * mapper = vtkPolyDataMapper::New(); mapper->SetInput( input ); vtkActor * actor = vtkActor::New(); actor->SetMapper( mapper ); Renderer->AddViewProp(actor); renwin->AddRenderer(Renderer); Renderer->Delete(); mapper->Delete(); actor->Delete(); } */ void vtkImageColorViewer::AddInput(vtkImageData * input) { vtkRenderWindow *renwin = this->GetRenderWindow (); renwin->SetNumberOfLayers(2); vtkRenderer *renderer = vtkRenderer::New(); renderer->SetLayer(1); OverlayImageActor->SetOpacity(0.5); vtkImageMapToWindowLevelColors2 *windowLevel = vtkImageMapToWindowLevelColors2::New(); #if (VTK_MAJOR_VERSION >= 6) windowLevel->SetInputData(input); OverlayImageActor->SetInputData(windowLevel->GetOutput()); #else windowLevel->SetInput(input); OverlayImageActor->SetInput(windowLevel->GetOutput()); #endif renderer->AddViewProp(OverlayImageActor); OverlayImageActor->SetVisibility(1); renwin->AddRenderer(renderer); renderer->Delete(); windowLevel->Delete(); } void vtkImageColorViewer::AddInputConnection(vtkAlgorithmOutput* input) { vtkRenderWindow *renwin = this->GetRenderWindow (); renwin->SetNumberOfLayers(2); vtkRenderer *renderer = vtkRenderer::New(); renderer->SetLayer(1); OverlayImageActor->SetOpacity(0.5); vtkImageMapToWindowLevelColors2 *windowLevel = vtkImageMapToWindowLevelColors2::New(); windowLevel->SetInputConnection(input); #if (VTK_MAJOR_VERSION >= 6) OverlayImageActor->SetInputData(windowLevel->GetOutput()); #else OverlayImageActor->SetInput(windowLevel->GetOutput()); #endif renderer->AddViewProp(OverlayImageActor); OverlayImageActor->SetVisibility(1); renwin->AddRenderer(renderer); renderer->Delete(); windowLevel->Delete(); } double vtkImageColorViewer::GetOverlayVisibility() { return this->OverlayImageActor->GetVisibility(); } void vtkImageColorViewer::SetOverlayVisibility(double vis) { this->OverlayImageActor->SetVisibility((int)vis); } //---------------------------------------------------------------------------- #ifndef VTK_LEGACY_REMOVE int vtkImageColorViewer::GetWholeZMin() { VTK_LEGACY_REPLACED_BODY(vtkImageColorViewer::GetWholeZMin, "VTK 5.0", vtkImageColorViewer::GetSliceMin); return this->GetSliceMin(); } int vtkImageColorViewer::GetWholeZMax() { VTK_LEGACY_REPLACED_BODY(vtkImageColorViewer::GetWholeZMax, "VTK 5.0", vtkImageColorViewer::GetSliceMax); return this->GetSliceMax(); } int vtkImageColorViewer::GetZSlice() { VTK_LEGACY_REPLACED_BODY(vtkImageColorViewer::GetZSlice, "VTK 5.0", vtkImageColorViewer::GetSlice); return this->GetSlice(); } void vtkImageColorViewer::SetZSlice(int s) { VTK_LEGACY_REPLACED_BODY(vtkImageColorViewer::SetZSlice, "VTK 5.0", vtkImageColorViewer::SetSlice); this->SetSlice(s); } #endif //---------------------------------------------------------------------------- void vtkImageColorViewer::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "RenderWindow:\n"; this->RenderWindow->PrintSelf(os,indent.GetNextIndent()); os << indent << "Renderer:\n"; this->Renderer->PrintSelf(os,indent.GetNextIndent()); os << indent << "ImageActor:\n"; this->ImageActor->PrintSelf(os,indent.GetNextIndent()); os << indent << "WindowLevel:\n" << endl; this->WindowLevel->PrintSelf(os,indent.GetNextIndent()); os << indent << "Slice: " << this->Slice << endl; os << indent << "SliceOrientation: " << this->SliceOrientation << endl; os << indent << "InteractorStyle: " << endl; if (this->InteractorStyle) { os << "\n"; this->InteractorStyle->PrintSelf(os,indent.GetNextIndent()); } else { os << "None"; } } GDCM-3.0.10/Utilities/VTK/vtkImageColorViewer.h000066400000000000000000000213731412732066400210400ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // .NAME vtkImageColorViewer - Display a 2D image. // .SECTION Description // vtkImageColorViewer is a convenience class for displaying a 2D image. It // packages up the functionality found in vtkRenderWindow, vtkRenderer, // vtkImageActor and vtkImageMapToWindowLevelColors into a single easy to use // class. This class also creates an image interactor style // (vtkInteractorStyleImage) that allows zooming and panning of images, and // supports interactive window/level operations on the image. Note that // vtkImageColorViewer is simply a wrapper around these classes. // // vtkImageColorViewer uses the 3D rendering and texture mapping engine // to draw an image on a plane. This allows for rapid rendering, // zooming, and panning. The image is placed in the 3D scene at a // depth based on the z-coordinate of the particular image slice. Each // call to SetSlice() changes the image data (slice) displayed AND // changes the depth of the displayed slice in the 3D scene. This can // be controlled by the AutoAdjustCameraClippingRange ivar of the // InteractorStyle member. // // It is possible to mix images and geometry, using the methods: // // viewer->SetInput( myImage ); // viewer->GetRenderer()->AddActor( myActor ); // // This can be used to annotate an image with a PolyData of "edges" or // or highlight sections of an image or display a 3D isosurface // with a slice from the volume, etc. Any portions of your geometry // that are in front of the displayed slice will be visible; any // portions of your geometry that are behind the displayed slice will // be obscured. A more general framework (with respect to viewing // direction) for achieving this effect is provided by the // vtkImagePlaneWidget . // // Note that pressing 'r' will reset the window/level and pressing // shift+'r' or control+'r' will reset the camera. // // .SECTION See Also // vtkRenderWindow vtkRenderer vtkImageActor vtkImageMapToWindowLevelColors #ifndef VTKIMAGECOLORVIEWER_H #define VTKIMAGECOLORVIEWER_H #include "vtkObject.h" #include "vtkVersion.h" class vtkAlgorithm; class vtkAlgorithmOutput; class vtkImageActor; class vtkImageData; class vtkImageMapToWindowLevelColors2; class vtkInformation; class vtkInteractorStyleImage; class vtkRenderWindow; class vtkRenderer; class vtkRenderWindowInteractor; class vtkPolyData; class VTK_EXPORT vtkImageColorViewer : public vtkObject { public: static vtkImageColorViewer *New(); vtkTypeMacro(vtkImageColorViewer,vtkObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Get the name of rendering window. virtual const char *GetWindowName(); // Description: // Render the resulting image. virtual void Render(void); // Description: // Set/Get the input image to the viewer. #if (VTK_MAJOR_VERSION >= 6) virtual void SetInputData(vtkImageData *in); #else virtual void SetInput(vtkImageData *in); #endif virtual vtkImageData *GetInput(); virtual void SetInputConnection(vtkAlgorithmOutput* input); virtual void AddInputConnection(vtkAlgorithmOutput* input); virtual void AddInput(vtkImageData * input); //virtual void AddInput(vtkPolyData * input); double GetOverlayVisibility(); void SetOverlayVisibility(double vis); // Description: // Set/get the slice orientation //BTX enum { SLICE_ORIENTATION_YZ = 0, SLICE_ORIENTATION_XZ = 1, SLICE_ORIENTATION_XY = 2 }; //ETX vtkGetMacro(SliceOrientation, int); virtual void SetSliceOrientation(int orientation); virtual void SetSliceOrientationToXY() { this->SetSliceOrientation(vtkImageColorViewer::SLICE_ORIENTATION_XY); }; virtual void SetSliceOrientationToYZ() { this->SetSliceOrientation(vtkImageColorViewer::SLICE_ORIENTATION_YZ); }; virtual void SetSliceOrientationToXZ() { this->SetSliceOrientation(vtkImageColorViewer::SLICE_ORIENTATION_XZ); }; // Description: // Set/Get the current slice to display (depending on the orientation // this can be in X, Y or Z). vtkGetMacro(Slice, int); virtual void SetSlice(int s); // Description: // Update the display extent manually so that the proper slice for the // given orientation is displayed. It will also try to set a // reasonable camera clipping range. // This method is called automatically when the Input is changed, but // most of the time the input of this class is likely to remain the same, // i.e. connected to the output of a filter, or an image reader. When the // input of this filter or reader itself is changed, an error message might // be displayed since the current display extent is probably outside // the new whole extent. Calling this method will ensure that the display // extent is reset properly. virtual void UpdateDisplayExtent(); // Description: // Return the minimum and maximum slice values (depending on the orientation // this can be in X, Y or Z). virtual int GetSliceMin(); virtual int GetSliceMax(); virtual void GetSliceRange(int range[2]) { this->GetSliceRange(range[0], range[1]); } virtual void GetSliceRange(int &min, int &max); virtual int* GetSliceRange(); // Description: // Set window and level for mapping pixels to colors. virtual double GetColorWindow(); virtual double GetColorLevel(); virtual void SetColorWindow(double s); virtual void SetColorLevel(double s); // Description: // These are here when using a Tk window. virtual void SetDisplayId(void *a); virtual void SetWindowId(void *a); virtual void SetParentId(void *a); // Description: // Set/Get the position in screen coordinates of the rendering window. virtual int* GetPosition(); virtual void SetPosition(int a,int b); virtual void SetPosition(int a[2]) { this->SetPosition(a[0],a[1]); } // Description: // Set/Get the size of the window in screen coordinates in pixels. virtual int* GetSize(); virtual void SetSize(int a, int b); virtual void SetSize(int a[2]) { this->SetSize(a[0],a[1]); } // Description: // Get the internal render window, renderer, image actor, and // image map instances. vtkGetObjectMacro(RenderWindow,vtkRenderWindow); vtkGetObjectMacro(Renderer, vtkRenderer); vtkGetObjectMacro(ImageActor,vtkImageActor); vtkGetObjectMacro(WindowLevel,vtkImageMapToWindowLevelColors2); vtkGetObjectMacro(InteractorStyle,vtkInteractorStyleImage); // Description: // Set your own renderwindow and renderer virtual void SetRenderWindow(vtkRenderWindow *arg); virtual void SetRenderer(vtkRenderer *arg); // Description: // Attach an interactor for the internal render window. virtual void SetupInteractor(vtkRenderWindowInteractor*); // Description: // Create a window in memory instead of on the screen. This may not // be supported for every type of window and on some windows you may // need to invoke this prior to the first render. virtual void SetOffScreenRendering(int); virtual int GetOffScreenRendering(); vtkBooleanMacro(OffScreenRendering,int); // Description: // @deprecated Replaced by vtkImageColorViewer::GetSliceMin() as of VTK 5.0. VTK_LEGACY(int GetWholeZMin()); // Description: // @deprecated Replaced by vtkImageColorViewer::GetSliceMax() as of VTK 5.0. VTK_LEGACY(int GetWholeZMax()); // Description: // @deprecated Replaced by vtkImageColorViewer::GetSlice() as of VTK 5.0. VTK_LEGACY(int GetZSlice()); // Description: // @deprecated Replaced by vtkImageColorViewer::SetSlice() as of VTK 5.0. VTK_LEGACY(void SetZSlice(int)); protected: vtkImageColorViewer(); ~vtkImageColorViewer(); virtual void InstallPipeline(); virtual void UnInstallPipeline(); vtkImageMapToWindowLevelColors2 *WindowLevel; vtkRenderWindow *RenderWindow; vtkRenderer *Renderer; vtkImageActor *ImageActor; vtkImageActor *OverlayImageActor; vtkRenderWindowInteractor *Interactor; vtkInteractorStyleImage *InteractorStyle; int SliceOrientation; int FirstRender; int Slice; virtual void UpdateOrientation(); #if (VTK_MAJOR_VERSION >= 6) vtkAlgorithm* GetInputAlgorithm(); vtkInformation* GetInputInformation(); #endif friend class vtkImageColorViewerCallback; private: vtkImageColorViewer(const vtkImageColorViewer&); // Not implemented. void operator=(const vtkImageColorViewer&); // Not implemented. }; #endif GDCM-3.0.10/Utilities/VTK/vtkImageMapToColors16.cxx000066400000000000000000000246131412732066400215240ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /*========================================================================= Portions of this file are subject to the VTK Toolkit Version 3 copyright. Program: Visualization Toolkit Module: $RCSfile: vtkImageMapToColors16.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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 "vtkImageMapToColors16.h" #include "vtkImageData.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkObjectFactory.h" #include "vtkStreamingDemandDrivenPipeline.h" #include "vtkScalarsToColors.h" #include "vtkPointData.h" //vtkCxxRevisionMacro(vtkImageMapToColors16, "$Revision: 1.30 $") vtkStandardNewMacro(vtkImageMapToColors16) vtkCxxSetObjectMacro(vtkImageMapToColors16,LookupTable,vtkScalarsToColors) //---------------------------------------------------------------------------- // Constructor sets default values vtkImageMapToColors16::vtkImageMapToColors16() { this->OutputFormat = 4; this->ActiveComponent = 0; this->PassAlphaToOutput = 0; this->LookupTable = NULL; this->DataWasPassed = 0; } //---------------------------------------------------------------------------- vtkImageMapToColors16::~vtkImageMapToColors16() { if (this->LookupTable != NULL) { this->LookupTable->UnRegister(this); } } //---------------------------------------------------------------------------- #ifdef VTK_HAS_MTIME_TYPE vtkMTimeType #else unsigned long #endif vtkImageMapToColors16::GetMTime() { unsigned long t1, t2; t1 = this->Superclass::GetMTime(); if (this->LookupTable) { t2 = this->LookupTable->GetMTime(); if (t2 > t1) { t1 = t2; } } return t1; } //---------------------------------------------------------------------------- // This method checks to see if we can simply reference the input data int vtkImageMapToColors16::RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) { vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); vtkInformation *outInfo = outputVector->GetInformationObject(0); vtkImageData *outData = vtkImageData::SafeDownCast( outInfo->Get(vtkDataObject::DATA_OBJECT())); vtkImageData *inData = vtkImageData::SafeDownCast( inInfo->Get(vtkDataObject::DATA_OBJECT())); // If LookupTable is null, just pass the data if (this->LookupTable == NULL) { vtkDebugMacro("RequestData: LookupTable not set, "\ "passing input to output."); outData->SetExtent(inData->GetExtent()); outData->GetPointData()->PassData(inData->GetPointData()); this->DataWasPassed = 1; } else // normal behaviour { this->LookupTable->Build(); //make sure table is built if (this->DataWasPassed) { outData->GetPointData()->SetScalars(NULL); this->DataWasPassed = 0; } return this->Superclass::RequestData(request, inputVector, outputVector); } return 1; } //---------------------------------------------------------------------------- int vtkImageMapToColors16::RequestInformation ( vtkInformation * vtkNotUsed(request), vtkInformationVector **inputVector, vtkInformationVector *outputVector) { // get the info objects vtkInformation* outInfo = outputVector->GetInformationObject(0); vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); int numComponents = 4; switch (this->OutputFormat) { case VTK_RGBA: numComponents = 4; break; case VTK_RGB: numComponents = 3; break; case VTK_LUMINANCE_ALPHA: numComponents = 2; break; case VTK_LUMINANCE: numComponents = 1; break; default: vtkErrorMacro("RequestInformation: Unrecognized color format."); break; } if (this->LookupTable == NULL) { vtkInformation *scalarInfo = vtkDataObject::GetActiveFieldInformation(inInfo, vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); if ( scalarInfo->Get(vtkDataObject::FIELD_ARRAY_TYPE()) != VTK_UNSIGNED_CHAR ) { vtkErrorMacro( "RequestInformation: No LookupTable was set but input data is not " "VTK_UNSIGNED_CHAR, therefore input can't be passed through!"); return 1; } else if ( numComponents != scalarInfo->Get(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS()) ) { vtkErrorMacro( "RequestInformation: No LookupTable was set but number of components " "in input doesn't match OutputFormat, therefore input can't be passed" " through!"); return 1; } } // vtkDataObject:: // SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, numComponents); vtkDataObject:: SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_SHORT, numComponents); return 1; } //---------------------------------------------------------------------------- // This non-templated function executes the filter for any type of data. void vtkImageMapToColors16Execute(vtkImageMapToColors16 *self, vtkImageData *inData, void *inPtr, vtkImageData *outData, unsigned short *outPtr, int outExt[6], int id) { int idxY, idxZ; int extX, extY, extZ; vtkIdType inIncX, inIncY, inIncZ; vtkIdType outIncX, outIncY, outIncZ; unsigned long count = 0; unsigned long target; int dataType = inData->GetScalarType(); int scalarSize = inData->GetScalarSize(); int numberOfComponents,numberOfOutputComponents,outputFormat; int rowLength; vtkScalarsToColors *lookupTable = self->GetLookupTable(); unsigned short *outPtr1; void *inPtr1; // find the region to loop over extX = outExt[1] - outExt[0] + 1; extY = outExt[3] - outExt[2] + 1; extZ = outExt[5] - outExt[4] + 1; target = static_cast(extZ*extY/50.0); target++; // Get increments to march through data inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); // because we are using void * and char * we must take care // of the scalar size in the increments inIncY *= scalarSize; inIncZ *= scalarSize; outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); numberOfComponents = inData->GetNumberOfScalarComponents(); numberOfOutputComponents = outData->GetNumberOfScalarComponents(); outputFormat = self->GetOutputFormat(); rowLength = extX*scalarSize*numberOfComponents; // Loop through output pixels outPtr1 = outPtr; inPtr1 = static_cast( static_cast(inPtr) + self->GetActiveComponent()*scalarSize); for (idxZ = 0; idxZ < extZ; idxZ++) { for (idxY = 0; !self->AbortExecute && idxY < extY; idxY++) { if (!id) { if (!(count%target)) { self->UpdateProgress((double)count/(50.0*(double)target)); } count++; } lookupTable->MapScalarsThroughTable2(inPtr1,(unsigned char*)outPtr1, dataType,extX,numberOfComponents, outputFormat); //if (self->GetPassAlphaToOutput() && // dataType == VTK_UNSIGNED_CHAR && numberOfComponents > 1 && // (outputFormat == VTK_RGBA || outputFormat == VTK_LUMINANCE_ALPHA)) // { // unsigned char *outPtr2 = outPtr1 + numberOfOutputComponents - 1; // unsigned char *inPtr2 = static_cast(inPtr1) // - self->GetActiveComponent()*scalarSize + numberOfComponents - 1; // for (int i = 0; i < extX; i++) // { // *outPtr2 = (*outPtr2 * *inPtr2)/255; // outPtr2 += numberOfOutputComponents; // inPtr2 += numberOfComponents; // } // } outPtr1 += outIncY + extX*numberOfOutputComponents; inPtr1 = static_cast( static_cast(inPtr1) + inIncY + rowLength); } outPtr1 += outIncZ; inPtr1 = static_cast(static_cast(inPtr1) + inIncZ); } } //---------------------------------------------------------------------------- // This method is passed a input and output data, and executes the filter // algorithm to fill the output from the input. void vtkImageMapToColors16::ThreadedRequestData( vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *vtkNotUsed(outputVector), vtkImageData ***inData, vtkImageData **outData, int outExt[6], int id) { void *inPtr = inData[0][0]->GetScalarPointerForExtent(outExt); void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); vtkImageMapToColors16Execute(this, inData[0][0], inPtr, outData[0], static_cast(outPtr), outExt, id); } //---------------------------------------------------------------------------- void vtkImageMapToColors16::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "OutputFormat: " << (this->OutputFormat == VTK_RGBA ? "RGBA" : (this->OutputFormat == VTK_RGB ? "RGB" : (this->OutputFormat == VTK_LUMINANCE_ALPHA ? "LuminanceAlpha" : (this->OutputFormat == VTK_LUMINANCE ? "Luminance" : "Unknown")))) << "\n"; os << indent << "ActiveComponent: " << this->ActiveComponent << "\n"; os << indent << "PassAlphaToOutput: " << this->PassAlphaToOutput << "\n"; os << indent << "LookupTable: "; if (this->LookupTable) { this->LookupTable->PrintSelf(os << endl,indent.GetNextIndent()); } else { os << "(none)\n"; } } GDCM-3.0.10/Utilities/VTK/vtkImageMapToColors16.h000066400000000000000000000103131412732066400211410ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /*========================================================================= Portions of this file are subject to the VTK Toolkit Version 3 copyright. Program: Visualization Toolkit Module: $RCSfile: vtkImageMapToColors16.h,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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. =========================================================================*/ // .NAME vtkImageMapToColors16 - map the input image through a lookup table // .SECTION Description // The vtkImageMapToColors16 filter will take an input image of any valid // scalar type, and map the first component of the image through a // lookup table. The result is an image of type VTK_UNSIGNED_CHAR. // If the lookup table is not set, or is set to NULL, then the input // data will be passed through if it is already of type VTK_UNSIGNED_CHAR. // .SECTION See Also // vtkLookupTable vtkScalarsToColors #ifndef VTKIMAGEMAPTOCOLORS16_H #define VTKIMAGEMAPTOCOLORS16_H #include "vtkThreadedImageAlgorithm.h" class vtkScalarsToColors; class VTK_EXPORT vtkImageMapToColors16 : public vtkThreadedImageAlgorithm { public: static vtkImageMapToColors16 *New(); vtkTypeMacro(vtkImageMapToColors16,vtkThreadedImageAlgorithm); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set the lookup table. virtual void SetLookupTable(vtkScalarsToColors*); vtkGetObjectMacro(LookupTable,vtkScalarsToColors); // Description: // Set the output format, the default is RGBA. vtkSetMacro(OutputFormat,int); vtkGetMacro(OutputFormat,int); void SetOutputFormatToRGBA() { this->OutputFormat = VTK_RGBA; }; void SetOutputFormatToRGB() { this->OutputFormat = VTK_RGB; }; void SetOutputFormatToLuminanceAlpha() { this->OutputFormat = VTK_LUMINANCE_ALPHA; }; void SetOutputFormatToLuminance() { this->OutputFormat = VTK_LUMINANCE; }; // Description: // Set the component to map for multi-component images (default: 0) vtkSetMacro(ActiveComponent,int); vtkGetMacro(ActiveComponent,int); // Description: // Use the alpha component of the input when computing the alpha component // of the output (useful when converting monochrome+alpha data to RGBA) vtkSetMacro(PassAlphaToOutput,int); vtkBooleanMacro(PassAlphaToOutput,int); vtkGetMacro(PassAlphaToOutput,int); // Description: // We need to check the modified time of the lookup table too. #ifdef VTK_HAS_MTIME_TYPE virtual vtkMTimeType GetMTime(); #else virtual unsigned long GetMTime(); #endif protected: vtkImageMapToColors16(); ~vtkImageMapToColors16(); virtual int RequestInformation (vtkInformation *, vtkInformationVector **, vtkInformationVector *); void ThreadedRequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector, vtkImageData ***inData, vtkImageData **outData, int extent[6], int id); virtual int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector); vtkScalarsToColors *LookupTable; int OutputFormat; int ActiveComponent; int PassAlphaToOutput; int DataWasPassed; private: vtkImageMapToColors16(const vtkImageMapToColors16&); // Not implemented. void operator=(const vtkImageMapToColors16&); // Not implemented. }; #endif GDCM-3.0.10/Utilities/VTK/vtkImageMapToWindowLevelColors2.cxx000066400000000000000000000353641412732066400236240ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /*========================================================================= Portions of this file are subject to the VTK Toolkit Version 3 copyright. Program: Visualization Toolkit Module: $RCSfile: vtkImageMapToWindowLevelColors2.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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 "vtkImageMapToWindowLevelColors2.h" #include "vtkDataArray.h" #include "vtkImageData.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkObjectFactory.h" #include "vtkScalarsToColors.h" #include "vtkPointData.h" //vtkCxxRevisionMacro(vtkImageMapToWindowLevelColors2, "$Revision: 1.3 $") vtkStandardNewMacro(vtkImageMapToWindowLevelColors2) // Constructor sets default values vtkImageMapToWindowLevelColors2::vtkImageMapToWindowLevelColors2() { this->Window = 255; this->Level = 127.5; } vtkImageMapToWindowLevelColors2::~vtkImageMapToWindowLevelColors2() { } //---------------------------------------------------------------------------- // This method checks to see if we can simply reference the input data int vtkImageMapToWindowLevelColors2::RequestData( vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) { vtkInformation *outInfo = outputVector->GetInformationObject(0); vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); vtkImageData *outData = vtkImageData::SafeDownCast( outInfo->Get(vtkDataObject::DATA_OBJECT())); vtkImageData *inData = vtkImageData::SafeDownCast( inInfo->Get(vtkDataObject::DATA_OBJECT())); // If LookupTable is null and window / level produces no change, // then just pass the data if (this->LookupTable == NULL && (inData->GetScalarType() == VTK_UNSIGNED_CHAR && this->Window == 255 && this->Level == 127.5)) { vtkDebugMacro("ExecuteData: LookupTable not set, "\ "Window / Level at default, "\ "passing input to output."); outData->SetExtent(inData->GetExtent()); outData->GetPointData()->PassData(inData->GetPointData()); this->DataWasPassed = 1; } else // normal behaviour - skip up a level since we don't want to // call the superclasses ExecuteData - it would pass the data if there // is no lookup table even if there is a window / level - wrong // behavior. { if (this->DataWasPassed) { outData->GetPointData()->SetScalars(NULL); this->DataWasPassed = 0; } return this->vtkThreadedImageAlgorithm::RequestData(request, inputVector, outputVector); } return 1; } //---------------------------------------------------------------------------- int vtkImageMapToWindowLevelColors2::RequestInformation ( vtkInformation *vtkNotUsed(request), vtkInformationVector **inputVector, vtkInformationVector *outputVector) { vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); vtkInformation *outInfo = outputVector->GetInformationObject(0); vtkInformation *inScalarInfo = vtkDataObject::GetActiveFieldInformation(inInfo, vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); if (!inScalarInfo) { vtkErrorMacro("Missing scalar field on input information!"); return 0; } // If LookupTable is null and window / level produces no change, // then the data will be passed if ( this->LookupTable == NULL && (inScalarInfo->Get(vtkDataObject::FIELD_ARRAY_TYPE()) == VTK_UNSIGNED_CHAR && this->Window == 255 && this->Level == 127.5) ) { if (inScalarInfo->Get(vtkDataObject::FIELD_ARRAY_TYPE()) != VTK_UNSIGNED_CHAR) { vtkErrorMacro("ExecuteInformation: No LookupTable was set and input data is not VTK_UNSIGNED_CHAR!"); } else { // no lookup table, pass the input if it was UNSIGNED_CHAR vtkDataObject::SetPointDataActiveScalarInfo (outInfo, VTK_UNSIGNED_CHAR, inScalarInfo->Get(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS())); } } else // the lookup table was set or window / level produces a change { int numComponents = 4; switch (this->OutputFormat) { case VTK_RGBA: numComponents = 4; break; case VTK_RGB: numComponents = 3; break; case VTK_LUMINANCE_ALPHA: numComponents = 2; break; case VTK_LUMINANCE: numComponents = 1; break; default: vtkErrorMacro("ExecuteInformation: Unrecognized color format."); break; } vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, numComponents); } return 1; } /* * This templated routine calculates effective lower and upper limits * for a window of values of type T, lower and upper. */ template void vtkImageMapToWindowLevelClamps ( vtkImageData *data, double w, double l, T& lower, T& upper, unsigned char &lower_val, unsigned char &upper_val) { double f_lower, f_upper, f_lower_val, f_upper_val; double adjustedLower, adjustedUpper; double range[2]; data->GetPointData()->GetScalars()->GetDataTypeRange( range ); f_lower = l - fabs(w) / 2.0; f_upper = f_lower + fabs(w); // Set the correct lower value if ( f_lower <= range[1]) { if (f_lower >= range[0]) { lower = (T) f_lower; adjustedLower = f_lower; } else { lower = (T) range[0]; adjustedLower = range[0]; } } else { lower = (T) range[1]; adjustedLower = range[1]; } // Set the correct upper value if ( f_upper >= range[0]) { if (f_upper <= range[1]) { upper = (T) f_upper; adjustedUpper = f_upper; } else { upper = (T) range[1]; adjustedUpper = range[1]; } } else { upper = (T) range [0]; adjustedUpper = range [0]; } // now compute the lower and upper values if (w >= 0) { f_lower_val = 255.0*(adjustedLower - f_lower)/w; f_upper_val = 255.0*(adjustedUpper - f_lower)/w; } else { f_lower_val = 255.0 + 255.0*(adjustedLower - f_lower)/w; f_upper_val = 255.0 + 255.0*(adjustedUpper - f_lower)/w; } if (f_upper_val > 255) { upper_val = 255; } else if (f_upper_val < 0) { upper_val = 0; } else { upper_val = (unsigned char)(f_upper_val); } if (f_lower_val > 255) { lower_val = 255; } else if (f_lower_val < 0) { lower_val = 0; } else { lower_val = (unsigned char)(f_lower_val); } } //---------------------------------------------------------------------------- // Small helper to do the clamp: template void vtkClampHelper1(T* iptr, unsigned char *optr, T lower, T upper, unsigned char lower_val, unsigned char upper_val, double shift, double scale) { unsigned short ushort_val; if (*iptr <= lower) { ushort_val = lower_val; } else if (*iptr >= upper) { ushort_val = upper_val; } else { ushort_val = (unsigned char) (((double)*iptr + shift)*scale); } *optr = (unsigned char)((*optr * ushort_val) >> 8); } //---------------------------------------------------------------------------- template void vtkClampHelper2(T* iptr, unsigned char *optr, T lower, T upper, unsigned char lower_val, unsigned char upper_val, double shift, double scale) { unsigned char result_val; if (*iptr <= lower) { result_val = lower_val; } else if (*iptr >= upper) { result_val = upper_val; } else { result_val = (unsigned char) (((double)*iptr + shift)*scale); } *optr = result_val; } //---------------------------------------------------------------------------- // This non-templated function executes the filter for any type of data. template void vtkImageMapToWindowLevelColors2Execute( vtkImageMapToWindowLevelColors2 *self, vtkImageData *inData, T *inPtr, vtkImageData *outData, unsigned char *outPtr, int outExt[6], int id) { int idxX, idxY, idxZ; int extX, extY, extZ; vtkIdType inIncX, inIncY, inIncZ; vtkIdType outIncX, outIncY, outIncZ; unsigned long count = 0; unsigned long target; int dataType = inData->GetScalarType(); int numberOfComponents,numberOfOutputComponents,outputFormat; int rowLength; vtkScalarsToColors *lookupTable = self->GetLookupTable(); unsigned char *outPtr1; T *inPtr1; unsigned char *optr; T *iptr; double shift = self->GetWindow() / 2.0 - self->GetLevel(); double scale = 255.0 / self->GetWindow(); T lower, upper; unsigned char lower_val, upper_val; vtkImageMapToWindowLevelClamps( inData, self->GetWindow(), self->GetLevel(), lower, upper, lower_val, upper_val ); // find the region to loop over extX = outExt[1] - outExt[0] + 1; extY = outExt[3] - outExt[2] + 1; extZ = outExt[5] - outExt[4] + 1; target = (unsigned long)(extZ*extY/50.0); target++; // Get increments to march through data inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); numberOfComponents = inData->GetNumberOfScalarComponents(); numberOfOutputComponents = outData->GetNumberOfScalarComponents(); outputFormat = self->GetOutputFormat(); rowLength = extX*numberOfComponents; // Loop through output pixels outPtr1 = outPtr; inPtr1 = inPtr; for (idxZ = 0; idxZ < extZ; idxZ++) { for (idxY = 0; !self->AbortExecute && idxY < extY; idxY++) { if (!id) { if (!(count%target)) { self->UpdateProgress((double)count/(50.0*(double)target)); } count++; } iptr = inPtr1; optr = outPtr1; if ( lookupTable ) { lookupTable->MapScalarsThroughTable2(inPtr1,(unsigned char *)outPtr1, dataType,extX,numberOfComponents, outputFormat); for (idxX = 0; idxX < extX; idxX++) { vtkClampHelper1(iptr,optr,lower,upper,lower_val,upper_val,shift,scale); switch (outputFormat) { case VTK_RGBA: vtkClampHelper1(iptr+(1%numberOfComponents),optr+1,lower,upper,lower_val,upper_val,shift,scale); vtkClampHelper1(iptr+(2%numberOfComponents),optr+2,lower,upper,lower_val,upper_val,shift,scale); *(optr+3) = 255; break; case VTK_RGB: vtkClampHelper1(iptr+(1%numberOfComponents),optr+1,lower,upper,lower_val,upper_val,shift,scale); vtkClampHelper1(iptr+(2%numberOfComponents),optr+2,lower,upper,lower_val,upper_val,shift,scale); break; case VTK_LUMINANCE_ALPHA: *(optr+1) = 255; break; } iptr += numberOfComponents; optr += numberOfOutputComponents; } } else { for (idxX = 0; idxX < extX; idxX++) { // We want to shift to the right position depending on the numberOfComponents from input // if grayscale we should stay at the same position, otherwise need to shift to r,g,b // (0%numberOfComponents) == 0 ... // (1%numberOfComponents) == 0 or 1 vtkClampHelper2(iptr,optr,lower,upper,lower_val,upper_val,shift,scale); switch (outputFormat) { case VTK_RGBA: vtkClampHelper2(iptr+(1%numberOfComponents),optr+1,lower,upper,lower_val,upper_val,shift,scale); vtkClampHelper2(iptr+(2%numberOfComponents),optr+2,lower,upper,lower_val,upper_val,shift,scale); *(optr+3) = 255; break; case VTK_RGB: vtkClampHelper2(iptr+(1%numberOfComponents),optr+1,lower,upper,lower_val,upper_val,shift,scale); vtkClampHelper2(iptr+(2%numberOfComponents),optr+2,lower,upper,lower_val,upper_val,shift,scale); break; case VTK_LUMINANCE_ALPHA: *(optr+1) = 255; break; } iptr += numberOfComponents; optr += numberOfOutputComponents; } } outPtr1 += outIncY + extX*numberOfOutputComponents; inPtr1 += inIncY + rowLength; } outPtr1 += outIncZ; inPtr1 += inIncZ; } } //---------------------------------------------------------------------------- // This method is passed a input and output data, and executes the filter // algorithm to fill the output from the input. void vtkImageMapToWindowLevelColors2::ThreadedRequestData( vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *vtkNotUsed(outputVector), vtkImageData ***inData, vtkImageData **outData, int outExt[6], int id) { void *inPtr = inData[0][0]->GetScalarPointerForExtent(outExt); void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); switch (inData[0][0]->GetScalarType()) { vtkTemplateMacro( vtkImageMapToWindowLevelColors2Execute( this, inData[0][0], (VTK_TT *)(inPtr), outData[0], (unsigned char *)(outPtr), outExt, id)); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } //---------------------------------------------------------------------------- void vtkImageMapToWindowLevelColors2::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Window: " << this->Window << endl; os << indent << "Level: " << this->Level << endl; } GDCM-3.0.10/Utilities/VTK/vtkImageMapToWindowLevelColors2.h000066400000000000000000000071731412732066400232460ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /*========================================================================= Portions of this file are subject to the VTK Toolkit Version 3 copyright. Program: Visualization Toolkit Module: $RCSfile: vtkImageMapToWindowLevelColors2.h,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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. =========================================================================*/ // .NAME vtkImageMapToWindowLevelColors2 - map the input image through a lookup table and window / level it // .SECTION Description // The vtkImageMapToWindowLevelColors2 filter will take an input image of any // valid scalar type, and map the first component of the image through a // lookup table. This resulting color will be modulated with value obtained // by a window / level operation. The result is an image of type // VTK_UNSIGNED_CHAR. If the lookup table is not set, or is set to NULL, then // the input data will be passed through if it is already of type // UNSIGNED_CHAR. // // .SECTION See Also // vtkLookupTable vtkScalarsToColors #ifndef VTKIMAGEMAPTOWINDOWLEVELCOLORS2_H #define VTKIMAGEMAPTOWINDOWLEVELCOLORS2_H #include "vtkImageMapToColors.h" class VTK_EXPORT vtkImageMapToWindowLevelColors2 : public vtkImageMapToColors { public: static vtkImageMapToWindowLevelColors2 *New(); vtkTypeMacro(vtkImageMapToWindowLevelColors2,vtkImageMapToColors); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Set / Get the Window to use -> modulation will be performed on the // color based on (S - (L - W/2))/W where S is the scalar value, L is // the level and W is the window. vtkSetMacro( Window, double ); vtkGetMacro( Window, double ); // Description: // Set / Get the Level to use -> modulation will be performed on the // color based on (S - (L - W/2))/W where S is the scalar value, L is // the level and W is the window. vtkSetMacro( Level, double ); vtkGetMacro( Level, double ); protected: vtkImageMapToWindowLevelColors2(); ~vtkImageMapToWindowLevelColors2(); virtual int RequestInformation (vtkInformation *, vtkInformationVector **, vtkInformationVector *); void ThreadedRequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector, vtkImageData ***inData, vtkImageData **outData, int extent[6], int id); virtual int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector); double Window; double Level; private: vtkImageMapToWindowLevelColors2(const vtkImageMapToWindowLevelColors2&); // Not implemented. void operator=(const vtkImageMapToWindowLevelColors2&); // Not implemented. }; #endif GDCM-3.0.10/Utilities/VTK/vtkImagePlanarComponentsToComponents.cxx000066400000000000000000000115671412732066400250130ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /*========================================================================= Portions of this file are subject to the VTK Toolkit Version 3 copyright. Program: Visualization Toolkit Module: $RCSfile: vtkImagePlanarComponentsToComponents.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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 "vtkImagePlanarComponentsToComponents.h" #include "vtkImageData.h" #include "vtkImageProgressIterator.h" #include "vtkMath.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkObjectFactory.h" #include "vtkStreamingDemandDrivenPipeline.h" #include "gdcmImageChangePlanarConfiguration.h" #include //vtkCxxRevisionMacro(vtkImagePlanarComponentsToComponents, "$Revision: 1.31 $") vtkStandardNewMacro(vtkImagePlanarComponentsToComponents) //---------------------------------------------------------------------------- vtkImagePlanarComponentsToComponents::vtkImagePlanarComponentsToComponents() { this->SetNumberOfInputPorts(1); this->SetNumberOfOutputPorts(1); } //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkImagePlanarComponentsToComponentsExecute(vtkImagePlanarComponentsToComponents *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], int id, T *) { int maxX, maxY, maxZ; // find the region to loop over maxX = outExt[1] - outExt[0]; maxY = outExt[3] - outExt[2]; maxZ = outExt[5] - outExt[4]; (void)self; (void)id; //target = static_cast((maxZ+1)*(maxY+1)/50.0); //target++; const T *inPtr = (T*)inData->GetScalarPointer(outExt[0],outExt[2],outExt[4]); T *outPtr = static_cast(outData->GetScalarPointer(outExt[0],outExt[2],outExt[4])); // Loop through ouput pixels size_t framesize = (maxX+1) * (maxY+1) * 3; for(int z = 0; z <= maxZ; ++z) { const T *frame = inPtr + z * framesize; size_t size = framesize / 3; const T *r = frame + 0; const T *g = frame + size; const T *b = frame + size + size; T *framecopy = outPtr + z * framesize; gdcm::ImageChangePlanarConfiguration::RGBPlanesToRGBPixels(framecopy, r, g, b, size); } } //---------------------------------------------------------------------------- int vtkImagePlanarComponentsToComponents::RequestData( vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* outputVector) { int idxX, idxY, idxZ; vtkIdType outIncX, outIncY, outIncZ; int *outExt; double sum; double yContrib, zContrib; double temp, temp2; unsigned long count = 0; unsigned long target; // // get the input vtkInformation* in1Info = inputVector[0]->GetInformationObject(0); vtkImageData *inData = vtkImageData::SafeDownCast( in1Info->Get(vtkDataObject::DATA_OBJECT())); vtkInformation *outInfo = outputVector->GetInformationObject(0); vtkImageData *output = vtkImageData::SafeDownCast( outInfo->Get(vtkDataObject::DATA_OBJECT())); vtkImageData *data = this->AllocateOutputData(output); if (data->GetScalarType() != VTK_UNSIGNED_CHAR && data->GetScalarType() != VTK_UNSIGNED_SHORT ) { vtkErrorMacro("Execute: This source only deal with uchar/ushort"); } outExt = data->GetExtent(); // Get increments to march through data data->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); switch (inData->GetScalarType()) { vtkTemplateMacro( vtkImagePlanarComponentsToComponentsExecute(this, inData, data, outExt, 0, static_cast(0))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return 0; } return 1; } //---------------------------------------------------------------------------- void vtkImagePlanarComponentsToComponents::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } GDCM-3.0.10/Utilities/VTK/vtkImagePlanarComponentsToComponents.h000066400000000000000000000054541412732066400244360ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /*========================================================================= Portions of this file are subject to the VTK Toolkit Version 3 copyright. Program: Visualization Toolkit Module: $RCSfile: vtkImagePlanarComponentsToComponents.h,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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. =========================================================================*/ // .NAME vtkImagePlanarComponentsToComponents - Converts planar comp to pixel comp // .SECTION Description // .SECTION See Also // TODO: Can I make this filter threaded ? // TODO: How do I handle the VTK-flipping (FileLowerLeft)? #ifndef VTKIMAGEPLANARCOMPONENTSTOCOMPONENTS_H #define VTKIMAGEPLANARCOMPONENTSTOCOMPONENTS_H #include "vtkImageAlgorithm.h" // everything is now handled within the vtkGDCMImageReader as Planar Configuration can not // be externalized (conflict with file lower left) #error do not use this class //class VTK_EXPORT vtkImagePlanarComponentsToComponents : public vtkThreadedImageAlgorithm class VTK_EXPORT vtkImagePlanarComponentsToComponents : public vtkImageAlgorithm { public: static vtkImagePlanarComponentsToComponents *New(); //vtkTypeMacro(vtkImagePlanarComponentsToComponents,vtkThreadedImageAlgorithm); vtkTypeMacro(vtkImagePlanarComponentsToComponents,vtkImageAlgorithm); void PrintSelf(ostream& os, vtkIndent indent); protected: vtkImagePlanarComponentsToComponents(); ~vtkImagePlanarComponentsToComponents() {}; // void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, // int ext[6], int id); // virtual int RequestInformation (vtkInformation *, vtkInformationVector**, vtkInformationVector *); virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); private: vtkImagePlanarComponentsToComponents(const vtkImagePlanarComponentsToComponents&); // Not implemented. void operator=(const vtkImagePlanarComponentsToComponents&); // Not implemented. }; #endif GDCM-3.0.10/Utilities/VTK/vtkImageRGBToYBR.cxx000066400000000000000000000110741412732066400204420ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /*========================================================================= Portions of this file are subject to the VTK Toolkit Version 3 copyright. Program: Visualization Toolkit Module: $RCSfile: vtkImageRGBToYBR.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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 "vtkImageRGBToYBR.h" #include "vtkImageData.h" #include "vtkImageProgressIterator.h" #include "vtkMath.h" #include "vtkObjectFactory.h" //vtkCxxRevisionMacro(vtkImageRGBToYBR, "$Revision: 1.31 $") vtkStandardNewMacro(vtkImageRGBToYBR) //---------------------------------------------------------------------------- vtkImageRGBToYBR::vtkImageRGBToYBR() { this->SetNumberOfInputPorts(1); this->SetNumberOfOutputPorts(1); } //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkImageRGBToYBRExecute(vtkImageRGBToYBR *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], int id, T *) { vtkImageIterator inIt(inData, outExt); vtkImageProgressIterator outIt(outData, outExt, self, id); int idxC; // find the region to loop over int maxC = inData->GetNumberOfScalarComponents()-1; // Loop through ouput pixels while (!outIt.IsAtEnd()) { T* inSI = inIt.BeginSpan(); T* outSI = outIt.BeginSpan(); T* outSIEnd = outIt.EndSpan(); while (outSI != outSIEnd) { // http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf // Pixel operation unsigned char r = (unsigned char)(*inSI); ++inSI; unsigned char g = (unsigned char)(*inSI); ++inSI; unsigned char b = (unsigned char)(*inSI); ++inSI; double y = 0.257 * r + 0.504 * g + 0.098 * b + 16; double u = -0.148* r - 0.291 * g + 0.439 * b + 128; double v = 0.439 * r - 0.368 * g - 0.071 * b + 128; // assign output. *outSI = (T)(y); ++outSI; *outSI = (T)(u); ++outSI; *outSI = (T)(v); ++outSI; for (idxC = 3; idxC <= maxC; idxC++) { *outSI++ = *inSI++; } } inIt.NextSpan(); outIt.NextSpan(); } } //---------------------------------------------------------------------------- void vtkImageRGBToYBR::ThreadedExecute (vtkImageData *inData, vtkImageData *outData, int outExt[6], int id) { vtkDebugMacro(<< "Execute: inData = " << inData << ", outData = " << outData); // this filter expects that input is the same type as output. if (inData->GetScalarType() != outData->GetScalarType()) { vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType() << ", must match out ScalarType " << outData->GetScalarType()); return; } if (inData->GetScalarType() != VTK_UNSIGNED_CHAR ) { return; } // need three components for input and output if (inData->GetNumberOfScalarComponents() < 3) { vtkErrorMacro("Input has too few components"); return; } if (outData->GetNumberOfScalarComponents() < 3) { vtkErrorMacro("Output has too few components"); return; } switch (inData->GetScalarType()) { vtkTemplateMacro( vtkImageRGBToYBRExecute(this, inData, outData, outExt, id, static_cast(0))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } //---------------------------------------------------------------------------- void vtkImageRGBToYBR::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } GDCM-3.0.10/Utilities/VTK/vtkImageRGBToYBR.h000066400000000000000000000042031412732066400200630ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /*========================================================================= Portions of this file are subject to the VTK Toolkit Version 3 copyright. Program: Visualization Toolkit Module: $RCSfile: vtkImageRGBToYBR.h,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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. =========================================================================*/ // .NAME vtkImageRGBToYBR - Converts YBR components to RGB. // .SECTION Description // For each pixel with hue, saturation and value components this filter // outputs the color coded as red, green, blue. Output type must be the same // as input type. // .SECTION See Also // vtkImageRGBToHSV #ifndef VTKIMAGERGBTOYBR_H #define VTKIMAGERGBTOYBR_H #include "vtkThreadedImageAlgorithm.h" class VTK_EXPORT vtkImageRGBToYBR : public vtkThreadedImageAlgorithm { public: static vtkImageRGBToYBR *New(); vtkTypeMacro(vtkImageRGBToYBR,vtkThreadedImageAlgorithm); void PrintSelf(ostream& os, vtkIndent indent); protected: vtkImageRGBToYBR(); ~vtkImageRGBToYBR() {}; void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, int ext[6], int id); private: vtkImageRGBToYBR(const vtkImageRGBToYBR&); // Not implemented. void operator=(const vtkImageRGBToYBR&); // Not implemented. }; #endif GDCM-3.0.10/Utilities/VTK/vtkImageYBRToRGB.cxx000066400000000000000000000140461412732066400204440ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /*========================================================================= Portions of this file are subject to the VTK Toolkit Version 3 copyright. Program: Visualization Toolkit Module: $RCSfile: vtkImageYBRToRGB.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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 "vtkImageYBRToRGB.h" #include "vtkImageData.h" #include "vtkImageProgressIterator.h" #include "vtkMath.h" #include "vtkObjectFactory.h" //vtkCxxRevisionMacro(vtkImageYBRToRGB, "$Revision: 1.31 $") vtkStandardNewMacro(vtkImageYBRToRGB) //---------------------------------------------------------------------------- vtkImageYBRToRGB::vtkImageYBRToRGB() { this->SetNumberOfInputPorts(1); this->SetNumberOfOutputPorts(1); } //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkImageYBRToRGBExecute(vtkImageYBRToRGB *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], int id, T *) { vtkImageIterator inIt(inData, outExt); vtkImageProgressIterator outIt(outData, outExt, self, id); int idxC; // find the region to loop over int maxC = inData->GetNumberOfScalarComponents()-1; int R, G, B; // Loop through ouput pixels while (!outIt.IsAtEnd()) { T* inSI = inIt.BeginSpan(); T* outSI = outIt.BeginSpan(); T* outSIEnd = outIt.EndSpan(); while (outSI != outSIEnd) { // Pixel operation #if 1 #if 1 unsigned char a = (unsigned char)(*inSI); ++inSI; unsigned char b = (unsigned char)(*inSI); ++inSI; unsigned char c = (unsigned char)(*inSI); ++inSI; R = 38142 *(a-16) + 52298 *(c -128); G = 38142 *(a-16) - 26640 *(c -128) - 12845 *(b -128); B = 38142 *(a-16) + 66093 *(b -128); R = (R+16384)>>15; G = (G+16384)>>15; B = (B+16384)>>15; #else int /*unsigned char*/ y = (unsigned char)(*inSI); ++inSI; y -= 16; unsigned char u = (unsigned char)(*inSI); ++inSI; int Cb = (int)u - 128; unsigned char v = (unsigned char)(*inSI); ++inSI; int Cr = (int)v - 128; // R = y + (1.4075 * (v - 128)); // G = y - (0.3455 * (u - 128) - (0.7169 * (v - 128))); // B = y + (1.7790 * (u - 128)); R = y + 1.40200 * Cr + 0.5; G = y - 0.34414 * Cb - 0.71414 * Cr + 0.5; B = y + 1.77200 * Cb + 0.5; //int a = (int)y - 16; //int b = (int)u - 128; //int c = (int)v - 128; //R = ( 1.164 * a + 0. * b + 1.596 * c ); //G = ( 1.164 * a + 0.391 * b + 0.813 * c ); //B = ( 1.164 * a + 2.018 * b + 0. * c ); #endif if (R < 0) R = 0; if (G < 0) G = 0; if (B < 0) B = 0; if (R > 255) R = 255; if (G > 255) G = 255; if (B > 255) B = 255; #endif /* double y = *inSI; ++inSI; double u = *inSI; ++inSI; double v = *inSI; ++inSI; unsigned char R,G,B; double maxval = 255.; double dr = y + 1.4020 * v - 0.7010 * maxval; double dg = y - 0.3441 * u - 0.7141 * v + 0.5291 * maxval; double db = y + 1.7720 * u - 0.8859 * maxval; R = (dr < 0.0) ? 0 : ((dr+0.5) > maxval) ? maxval : (unsigned char)(dr+0.5); G = (dg < 0.0) ? 0 : ((dg+0.5) > maxval) ? maxval : (unsigned char)(dg+0.5); B = (db < 0.0) ? 0 : ((db+0.5) > maxval) ? maxval : (unsigned char)(db+0.5); */ // assign output. *outSI = (T)(R); ++outSI; *outSI = (T)(G); ++outSI; *outSI = (T)(B); ++outSI; for (idxC = 3; idxC <= maxC; idxC++) { *outSI++ = *inSI++; } } inIt.NextSpan(); outIt.NextSpan(); } } //---------------------------------------------------------------------------- void vtkImageYBRToRGB::ThreadedExecute (vtkImageData *inData, vtkImageData *outData, int outExt[6], int id) { vtkDebugMacro(<< "Execute: inData = " << inData << ", outData = " << outData); // this filter expects that input is the same type as output. if (inData->GetScalarType() != outData->GetScalarType()) { vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType() << ", must match out ScalarType " << outData->GetScalarType()); return; } if (inData->GetScalarType() != VTK_UNSIGNED_CHAR ) { return; } // need three components for input and output if (inData->GetNumberOfScalarComponents() < 3) { vtkErrorMacro("Input has too few components"); return; } if (outData->GetNumberOfScalarComponents() < 3) { vtkErrorMacro("Output has too few components"); return; } switch (inData->GetScalarType()) { vtkTemplateMacro( vtkImageYBRToRGBExecute(this, inData, outData, outExt, id, static_cast(0))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } //---------------------------------------------------------------------------- void vtkImageYBRToRGB::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } GDCM-3.0.10/Utilities/VTK/vtkImageYBRToRGB.h000066400000000000000000000042031412732066400200630ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /*========================================================================= Portions of this file are subject to the VTK Toolkit Version 3 copyright. Program: Visualization Toolkit Module: $RCSfile: vtkImageYBRToRGB.h,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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. =========================================================================*/ // .NAME vtkImageYBRToRGB - Converts YBR components to RGB. // .SECTION Description // For each pixel with hue, saturation and value components this filter // outputs the color coded as red, green, blue. Output type must be the same // as input type. // .SECTION See Also // vtkImageRGBToHSV #ifndef VTKIMAGEYBRTORGB_H #define VTKIMAGEYBRTORGB_H #include "vtkThreadedImageAlgorithm.h" class VTK_EXPORT vtkImageYBRToRGB : public vtkThreadedImageAlgorithm { public: static vtkImageYBRToRGB *New(); vtkTypeMacro(vtkImageYBRToRGB,vtkThreadedImageAlgorithm); void PrintSelf(ostream& os, vtkIndent indent); protected: vtkImageYBRToRGB(); ~vtkImageYBRToRGB() {}; void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, int ext[6], int id); private: vtkImageYBRToRGB(const vtkImageYBRToRGB&); // Not implemented. void operator=(const vtkImageYBRToRGB&); // Not implemented. }; #endif GDCM-3.0.10/Utilities/VTK/vtkLookupTable16.cxx000066400000000000000000000332211412732066400205730ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /*========================================================================= Portions of this file are subject to the VTK Toolkit Version 3 copyright. Program: Visualization Toolkit Module: $RCSfile: vtkLookupTable16.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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 "vtkLookupTable16.h" #include "vtkObjectFactory.h" #include //vtkCxxRevisionMacro(vtkLookupTable16, "$Revision: 1.107 $") vtkStandardNewMacro(vtkLookupTable16) vtkLookupTable16::vtkLookupTable16(int sze, int ext) : vtkLookupTable(sze, ext) { this->Table16 = vtkUnsignedShortArray::New(); this->Table16->Register(this); this->Table16->Delete(); this->Table16->SetNumberOfComponents(4); this->Table16->Allocate(4*sze,4*ext); } //---------------------------------------------------------------------------- vtkLookupTable16::~vtkLookupTable16() { this->Table16->UnRegister(this); this->Table16 = NULL; } void vtkLookupTable16::Build() { } void vtkLookupTable16::SetNumberOfTableValues(vtkIdType number) { if (this->NumberOfColors == number) { return; } this->Modified(); this->NumberOfColors = number; this->Table16->SetNumberOfTuples(number); } //---------------------------------------------------------------------------- // Apply shift/scale to the scalar value v and do table lookup. inline unsigned short *vtkLinearLookup16(double v, unsigned short *table, double maxIndex, double shift, double scale) { double findx = (v + shift)*scale; if (findx < 0) { findx = 0; } if (findx > maxIndex) { findx = maxIndex; } return &table[4*static_cast(findx)]; /* round return &table[4*(int)(findx + 0.5f)]; */ } void vtkLookupTableLogRange16(double [2], double [2]) { assert(0); } inline double vtkApplyLogScale16(double , double [2], double [2]) { assert(0); return 0; } template void vtkLookupTable16MapData(vtkLookupTable16 *self, T *input, unsigned short *output, int length, int inIncr, int outFormat) { int i = length; double *range = self->GetTableRange(); double maxIndex = (double)self->GetNumberOfColors() - 1; double shift, scale; unsigned short *table = self->GetPointer(0); unsigned short *cptr; double alpha; if ( (alpha=self->GetAlpha()) >= 1.0 ) //no blending required { if (self->GetScale() == VTK_SCALE_LOG10) { double val; double logRange[2]; vtkLookupTableLogRange16(range, logRange); shift = -logRange[0]; if (logRange[1] <= logRange[0]) { scale = VTK_DOUBLE_MAX; } else { /* while this looks like the wrong scale, it is the correct scale * taking into account the truncation to int that happens below. */ scale = (maxIndex + 1)/(logRange[1] - logRange[0]); } if (outFormat == VTK_RGBA) { while (--i >= 0) { val = vtkApplyLogScale16((double)*input, range, logRange); cptr = vtkLinearLookup16(val, table, maxIndex, shift, scale); *output++ = *cptr++; *output++ = *cptr++; *output++ = *cptr++; *output++ = *cptr++; input += inIncr; } } else if (outFormat == VTK_RGB) { while (--i >= 0) { val = vtkApplyLogScale16((double)*input, range, logRange); cptr = vtkLinearLookup16(val, table, maxIndex, shift, scale); *output++ = *cptr++; *output++ = *cptr++; *output++ = *cptr++; input += inIncr; } } else if (outFormat == VTK_LUMINANCE_ALPHA) { while (--i >= 0) { val = vtkApplyLogScale16((double)*input, range, logRange); cptr = vtkLinearLookup16(val, table, maxIndex, shift, scale); *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + cptr[2]*0.11 + 0.5); *output++ = cptr[3]; input += inIncr; } } else // outFormat == VTK_LUMINANCE { while (--i >= 0) { val = vtkApplyLogScale16((double)*input, range, logRange); cptr = vtkLinearLookup16(val, table, maxIndex, shift, scale); *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + cptr[2]*0.11 + 0.5); input += inIncr; } } }//if log scale else //not log scale { shift = -range[0]; if (range[1] <= range[0]) { scale = VTK_DOUBLE_MAX; } else { /* while this looks like the wrong scale, it is the correct scale * taking into account the truncation to int that happens below. */ scale = (maxIndex + 1)/(range[1] - range[0]); } if (outFormat == VTK_RGBA) { while (--i >= 0) { cptr = vtkLinearLookup16((double)*input, table, maxIndex, shift, scale); *output++ = *cptr++; *output++ = *cptr++; *output++ = *cptr++; *output++ = *cptr++; input += inIncr; } } else if (outFormat == VTK_RGB) { while (--i >= 0) { cptr = vtkLinearLookup16((double)*input, table, maxIndex, shift, scale); *output++ = *cptr++; *output++ = *cptr++; *output++ = *cptr++; input += inIncr; } } else if (outFormat == VTK_LUMINANCE_ALPHA) { while (--i >= 0) { cptr = vtkLinearLookup16((double)*input, table, maxIndex, shift, scale); *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + cptr[2]*0.11 + 0.5); *output++ = cptr[3]; input += inIncr; } } else // outFormat == VTK_LUMINANCE { while (--i >= 0) { cptr = vtkLinearLookup16((double)*input, table, maxIndex, shift, scale); *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + cptr[2]*0.11 + 0.5); input += inIncr; } } }//if not log lookup }//if blending not needed else //blend with the specified alpha { if (self->GetScale() == VTK_SCALE_LOG10) { double val; double logRange[2]; vtkLookupTableLogRange16(range, logRange); shift = -logRange[0]; if (logRange[1] <= logRange[0]) { scale = VTK_DOUBLE_MAX; } else { /* while this looks like the wrong scale, it is the correct scale * taking into account the truncation to int that happens below. */ scale = (maxIndex + 1)/(logRange[1] - logRange[0]); } if (outFormat == VTK_RGBA) { while (--i >= 0) { val = vtkApplyLogScale16((double)*input, range, logRange); cptr = vtkLinearLookup16(val, table, maxIndex, shift, scale); *output++ = *cptr++; *output++ = *cptr++; *output++ = *cptr++; *output++ = static_cast((*cptr)*alpha); cptr++; input += inIncr; } } else if (outFormat == VTK_RGB) { while (--i >= 0) { val = vtkApplyLogScale16((double)*input, range, logRange); cptr = vtkLinearLookup16(val, table, maxIndex, shift, scale); *output++ = *cptr++; *output++ = *cptr++; *output++ = *cptr++; input += inIncr; } } else if (outFormat == VTK_LUMINANCE_ALPHA) { while (--i >= 0) { val = vtkApplyLogScale16((double)*input, range, logRange); cptr = vtkLinearLookup16(val, table, maxIndex, shift, scale); *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + cptr[2]*0.11 + 0.5); *output++ = static_cast(alpha*cptr[3]); input += inIncr; } } else // outFormat == VTK_LUMINANCE { while (--i >= 0) { val = vtkApplyLogScale16((double)*input, range, logRange); cptr = vtkLinearLookup16(val, table, maxIndex, shift, scale); *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + cptr[2]*0.11 + 0.5); input += inIncr; } } }//log scale with blending else //no log scale with blending { shift = -range[0]; if (range[1] <= range[0]) { scale = VTK_DOUBLE_MAX; } else { /* while this looks like the wrong scale, it is the correct scale * taking into account the truncation to int that happens below. */ scale = (maxIndex + 1)/(range[1] - range[0]); } if (outFormat == VTK_RGBA) { while (--i >= 0) { cptr = vtkLinearLookup16((double)*input, table, maxIndex, shift, scale); *output++ = *cptr++; *output++ = *cptr++; *output++ = *cptr++; *output++ = static_cast((*cptr)*alpha); cptr++; input += inIncr; } } else if (outFormat == VTK_RGB) { while (--i >= 0) { cptr = vtkLinearLookup16((double)*input, table, maxIndex, shift, scale); *output++ = *cptr++; *output++ = *cptr++; *output++ = *cptr++; input += inIncr; } } else if (outFormat == VTK_LUMINANCE_ALPHA) { while (--i >= 0) { cptr = vtkLinearLookup16((double)*input, table, maxIndex, shift, scale); *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + cptr[2]*0.11 + 0.5); *output++ = static_cast(cptr[3]*alpha); input += inIncr; } } else // outFormat == VTK_LUMINANCE { while (--i >= 0) { cptr = vtkLinearLookup16((double)*input, table, maxIndex, shift, scale); *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + cptr[2]*0.11 + 0.5); input += inIncr; } } }//no log scale }//alpha blending } //---------------------------------------------------------------------------- void vtkLookupTable16::MapScalarsThroughTable2(void *input, unsigned char *output, int inputDataType, int numberOfValues, int inputIncrement, int outputFormat) { if (this->UseMagnitude && inputIncrement > 1) { assert(0); // switch (inputDataType) // { // vtkTemplateMacro( // vtkLookupTableMapMag(this,static_cast(input),(unsigned short*)output, // numberOfValues,inputIncrement,outputFormat); // return // ); // case VTK_BIT: // vtkErrorMacro("Cannot comput magnitude of bit array."); // break; // default: // vtkErrorMacro(<< "MapImageThroughTable: Unknown input ScalarType"); // } } switch (inputDataType) { case VTK_BIT: { assert(0); //vtkIdType i, id; //vtkBitArray *bitArray = vtkBitArray::New(); //bitArray->SetVoidArray(input,numberOfValues,1); //vtkUnsignedCharArray *newInput = vtkUnsignedCharArray::New(); //newInput->SetNumberOfValues(numberOfValues); //for (id=i=0; iSetValue(i, bitArray->GetValue(id)); // } //vtkLookupTableMapData(this, // static_cast(newInput->GetPointer(0)), // output,numberOfValues, // inputIncrement,outputFormat); //newInput->Delete(); //bitArray->Delete(); } break; vtkTemplateMacro( vtkLookupTable16MapData(this,static_cast(input),(unsigned short*)output, numberOfValues,inputIncrement,outputFormat) ); default: vtkErrorMacro(<< "MapImageThroughTable: Unknown input ScalarType"); return; } } void vtkLookupTable16::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } GDCM-3.0.10/Utilities/VTK/vtkLookupTable16.h000066400000000000000000000055001412732066400202170ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ /*========================================================================= Portions of this file are subject to the VTK Toolkit Version 3 copyright. Program: Visualization Toolkit Module: $RCSfile: vtkLookupTable16.h,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm 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. =========================================================================*/ // .NAME vtkLookupTable16 - // .SECTION Description // // .SECTION Caveats // // .SECTION See Also // vtkLookupTable #ifndef VTKLOOKUPTABLE16_H #define VTKLOOKUPTABLE16_H #include "vtkLookupTable.h" #include "vtkUnsignedShortArray.h" class VTK_EXPORT vtkLookupTable16 : public vtkLookupTable { public: static vtkLookupTable16 *New(); vtkTypeMacro(vtkLookupTable16,vtkLookupTable); void PrintSelf(ostream& os, vtkIndent indent); void Build(); void SetNumberOfTableValues(vtkIdType number); unsigned char *WritePointer(const vtkIdType id, const int number); unsigned short *GetPointer(const vtkIdType id) { return this->Table16->GetPointer(4*id); }; protected: vtkLookupTable16(int sze=256, int ext=256); ~vtkLookupTable16(); vtkUnsignedShortArray *Table16; void MapScalarsThroughTable2(void *input, unsigned char *output, int inputDataType, int numberOfValues, int inputIncrement, int outputFormat); private: vtkLookupTable16(const vtkLookupTable16&); // Not implemented. void operator=(const vtkLookupTable16&); // Not implemented. }; //---------------------------------------------------------------------------- inline unsigned char *vtkLookupTable16::WritePointer(const vtkIdType id, const int number) { //this->InsertTime.Modified(); return (unsigned char*)this->Table16->WritePointer(4*id,4*number); } #endif GDCM-3.0.10/Utilities/VTK/vtkRTStructSetProperties.cxx000066400000000000000000000302101412732066400224610ustar00rootroot00000000000000/*========================================================================= 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 "vtkRTStructSetProperties.h" #include "vtkObjectFactory.h" #include "gdcmDirectory.h" #include "gdcmScanner.h" #include "gdcmDataSet.h" #include "gdcmReader.h" #include #include #include #include #include // for strftime #include // for isdigit #include //---------------------------------------------------------------------------- //vtkCxxRevisionMacro(vtkRTStructSetProperties, "1.21") vtkStandardNewMacro(vtkRTStructSetProperties) struct StructureSetROI { int ROINumber; std::string RefFrameRefUID; std::string ROIName; std::string ROIGenerationAlgorithm; std::string ROIDescription; // (3006,0080) SQ (Sequence with undefine)# u/l, 1 RTROIObservationsSequence // (3006,0082) IS [0] # 2, 1 ObservationNumber // (3006,0084) IS [0] # 2, 1 ReferencedROINumber // (3006,0085) SH [Station 4L] # 10, 1 ROIObservationLabel // (3006,00a4) CS [ORGAN] # 6, 1 RTROIInterpretedType // (3006,00a6) PN (no value available) # 0, 0 ROIInterpreter int ObservationNumber; // RefROI is AFAIK simply ROINumber std::string RTROIInterpretedType; std::string ROIInterpreter; std::string ROIObservationLabel; }; //---------------------------------------------------------------------------- class vtkRTStructSetPropertiesInternals { public: void Print(ostream &os, vtkIndent indent) { (void)os; (void)indent; } void DeepCopy(vtkRTStructSetPropertiesInternals *p) { ReferencedFrameOfReferences = p->ReferencedFrameOfReferences; } vtkIdType GetNumberOfContourReferencedFrameOfReferences() { return ContourReferencedFrameOfReferences.size(); } vtkIdType GetNumberOfContourReferencedFrameOfReferences(vtkIdType pdnum) { return ContourReferencedFrameOfReferences[pdnum].size(); } const char *GetContourReferencedFrameOfReferenceClassUID( vtkIdType pdnum, vtkIdType id ) { return ContourReferencedFrameOfReferences[pdnum][ id ].first.c_str(); } const char *GetContourReferencedFrameOfReferenceInstanceUID( vtkIdType pdnum, vtkIdType id ) { return ContourReferencedFrameOfReferences[pdnum][ id ].second.c_str(); } vtkIdType GetNumberOfReferencedFrameOfReferences() { return ReferencedFrameOfReferences.size(); } const char *GetReferencedFrameOfReferenceClassUID( vtkIdType id ) { return ReferencedFrameOfReferences[ id ].first.c_str(); } const char *GetReferencedFrameOfReferenceInstanceUID(vtkIdType id ) { return ReferencedFrameOfReferences[ id ].second.c_str(); } void AddContourReferencedFrameOfReference( vtkIdType pdnum, const char *classuid , const char * instanceuid ) { ContourReferencedFrameOfReferences.resize(pdnum+1); ContourReferencedFrameOfReferences[pdnum].push_back( std::make_pair( classuid, instanceuid ) ); } std::vector< std::vector < std::pair< std::string, std::string > > > ContourReferencedFrameOfReferences; void AddReferencedFrameOfReference( const char *classuid , const char * instanceuid ) { ReferencedFrameOfReferences.push_back( std::make_pair( classuid, instanceuid ) ); } std::vector < std::pair< std::string, std::string > > ReferencedFrameOfReferences; void AddStructureSetROIObservation( int refnumber, int observationnumber, const char *rtroiinterpretedtype, const char *roiinterpreter, const char *roiobservationlabel ) { //std::cout << "AddStructureSetROIObservation: " << refnumber << std::endl; std::vector::iterator it = StructureSetROIs.begin(); bool found = false; for( ; it != StructureSetROIs.end(); ++it ) { if( it->ROINumber == refnumber ) { assert( !found ); found = true; it->ObservationNumber = observationnumber; if( rtroiinterpretedtype ) it->RTROIInterpretedType = rtroiinterpretedtype; if( roiinterpreter ) it->ROIInterpreter = roiinterpreter; if( roiobservationlabel ) it->ROIObservationLabel = roiobservationlabel; } } // postcond assert( found ); } void AddStructureSetROI( int roinumber, const char* refframerefuid, const char* roiname, const char* roigenerationalgorithm, const char* roidescription ) { StructureSetROI structuresetroi; structuresetroi.ROINumber = roinumber; if( refframerefuid ) structuresetroi.RefFrameRefUID = refframerefuid; if( roiname ) structuresetroi.ROIName = roiname; if( roigenerationalgorithm ) structuresetroi.ROIGenerationAlgorithm = roigenerationalgorithm; if( roidescription ) structuresetroi.ROIDescription = roidescription; StructureSetROIs.push_back( structuresetroi ); } vtkIdType GetNumberOfStructureSetROIs() { return StructureSetROIs.size(); } int GetStructureSetObservationNumber(vtkIdType id) { return StructureSetROIs[id].ObservationNumber; } int GetStructureSetROINumber(vtkIdType id) { return StructureSetROIs[id].ROINumber; } const char *GetStructureSetRTROIInterpretedType(vtkIdType id) { return StructureSetROIs[id].RTROIInterpretedType.c_str(); } const char *GetStructureSetROIObservationLabel(vtkIdType id) { return StructureSetROIs[id].ROIObservationLabel.c_str(); } const char *GetStructureSetROIRefFrameRefUID(vtkIdType id) { return StructureSetROIs[id].RefFrameRefUID.c_str(); } const char *GetStructureSetROIName(vtkIdType id) { return StructureSetROIs[id].ROIName.c_str(); } const char *GetStructureSetROIGenerationAlgorithm(vtkIdType id) { return StructureSetROIs[id].ROIGenerationAlgorithm.c_str(); } const char *GetStructureSetROIDescription(vtkIdType id) { return StructureSetROIs[id].ROIDescription.c_str(); } std::vector StructureSetROIs; }; //---------------------------------------------------------------------------- vtkRTStructSetProperties::vtkRTStructSetProperties() { this->Internals = new vtkRTStructSetPropertiesInternals; this->StructureSetLabel = NULL; this->StructureSetName = NULL; this->StructureSetDate = NULL; this->StructureSetTime = NULL; this->SOPInstanceUID= NULL; this->StudyInstanceUID = NULL; this->SeriesInstanceUID = NULL; this->ReferenceSeriesInstanceUID = NULL; this->ReferenceFrameOfReferenceUID = NULL; } //---------------------------------------------------------------------------- vtkRTStructSetProperties::~vtkRTStructSetProperties() { delete this->Internals; this->Clear(); } //---------------------------------------------------------------------------- void vtkRTStructSetProperties::AddContourReferencedFrameOfReference(vtkIdType pdnum, const char *classuid , const char * instanceuid ) { this->Internals->AddContourReferencedFrameOfReference(pdnum, classuid, instanceuid ); } const char *vtkRTStructSetProperties::GetContourReferencedFrameOfReferenceClassUID( vtkIdType pdnum, vtkIdType id ) { return this->Internals->GetContourReferencedFrameOfReferenceClassUID(pdnum, id ); } const char *vtkRTStructSetProperties::GetContourReferencedFrameOfReferenceInstanceUID( vtkIdType pdnum, vtkIdType id ) { return this->Internals->GetContourReferencedFrameOfReferenceInstanceUID(pdnum ,id ); } vtkIdType vtkRTStructSetProperties::GetNumberOfContourReferencedFrameOfReferences() { return this->Internals->GetNumberOfContourReferencedFrameOfReferences(); } vtkIdType vtkRTStructSetProperties::GetNumberOfContourReferencedFrameOfReferences(vtkIdType pdnum) { return this->Internals->GetNumberOfContourReferencedFrameOfReferences(pdnum); } void vtkRTStructSetProperties::AddReferencedFrameOfReference( const char *classuid , const char * instanceuid ) { this->Internals->AddReferencedFrameOfReference( classuid, instanceuid ); } const char *vtkRTStructSetProperties::GetReferencedFrameOfReferenceClassUID( vtkIdType id ) { return this->Internals->GetReferencedFrameOfReferenceClassUID(id ); } const char *vtkRTStructSetProperties::GetReferencedFrameOfReferenceInstanceUID( vtkIdType id ) { return this->Internals->GetReferencedFrameOfReferenceInstanceUID(id ); } vtkIdType vtkRTStructSetProperties::GetNumberOfReferencedFrameOfReferences() { return this->Internals->GetNumberOfReferencedFrameOfReferences(); } void vtkRTStructSetProperties::AddStructureSetROIObservation( int refnumber, int observationnumber, const char *rtroiinterpretedtype, const char *roiinterpreter, const char *roiobservationlabel ) { this->Internals->AddStructureSetROIObservation( refnumber, observationnumber, rtroiinterpretedtype, roiinterpreter, roiobservationlabel ); } void vtkRTStructSetProperties::AddStructureSetROI( int roinumber, const char* refframerefuid, const char* roiname, const char* roigenerationalgorithm, const char* roidescription ) { this->Internals->AddStructureSetROI( roinumber, refframerefuid, roiname, roigenerationalgorithm, roidescription ); } vtkIdType vtkRTStructSetProperties::GetNumberOfStructureSetROIs() { return this->Internals->GetNumberOfStructureSetROIs(); } int vtkRTStructSetProperties::GetStructureSetObservationNumber(vtkIdType id) { return this->Internals->GetStructureSetObservationNumber(id); } int vtkRTStructSetProperties::GetStructureSetROINumber(vtkIdType id) { return this->Internals->GetStructureSetROINumber(id); } const char *vtkRTStructSetProperties::GetStructureSetRTROIInterpretedType(vtkIdType id) { return this->Internals->GetStructureSetRTROIInterpretedType(id); } const char *vtkRTStructSetProperties::GetStructureSetROIObservationLabel(vtkIdType id) { return this->Internals->GetStructureSetROIObservationLabel(id); } const char *vtkRTStructSetProperties::GetStructureSetROIRefFrameRefUID(vtkIdType id) { return this->Internals->GetStructureSetROIRefFrameRefUID(id); } const char *vtkRTStructSetProperties::GetStructureSetROIName(vtkIdType id) { return this->Internals->GetStructureSetROIName(id); } const char *vtkRTStructSetProperties::GetStructureSetROIGenerationAlgorithm(vtkIdType id) { return this->Internals->GetStructureSetROIGenerationAlgorithm(id); } const char *vtkRTStructSetProperties::GetStructureSetROIDescription(vtkIdType id) { return this->Internals->GetStructureSetROIDescription(id); } //---------------------------------------------------------------------------- void vtkRTStructSetProperties::Clear() { this->SetStructureSetLabel(NULL); this->SetStructureSetName(NULL); this->SetStructureSetDate(NULL); this->SetStructureSetTime(NULL); this->SetSOPInstanceUID( NULL ); this->SetStudyInstanceUID ( NULL ); this->SetSeriesInstanceUID ( NULL ); this->SetReferenceSeriesInstanceUID ( NULL ); this->SetReferenceFrameOfReferenceUID ( NULL ); } //---------------------------------------------------------------------------- void vtkRTStructSetProperties::DeepCopy(vtkRTStructSetProperties *p) { if (p == NULL) { return; } this->Clear(); this->SetStructureSetDate(p->GetStructureSetDate()); this->SetStructureSetTime(p->GetStructureSetTime()); this->Internals->DeepCopy( p->Internals ); } //---------------------------------------------------------------------------- void vtkRTStructSetProperties::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << "\n" << indent << "StructureSetDate: "; if (this->StructureSetDate) { os << this->StructureSetDate; } os << "\n" << indent << "StructureSetTime: "; if (this->StructureSetTime) { os << this->StructureSetTime; } this->Internals->Print(os << "\n", indent.GetNextIndent() ); } GDCM-3.0.10/Utilities/VTK/vtkRTStructSetProperties.h000066400000000000000000000103361412732066400221150ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ // .NAME vtkRTStructSetProperties - some rtstruct properties. // .SECTION Description // // .SECTION See Also // vtkGDCMPolyDataReader vtkGDCMPolyDataWriter #ifndef VTKRTSTRUCTSETPROPERTIES_H #define VTKRTSTRUCTSETPROPERTIES_H #include "vtkObject.h" class vtkRTStructSetPropertiesInternals; class VTK_EXPORT vtkRTStructSetProperties : public vtkObject { public: static vtkRTStructSetProperties *New(); vtkTypeMacro(vtkRTStructSetProperties,vtkObject); void PrintSelf(ostream& os, vtkIndent indent); // Description: // Convenience method to reset all fields to an empty string/value virtual void Clear(); // Description: // vtkSetStringMacro(StructureSetLabel); vtkGetStringMacro(StructureSetLabel); vtkSetStringMacro(StructureSetName); vtkGetStringMacro(StructureSetName); vtkSetStringMacro(StructureSetDate); vtkGetStringMacro(StructureSetDate); vtkSetStringMacro(StructureSetTime); vtkGetStringMacro(StructureSetTime); vtkSetStringMacro(SOPInstanceUID); vtkGetStringMacro(SOPInstanceUID); vtkSetStringMacro(StudyInstanceUID); vtkGetStringMacro(StudyInstanceUID); vtkSetStringMacro(SeriesInstanceUID); vtkGetStringMacro(SeriesInstanceUID); vtkSetStringMacro(ReferenceSeriesInstanceUID); vtkGetStringMacro(ReferenceSeriesInstanceUID); vtkSetStringMacro(ReferenceFrameOfReferenceUID); vtkGetStringMacro(ReferenceFrameOfReferenceUID); // Description: // Copy the contents of p to this instance. virtual void DeepCopy(vtkRTStructSetProperties *p); void AddContourReferencedFrameOfReference( vtkIdType pdnum, const char *classuid , const char * instanceuid ); const char *GetContourReferencedFrameOfReferenceClassUID( vtkIdType pdnum, vtkIdType id ); const char *GetContourReferencedFrameOfReferenceInstanceUID( vtkIdType pdnum, vtkIdType id ); vtkIdType GetNumberOfContourReferencedFrameOfReferences(); vtkIdType GetNumberOfContourReferencedFrameOfReferences(vtkIdType pdnum); void AddReferencedFrameOfReference( const char *classuid , const char * instanceuid ); const char *GetReferencedFrameOfReferenceClassUID( vtkIdType id ); const char *GetReferencedFrameOfReferenceInstanceUID( vtkIdType id ); vtkIdType GetNumberOfReferencedFrameOfReferences(); void AddStructureSetROI( int roinumber, const char* refframerefuid, const char* roiname, const char* ROIGenerationAlgorithm, const char* ROIDescription = 0 ); void AddStructureSetROIObservation( int refnumber, int observationnumber, const char *rtroiinterpretedtype, const char *roiinterpreter, const char *roiobservationlabel = 0 ); vtkIdType GetNumberOfStructureSetROIs(); int GetStructureSetObservationNumber(vtkIdType id); int GetStructureSetROINumber(vtkIdType id); const char *GetStructureSetROIRefFrameRefUID(vtkIdType); const char *GetStructureSetROIName(vtkIdType); const char *GetStructureSetROIGenerationAlgorithm(vtkIdType); const char *GetStructureSetROIDescription(vtkIdType id); const char *GetStructureSetRTROIInterpretedType(vtkIdType id); const char *GetStructureSetROIObservationLabel(vtkIdType id); protected: vtkRTStructSetProperties(); ~vtkRTStructSetProperties(); char *StructureSetLabel; char *StructureSetName; char *StructureSetDate; char *StructureSetTime; char *SOPInstanceUID; char *StudyInstanceUID; char *SeriesInstanceUID; char *ReferenceSeriesInstanceUID; char *ReferenceFrameOfReferenceUID; // Description: // PIMPL Encapsulation for STL containers //BTX vtkRTStructSetPropertiesInternals *Internals; //ETX private: vtkRTStructSetProperties(const vtkRTStructSetProperties&); // Not implemented. void operator=(const vtkRTStructSetProperties&); // Not implemented. }; #endif GDCM-3.0.10/Utilities/VTK/vtkgdcm.i000066400000000000000000000371531412732066400165530ustar00rootroot00000000000000/*========================================================================= 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. =========================================================================*/ %module(docstring="A VTK/GDCM binding") vtkgdcm #pragma SWIG nowarn=504,510 //%pragma(csharp) moduleimports=%{ //using Kitware.VTK; //%} #if defined(SWIGCSHARP) %{ #define SWIGCSHARP %} #endif #if defined(SWIGPHP) %{ #define SWIGPHP %} #endif %{ //#define VTK_MAJOR_VERSION 7 //#define VTK_MINOR_VERSION 1 //#define VTK_BUILD_VERSION 1 //#define VTK_VERSION "7.1.1" %} #define VTK_OVERRIDE override #define VTK_FINAL final #define VTK_DELETE_FUNCTION = delete #define VTK_NEWINSTANCE #define VTK_LEGACY(X) %{ // Let's reproduce the stack of include, when one would include vtkSetGet: #include "vtkConfigure.h" #include "vtkType.h" #include "vtkSystemIncludes.h" #include "vtkSetGet.h" #include // Common stuff #include "vtkObjectBase.h" #include "vtkObject.h" #include "vtkStringArray.h" #include "vtkMatrix4x4.h" #include "vtkMedicalImageProperties.h" // Wrap vtkImageData #include "vtkDataObject.h" #include "vtkDataSet.h" #include "vtkImageData.h" #include "vtkPointSet.h" #include "vtkPolyData.h" #include "vtkGDCMTesting.h" // same for vtkGDCMImageReader / vtkGDCMImageWriter so that we get all // parent's member class functions properly wrapped. (Update, SetFileName ...) #include "vtkAlgorithm.h" #include "vtkImageAlgorithm.h" #include "vtkThreadedImageAlgorithm.h" #include "vtkImageWriter.h" #include "vtkImageReader2.h" #include "vtkMedicalImageReader2.h" #include "vtkGDCMImageReader.h" #include "vtkGDCMImageWriter.h" #include "vtkImageExport.h" #include "vtkImageImport.h" #include "vtkImageCast.h" #include "vtkVolumeReader.h" #include "vtkVolume16Reader.h" #include "vtkWindowToImageFilter.h" #include "vtkToolkits.h" // VTK_DATA_ROOT %} //%typemap(csimports) vtkGDCMImageWriter %{ //%typemap(csimports) SWIGTYPE %{ //// I need to duplicate those also: //using System; //using System.Runtime.InteropServices; //// my special import: //using Kitware.VTK; //using Kitware.mummy.Runtime; //%} //%pragma(csharp) imclassimports=%{ //using System; //using System.Runtime.InteropServices; //using My.Own.Namespace; //%} #if defined( USEACTIVIZ ) || defined (SWIGCSHARP) %typemap(csimports) SWIGTYPE %{ // I need to duplicate those also: using System; using System.Runtime.InteropServices; %} #endif #if defined( USEACTIVIZ ) %typemap(csimports) SWIGTYPE %{ // my special import: using Kitware.VTK; //using Kitware.mummy.Runtime; %} #endif #define GDCM_EXPORT #define VTK_EXPORT #define VTK_COMMON_EXPORT #define VTK_FILTERING_EXPORT #define VTK_IO_EXPORT #define VTK_IMAGING_EXPORT #define VTK_RENDERING_EXPORT #define VTKCOMMONCORE_EXPORT #define VTKCOMMONMATH_EXPORT #define VTKIOIMAGE_EXPORT #define VTKCOMMONDATAMODEL_EXPORT #define VTKCOMMONEXECUTIONMODEL_EXPORT #define VTKRENDERINGCORE_EXPORT #define VTKIMAGINGCORE_EXPORT // FIXME. Including #include vtkSetGet would not work on siwg 1.3.33 ... #define vtkGetMacro(name,type) virtual type Get##name (); #define vtkSetMacro(name,type) virtual void Set##name (type _arg); #define vtkBooleanMacro(name,type) \ virtual void name##On (); \ virtual void name##Off (); #define vtkGetVector3Macro(name,type) virtual type *Get##name (); #define vtkGetVector6Macro(name,type) virtual type *Get##name (); #define vtkGetObjectMacro(name,type) virtual type *Get##name (); #define vtkSetClampMacro(name,type,min,max) virtual void Set##name (type _arg); #define vtkSetStringMacro(name) virtual void Set##name (const char* _arg); #define vtkGetStringMacro(name) virtual char* Get##name (); #define vtkGetVectorMacro(name,type,count) virtual type *Get##name (); #define vtkNotUsed(x) x #define vtkGetVector2Macro(name,type) virtual type *Get##name (); #define vtkSetVector2Macro(name,type) virtual void Set##name (type _arg1, type _arg2); #define vtkSetVector3Macro(name,type) virtual void Set##name (type _arg1, type _arg2, type _arg3); //%include "vtkConfigure.h" //%ignore vtkGDCMImageReader::GetOverlay; //%ignore vtkGDCMImageReader::GetIconImage; // //%ignore vtkAlgorithm::GetOutputDataObject; //%ignore vtkAlgorithm::GetInputDataObject; // //%ignore vtkImageAlgorithm::GetOutput; //%ignore vtkImageAlgorithm::GetInput; //%ignore vtkImageAlgorithm::GetImageDataInput; %ignore operator<<(ostream& os, vtkObjectBase& o); %ignore vtkMatrix4x4::operator[]; %ignore vtkMatrix4x4::Determinant(vtkMatrix4x4 &); %ignore vtkMatrix4x4::Adjoint(vtkMatrix4x4 *in, vtkMatrix4x4 *out); %ignore vtkMatrix4x4::Invert(vtkMatrix4x4 *in, vtkMatrix4x4 *out); %ignore vtkMatrix4x4::Transpose(vtkMatrix4x4 *in, vtkMatrix4x4 *out); // In VTK 5.8 we have to ignore the const variant: %ignore vtkMatrix4x4::Invert(const vtkMatrix4x4 *in, vtkMatrix4x4 *out); %ignore vtkMatrix4x4::Transpose(const vtkMatrix4x4 *in, vtkMatrix4x4 *out); %ignore vtkImageWriter::GetInput; // I am getting a warning on swig 1.3.33 because of vtkImageAlgorithm.GetInput // Let's wrap the following constants: // this is only a subset of vtkSystemIncludes.h : #define VTK_LUMINANCE 1 #define VTK_LUMINANCE_ALPHA 2 #define VTK_RGB 3 #define VTK_RGBA 4 //#include "vtkConfigure.h" //#define VTK_USE_64BIT_IDS // //#ifdef VTK_USE_64BIT_IDS //typedef long long vtkIdType; //#else //typedef int vtkIdType; //#endif //typedef vtkIdType2 vtkIdType; //%apply vtkIdType { vtkIdType } //#define vtkIdType vtkIdType; //%include "vtkType.h" #ifdef USEACTIVIZ %typemap(cstype) vtkDataObject * "vtkDataObject" %typemap(csin) vtkDataObject * "$csinput.GetCppThis()" /* public vtkDataObject GetOutputDataObject(int port) { IntPtr cPtr = vtkgdcmPINVOKE.vtkAlgorithm_GetOutputDataObject(swigCPtr, port); SWIGTYPE_p_vtkDataObject ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_vtkDataObject(cPtr, false); return ret; } */ %typemap(csout) (vtkDataObject*) { IntPtr rawCppThisSwig = $imcall; vtkDataObject data = new vtkDataObject( rawCppThisSwig, false, false ); return data; } %typemap(cstype) vtkStringArray * "vtkStringArray" %typemap(csin) vtkStringArray * "$csinput.GetCppThis()" %typemap(csout) (vtkStringArray*) { IntPtr rawCppThisSwig = $imcall; vtkStringArray data = new vtkStringArray( rawCppThisSwig, false, false ); return data; } %typemap(cstype) vtkPolyData * "vtkPolyData" %typemap(csin) vtkPolyData * "$csinput.GetCppThis()" %typemap(csout) (vtkPolyData*) { IntPtr rawCppThisSwig = $imcall; vtkPolyData data = new vtkPolyData( rawCppThisSwig, false, false ); return data; } %typemap(cstype) vtkMatrix4x4 * "vtkMatrix4x4" %typemap(csin) vtkMatrix4x4 * "$csinput.GetCppThis()" %typemap(csout) (vtkMatrix4x4*) { IntPtr rawCppThisSwig = $imcall; vtkMatrix4x4 data = new vtkMatrix4x4( rawCppThisSwig, false, false ); return data; } %typemap(cstype) vtkMedicalImageProperties * "vtkMedicalImageProperties" %typemap(csin) vtkMedicalImageProperties * "$csinput.GetCppThis()" %typemap(csout) (vtkMedicalImageProperties*) { IntPtr rawCppThisSwig = $imcall; vtkMedicalImageProperties data = new vtkMedicalImageProperties( rawCppThisSwig, false, false ); return data; } %typemap(cstype) vtkImageData * "vtkImageData" %typemap(csin) vtkImageData * "$csinput.GetCppThis()" %typemap(csout) (vtkImageData *) { IntPtr rawCppThisSwig = $imcall; vtkImageData data = new vtkImageData( rawCppThisSwig, false, false ); //vtkImageData data = null; //bool created; //if( IntPtr.Zero != rawCppThisSwig ) // { // data = (vtkImageData) Kitware.mummy.Runtime.Methods.CreateWrappedObject( // vtkImageData.MRClassNameKey, rawCppThisSwig, false, out created); // // created is true if the C# object was created by this call, false if it was already cached in the table // } return data; } // //%typemap(csout) (vtkDataObject *) { // vtkImageData data = null; //// uint mteStatus = 0; //// uint maxValue = uint.MaxValue; //// uint rawRefCount = 0; //// IntPtr rawCppThis = ////vtkImageAlgorithm_GetOutput_06(base.GetCppThis(), ref mteStatus, ref ////maxValue, ref rawRefCount); //// IntPtr rawCppThisSwig = $imcall; //// if (IntPtr.Zero != rawCppThisSwig) //// { //// bool flag; //// data = (vtkImageData) Methods.CreateWrappedObject(mteStatus, ////maxValue, rawRefCount, rawCppThisSwig, true, out flag); //// if (flag) //// { //// data.Register(null); //// } //// } // return data; //} // #endif //USEACTIVIZ #ifdef USEACTIVIZ // By hiding all New operator I make sure that no-one will ever be // able to create a swig wrap object I did not decide to allow. // For instance the only two objects allowed for now are: // - vtkGDCMImageReader // - vtkGDCMImageWriter // BUG: // when using %ignore vtkObjectBase::New() // the vtkObjectBase_New() function is not generated, which is used // internally in the new cstor that I provide %csmethodmodifiers vtkObjectBase::New() "internal new" %csmethodmodifiers vtkObject::New() "internal new" %csmethodmodifiers vtkAlgorithm::New() "internal new" %csmethodmodifiers vtkImageAlgorithm::New() "internal new" %csmethodmodifiers vtkImageWriter::New() "internal new" %csmethodmodifiers vtkImageReader2::New() "internal new" %csmethodmodifiers vtkMedicalImageReader2::New() "internal new" %csmethodmodifiers vtkGDCMImageReader::New() "public new" %csmethodmodifiers vtkGDCMImageWriter::New() "public new" %csmethodmodifiers vtkGDCMTesting::New() "public new" #endif %newobject vtkGDCMTesting::New(); %newobject vtkGDCMImageWriter::New(); %newobject vtkGDCMImageReader::New(); %delobject vtkObjectBase::Delete(); // TODO: I need to fix Delete and make sure SWIG owns the C++ ptr (call ->Delete in the Dispose layer) //%ignore vtkObjectBase::Delete; %ignore vtkObjectBase::FastDelete; %ignore vtkObjectBase::PrintSelf; %ignore vtkObjectBase::PrintHeader; %ignore vtkObjectBase::PrintTrailer; %ignore vtkObjectBase::Print; %ignore vtkObjectBase::PrintRevisions; %ignore vtkObject::PrintSelf; %ignore vtkAlgorithm::PrintSelf; %ignore vtkImageAlgorithm::PrintSelf; %ignore vtkImageAlgorithm::ProcessRequest; %ignore vtkImageWriter::PrintSelf; %ignore vtkImageReader2::PrintSelf; %ignore vtkMedicalImageReader2::PrintSelf; %ignore vtkGDCMImageReader::PrintSelf; %ignore vtkGDCMImageWriter::PrintSelf; %typemap(csdisposing_derived, methodname="Dispose", methodmodifiers="protected", parameters="bool disposing") vtkGDCMTesting { lock(this) { if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) { swigCMemOwn = false; vtkgdcmPINVOKE.vtkObjectBase_Delete(swigCPtr); } swigCPtr = new HandleRef(null, IntPtr.Zero); base.Dispose(disposing); } } %typemap(csdisposing_derived, methodname="Dispose", methodmodifiers="protected", parameters="bool disposing") vtkGDCMImageReader { lock(this) { if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) { swigCMemOwn = false; vtkgdcmPINVOKE.vtkObjectBase_Delete(swigCPtr); } swigCPtr = new HandleRef(null, IntPtr.Zero); base.Dispose(disposing); } } %typemap(csdisposing_derived, methodname="Dispose", methodmodifiers="protected", parameters="bool disposing") vtkGDCMImageWriter { lock(this) { if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) { swigCMemOwn = false; vtkgdcmPINVOKE.vtkObjectBase_Delete(swigCPtr); } swigCPtr = new HandleRef(null, IntPtr.Zero); base.Dispose(disposing); } } %include "vtkObjectBase.h" #ifdef SWIGCSHARP %csmethodmodifiers vtkObjectBase::ToString() "public override" #endif %extend vtkObjectBase { const char *ToString() { static std::string buffer; std::ostringstream os; self->Print( os ); buffer = os.str(); return buffer.c_str(); } }; %include "vtkObject.h" %defaultdtor vtkGDCMTesting; // FIXME does not seems to be working %include "vtkGDCMTesting.h" #ifndef USEACTIVIZ %include "vtkStringArray.h" %include "vtkMatrix4x4.h" %include "vtkMedicalImageProperties.h" %include "vtkDataObject.h" %include "vtkDataSet.h" %include "vtkImageData.h" %include "vtkPointSet.h" %include "vtkPolyData.h" #endif %include "vtkAlgorithm.h" %include "vtkImageAlgorithm.h" #ifndef USEACTIVIZ %include "vtkThreadedImageAlgorithm.h" #endif %include "vtkImageWriter.h" /* By default swig generates: public virtual SWIGTYPE_p_double GetImageOrientationPatient() { IntPtr cPtr = vtkgdcmPINVOKE.vtkGDCMImageReader_GetImageOrientationPatient(swigCPtr); SWIGTYPE_p_double ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_double(cPtr, false); return ret; } while we would want: public virtual double[] GetImageOrientationPatient() { IntPtr source = vtkgdcmPINVOKE.vtkGDCMImageReader_GetImageOrientationPatient(swigCPtr); double[] ret = null; if (IntPtr.Zero != source) { ret = new double[6]; Marshal.Copy(source, destination, 0, destination.Length); } return ret; } */ //%typemap(ctype) double[] "double*" %typemap(cstype) double * "double[]" %typemap(csout) double* GetImagePositionPatient() { IntPtr source = $imcall; double[] destination = null; if (IntPtr.Zero != source) { destination = new double[3]; Marshal.Copy(source, destination, 0, destination.Length); } return destination; } %typemap(csout) double* GetImageOrientationPatient() { IntPtr source = $imcall; double[] destination = null; if (IntPtr.Zero != source) { destination = new double[6]; Marshal.Copy(source, destination, 0, destination.Length); } return destination; } %typemap(csout) double* GetDataSpacing() { IntPtr source = $imcall; double[] destination = null; if (IntPtr.Zero != source) { destination = new double[3]; Marshal.Copy(source, destination, 0, destination.Length); } return destination; } %typemap(csout) double* GetDataOrigin() { IntPtr source = $imcall; double[] destination = null; if (IntPtr.Zero != source) { destination = new double[3]; Marshal.Copy(source, destination, 0, destination.Length); } return destination; } %include "vtkImageReader2.h" %include "vtkMedicalImageReader2.h" //%rename (vtkGDCMImageReaderInternal) vtkGDCMImageReader; //%rename (vtkGDCMImageWriterInternal) vtkGDCMImageWriter; %include "vtkGDCMImageReader.h" %include "vtkGDCMImageWriter.h" %extend vtkGDCMTesting { %typemap(cscode) vtkGDCMTesting %{ public vtkGDCMTesting() : this(vtkgdcmPINVOKE.vtkGDCMTesting_New(), true) { } ~vtkGDCMTesting() { Dispose(); } %} }; %extend vtkGDCMImageReader { %typemap(cscode) vtkGDCMImageReader %{ public vtkGDCMImageReader() : this(vtkgdcmPINVOKE.vtkGDCMImageReader_New(), true) { } ~vtkGDCMImageReader() { Dispose(); } %} }; #ifdef SWIGPHP %extend vtkGDCMImageReader { //public function __construct2($res=null) { // $this->_cPtr=vtkGDCMImageReader_Create(); //} //%typemap(out) vtkGDCMImageReader* (vtkGDCMImageReader::New) //%{ //public function __construct($res=null) { // $this->_cPtr=vtkGDCMImageReader_Create(); //} //%} }; #endif %extend vtkGDCMImageWriter { %typemap(cscode) vtkGDCMImageWriter %{ public vtkGDCMImageWriter() : this(vtkgdcmPINVOKE.vtkGDCMImageWriter_New(), true) { } ~vtkGDCMImageWriter() { Dispose(); } %} }; %clear double*; %clear double* GetDataSpacing(); %clear double* GetDataOrigin(); #ifdef SWIGPHP %include "vtkWindowToImageFilter.h" #endif #ifndef USEACTIVIZ %include "vtkImageExport.h" %include "vtkImageImport.h" %include "vtkImageCast.h" %include "vtkVolumeReader.h" %include "vtkVolume16Reader.h" #endif GDCM-3.0.10/Utilities/VTK/vtkgdcm.py000066400000000000000000000041551412732066400167470ustar00rootroot00000000000000############################################################################ # # 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. # ############################################################################ """ This module loads all the classes from the GDCM-VTK library into its namespace. This is a required module.""" import os # FIXME: GDCM_WHEREAMI need also to be set here, since the lib is dlopen'ed before gdcm.py is # actually read... os.environ["GDCM_WHEREAMI"]=os.path.dirname(__file__) if os.name == 'posix': # extremely important ! # http://gcc.gnu.org/faq.html#dso # http://mail.python.org/pipermail/python-dev/2002-May/023923.html # http://wiki.python.org/moin/boost.python/CrossExtensionModuleDependencies # This is now merged in VTK 5.2: # http://vtk.org/cgi-bin/viewcvs.cgi/Wrapping/Python/vtk/__init__.py?r1=1.13&r2=1.14 import sys orig_dlopen_flags = sys.getdlopenflags() try: import dl except ImportError: # are we on AMD64 ? try: import DLFCN as dl except ImportError: print("Could not import dl") dl = None if dl: #print "dl was imported" #sys.setdlopenflags(dl.RTLD_LAZY|dl.RTLD_GLOBAL) sys.setdlopenflags(dl.RTLD_NOW|dl.RTLD_GLOBAL) try: from libvtkgdcmPython import * except ImportError: # maybe vtk7 from vtkgdcmPython import * # revert: sys.setdlopenflags(orig_dlopen_flags) del sys, dl del orig_dlopen_flags else: from vtkgdcmPython import * # to provide a compatibilty layer with VTK 4.2 and VTK 4.4 where vtkStringArray was not present # and VTK 5.x where there is one... try: # if vtkStringArray can be found in vtk let's use it ! from vtk import vtkStringArray except: print("Using compatibility layer (VTK 4) for vtkStringArray") # bye bye del os GDCM-3.0.10/Utilities/dicom3tools/000077500000000000000000000000001412732066400165245ustar00rootroot00000000000000GDCM-3.0.10/Utilities/dicom3tools/process.sh000077500000000000000000000022601412732066400205410ustar00rootroot00000000000000#!/bin/sh -xe ############################################################################ # # 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. # ############################################################################ # This script convert dicom3tools internal txt format into XML for GDCM # Usage: # $ process.sh agfa.tpl # remove empty lines sed '/^\s*$/d' $1 > /tmp/clean2.tpl # remove comments: sed '/^#/d' /tmp/clean2.tpl > /tmp/clean.tpl # convert to xml sed 's/^.*$/' /tmp/dummy.xml # add end: echo '' >> /tmp/dummy.xml # format and check if valid xml xmllint --format /tmp/dummy.xml -o `basename $1 tpl`xml GDCM-3.0.10/Utilities/doxygen/000077500000000000000000000000001412732066400157425ustar00rootroot00000000000000GDCM-3.0.10/Utilities/doxygen/CMakeLists.txt000066400000000000000000000326071412732066400205120ustar00rootroot00000000000000# Documentation # http://www.stack.nl/~dimitri/doxygen # http://www.stack.nl/~dimitri/doxygen/commands.html#cmdsa if(GDCM_DOCUMENTATION) find_package(Doxygen REQUIRED) if(GDCM_DOXYGEN_NO_FOOTER) set(GDCM_HTML_FOOTER) else() # Otherwise use gdcm/piwik/sf.net footer: set(GDCM_HTML_FOOTER ${GDCM_SOURCE_DIR}/Utilities/doxygen/footer.html) endif() configure_file( ${GDCM_SOURCE_DIR}/Utilities/doxygen/doxyfile.in ${GDCM_BINARY_DIR}/Utilities/doxygen/Doxyfile ) file(GLOB_RECURSE headerfiles "${GDCM_SOURCE_DIR}/Source/*.h" "${GDCM_SOURCE_DIR}/Wrapping/*.h" "${GDCM_SOURCE_DIR}/Utilities/VTK/*.h" #"${GDCM_SOURCE_DIR}/Utilities/doxygen/man/*.dox" ) list(REMOVE_ITEM headerfiles "${GDCM_SOURCE_DIR}/Source/DataDictionary/gdcmTagKeywords.h" "${GDCM_SOURCE_DIR}/Source/DataDictionary/gdcmTagToType.h" ) #message(${headerfiles}) # We are depending only on header files and README.txt but other files # could be needed for complete dependencies file(GLOB_RECURSE examplefiles "${GDCM_SOURCE_DIR}/Examples/*.cxx" "${GDCM_SOURCE_DIR}/Examples/*.cs" "${GDCM_SOURCE_DIR}/Examples/*.java" "${GDCM_SOURCE_DIR}/Examples/*.py" ) file(GLOB_RECURSE vtkexamplefiles "${GDCM_SOURCE_DIR}/Utilities/VTK/Examples/*.cxx" "${GDCM_SOURCE_DIR}/Utilities/VTK/Examples/*.cs" "${GDCM_SOURCE_DIR}/Utilities/VTK/Examples/*.java" "${GDCM_SOURCE_DIR}/Utilities/VTK/Examples/*.py" ) set(DOXYFILE_EXAMPLES) foreach(file ${examplefiles} ${vtkexamplefiles}) get_filename_component(f ${file} NAME) set(DOXYFILE_EXAMPLES "${DOXYFILE_EXAMPLES}\n\\example ${f}") endforeach() configure_file( ${GDCM_SOURCE_DIR}/Utilities/doxygen/TestsList.txt.in ${GDCM_BINARY_DIR}/Utilities/doxygen/TestsList.txt @ONLY ) if(GDCM_MINOR_VERSION MATCHES "[02468]$") set(GDCM_DOC_PDF_LINK "http://gdcm.sourceforge.net/${GDCM_MAJOR_VERSION}.${GDCM_MINOR_VERSION}/gdcm-${GDCM_VERSION}.pdf" ) set(GDCM_DOC_TARBALL_LINK "http://gdcm.sourceforge.net/${GDCM_MAJOR_VERSION}.${GDCM_MINOR_VERSION}/gdcm-${GDCM_VERSION}-doc.tar.gz" ) else() set(GDCM_DOC_PDF_LINK "http://gdcm.sourceforge.net/gdcm-${GDCM_VERSION}.pdf" ) set(GDCM_DOC_TARBALL_LINK "http://gdcm.sourceforge.net/gdcm-${GDCM_VERSION}-doc.tar.gz" ) endif() configure_file( ${GDCM_SOURCE_DIR}/Utilities/doxygen/README.txt.in ${GDCM_BINARY_DIR}/Utilities/doxygen/README.txt @ONLY ) set(GDCM_DOC_TARBALL ${CMAKE_CURRENT_BINARY_DIR}/gdcm-${GDCM_VERSION}-doc.tar.gz ) # epstopdf is needed: sudo apt-get install texlive-extra-utils # pdflatex is needed: sudo apt-get install texlive-latex-extra add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/html/index.html ${CMAKE_CURRENT_BINARY_DIR}/latex/Makefile # let's create the tarball within the same custom command to avoid complex dep. rules. ${GDCM_DOC_TARBALL} ${CMAKE_CURRENT_BINARY_DIR}/latex/refman.tex # output #1 (fake) # 1. first thing first let's run doxygen COMMAND ${DOXYGEN} ARGS ${GDCM_BINARY_DIR}/Utilities/doxygen/Doxyfile # 2. tarball gen. COMMAND ${CMAKE_COMMAND} ARGS -E tar cfz ${GDCM_DOC_TARBALL} html DEPENDS ${GDCM_BINARY_DIR}/Utilities/doxygen/Doxyfile ${GDCM_BINARY_DIR}/Utilities/doxygen/README.txt ${GDCM_BINARY_DIR}/Utilities/doxygen/TestsList.txt ${headerfiles} COMMENT "GDCM: Creating doxygen doc + tarball" #WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) # PDF building part: # When building latex, we have to run a custom command to produce the pdf file: if(UNIX AND GDCM_PDF_DOCUMENTATION) find_program(PDFOPT_EXECUTABLE pdfopt) find_program(SED_EXECUTABLE sed) find_package(LATEX REQUIRED) mark_as_advanced(PDFOPT_EXECUTABLE SED_EXECUTABLE) # Let's customize the pdf tags a little usind sed: # Apparently egrep is also needed... # BAD: there is a circular dependency where refman.tex depend on refman.tex in the sed steps... # hack our way in anyway by simply removing the dep... #add_custom_command( # ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/patchtex.cmake #) # TODO, foreach(*.tex) # sed -i -e "/home/mmalaterre/Projects/" ... string(REPLACE "/" "\\/" sed_gdcm_source_dir ${GDCM_SOURCE_DIR}) #message(${sed_gdcm_source_dir}) add_custom_command( OUTPUT #${CMAKE_CURRENT_BINARY_DIR}/latex/refman.tex # output #1 (fake) ${CMAKE_CURRENT_BINARY_DIR}/latex/refman.pdf # output #2 # Command #1 COMMAND ${SED_EXECUTABLE} ARGS -i.tmp -e "'s/]{hyperref}/]{hyperref}\\\\hypersetup{pdftitle={GDCM ${GDCM_VERSION} Reference Manual},pdfauthor={Mathieu Malaterre and co.},pdfsubject={Grassroots DICOM API reference},pdfkeywords={GDCM,DICOM,Network,Query\\/Retrieve,JPEG,Lossless JPEG,JPEG-LS,J2K,JPEG 2000,RLE},pdfpagemode={UseOutlines},bookmarks,bookmarksopen,pdfstartview={FitH},backref,colorlinks,linkcolor={black},citecolor={black},urlcolor={black},baseurl={http:\\/\\/gdcm.sourceforge.net}}\\\\hyperbaseurl{http:\\/\\/gdcm.sourceforge.net}/g'" ${CMAKE_CURRENT_BINARY_DIR}/latex/refman.tex # Command #2 COMMAND ${SED_EXECUTABLE} ARGS -i.tmp -e "'s/${sed_gdcm_source_dir}/gdcm/g'" ${CMAKE_CURRENT_BINARY_DIR}/latex/*.tex # Command #3 COMMAND make ARGS -C ${CMAKE_CURRENT_BINARY_DIR}/latex DEPENDS #${CMAKE_CURRENT_BINARY_DIR}/latex/refman.tex ${CMAKE_CURRENT_BINARY_DIR}/latex/Makefile #${GDCM_DOC_TARBALL} COMMENT "GDCM: Creating (patched) pdf of documentation" ) if(PDFOPT_EXECUTABLE) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/latex/gdcm-${GDCM_VERSION}.pdf COMMAND ${PDFOPT_EXECUTABLE} ARGS ${CMAKE_CURRENT_BINARY_DIR}/latex/refman.pdf ${CMAKE_CURRENT_BINARY_DIR}/latex/gdcm-${GDCM_VERSION}.pdf DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/latex/refman.pdf COMMENT "GDCM: Creating optimized pdf version of documentation" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/latex ) else() add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/latex/gdcm-${GDCM_VERSION}.pdf COMMAND ${CMAKE_COMMAND} -E copy ARGS ${CMAKE_CURRENT_BINARY_DIR}/latex/refman.pdf ${CMAKE_CURRENT_BINARY_DIR}/latex/gdcm-${GDCM_VERSION}.pdf DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/latex/refman.pdf COMMENT "GDCM: Creating unoptimized pdf version of documentation" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/latex ) endif() # add target to 'ALL' add_custom_target(GDCMDoxygenPDF DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/latex/gdcm-${GDCM_VERSION}.pdf COMMENT "GDCM: Executing GDCMDoxygenPDF" ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/latex/gdcm-${GDCM_VERSION}.pdf DESTINATION ${GDCM_INSTALL_DOC_DIR} ) add_dependencies(DoxygenDoc GDCMDoxygenPDF) else() # make DoxygenDoc depends on the final tarball thus all file are garantee to be generated add_custom_target(GDCMDoxygenDoc DEPENDS ${GDCM_DOC_TARBALL} COMMENT "GDCM: Executing GDCMDoxygenDoc" ) add_dependencies(DoxygenDoc GDCMDoxygenDoc) endif() # Install html pages: #install(FILES # ${CMAKE_CURRENT_BINARY_DIR}/html/gdcm2vtk.html # ${CMAKE_CURRENT_BINARY_DIR}/html/gdcmconv.html # ${CMAKE_CURRENT_BINARY_DIR}/html/gdcmanon.html # ${CMAKE_CURRENT_BINARY_DIR}/html/gdcmgendir.html # ${CMAKE_CURRENT_BINARY_DIR}/html/gdcmdump.html # ${CMAKE_CURRENT_BINARY_DIR}/html/gdcmimg.html # ${CMAKE_CURRENT_BINARY_DIR}/html/gdcminfo.html # ${CMAKE_CURRENT_BINARY_DIR}/html/gdcmpdf.html # ${CMAKE_CURRENT_BINARY_DIR}/html/gdcmraw.html # ${CMAKE_CURRENT_BINARY_DIR}/html/gdcmscanner.html # ${CMAKE_CURRENT_BINARY_DIR}/html/gdcmtar.html # ${CMAKE_CURRENT_BINARY_DIR}/html/gdcmviewer.html # DESTINATION ${GDCM_INSTALL_DOC_DIR} COMPONENT DebugDevel #) #install(FILES # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcm2vtk.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcm2pnm.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcmconv.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcmpap3.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcmxml.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcmanon.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcmgendir.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcmdump.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcmdiff.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcmimg.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcminfo.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcmpdf.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcmraw.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcmscu.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcmscanner.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcmtar.1 # ${CMAKE_CURRENT_BINARY_DIR}/man/man1/gdcmviewer.1 # DESTINATION ${GDCM_INSTALL_MAN_DIR}/man1 COMPONENT DebugDevel #) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION ${GDCM_INSTALL_DOC_DIR} PATTERN "*.md5" EXCLUDE PATTERN "*.dot" EXCLUDE ) # http://lists.debian.org/debian-italian/2006/12/msg00878.html # man2txt : man man | col -b | less if(GDCM_USE_VTK) # Make this option a hidden option as vtkgdcm/doxygen stuff is a mess (copy/paste # from paraview). It always rerun -sigh- if(GDCM_VTK_DOCUMENTATION) set(BUILD_DOCUMENTATION 1) endif() add_subdirectory(vtk) endif() endif() option(GDCM_BUILD_DOCBOOK_MANPAGES "Build man pages from XML docbook ?" ON) mark_as_advanced(GDCM_BUILD_DOCBOOK_MANPAGES) if(GDCM_BUILD_DOCBOOK_MANPAGES) set(MANPAGES_XML gdcm2pnm gdcm2vtk gdcmanon gdcmconv gdcmdiff gdcmdump gdcmgendir gdcmimg gdcminfo gdcmpap3 gdcmpdf gdcmraw gdcmscanner gdcmscu gdcmtar gdcmviewer gdcmxml ) find_package(LibXslt) # need an XSLT 1.0 processor, use xsltproc, maybe add more implementations later if(LIBXSLT_XSLTPROC_EXECUTABLE) set(XSLT_PROCESSOR ${LIBXSLT_XSLTPROC_EXECUTABLE}) # http://docbook.sourceforge.net/release/xsl/current/doc/manpages/man.output.quietly.html set(XSLT_PROCESSOR_ARG --param man.output.quietly 1 --maxdepth 6000 ) # User can change the behavior at cmake time: if(NOT DEFINED GDCM_MANPAGES_USE_NONET) set(GDCM_MANPAGES_USE_NONET FALSE) # By default I want nonet on Debian (docbook-xsl-ns) # on fedora you need to install docbook-style-xsl if(EXISTS /etc/xml/catalog) # https://cmake.org/pipermail/cmake/2007-May/014317.html file(READ /etc/xml/catalog xml_catalog_in) # # string(REGEX REPLACE "\r?\n" ";" xml_catalog ${xml_catalog_in}) set(DOCBOOK_REWRITE_PREFIX_FOUND FALSE) foreach(line ${xml_catalog}) string(REGEX MATCH "^.*systemIdStartString=\"http://docbook.sourceforge.net/release/xsl-ns/\".*" out1 ${line}) string(REGEX REPLACE "^.*systemIdStartString=\"http://docbook.sourceforge.net/release/xsl-ns/\".*\"([A-Za-z ]*)\".*" "\\1" output_variable ${line}) if(out1) message(STATUS "Your docbook install was found here :${output_variable}") set(DOCBOOK_REWRITE_PREFIX_FOUND TRUE) endif() endforeach() # Need both the catalog and the docbook installation if(DOCBOOK_REWRITE_PREFIX_FOUND) set(GDCM_MANPAGES_USE_NONET TRUE) else() message(WARNING "Could not find the location of your docbook-xsl-ns installation. Please make sure your internet connection works. Or skip man pages generation: GDCM_BUILD_DOCBOOK_MANPAGES:BOOL=OFF.") endif() else() message(STATUS "Could not find /etc/xml/catalog") endif() endif() if(GDCM_MANPAGES_USE_NONET) list(APPEND XSLT_PROCESSOR_ARG --nonet) endif() else() find_program(MSXSL_EXECUTABLE msxsl ) mark_as_advanced(MSXSL_EXECUTABLE) if(MSXSL_EXECUTABLE) set(XSLT_PROCESSOR ${MSXSL_EXECUTABLE}) set(XSLT_PROCESSOR_ARG "-pi") # msxsl.exe -pi gdcmimg.xml # #Error occurred while executing stylesheet 'http://docbook.sourceforge.net/release/xsl-ns/current/manpages/docbook.xsl'. # #Code: 0x80004005 #Namespace 'http://exslt.org/common' does not contain any functions. # -> http://stackoverflow.com/a/16605034/136285 ?? endif() endif() if(XSLT_PROCESSOR) configure_file(version.txt.in version.txt @ONLY) foreach(docbook ${MANPAGES_XML}) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${docbook}.1 COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/man/${docbook}.xml ${CMAKE_CURRENT_BINARY_DIR}/${docbook}.xml COMMAND ${XSLT_PROCESSOR} ${XSLT_PROCESSOR_ARG} ${CMAKE_CURRENT_BINARY_DIR}/${docbook}.xml DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/man/${docbook}.xml ) list(APPEND MANPAGES ${CMAKE_CURRENT_BINARY_DIR}/${docbook}.1 ) endforeach() add_custom_target(DOCBOOK_MANPAGES ALL DEPENDS ${MANPAGES} COMMENT "docbook manpages" ) install(FILES ${MANPAGES} DESTINATION ${GDCM_INSTALL_MAN_DIR}/man1 COMPONENT DebugDevel ) else() message(WARNING "Cannot build man page from docbook (need an XSL processor)") endif() endif() # GDCM_BUILD_DOCBOOK_MANPAGES GDCM-3.0.10/Utilities/doxygen/README000066400000000000000000000010741412732066400166240ustar00rootroot00000000000000If you are reading this you are wondering what are ll those doxygen options: - I need HTML output for the doc at: http://gdcm.sourceforge.net/html/ - I need the MAN output for the generated man pages, for debian packaging this is a lintian error when a cmd line tool does not prodivde a man-page. - I need XML output for the python help page. See also the doxy2swig.py that is located in Wrapping/Python dir. - Specify a special FOOTER so that Piwik engine is on and will generate traffic to sf.net. The rest of the non-default options is currently not documented... GDCM-3.0.10/Utilities/doxygen/README.txt.in000066400000000000000000000004361412732066400200500ustar00rootroot00000000000000/** \mainpage GDCM Documentation This is the developpers documentation. A PDF version of this doxygen documentation can be found here: @GDCM_DOC_PDF_LINK@ A tarball version of this HTML doxygen documentation can be found here: @GDCM_DOC_TARBALL_LINK@ \author Mathieu Malaterre */ GDCM-3.0.10/Utilities/doxygen/TestsList.txt.in000066400000000000000000000000351412732066400210440ustar00rootroot00000000000000/** @DOXYFILE_EXAMPLES@ */ GDCM-3.0.10/Utilities/doxygen/authors.xml000066400000000000000000000035161412732066400201560ustar00rootroot00000000000000 Fabrice Bellet <bellet@users.sourceforge.net> Christina Roßmanith <chrrossmanith@users.sourceforge.net> Charles Pareto <chuckdawit@users.sourceforge.net> Charl P. Botha <cpbotha@users.sourceforge.net> Dean Inglis <deaninglis@users.sourceforge.net> Daniele E. Domenichelli <drdanz@users.sourceforge.net> Jean-Pierre Roux <jprx@users.sourceforge.net> Mathieu Malaterre <malat@users.sourceforge.net> Niels Dekker Rogue Research <rogueresearch@users.sourceforge.net> Shane Blackett <sablackett@users.sourceforge.net> Joel Spaltenstein <spalte@users.sourceforge.net> GDCM-3.0.10/Utilities/doxygen/doxyfile.in000066400000000000000000003163021412732066400201220ustar00rootroot00000000000000# Doxyfile 1.8.9.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = GDCM # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = @GDCM_VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = @GDCM_BINARY_DIR@/Utilities/doxygen # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = NO # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 2 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran. In the later case the parser tries to guess whether the code is fixed # or free formatted code, this is the default for Fortran type files), VHDL. For # instance to make doxygen treat .inc files as Fortran files (default is PHP), # and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO, these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = YES # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = YES # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete # parameter documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. # Note: If this tag is empty the current directory is searched. INPUT = @GDCM_SOURCE_DIR@/Source \ @GDCM_SOURCE_DIR@/Wrapping \ @GDCM_SOURCE_DIR@/Utilities/VTK \ @GDCM_SOURCE_DIR@/Utilities/doxygen/man \ @GDCM_BINARY_DIR@/Utilities/doxygen/README.txt \ @GDCM_BINARY_DIR@/Utilities/doxygen/TestsList.txt # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank the # following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, # *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, # *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, # *.qsf, *.as and *.js. FILE_PATTERNS = *.h \ *.dox # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = @GDCM_SOURCE_DIR@/Source/DataDictionary/gdcmTagToType.h \ @GDCM_SOURCE_DIR@/Source/DataDictionary/gdcmTagKeywords.h \ @GDCM_SOURCE_DIR@/Source/Common/zipstreamimpl.h \ @GDCM_SOURCE_DIR@/Source/Common/zipstreamimpl.hpp \ @GDCM_SOURCE_DIR@/Source/MediaStorageAndFileFormat/gdcm_jp2.h \ @GDCM_SOURCE_DIR@/Source/MediaStorageAndFileFormat/gdcm_j2k.h # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = */.git/* \ */VTK4/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = @GDCM_SOURCE_DIR@/Examples \ @GDCM_SOURCE_DIR@/Testing \ @GDCM_SOURCE_DIR@/Applications \ @GDCM_SOURCE_DIR@/Utilities/VTK/Examples \ @GDCM_SOURCE_DIR@/Utilities/VTK/Testing \ @GDCM_SOURCE_DIR@/Utilities/VTK/Applications # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = *.cxx \ *.py \ *.java \ *.cs # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = YES # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the # clang parser (see: http://clang.llvm.org/) for more accurate parsing at the # cost of reduced performance. This can be particularly helpful with template # rich C++ code for which doxygen's built-in parser lacks the necessary type # information. # Note: The availability of this option depends on whether or not doxygen was # compiled with the --with-libclang option. # The default value is: NO. CLANG_ASSISTED_PARSING = NO # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that # the include paths will already be set by doxygen for the files and directories # specified with INPUT and INCLUDE_PATH. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. CLANG_OPTIONS = #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 3 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .xhtml # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = @GDCM_HTML_FOOTER@ # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to YES can help to show when doxygen was last run and thus if the # documentation is up to date. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the master .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 1 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /